1 /* $OpenBSD: if_wi_usb.c,v 1.55 2011/12/03 03:34:40 krw Exp $ */ 2 3 /* 4 * Copyright (c) 2003 Dale Rahn. All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 16 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 17 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 18 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 19 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 20 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 21 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 22 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 24 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 * 26 * Effort sponsored in part by the Defense Advanced Research Projects 27 * Agency (DARPA) and Air Force Research Laboratory, Air Force 28 * Materiel Command, USAF, under agreement number F30602-01-2-0537. 29 */ 30 #include "bpfilter.h" 31 32 #include <sys/param.h> 33 #include <sys/systm.h> 34 #include <sys/sockio.h> 35 #include <sys/mbuf.h> 36 #include <sys/malloc.h> 37 #include <sys/kernel.h> 38 #include <sys/proc.h> 39 #include <sys/socket.h> 40 #include <sys/device.h> 41 #include <sys/timeout.h> 42 #include <sys/kthread.h> 43 #include <sys/tree.h> 44 45 #include <net/if.h> 46 #include <net/if_dl.h> 47 #include <net/if_media.h> 48 #include <net/if_types.h> 49 50 #ifdef INET 51 #include <netinet/in.h> 52 #include <netinet/in_systm.h> 53 #include <netinet/in_var.h> 54 #include <netinet/ip.h> 55 #include <netinet/if_ether.h> 56 #endif 57 58 #include <dev/usb/usb.h> 59 #include <dev/usb/usbdi.h> 60 #include <dev/usb/usbdi_util.h> 61 #include <dev/usb/usbdevs.h> 62 63 #define ROUNDUP64(x) (((x)+63) & ~63) 64 65 #include <net80211/ieee80211_var.h> 66 #include <net80211/ieee80211_ioctl.h> 67 68 #if NBPFILTER > 0 69 #include <net/bpf.h> 70 #endif 71 72 #include <machine/bus.h> 73 74 #include <dev/rndvar.h> 75 76 #include <dev/ic/if_wireg.h> 77 #include <dev/ic/if_wi_ieee.h> 78 #include <dev/ic/if_wivar.h> 79 80 #include <dev/usb/if_wi_usb.h> 81 82 int wi_usb_do_transmit_sync(struct wi_usb_softc *wsc, struct wi_usb_chain *c, 83 void *ident); 84 void wi_usb_txeof(usbd_xfer_handle xfer, usbd_private_handle priv, 85 usbd_status status); 86 void wi_usb_txeof_frm(usbd_xfer_handle xfer, usbd_private_handle priv, 87 usbd_status status); 88 void wi_usb_rxeof(usbd_xfer_handle xfer, usbd_private_handle priv, 89 usbd_status status); 90 void wi_usb_intr(usbd_xfer_handle xfer, usbd_private_handle priv, 91 usbd_status status); 92 void wi_usb_stop(struct wi_usb_softc *usc); 93 int wi_usb_tx_list_init(struct wi_usb_softc *usc); 94 int wi_usb_rx_list_init(struct wi_usb_softc *usc); 95 int wi_usb_open_pipes(struct wi_usb_softc *usc); 96 void wi_usb_cmdresp(struct wi_usb_chain *c); 97 void wi_usb_rridresp(struct wi_usb_chain *c); 98 void wi_usb_wridresp(struct wi_usb_chain *c); 99 void wi_usb_infofrm(struct wi_usb_chain *c, int len); 100 int wi_send_packet(struct wi_usb_softc *sc, int id); 101 void wi_usb_rxfrm(struct wi_usb_softc *usc, wi_usb_usbin *uin, int total_len); 102 void wi_usb_txfrm(struct wi_usb_softc *usc, wi_usb_usbin *uin, int total_len); 103 void wi_usb_start_thread(void *); 104 105 int wi_usb_tx_lock_try(struct wi_usb_softc *sc); 106 void wi_usb_tx_lock(struct wi_usb_softc *usc); 107 void wi_usb_tx_unlock(struct wi_usb_softc *usc); 108 void wi_usb_ctl_lock(struct wi_usb_softc *usc); 109 void wi_usb_ctl_unlock(struct wi_usb_softc *usc); 110 111 void wi_dump_data(void *buffer, int len); 112 113 void wi_usb_thread(void *arg); 114 115 #ifdef WI_USB_DEBUG 116 #define DPRINTF(x) do { if (wi_usbdebug) printf x; } while (0) 117 #define DPRINTFN(n,x) do { if (wi_usbdebug >= (n)) printf x; } while (0) 118 int wi_usbdebug = 1; 119 #else 120 #define DPRINTF(x) 121 #define DPRINTFN(n,x) 122 #endif 123 124 struct wi_usb_thread_info { 125 int status; 126 int dying; 127 int idle; 128 }; 129 130 /* thread status flags */ 131 #define WI_START 0x01 132 #define WI_DYING 0x02 133 #define WI_INQUIRE 0x04 134 #define WI_WATCHDOG 0x08 135 136 137 struct wi_usb_softc { 138 struct wi_softc sc_wi; 139 #define wi_usb_dev sc_wi.sc_dev 140 141 struct timeout wi_usb_stat_ch; 142 143 usbd_device_handle wi_usb_udev; 144 usbd_interface_handle wi_usb_iface; 145 u_int16_t wi_usb_vendor; 146 u_int16_t wi_usb_product; 147 int wi_usb_ed[WI_USB_ENDPT_MAX]; 148 usbd_pipe_handle wi_usb_ep[WI_USB_ENDPT_MAX]; 149 150 struct wi_usb_chain wi_usb_tx_chain[WI_USB_TX_LIST_CNT]; 151 struct wi_usb_chain wi_usb_rx_chain[WI_USB_RX_LIST_CNT]; 152 153 int wi_usb_refcnt; 154 char wi_usb_dying; 155 char wi_usb_attached; 156 int wi_usb_intr_errs; 157 struct timeval wi_usb_rx_notice; 158 159 int wi_usb_pollpending; 160 161 wi_usb_usbin wi_usb_ibuf; 162 int wi_usb_tx_prod; 163 int wi_usb_tx_cons; 164 int wi_usb_tx_cnt; 165 int wi_usb_rx_prod; 166 167 struct wi_ltv_gen *ridltv; 168 int ridresperr; 169 170 int cmdresp; 171 int cmdresperr; 172 int txresp; 173 int txresperr; 174 175 /* nummem (tx/mgmt) */ 176 int wi_usb_nummem; 177 #define MAX_WI_NMEM 3 178 void *wi_usb_txmem[MAX_WI_NMEM]; 179 int wi_usb_txmemsize[MAX_WI_NMEM]; 180 void *wi_usb_rxmem; 181 int wi_usb_rxmemsize; 182 183 void *wi_info; 184 void *wi_rxframe; 185 186 /* prevent multiple outstanding USB requests */ 187 int wi_lock; 188 int wi_lockwait; 189 190 /* prevent multiple command requests */ 191 int wi_ctllock; 192 int wi_ctllockwait; 193 struct proc *wi_curproc; 194 195 /* kthread */ 196 struct wi_usb_thread_info *wi_thread_info; 197 int wi_resetonce; 198 }; 199 200 struct wi_funcs wi_func_usb = { 201 wi_cmd_usb, 202 wi_read_record_usb, 203 wi_write_record_usb, 204 wi_alloc_nicmem_usb, 205 wi_read_data_usb, 206 wi_write_data_usb, 207 wi_get_fid_usb, 208 wi_init_usb, 209 210 wi_start_usb, 211 wi_ioctl_usb, 212 wi_watchdog_usb, 213 wi_inquire_usb, 214 }; 215 216 /* 217 * Various supported device vendors/products. 218 */ 219 const struct wi_usb_type { 220 struct usb_devno wi_usb_device; 221 u_int16_t wi_usb_flags; 222 /* XXX */ 223 } wi_usb_devs[] = { 224 {{ USB_VENDOR_ACCTON, USB_PRODUCT_ACCTON_111 }, 0 }, 225 {{ USB_VENDOR_ACERW, USB_PRODUCT_ACERW_WARPLINK }, 0 }, 226 {{ USB_VENDOR_ACTIONTEC, USB_PRODUCT_ACTIONTEC_FREELAN }, 0 }, 227 {{ USB_VENDOR_ACTIONTEC, USB_PRODUCT_ACTIONTEC_PRISM_25 }, 0 }, 228 {{ USB_VENDOR_ACTIONTEC, USB_PRODUCT_ACTIONTEC_PRISM_25A }, 0 }, 229 {{ USB_VENDOR_ADAPTEC, USB_PRODUCT_ADAPTEC_AWN8020 }, 0 }, 230 {{ USB_VENDOR_AMBIT, USB_PRODUCT_AMBIT_WLAN }, 0 }, 231 {{ USB_VENDOR_ASUSTEK, USB_PRODUCT_ASUSTEK_WL140 }, 0 }, 232 {{ USB_VENDOR_AVERATEC, USB_PRODUCT_AVERATEC_USBWLAN }, 0 }, 233 {{ USB_VENDOR_COMPAQ, USB_PRODUCT_COMPAQ_W100 }, 0 }, 234 {{ USB_VENDOR_COMPAQ, USB_PRODUCT_COMPAQ_W200 }, 0 }, 235 {{ USB_VENDOR_COREGA, USB_PRODUCT_COREGA_WLANUSB }, 0 }, 236 {{ USB_VENDOR_COREGA, USB_PRODUCT_COREGA_WLUSB_11_KEY }, 0 }, 237 {{ USB_VENDOR_DELL, USB_PRODUCT_DELL_TM1180 }, 0 }, 238 {{ USB_VENDOR_DLINK, USB_PRODUCT_DLINK_DWL120F }, 0 }, 239 {{ USB_VENDOR_DLINK, USB_PRODUCT_DLINK_DWL122 }, 0 }, 240 {{ USB_VENDOR_INTEL, USB_PRODUCT_INTEL_I2011B }, 0 }, 241 {{ USB_VENDOR_INTERSIL, USB_PRODUCT_INTERSIL_PRISM_2X }, 0 }, 242 {{ USB_VENDOR_IODATA, USB_PRODUCT_IODATA_USBWNB11 }, 0 }, 243 {{ USB_VENDOR_JVC, USB_PRODUCT_JVC_MP_XP7250_WL }, 0 }, 244 {{ USB_VENDOR_LINKSYS, USB_PRODUCT_LINKSYS_WUSB11_25 }, 0 }, 245 {{ USB_VENDOR_LINKSYS, USB_PRODUCT_LINKSYS_WUSB12_11 }, 0 }, 246 {{ USB_VENDOR_LINKSYS3, USB_PRODUCT_LINKSYS3_WUSB11V30 }, 0 }, 247 {{ USB_VENDOR_MELCO, USB_PRODUCT_MELCO_KB11 }, 0 }, 248 {{ USB_VENDOR_MELCO, USB_PRODUCT_MELCO_KS11G }, 0 }, 249 {{ USB_VENDOR_MELCO, USB_PRODUCT_MELCO_S11 }, 0 }, 250 {{ USB_VENDOR_MICROSOFT, USB_PRODUCT_MICROSOFT_MN510 }, 0 }, 251 {{ USB_VENDOR_NETGEAR, USB_PRODUCT_NETGEAR_MA111NA }, 0 }, 252 {{ USB_VENDOR_PHEENET, USB_PRODUCT_PHEENET_WL503IA }, 0 }, 253 {{ USB_VENDOR_PHEENET, USB_PRODUCT_PHEENET_WM168B }, 0 }, 254 {{ USB_VENDOR_PLANEX, USB_PRODUCT_PLANEX_GW_US11H }, 0 }, 255 {{ USB_VENDOR_SIEMENS, USB_PRODUCT_SIEMENS_SPEEDSTREAM22 }, 0 }, 256 {{ USB_VENDOR_SITECOM2, USB_PRODUCT_SITECOM2_WL022 }, 0 }, 257 {{ USB_VENDOR_TEKRAM, USB_PRODUCT_TEKRAM_0193 }, 0 }, 258 {{ USB_VENDOR_TEKRAM, USB_PRODUCT_TEKRAM_ZYAIR_B200 }, 0 }, 259 {{ USB_VENDOR_USR, USB_PRODUCT_USR_USR1120 }, 0 }, 260 {{ USB_VENDOR_VIEWSONIC, USB_PRODUCT_VIEWSONIC_AIRSYNC }, 0 }, 261 {{ USB_VENDOR_ZCOM, USB_PRODUCT_ZCOM_XI725 }, 0 }, 262 {{ USB_VENDOR_ZCOM, USB_PRODUCT_ZCOM_XI735 }, 0 } 263 }; 264 #define wi_usb_lookup(v, p) ((struct wi_usb_type *)usb_lookup(wi_usb_devs, v, p)) 265 266 int wi_usb_match(struct device *, void *, void *); 267 void wi_usb_attach(struct device *, struct device *, void *); 268 int wi_usb_detach(struct device *, int); 269 int wi_usb_activate(struct device *, int); 270 271 struct cfdriver wi_usb_cd = { 272 NULL, "wi_usb", DV_IFNET 273 }; 274 275 const struct cfattach wi_usb_ca = { 276 sizeof(struct wi_usb_softc), 277 wi_usb_match, 278 wi_usb_attach, 279 wi_usb_detach, 280 wi_usb_activate, 281 }; 282 283 int 284 wi_usb_match(struct device *parent, void *match, void *aux) 285 { 286 struct usb_attach_arg *uaa = aux; 287 288 if (uaa->iface != NULL) 289 return (UMATCH_NONE); 290 291 return (wi_usb_lookup(uaa->vendor, uaa->product) != NULL ? 292 UMATCH_VENDOR_PRODUCT : UMATCH_NONE); 293 } 294 295 296 /* 297 * Attach the interface. Allocate softc structures, do ifmedia 298 * setup and ethernet/BPF attach. 299 */ 300 void 301 wi_usb_attach(struct device *parent, struct device *self, void *aux) 302 { 303 struct wi_usb_softc *sc = (struct wi_usb_softc *)self; 304 struct usb_attach_arg *uaa = aux; 305 /* int s; */ 306 usbd_device_handle dev = uaa->device; 307 usbd_interface_handle iface; 308 usbd_status err; 309 usb_interface_descriptor_t *id; 310 usb_endpoint_descriptor_t *ed; 311 int i; 312 313 DPRINTFN(5,(" : wi_usb_attach: sc=%p", sc)); 314 315 err = usbd_set_config_no(dev, WI_USB_CONFIG_NO, 1); 316 if (err) { 317 printf("%s: setting config no failed\n", sc->wi_usb_dev.dv_xname); 318 return; 319 } 320 321 /* XXX - any tasks? */ 322 323 err = usbd_device2interface_handle(dev, WI_USB_IFACE_IDX, &iface); 324 if (err) { 325 printf("%s: getting interface handle failed\n", 326 sc->wi_usb_dev.dv_xname); 327 return; 328 } 329 330 /* XXX - flags? */ 331 332 sc->wi_usb_udev = dev; 333 sc->wi_usb_iface = iface; 334 sc->wi_usb_product = uaa->product; 335 sc->wi_usb_vendor = uaa->vendor; 336 337 sc->sc_wi.wi_usb_cdata = sc; 338 sc->sc_wi.wi_flags |= WI_FLAGS_BUS_USB; 339 340 sc->wi_lock = 0; 341 sc->wi_lockwait = 0; 342 sc->wi_resetonce = 0; 343 344 id = usbd_get_interface_descriptor(iface); 345 346 /* Find endpoints. */ 347 for (i = 0; i < id->bNumEndpoints; i++) { 348 ed = usbd_interface2endpoint_descriptor(iface, i); 349 if (ed == NULL) { 350 printf("%s: couldn't get endpoint descriptor %d\n", 351 sc->wi_usb_dev.dv_xname, i); 352 return; 353 } 354 if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN && 355 UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) { 356 sc->wi_usb_ed[WI_USB_ENDPT_RX] = ed->bEndpointAddress; 357 } else if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_OUT && 358 UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) { 359 sc->wi_usb_ed[WI_USB_ENDPT_TX] = ed->bEndpointAddress; 360 } else if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN && 361 UE_GET_XFERTYPE(ed->bmAttributes) == UE_INTERRUPT) { 362 sc->wi_usb_ed[WI_USB_ENDPT_INTR] = ed->bEndpointAddress; 363 } 364 } 365 366 sc->wi_usb_nummem = 0; 367 368 /* attach wi device */ 369 370 if (wi_usb_rx_list_init(sc)) { 371 printf("%s: rx list init failed\n", 372 sc->wi_usb_dev.dv_xname); 373 return; 374 } 375 if (wi_usb_tx_list_init(sc)) { 376 printf("%s: tx list init failed\n", 377 sc->wi_usb_dev.dv_xname); 378 return; 379 } 380 381 if (wi_usb_open_pipes(sc)){ 382 printf("%s: open pipes failed\n", 383 sc->wi_usb_dev.dv_xname); 384 return; 385 } 386 387 sc->wi_usb_attached = 1; 388 389 kthread_create_deferred(wi_usb_start_thread, sc); 390 } 391 392 int 393 wi_usb_detach(struct device *self, int flags) 394 { 395 struct wi_usb_softc *sc = (struct wi_usb_softc *)self; 396 struct ifnet *ifp = WI_GET_IFP(sc); 397 struct wi_softc *wsc = &sc->sc_wi; 398 int s; 399 int err; 400 401 /* Detached before attach finished, so just bail out. */ 402 if (!sc->wi_usb_attached) 403 return (0); 404 405 if (sc->wi_thread_info != NULL) { 406 sc->wi_thread_info->dying = 1; 407 408 sc->wi_thread_info->status |= WI_DYING; 409 if (sc->wi_thread_info->idle) 410 wakeup(sc->wi_thread_info); 411 } 412 413 /* tasks? */ 414 415 s = splusb(); 416 /* detach wi */ 417 418 if (!(wsc->wi_flags & WI_FLAGS_ATTACHED)) { 419 printf("%s: already detached\n", sc->wi_usb_dev.dv_xname); 420 splx(s); 421 return (0); 422 } 423 424 wi_detach(&sc->sc_wi); 425 426 wsc->wi_flags = 0; 427 428 if (ifp->if_softc != NULL) { 429 ether_ifdetach(ifp); 430 if_detach(ifp); 431 } 432 433 sc->wi_usb_attached = 0; 434 435 if (--sc->wi_usb_refcnt >= 0) { 436 /* Wait for processes to go away. */ 437 usb_detach_wait(&sc->wi_usb_dev); 438 } 439 440 while (sc->wi_usb_nummem) { 441 sc->wi_usb_nummem--; 442 if (sc->wi_usb_txmem[sc->wi_usb_nummem] != NULL) 443 free(sc->wi_usb_txmem[sc->wi_usb_nummem], M_DEVBUF); 444 sc->wi_usb_txmem[sc->wi_usb_nummem] = NULL; 445 } 446 447 if (sc->wi_usb_ep[WI_USB_ENDPT_INTR] != NULL) { 448 err = usbd_abort_pipe(sc->wi_usb_ep[WI_USB_ENDPT_INTR]); 449 if (err) { 450 printf("%s: abort intr pipe failed: %s\n", 451 sc->wi_usb_dev.dv_xname, usbd_errstr(err)); 452 } 453 err = usbd_close_pipe(sc->wi_usb_ep[WI_USB_ENDPT_INTR]); 454 if (err) { 455 printf("%s: close intr pipe failed: %s\n", 456 sc->wi_usb_dev.dv_xname, usbd_errstr(err)); 457 } 458 sc->wi_usb_ep[WI_USB_ENDPT_INTR] = NULL; 459 } 460 if (sc->wi_usb_ep[WI_USB_ENDPT_TX] != NULL) { 461 err = usbd_abort_pipe(sc->wi_usb_ep[WI_USB_ENDPT_TX]); 462 if (err) { 463 printf("%s: abort tx pipe failed: %s\n", 464 sc->wi_usb_dev.dv_xname, usbd_errstr(err)); 465 } 466 err = usbd_close_pipe(sc->wi_usb_ep[WI_USB_ENDPT_TX]); 467 if (err) { 468 printf("%s: close tx pipe failed: %s\n", 469 sc->wi_usb_dev.dv_xname, usbd_errstr(err)); 470 } 471 sc->wi_usb_ep[WI_USB_ENDPT_TX] = NULL; 472 } 473 if (sc->wi_usb_ep[WI_USB_ENDPT_RX] != NULL) { 474 err = usbd_abort_pipe(sc->wi_usb_ep[WI_USB_ENDPT_RX]); 475 if (err) { 476 printf("%s: abort rx pipe failed: %s\n", 477 sc->wi_usb_dev.dv_xname, usbd_errstr(err)); 478 } 479 err = usbd_close_pipe(sc->wi_usb_ep[WI_USB_ENDPT_RX]); 480 if (err) { 481 printf("%s: close rx pipe failed: %s\n", 482 sc->wi_usb_dev.dv_xname, usbd_errstr(err)); 483 } 484 sc->wi_usb_ep[WI_USB_ENDPT_RX] = NULL; 485 } 486 487 splx(s); 488 489 return (0); 490 } 491 492 int 493 wi_send_packet(struct wi_usb_softc *sc, int id) 494 { 495 struct wi_usb_chain *c; 496 struct wi_frame *wibuf; 497 int total_len, rnd_len; 498 int err; 499 500 c = &sc->wi_usb_tx_chain[0]; 501 502 DPRINTFN(10,("%s: %s: id=%x\n", 503 sc->wi_usb_dev.dv_xname, __func__, id)); 504 505 /* assemble packet from write_data buffer */ 506 if (id == 0 || id == 1) { 507 /* tx_lock acquired before wi_start() */ 508 wibuf = sc->wi_usb_txmem[id]; 509 510 total_len = sizeof (struct wi_frame) + 511 letoh16(wibuf->wi_dat_len); 512 rnd_len = ROUNDUP64(total_len); 513 if ((total_len > sc->wi_usb_txmemsize[id]) || 514 (rnd_len > WI_USB_BUFSZ )){ 515 printf("invalid packet len: %x memsz %x max %x\n", 516 total_len, sc->wi_usb_txmemsize[id], WI_USB_BUFSZ); 517 518 err = EIO; 519 goto err_ret; 520 } 521 522 sc->txresp = WI_CMD_TX; 523 sc->txresperr = 0; 524 525 bcopy(wibuf, c->wi_usb_buf, total_len); 526 527 bzero(((char *)c->wi_usb_buf)+total_len, 528 rnd_len - total_len); 529 530 /* zero old packet for next TX */ 531 bzero(wibuf, total_len); 532 533 total_len = rnd_len; 534 535 DPRINTFN(5,("%s: %s: id=%x len=%x\n", 536 sc->wi_usb_dev.dv_xname, __func__, id, total_len)); 537 538 usbd_setup_xfer(c->wi_usb_xfer, sc->wi_usb_ep[WI_USB_ENDPT_TX], 539 c, c->wi_usb_buf, rnd_len, 540 USBD_FORCE_SHORT_XFER | USBD_NO_COPY, 541 WI_USB_TX_TIMEOUT, wi_usb_txeof_frm); 542 543 err = usbd_transfer(c->wi_usb_xfer); 544 if (err != USBD_IN_PROGRESS && err != USBD_NORMAL_COMPLETION) { 545 printf("%s: %s: error=%s\n", 546 sc->wi_usb_dev.dv_xname, __func__, 547 usbd_errstr(err)); 548 /* Stop the interface from process context. */ 549 wi_usb_stop(sc); 550 err = EIO; 551 } else { 552 err = 0; 553 } 554 555 DPRINTFN(5,("%s: %s: exit err=%x\n", 556 sc->wi_usb_dev.dv_xname, __func__, err)); 557 err_ret: 558 return err; 559 } 560 printf("%s:%s: invalid packet id sent %x\n", 561 sc->wi_usb_dev.dv_xname, __func__, id); 562 return 0; 563 } 564 565 int 566 wi_cmd_usb(struct wi_softc *wsc, int cmd, int val0, int val1, int val2) 567 { 568 struct wi_usb_chain *c; 569 struct wi_usb_softc *sc = wsc->wi_usb_cdata; 570 struct wi_cmdreq *pcmd; 571 int total_len, rnd_len; 572 int err; 573 574 DPRINTFN(5,("%s: %s: enter cmd=%x %x %x %x\n", 575 sc->wi_usb_dev.dv_xname, __func__, cmd, val0, val1, val2)); 576 577 if ((cmd & WI_CMD_CODE_MASK) == WI_CMD_TX) { 578 return wi_send_packet(sc, val0); 579 } 580 581 582 if ((cmd & WI_CMD_CODE_MASK) == WI_CMD_INI) { 583 /* free alloc_nicmem regions */ 584 while (sc->wi_usb_nummem) { 585 sc->wi_usb_nummem--; 586 free(sc->wi_usb_txmem[sc->wi_usb_nummem], M_DEVBUF); 587 sc->wi_usb_txmem[sc->wi_usb_nummem] = NULL; 588 } 589 590 #if 0 591 /* if this is the first time, init, otherwise do not?? */ 592 if (sc->wi_resetonce) { 593 return 0; 594 } else 595 sc->wi_resetonce = 1; 596 #endif 597 } 598 599 wi_usb_ctl_lock(sc); 600 601 wi_usb_tx_lock(sc); 602 603 c = &sc->wi_usb_tx_chain[0]; 604 pcmd = c->wi_usb_buf; 605 606 607 total_len = sizeof (struct wi_cmdreq); 608 rnd_len = ROUNDUP64(total_len); 609 if (rnd_len > WI_USB_BUFSZ) { 610 printf("read_record buf size err %x %x\n", 611 rnd_len, WI_USB_BUFSZ); 612 err = EIO; 613 goto err_ret; 614 } 615 616 sc->cmdresp = cmd; 617 sc->cmdresperr = 0; 618 619 pcmd->type = htole16(WI_USB_CMDREQ); 620 pcmd->cmd = htole16(cmd); 621 pcmd->param0 = htole16(val0); 622 pcmd->param1 = htole16(val1); 623 pcmd->param2 = htole16(val2); 624 625 bzero(((char*)pcmd)+total_len, rnd_len - total_len); 626 627 usbd_setup_xfer(c->wi_usb_xfer, sc->wi_usb_ep[WI_USB_ENDPT_TX], 628 c, c->wi_usb_buf, rnd_len, USBD_FORCE_SHORT_XFER | USBD_NO_COPY, 629 WI_USB_TX_TIMEOUT, wi_usb_txeof); 630 631 err = wi_usb_do_transmit_sync(sc, c, &sc->cmdresperr); 632 633 if (err == 0) 634 err = sc->cmdresperr; 635 636 sc->cmdresperr = 0; 637 638 err_ret: 639 wi_usb_tx_unlock(sc); 640 641 wi_usb_ctl_unlock(sc); 642 643 DPRINTFN(5,("%s: %s: exit err=%x\n", 644 sc->wi_usb_dev.dv_xname, __func__, err)); 645 return err; 646 } 647 648 649 int 650 wi_read_record_usb(struct wi_softc *wsc, struct wi_ltv_gen *ltv) 651 { 652 struct wi_usb_chain *c; 653 struct wi_usb_softc *sc = wsc->wi_usb_cdata; 654 struct wi_rridreq *prid; 655 int total_len, rnd_len; 656 int err; 657 struct wi_ltv_gen *oltv = NULL, p2ltv; 658 659 DPRINTFN(5,("%s: %s: enter rid=%x\n", 660 sc->wi_usb_dev.dv_xname, __func__, ltv->wi_type)); 661 662 /* Do we need to deal with these here, as in _io version? 663 * WI_RID_ENCRYPTION -> WI_RID_P2_ENCRYPTION 664 * WI_RID_TX_CRYPT_KEY -> WI_RID_P2_TX_CRYPT_KEY 665 */ 666 if (wsc->sc_firmware_type != WI_LUCENT) { 667 oltv = ltv; 668 switch (ltv->wi_type) { 669 case WI_RID_ENCRYPTION: 670 p2ltv.wi_type = WI_RID_P2_ENCRYPTION; 671 p2ltv.wi_len = 2; 672 ltv = &p2ltv; 673 break; 674 case WI_RID_TX_CRYPT_KEY: 675 if (ltv->wi_val > WI_NLTV_KEYS) 676 return (EINVAL); 677 p2ltv.wi_type = WI_RID_P2_TX_CRYPT_KEY; 678 p2ltv.wi_len = 2; 679 ltv = &p2ltv; 680 break; 681 } 682 } 683 684 wi_usb_tx_lock(sc); 685 686 c = &sc->wi_usb_tx_chain[0]; 687 prid = c->wi_usb_buf; 688 689 total_len = sizeof(struct wi_rridreq); 690 rnd_len = ROUNDUP64(total_len); 691 692 if (rnd_len > WI_USB_BUFSZ) { 693 printf("read_record buf size err %x %x\n", 694 rnd_len, WI_USB_BUFSZ); 695 wi_usb_tx_unlock(sc); 696 return EIO; 697 } 698 699 sc->ridltv = ltv; 700 sc->ridresperr = 0; 701 702 prid->type = htole16(WI_USB_RRIDREQ); 703 prid->frmlen = htole16(2); /* variable size? */ 704 prid->rid = htole16(ltv->wi_type); 705 706 bzero(((char*)prid)+total_len, rnd_len - total_len); 707 708 usbd_setup_xfer(c->wi_usb_xfer, sc->wi_usb_ep[WI_USB_ENDPT_TX], 709 c, c->wi_usb_buf, rnd_len, USBD_FORCE_SHORT_XFER | USBD_NO_COPY, 710 WI_USB_TX_TIMEOUT, wi_usb_txeof); 711 712 DPRINTFN(10,("%s: %s: total_len=%x, wilen %d\n", 713 sc->wi_usb_dev.dv_xname, __func__, total_len, ltv->wi_len)); 714 715 err = wi_usb_do_transmit_sync(sc, c, &sc->ridresperr); 716 717 /* Do we need to deal with these here, as in _io version? 718 * 719 * WI_RID_TX_RATE 720 * WI_RID_CUR_TX_RATE 721 * WI_RID_ENCRYPTION 722 * WI_RID_TX_CRYPT_KEY 723 * WI_RID_CNFAUTHMODE 724 */ 725 if (ltv->wi_type == WI_RID_PORTTYPE && wsc->wi_ptype == WI_PORTTYPE_IBSS 726 && ltv->wi_val == wsc->wi_ibss_port) { 727 /* 728 * Convert vendor IBSS port type to WI_PORTTYPE_IBSS. 729 * Since Lucent uses port type 1 for BSS *and* IBSS we 730 * have to rely on wi_ptype to distinguish this for us. 731 */ 732 ltv->wi_val = htole16(WI_PORTTYPE_IBSS); 733 } else if (wsc->sc_firmware_type != WI_LUCENT) { 734 int v; 735 736 switch (oltv->wi_type) { 737 case WI_RID_TX_RATE: 738 case WI_RID_CUR_TX_RATE: 739 switch (letoh16(ltv->wi_val)) { 740 case 1: v = 1; break; 741 case 2: v = 2; break; 742 case 3: v = 6; break; 743 case 4: v = 5; break; 744 case 7: v = 7; break; 745 case 8: v = 11; break; 746 case 15: v = 3; break; 747 default: v = 0x100 + letoh16(ltv->wi_val); break; 748 } 749 oltv->wi_val = htole16(v); 750 break; 751 case WI_RID_ENCRYPTION: 752 oltv->wi_len = 2; 753 if (ltv->wi_val & htole16(0x01)) 754 oltv->wi_val = htole16(1); 755 else 756 oltv->wi_val = htole16(0); 757 break; 758 case WI_RID_TX_CRYPT_KEY: 759 case WI_RID_CNFAUTHMODE: 760 oltv->wi_len = 2; 761 oltv->wi_val = ltv->wi_val; 762 break; 763 } 764 } 765 766 if (err == 0) 767 err = sc->ridresperr; 768 769 sc->ridresperr = 0; 770 771 wi_usb_tx_unlock(sc); 772 773 DPRINTFN(5,("%s: %s: exit err=%x\n", 774 sc->wi_usb_dev.dv_xname, __func__, err)); 775 return err; 776 } 777 778 int 779 wi_write_record_usb(struct wi_softc *wsc, struct wi_ltv_gen *ltv) 780 { 781 struct wi_usb_chain *c; 782 struct wi_usb_softc *sc = wsc->wi_usb_cdata; 783 struct wi_wridreq *prid; 784 int total_len, rnd_len; 785 int err; 786 struct wi_ltv_gen p2ltv; 787 u_int16_t val = 0; 788 int i; 789 790 DPRINTFN(5,("%s: %s: enter rid=%x wi_len %d copying %x\n", 791 sc->wi_usb_dev.dv_xname, __func__, ltv->wi_type, ltv->wi_len, 792 (ltv->wi_len-1)*2 )); 793 794 /* Do we need to deal with these here, as in _io version? 795 * WI_PORTTYPE_IBSS -> WI_RID_PORTTYPE 796 * RID_TX_RATE munging 797 * RID_ENCRYPTION 798 * WI_RID_TX_CRYPT_KEY 799 * WI_RID_DEFLT_CRYPT_KEYS 800 */ 801 if (ltv->wi_type == WI_RID_PORTTYPE && 802 letoh16(ltv->wi_val) == WI_PORTTYPE_IBSS) { 803 /* Convert WI_PORTTYPE_IBSS to vendor IBSS port type. */ 804 p2ltv.wi_type = WI_RID_PORTTYPE; 805 p2ltv.wi_len = 2; 806 p2ltv.wi_val = wsc->wi_ibss_port; 807 ltv = &p2ltv; 808 } else if (wsc->sc_firmware_type != WI_LUCENT) { 809 int v; 810 811 switch (ltv->wi_type) { 812 case WI_RID_TX_RATE: 813 p2ltv.wi_type = WI_RID_TX_RATE; 814 p2ltv.wi_len = 2; 815 switch (letoh16(ltv->wi_val)) { 816 case 1: v = 1; break; 817 case 2: v = 2; break; 818 case 3: v = 15; break; 819 case 5: v = 4; break; 820 case 6: v = 3; break; 821 case 7: v = 7; break; 822 case 11: v = 8; break; 823 default: return EINVAL; 824 } 825 p2ltv.wi_val = htole16(v); 826 ltv = &p2ltv; 827 break; 828 case WI_RID_ENCRYPTION: 829 p2ltv.wi_type = WI_RID_P2_ENCRYPTION; 830 p2ltv.wi_len = 2; 831 if (ltv->wi_val & htole16(0x01)) { 832 val = PRIVACY_INVOKED; 833 /* 834 * If using shared key WEP we must set the 835 * EXCLUDE_UNENCRYPTED bit. Symbol cards 836 * need this bit set even when not using 837 * shared key. We can't just test for 838 * IEEE80211_AUTH_SHARED since Symbol cards 839 * have 2 shared key modes. 840 */ 841 if (wsc->wi_authtype != IEEE80211_AUTH_OPEN || 842 wsc->sc_firmware_type == WI_SYMBOL) 843 val |= EXCLUDE_UNENCRYPTED; 844 845 switch (wsc->wi_crypto_algorithm) { 846 case WI_CRYPTO_FIRMWARE_WEP: 847 /* 848 * TX encryption is broken in 849 * Host AP mode. 850 */ 851 if (wsc->wi_ptype == WI_PORTTYPE_HOSTAP) 852 val |= HOST_ENCRYPT; 853 break; 854 case WI_CRYPTO_SOFTWARE_WEP: 855 val |= HOST_ENCRYPT|HOST_DECRYPT; 856 break; 857 } 858 p2ltv.wi_val = htole16(val); 859 } else 860 p2ltv.wi_val = htole16(HOST_ENCRYPT | HOST_DECRYPT); 861 ltv = &p2ltv; 862 break; 863 case WI_RID_TX_CRYPT_KEY: 864 if (ltv->wi_val > WI_NLTV_KEYS) 865 return (EINVAL); 866 p2ltv.wi_type = WI_RID_P2_TX_CRYPT_KEY; 867 p2ltv.wi_len = 2; 868 p2ltv.wi_val = ltv->wi_val; 869 ltv = &p2ltv; 870 break; 871 case WI_RID_DEFLT_CRYPT_KEYS: { 872 int error; 873 int keylen; 874 struct wi_ltv_str ws; 875 struct wi_ltv_keys *wk; 876 877 wk = (struct wi_ltv_keys *)ltv; 878 keylen = wk->wi_keys[wsc->wi_tx_key].wi_keylen; 879 keylen = letoh16(keylen); 880 881 for (i = 0; i < 4; i++) { 882 bzero(&ws, sizeof(ws)); 883 ws.wi_len = (keylen > 5) ? 8 : 4; 884 ws.wi_type = WI_RID_P2_CRYPT_KEY0 + i; 885 bcopy(&wk->wi_keys[i].wi_keydat, 886 ws.wi_str, keylen); 887 error = wi_write_record_usb(wsc, 888 (struct wi_ltv_gen *)&ws); 889 if (error) 890 return (error); 891 } 892 } 893 return (0); 894 } 895 } 896 897 wi_usb_tx_lock(sc); 898 899 c = &sc->wi_usb_tx_chain[0]; 900 901 prid = c->wi_usb_buf; 902 903 total_len = sizeof(prid->type) + sizeof(prid->frmlen) + 904 sizeof(prid->rid) + (ltv->wi_len-1)*2; 905 rnd_len = ROUNDUP64(total_len); 906 if (rnd_len > WI_USB_BUFSZ) { 907 printf("write_record buf size err %x %x\n", 908 rnd_len, WI_USB_BUFSZ); 909 wi_usb_tx_unlock(sc); 910 return EIO; 911 } 912 913 prid->type = htole16(WI_USB_WRIDREQ); 914 prid->frmlen = htole16(ltv->wi_len); 915 prid->rid = htole16(ltv->wi_type); 916 if (ltv->wi_len > 1) 917 bcopy(<v->wi_val, &prid->data[0], (ltv->wi_len-1)*2); 918 919 bzero(((char*)prid)+total_len, rnd_len - total_len); 920 921 usbd_setup_xfer(c->wi_usb_xfer, sc->wi_usb_ep[WI_USB_ENDPT_TX], 922 c, c->wi_usb_buf, rnd_len, USBD_FORCE_SHORT_XFER | USBD_NO_COPY, 923 WI_USB_TX_TIMEOUT, wi_usb_txeof); 924 925 err = wi_usb_do_transmit_sync(sc, c, &sc->ridresperr); 926 927 if (err == 0) 928 err = sc->ridresperr; 929 930 sc->ridresperr = 0; 931 932 wi_usb_tx_unlock(sc); 933 934 DPRINTFN(5,("%s: %s: exit err=%x\n", 935 sc->wi_usb_dev.dv_xname, __func__, err)); 936 return err; 937 } 938 939 /* 940 * This is an ugly compat portion to emulate the I/O which writes 941 * a packet or management information 942 * The data is copied into local memory for the requested 943 * 'id' then on the wi_cmd WI_CMD_TX, the id argument 944 * will identify which buffer to use 945 */ 946 int 947 wi_alloc_nicmem_usb(struct wi_softc *wsc, int len, int *id) 948 { 949 int nmem; 950 struct wi_usb_softc *sc = wsc->wi_usb_cdata; 951 952 DPRINTFN(10,("%s: %s: enter len=%x\n", 953 sc->wi_usb_dev.dv_xname, __func__, len)); 954 955 /* 956 * NOTE THIS IS A USB DEVICE WHICH WILL LIKELY HAVE MANY 957 * CONNECTS/DISCONNECTS, FREE THIS MEMORY XXX XXX XXX !!! !!! 958 */ 959 nmem = sc->wi_usb_nummem++; 960 961 if (nmem >= MAX_WI_NMEM) { 962 sc->wi_usb_nummem--; 963 return ENOMEM; 964 } 965 966 sc->wi_usb_txmem[nmem] = malloc(len, M_DEVBUF, M_WAITOK | M_CANFAIL); 967 if (sc->wi_usb_txmem[nmem] == NULL) { 968 sc->wi_usb_nummem--; 969 return ENOMEM; 970 } 971 sc->wi_usb_txmemsize[nmem] = len; 972 973 *id = nmem; 974 return 0; 975 } 976 977 /* 978 * this is crazy, we skip the first 16 bits of the buf so that it 979 * can be used as the 'type' of the usb transfer. 980 */ 981 982 983 int 984 wi_write_data_usb(struct wi_softc *wsc, int id, int off, caddr_t buf, int len) 985 { 986 u_int8_t *ptr; 987 struct wi_usb_softc *sc = wsc->wi_usb_cdata; 988 989 DPRINTFN(10,("%s: %s: id %x off %x len %d\n", 990 sc->wi_usb_dev.dv_xname, __func__, id, off, len)); 991 992 if (id < 0 && id >= sc->wi_usb_nummem) 993 return EIO; 994 995 ptr = (u_int8_t *)(sc->wi_usb_txmem[id]) + off; 996 997 if (len + off > sc->wi_usb_txmemsize[id]) 998 return EIO; 999 DPRINTFN(10,("%s: %s: completed \n", 1000 sc->wi_usb_dev.dv_xname, __func__)); 1001 1002 bcopy(buf, ptr, len); 1003 return 0; 1004 } 1005 1006 /* 1007 * On the prism I/O, this read_data points to the hardware buffer 1008 * which contains the 1009 */ 1010 int 1011 wi_read_data_usb(struct wi_softc *wsc, int id, int off, caddr_t buf, int len) 1012 { 1013 u_int8_t *ptr; 1014 struct wi_usb_softc *sc = wsc->wi_usb_cdata; 1015 1016 DPRINTFN(10,("%s: %s: id %x off %x len %d\n", 1017 sc->wi_usb_dev.dv_xname, __func__, id, off, len)); 1018 1019 if (id == 0x1001 && sc->wi_info != NULL) 1020 ptr = (u_int8_t *)sc->wi_info + off; 1021 else if (id == 0x1000 && sc->wi_rxframe != NULL) 1022 ptr = (u_int8_t *)sc->wi_rxframe + off; 1023 else if (id >= 0 && id < sc->wi_usb_nummem) { 1024 1025 if (sc->wi_usb_txmem[id] == NULL) 1026 return EIO; 1027 if (len + off > sc->wi_usb_txmemsize[id]) 1028 return EIO; 1029 1030 ptr = (u_int8_t *)(sc->wi_usb_txmem[id]) + off; 1031 } else 1032 return EIO; 1033 1034 if (id < sc->wi_usb_nummem) { 1035 ptr = (u_int8_t *)(sc->wi_usb_txmem[id]) + off; 1036 1037 if (len + off > sc->wi_usb_txmemsize[id]) 1038 return EIO; 1039 } 1040 1041 bcopy(ptr, buf, len); 1042 return 0; 1043 } 1044 1045 void 1046 wi_usb_stop(struct wi_usb_softc *sc) 1047 { 1048 DPRINTFN(1,("%s: %s: enter\n", sc->wi_usb_dev.dv_xname,__func__)); 1049 /* XXX */ 1050 1051 /* Stop transfers */ 1052 } 1053 1054 int 1055 wi_usb_do_transmit_sync(struct wi_usb_softc *sc, struct wi_usb_chain *c, 1056 void *ident) 1057 { 1058 usbd_status err; 1059 1060 DPRINTFN(10,("%s: %s:\n", 1061 sc->wi_usb_dev.dv_xname, __func__)); 1062 1063 sc->wi_usb_refcnt++; 1064 err = usbd_transfer(c->wi_usb_xfer); 1065 if (err != USBD_IN_PROGRESS && err != USBD_NORMAL_COMPLETION) { 1066 printf("%s: %s error=%s\n", 1067 sc->wi_usb_dev.dv_xname, __func__, 1068 usbd_errstr(err)); 1069 /* Stop the interface from process context. */ 1070 wi_usb_stop(sc); 1071 err = EIO; 1072 goto done; 1073 } 1074 err = tsleep(ident, PRIBIO, "wiTXsync", hz*1); 1075 if (err) { 1076 DPRINTFN(1,("%s: %s: err %x\n", 1077 sc->wi_usb_dev.dv_xname, __func__, err)); 1078 err = ETIMEDOUT; 1079 } 1080 done: 1081 if (--sc->wi_usb_refcnt < 0) 1082 usb_detach_wakeup(&sc->wi_usb_dev); 1083 return err; 1084 } 1085 1086 1087 /* 1088 * A command/rrid/wrid was sent to the chip. It's safe for us to clean up 1089 * the list buffers. 1090 */ 1091 1092 void 1093 wi_usb_txeof(usbd_xfer_handle xfer, usbd_private_handle priv, 1094 usbd_status status) 1095 { 1096 struct wi_usb_chain *c = priv; 1097 struct wi_usb_softc *sc = c->wi_usb_sc; 1098 1099 int s; 1100 1101 if (sc->wi_usb_dying) 1102 return; 1103 1104 s = splnet(); 1105 1106 DPRINTFN(10,("%s: %s: enter status=%d\n", sc->wi_usb_dev.dv_xname, 1107 __func__, status)); 1108 1109 if (status != USBD_NORMAL_COMPLETION) { 1110 if (status == USBD_NOT_STARTED || status == USBD_CANCELLED) { 1111 splx(s); 1112 return; 1113 } 1114 printf("%s: usb error on tx: %s\n", sc->wi_usb_dev.dv_xname, 1115 usbd_errstr(status)); 1116 if (status == USBD_STALLED) { 1117 sc->wi_usb_refcnt++; 1118 usbd_clear_endpoint_stall_async( 1119 sc->wi_usb_ep[WI_USB_ENDPT_TX]); 1120 if (--sc->wi_usb_refcnt < 0) 1121 usb_detach_wakeup(&sc->wi_usb_dev); 1122 } 1123 splx(s); 1124 return; 1125 } 1126 1127 splx(s); 1128 } 1129 1130 /* 1131 * A packet was sent to the chip. It's safe for us to clean up 1132 * the list buffers. 1133 */ 1134 1135 void 1136 wi_usb_txeof_frm(usbd_xfer_handle xfer, usbd_private_handle priv, 1137 usbd_status status) 1138 { 1139 struct wi_usb_chain *c = priv; 1140 struct wi_usb_softc *sc = c->wi_usb_sc; 1141 struct wi_softc *wsc = &sc->sc_wi; 1142 struct ifnet *ifp = &wsc->sc_ic.ic_if; 1143 1144 int s; 1145 int err = 0; 1146 1147 if (sc->wi_usb_dying) 1148 return; 1149 1150 s = splnet(); 1151 1152 DPRINTFN(10,("%s: %s: enter status=%d\n", sc->wi_usb_dev.dv_xname, 1153 __func__, status)); 1154 1155 if (status != USBD_NORMAL_COMPLETION) { 1156 if (status == USBD_NOT_STARTED || status == USBD_CANCELLED) { 1157 splx(s); 1158 return; 1159 } 1160 printf("%s: usb error on tx: %s\n", sc->wi_usb_dev.dv_xname, 1161 usbd_errstr(status)); 1162 if (status == USBD_STALLED) { 1163 sc->wi_usb_refcnt++; 1164 usbd_clear_endpoint_stall_async( 1165 sc->wi_usb_ep[WI_USB_ENDPT_TX]); 1166 if (--sc->wi_usb_refcnt < 0) 1167 usb_detach_wakeup(&sc->wi_usb_dev); 1168 } 1169 splx(s); 1170 return; 1171 } 1172 1173 if (status) 1174 err = WI_EV_TX_EXC; 1175 1176 wi_txeof(wsc, err); 1177 1178 wi_usb_tx_unlock(sc); 1179 1180 if (!IFQ_IS_EMPTY(&ifp->if_snd)) 1181 wi_start_usb(ifp); 1182 1183 splx(s); 1184 } 1185 1186 int 1187 wi_usb_rx_list_init(struct wi_usb_softc *sc) 1188 { 1189 struct wi_usb_chain *c; 1190 int i; 1191 1192 DPRINTFN(10,("%s: %s: enter\n", sc->wi_usb_dev.dv_xname, __func__)); 1193 1194 for (i = 0; i < WI_USB_RX_LIST_CNT; i++) { 1195 c = &sc->wi_usb_rx_chain[i]; 1196 c->wi_usb_sc = sc; 1197 c->wi_usb_idx = i; 1198 if (c->wi_usb_xfer != NULL) { 1199 printf("UGH RX\n"); 1200 } 1201 if (c->wi_usb_xfer == NULL) { 1202 c->wi_usb_xfer = usbd_alloc_xfer(sc->wi_usb_udev); 1203 if (c->wi_usb_xfer == NULL) 1204 return (ENOBUFS); 1205 c->wi_usb_buf = usbd_alloc_buffer(c->wi_usb_xfer, 1206 WI_USB_BUFSZ); 1207 if (c->wi_usb_buf == NULL) 1208 return (ENOBUFS); /* XXX free xfer */ 1209 } 1210 } 1211 1212 return (0); 1213 } 1214 1215 int 1216 wi_usb_tx_list_init(struct wi_usb_softc *sc) 1217 { 1218 struct wi_usb_chain *c; 1219 int i; 1220 1221 DPRINTFN(10,("%s: %s: enter\n", sc->wi_usb_dev.dv_xname, __func__)); 1222 1223 for (i = 0; i < WI_USB_TX_LIST_CNT; i++) { 1224 c = &sc->wi_usb_tx_chain[i]; 1225 c->wi_usb_sc = sc; 1226 c->wi_usb_idx = i; 1227 c->wi_usb_mbuf = NULL; 1228 if (c->wi_usb_xfer != NULL) { 1229 printf("UGH TX\n"); 1230 } 1231 if (c->wi_usb_xfer == NULL) { 1232 c->wi_usb_xfer = usbd_alloc_xfer(sc->wi_usb_udev); 1233 if (c->wi_usb_xfer == NULL) 1234 return (ENOBUFS); 1235 c->wi_usb_buf = usbd_alloc_buffer(c->wi_usb_xfer, 1236 WI_USB_BUFSZ); 1237 if (c->wi_usb_buf == NULL) 1238 return (ENOBUFS); 1239 } 1240 } 1241 1242 return (0); 1243 } 1244 1245 int 1246 wi_usb_open_pipes(struct wi_usb_softc *sc) 1247 { 1248 usbd_status err; 1249 int error = 0; 1250 struct wi_usb_chain *c; 1251 int i; 1252 1253 DPRINTFN(10,("%s: %s: enter\n", sc->wi_usb_dev.dv_xname,__func__)); 1254 1255 sc->wi_usb_refcnt++; 1256 1257 /* Open RX and TX pipes. */ 1258 err = usbd_open_pipe(sc->wi_usb_iface, sc->wi_usb_ed[WI_USB_ENDPT_RX], 1259 USBD_EXCLUSIVE_USE, &sc->wi_usb_ep[WI_USB_ENDPT_RX]); 1260 if (err) { 1261 printf("%s: open rx pipe failed: %s\n", 1262 sc->wi_usb_dev.dv_xname, usbd_errstr(err)); 1263 error = EIO; 1264 goto done; 1265 } 1266 1267 err = usbd_open_pipe(sc->wi_usb_iface, sc->wi_usb_ed[WI_USB_ENDPT_TX], 1268 USBD_EXCLUSIVE_USE, &sc->wi_usb_ep[WI_USB_ENDPT_TX]); 1269 if (err) { 1270 printf("%s: open tx pipe failed: %s\n", 1271 sc->wi_usb_dev.dv_xname, usbd_errstr(err)); 1272 error = EIO; 1273 goto done; 1274 } 1275 1276 /* is this used? */ 1277 err = usbd_open_pipe_intr(sc->wi_usb_iface, 1278 sc->wi_usb_ed[WI_USB_ENDPT_INTR], USBD_EXCLUSIVE_USE, 1279 &sc->wi_usb_ep[WI_USB_ENDPT_INTR], sc, &sc->wi_usb_ibuf, 1280 WI_USB_INTR_PKTLEN, wi_usb_intr, WI_USB_INTR_INTERVAL); 1281 if (err) { 1282 printf("%s: open intr pipe failed: %s\n", 1283 sc->wi_usb_dev.dv_xname, usbd_errstr(err)); 1284 error = EIO; 1285 goto done; 1286 } 1287 1288 /* Start up the receive pipe. */ 1289 for (i = 0; i < WI_USB_RX_LIST_CNT; i++) { 1290 c = &sc->wi_usb_rx_chain[i]; 1291 usbd_setup_xfer(c->wi_usb_xfer, sc->wi_usb_ep[WI_USB_ENDPT_RX], 1292 c, c->wi_usb_buf, WI_USB_BUFSZ, 1293 USBD_SHORT_XFER_OK | USBD_NO_COPY, USBD_NO_TIMEOUT, 1294 wi_usb_rxeof); 1295 DPRINTFN(10,("%s: %s: start read\n", sc->wi_usb_dev.dv_xname, 1296 __func__)); 1297 usbd_transfer(c->wi_usb_xfer); 1298 } 1299 1300 done: 1301 if (--sc->wi_usb_refcnt < 0) 1302 usb_detach_wakeup(&sc->wi_usb_dev); 1303 1304 return (error); 1305 } 1306 1307 /* 1308 * This is a bit of a kludge, however wi_rxeof and wi_update_stats 1309 * call wi_get_fid to determine where the data associated with 1310 * the transaction is located, the returned id is then used to 1311 * wi_read_data the information out. 1312 * 1313 * This code returns which 'fid' should be used. The results are only valid 1314 * during a wi_usb_rxeof because the data is received packet is 'held' 1315 * an a variable for reading by wi_read_data_usb for that period. 1316 * 1317 * for magic numbers this uses 0x1000, 0x1001 for rx/info 1318 */ 1319 1320 int 1321 wi_get_fid_usb(struct wi_softc *sc, int fid) 1322 { 1323 switch (fid) { 1324 case WI_RX_FID: 1325 return 0x1000; 1326 case WI_INFO_FID: 1327 return 0x1001; 1328 default: 1329 return 0x1111; 1330 } 1331 1332 } 1333 1334 int 1335 wi_usb_activate(struct device *self, int act) 1336 { 1337 struct wi_usb_softc *sc = (struct wi_usb_softc *)self; 1338 1339 DPRINTFN(10,("%s: %s: enter\n", sc->wi_usb_dev.dv_xname, __func__)); 1340 1341 switch (act) { 1342 case DVACT_DEACTIVATE: 1343 sc->wi_usb_dying = 1; 1344 sc->wi_thread_info->dying = 1; 1345 break; 1346 } 1347 return (0); 1348 } 1349 1350 #if 0 1351 void 1352 wi_dump_data(void *buffer, int len) 1353 { 1354 int i; 1355 for (i = 0; i < len; i++) { 1356 if (((i) % 16) == 0) 1357 printf("\n %02x:", i); 1358 printf(" %02x", 1359 ((uint8_t *)(buffer))[i]); 1360 1361 } 1362 printf("\n"); 1363 1364 } 1365 #endif 1366 1367 /* 1368 * A frame has been received. 1369 */ 1370 void 1371 wi_usb_rxeof(usbd_xfer_handle xfer, usbd_private_handle priv, usbd_status status) 1372 { 1373 struct wi_usb_chain *c = priv; 1374 struct wi_usb_softc *sc = c->wi_usb_sc; 1375 wi_usb_usbin *uin; 1376 int total_len = 0; 1377 u_int16_t rtype; 1378 1379 if (sc->wi_usb_dying) 1380 return; 1381 1382 DPRINTFN(10,("%s: %s: enter status=%d\n", sc->wi_usb_dev.dv_xname, 1383 __func__, status)); 1384 1385 1386 if (status != USBD_NORMAL_COMPLETION) { 1387 if (status == USBD_NOT_STARTED || status == USBD_IOERROR 1388 || status == USBD_CANCELLED) { 1389 printf("%s: %u usb errors on rx: %s\n", 1390 sc->wi_usb_dev.dv_xname, 1, 1391 /* sc->wi_usb_rx_errs, */ 1392 usbd_errstr(status)); 1393 return; 1394 } 1395 #if 0 1396 sc->wi_usb_rx_errs++; 1397 if (usbd_ratecheck(&sc->wi_usb_rx_notice)) { 1398 printf("%s: %u usb errors on rx: %s\n", 1399 sc->wi_usb_dev.dv_xname, sc->wi_usb_rx_errs, 1400 usbd_errstr(status)); 1401 sc->wi_usb_rx_errs = 0; 1402 } 1403 #endif 1404 if (status == USBD_STALLED) { 1405 sc->wi_usb_refcnt++; 1406 usbd_clear_endpoint_stall_async( 1407 sc->wi_usb_ep[WI_USB_ENDPT_RX]); 1408 if (--sc->wi_usb_refcnt < 0) 1409 usb_detach_wakeup(&sc->wi_usb_dev); 1410 } 1411 goto done; 1412 } 1413 1414 usbd_get_xfer_status(xfer, NULL, NULL, &total_len, NULL); 1415 1416 if (total_len < 6) /* short XXX */ 1417 goto done; 1418 1419 uin = (wi_usb_usbin *)(c->wi_usb_buf); 1420 1421 rtype = letoh16(uin->type); 1422 1423 1424 #if 0 1425 wi_dump_data(c->wi_usb_buf, total_len); 1426 #endif 1427 1428 if (WI_USB_ISRXFRM(rtype)) { 1429 wi_usb_rxfrm(sc, uin, total_len); 1430 goto done; 1431 } 1432 if (WI_USB_ISTXFRM(rtype)) { 1433 DPRINTFN(2,("%s: %s: txfrm type %x\n", 1434 sc->wi_usb_dev.dv_xname, __func__, rtype)); 1435 wi_usb_txfrm(sc, uin, total_len); 1436 goto done; 1437 } 1438 1439 switch (rtype) { 1440 case WI_USB_INFOFRM: 1441 /* info packet, INFO_FID hmm */ 1442 DPRINTFN(10,("%s: %s: infofrm type %x\n", 1443 sc->wi_usb_dev.dv_xname, __func__, rtype)); 1444 wi_usb_infofrm(c, total_len); 1445 break; 1446 case WI_USB_CMDRESP: 1447 wi_usb_cmdresp(c); 1448 break; 1449 case WI_USB_WRIDRESP: 1450 wi_usb_wridresp(c); 1451 break; 1452 case WI_USB_RRIDRESP: 1453 wi_usb_rridresp(c); 1454 break; 1455 case WI_USB_WMEMRESP: 1456 /* Not currently used */ 1457 DPRINTFN(2,("%s: %s: wmemresp type %x\n", 1458 sc->wi_usb_dev.dv_xname, __func__, rtype)); 1459 break; 1460 case WI_USB_RMEMRESP: 1461 /* Not currently used */ 1462 DPRINTFN(2,("%s: %s: rmemresp type %x\n", 1463 sc->wi_usb_dev.dv_xname, __func__, rtype)); 1464 break; 1465 case WI_USB_BUFAVAIL: 1466 printf("wi_usb: received USB_BUFAVAIL packet\n"); /* XXX */ 1467 break; 1468 case WI_USB_ERROR: 1469 printf("wi_usb: received USB_ERROR packet\n"); /* XXX */ 1470 break; 1471 #if 0 1472 default: 1473 printf("wi_usb: received Unknown packet 0x%x len %x\n", 1474 rtype, total_len); 1475 wi_dump_data(c->wi_usb_buf, total_len); 1476 #endif 1477 } 1478 1479 done: 1480 /* Setup new transfer. */ 1481 usbd_setup_xfer(c->wi_usb_xfer, sc->wi_usb_ep[WI_USB_ENDPT_RX], 1482 c, c->wi_usb_buf, WI_USB_BUFSZ, USBD_SHORT_XFER_OK | USBD_NO_COPY, 1483 USBD_NO_TIMEOUT, wi_usb_rxeof); 1484 sc->wi_usb_refcnt++; 1485 usbd_transfer(c->wi_usb_xfer); 1486 if (--sc->wi_usb_refcnt < 0) 1487 usb_detach_wakeup(&sc->wi_usb_dev); 1488 1489 DPRINTFN(10,("%s: %s: start rx\n", sc->wi_usb_dev.dv_xname, 1490 __func__)); 1491 } 1492 1493 void 1494 wi_usb_intr(usbd_xfer_handle xfer, usbd_private_handle priv, usbd_status status) 1495 { 1496 struct wi_usb_softc *sc = priv; 1497 1498 DPRINTFN(2,("%s: %s: enter\n", sc->wi_usb_dev.dv_xname, __func__)); 1499 1500 if (sc->wi_usb_dying) 1501 return; 1502 1503 if (status != USBD_NORMAL_COMPLETION) { 1504 if (status == USBD_NOT_STARTED || status == USBD_CANCELLED) 1505 return; 1506 1507 if (status == USBD_STALLED) { 1508 sc->wi_usb_refcnt++; 1509 usbd_clear_endpoint_stall_async( 1510 sc->wi_usb_ep[WI_USB_ENDPT_RX]); 1511 if (--sc->wi_usb_refcnt < 0) 1512 usb_detach_wakeup(&sc->wi_usb_dev); 1513 } 1514 return; 1515 } 1516 /* XXX oerrors or collisions? */ 1517 } 1518 void 1519 wi_usb_cmdresp(struct wi_usb_chain *c) 1520 { 1521 struct wi_cmdresp *presp = (struct wi_cmdresp *)(c->wi_usb_buf); 1522 u_int16_t status = letoh16(presp->status); 1523 struct wi_usb_softc *sc = c->wi_usb_sc; 1524 uint16_t type; 1525 uint16_t cmdresperr; 1526 1527 type = htole16(presp->type); 1528 cmdresperr = letoh16(presp->resp0); 1529 DPRINTFN(10,("%s: %s: enter type=%x, status=%x, cmdresp=%x, " 1530 "resp=%x,%x,%x\n", 1531 sc->wi_usb_dev.dv_xname, __func__, type, status, sc->cmdresp, 1532 cmdresperr, letoh16(presp->resp1), 1533 letoh16(presp->resp2))); 1534 1535 /* XXX */ 1536 if (sc->cmdresp != (status & WI_STAT_CMD_CODE)) { 1537 DPRINTFN(1,("%s: cmd ty %x st %x cmd %x failed %x\n", 1538 sc->wi_usb_dev.dv_xname, 1539 type, status, sc->cmdresp, cmdresperr)); 1540 return; 1541 } 1542 1543 sc->cmdresperr = (status & WI_STAT_CMD_RESULT) >> 8; 1544 1545 sc->cmdresp = 0; /* good value for idle == INI ?? XXX */ 1546 1547 wakeup(&sc->cmdresperr); 1548 } 1549 void 1550 wi_usb_rridresp(struct wi_usb_chain *c) 1551 { 1552 struct wi_rridresp *presp = (struct wi_rridresp *)(c->wi_usb_buf); 1553 u_int16_t frmlen = letoh16(presp->frmlen); 1554 struct wi_usb_softc *sc = c->wi_usb_sc; 1555 struct wi_ltv_gen *ltv; 1556 uint16_t rid; 1557 1558 rid = letoh16(presp->rid); 1559 ltv = sc->ridltv; 1560 1561 if (ltv == 0) { 1562 DPRINTFN(5,("%s: %s: enter ltv = 0 rid=%x len %d\n", 1563 sc->wi_usb_dev.dv_xname, __func__, rid, 1564 frmlen)); 1565 return; 1566 } 1567 1568 DPRINTFN(5,("%s: %s: enter rid=%x expecting %x len %d exptlen %d\n", 1569 sc->wi_usb_dev.dv_xname, __func__, rid, ltv->wi_type, 1570 frmlen, ltv->wi_len)); 1571 1572 rid = letoh16(presp->rid); 1573 1574 if (rid != ltv->wi_type) { 1575 sc->ridresperr = EIO; 1576 return; 1577 } 1578 1579 if (frmlen > ltv->wi_len) { 1580 sc->ridresperr = ENOSPC; 1581 sc->ridltv = 0; 1582 wakeup(&sc->ridresperr); 1583 return; 1584 } 1585 1586 ltv->wi_len = frmlen; 1587 1588 DPRINTFN(10,("%s: %s: copying %d frmlen %d\n", 1589 sc->wi_usb_dev.dv_xname, __func__, (ltv->wi_len-1)*2, 1590 frmlen)); 1591 1592 if (ltv->wi_len > 1) 1593 bcopy(&presp->data[0], <v->wi_val, 1594 (ltv->wi_len-1)*2); 1595 1596 sc->ridresperr = 0; 1597 sc->ridltv = 0; 1598 wakeup(&sc->ridresperr); 1599 1600 } 1601 1602 void 1603 wi_usb_wridresp(struct wi_usb_chain *c) 1604 { 1605 struct wi_wridresp *presp = (struct wi_wridresp *)(c->wi_usb_buf); 1606 struct wi_usb_softc *sc = c->wi_usb_sc; 1607 uint16_t status; 1608 1609 status = letoh16(presp->status); 1610 1611 DPRINTFN(10,("%s: %s: enter status=%x\n", 1612 sc->wi_usb_dev.dv_xname, __func__, status)); 1613 1614 sc->ridresperr = (status & WI_STAT_CMD_RESULT) >> 8; 1615 sc->ridltv = 0; 1616 wakeup(&sc->ridresperr); 1617 } 1618 1619 void 1620 wi_usb_infofrm(struct wi_usb_chain *c, int len) 1621 { 1622 struct wi_usb_softc *sc = c->wi_usb_sc; 1623 1624 DPRINTFN(10,("%s: %s: enter\n", 1625 sc->wi_usb_dev.dv_xname, __func__)); 1626 1627 sc->wi_info = ((char *)c->wi_usb_buf) + 2; 1628 wi_update_stats(&sc->sc_wi); 1629 sc->wi_info = NULL; 1630 } 1631 1632 void 1633 wi_usb_txfrm(struct wi_usb_softc *sc, wi_usb_usbin *uin, int total_len) 1634 { 1635 u_int16_t status; 1636 int s; 1637 struct wi_softc *wsc = &sc->sc_wi; 1638 struct ifnet *ifp = &wsc->sc_ic.ic_if; 1639 1640 s = splnet(); 1641 status = letoh16(uin->type); /* XXX -- type == status */ 1642 1643 1644 DPRINTFN(2,("%s: %s: enter status=%d\n", 1645 sc->wi_usb_dev.dv_xname, __func__, status)); 1646 1647 if (sc->txresp == WI_CMD_TX) { 1648 sc->txresperr=status; 1649 sc->txresp = 0; 1650 wakeup(&sc->txresperr); 1651 } else { 1652 if (status != 0) /* XXX */ 1653 wi_watchdog_usb(ifp); 1654 DPRINTFN(1,("%s: %s: txresp not expected status=%d \n", 1655 sc->wi_usb_dev.dv_xname, __func__, status)); 1656 } 1657 1658 splx(s); 1659 } 1660 void 1661 wi_usb_rxfrm(struct wi_usb_softc *sc, wi_usb_usbin *uin, int total_len) 1662 { 1663 int s; 1664 1665 DPRINTFN(5,("%s: %s: enter len=%d\n", 1666 sc->wi_usb_dev.dv_xname, __func__, total_len)); 1667 1668 s = splnet(); 1669 1670 sc->wi_rxframe = (void *)uin; 1671 1672 wi_rxeof(&sc->sc_wi); 1673 1674 sc->wi_rxframe = NULL; 1675 1676 splx(s); 1677 1678 } 1679 1680 1681 void 1682 wi_usb_start_thread(void *arg) 1683 { 1684 struct wi_usb_softc *sc = arg; 1685 kthread_create (wi_usb_thread, arg, NULL, sc->wi_usb_dev.dv_xname); 1686 } 1687 1688 void 1689 wi_start_usb(struct ifnet *ifp) 1690 { 1691 struct wi_softc *wsc; 1692 struct wi_usb_softc *sc; 1693 int s; 1694 1695 wsc = ifp->if_softc; 1696 sc = wsc->wi_usb_cdata; 1697 1698 s = splnet(); 1699 1700 DPRINTFN(5,("%s: %s:\n", 1701 sc->wi_usb_dev.dv_xname, __func__)); 1702 1703 if (wi_usb_tx_lock_try(sc)) { 1704 /* lock acquired do start now */ 1705 wi_func_io.f_start(ifp); 1706 } else { 1707 sc->wi_thread_info->status |= WI_START; 1708 if (sc->wi_thread_info->idle) 1709 wakeup(sc->wi_thread_info); 1710 } 1711 1712 splx(s); 1713 } 1714 1715 /* 1716 * inquire is called from interrupt context (timeout) 1717 * It is not possible to sleep in interrupt context so it is necessary 1718 * to signal the kernel thread to perform the action. 1719 */ 1720 void 1721 wi_init_usb(struct wi_softc *wsc) 1722 { 1723 DPRINTFN(5,("%s: %s:\n", WI_PRT_ARG(wsc), __func__)); 1724 1725 wi_usb_ctl_lock(wsc->wi_usb_cdata); 1726 wi_func_io.f_init(wsc); 1727 wi_usb_ctl_unlock(wsc->wi_usb_cdata); 1728 } 1729 1730 1731 /* 1732 * inquire is called from interrupt context (timeout) 1733 * It is not possible to sleep in interrupt context so it is necessary 1734 * to signal the kernel thread to perform the action. 1735 */ 1736 void 1737 wi_inquire_usb(void *xsc) 1738 { 1739 struct wi_softc *wsc = xsc; 1740 struct wi_usb_softc *sc = wsc->wi_usb_cdata; 1741 int s; 1742 1743 1744 s = splnet(); 1745 1746 DPRINTFN(2,("%s: %s:\n", 1747 sc->wi_usb_dev.dv_xname, __func__)); 1748 1749 sc->wi_thread_info->status |= WI_INQUIRE; 1750 1751 if (sc->wi_thread_info->idle) 1752 wakeup(sc->wi_thread_info); 1753 splx(s); 1754 } 1755 1756 /* 1757 * Watchdog is normally called from interrupt context (timeout) 1758 * It is not possible to sleep in interrupt context so it is necessary 1759 * to signal the kernel thread to perform the action. 1760 */ 1761 void 1762 wi_watchdog_usb(struct ifnet *ifp) 1763 { 1764 struct wi_softc *wsc; 1765 struct wi_usb_softc *sc; 1766 int s; 1767 1768 wsc = ifp->if_softc; 1769 sc = wsc->wi_usb_cdata; 1770 1771 s = splnet(); 1772 1773 DPRINTFN(5,("%s: %s: ifp %x\n", 1774 sc->wi_usb_dev.dv_xname, __func__, ifp)); 1775 1776 sc->wi_thread_info->status |= WI_WATCHDOG; 1777 1778 if (sc->wi_thread_info->idle) 1779 wakeup(sc->wi_thread_info); 1780 splx(s); 1781 } 1782 1783 /* 1784 * ioctl will always be called from a user context, 1785 * therefore it is possible to sleep in the calling context 1786 * acquire the lock and call the real ioctl fucntion directly 1787 */ 1788 int 1789 wi_ioctl_usb(struct ifnet *ifp, u_long command, caddr_t data) 1790 { 1791 struct wi_softc *wsc; 1792 int err; 1793 1794 wsc = ifp->if_softc; 1795 1796 wi_usb_ctl_lock(wsc->wi_usb_cdata); 1797 err = wi_func_io.f_ioctl(ifp, command, data); 1798 wi_usb_ctl_unlock(wsc->wi_usb_cdata); 1799 return err; 1800 } 1801 1802 void 1803 wi_usb_thread(void *arg) 1804 { 1805 struct wi_usb_softc *sc = arg; 1806 struct wi_usb_thread_info *wi_thread_info; 1807 int s; 1808 1809 wi_thread_info = malloc(sizeof(*wi_thread_info), M_DEVBUF, M_WAITOK); 1810 1811 /* 1812 * is there a remote possibility that the device could 1813 * be removed before the kernel thread starts up? 1814 */ 1815 1816 sc->wi_usb_refcnt++; 1817 1818 sc->wi_thread_info = wi_thread_info; 1819 wi_thread_info->dying = 0; 1820 wi_thread_info->status = 0; 1821 1822 wi_usb_ctl_lock(sc); 1823 1824 wi_attach(&sc->sc_wi, &wi_func_usb); 1825 1826 wi_usb_ctl_unlock(sc); 1827 1828 for(;;) { 1829 if (wi_thread_info->dying) { 1830 if (--sc->wi_usb_refcnt < 0) 1831 usb_detach_wakeup(&sc->wi_usb_dev); 1832 kthread_exit(0); 1833 } 1834 1835 DPRINTFN(5,("%s: %s: dying %x status %x\n", 1836 sc->wi_usb_dev.dv_xname, __func__, 1837 wi_thread_info->dying, wi_thread_info->status)); 1838 1839 wi_usb_ctl_lock(sc); 1840 1841 DPRINTFN(5,("%s: %s: starting %x\n", 1842 sc->wi_usb_dev.dv_xname, __func__, 1843 wi_thread_info->status)); 1844 1845 s = splusb(); 1846 if (wi_thread_info->status & WI_START) { 1847 wi_thread_info->status &= ~WI_START; 1848 wi_usb_tx_lock(sc); 1849 wi_func_io.f_start(&sc->sc_wi.sc_ic.ic_if); 1850 /* 1851 * tx_unlock is explicitly missing here 1852 * it is done in txeof_frm 1853 */ 1854 } else if (wi_thread_info->status & WI_INQUIRE) { 1855 wi_thread_info->status &= ~WI_INQUIRE; 1856 wi_func_io.f_inquire(&sc->sc_wi); 1857 } else if (wi_thread_info->status & WI_WATCHDOG) { 1858 wi_thread_info->status &= ~WI_WATCHDOG; 1859 wi_func_io.f_watchdog( &sc->sc_wi.sc_ic.ic_if); 1860 } 1861 splx(s); 1862 1863 DPRINTFN(5,("%s: %s: ending %x\n", 1864 sc->wi_usb_dev.dv_xname, __func__, 1865 wi_thread_info->status)); 1866 wi_usb_ctl_unlock(sc); 1867 1868 if (wi_thread_info->status == 0) { 1869 s = splnet(); 1870 wi_thread_info->idle = 1; 1871 tsleep(wi_thread_info, PRIBIO, "wiIDL", 0); 1872 wi_thread_info->idle = 0; 1873 splx(s); 1874 } 1875 } 1876 } 1877 1878 int 1879 wi_usb_tx_lock_try(struct wi_usb_softc *sc) 1880 { 1881 int s; 1882 1883 s = splnet(); 1884 1885 DPRINTFN(10,("%s: %s: enter\n", sc->wi_usb_dev.dv_xname, __func__)); 1886 1887 if (sc->wi_lock != 0) { 1888 splx(s); 1889 return 0; /* failed to aquire lock */ 1890 } 1891 1892 sc->wi_lock = 1; 1893 1894 splx(s); 1895 1896 return 1; 1897 } 1898 void 1899 wi_usb_tx_lock(struct wi_usb_softc *sc) 1900 { 1901 int s; 1902 1903 s = splnet(); 1904 1905 again: 1906 DPRINTFN(10,("%s: %s: enter\n", sc->wi_usb_dev.dv_xname, __func__)); 1907 1908 if (sc->wi_lock != 0) { 1909 sc->wi_lockwait++; 1910 DPRINTFN(10,("%s: %s: busy %d\n", sc->wi_usb_dev.dv_xname, 1911 __func__, sc->wi_lockwait )); 1912 tsleep(&sc->wi_lock, PRIBIO, "witxl", 0); 1913 } 1914 1915 if (sc->wi_lock != 0) 1916 goto again; 1917 sc->wi_lock = 1; 1918 1919 splx(s); 1920 1921 return; 1922 1923 } 1924 1925 void 1926 wi_usb_tx_unlock(struct wi_usb_softc *sc) 1927 { 1928 int s; 1929 s = splnet(); 1930 1931 sc->wi_lock = 0; 1932 1933 DPRINTFN(10,("%s: %s: enter\n", sc->wi_usb_dev.dv_xname, __func__)); 1934 1935 if (sc->wi_lockwait) { 1936 DPRINTFN(10,("%s: %s: waking\n", 1937 sc->wi_usb_dev.dv_xname, __func__)); 1938 sc->wi_lockwait = 0; 1939 wakeup(&sc->wi_lock); 1940 } 1941 1942 splx(s); 1943 } 1944 1945 void 1946 wi_usb_ctl_lock(struct wi_usb_softc *sc) 1947 { 1948 int s; 1949 1950 s = splnet(); 1951 1952 again: 1953 DPRINTFN(10,("%s: %s: enter\n", sc->wi_usb_dev.dv_xname, 1954 __func__)); 1955 1956 if (sc->wi_ctllock != 0) { 1957 if (curproc == sc->wi_curproc) { 1958 /* allow recursion */ 1959 sc->wi_ctllock++; 1960 splx(s); 1961 return; 1962 } 1963 sc->wi_ctllockwait++; 1964 DPRINTFN(10,("%s: %s: busy %d\n", sc->wi_usb_dev.dv_xname, 1965 __func__, sc->wi_ctllockwait )); 1966 tsleep(&sc->wi_ctllock, PRIBIO, "wiusbthr", 0); 1967 } 1968 1969 if (sc->wi_ctllock != 0) 1970 goto again; 1971 sc->wi_ctllock++; 1972 sc->wi_curproc = curproc; 1973 1974 splx(s); 1975 1976 return; 1977 1978 } 1979 1980 void 1981 wi_usb_ctl_unlock(struct wi_usb_softc *sc) 1982 { 1983 int s; 1984 1985 s = splnet(); 1986 1987 sc->wi_ctllock--; 1988 1989 DPRINTFN(10,("%s: %s: enter\n", sc->wi_usb_dev.dv_xname, __func__)); 1990 1991 if (sc->wi_ctllock == 0 && sc->wi_ctllockwait) { 1992 DPRINTFN(10,("%s: %s: waking\n", 1993 sc->wi_usb_dev.dv_xname, __func__)); 1994 sc->wi_ctllockwait = 0; 1995 sc->wi_curproc = 0; 1996 wakeup(&sc->wi_ctllock); 1997 } 1998 1999 splx(s); 2000 } 2001