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