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