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