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