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