Bug Summary

File:dev/usb/if_athn_usb.c
Warning:line 1618, column 25
Value stored to 'usc' during its initialization 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_athn_usb.c -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model static -mframe-pointer=all -relaxed-aliasing -fno-rounding-math -mconstructor-aliases -ffreestanding -mcmodel=kernel -target-cpu x86-64 -target-feature +retpoline-indirect-calls -target-feature +retpoline-indirect-branches -target-feature -sse2 -target-feature -sse -target-feature -3dnow -target-feature -mmx -target-feature +save-args -disable-red-zone -no-implicit-float -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/usr/src/sys/arch/amd64/compile/GENERIC.MP/obj -nostdsysteminc -nobuiltininc -resource-dir /usr/local/lib/clang/13.0.0 -I /usr/src/sys -I /usr/src/sys/arch/amd64/compile/GENERIC.MP/obj -I /usr/src/sys/arch -I /usr/src/sys/dev/pci/drm/include -I /usr/src/sys/dev/pci/drm/include/uapi -I /usr/src/sys/dev/pci/drm/amd/include/asic_reg -I /usr/src/sys/dev/pci/drm/amd/include -I /usr/src/sys/dev/pci/drm/amd/amdgpu -I /usr/src/sys/dev/pci/drm/amd/display -I /usr/src/sys/dev/pci/drm/amd/display/include -I /usr/src/sys/dev/pci/drm/amd/display/dc -I /usr/src/sys/dev/pci/drm/amd/display/amdgpu_dm -I /usr/src/sys/dev/pci/drm/amd/pm/inc -I /usr/src/sys/dev/pci/drm/amd/pm/swsmu -I /usr/src/sys/dev/pci/drm/amd/pm/swsmu/smu11 -I /usr/src/sys/dev/pci/drm/amd/pm/swsmu/smu12 -I /usr/src/sys/dev/pci/drm/amd/pm/powerplay -I /usr/src/sys/dev/pci/drm/amd/pm/powerplay/hwmgr -I /usr/src/sys/dev/pci/drm/amd/pm/powerplay/smumgr -I /usr/src/sys/dev/pci/drm/amd/display/dc/inc -I /usr/src/sys/dev/pci/drm/amd/display/dc/inc/hw -I /usr/src/sys/dev/pci/drm/amd/display/dc/clk_mgr -I /usr/src/sys/dev/pci/drm/amd/display/modules/inc -I /usr/src/sys/dev/pci/drm/amd/display/modules/hdcp -I /usr/src/sys/dev/pci/drm/amd/display/dmub/inc -I /usr/src/sys/dev/pci/drm/i915 -D DDB -D DIAGNOSTIC -D KTRACE -D ACCOUNTING -D KMEMSTATS -D PTRACE -D POOL_DEBUG -D CRYPTO -D SYSVMSG -D SYSVSEM -D SYSVSHM -D UVM_SWAP_ENCRYPT -D FFS -D FFS2 -D FFS_SOFTUPDATES -D UFS_DIRHASH -D QUOTA -D EXT2FS -D MFS -D NFSCLIENT -D NFSSERVER -D CD9660 -D UDF -D MSDOSFS -D FIFO -D FUSE -D SOCKET_SPLICE -D TCP_ECN -D TCP_SIGNATURE -D INET6 -D IPSEC -D PPP_BSDCOMP -D PPP_DEFLATE -D PIPEX -D MROUTING -D MPLS -D BOOT_CONFIG -D USER_PCICONF -D APERTURE -D MTRR -D NTFS -D HIBERNATE -D PCIVERBOSE -D USBVERBOSE -D WSDISPLAY_COMPAT_USL -D WSDISPLAY_COMPAT_RAWKBD -D WSDISPLAY_DEFAULTSCREENS=6 -D X86EMU -D ONEWIREVERBOSE -D MULTIPROCESSOR -D MAXUSERS=80 -D _KERNEL -D CONFIG_DRM_AMD_DC_DCN3_0 -O2 -Wno-pointer-sign -Wno-address-of-packed-member -Wno-constant-conversion -Wno-unused-but-set-variable -Wno-gnu-folding-constant -fdebug-compilation-dir=/usr/src/sys/arch/amd64/compile/GENERIC.MP/obj -ferror-limit 19 -fwrapv -D_RET_PROTECTOR -ret-protector -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -fno-builtin-malloc -fno-builtin-calloc -fno-builtin-realloc -fno-builtin-valloc -fno-builtin-free -fno-builtin-strdup -fno-builtin-strndup -analyzer-output=html -faddrsig -o /usr/obj/sys/arch/amd64/compile/GENERIC.MP/scan-build/2022-01-12-131800-47421-1 -x c /usr/src/sys/dev/usb/if_athn_usb.c
1/* $OpenBSD: if_athn_usb.c,v 1.63 2021/11/22 10:17:14 mglocker Exp $ */
2
3/*-
4 * Copyright (c) 2011 Damien Bergamini <damien.bergamini@free.fr>
5 * Copyright (c) 2018 Stefan Sperling <stsp@openbsd.org>
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 * USB front-end for Atheros AR9271 and AR7010 chipsets.
22 */
23
24#include "bpfilter.h"
25
26#include <sys/param.h>
27#include <sys/sockio.h>
28#include <sys/mbuf.h>
29#include <sys/kernel.h>
30#include <sys/socket.h>
31#include <sys/systm.h>
32#include <sys/timeout.h>
33#include <sys/conf.h>
34#include <sys/device.h>
35#include <sys/endian.h>
36
37#include <machine/bus.h>
38#include <machine/intr.h>
39
40#if NBPFILTER1 > 0
41#include <net/bpf.h>
42#endif
43#include <net/if.h>
44#include <net/if_dl.h>
45#include <net/if_media.h>
46
47#include <netinet/in.h>
48#include <netinet/if_ether.h>
49
50#include <net80211/ieee80211_var.h>
51#include <net80211/ieee80211_amrr.h>
52#include <net80211/ieee80211_ra.h>
53#include <net80211/ieee80211_radiotap.h>
54
55#include <dev/ic/athnreg.h>
56#include <dev/ic/ar5008reg.h>
57#include <dev/ic/athnvar.h>
58
59#include <dev/usb/usb.h>
60#include <dev/usb/usbdi.h>
61#include <dev/usb/usbdi_util.h>
62#include <dev/usb/usbdevs.h>
63
64#include <dev/usb/if_athn_usb.h>
65
66static const struct athn_usb_type {
67 struct usb_devno devno;
68 u_int flags;
69} athn_usb_devs[] = {
70 {{ USB_VENDOR_ACCTON0x083a, USB_PRODUCT_ACCTON_AR92800xa704 },
71 ATHN_USB_FLAG_AR70100x01 },
72 {{ USB_VENDOR_ACTIONTEC0x1668, USB_PRODUCT_ACTIONTEC_AR92870x1200 },
73 ATHN_USB_FLAG_AR70100x01 },
74 {{ USB_VENDOR_ATHEROS20x0cf3, USB_PRODUCT_ATHEROS2_AR9271_10x1006 }},
75 {{ USB_VENDOR_ATHEROS20x0cf3, USB_PRODUCT_ATHEROS2_AR9271_20x9271 }},
76 {{ USB_VENDOR_ATHEROS20x0cf3, USB_PRODUCT_ATHEROS2_AR9271_30xb003 }},
77 {{ USB_VENDOR_ATHEROS20x0cf3, USB_PRODUCT_ATHEROS2_AR92800x7010 },
78 ATHN_USB_FLAG_AR70100x01 },
79 {{ USB_VENDOR_ATHEROS20x0cf3, USB_PRODUCT_ATHEROS2_AR92870x7015 },
80 ATHN_USB_FLAG_AR70100x01 },
81 {{ USB_VENDOR_AZUREWAVE0x13d3, USB_PRODUCT_AZUREWAVE_AR9271_10x3327 }},
82 {{ USB_VENDOR_AZUREWAVE0x13d3, USB_PRODUCT_AZUREWAVE_AR9271_20x3328 }},
83 {{ USB_VENDOR_AZUREWAVE0x13d3, USB_PRODUCT_AZUREWAVE_AR9271_30x3346 }},
84 {{ USB_VENDOR_AZUREWAVE0x13d3, USB_PRODUCT_AZUREWAVE_AR9271_40x3348 }},
85 {{ USB_VENDOR_AZUREWAVE0x13d3, USB_PRODUCT_AZUREWAVE_AR9271_50x3349 }},
86 {{ USB_VENDOR_AZUREWAVE0x13d3, USB_PRODUCT_AZUREWAVE_AR9271_60x3350 }},
87 {{ USB_VENDOR_DLINK20x07d1, USB_PRODUCT_DLINK2_AR92710x3a10 }},
88 {{ USB_VENDOR_LITEON0x04ca, USB_PRODUCT_LITEON_AR92710x4605 }},
89 {{ USB_VENDOR_NETGEAR0x0846, USB_PRODUCT_NETGEAR_WNA11000x9030 }},
90 {{ USB_VENDOR_NETGEAR0x0846, USB_PRODUCT_NETGEAR_WNDA32000x9018 },
91 ATHN_USB_FLAG_AR70100x01 },
92 {{ USB_VENDOR_PANASONIC0x04da, USB_PRODUCT_PANASONIC_N5HBZ00000550x3904 },
93 ATHN_USB_FLAG_AR70100x01 },
94 {{ USB_VENDOR_MELCO0x0411, USB_PRODUCT_MELCO_UWABR1000x017f },
95 ATHN_USB_FLAG_AR70100x01 },
96 {{ USB_VENDOR_VIA0x040d, USB_PRODUCT_VIA_AR92710x3801 }}
97};
98#define athn_usb_lookup(v, p)((const struct athn_usb_type *)usbd_match_device((const struct
usb_devno *)(athn_usb_devs), sizeof (athn_usb_devs) / sizeof
((athn_usb_devs)[0]), sizeof ((athn_usb_devs)[0]), (v), (p))
)
\
99 ((const struct athn_usb_type *)usb_lookup(athn_usb_devs, v, p)usbd_match_device((const struct usb_devno *)(athn_usb_devs), sizeof
(athn_usb_devs) / sizeof ((athn_usb_devs)[0]), sizeof ((athn_usb_devs
)[0]), (v), (p))
)
100
101int athn_usb_match(struct device *, void *, void *);
102void athn_usb_attach(struct device *, struct device *, void *);
103int athn_usb_detach(struct device *, int);
104void athn_usb_attachhook(struct device *);
105int athn_usb_open_pipes(struct athn_usb_softc *);
106void athn_usb_close_pipes(struct athn_usb_softc *);
107int athn_usb_alloc_rx_list(struct athn_usb_softc *);
108void athn_usb_free_rx_list(struct athn_usb_softc *);
109int athn_usb_alloc_tx_list(struct athn_usb_softc *);
110void athn_usb_free_tx_list(struct athn_usb_softc *);
111int athn_usb_alloc_tx_cmd(struct athn_usb_softc *);
112void athn_usb_free_tx_cmd(struct athn_usb_softc *);
113void athn_usb_task(void *);
114void athn_usb_do_async(struct athn_usb_softc *,
115 void (*)(struct athn_usb_softc *, void *), void *, int);
116void athn_usb_wait_async(struct athn_usb_softc *);
117int athn_usb_load_firmware(struct athn_usb_softc *);
118int athn_usb_htc_msg(struct athn_usb_softc *, uint16_t, void *,
119 int);
120int athn_usb_htc_setup(struct athn_usb_softc *);
121int athn_usb_htc_connect_svc(struct athn_usb_softc *, uint16_t,
122 uint8_t, uint8_t, uint8_t *);
123int athn_usb_wmi_xcmd(struct athn_usb_softc *, uint16_t, void *,
124 int, void *);
125int athn_usb_read_rom(struct athn_softc *);
126uint32_t athn_usb_read(struct athn_softc *, uint32_t);
127void athn_usb_write(struct athn_softc *, uint32_t, uint32_t);
128void athn_usb_write_barrier(struct athn_softc *);
129int athn_usb_media_change(struct ifnet *);
130void athn_usb_next_scan(void *);
131int athn_usb_newstate(struct ieee80211com *, enum ieee80211_state,
132 int);
133void athn_usb_newstate_cb(struct athn_usb_softc *, void *);
134void athn_usb_newassoc(struct ieee80211com *,
135 struct ieee80211_node *, int);
136void athn_usb_newassoc_cb(struct athn_usb_softc *, void *);
137struct ieee80211_node *athn_usb_node_alloc(struct ieee80211com *);
138void athn_usb_count_active_sta(void *, struct ieee80211_node *);
139void athn_usb_newauth_cb(struct athn_usb_softc *, void *);
140int athn_usb_newauth(struct ieee80211com *,
141 struct ieee80211_node *, int, uint16_t);
142void athn_usb_node_free(struct ieee80211com *,
143 struct ieee80211_node *);
144void athn_usb_node_free_cb(struct athn_usb_softc *, void *);
145int athn_usb_ampdu_tx_start(struct ieee80211com *,
146 struct ieee80211_node *, uint8_t);
147void athn_usb_ampdu_tx_start_cb(struct athn_usb_softc *, void *);
148void athn_usb_ampdu_tx_stop(struct ieee80211com *,
149 struct ieee80211_node *, uint8_t);
150void athn_usb_ampdu_tx_stop_cb(struct athn_usb_softc *, void *);
151void athn_usb_clean_nodes(void *, struct ieee80211_node *);
152int athn_usb_create_node(struct athn_usb_softc *,
153 struct ieee80211_node *);
154int athn_usb_node_set_rates(struct athn_usb_softc *,
155 struct ieee80211_node *);
156int athn_usb_remove_node(struct athn_usb_softc *,
157 struct ieee80211_node *);
158void athn_usb_rx_enable(struct athn_softc *);
159int athn_set_chan(struct athn_softc *, struct ieee80211_channel *,
160 struct ieee80211_channel *);
161int athn_usb_switch_chan(struct athn_softc *,
162 struct ieee80211_channel *, struct ieee80211_channel *);
163void athn_usb_updateedca(struct ieee80211com *);
164void athn_usb_updateedca_cb(struct athn_usb_softc *, void *);
165void athn_usb_updateslot(struct ieee80211com *);
166void athn_usb_updateslot_cb(struct athn_usb_softc *, void *);
167int athn_usb_set_key(struct ieee80211com *,
168 struct ieee80211_node *, struct ieee80211_key *);
169void athn_usb_set_key_cb(struct athn_usb_softc *, void *);
170void athn_usb_delete_key(struct ieee80211com *,
171 struct ieee80211_node *, struct ieee80211_key *);
172void athn_usb_delete_key_cb(struct athn_usb_softc *, void *);
173void athn_usb_bcneof(struct usbd_xfer *, void *,
174 usbd_status);
175void athn_usb_swba(struct athn_usb_softc *);
176void athn_usb_tx_status(void *, struct ieee80211_node *);
177void athn_usb_rx_wmi_ctrl(struct athn_usb_softc *, uint8_t *, int);
178void athn_usb_intr(struct usbd_xfer *, void *,
179 usbd_status);
180void athn_usb_rx_radiotap(struct athn_softc *, struct mbuf *,
181 struct ar_rx_status *);
182void athn_usb_rx_frame(struct athn_usb_softc *, struct mbuf *,
183 struct mbuf_list *);
184void athn_usb_rxeof(struct usbd_xfer *, void *,
185 usbd_status);
186void athn_usb_txeof(struct usbd_xfer *, void *,
187 usbd_status);
188int athn_usb_tx(struct athn_softc *, struct mbuf *,
189 struct ieee80211_node *);
190void athn_usb_start(struct ifnet *);
191void athn_usb_watchdog(struct ifnet *);
192int athn_usb_ioctl(struct ifnet *, u_long, caddr_t);
193int athn_usb_init(struct ifnet *);
194void athn_usb_stop(struct ifnet *);
195void ar9271_load_ani(struct athn_softc *);
196int ar5008_ccmp_decap(struct athn_softc *, struct mbuf *,
197 struct ieee80211_node *);
198int ar5008_ccmp_encap(struct mbuf *, u_int, struct ieee80211_key *);
199
200/* Shortcut. */
201#define athn_usb_wmi_cmd(sc, cmd_id)athn_usb_wmi_xcmd(sc, cmd_id, ((void *)0), 0, ((void *)0)) \
202 athn_usb_wmi_xcmd(sc, cmd_id, NULL((void *)0), 0, NULL((void *)0))
203
204/* Extern functions. */
205void athn_led_init(struct athn_softc *);
206void athn_set_led(struct athn_softc *, int);
207void athn_btcoex_init(struct athn_softc *);
208void athn_set_rxfilter(struct athn_softc *, uint32_t);
209int athn_reset(struct athn_softc *, int);
210void athn_init_pll(struct athn_softc *,
211 const struct ieee80211_channel *);
212int athn_set_power_awake(struct athn_softc *);
213void athn_set_power_sleep(struct athn_softc *);
214void athn_reset_key(struct athn_softc *, int);
215int athn_set_key(struct ieee80211com *, struct ieee80211_node *,
216 struct ieee80211_key *);
217void athn_delete_key(struct ieee80211com *, struct ieee80211_node *,
218 struct ieee80211_key *);
219void athn_rx_start(struct athn_softc *);
220void athn_set_sta_timers(struct athn_softc *);
221void athn_set_hostap_timers(struct athn_softc *);
222void athn_set_opmode(struct athn_softc *);
223void athn_set_bss(struct athn_softc *, struct ieee80211_node *);
224int athn_hw_reset(struct athn_softc *, struct ieee80211_channel *,
225 struct ieee80211_channel *, int);
226void athn_updateedca(struct ieee80211com *);
227void athn_updateslot(struct ieee80211com *);
228
229const struct cfattach athn_usb_ca = {
230 sizeof(struct athn_usb_softc),
231 athn_usb_match,
232 athn_usb_attach,
233 athn_usb_detach
234};
235
236int
237athn_usb_match(struct device *parent, void *match, void *aux)
238{
239 struct usb_attach_arg *uaa = aux;
240
241 if (uaa->iface == NULL((void *)0) || uaa->configno != 1)
242 return (UMATCH_NONE0);
243
244 return ((athn_usb_lookup(uaa->vendor, uaa->product)((const struct athn_usb_type *)usbd_match_device((const struct
usb_devno *)(athn_usb_devs), sizeof (athn_usb_devs) / sizeof
((athn_usb_devs)[0]), sizeof ((athn_usb_devs)[0]), (uaa->
vendor), (uaa->product)))
!= NULL((void *)0)) ?
245 UMATCH_VENDOR_PRODUCT_CONF_IFACE8 : UMATCH_NONE0);
246}
247
248void
249athn_usb_attach(struct device *parent, struct device *self, void *aux)
250{
251 struct athn_usb_softc *usc = (struct athn_usb_softc *)self;
252 struct athn_softc *sc = &usc->sc_sc;
253 struct usb_attach_arg *uaa = aux;
254
255 usc->sc_udev = uaa->device;
256 usc->sc_iface = uaa->iface;
257
258 usc->flags = athn_usb_lookup(uaa->vendor, uaa->product)((const struct athn_usb_type *)usbd_match_device((const struct
usb_devno *)(athn_usb_devs), sizeof (athn_usb_devs) / sizeof
((athn_usb_devs)[0]), sizeof ((athn_usb_devs)[0]), (uaa->
vendor), (uaa->product)))
->flags;
259 sc->flags |= ATHN_FLAG_USB(1 << 1);
260#ifdef notyet
261 /* Check if it is a combo WiFi+Bluetooth (WB193) device. */
262 if (strncmp(product, "wb193", 5) == 0)
263 sc->flags |= ATHN_FLAG_BTCOEX3WIRE(1 << 8);
264#endif
265
266 sc->ops.read = athn_usb_read;
267 sc->ops.write = athn_usb_write;
268 sc->ops.write_barrier = athn_usb_write_barrier;
269
270 usb_init_task(&usc->sc_task, athn_usb_task, sc, USB_TASK_TYPE_GENERIC)((&usc->sc_task)->fun = (athn_usb_task), (&usc->
sc_task)->arg = (sc), (&usc->sc_task)->type = (0
), (&usc->sc_task)->state = 0x0)
;
271
272 if (athn_usb_open_pipes(usc) != 0)
273 return;
274
275 /* Allocate xfer for firmware commands. */
276 if (athn_usb_alloc_tx_cmd(usc) != 0)
277 return;
278
279 config_mountroot(self, athn_usb_attachhook);
280}
281
282int
283athn_usb_detach(struct device *self, int flags)
284{
285 struct athn_usb_softc *usc = (struct athn_usb_softc *)self;
286 struct athn_softc *sc = &usc->sc_sc;
287
288 if (usc->sc_athn_attached)
289 athn_detach(sc);
290
291 /* Wait for all async commands to complete. */
292 athn_usb_wait_async(usc);
293
294 usbd_ref_wait(usc->sc_udev);
295
296 /* Abort and close Tx/Rx pipes. */
297 athn_usb_close_pipes(usc);
298
299 /* Free Tx/Rx buffers. */
300 athn_usb_free_tx_cmd(usc);
301 athn_usb_free_tx_list(usc);
302 athn_usb_free_rx_list(usc);
303
304 return (0);
305}
306
307void
308athn_usb_attachhook(struct device *self)
309{
310 struct athn_usb_softc *usc = (struct athn_usb_softc *)self;
311 struct athn_softc *sc = &usc->sc_sc;
312 struct athn_ops *ops = &sc->ops;
313 struct ieee80211com *ic = &sc->sc_ic;
314 struct ifnet *ifp = &ic->ic_ific_ac.ac_if;
315 int s, i, error;
316
317 /* Load firmware. */
318 error = athn_usb_load_firmware(usc);
319 if (error != 0) {
320 printf("%s: could not load firmware\n", sc->sc_dev.dv_xname);
321 return;
322 }
323
324 /* Setup the host transport communication interface. */
325 error = athn_usb_htc_setup(usc);
326 if (error != 0)
327 return;
328
329 /* We're now ready to attach the bus agnostic driver. */
330 s = splnet()splraise(0x7);
331 error = athn_attach(sc);
332 if (error != 0) {
333 splx(s)spllower(s);
334 return;
335 }
336 usc->sc_athn_attached = 1;
337 /* Override some operations for USB. */
338 ifp->if_ioctl = athn_usb_ioctl;
339 ifp->if_start = athn_usb_start;
340 ifp->if_watchdog = athn_usb_watchdog;
341 ic->ic_node_alloc = athn_usb_node_alloc;
342 ic->ic_newauth = athn_usb_newauth;
343 ic->ic_newassoc = athn_usb_newassoc;
344#ifndef IEEE80211_STA_ONLY
345 usc->sc_node_free = ic->ic_node_free;
346 ic->ic_node_free = athn_usb_node_free;
347#endif
348 ic->ic_updateslot = athn_usb_updateslot;
349 ic->ic_updateedca = athn_usb_updateedca;
350 ic->ic_set_key = athn_usb_set_key;
351 ic->ic_delete_key = athn_usb_delete_key;
352#ifdef notyet
353 ic->ic_ampdu_tx_start = athn_usb_ampdu_tx_start;
354 ic->ic_ampdu_tx_stop = athn_usb_ampdu_tx_stop;
355#endif
356 ic->ic_newstate = athn_usb_newstate;
357 ic->ic_media.ifm_change = athn_usb_media_change;
358 timeout_set(&sc->scan_to, athn_usb_next_scan, usc);
359
360 ops->rx_enable = athn_usb_rx_enable;
361 splx(s)spllower(s);
362
363 /* Reset HW key cache entries. */
364 for (i = 0; i < sc->kc_entries; i++)
365 athn_reset_key(sc, i);
366
367 ops->enable_antenna_diversity(sc);
368
369#ifdef ATHN_BT_COEXISTENCE
370 /* Configure bluetooth coexistence for combo chips. */
371 if (sc->flags & ATHN_FLAG_BTCOEX((1 << 7) | (1 << 8)))
372 athn_btcoex_init(sc);
373#endif
374 /* Configure LED. */
375 athn_led_init(sc);
376}
377
378int
379athn_usb_open_pipes(struct athn_usb_softc *usc)
380{
381 usb_endpoint_descriptor_t *ed;
382 int isize, error;
383
384 error = usbd_open_pipe(usc->sc_iface, AR_PIPE_TX_DATA(0x00 | 1), 0,
385 &usc->tx_data_pipe);
386 if (error != 0) {
387 printf("%s: could not open Tx bulk pipe\n",
388 usc->usb_devsc_sc.sc_dev.dv_xname);
389 goto fail;
390 }
391
392 error = usbd_open_pipe(usc->sc_iface, AR_PIPE_RX_DATA(0x80 | 2), 0,
393 &usc->rx_data_pipe);
394 if (error != 0) {
395 printf("%s: could not open Rx bulk pipe\n",
396 usc->usb_devsc_sc.sc_dev.dv_xname);
397 goto fail;
398 }
399
400 ed = usbd_get_endpoint_descriptor(usc->sc_iface, AR_PIPE_RX_INTR(0x80 | 3));
401 if (ed == NULL((void *)0)) {
402 printf("%s: could not retrieve Rx intr pipe descriptor\n",
403 usc->usb_devsc_sc.sc_dev.dv_xname);
404 goto fail;
405 }
406 isize = UGETW(ed->wMaxPacketSize)(*(u_int16_t *)(ed->wMaxPacketSize));
407 if (isize == 0) {
408 printf("%s: invalid Rx intr pipe descriptor\n",
409 usc->usb_devsc_sc.sc_dev.dv_xname);
410 goto fail;
411 }
412 usc->ibuf = malloc(isize, M_USBDEV102, M_NOWAIT0x0002);
413 if (usc->ibuf == NULL((void *)0)) {
414 printf("%s: could not allocate Rx intr buffer\n",
415 usc->usb_devsc_sc.sc_dev.dv_xname);
416 goto fail;
417 }
418 usc->ibuflen = isize;
419 error = usbd_open_pipe_intr(usc->sc_iface, AR_PIPE_RX_INTR(0x80 | 3),
420 USBD_SHORT_XFER_OK0x04, &usc->rx_intr_pipe, usc, usc->ibuf, isize,
421 athn_usb_intr, USBD_DEFAULT_INTERVAL(-1));
422 if (error != 0) {
423 printf("%s: could not open Rx intr pipe\n",
424 usc->usb_devsc_sc.sc_dev.dv_xname);
425 goto fail;
426 }
427
428 error = usbd_open_pipe(usc->sc_iface, AR_PIPE_TX_INTR(0x00 | 4), 0,
429 &usc->tx_intr_pipe);
430 if (error != 0) {
431 printf("%s: could not open Tx intr pipe\n",
432 usc->usb_devsc_sc.sc_dev.dv_xname);
433 goto fail;
434 }
435 fail:
436 if (error != 0)
437 athn_usb_close_pipes(usc);
438 return (error);
439}
440
441void
442athn_usb_close_pipes(struct athn_usb_softc *usc)
443{
444 if (usc->tx_data_pipe != NULL((void *)0)) {
445 usbd_close_pipe(usc->tx_data_pipe);
446 usc->tx_data_pipe = NULL((void *)0);
447 }
448 if (usc->rx_data_pipe != NULL((void *)0)) {
449 usbd_close_pipe(usc->rx_data_pipe);
450 usc->rx_data_pipe = NULL((void *)0);
451 }
452 if (usc->tx_intr_pipe != NULL((void *)0)) {
453 usbd_close_pipe(usc->tx_intr_pipe);
454 usc->tx_intr_pipe = NULL((void *)0);
455 }
456 if (usc->rx_intr_pipe != NULL((void *)0)) {
457 usbd_close_pipe(usc->rx_intr_pipe);
458 usc->rx_intr_pipe = NULL((void *)0);
459 }
460 if (usc->ibuf != NULL((void *)0)) {
461 free(usc->ibuf, M_USBDEV102, usc->ibuflen);
462 usc->ibuf = NULL((void *)0);
463 }
464}
465
466int
467athn_usb_alloc_rx_list(struct athn_usb_softc *usc)
468{
469 struct athn_usb_rx_data *data;
470 int i, error = 0;
471
472 for (i = 0; i < ATHN_USB_RX_LIST_COUNT1; i++) {
473 data = &usc->rx_data[i];
474
475 data->sc = usc; /* Backpointer for callbacks. */
476
477 data->xfer = usbd_alloc_xfer(usc->sc_udev);
478 if (data->xfer == NULL((void *)0)) {
479 printf("%s: could not allocate xfer\n",
480 usc->usb_devsc_sc.sc_dev.dv_xname);
481 error = ENOMEM12;
482 break;
483 }
484 data->buf = usbd_alloc_buffer(data->xfer, ATHN_USB_RXBUFSZ(8 * 1024));
485 if (data->buf == NULL((void *)0)) {
486 printf("%s: could not allocate xfer buffer\n",
487 usc->usb_devsc_sc.sc_dev.dv_xname);
488 error = ENOMEM12;
489 break;
490 }
491 }
492 if (error != 0)
493 athn_usb_free_rx_list(usc);
494 return (error);
495}
496
497void
498athn_usb_free_rx_list(struct athn_usb_softc *usc)
499{
500 int i;
501
502 /* NB: Caller must abort pipe first. */
503 for (i = 0; i < ATHN_USB_RX_LIST_COUNT1; i++) {
504 if (usc->rx_data[i].xfer != NULL((void *)0))
505 usbd_free_xfer(usc->rx_data[i].xfer);
506 usc->rx_data[i].xfer = NULL((void *)0);
507 }
508}
509
510int
511athn_usb_alloc_tx_list(struct athn_usb_softc *usc)
512{
513 struct athn_usb_tx_data *data;
514 int i, error = 0;
515
516 TAILQ_INIT(&usc->tx_free_list)do { (&usc->tx_free_list)->tqh_first = ((void *)0);
(&usc->tx_free_list)->tqh_last = &(&usc->
tx_free_list)->tqh_first; } while (0)
;
517 for (i = 0; i < ATHN_USB_TX_LIST_COUNT(8 + 1); i++) {
518 data = &usc->tx_data[i];
519
520 data->sc = usc; /* Backpointer for callbacks. */
521
522 data->xfer = usbd_alloc_xfer(usc->sc_udev);
523 if (data->xfer == NULL((void *)0)) {
524 printf("%s: could not allocate xfer\n",
525 usc->usb_devsc_sc.sc_dev.dv_xname);
526 error = ENOMEM12;
527 break;
528 }
529 data->buf = usbd_alloc_buffer(data->xfer, ATHN_USB_TXBUFSZ((sizeof(struct ar_stream_hdr) + sizeof(struct ar_htc_frame_hdr
) + sizeof(struct ar_tx_frame) + (2300 + 4 + (3 + 1 + 4)) + 3
) & ~3)
);
530 if (data->buf == NULL((void *)0)) {
531 printf("%s: could not allocate xfer buffer\n",
532 usc->usb_devsc_sc.sc_dev.dv_xname);
533 error = ENOMEM12;
534 break;
535 }
536 /* Append this Tx buffer to our free list. */
537 TAILQ_INSERT_TAIL(&usc->tx_free_list, data, next)do { (data)->next.tqe_next = ((void *)0); (data)->next.
tqe_prev = (&usc->tx_free_list)->tqh_last; *(&usc
->tx_free_list)->tqh_last = (data); (&usc->tx_free_list
)->tqh_last = &(data)->next.tqe_next; } while (0)
;
538 }
539 if (error != 0)
540 athn_usb_free_tx_list(usc);
541 return (error);
542}
543
544void
545athn_usb_free_tx_list(struct athn_usb_softc *usc)
546{
547 int i;
548
549 /* NB: Caller must abort pipe first. */
550 for (i = 0; i < ATHN_USB_TX_LIST_COUNT(8 + 1); i++) {
551 if (usc->tx_data[i].xfer != NULL((void *)0))
552 usbd_free_xfer(usc->tx_data[i].xfer);
553 usc->tx_data[i].xfer = NULL((void *)0);
554 }
555}
556
557int
558athn_usb_alloc_tx_cmd(struct athn_usb_softc *usc)
559{
560 struct athn_usb_tx_data *data = &usc->tx_cmd;
561
562 data->sc = usc; /* Backpointer for callbacks. */
563
564 data->xfer = usbd_alloc_xfer(usc->sc_udev);
565 if (data->xfer == NULL((void *)0)) {
566 printf("%s: could not allocate xfer\n",
567 usc->usb_devsc_sc.sc_dev.dv_xname);
568 return (ENOMEM12);
569 }
570 data->buf = usbd_alloc_buffer(data->xfer, ATHN_USB_TXCMDSZ512);
571 if (data->buf == NULL((void *)0)) {
572 printf("%s: could not allocate xfer buffer\n",
573 usc->usb_devsc_sc.sc_dev.dv_xname);
574 return (ENOMEM12);
575 }
576 return (0);
577}
578
579void
580athn_usb_free_tx_cmd(struct athn_usb_softc *usc)
581{
582 if (usc->tx_cmd.xfer != NULL((void *)0))
583 usbd_free_xfer(usc->tx_cmd.xfer);
584 usc->tx_cmd.xfer = NULL((void *)0);
585}
586
587void
588athn_usb_task(void *arg)
589{
590 struct athn_usb_softc *usc = arg;
591 struct athn_usb_host_cmd_ring *ring = &usc->cmdq;
592 struct athn_usb_host_cmd *cmd;
593 int s;
594
595 /* Process host commands. */
596 s = splusb()splraise(0x5);
597 while (ring->next != ring->cur) {
598 cmd = &ring->cmd[ring->next];
599 splx(s)spllower(s);
600 /* Invoke callback. */
601 cmd->cb(usc, cmd->data);
602 s = splusb()splraise(0x5);
603 ring->queued--;
604 ring->next = (ring->next + 1) % ATHN_USB_HOST_CMD_RING_COUNT32;
605 }
606 splx(s)spllower(s);
607}
608
609void
610athn_usb_do_async(struct athn_usb_softc *usc,
611 void (*cb)(struct athn_usb_softc *, void *), void *arg, int len)
612{
613 struct athn_usb_host_cmd_ring *ring = &usc->cmdq;
614 struct athn_usb_host_cmd *cmd;
615 int s;
616
617 if (ring->queued == ATHN_USB_HOST_CMD_RING_COUNT32) {
618 printf("%s: host cmd queue overrun\n", usc->usb_devsc_sc.sc_dev.dv_xname);
619 return; /* XXX */
620 }
621
622 s = splusb()splraise(0x5);
623 cmd = &ring->cmd[ring->cur];
624 cmd->cb = cb;
625 KASSERT(len <= sizeof(cmd->data))((len <= sizeof(cmd->data)) ? (void)0 : __assert("diagnostic "
, "/usr/src/sys/dev/usb/if_athn_usb.c", 625, "len <= sizeof(cmd->data)"
))
;
626 memcpy(cmd->data, arg, len)__builtin_memcpy((cmd->data), (arg), (len));
627 ring->cur = (ring->cur + 1) % ATHN_USB_HOST_CMD_RING_COUNT32;
628
629 /* If there is no pending command already, schedule a task. */
630 if (++ring->queued == 1)
631 usb_add_task(usc->sc_udev, &usc->sc_task);
632 splx(s)spllower(s);
633}
634
635void
636athn_usb_wait_async(struct athn_usb_softc *usc)
637{
638 /* Wait for all queued asynchronous commands to complete. */
639 usb_wait_task(usc->sc_udev, &usc->sc_task);
640}
641
642int
643athn_usb_load_firmware(struct athn_usb_softc *usc)
644{
645 usb_device_descriptor_t *dd;
646 usb_device_request_t req;
647 const char *name;
648 u_char *fw, *ptr;
649 size_t fwsize, size;
650 uint32_t addr;
651 int s, mlen, error;
652
653 /* Determine which firmware image to load. */
654 if (usc->flags & ATHN_USB_FLAG_AR70100x01) {
655 dd = usbd_get_device_descriptor(usc->sc_udev);
656 name = "athn-open-ar7010";
657 } else
658 name = "athn-open-ar9271";
659 /* Read firmware image from the filesystem. */
660 if ((error = loadfirmware(name, &fw, &fwsize)) != 0) {
661 printf("%s: failed loadfirmware of file %s (error %d)\n",
662 usc->usb_devsc_sc.sc_dev.dv_xname, name, error);
663 return (error);
664 }
665 /* Load firmware image. */
666 ptr = fw;
667 addr = AR9271_FIRMWARE0x501000 >> 8;
668 req.bmRequestType = UT_WRITE_VENDOR_DEVICE(0x00 | 0x40 | 0x00);
669 req.bRequest = AR_FW_DOWNLOAD0x30;
670 USETW(req.wIndex, 0)(*(u_int16_t *)(req.wIndex) = (0));
671 size = fwsize;
672 while (size > 0) {
673 mlen = MIN(size, 4096)(((size)<(4096))?(size):(4096));
674
675 USETW(req.wValue, addr)(*(u_int16_t *)(req.wValue) = (addr));
676 USETW(req.wLength, mlen)(*(u_int16_t *)(req.wLength) = (mlen));
677 error = usbd_do_request(usc->sc_udev, &req, ptr);
678 if (error != 0) {
679 free(fw, M_DEVBUF2, fwsize);
680 return (error);
681 }
682 addr += mlen >> 8;
683 ptr += mlen;
684 size -= mlen;
685 }
686 free(fw, M_DEVBUF2, fwsize);
687
688 /* Start firmware. */
689 if (usc->flags & ATHN_USB_FLAG_AR70100x01)
690 addr = AR7010_FIRMWARE_TEXT0x906000 >> 8;
691 else
692 addr = AR9271_FIRMWARE_TEXT0x903000 >> 8;
693 req.bmRequestType = UT_WRITE_VENDOR_DEVICE(0x00 | 0x40 | 0x00);
694 req.bRequest = AR_FW_DOWNLOAD_COMP0x31;
695 USETW(req.wIndex, 0)(*(u_int16_t *)(req.wIndex) = (0));
696 USETW(req.wValue, addr)(*(u_int16_t *)(req.wValue) = (addr));
697 USETW(req.wLength, 0)(*(u_int16_t *)(req.wLength) = (0));
698 s = splusb()splraise(0x5);
699 usc->wait_msg_id = AR_HTC_MSG_READY0x0001;
700 error = usbd_do_request(usc->sc_udev, &req, NULL((void *)0));
701 /* Wait at most 1 second for firmware to boot. */
702 if (error == 0 && usc->wait_msg_id != 0)
703 error = tsleep_nsec(&usc->wait_msg_id, 0, "athnfw",
704 SEC_TO_NSEC(1));
705 usc->wait_msg_id = 0;
706 splx(s)spllower(s);
707 return (error);
708}
709
710int
711athn_usb_htc_msg(struct athn_usb_softc *usc, uint16_t msg_id, void *buf,
712 int len)
713{
714 struct athn_usb_tx_data *data = &usc->tx_cmd;
715 struct ar_htc_frame_hdr *htc;
716 struct ar_htc_msg_hdr *msg;
717
718 htc = (struct ar_htc_frame_hdr *)data->buf;
719 memset(htc, 0, sizeof(*htc))__builtin_memset((htc), (0), (sizeof(*htc)));
720 htc->endpoint_id = 0;
721 htc->payload_len = htobe16(sizeof(*msg) + len)(__uint16_t)(__builtin_constant_p(sizeof(*msg) + len) ? (__uint16_t
)(((__uint16_t)(sizeof(*msg) + len) & 0xffU) << 8 |
((__uint16_t)(sizeof(*msg) + len) & 0xff00U) >> 8)
: __swap16md(sizeof(*msg) + len))
;
722
723 msg = (struct ar_htc_msg_hdr *)&htc[1];
724 msg->msg_id = htobe16(msg_id)(__uint16_t)(__builtin_constant_p(msg_id) ? (__uint16_t)(((__uint16_t
)(msg_id) & 0xffU) << 8 | ((__uint16_t)(msg_id) &
0xff00U) >> 8) : __swap16md(msg_id))
;
725
726 memcpy(&msg[1], buf, len)__builtin_memcpy((&msg[1]), (buf), (len));
727
728 usbd_setup_xfer(data->xfer, usc->tx_intr_pipe, NULL((void *)0), data->buf,
729 sizeof(*htc) + sizeof(*msg) + len,
730 USBD_SHORT_XFER_OK0x04 | USBD_NO_COPY0x01 | USBD_SYNCHRONOUS0x02,
731 ATHN_USB_CMD_TIMEOUT1000, NULL((void *)0));
732 return (usbd_transfer(data->xfer));
733}
734
735int
736athn_usb_htc_setup(struct athn_usb_softc *usc)
737{
738 struct ar_htc_msg_config_pipe cfg;
739 int s, error;
740
741 /*
742 * Connect WMI services to USB pipes.
743 */
744 error = athn_usb_htc_connect_svc(usc, AR_SVC_WMI_CONTROL((1) << 8 | (0)),
745 AR_PIPE_TX_INTR(0x00 | 4), AR_PIPE_RX_INTR(0x80 | 3), &usc->ep_ctrl);
746 if (error != 0)
747 return (error);
748 error = athn_usb_htc_connect_svc(usc, AR_SVC_WMI_BEACON((1) << 8 | (1)),
749 AR_PIPE_TX_DATA(0x00 | 1), AR_PIPE_RX_DATA(0x80 | 2), &usc->ep_bcn);
750 if (error != 0)
751 return (error);
752 error = athn_usb_htc_connect_svc(usc, AR_SVC_WMI_CAB((1) << 8 | (2)),
753 AR_PIPE_TX_DATA(0x00 | 1), AR_PIPE_RX_DATA(0x80 | 2), &usc->ep_cab);
754 if (error != 0)
755 return (error);
756 error = athn_usb_htc_connect_svc(usc, AR_SVC_WMI_UAPSD((1) << 8 | (3)),
757 AR_PIPE_TX_DATA(0x00 | 1), AR_PIPE_RX_DATA(0x80 | 2), &usc->ep_uapsd);
758 if (error != 0)
759 return (error);
760 error = athn_usb_htc_connect_svc(usc, AR_SVC_WMI_MGMT((1) << 8 | (4)),
761 AR_PIPE_TX_DATA(0x00 | 1), AR_PIPE_RX_DATA(0x80 | 2), &usc->ep_mgmt);
762 if (error != 0)
763 return (error);
764 error = athn_usb_htc_connect_svc(usc, AR_SVC_WMI_DATA_BE((1) << 8 | (7)),
765 AR_PIPE_TX_DATA(0x00 | 1), AR_PIPE_RX_DATA(0x80 | 2), &usc->ep_data[EDCA_AC_BE]);
766 if (error != 0)
767 return (error);
768 error = athn_usb_htc_connect_svc(usc, AR_SVC_WMI_DATA_BK((1) << 8 | (8)),
769 AR_PIPE_TX_DATA(0x00 | 1), AR_PIPE_RX_DATA(0x80 | 2), &usc->ep_data[EDCA_AC_BK]);
770 if (error != 0)
771 return (error);
772 error = athn_usb_htc_connect_svc(usc, AR_SVC_WMI_DATA_VI((1) << 8 | (6)),
773 AR_PIPE_TX_DATA(0x00 | 1), AR_PIPE_RX_DATA(0x80 | 2), &usc->ep_data[EDCA_AC_VI]);
774 if (error != 0)
775 return (error);
776 error = athn_usb_htc_connect_svc(usc, AR_SVC_WMI_DATA_VO((1) << 8 | (5)),
777 AR_PIPE_TX_DATA(0x00 | 1), AR_PIPE_RX_DATA(0x80 | 2), &usc->ep_data[EDCA_AC_VO]);
778 if (error != 0)
779 return (error);
780
781 /* Set credits for WLAN Tx pipe. */
782 memset(&cfg, 0, sizeof(cfg))__builtin_memset((&cfg), (0), (sizeof(cfg)));
783 cfg.pipe_id = UE_GET_ADDR(AR_PIPE_TX_DATA)(((0x00 | 1)) & 0x0f);
784 cfg.credits = (usc->flags & ATHN_USB_FLAG_AR70100x01) ? 45 : 33;
785 s = splusb()splraise(0x5);
786 usc->wait_msg_id = AR_HTC_MSG_CONF_PIPE_RSP0x0006;
787 error = athn_usb_htc_msg(usc, AR_HTC_MSG_CONF_PIPE0x0005, &cfg, sizeof(cfg));
788 if (error == 0 && usc->wait_msg_id != 0)
789 error = tsleep_nsec(&usc->wait_msg_id, 0, "athnhtc",
790 SEC_TO_NSEC(1));
791 usc->wait_msg_id = 0;
792 splx(s)spllower(s);
793 if (error != 0) {
794 printf("%s: could not configure pipe\n",
795 usc->usb_devsc_sc.sc_dev.dv_xname);
796 return (error);
797 }
798
799 error = athn_usb_htc_msg(usc, AR_HTC_MSG_SETUP_COMPLETE0x0004, NULL((void *)0), 0);
800 if (error != 0) {
801 printf("%s: could not complete setup\n",
802 usc->usb_devsc_sc.sc_dev.dv_xname);
803 return (error);
804 }
805 return (0);
806}
807
808int
809athn_usb_htc_connect_svc(struct athn_usb_softc *usc, uint16_t svc_id,
810 uint8_t ul_pipe, uint8_t dl_pipe, uint8_t *endpoint_id)
811{
812 struct ar_htc_msg_conn_svc msg;
813 struct ar_htc_msg_conn_svc_rsp rsp;
814 int s, error;
815
816 memset(&msg, 0, sizeof(msg))__builtin_memset((&msg), (0), (sizeof(msg)));
817 msg.svc_id = htobe16(svc_id)(__uint16_t)(__builtin_constant_p(svc_id) ? (__uint16_t)(((__uint16_t
)(svc_id) & 0xffU) << 8 | ((__uint16_t)(svc_id) &
0xff00U) >> 8) : __swap16md(svc_id))
;
818 msg.dl_pipeid = UE_GET_ADDR(dl_pipe)((dl_pipe) & 0x0f);
819 msg.ul_pipeid = UE_GET_ADDR(ul_pipe)((ul_pipe) & 0x0f);
820 s = splusb()splraise(0x5);
821 usc->msg_conn_svc_rsp = &rsp;
822 usc->wait_msg_id = AR_HTC_MSG_CONN_SVC_RSP0x0003;
823 error = athn_usb_htc_msg(usc, AR_HTC_MSG_CONN_SVC0x0002, &msg, sizeof(msg));
824 /* Wait at most 1 second for response. */
825 if (error == 0 && usc->wait_msg_id != 0)
826 error = tsleep_nsec(&usc->wait_msg_id, 0, "athnhtc",
827 SEC_TO_NSEC(1));
828 usc->wait_msg_id = 0;
829 splx(s)spllower(s);
830 if (error != 0) {
831 printf("%s: error waiting for service %d connection\n",
832 usc->usb_devsc_sc.sc_dev.dv_xname, svc_id);
833 return (error);
834 }
835 if (rsp.status != AR_HTC_SVC_SUCCESS0) {
836 printf("%s: service %d connection failed, error %d\n",
837 usc->usb_devsc_sc.sc_dev.dv_xname, svc_id, rsp.status);
838 return (EIO5);
839 }
840 DPRINTF(("service %d successfully connected to endpoint %d\n",
841 svc_id, rsp.endpoint_id));
842
843 /* Return endpoint id. */
844 *endpoint_id = rsp.endpoint_id;
845 return (0);
846}
847
848int
849athn_usb_wmi_xcmd(struct athn_usb_softc *usc, uint16_t cmd_id, void *ibuf,
850 int ilen, void *obuf)
851{
852 struct athn_usb_tx_data *data = &usc->tx_cmd;
853 struct ar_htc_frame_hdr *htc;
854 struct ar_wmi_cmd_hdr *wmi;
855 int s, error;
856
857 if (usbd_is_dying(usc->sc_udev))
858 return ENXIO6;
859
860 s = splusb()splraise(0x5);
861 while (usc->wait_cmd_id) {
862 /*
863 * The previous USB transfer is not done yet. We can't use
864 * data->xfer until it is done or we'll cause major confusion
865 * in the USB stack.
866 */
867 tsleep_nsec(&usc->wait_cmd_id, 0, "athnwmx",
868 MSEC_TO_NSEC(ATHN_USB_CMD_TIMEOUT1000));
869 if (usbd_is_dying(usc->sc_udev)) {
870 splx(s)spllower(s);
871 return ENXIO6;
872 }
873 }
874 splx(s)spllower(s);
875
876 htc = (struct ar_htc_frame_hdr *)data->buf;
877 memset(htc, 0, sizeof(*htc))__builtin_memset((htc), (0), (sizeof(*htc)));
878 htc->endpoint_id = usc->ep_ctrl;
879 htc->payload_len = htobe16(sizeof(*wmi) + ilen)(__uint16_t)(__builtin_constant_p(sizeof(*wmi) + ilen) ? (__uint16_t
)(((__uint16_t)(sizeof(*wmi) + ilen) & 0xffU) << 8 |
((__uint16_t)(sizeof(*wmi) + ilen) & 0xff00U) >> 8
) : __swap16md(sizeof(*wmi) + ilen))
;
880
881 wmi = (struct ar_wmi_cmd_hdr *)&htc[1];
882 wmi->cmd_id = htobe16(cmd_id)(__uint16_t)(__builtin_constant_p(cmd_id) ? (__uint16_t)(((__uint16_t
)(cmd_id) & 0xffU) << 8 | ((__uint16_t)(cmd_id) &
0xff00U) >> 8) : __swap16md(cmd_id))
;
883 usc->wmi_seq_no++;
884 wmi->seq_no = htobe16(usc->wmi_seq_no)(__uint16_t)(__builtin_constant_p(usc->wmi_seq_no) ? (__uint16_t
)(((__uint16_t)(usc->wmi_seq_no) & 0xffU) << 8 |
((__uint16_t)(usc->wmi_seq_no) & 0xff00U) >> 8)
: __swap16md(usc->wmi_seq_no))
;
885
886 memcpy(&wmi[1], ibuf, ilen)__builtin_memcpy((&wmi[1]), (ibuf), (ilen));
887
888 usbd_setup_xfer(data->xfer, usc->tx_intr_pipe, NULL((void *)0), data->buf,
889 sizeof(*htc) + sizeof(*wmi) + ilen,
890 USBD_SHORT_XFER_OK0x04 | USBD_NO_COPY0x01, ATHN_USB_CMD_TIMEOUT1000,
891 NULL((void *)0));
892 s = splusb()splraise(0x5);
893 error = usbd_transfer(data->xfer);
894 if (__predict_false(error != USBD_IN_PROGRESS && error != 0)__builtin_expect(((error != USBD_IN_PROGRESS && error
!= 0) != 0), 0)
) {
895 splx(s)spllower(s);
896 return (error);
897 }
898 usc->obuf = obuf;
899 usc->wait_cmd_id = cmd_id;
900 /*
901 * Wait for WMI command complete interrupt. In case it does not fire
902 * wait until the USB transfer times out to avoid racing the transfer.
903 */
904 error = tsleep_nsec(&usc->wait_cmd_id, 0, "athnwmi",
905 MSEC_TO_NSEC(ATHN_USB_CMD_TIMEOUT1000));
906 if (error) {
907 if (error == EWOULDBLOCK35) {
908 printf("%s: firmware command 0x%x timed out\n",
909 usc->usb_devsc_sc.sc_dev.dv_xname, cmd_id);
910 error = ETIMEDOUT60;
911 }
912 }
913
914 /*
915 * Both the WMI command and transfer are done or have timed out.
916 * Allow other threads to enter this function and use data->xfer.
917 */
918 usc->wait_cmd_id = 0;
919 wakeup(&usc->wait_cmd_id);
920
921 splx(s)spllower(s);
922 return (error);
923}
924
925int
926athn_usb_read_rom(struct athn_softc *sc)
927{
928 struct athn_usb_softc *usc = (struct athn_usb_softc *)sc;
929 uint32_t addrs[8], vals[8], addr;
930 uint16_t *eep;
931 int i, j, error;
932
933 /* Read EEPROM by blocks of 16 bytes. */
934 eep = sc->eep;
935 addr = AR_EEPROM_OFFSET(sc->eep_base)(0x2000 + (sc->eep_base) * 4);
936 for (i = 0; i < sc->eep_size / 16; i++) {
937 for (j = 0; j < 8; j++, addr += 4)
938 addrs[j] = htobe32(addr)(__uint32_t)(__builtin_constant_p(addr) ? (__uint32_t)(((__uint32_t
)(addr) & 0xff) << 24 | ((__uint32_t)(addr) & 0xff00
) << 8 | ((__uint32_t)(addr) & 0xff0000) >> 8
| ((__uint32_t)(addr) & 0xff000000) >> 24) : __swap32md
(addr))
;
939 error = athn_usb_wmi_xcmd(usc, AR_WMI_CMD_REG_READ0x014,
940 addrs, sizeof(addrs), vals);
941 if (error != 0)
942 break;
943 for (j = 0; j < 8; j++)
944 *eep++ = betoh32(vals[j])(__uint32_t)(__builtin_constant_p(vals[j]) ? (__uint32_t)(((__uint32_t
)(vals[j]) & 0xff) << 24 | ((__uint32_t)(vals[j]) &
0xff00) << 8 | ((__uint32_t)(vals[j]) & 0xff0000) >>
8 | ((__uint32_t)(vals[j]) & 0xff000000) >> 24) : __swap32md
(vals[j]))
;
945 }
946 return (error);
947}
948
949uint32_t
950athn_usb_read(struct athn_softc *sc, uint32_t addr)
951{
952 struct athn_usb_softc *usc = (struct athn_usb_softc *)sc;
953 uint32_t val;
954 int error;
955
956 /* Flush pending writes for strict consistency. */
957 athn_usb_write_barrier(sc);
958
959 addr = htobe32(addr)(__uint32_t)(__builtin_constant_p(addr) ? (__uint32_t)(((__uint32_t
)(addr) & 0xff) << 24 | ((__uint32_t)(addr) & 0xff00
) << 8 | ((__uint32_t)(addr) & 0xff0000) >> 8
| ((__uint32_t)(addr) & 0xff000000) >> 24) : __swap32md
(addr))
;
960 error = athn_usb_wmi_xcmd(usc, AR_WMI_CMD_REG_READ0x014,
961 &addr, sizeof(addr), &val);
962 if (error != 0)
963 return (0xdeadbeef);
964 return (betoh32(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))
);
965}
966
967void
968athn_usb_write(struct athn_softc *sc, uint32_t addr, uint32_t val)
969{
970 struct athn_usb_softc *usc = (struct athn_usb_softc *)sc;
971
972 usc->wbuf[usc->wcount].addr = htobe32(addr)(__uint32_t)(__builtin_constant_p(addr) ? (__uint32_t)(((__uint32_t
)(addr) & 0xff) << 24 | ((__uint32_t)(addr) & 0xff00
) << 8 | ((__uint32_t)(addr) & 0xff0000) >> 8
| ((__uint32_t)(addr) & 0xff000000) >> 24) : __swap32md
(addr))
;
973 usc->wbuf[usc->wcount].val = 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))
;
974 if (++usc->wcount == AR_MAX_WRITE_COUNT32)
975 athn_usb_write_barrier(sc);
976}
977
978void
979athn_usb_write_barrier(struct athn_softc *sc)
980{
981 struct athn_usb_softc *usc = (struct athn_usb_softc *)sc;
982
983 if (usc->wcount == 0)
984 return; /* Nothing to write. */
985
986 (void)athn_usb_wmi_xcmd(usc, AR_WMI_CMD_REG_WRITE0x015,
987 usc->wbuf, usc->wcount * sizeof(usc->wbuf[0]), NULL((void *)0));
988 usc->wcount = 0; /* Always flush buffer. */
989}
990
991int
992athn_usb_media_change(struct ifnet *ifp)
993{
994 struct athn_usb_softc *usc = (struct athn_usb_softc *)ifp->if_softc;
995 int error;
996
997 if (usbd_is_dying(usc->sc_udev))
998 return ENXIO6;
999
1000 error = ieee80211_media_change(ifp);
1001 if (error != ENETRESET52)
1002 return (error);
1003
1004 if ((ifp->if_flags & (IFF_UP0x1 | IFF_RUNNING0x40)) ==
1005 (IFF_UP0x1 | IFF_RUNNING0x40)) {
1006 athn_usb_stop(ifp);
1007 error = athn_usb_init(ifp);
1008 }
1009 return (error);
1010}
1011
1012void
1013athn_usb_next_scan(void *arg)
1014{
1015 struct athn_usb_softc *usc = arg;
1016 struct athn_softc *sc = &usc->sc_sc;
1017 struct ieee80211com *ic = &sc->sc_ic;
1018 int s;
1019
1020 if (usbd_is_dying(usc->sc_udev))
1021 return;
1022
1023 usbd_ref_incr(usc->sc_udev);
1024
1025 s = splnet()splraise(0x7);
1026 if (ic->ic_state == IEEE80211_S_SCAN)
1027 ieee80211_next_scan(&ic->ic_ific_ac.ac_if);
1028 splx(s)spllower(s);
1029
1030 usbd_ref_decr(usc->sc_udev);
1031}
1032
1033int
1034athn_usb_newstate(struct ieee80211com *ic, enum ieee80211_state nstate,
1035 int arg)
1036{
1037 struct athn_usb_softc *usc = ic->ic_softcic_ac.ac_if.if_softc;
1038 struct athn_usb_cmd_newstate cmd;
1039
1040 /* Do it in a process context. */
1041 cmd.state = nstate;
1042 cmd.arg = arg;
1043 athn_usb_do_async(usc, athn_usb_newstate_cb, &cmd, sizeof(cmd));
1044 return (0);
1045}
1046
1047void
1048athn_usb_newstate_cb(struct athn_usb_softc *usc, void *arg)
1049{
1050 struct athn_usb_cmd_newstate *cmd = arg;
1051 struct athn_softc *sc = &usc->sc_sc;
1052 struct ieee80211com *ic = &sc->sc_ic;
1053 enum ieee80211_state ostate;
1054 uint32_t reg, imask;
1055 int s, error;
1056
1057 timeout_del(&sc->calib_to);
1058
1059 s = splnet()splraise(0x7);
1060 ostate = ic->ic_state;
1061
1062 if (ostate == IEEE80211_S_RUN && ic->ic_opmode == IEEE80211_M_STA) {
1063 athn_usb_remove_node(usc, ic->ic_bss);
1064 reg = AR_READ(sc, AR_RX_FILTER)(sc)->ops.read((sc), (0x803c));
1065 reg = (reg & ~AR_RX_FILTER_MYBEACON0x00000200) |
1066 AR_RX_FILTER_BEACON0x00000010;
1067 AR_WRITE(sc, AR_RX_FILTER, reg)(sc)->ops.write((sc), (0x803c), (reg));
1068 AR_WRITE_BARRIER(sc)(sc)->ops.write_barrier((sc));
1069 }
1070 switch (cmd->state) {
1071 case IEEE80211_S_INIT:
1072 athn_set_led(sc, 0);
1073 break;
1074 case IEEE80211_S_SCAN:
1075 /* Make the LED blink while scanning. */
1076 athn_set_led(sc, !sc->led_state);
1077 error = athn_usb_switch_chan(sc, ic->ic_bss->ni_chan, NULL((void *)0));
1078 if (error)
1079 printf("%s: could not switch to channel %d\n",
1080 usc->usb_devsc_sc.sc_dev.dv_xname,
1081 ieee80211_chan2ieee(ic, ic->ic_bss->ni_chan));
1082 if (!usbd_is_dying(usc->sc_udev))
1083 timeout_add_msec(&sc->scan_to, 200);
1084 break;
1085 case IEEE80211_S_AUTH:
1086 athn_set_led(sc, 0);
1087 error = athn_usb_switch_chan(sc, ic->ic_bss->ni_chan, NULL((void *)0));
1088 if (error)
1089 printf("%s: could not switch to channel %d\n",
1090 usc->usb_devsc_sc.sc_dev.dv_xname,
1091 ieee80211_chan2ieee(ic, ic->ic_bss->ni_chan));
1092 break;
1093 case IEEE80211_S_ASSOC:
1094 break;
1095 case IEEE80211_S_RUN:
1096 athn_set_led(sc, 1);
1097
1098 if (ic->ic_opmode == IEEE80211_M_MONITOR)
1099 break;
1100
1101 if (ic->ic_opmode == IEEE80211_M_STA) {
1102 /* Create node entry for our BSS */
1103 error = athn_usb_create_node(usc, ic->ic_bss);
1104 if (error)
1105 printf("%s: could not update firmware station "
1106 "table\n", usc->usb_devsc_sc.sc_dev.dv_xname);
1107 }
1108 athn_set_bss(sc, ic->ic_bss);
1109 athn_usb_wmi_cmd(usc, AR_WMI_CMD_DISABLE_INTR)athn_usb_wmi_xcmd(usc, 0x004, ((void *)0), 0, ((void *)0));
1110#ifndef IEEE80211_STA_ONLY
1111 if (ic->ic_opmode == IEEE80211_M_HOSTAP) {
1112 athn_usb_switch_chan(sc, ic->ic_bss->ni_chan, NULL((void *)0));
1113 athn_set_hostap_timers(sc);
1114 /* Enable software beacon alert interrupts. */
1115 imask = htobe32(AR_IMR_SWBA)(__uint32_t)(__builtin_constant_p(0x00010000) ? (__uint32_t)(
((__uint32_t)(0x00010000) & 0xff) << 24 | ((__uint32_t
)(0x00010000) & 0xff00) << 8 | ((__uint32_t)(0x00010000
) & 0xff0000) >> 8 | ((__uint32_t)(0x00010000) &
0xff000000) >> 24) : __swap32md(0x00010000))
;
1116 } else
1117#endif
1118 {
1119 athn_set_sta_timers(sc);
1120 /* Enable beacon miss interrupts. */
1121 imask = htobe32(AR_IMR_BMISS)(__uint32_t)(__builtin_constant_p(0x00040000) ? (__uint32_t)(
((__uint32_t)(0x00040000) & 0xff) << 24 | ((__uint32_t
)(0x00040000) & 0xff00) << 8 | ((__uint32_t)(0x00040000
) & 0xff0000) >> 8 | ((__uint32_t)(0x00040000) &
0xff000000) >> 24) : __swap32md(0x00040000))
;
1122
1123 /* Stop receiving beacons from other BSS. */
1124 reg = AR_READ(sc, AR_RX_FILTER)(sc)->ops.read((sc), (0x803c));
1125 reg = (reg & ~AR_RX_FILTER_BEACON0x00000010) |
1126 AR_RX_FILTER_MYBEACON0x00000200;
1127 AR_WRITE(sc, AR_RX_FILTER, reg)(sc)->ops.write((sc), (0x803c), (reg));
1128 AR_WRITE_BARRIER(sc)(sc)->ops.write_barrier((sc));
1129 }
1130 athn_usb_wmi_xcmd(usc, AR_WMI_CMD_ENABLE_INTR0x005,
1131 &imask, sizeof(imask), NULL((void *)0));
1132 break;
1133 }
1134 (void)sc->sc_newstate(ic, cmd->state, cmd->arg);
1135 splx(s)spllower(s);
1136}
1137
1138void
1139athn_usb_newassoc(struct ieee80211com *ic, struct ieee80211_node *ni,
1140 int isnew)
1141{
1142#ifndef IEEE80211_STA_ONLY
1143 struct athn_usb_softc *usc = ic->ic_softcic_ac.ac_if.if_softc;
1144
1145 if (ic->ic_opmode != IEEE80211_M_HOSTAP &&
1146 ic->ic_state != IEEE80211_S_RUN)
1147 return;
1148
1149 /* Update the node's supported rates in a process context. */
1150 ieee80211_ref_node(ni);
1151 athn_usb_do_async(usc, athn_usb_newassoc_cb, &ni, sizeof(ni));
1152#endif
1153}
1154
1155#ifndef IEEE80211_STA_ONLY
1156void
1157athn_usb_newassoc_cb(struct athn_usb_softc *usc, void *arg)
1158{
1159 struct ieee80211com *ic = &usc->sc_sc.sc_ic;
1160 struct ieee80211_node *ni = *(void **)arg;
1161 struct athn_node *an = (struct athn_node *)ni;
1162 int s;
1163
1164 if (ic->ic_state != IEEE80211_S_RUN)
1165 return;
1166
1167 s = splnet()splraise(0x7);
1168 /* NB: Node may have left before we got scheduled. */
1169 if (an->sta_index != 0)
1170 (void)athn_usb_node_set_rates(usc, ni);
1171 ieee80211_release_node(ic, ni);
1172 splx(s)spllower(s);
1173}
1174#endif
1175
1176struct ieee80211_node *
1177athn_usb_node_alloc(struct ieee80211com *ic)
1178{
1179 struct athn_node *an;
1180
1181 an = malloc(sizeof(struct athn_node), M_USBDEV102, M_NOWAIT0x0002 | M_ZERO0x0008);
1182 return (struct ieee80211_node *)an;
1183}
1184
1185
1186#ifndef IEEE80211_STA_ONLY
1187void
1188athn_usb_count_active_sta(void *arg, struct ieee80211_node *ni)
1189{
1190 int *nsta = arg;
1191 struct athn_node *an = (struct athn_node *)ni;
1192
1193 if (an->sta_index == 0)
1194 return;
1195
1196 if ((ni->ni_state == IEEE80211_STA_AUTH ||
1197 ni->ni_state == IEEE80211_STA_ASSOC) &&
1198 ni->ni_inact < IEEE80211_INACT_MAX(300/5))
1199 (*nsta)++;
1200}
1201
1202struct athn_usb_newauth_cb_arg {
1203 struct ieee80211_node *ni;
1204 uint16_t seq;
1205};
1206
1207void
1208athn_usb_newauth_cb(struct athn_usb_softc *usc, void *arg)
1209{
1210 struct ieee80211com *ic = &usc->sc_sc.sc_ic;
1211 struct athn_usb_newauth_cb_arg *a = arg;
1212 struct ieee80211_node *ni = a->ni;
1213 uint16_t seq = a->seq;
1214 struct athn_node *an = (struct athn_node *)ni;
1215 int s, error = 0;
1216
1217 if (ic->ic_state != IEEE80211_S_RUN)
1218 return;
1219
1220 s = splnet()splraise(0x7);
1221 if (an->sta_index == 0) {
1222 error = athn_usb_create_node(usc, ni);
1223 if (error)
1224 printf("%s: could not add station %s to firmware "
1225 "table\n", usc->usb_devsc_sc.sc_dev.dv_xname,
1226 ether_sprintf(ni->ni_macaddr));
1227 }
1228 if (error == 0)
1229 ieee80211_auth_open_confirm(ic, ni, seq);
1230 ieee80211_unref_node(&ni);
1231 splx(s)spllower(s);
1232}
1233#endif
1234
1235int
1236athn_usb_newauth(struct ieee80211com *ic, struct ieee80211_node *ni,
1237 int isnew, uint16_t seq)
1238{
1239#ifndef IEEE80211_STA_ONLY
1240 struct athn_usb_softc *usc = ic->ic_softcic_ac.ac_if.if_softc;
1241 struct ifnet *ifp = &ic->ic_ific_ac.ac_if;
1242 struct athn_node *an = (struct athn_node *)ni;
1243 int nsta;
1244 struct athn_usb_newauth_cb_arg arg;
1245
1246 if (ic->ic_opmode != IEEE80211_M_HOSTAP)
1247 return 0;
1248
1249 if (!isnew && an->sta_index != 0) /* already in firmware table */
1250 return 0;
1251
1252 /* Check if we have room in the firmware table. */
1253 nsta = 1; /* Account for default node. */
1254 ieee80211_iterate_nodes(ic, athn_usb_count_active_sta, &nsta);
1255 if (nsta >= AR_USB_MAX_STA8) {
1256 if (ifp->if_flags & IFF_DEBUG0x4)
1257 printf("%s: cannot authenticate station %s: firmware "
1258 "table is full\n", usc->usb_devsc_sc.sc_dev.dv_xname,
1259 ether_sprintf(ni->ni_macaddr));
1260 return ENOSPC28;
1261 }
1262
1263 /*
1264 * In a process context, try to add this node to the
1265 * firmware table and confirm the AUTH request.
1266 */
1267 arg.ni = ieee80211_ref_node(ni);
1268 arg.seq = seq;
1269 athn_usb_do_async(usc, athn_usb_newauth_cb, &arg, sizeof(arg));
1270 return EBUSY16;
1271#else
1272 return 0;
1273#endif /* IEEE80211_STA_ONLY */
1274}
1275
1276#ifndef IEEE80211_STA_ONLY
1277void
1278athn_usb_node_free(struct ieee80211com *ic, struct ieee80211_node *ni)
1279{
1280 struct athn_usb_softc *usc = ic->ic_softcic_ac.ac_if.if_softc;
1281 struct athn_node *an = (struct athn_node *)ni;
1282
1283 /*
1284 * Remove the node from the firmware table in a process context.
1285 * Pass an index rather than the pointer which we will free.
1286 */
1287 if (an->sta_index != 0)
1288 athn_usb_do_async(usc, athn_usb_node_free_cb,
1289 &an->sta_index, sizeof(an->sta_index));
1290 usc->sc_node_free(ic, ni);
1291}
1292
1293void
1294athn_usb_node_free_cb(struct athn_usb_softc *usc, void *arg)
1295{
1296 struct ieee80211com *ic = &usc->sc_sc.sc_ic;
1297 struct ifnet *ifp = &ic->ic_ific_ac.ac_if;
1298 uint8_t sta_index = *(uint8_t *)arg;
1299 int error;
1300
1301 error = athn_usb_wmi_xcmd(usc, AR_WMI_CMD_NODE_REMOVE0x011,
1302 &sta_index, sizeof(sta_index), NULL((void *)0));
1303 if (error) {
1304 printf("%s: could not remove station %u from firmware table\n",
1305 usc->usb_devsc_sc.sc_dev.dv_xname, sta_index);
1306 return;
1307 }
1308 usc->free_node_slots |= (1 << sta_index);
1309 if (ifp->if_flags & IFF_DEBUG0x4)
1310 printf("%s: station %u removed from firmware table\n",
1311 usc->usb_devsc_sc.sc_dev.dv_xname, sta_index);
1312}
1313#endif /* IEEE80211_STA_ONLY */
1314
1315int
1316athn_usb_ampdu_tx_start(struct ieee80211com *ic, struct ieee80211_node *ni,
1317 uint8_t tid)
1318{
1319 struct athn_usb_softc *usc = ic->ic_softcic_ac.ac_if.if_softc;
1320 struct athn_node *an = (struct athn_node *)ni;
1321 struct athn_usb_aggr_cmd cmd;
1322
1323 /* Do it in a process context. */
1324 cmd.sta_index = an->sta_index;
1325 cmd.tid = tid;
1326 athn_usb_do_async(usc, athn_usb_ampdu_tx_start_cb, &cmd, sizeof(cmd));
1327 return (0);
1328}
1329
1330void
1331athn_usb_ampdu_tx_start_cb(struct athn_usb_softc *usc, void *arg)
1332{
1333 struct athn_usb_aggr_cmd *cmd = arg;
1334 struct ar_htc_target_aggr aggr;
1335
1336 memset(&aggr, 0, sizeof(aggr))__builtin_memset((&aggr), (0), (sizeof(aggr)));
1337 aggr.sta_index = cmd->sta_index;
1338 aggr.tidno = cmd->tid;
1339 aggr.aggr_enable = 1;
1340 (void)athn_usb_wmi_xcmd(usc, AR_WMI_CMD_TX_AGGR_ENABLE0x019,
1341 &aggr, sizeof(aggr), NULL((void *)0));
1342}
1343
1344void
1345athn_usb_ampdu_tx_stop(struct ieee80211com *ic, struct ieee80211_node *ni,
1346 uint8_t tid)
1347{
1348 struct athn_usb_softc *usc = ic->ic_softcic_ac.ac_if.if_softc;
1349 struct athn_node *an = (struct athn_node *)ni;
1350 struct athn_usb_aggr_cmd cmd;
1351
1352 /* Do it in a process context. */
1353 cmd.sta_index = an->sta_index;
1354 cmd.tid = tid;
1355 athn_usb_do_async(usc, athn_usb_ampdu_tx_stop_cb, &cmd, sizeof(cmd));
1356}
1357
1358void
1359athn_usb_ampdu_tx_stop_cb(struct athn_usb_softc *usc, void *arg)
1360{
1361 struct athn_usb_aggr_cmd *cmd = arg;
1362 struct ar_htc_target_aggr aggr;
1363
1364 memset(&aggr, 0, sizeof(aggr))__builtin_memset((&aggr), (0), (sizeof(aggr)));
1365 aggr.sta_index = cmd->sta_index;
1366 aggr.tidno = cmd->tid;
1367 aggr.aggr_enable = 0;
1368 (void)athn_usb_wmi_xcmd(usc, AR_WMI_CMD_TX_AGGR_ENABLE0x019,
1369 &aggr, sizeof(aggr), NULL((void *)0));
1370}
1371
1372#ifndef IEEE80211_STA_ONLY
1373/* Try to find a node we can evict to make room in the firmware table. */
1374void
1375athn_usb_clean_nodes(void *arg, struct ieee80211_node *ni)
1376{
1377 struct athn_usb_softc *usc = arg;
1378 struct ieee80211com *ic = &usc->sc_sc.sc_ic;
1379 struct athn_node *an = (struct athn_node *)ni;
1380
1381 /*
1382 * Don't remove the default node (used for management frames).
1383 * Nodes which are not in the firmware table also have index zero.
1384 */
1385 if (an->sta_index == 0)
1386 return;
1387
1388 /* Remove non-associated nodes. */
1389 if (ni->ni_state != IEEE80211_STA_AUTH &&
1390 ni->ni_state != IEEE80211_STA_ASSOC) {
1391 athn_usb_remove_node(usc, ni);
1392 return;
1393 }
1394
1395 /*
1396 * Kick off inactive associated nodes. This won't help
1397 * immediately but will help if the new STA retries later.
1398 */
1399 if (ni->ni_inact >= IEEE80211_INACT_MAX(300/5)) {
1400 IEEE80211_SEND_MGMT(ic, ni, IEEE80211_FC0_SUBTYPE_DEAUTH,((*(ic)->ic_send_mgmt)(ic, ni, 0xc0, IEEE80211_REASON_AUTH_EXPIRE
, 0))
1401 IEEE80211_REASON_AUTH_EXPIRE)((*(ic)->ic_send_mgmt)(ic, ni, 0xc0, IEEE80211_REASON_AUTH_EXPIRE
, 0))
;
1402 ieee80211_node_leave(ic, ni);
1403 }
1404}
1405#endif
1406
1407int
1408athn_usb_create_node(struct athn_usb_softc *usc, struct ieee80211_node *ni)
1409{
1410 struct athn_node *an = (struct athn_node *)ni;
1411 struct ar_htc_target_sta sta;
1412 int error, sta_index;
1413#ifndef IEEE80211_STA_ONLY
1414 struct ieee80211com *ic = &usc->sc_sc.sc_ic;
1415 struct ifnet *ifp = &ic->ic_ific_ac.ac_if;
1416
1417 /* Firmware cannot handle more than 8 STAs. Try to make room first. */
1418 if (ic->ic_opmode == IEEE80211_M_HOSTAP)
1419 ieee80211_iterate_nodes(ic, athn_usb_clean_nodes, usc);
1420#endif
1421 if (usc->free_node_slots == 0x00)
1422 return ENOBUFS55;
1423
1424 sta_index = ffs(usc->free_node_slots) - 1;
1425 if (sta_index < 0 || sta_index >= AR_USB_MAX_STA8)
1426 return ENOSPC28;
1427
1428 /* Create node entry on target. */
1429 memset(&sta, 0, sizeof(sta))__builtin_memset((&sta), (0), (sizeof(sta)));
1430 IEEE80211_ADDR_COPY(sta.macaddr, ni->ni_macaddr)__builtin_memcpy((sta.macaddr), (ni->ni_macaddr), (6));
1431 IEEE80211_ADDR_COPY(sta.bssid, ni->ni_bssid)__builtin_memcpy((sta.bssid), (ni->ni_bssid), (6));
1432 sta.sta_index = sta_index;
1433 sta.maxampdu = 0xffff;
1434 if (ni->ni_flags & IEEE80211_NODE_HT0x0400)
1435 sta.flags |= htobe16(AR_HTC_STA_HT)(__uint16_t)(__builtin_constant_p(0x0008) ? (__uint16_t)(((__uint16_t
)(0x0008) & 0xffU) << 8 | ((__uint16_t)(0x0008) &
0xff00U) >> 8) : __swap16md(0x0008))
;
1436 error = athn_usb_wmi_xcmd(usc, AR_WMI_CMD_NODE_CREATE0x010,
1437 &sta, sizeof(sta), NULL((void *)0));
1438 if (error != 0)
1439 return (error);
1440 an->sta_index = sta_index;
1441 usc->free_node_slots &= ~(1 << an->sta_index);
1442
1443#ifndef IEEE80211_STA_ONLY
1444 if (ifp->if_flags & IFF_DEBUG0x4)
1445 printf("%s: station %u (%s) added to firmware table\n",
1446 usc->usb_devsc_sc.sc_dev.dv_xname, sta_index,
1447 ether_sprintf(ni->ni_macaddr));
1448#endif
1449 return athn_usb_node_set_rates(usc, ni);
1450}
1451
1452int
1453athn_usb_node_set_rates(struct athn_usb_softc *usc, struct ieee80211_node *ni)
1454{
1455 struct athn_node *an = (struct athn_node *)ni;
1456 struct ar_htc_target_rate rate;
1457 int i, j;
1458
1459 /* Setup supported rates. */
1460 memset(&rate, 0, sizeof(rate))__builtin_memset((&rate), (0), (sizeof(rate)));
1461 rate.sta_index = an->sta_index;
1462 rate.isnew = 1;
1463 rate.lg_rates.rs_nrates = ni->ni_rates.rs_nrates;
1464 memcpy(rate.lg_rates.rs_rates, ni->ni_rates.rs_rates,__builtin_memcpy((rate.lg_rates.rs_rates), (ni->ni_rates.rs_rates
), (ni->ni_rates.rs_nrates))
1465 ni->ni_rates.rs_nrates)__builtin_memcpy((rate.lg_rates.rs_rates), (ni->ni_rates.rs_rates
), (ni->ni_rates.rs_nrates))
;
1466 if (ni->ni_flags & IEEE80211_NODE_HT0x0400) {
1467 rate.capflags |= htobe32(AR_RC_HT_FLAG)(__uint32_t)(__builtin_constant_p(0x00000008) ? (__uint32_t)(
((__uint32_t)(0x00000008) & 0xff) << 24 | ((__uint32_t
)(0x00000008) & 0xff00) << 8 | ((__uint32_t)(0x00000008
) & 0xff0000) >> 8 | ((__uint32_t)(0x00000008) &
0xff000000) >> 24) : __swap32md(0x00000008))
;
1468 /* Setup HT rates. */
1469 for (i = 0, j = 0; i < IEEE80211_HT_NUM_MCS77; i++) {
1470 if (!isset(ni->ni_rxmcs, i)((ni->ni_rxmcs)[(i)>>3] & (1<<((i)&(8 -
1))))
)
1471 continue;
1472 if (j >= AR_HTC_RATE_MAX30)
1473 break;
1474 rate.ht_rates.rs_rates[j++] = i;
1475 }
1476 rate.ht_rates.rs_nrates = j;
1477
1478 if (ni->ni_rxmcs[1]) /* dual-stream MIMO rates */
1479 rate.capflags |= htobe32(AR_RC_DS_FLAG)(__uint32_t)(__builtin_constant_p(0x00000001) ? (__uint32_t)(
((__uint32_t)(0x00000001) & 0xff) << 24 | ((__uint32_t
)(0x00000001) & 0xff00) << 8 | ((__uint32_t)(0x00000001
) & 0xff0000) >> 8 | ((__uint32_t)(0x00000001) &
0xff000000) >> 24) : __swap32md(0x00000001))
;
1480#ifdef notyet
1481 if (ni->ni_htcaps & IEEE80211_HTCAP_CBW20_400x00000002)
1482 rate.capflags |= htobe32(AR_RC_40_FLAG)(__uint32_t)(__builtin_constant_p(0x00000002) ? (__uint32_t)(
((__uint32_t)(0x00000002) & 0xff) << 24 | ((__uint32_t
)(0x00000002) & 0xff00) << 8 | ((__uint32_t)(0x00000002
) & 0xff0000) >> 8 | ((__uint32_t)(0x00000002) &
0xff000000) >> 24) : __swap32md(0x00000002))
;
1483 if (ni->ni_htcaps & IEEE80211_HTCAP_SGI400x00000040)
1484 rate.capflags |= htobe32(AR_RC_SGI_FLAG)(__uint32_t)(__builtin_constant_p(0x00000004) ? (__uint32_t)(
((__uint32_t)(0x00000004) & 0xff) << 24 | ((__uint32_t
)(0x00000004) & 0xff00) << 8 | ((__uint32_t)(0x00000004
) & 0xff0000) >> 8 | ((__uint32_t)(0x00000004) &
0xff000000) >> 24) : __swap32md(0x00000004))
;
1485 if (ni->ni_htcaps & IEEE80211_HTCAP_SGI200x00000020)
1486 rate.capflags |= htobe32(AR_RC_SGI_FLAG)(__uint32_t)(__builtin_constant_p(0x00000004) ? (__uint32_t)(
((__uint32_t)(0x00000004) & 0xff) << 24 | ((__uint32_t
)(0x00000004) & 0xff00) << 8 | ((__uint32_t)(0x00000004
) & 0xff0000) >> 8 | ((__uint32_t)(0x00000004) &
0xff000000) >> 24) : __swap32md(0x00000004))
;
1487#endif
1488 }
1489
1490 return athn_usb_wmi_xcmd(usc, AR_WMI_CMD_RC_RATE_UPDATE0x017,
1491 &rate, sizeof(rate), NULL((void *)0));
1492}
1493
1494int
1495athn_usb_remove_node(struct athn_usb_softc *usc, struct ieee80211_node *ni)
1496{
1497 struct athn_node *an = (struct athn_node *)ni;
1498 int error;
1499#ifndef IEEE80211_STA_ONLY
1500 struct ieee80211com *ic = &usc->sc_sc.sc_ic;
1501 struct ifnet *ifp = &ic->ic_ific_ac.ac_if;
1502#endif
1503
1504 error = athn_usb_wmi_xcmd(usc, AR_WMI_CMD_NODE_REMOVE0x011,
1505 &an->sta_index, sizeof(an->sta_index), NULL((void *)0));
1506 if (error) {
1507 printf("%s: could not remove station %u (%s) from "
1508 "firmware table\n", usc->usb_devsc_sc.sc_dev.dv_xname, an->sta_index,
1509 ether_sprintf(ni->ni_macaddr));
1510 return error;
1511 }
1512
1513#ifndef IEEE80211_STA_ONLY
1514 if (ifp->if_flags & IFF_DEBUG0x4)
1515 printf("%s: station %u (%s) removed from firmware table\n",
1516 usc->usb_devsc_sc.sc_dev.dv_xname, an->sta_index,
1517 ether_sprintf(ni->ni_macaddr));
1518#endif
1519
1520 usc->free_node_slots |= (1 << an->sta_index);
1521 an->sta_index = 0;
1522 return 0;
1523}
1524
1525void
1526athn_usb_rx_enable(struct athn_softc *sc)
1527{
1528 AR_WRITE(sc, AR_CR, AR_CR_RXE)(sc)->ops.write((sc), (0x0008), ((((sc)->mac_ver > 0x1c0
|| (((sc)->mac_ver == 0x1c0) && (sc)->mac_rev >=
2)) ? 0x000c : 0x0004)))
;
1529 AR_WRITE_BARRIER(sc)(sc)->ops.write_barrier((sc));
1530}
1531
1532int
1533athn_usb_switch_chan(struct athn_softc *sc, struct ieee80211_channel *c,
1534 struct ieee80211_channel *extc)
1535{
1536 struct athn_usb_softc *usc = (struct athn_usb_softc *)sc;
1537 uint16_t mode;
1538 int error;
1539
1540 /* Disable interrupts. */
1541 error = athn_usb_wmi_cmd(usc, AR_WMI_CMD_DISABLE_INTR)athn_usb_wmi_xcmd(usc, 0x004, ((void *)0), 0, ((void *)0));
1542 if (error != 0)
1543 goto reset;
1544 /* Stop all Tx queues. */
1545 error = athn_usb_wmi_cmd(usc, AR_WMI_CMD_DRAIN_TXQ_ALL)athn_usb_wmi_xcmd(usc, 0x00b, ((void *)0), 0, ((void *)0));
1546 if (error != 0)
1547 goto reset;
1548 /* Stop Rx. */
1549 error = athn_usb_wmi_cmd(usc, AR_WMI_CMD_STOP_RECV)athn_usb_wmi_xcmd(usc, 0x00d, ((void *)0), 0, ((void *)0));
1550 if (error != 0)
1551 goto reset;
1552
1553 /* If band or bandwidth changes, we need to do a full reset. */
1554 if (c->ic_flags != sc->curchan->ic_flags ||
1555 ((extc != NULL((void *)0)) ^ (sc->curchanext != NULL((void *)0)))) {
1556 DPRINTFN(2, ("channel band switch\n"));
1557 goto reset;
1558 }
1559
1560 error = athn_set_chan(sc, c, extc);
1561 if (AR_SREV_9271(sc)((sc)->mac_ver == 0x140) && error == 0)
1562 ar9271_load_ani(sc);
1563 if (error != 0) {
1564 reset: /* Error found, try a full reset. */
1565 DPRINTFN(3, ("needs a full reset\n"));
1566 error = athn_hw_reset(sc, c, extc, 0);
1567 if (error != 0) /* Hopeless case. */
1568 return (error);
1569
1570 error = athn_set_chan(sc, c, extc);
1571 if (AR_SREV_9271(sc)((sc)->mac_ver == 0x140) && error == 0)
1572 ar9271_load_ani(sc);
1573 if (error != 0)
1574 return (error);
1575 }
1576
1577 sc->ops.set_txpower(sc, c, extc);
1578
1579 error = athn_usb_wmi_cmd(usc, AR_WMI_CMD_START_RECV)athn_usb_wmi_xcmd(usc, 0x00c, ((void *)0), 0, ((void *)0));
1580 if (error != 0)
1581 return (error);
1582 athn_rx_start(sc);
1583
1584 mode = htobe16(IEEE80211_IS_CHAN_2GHZ(c) ?(__uint16_t)(__builtin_constant_p((((c)->ic_flags & 0x0080
) != 0) ? 1 : 0) ? (__uint16_t)(((__uint16_t)((((c)->ic_flags
& 0x0080) != 0) ? 1 : 0) & 0xffU) << 8 | ((__uint16_t
)((((c)->ic_flags & 0x0080) != 0) ? 1 : 0) & 0xff00U
) >> 8) : __swap16md((((c)->ic_flags & 0x0080) !=
0) ? 1 : 0))
1585 AR_HTC_MODE_11NG : AR_HTC_MODE_11NA)(__uint16_t)(__builtin_constant_p((((c)->ic_flags & 0x0080
) != 0) ? 1 : 0) ? (__uint16_t)(((__uint16_t)((((c)->ic_flags
& 0x0080) != 0) ? 1 : 0) & 0xffU) << 8 | ((__uint16_t
)((((c)->ic_flags & 0x0080) != 0) ? 1 : 0) & 0xff00U
) >> 8) : __swap16md((((c)->ic_flags & 0x0080) !=
0) ? 1 : 0))
;
1586 error = athn_usb_wmi_xcmd(usc, AR_WMI_CMD_SET_MODE0x00f,
1587 &mode, sizeof(mode), NULL((void *)0));
1588 if (error != 0)
1589 return (error);
1590
1591 /* Re-enable interrupts. */
1592 error = athn_usb_wmi_cmd(usc, AR_WMI_CMD_ENABLE_INTR)athn_usb_wmi_xcmd(usc, 0x005, ((void *)0), 0, ((void *)0));
1593 return (error);
1594}
1595
1596void
1597athn_usb_updateedca(struct ieee80211com *ic)
1598{
1599 struct athn_usb_softc *usc = ic->ic_softcic_ac.ac_if.if_softc;
1600
1601 /* Do it in a process context. */
1602 athn_usb_do_async(usc, athn_usb_updateedca_cb, NULL((void *)0), 0);
1603}
1604
1605void
1606athn_usb_updateedca_cb(struct athn_usb_softc *usc, void *arg)
1607{
1608 int s;
1609
1610 s = splnet()splraise(0x7);
1611 athn_updateedca(&usc->sc_sc.sc_ic);
1612 splx(s)spllower(s);
1613}
1614
1615void
1616athn_usb_updateslot(struct ieee80211com *ic)
1617{
1618 struct athn_usb_softc *usc = ic->ic_softcic_ac.ac_if.if_softc;
Value stored to 'usc' during its initialization is never read
1619
1620 return; /* XXX */
1621 /* Do it in a process context. */
1622 athn_usb_do_async(usc, athn_usb_updateslot_cb, NULL((void *)0), 0);
1623}
1624
1625void
1626athn_usb_updateslot_cb(struct athn_usb_softc *usc, void *arg)
1627{
1628 int s;
1629
1630 s = splnet()splraise(0x7);
1631 athn_updateslot(&usc->sc_sc.sc_ic);
1632 splx(s)spllower(s);
1633}
1634
1635int
1636athn_usb_set_key(struct ieee80211com *ic, struct ieee80211_node *ni,
1637 struct ieee80211_key *k)
1638{
1639 struct athn_usb_softc *usc = ic->ic_softcic_ac.ac_if.if_softc;
1640 struct athn_usb_cmd_key cmd;
1641
1642 /* Defer setting of WEP keys until interface is brought up. */
1643 if ((ic->ic_ific_ac.ac_if.if_flags & (IFF_UP0x1 | IFF_RUNNING0x40)) !=
1644 (IFF_UP0x1 | IFF_RUNNING0x40))
1645 return (0);
1646
1647 /* Do it in a process context. */
1648 cmd.ni = (ni != NULL((void *)0)) ? ieee80211_ref_node(ni) : NULL((void *)0);
1649 cmd.key = k;
1650 athn_usb_do_async(usc, athn_usb_set_key_cb, &cmd, sizeof(cmd));
1651 usc->sc_key_tasks++;
1652 return EBUSY16;
1653}
1654
1655void
1656athn_usb_set_key_cb(struct athn_usb_softc *usc, void *arg)
1657{
1658 struct ieee80211com *ic = &usc->sc_sc.sc_ic;
1659 struct athn_usb_cmd_key *cmd = arg;
1660 int s;
1661
1662 usc->sc_key_tasks--;
1663
1664 s = splnet()splraise(0x7);
1665 athn_usb_write_barrier(&usc->sc_sc);
1666 athn_set_key(ic, cmd->ni, cmd->key);
1667 if (usc->sc_key_tasks == 0) {
1668 DPRINTF(("marking port %s valid\n",
1669 ether_sprintf(cmd->ni->ni_macaddr)));
1670 cmd->ni->ni_port_valid = 1;
1671 ieee80211_set_link_state(ic, LINK_STATE_UP4);
1672 }
1673 if (cmd->ni != NULL((void *)0))
1674 ieee80211_release_node(ic, cmd->ni);
1675 splx(s)spllower(s);
1676}
1677
1678void
1679athn_usb_delete_key(struct ieee80211com *ic, struct ieee80211_node *ni,
1680 struct ieee80211_key *k)
1681{
1682 struct athn_usb_softc *usc = ic->ic_softcic_ac.ac_if.if_softc;
1683 struct athn_usb_cmd_key cmd;
1684
1685 if (!(ic->ic_ific_ac.ac_if.if_flags & IFF_RUNNING0x40) ||
1686 ic->ic_state != IEEE80211_S_RUN)
1687 return; /* Nothing to do. */
1688
1689 /* Do it in a process context. */
1690 cmd.ni = (ni != NULL((void *)0)) ? ieee80211_ref_node(ni) : NULL((void *)0);
1691 cmd.key = k;
1692 athn_usb_do_async(usc, athn_usb_delete_key_cb, &cmd, sizeof(cmd));
1693}
1694
1695void
1696athn_usb_delete_key_cb(struct athn_usb_softc *usc, void *arg)
1697{
1698 struct ieee80211com *ic = &usc->sc_sc.sc_ic;
1699 struct athn_usb_cmd_key *cmd = arg;
1700 int s;
1701
1702 s = splnet()splraise(0x7);
1703 athn_delete_key(ic, cmd->ni, cmd->key);
1704 if (cmd->ni != NULL((void *)0))
1705 ieee80211_release_node(ic, cmd->ni);
1706 splx(s)spllower(s);
1707}
1708
1709#ifndef IEEE80211_STA_ONLY
1710void
1711athn_usb_bcneof(struct usbd_xfer *xfer, void *priv,
1712 usbd_status status)
1713{
1714 struct athn_usb_tx_data *data = priv;
1715 struct athn_usb_softc *usc = data->sc;
1716
1717 if (__predict_false(status == USBD_STALLED)__builtin_expect(((status == USBD_STALLED) != 0), 0))
1718 usbd_clear_endpoint_stall_async(usc->tx_data_pipe);
1719 usc->tx_bcn = data;
1720}
1721
1722/*
1723 * Process Software Beacon Alert interrupts.
1724 */
1725void
1726athn_usb_swba(struct athn_usb_softc *usc)
1727{
1728 struct athn_softc *sc = &usc->sc_sc;
1729 struct ieee80211com *ic = &sc->sc_ic;
1730 struct athn_usb_tx_data *data;
1731 struct ieee80211_frame *wh;
1732 struct ar_stream_hdr *hdr;
1733 struct ar_htc_frame_hdr *htc;
1734 struct ar_tx_bcn *bcn;
1735 struct mbuf *m;
1736 int error;
1737
1738 if (ic->ic_dtim_count == 0)
1739 ic->ic_dtim_count = ic->ic_dtim_period - 1;
1740 else
1741 ic->ic_dtim_count--;
1742
1743 /* Make sure previous beacon has been sent. */
1744 if (usc->tx_bcn == NULL((void *)0))
1745 return;
1746 data = usc->tx_bcn;
1747
1748 /* Get new beacon. */
1749 m = ieee80211_beacon_alloc(ic, ic->ic_bss);
1750 if (__predict_false(m == NULL)__builtin_expect(((m == ((void *)0)) != 0), 0))
1751 return;
1752 /* Assign sequence number. */
1753 wh = mtod(m, struct ieee80211_frame *)((struct ieee80211_frame *)((m)->m_hdr.mh_data));
1754 *(uint16_t *)&wh->i_seq[0] =
1755 htole16(ic->ic_bss->ni_txseq << IEEE80211_SEQ_SEQ_SHIFT)((__uint16_t)(ic->ic_bss->ni_txseq << 4));
1756 ic->ic_bss->ni_txseq++;
1757
1758 hdr = (struct ar_stream_hdr *)data->buf;
1759 hdr->tag = htole16(AR_USB_TX_STREAM_TAG)((__uint16_t)(0x697e));
1760 hdr->len = htole16(sizeof(*htc) + sizeof(*bcn) + m->m_pkthdr.len)((__uint16_t)(sizeof(*htc) + sizeof(*bcn) + m->M_dat.MH.MH_pkthdr
.len))
;
1761
1762 htc = (struct ar_htc_frame_hdr *)&hdr[1];
1763 memset(htc, 0, sizeof(*htc))__builtin_memset((htc), (0), (sizeof(*htc)));
1764 htc->endpoint_id = usc->ep_bcn;
1765 htc->payload_len = htobe16(sizeof(*bcn) + m->m_pkthdr.len)(__uint16_t)(__builtin_constant_p(sizeof(*bcn) + m->M_dat.
MH.MH_pkthdr.len) ? (__uint16_t)(((__uint16_t)(sizeof(*bcn) +
m->M_dat.MH.MH_pkthdr.len) & 0xffU) << 8 | ((__uint16_t
)(sizeof(*bcn) + m->M_dat.MH.MH_pkthdr.len) & 0xff00U)
>> 8) : __swap16md(sizeof(*bcn) + m->M_dat.MH.MH_pkthdr
.len))
;
1766
1767 bcn = (struct ar_tx_bcn *)&htc[1];
1768 memset(bcn, 0, sizeof(*bcn))__builtin_memset((bcn), (0), (sizeof(*bcn)));
1769 bcn->vif_idx = 0;
1770
1771 m_copydata(m, 0, m->m_pkthdrM_dat.MH.MH_pkthdr.len, &bcn[1]);
1772
1773 usbd_setup_xfer(data->xfer, usc->tx_data_pipe, data, data->buf,
1774 sizeof(*hdr) + sizeof(*htc) + sizeof(*bcn) + m->m_pkthdrM_dat.MH.MH_pkthdr.len,
1775 USBD_SHORT_XFER_OK0x04 | USBD_NO_COPY0x01, ATHN_USB_TX_TIMEOUT5000,
1776 athn_usb_bcneof);
1777
1778 m_freem(m);
1779 usc->tx_bcn = NULL((void *)0);
1780 error = usbd_transfer(data->xfer);
1781 if (__predict_false(error != USBD_IN_PROGRESS && error != 0)__builtin_expect(((error != USBD_IN_PROGRESS && error
!= 0) != 0), 0)
)
1782 usc->tx_bcn = data;
1783}
1784#endif
1785
1786/* Update current transmit rate for a node based on firmware Tx status. */
1787void
1788athn_usb_tx_status(void *arg, struct ieee80211_node *ni)
1789{
1790 struct ar_wmi_evt_txstatus *ts = arg;
1791 struct athn_node *an = (struct athn_node *)ni;
1792 uint8_t rate_index = (ts->rate & AR_HTC_TXSTAT_RATE0x0f);
1793
1794 if (an->sta_index != ts->cookie) /* Tx report for a different node */
1795 return;
1796
1797 if (ts->flags & AR_HTC_TXSTAT_MCS0x08) {
1798 if (isset(ni->ni_rxmcs, rate_index)((ni->ni_rxmcs)[(rate_index)>>3] & (1<<((rate_index
)&(8 -1))))
)
1799 ni->ni_txmcs = rate_index;
1800 } else if (rate_index < ni->ni_rates.rs_nrates)
1801 ni->ni_txrate = rate_index;
1802}
1803
1804void
1805athn_usb_rx_wmi_ctrl(struct athn_usb_softc *usc, uint8_t *buf, int len)
1806{
1807 struct ar_wmi_cmd_hdr *wmi;
1808 uint16_t cmd_id;
1809
1810 if (__predict_false(len < sizeof(*wmi))__builtin_expect(((len < sizeof(*wmi)) != 0), 0))
1811 return;
1812 wmi = (struct ar_wmi_cmd_hdr *)buf;
1813 cmd_id = betoh16(wmi->cmd_id)(__uint16_t)(__builtin_constant_p(wmi->cmd_id) ? (__uint16_t
)(((__uint16_t)(wmi->cmd_id) & 0xffU) << 8 | ((__uint16_t
)(wmi->cmd_id) & 0xff00U) >> 8) : __swap16md(wmi
->cmd_id))
;
1814
1815 if (!(cmd_id & AR_WMI_EVT_FLAG0x1000)) {
1816 if (usc->wait_cmd_id != cmd_id)
1817 return; /* Unexpected reply. */
1818 if (usc->obuf != NULL((void *)0)) {
1819 /* Copy answer into caller supplied buffer. */
1820 memcpy(usc->obuf, &wmi[1], len - sizeof(*wmi))__builtin_memcpy((usc->obuf), (&wmi[1]), (len - sizeof
(*wmi)))
;
1821 }
1822 /* Notify caller of completion. */
1823 wakeup(&usc->wait_cmd_id);
1824 return;
1825 }
1826 switch (cmd_id & 0xfff) {
1827#ifndef IEEE80211_STA_ONLY
1828 case AR_WMI_EVT_SWBA0x002:
1829 athn_usb_swba(usc);
1830 break;
1831#endif
1832 case AR_WMI_EVT_TXSTATUS0x007: {
1833 struct ar_wmi_evt_txstatus_list *tsl;
1834 int i;
1835
1836 tsl = (struct ar_wmi_evt_txstatus_list *)&wmi[1];
1837 for (i = 0; i < tsl->count && i < nitems(tsl->ts)(sizeof((tsl->ts)) / sizeof((tsl->ts)[0])); i++) {
1838 struct ieee80211com *ic = &usc->sc_sc.sc_ic;
1839 struct athn_node *an = (struct athn_node *)ic->ic_bss;
1840 struct ar_wmi_evt_txstatus *ts = &tsl->ts[i];
1841 uint8_t qid;
1842
1843 /* Skip the node we use to send management frames. */
1844 if (ts->cookie == 0)
1845 continue;
1846
1847 /* Skip Tx reports for non-data frame endpoints. */
1848 qid = (ts->rate & AR_HTC_TXSTAT_EPID0xf0) >>
1849 AR_HTC_TXSTAT_EPID_SHIFT4;
1850 if (qid != usc->ep_data[EDCA_AC_BE] &&
1851 qid != usc->ep_data[EDCA_AC_BK] &&
1852 qid != usc->ep_data[EDCA_AC_VI] &&
1853 qid != usc->ep_data[EDCA_AC_VO])
1854 continue;
1855
1856 if (ts->cookie == an->sta_index)
1857 athn_usb_tx_status(ts, ic->ic_bss);
1858 else
1859 ieee80211_iterate_nodes(ic, athn_usb_tx_status,
1860 ts);
1861 }
1862 break;
1863 }
1864 case AR_WMI_EVT_FATAL0x003:
1865 printf("%s: fatal firmware error\n", usc->usb_devsc_sc.sc_dev.dv_xname);
1866 break;
1867 default:
1868 DPRINTF(("WMI event %d ignored\n", cmd_id));
1869 break;
1870 }
1871}
1872
1873void
1874athn_usb_intr(struct usbd_xfer *xfer, void *priv,
1875 usbd_status status)
1876{
1877 struct athn_usb_softc *usc = priv;
1878 struct ar_htc_frame_hdr *htc;
1879 struct ar_htc_msg_hdr *msg;
1880 uint8_t *buf = usc->ibuf;
1881 uint16_t msg_id;
1882 int len;
1883
1884 if (__predict_false(status != USBD_NORMAL_COMPLETION)__builtin_expect(((status != USBD_NORMAL_COMPLETION) != 0), 0
)
) {
1885 DPRINTF(("intr status=%d\n", status));
1886 if (status == USBD_STALLED)
1887 usbd_clear_endpoint_stall_async(usc->rx_intr_pipe);
1888 else if (status == USBD_IOERROR) {
1889 /*
1890 * The device has gone away. If async commands are
1891 * pending or running ensure the device dies ASAP
1892 * and any blocked processes are woken up.
1893 */
1894 if (usc->cmdq.queued > 0)
1895 usbd_deactivate(usc->sc_udev);
1896 }
1897 return;
1898 }
1899 usbd_get_xfer_status(xfer, NULL((void *)0), NULL((void *)0), &len, NULL((void *)0));
1900
1901 /* Skip watchdog pattern if present. */
1902 if (len >= 4 && *(uint32_t *)buf == htobe32(0x00c60000)(__uint32_t)(__builtin_constant_p(0x00c60000) ? (__uint32_t)(
((__uint32_t)(0x00c60000) & 0xff) << 24 | ((__uint32_t
)(0x00c60000) & 0xff00) << 8 | ((__uint32_t)(0x00c60000
) & 0xff0000) >> 8 | ((__uint32_t)(0x00c60000) &
0xff000000) >> 24) : __swap32md(0x00c60000))
) {
1903 buf += 4;
1904 len -= 4;
1905 }
1906 if (__predict_false(len < sizeof(*htc))__builtin_expect(((len < sizeof(*htc)) != 0), 0))
1907 return;
1908 htc = (struct ar_htc_frame_hdr *)buf;
1909 /* Skip HTC header. */
1910 buf += sizeof(*htc);
1911 len -= sizeof(*htc);
1912
1913 if (htc->endpoint_id != 0) {
1914 if (__predict_false(htc->endpoint_id != usc->ep_ctrl)__builtin_expect(((htc->endpoint_id != usc->ep_ctrl) !=
0), 0)
)
1915 return;
1916 /* Remove trailer if present. */
1917 if (htc->flags & AR_HTC_FLAG_TRAILER0x02) {
1918 if (__predict_false(len < htc->control[0])__builtin_expect(((len < htc->control[0]) != 0), 0))
1919 return;
1920 len -= htc->control[0];
1921 }
1922 athn_usb_rx_wmi_ctrl(usc, buf, len);
1923 return;
1924 }
1925 /* Endpoint 0 carries HTC messages. */
1926 if (__predict_false(len < sizeof(*msg))__builtin_expect(((len < sizeof(*msg)) != 0), 0))
1927 return;
1928 msg = (struct ar_htc_msg_hdr *)buf;
1929 msg_id = betoh16(msg->msg_id)(__uint16_t)(__builtin_constant_p(msg->msg_id) ? (__uint16_t
)(((__uint16_t)(msg->msg_id) & 0xffU) << 8 | ((__uint16_t
)(msg->msg_id) & 0xff00U) >> 8) : __swap16md(msg
->msg_id))
;
1930 DPRINTF(("Rx HTC message %d\n", msg_id));
1931 switch (msg_id) {
1932 case AR_HTC_MSG_READY0x0001:
1933 if (usc->wait_msg_id != msg_id)
1934 break;
1935 usc->wait_msg_id = 0;
1936 wakeup(&usc->wait_msg_id);
1937 break;
1938 case AR_HTC_MSG_CONN_SVC_RSP0x0003:
1939 if (usc->wait_msg_id != msg_id)
1940 break;
1941 if (usc->msg_conn_svc_rsp != NULL((void *)0)) {
1942 memcpy(usc->msg_conn_svc_rsp, &msg[1],__builtin_memcpy((usc->msg_conn_svc_rsp), (&msg[1]), (
sizeof(struct ar_htc_msg_conn_svc_rsp)))
1943 sizeof(struct ar_htc_msg_conn_svc_rsp))__builtin_memcpy((usc->msg_conn_svc_rsp), (&msg[1]), (
sizeof(struct ar_htc_msg_conn_svc_rsp)))
;
1944 }
1945 usc->wait_msg_id = 0;
1946 wakeup(&usc->wait_msg_id);
1947 break;
1948 case AR_HTC_MSG_CONF_PIPE_RSP0x0006:
1949 if (usc->wait_msg_id != msg_id)
1950 break;
1951 usc->wait_msg_id = 0;
1952 wakeup(&usc->wait_msg_id);
1953 break;
1954 default:
1955 DPRINTF(("HTC message %d ignored\n", msg_id));
1956 break;
1957 }
1958}
1959
1960#if NBPFILTER1 > 0
1961void
1962athn_usb_rx_radiotap(struct athn_softc *sc, struct mbuf *m,
1963 struct ar_rx_status *rs)
1964{
1965#define IEEE80211_RADIOTAP_F_SHORTGI0x80 0x80 /* XXX from FBSD */
1966
1967 struct athn_rx_radiotap_header *tap = &sc->sc_rxtapsc_rxtapu.th;
1968 struct ieee80211com *ic = &sc->sc_ic;
1969 struct mbuf mb;
1970 uint8_t rate;
1971
1972 tap->wr_flags = IEEE80211_RADIOTAP_F_FCS0x10;
1973 tap->wr_tsft = htole64(betoh64(rs->rs_tstamp))((__uint64_t)((__uint64_t)(__builtin_constant_p(rs->rs_tstamp
) ? (__uint64_t)((((__uint64_t)(rs->rs_tstamp) & 0xff)
<< 56) | ((__uint64_t)(rs->rs_tstamp) & 0xff00ULL
) << 40 | ((__uint64_t)(rs->rs_tstamp) & 0xff0000ULL
) << 24 | ((__uint64_t)(rs->rs_tstamp) & 0xff000000ULL
) << 8 | ((__uint64_t)(rs->rs_tstamp) & 0xff00000000ULL
) >> 8 | ((__uint64_t)(rs->rs_tstamp) & 0xff0000000000ULL
) >> 24 | ((__uint64_t)(rs->rs_tstamp) & 0xff000000000000ULL
) >> 40 | ((__uint64_t)(rs->rs_tstamp) & 0xff00000000000000ULL
) >> 56) : __swap64md(rs->rs_tstamp))))
;
1974 tap->wr_chan_freq = htole16(ic->ic_bss->ni_chan->ic_freq)((__uint16_t)(ic->ic_bss->ni_chan->ic_freq));
1975 tap->wr_chan_flags = htole16(ic->ic_bss->ni_chan->ic_flags)((__uint16_t)(ic->ic_bss->ni_chan->ic_flags));
1976 tap->wr_dbm_antsignal = rs->rs_rssi;
1977 /* XXX noise. */
1978 tap->wr_antenna = rs->rs_antenna;
1979 tap->wr_rate = 0; /* In case it can't be found below. */
1980 rate = rs->rs_rate;
1981 if (rate & 0x80) { /* HT. */
1982 /* Bit 7 set means HT MCS instead of rate. */
1983 tap->wr_rate = rate;
1984 if (!(rs->rs_flags & AR_RXS_FLAG_GI0x04))
1985 tap->wr_flags |= IEEE80211_RADIOTAP_F_SHORTGI0x80;
1986
1987 } else if (rate & 0x10) { /* CCK. */
1988 if (rate & 0x04)
1989 tap->wr_flags |= IEEE80211_RADIOTAP_F_SHORTPRE0x02;
1990 switch (rate & ~0x14) {
1991 case 0xb: tap->wr_rate = 2; break;
1992 case 0xa: tap->wr_rate = 4; break;
1993 case 0x9: tap->wr_rate = 11; break;
1994 case 0x8: tap->wr_rate = 22; break;
1995 }
1996 } else { /* OFDM. */
1997 switch (rate) {
1998 case 0xb: tap->wr_rate = 12; break;
1999 case 0xf: tap->wr_rate = 18; break;
2000 case 0xa: tap->wr_rate = 24; break;
2001 case 0xe: tap->wr_rate = 36; break;
2002 case 0x9: tap->wr_rate = 48; break;
2003 case 0xd: tap->wr_rate = 72; break;
2004 case 0x8: tap->wr_rate = 96; break;
2005 case 0xc: tap->wr_rate = 108; break;
2006 }
2007 }
2008 mb.m_datam_hdr.mh_data = (caddr_t)tap;
2009 mb.m_lenm_hdr.mh_len = sc->sc_rxtap_len;
2010 mb.m_nextm_hdr.mh_next = m;
2011 mb.m_nextpktm_hdr.mh_nextpkt = NULL((void *)0);
2012 mb.m_typem_hdr.mh_type = 0;
2013 mb.m_flagsm_hdr.mh_flags = 0;
2014 bpf_mtap(sc->sc_drvbpf, &mb, BPF_DIRECTION_IN(1 << 0));
2015}
2016#endif
2017
2018void
2019athn_usb_rx_frame(struct athn_usb_softc *usc, struct mbuf *m,
2020 struct mbuf_list *ml)
2021{
2022 struct athn_softc *sc = &usc->sc_sc;
2023 struct ieee80211com *ic = &sc->sc_ic;
2024 struct ifnet *ifp = &ic->ic_ific_ac.ac_if;
2025 struct ieee80211_frame *wh;
2026 struct ieee80211_node *ni;
2027 struct ieee80211_rxinfo rxi;
2028 struct ar_htc_frame_hdr *htc;
2029 struct ar_rx_status *rs;
2030 uint16_t datalen;
2031 int s;
2032
2033 if (__predict_false(m->m_len < sizeof(*htc))__builtin_expect(((m->m_hdr.mh_len < sizeof(*htc)) != 0
), 0)
)
2034 goto skip;
2035 htc = mtod(m, struct ar_htc_frame_hdr *)((struct ar_htc_frame_hdr *)((m)->m_hdr.mh_data));
2036 if (__predict_false(htc->endpoint_id == 0)__builtin_expect(((htc->endpoint_id == 0) != 0), 0)) {
2037 DPRINTF(("bad endpoint %d\n", htc->endpoint_id));
2038 goto skip;
2039 }
2040 if (htc->flags & AR_HTC_FLAG_TRAILER0x02) {
2041 if (m->m_lenm_hdr.mh_len < htc->control[0])
2042 goto skip;
2043 m_adj(m, -(int)htc->control[0]);
2044 }
2045 m_adj(m, sizeof(*htc)); /* Strip HTC header. */
2046
2047 if (__predict_false(m->m_len < sizeof(*rs))__builtin_expect(((m->m_hdr.mh_len < sizeof(*rs)) != 0)
, 0)
)
2048 goto skip;
2049 rs = mtod(m, struct ar_rx_status *)((struct ar_rx_status *)((m)->m_hdr.mh_data));
2050
2051 /* Make sure that payload fits. */
2052 datalen = betoh16(rs->rs_datalen)(__uint16_t)(__builtin_constant_p(rs->rs_datalen) ? (__uint16_t
)(((__uint16_t)(rs->rs_datalen) & 0xffU) << 8 | (
(__uint16_t)(rs->rs_datalen) & 0xff00U) >> 8) : __swap16md
(rs->rs_datalen))
;
2053 if (__predict_false(m->m_len < sizeof(*rs) + datalen)__builtin_expect(((m->m_hdr.mh_len < sizeof(*rs) + datalen
) != 0), 0)
)
2054 goto skip;
2055
2056 if (__predict_false(datalen < sizeof(*wh) + IEEE80211_CRC_LEN)__builtin_expect(((datalen < sizeof(*wh) + 4) != 0), 0))
2057 goto skip;
2058
2059 if (rs->rs_status != 0) {
2060 if (rs->rs_status & AR_RXS_RXERR_DECRYPT0x08)
2061 ic->ic_stats.is_ccmp_dec_errs++;
2062 ifp->if_ierrorsif_data.ifi_ierrors++;
2063 goto skip;
2064 }
2065 m_adj(m, sizeof(*rs)); /* Strip Rx status. */
2066
2067 s = splnet()splraise(0x7);
2068
2069 /* Grab a reference to the source node. */
2070 wh = mtod(m, struct ieee80211_frame *)((struct ieee80211_frame *)((m)->m_hdr.mh_data));
2071 ni = ieee80211_find_rxnode(ic, wh);
2072
2073 /* Remove any HW padding after the 802.11 header. */
2074 if (!(wh->i_fc[0] & IEEE80211_FC0_TYPE_CTL0x04)) {
2075 u_int hdrlen = ieee80211_get_hdrlen(wh);
2076 if (hdrlen & 3) {
2077 memmove((caddr_t)wh + 2, wh, hdrlen)__builtin_memmove(((caddr_t)wh + 2), (wh), (hdrlen));
2078 m_adj(m, 2);
2079 }
2080 wh = mtod(m, struct ieee80211_frame *)((struct ieee80211_frame *)((m)->m_hdr.mh_data));
2081 }
2082#if NBPFILTER1 > 0
2083 if (__predict_false(sc->sc_drvbpf != NULL)__builtin_expect(((sc->sc_drvbpf != ((void *)0)) != 0), 0))
2084 athn_usb_rx_radiotap(sc, m, rs);
2085#endif
2086 /* Trim 802.11 FCS after radiotap. */
2087 m_adj(m, -IEEE80211_CRC_LEN4);
2088
2089 /* Send the frame to the 802.11 layer. */
2090 rxi.rxi_flags = 0;
2091 rxi.rxi_rssi = rs->rs_rssi + AR_USB_DEFAULT_NF(-95);
2092 rxi.rxi_tstamp = betoh64(rs->rs_tstamp)(__uint64_t)(__builtin_constant_p(rs->rs_tstamp) ? (__uint64_t
)((((__uint64_t)(rs->rs_tstamp) & 0xff) << 56) |
((__uint64_t)(rs->rs_tstamp) & 0xff00ULL) << 40
| ((__uint64_t)(rs->rs_tstamp) & 0xff0000ULL) <<
24 | ((__uint64_t)(rs->rs_tstamp) & 0xff000000ULL) <<
8 | ((__uint64_t)(rs->rs_tstamp) & 0xff00000000ULL) >>
8 | ((__uint64_t)(rs->rs_tstamp) & 0xff0000000000ULL)
>> 24 | ((__uint64_t)(rs->rs_tstamp) & 0xff000000000000ULL
) >> 40 | ((__uint64_t)(rs->rs_tstamp) & 0xff00000000000000ULL
) >> 56) : __swap64md(rs->rs_tstamp))
;
2093 if (!(wh->i_fc[0] & IEEE80211_FC0_TYPE_CTL0x04) &&
2094 (wh->i_fc[1] & IEEE80211_FC1_PROTECTED0x40) &&
2095 (ic->ic_flags & IEEE80211_F_RSNON0x00200000) &&
2096 (ni->ni_flags & IEEE80211_NODE_RXPROT0x0008) &&
2097 (ni->ni_rsncipher == IEEE80211_CIPHER_CCMP ||
2098 (IEEE80211_IS_MULTICAST(wh->i_addr1)(*(wh->i_addr1) & 0x01) &&
2099 ni->ni_rsngroupcipher == IEEE80211_CIPHER_CCMP))) {
2100 if (ar5008_ccmp_decap(sc, m, ni) != 0) {
2101 ifp->if_ierrorsif_data.ifi_ierrors++;
2102 ieee80211_release_node(ic, ni);
2103 splx(s)spllower(s);
2104 goto skip;
2105 }
2106 rxi.rxi_flags |= IEEE80211_RXI_HWDEC0x00000001;
2107 }
2108 ieee80211_inputm(ifp, m, ni, &rxi, ml);
2109
2110 /* Node is no longer needed. */
2111 ieee80211_release_node(ic, ni);
2112 splx(s)spllower(s);
2113 return;
2114 skip:
2115 m_freem(m);
2116}
2117
2118void
2119athn_usb_rxeof(struct usbd_xfer *xfer, void *priv,
2120 usbd_status status)
2121{
2122 struct mbuf_list ml = MBUF_LIST_INITIALIZER(){ ((void *)0), ((void *)0), 0 };
2123 struct athn_usb_rx_data *data = priv;
2124 struct athn_usb_softc *usc = data->sc;
2125 struct athn_softc *sc = &usc->sc_sc;
2126 struct ifnet *ifp = &sc->sc_ic.ic_ific_ac.ac_if;
2127 struct athn_usb_rx_stream *stream = &usc->rx_stream;
2128 uint8_t *buf = data->buf;
2129 struct ar_stream_hdr *hdr;
2130 struct mbuf *m;
2131 uint16_t pktlen;
2132 int off, len;
2133
2134 if (__predict_false(status != USBD_NORMAL_COMPLETION)__builtin_expect(((status != USBD_NORMAL_COMPLETION) != 0), 0
)
) {
2135 DPRINTF(("RX status=%d\n", status));
2136 if (status == USBD_STALLED)
2137 usbd_clear_endpoint_stall_async(usc->rx_data_pipe);
2138 if (status != USBD_CANCELLED)
2139 goto resubmit;
2140 return;
2141 }
2142 usbd_get_xfer_status(xfer, NULL((void *)0), NULL((void *)0), &len, NULL((void *)0));
2143
2144 if (stream->left > 0) {
2145 if (len >= stream->left) {
2146 /* We have all our pktlen bytes now. */
2147 if (__predict_true(stream->m != NULL)__builtin_expect(((stream->m != ((void *)0)) != 0), 1)) {
2148 memcpy(mtod(stream->m, uint8_t *) +__builtin_memcpy((((uint8_t *)((stream->m)->m_hdr.mh_data
)) + stream->moff), (buf), (stream->left))
2149 stream->moff, buf, stream->left)__builtin_memcpy((((uint8_t *)((stream->m)->m_hdr.mh_data
)) + stream->moff), (buf), (stream->left))
;
2150 athn_usb_rx_frame(usc, stream->m, &ml);
2151 stream->m = NULL((void *)0);
2152 }
2153 /* Next header is 32-bit aligned. */
2154 off = (stream->left + 3) & ~3;
2155 buf += off;
2156 len -= off;
2157 stream->left = 0;
2158 } else {
2159 /* Still need more bytes, save what we have. */
2160 if (__predict_true(stream->m != NULL)__builtin_expect(((stream->m != ((void *)0)) != 0), 1)) {
2161 memcpy(mtod(stream->m, uint8_t *) +__builtin_memcpy((((uint8_t *)((stream->m)->m_hdr.mh_data
)) + stream->moff), (buf), (len))
2162 stream->moff, buf, len)__builtin_memcpy((((uint8_t *)((stream->m)->m_hdr.mh_data
)) + stream->moff), (buf), (len))
;
2163 stream->moff += len;
2164 }
2165 stream->left -= len;
2166 goto resubmit;
2167 }
2168 }
2169 KASSERT(stream->left == 0)((stream->left == 0) ? (void)0 : __assert("diagnostic ", "/usr/src/sys/dev/usb/if_athn_usb.c"
, 2169, "stream->left == 0"))
;
2170 while (len >= sizeof(*hdr)) {
2171 hdr = (struct ar_stream_hdr *)buf;
2172 if (hdr->tag != htole16(AR_USB_RX_STREAM_TAG)((__uint16_t)(0x4e00))) {
2173 DPRINTF(("invalid tag 0x%x\n", hdr->tag));
2174 break;
2175 }
2176 pktlen = letoh16(hdr->len)((__uint16_t)(hdr->len));
2177 buf += sizeof(*hdr);
2178 len -= sizeof(*hdr);
2179
2180 if (__predict_true(pktlen <= MCLBYTES)__builtin_expect(((pktlen <= (1 << 11)) != 0), 1)) {
2181 /* Allocate an mbuf to store the next pktlen bytes. */
2182 MGETHDR(m, M_DONTWAIT, MT_DATA)m = m_gethdr((0x0002), (1));
2183 if (__predict_true(m != NULL)__builtin_expect(((m != ((void *)0)) != 0), 1)) {
2184 m->m_pkthdrM_dat.MH.MH_pkthdr.len = m->m_lenm_hdr.mh_len = pktlen;
2185 if (pktlen > MHLEN((256 - sizeof(struct m_hdr)) - sizeof(struct pkthdr))) {
2186 MCLGET(m, M_DONTWAIT)(void) m_clget((m), (0x0002), (1 << 11));
2187 if (!(m->m_flagsm_hdr.mh_flags & M_EXT0x0001)) {
2188 m_free(m);
2189 m = NULL((void *)0);
2190 }
2191 }
2192 }
2193 } else /* Drop frames larger than MCLBYTES. */
2194 m = NULL((void *)0);
2195
2196 if (m == NULL((void *)0))
2197 ifp->if_ierrorsif_data.ifi_ierrors++;
2198
2199 /*
2200 * NB: m can be NULL, in which case the next pktlen bytes
2201 * will be discarded from the Rx stream.
2202 */
2203 if (pktlen > len) {
2204 /* Need more bytes, save what we have. */
2205 stream->m = m; /* NB: m can be NULL. */
2206 if (__predict_true(stream->m != NULL)__builtin_expect(((stream->m != ((void *)0)) != 0), 1)) {
2207 memcpy(mtod(stream->m, uint8_t *), buf, len)__builtin_memcpy((((uint8_t *)((stream->m)->m_hdr.mh_data
))), (buf), (len))
;
2208 stream->moff = len;
2209 }
2210 stream->left = pktlen - len;
2211 goto resubmit;
2212 }
2213 if (__predict_true(m != NULL)__builtin_expect(((m != ((void *)0)) != 0), 1)) {
2214 /* We have all the pktlen bytes in this xfer. */
2215 memcpy(mtod(m, uint8_t *), buf, pktlen)__builtin_memcpy((((uint8_t *)((m)->m_hdr.mh_data))), (buf
), (pktlen))
;
2216 athn_usb_rx_frame(usc, m, &ml);
2217 }
2218
2219 /* Next header is 32-bit aligned. */
2220 off = (pktlen + 3) & ~3;
2221 buf += off;
2222 len -= off;
2223 }
2224 if_input(ifp, &ml);
2225
2226 resubmit:
2227 /* Setup a new transfer. */
2228 usbd_setup_xfer(xfer, usc->rx_data_pipe, data, data->buf,
2229 ATHN_USB_RXBUFSZ(8 * 1024), USBD_SHORT_XFER_OK0x04 | USBD_NO_COPY0x01,
2230 USBD_NO_TIMEOUT0, athn_usb_rxeof);
2231 (void)usbd_transfer(xfer);
2232}
2233
2234void
2235athn_usb_txeof(struct usbd_xfer *xfer, void *priv,
2236 usbd_status status)
2237{
2238 struct athn_usb_tx_data *data = priv;
2239 struct athn_usb_softc *usc = data->sc;
2240 struct athn_softc *sc = &usc->sc_sc;
2241 struct ifnet *ifp = &sc->sc_ic.ic_ific_ac.ac_if;
2242 int s;
2243
2244 s = splnet()splraise(0x7);
2245 /* Put this Tx buffer back to our free list. */
2246 TAILQ_INSERT_TAIL(&usc->tx_free_list, data, next)do { (data)->next.tqe_next = ((void *)0); (data)->next.
tqe_prev = (&usc->tx_free_list)->tqh_last; *(&usc
->tx_free_list)->tqh_last = (data); (&usc->tx_free_list
)->tqh_last = &(data)->next.tqe_next; } while (0)
;
2247
2248 if (__predict_false(status != USBD_NORMAL_COMPLETION)__builtin_expect(((status != USBD_NORMAL_COMPLETION) != 0), 0
)
) {
2249 DPRINTF(("TX status=%d\n", status));
2250 if (status == USBD_STALLED)
2251 usbd_clear_endpoint_stall_async(usc->tx_data_pipe);
2252 ifp->if_oerrorsif_data.ifi_oerrors++;
2253 splx(s)spllower(s);
2254 /* XXX Why return? */
2255 return;
2256 }
2257 sc->sc_tx_timer = 0;
2258
2259 /* We just released a Tx buffer, notify Tx. */
2260 if (ifq_is_oactive(&ifp->if_snd)) {
2261 ifq_clr_oactive(&ifp->if_snd);
2262 ifp->if_start(ifp);
2263 }
2264 splx(s)spllower(s);
2265}
2266
2267int
2268athn_usb_tx(struct athn_softc *sc, struct mbuf *m, struct ieee80211_node *ni)
2269{
2270 struct athn_usb_softc *usc = (struct athn_usb_softc *)sc;
2271 struct athn_node *an = (struct athn_node *)ni;
2272 struct ieee80211com *ic = &sc->sc_ic;
2273 struct ieee80211_frame *wh;
2274 struct ieee80211_key *k = NULL((void *)0);
2275 struct athn_usb_tx_data *data;
2276 struct ar_stream_hdr *hdr;
2277 struct ar_htc_frame_hdr *htc;
2278 struct ar_tx_frame *txf;
2279 struct ar_tx_mgmt *txm;
2280 uint8_t *frm;
2281 uint16_t qos;
2282 uint8_t qid, tid = 0;
2283 int hasqos, xferlen, error;
2284
2285 wh = mtod(m, struct ieee80211_frame *)((struct ieee80211_frame *)((m)->m_hdr.mh_data));
2286 if (wh->i_fc[1] & IEEE80211_FC1_PROTECTED0x40) {
2287 k = ieee80211_get_txkey(ic, wh, ni);
2288 if (k->k_cipher == IEEE80211_CIPHER_CCMP) {
2289 u_int hdrlen = ieee80211_get_hdrlen(wh);
2290 if (ar5008_ccmp_encap(m, hdrlen, k) != 0)
2291 return (ENOBUFS55);
2292 } else {
2293 if ((m = ieee80211_encrypt(ic, m, k)) == NULL((void *)0))
2294 return (ENOBUFS55);
2295 k = NULL((void *)0); /* skip hardware crypto further below */
2296 }
2297 wh = mtod(m, struct ieee80211_frame *)((struct ieee80211_frame *)((m)->m_hdr.mh_data));
2298 }
2299 if ((hasqos = ieee80211_has_qos(wh))) {
2300 qos = ieee80211_get_qos(wh);
2301 tid = qos & IEEE80211_QOS_TID0x000f;
2302 qid = ieee80211_up_to_ac(ic, tid);
2303 } else
2304 qid = EDCA_AC_BE;
2305
2306 /* Grab a Tx buffer from our free list. */
2307 data = TAILQ_FIRST(&usc->tx_free_list)((&usc->tx_free_list)->tqh_first);
2308 TAILQ_REMOVE(&usc->tx_free_list, data, next)do { if (((data)->next.tqe_next) != ((void *)0)) (data)->
next.tqe_next->next.tqe_prev = (data)->next.tqe_prev; else
(&usc->tx_free_list)->tqh_last = (data)->next.tqe_prev
; *(data)->next.tqe_prev = (data)->next.tqe_next; ((data
)->next.tqe_prev) = ((void *)-1); ((data)->next.tqe_next
) = ((void *)-1); } while (0)
;
2309
2310#if NBPFILTER1 > 0
2311 /* XXX Change radiotap Tx header for USB (no txrate). */
2312 if (__predict_false(sc->sc_drvbpf != NULL)__builtin_expect(((sc->sc_drvbpf != ((void *)0)) != 0), 0)) {
2313 struct athn_tx_radiotap_header *tap = &sc->sc_txtapsc_txtapu.th;
2314 struct mbuf mb;
2315
2316 tap->wt_flags = 0;
2317 tap->wt_chan_freq = htole16(ic->ic_bss->ni_chan->ic_freq)((__uint16_t)(ic->ic_bss->ni_chan->ic_freq));
2318 tap->wt_chan_flags = htole16(ic->ic_bss->ni_chan->ic_flags)((__uint16_t)(ic->ic_bss->ni_chan->ic_flags));
2319 mb.m_datam_hdr.mh_data = (caddr_t)tap;
2320 mb.m_lenm_hdr.mh_len = sc->sc_txtap_len;
2321 mb.m_nextm_hdr.mh_next = m;
2322 mb.m_nextpktm_hdr.mh_nextpkt = NULL((void *)0);
2323 mb.m_typem_hdr.mh_type = 0;
2324 mb.m_flagsm_hdr.mh_flags = 0;
2325 bpf_mtap(sc->sc_drvbpf, &mb, BPF_DIRECTION_OUT(1 << 1));
2326 }
2327#endif
2328
2329 /* NB: We don't take advantage of USB Tx stream mode for now. */
2330 hdr = (struct ar_stream_hdr *)data->buf;
2331 hdr->tag = htole16(AR_USB_TX_STREAM_TAG)((__uint16_t)(0x697e));
2332
2333 htc = (struct ar_htc_frame_hdr *)&hdr[1];
2334 memset(htc, 0, sizeof(*htc))__builtin_memset((htc), (0), (sizeof(*htc)));
2335 if ((wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK0x0c) ==
2336 IEEE80211_FC0_TYPE_DATA0x08) {
2337 htc->endpoint_id = usc->ep_data[qid];
2338
2339 txf = (struct ar_tx_frame *)&htc[1];
2340 memset(txf, 0, sizeof(*txf))__builtin_memset((txf), (0), (sizeof(*txf)));
2341 txf->data_type = AR_HTC_NORMAL2;
2342 txf->node_idx = an->sta_index;
2343 txf->vif_idx = 0;
2344 txf->tid = tid;
2345 if (m->m_pkthdrM_dat.MH.MH_pkthdr.len + IEEE80211_CRC_LEN4 > ic->ic_rtsthreshold)
2346 txf->flags |= htobe32(AR_HTC_TX_RTSCTS)(__uint32_t)(__builtin_constant_p(0x00000002) ? (__uint32_t)(
((__uint32_t)(0x00000002) & 0xff) << 24 | ((__uint32_t
)(0x00000002) & 0xff00) << 8 | ((__uint32_t)(0x00000002
) & 0xff0000) >> 8 | ((__uint32_t)(0x00000002) &
0xff000000) >> 24) : __swap32md(0x00000002))
;
2347 else if (ic->ic_flags & IEEE80211_F_USEPROT0x00100000) {
2348 if (ic->ic_protmode == IEEE80211_PROT_CTSONLY)
2349 txf->flags |= htobe32(AR_HTC_TX_CTSONLY)(__uint32_t)(__builtin_constant_p(0x00000001) ? (__uint32_t)(
((__uint32_t)(0x00000001) & 0xff) << 24 | ((__uint32_t
)(0x00000001) & 0xff00) << 8 | ((__uint32_t)(0x00000001
) & 0xff0000) >> 8 | ((__uint32_t)(0x00000001) &
0xff000000) >> 24) : __swap32md(0x00000001))
;
2350 else if (ic->ic_protmode == IEEE80211_PROT_RTSCTS)
2351 txf->flags |= htobe32(AR_HTC_TX_RTSCTS)(__uint32_t)(__builtin_constant_p(0x00000002) ? (__uint32_t)(
((__uint32_t)(0x00000002) & 0xff) << 24 | ((__uint32_t
)(0x00000002) & 0xff00) << 8 | ((__uint32_t)(0x00000002
) & 0xff0000) >> 8 | ((__uint32_t)(0x00000002) &
0xff000000) >> 24) : __swap32md(0x00000002))
;
2352 }
2353
2354 if (k != NULL((void *)0)) {
2355 /* Map 802.11 cipher to hardware encryption type. */
2356 if (k->k_cipher == IEEE80211_CIPHER_CCMP) {
2357 txf->key_type = AR_ENCR_TYPE_AES2;
2358 } else
2359 panic("unsupported cipher");
2360 /*
2361 * NB: The key cache entry index is stored in the key
2362 * private field when the key is installed.
2363 */
2364 txf->key_idx = (uintptr_t)k->k_priv;
2365 } else
2366 txf->key_idx = 0xff;
2367
2368 txf->cookie = an->sta_index;
2369 frm = (uint8_t *)&txf[1];
2370 } else {
2371 htc->endpoint_id = usc->ep_mgmt;
2372
2373 txm = (struct ar_tx_mgmt *)&htc[1];
2374 memset(txm, 0, sizeof(*txm))__builtin_memset((txm), (0), (sizeof(*txm)));
2375 txm->node_idx = an->sta_index;
2376 txm->vif_idx = 0;
2377 txm->key_idx = 0xff;
2378 txm->cookie = an->sta_index;
2379 frm = (uint8_t *)&txm[1];
2380 }
2381 /* Copy payload. */
2382 m_copydata(m, 0, m->m_pkthdrM_dat.MH.MH_pkthdr.len, frm);
2383 frm += m->m_pkthdrM_dat.MH.MH_pkthdr.len;
2384 m_freem(m);
2385
2386 /* Finalize headers. */
2387 htc->payload_len = htobe16(frm - (uint8_t *)&htc[1])(__uint16_t)(__builtin_constant_p(frm - (uint8_t *)&htc[1
]) ? (__uint16_t)(((__uint16_t)(frm - (uint8_t *)&htc[1])
& 0xffU) << 8 | ((__uint16_t)(frm - (uint8_t *)&
htc[1]) & 0xff00U) >> 8) : __swap16md(frm - (uint8_t
*)&htc[1]))
;
2388 hdr->len = htole16(frm - (uint8_t *)&hdr[1])((__uint16_t)(frm - (uint8_t *)&hdr[1]));
2389 xferlen = frm - data->buf;
2390
2391 usbd_setup_xfer(data->xfer, usc->tx_data_pipe, data, data->buf,
2392 xferlen, USBD_FORCE_SHORT_XFER0x08 | USBD_NO_COPY0x01, ATHN_USB_TX_TIMEOUT5000,
2393 athn_usb_txeof);
2394 error = usbd_transfer(data->xfer);
2395 if (__predict_false(error != USBD_IN_PROGRESS && error != 0)__builtin_expect(((error != USBD_IN_PROGRESS && error
!= 0) != 0), 0)
) {
2396 /* Put this Tx buffer back to our free list. */
2397 TAILQ_INSERT_TAIL(&usc->tx_free_list, data, next)do { (data)->next.tqe_next = ((void *)0); (data)->next.
tqe_prev = (&usc->tx_free_list)->tqh_last; *(&usc
->tx_free_list)->tqh_last = (data); (&usc->tx_free_list
)->tqh_last = &(data)->next.tqe_next; } while (0)
;
2398 return (error);
2399 }
2400 ieee80211_release_node(ic, ni);
2401 return (0);
2402}
2403
2404void
2405athn_usb_start(struct ifnet *ifp)
2406{
2407 struct athn_softc *sc = ifp->if_softc;
2408 struct athn_usb_softc *usc = (struct athn_usb_softc *)sc;
2409 struct ieee80211com *ic = &sc->sc_ic;
2410 struct ieee80211_node *ni;
2411 struct mbuf *m;
2412
2413 if (!(ifp->if_flags & IFF_RUNNING0x40) || ifq_is_oactive(&ifp->if_snd))
2414 return;
2415
2416 for (;;) {
2417 if (TAILQ_EMPTY(&usc->tx_free_list)(((&usc->tx_free_list)->tqh_first) == ((void *)0))) {
2418 ifq_set_oactive(&ifp->if_snd);
2419 break;
2420 }
2421 /* Send pending management frames first. */
2422 m = mq_dequeue(&ic->ic_mgtq);
2423 if (m != NULL((void *)0)) {
2424 ni = m->m_pkthdrM_dat.MH.MH_pkthdr.ph_cookie;
2425 goto sendit;
2426 }
2427 if (ic->ic_state != IEEE80211_S_RUN)
2428 break;
2429
2430 /* Encapsulate and send data frames. */
2431 m = ifq_dequeue(&ifp->if_snd);
2432 if (m == NULL((void *)0))
2433 break;
2434#if NBPFILTER1 > 0
2435 if (ifp->if_bpf != NULL((void *)0))
2436 bpf_mtap(ifp->if_bpf, m, BPF_DIRECTION_OUT(1 << 1));
2437#endif
2438 if ((m = ieee80211_encap(ifp, m, &ni)) == NULL((void *)0))
2439 continue;
2440 sendit:
2441#if NBPFILTER1 > 0
2442 if (ic->ic_rawbpf != NULL((void *)0))
2443 bpf_mtap(ic->ic_rawbpf, m, BPF_DIRECTION_OUT(1 << 1));
2444#endif
2445 if (athn_usb_tx(sc, m, ni) != 0) {
2446 ieee80211_release_node(ic, ni);
2447 ifp->if_oerrorsif_data.ifi_oerrors++;
2448 continue;
2449 }
2450
2451 sc->sc_tx_timer = 5;
2452 ifp->if_timer = 1;
2453 }
2454}
2455
2456void
2457athn_usb_watchdog(struct ifnet *ifp)
2458{
2459 struct athn_softc *sc = ifp->if_softc;
2460
2461 ifp->if_timer = 0;
2462
2463 if (sc->sc_tx_timer > 0) {
2464 if (--sc->sc_tx_timer == 0) {
2465 printf("%s: device timeout\n", sc->sc_dev.dv_xname);
2466 /* athn_usb_init(ifp); XXX needs a process context! */
2467 ifp->if_oerrorsif_data.ifi_oerrors++;
2468 return;
2469 }
2470 ifp->if_timer = 1;
2471 }
2472 ieee80211_watchdog(ifp);
2473}
2474
2475int
2476athn_usb_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
2477{
2478 struct athn_softc *sc = ifp->if_softc;
2479 struct athn_usb_softc *usc = (struct athn_usb_softc *)sc;
2480 struct ieee80211com *ic = &sc->sc_ic;
2481 int s, error = 0;
2482
2483 if (usbd_is_dying(usc->sc_udev))
2484 return ENXIO6;
2485
2486 usbd_ref_incr(usc->sc_udev);
2487
2488 s = splnet()splraise(0x7);
2489
2490 switch (cmd) {
2491 case SIOCSIFADDR((unsigned long)0x80000000 | ((sizeof(struct ifreq) & 0x1fff
) << 16) | ((('i')) << 8) | ((12)))
:
2492 ifp->if_flags |= IFF_UP0x1;
2493 /* FALLTHROUGH */
2494 case SIOCSIFFLAGS((unsigned long)0x80000000 | ((sizeof(struct ifreq) & 0x1fff
) << 16) | ((('i')) << 8) | ((16)))
:
2495 if (ifp->if_flags & IFF_UP0x1) {
2496 if (!(ifp->if_flags & IFF_RUNNING0x40))
2497 error = athn_usb_init(ifp);
2498 } else {
2499 if (ifp->if_flags & IFF_RUNNING0x40)
2500 athn_usb_stop(ifp);
2501 }
2502 break;
2503 case SIOCS80211CHANNEL((unsigned long)0x80000000 | ((sizeof(struct ieee80211chanreq
) & 0x1fff) << 16) | ((('i')) << 8) | ((238))
)
:
2504 error = ieee80211_ioctl(ifp, cmd, data);
2505 if (error == ENETRESET52 &&
2506 ic->ic_opmode == IEEE80211_M_MONITOR) {
2507 if ((ifp->if_flags & (IFF_UP0x1 | IFF_RUNNING0x40)) ==
2508 (IFF_UP0x1 | IFF_RUNNING0x40)) {
2509 athn_usb_switch_chan(sc, ic->ic_ibss_chan,
2510 NULL((void *)0));
2511 }
2512 error = 0;
2513 }
2514 break;
2515 default:
2516 error = ieee80211_ioctl(ifp, cmd, data);
2517 }
2518
2519 if (error == ENETRESET52) {
2520 error = 0;
2521 if ((ifp->if_flags & (IFF_UP0x1 | IFF_RUNNING0x40)) ==
2522 (IFF_UP0x1 | IFF_RUNNING0x40)) {
2523 athn_usb_stop(ifp);
2524 error = athn_usb_init(ifp);
2525 }
2526 }
2527 splx(s)spllower(s);
2528
2529 usbd_ref_decr(usc->sc_udev);
2530
2531 return (error);
2532}
2533
2534int
2535athn_usb_init(struct ifnet *ifp)
2536{
2537 struct athn_softc *sc = ifp->if_softc;
2538 struct athn_usb_softc *usc = (struct athn_usb_softc *)sc;
2539 struct athn_ops *ops = &sc->ops;
2540 struct ieee80211com *ic = &sc->sc_ic;
2541 struct ieee80211_channel *c, *extc;
2542 struct athn_usb_rx_data *data;
2543 struct ar_htc_target_vif hvif;
2544 struct ar_htc_target_sta sta;
2545 struct ar_htc_cap_target hic;
2546 uint16_t mode;
2547 int i, error;
2548
2549 /* Init host async commands ring. */
2550 usc->cmdq.cur = usc->cmdq.next = usc->cmdq.queued = 0;
2551
2552 /* Allocate Tx/Rx buffers. */
2553 error = athn_usb_alloc_rx_list(usc);
2554 if (error != 0)
2555 goto fail;
2556 error = athn_usb_alloc_tx_list(usc);
2557 if (error != 0)
2558 goto fail;
2559 /* Steal one buffer for beacons. */
2560 usc->tx_bcn = TAILQ_FIRST(&usc->tx_free_list)((&usc->tx_free_list)->tqh_first);
2561 TAILQ_REMOVE(&usc->tx_free_list, usc->tx_bcn, next)do { if (((usc->tx_bcn)->next.tqe_next) != ((void *)0))
(usc->tx_bcn)->next.tqe_next->next.tqe_prev = (usc->
tx_bcn)->next.tqe_prev; else (&usc->tx_free_list)->
tqh_last = (usc->tx_bcn)->next.tqe_prev; *(usc->tx_bcn
)->next.tqe_prev = (usc->tx_bcn)->next.tqe_next; ((usc
->tx_bcn)->next.tqe_prev) = ((void *)-1); ((usc->tx_bcn
)->next.tqe_next) = ((void *)-1); } while (0)
;
2562
2563 c = ic->ic_bss->ni_chan = ic->ic_ibss_chan;
2564 extc = NULL((void *)0);
2565
2566 /* In case a new MAC address has been configured. */
2567 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))
;
2568
2569 error = athn_set_power_awake(sc);
2570 if (error != 0)
2571 goto fail;
2572
2573 error = athn_usb_wmi_cmd(usc, AR_WMI_CMD_FLUSH_RECV)athn_usb_wmi_xcmd(usc, 0x00e, ((void *)0), 0, ((void *)0));
2574 if (error != 0)
2575 goto fail;
2576
2577 error = athn_hw_reset(sc, c, extc, 1);
2578 if (error != 0)
2579 goto fail;
2580
2581 ops->set_txpower(sc, c, extc);
2582
2583 mode = htobe16(IEEE80211_IS_CHAN_2GHZ(c) ?(__uint16_t)(__builtin_constant_p((((c)->ic_flags & 0x0080
) != 0) ? 1 : 0) ? (__uint16_t)(((__uint16_t)((((c)->ic_flags
& 0x0080) != 0) ? 1 : 0) & 0xffU) << 8 | ((__uint16_t
)((((c)->ic_flags & 0x0080) != 0) ? 1 : 0) & 0xff00U
) >> 8) : __swap16md((((c)->ic_flags & 0x0080) !=
0) ? 1 : 0))
2584 AR_HTC_MODE_11NG : AR_HTC_MODE_11NA)(__uint16_t)(__builtin_constant_p((((c)->ic_flags & 0x0080
) != 0) ? 1 : 0) ? (__uint16_t)(((__uint16_t)((((c)->ic_flags
& 0x0080) != 0) ? 1 : 0) & 0xffU) << 8 | ((__uint16_t
)((((c)->ic_flags & 0x0080) != 0) ? 1 : 0) & 0xff00U
) >> 8) : __swap16md((((c)->ic_flags & 0x0080) !=
0) ? 1 : 0))
;
2585 error = athn_usb_wmi_xcmd(usc, AR_WMI_CMD_SET_MODE0x00f,
2586 &mode, sizeof(mode), NULL((void *)0));
2587 if (error != 0)
2588 goto fail;
2589
2590 error = athn_usb_wmi_cmd(usc, AR_WMI_CMD_ATH_INIT)athn_usb_wmi_xcmd(usc, 0x006, ((void *)0), 0, ((void *)0));
2591 if (error != 0)
2592 goto fail;
2593
2594 error = athn_usb_wmi_cmd(usc, AR_WMI_CMD_START_RECV)athn_usb_wmi_xcmd(usc, 0x00c, ((void *)0), 0, ((void *)0));
2595 if (error != 0)
2596 goto fail;
2597
2598 athn_rx_start(sc);
2599
2600 /* Create main interface on target. */
2601 memset(&hvif, 0, sizeof(hvif))__builtin_memset((&hvif), (0), (sizeof(hvif)));
2602 hvif.index = 0;
2603 IEEE80211_ADDR_COPY(hvif.myaddr, ic->ic_myaddr)__builtin_memcpy((hvif.myaddr), (ic->ic_myaddr), (6));
2604 switch (ic->ic_opmode) {
2605 case IEEE80211_M_STA:
2606 hvif.opmode = htobe32(AR_HTC_M_STA)(__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
))
;
2607 break;
2608 case IEEE80211_M_MONITOR:
2609 hvif.opmode = htobe32(AR_HTC_M_MONITOR)(__uint32_t)(__builtin_constant_p(8) ? (__uint32_t)(((__uint32_t
)(8) & 0xff) << 24 | ((__uint32_t)(8) & 0xff00)
<< 8 | ((__uint32_t)(8) & 0xff0000) >> 8 | (
(__uint32_t)(8) & 0xff000000) >> 24) : __swap32md(8
))
;
2610 break;
2611#ifndef IEEE80211_STA_ONLY
2612 case IEEE80211_M_IBSS:
2613 hvif.opmode = htobe32(AR_HTC_M_IBSS)(__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
))
;
2614 break;
2615 case IEEE80211_M_AHDEMO:
2616 hvif.opmode = htobe32(AR_HTC_M_AHDEMO)(__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
))
;
2617 break;
2618 case IEEE80211_M_HOSTAP:
2619 hvif.opmode = htobe32(AR_HTC_M_HOSTAP)(__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
))
;
2620 break;
2621#endif
2622 }
2623 hvif.rtsthreshold = htobe16(ic->ic_rtsthreshold)(__uint16_t)(__builtin_constant_p(ic->ic_rtsthreshold) ? (
__uint16_t)(((__uint16_t)(ic->ic_rtsthreshold) & 0xffU
) << 8 | ((__uint16_t)(ic->ic_rtsthreshold) & 0xff00U
) >> 8) : __swap16md(ic->ic_rtsthreshold))
;
2624 DPRINTF(("creating VAP\n"));
2625 error = athn_usb_wmi_xcmd(usc, AR_WMI_CMD_VAP_CREATE0x013,
2626 &hvif, sizeof(hvif), NULL((void *)0));
2627 if (error != 0)
2628 goto fail;
2629
2630 /* Create a fake node to send management frames before assoc. */
2631 memset(&sta, 0, sizeof(sta))__builtin_memset((&sta), (0), (sizeof(sta)));
2632 IEEE80211_ADDR_COPY(sta.macaddr, ic->ic_myaddr)__builtin_memcpy((sta.macaddr), (ic->ic_myaddr), (6));
2633 sta.sta_index = 0;
2634 sta.is_vif_sta = 1;
2635 sta.vif_index = hvif.index;
2636 sta.maxampdu = 0xffff;
2637 DPRINTF(("creating default node\n"));
2638 error = athn_usb_wmi_xcmd(usc, AR_WMI_CMD_NODE_CREATE0x010,
2639 &sta, sizeof(sta), NULL((void *)0));
2640 if (error != 0)
2641 goto fail;
2642 usc->free_node_slots = ~(1 << sta.sta_index);
2643
2644 /* Update target capabilities. */
2645 memset(&hic, 0, sizeof(hic))__builtin_memset((&hic), (0), (sizeof(hic)));
2646 hic.ampdu_limit = htobe32(0x0000ffff)(__uint32_t)(__builtin_constant_p(0x0000ffff) ? (__uint32_t)(
((__uint32_t)(0x0000ffff) & 0xff) << 24 | ((__uint32_t
)(0x0000ffff) & 0xff00) << 8 | ((__uint32_t)(0x0000ffff
) & 0xff0000) >> 8 | ((__uint32_t)(0x0000ffff) &
0xff000000) >> 24) : __swap32md(0x0000ffff))
;
2647 hic.ampdu_subframes = 20;
2648 hic.txchainmask = sc->txchainmask;
2649 DPRINTF(("updating target configuration\n"));
2650 error = athn_usb_wmi_xcmd(usc, AR_WMI_CMD_TARGET_IC_UPDATE0x018,
2651 &hic, sizeof(hic), NULL((void *)0));
2652 if (error != 0)
2653 goto fail;
2654
2655 /* Queue Rx xfers. */
2656 for (i = 0; i < ATHN_USB_RX_LIST_COUNT1; i++) {
2657 data = &usc->rx_data[i];
2658
2659 usbd_setup_xfer(data->xfer, usc->rx_data_pipe, data, data->buf,
2660 ATHN_USB_RXBUFSZ(8 * 1024), USBD_SHORT_XFER_OK0x04 | USBD_NO_COPY0x01,
2661 USBD_NO_TIMEOUT0, athn_usb_rxeof);
2662 error = usbd_transfer(data->xfer);
2663 if (error != 0 && error != USBD_IN_PROGRESS)
2664 goto fail;
2665 }
2666 /* We're ready to go. */
2667 ifp->if_flags |= IFF_RUNNING0x40;
2668 ifq_clr_oactive(&ifp->if_snd);
2669
2670#ifdef notyet
2671 if (ic->ic_flags & IEEE80211_F_WEPON0x00000100) {
2672 /* Install WEP keys. */
2673 for (i = 0; i < IEEE80211_WEP_NKID4; i++)
2674 athn_usb_set_key(ic, NULL((void *)0), &ic->ic_nw_keys[i]);
2675 }
2676#endif
2677 if (ic->ic_opmode == IEEE80211_M_MONITOR)
2678 ieee80211_new_state(ic, IEEE80211_S_RUN, -1)(((ic)->ic_newstate)((ic), (IEEE80211_S_RUN), (-1)));
2679 else
2680 ieee80211_new_state(ic, IEEE80211_S_SCAN, -1)(((ic)->ic_newstate)((ic), (IEEE80211_S_SCAN), (-1)));
2681 athn_usb_wait_async(usc);
2682 return (0);
2683 fail:
2684 athn_usb_stop(ifp);
2685 return (error);
2686}
2687
2688void
2689athn_usb_stop(struct ifnet *ifp)
2690{
2691 struct athn_softc *sc = ifp->if_softc;
2692 struct athn_usb_softc *usc = (struct athn_usb_softc *)sc;
2693 struct ieee80211com *ic = &sc->sc_ic;
2694 struct ar_htc_target_vif hvif;
2695 uint8_t sta_index;
2696 int s;
2697
2698 sc->sc_tx_timer = 0;
2699 ifp->if_timer = 0;
2700 ifp->if_flags &= ~IFF_RUNNING0x40;
2701 ifq_clr_oactive(&ifp->if_snd);
2702
2703 s = splusb()splraise(0x5);
2704 ieee80211_new_state(ic, IEEE80211_S_INIT, -1)(((ic)->ic_newstate)((ic), (IEEE80211_S_INIT), (-1)));
2705
2706 /* Wait for all async commands to complete. */
2707 athn_usb_wait_async(usc);
2708
2709 timeout_del(&sc->scan_to);
2710 timeout_del(&sc->calib_to);
2711
2712 /* Remove all non-default nodes. */
2713 for (sta_index = 1; sta_index < AR_USB_MAX_STA8; sta_index++) {
2714 if (usc->free_node_slots & (1 << sta_index))
2715 continue;
2716 (void)athn_usb_wmi_xcmd(usc, AR_WMI_CMD_NODE_REMOVE0x011,
2717 &sta_index, sizeof(sta_index), NULL((void *)0));
2718 }
2719
2720 /* Remove main interface. This also invalidates our default node. */
2721 memset(&hvif, 0, sizeof(hvif))__builtin_memset((&hvif), (0), (sizeof(hvif)));
2722 hvif.index = 0;
2723 IEEE80211_ADDR_COPY(hvif.myaddr, ic->ic_myaddr)__builtin_memcpy((hvif.myaddr), (ic->ic_myaddr), (6));
2724 (void)athn_usb_wmi_xcmd(usc, AR_WMI_CMD_VAP_REMOVE0x012,
2725 &hvif, sizeof(hvif), NULL((void *)0));
2726
2727 usc->free_node_slots = 0xff;
2728
2729 (void)athn_usb_wmi_cmd(usc, AR_WMI_CMD_DISABLE_INTR)athn_usb_wmi_xcmd(usc, 0x004, ((void *)0), 0, ((void *)0));
2730 (void)athn_usb_wmi_cmd(usc, AR_WMI_CMD_DRAIN_TXQ_ALL)athn_usb_wmi_xcmd(usc, 0x00b, ((void *)0), 0, ((void *)0));
2731 (void)athn_usb_wmi_cmd(usc, AR_WMI_CMD_STOP_RECV)athn_usb_wmi_xcmd(usc, 0x00d, ((void *)0), 0, ((void *)0));
2732
2733 athn_reset(sc, 0);
2734 athn_init_pll(sc, NULL((void *)0));
2735 athn_set_power_awake(sc);
2736 athn_reset(sc, 1);
2737 athn_init_pll(sc, NULL((void *)0));
2738 athn_set_power_sleep(sc);
2739
2740 /* Abort Tx/Rx. */
2741 usbd_abort_pipe(usc->tx_data_pipe);
2742 usbd_abort_pipe(usc->rx_data_pipe);
2743
2744 /* Free Tx/Rx buffers. */
2745 athn_usb_free_tx_list(usc);
2746 athn_usb_free_rx_list(usc);
2747 splx(s)spllower(s);
2748
2749 /* Flush Rx stream. */
2750 m_freem(usc->rx_stream.m);
2751 usc->rx_stream.m = NULL((void *)0);
2752 usc->rx_stream.left = 0;
2753}