1 /* $OpenBSD: if_wi_usb.c,v 1.45 2009/02/14 20:05:09 chl 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 521 err = EIO; 522 goto err_ret; 523 } 524 525 sc->txresp = WI_CMD_TX; 526 sc->txresperr = 0; 527 528 bcopy(wibuf, c->wi_usb_buf, total_len); 529 530 bzero(((char *)c->wi_usb_buf)+total_len, 531 rnd_len - total_len); 532 533 /* zero old packet for next TX */ 534 bzero(wibuf, total_len); 535 536 total_len = rnd_len; 537 538 DPRINTFN(5,("%s: %s: id=%x len=%x\n", 539 sc->wi_usb_dev.dv_xname, __func__, id, total_len)); 540 541 usbd_setup_xfer(c->wi_usb_xfer, sc->wi_usb_ep[WI_USB_ENDPT_TX], 542 c, c->wi_usb_buf, rnd_len, 543 USBD_FORCE_SHORT_XFER | USBD_NO_COPY, 544 WI_USB_TX_TIMEOUT, wi_usb_txeof_frm); 545 546 err = usbd_transfer(c->wi_usb_xfer); 547 if (err != USBD_IN_PROGRESS && err != USBD_NORMAL_COMPLETION) { 548 printf("%s: %s: error=%s\n", 549 sc->wi_usb_dev.dv_xname, __func__, 550 usbd_errstr(err)); 551 /* Stop the interface from process context. */ 552 wi_usb_stop(sc); 553 err = EIO; 554 } else { 555 err = 0; 556 } 557 558 DPRINTFN(5,("%s: %s: exit err=%x\n", 559 sc->wi_usb_dev.dv_xname, __func__, err)); 560 err_ret: 561 return err; 562 } 563 printf("%s:%s: invalid packet id sent %x\n", 564 sc->wi_usb_dev.dv_xname, __func__, id); 565 return 0; 566 } 567 568 int 569 wi_cmd_usb(struct wi_softc *wsc, int cmd, int val0, int val1, int val2) 570 { 571 struct wi_usb_chain *c; 572 struct wi_usb_softc *sc = wsc->wi_usb_cdata; 573 struct wi_cmdreq *pcmd; 574 int total_len, rnd_len; 575 int err; 576 577 DPRINTFN(5,("%s: %s: enter cmd=%x %x %x %x\n", 578 sc->wi_usb_dev.dv_xname, __func__, cmd, val0, val1, val2)); 579 580 if ((cmd & WI_CMD_CODE_MASK) == WI_CMD_TX) { 581 return wi_send_packet(sc, val0); 582 } 583 584 585 if ((cmd & WI_CMD_CODE_MASK) == WI_CMD_INI) { 586 /* free alloc_nicmem regions */ 587 while (sc->wi_usb_nummem) { 588 sc->wi_usb_nummem--; 589 free(sc->wi_usb_txmem[sc->wi_usb_nummem], M_DEVBUF); 590 sc->wi_usb_txmem[sc->wi_usb_nummem] = NULL; 591 } 592 593 #if 0 594 /* if this is the first time, init, otherwise do not?? */ 595 if (sc->wi_resetonce) { 596 return 0; 597 } else 598 sc->wi_resetonce = 1; 599 #endif 600 } 601 602 wi_usb_ctl_lock(sc); 603 604 wi_usb_tx_lock(sc); 605 606 c = &sc->wi_usb_tx_chain[0]; 607 pcmd = c->wi_usb_buf; 608 609 610 total_len = sizeof (struct wi_cmdreq); 611 rnd_len = ROUNDUP64(total_len); 612 if (rnd_len > WI_USB_BUFSZ) { 613 printf("read_record buf size err %x %x\n", 614 rnd_len, WI_USB_BUFSZ); 615 err = EIO; 616 goto err_ret; 617 } 618 619 sc->cmdresp = cmd; 620 sc->cmdresperr = 0; 621 622 pcmd->type = htole16(WI_USB_CMDREQ); 623 pcmd->cmd = htole16(cmd); 624 pcmd->param0 = htole16(val0); 625 pcmd->param1 = htole16(val1); 626 pcmd->param2 = htole16(val2); 627 628 bzero(((char*)pcmd)+total_len, rnd_len - total_len); 629 630 usbd_setup_xfer(c->wi_usb_xfer, sc->wi_usb_ep[WI_USB_ENDPT_TX], 631 c, c->wi_usb_buf, rnd_len, USBD_FORCE_SHORT_XFER | USBD_NO_COPY, 632 WI_USB_TX_TIMEOUT, wi_usb_txeof); 633 634 err = wi_usb_do_transmit_sync(sc, c, &sc->cmdresperr); 635 636 if (err == 0) 637 err = sc->cmdresperr; 638 639 sc->cmdresperr = 0; 640 641 err_ret: 642 wi_usb_tx_unlock(sc); 643 644 wi_usb_ctl_unlock(sc); 645 646 DPRINTFN(5,("%s: %s: exit err=%x\n", 647 sc->wi_usb_dev.dv_xname, __func__, err)); 648 return err; 649 } 650 651 652 int 653 wi_read_record_usb(struct wi_softc *wsc, struct wi_ltv_gen *ltv) 654 { 655 struct wi_usb_chain *c; 656 struct wi_usb_softc *sc = wsc->wi_usb_cdata; 657 struct wi_rridreq *prid; 658 int total_len, rnd_len; 659 int err; 660 struct wi_ltv_gen *oltv, p2ltv; 661 662 DPRINTFN(5,("%s: %s: enter rid=%x\n", 663 sc->wi_usb_dev.dv_xname, __func__, ltv->wi_type)); 664 665 /* Do we need to deal with these here, as in _io version? 666 * WI_RID_ENCRYPTION -> WI_RID_P2_ENCRYPTION 667 * WI_RID_TX_CRYPT_KEY -> WI_RID_P2_TX_CRYPT_KEY 668 */ 669 if (wsc->sc_firmware_type != WI_LUCENT) { 670 oltv = ltv; 671 switch (ltv->wi_type) { 672 case WI_RID_ENCRYPTION: 673 p2ltv.wi_type = WI_RID_P2_ENCRYPTION; 674 p2ltv.wi_len = 2; 675 ltv = &p2ltv; 676 break; 677 case WI_RID_TX_CRYPT_KEY: 678 if (ltv->wi_val > WI_NLTV_KEYS) 679 return (EINVAL); 680 p2ltv.wi_type = WI_RID_P2_TX_CRYPT_KEY; 681 p2ltv.wi_len = 2; 682 ltv = &p2ltv; 683 break; 684 } 685 } 686 687 wi_usb_tx_lock(sc); 688 689 c = &sc->wi_usb_tx_chain[0]; 690 prid = c->wi_usb_buf; 691 692 total_len = sizeof(struct wi_rridreq); 693 rnd_len = ROUNDUP64(total_len); 694 695 if (rnd_len > WI_USB_BUFSZ) { 696 printf("read_record buf size err %x %x\n", 697 rnd_len, WI_USB_BUFSZ); 698 wi_usb_tx_unlock(sc); 699 return EIO; 700 } 701 702 sc->ridltv = ltv; 703 sc->ridresperr = 0; 704 705 prid->type = htole16(WI_USB_RRIDREQ); 706 prid->frmlen = htole16(2); /* variable size? */ 707 prid->rid = htole16(ltv->wi_type); 708 709 bzero(((char*)prid)+total_len, rnd_len - total_len); 710 711 usbd_setup_xfer(c->wi_usb_xfer, sc->wi_usb_ep[WI_USB_ENDPT_TX], 712 c, c->wi_usb_buf, rnd_len, USBD_FORCE_SHORT_XFER | USBD_NO_COPY, 713 WI_USB_TX_TIMEOUT, wi_usb_txeof); 714 715 DPRINTFN(10,("%s: %s: total_len=%x, wilen %d\n", 716 sc->wi_usb_dev.dv_xname, __func__, total_len, ltv->wi_len)); 717 718 err = wi_usb_do_transmit_sync(sc, c, &sc->ridresperr); 719 720 /* Do we need to deal with these here, as in _io version? 721 * 722 * WI_RID_TX_RATE 723 * WI_RID_CUR_TX_RATE 724 * WI_RID_ENCRYPTION 725 * WI_RID_TX_CRYPT_KEY 726 * WI_RID_CNFAUTHMODE 727 */ 728 if (ltv->wi_type == WI_RID_PORTTYPE && wsc->wi_ptype == WI_PORTTYPE_IBSS 729 && ltv->wi_val == wsc->wi_ibss_port) { 730 /* 731 * Convert vendor IBSS port type to WI_PORTTYPE_IBSS. 732 * Since Lucent uses port type 1 for BSS *and* IBSS we 733 * have to rely on wi_ptype to distinguish this for us. 734 */ 735 ltv->wi_val = htole16(WI_PORTTYPE_IBSS); 736 } else if (wsc->sc_firmware_type != WI_LUCENT) { 737 int v; 738 739 switch (oltv->wi_type) { 740 case WI_RID_TX_RATE: 741 case WI_RID_CUR_TX_RATE: 742 switch (letoh16(ltv->wi_val)) { 743 case 1: v = 1; break; 744 case 2: v = 2; break; 745 case 3: v = 6; break; 746 case 4: v = 5; break; 747 case 7: v = 7; break; 748 case 8: v = 11; break; 749 case 15: v = 3; break; 750 default: v = 0x100 + letoh16(ltv->wi_val); break; 751 } 752 oltv->wi_val = htole16(v); 753 break; 754 case WI_RID_ENCRYPTION: 755 oltv->wi_len = 2; 756 if (ltv->wi_val & htole16(0x01)) 757 oltv->wi_val = htole16(1); 758 else 759 oltv->wi_val = htole16(0); 760 break; 761 case WI_RID_TX_CRYPT_KEY: 762 case WI_RID_CNFAUTHMODE: 763 oltv->wi_len = 2; 764 oltv->wi_val = ltv->wi_val; 765 break; 766 } 767 } 768 769 if (err == 0) 770 err = sc->ridresperr; 771 772 sc->ridresperr = 0; 773 774 wi_usb_tx_unlock(sc); 775 776 DPRINTFN(5,("%s: %s: exit err=%x\n", 777 sc->wi_usb_dev.dv_xname, __func__, err)); 778 return err; 779 } 780 781 int 782 wi_write_record_usb(struct wi_softc *wsc, struct wi_ltv_gen *ltv) 783 { 784 struct wi_usb_chain *c; 785 struct wi_usb_softc *sc = wsc->wi_usb_cdata; 786 struct wi_wridreq *prid; 787 int total_len, rnd_len; 788 int err; 789 struct wi_ltv_gen p2ltv; 790 u_int16_t val = 0; 791 int i; 792 793 DPRINTFN(5,("%s: %s: enter rid=%x wi_len %d copying %x\n", 794 sc->wi_usb_dev.dv_xname, __func__, ltv->wi_type, ltv->wi_len, 795 (ltv->wi_len-1)*2 )); 796 797 /* Do we need to deal with these here, as in _io version? 798 * WI_PORTTYPE_IBSS -> WI_RID_PORTTYPE 799 * RID_TX_RATE munging 800 * RID_ENCRYPTION 801 * WI_RID_TX_CRYPT_KEY 802 * WI_RID_DEFLT_CRYPT_KEYS 803 */ 804 if (ltv->wi_type == WI_RID_PORTTYPE && 805 letoh16(ltv->wi_val) == WI_PORTTYPE_IBSS) { 806 /* Convert WI_PORTTYPE_IBSS to vendor IBSS port type. */ 807 p2ltv.wi_type = WI_RID_PORTTYPE; 808 p2ltv.wi_len = 2; 809 p2ltv.wi_val = wsc->wi_ibss_port; 810 ltv = &p2ltv; 811 } else if (wsc->sc_firmware_type != WI_LUCENT) { 812 int v; 813 814 switch (ltv->wi_type) { 815 case WI_RID_TX_RATE: 816 p2ltv.wi_type = WI_RID_TX_RATE; 817 p2ltv.wi_len = 2; 818 switch (letoh16(ltv->wi_val)) { 819 case 1: v = 1; break; 820 case 2: v = 2; break; 821 case 3: v = 15; break; 822 case 5: v = 4; break; 823 case 6: v = 3; break; 824 case 7: v = 7; break; 825 case 11: v = 8; break; 826 default: return EINVAL; 827 } 828 p2ltv.wi_val = htole16(v); 829 ltv = &p2ltv; 830 break; 831 case WI_RID_ENCRYPTION: 832 p2ltv.wi_type = WI_RID_P2_ENCRYPTION; 833 p2ltv.wi_len = 2; 834 if (ltv->wi_val & htole16(0x01)) { 835 val = PRIVACY_INVOKED; 836 /* 837 * If using shared key WEP we must set the 838 * EXCLUDE_UNENCRYPTED bit. Symbol cards 839 * need this bit set even when not using 840 * shared key. We can't just test for 841 * IEEE80211_AUTH_SHARED since Symbol cards 842 * have 2 shared key modes. 843 */ 844 if (wsc->wi_authtype != IEEE80211_AUTH_OPEN || 845 wsc->sc_firmware_type == WI_SYMBOL) 846 val |= EXCLUDE_UNENCRYPTED; 847 848 switch (wsc->wi_crypto_algorithm) { 849 case WI_CRYPTO_FIRMWARE_WEP: 850 /* 851 * TX encryption is broken in 852 * Host AP mode. 853 */ 854 if (wsc->wi_ptype == WI_PORTTYPE_HOSTAP) 855 val |= HOST_ENCRYPT; 856 break; 857 case WI_CRYPTO_SOFTWARE_WEP: 858 val |= HOST_ENCRYPT|HOST_DECRYPT; 859 break; 860 } 861 p2ltv.wi_val = htole16(val); 862 } else 863 p2ltv.wi_val = htole16(HOST_ENCRYPT | HOST_DECRYPT); 864 ltv = &p2ltv; 865 break; 866 case WI_RID_TX_CRYPT_KEY: 867 if (ltv->wi_val > WI_NLTV_KEYS) 868 return (EINVAL); 869 p2ltv.wi_type = WI_RID_P2_TX_CRYPT_KEY; 870 p2ltv.wi_len = 2; 871 p2ltv.wi_val = ltv->wi_val; 872 ltv = &p2ltv; 873 break; 874 case WI_RID_DEFLT_CRYPT_KEYS: { 875 int error; 876 int keylen; 877 struct wi_ltv_str ws; 878 struct wi_ltv_keys *wk; 879 880 wk = (struct wi_ltv_keys *)ltv; 881 keylen = wk->wi_keys[wsc->wi_tx_key].wi_keylen; 882 keylen = letoh16(keylen); 883 884 for (i = 0; i < 4; i++) { 885 bzero(&ws, sizeof(ws)); 886 ws.wi_len = (keylen > 5) ? 8 : 4; 887 ws.wi_type = WI_RID_P2_CRYPT_KEY0 + i; 888 bcopy(&wk->wi_keys[i].wi_keydat, 889 ws.wi_str, keylen); 890 error = wi_write_record_usb(wsc, 891 (struct wi_ltv_gen *)&ws); 892 if (error) 893 return (error); 894 } 895 } 896 return (0); 897 } 898 } 899 900 wi_usb_tx_lock(sc); 901 902 c = &sc->wi_usb_tx_chain[0]; 903 904 prid = c->wi_usb_buf; 905 906 total_len = sizeof(prid->type) + sizeof(prid->frmlen) + 907 sizeof(prid->rid) + (ltv->wi_len-1)*2; 908 rnd_len = ROUNDUP64(total_len); 909 if (rnd_len > WI_USB_BUFSZ) { 910 printf("write_record buf size err %x %x\n", 911 rnd_len, WI_USB_BUFSZ); 912 wi_usb_tx_unlock(sc); 913 return EIO; 914 } 915 916 prid->type = htole16(WI_USB_WRIDREQ); 917 prid->frmlen = htole16(ltv->wi_len); 918 prid->rid = htole16(ltv->wi_type); 919 if (ltv->wi_len > 1) 920 bcopy((u_int8_t *)<v->wi_val, (u_int8_t *)&prid->data[0], 921 (ltv->wi_len-1)*2); 922 923 bzero(((char*)prid)+total_len, rnd_len - total_len); 924 925 usbd_setup_xfer(c->wi_usb_xfer, sc->wi_usb_ep[WI_USB_ENDPT_TX], 926 c, c->wi_usb_buf, rnd_len, USBD_FORCE_SHORT_XFER | USBD_NO_COPY, 927 WI_USB_TX_TIMEOUT, wi_usb_txeof); 928 929 err = wi_usb_do_transmit_sync(sc, c, &sc->ridresperr); 930 931 if (err == 0) 932 err = sc->ridresperr; 933 934 sc->ridresperr = 0; 935 936 wi_usb_tx_unlock(sc); 937 938 DPRINTFN(5,("%s: %s: exit err=%x\n", 939 sc->wi_usb_dev.dv_xname, __func__, err)); 940 return err; 941 } 942 943 /* 944 * This is an ugly compat portion to emulate the I/O which writes 945 * a packet or management information 946 * The data is copied into local memory for the requested 947 * 'id' then on the wi_cmd WI_CMD_TX, the id argument 948 * will identify which buffer to use 949 */ 950 int 951 wi_alloc_nicmem_usb(struct wi_softc *wsc, int len, int *id) 952 { 953 int nmem; 954 struct wi_usb_softc *sc = wsc->wi_usb_cdata; 955 956 DPRINTFN(10,("%s: %s: enter len=%x\n", 957 sc->wi_usb_dev.dv_xname, __func__, len)); 958 959 /* 960 * NOTE THIS IS A USB DEVICE WHICH WILL LIKELY HAVE MANY 961 * CONNECTS/DISCONNECTS, FREE THIS MEMORY XXX XXX XXX !!! !!! 962 */ 963 nmem = sc->wi_usb_nummem++; 964 965 if (nmem >= MAX_WI_NMEM) { 966 sc->wi_usb_nummem--; 967 return ENOMEM; 968 } 969 970 sc->wi_usb_txmem[nmem] = malloc(len, M_DEVBUF, M_WAITOK); 971 if (sc->wi_usb_txmem[nmem] == NULL) { 972 sc->wi_usb_nummem--; 973 return ENOMEM; 974 } 975 sc->wi_usb_txmemsize[nmem] = len; 976 977 *id = nmem; 978 return 0; 979 } 980 981 /* 982 * this is crazy, we skip the first 16 bits of the buf so that it 983 * can be used as the 'type' of the usb transfer. 984 */ 985 986 987 int 988 wi_write_data_usb(struct wi_softc *wsc, int id, int off, caddr_t buf, int len) 989 { 990 u_int8_t *ptr; 991 struct wi_usb_softc *sc = wsc->wi_usb_cdata; 992 993 DPRINTFN(10,("%s: %s: id %x off %x len %d\n", 994 sc->wi_usb_dev.dv_xname, __func__, id, off, len)); 995 996 if (id < 0 && id >= sc->wi_usb_nummem) 997 return EIO; 998 999 ptr = (u_int8_t *)(sc->wi_usb_txmem[id]) + off; 1000 1001 if (len + off > sc->wi_usb_txmemsize[id]) 1002 return EIO; 1003 DPRINTFN(10,("%s: %s: completed \n", 1004 sc->wi_usb_dev.dv_xname, __func__)); 1005 1006 bcopy(buf, ptr, len); 1007 return 0; 1008 } 1009 1010 /* 1011 * On the prism I/O, this read_data points to the hardware buffer 1012 * which contains the 1013 */ 1014 int 1015 wi_read_data_usb(struct wi_softc *wsc, int id, int off, caddr_t buf, int len) 1016 { 1017 u_int8_t *ptr; 1018 struct wi_usb_softc *sc = wsc->wi_usb_cdata; 1019 1020 DPRINTFN(10,("%s: %s: id %x off %x len %d\n", 1021 sc->wi_usb_dev.dv_xname, __func__, id, off, len)); 1022 1023 if (id == 0x1001 && sc->wi_info != NULL) 1024 ptr = (u_int8_t *)sc->wi_info + off; 1025 else if (id == 0x1000 && sc->wi_rxframe != NULL) 1026 ptr = (u_int8_t *)sc->wi_rxframe + off; 1027 else if (id >= 0 && id < sc->wi_usb_nummem) { 1028 1029 if (sc->wi_usb_txmem[id] == NULL) 1030 return EIO; 1031 if (len + off > sc->wi_usb_txmemsize[id]) 1032 return EIO; 1033 1034 ptr = (u_int8_t *)(sc->wi_usb_txmem[id]) + off; 1035 } else 1036 return EIO; 1037 1038 if (id < sc->wi_usb_nummem) { 1039 ptr = (u_int8_t *)(sc->wi_usb_txmem[id]) + off; 1040 1041 if (len + off > sc->wi_usb_txmemsize[id]) 1042 return EIO; 1043 } 1044 1045 bcopy(ptr, buf, len); 1046 return 0; 1047 } 1048 1049 void 1050 wi_usb_stop(struct wi_usb_softc *sc) 1051 { 1052 DPRINTFN(1,("%s: %s: enter\n", sc->wi_usb_dev.dv_xname,__func__)); 1053 /* XXX */ 1054 1055 /* Stop transfers */ 1056 } 1057 1058 int 1059 wi_usb_do_transmit_sync(struct wi_usb_softc *sc, struct wi_usb_chain *c, 1060 void *ident) 1061 { 1062 usbd_status err; 1063 1064 DPRINTFN(10,("%s: %s:\n", 1065 sc->wi_usb_dev.dv_xname, __func__)); 1066 1067 sc->wi_usb_refcnt++; 1068 err = usbd_transfer(c->wi_usb_xfer); 1069 if (err != USBD_IN_PROGRESS && err != USBD_NORMAL_COMPLETION) { 1070 printf("%s: %s error=%s\n", 1071 sc->wi_usb_dev.dv_xname, __func__, 1072 usbd_errstr(err)); 1073 /* Stop the interface from process context. */ 1074 wi_usb_stop(sc); 1075 err = EIO; 1076 goto done; 1077 } 1078 err = tsleep(ident, PRIBIO, "wiTXsync", hz*1); 1079 if (err) { 1080 DPRINTFN(1,("%s: %s: err %x\n", 1081 sc->wi_usb_dev.dv_xname, __func__, err)); 1082 err = ETIMEDOUT; 1083 } 1084 done: 1085 if (--sc->wi_usb_refcnt < 0) 1086 usb_detach_wakeup(&sc->wi_usb_dev); 1087 return err; 1088 } 1089 1090 1091 /* 1092 * A command/rrid/wrid was sent to the chip. It's safe for us to clean up 1093 * the list buffers. 1094 */ 1095 1096 void 1097 wi_usb_txeof(usbd_xfer_handle xfer, usbd_private_handle priv, 1098 usbd_status status) 1099 { 1100 struct wi_usb_chain *c = priv; 1101 struct wi_usb_softc *sc = c->wi_usb_sc; 1102 1103 int s; 1104 1105 if (sc->wi_usb_dying) 1106 return; 1107 1108 s = splnet(); 1109 1110 DPRINTFN(10,("%s: %s: enter status=%d\n", sc->wi_usb_dev.dv_xname, 1111 __func__, status)); 1112 1113 if (status != USBD_NORMAL_COMPLETION) { 1114 if (status == USBD_NOT_STARTED || status == USBD_CANCELLED) { 1115 splx(s); 1116 return; 1117 } 1118 printf("%s: usb error on tx: %s\n", sc->wi_usb_dev.dv_xname, 1119 usbd_errstr(status)); 1120 if (status == USBD_STALLED) { 1121 sc->wi_usb_refcnt++; 1122 usbd_clear_endpoint_stall_async( 1123 sc->wi_usb_ep[WI_USB_ENDPT_TX]); 1124 if (--sc->wi_usb_refcnt < 0) 1125 usb_detach_wakeup(&sc->wi_usb_dev); 1126 } 1127 splx(s); 1128 return; 1129 } 1130 1131 splx(s); 1132 } 1133 1134 /* 1135 * A packet was sent to the chip. It's safe for us to clean up 1136 * the list buffers. 1137 */ 1138 1139 void 1140 wi_usb_txeof_frm(usbd_xfer_handle xfer, usbd_private_handle priv, 1141 usbd_status status) 1142 { 1143 struct wi_usb_chain *c = priv; 1144 struct wi_usb_softc *sc = c->wi_usb_sc; 1145 struct wi_softc *wsc = &sc->sc_wi; 1146 struct ifnet *ifp = &wsc->sc_ic.ic_if; 1147 1148 int s; 1149 int err = 0; 1150 1151 if (sc->wi_usb_dying) 1152 return; 1153 1154 s = splnet(); 1155 1156 DPRINTFN(10,("%s: %s: enter status=%d\n", sc->wi_usb_dev.dv_xname, 1157 __func__, status)); 1158 1159 if (status != USBD_NORMAL_COMPLETION) { 1160 if (status == USBD_NOT_STARTED || status == USBD_CANCELLED) { 1161 splx(s); 1162 return; 1163 } 1164 printf("%s: usb error on tx: %s\n", sc->wi_usb_dev.dv_xname, 1165 usbd_errstr(status)); 1166 if (status == USBD_STALLED) { 1167 sc->wi_usb_refcnt++; 1168 usbd_clear_endpoint_stall_async( 1169 sc->wi_usb_ep[WI_USB_ENDPT_TX]); 1170 if (--sc->wi_usb_refcnt < 0) 1171 usb_detach_wakeup(&sc->wi_usb_dev); 1172 } 1173 splx(s); 1174 return; 1175 } 1176 1177 if (status) 1178 err = WI_EV_TX_EXC; 1179 1180 wi_txeof(wsc, err); 1181 1182 wi_usb_tx_unlock(sc); 1183 1184 if (!IFQ_IS_EMPTY(&ifp->if_snd)) 1185 wi_start_usb(ifp); 1186 1187 splx(s); 1188 } 1189 1190 int 1191 wi_usb_rx_list_init(struct wi_usb_softc *sc) 1192 { 1193 struct wi_usb_chain *c; 1194 int i; 1195 1196 DPRINTFN(10,("%s: %s: enter\n", sc->wi_usb_dev.dv_xname, __func__)); 1197 1198 for (i = 0; i < WI_USB_RX_LIST_CNT; i++) { 1199 c = &sc->wi_usb_rx_chain[i]; 1200 c->wi_usb_sc = sc; 1201 c->wi_usb_idx = i; 1202 if (c->wi_usb_xfer != NULL) { 1203 printf("UGH RX\n"); 1204 } 1205 if (c->wi_usb_xfer == NULL) { 1206 c->wi_usb_xfer = usbd_alloc_xfer(sc->wi_usb_udev); 1207 if (c->wi_usb_xfer == NULL) 1208 return (ENOBUFS); 1209 c->wi_usb_buf = usbd_alloc_buffer(c->wi_usb_xfer, 1210 WI_USB_BUFSZ); 1211 if (c->wi_usb_buf == NULL) 1212 return (ENOBUFS); /* XXX free xfer */ 1213 } 1214 } 1215 1216 return (0); 1217 } 1218 1219 int 1220 wi_usb_tx_list_init(struct wi_usb_softc *sc) 1221 { 1222 struct wi_usb_chain *c; 1223 int i; 1224 1225 DPRINTFN(10,("%s: %s: enter\n", sc->wi_usb_dev.dv_xname, __func__)); 1226 1227 for (i = 0; i < WI_USB_TX_LIST_CNT; i++) { 1228 c = &sc->wi_usb_tx_chain[i]; 1229 c->wi_usb_sc = sc; 1230 c->wi_usb_idx = i; 1231 c->wi_usb_mbuf = NULL; 1232 if (c->wi_usb_xfer != NULL) { 1233 printf("UGH TX\n"); 1234 } 1235 if (c->wi_usb_xfer == NULL) { 1236 c->wi_usb_xfer = usbd_alloc_xfer(sc->wi_usb_udev); 1237 if (c->wi_usb_xfer == NULL) 1238 return (ENOBUFS); 1239 c->wi_usb_buf = usbd_alloc_buffer(c->wi_usb_xfer, 1240 WI_USB_BUFSZ); 1241 if (c->wi_usb_buf == NULL) 1242 return (ENOBUFS); 1243 } 1244 } 1245 1246 return (0); 1247 } 1248 1249 int 1250 wi_usb_open_pipes(struct wi_usb_softc *sc) 1251 { 1252 usbd_status err; 1253 int error = 0; 1254 struct wi_usb_chain *c; 1255 int i; 1256 1257 DPRINTFN(10,("%s: %s: enter\n", sc->wi_usb_dev.dv_xname,__func__)); 1258 1259 sc->wi_usb_refcnt++; 1260 1261 /* Open RX and TX pipes. */ 1262 err = usbd_open_pipe(sc->wi_usb_iface, sc->wi_usb_ed[WI_USB_ENDPT_RX], 1263 USBD_EXCLUSIVE_USE, &sc->wi_usb_ep[WI_USB_ENDPT_RX]); 1264 if (err) { 1265 printf("%s: open rx pipe failed: %s\n", 1266 sc->wi_usb_dev.dv_xname, usbd_errstr(err)); 1267 error = EIO; 1268 goto done; 1269 } 1270 1271 err = usbd_open_pipe(sc->wi_usb_iface, sc->wi_usb_ed[WI_USB_ENDPT_TX], 1272 USBD_EXCLUSIVE_USE, &sc->wi_usb_ep[WI_USB_ENDPT_TX]); 1273 if (err) { 1274 printf("%s: open tx pipe failed: %s\n", 1275 sc->wi_usb_dev.dv_xname, usbd_errstr(err)); 1276 error = EIO; 1277 goto done; 1278 } 1279 1280 /* is this used? */ 1281 err = usbd_open_pipe_intr(sc->wi_usb_iface, 1282 sc->wi_usb_ed[WI_USB_ENDPT_INTR], USBD_EXCLUSIVE_USE, 1283 &sc->wi_usb_ep[WI_USB_ENDPT_INTR], sc, &sc->wi_usb_ibuf, 1284 WI_USB_INTR_PKTLEN, wi_usb_intr, WI_USB_INTR_INTERVAL); 1285 if (err) { 1286 printf("%s: open intr pipe failed: %s\n", 1287 sc->wi_usb_dev.dv_xname, usbd_errstr(err)); 1288 error = EIO; 1289 goto done; 1290 } 1291 1292 /* Start up the receive pipe. */ 1293 for (i = 0; i < WI_USB_RX_LIST_CNT; i++) { 1294 c = &sc->wi_usb_rx_chain[i]; 1295 usbd_setup_xfer(c->wi_usb_xfer, sc->wi_usb_ep[WI_USB_ENDPT_RX], 1296 c, c->wi_usb_buf, WI_USB_BUFSZ, 1297 USBD_SHORT_XFER_OK | USBD_NO_COPY, USBD_NO_TIMEOUT, 1298 wi_usb_rxeof); 1299 DPRINTFN(10,("%s: %s: start read\n", sc->wi_usb_dev.dv_xname, 1300 __func__)); 1301 usbd_transfer(c->wi_usb_xfer); 1302 } 1303 1304 done: 1305 if (--sc->wi_usb_refcnt < 0) 1306 usb_detach_wakeup(&sc->wi_usb_dev); 1307 1308 return (error); 1309 } 1310 1311 /* 1312 * This is a bit of a kludge, however wi_rxeof and wi_update_stats 1313 * call wi_get_fid to determine where the data associated with 1314 * the transaction is located, the returned id is then used to 1315 * wi_read_data the information out. 1316 * 1317 * This code returns which 'fid' should be used. The results are only valid 1318 * during a wi_usb_rxeof because the data is received packet is 'held' 1319 * an a variable for reading by wi_read_data_usb for that period. 1320 * 1321 * for magic numbers this uses 0x1000, 0x1001 for rx/info 1322 */ 1323 1324 int 1325 wi_get_fid_usb(struct wi_softc *sc, int fid) 1326 { 1327 switch (fid) { 1328 case WI_RX_FID: 1329 return 0x1000; 1330 case WI_INFO_FID: 1331 return 0x1001; 1332 default: 1333 return 0x1111; 1334 } 1335 1336 } 1337 1338 int 1339 wi_usb_activate(struct device *self, enum devact act) 1340 { 1341 struct wi_usb_softc *sc = (struct wi_usb_softc *)self; 1342 1343 DPRINTFN(10,("%s: %s: enter\n", sc->wi_usb_dev.dv_xname, __func__)); 1344 1345 switch (act) { 1346 case DVACT_ACTIVATE: 1347 break; 1348 1349 case DVACT_DEACTIVATE: 1350 sc->wi_usb_dying = 1; 1351 sc->wi_thread_info->dying = 1; 1352 break; 1353 } 1354 return (0); 1355 } 1356 1357 #if 0 1358 void 1359 wi_dump_data(void *buffer, int len) 1360 { 1361 int i; 1362 for (i = 0; i < len; i++) { 1363 if (((i) % 16) == 0) 1364 printf("\n %02x:", i); 1365 printf(" %02x", 1366 ((uint8_t *)(buffer))[i]); 1367 1368 } 1369 printf("\n"); 1370 1371 } 1372 #endif 1373 1374 /* 1375 * A frame has been received. 1376 */ 1377 void 1378 wi_usb_rxeof(usbd_xfer_handle xfer, usbd_private_handle priv, usbd_status status) 1379 { 1380 struct wi_usb_chain *c = priv; 1381 struct wi_usb_softc *sc = c->wi_usb_sc; 1382 wi_usb_usbin *uin; 1383 int total_len = 0; 1384 u_int16_t rtype; 1385 1386 if (sc->wi_usb_dying) 1387 return; 1388 1389 DPRINTFN(10,("%s: %s: enter status=%d\n", sc->wi_usb_dev.dv_xname, 1390 __func__, status)); 1391 1392 1393 if (status != USBD_NORMAL_COMPLETION) { 1394 if (status == USBD_NOT_STARTED || status == USBD_IOERROR 1395 || status == USBD_CANCELLED) { 1396 printf("%s: %u usb errors on rx: %s\n", 1397 sc->wi_usb_dev.dv_xname, 1, 1398 /* sc->wi_usb_rx_errs, */ 1399 usbd_errstr(status)); 1400 return; 1401 } 1402 #if 0 1403 sc->wi_usb_rx_errs++; 1404 if (usbd_ratecheck(&sc->wi_usb_rx_notice)) { 1405 printf("%s: %u usb errors on rx: %s\n", 1406 sc->wi_usb_dev.dv_xname, sc->wi_usb_rx_errs, 1407 usbd_errstr(status)); 1408 sc->wi_usb_rx_errs = 0; 1409 } 1410 #endif 1411 if (status == USBD_STALLED) { 1412 sc->wi_usb_refcnt++; 1413 usbd_clear_endpoint_stall_async( 1414 sc->wi_usb_ep[WI_USB_ENDPT_RX]); 1415 if (--sc->wi_usb_refcnt < 0) 1416 usb_detach_wakeup(&sc->wi_usb_dev); 1417 } 1418 goto done; 1419 } 1420 1421 usbd_get_xfer_status(xfer, NULL, NULL, &total_len, NULL); 1422 1423 if (total_len < 6) /* short XXX */ 1424 goto done; 1425 1426 uin = (wi_usb_usbin *)(c->wi_usb_buf); 1427 1428 rtype = letoh16(uin->type); 1429 1430 1431 #if 0 1432 wi_dump_data(c->wi_usb_buf, total_len); 1433 #endif 1434 1435 if (WI_USB_ISRXFRM(rtype)) { 1436 wi_usb_rxfrm(sc, uin, total_len); 1437 goto done; 1438 } 1439 if (WI_USB_ISTXFRM(rtype)) { 1440 DPRINTFN(2,("%s: %s: txfrm type %x\n", 1441 sc->wi_usb_dev.dv_xname, __func__, rtype)); 1442 wi_usb_txfrm(sc, uin, total_len); 1443 goto done; 1444 } 1445 1446 switch (rtype) { 1447 case WI_USB_INFOFRM: 1448 /* info packet, INFO_FID hmm */ 1449 DPRINTFN(10,("%s: %s: infofrm type %x\n", 1450 sc->wi_usb_dev.dv_xname, __func__, rtype)); 1451 wi_usb_infofrm(c, total_len); 1452 break; 1453 case WI_USB_CMDRESP: 1454 wi_usb_cmdresp(c); 1455 break; 1456 case WI_USB_WRIDRESP: 1457 wi_usb_wridresp(c); 1458 break; 1459 case WI_USB_RRIDRESP: 1460 wi_usb_rridresp(c); 1461 break; 1462 case WI_USB_WMEMRESP: 1463 /* Not currently used */ 1464 DPRINTFN(2,("%s: %s: wmemresp type %x\n", 1465 sc->wi_usb_dev.dv_xname, __func__, rtype)); 1466 break; 1467 case WI_USB_RMEMRESP: 1468 /* Not currently used */ 1469 DPRINTFN(2,("%s: %s: rmemresp type %x\n", 1470 sc->wi_usb_dev.dv_xname, __func__, rtype)); 1471 break; 1472 case WI_USB_BUFAVAIL: 1473 printf("wi_usb: received USB_BUFAVAIL packet\n"); /* XXX */ 1474 break; 1475 case WI_USB_ERROR: 1476 printf("wi_usb: received USB_ERROR packet\n"); /* XXX */ 1477 break; 1478 #if 0 1479 default: 1480 printf("wi_usb: received Unknown packet 0x%x len %x\n", 1481 rtype, total_len); 1482 wi_dump_data(c->wi_usb_buf, total_len); 1483 #endif 1484 } 1485 1486 done: 1487 /* Setup new transfer. */ 1488 usbd_setup_xfer(c->wi_usb_xfer, sc->wi_usb_ep[WI_USB_ENDPT_RX], 1489 c, c->wi_usb_buf, WI_USB_BUFSZ, USBD_SHORT_XFER_OK | USBD_NO_COPY, 1490 USBD_NO_TIMEOUT, wi_usb_rxeof); 1491 sc->wi_usb_refcnt++; 1492 usbd_transfer(c->wi_usb_xfer); 1493 if (--sc->wi_usb_refcnt < 0) 1494 usb_detach_wakeup(&sc->wi_usb_dev); 1495 1496 DPRINTFN(10,("%s: %s: start rx\n", sc->wi_usb_dev.dv_xname, 1497 __func__)); 1498 } 1499 1500 void 1501 wi_usb_intr(usbd_xfer_handle xfer, usbd_private_handle priv, usbd_status status) 1502 { 1503 struct wi_usb_softc *sc = priv; 1504 1505 DPRINTFN(2,("%s: %s: enter\n", sc->wi_usb_dev.dv_xname, __func__)); 1506 1507 if (sc->wi_usb_dying) 1508 return; 1509 1510 if (status != USBD_NORMAL_COMPLETION) { 1511 if (status == USBD_NOT_STARTED || status == USBD_CANCELLED) 1512 return; 1513 1514 if (status == USBD_STALLED) { 1515 sc->wi_usb_refcnt++; 1516 usbd_clear_endpoint_stall_async( 1517 sc->wi_usb_ep[WI_USB_ENDPT_RX]); 1518 if (--sc->wi_usb_refcnt < 0) 1519 usb_detach_wakeup(&sc->wi_usb_dev); 1520 } 1521 return; 1522 } 1523 /* XXX oerrors or collisions? */ 1524 } 1525 void 1526 wi_usb_cmdresp(struct wi_usb_chain *c) 1527 { 1528 struct wi_cmdresp *presp = (struct wi_cmdresp *)(c->wi_usb_buf); 1529 u_int16_t status = letoh16(presp->status); 1530 struct wi_usb_softc *sc = c->wi_usb_sc; 1531 uint16_t type; 1532 uint16_t cmdresperr; 1533 1534 type = htole16(presp->type); 1535 cmdresperr = letoh16(presp->resp0); 1536 DPRINTFN(10,("%s: %s: enter type=%x, status=%x, cmdresp=%x, " 1537 "resp=%x,%x,%x\n", 1538 sc->wi_usb_dev.dv_xname, __func__, type, status, sc->cmdresp, 1539 cmdresperr, letoh16(presp->resp1), 1540 letoh16(presp->resp2))); 1541 1542 /* XXX */ 1543 if (sc->cmdresp != (status & WI_STAT_CMD_CODE)) { 1544 DPRINTFN(1,("%s: cmd ty %x st %x cmd %x failed %x\n", 1545 sc->wi_usb_dev.dv_xname, 1546 type, status, sc->cmdresp, cmdresperr)); 1547 return; 1548 } 1549 1550 sc->cmdresperr = (status & WI_STAT_CMD_RESULT) >> 8; 1551 1552 sc->cmdresp = 0; /* good value for idle == INI ?? XXX */ 1553 1554 wakeup(&sc->cmdresperr); 1555 } 1556 void 1557 wi_usb_rridresp(struct wi_usb_chain *c) 1558 { 1559 struct wi_rridresp *presp = (struct wi_rridresp *)(c->wi_usb_buf); 1560 u_int16_t frmlen = letoh16(presp->frmlen); 1561 struct wi_usb_softc *sc = c->wi_usb_sc; 1562 struct wi_ltv_gen *ltv; 1563 uint16_t rid; 1564 1565 rid = letoh16(presp->rid); 1566 ltv = sc->ridltv; 1567 1568 if (ltv == 0) { 1569 DPRINTFN(5,("%s: %s: enter ltv = 0 rid=%x len %d\n", 1570 sc->wi_usb_dev.dv_xname, __func__, rid, 1571 frmlen)); 1572 return; 1573 } 1574 1575 DPRINTFN(5,("%s: %s: enter rid=%x expecting %x len %d exptlen %d\n", 1576 sc->wi_usb_dev.dv_xname, __func__, rid, ltv->wi_type, 1577 frmlen, ltv->wi_len)); 1578 1579 rid = letoh16(presp->rid); 1580 1581 if (rid != ltv->wi_type) { 1582 sc->ridresperr = EIO; 1583 return; 1584 } 1585 1586 if (frmlen > ltv->wi_len) { 1587 sc->ridresperr = ENOSPC; 1588 sc->ridltv = 0; 1589 wakeup(&sc->ridresperr); 1590 return; 1591 } 1592 1593 ltv->wi_len = frmlen; 1594 1595 DPRINTFN(10,("%s: %s: copying %d frmlen %d\n", 1596 sc->wi_usb_dev.dv_xname, __func__, (ltv->wi_len-1)*2, 1597 frmlen)); 1598 1599 if (ltv->wi_len > 1) 1600 bcopy(&presp->data[0], (u_int8_t *)<v->wi_val, 1601 (ltv->wi_len-1)*2); 1602 1603 sc->ridresperr = 0; 1604 sc->ridltv = 0; 1605 wakeup(&sc->ridresperr); 1606 1607 } 1608 1609 void 1610 wi_usb_wridresp(struct wi_usb_chain *c) 1611 { 1612 struct wi_wridresp *presp = (struct wi_wridresp *)(c->wi_usb_buf); 1613 struct wi_usb_softc *sc = c->wi_usb_sc; 1614 uint16_t status; 1615 1616 status = letoh16(presp->status); 1617 1618 DPRINTFN(10,("%s: %s: enter status=%x\n", 1619 sc->wi_usb_dev.dv_xname, __func__, status)); 1620 1621 sc->ridresperr = (status & WI_STAT_CMD_RESULT) >> 8; 1622 sc->ridltv = 0; 1623 wakeup(&sc->ridresperr); 1624 } 1625 1626 void 1627 wi_usb_infofrm(struct wi_usb_chain *c, int len) 1628 { 1629 struct wi_usb_softc *sc = c->wi_usb_sc; 1630 1631 DPRINTFN(10,("%s: %s: enter\n", 1632 sc->wi_usb_dev.dv_xname, __func__)); 1633 1634 sc->wi_info = ((char *)c->wi_usb_buf) + 2; 1635 wi_update_stats(&sc->sc_wi); 1636 sc->wi_info = NULL; 1637 } 1638 1639 void 1640 wi_usb_txfrm(struct wi_usb_softc *sc, wi_usb_usbin *uin, int total_len) 1641 { 1642 u_int16_t status; 1643 int s; 1644 struct wi_softc *wsc = &sc->sc_wi; 1645 struct ifnet *ifp = &wsc->sc_ic.ic_if; 1646 1647 s = splnet(); 1648 status = letoh16(uin->type); /* XXX -- type == status */ 1649 1650 1651 DPRINTFN(2,("%s: %s: enter status=%d\n", 1652 sc->wi_usb_dev.dv_xname, __func__, status)); 1653 1654 if (sc->txresp == WI_CMD_TX) { 1655 sc->txresperr=status; 1656 sc->txresp = 0; 1657 wakeup(&sc->txresperr); 1658 } else { 1659 if (status != 0) /* XXX */ 1660 wi_watchdog_usb(ifp); 1661 DPRINTFN(1,("%s: %s: txresp not expected status=%d \n", 1662 sc->wi_usb_dev.dv_xname, __func__, status)); 1663 } 1664 1665 splx(s); 1666 } 1667 void 1668 wi_usb_rxfrm(struct wi_usb_softc *sc, wi_usb_usbin *uin, int total_len) 1669 { 1670 int s; 1671 1672 DPRINTFN(5,("%s: %s: enter len=%d\n", 1673 sc->wi_usb_dev.dv_xname, __func__, total_len)); 1674 1675 s = splnet(); 1676 1677 sc->wi_rxframe = (void *)uin; 1678 1679 wi_rxeof(&sc->sc_wi); 1680 1681 sc->wi_rxframe = NULL; 1682 1683 splx(s); 1684 1685 } 1686 1687 1688 void 1689 wi_usb_start_thread(void *arg) 1690 { 1691 struct wi_usb_softc *sc = arg; 1692 kthread_create (wi_usb_thread, arg, NULL, sc->wi_usb_dev.dv_xname); 1693 } 1694 1695 void 1696 wi_start_usb(struct ifnet *ifp) 1697 { 1698 struct wi_softc *wsc; 1699 struct wi_usb_softc *sc; 1700 int s; 1701 1702 wsc = ifp->if_softc; 1703 sc = wsc->wi_usb_cdata; 1704 1705 s = splnet(); 1706 1707 DPRINTFN(5,("%s: %s:\n", 1708 sc->wi_usb_dev.dv_xname, __func__)); 1709 1710 if (wi_usb_tx_lock_try(sc)) { 1711 /* lock acquired do start now */ 1712 wi_func_io.f_start(ifp); 1713 } else { 1714 sc->wi_thread_info->status |= WI_START; 1715 if (sc->wi_thread_info->idle) 1716 wakeup(sc->wi_thread_info); 1717 } 1718 1719 splx(s); 1720 } 1721 1722 /* 1723 * inquire is called from interrupt context (timeout) 1724 * It is not possible to sleep in interrupt context so it is necessary 1725 * to signal the kernel thread to perform the action. 1726 */ 1727 void 1728 wi_init_usb(struct wi_softc *wsc) 1729 { 1730 DPRINTFN(5,("%s: %s:\n", WI_PRT_ARG(wsc), __func__)); 1731 1732 wi_usb_ctl_lock(wsc->wi_usb_cdata); 1733 wi_func_io.f_init(wsc); 1734 wi_usb_ctl_unlock(wsc->wi_usb_cdata); 1735 } 1736 1737 1738 /* 1739 * inquire is called from interrupt context (timeout) 1740 * It is not possible to sleep in interrupt context so it is necessary 1741 * to signal the kernel thread to perform the action. 1742 */ 1743 void 1744 wi_inquire_usb(void *xsc) 1745 { 1746 struct wi_softc *wsc = xsc; 1747 struct wi_usb_softc *sc = wsc->wi_usb_cdata; 1748 int s; 1749 1750 1751 s = splnet(); 1752 1753 DPRINTFN(2,("%s: %s:\n", 1754 sc->wi_usb_dev.dv_xname, __func__)); 1755 1756 sc->wi_thread_info->status |= WI_INQUIRE; 1757 1758 if (sc->wi_thread_info->idle) 1759 wakeup(sc->wi_thread_info); 1760 splx(s); 1761 } 1762 1763 /* 1764 * Watchdog is normally called from interrupt context (timeout) 1765 * It is not possible to sleep in interrupt context so it is necessary 1766 * to signal the kernel thread to perform the action. 1767 */ 1768 void 1769 wi_watchdog_usb(struct ifnet *ifp) 1770 { 1771 struct wi_softc *wsc; 1772 struct wi_usb_softc *sc; 1773 int s; 1774 1775 wsc = ifp->if_softc; 1776 sc = wsc->wi_usb_cdata; 1777 1778 s = splnet(); 1779 1780 DPRINTFN(5,("%s: %s: ifp %x\n", 1781 sc->wi_usb_dev.dv_xname, __func__, ifp)); 1782 1783 sc->wi_thread_info->status |= WI_WATCHDOG; 1784 1785 if (sc->wi_thread_info->idle) 1786 wakeup(sc->wi_thread_info); 1787 splx(s); 1788 } 1789 1790 /* 1791 * ioctl will always be called from a user context, 1792 * therefore it is possible to sleep in the calling context 1793 * acquire the lock and call the real ioctl fucntion directly 1794 */ 1795 int 1796 wi_ioctl_usb(struct ifnet *ifp, u_long command, caddr_t data) 1797 { 1798 struct wi_softc *wsc; 1799 int err; 1800 1801 wsc = ifp->if_softc; 1802 1803 wi_usb_ctl_lock(wsc->wi_usb_cdata); 1804 err = wi_func_io.f_ioctl(ifp, command, data); 1805 wi_usb_ctl_unlock(wsc->wi_usb_cdata); 1806 return err; 1807 } 1808 1809 void 1810 wi_usb_thread(void *arg) 1811 { 1812 struct wi_usb_softc *sc = arg; 1813 struct wi_usb_thread_info *wi_thread_info; 1814 int s; 1815 1816 wi_thread_info = malloc(sizeof(*wi_thread_info), M_DEVBUF, M_WAITOK); 1817 1818 /* 1819 * is there a remote possibility that the device could 1820 * be removed before the kernel thread starts up? 1821 */ 1822 1823 sc->wi_usb_refcnt++; 1824 1825 sc->wi_thread_info = wi_thread_info; 1826 wi_thread_info->dying = 0; 1827 wi_thread_info->status = 0; 1828 1829 wi_usb_ctl_lock(sc); 1830 1831 wi_attach(&sc->sc_wi, &wi_func_usb); 1832 1833 wi_usb_ctl_unlock(sc); 1834 1835 for(;;) { 1836 if (wi_thread_info->dying) { 1837 if (--sc->wi_usb_refcnt < 0) 1838 usb_detach_wakeup(&sc->wi_usb_dev); 1839 kthread_exit(0); 1840 } 1841 1842 DPRINTFN(5,("%s: %s: dying %x status %x\n", 1843 sc->wi_usb_dev.dv_xname, __func__, 1844 wi_thread_info->dying, wi_thread_info->status)); 1845 1846 wi_usb_ctl_lock(sc); 1847 1848 DPRINTFN(5,("%s: %s: starting %x\n", 1849 sc->wi_usb_dev.dv_xname, __func__, 1850 wi_thread_info->status)); 1851 1852 s = splusb(); 1853 if (wi_thread_info->status & WI_START) { 1854 wi_thread_info->status &= ~WI_START; 1855 wi_usb_tx_lock(sc); 1856 wi_func_io.f_start(&sc->sc_wi.sc_ic.ic_if); 1857 /* 1858 * tx_unlock is explicitly missing here 1859 * it is done in txeof_frm 1860 */ 1861 } else if (wi_thread_info->status & WI_INQUIRE) { 1862 wi_thread_info->status &= ~WI_INQUIRE; 1863 wi_func_io.f_inquire(&sc->sc_wi); 1864 } else if (wi_thread_info->status & WI_WATCHDOG) { 1865 wi_thread_info->status &= ~WI_WATCHDOG; 1866 wi_func_io.f_watchdog( &sc->sc_wi.sc_ic.ic_if); 1867 } 1868 splx(s); 1869 1870 DPRINTFN(5,("%s: %s: ending %x\n", 1871 sc->wi_usb_dev.dv_xname, __func__, 1872 wi_thread_info->status)); 1873 wi_usb_ctl_unlock(sc); 1874 1875 if (wi_thread_info->status == 0) { 1876 s = splnet(); 1877 wi_thread_info->idle = 1; 1878 tsleep(wi_thread_info, PRIBIO, "wiIDL", 0); 1879 wi_thread_info->idle = 0; 1880 splx(s); 1881 } 1882 } 1883 } 1884 1885 int 1886 wi_usb_tx_lock_try(struct wi_usb_softc *sc) 1887 { 1888 int s; 1889 1890 s = splnet(); 1891 1892 DPRINTFN(10,("%s: %s: enter\n", sc->wi_usb_dev.dv_xname, __func__)); 1893 1894 if (sc->wi_lock != 0) { 1895 return 0; /* failed to aquire lock */ 1896 } 1897 1898 sc->wi_lock = 1; 1899 1900 splx(s); 1901 1902 return 1; 1903 } 1904 void 1905 wi_usb_tx_lock(struct wi_usb_softc *sc) 1906 { 1907 int s; 1908 1909 s = splnet(); 1910 1911 again: 1912 DPRINTFN(10,("%s: %s: enter\n", sc->wi_usb_dev.dv_xname, __func__)); 1913 1914 if (sc->wi_lock != 0) { 1915 sc->wi_lockwait++; 1916 DPRINTFN(10,("%s: %s: busy %d\n", sc->wi_usb_dev.dv_xname, 1917 __func__, sc->wi_lockwait )); 1918 tsleep(&sc->wi_lock, PRIBIO, "witxl", 0); 1919 } 1920 1921 if (sc->wi_lock != 0) 1922 goto again; 1923 sc->wi_lock = 1; 1924 1925 splx(s); 1926 1927 return; 1928 1929 } 1930 1931 void 1932 wi_usb_tx_unlock(struct wi_usb_softc *sc) 1933 { 1934 int s; 1935 s = splnet(); 1936 1937 sc->wi_lock = 0; 1938 1939 DPRINTFN(10,("%s: %s: enter\n", sc->wi_usb_dev.dv_xname, __func__)); 1940 1941 if (sc->wi_lockwait) { 1942 DPRINTFN(10,("%s: %s: waking\n", 1943 sc->wi_usb_dev.dv_xname, __func__)); 1944 sc->wi_lockwait = 0; 1945 wakeup(&sc->wi_lock); 1946 } 1947 1948 splx(s); 1949 } 1950 1951 void 1952 wi_usb_ctl_lock(struct wi_usb_softc *sc) 1953 { 1954 int s; 1955 1956 s = splnet(); 1957 1958 again: 1959 DPRINTFN(10,("%s: %s: enter\n", sc->wi_usb_dev.dv_xname, 1960 __func__)); 1961 1962 if (sc->wi_ctllock != 0) { 1963 if (curproc == sc->wi_curproc) { 1964 /* allow recursion */ 1965 sc->wi_ctllock++; 1966 splx(s); 1967 return; 1968 } 1969 sc->wi_ctllockwait++; 1970 DPRINTFN(10,("%s: %s: busy %d\n", sc->wi_usb_dev.dv_xname, 1971 __func__, sc->wi_ctllockwait )); 1972 tsleep(&sc->wi_ctllock, PRIBIO, "wiusbthr", 0); 1973 } 1974 1975 if (sc->wi_ctllock != 0) 1976 goto again; 1977 sc->wi_ctllock++; 1978 sc->wi_curproc = curproc; 1979 1980 splx(s); 1981 1982 return; 1983 1984 } 1985 1986 void 1987 wi_usb_ctl_unlock(struct wi_usb_softc *sc) 1988 { 1989 int s; 1990 1991 s = splnet(); 1992 1993 sc->wi_ctllock--; 1994 1995 DPRINTFN(10,("%s: %s: enter\n", sc->wi_usb_dev.dv_xname, __func__)); 1996 1997 if (sc->wi_ctllock == 0 && sc->wi_ctllockwait) { 1998 DPRINTFN(10,("%s: %s: waking\n", 1999 sc->wi_usb_dev.dv_xname, __func__)); 2000 sc->wi_ctllockwait = 0; 2001 sc->wi_curproc = 0; 2002 wakeup(&sc->wi_ctllock); 2003 } 2004 2005 splx(s); 2006 } 2007