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.0 -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name if_uath.c -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model static -mframe-pointer=all -relaxed-aliasing -fno-rounding-math -mconstructor-aliases -ffreestanding -mcmodel=kernel -target-cpu x86-64 -target-feature +retpoline-indirect-calls -target-feature +retpoline-indirect-branches -target-feature -sse2 -target-feature -sse -target-feature -3dnow -target-feature -mmx -target-feature +save-args -disable-red-zone -no-implicit-float -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/usr/src/sys/arch/amd64/compile/GENERIC.MP/obj -nostdsysteminc -nobuiltininc -resource-dir /usr/local/lib/clang/13.0.0 -I /usr/src/sys -I /usr/src/sys/arch/amd64/compile/GENERIC.MP/obj -I /usr/src/sys/arch -I /usr/src/sys/dev/pci/drm/include -I /usr/src/sys/dev/pci/drm/include/uapi -I /usr/src/sys/dev/pci/drm/amd/include/asic_reg -I /usr/src/sys/dev/pci/drm/amd/include -I /usr/src/sys/dev/pci/drm/amd/amdgpu -I /usr/src/sys/dev/pci/drm/amd/display -I /usr/src/sys/dev/pci/drm/amd/display/include -I /usr/src/sys/dev/pci/drm/amd/display/dc -I /usr/src/sys/dev/pci/drm/amd/display/amdgpu_dm -I /usr/src/sys/dev/pci/drm/amd/pm/inc -I /usr/src/sys/dev/pci/drm/amd/pm/swsmu -I /usr/src/sys/dev/pci/drm/amd/pm/swsmu/smu11 -I /usr/src/sys/dev/pci/drm/amd/pm/swsmu/smu12 -I /usr/src/sys/dev/pci/drm/amd/pm/powerplay -I /usr/src/sys/dev/pci/drm/amd/pm/powerplay/hwmgr -I /usr/src/sys/dev/pci/drm/amd/pm/powerplay/smumgr -I /usr/src/sys/dev/pci/drm/amd/display/dc/inc -I /usr/src/sys/dev/pci/drm/amd/display/dc/inc/hw -I /usr/src/sys/dev/pci/drm/amd/display/dc/clk_mgr -I /usr/src/sys/dev/pci/drm/amd/display/modules/inc -I /usr/src/sys/dev/pci/drm/amd/display/modules/hdcp -I /usr/src/sys/dev/pci/drm/amd/display/dmub/inc -I /usr/src/sys/dev/pci/drm/i915 -D DDB -D DIAGNOSTIC -D KTRACE -D ACCOUNTING -D KMEMSTATS -D PTRACE -D POOL_DEBUG -D CRYPTO -D SYSVMSG -D SYSVSEM -D SYSVSHM -D UVM_SWAP_ENCRYPT -D FFS -D FFS2 -D FFS_SOFTUPDATES -D UFS_DIRHASH -D QUOTA -D EXT2FS -D MFS -D NFSCLIENT -D NFSSERVER -D CD9660 -D UDF -D MSDOSFS -D FIFO -D FUSE -D SOCKET_SPLICE -D TCP_ECN -D TCP_SIGNATURE -D INET6 -D IPSEC -D PPP_BSDCOMP -D PPP_DEFLATE -D PIPEX -D MROUTING -D MPLS -D BOOT_CONFIG -D USER_PCICONF -D APERTURE -D MTRR -D NTFS -D HIBERNATE -D PCIVERBOSE -D USBVERBOSE -D WSDISPLAY_COMPAT_USL -D WSDISPLAY_COMPAT_RAWKBD -D WSDISPLAY_DEFAULTSCREENS=6 -D X86EMU -D ONEWIREVERBOSE -D MULTIPROCESSOR -D MAXUSERS=80 -D _KERNEL -D CONFIG_DRM_AMD_DC_DCN3_0 -O2 -Wno-pointer-sign -Wno-address-of-packed-member -Wno-constant-conversion -Wno-unused-but-set-variable -Wno-gnu-folding-constant -fdebug-compilation-dir=/usr/src/sys/arch/amd64/compile/GENERIC.MP/obj -ferror-limit 19 -fwrapv -D_RET_PROTECTOR -ret-protector -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -fno-builtin-malloc -fno-builtin-calloc -fno-builtin-realloc -fno-builtin-valloc -fno-builtin-free -fno-builtin-strdup -fno-builtin-strndup -analyzer-output=html -faddrsig -o /usr/obj/sys/arch/amd64/compile/GENERIC.MP/scan-build/2022-01-12-131800-47421-1 -x c /usr/src/sys/dev/usb/if_uath.c
1/* $OpenBSD: if_uath.c,v 1.87 2021/02/25 02:48:20 dlg 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(0x7);
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(0x5);
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 rxi.rxi_flags = 0;
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(0x7);
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 rxi.rxi_tstamp = 0; /* unused */
1267 ieee80211_input(ifp, m, ni, &rxi);
1268
1269 /* node is no longer needed */
1270 ieee80211_release_node(ic, ni);
1271 splx(s)spllower(s);
1272
1273skip: /* setup a new transfer */
1274 usbd_setup_xfer(xfer, sc->data_rx_pipe, data, data->buf, sc->rxbufsz,
1275 USBD_SHORT_XFER_OK0x04, USBD_NO_TIMEOUT0, uath_data_rxeof);
1276 (void)usbd_transfer(data->xfer);
1277}
1278
1279int
1280uath_tx_null(struct uath_softc *sc)
1281{
1282 struct uath_tx_data *data;
1283 struct uath_tx_desc *desc;
1284
1285 data = &sc->tx_data[sc->data_idx];
1286
1287 data->ni = NULL((void *)0);
1288
1289 *(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))))
;
1290 desc = (struct uath_tx_desc *)(data->buf + sizeof (uint32_t));
1291
1292 bzero(desc, sizeof (struct uath_tx_desc))__builtin_bzero((desc), (sizeof (struct uath_tx_desc)));
1293 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)))
;
1294 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))
;
1295
1296 usbd_setup_xfer(data->xfer, sc->data_tx_pipe, data, data->buf,
1297 sizeof (uint32_t) + sizeof (struct uath_tx_desc), USBD_NO_COPY0x01 |
1298 USBD_FORCE_SHORT_XFER0x08 | USBD_SYNCHRONOUS0x02, UATH_DATA_TIMEOUT10000, NULL((void *)0));
1299 if (usbd_transfer(data->xfer) != 0)
1300 return EIO5;
1301
1302 sc->data_idx = (sc->data_idx + 1) % UATH_TX_DATA_LIST_COUNT8;
1303
1304 return uath_cmd_write(sc, UATH_CMD_0F0x0f, NULL((void *)0), 0, UATH_CMD_FLAG_ASYNC(1 << 0));
1305}
1306
1307void
1308uath_data_txeof(struct usbd_xfer *xfer, void *priv,
1309 usbd_status status)
1310{
1311 struct uath_tx_data *data = priv;
1312 struct uath_softc *sc = data->sc;
1313 struct ieee80211com *ic = &sc->sc_ic;
1314 struct ifnet *ifp = &ic->ic_ific_ac.ac_if;
1315 int s;
1316
1317 if (status != USBD_NORMAL_COMPLETION) {
1318 if (status == USBD_NOT_STARTED || status == USBD_CANCELLED)
1319 return;
1320
1321 printf("%s: could not transmit buffer: %s\n",
1322 sc->sc_dev.dv_xname, usbd_errstr(status));
1323
1324 if (status == USBD_STALLED)
1325 usbd_clear_endpoint_stall_async(sc->data_tx_pipe);
1326
1327 ifp->if_oerrorsif_data.ifi_oerrors++;
1328 return;
1329 }
1330
1331 s = splnet()splraise(0x7);
1332
1333 ieee80211_release_node(ic, data->ni);
1334 data->ni = NULL((void *)0);
1335
1336 sc->tx_queued--;
1337
1338 sc->sc_tx_timer = 0;
1339 ifq_clr_oactive(&ifp->if_snd);
1340 uath_start(ifp);
1341
1342 splx(s)spllower(s);
1343}
1344
1345int
1346uath_tx_data(struct uath_softc *sc, struct mbuf *m0, struct ieee80211_node *ni)
1347{
1348 struct ieee80211com *ic = &sc->sc_ic;
1349 struct uath_tx_data *data;
1350 struct uath_tx_desc *desc;
1351 const struct ieee80211_frame *wh;
1352 int paylen, totlen, xferlen, error;
1353
1354 data = &sc->tx_data[sc->data_idx];
1355 desc = (struct uath_tx_desc *)(data->buf + sizeof (uint32_t));
1356
1357 data->ni = ni;
1358
1359#if NBPFILTER1 > 0
1360 if (sc->sc_drvbpf != NULL((void *)0)) {
1361 struct mbuf mb;
1362 struct uath_tx_radiotap_header *tap = &sc->sc_txtapsc_txtapu.th;
1363
1364 tap->wt_flags = 0;
1365 tap->wt_chan_freq = htole16(ic->ic_bss->ni_chan->ic_freq)((__uint16_t)(ic->ic_bss->ni_chan->ic_freq));
1366 tap->wt_chan_flags = htole16(ic->ic_bss->ni_chan->ic_flags)((__uint16_t)(ic->ic_bss->ni_chan->ic_flags));
1367
1368 mb.m_datam_hdr.mh_data = (caddr_t)tap;
1369 mb.m_lenm_hdr.mh_len = sc->sc_txtap_len;
1370 mb.m_nextm_hdr.mh_next = m0;
1371 mb.m_nextpktm_hdr.mh_nextpkt = NULL((void *)0);
1372 mb.m_typem_hdr.mh_type = 0;
1373 mb.m_flagsm_hdr.mh_flags = 0;
1374 bpf_mtap(sc->sc_drvbpf, &mb, BPF_DIRECTION_OUT(1 << 1));
1375 }
1376#endif
1377
1378 paylen = m0->m_pkthdrM_dat.MH.MH_pkthdr.len;
1379 xferlen = sizeof (uint32_t) + sizeof (struct uath_tx_desc) + paylen;
1380
1381 wh = mtod(m0, struct ieee80211_frame *)((struct ieee80211_frame *)((m0)->m_hdr.mh_data));
1382 if (wh->i_fc[1] & IEEE80211_FC1_WEP0x40) {
1383 uint8_t *frm = (uint8_t *)(desc + 1);
1384 uint32_t iv;
1385
1386 /* h/w WEP: it's up to the host to fill the IV field */
1387 bcopy(wh, frm, sizeof (struct ieee80211_frame));
1388 frm += sizeof (struct ieee80211_frame);
1389
1390 /* insert IV: code copied from net80211 */
1391 iv = (ic->ic_iv != 0) ? ic->ic_iv : arc4random();
1392 if (iv >= 0x03ff00 && (iv & 0xf8ff00) == 0x00ff00)
1393 iv += 0x000100;
1394 ic->ic_iv = iv + 1;
1395
1396 *frm++ = iv & 0xff;
1397 *frm++ = (iv >> 8) & 0xff;
1398 *frm++ = (iv >> 16) & 0xff;
1399 *frm++ = ic->ic_wep_txkeyic_def_txkey << 6;
1400
1401 m_copydata(m0, sizeof(struct ieee80211_frame),
1402 m0->m_pkthdrM_dat.MH.MH_pkthdr.len - sizeof(struct ieee80211_frame), frm);
1403
1404 paylen += IEEE80211_WEP_IVLEN3 + IEEE80211_WEP_KIDLEN1;
1405 xferlen += IEEE80211_WEP_IVLEN3 + IEEE80211_WEP_KIDLEN1;
1406 totlen = xferlen + IEEE80211_WEP_CRCLEN4;
1407 } else {
1408 m_copydata(m0, 0, m0->m_pkthdrM_dat.MH.MH_pkthdr.len, desc + 1);
1409 totlen = xferlen;
1410 }
1411
1412 /* fill Tx descriptor */
1413 *(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))))
;
1414
1415 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))
;
1416 desc->priv = sc->data_idx; /* don't care about endianness */
1417 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))
;
1418 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))
;
1419 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
))
;
1420 if (IEEE80211_IS_MULTICAST(wh->i_addr1)(*(wh->i_addr1) & 0x01)) {
1421 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))
;
1422 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
))
;
1423 } else {
1424 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
))
;
1425 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
))
;
1426 }
1427
1428 m_freem(m0); /* mbuf is no longer needed */
1429
1430#ifdef UATH_DEBUG
1431 if (uath_debug >= 6) {
1432 printf("sending frame index=%u len=%d xferlen=%d",
1433 sc->data_idx, paylen, xferlen);
1434 uath_dump_cmd(data->buf, xferlen, '+');
1435 }
1436#endif
1437 usbd_setup_xfer(data->xfer, sc->data_tx_pipe, data, data->buf, xferlen,
1438 USBD_FORCE_SHORT_XFER0x08 | USBD_NO_COPY0x01, UATH_DATA_TIMEOUT10000,
1439 uath_data_txeof);
1440 error = usbd_transfer(data->xfer);
1441 if (error != USBD_IN_PROGRESS && error != 0) {
1442 ic->ic_ific_ac.ac_if.if_oerrorsif_data.ifi_oerrors++;
1443 return error;
1444 }
1445 sc->data_idx = (sc->data_idx + 1) % UATH_TX_DATA_LIST_COUNT8;
1446 sc->tx_queued++;
1447
1448 return 0;
1449}
1450
1451void
1452uath_start(struct ifnet *ifp)
1453{
1454 struct uath_softc *sc = ifp->if_softc;
1455 struct ieee80211com *ic = &sc->sc_ic;
1456 struct ieee80211_node *ni;
1457 struct mbuf *m0;
1458
1459 /*
1460 * net80211 may still try to send management frames even if the
1461 * IFF_RUNNING flag is not set...
1462 */
1463 if (!(ifp->if_flags & IFF_RUNNING0x40) && ifq_is_oactive(&ifp->if_snd))
1464 return;
1465
1466 for (;;) {
1467 if (sc->tx_queued >= UATH_TX_DATA_LIST_COUNT8) {
1468 ifq_set_oactive(&ifp->if_snd);
1469 break;
1470 }
1471
1472 m0 = mq_dequeue(&ic->ic_mgtq);
1473 if (m0 != NULL((void *)0)) {
1474 ni = m0->m_pkthdrM_dat.MH.MH_pkthdr.ph_cookie;
1475#if NBPFILTER1 > 0
1476 if (ic->ic_rawbpf != NULL((void *)0))
1477 bpf_mtap(ic->ic_rawbpf, m0, BPF_DIRECTION_OUT(1 << 1));
1478#endif
1479 if (uath_tx_data(sc, m0, ni) != 0)
1480 break;
1481 } else {
1482 if (ic->ic_state != IEEE80211_S_RUN)
1483 break;
1484
1485 m0 = ifq_dequeue(&ifp->if_snd);
1486 if (m0 == NULL((void *)0))
1487 break;
1488#if NBPFILTER1 > 0
1489 if (ifp->if_bpf != NULL((void *)0))
1490 bpf_mtap(ifp->if_bpf, m0, BPF_DIRECTION_OUT(1 << 1));
1491#endif
1492 m0 = ieee80211_encap(ifp, m0, &ni);
1493 if (m0 == NULL((void *)0))
1494 continue;
1495#if NBPFILTER1 > 0
1496 if (ic->ic_rawbpf != NULL((void *)0))
1497 bpf_mtap(ic->ic_rawbpf, m0, BPF_DIRECTION_OUT(1 << 1));
1498#endif
1499 if (uath_tx_data(sc, m0, ni) != 0) {
1500 if (ni != NULL((void *)0))
1501 ieee80211_release_node(ic, ni);
1502 ifp->if_oerrorsif_data.ifi_oerrors++;
1503 break;
1504 }
1505 }
1506
1507 sc->sc_tx_timer = 5;
1508 ifp->if_timer = 1;
1509 }
1510}
1511
1512void
1513uath_watchdog(struct ifnet *ifp)
1514{
1515 struct uath_softc *sc = ifp->if_softc;
1516
1517 ifp->if_timer = 0;
1518
1519 if (sc->sc_tx_timer > 0) {
1520 if (--sc->sc_tx_timer == 0) {
1521 printf("%s: device timeout\n", sc->sc_dev.dv_xname);
1522 /*uath_init(ifp); XXX needs a process context! */
1523 ifp->if_oerrorsif_data.ifi_oerrors++;
1524 return;
1525 }
1526 ifp->if_timer = 1;
1527 }
1528
1529 ieee80211_watchdog(ifp);
1530}
1531
1532int
1533uath_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
1534{
1535 int s, error = 0;
1536
1537 s = splnet()splraise(0x7);
1538
1539 switch (cmd) {
1540 case SIOCSIFADDR((unsigned long)0x80000000 | ((sizeof(struct ifreq) & 0x1fff
) << 16) | ((('i')) << 8) | ((12)))
:
1541 ifp->if_flags |= IFF_UP0x1;
1542 /* FALLTHROUGH */
1543 case SIOCSIFFLAGS((unsigned long)0x80000000 | ((sizeof(struct ifreq) & 0x1fff
) << 16) | ((('i')) << 8) | ((16)))
:
1544 if (ifp->if_flags & IFF_UP0x1) {
1545 if (!(ifp->if_flags & IFF_RUNNING0x40))
1546 uath_init(ifp);
1547 } else {
1548 if (ifp->if_flags & IFF_RUNNING0x40)
1549 uath_stop(ifp, 1);
1550 }
1551 break;
1552
1553 default:
1554 error = ieee80211_ioctl(ifp, cmd, data);
1555 }
1556
1557 if (error == ENETRESET52) {
1558 if ((ifp->if_flags & (IFF_UP0x1 | IFF_RUNNING0x40)) ==
1559 (IFF_UP0x1 | IFF_RUNNING0x40))
1560 uath_init(ifp);
1561 error = 0;
1562 }
1563
1564 splx(s)spllower(s);
1565
1566 return error;
1567}
1568
1569int
1570uath_query_eeprom(struct uath_softc *sc)
1571{
1572 uint32_t tmp;
1573 int error;
1574
1575 /* retrieve MAC address */
1576 error = uath_read_eeprom(sc, UATH_EEPROM_MACADDR0x0b, sc->sc_ic.ic_myaddr);
1577 if (error != 0) {
1578 printf("%s: could not read MAC address\n",
1579 sc->sc_dev.dv_xname);
1580 return error;
1581 }
1582
1583 /* retrieve the maximum frame size that the hardware can receive */
1584 error = uath_read_eeprom(sc, UATH_EEPROM_RXBUFSZ0x0f, &tmp);
1585 if (error != 0) {
1586 printf("%s: could not read maximum Rx buffer size\n",
1587 sc->sc_dev.dv_xname);
1588 return error;
1589 }
1590 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;
1591 DPRINTF(("maximum Rx buffer size %d\n", sc->rxbufsz));
1592 return 0;
1593}
1594
1595int
1596uath_reset(struct uath_softc *sc)
1597{
1598 struct uath_cmd_setup setup;
1599 uint32_t reg, val;
1600 int s, error;
1601
1602 /* init device with some voodoo incantations.. */
1603 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
))
;
1604 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
))
;
1605 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))
;
1606 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))
;
1607 s = splusb()splraise(0x5);
1608 error = uath_cmd_write(sc, UATH_CMD_SETUP0x01, &setup, sizeof setup,
1609 UATH_CMD_FLAG_ASYNC(1 << 0));
1610 /* ..and wait until firmware notifies us that it is ready */
1611 if (error == 0)
1612 error = tsleep_nsec(UATH_COND_INIT(sc)((caddr_t)sc + 1), PCATCH0x100, "uathinit",
1613 SEC_TO_NSEC(5));
1614 splx(s)spllower(s);
1615 if (error != 0)
1616 return error;
1617
1618 /* read PHY registers */
1619 for (reg = 0x09; reg <= 0x24; reg++) {
1620 if (reg == 0x0b || reg == 0x0c)
1621 continue;
1622 DELAY(100)(*delay_func)(100);
1623 if ((error = uath_read_reg(sc, reg, &val)) != 0)
1624 return error;
1625 DPRINTFN(2, ("reg 0x%02x=0x%08x\n", reg, val));
1626 }
1627 return error;
1628}
1629
1630int
1631uath_reset_tx_queues(struct uath_softc *sc)
1632{
1633 int ac, error;
1634
1635 for (ac = 0; ac < 4; ac++) {
1636 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)))
;
1637
1638 DPRINTF(("resetting Tx queue %d\n", UATH_AC_TO_QID(ac)));
1639 error = uath_cmd_write(sc, UATH_CMD_RESET_QUEUE0x3b, &qid,
1640 sizeof qid, 0);
1641 if (error != 0)
1642 break;
1643 }
1644 return error;
1645}
1646
1647int
1648uath_wme_init(struct uath_softc *sc)
1649{
1650 struct uath_qinfo qinfo;
1651 int ac, error;
1652 static const struct uath_wme_settings uath_wme_11g[4] = {
1653 { 7, 4, 10, 0, 0 }, /* Background */
1654 { 3, 4, 10, 0, 0 }, /* Best-Effort */
1655 { 3, 3, 4, 26, 0 }, /* Video */
1656 { 2, 2, 3, 47, 0 } /* Voice */
1657 };
1658
1659 bzero(&qinfo, sizeof qinfo)__builtin_bzero((&qinfo), (sizeof qinfo));
1660 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))
;
1661 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? */
1662 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
))
;
1663 for (ac = 0; ac < 4; ac++) {
1664 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)))
;
1665 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))
;
1666 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))
;
1667 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))
;
1668 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))
;
1669 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)))
1670 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)))
;
1671 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))
;
1672
1673 DPRINTF(("setting up Tx queue %d\n", UATH_AC_TO_QID(ac)));
1674 error = uath_cmd_write(sc, UATH_CMD_SET_QUEUE0x3a, &qinfo,
1675 sizeof qinfo, 0);
1676 if (error != 0)
1677 break;
1678 }
1679 return error;
1680}
1681
1682int
1683uath_set_chan(struct uath_softc *sc, struct ieee80211_channel *c)
1684{
1685 struct uath_set_chan chan;
1686
1687 bzero(&chan, sizeof chan)__builtin_bzero((&chan), (sizeof chan));
1688 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))
;
1689 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))
;
1690 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))
;
1691 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))
;
1692 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
))
;
1693
1694 DPRINTF(("switching to channel %d\n",
1695 ieee80211_chan2ieee(&sc->sc_ic, c)));
1696 return uath_cmd_write(sc, UATH_CMD_SET_CHAN0x34, &chan, sizeof chan, 0);
1697}
1698
1699int
1700uath_set_key(struct uath_softc *sc, const struct ieee80211_key *k, int index)
1701{
1702 struct uath_cmd_crypto crypto;
1703 int i;
1704
1705 bzero(&crypto, sizeof crypto)__builtin_bzero((&crypto), (sizeof crypto));
1706 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))
;
1707 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
))
;
1708 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))
;
1709 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))
;
1710 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))
;
1711 if (index != UATH_DEFAULT_KEY6)
1712 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))
;
1713 memset(crypto.magic2, 0xff, sizeof crypto.magic2)__builtin_memset((crypto.magic2), (0xff), (sizeof crypto.magic2
))
;
1714
1715 /*
1716 * Each byte of the key must be XOR'ed with 10101010 before being
1717 * transmitted to the firmware.
1718 */
1719 for (i = 0; i < k->k_len; i++)
1720 crypto.key[i] = k->k_key[i] ^ 0xaa;
1721
1722 DPRINTF(("setting crypto key index=%d len=%d\n", index, k->k_len));
1723 return uath_cmd_write(sc, UATH_CMD_CRYPTO0x1d, &crypto, sizeof crypto, 0);
1724}
1725
1726int
1727uath_set_keys(struct uath_softc *sc)
1728{
1729 const struct ieee80211com *ic = &sc->sc_ic;
1730 int i, error;
1731
1732 for (i = 0; i < IEEE80211_WEP_NKID4; i++) {
1733 const struct ieee80211_key *k = &ic->ic_nw_keys[i];
1734
1735 if (k->k_len > 0 && (error = uath_set_key(sc, k, i)) != 0)
1736 return error;
1737 }
1738 return uath_set_key(sc, &ic->ic_nw_keys[ic->ic_wep_txkeyic_def_txkey],
1739 UATH_DEFAULT_KEY6);
1740}
1741
1742int
1743uath_set_rates(struct uath_softc *sc, const struct ieee80211_rateset *rs)
1744{
1745 struct uath_cmd_rates rates;
1746
1747 bzero(&rates, sizeof rates)__builtin_bzero((&rates), (sizeof rates));
1748 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))
;
1749 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))
;
1750 rates.nrates = rs->rs_nrates;
1751 bcopy(rs->rs_rates, rates.rates, rs->rs_nrates);
1752
1753 DPRINTF(("setting supported rates nrates=%d\n", rs->rs_nrates));
1754 return uath_cmd_write(sc, UATH_CMD_SET_RATES0x26, &rates, sizeof rates, 0);
1755}
1756
1757int
1758uath_set_rxfilter(struct uath_softc *sc, uint32_t filter, uint32_t flags)
1759{
1760 struct uath_cmd_filter rxfilter;
1761
1762 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))
;
1763 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))
;
1764
1765 DPRINTF(("setting Rx filter=0x%x flags=0x%x\n", filter, flags));
1766 return uath_cmd_write(sc, UATH_CMD_SET_FILTER0x32, &rxfilter,
1767 sizeof rxfilter, 0);
1768}
1769
1770int
1771uath_set_led(struct uath_softc *sc, int which, int on)
1772{
1773 struct uath_cmd_led led;
1774
1775 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))
;
1776 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))
;
1777
1778 DPRINTFN(2, ("switching %s led %s\n",
1779 (which == UATH_LED_LINK) ? "link" : "activity",
1780 on ? "on" : "off"));
1781 return uath_cmd_write(sc, UATH_CMD_SET_LED0x17, &led, sizeof led, 0);
1782}
1783
1784int
1785uath_switch_channel(struct uath_softc *sc, struct ieee80211_channel *c)
1786{
1787 uint32_t val;
1788 int error;
1789
1790 /* set radio frequency */
1791 if ((error = uath_set_chan(sc, c)) != 0) {
1792 printf("%s: could not set channel\n", sc->sc_dev.dv_xname);
1793 return error;
1794 }
1795
1796 /* reset Tx rings */
1797 if ((error = uath_reset_tx_queues(sc)) != 0) {
1798 printf("%s: could not reset Tx queues\n",
1799 sc->sc_dev.dv_xname);
1800 return error;
1801 }
1802
1803 /* set Tx rings WME properties */
1804 if ((error = uath_wme_init(sc)) != 0) {
1805 printf("%s: could not init Tx queues\n",
1806 sc->sc_dev.dv_xname);
1807 return error;
1808 }
1809
1810 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
))
;
1811 error = uath_cmd_write(sc, UATH_CMD_SET_STATE0x20, &val, sizeof val, 0);
1812 if (error != 0) {
1813 printf("%s: could not set state\n", sc->sc_dev.dv_xname);
1814 return error;
1815 }
1816
1817 return uath_tx_null(sc);
1818}
1819
1820int
1821uath_init(struct ifnet *ifp)
1822{
1823 struct uath_softc *sc = ifp->if_softc;
1824 struct ieee80211com *ic = &sc->sc_ic;
1825 struct uath_cmd_31 cmd31;
1826 uint32_t val;
1827 int i, error;
1828
1829 /* reset data and command rings */
1830 sc->tx_queued = sc->data_idx = sc->cmd_idx = 0;
1831
1832 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
))
;
1833 (void)uath_cmd_write(sc, UATH_CMD_020x02, &val, sizeof val, 0);
1834
1835 /* set MAC address */
1836 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))
;
1837 (void)uath_write_multi(sc, 0x13, ic->ic_myaddr, IEEE80211_ADDR_LEN6);
1838
1839 (void)uath_write_reg(sc, 0x02, 0x00000001);
1840 (void)uath_write_reg(sc, 0x0e, 0x0000003f);
1841 (void)uath_write_reg(sc, 0x10, 0x00000001);
1842 (void)uath_write_reg(sc, 0x06, 0x0000001e);
1843
1844 /*
1845 * Queue Rx data xfers.
1846 */
1847 for (i = 0; i < UATH_RX_DATA_LIST_COUNT1; i++) {
1848 struct uath_rx_data *data = &sc->rx_data[i];
1849
1850 usbd_setup_xfer(data->xfer, sc->data_rx_pipe, data, data->buf,
1851 sc->rxbufsz, USBD_SHORT_XFER_OK0x04, USBD_NO_TIMEOUT0,
1852 uath_data_rxeof);
1853 error = usbd_transfer(data->xfer);
1854 if (error != USBD_IN_PROGRESS && error != 0) {
1855 printf("%s: could not queue Rx transfer\n",
1856 sc->sc_dev.dv_xname);
1857 goto fail;
1858 }
1859 }
1860
1861 error = uath_cmd_read(sc, UATH_CMD_070x07, NULL((void *)0), 0, &val,
1862 UATH_CMD_FLAG_MAGIC(1 << 2));
1863 if (error != 0) {
1864 printf("%s: could not send read command 07h\n",
1865 sc->sc_dev.dv_xname);
1866 goto fail;
1867 }
1868 DPRINTF(("command 07h return code: %x\n", betoh32(val)));
1869
1870 /* set default channel */
1871 ic->ic_bss->ni_chan = ic->ic_ibss_chan;
1872 if ((error = uath_set_chan(sc, ic->ic_bss->ni_chan)) != 0) {
1873 printf("%s: could not set channel\n", sc->sc_dev.dv_xname);
1874 goto fail;
1875 }
1876
1877 if ((error = uath_wme_init(sc)) != 0) {
1878 printf("%s: could not setup WME parameters\n",
1879 sc->sc_dev.dv_xname);
1880 goto fail;
1881 }
1882
1883 /* init MAC registers */
1884 (void)uath_write_reg(sc, 0x19, 0x00000000);
1885 (void)uath_write_reg(sc, 0x1a, 0x0000003c);
1886 (void)uath_write_reg(sc, 0x1b, 0x0000003c);
1887 (void)uath_write_reg(sc, 0x1c, 0x00000000);
1888 (void)uath_write_reg(sc, 0x1e, 0x00000000);
1889 (void)uath_write_reg(sc, 0x1f, 0x00000003);
1890 (void)uath_write_reg(sc, 0x0c, 0x00000000);
1891 (void)uath_write_reg(sc, 0x0f, 0x00000002);
1892 (void)uath_write_reg(sc, 0x0a, 0x00000007); /* XXX retry? */
1893 (void)uath_write_reg(sc, 0x09, ic->ic_rtsthreshold);
1894
1895 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
))
;
1896 (void)uath_cmd_write(sc, UATH_CMD_270x27, &val, sizeof val, 0);
1897 (void)uath_cmd_write(sc, UATH_CMD_270x27, &val, sizeof val, 0);
1898 (void)uath_cmd_write(sc, UATH_CMD_1B0x1b, NULL((void *)0), 0, 0);
1899
1900 if ((error = uath_set_keys(sc)) != 0) {
1901 printf("%s: could not set crypto keys\n",
1902 sc->sc_dev.dv_xname);
1903 goto fail;
1904 }
1905
1906 /* enable Rx */
1907 (void)uath_set_rxfilter(sc, 0x0000, 4);
1908 (void)uath_set_rxfilter(sc, 0x0817, 1);
1909
1910 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))
;
1911 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))
;
1912 (void)uath_cmd_write(sc, UATH_CMD_310x31, &cmd31, sizeof cmd31, 0);
1913
1914 ifp->if_flags |= IFF_RUNNING0x40;
1915 ifq_clr_oactive(&ifp->if_snd);
1916
1917 if (ic->ic_opmode == IEEE80211_M_MONITOR)
1918 ieee80211_new_state(ic, IEEE80211_S_RUN, -1)(((ic)->ic_newstate)((ic), (IEEE80211_S_RUN), (-1)));
1919 else
1920 ieee80211_new_state(ic, IEEE80211_S_SCAN, -1)(((ic)->ic_newstate)((ic), (IEEE80211_S_SCAN), (-1)));
1921
1922 return 0;
1923
1924fail: uath_stop(ifp, 1);
1925 return error;
1926}
1927
1928void
1929uath_stop(struct ifnet *ifp, int disable)
1930{
1931 struct uath_softc *sc = ifp->if_softc;
1932 struct ieee80211com *ic = &sc->sc_ic;
1933 uint32_t val;
1934 int s;
1935
1936 s = splusb()splraise(0x5);
1937
1938 sc->sc_tx_timer = 0;
1939 ifp->if_timer = 0;
1940 ifp->if_flags &= ~IFF_RUNNING0x40;
1941 ifq_clr_oactive(&ifp->if_snd);
1942
1943 ieee80211_new_state(ic, IEEE80211_S_INIT, -1)(((ic)->ic_newstate)((ic), (IEEE80211_S_INIT), (-1))); /* free all nodes */
1944
1945 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
))
;
1946 (void)uath_cmd_write(sc, UATH_CMD_SET_STATE0x20, &val, sizeof val, 0);
1947 (void)uath_cmd_write(sc, UATH_CMD_RESET0x35, NULL((void *)0), 0, 0);
1948
1949 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
))
;
1950 (void)uath_cmd_write(sc, UATH_CMD_150x15, &val, sizeof val, 0);
1951
1952#if 0
1953 (void)uath_cmd_read(sc, UATH_CMD_SHUTDOWN0x08, NULL((void *)0), 0, NULL((void *)0),
1954 UATH_CMD_FLAG_MAGIC(1 << 2));
1955#endif
1956
1957 /* abort any pending transfers */
1958 usbd_abort_pipe(sc->data_tx_pipe);
1959 usbd_abort_pipe(sc->data_rx_pipe);
1960 usbd_abort_pipe(sc->cmd_tx_pipe);
1961
1962 splx(s)spllower(s);
1963}
1964
1965/*
1966 * Load the MIPS R4000 microcode into the device. Once the image is loaded,
1967 * the device will detach itself from the bus and reattach later with a new
1968 * product Id (a la ezusb). XXX this could also be implemented in userland
1969 * through /dev/ugen.
1970 */
1971int
1972uath_loadfirmware(struct uath_softc *sc, const u_char *fw, int len)
1973{
1974 struct usbd_xfer *ctlxfer, *txxfer, *rxxfer;
1975 struct uath_fwblock *txblock, *rxblock;
1976 uint8_t *txdata;
1977 int error = 0;
1978
1979 if ((ctlxfer = usbd_alloc_xfer(sc->sc_udev)) == NULL((void *)0)) {
1980 printf("%s: could not allocate Tx control xfer\n",
1981 sc->sc_dev.dv_xname);
1982 error = USBD_NOMEM;
1983 goto fail1;
1984 }
1985 txblock = usbd_alloc_buffer(ctlxfer, sizeof (struct uath_fwblock));
1986 if (txblock == NULL((void *)0)) {
1987 printf("%s: could not allocate Tx control block\n",
1988 sc->sc_dev.dv_xname);
1989 error = USBD_NOMEM;
1990 goto fail2;
1991 }
1992
1993 if ((txxfer = usbd_alloc_xfer(sc->sc_udev)) == NULL((void *)0)) {
1994 printf("%s: could not allocate Tx xfer\n",
1995 sc->sc_dev.dv_xname);
1996 error = USBD_NOMEM;
1997 goto fail2;
1998 }
1999 txdata = usbd_alloc_buffer(txxfer, UATH_MAX_FWBLOCK_SIZE2048);
2000 if (txdata == NULL((void *)0)) {
2001 printf("%s: could not allocate Tx buffer\n",
2002 sc->sc_dev.dv_xname);
2003 error = USBD_NOMEM;
2004 goto fail3;
2005 }
2006
2007 if ((rxxfer = usbd_alloc_xfer(sc->sc_udev)) == NULL((void *)0)) {
2008 printf("%s: could not allocate Rx control xfer\n",
2009 sc->sc_dev.dv_xname);
2010 error = USBD_NOMEM;
2011 goto fail3;
2012 }
2013 rxblock = usbd_alloc_buffer(rxxfer, sizeof (struct uath_fwblock));
2014 if (rxblock == NULL((void *)0)) {
2015 printf("%s: could not allocate Rx control block\n",
2016 sc->sc_dev.dv_xname);
2017 error = USBD_NOMEM;
2018 goto fail4;
2019 }
2020
2021 bzero(txblock, sizeof (struct uath_fwblock))__builtin_bzero((txblock), (sizeof (struct uath_fwblock)));
2022 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
)))
;
2023 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))
;
2024
2025 while (len > 0) {
2026 int mlen = min(len, UATH_MAX_FWBLOCK_SIZE2048);
2027
2028 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))
;
2029 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))
;
2030
2031 DPRINTF(("sending firmware block: %d bytes remaining\n",
2032 len - mlen));
2033
2034 /* send firmware block meta-data */
2035 usbd_setup_xfer(ctlxfer, sc->cmd_tx_pipe, sc, txblock,
2036 sizeof (struct uath_fwblock),
2037 USBD_NO_COPY0x01 | USBD_SYNCHRONOUS0x02,
2038 UATH_CMD_TIMEOUT1000, NULL((void *)0));
2039 if ((error = usbd_transfer(ctlxfer)) != 0) {
2040 printf("%s: could not send firmware block info\n",
2041 sc->sc_dev.dv_xname);
2042 break;
2043 }
2044
2045 /* send firmware block data */
2046 bcopy(fw, txdata, mlen);
2047 usbd_setup_xfer(txxfer, sc->data_tx_pipe, sc, txdata, mlen,
2048 USBD_NO_COPY0x01 | USBD_SYNCHRONOUS0x02, UATH_DATA_TIMEOUT10000, NULL((void *)0));
2049 if ((error = usbd_transfer(txxfer)) != 0) {
2050 printf("%s: could not send firmware block data\n",
2051 sc->sc_dev.dv_xname);
2052 break;
2053 }
2054
2055 /* wait for ack from firmware */
2056 usbd_setup_xfer(rxxfer, sc->cmd_rx_pipe, sc, rxblock,
2057 sizeof (struct uath_fwblock), USBD_SHORT_XFER_OK0x04 |
2058 USBD_NO_COPY0x01 | USBD_SYNCHRONOUS0x02, UATH_CMD_TIMEOUT1000, NULL((void *)0));
2059 if ((error = usbd_transfer(rxxfer)) != 0) {
2060 printf("%s: could not read firmware answer\n",
2061 sc->sc_dev.dv_xname);
2062 break;
2063 }
2064
2065 DPRINTFN(2, ("rxblock flags=0x%x total=%d\n",
2066 betoh32(rxblock->flags), betoh32(rxblock->rxtotal)));
2067 fw += mlen;
2068 len -= mlen;
2069 }
2070
2071fail4: usbd_free_xfer(rxxfer);
2072fail3: usbd_free_xfer(txxfer);
2073fail2: usbd_free_xfer(ctlxfer);
2074fail1: return error;
2075}