1 /* 2 * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 3 * Use is subject to license terms. 4 */ 5 6 /* 7 * Copyright (c) 2003, 2004 8 * Daan Vreeken <Danovitsch@Vitsch.net>. All rights reserved. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 3. All advertising materials mentioning features or use of this software 19 * must display the following acknowledgement: 20 * This product includes software developed by Daan Vreeken. 21 * 4. Neither the name of the author nor the names of any co-contributors 22 * may be used to endorse or promote products derived from this software 23 * without specific prior written permission. 24 * 25 * THIS SOFTWARE IS PROVIDED BY Daan Vreeken AND CONTRIBUTORS ``AS IS'' AND 26 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 27 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 28 * ARE DISCLAIMED. IN NO EVENT SHALL Daan Vreeken OR THE VOICES IN HIS HEAD 29 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 30 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 31 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 32 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 33 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 34 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 35 * THE POSSIBILITY OF SUCH DAMAGE. 36 */ 37 38 /* 39 * Atmel AT76c503 / AT76c503a / AT76c505 / AT76c505a USB WLAN driver 40 * 41 * Originally written by Daan Vreeken <Danovitsch @ Vitsch . net> 42 * http://vitsch.net/bsd/atuwi 43 * 44 * Contributed to by : 45 * Chris Whitehouse, Alistair Phillips, Peter Pilka, Martijn van Buul, 46 * Suihong Liang, Arjan van Leeuwen, Stuart Walsh 47 * 48 * Ported to OpenBSD by Theo de Raadt and David Gwynne. 49 */ 50 51 #include <sys/strsubr.h> 52 #include <sys/strsun.h> 53 #include <sys/mac_provider.h> 54 #include <sys/mac_wifi.h> 55 #include <sys/net80211.h> 56 #define USBDRV_MAJOR_VER 2 57 #define USBDRV_MINOR_VER 0 58 #include <sys/usb/usba.h> 59 #include <sys/usb/usba/usba_types.h> 60 61 #include "fw/atmel_rfmd.hex" 62 #include "fw/atmel_rfmd2958.hex" 63 #include "fw/atmel_rfmd2958-smc.hex" 64 #include "fw/atmel_intersil.hex" 65 #include "fw/atmel_at76c505_rfmd.hex" 66 #include "fw/atmel_at76c503_rfmd_acc.hex" 67 #include "fw/atmel_at76c503_i3863.hex" 68 #include "atu.h" 69 70 static void *atu_soft_state_p; 71 static mac_callbacks_t atu_m_callbacks; 72 static const struct ieee80211_rateset atu_rateset = {4, {2, 4, 11, 22}}; 73 74 static int 75 atu_usb_request(struct atu_softc *sc, uint8_t type, 76 uint8_t request, uint16_t value, uint16_t index, uint16_t length, 77 uint8_t *data) 78 { 79 usb_ctrl_setup_t req; 80 usb_cb_flags_t cf; 81 usb_cr_t cr; 82 mblk_t *mp = NULL; 83 int uret = USB_SUCCESS; 84 85 bzero(&req, sizeof (req)); 86 req.bmRequestType = type; 87 req.bRequest = request; 88 req.wValue = value; 89 req.wIndex = index; 90 req.wLength = length; 91 req.attrs = USB_ATTRS_NONE; 92 93 if (type & USB_DEV_REQ_DEV_TO_HOST) { 94 req.attrs = USB_ATTRS_AUTOCLEARING; 95 uret = usb_pipe_ctrl_xfer_wait(sc->sc_udev->dev_default_ph, 96 &req, &mp, &cr, &cf, 0); 97 if (mp == NULL) 98 return (EIO); 99 100 if (uret == USB_SUCCESS) 101 bcopy(mp->b_rptr, data, length); 102 } else { 103 if ((mp = allocb(length, BPRI_HI)) == NULL) 104 return (ENOMEM); 105 106 bcopy(data, mp->b_wptr, length); 107 mp->b_wptr += length; 108 uret = usb_pipe_ctrl_xfer_wait(sc->sc_udev->dev_default_ph, 109 &req, &mp, &cr, &cf, 0); 110 } 111 112 if (mp) 113 freemsg(mp); 114 115 return (uret == USB_SUCCESS ? 0 : EIO); 116 } 117 118 static int 119 atu_get_mib(struct atu_softc *sc, uint8_t type, uint8_t size, 120 uint8_t index, uint8_t *buf) 121 { 122 return atu_usb_request(sc, ATU_VENDOR_IF_IN, 0x033, 123 type << 8, index, size, buf); 124 } 125 126 static int 127 atu_get_cmd_status(struct atu_softc *sc, uint8_t cmd, uint8_t *status) 128 { 129 /* 130 * all other drivers (including Windoze) request 40 bytes of status 131 * and get a short-xfer of just 6 bytes. we can save 34 bytes of 132 * buffer if we just request those 6 bytes in the first place :) 133 */ 134 return atu_usb_request(sc, ATU_VENDOR_IF_IN, 0x22, cmd, 135 0x0000, 6, status); 136 } 137 138 static uint8_t 139 atu_get_dfu_state(struct atu_softc *sc) 140 { 141 uint8_t state; 142 143 if (atu_usb_request(sc, DFU_GETSTATE, 0, 0, 1, &state)) 144 return (DFUState_DFUError); 145 return (state); 146 } 147 148 static int 149 atu_get_opmode(struct atu_softc *sc, uint8_t *mode) 150 { 151 return atu_usb_request(sc, ATU_VENDOR_IF_IN, 0x33, 0x0001, 152 0x0000, 1, mode); 153 } 154 155 static int 156 atu_get_config(struct atu_softc *sc) 157 { 158 struct ieee80211com *ic = &sc->sc_ic; 159 struct atu_rfmd_conf rfmd_conf; 160 struct atu_intersil_conf intersil_conf; 161 int err; 162 163 switch (sc->sc_radio) { 164 case RadioRFMD: 165 case RadioRFMD2958: 166 case RadioRFMD2958_SMC: 167 case AT76C503_RFMD_ACC: 168 case AT76C505_RFMD: 169 err = atu_usb_request(sc, ATU_VENDOR_IF_IN, 0x33, 0x0a02, 170 0x0000, sizeof (rfmd_conf), (uint8_t *)&rfmd_conf); 171 if (err) { 172 cmn_err(CE_WARN, "%s: get RFMD config failed\n", 173 sc->sc_name); 174 return (err); 175 } 176 bcopy(rfmd_conf.MACAddr, ic->ic_macaddr, IEEE80211_ADDR_LEN); 177 break; 178 179 case RadioIntersil: 180 case AT76C503_i3863: 181 err = atu_usb_request(sc, ATU_VENDOR_IF_IN, 0x33, 0x0902, 182 0x0000, sizeof (intersil_conf), (uint8_t *)&intersil_conf); 183 if (err) { 184 cmn_err(CE_WARN, "%s: get Intersil config failed\n", 185 sc->sc_name); 186 return (err); 187 } 188 bcopy(intersil_conf.MACAddr, ic->ic_macaddr, 189 IEEE80211_ADDR_LEN); 190 break; 191 } 192 193 return (0); 194 } 195 196 static int 197 atu_wait_completion(struct atu_softc *sc, uint8_t cmd, uint8_t *status) 198 { 199 uint8_t statusreq[6]; 200 int idle_count = 0, err; 201 202 while ((err = atu_get_cmd_status(sc, cmd, statusreq)) == 0) { 203 204 if ((statusreq[5] != STATUS_IN_PROGRESS) && 205 (statusreq[5] != STATUS_IDLE)) { 206 if (status != NULL) 207 *status = statusreq[5]; 208 return (0); 209 } else if (idle_count++ > 60) { 210 cmn_err(CE_WARN, "%s: command (0x%02x) timeout\n", 211 sc->sc_name, cmd); 212 return (ETIME); 213 } 214 215 drv_usecwait(10 * 1000); 216 } 217 218 return (err); 219 } 220 221 static int 222 atu_send_command(struct atu_softc *sc, uint8_t *command, int size) 223 { 224 return atu_usb_request(sc, ATU_VENDOR_DEV_OUT, 0x0e, 0x0000, 225 0x0000, size, command); 226 } 227 228 static int 229 atu_send_mib(struct atu_softc *sc, uint8_t type, uint8_t size, 230 uint8_t index, void *data) 231 { 232 struct atu_cmd_set_mib request; 233 int err; 234 235 bzero(&request, sizeof (request)); 236 request.AtCmd = CMD_SET_MIB; 237 request.AtSize = size + 4; 238 request.MIBType = type; 239 request.MIBSize = size; 240 request.MIBIndex = index; 241 request.MIBReserved = 0; 242 243 /* 244 * For 1 and 2 byte requests we assume a direct value, 245 * everything bigger than 2 bytes we assume a pointer to the data 246 */ 247 switch (size) { 248 case 0: 249 break; 250 case 1: 251 request.data[0] = (long)data & 0x000000ff; 252 break; 253 case 2: 254 request.data[0] = (long)data & 0x000000ff; 255 request.data[1] = (long)data >> 8; 256 break; 257 default: 258 bcopy(data, request.data, size); 259 break; 260 } 261 262 err = atu_usb_request(sc, ATU_VENDOR_DEV_OUT, 0x0e, 0x0000, 263 0x0000, size+8, (uint8_t *)&request); 264 if (err) 265 return (err); 266 267 return (atu_wait_completion(sc, CMD_SET_MIB, NULL)); 268 } 269 270 static int 271 atu_switch_radio(struct atu_softc *sc, boolean_t on) 272 { 273 struct atu_cmd radio; 274 boolean_t ostate; 275 int err; 276 277 /* Intersil doesn't seem to support radio switch */ 278 if (sc->sc_radio == RadioIntersil) 279 return (0); 280 281 ostate = ATU_RADIO_ON(sc) ? B_TRUE : B_FALSE; 282 if (on != ostate) { 283 bzero(&radio, sizeof (radio)); 284 radio.Cmd = on ? CMD_RADIO_ON : CMD_RADIO_OFF; 285 286 err = atu_send_command(sc, (uint8_t *)&radio, 287 sizeof (radio)); 288 if (err) 289 return (err); 290 291 err = atu_wait_completion(sc, radio.Cmd, NULL); 292 if (err) 293 return (err); 294 295 if (on) 296 sc->sc_flags |= ATU_FLAG_RADIO_ON; 297 else 298 sc->sc_flags &= ~ATU_FLAG_RADIO_ON; 299 } 300 301 return (0); 302 } 303 304 static int 305 atu_config(struct atu_softc *sc) 306 { 307 struct ieee80211com *ic = &sc->sc_ic; 308 struct ieee80211_key *k; 309 struct atu_cmd_card_config cmd; 310 uint8_t rates[4] = {0x82, 0x84, 0x8B, 0x96}; 311 int err, i; 312 313 err = atu_send_mib(sc, MIB_MAC_ADDR_STA, ic->ic_macaddr); 314 if (err) { 315 cmn_err(CE_WARN, "%s: setting MAC address failed\n", 316 sc->sc_name); 317 return (err); 318 } 319 320 bzero(&cmd, sizeof (cmd)); 321 cmd.Cmd = CMD_STARTUP; 322 cmd.Reserved = 0; 323 cmd.Size = sizeof (cmd) - 4; 324 cmd.Channel = ATU_DEF_CHAN; 325 cmd.ShortRetryLimit = 7; 326 cmd.RTS_Threshold = 2347; 327 cmd.FragThreshold = 2346; 328 cmd.PromiscuousMode = 1; 329 cmd.AutoRateFallback = 1; 330 bcopy(rates, cmd.BasicRateSet, 4); 331 332 if (ic->ic_flags & IEEE80211_F_PRIVACY) { 333 k = ic->ic_nw_keys + ic->ic_def_txkey; 334 switch (k->wk_keylen) { 335 case 5: 336 cmd.EncryptionType = ATU_ENC_WEP40; 337 break; 338 case 13: 339 cmd.EncryptionType = ATU_ENC_WEP104; 340 break; 341 default: 342 cmn_err(CE_WARN, "%s: key invalid (%d bytes)\n", 343 sc->sc_name, k->wk_keylen); 344 goto nowep; 345 } 346 cmd.PrivacyInvoked = 1; 347 cmd.ExcludeUnencrypted = 1; 348 cmd.WEP_DefaultKeyID = ic->ic_def_txkey; 349 for (i = 0; i < IEEE80211_WEP_NKID; i++) { 350 k = ic->ic_nw_keys + i; 351 if (k->wk_keylen == 0) 352 continue; 353 bcopy(k->wk_key, cmd.WEP_DefaultKey + i, k->wk_keylen); 354 } 355 } else { 356 nowep: 357 cmd.EncryptionType = ATU_ENC_NONE; 358 } 359 360 bcopy(ic->ic_des_essid, cmd.SSID, ic->ic_des_esslen); 361 cmd.SSID_Len = ic->ic_des_esslen; 362 cmd.BeaconPeriod = 100; 363 364 err = atu_send_command(sc, (uint8_t *)&cmd, sizeof (cmd)); 365 if (err) 366 return (err); 367 err = atu_wait_completion(sc, CMD_STARTUP, NULL); 368 if (err) 369 return (err); 370 371 err = atu_switch_radio(sc, B_TRUE); 372 if (err) 373 return (err); 374 375 err = atu_send_mib(sc, MIB_MAC_MGMT_POWER_MODE, 376 (void *)ATU_POWER_ACTIVE); 377 if (err) 378 return (err); 379 380 return (0); 381 } 382 383 static int 384 atu_start_scan(struct atu_softc *sc) 385 { 386 struct ieee80211com *ic = &sc->sc_ic; 387 struct atu_cmd_do_scan scan; 388 int err; 389 390 if (!ATU_RUNNING(sc)) 391 return (EIO); 392 393 bzero(&scan, sizeof (scan)); 394 scan.Cmd = CMD_START_SCAN; 395 scan.Reserved = 0; 396 scan.Size = sizeof (scan) - 4; 397 (void) memset(scan.BSSID, 0xff, sizeof (scan.BSSID)); 398 bcopy(ic->ic_des_essid, scan.SSID, ic->ic_des_esslen); 399 scan.SSID_Len = ic->ic_des_esslen; 400 scan.ScanType = ATU_SCAN_ACTIVE; 401 scan.Channel = ieee80211_chan2ieee(ic, ic->ic_curchan); 402 scan.ProbeDelay = 0; 403 scan.MinChannelTime = 20; 404 scan.MaxChannelTime = 40; 405 scan.InternationalScan = 0; 406 407 err = atu_send_command(sc, (uint8_t *)&scan, sizeof (scan)); 408 if (err) { 409 cmn_err(CE_WARN, "%s: SCAN command failed\n", 410 sc->sc_name); 411 return (err); 412 } 413 414 err = atu_wait_completion(sc, CMD_START_SCAN, NULL); 415 if (err) { 416 cmn_err(CE_WARN, "%s: SCAN completion failed\n", 417 sc->sc_name); 418 return (err); 419 } 420 421 return (0); 422 } 423 424 static int 425 atu_join(struct atu_softc *sc, struct ieee80211_node *node) 426 { 427 struct atu_cmd_join join; 428 uint8_t status; 429 int err; 430 431 bzero(&join, sizeof (join)); 432 join.Cmd = CMD_JOIN; 433 join.Reserved = 0x00; 434 join.Size = sizeof (join) - 4; 435 bcopy(node->in_bssid, join.bssid, IEEE80211_ADDR_LEN); 436 bcopy(node->in_essid, join.essid, node->in_esslen); 437 join.essid_size = node->in_esslen; 438 439 if (node->in_capinfo & IEEE80211_CAPINFO_IBSS) 440 join.bss_type = ATU_MODE_IBSS; 441 else 442 join.bss_type = ATU_MODE_STA; 443 444 join.channel = ieee80211_chan2ieee(&sc->sc_ic, node->in_chan); 445 join.timeout = ATU_JOIN_TIMEOUT; 446 join.reserved = 0x00; 447 448 err = atu_send_command(sc, (uint8_t *)&join, sizeof (join)); 449 if (err) { 450 cmn_err(CE_WARN, "%s: JOIN command failed\n", 451 sc->sc_name); 452 return (err); 453 } 454 err = atu_wait_completion(sc, CMD_JOIN, &status); 455 if (err) 456 return (err); 457 458 if (status != STATUS_COMPLETE) { 459 cmn_err(CE_WARN, "%s: incorrect JOIN state (0x%02x)\n", 460 sc->sc_name, status); 461 return (EIO); 462 } 463 464 return (0); 465 } 466 467 static int 468 atu_newstate(struct ieee80211com *ic, enum ieee80211_state nstate, int arg) 469 { 470 struct atu_softc *sc = (struct atu_softc *)ic; 471 enum ieee80211_state ostate = ic->ic_state; 472 int err = 0; 473 474 ATU_LOCK(sc); 475 476 if (sc->sc_scan_timer != 0) { 477 ATU_UNLOCK(sc); 478 (void) untimeout(sc->sc_scan_timer); 479 ATU_LOCK(sc); 480 sc->sc_scan_timer = 0; 481 } 482 ostate = ic->ic_state; 483 484 switch (nstate) { 485 case IEEE80211_S_SCAN: 486 switch (ostate) { 487 case IEEE80211_S_SCAN: 488 case IEEE80211_S_AUTH: 489 case IEEE80211_S_ASSOC: 490 case IEEE80211_S_RUN: 491 ATU_UNLOCK(sc); 492 sc->sc_newstate(ic, nstate, arg); 493 ATU_LOCK(sc); 494 if ((err = atu_start_scan(sc)) != 0) { 495 ATU_UNLOCK(sc); 496 ieee80211_cancel_scan(ic); 497 return (err); 498 } 499 sc->sc_scan_timer = timeout( 500 (void (*) (void*))ieee80211_next_scan, 501 (void *)&sc->sc_ic, 0); 502 503 ATU_UNLOCK(sc); 504 return (err); 505 default: 506 break; 507 } 508 break; 509 510 case IEEE80211_S_AUTH: 511 switch (ostate) { 512 case IEEE80211_S_INIT: 513 case IEEE80211_S_SCAN: 514 err = atu_join(sc, ic->ic_bss); 515 if (err) { 516 ATU_UNLOCK(sc); 517 return (err); 518 } 519 break; 520 default: 521 break; 522 } 523 default: 524 break; 525 } 526 527 ATU_UNLOCK(sc); 528 err = sc->sc_newstate(ic, nstate, arg); 529 530 return (err); 531 } 532 533 static int 534 atu_open_pipes(struct atu_softc *sc) 535 { 536 usb_ep_data_t *ep; 537 usb_pipe_policy_t policy = {0}; 538 int uret; 539 540 ep = usb_lookup_ep_data(sc->sc_dip, sc->sc_udev, 0, 0, 0, 541 USB_EP_ATTR_BULK, USB_EP_DIR_OUT); 542 policy.pp_max_async_reqs = ATU_TX_LIST_CNT; 543 544 uret = usb_pipe_open(sc->sc_dip, &ep->ep_descr, &policy, 545 USB_FLAGS_SLEEP, &sc->sc_tx_pipe); 546 if (uret != USB_SUCCESS) 547 goto fail; 548 549 ep = usb_lookup_ep_data(sc->sc_dip, sc->sc_udev, 0, 0, 0, 550 USB_EP_ATTR_BULK, USB_EP_DIR_IN); 551 policy.pp_max_async_reqs = ATU_RX_LIST_CNT + 32; 552 553 uret = usb_pipe_open(sc->sc_dip, &ep->ep_descr, &policy, 554 USB_FLAGS_SLEEP, &sc->sc_rx_pipe); 555 if (uret != USB_SUCCESS) 556 goto fail; 557 558 return (0); 559 fail: 560 if (sc->sc_rx_pipe != NULL) { 561 usb_pipe_close(sc->sc_dip, sc->sc_rx_pipe, 562 USB_FLAGS_SLEEP, NULL, 0); 563 sc->sc_rx_pipe = NULL; 564 } 565 566 if (sc->sc_tx_pipe != NULL) { 567 usb_pipe_close(sc->sc_dip, sc->sc_tx_pipe, 568 USB_FLAGS_SLEEP, NULL, 0); 569 sc->sc_tx_pipe = NULL; 570 } 571 572 return (EIO); 573 } 574 575 static void 576 atu_close_pipes(struct atu_softc *sc) 577 { 578 usb_flags_t flags = USB_FLAGS_SLEEP; 579 580 if (sc->sc_rx_pipe != NULL) { 581 usb_pipe_reset(sc->sc_dip, sc->sc_rx_pipe, flags, NULL, 0); 582 usb_pipe_close(sc->sc_dip, sc->sc_rx_pipe, flags, NULL, 0); 583 sc->sc_rx_pipe = NULL; 584 } 585 586 if (sc->sc_tx_pipe != NULL) { 587 usb_pipe_reset(sc->sc_dip, sc->sc_tx_pipe, flags, NULL, 0); 588 usb_pipe_close(sc->sc_dip, sc->sc_tx_pipe, flags, NULL, 0); 589 sc->sc_tx_pipe = NULL; 590 } 591 } 592 593 static int atu_rx_trigger(struct atu_softc *sc); 594 595 /*ARGSUSED*/ 596 static void 597 atu_rxeof(usb_pipe_handle_t pipe, usb_bulk_req_t *req) 598 { 599 struct atu_softc *sc = (struct atu_softc *)req->bulk_client_private; 600 struct ieee80211com *ic = &sc->sc_ic; 601 struct ieee80211_node *ni; 602 struct atu_rx_hdr *h; 603 struct ieee80211_frame *wh; 604 mblk_t *mp = req->bulk_data; 605 int len, pktlen; 606 607 req->bulk_data = NULL; 608 if (req->bulk_completion_reason != USB_CR_OK) { 609 sc->sc_rx_err++; 610 goto fail; 611 } 612 613 len = msgdsize(mp); 614 if (len < ATU_RX_HDRLEN + ATU_MIN_FRAMELEN) { 615 cmn_err(CE_CONT, "%s: fragment (%d bytes)\n", 616 sc->sc_name, len); 617 sc->sc_rx_err++; 618 goto fail; 619 } 620 621 h = (struct atu_rx_hdr *)mp->b_rptr; 622 pktlen = h->length - 4; 623 if (pktlen + ATU_RX_HDRLEN + 4 != len) { 624 cmn_err(CE_CONT, "%s: jumbo (%d bytes -> %d bytes)\n", 625 sc->sc_name, len, pktlen); 626 sc->sc_rx_err++; 627 goto fail; 628 } 629 630 mp->b_rptr += ATU_RX_HDRLEN; 631 mp->b_wptr = mp->b_rptr + pktlen; 632 wh = (struct ieee80211_frame *)mp->b_rptr; 633 634 if (wh->i_fc[1] & IEEE80211_FC1_WEP) 635 wh->i_fc[1] &= ~IEEE80211_FC1_WEP; 636 637 ni = ieee80211_find_rxnode(ic, wh); 638 (void) ieee80211_input(ic, mp, ni, h->rssi, h->rx_time); 639 ieee80211_free_node(ni); 640 done: 641 usb_free_bulk_req(req); 642 643 mutex_enter(&sc->sc_rxlock); 644 sc->rx_queued--; 645 mutex_exit(&sc->sc_rxlock); 646 647 if (ATU_RUNNING(sc)) 648 (void) atu_rx_trigger(sc); 649 return; 650 fail: 651 freemsg(mp); 652 goto done; 653 } 654 655 /*ARGSUSED*/ 656 static void 657 atu_txeof(usb_pipe_handle_t pipe, usb_bulk_req_t *req) 658 { 659 struct atu_softc *sc = (struct atu_softc *)req->bulk_client_private; 660 struct ieee80211com *ic = &sc->sc_ic; 661 662 if (req->bulk_completion_reason != USB_CR_OK) 663 ic->ic_stats.is_tx_failed++; 664 usb_free_bulk_req(req); 665 666 mutex_enter(&sc->sc_txlock); 667 sc->tx_queued--; 668 669 if (sc->sc_need_sched) { 670 sc->sc_need_sched = 0; 671 mac_tx_update(ic->ic_mach); 672 } 673 674 mutex_exit(&sc->sc_txlock); 675 } 676 677 static int 678 atu_rx_trigger(struct atu_softc *sc) 679 { 680 usb_bulk_req_t *req; 681 int uret; 682 683 req = usb_alloc_bulk_req(sc->sc_dip, ATU_RX_BUFSZ, USB_FLAGS_SLEEP); 684 if (req == NULL) 685 return (ENOMEM); 686 687 req->bulk_len = ATU_RX_BUFSZ; 688 req->bulk_client_private = (usb_opaque_t)sc; 689 req->bulk_timeout = 0; 690 req->bulk_attributes = USB_ATTRS_SHORT_XFER_OK | USB_ATTRS_AUTOCLEARING; 691 req->bulk_cb = atu_rxeof; 692 req->bulk_exc_cb = atu_rxeof; 693 req->bulk_completion_reason = 0; 694 req->bulk_cb_flags = 0; 695 696 uret = usb_pipe_bulk_xfer(sc->sc_rx_pipe, req, 0); 697 if (uret != USB_SUCCESS) { 698 usb_free_bulk_req(req); 699 return (EIO); 700 } 701 702 mutex_enter(&sc->sc_rxlock); 703 sc->rx_queued++; 704 mutex_exit(&sc->sc_rxlock); 705 706 return (0); 707 } 708 709 static int 710 atu_tx_trigger(struct atu_softc *sc, mblk_t *mp) 711 { 712 usb_bulk_req_t *req; 713 int uret; 714 715 req = usb_alloc_bulk_req(sc->sc_dip, 0, USB_FLAGS_SLEEP); 716 if (req == NULL) 717 return (EIO); 718 719 req->bulk_len = msgdsize(mp); 720 req->bulk_data = mp; 721 req->bulk_client_private = (usb_opaque_t)sc; 722 req->bulk_timeout = 10; 723 req->bulk_attributes = USB_ATTRS_AUTOCLEARING; 724 req->bulk_cb = atu_txeof; 725 req->bulk_exc_cb = atu_txeof; 726 req->bulk_completion_reason = 0; 727 req->bulk_cb_flags = 0; 728 729 uret = usb_pipe_bulk_xfer(sc->sc_tx_pipe, req, 0); 730 if (uret != USB_SUCCESS) { 731 req->bulk_data = NULL; 732 usb_free_bulk_req(req); 733 return (EIO); 734 } 735 736 mutex_enter(&sc->sc_txlock); 737 sc->tx_queued++; 738 mutex_exit(&sc->sc_txlock); 739 740 return (0); 741 } 742 743 static int 744 atu_init_rx_queue(struct atu_softc *sc) 745 { 746 int err, i; 747 748 mutex_enter(&sc->sc_rxlock); 749 sc->rx_queued = 0; 750 mutex_exit(&sc->sc_rxlock); 751 752 for (i = 0; i < ATU_RX_LIST_CNT; i++) { 753 err = atu_rx_trigger(sc); 754 if (err) 755 return (err); 756 } 757 758 return (0); 759 } 760 761 static void 762 atu_init_tx_queue(struct atu_softc *sc) 763 { 764 mutex_enter(&sc->sc_txlock); 765 sc->tx_queued = 0; 766 mutex_exit(&sc->sc_txlock); 767 } 768 769 static int 770 atu_send(ieee80211com_t *ic, mblk_t *mp, uint8_t type) 771 { 772 struct atu_softc *sc = (struct atu_softc *)ic; 773 struct ieee80211_node *ni = NULL; 774 struct atu_tx_hdr *desc; 775 struct ieee80211_frame *wh; 776 mblk_t *m; 777 int pktlen = msgdsize(mp), err = 0; 778 779 mutex_enter(&sc->sc_txlock); 780 if (sc->tx_queued > ATU_TX_LIST_CNT) { 781 sc->sc_tx_nobuf++; 782 mutex_exit(&sc->sc_txlock); 783 err = ENOMEM; 784 goto fail; 785 } 786 mutex_exit(&sc->sc_txlock); 787 788 m = allocb(ATU_TX_BUFSZ, BPRI_MED); 789 if (m == NULL) { 790 sc->sc_tx_nobuf++; 791 err = ENOMEM; 792 goto fail; 793 } 794 /* reserve tx header space */ 795 m->b_rptr += ATU_TX_HDRLEN; 796 m->b_wptr += ATU_TX_HDRLEN; 797 798 /* copy and (implicitly) free old data */ 799 mcopymsg(mp, m->b_wptr); 800 m->b_wptr += pktlen; 801 wh = (struct ieee80211_frame *)m->b_rptr; 802 803 ni = ieee80211_find_txnode(ic, wh->i_addr1); 804 if (ni == NULL) { 805 ic->ic_stats.is_tx_failed++; 806 freemsg(m); 807 err = ENXIO; 808 goto fail; 809 } 810 811 if (type == IEEE80211_FC0_TYPE_DATA) 812 (void) ieee80211_encap(ic, m, ni); 813 814 /* full WEP in device, prune WEP fields (IV, KID) */ 815 if (wh->i_fc[1] & IEEE80211_FC1_WEP) { 816 (void) memmove(m->b_rptr + IEEE80211_WEP_IVLEN 817 + IEEE80211_WEP_KIDLEN, m->b_rptr, 818 sizeof (struct ieee80211_frame)); 819 m->b_rptr += IEEE80211_WEP_IVLEN + IEEE80211_WEP_KIDLEN; 820 } 821 pktlen = msgdsize(m); 822 m->b_rptr -= ATU_TX_HDRLEN; 823 824 /* setup tx header */ 825 desc = (struct atu_tx_hdr *)m->b_rptr; 826 bzero(desc, ATU_TX_HDRLEN); 827 desc->length = (uint16_t)pktlen; 828 desc->tx_rate = ATU_DEF_TX_RATE; 829 830 err = atu_tx_trigger(sc, m); 831 if (!err) { 832 ic->ic_stats.is_tx_frags++; 833 ic->ic_stats.is_tx_bytes += pktlen; 834 } else { 835 ic->ic_stats.is_tx_failed++; 836 freemsg(m); 837 } 838 fail: 839 if (ni != NULL) 840 ieee80211_free_node(ni); 841 842 return (err); 843 } 844 845 static int 846 atu_stop(struct atu_softc *sc) 847 { 848 sc->sc_flags &= ~ATU_FLAG_RUNNING; 849 atu_close_pipes(sc); 850 851 return (atu_switch_radio(sc, B_FALSE)); 852 } 853 854 static int 855 atu_init(struct atu_softc *sc) 856 { 857 int err; 858 859 err = atu_stop(sc); 860 if (err) 861 return (err); 862 863 err = atu_open_pipes(sc); 864 if (err) 865 goto fail; 866 867 err = atu_config(sc); 868 if (err) { 869 cmn_err(CE_WARN, "%s: startup config failed\n", 870 sc->sc_name); 871 goto fail; 872 } 873 874 atu_init_tx_queue(sc); 875 876 err = atu_init_rx_queue(sc); 877 if (err) { 878 cmn_err(CE_WARN, "%s: rx queue init failed\n", sc->sc_name); 879 goto fail; 880 } 881 882 sc->sc_flags |= ATU_FLAG_RUNNING; 883 884 return (0); 885 fail: 886 (void) atu_stop(sc); 887 return (err); 888 } 889 890 static void 891 atu_watchdog(void *arg) 892 { 893 struct atu_softc *sc = arg; 894 struct ieee80211com *ic = &sc->sc_ic; 895 896 ieee80211_stop_watchdog(ic); 897 898 ATU_LOCK(sc); 899 if (!ATU_RUNNING(sc)) { 900 ATU_UNLOCK(sc); 901 return; 902 } 903 904 ATU_UNLOCK(sc); 905 switch (ic->ic_state) { 906 case IEEE80211_S_AUTH: 907 case IEEE80211_S_ASSOC: 908 if (ic->ic_bss->in_fails > 0) 909 ieee80211_new_state(ic, IEEE80211_S_INIT, -1); 910 else 911 ieee80211_watchdog(ic); 912 break; 913 } 914 } 915 916 static int 917 atu_dfu_stage1(void *arg) 918 { 919 struct atu_softc *sc = arg; 920 uint8_t state, *ptr = NULL, status[6]; 921 int block_size, bytes_left = 0, block = 0, err, i, count = 0; 922 923 /* 924 * Uploading firmware is done with the DFU (Device Firmware Upgrade) 925 * interface. See "Universal Serial Bus - Device Class Specification 926 * for Device Firmware Upgrade" pdf for details of the protocol. 927 * Maybe this could be moved to a separate 'firmware driver' once more 928 * device drivers need it... For now we'll just do it here. 929 * 930 * Just for your information, the Atmel's DFU descriptor looks like 931 * this: 932 * 933 * 07 size 934 * 21 type 935 * 01 capabilities : only firmware download, *need* reset 936 * after download 937 * 13 05 detach timeout : max 1299ms between DFU_DETACH and 938 * reset 939 * 00 04 max bytes of firmware per transaction : 1024 940 */ 941 for (i = 0; i < sizeof (atu_fw_table) / sizeof (atu_fw_table[0]); i++) 942 if (sc->sc_radio == atu_fw_table[i].atur_type) { 943 ptr = atu_fw_table[i].atur_int; 944 bytes_left = atu_fw_table[i].atur_int_size; 945 } 946 947 state = atu_get_dfu_state(sc); 948 while (block >= 0 && state > 0) { 949 switch (state) { 950 case DFUState_DnLoadSync: 951 /* get DFU status */ 952 err = atu_usb_request(sc, DFU_GETSTATUS, 0, 0, 6, 953 status); 954 if (err) { 955 cmn_err(CE_WARN, "%s: DFU get status failed\n", 956 sc->sc_name); 957 return (err); 958 } 959 /* success means state => DnLoadIdle */ 960 state = DFUState_DnLoadIdle; 961 continue; 962 963 case DFUState_DFUIdle: 964 case DFUState_DnLoadIdle: 965 if (bytes_left >= DFU_MaxBlockSize) 966 block_size = DFU_MaxBlockSize; 967 else 968 block_size = bytes_left; 969 970 err = atu_usb_request(sc, DFU_DNLOAD, block++, 0, 971 block_size, ptr); 972 if (err) { 973 cmn_err(CE_WARN, "%s: DFU download failed\n", 974 sc->sc_name); 975 return (err); 976 } 977 978 ptr += block_size; 979 bytes_left -= block_size; 980 if (block_size == 0) 981 block = -1; 982 break; 983 984 case DFUState_DFUError: 985 cmn_err(CE_WARN, "%s: DFU state error\n", sc->sc_name); 986 return (EIO); 987 988 default: 989 drv_usecwait(10*1000); 990 if (++count > 100) { 991 cmn_err(CE_WARN, "%s: DFU timeout\n", 992 sc->sc_name); 993 return (ETIME); 994 } 995 break; 996 } 997 998 state = atu_get_dfu_state(sc); 999 } 1000 if (state != DFUState_ManifestSync) 1001 cmn_err(CE_WARN, "%s: DFU state (%d) != ManifestSync\n", 1002 sc->sc_name, state); 1003 1004 err = atu_usb_request(sc, DFU_GETSTATUS, 0, 0, 6, status); 1005 if (err) { 1006 cmn_err(CE_WARN, "%s: DFU get status failed\n", 1007 sc->sc_name); 1008 return (err); 1009 } 1010 1011 err = atu_usb_request(sc, DFU_REMAP, 0, 0, 0, NULL); 1012 if (err && !(sc->sc_quirk & ATU_QUIRK_NO_REMAP)) { 1013 cmn_err(CE_WARN, "%s: DFU remap failed\n", sc->sc_name); 1014 return (err); 1015 } 1016 1017 /* 1018 * after a lot of trying and measuring I found out the device needs 1019 * about 56 miliseconds after sending the remap command before 1020 * it's ready to communicate again. So we'll wait just a little bit 1021 * longer than that to be sure... 1022 */ 1023 drv_usecwait((56+100)*1000); 1024 1025 return (0); 1026 } 1027 1028 static int 1029 atu_dfu_stage2(void *arg) 1030 { 1031 struct atu_softc *sc = arg; 1032 uint8_t *ptr = NULL; 1033 int block_size, bytes_left = 0, block = 0, err, i; 1034 1035 for (i = 0; i < sizeof (atu_fw_table) / sizeof (atu_fw_table[0]); i++) 1036 if (sc->sc_radio == atu_fw_table[i].atur_type) { 1037 ptr = atu_fw_table[i].atur_ext; 1038 bytes_left = atu_fw_table[i].atur_ext_size; 1039 } 1040 1041 while (bytes_left) { 1042 if (bytes_left > 1024) 1043 block_size = 1024; 1044 else 1045 block_size = bytes_left; 1046 1047 err = atu_usb_request(sc, ATU_VENDOR_DEV_OUT, 0x0e, 1048 0x0802, block, block_size, ptr); 1049 if (err) { 1050 cmn_err(CE_WARN, "%s: stage2 firmware load failed\n", 1051 sc->sc_name); 1052 return (err); 1053 } 1054 1055 ptr += block_size; 1056 block++; 1057 bytes_left -= block_size; 1058 } 1059 1060 err = atu_usb_request(sc, ATU_VENDOR_DEV_OUT, 0x0e, 0x0802, 1061 block, 0, NULL); 1062 if (err) { 1063 cmn_err(CE_WARN, "%s: zero-length block load failed\n", 1064 sc->sc_name); 1065 return (err); 1066 } 1067 1068 /* 1069 * The SMC2662w V.4 seems to require some time to do its thing with 1070 * the stage2 firmware... 20 ms isn't enough, but 21 ms works 100 1071 * times out of 100 tries. We'll wait a bit longer just to be sure 1072 */ 1073 if (sc->sc_quirk & ATU_QUIRK_FW_DELAY) 1074 drv_usecwait((21 + 100) * 1000); 1075 1076 return (0); 1077 } 1078 1079 static int 1080 atu_load_microcode(struct atu_softc *sc, boolean_t attach) 1081 { 1082 usb_dev_reset_lvl_t reset; 1083 uint8_t mode, chan; 1084 int err; 1085 1086 reset = attach ? USB_RESET_LVL_REATTACH : USB_RESET_LVL_DEFAULT; 1087 1088 err = atu_get_opmode(sc, &mode); 1089 if (!err) { 1090 if (mode == ATU_DEV_READY) 1091 return (0); 1092 /* 1093 * Opmode of SMC2662 V.4 does not change after stage2 1094 * firmware download. If succeeded reading the channel 1095 * number, stage2 firmware is already running. 1096 */ 1097 if (sc->sc_radio != RadioIntersil && 1098 atu_get_mib(sc, MIB_PHY_CHANNEL, &chan) == 0) 1099 return (0); 1100 1101 if (mode == ATU_DEV_STAGE2) 1102 stage2: 1103 return (atu_dfu_stage2(sc)); 1104 } 1105 1106 err = atu_dfu_stage1(sc); 1107 if (err) 1108 return (err); 1109 1110 if (usb_reset_device(sc->sc_dip, reset) != USB_SUCCESS) 1111 return (EIO); 1112 1113 if (attach) 1114 return (EAGAIN); 1115 else 1116 goto stage2; 1117 } 1118 1119 static int 1120 atu_disconnect(dev_info_t *dip) 1121 { 1122 struct atu_softc *sc; 1123 struct ieee80211com *ic; 1124 1125 sc = ddi_get_soft_state(atu_soft_state_p, ddi_get_instance(dip)); 1126 ic = &sc->sc_ic; 1127 1128 ieee80211_new_state(ic, IEEE80211_S_INIT, -1); 1129 ieee80211_stop_watchdog(ic); 1130 1131 ATU_LOCK(sc); 1132 if (sc->sc_scan_timer != 0) { 1133 ATU_UNLOCK(sc); 1134 (void) untimeout(sc->sc_scan_timer); 1135 ATU_LOCK(sc); 1136 sc->sc_scan_timer = 0; 1137 } 1138 1139 sc->sc_flags &= ~(ATU_FLAG_RUNNING | ATU_FLAG_RADIO_ON); 1140 atu_close_pipes(sc); 1141 1142 ATU_UNLOCK(sc); 1143 return (0); 1144 } 1145 1146 static int 1147 atu_reconnect(dev_info_t *dip) 1148 { 1149 struct atu_softc *sc; 1150 int err; 1151 1152 sc = ddi_get_soft_state(atu_soft_state_p, ddi_get_instance(dip)); 1153 if (usb_check_same_device(sc->sc_dip, NULL, USB_LOG_L2, -1, 1154 USB_CHK_BASIC, NULL) != USB_SUCCESS) 1155 return (DDI_FAILURE); 1156 1157 ATU_LOCK(sc); 1158 err = atu_load_microcode(sc, B_FALSE); 1159 if (!err) 1160 err = atu_init(sc); 1161 1162 ATU_UNLOCK(sc); 1163 return (err ? DDI_FAILURE : DDI_SUCCESS); 1164 } 1165 1166 static int 1167 atu_attach(dev_info_t *dip, ddi_attach_cmd_t cmd) 1168 { 1169 struct atu_softc *sc; 1170 struct ieee80211com *ic; 1171 mac_register_t *macp; 1172 wifi_data_t wd = {0}; 1173 int instance, i, err; 1174 1175 switch (cmd) { 1176 case DDI_ATTACH: 1177 break; 1178 case DDI_RESUME: 1179 sc = ddi_get_soft_state(atu_soft_state_p, 1180 ddi_get_instance(dip)); 1181 if (usb_check_same_device(sc->sc_dip, NULL, USB_LOG_L2, -1, 1182 USB_CHK_BASIC, NULL) != USB_SUCCESS) 1183 return (DDI_SUCCESS); 1184 1185 if (atu_load_microcode(sc, B_FALSE) == 0) 1186 (void) atu_init(sc); 1187 1188 return (DDI_SUCCESS); 1189 default: 1190 return (DDI_FAILURE); 1191 } 1192 1193 instance = ddi_get_instance(dip); 1194 if (ddi_soft_state_zalloc(atu_soft_state_p, instance) != DDI_SUCCESS) 1195 return (DDI_FAILURE); 1196 1197 sc = ddi_get_soft_state(atu_soft_state_p, instance); 1198 ic = &sc->sc_ic; 1199 sc->sc_dip = dip; 1200 1201 (void) snprintf(sc->sc_name, sizeof (sc->sc_name), "%s%d", 1202 "atu", instance); 1203 1204 err = usb_client_attach(dip, USBDRV_VERSION, 0); 1205 if (err != USB_SUCCESS) 1206 goto fail1; 1207 1208 err = usb_get_dev_data(dip, &sc->sc_udev, USB_PARSE_LVL_ALL, 0); 1209 if (err != USB_SUCCESS) { 1210 sc->sc_udev = NULL; 1211 goto fail2; 1212 } 1213 1214 for (i = 0; i < sizeof (atu_dev_table)/sizeof (atu_dev_table[0]); i++) { 1215 struct atu_dev_type *t = &atu_dev_table[i]; 1216 if (sc->sc_udev->dev_descr->idVendor == t->atu_vid && 1217 sc->sc_udev->dev_descr->idProduct == t->atu_pid) { 1218 sc->sc_radio = t->atu_radio; 1219 sc->sc_quirk = t->atu_quirk; 1220 } 1221 } 1222 1223 err = atu_load_microcode(sc, B_TRUE); 1224 if (err == EAGAIN) { 1225 sc->sc_flags |= ATU_FLAG_REATTACH; /* reattaching */ 1226 return (DDI_SUCCESS); 1227 } else if (err) { 1228 goto fail2; 1229 } 1230 sc->sc_flags &= ~ATU_FLAG_REATTACH; 1231 1232 /* read device config & MAC address */ 1233 err = atu_get_config(sc); 1234 if (err) { 1235 cmn_err(CE_WARN, "%s: read device config failed\n", 1236 sc->sc_name); 1237 goto fail2; 1238 } 1239 1240 mutex_init(&sc->sc_genlock, NULL, MUTEX_DRIVER, NULL); 1241 mutex_init(&sc->sc_txlock, NULL, MUTEX_DRIVER, NULL); 1242 mutex_init(&sc->sc_rxlock, NULL, MUTEX_DRIVER, NULL); 1243 1244 ic->ic_phytype = IEEE80211_T_DS; 1245 ic->ic_opmode = IEEE80211_M_STA; 1246 ic->ic_caps = IEEE80211_C_SHPREAMBLE | IEEE80211_C_WEP; 1247 ic->ic_sup_rates[IEEE80211_MODE_11B] = atu_rateset; 1248 ic->ic_maxrssi = atu_fw_table[sc->sc_radio].max_rssi; 1249 ic->ic_state = IEEE80211_S_INIT; 1250 for (i = 1; i <= 14; i++) { 1251 ic->ic_sup_channels[i].ich_freq = 1252 ieee80211_ieee2mhz(i, IEEE80211_CHAN_2GHZ); 1253 ic->ic_sup_channels[i].ich_flags = 1254 IEEE80211_CHAN_CCK | IEEE80211_CHAN_2GHZ | 1255 IEEE80211_CHAN_PASSIVE; 1256 } 1257 ic->ic_xmit = atu_send; 1258 ieee80211_attach(ic); 1259 1260 sc->sc_newstate = ic->ic_newstate; 1261 ic->ic_newstate = atu_newstate; 1262 ic->ic_watchdog = atu_watchdog; 1263 ieee80211_media_init(ic); 1264 1265 ic->ic_def_txkey = 0; 1266 wd.wd_opmode = ic->ic_opmode; 1267 wd.wd_secalloc = WIFI_SEC_NONE; 1268 IEEE80211_ADDR_COPY(wd.wd_bssid, ic->ic_bss->in_bssid); 1269 1270 macp = mac_alloc(MAC_VERSION); 1271 if (macp == NULL) 1272 goto fail3; 1273 1274 macp->m_type_ident = MAC_PLUGIN_IDENT_WIFI; 1275 macp->m_driver = sc; 1276 macp->m_dip = dip; 1277 macp->m_src_addr = ic->ic_macaddr; 1278 macp->m_callbacks = &atu_m_callbacks; 1279 macp->m_min_sdu = 0; 1280 macp->m_max_sdu = IEEE80211_MTU; 1281 macp->m_pdata = &wd; 1282 macp->m_pdata_size = sizeof (wd); 1283 1284 err = mac_register(macp, &ic->ic_mach); 1285 mac_free(macp); 1286 if (err) 1287 goto fail3; 1288 1289 err = usb_register_hotplug_cbs(sc->sc_dip, atu_disconnect, 1290 atu_reconnect); 1291 if (err != USB_SUCCESS) 1292 goto fail4; 1293 1294 err = ddi_create_minor_node(dip, sc->sc_name, S_IFCHR, 1295 instance + 1, DDI_NT_NET_WIFI, 0); 1296 if (err != DDI_SUCCESS) 1297 cmn_err(CE_WARN, "%s: minor node creation failed\n", 1298 sc->sc_name); 1299 1300 mac_link_update(ic->ic_mach, LINK_STATE_DOWN); 1301 return (DDI_SUCCESS); 1302 1303 fail4: 1304 (void) mac_unregister(ic->ic_mach); 1305 fail3: 1306 mutex_destroy(&sc->sc_genlock); 1307 mutex_destroy(&sc->sc_rxlock); 1308 mutex_destroy(&sc->sc_txlock); 1309 fail2: 1310 usb_client_detach(sc->sc_dip, sc->sc_udev); 1311 fail1: 1312 ddi_soft_state_free(atu_soft_state_p, instance); 1313 1314 return (DDI_FAILURE); 1315 } 1316 1317 static int 1318 atu_detach(dev_info_t *dip, ddi_detach_cmd_t cmd) 1319 { 1320 struct atu_softc *sc; 1321 int err; 1322 1323 sc = ddi_get_soft_state(atu_soft_state_p, ddi_get_instance(dip)); 1324 1325 switch (cmd) { 1326 case DDI_DETACH: 1327 break; 1328 case DDI_SUSPEND: 1329 ieee80211_new_state(&sc->sc_ic, IEEE80211_S_INIT, -1); 1330 ieee80211_stop_watchdog(&sc->sc_ic); 1331 1332 ATU_LOCK(sc); 1333 if (sc->sc_scan_timer != 0) { 1334 ATU_UNLOCK(sc); 1335 (void) untimeout(sc->sc_scan_timer); 1336 ATU_LOCK(sc); 1337 sc->sc_scan_timer = 0; 1338 } 1339 (void) atu_stop(sc); 1340 1341 ATU_UNLOCK(sc); 1342 return (DDI_SUCCESS); 1343 default: 1344 return (DDI_FAILURE); 1345 } 1346 1347 if (!ATU_REATTACH(sc)) { 1348 err = mac_disable(sc->sc_ic.ic_mach); 1349 if (err) 1350 return (DDI_FAILURE); 1351 1352 (void) atu_stop(sc); 1353 1354 usb_unregister_hotplug_cbs(dip); 1355 (void) mac_unregister(sc->sc_ic.ic_mach); 1356 ieee80211_detach(&sc->sc_ic); 1357 1358 mutex_destroy(&sc->sc_genlock); 1359 mutex_destroy(&sc->sc_txlock); 1360 mutex_destroy(&sc->sc_rxlock); 1361 1362 ddi_remove_minor_node(dip, NULL); 1363 } 1364 1365 usb_client_detach(dip, sc->sc_udev); 1366 ddi_soft_state_free(atu_soft_state_p, ddi_get_instance(dip)); 1367 1368 return (DDI_SUCCESS); 1369 } 1370 1371 DDI_DEFINE_STREAM_OPS(atu_dev_ops, nulldev, nulldev, atu_attach, 1372 atu_detach, nodev, NULL, D_MP, NULL, ddi_quiesce_not_needed); 1373 1374 static struct modldrv atu_modldrv = { 1375 &mod_driverops, 1376 "atu driver v1.1", 1377 &atu_dev_ops 1378 }; 1379 1380 static struct modlinkage modlinkage = { 1381 MODREV_1, 1382 (void *)&atu_modldrv, 1383 NULL 1384 }; 1385 1386 int 1387 _info(struct modinfo *modinfop) 1388 { 1389 return (mod_info(&modlinkage, modinfop)); 1390 } 1391 1392 int 1393 _init(void) 1394 { 1395 int status; 1396 1397 status = ddi_soft_state_init(&atu_soft_state_p, 1398 sizeof (struct atu_softc), 1); 1399 if (status != 0) 1400 return (status); 1401 1402 mac_init_ops(&atu_dev_ops, "atu"); 1403 status = mod_install(&modlinkage); 1404 if (status != 0) { 1405 mac_fini_ops(&atu_dev_ops); 1406 ddi_soft_state_fini(&atu_soft_state_p); 1407 } 1408 return (status); 1409 } 1410 1411 int 1412 _fini(void) 1413 { 1414 int status; 1415 1416 status = mod_remove(&modlinkage); 1417 if (status == 0) { 1418 mac_fini_ops(&atu_dev_ops); 1419 ddi_soft_state_fini(&atu_soft_state_p); 1420 } 1421 return (status); 1422 } 1423 1424 static int 1425 atu_m_start(void *arg) 1426 { 1427 struct atu_softc *sc = (struct atu_softc *)arg; 1428 int err; 1429 1430 ATU_LOCK(sc); 1431 err = atu_init(sc); 1432 1433 ATU_UNLOCK(sc); 1434 return (err); 1435 } 1436 1437 static void 1438 atu_m_stop(void *arg) 1439 { 1440 struct atu_softc *sc = (struct atu_softc *)arg; 1441 struct ieee80211com *ic = &sc->sc_ic; 1442 1443 ieee80211_new_state(ic, IEEE80211_S_INIT, -1); 1444 ieee80211_stop_watchdog(ic); 1445 1446 ATU_LOCK(sc); 1447 if (sc->sc_scan_timer != 0) { 1448 ATU_UNLOCK(sc); 1449 (void) untimeout(sc->sc_scan_timer); 1450 ATU_LOCK(sc); 1451 sc->sc_scan_timer = 0; 1452 } 1453 (void) atu_stop(sc); 1454 1455 ATU_UNLOCK(sc); 1456 } 1457 1458 /*ARGSUSED*/ 1459 static int 1460 atu_m_unicst(void *arg, const uint8_t *macaddr) 1461 { 1462 return (ENOTSUP); 1463 } 1464 1465 /*ARGSUSED*/ 1466 static int 1467 atu_m_multicst(void *arg, boolean_t add, const uint8_t *mca) 1468 { 1469 return (ENOTSUP); 1470 } 1471 1472 /*ARGSUSED*/ 1473 static int 1474 atu_m_promisc(void *arg, boolean_t on) 1475 { 1476 return (0); 1477 } 1478 1479 static int 1480 atu_m_setprop(void *arg, const char *name, mac_prop_id_t id, uint_t len, 1481 const void *buf) 1482 { 1483 struct atu_softc *sc = (struct atu_softc *)arg; 1484 struct ieee80211com *ic = &sc->sc_ic; 1485 int err; 1486 1487 err = ieee80211_setprop(ic, name, id, len, buf); 1488 if (err != ENETRESET) 1489 return (err); 1490 if (ic->ic_des_esslen == 0) 1491 return (0); 1492 1493 ATU_LOCK(sc); 1494 if (ATU_RUNNING(sc)) { 1495 if (sc->sc_scan_timer != 0) { 1496 ATU_UNLOCK(sc); 1497 (void) untimeout(sc->sc_scan_timer); 1498 ATU_LOCK(sc); 1499 sc->sc_scan_timer = 0; 1500 } 1501 err = atu_init(sc); 1502 1503 ATU_UNLOCK(sc); 1504 if (err) 1505 return (err); 1506 ieee80211_new_state(ic, IEEE80211_S_SCAN, -1); 1507 ATU_LOCK(sc); 1508 } 1509 1510 ATU_UNLOCK(sc); 1511 return (0); 1512 } 1513 1514 static void 1515 atu_m_ioctl(void* arg, queue_t *wq, mblk_t *mp) 1516 { 1517 struct atu_softc *sc = (struct atu_softc *)arg; 1518 struct ieee80211com *ic = &sc->sc_ic; 1519 int err; 1520 1521 err = ieee80211_ioctl(ic, wq, mp); 1522 if (err != ENETRESET || ic->ic_des_esslen == 0) 1523 return; 1524 1525 ATU_LOCK(sc); 1526 if (ATU_RUNNING(sc)) { 1527 if (sc->sc_scan_timer != 0) { 1528 ATU_UNLOCK(sc); 1529 (void) untimeout(sc->sc_scan_timer); 1530 ATU_LOCK(sc); 1531 sc->sc_scan_timer = 0; 1532 } 1533 err = atu_init(sc); 1534 1535 ATU_UNLOCK(sc); 1536 if (err) 1537 return; 1538 ieee80211_new_state(ic, IEEE80211_S_SCAN, -1); 1539 ATU_LOCK(sc); 1540 } 1541 1542 ATU_UNLOCK(sc); 1543 } 1544 1545 static mblk_t * 1546 atu_m_tx(void *arg, mblk_t *mp) 1547 { 1548 struct atu_softc *sc = (struct atu_softc *)arg; 1549 struct ieee80211com *ic = &sc->sc_ic; 1550 mblk_t *next; 1551 1552 if (ic->ic_state != IEEE80211_S_RUN) { 1553 freemsgchain(mp); 1554 return (NULL); 1555 } 1556 1557 while (mp != NULL) { 1558 next = mp->b_next; 1559 mp->b_next = NULL; 1560 if (atu_send(ic, mp, IEEE80211_FC0_TYPE_DATA) == ENOMEM) { 1561 mutex_enter(&sc->sc_txlock); 1562 sc->sc_need_sched = 1; 1563 mutex_exit(&sc->sc_txlock); 1564 1565 mp->b_next = next; 1566 return (mp); 1567 } 1568 mp = next; 1569 } 1570 1571 return (mp); 1572 } 1573 1574 static int 1575 atu_m_stat(void *arg, uint_t stat, uint64_t *val) 1576 { 1577 struct atu_softc *sc = (struct atu_softc *)arg; 1578 ieee80211com_t *ic = &sc->sc_ic; 1579 ieee80211_node_t *in; 1580 1581 ATU_LOCK(sc); 1582 switch (stat) { 1583 case MAC_STAT_IFSPEED: 1584 in = ic->ic_bss; 1585 *val = ((ic->ic_fixed_rate == IEEE80211_FIXED_RATE_NONE) ? 1586 IEEE80211_RATE(in->in_txrate) : 1587 ic->ic_fixed_rate) / 2 * 1000000; 1588 break; 1589 case MAC_STAT_NOXMTBUF: 1590 *val = sc->sc_tx_nobuf; 1591 break; 1592 case MAC_STAT_NORCVBUF: 1593 *val = sc->sc_rx_nobuf; 1594 break; 1595 case MAC_STAT_IERRORS: 1596 *val = sc->sc_rx_err; 1597 break; 1598 case MAC_STAT_RBYTES: 1599 *val = ic->ic_stats.is_rx_bytes; 1600 break; 1601 case MAC_STAT_IPACKETS: 1602 *val = ic->ic_stats.is_rx_frags; 1603 break; 1604 case MAC_STAT_OBYTES: 1605 *val = ic->ic_stats.is_tx_bytes; 1606 break; 1607 case MAC_STAT_OPACKETS: 1608 *val = ic->ic_stats.is_tx_frags; 1609 break; 1610 case MAC_STAT_OERRORS: 1611 *val = ic->ic_stats.is_tx_failed; 1612 break; 1613 case WIFI_STAT_TX_FRAGS: 1614 case WIFI_STAT_MCAST_TX: 1615 case WIFI_STAT_TX_FAILED: 1616 case WIFI_STAT_TX_RETRANS: 1617 case WIFI_STAT_TX_RERETRANS: 1618 case WIFI_STAT_RTS_SUCCESS: 1619 case WIFI_STAT_RTS_FAILURE: 1620 case WIFI_STAT_ACK_FAILURE: 1621 case WIFI_STAT_RX_FRAGS: 1622 case WIFI_STAT_MCAST_RX: 1623 case WIFI_STAT_FCS_ERRORS: 1624 case WIFI_STAT_WEP_ERRORS: 1625 case WIFI_STAT_RX_DUPS: 1626 ATU_UNLOCK(sc); 1627 return (ieee80211_stat(ic, stat, val)); 1628 default: 1629 ATU_UNLOCK(sc); 1630 return (ENOTSUP); 1631 } 1632 1633 ATU_UNLOCK(sc); 1634 return (0); 1635 } 1636 1637 static mac_callbacks_t atu_m_callbacks = { 1638 MC_IOCTL | MC_SETPROP | MC_GETPROP, 1639 atu_m_stat, 1640 atu_m_start, 1641 atu_m_stop, 1642 atu_m_promisc, 1643 atu_m_multicst, 1644 atu_m_unicst, 1645 atu_m_tx, 1646 atu_m_ioctl, 1647 NULL, 1648 NULL, 1649 NULL, 1650 atu_m_setprop, 1651 ieee80211_getprop 1652 }; 1653