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