Bug Summary

File:dev/usb/if_otus.c
Warning:line 1937, column 2
Value stored to 'chan' 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_otus.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_otus.c
1/* $OpenBSD: if_otus.c,v 1.70 2021/11/22 10:17:14 mglocker Exp $ */
2
3/*-
4 * Copyright (c) 2009 Damien Bergamini <damien.bergamini@free.fr>
5 *
6 * Permission to use, copy, modify, and distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
9 *
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 */
18
19/*
20 * Driver for Atheros AR9001U chipset.
21 */
22
23#include "bpfilter.h"
24
25#include <sys/param.h>
26#include <sys/sockio.h>
27#include <sys/mbuf.h>
28#include <sys/kernel.h>
29#include <sys/socket.h>
30#include <sys/systm.h>
31#include <sys/timeout.h>
32#include <sys/conf.h>
33#include <sys/device.h>
34#include <sys/endian.h>
35
36#include <machine/intr.h>
37
38#if NBPFILTER1 > 0
39#include <net/bpf.h>
40#endif
41#include <net/if.h>
42#include <net/if_dl.h>
43#include <net/if_media.h>
44
45#include <netinet/in.h>
46#include <netinet/if_ether.h>
47
48#include <net80211/ieee80211_var.h>
49#include <net80211/ieee80211_amrr.h>
50#include <net80211/ieee80211_radiotap.h>
51
52#include <dev/usb/usb.h>
53#include <dev/usb/usbdi.h>
54#include <dev/usb/usbdi_util.h>
55#include <dev/usb/usbdevs.h>
56
57#include <dev/usb/if_otusreg.h>
58
59#ifdef OTUS_DEBUG
60#define DPRINTF(x) do { if (otus_debug) printf x; } while (0)
61#define DPRINTFN(n, x) do { if (otus_debug >= (n)) printf x; } while (0)
62int otus_debug = 1;
63#else
64#define DPRINTF(x)
65#define DPRINTFN(n, x)
66#endif
67
68static const struct usb_devno otus_devs[] = {
69 { USB_VENDOR_ACCTON0x083a, USB_PRODUCT_ACCTON_WN75120xf522 },
70 { USB_VENDOR_ATHEROS20x0cf3, USB_PRODUCT_ATHEROS2_3CRUSBN2750x1010 },
71 { USB_VENDOR_ATHEROS20x0cf3, USB_PRODUCT_ATHEROS2_TG121N0x1001 },
72 { USB_VENDOR_ATHEROS20x0cf3, USB_PRODUCT_ATHEROS2_AR91700x9170 },
73 { USB_VENDOR_ATHEROS20x0cf3, USB_PRODUCT_ATHEROS2_WN6120x1011 },
74 { USB_VENDOR_ATHEROS20x0cf3, USB_PRODUCT_ATHEROS2_WN821NV20x1002 },
75 { USB_VENDOR_AVM0x057c, USB_PRODUCT_AVM_FRITZWLAN0x8401 },
76 { USB_VENDOR_CACE0xcace, USB_PRODUCT_CACE_AIRPCAPNX0x0300 },
77 { USB_VENDOR_DLINK20x07d1, USB_PRODUCT_DLINK2_DWA130D10x3a0f },
78 { USB_VENDOR_DLINK20x07d1, USB_PRODUCT_DLINK2_DWA160A10x3c10 },
79 { USB_VENDOR_DLINK20x07d1, USB_PRODUCT_DLINK2_DWA160A20x3a09 },
80 { USB_VENDOR_IODATA0x04bb, USB_PRODUCT_IODATA_WNGDNUS20x093f },
81 { USB_VENDOR_NEC0x0409, USB_PRODUCT_NEC_WL300NUG0x0249 },
82 { USB_VENDOR_NETGEAR0x0846, USB_PRODUCT_NETGEAR_WN111V20x9001 },
83 { USB_VENDOR_NETGEAR0x0846, USB_PRODUCT_NETGEAR_WNA10000x9040 },
84 { USB_VENDOR_NETGEAR0x0846, USB_PRODUCT_NETGEAR_WNDA31000x9010 },
85 { USB_VENDOR_PLANEX20x2019, USB_PRODUCT_PLANEX2_GW_US3000x5304 },
86 { USB_VENDOR_WISTRONNEWEB0x1435, USB_PRODUCT_WISTRONNEWEB_O84940x0804 },
87 { USB_VENDOR_WISTRONNEWEB0x1435, USB_PRODUCT_WISTRONNEWEB_WNC06000x0326 },
88 { USB_VENDOR_ZCOM0x0cde, USB_PRODUCT_ZCOM_UB810x0023 },
89 { USB_VENDOR_ZCOM0x0cde, USB_PRODUCT_ZCOM_UB820x0026 },
90 { USB_VENDOR_ZYDAS0x0ace, USB_PRODUCT_ZYDAS_ZD12210x1221 },
91 { USB_VENDOR_ZYXEL0x0586, USB_PRODUCT_ZYXEL_NWD271N0x3417 }
92};
93
94int otus_match(struct device *, void *, void *);
95void otus_attach(struct device *, struct device *, void *);
96int otus_detach(struct device *, int);
97void otus_attachhook(struct device *);
98void otus_get_chanlist(struct otus_softc *);
99int otus_load_firmware(struct otus_softc *, const char *,
100 uint32_t);
101int otus_open_pipes(struct otus_softc *);
102void otus_close_pipes(struct otus_softc *);
103int otus_alloc_tx_cmd(struct otus_softc *);
104void otus_free_tx_cmd(struct otus_softc *);
105int otus_alloc_tx_data_list(struct otus_softc *);
106void otus_free_tx_data_list(struct otus_softc *);
107int otus_alloc_rx_data_list(struct otus_softc *);
108void otus_free_rx_data_list(struct otus_softc *);
109void otus_next_scan(void *);
110void otus_task(void *);
111void otus_do_async(struct otus_softc *,
112 void (*)(struct otus_softc *, void *), void *, int);
113int otus_newstate(struct ieee80211com *, enum ieee80211_state,
114 int);
115void otus_newstate_cb(struct otus_softc *, void *);
116int otus_cmd(struct otus_softc *, uint8_t, const void *, int,
117 void *);
118void otus_write(struct otus_softc *, uint32_t, uint32_t);
119int otus_write_barrier(struct otus_softc *);
120struct ieee80211_node *otus_node_alloc(struct ieee80211com *);
121int otus_media_change(struct ifnet *);
122int otus_read_eeprom(struct otus_softc *);
123void otus_newassoc(struct ieee80211com *, struct ieee80211_node *,
124 int);
125void otus_intr(struct usbd_xfer *, void *, usbd_status);
126void otus_cmd_rxeof(struct otus_softc *, uint8_t *, int);
127void otus_sub_rxeof(struct otus_softc *, uint8_t *, int,
128 struct mbuf_list *);
129void otus_rxeof(struct usbd_xfer *, void *, usbd_status);
130void otus_txeof(struct usbd_xfer *, void *, usbd_status);
131int otus_tx(struct otus_softc *, struct mbuf *,
132 struct ieee80211_node *);
133void otus_start(struct ifnet *);
134void otus_watchdog(struct ifnet *);
135int otus_ioctl(struct ifnet *, u_long, caddr_t);
136int otus_set_multi(struct otus_softc *);
137void otus_updateedca(struct ieee80211com *);
138void otus_updateedca_cb(struct otus_softc *, void *);
139void otus_updateslot(struct ieee80211com *);
140void otus_updateslot_cb(struct otus_softc *, void *);
141int otus_init_mac(struct otus_softc *);
142uint32_t otus_phy_get_def(struct otus_softc *, uint32_t);
143int otus_set_board_values(struct otus_softc *,
144 struct ieee80211_channel *);
145int otus_program_phy(struct otus_softc *,
146 struct ieee80211_channel *);
147int otus_set_rf_bank4(struct otus_softc *,
148 struct ieee80211_channel *);
149void otus_get_delta_slope(uint32_t, uint32_t *, uint32_t *);
150int otus_set_chan(struct otus_softc *, struct ieee80211_channel *,
151 int);
152int otus_set_key(struct ieee80211com *, struct ieee80211_node *,
153 struct ieee80211_key *);
154void otus_set_key_cb(struct otus_softc *, void *);
155void otus_delete_key(struct ieee80211com *, struct ieee80211_node *,
156 struct ieee80211_key *);
157void otus_delete_key_cb(struct otus_softc *, void *);
158void otus_calibrate_to(void *);
159int otus_set_bssid(struct otus_softc *, const uint8_t *);
160int otus_set_macaddr(struct otus_softc *, const uint8_t *);
161void otus_led_newstate_type1(struct otus_softc *);
162void otus_led_newstate_type2(struct otus_softc *);
163void otus_led_newstate_type3(struct otus_softc *);
164int otus_init(struct ifnet *);
165void otus_stop(struct ifnet *);
166
167struct cfdriver otus_cd = {
168 NULL((void *)0), "otus", DV_IFNET
169};
170
171const struct cfattach otus_ca = {
172 sizeof (struct otus_softc), otus_match, otus_attach, otus_detach
173};
174
175int
176otus_match(struct device *parent, void *match, void *aux)
177{
178 struct usb_attach_arg *uaa = aux;
179
180 if (uaa->iface == NULL((void *)0) || uaa->configno != 1)
181 return UMATCH_NONE0;
182
183 return (usb_lookup(otus_devs, uaa->vendor, uaa->product)usbd_match_device((const struct usb_devno *)(otus_devs), sizeof
(otus_devs) / sizeof ((otus_devs)[0]), sizeof ((otus_devs)[0
]), (uaa->vendor), (uaa->product))
!= NULL((void *)0)) ?
184 UMATCH_VENDOR_PRODUCT13 : UMATCH_NONE0;
185}
186
187void
188otus_attach(struct device *parent, struct device *self, void *aux)
189{
190 struct otus_softc *sc = (struct otus_softc *)self;
191 struct usb_attach_arg *uaa = aux;
192 int error;
193
194 sc->sc_udev = uaa->device;
195
196 usb_init_task(&sc->sc_task, otus_task, sc, USB_TASK_TYPE_GENERIC)((&sc->sc_task)->fun = (otus_task), (&sc->sc_task
)->arg = (sc), (&sc->sc_task)->type = (0), (&
sc->sc_task)->state = 0x0)
;
197 timeout_set(&sc->scan_to, otus_next_scan, sc);
198 timeout_set(&sc->calib_to, otus_calibrate_to, sc);
199
200 sc->amrr.amrr_min_success_threshold = 1;
201 sc->amrr.amrr_max_success_threshold = 10;
202
203 /* Get the first interface handle. */
204 error = usbd_device2interface_handle(sc->sc_udev, 0, &sc->sc_iface);
205 if (error != 0) {
206 printf("%s: could not get interface handle\n",
207 sc->sc_dev.dv_xname);
208 return;
209 }
210
211 if ((error = otus_open_pipes(sc)) != 0) {
212 printf("%s: could not open pipes\n", sc->sc_dev.dv_xname);
213 return;
214 }
215
216 config_mountroot(self, otus_attachhook);
217}
218
219int
220otus_detach(struct device *self, int flags)
221{
222 struct otus_softc *sc = (struct otus_softc *)self;
223 struct ifnet *ifp = &sc->sc_ic.ic_ific_ac.ac_if;
224 int s;
225
226 s = splusb()splraise(0x5);
227
228 if (timeout_initialized(&sc->scan_to)((&sc->scan_to)->to_flags & 0x04))
229 timeout_del(&sc->scan_to);
230 if (timeout_initialized(&sc->calib_to)((&sc->calib_to)->to_flags & 0x04))
231 timeout_del(&sc->calib_to);
232
233 /* Wait for all queued asynchronous commands to complete. */
234 usb_rem_wait_task(sc->sc_udev, &sc->sc_task);
235
236 usbd_ref_wait(sc->sc_udev);
237
238 if (ifp->if_softc != NULL((void *)0)) {
239 ifp->if_flags &= ~IFF_RUNNING0x40;
240 ifq_clr_oactive(&ifp->if_snd);
241 ieee80211_ifdetach(ifp);
242 if_detach(ifp);
243 }
244
245 otus_close_pipes(sc);
246
247 splx(s)spllower(s);
248
249 return 0;
250}
251
252void
253otus_attachhook(struct device *self)
254{
255 struct otus_softc *sc = (struct otus_softc *)self;
256 struct ieee80211com *ic = &sc->sc_ic;
257 struct ifnet *ifp = &ic->ic_ific_ac.ac_if;
258 usb_device_request_t req;
259 uint32_t in, out;
260 int error;
261
262 error = otus_load_firmware(sc, "otus-init", AR_FW_INIT_ADDR0x102800);
263 if (error != 0) {
264 printf("%s: could not load %s firmware\n",
265 sc->sc_dev.dv_xname, "init");
266 return;
267 }
268
269 usbd_delay_ms(sc->sc_udev, 1000);
270
271 error = otus_load_firmware(sc, "otus-main", AR_FW_MAIN_ADDR0x200000);
272 if (error != 0) {
273 printf("%s: could not load %s firmware\n",
274 sc->sc_dev.dv_xname, "main");
275 return;
276 }
277
278 /* Tell device that firmware transfer is complete. */
279 req.bmRequestType = UT_WRITE_VENDOR_DEVICE(0x00 | 0x40 | 0x00);
280 req.bRequest = AR_FW_DOWNLOAD_COMPLETE0x31;
281 USETW(req.wValue, 0)(*(u_int16_t *)(req.wValue) = (0));
282 USETW(req.wIndex, 0)(*(u_int16_t *)(req.wIndex) = (0));
283 USETW(req.wLength, 0)(*(u_int16_t *)(req.wLength) = (0));
284 if (usbd_do_request(sc->sc_udev, &req, NULL((void *)0)) != 0) {
285 printf("%s: firmware initialization failed\n",
286 sc->sc_dev.dv_xname);
287 return;
288 }
289
290 /* Send an ECHO command to check that everything is settled. */
291 in = 0xbadc0ffe;
292 if (otus_cmd(sc, AR_CMD_ECHO0x80, &in, sizeof in, &out) != 0) {
293 printf("%s: echo command failed\n", sc->sc_dev.dv_xname);
294 return;
295 }
296 if (in != out) {
297 printf("%s: echo reply mismatch: 0x%08x!=0x%08x\n",
298 sc->sc_dev.dv_xname, in, out);
299 return;
300 }
301
302 /* Read entire EEPROM. */
303 if (otus_read_eeprom(sc) != 0) {
304 printf("%s: could not read EEPROM\n", sc->sc_dev.dv_xname);
305 return;
306 }
307
308 sc->txmask = sc->eeprom.baseEepHeader.txMask;
309 sc->rxmask = sc->eeprom.baseEepHeader.rxMask;
310 sc->capflags = sc->eeprom.baseEepHeader.opCapFlags;
311 IEEE80211_ADDR_COPY(ic->ic_myaddr, sc->eeprom.baseEepHeader.macAddr)__builtin_memcpy((ic->ic_myaddr), (sc->eeprom.baseEepHeader
.macAddr), (6))
;
312 sc->sc_led_newstate = otus_led_newstate_type3; /* XXX */
313
314 printf("%s: MAC/BBP AR9170, RF AR%X, MIMO %dT%dR, address %s\n",
315 sc->sc_dev.dv_xname, (sc->capflags & AR5416_OPFLAGS_11A0x01) ?
316 0x9104 : ((sc->txmask == 0x5) ? 0x9102 : 0x9101),
317 (sc->txmask == 0x5) ? 2 : 1, (sc->rxmask == 0x5) ? 2 : 1,
318 ether_sprintf(ic->ic_myaddr));
319
320 ic->ic_phytype = IEEE80211_T_OFDM; /* not only, but not used */
321 ic->ic_opmode = IEEE80211_M_STA; /* default to BSS mode */
322 ic->ic_state = IEEE80211_S_INIT;
323
324 /* Set device capabilities. */
325 ic->ic_caps =
326 IEEE80211_C_MONITOR0x00000200 | /* monitor mode supported */
327 IEEE80211_C_SHPREAMBLE0x00000100 | /* short preamble supported */
328 IEEE80211_C_SHSLOT0x00000080 | /* short slot time supported */
329 IEEE80211_C_WEP0x00000001 | /* WEP */
330 IEEE80211_C_RSN0x00001000; /* WPA/RSN */
331
332 if (sc->eeprom.baseEepHeader.opCapFlags & AR5416_OPFLAGS_11G0x02) {
333 /* Set supported .11b and .11g rates. */
334 ic->ic_sup_rates[IEEE80211_MODE_11B] =
335 ieee80211_std_rateset_11b;
336 ic->ic_sup_rates[IEEE80211_MODE_11G] =
337 ieee80211_std_rateset_11g;
338 }
339 if (sc->eeprom.baseEepHeader.opCapFlags & AR5416_OPFLAGS_11A0x01) {
340 /* Set supported .11a rates. */
341 ic->ic_sup_rates[IEEE80211_MODE_11A] =
342 ieee80211_std_rateset_11a;
343 }
344
345 /* Build the list of supported channels. */
346 otus_get_chanlist(sc);
347
348 ifp->if_softc = sc;
349 ifp->if_flags = IFF_BROADCAST0x2 | IFF_SIMPLEX0x800 | IFF_MULTICAST0x8000;
350 ifp->if_ioctl = otus_ioctl;
351 ifp->if_start = otus_start;
352 ifp->if_watchdog = otus_watchdog;
353 memcpy(ifp->if_xname, sc->sc_dev.dv_xname, IFNAMSIZ)__builtin_memcpy((ifp->if_xname), (sc->sc_dev.dv_xname)
, (16))
;
354
355 if_attach(ifp);
356 ieee80211_ifattach(ifp);
357 ic->ic_node_alloc = otus_node_alloc;
358 ic->ic_newassoc = otus_newassoc;
359 ic->ic_updateslot = otus_updateslot;
360 ic->ic_updateedca = otus_updateedca;
361#ifdef notyet
362 ic->ic_set_key = otus_set_key;
363 ic->ic_delete_key = otus_delete_key;
364#endif
365 /* Override state transition machine. */
366 sc->sc_newstate = ic->ic_newstate;
367 ic->ic_newstate = otus_newstate;
368 ieee80211_media_init(ifp, otus_media_change, ieee80211_media_status);
369
370#if NBPFILTER1 > 0
371 bpfattach(&sc->sc_drvbpf, ifp, DLT_IEEE802_11_RADIO127,
372 sizeof (struct ieee80211_frame) + IEEE80211_RADIOTAP_HDRLEN64);
373
374 sc->sc_rxtap_len = sizeof sc->sc_rxtapu;
375 sc->sc_rxtapsc_rxtapu.th.wr_ihdr.it_len = htole16(sc->sc_rxtap_len)((__uint16_t)(sc->sc_rxtap_len));
376 sc->sc_rxtapsc_rxtapu.th.wr_ihdr.it_present = htole32(OTUS_RX_RADIOTAP_PRESENT)((__uint32_t)((1 << IEEE80211_RADIOTAP_FLAGS | 1 <<
IEEE80211_RADIOTAP_RATE | 1 << IEEE80211_RADIOTAP_CHANNEL
| 1 << IEEE80211_RADIOTAP_DB_ANTSIGNAL)))
;
377
378 sc->sc_txtap_len = sizeof sc->sc_txtapu;
379 sc->sc_txtapsc_txtapu.th.wt_ihdr.it_len = htole16(sc->sc_txtap_len)((__uint16_t)(sc->sc_txtap_len));
380 sc->sc_txtapsc_txtapu.th.wt_ihdr.it_present = htole32(OTUS_TX_RADIOTAP_PRESENT)((__uint32_t)((1 << IEEE80211_RADIOTAP_FLAGS | 1 <<
IEEE80211_RADIOTAP_RATE | 1 << IEEE80211_RADIOTAP_CHANNEL
)))
;
381#endif
382}
383
384void
385otus_get_chanlist(struct otus_softc *sc)
386{
387 struct ieee80211com *ic = &sc->sc_ic;
388 uint16_t domain;
389 uint8_t chan;
390 int i;
391
392 /* XXX regulatory domain. */
393 domain = letoh16(sc->eeprom.baseEepHeader.regDmn[0])((__uint16_t)(sc->eeprom.baseEepHeader.regDmn[0]));
394 DPRINTF(("regdomain=0x%04x\n", domain));
395
396 if (sc->eeprom.baseEepHeader.opCapFlags & AR5416_OPFLAGS_11G0x02) {
397 for (i = 0; i < 14; i++) {
398 chan = ar_chans[i];
399 ic->ic_channels[chan].ic_freq =
400 ieee80211_ieee2mhz(chan, IEEE80211_CHAN_2GHZ0x0080);
401 ic->ic_channels[chan].ic_flags =
402 IEEE80211_CHAN_CCK0x0020 | IEEE80211_CHAN_OFDM0x0040 |
403 IEEE80211_CHAN_DYN0x0400 | IEEE80211_CHAN_2GHZ0x0080;
404 }
405 }
406 if (sc->eeprom.baseEepHeader.opCapFlags & AR5416_OPFLAGS_11A0x01) {
407 for (i = 14; i < nitems(ar_chans)(sizeof((ar_chans)) / sizeof((ar_chans)[0])); i++) {
408 chan = ar_chans[i];
409 ic->ic_channels[chan].ic_freq =
410 ieee80211_ieee2mhz(chan, IEEE80211_CHAN_5GHZ0x0100);
411 ic->ic_channels[chan].ic_flags = IEEE80211_CHAN_A(0x0100 | 0x0040);
412 }
413 }
414}
415
416int
417otus_load_firmware(struct otus_softc *sc, const char *name, uint32_t addr)
418{
419 usb_device_request_t req;
420 size_t fwsize, size;
421 u_char *fw, *ptr;
422 int mlen, error;
423
424 /* Read firmware image from the filesystem. */
425 if ((error = loadfirmware(name, &fw, &fwsize)) != 0) {
426 printf("%s: failed loadfirmware of file %s (error %d)\n",
427 sc->sc_dev.dv_xname, name, error);
428 return error;
429 }
430 req.bmRequestType = UT_WRITE_VENDOR_DEVICE(0x00 | 0x40 | 0x00);
431 req.bRequest = AR_FW_DOWNLOAD0x30;
432 USETW(req.wIndex, 0)(*(u_int16_t *)(req.wIndex) = (0));
433
434 ptr = fw;
435 size = fwsize;
436 addr >>= 8;
437 while (size > 0) {
438 mlen = MIN(size, 4096)(((size)<(4096))?(size):(4096));
439
440 USETW(req.wValue, addr)(*(u_int16_t *)(req.wValue) = (addr));
441 USETW(req.wLength, mlen)(*(u_int16_t *)(req.wLength) = (mlen));
442 if (usbd_do_request(sc->sc_udev, &req, ptr) != 0) {
443 error = EIO5;
444 break;
445 }
446 addr += mlen >> 8;
447 ptr += mlen;
448 size -= mlen;
449 }
450 free(fw, M_DEVBUF2, fwsize);
451 return error;
452}
453
454int
455otus_open_pipes(struct otus_softc *sc)
456{
457 usb_endpoint_descriptor_t *ed;
458 int i, isize, error;
459
460 error = usbd_open_pipe(sc->sc_iface, AR_EPT_BULK_RX_NO(0x80 | 2), 0,
461 &sc->data_rx_pipe);
462 if (error != 0) {
463 printf("%s: could not open Rx bulk pipe\n",
464 sc->sc_dev.dv_xname);
465 goto fail;
466 }
467
468 ed = usbd_get_endpoint_descriptor(sc->sc_iface, AR_EPT_INTR_RX_NO(0x80 | 3));
469 if (ed == NULL((void *)0)) {
470 printf("%s: could not retrieve Rx intr pipe descriptor\n",
471 sc->sc_dev.dv_xname);
472 goto fail;
473 }
474 isize = UGETW(ed->wMaxPacketSize)(*(u_int16_t *)(ed->wMaxPacketSize));
475 if (isize == 0) {
476 printf("%s: invalid Rx intr pipe descriptor\n",
477 sc->sc_dev.dv_xname);
478 goto fail;
479 }
480 sc->ibuf = malloc(isize, M_USBDEV102, M_NOWAIT0x0002);
481 if (sc->ibuf == NULL((void *)0)) {
482 printf("%s: could not allocate Rx intr buffer\n",
483 sc->sc_dev.dv_xname);
484 goto fail;
485 }
486 sc->ibuflen = isize;
487 error = usbd_open_pipe_intr(sc->sc_iface, AR_EPT_INTR_RX_NO(0x80 | 3),
488 USBD_SHORT_XFER_OK0x04, &sc->cmd_rx_pipe, sc, sc->ibuf, isize,
489 otus_intr, USBD_DEFAULT_INTERVAL(-1));
490 if (error != 0) {
491 printf("%s: could not open Rx intr pipe\n",
492 sc->sc_dev.dv_xname);
493 goto fail;
494 }
495
496 error = usbd_open_pipe(sc->sc_iface, AR_EPT_BULK_TX_NO(0x00 | 1), 0,
497 &sc->data_tx_pipe);
498 if (error != 0) {
499 printf("%s: could not open Tx bulk pipe\n",
500 sc->sc_dev.dv_xname);
501 goto fail;
502 }
503
504 error = usbd_open_pipe(sc->sc_iface, AR_EPT_INTR_TX_NO(0x00 | 4), 0,
505 &sc->cmd_tx_pipe);
506 if (error != 0) {
507 printf("%s: could not open Tx intr pipe\n",
508 sc->sc_dev.dv_xname);
509 goto fail;
510 }
511
512 if (otus_alloc_tx_cmd(sc) != 0) {
513 printf("%s: could not allocate command xfer\n",
514 sc->sc_dev.dv_xname);
515 goto fail;
516 }
517
518 if (otus_alloc_tx_data_list(sc) != 0) {
519 printf("%s: could not allocate Tx xfers\n",
520 sc->sc_dev.dv_xname);
521 goto fail;
522 }
523
524 if (otus_alloc_rx_data_list(sc) != 0) {
525 printf("%s: could not allocate Rx xfers\n",
526 sc->sc_dev.dv_xname);
527 goto fail;
528 }
529
530 for (i = 0; i < OTUS_RX_DATA_LIST_COUNT1; i++) {
531 struct otus_rx_data *data = &sc->rx_data[i];
532
533 usbd_setup_xfer(data->xfer, sc->data_rx_pipe, data, data->buf,
534 OTUS_RXBUFSZ(8 * 1024), USBD_SHORT_XFER_OK0x04 | USBD_NO_COPY0x01,
535 USBD_NO_TIMEOUT0, otus_rxeof);
536 error = usbd_transfer(data->xfer);
537 if (error != USBD_IN_PROGRESS && error != 0) {
538 printf("%s: could not queue Rx xfer\n",
539 sc->sc_dev.dv_xname);
540 goto fail;
541 }
542 }
543 return 0;
544
545 fail: otus_close_pipes(sc);
546 return error;
547}
548
549void
550otus_close_pipes(struct otus_softc *sc)
551{
552 otus_free_tx_cmd(sc);
553 otus_free_tx_data_list(sc);
554 otus_free_rx_data_list(sc);
555
556 if (sc->data_rx_pipe != NULL((void *)0))
557 usbd_close_pipe(sc->data_rx_pipe);
558 if (sc->cmd_rx_pipe != NULL((void *)0))
559 usbd_close_pipe(sc->cmd_rx_pipe);
560 if (sc->ibuf != NULL((void *)0))
561 free(sc->ibuf, M_USBDEV102, sc->ibuflen);
562 if (sc->data_tx_pipe != NULL((void *)0))
563 usbd_close_pipe(sc->data_tx_pipe);
564 if (sc->cmd_tx_pipe != NULL((void *)0))
565 usbd_close_pipe(sc->cmd_tx_pipe);
566}
567
568int
569otus_alloc_tx_cmd(struct otus_softc *sc)
570{
571 struct otus_tx_cmd *cmd = &sc->tx_cmd;
572
573 cmd->xfer = usbd_alloc_xfer(sc->sc_udev);
574 if (cmd->xfer == NULL((void *)0)) {
575 printf("%s: could not allocate xfer\n",
576 sc->sc_dev.dv_xname);
577 return ENOMEM12;
578 }
579 cmd->buf = usbd_alloc_buffer(cmd->xfer, OTUS_MAX_TXCMDSZ64);
580 if (cmd->buf == NULL((void *)0)) {
581 printf("%s: could not allocate xfer buffer\n",
582 sc->sc_dev.dv_xname);
583 usbd_free_xfer(cmd->xfer);
584 cmd->xfer = NULL((void *)0);
585 return ENOMEM12;
586 }
587 return 0;
588}
589
590void
591otus_free_tx_cmd(struct otus_softc *sc)
592{
593 /* Make sure no transfers are pending. */
594 usbd_abort_pipe(sc->cmd_tx_pipe);
595
596 if (sc->tx_cmd.xfer != NULL((void *)0))
597 usbd_free_xfer(sc->tx_cmd.xfer);
598}
599
600int
601otus_alloc_tx_data_list(struct otus_softc *sc)
602{
603 struct otus_tx_data *data;
604 int i, error;
605
606 for (i = 0; i < OTUS_TX_DATA_LIST_COUNT8; i++) {
607 data = &sc->tx_data[i];
608
609 data->sc = sc; /* Backpointer for callbacks. */
610
611 data->xfer = usbd_alloc_xfer(sc->sc_udev);
612 if (data->xfer == NULL((void *)0)) {
613 printf("%s: could not allocate xfer\n",
614 sc->sc_dev.dv_xname);
615 error = ENOMEM12;
616 goto fail;
617 }
618 data->buf = usbd_alloc_buffer(data->xfer, OTUS_TXBUFSZ(4 * 1024));
619 if (data->buf == NULL((void *)0)) {
620 printf("%s: could not allocate xfer buffer\n",
621 sc->sc_dev.dv_xname);
622 error = ENOMEM12;
623 goto fail;
624 }
625 }
626 return 0;
627
628fail: otus_free_tx_data_list(sc);
629 return error;
630}
631
632void
633otus_free_tx_data_list(struct otus_softc *sc)
634{
635 int i;
636
637 /* Make sure no transfers are pending. */
638 usbd_abort_pipe(sc->data_tx_pipe);
639
640 for (i = 0; i < OTUS_TX_DATA_LIST_COUNT8; i++)
641 if (sc->tx_data[i].xfer != NULL((void *)0))
642 usbd_free_xfer(sc->tx_data[i].xfer);
643}
644
645int
646otus_alloc_rx_data_list(struct otus_softc *sc)
647{
648 struct otus_rx_data *data;
649 int i, error;
650
651 for (i = 0; i < OTUS_RX_DATA_LIST_COUNT1; i++) {
652 data = &sc->rx_data[i];
653
654 data->sc = sc; /* Backpointer for callbacks. */
655
656 data->xfer = usbd_alloc_xfer(sc->sc_udev);
657 if (data->xfer == NULL((void *)0)) {
658 printf("%s: could not allocate xfer\n",
659 sc->sc_dev.dv_xname);
660 error = ENOMEM12;
661 goto fail;
662 }
663 data->buf = usbd_alloc_buffer(data->xfer, OTUS_RXBUFSZ(8 * 1024));
664 if (data->buf == NULL((void *)0)) {
665 printf("%s: could not allocate xfer buffer\n",
666 sc->sc_dev.dv_xname);
667 error = ENOMEM12;
668 goto fail;
669 }
670 }
671 return 0;
672
673fail: otus_free_rx_data_list(sc);
674 return error;
675}
676
677void
678otus_free_rx_data_list(struct otus_softc *sc)
679{
680 int i;
681
682 /* Make sure no transfers are pending. */
683 usbd_abort_pipe(sc->data_rx_pipe);
684
685 for (i = 0; i < OTUS_RX_DATA_LIST_COUNT1; i++)
686 if (sc->rx_data[i].xfer != NULL((void *)0))
687 usbd_free_xfer(sc->rx_data[i].xfer);
688}
689
690void
691otus_next_scan(void *arg)
692{
693 struct otus_softc *sc = arg;
694 struct ieee80211com *ic = &sc->sc_ic;
695 struct ifnet *ifp = &ic->ic_ific_ac.ac_if;
696
697 if (usbd_is_dying(sc->sc_udev))
698 return;
699
700 usbd_ref_incr(sc->sc_udev);
701
702 if (sc->sc_ic.ic_state == IEEE80211_S_SCAN &&
703 (ifp->if_flags & IFF_RUNNING0x40))
704 ieee80211_next_scan(&sc->sc_ic.ic_ific_ac.ac_if);
705
706 usbd_ref_decr(sc->sc_udev);
707}
708
709void
710otus_task(void *arg)
711{
712 struct otus_softc *sc = arg;
713 struct otus_host_cmd_ring *ring = &sc->cmdq;
714 struct otus_host_cmd *cmd;
715 int s;
716
717 /* Process host commands. */
718 s = splusb()splraise(0x5);
719 while (ring->next != ring->cur) {
720 cmd = &ring->cmd[ring->next];
721 splx(s)spllower(s);
722 /* Callback. */
723 cmd->cb(sc, cmd->data);
724 s = splusb()splraise(0x5);
725 ring->queued--;
726 ring->next = (ring->next + 1) % OTUS_HOST_CMD_RING_COUNT32;
727 }
728 splx(s)spllower(s);
729}
730
731void
732otus_do_async(struct otus_softc *sc, void (*cb)(struct otus_softc *, void *),
733 void *arg, int len)
734{
735 struct otus_host_cmd_ring *ring = &sc->cmdq;
736 struct otus_host_cmd *cmd;
737 int s;
738
739 s = splusb()splraise(0x5);
740 cmd = &ring->cmd[ring->cur];
741 cmd->cb = cb;
742 KASSERT(len <= sizeof (cmd->data))((len <= sizeof (cmd->data)) ? (void)0 : __assert("diagnostic "
, "/usr/src/sys/dev/usb/if_otus.c", 742, "len <= sizeof (cmd->data)"
))
;
743 memcpy(cmd->data, arg, len)__builtin_memcpy((cmd->data), (arg), (len));
744 ring->cur = (ring->cur + 1) % OTUS_HOST_CMD_RING_COUNT32;
745
746 /* If there is no pending command already, schedule a task. */
747 if (++ring->queued == 1)
748 usb_add_task(sc->sc_udev, &sc->sc_task);
749 splx(s)spllower(s);
750}
751
752int
753otus_newstate(struct ieee80211com *ic, enum ieee80211_state nstate, int arg)
754{
755 struct otus_softc *sc = ic->ic_softcic_ac.ac_if.if_softc;
756 struct otus_cmd_newstate cmd;
757
758 /* Do it in a process context. */
759 cmd.state = nstate;
760 cmd.arg = arg;
761 otus_do_async(sc, otus_newstate_cb, &cmd, sizeof cmd);
762 return 0;
763}
764
765void
766otus_newstate_cb(struct otus_softc *sc, void *arg)
767{
768 struct otus_cmd_newstate *cmd = arg;
769 struct ieee80211com *ic = &sc->sc_ic;
770 struct ieee80211_node *ni;
771 int s;
772
773 s = splnet()splraise(0x7);
774
775 switch (cmd->state) {
776 case IEEE80211_S_INIT:
777 break;
778
779 case IEEE80211_S_SCAN:
780 (void)otus_set_chan(sc, ic->ic_bss->ni_chan, 0);
781 if (!usbd_is_dying(sc->sc_udev))
782 timeout_add_msec(&sc->scan_to, 200);
783 break;
784
785 case IEEE80211_S_AUTH:
786 case IEEE80211_S_ASSOC:
787 (void)otus_set_chan(sc, ic->ic_bss->ni_chan, 0);
788 break;
789
790 case IEEE80211_S_RUN:
791 (void)otus_set_chan(sc, ic->ic_bss->ni_chan, 1);
792
793 ni = ic->ic_bss;
794
795 if (ic->ic_opmode == IEEE80211_M_STA) {
796 otus_updateslot(ic);
797 otus_set_bssid(sc, ni->ni_bssid);
798
799 /* Fake a join to init the Tx rate. */
800 otus_newassoc(ic, ni, 1);
801
802 /* Start calibration timer. */
803 if (!usbd_is_dying(sc->sc_udev))
804 timeout_add_sec(&sc->calib_to, 1);
805 }
806 break;
807 }
808
809 sc->sc_led_newstate(sc);
810 (void)sc->sc_newstate(ic, cmd->state, cmd->arg);
811
812 splx(s)spllower(s);
813}
814
815int
816otus_cmd(struct otus_softc *sc, uint8_t code, const void *idata, int ilen,
817 void *odata)
818{
819 struct otus_tx_cmd *cmd = &sc->tx_cmd;
820 struct ar_cmd_hdr *hdr;
821 int s, xferlen, error;
822
823 /* Always bulk-out a multiple of 4 bytes. */
824 xferlen = (sizeof (*hdr) + ilen + 3) & ~3;
825
826 hdr = (struct ar_cmd_hdr *)cmd->buf;
827 hdr->code = code;
828 hdr->len = ilen;
829 hdr->token = ++cmd->token; /* Don't care about endianness. */
830 memcpy((uint8_t *)&hdr[1], idata, ilen)__builtin_memcpy(((uint8_t *)&hdr[1]), (idata), (ilen));
831
832 DPRINTFN(2, ("sending command code=0x%02x len=%d token=%d\n",
833 code, ilen, hdr->token));
834
835 s = splusb()splraise(0x5);
836 cmd->odata = odata;
837 cmd->done = 0;
838
839 usbd_setup_xfer(cmd->xfer, sc->cmd_tx_pipe, cmd, cmd->buf, xferlen,
840 USBD_FORCE_SHORT_XFER0x08 | USBD_NO_COPY0x01 | USBD_SYNCHRONOUS0x02,
841 OTUS_CMD_TIMEOUT1000, NULL((void *)0));
842 error = usbd_transfer(cmd->xfer);
843 if (error != 0) {
844 splx(s)spllower(s);
845 printf("%s: could not send command 0x%x (error=%s)\n",
846 sc->sc_dev.dv_xname, code, usbd_errstr(error));
847 return EIO5;
848 }
849 if (!cmd->done)
850 error = tsleep_nsec(cmd, PCATCH0x100, "otuscmd", SEC_TO_NSEC(1));
851 cmd->odata = NULL((void *)0); /* In case answer is received too late. */
852 splx(s)spllower(s);
853 if (error != 0) {
854 printf("%s: timeout waiting for command 0x%02x reply\n",
855 sc->sc_dev.dv_xname, code);
856 }
857 return error;
858}
859
860void
861otus_write(struct otus_softc *sc, uint32_t reg, uint32_t val)
862{
863 sc->write_buf[sc->write_idx].reg = htole32(reg)((__uint32_t)(reg));
864 sc->write_buf[sc->write_idx].val = htole32(val)((__uint32_t)(val));
865
866 if (++sc->write_idx > AR_MAX_WRITE_IDX6)
867 (void)otus_write_barrier(sc);
868}
869
870int
871otus_write_barrier(struct otus_softc *sc)
872{
873 int error;
874
875 if (sc->write_idx == 0)
876 return 0; /* Nothing to flush. */
877
878 error = otus_cmd(sc, AR_CMD_WREG0x01, sc->write_buf,
879 sizeof (sc->write_buf[0]) * sc->write_idx, NULL((void *)0));
880 sc->write_idx = 0;
881 return error;
882}
883
884struct ieee80211_node *
885otus_node_alloc(struct ieee80211com *ic)
886{
887 return malloc(sizeof (struct otus_node), M_USBDEV102, M_NOWAIT0x0002 | M_ZERO0x0008);
888}
889
890int
891otus_media_change(struct ifnet *ifp)
892{
893 struct otus_softc *sc = ifp->if_softc;
894 struct ieee80211com *ic = &sc->sc_ic;
895 uint8_t rate, ridx;
896 int error;
897
898 error = ieee80211_media_change(ifp);
899 if (error != ENETRESET52)
900 return error;
901
902 if (ic->ic_fixed_rate != -1) {
903 rate = ic->ic_sup_rates[ic->ic_curmode].
904 rs_rates[ic->ic_fixed_rate] & IEEE80211_RATE_VAL0x7f;
905 for (ridx = 0; ridx <= OTUS_RIDX_MAX11; ridx++)
906 if (otus_rates[ridx].rate == rate)
907 break;
908 sc->fixed_ridx = ridx;
909 }
910
911 if ((ifp->if_flags & (IFF_UP0x1 | IFF_RUNNING0x40)) == (IFF_UP0x1 | IFF_RUNNING0x40))
912 error = otus_init(ifp);
913
914 return error;
915}
916
917int
918otus_read_eeprom(struct otus_softc *sc)
919{
920 uint32_t regs[8], reg;
921 uint8_t *eep;
922 int i, j, error;
923
924 /* Read EEPROM by blocks of 32 bytes. */
925 eep = (uint8_t *)&sc->eeprom;
926 reg = AR_EEPROM_OFFSET0x1600;
927 for (i = 0; i < sizeof (sc->eeprom) / 32; i++) {
928 for (j = 0; j < 8; j++, reg += 4)
929 regs[j] = htole32(reg)((__uint32_t)(reg));
930 error = otus_cmd(sc, AR_CMD_RREG0x00, regs, sizeof regs, eep);
931 if (error != 0)
932 break;
933 eep += 32;
934 }
935 return error;
936}
937
938void
939otus_newassoc(struct ieee80211com *ic, struct ieee80211_node *ni, int isnew)
940{
941 struct otus_softc *sc = ic->ic_softcic_ac.ac_if.if_softc;
942 struct otus_node *on = (void *)ni;
943 struct ieee80211_rateset *rs = &ni->ni_rates;
944 uint8_t rate;
945 int ridx, i;
946
947 DPRINTF(("new assoc isnew=%d addr=%s\n",
948 isnew, ether_sprintf(ni->ni_macaddr)));
949
950 ieee80211_amrr_node_init(&sc->amrr, &on->amn);
951 /* Start at lowest available bit-rate, AMRR will raise. */
952 ni->ni_txrate = 0;
953
954 for (i = 0; i < rs->rs_nrates; i++) {
955 rate = rs->rs_rates[i] & IEEE80211_RATE_VAL0x7f;
956 /* Convert 802.11 rate to hardware rate index. */
957 for (ridx = 0; ridx <= OTUS_RIDX_MAX11; ridx++)
958 if (otus_rates[ridx].rate == rate)
959 break;
960 on->ridx[i] = ridx;
961 DPRINTF(("rate=0x%02x ridx=%d\n",
962 rs->rs_rates[i], on->ridx[i]));
963 }
964}
965
966/* ARGSUSED */
967void
968otus_intr(struct usbd_xfer *xfer, void *priv, usbd_status status)
969{
970#if 0
971 struct otus_softc *sc = priv;
972 int len;
973
974 /*
975 * The Rx intr pipe is unused with current firmware. Notifications
976 * and replies to commands are sent through the Rx bulk pipe instead
977 * (with a magic PLCP header.)
978 */
979 if (__predict_false(status != USBD_NORMAL_COMPLETION)__builtin_expect(((status != USBD_NORMAL_COMPLETION) != 0), 0
)
) {
980 DPRINTF(("intr status=%d\n", status));
981 if (status == USBD_STALLED)
982 usbd_clear_endpoint_stall_async(sc->cmd_rx_pipe);
983 return;
984 }
985 usbd_get_xfer_status(xfer, NULL((void *)0), NULL((void *)0), &len, NULL((void *)0));
986
987 otus_cmd_rxeof(sc, sc->ibuf, len);
988#endif
989}
990
991void
992otus_cmd_rxeof(struct otus_softc *sc, uint8_t *buf, int len)
993{
994 struct ieee80211com *ic = &sc->sc_ic;
995 struct otus_tx_cmd *cmd;
996 struct ar_cmd_hdr *hdr;
997 int s;
998
999 if (__predict_false(len < sizeof (*hdr))__builtin_expect(((len < sizeof (*hdr)) != 0), 0)) {
1000 DPRINTF(("cmd too small %d\n", len));
1001 return;
1002 }
1003 hdr = (struct ar_cmd_hdr *)buf;
1004 if (__predict_false(sizeof (*hdr) + hdr->len > len ||__builtin_expect(((sizeof (*hdr) + hdr->len > len || sizeof
(*hdr) + hdr->len > 64) != 0), 0)
1005 sizeof (*hdr) + hdr->len > 64)__builtin_expect(((sizeof (*hdr) + hdr->len > len || sizeof
(*hdr) + hdr->len > 64) != 0), 0)
) {
1006 DPRINTF(("cmd too large %d\n", hdr->len));
1007 return;
1008 }
1009
1010 if ((hdr->code & 0xc0) != 0xc0) {
1011 DPRINTFN(2, ("received reply code=0x%02x len=%d token=%d\n",
1012 hdr->code, hdr->len, hdr->token));
1013 cmd = &sc->tx_cmd;
1014 if (__predict_false(hdr->token != cmd->token)__builtin_expect(((hdr->token != cmd->token) != 0), 0))
1015 return;
1016 /* Copy answer into caller's supplied buffer. */
1017 if (cmd->odata != NULL((void *)0))
1018 memcpy(cmd->odata, &hdr[1], hdr->len)__builtin_memcpy((cmd->odata), (&hdr[1]), (hdr->len
))
;
1019 cmd->done = 1;
1020 wakeup(cmd);
1021 return;
1022 }
1023
1024 /* Received unsolicited notification. */
1025 DPRINTF(("received notification code=0x%02x len=%d\n",
1026 hdr->code, hdr->len));
1027 switch (hdr->code & 0x3f) {
1028 case AR_EVT_BEACON0x00:
1029 break;
1030 case AR_EVT_TX_COMP0x01:
1031 {
1032 struct ar_evt_tx_comp *tx = (struct ar_evt_tx_comp *)&hdr[1];
1033 struct ieee80211_node *ni;
1034 struct otus_node *on;
1035
1036 DPRINTF(("tx completed %s status=%d phy=0x%x\n",
1037 ether_sprintf(tx->macaddr), letoh16(tx->status),
1038 letoh32(tx->phy)));
1039 s = splnet()splraise(0x7);
1040#ifdef notyet
1041#ifndef IEEE80211_STA_ONLY
1042 if (ic->ic_opmode != IEEE80211_M_STA) {
1043 ni = ieee80211_find_node(ic, tx->macaddr);
1044 if (__predict_false(ni == NULL)__builtin_expect(((ni == ((void *)0)) != 0), 0)) {
1045 splx(s)spllower(s);
1046 break;
1047 }
1048 } else
1049#endif
1050#endif
1051 ni = ic->ic_bss;
1052 /* Update rate control statistics. */
1053 on = (void *)ni;
1054 /* NB: we do not set the TX_MAC_RATE_PROBING flag. */
1055 if (__predict_true(tx->status != 0)__builtin_expect(((tx->status != 0) != 0), 1))
1056 on->amn.amn_retrycnt++;
1057 splx(s)spllower(s);
1058 break;
1059 }
1060 case AR_EVT_TBTT0x02:
1061 break;
1062 }
1063}
1064
1065void
1066otus_sub_rxeof(struct otus_softc *sc, uint8_t *buf, int len,
1067 struct mbuf_list *ml)
1068{
1069 struct ieee80211com *ic = &sc->sc_ic;
1070 struct ifnet *ifp = &ic->ic_ific_ac.ac_if;
1071 struct ieee80211_rxinfo rxi;
1072 struct ieee80211_node *ni;
1073 struct ar_rx_tail *tail;
1074 struct ieee80211_frame *wh;
1075 struct mbuf *m;
1076 uint8_t *plcp;
1077 int s, mlen, align;
1078
1079 if (__predict_false(len < AR_PLCP_HDR_LEN)__builtin_expect(((len < 12) != 0), 0)) {
1080 DPRINTF(("sub-xfer too short %d\n", len));
1081 return;
1082 }
1083 plcp = buf;
1084
1085 /* All bits in the PLCP header are set to 1 for non-MPDU. */
1086 if (memcmp(plcp, AR_PLCP_HDR_INTR, AR_PLCP_HDR_LEN)__builtin_memcmp((plcp), (AR_PLCP_HDR_INTR), (12)) == 0) {
1087 otus_cmd_rxeof(sc, plcp + AR_PLCP_HDR_LEN12,
1088 len - AR_PLCP_HDR_LEN12);
1089 return;
1090 }
1091
1092 /* Received MPDU. */
1093 if (__predict_false(len < AR_PLCP_HDR_LEN + sizeof (*tail))__builtin_expect(((len < 12 + sizeof (*tail)) != 0), 0)) {
1094 DPRINTF(("MPDU too short %d\n", len));
1095 ifp->if_ierrorsif_data.ifi_ierrors++;
1096 return;
1097 }
1098 tail = (struct ar_rx_tail *)(plcp + len - sizeof (*tail));
1099
1100 /* Discard error frames. */
1101 if (__predict_false(tail->error != 0)__builtin_expect(((tail->error != 0) != 0), 0)) {
1102 DPRINTF(("error frame 0x%02x\n", tail->error));
1103 if (tail->error & AR_RX_ERROR_FCS(1 << 3)) {
1104 DPRINTFN(3, ("bad FCS\n"));
1105 } else if (tail->error & AR_RX_ERROR_MMIC(1 << 6)) {
1106 /* Report Michael MIC failures to net80211. */
1107 ic->ic_stats.is_rx_locmicfail++;
1108 ieee80211_michael_mic_failure(ic, 0);
1109 }
1110 ifp->if_ierrorsif_data.ifi_ierrors++;
1111 return;
1112 }
1113 /* Compute MPDU's length. */
1114 mlen = len - AR_PLCP_HDR_LEN12 - sizeof (*tail);
1115 /* Make sure there's room for an 802.11 header + FCS. */
1116 if (__predict_false(mlen < IEEE80211_MIN_LEN)__builtin_expect(((mlen < (sizeof(struct ieee80211_frame_min
) + 4)) != 0), 0)
) {
1117 ifp->if_ierrorsif_data.ifi_ierrors++;
1118 return;
1119 }
1120 mlen -= IEEE80211_CRC_LEN4; /* strip 802.11 FCS */
1121 if (mlen > MCLBYTES(1 << 11)) {
1122 DPRINTF(("frame too large: %d\n", mlen));
1123 ifp->if_ierrorsif_data.ifi_ierrors++;
1124 return;
1125 }
1126
1127 wh = (struct ieee80211_frame *)(plcp + AR_PLCP_HDR_LEN12);
1128 /* Provide a 32-bit aligned protocol header to the stack. */
1129 align = (ieee80211_has_qos(wh) ^ ieee80211_has_addr4(wh)) ? 2 : 0;
1130
1131 MGETHDR(m, M_DONTWAIT, MT_DATA)m = m_gethdr((0x0002), (1));
1132 if (__predict_false(m == NULL)__builtin_expect(((m == ((void *)0)) != 0), 0)) {
1133 ifp->if_ierrorsif_data.ifi_ierrors++;
1134 return;
1135 }
1136 if (align + mlen > MHLEN((256 - sizeof(struct m_hdr)) - sizeof(struct pkthdr))) {
1137 MCLGET(m, M_DONTWAIT)(void) m_clget((m), (0x0002), (1 << 11));
1138 if (__predict_false(!(m->m_flags & M_EXT))__builtin_expect(((!(m->m_hdr.mh_flags & 0x0001)) != 0
), 0)
) {
1139 ifp->if_ierrorsif_data.ifi_ierrors++;
1140 m_freem(m);
1141 return;
1142 }
1143 }
1144 /* Finalize mbuf. */
1145 m->m_datam_hdr.mh_data += align;
1146 memcpy(mtod(m, caddr_t), wh, mlen)__builtin_memcpy((((caddr_t)((m)->m_hdr.mh_data))), (wh), (
mlen))
;
1147 m->m_pkthdrM_dat.MH.MH_pkthdr.len = m->m_lenm_hdr.mh_len = mlen;
1148
1149#if NBPFILTER1 > 0
1150 if (__predict_false(sc->sc_drvbpf != NULL)__builtin_expect(((sc->sc_drvbpf != ((void *)0)) != 0), 0)) {
1151 struct otus_rx_radiotap_header *tap = &sc->sc_rxtapsc_rxtapu.th;
1152 struct mbuf mb;
1153
1154 tap->wr_flags = 0;
1155 tap->wr_chan_freq = htole16(ic->ic_ibss_chan->ic_freq)((__uint16_t)(ic->ic_ibss_chan->ic_freq));
1156 tap->wr_chan_flags = htole16(ic->ic_ibss_chan->ic_flags)((__uint16_t)(ic->ic_ibss_chan->ic_flags));
1157 tap->wr_antsignal = tail->rssi;
1158 tap->wr_rate = 2; /* In case it can't be found below. */
1159 switch (tail->status & AR_RX_STATUS_MT_MASK0x3) {
1160 case AR_RX_STATUS_MT_CCK0:
1161 switch (plcp[0]) {
1162 case 10: tap->wr_rate = 2; break;
1163 case 20: tap->wr_rate = 4; break;
1164 case 55: tap->wr_rate = 11; break;
1165 case 110: tap->wr_rate = 22; break;
1166 }
1167 if (tail->status & AR_RX_STATUS_SHPREAMBLE(1 << 3))
1168 tap->wr_flags |= IEEE80211_RADIOTAP_F_SHORTPRE0x02;
1169 break;
1170 case AR_RX_STATUS_MT_OFDM1:
1171 switch (plcp[0] & 0xf) {
1172 case 0xb: tap->wr_rate = 12; break;
1173 case 0xf: tap->wr_rate = 18; break;
1174 case 0xa: tap->wr_rate = 24; break;
1175 case 0xe: tap->wr_rate = 36; break;
1176 case 0x9: tap->wr_rate = 48; break;
1177 case 0xd: tap->wr_rate = 72; break;
1178 case 0x8: tap->wr_rate = 96; break;
1179 case 0xc: tap->wr_rate = 108; break;
1180 }
1181 break;
1182 }
1183 mb.m_datam_hdr.mh_data = (caddr_t)tap;
1184 mb.m_lenm_hdr.mh_len = sc->sc_rxtap_len;
1185 mb.m_nextm_hdr.mh_next = m;
1186 mb.m_nextpktm_hdr.mh_nextpkt = NULL((void *)0);
1187 mb.m_typem_hdr.mh_type = 0;
1188 mb.m_flagsm_hdr.mh_flags = 0;
1189 bpf_mtap(sc->sc_drvbpf, &mb, BPF_DIRECTION_IN(1 << 0));
1190 }
1191#endif
1192
1193 s = splnet()splraise(0x7);
1194 ni = ieee80211_find_rxnode(ic, wh);
1195 rxi.rxi_flags = 0;
1196 rxi.rxi_rssi = tail->rssi;
1197 rxi.rxi_tstamp = 0; /* unused */
1198 ieee80211_inputm(ifp, m, ni, &rxi, ml);
1199
1200 /* Node is no longer needed. */
1201 ieee80211_release_node(ic, ni);
1202 splx(s)spllower(s);
1203}
1204
1205void
1206otus_rxeof(struct usbd_xfer *xfer, void *priv, usbd_status status)
1207{
1208 struct mbuf_list ml = MBUF_LIST_INITIALIZER(){ ((void *)0), ((void *)0), 0 };
1209 struct otus_rx_data *data = priv;
1210 struct otus_softc *sc = data->sc;
1211 caddr_t buf = data->buf;
1212 struct ar_rx_head *head;
1213 uint16_t hlen;
1214 int len;
1215
1216 if (__predict_false(status != USBD_NORMAL_COMPLETION)__builtin_expect(((status != USBD_NORMAL_COMPLETION) != 0), 0
)
) {
1217 DPRINTF(("RX status=%d\n", status));
1218 if (status == USBD_STALLED)
1219 usbd_clear_endpoint_stall_async(sc->data_rx_pipe);
1220 if (status != USBD_CANCELLED)
1221 goto resubmit;
1222 return;
1223 }
1224 usbd_get_xfer_status(xfer, NULL((void *)0), NULL((void *)0), &len, NULL((void *)0));
1225
1226 while (len >= sizeof (*head)) {
1227 head = (struct ar_rx_head *)buf;
1228 if (__predict_false(head->tag != htole16(AR_RX_HEAD_TAG))__builtin_expect(((head->tag != ((__uint16_t)(0x4e00))) !=
0), 0)
) {
1229 DPRINTF(("tag not valid 0x%x\n", letoh16(head->tag)));
1230 break;
1231 }
1232 hlen = letoh16(head->len)((__uint16_t)(head->len));
1233 if (__predict_false(sizeof (*head) + hlen > len)__builtin_expect(((sizeof (*head) + hlen > len) != 0), 0)) {
1234 DPRINTF(("xfer too short %d/%d\n", len, hlen));
1235 break;
1236 }
1237 /* Process sub-xfer. */
1238 otus_sub_rxeof(sc, (uint8_t *)&head[1], hlen, &ml);
1239
1240 /* Next sub-xfer is aligned on a 32-bit boundary. */
1241 hlen = (sizeof (*head) + hlen + 3) & ~3;
1242 buf += hlen;
1243 len -= hlen;
1244 }
1245 if_input(&sc->sc_ic.ic_ific_ac.ac_if, &ml);
1246
1247 resubmit:
1248 usbd_setup_xfer(xfer, sc->data_rx_pipe, data, data->buf, OTUS_RXBUFSZ(8 * 1024),
1249 USBD_SHORT_XFER_OK0x04, USBD_NO_TIMEOUT0, otus_rxeof);
1250 (void)usbd_transfer(data->xfer);
1251}
1252
1253void
1254otus_txeof(struct usbd_xfer *xfer, void *priv, usbd_status status)
1255{
1256 struct otus_tx_data *data = priv;
1257 struct otus_softc *sc = data->sc;
1258 struct ieee80211com *ic = &sc->sc_ic;
1259 struct ifnet *ifp = &ic->ic_ific_ac.ac_if;
1260 int s;
1261
1262 s = splnet()splraise(0x7);
1263 sc->tx_queued--;
1264 if (__predict_false(status != USBD_NORMAL_COMPLETION)__builtin_expect(((status != USBD_NORMAL_COMPLETION) != 0), 0
)
) {
1265 DPRINTF(("TX status=%d\n", status));
1266 if (status == USBD_STALLED)
1267 usbd_clear_endpoint_stall_async(sc->data_tx_pipe);
1268 ifp->if_oerrorsif_data.ifi_oerrors++;
1269 splx(s)spllower(s);
1270 return;
1271 }
1272 sc->sc_tx_timer = 0;
1273 ifq_clr_oactive(&ifp->if_snd);
1274 otus_start(ifp);
1275 splx(s)spllower(s);
1276}
1277
1278int
1279otus_tx(struct otus_softc *sc, struct mbuf *m, struct ieee80211_node *ni)
1280{
1281 struct ieee80211com *ic = &sc->sc_ic;
1282 struct otus_node *on = (void *)ni;
1283 struct otus_tx_data *data;
1284 struct ieee80211_frame *wh;
1285 struct ieee80211_key *k;
1286 struct ar_tx_head *head;
1287 uint32_t phyctl;
1288 uint16_t macctl, qos;
1289 uint8_t tid, qid;
1290 int error, ridx, hasqos, xferlen;
1291
1292 wh = mtod(m, struct ieee80211_frame *)((struct ieee80211_frame *)((m)->m_hdr.mh_data));
1293 if (wh->i_fc[1] & IEEE80211_FC1_PROTECTED0x40) {
1294 k = ieee80211_get_txkey(ic, wh, ni);
1295 if ((m = ieee80211_encrypt(ic, m, k)) == NULL((void *)0))
1296 return ENOBUFS55;
1297 wh = mtod(m, struct ieee80211_frame *)((struct ieee80211_frame *)((m)->m_hdr.mh_data));
1298 }
1299
1300 if ((hasqos = ieee80211_has_qos(wh))) {
1301 qos = ieee80211_get_qos(wh);
1302 tid = qos & IEEE80211_QOS_TID0x000f;
1303 qid = ieee80211_up_to_ac(ic, tid);
1304 } else {
1305 qos = 0;
1306 qid = EDCA_AC_BE;
1307 }
1308
1309 /* Pickup a rate index. */
1310 if (IEEE80211_IS_MULTICAST(wh->i_addr1)(*(wh->i_addr1) & 0x01) ||
1311 (wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK0x0c) != IEEE80211_FC0_TYPE_DATA0x08)
1312 ridx = (ic->ic_curmode == IEEE80211_MODE_11A) ?
1313 OTUS_RIDX_OFDM64 : OTUS_RIDX_CCK10;
1314 else if (ic->ic_fixed_rate != -1)
1315 ridx = sc->fixed_ridx;
1316 else
1317 ridx = on->ridx[ni->ni_txrate];
1318
1319 phyctl = 0;
1320 macctl = AR_TX_MAC_BACKOFF(1 << 3) | AR_TX_MAC_HW_DUR(1 << 9) | AR_TX_MAC_QID(qid)((qid) << 10);
1321
1322 if (IEEE80211_IS_MULTICAST(wh->i_addr1)(*(wh->i_addr1) & 0x01) ||
1323 (hasqos && ((qos & IEEE80211_QOS_ACK_POLICY_MASK0x0060) ==
1324 IEEE80211_QOS_ACK_POLICY_NOACK0x0020)))
1325 macctl |= AR_TX_MAC_NOACK(1 << 2);
1326
1327 if (!IEEE80211_IS_MULTICAST(wh->i_addr1)(*(wh->i_addr1) & 0x01)) {
1328 if (m->m_pkthdrM_dat.MH.MH_pkthdr.len + IEEE80211_CRC_LEN4 >= ic->ic_rtsthreshold)
1329 macctl |= AR_TX_MAC_RTS(1 << 0);
1330 else if ((ic->ic_flags & IEEE80211_F_USEPROT0x00100000) &&
1331 ridx >= OTUS_RIDX_OFDM64) {
1332 if (ic->ic_protmode == IEEE80211_PROT_CTSONLY)
1333 macctl |= AR_TX_MAC_CTS(1 << 1);
1334 else if (ic->ic_protmode == IEEE80211_PROT_RTSCTS)
1335 macctl |= AR_TX_MAC_RTS(1 << 0);
1336 }
1337 }
1338
1339 phyctl |= AR_TX_PHY_MCS(otus_rates[ridx].mcs)((otus_rates[ridx].mcs) << 18);
1340 if (ridx >= OTUS_RIDX_OFDM64) {
1341 phyctl |= AR_TX_PHY_MT_OFDM1;
1342 if (ridx <= OTUS_RIDX_OFDM248)
1343 phyctl |= AR_TX_PHY_ANTMSK(sc->txmask)((sc->txmask) << 15);
1344 else
1345 phyctl |= AR_TX_PHY_ANTMSK(1)((1) << 15);
1346 } else { /* CCK */
1347 phyctl |= AR_TX_PHY_MT_CCK0;
1348 phyctl |= AR_TX_PHY_ANTMSK(sc->txmask)((sc->txmask) << 15);
1349 }
1350
1351 /* Update rate control stats for frames that are ACK'ed. */
1352 if (!(macctl & AR_TX_MAC_NOACK(1 << 2)))
1353 ((struct otus_node *)ni)->amn.amn_txcnt++;
1354
1355 data = &sc->tx_data[sc->tx_cur];
1356 /* Fill Tx descriptor. */
1357 head = (struct ar_tx_head *)data->buf;
1358 head->len = htole16(m->m_pkthdr.len + IEEE80211_CRC_LEN)((__uint16_t)(m->M_dat.MH.MH_pkthdr.len + 4));
1359 head->macctl = htole16(macctl)((__uint16_t)(macctl));
1360 head->phyctl = htole32(phyctl)((__uint32_t)(phyctl));
1361
1362#if NBPFILTER1 > 0
1363 if (__predict_false(sc->sc_drvbpf != NULL)__builtin_expect(((sc->sc_drvbpf != ((void *)0)) != 0), 0)) {
1364 struct otus_tx_radiotap_header *tap = &sc->sc_txtapsc_txtapu.th;
1365 struct mbuf mb;
1366
1367 tap->wt_flags = 0;
1368 tap->wt_rate = otus_rates[ridx].rate;
1369 tap->wt_chan_freq = htole16(ic->ic_bss->ni_chan->ic_freq)((__uint16_t)(ic->ic_bss->ni_chan->ic_freq));
1370 tap->wt_chan_flags = htole16(ic->ic_bss->ni_chan->ic_flags)((__uint16_t)(ic->ic_bss->ni_chan->ic_flags));
1371
1372 mb.m_datam_hdr.mh_data = (caddr_t)tap;
1373 mb.m_lenm_hdr.mh_len = sc->sc_txtap_len;
1374 mb.m_nextm_hdr.mh_next = m;
1375 mb.m_nextpktm_hdr.mh_nextpkt = NULL((void *)0);
1376 mb.m_typem_hdr.mh_type = 0;
1377 mb.m_flagsm_hdr.mh_flags = 0;
1378 bpf_mtap(sc->sc_drvbpf, &mb, BPF_DIRECTION_OUT(1 << 1));
1379 }
1380#endif
1381
1382 xferlen = sizeof (*head) + m->m_pkthdrM_dat.MH.MH_pkthdr.len;
1383 m_copydata(m, 0, m->m_pkthdrM_dat.MH.MH_pkthdr.len, &head[1]);
1384 m_freem(m);
1385
1386 DPRINTFN(5, ("tx queued=%d len=%d mac=0x%04x phy=0x%08x rate=%d\n",
1387 sc->tx_queued, head->len, head->macctl, head->phyctl,
1388 otus_rates[ridx].rate));
1389 usbd_setup_xfer(data->xfer, sc->data_tx_pipe, data, data->buf, xferlen,
1390 USBD_FORCE_SHORT_XFER0x08 | USBD_NO_COPY0x01, OTUS_TX_TIMEOUT1000, otus_txeof);
1391 error = usbd_transfer(data->xfer);
1392 if (__predict_false(error != USBD_IN_PROGRESS && error != 0)__builtin_expect(((error != USBD_IN_PROGRESS && error
!= 0) != 0), 0)
)
1393 return error;
1394
1395 ieee80211_release_node(ic, ni);
1396
1397 sc->tx_queued++;
1398 sc->tx_cur = (sc->tx_cur + 1) % OTUS_TX_DATA_LIST_COUNT8;
1399
1400 return 0;
1401}
1402
1403void
1404otus_start(struct ifnet *ifp)
1405{
1406 struct otus_softc *sc = ifp->if_softc;
1407 struct ieee80211com *ic = &sc->sc_ic;
1408 struct ieee80211_node *ni;
1409 struct mbuf *m;
1410
1411 if (!(ifp->if_flags & IFF_RUNNING0x40) || ifq_is_oactive(&ifp->if_snd))
1412 return;
1413
1414 for (;;) {
1415 if (sc->tx_queued >= OTUS_TX_DATA_LIST_COUNT8) {
1416 ifq_set_oactive(&ifp->if_snd);
1417 break;
1418 }
1419 /* Send pending management frames first. */
1420 m = mq_dequeue(&ic->ic_mgtq);
1421 if (m != NULL((void *)0)) {
1422 ni = m->m_pkthdrM_dat.MH.MH_pkthdr.ph_cookie;
1423 goto sendit;
1424 }
1425 if (ic->ic_state != IEEE80211_S_RUN)
1426 break;
1427
1428 /* Encapsulate and send data frames. */
1429 m = ifq_dequeue(&ifp->if_snd);
1430 if (m == NULL((void *)0))
1431 break;
1432#if NBPFILTER1 > 0
1433 if (ifp->if_bpf != NULL((void *)0))
1434 bpf_mtap(ifp->if_bpf, m, BPF_DIRECTION_OUT(1 << 1));
1435#endif
1436 if ((m = ieee80211_encap(ifp, m, &ni)) == NULL((void *)0))
1437 continue;
1438sendit:
1439#if NBPFILTER1 > 0
1440 if (ic->ic_rawbpf != NULL((void *)0))
1441 bpf_mtap(ic->ic_rawbpf, m, BPF_DIRECTION_OUT(1 << 1));
1442#endif
1443 if (otus_tx(sc, m, ni) != 0) {
1444 ieee80211_release_node(ic, ni);
1445 ifp->if_oerrorsif_data.ifi_oerrors++;
1446 continue;
1447 }
1448
1449 sc->sc_tx_timer = 5;
1450 ifp->if_timer = 1;
1451 }
1452}
1453
1454void
1455otus_watchdog(struct ifnet *ifp)
1456{
1457 struct otus_softc *sc = ifp->if_softc;
1458
1459 ifp->if_timer = 0;
1460
1461 if (sc->sc_tx_timer > 0) {
1462 if (--sc->sc_tx_timer == 0) {
1463 printf("%s: device timeout\n", sc->sc_dev.dv_xname);
1464 /* otus_init(ifp); XXX needs a process context! */
1465 ifp->if_oerrorsif_data.ifi_oerrors++;
1466 return;
1467 }
1468 ifp->if_timer = 1;
1469 }
1470 ieee80211_watchdog(ifp);
1471}
1472
1473int
1474otus_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
1475{
1476 struct otus_softc *sc = ifp->if_softc;
1477 struct ieee80211com *ic = &sc->sc_ic;
1478 int s, error = 0;
1479
1480 if (usbd_is_dying(sc->sc_udev))
1481 return ENXIO6;
1482
1483 usbd_ref_incr(sc->sc_udev);
1484
1485 s = splnet()splraise(0x7);
1486
1487 switch (cmd) {
1488 case SIOCSIFADDR((unsigned long)0x80000000 | ((sizeof(struct ifreq) & 0x1fff
) << 16) | ((('i')) << 8) | ((12)))
:
1489 ifp->if_flags |= IFF_UP0x1;
1490 /* FALLTHROUGH */
1491 case SIOCSIFFLAGS((unsigned long)0x80000000 | ((sizeof(struct ifreq) & 0x1fff
) << 16) | ((('i')) << 8) | ((16)))
:
1492 if (ifp->if_flags & IFF_UP0x1) {
1493 if ((ifp->if_flags & IFF_RUNNING0x40) &&
1494 ((ifp->if_flags ^ sc->sc_if_flags) &
1495 (IFF_ALLMULTI0x200 | IFF_PROMISC0x100)) != 0) {
1496 otus_set_multi(sc);
1497 } else if (!(ifp->if_flags & IFF_RUNNING0x40))
1498 otus_init(ifp);
1499
1500 } else if (ifp->if_flags & IFF_RUNNING0x40)
1501 otus_stop(ifp);
1502
1503 sc->sc_if_flags = ifp->if_flags;
1504 break;
1505 case SIOCS80211CHANNEL((unsigned long)0x80000000 | ((sizeof(struct ieee80211chanreq
) & 0x1fff) << 16) | ((('i')) << 8) | ((238))
)
:
1506 error = ieee80211_ioctl(ifp, cmd, data);
1507 if (error == ENETRESET52 &&
1508 ic->ic_opmode == IEEE80211_M_MONITOR) {
1509 if ((ifp->if_flags & (IFF_UP0x1 | IFF_RUNNING0x40)) ==
1510 (IFF_UP0x1 | IFF_RUNNING0x40))
1511 otus_set_chan(sc, ic->ic_ibss_chan, 0);
1512 error = 0;
1513 }
1514 break;
1515 default:
1516 error = ieee80211_ioctl(ifp, cmd, data);
1517 }
1518
1519 if (error == ENETRESET52) {
1520 if ((ifp->if_flags & (IFF_UP0x1 | IFF_RUNNING0x40)) ==
1521 (IFF_UP0x1 | IFF_RUNNING0x40))
1522 otus_init(ifp);
1523 error = 0;
1524 }
1525
1526 splx(s)spllower(s);
1527
1528 usbd_ref_decr(sc->sc_udev);
1529
1530 return error;
1531}
1532
1533int
1534otus_set_multi(struct otus_softc *sc)
1535{
1536 struct arpcom *ac = &sc->sc_ic.ic_ac;
1537 struct ifnet *ifp = &ac->ac_if;
1538 struct ether_multi *enm;
1539 struct ether_multistep step;
1540 uint32_t lo, hi;
1541 uint8_t bit;
1542
1543 if (ac->ac_multirangecnt > 0)
1544 ifp->if_flags |= IFF_ALLMULTI0x200;
1545
1546 if ((ifp->if_flags & (IFF_ALLMULTI0x200 | IFF_PROMISC0x100)) != 0) {
1547 lo = hi = 0xffffffff;
1548 goto done;
1549 }
1550 lo = hi = 0;
1551 ETHER_FIRST_MULTI(step, ac, enm)do { (step).e_enm = ((&(ac)->ac_multiaddrs)->lh_first
); do { if ((((enm)) = ((step)).e_enm) != ((void *)0)) ((step
)).e_enm = ((((enm)))->enm_list.le_next); } while ( 0); } while
( 0)
;
1552 while (enm != NULL((void *)0)) {
1553 bit = enm->enm_addrlo[5] >> 2;
1554 if (bit < 32)
1555 lo |= 1 << bit;
1556 else
1557 hi |= 1 << (bit - 32);
1558 ETHER_NEXT_MULTI(step, enm)do { if (((enm) = (step).e_enm) != ((void *)0)) (step).e_enm =
(((enm))->enm_list.le_next); } while ( 0)
;
1559 }
1560 done:
1561 hi |= 1U << 31; /* Make sure the broadcast bit is set. */
1562 otus_write(sc, AR_MAC_REG_GROUP_HASH_TBL_L(0x1c3000 + 0x624), lo);
1563 otus_write(sc, AR_MAC_REG_GROUP_HASH_TBL_H(0x1c3000 + 0x628), hi);
1564 return otus_write_barrier(sc);
1565}
1566
1567void
1568otus_updateedca(struct ieee80211com *ic)
1569{
1570 /* Do it in a process context. */
1571 otus_do_async(ic->ic_softcic_ac.ac_if.if_softc, otus_updateedca_cb, NULL((void *)0), 0);
1572}
1573
1574/* ARGSUSED */
1575void
1576otus_updateedca_cb(struct otus_softc *sc, void *arg)
1577{
1578#define EXP2(val) ((1 << (val)) - 1)
1579#define AIFS(val) ((val) * 9 + 10)
1580 struct ieee80211com *ic = &sc->sc_ic;
1581 const struct ieee80211_edca_ac_params *edca;
1582 int s;
1583
1584 s = splnet()splraise(0x7);
1585
1586 edca = (ic->ic_flags & IEEE80211_F_QOS0x00080000) ?
1587 ic->ic_edca_ac : otus_edca_def;
1588
1589 /* Set CWmin/CWmax values. */
1590 otus_write(sc, AR_MAC_REG_AC0_CW(0x1c3000 + 0xb00),
1591 EXP2(edca[EDCA_AC_BE].ac_ecwmax) << 16 |
1592 EXP2(edca[EDCA_AC_BE].ac_ecwmin));
1593 otus_write(sc, AR_MAC_REG_AC1_CW(0x1c3000 + 0xb04),
1594 EXP2(edca[EDCA_AC_BK].ac_ecwmax) << 16 |
1595 EXP2(edca[EDCA_AC_BK].ac_ecwmin));
1596 otus_write(sc, AR_MAC_REG_AC2_CW(0x1c3000 + 0xb08),
1597 EXP2(edca[EDCA_AC_VI].ac_ecwmax) << 16 |
1598 EXP2(edca[EDCA_AC_VI].ac_ecwmin));
1599 otus_write(sc, AR_MAC_REG_AC3_CW(0x1c3000 + 0xb0c),
1600 EXP2(edca[EDCA_AC_VO].ac_ecwmax) << 16 |
1601 EXP2(edca[EDCA_AC_VO].ac_ecwmin));
1602 otus_write(sc, AR_MAC_REG_AC4_CW(0x1c3000 + 0xb10), /* Special TXQ. */
1603 EXP2(edca[EDCA_AC_VO].ac_ecwmax) << 16 |
1604 EXP2(edca[EDCA_AC_VO].ac_ecwmin));
1605
1606 /* Set AIFSN values. */
1607 otus_write(sc, AR_MAC_REG_AC1_AC0_AIFS(0x1c3000 + 0xb14),
1608 AIFS(edca[EDCA_AC_VI].ac_aifsn) << 24 |
1609 AIFS(edca[EDCA_AC_BK].ac_aifsn) << 12 |
1610 AIFS(edca[EDCA_AC_BE].ac_aifsn));
1611 otus_write(sc, AR_MAC_REG_AC3_AC2_AIFS(0x1c3000 + 0xb18),
1612 AIFS(edca[EDCA_AC_VO].ac_aifsn) << 16 | /* Special TXQ. */
1613 AIFS(edca[EDCA_AC_VO].ac_aifsn) << 4 |
1614 AIFS(edca[EDCA_AC_VI].ac_aifsn) >> 8);
1615
1616 /* Set TXOP limit. */
1617 otus_write(sc, AR_MAC_REG_AC1_AC0_TXOP(0x1c3000 + 0xb44),
1618 edca[EDCA_AC_BK].ac_txoplimit << 16 |
1619 edca[EDCA_AC_BE].ac_txoplimit);
1620 otus_write(sc, AR_MAC_REG_AC3_AC2_TXOP(0x1c3000 + 0xb48),
1621 edca[EDCA_AC_VO].ac_txoplimit << 16 |
1622 edca[EDCA_AC_VI].ac_txoplimit);
1623
1624 splx(s)spllower(s);
1625
1626 (void)otus_write_barrier(sc);
1627#undef AIFS
1628#undef EXP2
1629}
1630
1631void
1632otus_updateslot(struct ieee80211com *ic)
1633{
1634 /* Do it in a process context. */
1635 otus_do_async(ic->ic_softcic_ac.ac_if.if_softc, otus_updateslot_cb, NULL((void *)0), 0);
1636}
1637
1638/* ARGSUSED */
1639void
1640otus_updateslot_cb(struct otus_softc *sc, void *arg)
1641{
1642 uint32_t slottime;
1643
1644 slottime = (sc->sc_ic.ic_flags & IEEE80211_F_SHSLOT0x00020000) ?
1645 IEEE80211_DUR_DS_SHSLOT9: IEEE80211_DUR_DS_SLOT20;
1646 otus_write(sc, AR_MAC_REG_SLOT_TIME(0x1c3000 + 0x6f0), slottime << 10);
1647 (void)otus_write_barrier(sc);
1648}
1649
1650int
1651otus_init_mac(struct otus_softc *sc)
1652{
1653 int error;
1654
1655 otus_write(sc, AR_MAC_REG_ACK_EXTENSION(0x1c3000 + 0x690), 0x40);
1656 otus_write(sc, AR_MAC_REG_RETRY_MAX(0x1c3000 + 0xb28), 0);
1657 otus_write(sc, AR_MAC_REG_SNIFFER(0x1c3000 + 0x674), 0x2000000);
1658 otus_write(sc, AR_MAC_REG_RX_THRESHOLD(0x1c3000 + 0x640), 0xc1f80);
1659 otus_write(sc, AR_MAC_REG_RX_PE_DELAY(0x1c3000 + 0x64c), 0x70);
1660 otus_write(sc, AR_MAC_REG_EIFS_AND_SIFS(0x1c3000 + 0x698), 0xa144000);
1661 otus_write(sc, AR_MAC_REG_SLOT_TIME(0x1c3000 + 0x6f0), 9 << 10);
1662 otus_write(sc, 0x1c3b2c, 0x19000000);
1663 /* NAV protects ACK only (in TXOP). */
1664 otus_write(sc, 0x1c3b38, 0x201);
1665 /* Set beacon Tx power to 0x7. */
1666 otus_write(sc, AR_MAC_REG_BCN_HT1(0x1c3000 + 0xda0), 0x8000170);
1667 otus_write(sc, AR_MAC_REG_BACKOFF_PROTECT(0x1c3000 + 0x63c), 0x105);
1668 otus_write(sc, 0x1c3b9c, 0x10000a);
1669 /* Filter any control frames, BAR is bit 24. */
1670 otus_write(sc, 0x1c368c, 0x0500ffff);
1671 otus_write(sc, 0x1c3c40, 0x1);
1672 otus_write(sc, AR_MAC_REG_BASIC_RATE(0x1c3000 + 0x630), 0x150f);
1673 otus_write(sc, AR_MAC_REG_MANDATORY_RATE(0x1c3000 + 0x634), 0x150f);
1674 otus_write(sc, AR_MAC_REG_RTS_CTS_RATE(0x1c3000 + 0x638), 0x10b01bb);
1675 otus_write(sc, 0x1c3694, 0x4003c1e);
1676 /* Enable LED0 and LED1. */
1677 otus_write(sc, 0x1d0100, 0x3);
1678 otus_write(sc, 0x1d0104, 0x3);
1679 /* Switch MAC to OTUS interface. */
1680 otus_write(sc, 0x1c3600, 0x3);
1681 otus_write(sc, 0x1c3c50, 0xffff);
1682 otus_write(sc, 0x1c3680, 0xf00008);
1683 /* Disable Rx timeout (workaround). */
1684 otus_write(sc, 0x1c362c, 0);
1685
1686 /* Set USB Rx stream mode maximum frame number to 2. */
1687 otus_write(sc, 0x1e1110, 0x4);
1688 /* Set USB Rx stream mode timeout to 10us. */
1689 otus_write(sc, 0x1e1114, 0x80);
1690
1691 /* Set clock frequency to 88/80MHz. */
1692 otus_write(sc, 0x1d4008, 0x73);
1693 /* Set WLAN DMA interrupt mode: generate intr per packet. */
1694 otus_write(sc, 0x1c3d7c, 0x110011);
1695 otus_write(sc, 0x1c3bb0, 0x4);
1696 otus_write(sc, AR_MAC_REG_TXOP_NOT_ENOUGH_INDICATION(0x1c3000 + 0xb30), 0x141e0f48);
1697
1698 /* Disable HW decryption for now. */
1699 otus_write(sc, 0x1c3678, 0x78);
1700
1701 if ((error = otus_write_barrier(sc)) != 0)
1702 return error;
1703
1704 /* Set default EDCA parameters. */
1705 otus_updateedca_cb(sc, NULL((void *)0));
1706
1707 return 0;
1708}
1709
1710/*
1711 * Return default value for PHY register based on current operating mode.
1712 */
1713uint32_t
1714otus_phy_get_def(struct otus_softc *sc, uint32_t reg)
1715{
1716 int i;
1717
1718 for (i = 0; i < nitems(ar5416_phy_regs)(sizeof((ar5416_phy_regs)) / sizeof((ar5416_phy_regs)[0])); i++)
1719 if (AR_PHY(ar5416_phy_regs[i])(0x1c5800 + (ar5416_phy_regs[i]) * 4) == reg)
1720 return sc->phy_vals[i];
1721 return 0; /* Register not found. */
1722}
1723
1724/*
1725 * Update PHY's programming based on vendor-specific data stored in EEPROM.
1726 * This is for FEM-type devices only.
1727 */
1728int
1729otus_set_board_values(struct otus_softc *sc, struct ieee80211_channel *c)
1730{
1731 const struct ModalEepHeader *eep;
1732 uint32_t tmp, offset;
1733
1734 if (IEEE80211_IS_CHAN_5GHZ(c)(((c)->ic_flags & 0x0100) != 0))
1735 eep = &sc->eeprom.modalHeader[0];
1736 else
1737 eep = &sc->eeprom.modalHeader[1];
1738
1739 /* Offset of chain 2. */
1740 offset = 2 * 0x1000;
1741
1742 tmp = letoh32(eep->antCtrlCommon)((__uint32_t)(eep->antCtrlCommon));
1743 otus_write(sc, AR_PHY_SWITCH_COM(0x1c5800 + 0x0164), tmp);
1744
1745 tmp = letoh32(eep->antCtrlChain[0])((__uint32_t)(eep->antCtrlChain[0]));
1746 otus_write(sc, AR_PHY_SWITCH_CHAIN_0(0x1c5800 + 0x0160), tmp);
1747
1748 tmp = letoh32(eep->antCtrlChain[1])((__uint32_t)(eep->antCtrlChain[1]));
1749 otus_write(sc, AR_PHY_SWITCH_CHAIN_0(0x1c5800 + 0x0160) + offset, tmp);
1750
1751 if (1 /* sc->sc_sco == AR_SCO_SCN */) {
1752 tmp = otus_phy_get_def(sc, AR_PHY_SETTLING(0x1c5800 + 0x0044));
1753 tmp &= ~(0x7f << 7);
1754 tmp |= (eep->switchSettling & 0x7f) << 7;
1755 otus_write(sc, AR_PHY_SETTLING(0x1c5800 + 0x0044), tmp);
1756 }
1757
1758 tmp = otus_phy_get_def(sc, AR_PHY_DESIRED_SZ(0x1c5800 + 0x0050));
1759 tmp &= ~0xffff;
1760 tmp |= eep->pgaDesiredSize << 8 | eep->adcDesiredSize;
1761 otus_write(sc, AR_PHY_DESIRED_SZ(0x1c5800 + 0x0050), tmp);
1762
1763 tmp = eep->txEndToXpaOff << 24 | eep->txEndToXpaOff << 16 |
1764 eep->txFrameToXpaOn << 8 | eep->txFrameToXpaOn;
1765 otus_write(sc, AR_PHY_RF_CTL4(0x1c5800 + 0x0034), tmp);
1766
1767 tmp = otus_phy_get_def(sc, AR_PHY_RF_CTL3(0x1c5800 + 0x0028));
1768 tmp &= ~(0xff << 16);
1769 tmp |= eep->txEndToRxOn << 16;
1770 otus_write(sc, AR_PHY_RF_CTL3(0x1c5800 + 0x0028), tmp);
1771
1772 tmp = otus_phy_get_def(sc, AR_PHY_CCA(0x1c5800 + 0x3064));
1773 tmp &= ~(0x7f << 12);
1774 tmp |= (eep->thresh62 & 0x7f) << 12;
1775 otus_write(sc, AR_PHY_CCA(0x1c5800 + 0x3064), tmp);
1776
1777 tmp = otus_phy_get_def(sc, AR_PHY_RXGAIN(0x1c5800 + 0x0048));
1778 tmp &= ~(0x3f << 12);
1779 tmp |= (eep->txRxAttenCh[0] & 0x3f) << 12;
1780 otus_write(sc, AR_PHY_RXGAIN(0x1c5800 + 0x0048), tmp);
1781
1782 tmp = otus_phy_get_def(sc, AR_PHY_RXGAIN(0x1c5800 + 0x0048) + offset);
1783 tmp &= ~(0x3f << 12);
1784 tmp |= (eep->txRxAttenCh[1] & 0x3f) << 12;
1785 otus_write(sc, AR_PHY_RXGAIN(0x1c5800 + 0x0048) + offset, tmp);
1786
1787 tmp = otus_phy_get_def(sc, AR_PHY_GAIN_2GHZ(0x1c5800 + 0x0a0c));
1788 tmp &= ~(0x3f << 18);
1789 tmp |= (eep->rxTxMarginCh[0] & 0x3f) << 18;
1790 if (IEEE80211_IS_CHAN_5GHZ(c)(((c)->ic_flags & 0x0100) != 0)) {
1791 tmp &= ~(0xf << 10);
1792 tmp |= (eep->bswMargin[0] & 0xf) << 10;
1793 }
1794 otus_write(sc, AR_PHY_GAIN_2GHZ(0x1c5800 + 0x0a0c), tmp);
1795
1796 tmp = otus_phy_get_def(sc, AR_PHY_GAIN_2GHZ(0x1c5800 + 0x0a0c) + offset);
1797 tmp &= ~(0x3f << 18);
1798 tmp |= (eep->rxTxMarginCh[1] & 0x3f) << 18;
1799 otus_write(sc, AR_PHY_GAIN_2GHZ(0x1c5800 + 0x0a0c) + offset, tmp);
1800
1801 tmp = otus_phy_get_def(sc, AR_PHY_TIMING_CTRL4(0x1c5800 + 0x0120));
1802 tmp &= ~(0x3f << 5 | 0x1f);
1803 tmp |= (eep->iqCalICh[0] & 0x3f) << 5 | (eep->iqCalQCh[0] & 0x1f);
1804 otus_write(sc, AR_PHY_TIMING_CTRL4(0x1c5800 + 0x0120), tmp);
1805
1806 tmp = otus_phy_get_def(sc, AR_PHY_TIMING_CTRL4(0x1c5800 + 0x0120) + offset);
1807 tmp &= ~(0x3f << 5 | 0x1f);
1808 tmp |= (eep->iqCalICh[1] & 0x3f) << 5 | (eep->iqCalQCh[1] & 0x1f);
1809 otus_write(sc, AR_PHY_TIMING_CTRL4(0x1c5800 + 0x0120) + offset, tmp);
1810
1811 tmp = otus_phy_get_def(sc, AR_PHY_TPCRG1(0x1c5800 + 0x0a58));
1812 tmp &= ~(0xf << 16);
1813 tmp |= (eep->xpd & 0xf) << 16;
1814 otus_write(sc, AR_PHY_TPCRG1(0x1c5800 + 0x0a58), tmp);
1815
1816 return otus_write_barrier(sc);
1817}
1818
1819int
1820otus_program_phy(struct otus_softc *sc, struct ieee80211_channel *c)
1821{
1822 const uint32_t *vals;
1823 int error, i;
1824
1825 /* Select PHY programming based on band and bandwidth. */
1826 if (IEEE80211_IS_CHAN_2GHZ(c)(((c)->ic_flags & 0x0080) != 0))
1827 vals = ar5416_phy_vals_2ghz_20mhz;
1828 else
1829 vals = ar5416_phy_vals_5ghz_20mhz;
1830 for (i = 0; i < nitems(ar5416_phy_regs)(sizeof((ar5416_phy_regs)) / sizeof((ar5416_phy_regs)[0])); i++)
1831 otus_write(sc, AR_PHY(ar5416_phy_regs[i])(0x1c5800 + (ar5416_phy_regs[i]) * 4), vals[i]);
1832 sc->phy_vals = vals;
1833
1834 if (sc->eeprom.baseEepHeader.deviceType == 0x80) /* FEM */
1835 if ((error = otus_set_board_values(sc, c)) != 0)
1836 return error;
1837
1838 /* Initial Tx power settings. */
1839 otus_write(sc, AR_PHY_POWER_TX_RATE_MAX(0x1c5800 + 0x013c), 0x7f);
1840 otus_write(sc, AR_PHY_POWER_TX_RATE1(0x1c5800 + 0x0134), 0x3f3f3f3f);
1841 otus_write(sc, AR_PHY_POWER_TX_RATE2(0x1c5800 + 0x0138), 0x3f3f3f3f);
1842 otus_write(sc, AR_PHY_POWER_TX_RATE3(0x1c5800 + 0x0a34), 0x3f3f3f3f);
1843 otus_write(sc, AR_PHY_POWER_TX_RATE4(0x1c5800 + 0x0a38), 0x3f3f3f3f);
1844 otus_write(sc, AR_PHY_POWER_TX_RATE5(0x1c5800 + 0x0b8c), 0x3f3f3f3f);
1845 otus_write(sc, AR_PHY_POWER_TX_RATE6(0x1c5800 + 0x0b90), 0x3f3f3f3f);
1846 otus_write(sc, AR_PHY_POWER_TX_RATE7(0x1c5800 + 0x0bcc), 0x3f3f3f3f);
1847 otus_write(sc, AR_PHY_POWER_TX_RATE8(0x1c5800 + 0x0bd0), 0x3f3f3f3f);
1848 otus_write(sc, AR_PHY_POWER_TX_RATE9(0x1c5800 + 0x0bd4), 0x3f3f3f3f);
1849
1850 if (IEEE80211_IS_CHAN_2GHZ(c)(((c)->ic_flags & 0x0080) != 0))
1851 otus_write(sc, 0x1d4014, 0x5163);
1852 else
1853 otus_write(sc, 0x1d4014, 0x5143);
1854
1855 return otus_write_barrier(sc);
1856}
1857
1858static __inline uint8_t
1859otus_reverse_bits(uint8_t v)
1860{
1861 v = ((v >> 1) & 0x55) | ((v & 0x55) << 1);
1862 v = ((v >> 2) & 0x33) | ((v & 0x33) << 2);
1863 v = ((v >> 4) & 0x0f) | ((v & 0x0f) << 4);
1864 return v;
1865}
1866
1867int
1868otus_set_rf_bank4(struct otus_softc *sc, struct ieee80211_channel *c)
1869{
1870 uint8_t chansel, d0, d1;
1871 uint16_t data;
1872 int error;
1873
1874 d0 = 0;
1875 if (IEEE80211_IS_CHAN_5GHZ(c)(((c)->ic_flags & 0x0100) != 0)) {
1876 chansel = (c->ic_freq - 4800) / 5;
1877 if (chansel & 1)
1878 d0 |= AR_BANK4_AMODE_REFSEL(2)((2) << 2);
1879 else
1880 d0 |= AR_BANK4_AMODE_REFSEL(1)((1) << 2);
1881 } else {
1882 d0 |= AR_BANK4_AMODE_REFSEL(2)((2) << 2);
1883 if (c->ic_freq == 2484) { /* CH 14 */
1884 d0 |= AR_BANK4_BMODE_LF_SYNTH_FREQ(1 << 1);
1885 chansel = 10 + (c->ic_freq - 2274) / 5;
1886 } else
1887 chansel = 16 + (c->ic_freq - 2272) / 5;
1888 chansel <<= 2;
1889 }
1890 d0 |= AR_BANK4_ADDR(1)((1) << 5) | AR_BANK4_CHUP(1 << 0);
1891 d1 = otus_reverse_bits(chansel);
1892
1893 /* Write bits 0-4 of d0 and d1. */
1894 data = (d1 & 0x1f) << 5 | (d0 & 0x1f);
1895 otus_write(sc, AR_PHY(44)(0x1c5800 + (44) * 4), data);
1896 /* Write bits 5-7 of d0 and d1. */
1897 data = (d1 >> 5) << 5 | (d0 >> 5);
1898 otus_write(sc, AR_PHY(58)(0x1c5800 + (58) * 4), data);
1899
1900 if ((error = otus_write_barrier(sc)) == 0)
1901 usbd_delay_ms(sc->sc_udev, 10);
1902 return error;
1903}
1904
1905void
1906otus_get_delta_slope(uint32_t coeff, uint32_t *exponent, uint32_t *mantissa)
1907{
1908#define COEFF_SCALE_SHIFT 24
1909 uint32_t exp, man;
1910
1911 /* exponent = 14 - floor(log2(coeff)) */
1912 for (exp = 31; exp > 0; exp--)
1913 if (coeff & (1 << exp))
1914 break;
1915 KASSERT(exp != 0)((exp != 0) ? (void)0 : __assert("diagnostic ", "/usr/src/sys/dev/usb/if_otus.c"
, 1915, "exp != 0"))
;
1916 exp = 14 - (exp - COEFF_SCALE_SHIFT);
1917
1918 /* mantissa = floor(coeff * 2^exponent + 0.5) */
1919 man = coeff + (1 << (COEFF_SCALE_SHIFT - exp - 1));
1920
1921 *mantissa = man >> (COEFF_SCALE_SHIFT - exp);
1922 *exponent = exp - 16;
1923#undef COEFF_SCALE_SHIFT
1924}
1925
1926int
1927otus_set_chan(struct otus_softc *sc, struct ieee80211_channel *c, int assoc)
1928{
1929 struct ieee80211com *ic = &sc->sc_ic;
1930 struct ar_cmd_frequency cmd;
1931 struct ar_rsp_frequency rsp;
1932 const uint32_t *vals;
1933 uint32_t coeff, exp, man, tmp;
1934 uint8_t code;
1935 int error, chan, i;
1936
1937 chan = ieee80211_chan2ieee(ic, c);
Value stored to 'chan' is never read
1938 DPRINTF(("setting channel %d (%dMHz)\n", chan, c->ic_freq));
1939
1940 tmp = IEEE80211_IS_CHAN_2GHZ(c)(((c)->ic_flags & 0x0080) != 0) ? 0x105 : 0x104;
1941 otus_write(sc, AR_MAC_REG_DYNAMIC_SIFS_ACK(0x1c3000 + 0x658), tmp);
1942 if ((error = otus_write_barrier(sc)) != 0)
1943 return error;
1944
1945 /* Disable BB Heavy Clip. */
1946 otus_write(sc, AR_PHY_HEAVY_CLIP_ENABLE(0x1c5800 + 0x01e0), 0x200);
1947 if ((error = otus_write_barrier(sc)) != 0)
1948 return error;
1949
1950 /* XXX Is that FREQ_START ? */
1951 error = otus_cmd(sc, AR_CMD_FREQ_STRAT0x33, NULL((void *)0), 0, NULL((void *)0));
1952 if (error != 0)
1953 return error;
1954
1955 /* Reprogram PHY and RF on channel band or bandwidth changes. */
1956 if (sc->bb_reset || c->ic_flags != sc->sc_curchan->ic_flags) {
1957 DPRINTF(("band switch\n"));
1958
1959 /* Cold/Warm reset BB/ADDA. */
1960 otus_write(sc, 0x1d4004, sc->bb_reset ? 0x800 : 0x400);
1961 if ((error = otus_write_barrier(sc)) != 0)
1962 return error;
1963 otus_write(sc, 0x1d4004, 0);
1964 if ((error = otus_write_barrier(sc)) != 0)
1965 return error;
1966 sc->bb_reset = 0;
1967
1968 if ((error = otus_program_phy(sc, c)) != 0) {
1969 printf("%s: could not program PHY\n",
1970 sc->sc_dev.dv_xname);
1971 return error;
1972 }
1973
1974 /* Select RF programming based on band. */
1975 if (IEEE80211_IS_CHAN_5GHZ(c)(((c)->ic_flags & 0x0100) != 0))
1976 vals = ar5416_banks_vals_5ghz;
1977 else
1978 vals = ar5416_banks_vals_2ghz;
1979 for (i = 0; i < nitems(ar5416_banks_regs)(sizeof((ar5416_banks_regs)) / sizeof((ar5416_banks_regs)[0])
)
; i++)
1980 otus_write(sc, AR_PHY(ar5416_banks_regs[i])(0x1c5800 + (ar5416_banks_regs[i]) * 4), vals[i]);
1981 if ((error = otus_write_barrier(sc)) != 0) {
1982 printf("%s: could not program RF\n",
1983 sc->sc_dev.dv_xname);
1984 return error;
1985 }
1986 code = AR_CMD_RF_INIT0x31;
1987 } else {
1988 code = AR_CMD_FREQUENCY0x30;
1989 }
1990
1991 if ((error = otus_set_rf_bank4(sc, c)) != 0)
1992 return error;
1993
1994 tmp = (sc->txmask == 0x5) ? 0x340 : 0x240;
1995 otus_write(sc, AR_PHY_TURBO(0x1c5800 + 0x0004), tmp);
1996 if ((error = otus_write_barrier(sc)) != 0)
1997 return error;
1998
1999 /* Send firmware command to set channel. */
2000 cmd.freq = htole32((uint32_t)c->ic_freq * 1000)((__uint32_t)((uint32_t)c->ic_freq * 1000));
2001 cmd.dynht2040 = htole32(0)((__uint32_t)(0));
2002 cmd.htena = htole32(1)((__uint32_t)(1));
2003 /* Set Delta Slope (exponent and mantissa). */
2004 coeff = (100 << 24) / c->ic_freq;
2005 otus_get_delta_slope(coeff, &exp, &man);
2006 cmd.dsc_exp = htole32(exp)((__uint32_t)(exp));
2007 cmd.dsc_man = htole32(man)((__uint32_t)(man));
2008 DPRINTF(("ds coeff=%u exp=%u man=%u\n", coeff, exp, man));
2009 /* For Short GI, coeff is 9/10 that of normal coeff. */
2010 coeff = (9 * coeff) / 10;
2011 otus_get_delta_slope(coeff, &exp, &man);
2012 cmd.dsc_shgi_exp = htole32(exp)((__uint32_t)(exp));
2013 cmd.dsc_shgi_man = htole32(man)((__uint32_t)(man));
2014 DPRINTF(("ds shgi coeff=%u exp=%u man=%u\n", coeff, exp, man));
2015 /* Set wait time for AGC and noise calibration (100 or 200ms). */
2016 cmd.check_loop_count = assoc ? htole32(2000)((__uint32_t)(2000)) : htole32(1000)((__uint32_t)(1000));
2017 DPRINTF(("%s\n", (code == AR_CMD_RF_INIT) ? "RF_INIT" : "FREQUENCY"));
2018 error = otus_cmd(sc, code, &cmd, sizeof cmd, &rsp);
2019 if (error != 0)
2020 return error;
2021 if ((rsp.status & htole32(AR_CAL_ERR_AGC | AR_CAL_ERR_NF_VAL)((__uint32_t)((1 << 0) | (1 << 2)))) != 0) {
2022 DPRINTF(("status=0x%x\n", letoh32(rsp.status)));
2023 /* Force cold reset on next channel. */
2024 sc->bb_reset = 1;
2025 }
2026#ifdef OTUS_DEBUG
2027 if (otus_debug) {
2028 printf("calibration status=0x%x\n", letoh32(rsp.status)((__uint32_t)(rsp.status)));
2029 for (i = 0; i < 2; i++) { /* 2 Rx chains */
2030 /* Sign-extend 9-bit NF values. */
2031 printf("noisefloor chain %d=%d\n", i,
2032 (((int32_t)letoh32(rsp.nf[i])((__uint32_t)(rsp.nf[i]))) << 4) >> 23);
2033 printf("noisefloor ext chain %d=%d\n", i,
2034 ((int32_t)letoh32(rsp.nf_ext[i])((__uint32_t)(rsp.nf_ext[i]))) >> 23);
2035 }
2036 }
2037#endif
2038 sc->sc_curchan = c;
2039 return 0;
2040}
2041
2042#ifdef notyet
2043int
2044otus_set_key(struct ieee80211com *ic, struct ieee80211_node *ni,
2045 struct ieee80211_key *k)
2046{
2047 struct otus_softc *sc = ic->ic_softcic_ac.ac_if.if_softc;
2048 struct otus_cmd_key cmd;
2049
2050 /* Defer setting of WEP keys until interface is brought up. */
2051 if ((ic->ic_ific_ac.ac_if.if_flags & (IFF_UP0x1 | IFF_RUNNING0x40)) !=
2052 (IFF_UP0x1 | IFF_RUNNING0x40))
2053 return 0;
2054
2055 /* Do it in a process context. */
2056 cmd.key = *k;
2057 cmd.ni = *ni;
2058 otus_do_async(sc, otus_set_key_cb, &cmd, sizeof cmd);
2059 sc->sc_key_tasks++
2060 return EBUSY16;
2061}
2062
2063void
2064otus_set_key_cb(struct otus_softc *sc, void *arg)
2065{
2066 struct otus_cmd_key *cmd = arg;
2067 struct ieee80211_key *k = &cmd->key;
2068 struct ar_cmd_ekey key;
2069 uint16_t cipher;
2070 int error;
2071
2072 sc->sc_keys_tasks--;
2073
2074 memset(&key, 0, sizeof key)__builtin_memset((&key), (0), (sizeof key));
2075 if (k->k_flags & IEEE80211_KEY_GROUP0x00000001) {
2076 key.uid = htole16(k->k_id)((__uint16_t)(k->k_id));
2077 IEEE80211_ADDR_COPY(key.macaddr, sc->sc_ic.ic_myaddr)__builtin_memcpy((key.macaddr), (sc->sc_ic.ic_myaddr), (6)
)
;
2078 key.macaddr[0] |= 0x80;
2079 } else {
2080 key.uid = htole16(OTUS_UID(cmd->associd))((__uint16_t)((((cmd->associd) &~ 0xc000) + 4)));
2081 IEEE80211_ADDR_COPY(key.macaddr, ni->ni_macaddr)__builtin_memcpy((key.macaddr), (ni->ni_macaddr), (6));
2082 }
2083 key.kix = htole16(0)((__uint16_t)(0));
2084 /* Map net80211 cipher to hardware. */
2085 switch (k->k_cipher) {
2086 case IEEE80211_CIPHER_WEP40:
2087 cipher = AR_CIPHER_WEP641;
2088 break;
2089 case IEEE80211_CIPHER_WEP104:
2090 cipher = AR_CIPHER_WEP1285;
2091 break;
2092 case IEEE80211_CIPHER_TKIP:
2093 cipher = AR_CIPHER_TKIP2;
2094 break;
2095 case IEEE80211_CIPHER_CCMP:
2096 cipher = AR_CIPHER_AES4;
2097 break;
2098 default:
2099 IEEE80211_SEND_MGMT(ic, cmd->ni, IEEE80211_FC0_SUBTYPE_DEAUTH,((*(ic)->ic_send_mgmt)(ic, cmd->ni, 0xc0, IEEE80211_REASON_AUTH_LEAVE
, 0))
2100 IEEE80211_REASON_AUTH_LEAVE)((*(ic)->ic_send_mgmt)(ic, cmd->ni, 0xc0, IEEE80211_REASON_AUTH_LEAVE
, 0))
;
2101 ieee80211_new_state(ic, IEEE80211_S_SCAN, -1)(((ic)->ic_newstate)((ic), (IEEE80211_S_SCAN), (-1)));
2102 return;
2103 }
2104 key.cipher = htole16(cipher)((__uint16_t)(cipher));
2105 memcpy(key.key, k->k_key, MIN(k->k_len, 16))__builtin_memcpy((key.key), (k->k_key), ((((k->k_len)<
(16))?(k->k_len):(16))))
;
2106 error = otus_cmd(sc, AR_CMD_EKEY0x28, &key, sizeof key, NULL((void *)0));
2107 if (error != 0 || k->k_cipher != IEEE80211_CIPHER_TKIP) {
2108 IEEE80211_SEND_MGMT(ic, cmd->ni, IEEE80211_FC0_SUBTYPE_DEAUTH,((*(ic)->ic_send_mgmt)(ic, cmd->ni, 0xc0, IEEE80211_REASON_AUTH_LEAVE
, 0))
2109 IEEE80211_REASON_AUTH_LEAVE)((*(ic)->ic_send_mgmt)(ic, cmd->ni, 0xc0, IEEE80211_REASON_AUTH_LEAVE
, 0))
;
2110 ieee80211_new_state(ic, IEEE80211_S_SCAN, -1)(((ic)->ic_newstate)((ic), (IEEE80211_S_SCAN), (-1)));
2111 return;
2112 }
2113
2114 /* TKIP: set Tx/Rx MIC Key. */
2115 key.kix = htole16(1)((__uint16_t)(1));
2116 memcpy(key.key, k->k_key + 16, 16)__builtin_memcpy((key.key), (k->k_key + 16), (16));
2117 (void)otus_cmd(sc, AR_CMD_EKEY0x28, &key, sizeof key, NULL((void *)0));
2118
2119 if (sc->sc_key_tasks == 0) {
2120 DPRINTF(("marking port %s valid\n",
2121 ether_sprintf(cmd->ni->ni_macaddr)));
2122 cmd->ni->ni_port_valid = 1;
2123 ieee80211_set_link_state(ic, LINK_STATE_UP4);
2124 }
2125}
2126
2127void
2128otus_delete_key(struct ieee80211com *ic, struct ieee80211_node *ni,
2129 struct ieee80211_key *k)
2130{
2131 struct otus_softc *sc = ic->ic_softcic_ac.ac_if.if_softc;
2132 struct otus_cmd_key cmd;
2133
2134 if (!(ic->ic_ific_ac.ac_if.if_flags & IFF_RUNNING0x40) ||
2135 ic->ic_state != IEEE80211_S_RUN)
2136 return; /* Nothing to do. */
2137
2138 /* Do it in a process context. */
2139 cmd.key = *k;
2140 cmd.associd = (ni != NULL((void *)0)) ? ni->ni_associd : 0;
2141 otus_do_async(sc, otus_delete_key_cb, &cmd, sizeof cmd);
2142}
2143
2144void
2145otus_delete_key_cb(struct otus_softc *sc, void *arg)
2146{
2147 struct otus_cmd_key *cmd = arg;
2148 struct ieee80211_key *k = &cmd->key;
2149 uint32_t uid;
2150
2151 if (k->k_flags & IEEE80211_KEY_GROUP0x00000001)
2152 uid = htole32(k->k_id)((__uint32_t)(k->k_id));
2153 else
2154 uid = htole32(OTUS_UID(cmd->associd))((__uint32_t)((((cmd->associd) &~ 0xc000) + 4)));
2155 (void)otus_cmd(sc, AR_CMD_DKEY0x29, &uid, sizeof uid, NULL((void *)0));
2156}
2157#endif
2158
2159void
2160otus_calibrate_to(void *arg)
2161{
2162 struct otus_softc *sc = arg;
2163 struct ieee80211com *ic = &sc->sc_ic;
2164 struct ieee80211_node *ni;
2165 int s;
2166
2167 if (usbd_is_dying(sc->sc_udev))
2168 return;
2169
2170 usbd_ref_incr(sc->sc_udev);
2171
2172 s = splnet()splraise(0x7);
2173 ni = ic->ic_bss;
2174 ieee80211_amrr_choose(&sc->amrr, ni, &((struct otus_node *)ni)->amn);
2175 splx(s)spllower(s);
2176
2177 if (!usbd_is_dying(sc->sc_udev))
2178 timeout_add_sec(&sc->calib_to, 1);
2179
2180 usbd_ref_decr(sc->sc_udev);
2181}
2182
2183int
2184otus_set_bssid(struct otus_softc *sc, const uint8_t *bssid)
2185{
2186 otus_write(sc, AR_MAC_REG_BSSID_L(0x1c3000 + 0x618),
2187 bssid[0] | bssid[1] << 8 | bssid[2] << 16 | bssid[3] << 24);
2188 otus_write(sc, AR_MAC_REG_BSSID_H(0x1c3000 + 0x61c),
2189 bssid[4] | bssid[5] << 8);
2190 return otus_write_barrier(sc);
2191}
2192
2193int
2194otus_set_macaddr(struct otus_softc *sc, const uint8_t *addr)
2195{
2196 otus_write(sc, AR_MAC_REG_MAC_ADDR_L(0x1c3000 + 0x610),
2197 addr[0] | addr[1] << 8 | addr[2] << 16 | addr[3] << 24);
2198 otus_write(sc, AR_MAC_REG_MAC_ADDR_H(0x1c3000 + 0x614),
2199 addr[4] | addr[5] << 8);
2200 return otus_write_barrier(sc);
2201}
2202
2203/* Default single-LED. */
2204void
2205otus_led_newstate_type1(struct otus_softc *sc)
2206{
2207 /* TBD */
2208}
2209
2210/* NETGEAR, dual-LED. */
2211void
2212otus_led_newstate_type2(struct otus_softc *sc)
2213{
2214 /* TBD */
2215}
2216
2217/* NETGEAR, single-LED/3 colors (blue, red, purple.) */
2218void
2219otus_led_newstate_type3(struct otus_softc *sc)
2220{
2221 struct ieee80211com *ic = &sc->sc_ic;
2222 uint32_t state = sc->led_state;
2223
2224 if (ic->ic_state == IEEE80211_S_INIT) {
2225 state = 0; /* LED off. */
2226 } else if (ic->ic_state == IEEE80211_S_RUN) {
2227 /* Associated, LED always on. */
2228 if (IEEE80211_IS_CHAN_2GHZ(sc->sc_curchan)(((sc->sc_curchan)->ic_flags & 0x0080) != 0))
2229 state = AR_LED0_ON(1 << 0); /* 2GHz=>Red. */
2230 else
2231 state = AR_LED1_ON(1 << 1); /* 5GHz=>Blue. */
2232 } else {
2233 /* Scanning, blink LED. */
2234 state ^= AR_LED0_ON(1 << 0) | AR_LED1_ON(1 << 1);
2235 if (IEEE80211_IS_CHAN_2GHZ(sc->sc_curchan)(((sc->sc_curchan)->ic_flags & 0x0080) != 0))
2236 state &= ~AR_LED1_ON(1 << 1);
2237 else
2238 state &= ~AR_LED0_ON(1 << 0);
2239 }
2240 if (state != sc->led_state) {
2241 otus_write(sc, 0x1d0104, state);
2242 if (otus_write_barrier(sc) == 0)
2243 sc->led_state = state;
2244 }
2245}
2246
2247int
2248otus_init(struct ifnet *ifp)
2249{
2250 struct otus_softc *sc = ifp->if_softc;
2251 struct ieee80211com *ic = &sc->sc_ic;
2252 int error;
2253
2254 /* Init host command ring. */
2255 sc->cmdq.cur = sc->cmdq.next = sc->cmdq.queued = 0;
2256
2257 if ((error = otus_init_mac(sc)) != 0) {
2258 printf("%s: could not initialize MAC\n", sc->sc_dev.dv_xname);
2259 return error;
2260 }
2261
2262 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))
;
2263 (void)otus_set_macaddr(sc, ic->ic_myaddr);
2264
2265 switch (ic->ic_opmode) {
2266#ifdef notyet
2267#ifndef IEEE80211_STA_ONLY
2268 case IEEE80211_M_HOSTAP:
2269 otus_write(sc, 0x1c3700, 0x0f0000a1);
2270 otus_write(sc, 0x1c3c40, 0x1);
2271 break;
2272 case IEEE80211_M_IBSS:
2273 otus_write(sc, 0x1c3700, 0x0f000000);
2274 otus_write(sc, 0x1c3c40, 0x1);
2275 break;
2276#endif
2277#endif
2278 case IEEE80211_M_STA:
2279 otus_write(sc, 0x1c3700, 0x0f000002);
2280 otus_write(sc, 0x1c3c40, 0x1);
2281 break;
2282 default:
2283 break;
2284 }
2285 otus_write(sc, AR_MAC_REG_SNIFFER(0x1c3000 + 0x674),
2286 (ic->ic_opmode == IEEE80211_M_MONITOR) ? 0x2000001 : 0x2000000);
2287 (void)otus_write_barrier(sc);
2288
2289 sc->bb_reset = 1; /* Force cold reset. */
2290 ic->ic_bss->ni_chan = ic->ic_ibss_chan;
2291 if ((error = otus_set_chan(sc, ic->ic_ibss_chan, 0)) != 0) {
2292 printf("%s: could not set channel\n", sc->sc_dev.dv_xname);
2293 return error;
2294 }
2295
2296 /* Start Rx. */
2297 otus_write(sc, AR_MAC_REG_DMA_TRIGGER(0x1c3000 + 0xd30), AR_DMA_TRIGGER_RXQ0x100);
2298 (void)otus_write_barrier(sc);
2299
2300 ifp->if_flags |= IFF_RUNNING0x40;
2301 ifq_clr_oactive(&ifp->if_snd);
2302
2303 if (ic->ic_opmode == IEEE80211_M_MONITOR)
2304 ieee80211_new_state(ic, IEEE80211_S_RUN, -1)(((ic)->ic_newstate)((ic), (IEEE80211_S_RUN), (-1)));
2305 else
2306 ieee80211_new_state(ic, IEEE80211_S_SCAN, -1)(((ic)->ic_newstate)((ic), (IEEE80211_S_SCAN), (-1)));
2307
2308 return 0;
2309}
2310
2311void
2312otus_stop(struct ifnet *ifp)
2313{
2314 struct otus_softc *sc = ifp->if_softc;
2315 struct ieee80211com *ic = &sc->sc_ic;
2316 int s;
2317
2318 sc->sc_tx_timer = 0;
2319 ifp->if_timer = 0;
2320 ifp->if_flags &= ~IFF_RUNNING0x40;
2321 ifq_clr_oactive(&ifp->if_snd);
2322
2323 timeout_del(&sc->scan_to);
2324 timeout_del(&sc->calib_to);
2325
2326 s = splusb()splraise(0x5);
2327 ieee80211_new_state(ic, IEEE80211_S_INIT, -1)(((ic)->ic_newstate)((ic), (IEEE80211_S_INIT), (-1)));
2328 /* Wait for all queued asynchronous commands to complete. */
2329 usb_wait_task(sc->sc_udev, &sc->sc_task);
2330 splx(s)spllower(s);
2331
2332 /* Stop Rx. */
2333 otus_write(sc, AR_MAC_REG_DMA_TRIGGER(0x1c3000 + 0xd30), 0);
2334 (void)otus_write_barrier(sc);
2335
2336 sc->tx_queued = 0;
2337}