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