Bug Summary

File:dev/usb/if_uath.c
Warning:line 1183, column 2
Value stored to 'hdr' is never read

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple amd64-unknown-openbsd7.4 -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name if_uath.c -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 -ffp-contract=on -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 -target-feature +retpoline-external-thunk -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/llvm16/lib/clang/16 -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/legacy-dpm -I /usr/src/sys/dev/pci/drm/amd/pm/swsmu -I /usr/src/sys/dev/pci/drm/amd/pm/swsmu/inc -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/swsmu/smu13 -I /usr/src/sys/dev/pci/drm/amd/pm/powerplay/inc -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/pm/swsmu/inc -I /usr/src/sys/dev/pci/drm/amd/pm/swsmu/inc/pmfw_if -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 SUSPEND -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 -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 -fcf-protection=branch -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 /home/ben/Projects/scan/2024-01-11-110808-61670-1 -x c /usr/src/sys/dev/usb/if_uath.c
1/* $OpenBSD: if_uath.c,v 1.88 2022/04/21 21:03:03 stsp Exp $ */
2
3/*-
4 * Copyright (c) 2006
5 * Damien Bergamini <damien.bergamini@free.fr>
6 *
7 * Permission to use, copy, modify, and distribute this software for any
8 * purpose with or without fee is hereby granted, provided that the above
9 * copyright notice and this permission notice appear in all copies.
10 *
11 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18 */
19
20/*-
21 * Driver for Atheros AR5005UG/AR5005UX chipsets.
22 *
23 * IMPORTANT NOTICE:
24 * This driver was written without any documentation or support from Atheros
25 * Communications. It is based on a black-box analysis of the Windows binary
26 * driver. It handles both pre and post-firmware devices.
27 */
28
29#include "bpfilter.h"
30
31#include <sys/param.h>
32#include <sys/sockio.h>
33#include <sys/mbuf.h>
34#include <sys/kernel.h>
35#include <sys/socket.h>
36#include <sys/systm.h>
37#include <sys/timeout.h>
38#include <sys/conf.h>
39#include <sys/device.h>
40#include <sys/endian.h>
41
42#include <machine/bus.h>
43#include <machine/intr.h>
44
45#if NBPFILTER1 > 0
46#include <net/bpf.h>
47#endif
48#include <net/if.h>
49#include <net/if_dl.h>
50#include <net/if_media.h>
51
52#include <netinet/in.h>
53#include <netinet/if_ether.h>
54
55#include <net80211/ieee80211_var.h>
56#include <net80211/ieee80211_radiotap.h>
57
58#include <dev/usb/usb.h>
59#include <dev/usb/usbdi.h>
60#include <dev/usb/usbdivar.h> /* needs_reattach() */
61#include <dev/usb/usbdi_util.h>
62#include <dev/usb/usbdevs.h>
63
64#include <dev/usb/if_uathreg.h>
65#include <dev/usb/if_uathvar.h>
66
67#ifdef UATH_DEBUG
68#define DPRINTF(x) do { if (uath_debug) printf x; } while (0)
69#define DPRINTFN(n, x) do { if (uath_debug >= (n)) printf x; } while (0)
70int uath_debug = 1;
71#else
72#define DPRINTF(x)
73#define DPRINTFN(n, x)
74#endif
75
76/*-
77 * Various supported device vendors/products.
78 * UB51: AR5005UG 802.11b/g, UB52: AR5005UX 802.11a/b/g
79 */
80#define UATH_DEV(v, p, f){ { USB_VENDOR_v, USB_PRODUCT_v_p }, (f) }, { { USB_VENDOR_v,
USB_PRODUCT_v_p_NF }, (f) | (1 << 0) }
\
81 { { USB_VENDOR_##v, USB_PRODUCT_##v##_##p }, (f) }, \
82 { { USB_VENDOR_##v, USB_PRODUCT_##v##_##p##_NF }, \
83 (f) | UATH_FLAG_PRE_FIRMWARE(1 << 0) }
84#define UATH_DEV_UG(v, p){ { USB_VENDOR_v, USB_PRODUCT_v_p }, (0) }, { { USB_VENDOR_v,
USB_PRODUCT_v_p_NF }, (0) | (1 << 0) }
UATH_DEV(v, p, 0){ { USB_VENDOR_v, USB_PRODUCT_v_p }, (0) }, { { USB_VENDOR_v,
USB_PRODUCT_v_p_NF }, (0) | (1 << 0) }
85#define UATH_DEV_UX(v, p){ { USB_VENDOR_v, USB_PRODUCT_v_p }, ((1 << 1)) }, { { USB_VENDOR_v
, USB_PRODUCT_v_p_NF }, ((1 << 1)) | (1 << 0) }
UATH_DEV(v, p, UATH_FLAG_ABG){ { USB_VENDOR_v, USB_PRODUCT_v_p }, ((1 << 1)) }, { { USB_VENDOR_v
, USB_PRODUCT_v_p_NF }, ((1 << 1)) | (1 << 0) }
86static const struct uath_type {
87 struct usb_devno dev;
88 unsigned int flags;
89#define UATH_FLAG_PRE_FIRMWARE(1 << 0) (1 << 0)
90#define UATH_FLAG_ABG(1 << 1) (1 << 1)
91} uath_devs[] = {
92 UATH_DEV_UG(ACCTON, SMCWUSBTG2){ { 0x083a, 0x4506 }, (0) }, { { 0x083a, 0x4507 }, (0) | (1 <<
0) }
,
93 UATH_DEV_UG(ATHEROS, AR5523){ { 0x168c, 0x0001 }, (0) }, { { 0x168c, 0x0002 }, (0) | (1 <<
0) }
,
94 UATH_DEV_UG(ATHEROS2, AR5523_1){ { 0x0cf3, 0x0001 }, (0) }, { { 0x0cf3, 0x0002 }, (0) | (1 <<
0) }
,
95 UATH_DEV_UG(ATHEROS2, AR5523_2){ { 0x0cf3, 0x0003 }, (0) }, { { 0x0cf3, 0x0004 }, (0) | (1 <<
0) }
,
96 UATH_DEV_UX(ATHEROS2, AR5523_3){ { 0x0cf3, 0x0005 }, ((1 << 1)) }, { { 0x0cf3, 0x0006 }
, ((1 << 1)) | (1 << 0) }
,
97 UATH_DEV_UG(CONCEPTRONIC, AR5523_1){ { 0x0d8e, 0x7801 }, (0) }, { { 0x0d8e, 0x7802 }, (0) | (1 <<
0) }
,
98 UATH_DEV_UX(CONCEPTRONIC, AR5523_2){ { 0x0d8e, 0x7811 }, ((1 << 1)) }, { { 0x0d8e, 0x7812 }
, ((1 << 1)) | (1 << 0) }
,
99 UATH_DEV_UX(DLINK, DWLAG122){ { 0x2001, 0x3a04 }, ((1 << 1)) }, { { 0x2001, 0x3a05 }
, ((1 << 1)) | (1 << 0) }
,
100 UATH_DEV_UX(DLINK, DWLAG132){ { 0x2001, 0x3a00 }, ((1 << 1)) }, { { 0x2001, 0x3a01 }
, ((1 << 1)) | (1 << 0) }
,
101 UATH_DEV_UG(DLINK, DWLG132){ { 0x2001, 0x3a02 }, (0) }, { { 0x2001, 0x3a03 }, (0) | (1 <<
0) }
,
102 UATH_DEV_UG(DLINK2, WUA2340){ { 0x07d1, 0x3a07 }, (0) }, { { 0x07d1, 0x3a08 }, (0) | (1 <<
0) }
,
103 UATH_DEV_UG(GIGASET, AR5523){ { 0x1690, 0x0712 }, (0) }, { { 0x1690, 0x0713 }, (0) | (1 <<
0) }
,
104 UATH_DEV_UG(GIGASET, SMCWUSBTG){ { 0x1690, 0x0710 }, (0) }, { { 0x1690, 0x0711 }, (0) | (1 <<
0) }
,
105 UATH_DEV_UG(GLOBALSUN, AR5523_1){ { 0x16ab, 0x7801 }, (0) }, { { 0x16ab, 0x7802 }, (0) | (1 <<
0) }
,
106 UATH_DEV_UX(GLOBALSUN, AR5523_2){ { 0x16ab, 0x7811 }, ((1 << 1)) }, { { 0x16ab, 0x7812 }
, ((1 << 1)) | (1 << 0) }
,
107 UATH_DEV_UG(IODATA, USBWNG54US){ { 0x04bb, 0x0928 }, (0) }, { { 0x04bb, 0x0929 }, (0) | (1 <<
0) }
,
108 UATH_DEV_UG(MELCO, WLIU2KAMG54){ { 0x0411, 0x0091 }, (0) }, { { 0x0411, 0x0092 }, (0) | (1 <<
0) }
,
109 UATH_DEV_UX(NETGEAR, WG111U){ { 0x0846, 0x4300 }, ((1 << 1)) }, { { 0x0846, 0x4301 }
, ((1 << 1)) | (1 << 0) }
,
110 UATH_DEV_UG(NETGEAR3, WG111T){ { 0x1385, 0x4250 }, (0) }, { { 0x1385, 0x4251 }, (0) | (1 <<
0) }
,
111 UATH_DEV_UG(NETGEAR3, WPN111){ { 0x1385, 0x5f00 }, (0) }, { { 0x1385, 0x5f01 }, (0) | (1 <<
0) }
,
112 UATH_DEV_UG(PHILIPS, SNU6500){ { 0x0471, 0x1232 }, (0) }, { { 0x0471, 0x1233 }, (0) | (1 <<
0) }
,
113 UATH_DEV_UX(UMEDIA, AR5523_2){ { 0x157e, 0x3205 }, ((1 << 1)) }, { { 0x157e, 0x3206 }
, ((1 << 1)) | (1 << 0) }
,
114 UATH_DEV_UG(UMEDIA, TEW444UBEU){ { 0x157e, 0x3006 }, (0) }, { { 0x157e, 0x3007 }, (0) | (1 <<
0) }
,
115 UATH_DEV_UG(WISTRONNEWEB, AR5523_1){ { 0x1435, 0x0826 }, (0) }, { { 0x1435, 0x0827 }, (0) | (1 <<
0) }
,
116 UATH_DEV_UX(WISTRONNEWEB, AR5523_2){ { 0x1435, 0x082a }, ((1 << 1)) }, { { 0x1435, 0x0829 }
, ((1 << 1)) | (1 << 0) }
,
117 UATH_DEV_UG(ZCOM, AR5523){ { 0x0cde, 0x0012 }, (0) }, { { 0x0cde, 0x0013 }, (0) | (1 <<
0) }
,
118
119 /* Devices that share one of the IDs above. */
120 { { USB_VENDOR_NETGEAR30x1385, USB_PRODUCT_NETGEAR3_WG111T_10x4252 }, 0 } \
121};
122#define uath_lookup(v, p)((const struct uath_type *)usbd_match_device((const struct usb_devno
*)(uath_devs), sizeof (uath_devs) / sizeof ((uath_devs)[0]),
sizeof ((uath_devs)[0]), (v), (p)))
\
123 ((const struct uath_type *)usb_lookup(uath_devs, v, p)usbd_match_device((const struct usb_devno *)(uath_devs), sizeof
(uath_devs) / sizeof ((uath_devs)[0]), sizeof ((uath_devs)[0
]), (v), (p))
)
124
125void uath_attachhook(struct device *);
126int uath_open_pipes(struct uath_softc *);
127void uath_close_pipes(struct uath_softc *);
128int uath_alloc_tx_data_list(struct uath_softc *);
129void uath_free_tx_data_list(struct uath_softc *);
130int uath_alloc_rx_data_list(struct uath_softc *);
131void uath_free_rx_data_list(struct uath_softc *);
132int uath_alloc_tx_cmd_list(struct uath_softc *);
133void uath_free_tx_cmd_list(struct uath_softc *);
134int uath_alloc_rx_cmd_list(struct uath_softc *);
135void uath_free_rx_cmd_list(struct uath_softc *);
136int uath_media_change(struct ifnet *);
137void uath_stat(void *);
138void uath_next_scan(void *);
139void uath_task(void *);
140int uath_newstate(struct ieee80211com *, enum ieee80211_state, int);
141#ifdef UATH_DEBUG
142void uath_dump_cmd(const uint8_t *, int, char);
143#endif
144int uath_cmd(struct uath_softc *, uint32_t, const void *, int, void *,
145 int);
146int uath_cmd_write(struct uath_softc *, uint32_t, const void *, int, int);
147int uath_cmd_read(struct uath_softc *, uint32_t, const void *, int, void *,
148 int);
149int uath_write_reg(struct uath_softc *, uint32_t, uint32_t);
150int uath_write_multi(struct uath_softc *, uint32_t, const void *, int);
151int uath_read_reg(struct uath_softc *, uint32_t, uint32_t *);
152int uath_read_eeprom(struct uath_softc *, uint32_t, void *);
153void uath_cmd_rxeof(struct usbd_xfer *, void *, usbd_status);
154void uath_data_rxeof(struct usbd_xfer *, void *, usbd_status);
155void uath_data_txeof(struct usbd_xfer *, void *, usbd_status);
156int uath_tx_null(struct uath_softc *);
157int uath_tx_data(struct uath_softc *, struct mbuf *,
158 struct ieee80211_node *);
159void uath_start(struct ifnet *);
160void uath_watchdog(struct ifnet *);
161int uath_ioctl(struct ifnet *, u_long, caddr_t);
162int uath_query_eeprom(struct uath_softc *);
163int uath_reset(struct uath_softc *);
164int uath_reset_tx_queues(struct uath_softc *);
165int uath_wme_init(struct uath_softc *);
166int uath_set_chan(struct uath_softc *, struct ieee80211_channel *);
167int uath_set_key(struct uath_softc *, const struct ieee80211_key *, int);
168int uath_set_keys(struct uath_softc *);
169int uath_set_rates(struct uath_softc *, const struct ieee80211_rateset *);
170int uath_set_rxfilter(struct uath_softc *, uint32_t, uint32_t);
171int uath_set_led(struct uath_softc *, int, int);
172int uath_switch_channel(struct uath_softc *, struct ieee80211_channel *);
173int uath_init(struct ifnet *);
174void uath_stop(struct ifnet *, int);
175int uath_loadfirmware(struct uath_softc *, const u_char *, int);
176
177int uath_match(struct device *, void *, void *);
178void uath_attach(struct device *, struct device *, void *);
179int uath_detach(struct device *, int);
180
181struct cfdriver uath_cd = {
182 NULL((void *)0), "uath", DV_IFNET
183};
184
185const struct cfattach uath_ca = {
186 sizeof(struct uath_softc), uath_match, uath_attach, uath_detach
187};
188
189int
190uath_match(struct device *parent, void *match, void *aux)
191{
192 struct usb_attach_arg *uaa = aux;
193
194 if (uaa->iface == NULL((void *)0) || uaa->configno != UATH_CONFIG_NO1)
195 return UMATCH_NONE0;
196
197 return (uath_lookup(uaa->vendor, uaa->product)((const struct uath_type *)usbd_match_device((const struct usb_devno
*)(uath_devs), sizeof (uath_devs) / sizeof ((uath_devs)[0]),
sizeof ((uath_devs)[0]), (uaa->vendor), (uaa->product)
))
!= NULL((void *)0)) ?
198 UMATCH_VENDOR_PRODUCT13 : UMATCH_NONE0;
199}
200
201void
202uath_attachhook(struct device *self)
203{
204 struct uath_softc *sc = (struct uath_softc *)self;
205 u_char *fw;
206 size_t size;
207 int error;
208
209 if ((error = loadfirmware("uath-ar5523", &fw, &size)) != 0) {
210 printf("%s: error %d, could not read firmware %s\n",
211 sc->sc_dev.dv_xname, error, "uath-ar5523");
212 return;
213 }
214
215 error = uath_loadfirmware(sc, fw, size);
216 free(fw, M_DEVBUF2, size);
217
218 if (error == 0) {
219 /*
220 * Hack alert: the device doesn't always gracefully detach
221 * from the bus after a firmware upload. We need to force
222 * a port reset and a re-exploration on the parent hub.
223 */
224 usbd_reset_port(sc->sc_uhub, sc->sc_port);
225 usb_needs_reattach(sc->sc_udev);
226 } else {
227 printf("%s: could not load firmware (error=%s)\n",
228 sc->sc_dev.dv_xname, usbd_errstr(error));
229 }
230}
231
232void
233uath_attach(struct device *parent, struct device *self, void *aux)
234{
235 struct uath_softc *sc = (struct uath_softc *)self;
236 struct usb_attach_arg *uaa = aux;
237 struct ieee80211com *ic = &sc->sc_ic;
238 struct ifnet *ifp = &ic->ic_ific_ac.ac_if;
239 usbd_status error;
240 int i;
241
242 sc->sc_udev = uaa->device;
243 sc->sc_uhub = uaa->device->myhub;
244 sc->sc_port = uaa->port;
245
246 sc->sc_flags = uath_lookup(uaa->vendor, uaa->product)((const struct uath_type *)usbd_match_device((const struct usb_devno
*)(uath_devs), sizeof (uath_devs) / sizeof ((uath_devs)[0]),
sizeof ((uath_devs)[0]), (uaa->vendor), (uaa->product)
))
->flags;
247
248 /* get the first interface handle */
249 error = usbd_device2interface_handle(sc->sc_udev, UATH_IFACE_INDEX0,
250 &sc->sc_iface);
251 if (error != 0) {
252 printf("%s: could not get interface handle\n",
253 sc->sc_dev.dv_xname);
254 return;
255 }
256
257 /*
258 * We must open the pipes early because they're used to upload the
259 * firmware (pre-firmware devices) or to send firmware commands.
260 */
261 if (uath_open_pipes(sc) != 0) {
262 printf("%s: could not open pipes\n", sc->sc_dev.dv_xname);
263 return;
264 }
265
266 if (sc->sc_flags & UATH_FLAG_PRE_FIRMWARE(1 << 0)) {
267 config_mountroot(self, uath_attachhook);
268 return;
269 }
270
271 /*
272 * Only post-firmware devices here.
273 */
274 usb_init_task(&sc->sc_task, uath_task, sc, USB_TASK_TYPE_GENERIC)((&sc->sc_task)->fun = (uath_task), (&sc->sc_task
)->arg = (sc), (&sc->sc_task)->type = (0), (&
sc->sc_task)->state = 0x0)
;
275 timeout_set(&sc->scan_to, uath_next_scan, sc);
276 timeout_set(&sc->stat_to, uath_stat, sc);
277
278 /*
279 * Allocate xfers for firmware commands.
280 */
281 if (uath_alloc_tx_cmd_list(sc) != 0) {
282 printf("%s: could not allocate Tx command list\n",
283 sc->sc_dev.dv_xname);
284 goto fail;
285 }
286 if (uath_alloc_rx_cmd_list(sc) != 0) {
287 printf("%s: could not allocate Rx command list\n",
288 sc->sc_dev.dv_xname);
289 goto fail;
290 }
291
292 /*
293 * Queue Rx command xfers.
294 */
295 for (i = 0; i < UATH_RX_CMD_LIST_COUNT1; i++) {
296 struct uath_rx_cmd *cmd = &sc->rx_cmd[i];
297
298 usbd_setup_xfer(cmd->xfer, sc->cmd_rx_pipe, cmd, cmd->buf,
299 UATH_MAX_RXCMDSZ512, USBD_SHORT_XFER_OK0x04 | USBD_NO_COPY0x01,
300 USBD_NO_TIMEOUT0, uath_cmd_rxeof);
301 error = usbd_transfer(cmd->xfer);
302 if (error != USBD_IN_PROGRESS && error != 0) {
303 printf("%s: could not queue Rx command xfer\n",
304 sc->sc_dev.dv_xname);
305 goto fail;
306 }
307 }
308
309 /*
310 * We're now ready to send/receive firmware commands.
311 */
312 if (uath_reset(sc) != 0) {
313 printf("%s: could not initialize adapter\n",
314 sc->sc_dev.dv_xname);
315 goto fail;
316 }
317 if (uath_query_eeprom(sc) != 0) {
318 printf("%s: could not read EEPROM\n", sc->sc_dev.dv_xname);
319 goto fail;
320 }
321
322 printf("%s: MAC/BBP AR5523, RF AR%c112, address %s\n",
323 sc->sc_dev.dv_xname, (sc->sc_flags & UATH_FLAG_ABG(1 << 1)) ? '5': '2',
324 ether_sprintf(ic->ic_myaddr));
325
326 /*
327 * Allocate xfers for Tx/Rx data pipes.
328 */
329 if (uath_alloc_tx_data_list(sc) != 0) {
330 printf("%s: could not allocate Tx data list\n",
331 sc->sc_dev.dv_xname);
332 goto fail;
333 }
334 if (uath_alloc_rx_data_list(sc) != 0) {
335 printf("%s: could not allocate Rx data list\n",
336 sc->sc_dev.dv_xname);
337 goto fail;
338 }
339
340 ic->ic_phytype = IEEE80211_T_OFDM; /* not only, but not used */
341 ic->ic_opmode = IEEE80211_M_STA; /* default to BSS mode */
342 ic->ic_state = IEEE80211_S_INIT;
343
344 /* set device capabilities */
345 ic->ic_caps =
346 IEEE80211_C_MONITOR0x00000200 | /* monitor mode supported */
347 IEEE80211_C_TXPMGT0x00000040 | /* tx power management */
348 IEEE80211_C_SHPREAMBLE0x00000100 | /* short preamble supported */
349 IEEE80211_C_SHSLOT0x00000080 | /* short slot time supported */
350 IEEE80211_C_WEP0x00000001; /* h/w WEP */
351
352 /* set supported .11b and .11g rates */
353 ic->ic_sup_rates[IEEE80211_MODE_11B] = ieee80211_std_rateset_11b;
354 ic->ic_sup_rates[IEEE80211_MODE_11G] = ieee80211_std_rateset_11g;
355
356 /* set supported .11b and .11g channels (1 through 14) */
357 for (i = 1; i <= 14; i++) {
358 ic->ic_channels[i].ic_freq =
359 ieee80211_ieee2mhz(i, IEEE80211_CHAN_2GHZ0x0080);
360 ic->ic_channels[i].ic_flags =
361 IEEE80211_CHAN_CCK0x0020 | IEEE80211_CHAN_OFDM0x0040 |
362 IEEE80211_CHAN_DYN0x0400 | IEEE80211_CHAN_2GHZ0x0080;
363 }
364
365 ifp->if_softc = sc;
366 ifp->if_flags = IFF_BROADCAST0x2 | IFF_SIMPLEX0x800 | IFF_MULTICAST0x8000;
367 ifp->if_ioctl = uath_ioctl;
368 ifp->if_start = uath_start;
369 ifp->if_watchdog = uath_watchdog;
370 memcpy(ifp->if_xname, sc->sc_dev.dv_xname, IFNAMSIZ)__builtin_memcpy((ifp->if_xname), (sc->sc_dev.dv_xname)
, (16))
;
371
372 if_attach(ifp);
373 ieee80211_ifattach(ifp);
374
375 /* override state transition machine */
376 sc->sc_newstate = ic->ic_newstate;
377 ic->ic_newstate = uath_newstate;
378 ieee80211_media_init(ifp, uath_media_change, ieee80211_media_status);
379
380#if NBPFILTER1 > 0
381 bpfattach(&sc->sc_drvbpf, ifp, DLT_IEEE802_11_RADIO127,
382 sizeof (struct ieee80211_frame) + IEEE80211_RADIOTAP_HDRLEN64);
383
384 sc->sc_rxtap_len = sizeof sc->sc_rxtapu;
385 sc->sc_rxtapsc_rxtapu.th.wr_ihdr.it_len = htole16(sc->sc_rxtap_len)((__uint16_t)(sc->sc_rxtap_len));
386 sc->sc_rxtapsc_rxtapu.th.wr_ihdr.it_present = htole32(UATH_RX_RADIOTAP_PRESENT)((__uint32_t)(((1 << IEEE80211_RADIOTAP_FLAGS) | (1 <<
IEEE80211_RADIOTAP_CHANNEL) | (1 << IEEE80211_RADIOTAP_DBM_ANTSIGNAL
))))
;
387
388 sc->sc_txtap_len = sizeof sc->sc_txtapu;
389 sc->sc_txtapsc_txtapu.th.wt_ihdr.it_len = htole16(sc->sc_txtap_len)((__uint16_t)(sc->sc_txtap_len));
390 sc->sc_txtapsc_txtapu.th.wt_ihdr.it_present = htole32(UATH_TX_RADIOTAP_PRESENT)((__uint32_t)(((1 << IEEE80211_RADIOTAP_FLAGS) | (1 <<
IEEE80211_RADIOTAP_CHANNEL))))
;
391#endif
392
393 return;
394
395fail: uath_close_pipes(sc);
396 uath_free_tx_data_list(sc);
397 uath_free_rx_cmd_list(sc);
398 uath_free_tx_cmd_list(sc);
399 usbd_deactivate(sc->sc_udev);
400}
401
402int
403uath_detach(struct device *self, int flags)
404{
405 struct uath_softc *sc = (struct uath_softc *)self;
406 struct ifnet *ifp = &sc->sc_ic.ic_ific_ac.ac_if;
407 int s;
408
409 s = splnet()splraise(0x4);
410
411 if (sc->sc_flags & UATH_FLAG_PRE_FIRMWARE(1 << 0)) {
412 uath_close_pipes(sc);
413 splx(s)spllower(s);
414 return 0;
415 }
416
417 /* post-firmware device */
418
419 usb_rem_task(sc->sc_udev, &sc->sc_task);
420 if (timeout_initialized(&sc->scan_to)((&sc->scan_to)->to_flags & 0x04))
421 timeout_del(&sc->scan_to);
422 if (timeout_initialized(&sc->stat_to)((&sc->stat_to)->to_flags & 0x04))
423 timeout_del(&sc->stat_to);
424
425 /* close Tx/Rx pipes */
426 uath_close_pipes(sc);
427
428 /* free xfers */
429 uath_free_tx_data_list(sc);
430 uath_free_rx_data_list(sc);
431 uath_free_tx_cmd_list(sc);
432 uath_free_rx_cmd_list(sc);
433
434 if (ifp->if_softc != NULL((void *)0)) {
435 ieee80211_ifdetach(ifp); /* free all nodes */
436 if_detach(ifp);
437 }
438
439 splx(s)spllower(s);
440
441 return 0;
442}
443
444int
445uath_open_pipes(struct uath_softc *sc)
446{
447 int error;
448
449 /*
450 * XXX pipes numbers are hardcoded because we don't have any way
451 * to distinguish the data pipes from the firmware command pipes
452 * (both are bulk pipes) using the endpoints descriptors.
453 */
454 error = usbd_open_pipe(sc->sc_iface, 0x01, USBD_EXCLUSIVE_USE0x01,
455 &sc->cmd_tx_pipe);
456 if (error != 0) {
457 printf("%s: could not open Tx command pipe: %s\n",
458 sc->sc_dev.dv_xname, usbd_errstr(error));
459 goto fail;
460 }
461
462 error = usbd_open_pipe(sc->sc_iface, 0x02, USBD_EXCLUSIVE_USE0x01,
463 &sc->data_tx_pipe);
464 if (error != 0) {
465 printf("%s: could not open Tx data pipe: %s\n",
466 sc->sc_dev.dv_xname, usbd_errstr(error));
467 goto fail;
468 }
469
470 error = usbd_open_pipe(sc->sc_iface, 0x81, USBD_EXCLUSIVE_USE0x01,
471 &sc->cmd_rx_pipe);
472 if (error != 0) {
473 printf("%s: could not open Rx command pipe: %s\n",
474 sc->sc_dev.dv_xname, usbd_errstr(error));
475 goto fail;
476 }
477
478 error = usbd_open_pipe(sc->sc_iface, 0x82, USBD_EXCLUSIVE_USE0x01,
479 &sc->data_rx_pipe);
480 if (error != 0) {
481 printf("%s: could not open Rx data pipe: %s\n",
482 sc->sc_dev.dv_xname, usbd_errstr(error));
483 goto fail;
484 }
485
486 return 0;
487
488fail: uath_close_pipes(sc);
489 return error;
490}
491
492void
493uath_close_pipes(struct uath_softc *sc)
494{
495 if (sc->data_tx_pipe != NULL((void *)0)) {
496 usbd_close_pipe(sc->data_tx_pipe);
497 sc->data_tx_pipe = NULL((void *)0);
498 }
499
500 if (sc->data_rx_pipe != NULL((void *)0)) {
501 usbd_close_pipe(sc->data_rx_pipe);
502 sc->data_rx_pipe = NULL((void *)0);
503 }
504
505 if (sc->cmd_tx_pipe != NULL((void *)0)) {
506 usbd_close_pipe(sc->cmd_tx_pipe);
507 sc->cmd_tx_pipe = NULL((void *)0);
508 }
509
510 if (sc->cmd_rx_pipe != NULL((void *)0)) {
511 usbd_close_pipe(sc->cmd_rx_pipe);
512 sc->cmd_rx_pipe = NULL((void *)0);
513 }
514}
515
516int
517uath_alloc_tx_data_list(struct uath_softc *sc)
518{
519 int i, error;
520
521 for (i = 0; i < UATH_TX_DATA_LIST_COUNT8; i++) {
522 struct uath_tx_data *data = &sc->tx_data[i];
523
524 data->sc = sc; /* backpointer for callbacks */
525
526 data->xfer = usbd_alloc_xfer(sc->sc_udev);
527 if (data->xfer == NULL((void *)0)) {
528 printf("%s: could not allocate xfer\n",
529 sc->sc_dev.dv_xname);
530 error = ENOMEM12;
531 goto fail;
532 }
533 data->buf = usbd_alloc_buffer(data->xfer, UATH_MAX_TXBUFSZ(sizeof (uint32_t) + sizeof (struct uath_tx_desc) + (2300 + 4
+ (3 + 1 + 4)))
);
534 if (data->buf == NULL((void *)0)) {
535 printf("%s: could not allocate xfer buffer\n",
536 sc->sc_dev.dv_xname);
537 error = ENOMEM12;
538 goto fail;
539 }
540 }
541 return 0;
542
543fail: uath_free_tx_data_list(sc);
544 return error;
545}
546
547void
548uath_free_tx_data_list(struct uath_softc *sc)
549{
550 int i;
551
552 for (i = 0; i < UATH_TX_DATA_LIST_COUNT8; i++)
553 if (sc->tx_data[i].xfer != NULL((void *)0)) {
554 usbd_free_xfer(sc->tx_data[i].xfer);
555 sc->tx_data[i].xfer = NULL((void *)0);
556 }
557}
558
559int
560uath_alloc_rx_data_list(struct uath_softc *sc)
561{
562 int i, error;
563
564 for (i = 0; i < UATH_RX_DATA_LIST_COUNT1; i++) {
565 struct uath_rx_data *data = &sc->rx_data[i];
566
567 data->sc = sc; /* backpointer for callbacks */
568
569 data->xfer = usbd_alloc_xfer(sc->sc_udev);
570 if (data->xfer == NULL((void *)0)) {
571 printf("%s: could not allocate xfer\n",
572 sc->sc_dev.dv_xname);
573 error = ENOMEM12;
574 goto fail;
575 }
576 if (usbd_alloc_buffer(data->xfer, sc->rxbufsz) == NULL((void *)0)) {
577 printf("%s: could not allocate xfer buffer\n",
578 sc->sc_dev.dv_xname);
579 error = ENOMEM12;
580 goto fail;
581 }
582
583 MGETHDR(data->m, M_DONTWAIT, MT_DATA)data->m = m_gethdr((0x0002), (1));
584 if (data->m == NULL((void *)0)) {
585 printf("%s: could not allocate rx mbuf\n",
586 sc->sc_dev.dv_xname);
587 error = ENOMEM12;
588 goto fail;
589 }
590 MCLGETL(data->m, M_DONTWAIT, sc->rxbufsz)m_clget((data->m), (0x0002), (sc->rxbufsz));
591 if (!(data->m->m_flagsm_hdr.mh_flags & M_EXT0x0001)) {
592 printf("%s: could not allocate rx mbuf cluster\n",
593 sc->sc_dev.dv_xname);
594 error = ENOMEM12;
595 goto fail;
596 }
597
598 data->buf = mtod(data->m, uint8_t *)((uint8_t *)((data->m)->m_hdr.mh_data));
599 }
600 return 0;
601
602fail: uath_free_rx_data_list(sc);
603 return error;
604}
605
606void
607uath_free_rx_data_list(struct uath_softc *sc)
608{
609 int i;
610
611 for (i = 0; i < UATH_RX_DATA_LIST_COUNT1; i++) {
612 struct uath_rx_data *data = &sc->rx_data[i];
613
614 if (data->xfer != NULL((void *)0)) {
615 usbd_free_xfer(data->xfer);
616 data->xfer = NULL((void *)0);
617 }
618
619 if (data->m != NULL((void *)0)) {
620 m_freem(data->m);
621 data->m = NULL((void *)0);
622 }
623 }
624}
625
626int
627uath_alloc_tx_cmd_list(struct uath_softc *sc)
628{
629 int i, error;
630
631 for (i = 0; i < UATH_TX_CMD_LIST_COUNT8; i++) {
632 struct uath_tx_cmd *cmd = &sc->tx_cmd[i];
633
634 cmd->sc = sc; /* backpointer for callbacks */
635
636 cmd->xfer = usbd_alloc_xfer(sc->sc_udev);
637 if (cmd->xfer == NULL((void *)0)) {
638 printf("%s: could not allocate xfer\n",
639 sc->sc_dev.dv_xname);
640 error = ENOMEM12;
641 goto fail;
642 }
643 cmd->buf = usbd_alloc_buffer(cmd->xfer, UATH_MAX_TXCMDSZ512);
644 if (cmd->buf == NULL((void *)0)) {
645 printf("%s: could not allocate xfer buffer\n",
646 sc->sc_dev.dv_xname);
647 error = ENOMEM12;
648 goto fail;
649 }
650 }
651 return 0;
652
653fail: uath_free_tx_cmd_list(sc);
654 return error;
655}
656
657void
658uath_free_tx_cmd_list(struct uath_softc *sc)
659{
660 int i;
661
662 for (i = 0; i < UATH_TX_CMD_LIST_COUNT8; i++)
663 if (sc->tx_cmd[i].xfer != NULL((void *)0)) {
664 usbd_free_xfer(sc->tx_cmd[i].xfer);
665 sc->tx_cmd[i].xfer = NULL((void *)0);
666 }
667}
668
669int
670uath_alloc_rx_cmd_list(struct uath_softc *sc)
671{
672 int i, error;
673
674 for (i = 0; i < UATH_RX_CMD_LIST_COUNT1; i++) {
675 struct uath_rx_cmd *cmd = &sc->rx_cmd[i];
676
677 cmd->sc = sc; /* backpointer for callbacks */
678
679 cmd->xfer = usbd_alloc_xfer(sc->sc_udev);
680 if (cmd->xfer == NULL((void *)0)) {
681 printf("%s: could not allocate xfer\n",
682 sc->sc_dev.dv_xname);
683 error = ENOMEM12;
684 goto fail;
685 }
686 cmd->buf = usbd_alloc_buffer(cmd->xfer, UATH_MAX_RXCMDSZ512);
687 if (cmd->buf == NULL((void *)0)) {
688 printf("%s: could not allocate xfer buffer\n",
689 sc->sc_dev.dv_xname);
690 error = ENOMEM12;
691 goto fail;
692 }
693 }
694 return 0;
695
696fail: uath_free_rx_cmd_list(sc);
697 return error;
698}
699
700void
701uath_free_rx_cmd_list(struct uath_softc *sc)
702{
703 int i;
704
705 for (i = 0; i < UATH_RX_CMD_LIST_COUNT1; i++)
706 if (sc->rx_cmd[i].xfer != NULL((void *)0)) {
707 usbd_free_xfer(sc->rx_cmd[i].xfer);
708 sc->rx_cmd[i].xfer = NULL((void *)0);
709 }
710}
711
712int
713uath_media_change(struct ifnet *ifp)
714{
715 int error;
716
717 error = ieee80211_media_change(ifp);
718 if (error != ENETRESET52)
719 return error;
720
721 if ((ifp->if_flags & (IFF_UP0x1 | IFF_RUNNING0x40)) == (IFF_UP0x1 | IFF_RUNNING0x40))
722 error = uath_init(ifp);
723
724 return error;
725}
726
727/*
728 * This function is called periodically (every second) when associated to
729 * query device statistics.
730 */
731void
732uath_stat(void *arg)
733{
734 struct uath_softc *sc = arg;
735 int error;
736
737 /*
738 * Send request for statistics asynchronously. The timer will be
739 * restarted when we'll get the stats notification.
740 */
741 error = uath_cmd_write(sc, UATH_CMD_STATS0x06, NULL((void *)0), 0,
742 UATH_CMD_FLAG_ASYNC(1 << 0));
743 if (error != 0) {
744 printf("%s: could not query statistics (error=%d)\n",
745 sc->sc_dev.dv_xname, error);
746 }
747}
748
749/*
750 * This function is called periodically (every 250ms) during scanning to
751 * switch from one channel to another.
752 */
753void
754uath_next_scan(void *arg)
755{
756 struct uath_softc *sc = arg;
757 struct ieee80211com *ic = &sc->sc_ic;
758 struct ifnet *ifp = &ic->ic_ific_ac.ac_if;
759
760 if (ic->ic_state == IEEE80211_S_SCAN)
761 ieee80211_next_scan(ifp);
762}
763
764void
765uath_task(void *arg)
766{
767 struct uath_softc *sc = arg;
768 struct ieee80211com *ic = &sc->sc_ic;
769 enum ieee80211_state ostate;
770
771 ostate = ic->ic_state;
772
773 switch (sc->sc_state) {
774 case IEEE80211_S_INIT:
775 if (ostate == IEEE80211_S_RUN) {
776 /* turn link and activity LEDs off */
777 (void)uath_set_led(sc, UATH_LED_LINK0, 0);
778 (void)uath_set_led(sc, UATH_LED_ACTIVITY1, 0);
779 }
780 break;
781
782 case IEEE80211_S_SCAN:
783 if (uath_switch_channel(sc, ic->ic_bss->ni_chan) != 0) {
784 printf("%s: could not switch channel\n",
785 sc->sc_dev.dv_xname);
786 break;
787 }
788 timeout_add_msec(&sc->scan_to, 250);
789 break;
790
791 case IEEE80211_S_AUTH:
792 {
793 struct ieee80211_node *ni = ic->ic_bss;
794 struct uath_cmd_bssid bssid;
795 struct uath_cmd_0b cmd0b;
796 struct uath_cmd_0c cmd0c;
797
798 if (uath_switch_channel(sc, ni->ni_chan) != 0) {
799 printf("%s: could not switch channel\n",
800 sc->sc_dev.dv_xname);
801 break;
802 }
803
804 (void)uath_cmd_write(sc, UATH_CMD_240x24, NULL((void *)0), 0, 0);
805
806 bzero(&bssid, sizeof bssid)__builtin_bzero((&bssid), (sizeof bssid));
807 bssid.len = htobe32(IEEE80211_ADDR_LEN)(__uint32_t)(__builtin_constant_p(6) ? (__uint32_t)(((__uint32_t
)(6) & 0xff) << 24 | ((__uint32_t)(6) & 0xff00)
<< 8 | ((__uint32_t)(6) & 0xff0000) >> 8 | (
(__uint32_t)(6) & 0xff000000) >> 24) : __swap32md(6
))
;
808 IEEE80211_ADDR_COPY(bssid.bssid, ni->ni_bssid)__builtin_memcpy((bssid.bssid), (ni->ni_bssid), (6));
809 (void)uath_cmd_write(sc, UATH_CMD_SET_BSSID0x21, &bssid,
810 sizeof bssid, 0);
811
812 bzero(&cmd0b, sizeof cmd0b)__builtin_bzero((&cmd0b), (sizeof cmd0b));
813 cmd0b.code = htobe32(2)(__uint32_t)(__builtin_constant_p(2) ? (__uint32_t)(((__uint32_t
)(2) & 0xff) << 24 | ((__uint32_t)(2) & 0xff00)
<< 8 | ((__uint32_t)(2) & 0xff0000) >> 8 | (
(__uint32_t)(2) & 0xff000000) >> 24) : __swap32md(2
))
;
814 cmd0b.size = htobe32(sizeof (cmd0b.data))(__uint32_t)(__builtin_constant_p(sizeof (cmd0b.data)) ? (__uint32_t
)(((__uint32_t)(sizeof (cmd0b.data)) & 0xff) << 24 |
((__uint32_t)(sizeof (cmd0b.data)) & 0xff00) << 8 |
((__uint32_t)(sizeof (cmd0b.data)) & 0xff0000) >> 8
| ((__uint32_t)(sizeof (cmd0b.data)) & 0xff000000) >>
24) : __swap32md(sizeof (cmd0b.data)))
;
815 (void)uath_cmd_write(sc, UATH_CMD_0B0x0b, &cmd0b, sizeof cmd0b, 0);
816
817 bzero(&cmd0c, sizeof cmd0c)__builtin_bzero((&cmd0c), (sizeof cmd0c));
818 cmd0c.magic1 = htobe32(2)(__uint32_t)(__builtin_constant_p(2) ? (__uint32_t)(((__uint32_t
)(2) & 0xff) << 24 | ((__uint32_t)(2) & 0xff00)
<< 8 | ((__uint32_t)(2) & 0xff0000) >> 8 | (
(__uint32_t)(2) & 0xff000000) >> 24) : __swap32md(2
))
;
819 cmd0c.magic2 = htobe32(7)(__uint32_t)(__builtin_constant_p(7) ? (__uint32_t)(((__uint32_t
)(7) & 0xff) << 24 | ((__uint32_t)(7) & 0xff00)
<< 8 | ((__uint32_t)(7) & 0xff0000) >> 8 | (
(__uint32_t)(7) & 0xff000000) >> 24) : __swap32md(7
))
;
820 cmd0c.magic3 = htobe32(1)(__uint32_t)(__builtin_constant_p(1) ? (__uint32_t)(((__uint32_t
)(1) & 0xff) << 24 | ((__uint32_t)(1) & 0xff00)
<< 8 | ((__uint32_t)(1) & 0xff0000) >> 8 | (
(__uint32_t)(1) & 0xff000000) >> 24) : __swap32md(1
))
;
821 (void)uath_cmd_write(sc, UATH_CMD_0C0x0c, &cmd0c, sizeof cmd0c, 0);
822
823 if (uath_set_rates(sc, &ni->ni_rates) != 0) {
824 printf("%s: could not set negotiated rate set\n",
825 sc->sc_dev.dv_xname);
826 break;
827 }
828 break;
829 }
830
831 case IEEE80211_S_ASSOC:
832 break;
833
834 case IEEE80211_S_RUN:
835 {
836 struct ieee80211_node *ni = ic->ic_bss;
837 struct uath_cmd_bssid bssid;
838 struct uath_cmd_xled xled;
839 uint32_t val;
840
841 if (ic->ic_opmode == IEEE80211_M_MONITOR) {
842 /* make both LEDs blink while monitoring */
843 bzero(&xled, sizeof xled)__builtin_bzero((&xled), (sizeof xled));
844 xled.which = htobe32(0)(__uint32_t)(__builtin_constant_p(0) ? (__uint32_t)(((__uint32_t
)(0) & 0xff) << 24 | ((__uint32_t)(0) & 0xff00)
<< 8 | ((__uint32_t)(0) & 0xff0000) >> 8 | (
(__uint32_t)(0) & 0xff000000) >> 24) : __swap32md(0
))
;
845 xled.rate = htobe32(1)(__uint32_t)(__builtin_constant_p(1) ? (__uint32_t)(((__uint32_t
)(1) & 0xff) << 24 | ((__uint32_t)(1) & 0xff00)
<< 8 | ((__uint32_t)(1) & 0xff0000) >> 8 | (
(__uint32_t)(1) & 0xff000000) >> 24) : __swap32md(1
))
;
846 xled.mode = htobe32(2)(__uint32_t)(__builtin_constant_p(2) ? (__uint32_t)(((__uint32_t
)(2) & 0xff) << 24 | ((__uint32_t)(2) & 0xff00)
<< 8 | ((__uint32_t)(2) & 0xff0000) >> 8 | (
(__uint32_t)(2) & 0xff000000) >> 24) : __swap32md(2
))
;
847 (void)uath_cmd_write(sc, UATH_CMD_SET_XLED0x18, &xled,
848 sizeof xled, 0);
849 break;
850 }
851
852 /*
853 * Tx rate is controlled by firmware, report the maximum
854 * negotiated rate in ifconfig output.
855 */
856 ni->ni_txrate = ni->ni_rates.rs_nrates - 1;
857
858 val = htobe32(1)(__uint32_t)(__builtin_constant_p(1) ? (__uint32_t)(((__uint32_t
)(1) & 0xff) << 24 | ((__uint32_t)(1) & 0xff00)
<< 8 | ((__uint32_t)(1) & 0xff0000) >> 8 | (
(__uint32_t)(1) & 0xff000000) >> 24) : __swap32md(1
))
;
859 (void)uath_cmd_write(sc, UATH_CMD_2E0x2e, &val, sizeof val, 0);
860
861 bzero(&bssid, sizeof bssid)__builtin_bzero((&bssid), (sizeof bssid));
862 bssid.flags1 = htobe32(0xc004)(__uint32_t)(__builtin_constant_p(0xc004) ? (__uint32_t)(((__uint32_t
)(0xc004) & 0xff) << 24 | ((__uint32_t)(0xc004) &
0xff00) << 8 | ((__uint32_t)(0xc004) & 0xff0000) >>
8 | ((__uint32_t)(0xc004) & 0xff000000) >> 24) : __swap32md
(0xc004))
;
863 bssid.flags2 = htobe32(0x003b)(__uint32_t)(__builtin_constant_p(0x003b) ? (__uint32_t)(((__uint32_t
)(0x003b) & 0xff) << 24 | ((__uint32_t)(0x003b) &
0xff00) << 8 | ((__uint32_t)(0x003b) & 0xff0000) >>
8 | ((__uint32_t)(0x003b) & 0xff000000) >> 24) : __swap32md
(0x003b))
;
864 bssid.len = htobe32(IEEE80211_ADDR_LEN)(__uint32_t)(__builtin_constant_p(6) ? (__uint32_t)(((__uint32_t
)(6) & 0xff) << 24 | ((__uint32_t)(6) & 0xff00)
<< 8 | ((__uint32_t)(6) & 0xff0000) >> 8 | (
(__uint32_t)(6) & 0xff000000) >> 24) : __swap32md(6
))
;
865 IEEE80211_ADDR_COPY(bssid.bssid, ni->ni_bssid)__builtin_memcpy((bssid.bssid), (ni->ni_bssid), (6));
866 (void)uath_cmd_write(sc, UATH_CMD_SET_BSSID0x21, &bssid,
867 sizeof bssid, 0);
868
869 /* turn link LED on */
870 (void)uath_set_led(sc, UATH_LED_LINK0, 1);
871
872 /* make activity LED blink */
873 bzero(&xled, sizeof xled)__builtin_bzero((&xled), (sizeof xled));
874 xled.which = htobe32(1)(__uint32_t)(__builtin_constant_p(1) ? (__uint32_t)(((__uint32_t
)(1) & 0xff) << 24 | ((__uint32_t)(1) & 0xff00)
<< 8 | ((__uint32_t)(1) & 0xff0000) >> 8 | (
(__uint32_t)(1) & 0xff000000) >> 24) : __swap32md(1
))
;
875 xled.rate = htobe32(1)(__uint32_t)(__builtin_constant_p(1) ? (__uint32_t)(((__uint32_t
)(1) & 0xff) << 24 | ((__uint32_t)(1) & 0xff00)
<< 8 | ((__uint32_t)(1) & 0xff0000) >> 8 | (
(__uint32_t)(1) & 0xff000000) >> 24) : __swap32md(1
))
;
876 xled.mode = htobe32(2)(__uint32_t)(__builtin_constant_p(2) ? (__uint32_t)(((__uint32_t
)(2) & 0xff) << 24 | ((__uint32_t)(2) & 0xff00)
<< 8 | ((__uint32_t)(2) & 0xff0000) >> 8 | (
(__uint32_t)(2) & 0xff000000) >> 24) : __swap32md(2
))
;
877 (void)uath_cmd_write(sc, UATH_CMD_SET_XLED0x18, &xled, sizeof xled,
878 0);
879
880 /* set state to associated */
881 val = htobe32(1)(__uint32_t)(__builtin_constant_p(1) ? (__uint32_t)(((__uint32_t
)(1) & 0xff) << 24 | ((__uint32_t)(1) & 0xff00)
<< 8 | ((__uint32_t)(1) & 0xff0000) >> 8 | (
(__uint32_t)(1) & 0xff000000) >> 24) : __swap32md(1
))
;
882 (void)uath_cmd_write(sc, UATH_CMD_SET_STATE0x20, &val, sizeof val,
883 0);
884
885 /* start statistics timer */
886 timeout_add_sec(&sc->stat_to, 1);
887 break;
888 }
889 }
890 sc->sc_newstate(ic, sc->sc_state, sc->sc_arg);
891}
892
893int
894uath_newstate(struct ieee80211com *ic, enum ieee80211_state nstate, int arg)
895{
896 struct uath_softc *sc = ic->ic_softcic_ac.ac_if.if_softc;
897
898 usb_rem_task(sc->sc_udev, &sc->sc_task);
899 timeout_del(&sc->scan_to);
900 timeout_del(&sc->stat_to);
901
902 /* do it in a process context */
903 sc->sc_state = nstate;
904 sc->sc_arg = arg;
905 usb_add_task(sc->sc_udev, &sc->sc_task);
906 return 0;
907}
908
909#ifdef UATH_DEBUG
910void
911uath_dump_cmd(const uint8_t *buf, int len, char prefix)
912{
913 int i;
914
915 for (i = 0; i < len; i++) {
916 if ((i % 16) == 0)
917 printf("\n%c ", prefix);
918 else if ((i % 4) == 0)
919 printf(" ");
920 printf("%02x", buf[i]);
921 }
922 printf("\n");
923}
924#endif
925
926/*
927 * Low-level function to send read or write commands to the firmware.
928 */
929int
930uath_cmd(struct uath_softc *sc, uint32_t code, const void *idata, int ilen,
931 void *odata, int flags)
932{
933 struct uath_cmd_hdr *hdr;
934 struct uath_tx_cmd *cmd;
935 uint16_t xferflags;
936 int s, xferlen, error;
937
938 /* grab a xfer */
939 cmd = &sc->tx_cmd[sc->cmd_idx];
940
941 /* always bulk-out a multiple of 4 bytes */
942 xferlen = (sizeof (struct uath_cmd_hdr) + ilen + 3) & ~3;
943
944 hdr = (struct uath_cmd_hdr *)cmd->buf;
945 bzero(hdr, sizeof (struct uath_cmd_hdr))__builtin_bzero((hdr), (sizeof (struct uath_cmd_hdr)));
946 hdr->len = htobe32(xferlen)(__uint32_t)(__builtin_constant_p(xferlen) ? (__uint32_t)(((__uint32_t
)(xferlen) & 0xff) << 24 | ((__uint32_t)(xferlen) &
0xff00) << 8 | ((__uint32_t)(xferlen) & 0xff0000) >>
8 | ((__uint32_t)(xferlen) & 0xff000000) >> 24) : __swap32md
(xferlen))
;
947 hdr->code = htobe32(code)(__uint32_t)(__builtin_constant_p(code) ? (__uint32_t)(((__uint32_t
)(code) & 0xff) << 24 | ((__uint32_t)(code) & 0xff00
) << 8 | ((__uint32_t)(code) & 0xff0000) >> 8
| ((__uint32_t)(code) & 0xff000000) >> 24) : __swap32md
(code))
;
948 hdr->priv = sc->cmd_idx; /* don't care about endianness */
949 hdr->magic = htobe32((flags & UATH_CMD_FLAG_MAGIC) ? 1 << 24 : 0)(__uint32_t)(__builtin_constant_p((flags & (1 << 2)
) ? 1 << 24 : 0) ? (__uint32_t)(((__uint32_t)((flags &
(1 << 2)) ? 1 << 24 : 0) & 0xff) << 24
| ((__uint32_t)((flags & (1 << 2)) ? 1 << 24
: 0) & 0xff00) << 8 | ((__uint32_t)((flags & (
1 << 2)) ? 1 << 24 : 0) & 0xff0000) >> 8
| ((__uint32_t)((flags & (1 << 2)) ? 1 << 24
: 0) & 0xff000000) >> 24) : __swap32md((flags &
(1 << 2)) ? 1 << 24 : 0))
;
950 bcopy(idata, (uint8_t *)(hdr + 1), ilen);
951
952#ifdef UATH_DEBUG
953 if (uath_debug >= 5) {
954 printf("sending command code=0x%02x flags=0x%x index=%u",
955 code, flags, sc->cmd_idx);
956 uath_dump_cmd(cmd->buf, xferlen, '+');
957 }
958#endif
959 xferflags = USBD_FORCE_SHORT_XFER0x08 | USBD_NO_COPY0x01;
960 if (!(flags & UATH_CMD_FLAG_READ(1 << 1))) {
961 if (!(flags & UATH_CMD_FLAG_ASYNC(1 << 0)))
962 xferflags |= USBD_SYNCHRONOUS0x02;
963 } else
964 s = splusb()splraise(0x2);
965
966 cmd->odata = odata;
967
968 usbd_setup_xfer(cmd->xfer, sc->cmd_tx_pipe, cmd, cmd->buf, xferlen,
969 xferflags, UATH_CMD_TIMEOUT1000, NULL((void *)0));
970 error = usbd_transfer(cmd->xfer);
971 if (error != USBD_IN_PROGRESS && error != 0) {
972 if (flags & UATH_CMD_FLAG_READ(1 << 1))
973 splx(s)spllower(s);
974 printf("%s: could not send command 0x%x (error=%s)\n",
975 sc->sc_dev.dv_xname, code, usbd_errstr(error));
976 return error;
977 }
978 sc->cmd_idx = (sc->cmd_idx + 1) % UATH_TX_CMD_LIST_COUNT8;
979
980 if (!(flags & UATH_CMD_FLAG_READ(1 << 1)))
981 return 0; /* write: don't wait for reply */
982
983 /* wait at most two seconds for command reply */
984 error = tsleep_nsec(cmd, PCATCH0x100, "uathcmd", SEC_TO_NSEC(2));
985 cmd->odata = NULL((void *)0); /* in case answer is received too late */
986 splx(s)spllower(s);
987 if (error != 0) {
988 printf("%s: timeout waiting for command reply\n",
989 sc->sc_dev.dv_xname);
990 }
991 return error;
992}
993
994int
995uath_cmd_write(struct uath_softc *sc, uint32_t code, const void *data, int len,
996 int flags)
997{
998 flags &= ~UATH_CMD_FLAG_READ(1 << 1);
999 return uath_cmd(sc, code, data, len, NULL((void *)0), flags);
1000}
1001
1002int
1003uath_cmd_read(struct uath_softc *sc, uint32_t code, const void *idata,
1004 int ilen, void *odata, int flags)
1005{
1006 flags |= UATH_CMD_FLAG_READ(1 << 1);
1007 return uath_cmd(sc, code, idata, ilen, odata, flags);
1008}
1009
1010int
1011uath_write_reg(struct uath_softc *sc, uint32_t reg, uint32_t val)
1012{
1013 struct uath_write_mac write;
1014 int error;
1015
1016 write.reg = htobe32(reg)(__uint32_t)(__builtin_constant_p(reg) ? (__uint32_t)(((__uint32_t
)(reg) & 0xff) << 24 | ((__uint32_t)(reg) & 0xff00
) << 8 | ((__uint32_t)(reg) & 0xff0000) >> 8 |
((__uint32_t)(reg) & 0xff000000) >> 24) : __swap32md
(reg))
;
1017 write.len = htobe32(0)(__uint32_t)(__builtin_constant_p(0) ? (__uint32_t)(((__uint32_t
)(0) & 0xff) << 24 | ((__uint32_t)(0) & 0xff00)
<< 8 | ((__uint32_t)(0) & 0xff0000) >> 8 | (
(__uint32_t)(0) & 0xff000000) >> 24) : __swap32md(0
))
; /* 0 = single write */
1018 *(uint32_t *)write.data = htobe32(val)(__uint32_t)(__builtin_constant_p(val) ? (__uint32_t)(((__uint32_t
)(val) & 0xff) << 24 | ((__uint32_t)(val) & 0xff00
) << 8 | ((__uint32_t)(val) & 0xff0000) >> 8 |
((__uint32_t)(val) & 0xff000000) >> 24) : __swap32md
(val))
;
1019
1020 error = uath_cmd_write(sc, UATH_CMD_WRITE_MAC0x04, &write,
1021 3 * sizeof (uint32_t), 0);
1022 if (error != 0) {
1023 printf("%s: could not write register 0x%02x\n",
1024 sc->sc_dev.dv_xname, reg);
1025 }
1026 return error;
1027}
1028
1029int
1030uath_write_multi(struct uath_softc *sc, uint32_t reg, const void *data,
1031 int len)
1032{
1033 struct uath_write_mac write;
1034 int error;
1035
1036 write.reg = htobe32(reg)(__uint32_t)(__builtin_constant_p(reg) ? (__uint32_t)(((__uint32_t
)(reg) & 0xff) << 24 | ((__uint32_t)(reg) & 0xff00
) << 8 | ((__uint32_t)(reg) & 0xff0000) >> 8 |
((__uint32_t)(reg) & 0xff000000) >> 24) : __swap32md
(reg))
;
1037 write.len = htobe32(len)(__uint32_t)(__builtin_constant_p(len) ? (__uint32_t)(((__uint32_t
)(len) & 0xff) << 24 | ((__uint32_t)(len) & 0xff00
) << 8 | ((__uint32_t)(len) & 0xff0000) >> 8 |
((__uint32_t)(len) & 0xff000000) >> 24) : __swap32md
(len))
;
1038 bcopy(data, write.data, len);
1039
1040 /* properly handle the case where len is zero (reset) */
1041 error = uath_cmd_write(sc, UATH_CMD_WRITE_MAC0x04, &write,
1042 (len == 0) ? sizeof (uint32_t) : 2 * sizeof (uint32_t) + len, 0);
1043 if (error != 0) {
1044 printf("%s: could not write %d bytes to register 0x%02x\n",
1045 sc->sc_dev.dv_xname, len, reg);
1046 }
1047 return error;
1048}
1049
1050int
1051uath_read_reg(struct uath_softc *sc, uint32_t reg, uint32_t *val)
1052{
1053 struct uath_read_mac read;
1054 int error;
1055
1056 reg = htobe32(reg)(__uint32_t)(__builtin_constant_p(reg) ? (__uint32_t)(((__uint32_t
)(reg) & 0xff) << 24 | ((__uint32_t)(reg) & 0xff00
) << 8 | ((__uint32_t)(reg) & 0xff0000) >> 8 |
((__uint32_t)(reg) & 0xff000000) >> 24) : __swap32md
(reg))
;
1057 error = uath_cmd_read(sc, UATH_CMD_READ_MAC0x03, &reg, sizeof reg, &read,
1058 0);
1059 if (error != 0) {
1060 printf("%s: could not read register 0x%02x\n",
1061 sc->sc_dev.dv_xname, betoh32(reg)(__uint32_t)(__builtin_constant_p(reg) ? (__uint32_t)(((__uint32_t
)(reg) & 0xff) << 24 | ((__uint32_t)(reg) & 0xff00
) << 8 | ((__uint32_t)(reg) & 0xff0000) >> 8 |
((__uint32_t)(reg) & 0xff000000) >> 24) : __swap32md
(reg))
);
1062 return error;
1063 }
1064 *val = betoh32(*(uint32_t *)read.data)(__uint32_t)(__builtin_constant_p(*(uint32_t *)read.data) ? (
__uint32_t)(((__uint32_t)(*(uint32_t *)read.data) & 0xff)
<< 24 | ((__uint32_t)(*(uint32_t *)read.data) & 0xff00
) << 8 | ((__uint32_t)(*(uint32_t *)read.data) & 0xff0000
) >> 8 | ((__uint32_t)(*(uint32_t *)read.data) & 0xff000000
) >> 24) : __swap32md(*(uint32_t *)read.data))
;
1065 return error;
1066}
1067
1068int
1069uath_read_eeprom(struct uath_softc *sc, uint32_t reg, void *odata)
1070{
1071 struct uath_read_mac read;
1072 int len, error;
1073
1074 reg = htobe32(reg)(__uint32_t)(__builtin_constant_p(reg) ? (__uint32_t)(((__uint32_t
)(reg) & 0xff) << 24 | ((__uint32_t)(reg) & 0xff00
) << 8 | ((__uint32_t)(reg) & 0xff0000) >> 8 |
((__uint32_t)(reg) & 0xff000000) >> 24) : __swap32md
(reg))
;
1075 error = uath_cmd_read(sc, UATH_CMD_READ_EEPROM0x05, &reg, sizeof reg,
1076 &read, 0);
1077 if (error != 0) {
1078 printf("%s: could not read EEPROM offset 0x%02x\n",
1079 sc->sc_dev.dv_xname, betoh32(reg)(__uint32_t)(__builtin_constant_p(reg) ? (__uint32_t)(((__uint32_t
)(reg) & 0xff) << 24 | ((__uint32_t)(reg) & 0xff00
) << 8 | ((__uint32_t)(reg) & 0xff0000) >> 8 |
((__uint32_t)(reg) & 0xff000000) >> 24) : __swap32md
(reg))
);
1080 return error;
1081 }
1082 len = betoh32(read.len)(__uint32_t)(__builtin_constant_p(read.len) ? (__uint32_t)(((
__uint32_t)(read.len) & 0xff) << 24 | ((__uint32_t)
(read.len) & 0xff00) << 8 | ((__uint32_t)(read.len)
& 0xff0000) >> 8 | ((__uint32_t)(read.len) & 0xff000000
) >> 24) : __swap32md(read.len))
;
1083 bcopy(read.data, odata, (len == 0) ? sizeof (uint32_t) : len);
1084 return error;
1085}
1086
1087void
1088uath_cmd_rxeof(struct usbd_xfer *xfer, void *priv,
1089 usbd_status status)
1090{
1091 struct uath_rx_cmd *cmd = priv;
1092 struct uath_softc *sc = cmd->sc;
1093 struct uath_cmd_hdr *hdr;
1094
1095 if (status != USBD_NORMAL_COMPLETION) {
1096 if (status == USBD_STALLED)
1097 usbd_clear_endpoint_stall_async(sc->cmd_rx_pipe);
1098 return;
1099 }
1100
1101 hdr = (struct uath_cmd_hdr *)cmd->buf;
1102
1103#ifdef UATH_DEBUG
1104 if (uath_debug >= 5) {
1105 printf("received command code=0x%x index=%u len=%u",
1106 betoh32(hdr->code)(__uint32_t)(__builtin_constant_p(hdr->code) ? (__uint32_t
)(((__uint32_t)(hdr->code) & 0xff) << 24 | ((__uint32_t
)(hdr->code) & 0xff00) << 8 | ((__uint32_t)(hdr->
code) & 0xff0000) >> 8 | ((__uint32_t)(hdr->code
) & 0xff000000) >> 24) : __swap32md(hdr->code))
, hdr->priv, betoh32(hdr->len)(__uint32_t)(__builtin_constant_p(hdr->len) ? (__uint32_t)
(((__uint32_t)(hdr->len) & 0xff) << 24 | ((__uint32_t
)(hdr->len) & 0xff00) << 8 | ((__uint32_t)(hdr->
len) & 0xff0000) >> 8 | ((__uint32_t)(hdr->len) &
0xff000000) >> 24) : __swap32md(hdr->len))
);
1107 uath_dump_cmd(cmd->buf, betoh32(hdr->len)(__uint32_t)(__builtin_constant_p(hdr->len) ? (__uint32_t)
(((__uint32_t)(hdr->len) & 0xff) << 24 | ((__uint32_t
)(hdr->len) & 0xff00) << 8 | ((__uint32_t)(hdr->
len) & 0xff0000) >> 8 | ((__uint32_t)(hdr->len) &
0xff000000) >> 24) : __swap32md(hdr->len))
, '-');
1108 }
1109#endif
1110
1111 switch (betoh32(hdr->code)(__uint32_t)(__builtin_constant_p(hdr->code) ? (__uint32_t
)(((__uint32_t)(hdr->code) & 0xff) << 24 | ((__uint32_t
)(hdr->code) & 0xff00) << 8 | ((__uint32_t)(hdr->
code) & 0xff0000) >> 8 | ((__uint32_t)(hdr->code
) & 0xff000000) >> 24) : __swap32md(hdr->code))
& 0xff) {
1112 /* reply to a read command */
1113 default:
1114 {
1115 struct uath_tx_cmd *txcmd = &sc->tx_cmd[hdr->priv];
1116
1117 if (txcmd->odata != NULL((void *)0)) {
1118 /* copy answer into caller's supplied buffer */
1119 bcopy((uint8_t *)(hdr + 1), txcmd->odata,
1120 betoh32(hdr->len)(__uint32_t)(__builtin_constant_p(hdr->len) ? (__uint32_t)
(((__uint32_t)(hdr->len) & 0xff) << 24 | ((__uint32_t
)(hdr->len) & 0xff00) << 8 | ((__uint32_t)(hdr->
len) & 0xff0000) >> 8 | ((__uint32_t)(hdr->len) &
0xff000000) >> 24) : __swap32md(hdr->len))
- sizeof (struct uath_cmd_hdr));
1121 }
1122 wakeup(txcmd); /* wake up caller */
1123 break;
1124 }
1125 /* spontaneous firmware notifications */
1126 case UATH_NOTIF_READY0x12:
1127 DPRINTF(("received device ready notification\n"));
1128 wakeup(UATH_COND_INIT(sc)((caddr_t)sc + 1));
1129 break;
1130
1131 case UATH_NOTIF_TX0x13:
1132 /* this notification is sent when UATH_TX_NOTIFY is set */
1133 DPRINTF(("received Tx notification\n"));
1134 break;
1135
1136 case UATH_NOTIF_STATS0x10:
1137 DPRINTFN(2, ("received device statistics\n"));
1138 timeout_add_sec(&sc->stat_to, 1);
1139 break;
1140 }
1141
1142 /* setup a new transfer */
1143 usbd_setup_xfer(xfer, sc->cmd_rx_pipe, cmd, cmd->buf, UATH_MAX_RXCMDSZ512,
1144 USBD_SHORT_XFER_OK0x04 | USBD_NO_COPY0x01, USBD_NO_TIMEOUT0,
1145 uath_cmd_rxeof);
1146 (void)usbd_transfer(xfer);
1147}
1148
1149void
1150uath_data_rxeof(struct usbd_xfer *xfer, void *priv,
1151 usbd_status status)
1152{
1153 struct uath_rx_data *data = priv;
1154 struct uath_softc *sc = data->sc;
1155 struct ieee80211com *ic = &sc->sc_ic;
1156 struct ifnet *ifp = &ic->ic_ific_ac.ac_if;
1157 struct ieee80211_frame *wh;
1158 struct ieee80211_rxinfo rxi;
1159 struct ieee80211_node *ni;
1160 struct uath_rx_desc *desc;
1161 struct mbuf *mnew, *m;
1162 uint32_t hdr;
1163 int s, len;
1164
1165 if (status != USBD_NORMAL_COMPLETION) {
1166 if (status == USBD_NOT_STARTED || status == USBD_CANCELLED)
1167 return;
1168
1169 if (status == USBD_STALLED)
1170 usbd_clear_endpoint_stall_async(sc->data_rx_pipe);
1171
1172 ifp->if_ierrorsif_data.ifi_ierrors++;
1173 return;
1174 }
1175 usbd_get_xfer_status(xfer, NULL((void *)0), NULL((void *)0), &len, NULL((void *)0));
1176
1177 if (len < UATH_MIN_RXBUFSZ(((sizeof (uint32_t) + sizeof (struct ieee80211_frame_min) + sizeof
(struct uath_rx_desc)) + 3) & ~3)
) {
1178 DPRINTF(("wrong xfer size (len=%d)\n", len));
1179 ifp->if_ierrorsif_data.ifi_ierrors++;
1180 goto skip;
1181 }
1182
1183 hdr = betoh32(*(uint32_t *)data->buf)(__uint32_t)(__builtin_constant_p(*(uint32_t *)data->buf) ?
(__uint32_t)(((__uint32_t)(*(uint32_t *)data->buf) & 0xff
) << 24 | ((__uint32_t)(*(uint32_t *)data->buf) &
0xff00) << 8 | ((__uint32_t)(*(uint32_t *)data->buf
) & 0xff0000) >> 8 | ((__uint32_t)(*(uint32_t *)data
->buf) & 0xff000000) >> 24) : __swap32md(*(uint32_t
*)data->buf))
;
Value stored to 'hdr' is never read
1184
1185 /* Rx descriptor is located at the end, 32-bit aligned */
1186 desc = (struct uath_rx_desc *)
1187 (data->buf + len - sizeof (struct uath_rx_desc));
1188
1189 if (betoh32(desc->len)(__uint32_t)(__builtin_constant_p(desc->len) ? (__uint32_t
)(((__uint32_t)(desc->len) & 0xff) << 24 | ((__uint32_t
)(desc->len) & 0xff00) << 8 | ((__uint32_t)(desc
->len) & 0xff0000) >> 8 | ((__uint32_t)(desc->
len) & 0xff000000) >> 24) : __swap32md(desc->len
))
> sc->rxbufsz) {
1190 DPRINTF(("bad descriptor (len=%d)\n", betoh32(desc->len)));
1191 ifp->if_ierrorsif_data.ifi_ierrors++;
1192 goto skip;
1193 }
1194
1195 /* there's probably a "bad CRC" flag somewhere in the descriptor.. */
1196
1197 MGETHDR(mnew, M_DONTWAIT, MT_DATA)mnew = m_gethdr((0x0002), (1));
1198 if (mnew == NULL((void *)0)) {
1199 printf("%s: could not allocate rx mbuf\n",
1200 sc->sc_dev.dv_xname);
1201 ifp->if_ierrorsif_data.ifi_ierrors++;
1202 goto skip;
1203 }
1204 MCLGETL(mnew, M_DONTWAIT, sc->rxbufsz)m_clget((mnew), (0x0002), (sc->rxbufsz));
1205 if (!(mnew->m_flagsm_hdr.mh_flags & M_EXT0x0001)) {
1206 printf("%s: could not allocate rx mbuf cluster\n",
1207 sc->sc_dev.dv_xname);
1208 m_freem(mnew);
1209 ifp->if_ierrorsif_data.ifi_ierrors++;
1210 goto skip;
1211 }
1212
1213 m = data->m;
1214 data->m = mnew;
1215
1216 /* finalize mbuf */
1217 m->m_datam_hdr.mh_data = data->buf + sizeof (uint32_t);
1218 m->m_pkthdrM_dat.MH.MH_pkthdr.len = m->m_lenm_hdr.mh_len = betoh32(desc->len)(__uint32_t)(__builtin_constant_p(desc->len) ? (__uint32_t
)(((__uint32_t)(desc->len) & 0xff) << 24 | ((__uint32_t
)(desc->len) & 0xff00) << 8 | ((__uint32_t)(desc
->len) & 0xff0000) >> 8 | ((__uint32_t)(desc->
len) & 0xff000000) >> 24) : __swap32md(desc->len
))
-
1219 sizeof (struct uath_rx_desc) - IEEE80211_CRC_LEN4;
1220
1221 data->buf = mtod(data->m, uint8_t *)((uint8_t *)((data->m)->m_hdr.mh_data));
1222
1223 wh = mtod(m, struct ieee80211_frame *)((struct ieee80211_frame *)((m)->m_hdr.mh_data));
1224 memset(&rxi, 0, sizeof(rxi))__builtin_memset((&rxi), (0), (sizeof(rxi)));
1225 if ((wh->i_fc[1] & IEEE80211_FC1_WEP0x40) &&
1226 ic->ic_opmode != IEEE80211_M_MONITOR) {
1227 /*
1228 * Hardware decrypts the frame itself but leaves the WEP bit
1229 * set in the 802.11 header and doesn't remove the IV and CRC
1230 * fields.
1231 */
1232 wh->i_fc[1] &= ~IEEE80211_FC1_WEP0x40;
1233 memmove((caddr_t)wh + IEEE80211_WEP_IVLEN +__builtin_memmove(((caddr_t)wh + 3 + 1), (wh), (sizeof (struct
ieee80211_frame)))
1234 IEEE80211_WEP_KIDLEN, wh, sizeof (struct ieee80211_frame))__builtin_memmove(((caddr_t)wh + 3 + 1), (wh), (sizeof (struct
ieee80211_frame)))
;
1235 m_adj(m, IEEE80211_WEP_IVLEN3 + IEEE80211_WEP_KIDLEN1);
1236 m_adj(m, -IEEE80211_WEP_CRCLEN4);
1237 wh = mtod(m, struct ieee80211_frame *)((struct ieee80211_frame *)((m)->m_hdr.mh_data));
1238
1239 rxi.rxi_flags |= IEEE80211_RXI_HWDEC0x00000001;
1240 }
1241
1242#if NBPFILTER1 > 0
1243 /* there are a lot more fields in the Rx descriptor */
1244 if (sc->sc_drvbpf != NULL((void *)0)) {
1245 struct mbuf mb;
1246 struct uath_rx_radiotap_header *tap = &sc->sc_rxtapsc_rxtapu.th;
1247
1248 tap->wr_flags = 0;
1249 tap->wr_chan_freq = htole16(betoh32(desc->freq))((__uint16_t)((__uint32_t)(__builtin_constant_p(desc->freq
) ? (__uint32_t)(((__uint32_t)(desc->freq) & 0xff) <<
24 | ((__uint32_t)(desc->freq) & 0xff00) << 8 |
((__uint32_t)(desc->freq) & 0xff0000) >> 8 | ((
__uint32_t)(desc->freq) & 0xff000000) >> 24) : __swap32md
(desc->freq))))
;
1250 tap->wr_chan_flags = htole16(ic->ic_bss->ni_chan->ic_flags)((__uint16_t)(ic->ic_bss->ni_chan->ic_flags));
1251 tap->wr_dbm_antsignal = (int8_t)betoh32(desc->rssi)(__uint32_t)(__builtin_constant_p(desc->rssi) ? (__uint32_t
)(((__uint32_t)(desc->rssi) & 0xff) << 24 | ((__uint32_t
)(desc->rssi) & 0xff00) << 8 | ((__uint32_t)(desc
->rssi) & 0xff0000) >> 8 | ((__uint32_t)(desc->
rssi) & 0xff000000) >> 24) : __swap32md(desc->rssi
))
;
1252
1253 mb.m_datam_hdr.mh_data = (caddr_t)tap;
1254 mb.m_lenm_hdr.mh_len = sc->sc_rxtap_len;
1255 mb.m_nextm_hdr.mh_next = m;
1256 mb.m_nextpktm_hdr.mh_nextpkt = NULL((void *)0);
1257 mb.m_typem_hdr.mh_type = 0;
1258 mb.m_flagsm_hdr.mh_flags = 0;
1259 bpf_mtap(sc->sc_drvbpf, &mb, BPF_DIRECTION_IN(1 << 0));
1260 }
1261#endif
1262
1263 s = splnet()splraise(0x4);
1264 ni = ieee80211_find_rxnode(ic, wh);
1265 rxi.rxi_rssi = (int)betoh32(desc->rssi)(__uint32_t)(__builtin_constant_p(desc->rssi) ? (__uint32_t
)(((__uint32_t)(desc->rssi) & 0xff) << 24 | ((__uint32_t
)(desc->rssi) & 0xff00) << 8 | ((__uint32_t)(desc
->rssi) & 0xff0000) >> 8 | ((__uint32_t)(desc->
rssi) & 0xff000000) >> 24) : __swap32md(desc->rssi
))
;
1266 ieee80211_input(ifp, m, ni, &rxi);
1267
1268 /* node is no longer needed */
1269 ieee80211_release_node(ic, ni);
1270 splx(s)spllower(s);
1271
1272skip: /* setup a new transfer */
1273 usbd_setup_xfer(xfer, sc->data_rx_pipe, data, data->buf, sc->rxbufsz,
1274 USBD_SHORT_XFER_OK0x04, USBD_NO_TIMEOUT0, uath_data_rxeof);
1275 (void)usbd_transfer(data->xfer);
1276}
1277
1278int
1279uath_tx_null(struct uath_softc *sc)
1280{
1281 struct uath_tx_data *data;
1282 struct uath_tx_desc *desc;
1283
1284 data = &sc->tx_data[sc->data_idx];
1285
1286 data->ni = NULL((void *)0);
1287
1288 *(uint32_t *)data->buf = UATH_MAKECTL(1, sizeof (struct uath_tx_desc))(__uint32_t)(__builtin_constant_p((1) << 16 | (sizeof (
struct uath_tx_desc))) ? (__uint32_t)(((__uint32_t)((1) <<
16 | (sizeof (struct uath_tx_desc))) & 0xff) << 24
| ((__uint32_t)((1) << 16 | (sizeof (struct uath_tx_desc
))) & 0xff00) << 8 | ((__uint32_t)((1) << 16 |
(sizeof (struct uath_tx_desc))) & 0xff0000) >> 8 |
((__uint32_t)((1) << 16 | (sizeof (struct uath_tx_desc
))) & 0xff000000) >> 24) : __swap32md((1) << 16
| (sizeof (struct uath_tx_desc))))
;
1289 desc = (struct uath_tx_desc *)(data->buf + sizeof (uint32_t));
1290
1291 bzero(desc, sizeof (struct uath_tx_desc))__builtin_bzero((desc), (sizeof (struct uath_tx_desc)));
1292 desc->len = htobe32(sizeof (struct uath_tx_desc))(__uint32_t)(__builtin_constant_p(sizeof (struct uath_tx_desc
)) ? (__uint32_t)(((__uint32_t)(sizeof (struct uath_tx_desc))
& 0xff) << 24 | ((__uint32_t)(sizeof (struct uath_tx_desc
)) & 0xff00) << 8 | ((__uint32_t)(sizeof (struct uath_tx_desc
)) & 0xff0000) >> 8 | ((__uint32_t)(sizeof (struct uath_tx_desc
)) & 0xff000000) >> 24) : __swap32md(sizeof (struct
uath_tx_desc)))
;
1293 desc->type = htobe32(UATH_TX_NULL)(__uint32_t)(__builtin_constant_p(0xf) ? (__uint32_t)(((__uint32_t
)(0xf) & 0xff) << 24 | ((__uint32_t)(0xf) & 0xff00
) << 8 | ((__uint32_t)(0xf) & 0xff0000) >> 8 |
((__uint32_t)(0xf) & 0xff000000) >> 24) : __swap32md
(0xf))
;
1294
1295 usbd_setup_xfer(data->xfer, sc->data_tx_pipe, data, data->buf,
1296 sizeof (uint32_t) + sizeof (struct uath_tx_desc), USBD_NO_COPY0x01 |
1297 USBD_FORCE_SHORT_XFER0x08 | USBD_SYNCHRONOUS0x02, UATH_DATA_TIMEOUT10000, NULL((void *)0));
1298 if (usbd_transfer(data->xfer) != 0)
1299 return EIO5;
1300
1301 sc->data_idx = (sc->data_idx + 1) % UATH_TX_DATA_LIST_COUNT8;
1302
1303 return uath_cmd_write(sc, UATH_CMD_0F0x0f, NULL((void *)0), 0, UATH_CMD_FLAG_ASYNC(1 << 0));
1304}
1305
1306void
1307uath_data_txeof(struct usbd_xfer *xfer, void *priv,
1308 usbd_status status)
1309{
1310 struct uath_tx_data *data = priv;
1311 struct uath_softc *sc = data->sc;
1312 struct ieee80211com *ic = &sc->sc_ic;
1313 struct ifnet *ifp = &ic->ic_ific_ac.ac_if;
1314 int s;
1315
1316 if (status != USBD_NORMAL_COMPLETION) {
1317 if (status == USBD_NOT_STARTED || status == USBD_CANCELLED)
1318 return;
1319
1320 printf("%s: could not transmit buffer: %s\n",
1321 sc->sc_dev.dv_xname, usbd_errstr(status));
1322
1323 if (status == USBD_STALLED)
1324 usbd_clear_endpoint_stall_async(sc->data_tx_pipe);
1325
1326 ifp->if_oerrorsif_data.ifi_oerrors++;
1327 return;
1328 }
1329
1330 s = splnet()splraise(0x4);
1331
1332 ieee80211_release_node(ic, data->ni);
1333 data->ni = NULL((void *)0);
1334
1335 sc->tx_queued--;
1336
1337 sc->sc_tx_timer = 0;
1338 ifq_clr_oactive(&ifp->if_snd);
1339 uath_start(ifp);
1340
1341 splx(s)spllower(s);
1342}
1343
1344int
1345uath_tx_data(struct uath_softc *sc, struct mbuf *m0, struct ieee80211_node *ni)
1346{
1347 struct ieee80211com *ic = &sc->sc_ic;
1348 struct uath_tx_data *data;
1349 struct uath_tx_desc *desc;
1350 const struct ieee80211_frame *wh;
1351 int paylen, totlen, xferlen, error;
1352
1353 data = &sc->tx_data[sc->data_idx];
1354 desc = (struct uath_tx_desc *)(data->buf + sizeof (uint32_t));
1355
1356 data->ni = ni;
1357
1358#if NBPFILTER1 > 0
1359 if (sc->sc_drvbpf != NULL((void *)0)) {
1360 struct mbuf mb;
1361 struct uath_tx_radiotap_header *tap = &sc->sc_txtapsc_txtapu.th;
1362
1363 tap->wt_flags = 0;
1364 tap->wt_chan_freq = htole16(ic->ic_bss->ni_chan->ic_freq)((__uint16_t)(ic->ic_bss->ni_chan->ic_freq));
1365 tap->wt_chan_flags = htole16(ic->ic_bss->ni_chan->ic_flags)((__uint16_t)(ic->ic_bss->ni_chan->ic_flags));
1366
1367 mb.m_datam_hdr.mh_data = (caddr_t)tap;
1368 mb.m_lenm_hdr.mh_len = sc->sc_txtap_len;
1369 mb.m_nextm_hdr.mh_next = m0;
1370 mb.m_nextpktm_hdr.mh_nextpkt = NULL((void *)0);
1371 mb.m_typem_hdr.mh_type = 0;
1372 mb.m_flagsm_hdr.mh_flags = 0;
1373 bpf_mtap(sc->sc_drvbpf, &mb, BPF_DIRECTION_OUT(1 << 1));
1374 }
1375#endif
1376
1377 paylen = m0->m_pkthdrM_dat.MH.MH_pkthdr.len;
1378 xferlen = sizeof (uint32_t) + sizeof (struct uath_tx_desc) + paylen;
1379
1380 wh = mtod(m0, struct ieee80211_frame *)((struct ieee80211_frame *)((m0)->m_hdr.mh_data));
1381 if (wh->i_fc[1] & IEEE80211_FC1_WEP0x40) {
1382 uint8_t *frm = (uint8_t *)(desc + 1);
1383 uint32_t iv;
1384
1385 /* h/w WEP: it's up to the host to fill the IV field */
1386 bcopy(wh, frm, sizeof (struct ieee80211_frame));
1387 frm += sizeof (struct ieee80211_frame);
1388
1389 /* insert IV: code copied from net80211 */
1390 iv = (ic->ic_iv != 0) ? ic->ic_iv : arc4random();
1391 if (iv >= 0x03ff00 && (iv & 0xf8ff00) == 0x00ff00)
1392 iv += 0x000100;
1393 ic->ic_iv = iv + 1;
1394
1395 *frm++ = iv & 0xff;
1396 *frm++ = (iv >> 8) & 0xff;
1397 *frm++ = (iv >> 16) & 0xff;
1398 *frm++ = ic->ic_wep_txkeyic_def_txkey << 6;
1399
1400 m_copydata(m0, sizeof(struct ieee80211_frame),
1401 m0->m_pkthdrM_dat.MH.MH_pkthdr.len - sizeof(struct ieee80211_frame), frm);
1402
1403 paylen += IEEE80211_WEP_IVLEN3 + IEEE80211_WEP_KIDLEN1;
1404 xferlen += IEEE80211_WEP_IVLEN3 + IEEE80211_WEP_KIDLEN1;
1405 totlen = xferlen + IEEE80211_WEP_CRCLEN4;
1406 } else {
1407 m_copydata(m0, 0, m0->m_pkthdrM_dat.MH.MH_pkthdr.len, desc + 1);
1408 totlen = xferlen;
1409 }
1410
1411 /* fill Tx descriptor */
1412 *(uint32_t *)data->buf = UATH_MAKECTL(1, xferlen - sizeof (uint32_t))(__uint32_t)(__builtin_constant_p((1) << 16 | (xferlen -
sizeof (uint32_t))) ? (__uint32_t)(((__uint32_t)((1) <<
16 | (xferlen - sizeof (uint32_t))) & 0xff) << 24 |
((__uint32_t)((1) << 16 | (xferlen - sizeof (uint32_t)
)) & 0xff00) << 8 | ((__uint32_t)((1) << 16 |
(xferlen - sizeof (uint32_t))) & 0xff0000) >> 8 | (
(__uint32_t)((1) << 16 | (xferlen - sizeof (uint32_t)))
& 0xff000000) >> 24) : __swap32md((1) << 16 |
(xferlen - sizeof (uint32_t))))
;
1413
1414 desc->len = htobe32(totlen)(__uint32_t)(__builtin_constant_p(totlen) ? (__uint32_t)(((__uint32_t
)(totlen) & 0xff) << 24 | ((__uint32_t)(totlen) &
0xff00) << 8 | ((__uint32_t)(totlen) & 0xff0000) >>
8 | ((__uint32_t)(totlen) & 0xff000000) >> 24) : __swap32md
(totlen))
;
1415 desc->priv = sc->data_idx; /* don't care about endianness */
1416 desc->paylen = htobe32(paylen)(__uint32_t)(__builtin_constant_p(paylen) ? (__uint32_t)(((__uint32_t
)(paylen) & 0xff) << 24 | ((__uint32_t)(paylen) &
0xff00) << 8 | ((__uint32_t)(paylen) & 0xff0000) >>
8 | ((__uint32_t)(paylen) & 0xff000000) >> 24) : __swap32md
(paylen))
;
1417 desc->type = htobe32(UATH_TX_DATA)(__uint32_t)(__builtin_constant_p(0xe) ? (__uint32_t)(((__uint32_t
)(0xe) & 0xff) << 24 | ((__uint32_t)(0xe) & 0xff00
) << 8 | ((__uint32_t)(0xe) & 0xff0000) >> 8 |
((__uint32_t)(0xe) & 0xff000000) >> 24) : __swap32md
(0xe))
;
1418 desc->flags = htobe32(0)(__uint32_t)(__builtin_constant_p(0) ? (__uint32_t)(((__uint32_t
)(0) & 0xff) << 24 | ((__uint32_t)(0) & 0xff00)
<< 8 | ((__uint32_t)(0) & 0xff0000) >> 8 | (
(__uint32_t)(0) & 0xff000000) >> 24) : __swap32md(0
))
;
1419 if (IEEE80211_IS_MULTICAST(wh->i_addr1)(*(wh->i_addr1) & 0x01)) {
1420 desc->dest = htobe32(UATH_ID_BROADCAST)(__uint32_t)(__builtin_constant_p(0xffffffff) ? (__uint32_t)(
((__uint32_t)(0xffffffff) & 0xff) << 24 | ((__uint32_t
)(0xffffffff) & 0xff00) << 8 | ((__uint32_t)(0xffffffff
) & 0xff0000) >> 8 | ((__uint32_t)(0xffffffff) &
0xff000000) >> 24) : __swap32md(0xffffffff))
;
1421 desc->magic = htobe32(3)(__uint32_t)(__builtin_constant_p(3) ? (__uint32_t)(((__uint32_t
)(3) & 0xff) << 24 | ((__uint32_t)(3) & 0xff00)
<< 8 | ((__uint32_t)(3) & 0xff0000) >> 8 | (
(__uint32_t)(3) & 0xff000000) >> 24) : __swap32md(3
))
;
1422 } else {
1423 desc->dest = htobe32(UATH_ID_BSS)(__uint32_t)(__builtin_constant_p(2) ? (__uint32_t)(((__uint32_t
)(2) & 0xff) << 24 | ((__uint32_t)(2) & 0xff00)
<< 8 | ((__uint32_t)(2) & 0xff0000) >> 8 | (
(__uint32_t)(2) & 0xff000000) >> 24) : __swap32md(2
))
;
1424 desc->magic = htobe32(1)(__uint32_t)(__builtin_constant_p(1) ? (__uint32_t)(((__uint32_t
)(1) & 0xff) << 24 | ((__uint32_t)(1) & 0xff00)
<< 8 | ((__uint32_t)(1) & 0xff0000) >> 8 | (
(__uint32_t)(1) & 0xff000000) >> 24) : __swap32md(1
))
;
1425 }
1426
1427 m_freem(m0); /* mbuf is no longer needed */
1428
1429#ifdef UATH_DEBUG
1430 if (uath_debug >= 6) {
1431 printf("sending frame index=%u len=%d xferlen=%d",
1432 sc->data_idx, paylen, xferlen);
1433 uath_dump_cmd(data->buf, xferlen, '+');
1434 }
1435#endif
1436 usbd_setup_xfer(data->xfer, sc->data_tx_pipe, data, data->buf, xferlen,
1437 USBD_FORCE_SHORT_XFER0x08 | USBD_NO_COPY0x01, UATH_DATA_TIMEOUT10000,
1438 uath_data_txeof);
1439 error = usbd_transfer(data->xfer);
1440 if (error != USBD_IN_PROGRESS && error != 0) {
1441 ic->ic_ific_ac.ac_if.if_oerrorsif_data.ifi_oerrors++;
1442 return error;
1443 }
1444 sc->data_idx = (sc->data_idx + 1) % UATH_TX_DATA_LIST_COUNT8;
1445 sc->tx_queued++;
1446
1447 return 0;
1448}
1449
1450void
1451uath_start(struct ifnet *ifp)
1452{
1453 struct uath_softc *sc = ifp->if_softc;
1454 struct ieee80211com *ic = &sc->sc_ic;
1455 struct ieee80211_node *ni;
1456 struct mbuf *m0;
1457
1458 /*
1459 * net80211 may still try to send management frames even if the
1460 * IFF_RUNNING flag is not set...
1461 */
1462 if (!(ifp->if_flags & IFF_RUNNING0x40) && ifq_is_oactive(&ifp->if_snd))
1463 return;
1464
1465 for (;;) {
1466 if (sc->tx_queued >= UATH_TX_DATA_LIST_COUNT8) {
1467 ifq_set_oactive(&ifp->if_snd);
1468 break;
1469 }
1470
1471 m0 = mq_dequeue(&ic->ic_mgtq);
1472 if (m0 != NULL((void *)0)) {
1473 ni = m0->m_pkthdrM_dat.MH.MH_pkthdr.ph_cookie;
1474#if NBPFILTER1 > 0
1475 if (ic->ic_rawbpf != NULL((void *)0))
1476 bpf_mtap(ic->ic_rawbpf, m0, BPF_DIRECTION_OUT(1 << 1));
1477#endif
1478 if (uath_tx_data(sc, m0, ni) != 0)
1479 break;
1480 } else {
1481 if (ic->ic_state != IEEE80211_S_RUN)
1482 break;
1483
1484 m0 = ifq_dequeue(&ifp->if_snd);
1485 if (m0 == NULL((void *)0))
1486 break;
1487#if NBPFILTER1 > 0
1488 if (ifp->if_bpf != NULL((void *)0))
1489 bpf_mtap(ifp->if_bpf, m0, BPF_DIRECTION_OUT(1 << 1));
1490#endif
1491 m0 = ieee80211_encap(ifp, m0, &ni);
1492 if (m0 == NULL((void *)0))
1493 continue;
1494#if NBPFILTER1 > 0
1495 if (ic->ic_rawbpf != NULL((void *)0))
1496 bpf_mtap(ic->ic_rawbpf, m0, BPF_DIRECTION_OUT(1 << 1));
1497#endif
1498 if (uath_tx_data(sc, m0, ni) != 0) {
1499 if (ni != NULL((void *)0))
1500 ieee80211_release_node(ic, ni);
1501 ifp->if_oerrorsif_data.ifi_oerrors++;
1502 break;
1503 }
1504 }
1505
1506 sc->sc_tx_timer = 5;
1507 ifp->if_timer = 1;
1508 }
1509}
1510
1511void
1512uath_watchdog(struct ifnet *ifp)
1513{
1514 struct uath_softc *sc = ifp->if_softc;
1515
1516 ifp->if_timer = 0;
1517
1518 if (sc->sc_tx_timer > 0) {
1519 if (--sc->sc_tx_timer == 0) {
1520 printf("%s: device timeout\n", sc->sc_dev.dv_xname);
1521 /*uath_init(ifp); XXX needs a process context! */
1522 ifp->if_oerrorsif_data.ifi_oerrors++;
1523 return;
1524 }
1525 ifp->if_timer = 1;
1526 }
1527
1528 ieee80211_watchdog(ifp);
1529}
1530
1531int
1532uath_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
1533{
1534 int s, error = 0;
1535
1536 s = splnet()splraise(0x4);
1537
1538 switch (cmd) {
1539 case SIOCSIFADDR((unsigned long)0x80000000 | ((sizeof(struct ifreq) & 0x1fff
) << 16) | ((('i')) << 8) | ((12)))
:
1540 ifp->if_flags |= IFF_UP0x1;
1541 /* FALLTHROUGH */
1542 case SIOCSIFFLAGS((unsigned long)0x80000000 | ((sizeof(struct ifreq) & 0x1fff
) << 16) | ((('i')) << 8) | ((16)))
:
1543 if (ifp->if_flags & IFF_UP0x1) {
1544 if (!(ifp->if_flags & IFF_RUNNING0x40))
1545 uath_init(ifp);
1546 } else {
1547 if (ifp->if_flags & IFF_RUNNING0x40)
1548 uath_stop(ifp, 1);
1549 }
1550 break;
1551
1552 default:
1553 error = ieee80211_ioctl(ifp, cmd, data);
1554 }
1555
1556 if (error == ENETRESET52) {
1557 if ((ifp->if_flags & (IFF_UP0x1 | IFF_RUNNING0x40)) ==
1558 (IFF_UP0x1 | IFF_RUNNING0x40))
1559 uath_init(ifp);
1560 error = 0;
1561 }
1562
1563 splx(s)spllower(s);
1564
1565 return error;
1566}
1567
1568int
1569uath_query_eeprom(struct uath_softc *sc)
1570{
1571 uint32_t tmp;
1572 int error;
1573
1574 /* retrieve MAC address */
1575 error = uath_read_eeprom(sc, UATH_EEPROM_MACADDR0x0b, sc->sc_ic.ic_myaddr);
1576 if (error != 0) {
1577 printf("%s: could not read MAC address\n",
1578 sc->sc_dev.dv_xname);
1579 return error;
1580 }
1581
1582 /* retrieve the maximum frame size that the hardware can receive */
1583 error = uath_read_eeprom(sc, UATH_EEPROM_RXBUFSZ0x0f, &tmp);
1584 if (error != 0) {
1585 printf("%s: could not read maximum Rx buffer size\n",
1586 sc->sc_dev.dv_xname);
1587 return error;
1588 }
1589 sc->rxbufsz = betoh32(tmp)(__uint32_t)(__builtin_constant_p(tmp) ? (__uint32_t)(((__uint32_t
)(tmp) & 0xff) << 24 | ((__uint32_t)(tmp) & 0xff00
) << 8 | ((__uint32_t)(tmp) & 0xff0000) >> 8 |
((__uint32_t)(tmp) & 0xff000000) >> 24) : __swap32md
(tmp))
& 0xfff;
1590 DPRINTF(("maximum Rx buffer size %d\n", sc->rxbufsz));
1591 return 0;
1592}
1593
1594int
1595uath_reset(struct uath_softc *sc)
1596{
1597 struct uath_cmd_setup setup;
1598 uint32_t reg, val;
1599 int s, error;
1600
1601 /* init device with some voodoo incantations.. */
1602 setup.magic1 = htobe32(1)(__uint32_t)(__builtin_constant_p(1) ? (__uint32_t)(((__uint32_t
)(1) & 0xff) << 24 | ((__uint32_t)(1) & 0xff00)
<< 8 | ((__uint32_t)(1) & 0xff0000) >> 8 | (
(__uint32_t)(1) & 0xff000000) >> 24) : __swap32md(1
))
;
1603 setup.magic2 = htobe32(5)(__uint32_t)(__builtin_constant_p(5) ? (__uint32_t)(((__uint32_t
)(5) & 0xff) << 24 | ((__uint32_t)(5) & 0xff00)
<< 8 | ((__uint32_t)(5) & 0xff0000) >> 8 | (
(__uint32_t)(5) & 0xff000000) >> 24) : __swap32md(5
))
;
1604 setup.magic3 = htobe32(200)(__uint32_t)(__builtin_constant_p(200) ? (__uint32_t)(((__uint32_t
)(200) & 0xff) << 24 | ((__uint32_t)(200) & 0xff00
) << 8 | ((__uint32_t)(200) & 0xff0000) >> 8 |
((__uint32_t)(200) & 0xff000000) >> 24) : __swap32md
(200))
;
1605 setup.magic4 = htobe32(27)(__uint32_t)(__builtin_constant_p(27) ? (__uint32_t)(((__uint32_t
)(27) & 0xff) << 24 | ((__uint32_t)(27) & 0xff00
) << 8 | ((__uint32_t)(27) & 0xff0000) >> 8 |
((__uint32_t)(27) & 0xff000000) >> 24) : __swap32md
(27))
;
1606 s = splusb()splraise(0x2);
1607 error = uath_cmd_write(sc, UATH_CMD_SETUP0x01, &setup, sizeof setup,
1608 UATH_CMD_FLAG_ASYNC(1 << 0));
1609 /* ..and wait until firmware notifies us that it is ready */
1610 if (error == 0)
1611 error = tsleep_nsec(UATH_COND_INIT(sc)((caddr_t)sc + 1), PCATCH0x100, "uathinit",
1612 SEC_TO_NSEC(5));
1613 splx(s)spllower(s);
1614 if (error != 0)
1615 return error;
1616
1617 /* read PHY registers */
1618 for (reg = 0x09; reg <= 0x24; reg++) {
1619 if (reg == 0x0b || reg == 0x0c)
1620 continue;
1621 DELAY(100)(*delay_func)(100);
1622 if ((error = uath_read_reg(sc, reg, &val)) != 0)
1623 return error;
1624 DPRINTFN(2, ("reg 0x%02x=0x%08x\n", reg, val));
1625 }
1626 return error;
1627}
1628
1629int
1630uath_reset_tx_queues(struct uath_softc *sc)
1631{
1632 int ac, error;
1633
1634 for (ac = 0; ac < 4; ac++) {
1635 const uint32_t qid = htobe32(UATH_AC_TO_QID(ac))(__uint32_t)(__builtin_constant_p((ac)) ? (__uint32_t)(((__uint32_t
)((ac)) & 0xff) << 24 | ((__uint32_t)((ac)) & 0xff00
) << 8 | ((__uint32_t)((ac)) & 0xff0000) >> 8
| ((__uint32_t)((ac)) & 0xff000000) >> 24) : __swap32md
((ac)))
;
1636
1637 DPRINTF(("resetting Tx queue %d\n", UATH_AC_TO_QID(ac)));
1638 error = uath_cmd_write(sc, UATH_CMD_RESET_QUEUE0x3b, &qid,
1639 sizeof qid, 0);
1640 if (error != 0)
1641 break;
1642 }
1643 return error;
1644}
1645
1646int
1647uath_wme_init(struct uath_softc *sc)
1648{
1649 struct uath_qinfo qinfo;
1650 int ac, error;
1651 static const struct uath_wme_settings uath_wme_11g[4] = {
1652 { 7, 4, 10, 0, 0 }, /* Background */
1653 { 3, 4, 10, 0, 0 }, /* Best-Effort */
1654 { 3, 3, 4, 26, 0 }, /* Video */
1655 { 2, 2, 3, 47, 0 } /* Voice */
1656 };
1657
1658 bzero(&qinfo, sizeof qinfo)__builtin_bzero((&qinfo), (sizeof qinfo));
1659 qinfo.size = htobe32(32)(__uint32_t)(__builtin_constant_p(32) ? (__uint32_t)(((__uint32_t
)(32) & 0xff) << 24 | ((__uint32_t)(32) & 0xff00
) << 8 | ((__uint32_t)(32) & 0xff0000) >> 8 |
((__uint32_t)(32) & 0xff000000) >> 24) : __swap32md
(32))
;
1660 qinfo.magic1 = htobe32(1)(__uint32_t)(__builtin_constant_p(1) ? (__uint32_t)(((__uint32_t
)(1) & 0xff) << 24 | ((__uint32_t)(1) & 0xff00)
<< 8 | ((__uint32_t)(1) & 0xff0000) >> 8 | (
(__uint32_t)(1) & 0xff000000) >> 24) : __swap32md(1
))
; /* XXX ack policy? */
1661 qinfo.magic2 = htobe32(1)(__uint32_t)(__builtin_constant_p(1) ? (__uint32_t)(((__uint32_t
)(1) & 0xff) << 24 | ((__uint32_t)(1) & 0xff00)
<< 8 | ((__uint32_t)(1) & 0xff0000) >> 8 | (
(__uint32_t)(1) & 0xff000000) >> 24) : __swap32md(1
))
;
1662 for (ac = 0; ac < 4; ac++) {
1663 qinfo.qid = htobe32(UATH_AC_TO_QID(ac))(__uint32_t)(__builtin_constant_p((ac)) ? (__uint32_t)(((__uint32_t
)((ac)) & 0xff) << 24 | ((__uint32_t)((ac)) & 0xff00
) << 8 | ((__uint32_t)((ac)) & 0xff0000) >> 8
| ((__uint32_t)((ac)) & 0xff000000) >> 24) : __swap32md
((ac)))
;
1664 qinfo.ac = htobe32(ac)(__uint32_t)(__builtin_constant_p(ac) ? (__uint32_t)(((__uint32_t
)(ac) & 0xff) << 24 | ((__uint32_t)(ac) & 0xff00
) << 8 | ((__uint32_t)(ac) & 0xff0000) >> 8 |
((__uint32_t)(ac) & 0xff000000) >> 24) : __swap32md
(ac))
;
1665 qinfo.aifsn = htobe32(uath_wme_11g[ac].aifsn)(__uint32_t)(__builtin_constant_p(uath_wme_11g[ac].aifsn) ? (
__uint32_t)(((__uint32_t)(uath_wme_11g[ac].aifsn) & 0xff)
<< 24 | ((__uint32_t)(uath_wme_11g[ac].aifsn) & 0xff00
) << 8 | ((__uint32_t)(uath_wme_11g[ac].aifsn) & 0xff0000
) >> 8 | ((__uint32_t)(uath_wme_11g[ac].aifsn) & 0xff000000
) >> 24) : __swap32md(uath_wme_11g[ac].aifsn))
;
1666 qinfo.logcwmin = htobe32(uath_wme_11g[ac].logcwmin)(__uint32_t)(__builtin_constant_p(uath_wme_11g[ac].logcwmin) ?
(__uint32_t)(((__uint32_t)(uath_wme_11g[ac].logcwmin) & 0xff
) << 24 | ((__uint32_t)(uath_wme_11g[ac].logcwmin) &
0xff00) << 8 | ((__uint32_t)(uath_wme_11g[ac].logcwmin
) & 0xff0000) >> 8 | ((__uint32_t)(uath_wme_11g[ac]
.logcwmin) & 0xff000000) >> 24) : __swap32md(uath_wme_11g
[ac].logcwmin))
;
1667 qinfo.logcwmax = htobe32(uath_wme_11g[ac].logcwmax)(__uint32_t)(__builtin_constant_p(uath_wme_11g[ac].logcwmax) ?
(__uint32_t)(((__uint32_t)(uath_wme_11g[ac].logcwmax) & 0xff
) << 24 | ((__uint32_t)(uath_wme_11g[ac].logcwmax) &
0xff00) << 8 | ((__uint32_t)(uath_wme_11g[ac].logcwmax
) & 0xff0000) >> 8 | ((__uint32_t)(uath_wme_11g[ac]
.logcwmax) & 0xff000000) >> 24) : __swap32md(uath_wme_11g
[ac].logcwmax))
;
1668 qinfo.txop = htobe32(UATH_TXOP_TO_US((__uint32_t)(__builtin_constant_p(((uath_wme_11g[ac].txop) <<
5)) ? (__uint32_t)(((__uint32_t)(((uath_wme_11g[ac].txop) <<
5)) & 0xff) << 24 | ((__uint32_t)(((uath_wme_11g[ac
].txop) << 5)) & 0xff00) << 8 | ((__uint32_t)
(((uath_wme_11g[ac].txop) << 5)) & 0xff0000) >>
8 | ((__uint32_t)(((uath_wme_11g[ac].txop) << 5)) &
0xff000000) >> 24) : __swap32md(((uath_wme_11g[ac].txop
) << 5)))
1669 uath_wme_11g[ac].txop))(__uint32_t)(__builtin_constant_p(((uath_wme_11g[ac].txop) <<
5)) ? (__uint32_t)(((__uint32_t)(((uath_wme_11g[ac].txop) <<
5)) & 0xff) << 24 | ((__uint32_t)(((uath_wme_11g[ac
].txop) << 5)) & 0xff00) << 8 | ((__uint32_t)
(((uath_wme_11g[ac].txop) << 5)) & 0xff0000) >>
8 | ((__uint32_t)(((uath_wme_11g[ac].txop) << 5)) &
0xff000000) >> 24) : __swap32md(((uath_wme_11g[ac].txop
) << 5)))
;
1670 qinfo.acm = htobe32(uath_wme_11g[ac].acm)(__uint32_t)(__builtin_constant_p(uath_wme_11g[ac].acm) ? (__uint32_t
)(((__uint32_t)(uath_wme_11g[ac].acm) & 0xff) << 24
| ((__uint32_t)(uath_wme_11g[ac].acm) & 0xff00) <<
8 | ((__uint32_t)(uath_wme_11g[ac].acm) & 0xff0000) >>
8 | ((__uint32_t)(uath_wme_11g[ac].acm) & 0xff000000) >>
24) : __swap32md(uath_wme_11g[ac].acm))
;
1671
1672 DPRINTF(("setting up Tx queue %d\n", UATH_AC_TO_QID(ac)));
1673 error = uath_cmd_write(sc, UATH_CMD_SET_QUEUE0x3a, &qinfo,
1674 sizeof qinfo, 0);
1675 if (error != 0)
1676 break;
1677 }
1678 return error;
1679}
1680
1681int
1682uath_set_chan(struct uath_softc *sc, struct ieee80211_channel *c)
1683{
1684 struct uath_set_chan chan;
1685
1686 bzero(&chan, sizeof chan)__builtin_bzero((&chan), (sizeof chan));
1687 chan.flags = htobe32(0x1400)(__uint32_t)(__builtin_constant_p(0x1400) ? (__uint32_t)(((__uint32_t
)(0x1400) & 0xff) << 24 | ((__uint32_t)(0x1400) &
0xff00) << 8 | ((__uint32_t)(0x1400) & 0xff0000) >>
8 | ((__uint32_t)(0x1400) & 0xff000000) >> 24) : __swap32md
(0x1400))
;
1688 chan.freq = htobe32(c->ic_freq)(__uint32_t)(__builtin_constant_p(c->ic_freq) ? (__uint32_t
)(((__uint32_t)(c->ic_freq) & 0xff) << 24 | ((__uint32_t
)(c->ic_freq) & 0xff00) << 8 | ((__uint32_t)(c->
ic_freq) & 0xff0000) >> 8 | ((__uint32_t)(c->ic_freq
) & 0xff000000) >> 24) : __swap32md(c->ic_freq))
;
1689 chan.magic1 = htobe32(20)(__uint32_t)(__builtin_constant_p(20) ? (__uint32_t)(((__uint32_t
)(20) & 0xff) << 24 | ((__uint32_t)(20) & 0xff00
) << 8 | ((__uint32_t)(20) & 0xff0000) >> 8 |
((__uint32_t)(20) & 0xff000000) >> 24) : __swap32md
(20))
;
1690 chan.magic2 = htobe32(50)(__uint32_t)(__builtin_constant_p(50) ? (__uint32_t)(((__uint32_t
)(50) & 0xff) << 24 | ((__uint32_t)(50) & 0xff00
) << 8 | ((__uint32_t)(50) & 0xff0000) >> 8 |
((__uint32_t)(50) & 0xff000000) >> 24) : __swap32md
(50))
;
1691 chan.magic3 = htobe32(1)(__uint32_t)(__builtin_constant_p(1) ? (__uint32_t)(((__uint32_t
)(1) & 0xff) << 24 | ((__uint32_t)(1) & 0xff00)
<< 8 | ((__uint32_t)(1) & 0xff0000) >> 8 | (
(__uint32_t)(1) & 0xff000000) >> 24) : __swap32md(1
))
;
1692
1693 DPRINTF(("switching to channel %d\n",
1694 ieee80211_chan2ieee(&sc->sc_ic, c)));
1695 return uath_cmd_write(sc, UATH_CMD_SET_CHAN0x34, &chan, sizeof chan, 0);
1696}
1697
1698int
1699uath_set_key(struct uath_softc *sc, const struct ieee80211_key *k, int index)
1700{
1701 struct uath_cmd_crypto crypto;
1702 int i;
1703
1704 bzero(&crypto, sizeof crypto)__builtin_bzero((&crypto), (sizeof crypto));
1705 crypto.keyidx = htobe32(index)(__uint32_t)(__builtin_constant_p(index) ? (__uint32_t)(((__uint32_t
)(index) & 0xff) << 24 | ((__uint32_t)(index) &
0xff00) << 8 | ((__uint32_t)(index) & 0xff0000) >>
8 | ((__uint32_t)(index) & 0xff000000) >> 24) : __swap32md
(index))
;
1706 crypto.magic1 = htobe32(1)(__uint32_t)(__builtin_constant_p(1) ? (__uint32_t)(((__uint32_t
)(1) & 0xff) << 24 | ((__uint32_t)(1) & 0xff00)
<< 8 | ((__uint32_t)(1) & 0xff0000) >> 8 | (
(__uint32_t)(1) & 0xff000000) >> 24) : __swap32md(1
))
;
1707 crypto.size = htobe32(368)(__uint32_t)(__builtin_constant_p(368) ? (__uint32_t)(((__uint32_t
)(368) & 0xff) << 24 | ((__uint32_t)(368) & 0xff00
) << 8 | ((__uint32_t)(368) & 0xff0000) >> 8 |
((__uint32_t)(368) & 0xff000000) >> 24) : __swap32md
(368))
;
1708 crypto.mask = htobe32(0xffff)(__uint32_t)(__builtin_constant_p(0xffff) ? (__uint32_t)(((__uint32_t
)(0xffff) & 0xff) << 24 | ((__uint32_t)(0xffff) &
0xff00) << 8 | ((__uint32_t)(0xffff) & 0xff0000) >>
8 | ((__uint32_t)(0xffff) & 0xff000000) >> 24) : __swap32md
(0xffff))
;
1709 crypto.flags = htobe32(0x80000068)(__uint32_t)(__builtin_constant_p(0x80000068) ? (__uint32_t)(
((__uint32_t)(0x80000068) & 0xff) << 24 | ((__uint32_t
)(0x80000068) & 0xff00) << 8 | ((__uint32_t)(0x80000068
) & 0xff0000) >> 8 | ((__uint32_t)(0x80000068) &
0xff000000) >> 24) : __swap32md(0x80000068))
;
1710 if (index != UATH_DEFAULT_KEY6)
1711 crypto.flags |= htobe32(index << 16)(__uint32_t)(__builtin_constant_p(index << 16) ? (__uint32_t
)(((__uint32_t)(index << 16) & 0xff) << 24 | (
(__uint32_t)(index << 16) & 0xff00) << 8 | ((
__uint32_t)(index << 16) & 0xff0000) >> 8 | (
(__uint32_t)(index << 16) & 0xff000000) >> 24
) : __swap32md(index << 16))
;
1712 memset(crypto.magic2, 0xff, sizeof crypto.magic2)__builtin_memset((crypto.magic2), (0xff), (sizeof crypto.magic2
))
;
1713
1714 /*
1715 * Each byte of the key must be XOR'ed with 10101010 before being
1716 * transmitted to the firmware.
1717 */
1718 for (i = 0; i < k->k_len; i++)
1719 crypto.key[i] = k->k_key[i] ^ 0xaa;
1720
1721 DPRINTF(("setting crypto key index=%d len=%d\n", index, k->k_len));
1722 return uath_cmd_write(sc, UATH_CMD_CRYPTO0x1d, &crypto, sizeof crypto, 0);
1723}
1724
1725int
1726uath_set_keys(struct uath_softc *sc)
1727{
1728 const struct ieee80211com *ic = &sc->sc_ic;
1729 int i, error;
1730
1731 for (i = 0; i < IEEE80211_WEP_NKID4; i++) {
1732 const struct ieee80211_key *k = &ic->ic_nw_keys[i];
1733
1734 if (k->k_len > 0 && (error = uath_set_key(sc, k, i)) != 0)
1735 return error;
1736 }
1737 return uath_set_key(sc, &ic->ic_nw_keys[ic->ic_wep_txkeyic_def_txkey],
1738 UATH_DEFAULT_KEY6);
1739}
1740
1741int
1742uath_set_rates(struct uath_softc *sc, const struct ieee80211_rateset *rs)
1743{
1744 struct uath_cmd_rates rates;
1745
1746 bzero(&rates, sizeof rates)__builtin_bzero((&rates), (sizeof rates));
1747 rates.magic1 = htobe32(0x02)(__uint32_t)(__builtin_constant_p(0x02) ? (__uint32_t)(((__uint32_t
)(0x02) & 0xff) << 24 | ((__uint32_t)(0x02) & 0xff00
) << 8 | ((__uint32_t)(0x02) & 0xff0000) >> 8
| ((__uint32_t)(0x02) & 0xff000000) >> 24) : __swap32md
(0x02))
;
1748 rates.size = htobe32(1 + sizeof rates.rates)(__uint32_t)(__builtin_constant_p(1 + sizeof rates.rates) ? (
__uint32_t)(((__uint32_t)(1 + sizeof rates.rates) & 0xff)
<< 24 | ((__uint32_t)(1 + sizeof rates.rates) & 0xff00
) << 8 | ((__uint32_t)(1 + sizeof rates.rates) & 0xff0000
) >> 8 | ((__uint32_t)(1 + sizeof rates.rates) & 0xff000000
) >> 24) : __swap32md(1 + sizeof rates.rates))
;
1749 rates.nrates = rs->rs_nrates;
1750 bcopy(rs->rs_rates, rates.rates, rs->rs_nrates);
1751
1752 DPRINTF(("setting supported rates nrates=%d\n", rs->rs_nrates));
1753 return uath_cmd_write(sc, UATH_CMD_SET_RATES0x26, &rates, sizeof rates, 0);
1754}
1755
1756int
1757uath_set_rxfilter(struct uath_softc *sc, uint32_t filter, uint32_t flags)
1758{
1759 struct uath_cmd_filter rxfilter;
1760
1761 rxfilter.filter = htobe32(filter)(__uint32_t)(__builtin_constant_p(filter) ? (__uint32_t)(((__uint32_t
)(filter) & 0xff) << 24 | ((__uint32_t)(filter) &
0xff00) << 8 | ((__uint32_t)(filter) & 0xff0000) >>
8 | ((__uint32_t)(filter) & 0xff000000) >> 24) : __swap32md
(filter))
;
1762 rxfilter.flags = htobe32(flags)(__uint32_t)(__builtin_constant_p(flags) ? (__uint32_t)(((__uint32_t
)(flags) & 0xff) << 24 | ((__uint32_t)(flags) &
0xff00) << 8 | ((__uint32_t)(flags) & 0xff0000) >>
8 | ((__uint32_t)(flags) & 0xff000000) >> 24) : __swap32md
(flags))
;
1763
1764 DPRINTF(("setting Rx filter=0x%x flags=0x%x\n", filter, flags));
1765 return uath_cmd_write(sc, UATH_CMD_SET_FILTER0x32, &rxfilter,
1766 sizeof rxfilter, 0);
1767}
1768
1769int
1770uath_set_led(struct uath_softc *sc, int which, int on)
1771{
1772 struct uath_cmd_led led;
1773
1774 led.which = htobe32(which)(__uint32_t)(__builtin_constant_p(which) ? (__uint32_t)(((__uint32_t
)(which) & 0xff) << 24 | ((__uint32_t)(which) &
0xff00) << 8 | ((__uint32_t)(which) & 0xff0000) >>
8 | ((__uint32_t)(which) & 0xff000000) >> 24) : __swap32md
(which))
;
1775 led.state = htobe32(on ? UATH_LED_ON : UATH_LED_OFF)(__uint32_t)(__builtin_constant_p(on ? 1 : 0) ? (__uint32_t)(
((__uint32_t)(on ? 1 : 0) & 0xff) << 24 | ((__uint32_t
)(on ? 1 : 0) & 0xff00) << 8 | ((__uint32_t)(on ? 1
: 0) & 0xff0000) >> 8 | ((__uint32_t)(on ? 1 : 0) &
0xff000000) >> 24) : __swap32md(on ? 1 : 0))
;
1776
1777 DPRINTFN(2, ("switching %s led %s\n",
1778 (which == UATH_LED_LINK) ? "link" : "activity",
1779 on ? "on" : "off"));
1780 return uath_cmd_write(sc, UATH_CMD_SET_LED0x17, &led, sizeof led, 0);
1781}
1782
1783int
1784uath_switch_channel(struct uath_softc *sc, struct ieee80211_channel *c)
1785{
1786 uint32_t val;
1787 int error;
1788
1789 /* set radio frequency */
1790 if ((error = uath_set_chan(sc, c)) != 0) {
1791 printf("%s: could not set channel\n", sc->sc_dev.dv_xname);
1792 return error;
1793 }
1794
1795 /* reset Tx rings */
1796 if ((error = uath_reset_tx_queues(sc)) != 0) {
1797 printf("%s: could not reset Tx queues\n",
1798 sc->sc_dev.dv_xname);
1799 return error;
1800 }
1801
1802 /* set Tx rings WME properties */
1803 if ((error = uath_wme_init(sc)) != 0) {
1804 printf("%s: could not init Tx queues\n",
1805 sc->sc_dev.dv_xname);
1806 return error;
1807 }
1808
1809 val = htobe32(0)(__uint32_t)(__builtin_constant_p(0) ? (__uint32_t)(((__uint32_t
)(0) & 0xff) << 24 | ((__uint32_t)(0) & 0xff00)
<< 8 | ((__uint32_t)(0) & 0xff0000) >> 8 | (
(__uint32_t)(0) & 0xff000000) >> 24) : __swap32md(0
))
;
1810 error = uath_cmd_write(sc, UATH_CMD_SET_STATE0x20, &val, sizeof val, 0);
1811 if (error != 0) {
1812 printf("%s: could not set state\n", sc->sc_dev.dv_xname);
1813 return error;
1814 }
1815
1816 return uath_tx_null(sc);
1817}
1818
1819int
1820uath_init(struct ifnet *ifp)
1821{
1822 struct uath_softc *sc = ifp->if_softc;
1823 struct ieee80211com *ic = &sc->sc_ic;
1824 struct uath_cmd_31 cmd31;
1825 uint32_t val;
1826 int i, error;
1827
1828 /* reset data and command rings */
1829 sc->tx_queued = sc->data_idx = sc->cmd_idx = 0;
1830
1831 val = htobe32(0)(__uint32_t)(__builtin_constant_p(0) ? (__uint32_t)(((__uint32_t
)(0) & 0xff) << 24 | ((__uint32_t)(0) & 0xff00)
<< 8 | ((__uint32_t)(0) & 0xff0000) >> 8 | (
(__uint32_t)(0) & 0xff000000) >> 24) : __swap32md(0
))
;
1832 (void)uath_cmd_write(sc, UATH_CMD_020x02, &val, sizeof val, 0);
1833
1834 /* set MAC address */
1835 IEEE80211_ADDR_COPY(ic->ic_myaddr, LLADDR(ifp->if_sadl))__builtin_memcpy((ic->ic_myaddr), (((caddr_t)((ifp->if_sadl
)->sdl_data + (ifp->if_sadl)->sdl_nlen))), (6))
;
1836 (void)uath_write_multi(sc, 0x13, ic->ic_myaddr, IEEE80211_ADDR_LEN6);
1837
1838 (void)uath_write_reg(sc, 0x02, 0x00000001);
1839 (void)uath_write_reg(sc, 0x0e, 0x0000003f);
1840 (void)uath_write_reg(sc, 0x10, 0x00000001);
1841 (void)uath_write_reg(sc, 0x06, 0x0000001e);
1842
1843 /*
1844 * Queue Rx data xfers.
1845 */
1846 for (i = 0; i < UATH_RX_DATA_LIST_COUNT1; i++) {
1847 struct uath_rx_data *data = &sc->rx_data[i];
1848
1849 usbd_setup_xfer(data->xfer, sc->data_rx_pipe, data, data->buf,
1850 sc->rxbufsz, USBD_SHORT_XFER_OK0x04, USBD_NO_TIMEOUT0,
1851 uath_data_rxeof);
1852 error = usbd_transfer(data->xfer);
1853 if (error != USBD_IN_PROGRESS && error != 0) {
1854 printf("%s: could not queue Rx transfer\n",
1855 sc->sc_dev.dv_xname);
1856 goto fail;
1857 }
1858 }
1859
1860 error = uath_cmd_read(sc, UATH_CMD_070x07, NULL((void *)0), 0, &val,
1861 UATH_CMD_FLAG_MAGIC(1 << 2));
1862 if (error != 0) {
1863 printf("%s: could not send read command 07h\n",
1864 sc->sc_dev.dv_xname);
1865 goto fail;
1866 }
1867 DPRINTF(("command 07h return code: %x\n", betoh32(val)));
1868
1869 /* set default channel */
1870 ic->ic_bss->ni_chan = ic->ic_ibss_chan;
1871 if ((error = uath_set_chan(sc, ic->ic_bss->ni_chan)) != 0) {
1872 printf("%s: could not set channel\n", sc->sc_dev.dv_xname);
1873 goto fail;
1874 }
1875
1876 if ((error = uath_wme_init(sc)) != 0) {
1877 printf("%s: could not setup WME parameters\n",
1878 sc->sc_dev.dv_xname);
1879 goto fail;
1880 }
1881
1882 /* init MAC registers */
1883 (void)uath_write_reg(sc, 0x19, 0x00000000);
1884 (void)uath_write_reg(sc, 0x1a, 0x0000003c);
1885 (void)uath_write_reg(sc, 0x1b, 0x0000003c);
1886 (void)uath_write_reg(sc, 0x1c, 0x00000000);
1887 (void)uath_write_reg(sc, 0x1e, 0x00000000);
1888 (void)uath_write_reg(sc, 0x1f, 0x00000003);
1889 (void)uath_write_reg(sc, 0x0c, 0x00000000);
1890 (void)uath_write_reg(sc, 0x0f, 0x00000002);
1891 (void)uath_write_reg(sc, 0x0a, 0x00000007); /* XXX retry? */
1892 (void)uath_write_reg(sc, 0x09, ic->ic_rtsthreshold);
1893
1894 val = htobe32(4)(__uint32_t)(__builtin_constant_p(4) ? (__uint32_t)(((__uint32_t
)(4) & 0xff) << 24 | ((__uint32_t)(4) & 0xff00)
<< 8 | ((__uint32_t)(4) & 0xff0000) >> 8 | (
(__uint32_t)(4) & 0xff000000) >> 24) : __swap32md(4
))
;
1895 (void)uath_cmd_write(sc, UATH_CMD_270x27, &val, sizeof val, 0);
1896 (void)uath_cmd_write(sc, UATH_CMD_270x27, &val, sizeof val, 0);
1897 (void)uath_cmd_write(sc, UATH_CMD_1B0x1b, NULL((void *)0), 0, 0);
1898
1899 if ((error = uath_set_keys(sc)) != 0) {
1900 printf("%s: could not set crypto keys\n",
1901 sc->sc_dev.dv_xname);
1902 goto fail;
1903 }
1904
1905 /* enable Rx */
1906 (void)uath_set_rxfilter(sc, 0x0000, 4);
1907 (void)uath_set_rxfilter(sc, 0x0817, 1);
1908
1909 cmd31.magic1 = htobe32(0xffffffff)(__uint32_t)(__builtin_constant_p(0xffffffff) ? (__uint32_t)(
((__uint32_t)(0xffffffff) & 0xff) << 24 | ((__uint32_t
)(0xffffffff) & 0xff00) << 8 | ((__uint32_t)(0xffffffff
) & 0xff0000) >> 8 | ((__uint32_t)(0xffffffff) &
0xff000000) >> 24) : __swap32md(0xffffffff))
;
1910 cmd31.magic2 = htobe32(0xffffffff)(__uint32_t)(__builtin_constant_p(0xffffffff) ? (__uint32_t)(
((__uint32_t)(0xffffffff) & 0xff) << 24 | ((__uint32_t
)(0xffffffff) & 0xff00) << 8 | ((__uint32_t)(0xffffffff
) & 0xff0000) >> 8 | ((__uint32_t)(0xffffffff) &
0xff000000) >> 24) : __swap32md(0xffffffff))
;
1911 (void)uath_cmd_write(sc, UATH_CMD_310x31, &cmd31, sizeof cmd31, 0);
1912
1913 ifp->if_flags |= IFF_RUNNING0x40;
1914 ifq_clr_oactive(&ifp->if_snd);
1915
1916 if (ic->ic_opmode == IEEE80211_M_MONITOR)
1917 ieee80211_new_state(ic, IEEE80211_S_RUN, -1)(((ic)->ic_newstate)((ic), (IEEE80211_S_RUN), (-1)));
1918 else
1919 ieee80211_new_state(ic, IEEE80211_S_SCAN, -1)(((ic)->ic_newstate)((ic), (IEEE80211_S_SCAN), (-1)));
1920
1921 return 0;
1922
1923fail: uath_stop(ifp, 1);
1924 return error;
1925}
1926
1927void
1928uath_stop(struct ifnet *ifp, int disable)
1929{
1930 struct uath_softc *sc = ifp->if_softc;
1931 struct ieee80211com *ic = &sc->sc_ic;
1932 uint32_t val;
1933 int s;
1934
1935 s = splusb()splraise(0x2);
1936
1937 sc->sc_tx_timer = 0;
1938 ifp->if_timer = 0;
1939 ifp->if_flags &= ~IFF_RUNNING0x40;
1940 ifq_clr_oactive(&ifp->if_snd);
1941
1942 ieee80211_new_state(ic, IEEE80211_S_INIT, -1)(((ic)->ic_newstate)((ic), (IEEE80211_S_INIT), (-1))); /* free all nodes */
1943
1944 val = htobe32(0)(__uint32_t)(__builtin_constant_p(0) ? (__uint32_t)(((__uint32_t
)(0) & 0xff) << 24 | ((__uint32_t)(0) & 0xff00)
<< 8 | ((__uint32_t)(0) & 0xff0000) >> 8 | (
(__uint32_t)(0) & 0xff000000) >> 24) : __swap32md(0
))
;
1945 (void)uath_cmd_write(sc, UATH_CMD_SET_STATE0x20, &val, sizeof val, 0);
1946 (void)uath_cmd_write(sc, UATH_CMD_RESET0x35, NULL((void *)0), 0, 0);
1947
1948 val = htobe32(0)(__uint32_t)(__builtin_constant_p(0) ? (__uint32_t)(((__uint32_t
)(0) & 0xff) << 24 | ((__uint32_t)(0) & 0xff00)
<< 8 | ((__uint32_t)(0) & 0xff0000) >> 8 | (
(__uint32_t)(0) & 0xff000000) >> 24) : __swap32md(0
))
;
1949 (void)uath_cmd_write(sc, UATH_CMD_150x15, &val, sizeof val, 0);
1950
1951#if 0
1952 (void)uath_cmd_read(sc, UATH_CMD_SHUTDOWN0x08, NULL((void *)0), 0, NULL((void *)0),
1953 UATH_CMD_FLAG_MAGIC(1 << 2));
1954#endif
1955
1956 /* abort any pending transfers */
1957 usbd_abort_pipe(sc->data_tx_pipe);
1958 usbd_abort_pipe(sc->data_rx_pipe);
1959 usbd_abort_pipe(sc->cmd_tx_pipe);
1960
1961 splx(s)spllower(s);
1962}
1963
1964/*
1965 * Load the MIPS R4000 microcode into the device. Once the image is loaded,
1966 * the device will detach itself from the bus and reattach later with a new
1967 * product Id (a la ezusb). XXX this could also be implemented in userland
1968 * through /dev/ugen.
1969 */
1970int
1971uath_loadfirmware(struct uath_softc *sc, const u_char *fw, int len)
1972{
1973 struct usbd_xfer *ctlxfer, *txxfer, *rxxfer;
1974 struct uath_fwblock *txblock, *rxblock;
1975 uint8_t *txdata;
1976 int error = 0;
1977
1978 if ((ctlxfer = usbd_alloc_xfer(sc->sc_udev)) == NULL((void *)0)) {
1979 printf("%s: could not allocate Tx control xfer\n",
1980 sc->sc_dev.dv_xname);
1981 error = USBD_NOMEM;
1982 goto fail1;
1983 }
1984 txblock = usbd_alloc_buffer(ctlxfer, sizeof (struct uath_fwblock));
1985 if (txblock == NULL((void *)0)) {
1986 printf("%s: could not allocate Tx control block\n",
1987 sc->sc_dev.dv_xname);
1988 error = USBD_NOMEM;
1989 goto fail2;
1990 }
1991
1992 if ((txxfer = usbd_alloc_xfer(sc->sc_udev)) == NULL((void *)0)) {
1993 printf("%s: could not allocate Tx xfer\n",
1994 sc->sc_dev.dv_xname);
1995 error = USBD_NOMEM;
1996 goto fail2;
1997 }
1998 txdata = usbd_alloc_buffer(txxfer, UATH_MAX_FWBLOCK_SIZE2048);
1999 if (txdata == NULL((void *)0)) {
2000 printf("%s: could not allocate Tx buffer\n",
2001 sc->sc_dev.dv_xname);
2002 error = USBD_NOMEM;
2003 goto fail3;
2004 }
2005
2006 if ((rxxfer = usbd_alloc_xfer(sc->sc_udev)) == NULL((void *)0)) {
2007 printf("%s: could not allocate Rx control xfer\n",
2008 sc->sc_dev.dv_xname);
2009 error = USBD_NOMEM;
2010 goto fail3;
2011 }
2012 rxblock = usbd_alloc_buffer(rxxfer, sizeof (struct uath_fwblock));
2013 if (rxblock == NULL((void *)0)) {
2014 printf("%s: could not allocate Rx control block\n",
2015 sc->sc_dev.dv_xname);
2016 error = USBD_NOMEM;
2017 goto fail4;
2018 }
2019
2020 bzero(txblock, sizeof (struct uath_fwblock))__builtin_bzero((txblock), (sizeof (struct uath_fwblock)));
2021 txblock->flags = htobe32(UATH_WRITE_BLOCK)(__uint32_t)(__builtin_constant_p((1 << 4)) ? (__uint32_t
)(((__uint32_t)((1 << 4)) & 0xff) << 24 | ((__uint32_t
)((1 << 4)) & 0xff00) << 8 | ((__uint32_t)((1
<< 4)) & 0xff0000) >> 8 | ((__uint32_t)((1 <<
4)) & 0xff000000) >> 24) : __swap32md((1 << 4
)))
;
2022 txblock->total = htobe32(len)(__uint32_t)(__builtin_constant_p(len) ? (__uint32_t)(((__uint32_t
)(len) & 0xff) << 24 | ((__uint32_t)(len) & 0xff00
) << 8 | ((__uint32_t)(len) & 0xff0000) >> 8 |
((__uint32_t)(len) & 0xff000000) >> 24) : __swap32md
(len))
;
2023
2024 while (len > 0) {
2025 int mlen = min(len, UATH_MAX_FWBLOCK_SIZE2048);
2026
2027 txblock->remain = htobe32(len - mlen)(__uint32_t)(__builtin_constant_p(len - mlen) ? (__uint32_t)(
((__uint32_t)(len - mlen) & 0xff) << 24 | ((__uint32_t
)(len - mlen) & 0xff00) << 8 | ((__uint32_t)(len - mlen
) & 0xff0000) >> 8 | ((__uint32_t)(len - mlen) &
0xff000000) >> 24) : __swap32md(len - mlen))
;
2028 txblock->len = htobe32(mlen)(__uint32_t)(__builtin_constant_p(mlen) ? (__uint32_t)(((__uint32_t
)(mlen) & 0xff) << 24 | ((__uint32_t)(mlen) & 0xff00
) << 8 | ((__uint32_t)(mlen) & 0xff0000) >> 8
| ((__uint32_t)(mlen) & 0xff000000) >> 24) : __swap32md
(mlen))
;
2029
2030 DPRINTF(("sending firmware block: %d bytes remaining\n",
2031 len - mlen));
2032
2033 /* send firmware block meta-data */
2034 usbd_setup_xfer(ctlxfer, sc->cmd_tx_pipe, sc, txblock,
2035 sizeof (struct uath_fwblock),
2036 USBD_NO_COPY0x01 | USBD_SYNCHRONOUS0x02,
2037 UATH_CMD_TIMEOUT1000, NULL((void *)0));
2038 if ((error = usbd_transfer(ctlxfer)) != 0) {
2039 printf("%s: could not send firmware block info\n",
2040 sc->sc_dev.dv_xname);
2041 break;
2042 }
2043
2044 /* send firmware block data */
2045 bcopy(fw, txdata, mlen);
2046 usbd_setup_xfer(txxfer, sc->data_tx_pipe, sc, txdata, mlen,
2047 USBD_NO_COPY0x01 | USBD_SYNCHRONOUS0x02, UATH_DATA_TIMEOUT10000, NULL((void *)0));
2048 if ((error = usbd_transfer(txxfer)) != 0) {
2049 printf("%s: could not send firmware block data\n",
2050 sc->sc_dev.dv_xname);
2051 break;
2052 }
2053
2054 /* wait for ack from firmware */
2055 usbd_setup_xfer(rxxfer, sc->cmd_rx_pipe, sc, rxblock,
2056 sizeof (struct uath_fwblock), USBD_SHORT_XFER_OK0x04 |
2057 USBD_NO_COPY0x01 | USBD_SYNCHRONOUS0x02, UATH_CMD_TIMEOUT1000, NULL((void *)0));
2058 if ((error = usbd_transfer(rxxfer)) != 0) {
2059 printf("%s: could not read firmware answer\n",
2060 sc->sc_dev.dv_xname);
2061 break;
2062 }
2063
2064 DPRINTFN(2, ("rxblock flags=0x%x total=%d\n",
2065 betoh32(rxblock->flags), betoh32(rxblock->rxtotal)));
2066 fw += mlen;
2067 len -= mlen;
2068 }
2069
2070fail4: usbd_free_xfer(rxxfer);
2071fail3: usbd_free_xfer(txxfer);
2072fail2: usbd_free_xfer(ctlxfer);
2073fail1: return error;
2074}