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