1 /* 2 * Copyright 2010 Sun Microsystems, Inc. All rights reserved. 3 * Use is subject to license terms. 4 */ 5 6 /* 7 * Copyright 2019 Joyent, Inc. 8 */ 9 10 /* 11 * Copyright (c) 2006 Sam Leffler, Errno Consulting 12 * Copyright (c) 2008-2009 Weongyo Jeong <weongyo@freebsd.org> 13 * All rights reserved. 14 * 15 * Redistribution and use in source and binary forms, with or without 16 * modification, are permitted provided that the following conditions 17 * are met: 18 * 1. Redistributions of source code must retain the above copyright 19 * notice, this list of conditions and the following disclaimer, 20 * without modification. 21 * 2. Redistributions in binary form must reproduce at minimum a disclaimer 22 * similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any 23 * redistribution must be conditioned upon including a substantially 24 * similar Disclaimer requirement for further binary redistribution. 25 * 26 * NO WARRANTY 27 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 28 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 29 * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY 30 * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL 31 * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, 32 * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 33 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 34 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER 35 * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 36 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 37 * THE POSSIBILITY OF SUCH DAMAGES. 38 */ 39 40 /* 41 * This driver is distantly derived from a driver of the same name 42 * by Damien Bergamini. The original copyright is included below: 43 * 44 * Copyright (c) 2006 45 * Damien Bergamini <damien.bergamini@free.fr> 46 * 47 * Permission to use, copy, modify, and distribute this software for any 48 * purpose with or without fee is hereby granted, provided that the above 49 * copyright notice and this permission notice appear in all copies. 50 * 51 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 52 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 53 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 54 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 55 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 56 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 57 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 58 */ 59 60 61 #include <sys/types.h> 62 #include <sys/cmn_err.h> 63 #include <sys/strsubr.h> 64 #include <sys/strsun.h> 65 #include <sys/modctl.h> 66 #include <sys/devops.h> 67 #include <sys/byteorder.h> 68 #include <sys/mac_provider.h> 69 #include <sys/mac_wifi.h> 70 #include <sys/net80211.h> 71 72 #define USBDRV_MAJOR_VER 2 73 #define USBDRV_MINOR_VER 0 74 #include <sys/usb/usba.h> 75 #include <sys/usb/usba/usba_types.h> 76 77 #include "uath_reg.h" 78 #include "uath_var.h" 79 80 static void *uath_soft_state_p = NULL; 81 82 /* 83 * Bit flags in the ral_dbg_flags 84 */ 85 #define UATH_DBG_MSG 0x000001 86 #define UATH_DBG_ERR 0x000002 87 #define UATH_DBG_USB 0x000004 88 #define UATH_DBG_TX 0x000008 89 #define UATH_DBG_RX 0x000010 90 #define UATH_DBG_FW 0x000020 91 #define UATH_DBG_TX_CMD 0x000040 92 #define UATH_DBG_RX_CMD 0x000080 93 #define UATH_DBG_ALL 0x000fff 94 95 uint32_t uath_dbg_flags = 0; 96 97 #ifdef DEBUG 98 #define UATH_DEBUG \ 99 uath_debug 100 #else 101 #define UATH_DEBUG(...) (void)(0) 102 #endif 103 104 /* 105 * Various supported device vendors/products. 106 * UB51: AR5005UG 802.11b/g, UB52: AR5005UX 802.11b/g 107 */ 108 #define UATH_FLAG_PRE_FIRMWARE (1 << 0) 109 #define UATH_FLAG_ABG (1 << 1) 110 #define UATH_FLAG_ERR (1 << 2) 111 #define UATH_DEV(v, p, f) \ 112 { { USB_VENDOR_##v, USB_PRODUCT_##v##_##p }, (f) }, \ 113 { { USB_VENDOR_##v, USB_PRODUCT_##v##_##p##_NF }, \ 114 (f) | UATH_FLAG_PRE_FIRMWARE } 115 #define UATH_DEV_UG(v, p) UATH_DEV(v, p, 0) 116 #define UATH_DEV_UX(v, p) UATH_DEV(v, p, UATH_FLAG_ABG) 117 118 struct uath_devno { 119 uint16_t vendor_id; 120 uint16_t product_id; 121 }; 122 123 static const struct uath_type { 124 struct uath_devno dev; 125 uint8_t flags; 126 } uath_devs[] = { 127 UATH_DEV_UG(ACCTON, SMCWUSBTG2), 128 UATH_DEV_UG(ATHEROS, AR5523), 129 UATH_DEV_UG(ATHEROS2, AR5523_1), 130 UATH_DEV_UG(ATHEROS2, AR5523_2), 131 UATH_DEV_UX(ATHEROS2, AR5523_3), 132 UATH_DEV_UG(CONCEPTRONIC, AR5523_1), 133 UATH_DEV_UX(CONCEPTRONIC, AR5523_2), 134 UATH_DEV_UX(DLINK, DWLAG122), 135 UATH_DEV_UX(DLINK, DWLAG132), 136 UATH_DEV_UG(DLINK, DWLG132), 137 UATH_DEV_UG(GIGASET, AR5523), 138 UATH_DEV_UG(GIGASET, SMCWUSBTG), 139 UATH_DEV_UG(GLOBALSUN, AR5523_1), 140 UATH_DEV_UX(GLOBALSUN, AR5523_2), 141 UATH_DEV_UG(IODATA, USBWNG54US), 142 UATH_DEV_UG(MELCO, WLIU2KAMG54), 143 UATH_DEV_UX(NETGEAR, WG111U), 144 UATH_DEV_UG(NETGEAR3, WG111T), 145 UATH_DEV_UG(NETGEAR3, WPN111), 146 UATH_DEV_UG(PHILIPS, SNU6500), 147 UATH_DEV_UX(UMEDIA, AR5523_2), 148 UATH_DEV_UG(UMEDIA, TEW444UBEU), 149 UATH_DEV_UG(WISTRONNEWEB, AR5523_1), 150 UATH_DEV_UX(WISTRONNEWEB, AR5523_2), 151 UATH_DEV_UG(ZCOM, AR5523) 152 }; 153 154 static char uath_fwmod[] = "uathfw"; 155 static char uath_binmod[] = "uathbin"; 156 157 /* 158 * Supported rates for 802.11b/g modes (in 500Kbps unit). 159 */ 160 static const struct ieee80211_rateset uath_rateset_11b = 161 { 4, { 2, 4, 11, 22 } }; 162 163 static const struct ieee80211_rateset uath_rateset_11g = 164 { 12, { 2, 4, 11, 22, 12, 18, 24, 36, 48, 72, 96, 108 } }; 165 166 /* 167 * device operations 168 */ 169 static int uath_attach(dev_info_t *, ddi_attach_cmd_t); 170 static int uath_detach(dev_info_t *, ddi_detach_cmd_t); 171 172 /* 173 * Module Loading Data & Entry Points 174 */ 175 DDI_DEFINE_STREAM_OPS(uath_dev_ops, nulldev, nulldev, uath_attach, 176 uath_detach, nodev, NULL, D_MP, NULL, ddi_quiesce_not_needed); 177 178 static struct modldrv uath_modldrv = { 179 &mod_driverops, /* Type of module. This one is a driver */ 180 "Atheros AR5523 USB Driver v1.1", /* short description */ 181 &uath_dev_ops /* driver specific ops */ 182 }; 183 184 static struct modlinkage modlinkage = { 185 MODREV_1, 186 (void *)&uath_modldrv, 187 NULL 188 }; 189 190 static int uath_m_stat(void *, uint_t, uint64_t *); 191 static int uath_m_start(void *); 192 static void uath_m_stop(void *); 193 static int uath_m_promisc(void *, boolean_t); 194 static int uath_m_multicst(void *, boolean_t, const uint8_t *); 195 static int uath_m_unicst(void *, const uint8_t *); 196 static mblk_t *uath_m_tx(void *, mblk_t *); 197 static void uath_m_ioctl(void *, queue_t *, mblk_t *); 198 static int uath_m_setprop(void *, const char *, mac_prop_id_t, 199 uint_t, const void *); 200 static int uath_m_getprop(void *, const char *, mac_prop_id_t, 201 uint_t, void *); 202 static void uath_m_propinfo(void *, const char *, mac_prop_id_t, 203 mac_prop_info_handle_t); 204 205 static mac_callbacks_t uath_m_callbacks = { 206 MC_IOCTL | MC_SETPROP | MC_GETPROP | MC_PROPINFO, 207 uath_m_stat, 208 uath_m_start, 209 uath_m_stop, 210 uath_m_promisc, 211 uath_m_multicst, 212 uath_m_unicst, 213 uath_m_tx, 214 NULL, 215 uath_m_ioctl, 216 NULL, 217 NULL, 218 NULL, 219 uath_m_setprop, 220 uath_m_getprop, 221 uath_m_propinfo 222 }; 223 224 static usb_alt_if_data_t * 225 uath_lookup_alt_if(usb_client_dev_data_t *, 226 uint_t, uint_t, uint_t); 227 static usb_ep_data_t * 228 uath_lookup_ep_data(dev_info_t *, 229 usb_client_dev_data_t *, uint_t, uint_t, uint8_t, uint8_t); 230 static const char * 231 uath_codename(int code); 232 233 static uint_t uath_lookup(uint16_t, uint16_t); 234 static void uath_list_all_eps(usb_alt_if_data_t *); 235 static int uath_open_pipes(struct uath_softc *); 236 static void uath_close_pipes(struct uath_softc *); 237 static int uath_fw_send(struct uath_softc *, 238 usb_pipe_handle_t, const void *, size_t); 239 static int uath_fw_ack(struct uath_softc *, int); 240 static int uath_loadsym(ddi_modhandle_t, char *, char **, size_t *); 241 static int uath_loadfirmware(struct uath_softc *); 242 static int uath_alloc_cmd_list(struct uath_softc *, 243 struct uath_cmd *, int, int); 244 static int uath_init_cmd_list(struct uath_softc *); 245 static void uath_free_cmd_list(struct uath_cmd *, int); 246 static int uath_host_available(struct uath_softc *); 247 static void uath_get_capability(struct uath_softc *, uint32_t, uint32_t *); 248 static int uath_get_devcap(struct uath_softc *); 249 static int uath_get_devstatus(struct uath_softc *, 250 uint8_t [IEEE80211_ADDR_LEN]); 251 static int uath_get_status(struct uath_softc *, uint32_t, void *, int); 252 253 static void uath_cmd_lock_init(struct uath_cmd_lock *); 254 static void uath_cmd_lock_destroy(struct uath_cmd_lock *); 255 static int uath_cmd_lock_wait(struct uath_cmd_lock *, clock_t); 256 static void uath_cmd_lock_signal(struct uath_cmd_lock *); 257 258 static int uath_cmd_read(struct uath_softc *, uint32_t, const void *, 259 int, void *, int, int); 260 static int uath_cmd_write(struct uath_softc *, uint32_t, const void *, 261 int, int); 262 static int uath_cmdsend(struct uath_softc *, uint32_t, 263 const void *, int, void *, int, int); 264 static int uath_rx_cmd_xfer(struct uath_softc *); 265 static int uath_tx_cmd_xfer(struct uath_softc *, 266 usb_pipe_handle_t, const void *, uint_t); 267 static void uath_cmd_txeof(usb_pipe_handle_t, struct usb_bulk_req *); 268 static void uath_cmd_rxeof(usb_pipe_handle_t, usb_bulk_req_t *); 269 static void uath_cmdeof(struct uath_softc *, struct uath_cmd *); 270 271 static void uath_init_data_queue(struct uath_softc *); 272 static int uath_rx_data_xfer(struct uath_softc *sc); 273 static int uath_tx_data_xfer(struct uath_softc *, mblk_t *); 274 static void uath_data_txeof(usb_pipe_handle_t, usb_bulk_req_t *); 275 static void uath_data_rxeof(usb_pipe_handle_t, usb_bulk_req_t *); 276 277 static int uath_create_connection(struct uath_softc *, uint32_t); 278 static int uath_set_rates(struct uath_softc *, 279 const struct ieee80211_rateset *); 280 static int uath_write_associd(struct uath_softc *); 281 static int uath_set_ledsteady(struct uath_softc *, int, int); 282 static int uath_set_ledblink(struct uath_softc *, int, int, int, int); 283 static void uath_update_rxstat(struct uath_softc *, uint32_t); 284 static int uath_send(ieee80211com_t *, mblk_t *, uint8_t); 285 static int uath_reconnect(dev_info_t *); 286 static int uath_disconnect(dev_info_t *); 287 static int uath_newstate(struct ieee80211com *, enum ieee80211_state, int); 288 289 static int uath_dataflush(struct uath_softc *); 290 static int uath_cmdflush(struct uath_softc *); 291 static int uath_flush(struct uath_softc *); 292 static int uath_set_ledstate(struct uath_softc *, int); 293 static int uath_set_chan(struct uath_softc *, struct ieee80211_channel *); 294 static int uath_reset_tx_queues(struct uath_softc *); 295 static int uath_wme_init(struct uath_softc *); 296 static int uath_config_multi(struct uath_softc *, 297 uint32_t, const void *, int); 298 static void uath_config(struct uath_softc *, uint32_t, uint32_t); 299 static int uath_switch_channel(struct uath_softc *, 300 struct ieee80211_channel *); 301 static int uath_set_rxfilter(struct uath_softc *, uint32_t, uint32_t); 302 static int uath_init_locked(void *); 303 static void uath_stop_locked(void *); 304 static int uath_init(struct uath_softc *); 305 static void uath_stop(struct uath_softc *); 306 static void uath_resume(struct uath_softc *); 307 308 static void 309 uath_debug(uint32_t dbg_flags, const int8_t *fmt, ...) 310 { 311 va_list args; 312 313 if (dbg_flags & uath_dbg_flags) { 314 va_start(args, fmt); 315 vcmn_err(CE_CONT, fmt, args); 316 va_end(args); 317 } 318 } 319 320 static uint_t 321 uath_lookup(uint16_t vendor_id, uint16_t product_id) 322 { 323 int i, size; 324 325 size = sizeof (uath_devs) / sizeof (struct uath_type); 326 327 for (i = 0; i < size; i++) { 328 if ((vendor_id == uath_devs[i].dev.vendor_id) && 329 (product_id == uath_devs[i].dev.product_id)) 330 return (uath_devs[i].flags); 331 } 332 return (UATH_FLAG_ERR); 333 } 334 335 /* 336 * Return a specific alt_if from the device descriptor tree. 337 */ 338 static usb_alt_if_data_t * 339 uath_lookup_alt_if(usb_client_dev_data_t *dev_data, uint_t config, 340 uint_t interface, uint_t alt) 341 { 342 usb_cfg_data_t *cfg_data; 343 usb_if_data_t *if_data; 344 usb_alt_if_data_t *if_alt_data; 345 346 /* 347 * Assume everything is in the tree for now, 348 * (USB_PARSE_LVL_ALL) 349 * so we can directly index the array. 350 */ 351 352 /* Descend to configuration, configs are 1-based */ 353 if (config < 1 || config > dev_data->dev_n_cfg) 354 return (NULL); 355 cfg_data = &dev_data->dev_cfg[config - 1]; 356 357 /* Descend to interface */ 358 if (interface > cfg_data->cfg_n_if - 1) 359 return (NULL); 360 if_data = &cfg_data->cfg_if[interface]; 361 362 /* Descend to alt */ 363 if (alt > if_data->if_n_alt - 1) 364 return (NULL); 365 if_alt_data = &if_data->if_alt[alt]; 366 367 return (if_alt_data); 368 } 369 370 /* 371 * Print all endpoints of an alt_if. 372 */ 373 static void 374 uath_list_all_eps(usb_alt_if_data_t *ifalt) 375 { 376 usb_ep_data_t *ep_data; 377 usb_ep_descr_t *ep_descr; 378 int i; 379 380 for (i = 0; i < ifalt->altif_n_ep; i++) { 381 ep_data = &ifalt->altif_ep[i]; 382 ep_descr = &ep_data->ep_descr; 383 UATH_DEBUG(UATH_DBG_USB, 384 "uath: uath_list_all_endpoint: " 385 "ep addresa[%x] is %x", 386 i, ep_descr->bEndpointAddress); 387 } 388 } 389 390 static usb_ep_data_t * 391 uath_lookup_ep_data(dev_info_t *dip, 392 usb_client_dev_data_t *dev_datap, 393 uint_t interface, 394 uint_t alternate, 395 uint8_t address, 396 uint8_t type) 397 { 398 usb_alt_if_data_t *altif_data; 399 int i; 400 401 if ((dip == NULL) || (dev_datap == NULL)) 402 return (NULL); 403 404 altif_data = &dev_datap->dev_curr_cfg-> 405 cfg_if[interface].if_alt[alternate]; 406 407 for (i = 0; i < altif_data->altif_n_ep; i++) { 408 usb_ep_descr_t *ept = &altif_data->altif_ep[i].ep_descr; 409 uint8_t ept_type = ept->bmAttributes & USB_EP_ATTR_MASK; 410 uint8_t ept_address = ept->bEndpointAddress; 411 412 if (ept->bLength == 0) 413 continue; 414 if ((ept_type == type) && 415 ((type == USB_EP_ATTR_CONTROL) || (address == ept_address))) 416 return (&altif_data->altif_ep[i]); 417 } 418 return (NULL); 419 } 420 421 /* 422 * Open communication pipes. 423 * The following pipes are used by the AR5523: 424 * ep0: 0x81 IN Rx cmd 425 * ep1: 0x01 OUT Tx cmd 426 * ep2: 0x82 IN Rx data 427 * ep3: 0x02 OUT Tx data 428 */ 429 static int 430 uath_open_pipes(struct uath_softc *sc) 431 { 432 usb_ep_data_t *ep_node; 433 usb_ep_descr_t *ep_descr; 434 usb_pipe_policy_t policy; 435 int err; 436 437 #ifdef DEBUG 438 usb_alt_if_data_t *altif_data; 439 440 altif_data = uath_lookup_alt_if(sc->sc_udev, UATH_CONFIG_NO, 441 UATH_IFACE_INDEX, UATH_ALT_IF_INDEX); 442 if (altif_data == NULL) { 443 UATH_DEBUG(UATH_DBG_ERR, "alt_if not found"); 444 return (USB_FAILURE); 445 } 446 447 uath_list_all_eps(altif_data); 448 #endif 449 450 /* 451 * XXX pipes numbers are hardcoded because we don't have any way 452 * to distinguish the data pipes from the firmware command pipes 453 * (both are bulk pipes) using the endpoints descriptors. 454 */ 455 ep_node = uath_lookup_ep_data(sc->sc_dev, sc->sc_udev, 456 0, 0, 0x81, USB_EP_ATTR_BULK); 457 ep_descr = &ep_node->ep_descr; 458 UATH_DEBUG(UATH_DBG_MSG, "uath: uath_open_pipes(): " 459 "find pipe %x\n", ep_descr->bEndpointAddress); 460 461 bzero(&policy, sizeof (usb_pipe_policy_t)); 462 policy.pp_max_async_reqs = UATH_CMD_LIST_COUNT; 463 464 err = usb_pipe_open(sc->sc_dev, &ep_node->ep_descr, 465 &policy, USB_FLAGS_SLEEP, &sc->rx_cmd_pipe); 466 if (err != USB_SUCCESS) { 467 UATH_DEBUG(UATH_DBG_ERR, "uath: uath_open_pipes(): " 468 "failed to open rx data pipe, err = %x\n", 469 err); 470 goto fail; 471 } 472 473 474 ep_node = uath_lookup_ep_data(sc->sc_dev, sc->sc_udev, 475 0, 0, 0x01, USB_EP_ATTR_BULK); 476 ep_descr = &ep_node->ep_descr; 477 UATH_DEBUG(UATH_DBG_ERR, "uath: uath_open_pipes(): " 478 "find pipe %x\n", 479 ep_descr->bEndpointAddress); 480 481 bzero(&policy, sizeof (usb_pipe_policy_t)); 482 policy.pp_max_async_reqs = UATH_CMD_LIST_COUNT; 483 484 err = usb_pipe_open(sc->sc_dev, &ep_node->ep_descr, 485 &policy, USB_FLAGS_SLEEP, &sc->tx_cmd_pipe); 486 if (err != USB_SUCCESS) { 487 UATH_DEBUG(UATH_DBG_ERR, "uath: uath_open_pipes(): " 488 "failed to open tx command pipe, err = %x\n", 489 err); 490 goto fail; 491 } 492 493 ep_node = uath_lookup_ep_data(sc->sc_dev, sc->sc_udev, 494 0, 0, 0x82, USB_EP_ATTR_BULK); 495 ep_descr = &ep_node->ep_descr; 496 UATH_DEBUG(UATH_DBG_ERR, "uath: uath_open_pipes(): " 497 "find pipe %x\n", 498 ep_descr->bEndpointAddress); 499 500 bzero(&policy, sizeof (usb_pipe_policy_t)); 501 policy.pp_max_async_reqs = UATH_RX_DATA_LIST_COUNT; 502 503 err = usb_pipe_open(sc->sc_dev, &ep_node->ep_descr, 504 &policy, USB_FLAGS_SLEEP, &sc->rx_data_pipe); 505 if (err != USB_SUCCESS) { 506 UATH_DEBUG(UATH_DBG_ERR, "uath: uath_open_pipes(): " 507 "failed to open tx pipe, err = %x\n", 508 err); 509 goto fail; 510 } 511 512 ep_node = uath_lookup_ep_data(sc->sc_dev, sc->sc_udev, 513 0, 0, 0x02, USB_EP_ATTR_BULK); 514 ep_descr = &ep_node->ep_descr; 515 UATH_DEBUG(UATH_DBG_ERR, "uath: uath_open_pipes(): " 516 "find pipe %x\n", 517 ep_descr->bEndpointAddress); 518 519 bzero(&policy, sizeof (usb_pipe_policy_t)); 520 policy.pp_max_async_reqs = UATH_TX_DATA_LIST_COUNT; 521 522 err = usb_pipe_open(sc->sc_dev, &ep_node->ep_descr, 523 &policy, USB_FLAGS_SLEEP, &sc->tx_data_pipe); 524 if (err != USB_SUCCESS) { 525 UATH_DEBUG(UATH_DBG_ERR, "uath: uath_open_pipes(): " 526 "failed to open rx command pipe, err = %x\n", 527 err); 528 goto fail; 529 } 530 531 return (UATH_SUCCESS); 532 fail: 533 uath_close_pipes(sc); 534 return (err); 535 } 536 537 static void 538 uath_close_pipes(struct uath_softc *sc) 539 { 540 usb_flags_t flags = USB_FLAGS_SLEEP; 541 542 if (sc->rx_cmd_pipe != NULL) { 543 usb_pipe_reset(sc->sc_dev, sc->rx_cmd_pipe, flags, NULL, 0); 544 usb_pipe_close(sc->sc_dev, sc->rx_cmd_pipe, flags, NULL, 0); 545 sc->rx_cmd_pipe = NULL; 546 } 547 548 if (sc->tx_cmd_pipe != NULL) { 549 usb_pipe_reset(sc->sc_dev, sc->tx_cmd_pipe, flags, NULL, 0); 550 usb_pipe_close(sc->sc_dev, sc->tx_cmd_pipe, flags, NULL, 0); 551 sc->tx_cmd_pipe = NULL; 552 } 553 554 if (sc->rx_data_pipe != NULL) { 555 usb_pipe_reset(sc->sc_dev, sc->rx_data_pipe, flags, NULL, 0); 556 usb_pipe_close(sc->sc_dev, sc->rx_data_pipe, flags, NULL, 0); 557 sc->rx_data_pipe = NULL; 558 } 559 560 if (sc->tx_data_pipe != NULL) { 561 usb_pipe_reset(sc->sc_dev, sc->tx_data_pipe, flags, NULL, 0); 562 usb_pipe_close(sc->sc_dev, sc->tx_data_pipe, flags, NULL, 0); 563 sc->tx_data_pipe = NULL; 564 } 565 566 } 567 568 static const char * 569 uath_codename(int code) 570 { 571 #define N(a) (sizeof (a)/sizeof (a[0])) 572 static const char *names[] = { 573 "0x00", 574 "HOST_AVAILABLE", 575 "BIND", 576 "TARGET_RESET", 577 "TARGET_GET_CAPABILITY", 578 "TARGET_SET_CONFIG", 579 "TARGET_GET_STATUS", 580 "TARGET_GET_STATS", 581 "TARGET_START", 582 "TARGET_STOP", 583 "TARGET_ENABLE", 584 "TARGET_DISABLE", 585 "CREATE_CONNECTION", 586 "UPDATE_CONNECT_ATTR", 587 "DELETE_CONNECT", 588 "SEND", 589 "FLUSH", 590 "STATS_UPDATE", 591 "BMISS", 592 "DEVICE_AVAIL", 593 "SEND_COMPLETE", 594 "DATA_AVAIL", 595 "SET_PWR_MODE", 596 "BMISS_ACK", 597 "SET_LED_STEADY", 598 "SET_LED_BLINK", 599 "SETUP_BEACON_DESC", 600 "BEACON_INIT", 601 "RESET_KEY_CACHE", 602 "RESET_KEY_CACHE_ENTRY", 603 "SET_KEY_CACHE_ENTRY", 604 "SET_DECOMP_MASK", 605 "SET_REGULATORY_DOMAIN", 606 "SET_LED_STATE", 607 "WRITE_ASSOCID", 608 "SET_STA_BEACON_TIMERS", 609 "GET_TSF", 610 "RESET_TSF", 611 "SET_ADHOC_MODE", 612 "SET_BASIC_RATE", 613 "MIB_CONTROL", 614 "GET_CHANNEL_DATA", 615 "GET_CUR_RSSI", 616 "SET_ANTENNA_SWITCH", 617 "0x2c", "0x2d", "0x2e", 618 "USE_SHORT_SLOT_TIME", 619 "SET_POWER_MODE", 620 "SETUP_PSPOLL_DESC", 621 "SET_RX_MULTICAST_FILTER", 622 "RX_FILTER", 623 "PER_CALIBRATION", 624 "RESET", 625 "DISABLE", 626 "PHY_DISABLE", 627 "SET_TX_POWER_LIMIT", 628 "SET_TX_QUEUE_PARAMS", 629 "SETUP_TX_QUEUE", 630 "RELEASE_TX_QUEUE", 631 }; 632 static char buf[8]; 633 634 if (code < N(names)) 635 return (names[code]); 636 if (code == WDCMSG_SET_DEFAULT_KEY) 637 return ("SET_DEFAULT_KEY"); 638 639 (void) snprintf(buf, sizeof (buf), "0x%02x", code); 640 return (buf); 641 #undef N 642 } 643 644 static int 645 uath_fw_send(struct uath_softc *sc, usb_pipe_handle_t pipe, 646 const void *data, size_t len) 647 { 648 usb_bulk_req_t *send_req; 649 mblk_t *mblk; 650 int res; 651 652 send_req = usb_alloc_bulk_req(sc->sc_dev, len, USB_FLAGS_SLEEP); 653 654 send_req->bulk_len = (int)len; 655 send_req->bulk_attributes = USB_ATTRS_AUTOCLEARING; 656 send_req->bulk_timeout = UATH_CMD_TIMEOUT; 657 658 mblk = send_req->bulk_data; 659 bcopy(data, mblk->b_wptr, len); 660 mblk->b_wptr += len; 661 662 res = usb_pipe_bulk_xfer(pipe, send_req, USB_FLAGS_SLEEP); 663 if (res != USB_SUCCESS) { 664 UATH_DEBUG(UATH_DBG_FW, "uath: uath_fw_send(): " 665 "Error %x writing data to bulk/out pipe", res); 666 return (UATH_FAILURE); 667 } 668 669 usb_free_bulk_req(send_req); 670 return (UATH_SUCCESS); 671 } 672 673 static int 674 uath_fw_ack(struct uath_softc *sc, int len) 675 { 676 struct uath_fwblock *rxblock; 677 usb_bulk_req_t *req; 678 mblk_t *mp; 679 int err; 680 681 req = usb_alloc_bulk_req(sc->sc_dev, len, USB_FLAGS_SLEEP); 682 if (req == NULL) { 683 UATH_DEBUG(UATH_DBG_FW, 684 "uath: uath_fw_ack(): " 685 "uath_rx_transfer(): failed to allocate req"); 686 return (UATH_FAILURE); 687 } 688 689 req->bulk_len = len; 690 req->bulk_client_private = (usb_opaque_t)sc; 691 req->bulk_timeout = 0; 692 req->bulk_attributes = USB_ATTRS_SHORT_XFER_OK 693 | USB_ATTRS_AUTOCLEARING; 694 695 err = usb_pipe_bulk_xfer(sc->rx_cmd_pipe, req, USB_FLAGS_SLEEP); 696 if (err != USB_SUCCESS) { 697 UATH_DEBUG(UATH_DBG_FW, "uath: uath_fw_ack(): " 698 "failed to do rx xfer, %d", err); 699 usb_free_bulk_req(req); 700 return (UATH_FAILURE); 701 } 702 703 mp = req->bulk_data; 704 req->bulk_data = NULL; 705 706 rxblock = (struct uath_fwblock *)mp->b_rptr; 707 UATH_DEBUG(UATH_DBG_FW, "uath: uath_fw_ack() " 708 "rxblock flags=0x%x total=%d\n", 709 BE_32(rxblock->flags), BE_32(rxblock->rxtotal)); 710 711 freemsg(mp); 712 usb_free_bulk_req(req); 713 714 return (UATH_SUCCESS); 715 } 716 717 /* 718 * find uath firmware module's "_start" "_end" symbols 719 * and get its size. 720 */ 721 static int 722 uath_loadsym(ddi_modhandle_t modp, char *sym, char **start, size_t *len) 723 { 724 char start_sym[64]; 725 char end_sym[64]; 726 char *p, *end; 727 int rv; 728 size_t n; 729 730 (void) snprintf(start_sym, sizeof (start_sym), "%s_start", sym); 731 (void) snprintf(end_sym, sizeof (end_sym), "%s_end", sym); 732 733 p = (char *)ddi_modsym(modp, start_sym, &rv); 734 if (p == NULL || rv != 0) { 735 UATH_DEBUG(UATH_DBG_MSG, "uath: uath_loadsym(): " 736 "mod %s: symbol %s not found\n", uath_fwmod, start_sym); 737 return (UATH_FAILURE); 738 } 739 740 end = (char *)ddi_modsym(modp, end_sym, &rv); 741 if (end == NULL || rv != 0) { 742 UATH_DEBUG(UATH_DBG_MSG, "uath: uath_loadsym(): " 743 "mod %s: symbol %s not found\n", uath_fwmod, end_sym); 744 return (UATH_FAILURE); 745 } 746 747 n = _PTRDIFF(end, p); 748 *start = p; 749 *len = n; 750 751 return (UATH_SUCCESS); 752 } 753 754 /* 755 * Load the MIPS R4000 microcode into the device. Once the image is loaded, 756 * the device will detach itself from the bus and reattach later with a new 757 * product Id (a la ezusb). XXX this could also be implemented in userland 758 * through /dev/ugen. 759 */ 760 static int 761 uath_loadfirmware(struct uath_softc *sc) 762 { 763 struct uath_fwblock txblock; 764 ddi_modhandle_t modp; 765 char *fw_index, *fw_image = NULL; 766 size_t fw_size, len; 767 int err = DDI_SUCCESS, rv = 0; 768 769 modp = ddi_modopen(uath_fwmod, KRTLD_MODE_FIRST, &rv); 770 if (modp == NULL) { 771 cmn_err(CE_WARN, "uath: uath_loadfirmware(): " 772 "module %s not found\n", uath_fwmod); 773 goto label; 774 } 775 776 err = uath_loadsym(modp, uath_binmod, &fw_index, &fw_size); 777 if (err != UATH_SUCCESS) { 778 cmn_err(CE_WARN, "uath: uath_loadfirmware(): " 779 "could not get firmware\n"); 780 goto label; 781 } 782 783 fw_image = (char *)kmem_alloc(fw_size, KM_SLEEP); 784 if (fw_image == NULL) { 785 UATH_DEBUG(UATH_DBG_ERR, "uath: uath_loadfirmware(): " 786 "failed to alloc firmware memory\n"); 787 err = UATH_FAILURE; 788 goto label; 789 } 790 791 (void) memcpy(fw_image, fw_index, fw_size); 792 fw_index = fw_image; 793 len = fw_size; 794 UATH_DEBUG(UATH_DBG_MSG, "loading firmware size = %lu\n", fw_size); 795 796 /* bzero(txblock, sizeof (struct uath_fwblock)); */ 797 txblock.flags = BE_32(UATH_WRITE_BLOCK); 798 txblock.total = BE_32(fw_size); 799 800 while (len > 0) { 801 size_t mlen = min(len, UATH_MAX_FWBLOCK_SIZE); 802 803 txblock.remain = BE_32(len - mlen); 804 txblock.len = BE_32(mlen); 805 806 UATH_DEBUG(UATH_DBG_FW, "uath: uath_loadfirmware(): " 807 "sending firmware block: %d bytes sending\n", mlen); 808 UATH_DEBUG(UATH_DBG_FW, "uath: uath_loadfirmware(): " 809 "sending firmware block: %d bytes remaining\n", 810 len - mlen); 811 812 /* send firmware block meta-data */ 813 err = uath_fw_send(sc, sc->tx_cmd_pipe, &txblock, 814 sizeof (struct uath_fwblock)); 815 if (err != UATH_SUCCESS) { 816 UATH_DEBUG(UATH_DBG_FW, "uath: uath_loadfirmware(): " 817 "send block meta-data error"); 818 goto label; 819 } 820 821 /* send firmware block data */ 822 err = uath_fw_send(sc, sc->tx_data_pipe, fw_index, mlen); 823 if (err != UATH_SUCCESS) { 824 UATH_DEBUG(UATH_DBG_FW, "uath: uath_loadfirmware() " 825 "send block data err"); 826 goto label; 827 } 828 829 /* wait for ack from firmware */ 830 err = uath_fw_ack(sc, sizeof (struct uath_fwblock)); 831 if (err != UATH_SUCCESS) { 832 UATH_DEBUG(UATH_DBG_FW, "uath: uath_loadfirmware() " 833 "rx block ack err"); 834 goto label; 835 } 836 837 fw_index += mlen; 838 len -= mlen; 839 } 840 841 label: 842 if (fw_image != NULL) 843 kmem_free(fw_image, fw_size); 844 fw_image = fw_index = NULL; 845 if (modp != NULL) 846 (void) ddi_modclose(modp); 847 return (err); 848 } 849 850 static int 851 uath_alloc_cmd_list(struct uath_softc *sc, struct uath_cmd cmds[], 852 int ncmd, int maxsz) 853 { 854 int i, err; 855 856 for (i = 0; i < ncmd; i++) { 857 struct uath_cmd *cmd = &cmds[i]; 858 859 cmd->sc = sc; /* backpointer for callbacks */ 860 cmd->msgid = i; 861 cmd->buf = kmem_zalloc(maxsz, KM_NOSLEEP); 862 if (cmd->buf == NULL) { 863 UATH_DEBUG(UATH_DBG_ERR, "uath: uath_alloc_cmd_list(): " 864 "could not allocate xfer buffer\n"); 865 err = DDI_ENOMEM; 866 goto fail; 867 } 868 } 869 return (UATH_SUCCESS); 870 871 fail: 872 uath_free_cmd_list(cmds, ncmd); 873 return (err); 874 } 875 876 static int 877 uath_init_cmd_list(struct uath_softc *sc) 878 { 879 int i; 880 881 sc->sc_cmdid = sc->rx_cmd_queued = sc->tx_cmd_queued = 0; 882 for (i = 0; i < UATH_CMD_LIST_COUNT; i++) { 883 if (uath_rx_cmd_xfer(sc) != UATH_SUCCESS) { 884 UATH_DEBUG(UATH_DBG_ERR, "uath: uath_init_cmd_list(): " 885 "failed to init cmd list %x\n", i); 886 return (UATH_FAILURE); 887 } 888 } 889 return (UATH_SUCCESS); 890 } 891 892 static void 893 uath_free_cmd_list(struct uath_cmd cmds[], int ncmd) 894 { 895 int i; 896 897 for (i = 0; i < ncmd; i++) 898 if (cmds[i].buf != NULL) { 899 kmem_free(cmds[i].buf, UATH_MAX_CMDSZ); 900 cmds[i].buf = NULL; 901 } 902 } 903 904 static int 905 uath_host_available(struct uath_softc *sc) 906 { 907 struct uath_cmd_host_available setup; 908 909 /* inform target the host is available */ 910 setup.sw_ver_major = BE_32(ATH_SW_VER_MAJOR); 911 setup.sw_ver_minor = BE_32(ATH_SW_VER_MINOR); 912 setup.sw_ver_patch = BE_32(ATH_SW_VER_PATCH); 913 setup.sw_ver_build = BE_32(ATH_SW_VER_BUILD); 914 return (uath_cmd_read(sc, WDCMSG_HOST_AVAILABLE, 915 &setup, sizeof (setup), NULL, 0, 0)); 916 } 917 918 static void 919 uath_get_capability(struct uath_softc *sc, uint32_t cap, uint32_t *val) 920 { 921 int err; 922 923 cap = BE_32(cap); 924 err = uath_cmd_read(sc, WDCMSG_TARGET_GET_CAPABILITY, &cap, 925 sizeof (cap), val, sizeof (uint32_t), UATH_CMD_FLAG_MAGIC); 926 if (err == UATH_SUCCESS) 927 *val = BE_32(*val); 928 else 929 UATH_DEBUG(UATH_DBG_ERR, "uath: uath_get_capability(): " 930 "could not read capability %u\n", BE_32(cap)); 931 } 932 933 static int 934 uath_get_devcap(struct uath_softc *sc) 935 { 936 struct uath_devcap *cap = &sc->sc_devcap; 937 938 /* collect device capabilities */ 939 uath_get_capability(sc, CAP_TARGET_VERSION, 940 &cap->targetVersion); 941 uath_get_capability(sc, CAP_TARGET_REVISION, 942 &cap->targetRevision); 943 uath_get_capability(sc, CAP_MAC_VERSION, 944 &cap->macVersion); 945 uath_get_capability(sc, CAP_MAC_REVISION, 946 &cap->macRevision); 947 uath_get_capability(sc, CAP_PHY_REVISION, 948 &cap->phyRevision); 949 uath_get_capability(sc, CAP_ANALOG_5GHz_REVISION, 950 &cap->analog5GhzRevision); 951 uath_get_capability(sc, CAP_ANALOG_2GHz_REVISION, 952 &cap->analog2GhzRevision); 953 uath_get_capability(sc, CAP_REG_DOMAIN, 954 &cap->regDomain); 955 uath_get_capability(sc, CAP_REG_CAP_BITS, 956 &cap->regCapBits); 957 958 /* NB: not supported in rev 1.5 */ 959 /* uath_get_capability(sc, CAP_COUNTRY_CODE, cap->countryCode); */ 960 961 uath_get_capability(sc, CAP_WIRELESS_MODES, 962 &cap->wirelessModes); 963 uath_get_capability(sc, CAP_CHAN_SPREAD_SUPPORT, 964 &cap->chanSpreadSupport); 965 uath_get_capability(sc, CAP_COMPRESS_SUPPORT, 966 &cap->compressSupport); 967 uath_get_capability(sc, CAP_BURST_SUPPORT, 968 &cap->burstSupport); 969 uath_get_capability(sc, CAP_FAST_FRAMES_SUPPORT, 970 &cap->fastFramesSupport); 971 uath_get_capability(sc, CAP_CHAP_TUNING_SUPPORT, 972 &cap->chapTuningSupport); 973 uath_get_capability(sc, CAP_TURBOG_SUPPORT, 974 &cap->turboGSupport); 975 uath_get_capability(sc, CAP_TURBO_PRIME_SUPPORT, 976 &cap->turboPrimeSupport); 977 uath_get_capability(sc, CAP_DEVICE_TYPE, 978 &cap->deviceType); 979 uath_get_capability(sc, CAP_WME_SUPPORT, 980 &cap->wmeSupport); 981 uath_get_capability(sc, CAP_TOTAL_QUEUES, 982 &cap->numTxQueues); 983 uath_get_capability(sc, CAP_CONNECTION_ID_MAX, 984 &cap->connectionIdMax); 985 986 uath_get_capability(sc, CAP_LOW_5GHZ_CHAN, 987 &cap->low5GhzChan); 988 uath_get_capability(sc, CAP_HIGH_5GHZ_CHAN, 989 &cap->high5GhzChan); 990 uath_get_capability(sc, CAP_LOW_2GHZ_CHAN, 991 &cap->low2GhzChan); 992 uath_get_capability(sc, CAP_HIGH_2GHZ_CHAN, 993 &cap->high2GhzChan); 994 uath_get_capability(sc, CAP_TWICE_ANTENNAGAIN_5G, 995 &cap->twiceAntennaGain5G); 996 uath_get_capability(sc, CAP_TWICE_ANTENNAGAIN_2G, 997 &cap->twiceAntennaGain2G); 998 999 uath_get_capability(sc, CAP_CIPHER_AES_CCM, 1000 &cap->supportCipherAES_CCM); 1001 uath_get_capability(sc, CAP_CIPHER_TKIP, 1002 &cap->supportCipherTKIP); 1003 uath_get_capability(sc, CAP_MIC_TKIP, 1004 &cap->supportMicTKIP); 1005 1006 cap->supportCipherWEP = 1; /* NB: always available */ 1007 return (UATH_SUCCESS); 1008 } 1009 1010 static int 1011 uath_get_status(struct uath_softc *sc, uint32_t which, void *odata, int olen) 1012 { 1013 int err; 1014 1015 which = BE_32(which); 1016 err = uath_cmd_read(sc, WDCMSG_TARGET_GET_STATUS, 1017 &which, sizeof (which), odata, olen, UATH_CMD_FLAG_MAGIC); 1018 if (err != UATH_SUCCESS) 1019 UATH_DEBUG(UATH_DBG_ERR, "uath: uath_get_status(): " 1020 "could not read EEPROM offset 0x%02x\n", BE_32(which)); 1021 return (err); 1022 } 1023 1024 static int 1025 uath_get_devstatus(struct uath_softc *sc, uint8_t macaddr[IEEE80211_ADDR_LEN]) 1026 { 1027 int err; 1028 1029 /* retrieve MAC address */ 1030 err = uath_get_status(sc, ST_MAC_ADDR, macaddr, IEEE80211_ADDR_LEN); 1031 if (err != UATH_SUCCESS) { 1032 UATH_DEBUG(UATH_DBG_ERR, "uath: uath_get_devstatus(): " 1033 "could not read MAC address\n"); 1034 return (err); 1035 } 1036 1037 err = uath_get_status(sc, ST_SERIAL_NUMBER, 1038 &sc->sc_serial[0], sizeof (sc->sc_serial)); 1039 if (err != UATH_SUCCESS) { 1040 UATH_DEBUG(UATH_DBG_ERR, "uath: uath_get_devstatus(): " 1041 "could not read device serial number\n"); 1042 return (err); 1043 } 1044 1045 return (UATH_SUCCESS); 1046 } 1047 1048 /* 1049 * uath_cmd_lock: a special signal structure that is used for notification 1050 * that a callback function has been called. 1051 */ 1052 1053 /* Initializes the uath_cmd_lock structure. */ 1054 static void 1055 uath_cmd_lock_init(struct uath_cmd_lock *lock) 1056 { 1057 ASSERT(lock != NULL); 1058 mutex_init(&lock->mutex, NULL, MUTEX_DRIVER, NULL); 1059 cv_init(&lock->cv, NULL, CV_DRIVER, NULL); 1060 lock->done = B_FALSE; 1061 } 1062 1063 /* Deinitalizes the uath_cb_lock structure. */ 1064 void 1065 uath_cmd_lock_destroy(struct uath_cmd_lock *lock) 1066 { 1067 ASSERT(lock != NULL); 1068 mutex_destroy(&lock->mutex); 1069 cv_destroy(&lock->cv); 1070 } 1071 1072 /* 1073 * Wait on lock until someone calls the "signal" function or the timeout 1074 * expires. Note: timeout is in microseconds. 1075 */ 1076 static int 1077 uath_cmd_lock_wait(struct uath_cmd_lock *lock, clock_t timeout) 1078 { 1079 int res, cv_res; 1080 clock_t etime; 1081 1082 ASSERT(lock != NULL); 1083 mutex_enter(&lock->mutex); 1084 1085 if (timeout < 0) { 1086 /* no timeout - wait as long as needed */ 1087 while (lock->done == B_FALSE) 1088 cv_wait(&lock->cv, &lock->mutex); 1089 } else { 1090 /* wait with timeout (given in usec) */ 1091 etime = ddi_get_lbolt() + drv_usectohz(timeout); 1092 while (lock->done == B_FALSE) { 1093 cv_res = cv_timedwait_sig(&lock->cv, 1094 &lock->mutex, etime); 1095 if (cv_res <= 0) break; 1096 } 1097 } 1098 1099 res = (lock->done == B_TRUE) ? UATH_SUCCESS : UATH_FAILURE; 1100 mutex_exit(&lock->mutex); 1101 1102 return (res); 1103 } 1104 1105 /* Signal that the job (eg. callback) is done and unblock anyone who waits. */ 1106 static void 1107 uath_cmd_lock_signal(struct uath_cmd_lock *lock) 1108 { 1109 ASSERT(lock != NULL); 1110 1111 mutex_enter(&lock->mutex); 1112 lock->done = B_TRUE; 1113 cv_broadcast(&lock->cv); 1114 mutex_exit(&lock->mutex); 1115 } 1116 1117 static int 1118 uath_cmd_read(struct uath_softc *sc, uint32_t code, const void *idata, 1119 int ilen, void *odata, int olen, int flags) 1120 { 1121 flags |= UATH_CMD_FLAG_READ; 1122 return (uath_cmdsend(sc, code, idata, ilen, odata, olen, flags)); 1123 } 1124 1125 static int 1126 uath_cmd_write(struct uath_softc *sc, uint32_t code, const void *data, 1127 int len, int flags) 1128 { 1129 flags &= ~UATH_CMD_FLAG_READ; 1130 return (uath_cmdsend(sc, code, data, len, NULL, 0, flags)); 1131 } 1132 1133 /* 1134 * Low-level function to send read or write commands to the firmware. 1135 */ 1136 static int 1137 uath_cmdsend(struct uath_softc *sc, uint32_t code, const void *idata, int ilen, 1138 void *odata, int olen, int flags) 1139 { 1140 struct uath_cmd_hdr *hdr; 1141 struct uath_cmd *cmd; 1142 int err; 1143 1144 /* grab a xfer */ 1145 cmd = &sc->sc_cmd[sc->sc_cmdid]; 1146 1147 cmd->flags = flags; 1148 /* always bulk-out a multiple of 4 bytes */ 1149 cmd->buflen = (sizeof (struct uath_cmd_hdr) + ilen + 3) & ~3; 1150 1151 hdr = (struct uath_cmd_hdr *)cmd->buf; 1152 bzero(hdr, sizeof (struct uath_cmd_hdr)); 1153 hdr->len = BE_32(cmd->buflen); 1154 hdr->code = BE_32(code); 1155 hdr->msgid = cmd->msgid; /* don't care about endianness */ 1156 hdr->magic = BE_32((cmd->flags & UATH_CMD_FLAG_MAGIC) ? 1 << 24 : 0); 1157 bcopy(idata, (uint8_t *)(hdr + 1), ilen); 1158 1159 UATH_DEBUG(UATH_DBG_TX_CMD, "uath: uath_cmdsend(): " 1160 "queue %x send %s [flags 0x%x] olen %d\n", 1161 cmd->msgid, uath_codename(code), cmd->flags, olen); 1162 1163 cmd->odata = odata; 1164 if (odata == NULL) 1165 UATH_DEBUG(UATH_DBG_TX_CMD, "uath: uath_cmdsend(): " 1166 "warning - odata is NULL\n"); 1167 else if (olen < UATH_MAX_CMDSZ - sizeof (*hdr) + sizeof (uint32_t)) 1168 UATH_DEBUG(UATH_DBG_TX_CMD, "uath: uath_cmdsend(): " 1169 "warning - olen %x is short\n, olen"); 1170 cmd->olen = olen; 1171 1172 err = uath_tx_cmd_xfer(sc, sc->tx_cmd_pipe, cmd->buf, cmd->buflen); 1173 if (err != UATH_SUCCESS) { 1174 UATH_DEBUG(UATH_DBG_ERR, "uath: uath_cmdsend(): " 1175 "Error writing command\n"); 1176 return (UATH_FAILURE); 1177 } 1178 1179 sc->sc_cmdid = (sc->sc_cmdid + 1) % UATH_CMD_LIST_COUNT; 1180 1181 if (cmd->flags & UATH_CMD_FLAG_READ) { 1182 /* wait at most two seconds for command reply */ 1183 uath_cmd_lock_init(&sc->rlock); 1184 err = uath_cmd_lock_wait(&sc->rlock, 2000000); 1185 cmd->odata = NULL; /* in case reply comes too late */ 1186 if (err != UATH_SUCCESS) { 1187 UATH_DEBUG(UATH_DBG_ERR, "uath: uath_cmdsend(): " 1188 "timeout waiting for reply, " 1189 "to cmd 0x%x (%u), queue %x\n", 1190 code, code, cmd->msgid); 1191 err = UATH_FAILURE; 1192 } else if (cmd->olen != olen) { 1193 UATH_DEBUG(UATH_DBG_ERR, "uath: uath_cmdsend(): " 1194 "unexpected reply data count " 1195 "to cmd 0x%x (%x), got %u, expected %u\n", 1196 code, cmd->msgid, cmd->olen, olen); 1197 err = UATH_FAILURE; 1198 } 1199 uath_cmd_lock_destroy(&sc->rlock); 1200 return (err); 1201 } 1202 1203 return (UATH_SUCCESS); 1204 } 1205 1206 /* ARGSUSED */ 1207 static void 1208 uath_cmd_txeof(usb_pipe_handle_t pipe, struct usb_bulk_req *req) 1209 { 1210 struct uath_softc *sc = (struct uath_softc *)req->bulk_client_private; 1211 1212 UATH_DEBUG(UATH_DBG_TX_CMD, "uath: uath_cmd_txeof(): " 1213 "cr:%s(%d), flags:0x%x, tx queued %d\n", 1214 usb_str_cr(req->bulk_completion_reason), 1215 req->bulk_completion_reason, 1216 req->bulk_cb_flags, 1217 sc->tx_cmd_queued); 1218 1219 if (req->bulk_completion_reason != USB_CR_OK) 1220 sc->sc_tx_err++; 1221 1222 mutex_enter(&sc->sc_txlock_cmd); 1223 sc->tx_cmd_queued--; 1224 mutex_exit(&sc->sc_txlock_cmd); 1225 usb_free_bulk_req(req); 1226 } 1227 1228 static int 1229 uath_tx_cmd_xfer(struct uath_softc *sc, 1230 usb_pipe_handle_t pipe, const void *data, uint_t len) 1231 { 1232 usb_bulk_req_t *send_req; 1233 mblk_t *mblk; 1234 int res; 1235 1236 send_req = usb_alloc_bulk_req(sc->sc_dev, len, USB_FLAGS_SLEEP); 1237 1238 send_req->bulk_client_private = (usb_opaque_t)sc; 1239 send_req->bulk_len = (int)len; 1240 send_req->bulk_attributes = USB_ATTRS_AUTOCLEARING; 1241 send_req->bulk_timeout = UATH_CMD_TIMEOUT; 1242 send_req->bulk_cb = uath_cmd_txeof; 1243 send_req->bulk_exc_cb = uath_cmd_txeof; 1244 send_req->bulk_completion_reason = 0; 1245 send_req->bulk_cb_flags = 0; 1246 1247 mblk = send_req->bulk_data; 1248 bcopy(data, mblk->b_rptr, len); 1249 mblk->b_wptr += len; 1250 1251 res = usb_pipe_bulk_xfer(pipe, send_req, USB_FLAGS_NOSLEEP); 1252 if (res != UATH_SUCCESS) { 1253 UATH_DEBUG(UATH_DBG_ERR, "uath: uath_tx_cmd_xfer(): " 1254 "Error %x writing cmd to bulk/out pipe", res); 1255 return (UATH_FAILURE); 1256 } 1257 1258 mutex_enter(&sc->sc_txlock_cmd); 1259 sc->tx_cmd_queued++; 1260 mutex_exit(&sc->sc_txlock_cmd); 1261 return (UATH_SUCCESS); 1262 } 1263 1264 static void 1265 uath_cmdeof(struct uath_softc *sc, struct uath_cmd *cmd) 1266 { 1267 struct uath_cmd_hdr *hdr; 1268 int dlen; 1269 1270 hdr = (struct uath_cmd_hdr *)cmd->buf; 1271 1272 hdr->code = BE_32(hdr->code); 1273 hdr->len = BE_32(hdr->len); 1274 hdr->magic = BE_32(hdr->magic); /* target status on return */ 1275 1276 /* NB: msgid is passed thru w/o byte swapping */ 1277 UATH_DEBUG(UATH_DBG_RX_CMD, "uath: uath_cmdeof(): " 1278 "%s: [ix %x] len=%x status %x\n", 1279 uath_codename(hdr->code), 1280 hdr->msgid, 1281 hdr->len, 1282 hdr->magic); 1283 1284 switch (hdr->code & 0xff) { 1285 /* reply to a read command */ 1286 default: 1287 dlen = hdr->len - sizeof (*hdr); 1288 UATH_DEBUG(UATH_DBG_RX_CMD, "uath: uath_cmdeof(): " 1289 "code %x data len %u\n", 1290 hdr->code & 0xff, dlen); 1291 1292 /* 1293 * The first response from the target after the 1294 * HOST_AVAILABLE has an invalid msgid so we must 1295 * treat it specially. 1296 */ 1297 if ((hdr->msgid < UATH_CMD_LIST_COUNT) && (hdr->code != 0x13)) { 1298 uint32_t *rp = (uint32_t *)(hdr + 1); 1299 uint_t olen; 1300 1301 if (!(sizeof (*hdr) <= hdr->len && 1302 hdr->len < UATH_MAX_CMDSZ)) { 1303 UATH_DEBUG(UATH_DBG_RX_CMD, 1304 "uath: uath_cmdeof(): " 1305 "invalid WDC msg length %u; " 1306 "msg ignored\n", 1307 hdr->len); 1308 return; 1309 } 1310 1311 /* 1312 * Calculate return/receive payload size; the 1313 * first word, if present, always gives the 1314 * number of bytes--unless it's 0 in which 1315 * case a single 32-bit word should be present. 1316 */ 1317 if (dlen >= sizeof (uint32_t)) { 1318 olen = BE_32(rp[0]); 1319 dlen -= sizeof (uint32_t); 1320 if (olen == 0) { 1321 /* convention is 0 =>'s one word */ 1322 olen = sizeof (uint32_t); 1323 /* XXX KASSERT(olen == dlen ) */ 1324 } 1325 } else 1326 olen = 0; 1327 1328 if (cmd->odata != NULL) { 1329 /* NB: cmd->olen validated in uath_cmd */ 1330 if (olen > cmd->olen) { 1331 /* XXX complain? */ 1332 UATH_DEBUG(UATH_DBG_RX_CMD, 1333 "uath: uath_cmdeof(): " 1334 "cmd 0x%x olen %u cmd olen %u\n", 1335 hdr->code, olen, cmd->olen); 1336 olen = cmd->olen; 1337 } 1338 if (olen > dlen) { 1339 /* XXX complain, shouldn't happen */ 1340 UATH_DEBUG(UATH_DBG_RX_CMD, 1341 "uath: uath_cmdeof(): " 1342 "cmd 0x%x olen %u dlen %u\n", 1343 hdr->code, olen, dlen); 1344 olen = dlen; 1345 } 1346 /* XXX have submitter do this */ 1347 /* copy answer into caller's supplied buffer */ 1348 bcopy(&rp[1], cmd->odata, olen); 1349 cmd->olen = olen; 1350 } 1351 } 1352 1353 /* Just signal that something happened */ 1354 uath_cmd_lock_signal(&sc->rlock); 1355 break; 1356 1357 case WDCMSG_TARGET_START: 1358 UATH_DEBUG(UATH_DBG_RX_CMD, "uath: uath_cmdeof(): " 1359 "receive TARGET STAERT\n"); 1360 1361 if (hdr->msgid >= UATH_CMD_LIST_COUNT) { 1362 /* XXX */ 1363 return; 1364 } 1365 dlen = hdr->len - sizeof (*hdr); 1366 if (dlen != sizeof (uint32_t)) { 1367 /* XXX something wrong */ 1368 return; 1369 } 1370 /* XXX have submitter do this */ 1371 /* copy answer into caller's supplied buffer */ 1372 bcopy(hdr + 1, cmd->odata, sizeof (uint32_t)); 1373 cmd->olen = sizeof (uint32_t); 1374 1375 /* wake up caller */ 1376 uath_cmd_lock_signal(&sc->rlock); 1377 break; 1378 1379 case WDCMSG_SEND_COMPLETE: 1380 /* this notification is sent when UATH_TX_NOTIFY is set */ 1381 UATH_DEBUG(UATH_DBG_RX_CMD, "uath: uath_cmdeof(): " 1382 "receive Tx notification\n"); 1383 break; 1384 1385 case WDCMSG_TARGET_GET_STATS: 1386 UATH_DEBUG(UATH_DBG_RX_CMD, "uath: uath_cmdeof(): " 1387 "received device statistics\n"); 1388 break; 1389 } 1390 } 1391 1392 /* ARGSUSED */ 1393 static void 1394 uath_cmd_rxeof(usb_pipe_handle_t pipe, usb_bulk_req_t *req) 1395 { 1396 struct uath_softc *sc = (struct uath_softc *)req->bulk_client_private; 1397 struct uath_cmd_hdr *hdr; 1398 struct uath_cmd *cmd; 1399 mblk_t *m, *mp; 1400 int len; 1401 1402 UATH_DEBUG(UATH_DBG_RX_CMD, "uath: uath_cmd_rxeof(): " 1403 "cr:%s(%d), flags:0x%x, rx queued %d\n", 1404 usb_str_cr(req->bulk_completion_reason), 1405 req->bulk_completion_reason, 1406 req->bulk_cb_flags, 1407 sc->rx_cmd_queued); 1408 1409 m = req->bulk_data; 1410 req->bulk_data = NULL; 1411 1412 if (req->bulk_completion_reason != USB_CR_OK) { 1413 UATH_DEBUG(UATH_DBG_RX_CMD, "uath: uath_cmd_rxeof(): " 1414 "USB CR is not OK\n"); 1415 goto fail; 1416 } 1417 1418 if (m->b_cont != NULL) { 1419 /* Fragmented message, concatenate */ 1420 mp = msgpullup(m, -1); 1421 freemsg(m); 1422 m = mp; 1423 mp = NULL; 1424 } 1425 1426 len = msgdsize(m); 1427 if (len < sizeof (struct uath_cmd_hdr)) { 1428 UATH_DEBUG(UATH_DBG_RX_CMD, "uath: uath_rx_cmdeof(): " 1429 "short xfer error\n"); 1430 goto fail; 1431 } 1432 1433 hdr = (struct uath_cmd_hdr *)m->b_rptr; 1434 if (BE_32(hdr->code) == 0x13) 1435 cmd = &sc->sc_cmd[0]; 1436 else 1437 cmd = &sc->sc_cmd[hdr->msgid]; 1438 1439 bcopy(m->b_rptr, cmd->buf, len); 1440 uath_cmdeof(sc, cmd); 1441 (void) uath_rx_cmd_xfer(sc); 1442 fail: 1443 mutex_enter(&sc->sc_rxlock_cmd); 1444 sc->rx_cmd_queued--; 1445 mutex_exit(&sc->sc_rxlock_cmd); 1446 if (m) freemsg(m); 1447 usb_free_bulk_req(req); 1448 } 1449 1450 static int 1451 uath_rx_cmd_xfer(struct uath_softc *sc) 1452 { 1453 usb_bulk_req_t *req; 1454 int err; 1455 1456 req = usb_alloc_bulk_req(sc->sc_dev, UATH_MAX_CMDSZ, USB_FLAGS_SLEEP); 1457 if (req == NULL) { 1458 UATH_DEBUG(UATH_DBG_MSG, "uath: uath_rx_cmd_xfer(): " 1459 "failed to allocate req"); 1460 return (UATH_FAILURE); 1461 } 1462 1463 req->bulk_len = UATH_MAX_CMDSZ; 1464 req->bulk_client_private = (usb_opaque_t)sc; 1465 req->bulk_cb = uath_cmd_rxeof; 1466 req->bulk_exc_cb = uath_cmd_rxeof; 1467 req->bulk_timeout = 0; 1468 req->bulk_completion_reason = 0; 1469 req->bulk_cb_flags = 0; 1470 req->bulk_attributes = USB_ATTRS_SHORT_XFER_OK 1471 | USB_ATTRS_AUTOCLEARING; 1472 1473 err = usb_pipe_bulk_xfer(sc->rx_cmd_pipe, req, USB_FLAGS_NOSLEEP); 1474 if (err != USB_SUCCESS) { 1475 UATH_DEBUG(UATH_DBG_MSG, "uath: uath_rx_cmd_xfer(): " 1476 "failed to do rx xfer, %d", err); 1477 usb_free_bulk_req(req); 1478 return (UATH_FAILURE); 1479 } 1480 1481 mutex_enter(&sc->sc_rxlock_cmd); 1482 sc->rx_cmd_queued++; 1483 mutex_exit(&sc->sc_rxlock_cmd); 1484 return (UATH_SUCCESS); 1485 } 1486 1487 static void 1488 uath_init_data_queue(struct uath_softc *sc) 1489 { 1490 sc->tx_data_queued = sc->rx_data_queued = 0; 1491 } 1492 1493 /* ARGSUSED */ 1494 static void 1495 uath_data_txeof(usb_pipe_handle_t pipe, usb_bulk_req_t *req) 1496 { 1497 struct uath_softc *sc = (struct uath_softc *)req->bulk_client_private; 1498 struct ieee80211com *ic = &sc->sc_ic; 1499 1500 UATH_DEBUG(UATH_DBG_TX, "uath: uath_data_txeof(): " 1501 "uath_txeof(): cr:%s(%d), flags:0x%x, tx_data_queued %d\n", 1502 usb_str_cr(req->bulk_completion_reason), 1503 req->bulk_completion_reason, 1504 req->bulk_cb_flags, 1505 sc->tx_data_queued); 1506 1507 if (req->bulk_completion_reason != USB_CR_OK) 1508 sc->sc_tx_err++; 1509 1510 mutex_enter(&sc->sc_txlock_data); 1511 sc->tx_data_queued--; 1512 1513 if (sc->sc_need_sched) { 1514 sc->sc_need_sched = 0; 1515 mac_tx_update(ic->ic_mach); 1516 } 1517 1518 mutex_exit(&sc->sc_txlock_data); 1519 usb_free_bulk_req(req); 1520 } 1521 1522 static int 1523 uath_tx_data_xfer(struct uath_softc *sc, mblk_t *mp) 1524 { 1525 usb_bulk_req_t *req; 1526 int err; 1527 1528 req = usb_alloc_bulk_req(sc->sc_dev, 0, USB_FLAGS_SLEEP); 1529 if (req == NULL) { 1530 UATH_DEBUG(UATH_DBG_TX, "uath: uath_tx_data_xfer(): " 1531 "uath_tx_data_xfer(): failed to allocate req"); 1532 freemsg(mp); 1533 return (UATH_FAILURE); 1534 } 1535 1536 req->bulk_len = msgdsize(mp); 1537 req->bulk_data = mp; 1538 req->bulk_client_private = (usb_opaque_t)sc; 1539 req->bulk_timeout = UATH_DATA_TIMEOUT; 1540 req->bulk_attributes = USB_ATTRS_AUTOCLEARING; 1541 req->bulk_cb = uath_data_txeof; 1542 req->bulk_exc_cb = uath_data_txeof; 1543 req->bulk_completion_reason = 0; 1544 req->bulk_cb_flags = 0; 1545 1546 if ((err = usb_pipe_bulk_xfer(sc->tx_data_pipe, req, 0)) != 1547 USB_SUCCESS) { 1548 1549 UATH_DEBUG(UATH_DBG_TX, "uath: uath_tx_data_xfer(): " 1550 "failed to do tx xfer, %d", err); 1551 usb_free_bulk_req(req); 1552 return (UATH_FAILURE); 1553 } 1554 1555 sc->tx_data_queued++; 1556 return (UATH_SUCCESS); 1557 } 1558 1559 /* ARGSUSED */ 1560 static void 1561 uath_data_rxeof(usb_pipe_handle_t pipe, usb_bulk_req_t *req) 1562 { 1563 struct uath_softc *sc = (struct uath_softc *)req->bulk_client_private; 1564 struct ieee80211com *ic = &sc->sc_ic; 1565 struct uath_chunk *chunk; 1566 struct uath_rx_desc *desc; 1567 struct ieee80211_frame *wh; 1568 struct ieee80211_node *ni; 1569 1570 mblk_t *m, *mp; 1571 uint8_t *rxbuf; 1572 int actlen, pktlen; 1573 1574 mutex_enter(&sc->sc_rxlock_data); 1575 1576 UATH_DEBUG(UATH_DBG_RX, "uath: uath_data_rxeof(): " 1577 "cr:%s(%d), flags:0x%x, rx_data_queued %d\n", 1578 usb_str_cr(req->bulk_completion_reason), 1579 req->bulk_completion_reason, 1580 req->bulk_cb_flags, 1581 sc->rx_data_queued); 1582 1583 mp = req->bulk_data; 1584 req->bulk_data = NULL; 1585 1586 if (req->bulk_completion_reason != USB_CR_OK) { 1587 UATH_DEBUG(UATH_DBG_RX, "uath: uath_data_rxeof(): " 1588 "USB CR is not OK\n"); 1589 sc->sc_rx_err++; 1590 goto fail; 1591 } 1592 1593 rxbuf = (uint8_t *)mp->b_rptr; 1594 actlen = (uintptr_t)mp->b_wptr - (uintptr_t)mp->b_rptr; 1595 if (actlen < UATH_MIN_RXBUFSZ) { 1596 UATH_DEBUG(UATH_DBG_RX, "uath_data_rxeof(): " 1597 "wrong recv size %d\n", actlen); 1598 sc->sc_rx_err++; 1599 goto fail; 1600 } 1601 1602 chunk = (struct uath_chunk *)rxbuf; 1603 if (chunk->seqnum == 0 && chunk->flags == 0 && chunk->length == 0) { 1604 UATH_DEBUG(UATH_DBG_RX, "uath: uath_data_rxeof(): " 1605 "strange response\n"); 1606 UATH_RESET_INTRX(sc); 1607 sc->sc_rx_err++; 1608 goto fail; 1609 } 1610 1611 if (chunk->seqnum != sc->sc_intrx_nextnum) { 1612 UATH_DEBUG(UATH_DBG_RX, "uath: uath_data_rxeof(): " 1613 "invalid seqnum %d, expected %d\n", 1614 chunk->seqnum, sc->sc_intrx_nextnum); 1615 UATH_STAT_INC(sc, st_badchunkseqnum); 1616 UATH_RESET_INTRX(sc); 1617 sc->sc_rx_err++; 1618 goto fail; 1619 } 1620 1621 /* check multi-chunk frames */ 1622 if ((chunk->seqnum == 0 && !(chunk->flags & UATH_CFLAGS_FINAL)) || 1623 (chunk->seqnum != 0 && (chunk->flags & UATH_CFLAGS_FINAL)) || 1624 chunk->flags & UATH_CFLAGS_RXMSG) { 1625 UATH_DEBUG(UATH_DBG_RX, "uath: uath_data_rxeof(): " 1626 "receive multi-chunk frames " 1627 "chunk seqnum %x, flags %x, length %u\n", 1628 chunk->seqnum, chunk->flags, BE_16(chunk->length)); 1629 UATH_STAT_INC(sc, st_multichunk); 1630 } 1631 1632 1633 /* if the frame is not final continue the transfer */ 1634 if (!(chunk->flags & UATH_CFLAGS_FINAL)) 1635 sc->sc_intrx_nextnum++; 1636 1637 /* 1638 * if the frame is not set UATH_CFLAGS_RXMSG, then rx descriptor is 1639 * located at the end, 32-bit aligned 1640 */ 1641 desc = (chunk->flags & UATH_CFLAGS_RXMSG) ? 1642 (struct uath_rx_desc *)(chunk + 1) : 1643 (struct uath_rx_desc *)(((uint8_t *)chunk) + 1644 sizeof (struct uath_chunk) + BE_16(chunk->length) - 1645 sizeof (struct uath_rx_desc)); 1646 1647 UATH_DEBUG(UATH_DBG_RX, "uath: uath_data_rxeof(): " 1648 "frame len %u code %u status %u rate %u antenna %u " 1649 "rssi %d channel %u phyerror %u connix %u " 1650 "decrypterror %u keycachemiss %u\n", 1651 BE_32(desc->framelen), BE_32(desc->code), BE_32(desc->status), 1652 BE_32(desc->rate), BE_32(desc->antenna), BE_32(desc->rssi), 1653 BE_32(desc->channel), BE_32(desc->phyerror), BE_32(desc->connix), 1654 BE_32(desc->decrypterror), BE_32(desc->keycachemiss)); 1655 1656 if (BE_32(desc->len) > IEEE80211_MAX_LEN) { 1657 UATH_DEBUG(UATH_DBG_RX, "uath: uath_data_rxeof(): " 1658 "bad descriptor (len=%d)\n", BE_32(desc->len)); 1659 UATH_STAT_INC(sc, st_toobigrxpkt); 1660 goto fail; 1661 } 1662 1663 uath_update_rxstat(sc, BE_32(desc->status)); 1664 1665 pktlen = BE_32(desc->framelen) - UATH_RX_DUMMYSIZE; 1666 1667 if ((m = allocb(pktlen, BPRI_MED)) == NULL) { 1668 UATH_DEBUG(UATH_DBG_RX, "uath: uath_data_rxeof(): " 1669 "allocate mblk failed.\n"); 1670 sc->sc_rx_nobuf++; 1671 goto fail; 1672 } 1673 bcopy((rxbuf + sizeof (struct uath_chunk)), m->b_rptr, pktlen); 1674 1675 m->b_wptr = m->b_rptr + pktlen; 1676 wh = (struct ieee80211_frame *)m->b_rptr; 1677 ni = ieee80211_find_rxnode(ic, wh); 1678 1679 /* send the frame to the 802.11 layer */ 1680 (void) ieee80211_input(ic, m, ni, (int)BE_32(desc->rssi), 0); 1681 1682 /* node is no longer needed */ 1683 ieee80211_free_node(ni); 1684 fail: 1685 sc->rx_data_queued--; 1686 if (mp) freemsg(mp); 1687 usb_free_bulk_req(req); 1688 mutex_exit(&sc->sc_rxlock_data); 1689 if (UATH_IS_RUNNING(sc) && !UATH_IS_SUSPEND(sc)) { 1690 (void) uath_rx_data_xfer(sc); 1691 } 1692 } 1693 1694 static int 1695 uath_rx_data_xfer(struct uath_softc *sc) 1696 { 1697 usb_bulk_req_t *req; 1698 int err; 1699 1700 req = usb_alloc_bulk_req(sc->sc_dev, 1701 IEEE80211_MAX_LEN, USB_FLAGS_SLEEP); 1702 if (req == NULL) { 1703 UATH_DEBUG(UATH_DBG_ERR, "uath: uath_rx_data_xfer(): " 1704 "failed to allocate req"); 1705 return (UATH_SUCCESS); 1706 } 1707 1708 req->bulk_len = IEEE80211_MAX_LEN; 1709 req->bulk_cb = uath_data_rxeof; 1710 req->bulk_exc_cb = uath_data_rxeof; 1711 req->bulk_client_private = (usb_opaque_t)sc; 1712 req->bulk_timeout = 0; 1713 req->bulk_completion_reason = 0; 1714 req->bulk_cb_flags = 0; 1715 req->bulk_attributes = USB_ATTRS_SHORT_XFER_OK 1716 | USB_ATTRS_AUTOCLEARING; 1717 1718 err = usb_pipe_bulk_xfer(sc->rx_data_pipe, req, 0); 1719 if (err != UATH_SUCCESS) { 1720 UATH_DEBUG(UATH_DBG_ERR, "uath: uath_rx_data_xfer(): " 1721 "failed to do rx xfer, %d", err); 1722 usb_free_bulk_req(req); 1723 return (UATH_FAILURE); 1724 } 1725 1726 mutex_enter(&sc->sc_rxlock_data); 1727 sc->rx_data_queued++; 1728 mutex_exit(&sc->sc_rxlock_data); 1729 return (UATH_SUCCESS); 1730 } 1731 1732 static void 1733 uath_update_rxstat(struct uath_softc *sc, uint32_t status) 1734 { 1735 1736 switch (status) { 1737 case UATH_STATUS_STOP_IN_PROGRESS: 1738 UATH_STAT_INC(sc, st_stopinprogress); 1739 break; 1740 case UATH_STATUS_CRC_ERR: 1741 UATH_STAT_INC(sc, st_crcerr); 1742 break; 1743 case UATH_STATUS_PHY_ERR: 1744 UATH_STAT_INC(sc, st_phyerr); 1745 break; 1746 case UATH_STATUS_DECRYPT_CRC_ERR: 1747 UATH_STAT_INC(sc, st_decrypt_crcerr); 1748 break; 1749 case UATH_STATUS_DECRYPT_MIC_ERR: 1750 UATH_STAT_INC(sc, st_decrypt_micerr); 1751 break; 1752 case UATH_STATUS_DECOMP_ERR: 1753 UATH_STAT_INC(sc, st_decomperr); 1754 break; 1755 case UATH_STATUS_KEY_ERR: 1756 UATH_STAT_INC(sc, st_keyerr); 1757 break; 1758 case UATH_STATUS_ERR: 1759 UATH_STAT_INC(sc, st_err); 1760 break; 1761 default: 1762 break; 1763 } 1764 } 1765 1766 static void 1767 uath_next_scan(void *arg) 1768 { 1769 struct uath_softc *sc = arg; 1770 struct ieee80211com *ic = &sc->sc_ic; 1771 1772 if (ic->ic_state == IEEE80211_S_SCAN) 1773 ieee80211_next_scan(ic); 1774 1775 sc->sc_scan_id = 0; 1776 } 1777 1778 static int 1779 uath_create_connection(struct uath_softc *sc, uint32_t connid) 1780 { 1781 const struct ieee80211_rateset *rs; 1782 struct ieee80211com *ic = &sc->sc_ic; 1783 struct ieee80211_node *ni = ic->ic_bss; 1784 struct uath_cmd_create_connection create; 1785 int err; 1786 1787 bzero(&create, sizeof (create)); 1788 create.connid = BE_32(connid); 1789 create.bssid = BE_32(0); 1790 /* XXX packed or not? */ 1791 create.size = BE_32(sizeof (struct uath_cmd_rateset)); 1792 1793 rs = &ni->in_rates; 1794 create.connattr.rateset.length = rs->ir_nrates; 1795 bcopy(rs->ir_rates, &create.connattr.rateset.set[0], 1796 rs->ir_nrates); 1797 1798 /* XXX turbo */ 1799 if (UATH_IS_CHAN_A(ni->in_chan)) 1800 create.connattr.wlanmode = BE_32(WLAN_MODE_11a); 1801 else if (UATH_IS_CHAN_ANYG(ni->in_chan)) 1802 create.connattr.wlanmode = BE_32(WLAN_MODE_11g); 1803 else 1804 create.connattr.wlanmode = BE_32(WLAN_MODE_11b); 1805 1806 err = uath_cmd_write(sc, WDCMSG_CREATE_CONNECTION, &create, 1807 sizeof (create), 0); 1808 return (err); 1809 } 1810 1811 static int 1812 uath_set_rates(struct uath_softc *sc, const struct ieee80211_rateset *rs) 1813 { 1814 struct uath_cmd_rates rates; 1815 int err; 1816 1817 bzero(&rates, sizeof (rates)); 1818 rates.connid = BE_32(UATH_ID_BSS); /* XXX */ 1819 rates.size = BE_32(sizeof (struct uath_cmd_rateset)); 1820 /* XXX bounds check rs->rs_nrates */ 1821 rates.rateset.length = rs->ir_nrates; 1822 bcopy(rs->ir_rates, &rates.rateset.set[0], rs->ir_nrates); 1823 1824 UATH_DEBUG(UATH_DBG_MSG, "uath: uath_set_rates(): " 1825 "setting supported rates nrates=%d\n", rs->ir_nrates); 1826 err = uath_cmd_write(sc, WDCMSG_SET_BASIC_RATE, 1827 &rates, sizeof (rates), 0); 1828 return (err); 1829 } 1830 1831 static int 1832 uath_write_associd(struct uath_softc *sc) 1833 { 1834 struct ieee80211com *ic = &sc->sc_ic; 1835 struct ieee80211_node *ni = ic->ic_bss; 1836 struct uath_cmd_set_associd associd; 1837 int err; 1838 1839 bzero(&associd, sizeof (associd)); 1840 associd.defaultrateix = BE_32(1); /* XXX */ 1841 associd.associd = BE_32(ni->in_associd); 1842 associd.timoffset = BE_32(0x3b); /* XXX */ 1843 IEEE80211_ADDR_COPY(associd.bssid, ni->in_bssid); 1844 err = uath_cmd_write(sc, WDCMSG_WRITE_ASSOCID, &associd, 1845 sizeof (associd), 0); 1846 return (err); 1847 } 1848 1849 static int 1850 uath_set_ledsteady(struct uath_softc *sc, int lednum, int ledmode) 1851 { 1852 struct uath_cmd_ledsteady led; 1853 int err; 1854 1855 led.lednum = BE_32(lednum); 1856 led.ledmode = BE_32(ledmode); 1857 1858 UATH_DEBUG(UATH_DBG_MSG, "uath: uath_set_ledsteady(): " 1859 "set %s led %s (steady)\n", 1860 (lednum == UATH_LED_LINK) ? "link" : "activity", 1861 ledmode ? "on" : "off"); 1862 err = uath_cmd_write(sc, WDCMSG_SET_LED_STEADY, &led, sizeof (led), 0); 1863 return (err); 1864 } 1865 1866 static int 1867 uath_set_ledblink(struct uath_softc *sc, int lednum, int ledmode, 1868 int blinkrate, int slowmode) 1869 { 1870 struct uath_cmd_ledblink led; 1871 int err; 1872 1873 led.lednum = BE_32(lednum); 1874 led.ledmode = BE_32(ledmode); 1875 led.blinkrate = BE_32(blinkrate); 1876 led.slowmode = BE_32(slowmode); 1877 1878 UATH_DEBUG(UATH_DBG_MSG, "uath: uath_set_ledblink(): " 1879 "set %s led %s (blink)\n", 1880 (lednum == UATH_LED_LINK) ? "link" : "activity", 1881 ledmode ? "on" : "off"); 1882 1883 err = uath_cmd_write(sc, WDCMSG_SET_LED_BLINK, 1884 &led, sizeof (led), 0); 1885 return (err); 1886 } 1887 1888 1889 static int 1890 uath_newstate(struct ieee80211com *ic, enum ieee80211_state nstate, int arg) 1891 { 1892 struct uath_softc *sc = (struct uath_softc *)ic; 1893 struct ieee80211_node *ni = ic->ic_bss; 1894 enum ieee80211_state ostate; 1895 int err; 1896 1897 ostate = ic->ic_state; 1898 UATH_DEBUG(UATH_DBG_MSG, "uath: uath_newstate(): " 1899 "%d -> %d\n", ostate, nstate); 1900 1901 if (sc->sc_scan_id != 0) { 1902 (void) untimeout(sc->sc_scan_id); 1903 sc->sc_scan_id = 0; 1904 } 1905 1906 UATH_LOCK(sc); 1907 1908 if (UATH_IS_DISCONNECT(sc) && (nstate != IEEE80211_S_INIT)) { 1909 UATH_UNLOCK(sc); 1910 return (DDI_SUCCESS); 1911 } 1912 1913 if (UATH_IS_SUSPEND(sc) && (nstate != IEEE80211_S_INIT)) { 1914 UATH_UNLOCK(sc); 1915 return (DDI_SUCCESS); 1916 } 1917 1918 switch (nstate) { 1919 case IEEE80211_S_INIT: 1920 if (ostate == IEEE80211_S_RUN) { 1921 /* turn link and activity LEDs off */ 1922 (void) uath_set_ledstate(sc, 0); 1923 } 1924 break; 1925 case IEEE80211_S_SCAN: 1926 if (uath_switch_channel(sc, ic->ic_curchan) != UATH_SUCCESS) { 1927 UATH_DEBUG(UATH_DBG_ERR, "uath: uath_newstate(): " 1928 "could not switch channel\n"); 1929 break; 1930 } 1931 sc->sc_scan_id = timeout(uath_next_scan, (void *)sc, 1932 drv_usectohz(250000)); 1933 break; 1934 case IEEE80211_S_AUTH: 1935 /* XXX good place? set RTS threshold */ 1936 uath_config(sc, CFG_USER_RTS_THRESHOLD, ic->ic_rtsthreshold); 1937 1938 if (uath_switch_channel(sc, ni->in_chan) != 0) { 1939 UATH_DEBUG(UATH_DBG_ERR, "uath: uath_newstate(): " 1940 "could not switch channel\n"); 1941 break; 1942 } 1943 if (uath_create_connection(sc, UATH_ID_BSS) != 0) { 1944 UATH_DEBUG(UATH_DBG_ERR, "uath: uath_newstate(): " 1945 "could not create connection\n"); 1946 break; 1947 } 1948 break; 1949 case IEEE80211_S_ASSOC: 1950 if (uath_set_rates(sc, &ni->in_rates) != 0) { 1951 UATH_DEBUG(UATH_DBG_ERR, "uath: uath_newstate(): " 1952 "could not set negotiated rate set\n"); 1953 break; 1954 } 1955 break; 1956 case IEEE80211_S_RUN: 1957 /* XXX monitor mode doesn't be supported */ 1958 if (ic->ic_opmode == IEEE80211_M_MONITOR) { 1959 (void) uath_set_ledstate(sc, 1); 1960 break; 1961 } 1962 1963 /* 1964 * Tx rate is controlled by firmware, report the maximum 1965 * negotiated rate in ifconfig output. 1966 */ 1967 ni->in_txrate = ni->in_rates.ir_nrates - 1; 1968 1969 if (uath_write_associd(sc) != 0) { 1970 UATH_DEBUG(UATH_DBG_ERR, "uath: uath_newstate(): " 1971 "could not write association id\n"); 1972 break; 1973 } 1974 /* turn link LED on */ 1975 (void) uath_set_ledsteady(sc, UATH_LED_LINK, UATH_LED_ON); 1976 /* make activity LED blink */ 1977 (void) uath_set_ledblink(sc, UATH_LED_ACTIVITY, 1978 UATH_LED_ON, 1, 2); 1979 /* set state to associated */ 1980 (void) uath_set_ledstate(sc, 1); 1981 break; 1982 } 1983 1984 UATH_UNLOCK(sc); 1985 1986 err = sc->sc_newstate(ic, nstate, arg); 1987 return (err); 1988 } 1989 1990 static int 1991 uath_send(ieee80211com_t *ic, mblk_t *mp, uint8_t type) 1992 { 1993 struct uath_softc *sc = (struct uath_softc *)ic; 1994 struct uath_chunk *chunk; 1995 struct uath_tx_desc *desc; 1996 struct ieee80211_frame *wh; 1997 struct ieee80211_node *ni = NULL; 1998 struct ieee80211_key *k; 1999 2000 mblk_t *m, *m0; 2001 int err, off, mblen; 2002 int pktlen, framelen, msglen; 2003 2004 err = UATH_SUCCESS; 2005 2006 mutex_enter(&sc->sc_txlock_data); 2007 2008 if (UATH_IS_SUSPEND(sc)) { 2009 err = 0; 2010 goto fail; 2011 } 2012 2013 if (sc->tx_data_queued > UATH_TX_DATA_LIST_COUNT) { 2014 UATH_DEBUG(UATH_DBG_TX, "uath: uath_send(): " 2015 "no TX buffer available!\n"); 2016 if ((type & IEEE80211_FC0_TYPE_MASK) == 2017 IEEE80211_FC0_TYPE_DATA) { 2018 sc->sc_need_sched = 1; 2019 } 2020 sc->sc_tx_nobuf++; 2021 err = ENOMEM; 2022 goto fail; 2023 } 2024 2025 m = allocb(UATH_MAX_TXBUFSZ, BPRI_MED); 2026 if (m == NULL) { 2027 UATH_DEBUG(UATH_DBG_TX, "uath: uath_send(): " 2028 "can't alloc mblk.\n"); 2029 err = DDI_FAILURE; 2030 goto fail; 2031 } 2032 2033 /* skip TX descriptor */ 2034 m->b_rptr += sizeof (struct uath_chunk) + sizeof (struct uath_tx_desc); 2035 m->b_wptr += sizeof (struct uath_chunk) + sizeof (struct uath_tx_desc); 2036 2037 for (off = 0, m0 = mp; m0 != NULL; m0 = m0->b_cont) { 2038 mblen = (uintptr_t)m0->b_wptr - (uintptr_t)m0->b_rptr; 2039 (void) memcpy(m->b_rptr + off, m0->b_rptr, mblen); 2040 off += mblen; 2041 } 2042 m->b_wptr += off; 2043 2044 wh = (struct ieee80211_frame *)m->b_rptr; 2045 2046 ni = ieee80211_find_txnode(ic, wh->i_addr1); 2047 if (ni == NULL) { 2048 err = DDI_FAILURE; 2049 freemsg(m); 2050 goto fail; 2051 } 2052 2053 if ((type & IEEE80211_FC0_TYPE_MASK) == 2054 IEEE80211_FC0_TYPE_DATA) { 2055 (void) ieee80211_encap(ic, m, ni); 2056 } 2057 2058 if (wh->i_fc[1] & IEEE80211_FC1_WEP) { 2059 k = ieee80211_crypto_encap(ic, m); 2060 if (k == NULL) { 2061 freemsg(m); 2062 err = DDI_FAILURE; 2063 goto fail; 2064 } 2065 /* packet header may have moved, reset our local pointer */ 2066 wh = (struct ieee80211_frame *)m->b_rptr; 2067 } 2068 2069 pktlen = (uintptr_t)m->b_wptr - (uintptr_t)m->b_rptr; 2070 framelen = pktlen + IEEE80211_CRC_LEN; 2071 msglen = framelen + sizeof (struct uath_tx_desc); 2072 2073 m->b_rptr -= sizeof (struct uath_chunk) + sizeof (struct uath_tx_desc); 2074 2075 chunk = (struct uath_chunk *)m->b_rptr; 2076 desc = (struct uath_tx_desc *)(chunk + 1); 2077 2078 /* one chunk only for now */ 2079 chunk->seqnum = 0; 2080 chunk->flags = UATH_CFLAGS_FINAL; 2081 chunk->length = BE_16(msglen); 2082 2083 /* fill Tx descriptor */ 2084 desc->msglen = BE_32(msglen); 2085 /* NB: to get UATH_TX_NOTIFY reply, `msgid' must be larger than 0 */ 2086 desc->msgid = sc->sc_msgid; /* don't care about endianness */ 2087 desc->type = BE_32(WDCMSG_SEND); 2088 switch (wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK) { 2089 case IEEE80211_FC0_TYPE_CTL: 2090 case IEEE80211_FC0_TYPE_MGT: 2091 /* NB: force all management frames to highest queue */ 2092 if (ni->in_flags & UATH_NODE_QOS) { 2093 /* NB: force all management frames to highest queue */ 2094 desc->txqid = BE_32(WME_AC_VO | UATH_TXQID_MINRATE); 2095 } else 2096 desc->txqid = BE_32(WME_AC_BE | UATH_TXQID_MINRATE); 2097 break; 2098 case IEEE80211_FC0_TYPE_DATA: 2099 /* XXX multicast frames should honor mcastrate */ 2100 desc->txqid = BE_32(WME_AC_BE); 2101 break; 2102 default: 2103 UATH_DEBUG(UATH_DBG_TX, "uath: uath_send(): " 2104 "bogus frame type 0x%x (%s)\n", 2105 wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK); 2106 err = EIO; 2107 goto fail; 2108 } 2109 2110 if (ic->ic_state == IEEE80211_S_AUTH || 2111 ic->ic_state == IEEE80211_S_ASSOC || 2112 ic->ic_state == IEEE80211_S_RUN) 2113 desc->connid = BE_32(UATH_ID_BSS); 2114 else 2115 desc->connid = BE_32(UATH_ID_INVALID); 2116 desc->flags = BE_32(0 /* no UATH_TX_NOTIFY */); 2117 desc->buflen = BE_32(pktlen); 2118 2119 (void) uath_tx_data_xfer(sc, m); 2120 2121 sc->sc_msgid = (sc->sc_msgid + 1) % UATH_TX_DATA_LIST_COUNT; 2122 2123 ic->ic_stats.is_tx_frags++; 2124 ic->ic_stats.is_tx_bytes += pktlen; 2125 2126 fail: 2127 if (ni != NULL) 2128 ieee80211_free_node(ni); 2129 if ((mp) && 2130 ((type & IEEE80211_FC0_TYPE_MASK) != IEEE80211_FC0_TYPE_DATA || 2131 err == 0)) { 2132 freemsg(mp); 2133 } 2134 mutex_exit(&sc->sc_txlock_data); 2135 return (err); 2136 } 2137 2138 static int 2139 uath_reconnect(dev_info_t *devinfo) 2140 { 2141 struct uath_softc *sc; 2142 struct ieee80211com *ic; 2143 int err; 2144 uint16_t vendor_id, product_id; 2145 2146 UATH_DEBUG(UATH_DBG_MSG, "uath: uath_reconnect(): " 2147 "uath online\n"); 2148 2149 sc = ddi_get_soft_state(uath_soft_state_p, ddi_get_instance(devinfo)); 2150 ASSERT(sc != NULL); 2151 ic = (struct ieee80211com *)&sc->sc_ic; 2152 2153 if (!UATH_IS_RECONNECT(sc)) { 2154 err = uath_open_pipes(sc); 2155 if (err != UATH_SUCCESS) { 2156 UATH_DEBUG(UATH_DBG_ERR, "uath: uath_reconnect(): " 2157 "could not open pipes\n"); 2158 return (DDI_FAILURE); 2159 } 2160 2161 err = uath_loadfirmware(sc); 2162 if (err != DDI_SUCCESS) { 2163 UATH_DEBUG(UATH_DBG_ERR, "uath: uath_reconnect(): " 2164 "could not download firmware\n"); 2165 return (DDI_FAILURE); 2166 } 2167 2168 uath_close_pipes(sc); 2169 usb_client_detach(sc->sc_dev, sc->sc_udev); 2170 2171 /* reset device */ 2172 err = usb_reset_device(sc->sc_dev, USB_RESET_LVL_DEFAULT); 2173 if (err != USB_SUCCESS) { 2174 UATH_DEBUG(UATH_DBG_ERR, "uath: uath_reconnect(): " 2175 "could not reset device %x\n", err); 2176 } 2177 2178 err = usb_client_attach(devinfo, USBDRV_VERSION, 0); 2179 if (err != USB_SUCCESS) { 2180 UATH_DEBUG(UATH_DBG_ERR, "uath: uath_reconnect(): " 2181 "usb_client_attach failed\n"); 2182 } 2183 2184 err = usb_get_dev_data(devinfo, &sc->sc_udev, 2185 USB_PARSE_LVL_ALL, 0); 2186 if (err != USB_SUCCESS) { 2187 sc->sc_udev = NULL; 2188 UATH_DEBUG(UATH_DBG_ERR, "uath: uath_reconnect(): " 2189 "usb_get_dev_data failed\n"); 2190 } 2191 2192 vendor_id = sc->sc_udev->dev_descr->idVendor; 2193 product_id = sc->sc_udev->dev_descr->idProduct; 2194 sc->dev_flags = uath_lookup(vendor_id, product_id); 2195 if (sc->dev_flags == UATH_FLAG_ERR) { 2196 UATH_DEBUG(UATH_DBG_ERR, "uath: uath_reconnect(): " 2197 "HW does not match\n"); 2198 } 2199 2200 UATH_DEBUG(UATH_DBG_MSG, "uath: uath_reconnect(): " 2201 "vendorId = %x,deviceID = %x, flags = %x\n", 2202 vendor_id, product_id, sc->dev_flags); 2203 2204 UATH_LOCK(sc); 2205 sc->sc_flags |= UATH_FLAG_RECONNECT; 2206 UATH_UNLOCK(sc); 2207 2208 } else { 2209 err = uath_open_pipes(sc); 2210 if (err != UATH_SUCCESS) { 2211 UATH_DEBUG(UATH_DBG_ERR, "uath: uath_reconnect(): " 2212 "could not open pipes\n"); 2213 return (DDI_FAILURE); 2214 } 2215 2216 /* 2217 * Allocate xfers for firmware commands. 2218 */ 2219 err = uath_alloc_cmd_list(sc, sc->sc_cmd, UATH_CMD_LIST_COUNT, 2220 UATH_MAX_CMDSZ); 2221 if (err != UATH_SUCCESS) { 2222 UATH_DEBUG(UATH_DBG_ERR, "uath: uath_reconnect(): " 2223 "could not allocate Tx command list\n"); 2224 return (DDI_FAILURE); 2225 } 2226 2227 err = uath_init_cmd_list(sc); 2228 if (err != UATH_SUCCESS) { 2229 UATH_DEBUG(UATH_DBG_ERR, "uath: uath_reconnect(): " 2230 "could not init RX command list\n"); 2231 return (DDI_FAILURE); 2232 } 2233 2234 /* 2235 * We're now ready to send+receive firmware commands. 2236 */ 2237 err = uath_host_available(sc); 2238 if (err != UATH_SUCCESS) { 2239 UATH_DEBUG(UATH_DBG_ERR, "uath: uath_reconnect(): " 2240 "could not initialize adapter\n"); 2241 return (DDI_FAILURE); 2242 } 2243 2244 err = uath_get_devcap(sc); 2245 if (err != UATH_SUCCESS) { 2246 UATH_DEBUG(UATH_DBG_ERR, "uath: uath_reconnect(): " 2247 "could not get device capabilities\n"); 2248 return (DDI_FAILURE); 2249 } 2250 2251 err = uath_get_devstatus(sc, ic->ic_macaddr); 2252 if (err != UATH_SUCCESS) { 2253 UATH_DEBUG(UATH_DBG_ERR, "uath: uath_reconnect(): " 2254 "could not get dev status\n"); 2255 return (DDI_FAILURE); 2256 } 2257 2258 err = usb_check_same_device(sc->sc_dev, NULL, USB_LOG_L2, -1, 2259 USB_CHK_BASIC, NULL); 2260 if (err != USB_SUCCESS) { 2261 UATH_DEBUG(UATH_DBG_ERR, "uath: uath_reconnect(): " 2262 "different device connected %x\n", err); 2263 return (DDI_FAILURE); 2264 } 2265 2266 err = uath_init(sc); 2267 if (err != UATH_SUCCESS) { 2268 UATH_DEBUG(UATH_DBG_ERR, "uath: uath_reconnect(): " 2269 "device re-connect failed\n"); 2270 return (DDI_FAILURE); 2271 } 2272 2273 UATH_LOCK(sc); 2274 sc->sc_flags &= ~UATH_FLAG_RECONNECT; 2275 sc->sc_flags &= ~UATH_FLAG_DISCONNECT; 2276 sc->sc_flags |= UATH_FLAG_RUNNING; 2277 UATH_UNLOCK(sc); 2278 } 2279 2280 return (DDI_SUCCESS); 2281 } 2282 2283 static int 2284 uath_disconnect(dev_info_t *devinfo) 2285 { 2286 struct uath_softc *sc; 2287 struct ieee80211com *ic; 2288 2289 /* 2290 * We can't call uath_stop() here, since the hardware is removed, 2291 * we can't access the register anymore. 2292 */ 2293 sc = ddi_get_soft_state(uath_soft_state_p, ddi_get_instance(devinfo)); 2294 ASSERT(sc != NULL); 2295 2296 if (sc->sc_flags & UATH_FLAG_RECONNECT) { 2297 UATH_DEBUG(UATH_DBG_MSG, "uath: uath_disconnect(): " 2298 "stage 0 in re-connect\n"); 2299 uath_close_pipes(sc); 2300 return (DDI_SUCCESS); 2301 } 2302 2303 UATH_LOCK(sc); 2304 sc->sc_flags |= UATH_FLAG_DISCONNECT; 2305 UATH_UNLOCK(sc); 2306 2307 ic = (struct ieee80211com *)&sc->sc_ic; 2308 ieee80211_new_state(ic, IEEE80211_S_INIT, -1); 2309 2310 UATH_LOCK(sc); 2311 sc->sc_flags &= ~UATH_FLAG_RUNNING; /* STOP */ 2312 UATH_UNLOCK(sc); 2313 2314 /* abort and free xfers */ 2315 uath_free_cmd_list(sc->sc_cmd, UATH_CMD_LIST_COUNT); 2316 2317 /* close Tx/Rx pipes */ 2318 uath_close_pipes(sc); 2319 2320 UATH_DEBUG(UATH_DBG_MSG, "uath: uath_disconnect(): " 2321 "offline success\n"); 2322 2323 return (DDI_SUCCESS); 2324 } 2325 2326 static int 2327 uath_dataflush(struct uath_softc *sc) 2328 { 2329 struct uath_chunk *chunk; 2330 struct uath_tx_desc *desc; 2331 uint8_t *buf; 2332 int err; 2333 2334 buf = kmem_alloc(UATH_MAX_TXBUFSZ, KM_NOSLEEP); 2335 if (buf == NULL) { 2336 UATH_DEBUG(UATH_DBG_ERR, "uath: uath_dataflush(): " 2337 "no bufs\n"); 2338 return (ENOBUFS); 2339 } 2340 2341 chunk = (struct uath_chunk *)buf; 2342 desc = (struct uath_tx_desc *)(chunk + 1); 2343 2344 /* one chunk only */ 2345 chunk->seqnum = 0; 2346 chunk->flags = UATH_CFLAGS_FINAL; 2347 chunk->length = BE_16(sizeof (struct uath_tx_desc)); 2348 2349 bzero(desc, sizeof (struct uath_tx_desc)); 2350 desc->msglen = BE_32(sizeof (struct uath_tx_desc)); 2351 desc->msgid = sc->sc_msgid; /* don't care about endianness */ 2352 desc->type = BE_32(WDCMSG_FLUSH); 2353 desc->txqid = BE_32(0); 2354 desc->connid = BE_32(0); 2355 desc->flags = BE_32(0); 2356 2357 UATH_DEBUG(UATH_DBG_MSG, "uath: uath_dataflush(): " 2358 "send flush ix %d\n", desc->msgid); 2359 2360 err = uath_fw_send(sc, sc->tx_data_pipe, buf, 2361 sizeof (struct uath_chunk) + sizeof (struct uath_tx_desc)); 2362 if (err != UATH_SUCCESS) { 2363 UATH_DEBUG(UATH_DBG_ERR, "uath: uath_dataflush(): " 2364 "data flush error"); 2365 return (UATH_FAILURE); 2366 } 2367 2368 kmem_free(buf, UATH_MAX_TXBUFSZ); 2369 sc->sc_msgid = (sc->sc_msgid + 1) % UATH_TX_DATA_LIST_COUNT; 2370 2371 return (UATH_SUCCESS); 2372 } 2373 2374 static int 2375 uath_cmdflush(struct uath_softc *sc) 2376 { 2377 return (uath_cmd_write(sc, WDCMSG_FLUSH, NULL, 0, 0)); 2378 } 2379 2380 static int 2381 uath_flush(struct uath_softc *sc) 2382 { 2383 int err; 2384 2385 err = uath_dataflush(sc); 2386 if (err != UATH_SUCCESS) 2387 goto failed; 2388 2389 err = uath_cmdflush(sc); 2390 if (err != UATH_SUCCESS) 2391 goto failed; 2392 2393 return (UATH_SUCCESS); 2394 failed: 2395 return (err); 2396 } 2397 2398 static int 2399 uath_set_ledstate(struct uath_softc *sc, int connected) 2400 { 2401 int err; 2402 2403 UATH_DEBUG(UATH_DBG_MSG, "uath: uath_set_ledstate(): " 2404 "set led state %sconnected\n", connected ? "" : "!"); 2405 2406 connected = BE_32(connected); 2407 err = uath_cmd_write(sc, WDCMSG_SET_LED_STATE, 2408 &connected, sizeof (connected), 0); 2409 return (err); 2410 } 2411 2412 static int 2413 uath_config_multi(struct uath_softc *sc, uint32_t reg, const void *data, 2414 int len) 2415 { 2416 struct uath_write_mac write; 2417 int err; 2418 2419 write.reg = BE_32(reg); 2420 write.len = BE_32(len); 2421 bcopy(data, write.data, len); 2422 2423 /* properly handle the case where len is zero (reset) */ 2424 err = uath_cmd_write(sc, WDCMSG_TARGET_SET_CONFIG, &write, 2425 (len == 0) ? sizeof (uint32_t) : 2 * sizeof (uint32_t) + len, 0); 2426 if (err != UATH_SUCCESS) { 2427 UATH_DEBUG(UATH_DBG_MSG, "uath: uath_config_multi(): " 2428 "could not write %d bytes to register 0x%02x\n", len, reg); 2429 } 2430 return (err); 2431 } 2432 2433 static void 2434 uath_config(struct uath_softc *sc, uint32_t reg, uint32_t val) 2435 { 2436 struct uath_write_mac write; 2437 int err; 2438 2439 write.reg = BE_32(reg); 2440 write.len = BE_32(0); /* 0 = single write */ 2441 *(uint32_t *)write.data = BE_32(val); 2442 2443 err = uath_cmd_write(sc, WDCMSG_TARGET_SET_CONFIG, &write, 2444 3 * sizeof (uint32_t), 0); 2445 if (err != UATH_SUCCESS) { 2446 UATH_DEBUG(UATH_DBG_MSG, "uath: uath_config(): " 2447 "could not write register 0x%02x\n", 2448 reg); 2449 } 2450 } 2451 2452 static int 2453 uath_switch_channel(struct uath_softc *sc, struct ieee80211_channel *c) 2454 { 2455 int err; 2456 2457 /* set radio frequency */ 2458 err = uath_set_chan(sc, c); 2459 if (err) { 2460 UATH_DEBUG(UATH_DBG_ERR, "uath: uath_switch_channel(): " 2461 "could not set channel\n"); 2462 goto failed; 2463 } 2464 2465 /* reset Tx rings */ 2466 err = uath_reset_tx_queues(sc); 2467 if (err) { 2468 UATH_DEBUG(UATH_DBG_ERR, "uath: uath_switch_channel(): " 2469 "could not reset Tx queues\n"); 2470 goto failed; 2471 } 2472 2473 /* set Tx rings WME properties */ 2474 err = uath_wme_init(sc); 2475 if (err) { 2476 UATH_DEBUG(UATH_DBG_ERR, "uath: uath_switch_channel(): " 2477 "could not init Tx queues\n"); 2478 goto failed; 2479 } 2480 2481 err = uath_set_ledstate(sc, 0); 2482 if (err) { 2483 UATH_DEBUG(UATH_DBG_ERR, "uath: uath_switch_channel(): " 2484 "could not set led state\n"); 2485 goto failed; 2486 } 2487 2488 err = uath_flush(sc); 2489 if (err) { 2490 UATH_DEBUG(UATH_DBG_ERR, "uath: uath_switch_channel(): " 2491 "could not flush pipes\n"); 2492 goto failed; 2493 } 2494 2495 failed: 2496 return (err); 2497 } 2498 2499 static int 2500 uath_set_rxfilter(struct uath_softc *sc, uint32_t bits, uint32_t op) 2501 { 2502 struct uath_cmd_rx_filter rxfilter; 2503 2504 rxfilter.bits = BE_32(bits); 2505 rxfilter.op = BE_32(op); 2506 2507 UATH_DEBUG(UATH_DBG_MSG, "uath: uath_set_rxfilter(): " 2508 "setting Rx filter=0x%x flags=0x%x\n", bits, op); 2509 2510 return ((uath_cmd_write(sc, WDCMSG_RX_FILTER, &rxfilter, 2511 sizeof (rxfilter), 0))); 2512 } 2513 2514 static int 2515 uath_set_chan(struct uath_softc *sc, struct ieee80211_channel *c) 2516 { 2517 struct ieee80211com *ic = &sc->sc_ic; 2518 struct uath_cmd_reset reset; 2519 2520 bzero(&reset, sizeof (reset)); 2521 if (IEEE80211_IS_CHAN_2GHZ(c)) 2522 reset.flags |= BE_32(UATH_CHAN_2GHZ); 2523 if (IEEE80211_IS_CHAN_5GHZ(c)) 2524 reset.flags |= BE_32(UATH_CHAN_5GHZ); 2525 /* NB: 11g =>'s 11b so don't specify both OFDM and CCK */ 2526 if (UATH_IS_CHAN_OFDM(c)) 2527 reset.flags |= BE_32(UATH_CHAN_OFDM); 2528 else if (UATH_IS_CHAN_CCK(c)) 2529 reset.flags |= BE_32(UATH_CHAN_CCK); 2530 /* turbo can be used in either 2GHz or 5GHz */ 2531 if (c->ich_flags & IEEE80211_CHAN_TURBO) 2532 reset.flags |= BE_32(UATH_CHAN_TURBO); 2533 2534 reset.freq = BE_32(c->ich_freq); 2535 reset.maxrdpower = BE_32(50); /* XXX */ 2536 reset.channelchange = BE_32(1); 2537 reset.keeprccontent = BE_32(0); 2538 2539 UATH_DEBUG(UATH_DBG_MSG, "uath: uath_set_chan(): " 2540 "set channel %d, flags 0x%x freq %u\n", 2541 ieee80211_chan2ieee(ic, c), 2542 BE_32(reset.flags), BE_32(reset.freq)); 2543 2544 return (uath_cmd_write(sc, WDCMSG_RESET, &reset, sizeof (reset), 0)); 2545 } 2546 2547 static int 2548 uath_reset_tx_queues(struct uath_softc *sc) 2549 { 2550 int ac, err; 2551 2552 for (ac = 0; ac < 4; ac++) { 2553 const uint32_t qid = BE_32(ac); 2554 err = uath_cmd_write(sc, WDCMSG_RELEASE_TX_QUEUE, &qid, 2555 sizeof (qid), 0); 2556 if (err != UATH_SUCCESS) 2557 break; 2558 } 2559 return (err); 2560 } 2561 2562 static int 2563 uath_wme_init(struct uath_softc *sc) 2564 { 2565 /* XXX get from net80211 */ 2566 static const struct uath_wme_settings uath_wme_11g[4] = { 2567 { 7, 4, 10, 0, 0 }, /* Background */ 2568 { 3, 4, 10, 0, 0 }, /* Best-Effort */ 2569 { 3, 3, 4, 26, 0 }, /* Video */ 2570 { 2, 2, 3, 47, 0 } /* Voice */ 2571 }; 2572 2573 struct uath_cmd_txq_setup qinfo; 2574 int ac, err; 2575 2576 for (ac = 0; ac < 4; ac++) { 2577 qinfo.qid = BE_32(ac); 2578 qinfo.len = BE_32(sizeof (qinfo.attr)); 2579 qinfo.attr.priority = BE_32(ac); /* XXX */ 2580 qinfo.attr.aifs = BE_32(uath_wme_11g[ac].aifsn); 2581 qinfo.attr.logcwmin = BE_32(uath_wme_11g[ac].logcwmin); 2582 qinfo.attr.logcwmax = BE_32(uath_wme_11g[ac].logcwmax); 2583 qinfo.attr.mode = BE_32(uath_wme_11g[ac].acm); 2584 qinfo.attr.qflags = BE_32(1); 2585 qinfo.attr.bursttime = 2586 BE_32(UATH_TXOP_TO_US(uath_wme_11g[ac].txop)); 2587 2588 err = uath_cmd_write(sc, WDCMSG_SETUP_TX_QUEUE, &qinfo, 2589 sizeof (qinfo), 0); 2590 if (err != UATH_SUCCESS) 2591 break; 2592 } 2593 return (err); 2594 } 2595 2596 static void 2597 uath_stop_locked(void *arg) 2598 { 2599 struct uath_softc *sc = (struct uath_softc *)arg; 2600 2601 /* flush data & control requests into the target */ 2602 (void) uath_flush(sc); 2603 2604 /* set a LED status to the disconnected. */ 2605 (void) uath_set_ledstate(sc, 0); 2606 2607 /* stop the target */ 2608 (void) uath_cmd_write(sc, WDCMSG_TARGET_STOP, NULL, 0, 0); 2609 2610 /* abort any pending transfers */ 2611 usb_pipe_reset(sc->sc_dev, sc->rx_data_pipe, USB_FLAGS_SLEEP, NULL, 0); 2612 usb_pipe_reset(sc->sc_dev, sc->tx_data_pipe, USB_FLAGS_SLEEP, NULL, 0); 2613 usb_pipe_reset(sc->sc_dev, sc->tx_cmd_pipe, USB_FLAGS_SLEEP, NULL, 0); 2614 } 2615 2616 static int 2617 uath_init_locked(void *arg) 2618 { 2619 struct uath_softc *sc = arg; 2620 struct ieee80211com *ic = &sc->sc_ic; 2621 uint32_t val; 2622 int i, err; 2623 2624 if (UATH_IS_RUNNING(sc)) 2625 uath_stop_locked(sc); 2626 2627 uath_init_data_queue(sc); 2628 2629 /* reset variables */ 2630 sc->sc_intrx_nextnum = sc->sc_msgid = 0; 2631 2632 val = BE_32(0); 2633 (void) uath_cmd_write(sc, WDCMSG_BIND, &val, sizeof (val), 0); 2634 2635 /* set MAC address */ 2636 (void) uath_config_multi(sc, CFG_MAC_ADDR, 2637 ic->ic_macaddr, IEEE80211_ADDR_LEN); 2638 2639 /* XXX honor net80211 state */ 2640 uath_config(sc, CFG_RATE_CONTROL_ENABLE, 0x00000001); 2641 uath_config(sc, CFG_DIVERSITY_CTL, 0x00000001); 2642 uath_config(sc, CFG_ABOLT, 0x0000003f); 2643 uath_config(sc, CFG_WME_ENABLED, 0x00000001); 2644 2645 uath_config(sc, CFG_SERVICE_TYPE, 1); 2646 uath_config(sc, CFG_TP_SCALE, 0x00000000); 2647 uath_config(sc, CFG_TPC_HALF_DBM5, 0x0000003c); 2648 uath_config(sc, CFG_TPC_HALF_DBM2, 0x0000003c); 2649 uath_config(sc, CFG_OVERRD_TX_POWER, 0x00000000); 2650 uath_config(sc, CFG_GMODE_PROTECTION, 0x00000000); 2651 uath_config(sc, CFG_GMODE_PROTECT_RATE_INDEX, 0x00000003); 2652 uath_config(sc, CFG_PROTECTION_TYPE, 0x00000000); 2653 uath_config(sc, CFG_MODE_CTS, 0x00000002); 2654 2655 err = uath_cmd_read(sc, WDCMSG_TARGET_START, NULL, 0, 2656 &val, sizeof (val), UATH_CMD_FLAG_MAGIC); 2657 if (err) { 2658 UATH_DEBUG(UATH_DBG_ERR, "uath: uath_init_locked(): " 2659 "could not start target\n"); 2660 goto fail; 2661 } 2662 2663 UATH_DEBUG(UATH_DBG_MSG, "uath: uath_init_locked(): " 2664 "%s returns handle: 0x%x\n", 2665 uath_codename(WDCMSG_TARGET_START), BE_32(val)); 2666 2667 /* set default channel */ 2668 err = uath_switch_channel(sc, ic->ic_curchan); 2669 if (err) { 2670 UATH_DEBUG(UATH_DBG_ERR, "uath: uath_init_locked(): " 2671 "could not switch channel, error %d\n", err); 2672 goto fail; 2673 } 2674 2675 val = BE_32(TARGET_DEVICE_AWAKE); 2676 (void) uath_cmd_write(sc, WDCMSG_SET_PWR_MODE, &val, sizeof (val), 0); 2677 /* XXX? check */ 2678 (void) uath_cmd_write(sc, WDCMSG_RESET_KEY_CACHE, NULL, 0, 0); 2679 2680 for (i = 0; i < UATH_RX_DATA_LIST_COUNT; i++) { 2681 err = uath_rx_data_xfer(sc); 2682 if (err != UATH_SUCCESS) { 2683 UATH_DEBUG(UATH_DBG_ERR, "uath: uath_init_locked(): " 2684 "could not alloc rx xfer %x\n", i); 2685 goto fail; 2686 } 2687 } 2688 2689 /* enable Rx */ 2690 (void) uath_set_rxfilter(sc, 0x0, UATH_FILTER_OP_INIT); 2691 (void) uath_set_rxfilter(sc, 2692 UATH_FILTER_RX_UCAST | UATH_FILTER_RX_MCAST | 2693 UATH_FILTER_RX_BCAST | UATH_FILTER_RX_BEACON, 2694 UATH_FILTER_OP_SET); 2695 2696 return (UATH_SUCCESS); 2697 2698 fail: 2699 uath_stop_locked(sc); 2700 return (err); 2701 } 2702 2703 static int 2704 uath_init(struct uath_softc *sc) 2705 { 2706 int err; 2707 2708 UATH_LOCK(sc); 2709 err = uath_init_locked(sc); 2710 if (err != UATH_SUCCESS) { 2711 UATH_DEBUG(UATH_DBG_ERR, "uath: uath_init(): " 2712 "failed to initialize uath hardware\n"); 2713 UATH_UNLOCK(sc); 2714 return (DDI_FAILURE); 2715 } 2716 UATH_UNLOCK(sc); 2717 return (DDI_SUCCESS); 2718 } 2719 2720 static void 2721 uath_stop(struct uath_softc *sc) 2722 { 2723 UATH_DEBUG(UATH_DBG_MSG, "uath: uath_stop(): " 2724 "uath stop now\n"); 2725 2726 UATH_LOCK(sc); 2727 uath_stop_locked(sc); 2728 UATH_UNLOCK(sc); 2729 } 2730 2731 static void 2732 uath_resume(struct uath_softc *sc) 2733 { 2734 int err; 2735 2736 UATH_DEBUG(UATH_DBG_MSG, "uath: uath_resume(): " 2737 "uath resume now\n"); 2738 2739 /* check device changes after suspend */ 2740 if (usb_check_same_device(sc->sc_dev, NULL, USB_LOG_L2, -1, 2741 USB_CHK_BASIC | USB_CHK_CFG, NULL) != USB_SUCCESS) { 2742 UATH_DEBUG(UATH_DBG_MSG, "uath: uath_resume: " 2743 "no or different device connected\n"); 2744 return; 2745 } 2746 2747 /* 2748 * initialize hardware 2749 */ 2750 err = uath_init_cmd_list(sc); 2751 if (err != UATH_SUCCESS) { 2752 UATH_DEBUG(UATH_DBG_MSG, "uath: uath_resume(): " 2753 "could not init RX command list\n"); 2754 return; 2755 } 2756 2757 err = uath_init(sc); 2758 if (err != UATH_SUCCESS) { 2759 UATH_DEBUG(UATH_DBG_MSG, "uath: uath_resume(): " 2760 "hardware init failed\n"); 2761 uath_stop(sc); 2762 return; 2763 } 2764 2765 ieee80211_new_state(&sc->sc_ic, IEEE80211_S_INIT, -1); 2766 UATH_LOCK(sc); 2767 sc->sc_flags &= ~UATH_FLAG_SUSPEND; 2768 sc->sc_flags |= UATH_FLAG_RUNNING; 2769 UATH_UNLOCK(sc); 2770 } 2771 2772 static int 2773 uath_m_start(void *arg) 2774 { 2775 struct uath_softc *sc = (struct uath_softc *)arg; 2776 struct ieee80211com *ic = &sc->sc_ic; 2777 int err; 2778 2779 /* 2780 * initialize hardware 2781 */ 2782 err = uath_init(sc); 2783 if (err != UATH_SUCCESS) { 2784 UATH_DEBUG(UATH_DBG_ERR, "uath: uath_m_start(): " 2785 "device configuration failed\n"); 2786 uath_stop(sc); 2787 return (err); 2788 } 2789 2790 ieee80211_new_state(ic, IEEE80211_S_INIT, -1); 2791 2792 UATH_LOCK(sc); 2793 sc->sc_flags |= UATH_FLAG_RUNNING; 2794 UATH_UNLOCK(sc); 2795 return (DDI_SUCCESS); 2796 } 2797 2798 static void 2799 uath_m_stop(void *arg) 2800 { 2801 struct uath_softc *sc = (struct uath_softc *)arg; 2802 struct ieee80211com *ic = &sc->sc_ic; 2803 2804 ieee80211_new_state(ic, IEEE80211_S_INIT, -1); 2805 2806 if (!UATH_IS_DISCONNECT(sc)) 2807 uath_stop(sc); 2808 2809 UATH_LOCK(sc); 2810 sc->sc_flags &= ~UATH_FLAG_RUNNING; 2811 UATH_UNLOCK(sc); 2812 } 2813 2814 static void 2815 uath_m_ioctl(void* arg, queue_t *wq, mblk_t *mp) 2816 { 2817 struct uath_softc *sc = (struct uath_softc *)arg; 2818 struct ieee80211com *ic = &sc->sc_ic; 2819 int err; 2820 2821 err = ieee80211_ioctl(ic, wq, mp); 2822 UATH_LOCK(sc); 2823 if (err == ENETRESET) { 2824 if (ic->ic_des_esslen) { 2825 if (UATH_IS_RUNNING(sc)) { 2826 UATH_UNLOCK(sc); 2827 (void) uath_init(sc); 2828 (void) ieee80211_new_state(ic, 2829 IEEE80211_S_SCAN, -1); 2830 UATH_LOCK(sc); 2831 } 2832 } 2833 } 2834 UATH_UNLOCK(sc); 2835 } 2836 2837 /*ARGSUSED*/ 2838 static int 2839 uath_m_unicst(void *arg, const uint8_t *macaddr) 2840 { 2841 return (0); 2842 } 2843 2844 /*ARGSUSED*/ 2845 static int 2846 uath_m_multicst(void *arg, boolean_t add, const uint8_t *mca) 2847 { 2848 return (0); 2849 } 2850 2851 /*ARGSUSED*/ 2852 static int 2853 uath_m_promisc(void *arg, boolean_t on) 2854 { 2855 return (0); 2856 } 2857 2858 /* 2859 * callback functions for /get/set properties 2860 */ 2861 static int 2862 uath_m_setprop(void *arg, const char *pr_name, mac_prop_id_t wldp_pr_num, 2863 uint_t wldp_length, const void *wldp_buf) 2864 { 2865 struct uath_softc *sc = (struct uath_softc *)arg; 2866 struct ieee80211com *ic = &sc->sc_ic; 2867 int err; 2868 2869 err = ieee80211_setprop(ic, pr_name, wldp_pr_num, 2870 wldp_length, wldp_buf); 2871 UATH_LOCK(sc); 2872 if (err == ENETRESET) { 2873 if (ic->ic_des_esslen && UATH_IS_RUNNING(sc)) { 2874 UATH_UNLOCK(sc); 2875 (void) uath_init(sc); 2876 (void) ieee80211_new_state(ic, IEEE80211_S_SCAN, -1); 2877 UATH_LOCK(sc); 2878 } 2879 err = 0; 2880 } 2881 UATH_UNLOCK(sc); 2882 return (err); 2883 } 2884 2885 static int 2886 uath_m_getprop(void *arg, const char *pr_name, mac_prop_id_t wldp_pr_num, 2887 uint_t wldp_length, void *wldp_buf) 2888 { 2889 struct uath_softc *sc = (struct uath_softc *)arg; 2890 int err; 2891 2892 err = ieee80211_getprop(&sc->sc_ic, pr_name, wldp_pr_num, 2893 wldp_length, wldp_buf); 2894 return (err); 2895 } 2896 2897 static void 2898 uath_m_propinfo(void *arg, const char *pr_name, mac_prop_id_t wldp_pr_num, 2899 mac_prop_info_handle_t prh) 2900 { 2901 struct uath_softc *sc = (struct uath_softc *)arg; 2902 2903 ieee80211_propinfo(&sc->sc_ic, pr_name, wldp_pr_num, prh); 2904 } 2905 2906 static int 2907 uath_m_stat(void *arg, uint_t stat, uint64_t *val) 2908 { 2909 struct uath_softc *sc = (struct uath_softc *)arg; 2910 struct ieee80211com *ic = &sc->sc_ic; 2911 struct ieee80211_node *ni = NULL; 2912 struct ieee80211_rateset *rs = NULL; 2913 2914 UATH_LOCK(sc); 2915 switch (stat) { 2916 case MAC_STAT_IFSPEED: 2917 ni = ic->ic_bss; 2918 rs = &ni->in_rates; 2919 *val = ((ic->ic_fixed_rate == IEEE80211_FIXED_RATE_NONE) ? 2920 (rs->ir_rates[ni->in_txrate] & IEEE80211_RATE_VAL) 2921 : ic->ic_fixed_rate) * 5000000ull; 2922 break; 2923 case MAC_STAT_NOXMTBUF: 2924 *val = sc->sc_tx_nobuf; 2925 break; 2926 case MAC_STAT_NORCVBUF: 2927 *val = sc->sc_rx_nobuf; 2928 break; 2929 case MAC_STAT_IERRORS: 2930 *val = sc->sc_rx_err; 2931 break; 2932 case MAC_STAT_RBYTES: 2933 *val = ic->ic_stats.is_rx_bytes; 2934 break; 2935 case MAC_STAT_IPACKETS: 2936 *val = ic->ic_stats.is_rx_frags; 2937 break; 2938 case MAC_STAT_OBYTES: 2939 *val = ic->ic_stats.is_tx_bytes; 2940 break; 2941 case MAC_STAT_OPACKETS: 2942 *val = ic->ic_stats.is_tx_frags; 2943 break; 2944 case MAC_STAT_OERRORS: 2945 case WIFI_STAT_TX_FAILED: 2946 *val = sc->sc_tx_err; 2947 break; 2948 case WIFI_STAT_TX_RETRANS: 2949 *val = sc->sc_tx_retries; 2950 break; 2951 case WIFI_STAT_FCS_ERRORS: 2952 case WIFI_STAT_WEP_ERRORS: 2953 case WIFI_STAT_TX_FRAGS: 2954 case WIFI_STAT_MCAST_TX: 2955 case WIFI_STAT_RTS_SUCCESS: 2956 case WIFI_STAT_RTS_FAILURE: 2957 case WIFI_STAT_ACK_FAILURE: 2958 case WIFI_STAT_RX_FRAGS: 2959 case WIFI_STAT_MCAST_RX: 2960 case WIFI_STAT_RX_DUPS: 2961 UATH_UNLOCK(sc); 2962 return (ieee80211_stat(ic, stat, val)); 2963 default: 2964 UATH_UNLOCK(sc); 2965 return (ENOTSUP); 2966 } 2967 UATH_UNLOCK(sc); 2968 2969 return (0); 2970 } 2971 2972 static mblk_t * 2973 uath_m_tx(void *arg, mblk_t *mp) 2974 { 2975 struct uath_softc *sc = (struct uath_softc *)arg; 2976 struct ieee80211com *ic = &sc->sc_ic; 2977 mblk_t *next; 2978 2979 /* 2980 * No data frames go out unless we're associated; this 2981 * should not happen as the 802.11 layer does not enable 2982 * the xmit queue until we enter the RUN state. 2983 */ 2984 if ((ic->ic_state != IEEE80211_S_RUN) || 2985 UATH_IS_SUSPEND(sc)) { 2986 UATH_DEBUG(UATH_DBG_MSG, "uath: uath_m_tx(): " 2987 "discard, state %u\n", ic->ic_state); 2988 freemsgchain(mp); 2989 return (NULL); 2990 } 2991 2992 while (mp != NULL) { 2993 next = mp->b_next; 2994 mp->b_next = NULL; 2995 if (uath_send(ic, mp, IEEE80211_FC0_TYPE_DATA) != DDI_SUCCESS) { 2996 mp->b_next = next; 2997 break; 2998 } 2999 mp = next; 3000 } 3001 return (mp); 3002 } 3003 3004 static int 3005 uath_attach(dev_info_t *devinfo, ddi_attach_cmd_t cmd) 3006 { 3007 struct uath_softc *sc; 3008 struct ieee80211com *ic; 3009 3010 int i, err, instance; 3011 char strbuf[32]; 3012 uint16_t vendor_id, product_id; 3013 3014 wifi_data_t wd = { 0 }; 3015 mac_register_t *macp; 3016 3017 switch (cmd) { 3018 case DDI_ATTACH: 3019 break; 3020 case DDI_RESUME: 3021 sc = ddi_get_soft_state(uath_soft_state_p, 3022 ddi_get_instance(devinfo)); 3023 ASSERT(sc != NULL); 3024 uath_resume(sc); 3025 return (DDI_SUCCESS); 3026 default: 3027 return (DDI_FAILURE); 3028 } 3029 3030 instance = ddi_get_instance(devinfo); 3031 err = ddi_soft_state_zalloc(uath_soft_state_p, instance); 3032 if (err != DDI_SUCCESS) { 3033 UATH_DEBUG(UATH_DBG_ERR, "uath: uath_attach(): " 3034 "ddi_soft_state_zalloc failed\n"); 3035 return (DDI_FAILURE); 3036 } 3037 3038 sc = ddi_get_soft_state(uath_soft_state_p, instance); 3039 ic = (ieee80211com_t *)&sc->sc_ic; 3040 sc->sc_dev = devinfo; 3041 3042 err = usb_client_attach(devinfo, USBDRV_VERSION, 0); 3043 if (err != USB_SUCCESS) { 3044 UATH_DEBUG(UATH_DBG_ERR, "uath: uath_attach(): " 3045 "usb_client_attach failed\n"); 3046 goto fail1; 3047 } 3048 3049 err = usb_get_dev_data(devinfo, &sc->sc_udev, USB_PARSE_LVL_ALL, 0); 3050 if (err != USB_SUCCESS) { 3051 sc->sc_udev = NULL; 3052 UATH_DEBUG(UATH_DBG_ERR, "uath: uath_attach(): " 3053 "usb_get_dev_data failed\n"); 3054 goto fail2; 3055 } 3056 3057 vendor_id = sc->sc_udev->dev_descr->idVendor; 3058 product_id = sc->sc_udev->dev_descr->idProduct; 3059 sc->dev_flags = uath_lookup(vendor_id, product_id); 3060 if (sc->dev_flags == UATH_FLAG_ERR) { 3061 UATH_DEBUG(UATH_DBG_ERR, "uath: uath_attach(): " 3062 "HW does not match\n"); 3063 goto fail2; 3064 } 3065 3066 UATH_DEBUG(UATH_DBG_MSG, "uath: uath_attach(): " 3067 "vendorId = %x,deviceID = %x, flags = %x\n", 3068 vendor_id, product_id, sc->dev_flags); 3069 3070 /* 3071 * We must open the pipes early because they're used to upload the 3072 * firmware (pre-firmware devices) or to send firmware commands. 3073 */ 3074 err = uath_open_pipes(sc); 3075 if (err != UATH_SUCCESS) { 3076 UATH_DEBUG(UATH_DBG_ERR, "uath: uath_attach(): " 3077 "could not open pipes\n"); 3078 goto fail3; 3079 } 3080 3081 if (sc->dev_flags & UATH_FLAG_PRE_FIRMWARE) { 3082 err = uath_loadfirmware(sc); 3083 if (err != DDI_SUCCESS) { 3084 UATH_DEBUG(UATH_DBG_ERR, "uath: uath_attach(): " 3085 "could not read firmware %s, err %d\n", 3086 "uath-ar5523", err); 3087 goto fail3; 3088 } 3089 3090 uath_close_pipes(sc); 3091 usb_client_detach(sc->sc_dev, sc->sc_udev); 3092 3093 err = usb_reset_device(devinfo, USB_RESET_LVL_REATTACH); 3094 if (err != USB_SUCCESS) { 3095 UATH_DEBUG(UATH_DBG_ERR, "uath: uath_attach(): " 3096 "could not re-attach, err %d\n", err); 3097 goto fail1; 3098 } 3099 return (DDI_SUCCESS); 3100 } 3101 3102 UATH_DEBUG(UATH_DBG_MSG, "uath: uath_attach(): " 3103 "firmware download and re-attach successfully\n"); 3104 3105 /* 3106 * Only post-firmware devices here. 3107 */ 3108 mutex_init(&sc->sc_genlock, NULL, MUTEX_DRIVER, NULL); 3109 mutex_init(&sc->sc_rxlock_cmd, NULL, MUTEX_DRIVER, NULL); 3110 mutex_init(&sc->sc_txlock_cmd, NULL, MUTEX_DRIVER, NULL); 3111 mutex_init(&sc->sc_rxlock_data, NULL, MUTEX_DRIVER, NULL); 3112 mutex_init(&sc->sc_txlock_data, NULL, MUTEX_DRIVER, NULL); 3113 3114 /* 3115 * Allocate xfers for firmware commands. 3116 */ 3117 err = uath_alloc_cmd_list(sc, sc->sc_cmd, UATH_CMD_LIST_COUNT, 3118 UATH_MAX_CMDSZ); 3119 if (err != UATH_SUCCESS) { 3120 UATH_DEBUG(UATH_DBG_ERR, "uath: uath_attach(): " 3121 "could not allocate Tx command list\n"); 3122 goto fail4; 3123 } 3124 3125 err = uath_init_cmd_list(sc); 3126 if (err != UATH_SUCCESS) { 3127 UATH_DEBUG(UATH_DBG_ERR, "uath: uath_attach(): " 3128 "could not init RX command list\n"); 3129 goto fail5; 3130 } 3131 3132 /* 3133 * We're now ready to send+receive firmware commands. 3134 */ 3135 err = uath_host_available(sc); 3136 if (err != UATH_SUCCESS) { 3137 UATH_DEBUG(UATH_DBG_ERR, "uath: uath_attach(): " 3138 "could not initialize adapter\n"); 3139 goto fail5; 3140 } 3141 3142 err = uath_get_devcap(sc); 3143 if (err != UATH_SUCCESS) { 3144 UATH_DEBUG(UATH_DBG_ERR, "uath: uath_attach(): " 3145 "could not get device capabilities\n"); 3146 goto fail5; 3147 } 3148 3149 err = uath_get_devstatus(sc, ic->ic_macaddr); 3150 if (err != UATH_SUCCESS) { 3151 UATH_DEBUG(UATH_DBG_ERR, "uath: uath_attach(): " 3152 "could not get dev status\n"); 3153 goto fail5; 3154 } 3155 3156 UATH_DEBUG(UATH_DBG_MSG, "uath: uath_attach(): " 3157 "MAC address is: %x:%x:%x:%x:%x:%x\n", 3158 ic->ic_macaddr[0], ic->ic_macaddr[1], ic->ic_macaddr[2], 3159 ic->ic_macaddr[3], ic->ic_macaddr[4], ic->ic_macaddr[5]); 3160 3161 ic->ic_phytype = IEEE80211_T_OFDM; /* not only, but not used */ 3162 ic->ic_opmode = IEEE80211_M_STA; /* default to BSS mode */ 3163 ic->ic_state = IEEE80211_S_INIT; 3164 3165 ic->ic_maxrssi = 40; 3166 3167 ic->ic_xmit = uath_send; 3168 3169 /* set device capabilities */ 3170 ic->ic_caps = 3171 IEEE80211_C_TXPMGT | /* tx power management */ 3172 IEEE80211_C_SHPREAMBLE | /* short preamble supported */ 3173 IEEE80211_C_SHSLOT; /* short slot time supported */ 3174 3175 ic->ic_caps |= IEEE80211_C_WPA; /* Support WPA/WPA2 */ 3176 3177 /* set supported .11b and .11g rates */ 3178 ic->ic_sup_rates[IEEE80211_MODE_11B] = uath_rateset_11b; 3179 ic->ic_sup_rates[IEEE80211_MODE_11G] = uath_rateset_11g; 3180 3181 /* set supported .11b and .11g channels (1 through 11) */ 3182 for (i = 1; i <= 11; i++) { 3183 ic->ic_sup_channels[i].ich_freq = 3184 ieee80211_ieee2mhz(i, IEEE80211_CHAN_2GHZ); 3185 ic->ic_sup_channels[i].ich_flags = 3186 IEEE80211_CHAN_CCK | IEEE80211_CHAN_OFDM | 3187 IEEE80211_CHAN_DYN | IEEE80211_CHAN_2GHZ; 3188 } 3189 3190 ieee80211_attach(ic); 3191 3192 /* register WPA door */ 3193 ieee80211_register_door(ic, ddi_driver_name(devinfo), 3194 ddi_get_instance(devinfo)); 3195 3196 /* override state transition machine */ 3197 sc->sc_newstate = ic->ic_newstate; 3198 ic->ic_newstate = uath_newstate; 3199 ieee80211_media_init(ic); 3200 ic->ic_def_txkey = 0; 3201 3202 sc->sc_flags = 0; 3203 3204 /* 3205 * Provide initial settings for the WiFi plugin; whenever this 3206 * information changes, we need to call mac_plugindata_update() 3207 */ 3208 wd.wd_opmode = ic->ic_opmode; 3209 wd.wd_secalloc = WIFI_SEC_NONE; 3210 IEEE80211_ADDR_COPY(wd.wd_bssid, ic->ic_bss->in_bssid); 3211 3212 if ((macp = mac_alloc(MAC_VERSION)) == NULL) { 3213 UATH_DEBUG(UATH_DBG_ERR, "uath_attach(): " 3214 "MAC version mismatch\n"); 3215 goto fail5; 3216 } 3217 3218 macp->m_type_ident = MAC_PLUGIN_IDENT_WIFI; 3219 macp->m_driver = sc; 3220 macp->m_dip = devinfo; 3221 macp->m_src_addr = ic->ic_macaddr; 3222 macp->m_callbacks = &uath_m_callbacks; 3223 macp->m_min_sdu = 0; 3224 macp->m_max_sdu = IEEE80211_MTU; 3225 macp->m_pdata = &wd; 3226 macp->m_pdata_size = sizeof (wd); 3227 3228 err = mac_register(macp, &ic->ic_mach); 3229 mac_free(macp); 3230 if (err != 0) { 3231 UATH_DEBUG(UATH_DBG_ERR, "uath_attach(): " 3232 "mac_register() error %x\n", err); 3233 goto fail5; 3234 }; 3235 3236 err = usb_register_hotplug_cbs(devinfo, 3237 uath_disconnect, uath_reconnect); 3238 if (err != USB_SUCCESS) { 3239 UATH_DEBUG(UATH_DBG_ERR, "uath: uath_attach(): " 3240 "failed to register events\n"); 3241 goto fail6; 3242 } 3243 3244 /* 3245 * Create minor node of type DDI_NT_NET_WIFI 3246 */ 3247 (void) snprintf(strbuf, sizeof (strbuf), "%s%d", 3248 "uath", instance); 3249 err = ddi_create_minor_node(devinfo, strbuf, S_IFCHR, 3250 instance + 1, DDI_NT_NET_WIFI, 0); 3251 if (err != DDI_SUCCESS) 3252 UATH_DEBUG(UATH_DBG_ERR, "uath: uath_attach(): " 3253 "ddi_create_minor_node() failed\n"); 3254 3255 /* 3256 * Notify link is down now 3257 */ 3258 mac_link_update(ic->ic_mach, LINK_STATE_DOWN); 3259 3260 UATH_DEBUG(UATH_DBG_MSG, "uath: uath_attach(): " 3261 "attach success\n"); 3262 return (DDI_SUCCESS); 3263 3264 fail6: 3265 (void) mac_unregister(ic->ic_mach); 3266 fail5: 3267 uath_free_cmd_list(sc->sc_cmd, UATH_CMD_LIST_COUNT); 3268 fail4: 3269 mutex_destroy(&sc->sc_genlock); 3270 mutex_destroy(&sc->sc_rxlock_cmd); 3271 mutex_destroy(&sc->sc_rxlock_data); 3272 mutex_destroy(&sc->sc_txlock_cmd); 3273 mutex_destroy(&sc->sc_txlock_data); 3274 fail3: 3275 uath_close_pipes(sc); 3276 fail2: 3277 usb_client_detach(sc->sc_dev, sc->sc_udev); 3278 fail1: 3279 ddi_soft_state_free(uath_soft_state_p, ddi_get_instance(devinfo)); 3280 return (DDI_FAILURE); 3281 } 3282 3283 static int 3284 uath_detach(dev_info_t *devinfo, ddi_detach_cmd_t cmd) 3285 { 3286 struct uath_softc *sc; 3287 3288 sc = ddi_get_soft_state(uath_soft_state_p, ddi_get_instance(devinfo)); 3289 ASSERT(sc != NULL); 3290 3291 switch (cmd) { 3292 case DDI_DETACH: 3293 break; 3294 case DDI_SUSPEND: 3295 if (UATH_IS_RUNNING(sc)) { 3296 ieee80211_new_state(&sc->sc_ic, IEEE80211_S_INIT, -1); 3297 uath_stop(sc); 3298 } 3299 UATH_LOCK(sc); 3300 sc->sc_flags &= ~UATH_FLAG_RUNNING; 3301 sc->sc_flags |= UATH_FLAG_SUSPEND; 3302 UATH_UNLOCK(sc); 3303 return (DDI_SUCCESS); 3304 default: 3305 return (DDI_FAILURE); 3306 } 3307 3308 if (sc->dev_flags & UATH_FLAG_PRE_FIRMWARE) { 3309 ddi_soft_state_free(uath_soft_state_p, 3310 ddi_get_instance(devinfo)); 3311 return (DDI_SUCCESS); 3312 } 3313 3314 if (!UATH_IS_DISCONNECT(sc) && UATH_IS_RUNNING(sc)) 3315 uath_stop(sc); 3316 3317 uath_free_cmd_list(sc->sc_cmd, UATH_CMD_LIST_COUNT); 3318 3319 if (mac_disable(sc->sc_ic.ic_mach) != 0) 3320 return (DDI_FAILURE); 3321 3322 /* 3323 * Unregister from the MAC layer subsystem 3324 */ 3325 if (mac_unregister(sc->sc_ic.ic_mach) != 0) 3326 return (DDI_FAILURE); 3327 3328 /* 3329 * detach ieee80211 layer 3330 */ 3331 ieee80211_detach(&sc->sc_ic); 3332 3333 /* close Tx/Rx pipes */ 3334 uath_close_pipes(sc); 3335 usb_unregister_hotplug_cbs(devinfo); 3336 3337 mutex_destroy(&sc->sc_genlock); 3338 mutex_destroy(&sc->sc_rxlock_cmd); 3339 mutex_destroy(&sc->sc_rxlock_data); 3340 mutex_destroy(&sc->sc_txlock_cmd); 3341 mutex_destroy(&sc->sc_txlock_data); 3342 3343 /* pipes will be close in uath_stop() */ 3344 usb_client_detach(devinfo, sc->sc_udev); 3345 sc->sc_udev = NULL; 3346 3347 ddi_remove_minor_node(devinfo, NULL); 3348 ddi_soft_state_free(uath_soft_state_p, ddi_get_instance(devinfo)); 3349 3350 return (DDI_SUCCESS); 3351 } 3352 3353 int 3354 _info(struct modinfo *modinfop) 3355 { 3356 return (mod_info(&modlinkage, modinfop)); 3357 } 3358 3359 int 3360 _init(void) 3361 { 3362 int status; 3363 3364 status = ddi_soft_state_init(&uath_soft_state_p, 3365 sizeof (struct uath_softc), 1); 3366 if (status != 0) 3367 return (status); 3368 3369 mac_init_ops(&uath_dev_ops, "uath"); 3370 status = mod_install(&modlinkage); 3371 if (status != 0) { 3372 mac_fini_ops(&uath_dev_ops); 3373 ddi_soft_state_fini(&uath_soft_state_p); 3374 } 3375 return (status); 3376 } 3377 3378 int 3379 _fini(void) 3380 { 3381 int status; 3382 3383 status = mod_remove(&modlinkage); 3384 if (status == 0) { 3385 mac_fini_ops(&uath_dev_ops); 3386 ddi_soft_state_fini(&uath_soft_state_p); 3387 } 3388 return (status); 3389 } 3390