Bug Summary

File:dev/usb/if_wi_usb.c
Warning:line 1500, column 2
Value stored to 'rid' is never read

Annotated Source Code

Press '?' to see keyboard shortcuts

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