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