Bug Summary

File:dev/usb/if_otus.c
Warning:line 887, column 9
Result of 'malloc' is converted to a pointer of type 'struct ieee80211_node', which is incompatible with sizeof operand type 'struct otus_node'

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple amd64-unknown-openbsd7.4 -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name if_otus.c -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model static -mframe-pointer=all -relaxed-aliasing -ffp-contract=on -fno-rounding-math -mconstructor-aliases -ffreestanding -mcmodel=kernel -target-cpu x86-64 -target-feature +retpoline-indirect-calls -target-feature +retpoline-indirect-branches -target-feature -sse2 -target-feature -sse -target-feature -3dnow -target-feature -mmx -target-feature +save-args -target-feature +retpoline-external-thunk -disable-red-zone -no-implicit-float -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/usr/src/sys/arch/amd64/compile/GENERIC.MP/obj -nostdsysteminc -nobuiltininc -resource-dir /usr/local/llvm16/lib/clang/16 -I /usr/src/sys -I /usr/src/sys/arch/amd64/compile/GENERIC.MP/obj -I /usr/src/sys/arch -I /usr/src/sys/dev/pci/drm/include -I /usr/src/sys/dev/pci/drm/include/uapi -I /usr/src/sys/dev/pci/drm/amd/include/asic_reg -I /usr/src/sys/dev/pci/drm/amd/include -I /usr/src/sys/dev/pci/drm/amd/amdgpu -I /usr/src/sys/dev/pci/drm/amd/display -I /usr/src/sys/dev/pci/drm/amd/display/include -I /usr/src/sys/dev/pci/drm/amd/display/dc -I /usr/src/sys/dev/pci/drm/amd/display/amdgpu_dm -I /usr/src/sys/dev/pci/drm/amd/pm/inc -I /usr/src/sys/dev/pci/drm/amd/pm/legacy-dpm -I /usr/src/sys/dev/pci/drm/amd/pm/swsmu -I /usr/src/sys/dev/pci/drm/amd/pm/swsmu/inc -I /usr/src/sys/dev/pci/drm/amd/pm/swsmu/smu11 -I /usr/src/sys/dev/pci/drm/amd/pm/swsmu/smu12 -I /usr/src/sys/dev/pci/drm/amd/pm/swsmu/smu13 -I /usr/src/sys/dev/pci/drm/amd/pm/powerplay/inc -I /usr/src/sys/dev/pci/drm/amd/pm/powerplay/hwmgr -I /usr/src/sys/dev/pci/drm/amd/pm/powerplay/smumgr -I /usr/src/sys/dev/pci/drm/amd/pm/swsmu/inc -I /usr/src/sys/dev/pci/drm/amd/pm/swsmu/inc/pmfw_if -I /usr/src/sys/dev/pci/drm/amd/display/dc/inc -I /usr/src/sys/dev/pci/drm/amd/display/dc/inc/hw -I /usr/src/sys/dev/pci/drm/amd/display/dc/clk_mgr -I /usr/src/sys/dev/pci/drm/amd/display/modules/inc -I /usr/src/sys/dev/pci/drm/amd/display/modules/hdcp -I /usr/src/sys/dev/pci/drm/amd/display/dmub/inc -I /usr/src/sys/dev/pci/drm/i915 -D DDB -D DIAGNOSTIC -D KTRACE -D ACCOUNTING -D KMEMSTATS -D PTRACE -D POOL_DEBUG -D CRYPTO -D SYSVMSG -D SYSVSEM -D SYSVSHM -D UVM_SWAP_ENCRYPT -D FFS -D FFS2 -D FFS_SOFTUPDATES -D UFS_DIRHASH -D QUOTA -D EXT2FS -D MFS -D NFSCLIENT -D NFSSERVER -D CD9660 -D UDF -D MSDOSFS -D FIFO -D FUSE -D SOCKET_SPLICE -D TCP_ECN -D TCP_SIGNATURE -D INET6 -D IPSEC -D PPP_BSDCOMP -D PPP_DEFLATE -D PIPEX -D MROUTING -D MPLS -D BOOT_CONFIG -D USER_PCICONF -D APERTURE -D MTRR -D NTFS -D SUSPEND -D HIBERNATE -D PCIVERBOSE -D USBVERBOSE -D WSDISPLAY_COMPAT_USL -D WSDISPLAY_COMPAT_RAWKBD -D WSDISPLAY_DEFAULTSCREENS=6 -D X86EMU -D ONEWIREVERBOSE -D MULTIPROCESSOR -D MAXUSERS=80 -D _KERNEL -O2 -Wno-pointer-sign -Wno-address-of-packed-member -Wno-constant-conversion -Wno-unused-but-set-variable -Wno-gnu-folding-constant -fdebug-compilation-dir=/usr/src/sys/arch/amd64/compile/GENERIC.MP/obj -ferror-limit 19 -fwrapv -D_RET_PROTECTOR -ret-protector -fcf-protection=branch -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -fno-builtin-malloc -fno-builtin-calloc -fno-builtin-realloc -fno-builtin-valloc -fno-builtin-free -fno-builtin-strdup -fno-builtin-strndup -analyzer-output=html -faddrsig -o /home/ben/Projects/scan/2024-01-11-110808-61670-1 -x c /usr/src/sys/dev/usb/if_otus.c
1/* $OpenBSD: if_otus.c,v 1.72 2023/03/08 04:43:08 guenther 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(0x2);
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(0x2);
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(0x2);
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(0x2);
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(0x4);
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(0x2);
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);
Result of 'malloc' is converted to a pointer of type 'struct ieee80211_node', which is incompatible with sizeof operand type 'struct otus_node'
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
966void
967otus_intr(struct usbd_xfer *xfer, void *priv, usbd_status status)
968{
969#if 0
970 struct otus_softc *sc = priv;
971 int len;
972
973 /*
974 * The Rx intr pipe is unused with current firmware. Notifications
975 * and replies to commands are sent through the Rx bulk pipe instead
976 * (with a magic PLCP header.)
977 */
978 if (__predict_false(status != USBD_NORMAL_COMPLETION)__builtin_expect(((status != USBD_NORMAL_COMPLETION) != 0), 0
)
) {
979 DPRINTF(("intr status=%d\n", status));
980 if (status == USBD_STALLED)
981 usbd_clear_endpoint_stall_async(sc->cmd_rx_pipe);
982 return;
983 }
984 usbd_get_xfer_status(xfer, NULL((void *)0), NULL((void *)0), &len, NULL((void *)0));
985
986 otus_cmd_rxeof(sc, sc->ibuf, len);
987#endif
988}
989
990void
991otus_cmd_rxeof(struct otus_softc *sc, uint8_t *buf, int len)
992{
993 struct ieee80211com *ic = &sc->sc_ic;
994 struct otus_tx_cmd *cmd;
995 struct ar_cmd_hdr *hdr;
996 int s;
997
998 if (__predict_false(len < sizeof (*hdr))__builtin_expect(((len < sizeof (*hdr)) != 0), 0)) {
999 DPRINTF(("cmd too small %d\n", len));
1000 return;
1001 }
1002 hdr = (struct ar_cmd_hdr *)buf;
1003 if (__predict_false(sizeof (*hdr) + hdr->len > len ||__builtin_expect(((sizeof (*hdr) + hdr->len > len || sizeof
(*hdr) + hdr->len > 64) != 0), 0)
1004 sizeof (*hdr) + hdr->len > 64)__builtin_expect(((sizeof (*hdr) + hdr->len > len || sizeof
(*hdr) + hdr->len > 64) != 0), 0)
) {
1005 DPRINTF(("cmd too large %d\n", hdr->len));
1006 return;
1007 }
1008
1009 if ((hdr->code & 0xc0) != 0xc0) {
1010 DPRINTFN(2, ("received reply code=0x%02x len=%d token=%d\n",
1011 hdr->code, hdr->len, hdr->token));
1012 cmd = &sc->tx_cmd;
1013 if (__predict_false(hdr->token != cmd->token)__builtin_expect(((hdr->token != cmd->token) != 0), 0))
1014 return;
1015 /* Copy answer into caller's supplied buffer. */
1016 if (cmd->odata != NULL((void *)0))
1017 memcpy(cmd->odata, &hdr[1], hdr->len)__builtin_memcpy((cmd->odata), (&hdr[1]), (hdr->len
))
;
1018 cmd->done = 1;
1019 wakeup(cmd);
1020 return;
1021 }
1022
1023 /* Received unsolicited notification. */
1024 DPRINTF(("received notification code=0x%02x len=%d\n",
1025 hdr->code, hdr->len));
1026 switch (hdr->code & 0x3f) {
1027 case AR_EVT_BEACON0x00:
1028 break;
1029 case AR_EVT_TX_COMP0x01:
1030 {
1031 struct ar_evt_tx_comp *tx = (struct ar_evt_tx_comp *)&hdr[1];
1032 struct ieee80211_node *ni;
1033 struct otus_node *on;
1034
1035 DPRINTF(("tx completed %s status=%d phy=0x%x\n",
1036 ether_sprintf(tx->macaddr), letoh16(tx->status),
1037 letoh32(tx->phy)));
1038 s = splnet()splraise(0x4);
1039#ifdef notyet
1040#ifndef IEEE80211_STA_ONLY
1041 if (ic->ic_opmode != IEEE80211_M_STA) {
1042 ni = ieee80211_find_node(ic, tx->macaddr);
1043 if (__predict_false(ni == NULL)__builtin_expect(((ni == ((void *)0)) != 0), 0)) {
1044 splx(s)spllower(s);
1045 break;
1046 }
1047 } else
1048#endif
1049#endif
1050 ni = ic->ic_bss;
1051 /* Update rate control statistics. */
1052 on = (void *)ni;
1053 /* NB: we do not set the TX_MAC_RATE_PROBING flag. */
1054 if (__predict_true(tx->status != 0)__builtin_expect(((tx->status != 0) != 0), 1))
1055 on->amn.amn_retrycnt++;
1056 splx(s)spllower(s);
1057 break;
1058 }
1059 case AR_EVT_TBTT0x02:
1060 break;
1061 }
1062}
1063
1064void
1065otus_sub_rxeof(struct otus_softc *sc, uint8_t *buf, int len,
1066 struct mbuf_list *ml)
1067{
1068 struct ieee80211com *ic = &sc->sc_ic;
1069 struct ifnet *ifp = &ic->ic_ific_ac.ac_if;
1070 struct ieee80211_rxinfo rxi;
1071 struct ieee80211_node *ni;
1072 struct ar_rx_tail *tail;
1073 struct ieee80211_frame *wh;
1074 struct mbuf *m;
1075 uint8_t *plcp;
1076 int s, mlen, align;
1077
1078 if (__predict_false(len < AR_PLCP_HDR_LEN)__builtin_expect(((len < 12) != 0), 0)) {
1079 DPRINTF(("sub-xfer too short %d\n", len));
1080 return;
1081 }
1082 plcp = buf;
1083
1084 /* All bits in the PLCP header are set to 1 for non-MPDU. */
1085 if (memcmp(plcp, AR_PLCP_HDR_INTR, AR_PLCP_HDR_LEN)__builtin_memcmp((plcp), (AR_PLCP_HDR_INTR), (12)) == 0) {
1086 otus_cmd_rxeof(sc, plcp + AR_PLCP_HDR_LEN12,
1087 len - AR_PLCP_HDR_LEN12);
1088 return;
1089 }
1090
1091 /* Received MPDU. */
1092 if (__predict_false(len < AR_PLCP_HDR_LEN + sizeof (*tail))__builtin_expect(((len < 12 + sizeof (*tail)) != 0), 0)) {
1093 DPRINTF(("MPDU too short %d\n", len));
1094 ifp->if_ierrorsif_data.ifi_ierrors++;
1095 return;
1096 }
1097 tail = (struct ar_rx_tail *)(plcp + len - sizeof (*tail));
1098
1099 /* Discard error frames. */
1100 if (__predict_false(tail->error != 0)__builtin_expect(((tail->error != 0) != 0), 0)) {
1101 DPRINTF(("error frame 0x%02x\n", tail->error));
1102 if (tail->error & AR_RX_ERROR_FCS(1 << 3)) {
1103 DPRINTFN(3, ("bad FCS\n"));
1104 } else if (tail->error & AR_RX_ERROR_MMIC(1 << 6)) {
1105 /* Report Michael MIC failures to net80211. */
1106 ic->ic_stats.is_rx_locmicfail++;
1107 ieee80211_michael_mic_failure(ic, 0);
1108 }
1109 ifp->if_ierrorsif_data.ifi_ierrors++;
1110 return;
1111 }
1112 /* Compute MPDU's length. */
1113 mlen = len - AR_PLCP_HDR_LEN12 - sizeof (*tail);
1114 /* Make sure there's room for an 802.11 header + FCS. */
1115 if (__predict_false(mlen < IEEE80211_MIN_LEN)__builtin_expect(((mlen < (sizeof(struct ieee80211_frame_min
) + 4)) != 0), 0)
) {
1116 ifp->if_ierrorsif_data.ifi_ierrors++;
1117 return;
1118 }
1119 mlen -= IEEE80211_CRC_LEN4; /* strip 802.11 FCS */
1120 if (mlen > MCLBYTES(1 << 11)) {
1121 DPRINTF(("frame too large: %d\n", mlen));
1122 ifp->if_ierrorsif_data.ifi_ierrors++;
1123 return;
1124 }
1125
1126 wh = (struct ieee80211_frame *)(plcp + AR_PLCP_HDR_LEN12);
1127 /* Provide a 32-bit aligned protocol header to the stack. */
1128 align = (ieee80211_has_qos(wh) ^ ieee80211_has_addr4(wh)) ? 2 : 0;
1129
1130 MGETHDR(m, M_DONTWAIT, MT_DATA)m = m_gethdr((0x0002), (1));
1131 if (__predict_false(m == NULL)__builtin_expect(((m == ((void *)0)) != 0), 0)) {
1132 ifp->if_ierrorsif_data.ifi_ierrors++;
1133 return;
1134 }
1135 if (align + mlen > MHLEN((256 - sizeof(struct m_hdr)) - sizeof(struct pkthdr))) {
1136 MCLGET(m, M_DONTWAIT)(void) m_clget((m), (0x0002), (1 << 11));
1137 if (__predict_false(!(m->m_flags & M_EXT))__builtin_expect(((!(m->m_hdr.mh_flags & 0x0001)) != 0
), 0)
) {
1138 ifp->if_ierrorsif_data.ifi_ierrors++;
1139 m_freem(m);
1140 return;
1141 }
1142 }
1143 /* Finalize mbuf. */
1144 m->m_datam_hdr.mh_data += align;
1145 memcpy(mtod(m, caddr_t), wh, mlen)__builtin_memcpy((((caddr_t)((m)->m_hdr.mh_data))), (wh), (
mlen))
;
1146 m->m_pkthdrM_dat.MH.MH_pkthdr.len = m->m_lenm_hdr.mh_len = mlen;
1147
1148#if NBPFILTER1 > 0
1149 if (__predict_false(sc->sc_drvbpf != NULL)__builtin_expect(((sc->sc_drvbpf != ((void *)0)) != 0), 0)) {
1150 struct otus_rx_radiotap_header *tap = &sc->sc_rxtapsc_rxtapu.th;
1151 struct mbuf mb;
1152
1153 tap->wr_flags = 0;
1154 tap->wr_chan_freq = htole16(ic->ic_ibss_chan->ic_freq)((__uint16_t)(ic->ic_ibss_chan->ic_freq));
1155 tap->wr_chan_flags = htole16(ic->ic_ibss_chan->ic_flags)((__uint16_t)(ic->ic_ibss_chan->ic_flags));
1156 tap->wr_antsignal = tail->rssi;
1157 tap->wr_rate = 2; /* In case it can't be found below. */
1158 switch (tail->status & AR_RX_STATUS_MT_MASK0x3) {
1159 case AR_RX_STATUS_MT_CCK0:
1160 switch (plcp[0]) {
1161 case 10: tap->wr_rate = 2; break;
1162 case 20: tap->wr_rate = 4; break;
1163 case 55: tap->wr_rate = 11; break;
1164 case 110: tap->wr_rate = 22; break;
1165 }
1166 if (tail->status & AR_RX_STATUS_SHPREAMBLE(1 << 3))
1167 tap->wr_flags |= IEEE80211_RADIOTAP_F_SHORTPRE0x02;
1168 break;
1169 case AR_RX_STATUS_MT_OFDM1:
1170 switch (plcp[0] & 0xf) {
1171 case 0xb: tap->wr_rate = 12; break;
1172 case 0xf: tap->wr_rate = 18; break;
1173 case 0xa: tap->wr_rate = 24; break;
1174 case 0xe: tap->wr_rate = 36; break;
1175 case 0x9: tap->wr_rate = 48; break;
1176 case 0xd: tap->wr_rate = 72; break;
1177 case 0x8: tap->wr_rate = 96; break;
1178 case 0xc: tap->wr_rate = 108; break;
1179 }
1180 break;
1181 }
1182 mb.m_datam_hdr.mh_data = (caddr_t)tap;
1183 mb.m_lenm_hdr.mh_len = sc->sc_rxtap_len;
1184 mb.m_nextm_hdr.mh_next = m;
1185 mb.m_nextpktm_hdr.mh_nextpkt = NULL((void *)0);
1186 mb.m_typem_hdr.mh_type = 0;
1187 mb.m_flagsm_hdr.mh_flags = 0;
1188 bpf_mtap(sc->sc_drvbpf, &mb, BPF_DIRECTION_IN(1 << 0));
1189 }
1190#endif
1191
1192 s = splnet()splraise(0x4);
1193 ni = ieee80211_find_rxnode(ic, wh);
1194 memset(&rxi, 0, sizeof(rxi))__builtin_memset((&rxi), (0), (sizeof(rxi)));
1195 rxi.rxi_rssi = tail->rssi;
1196 ieee80211_inputm(ifp, m, ni, &rxi, ml);
1197
1198 /* Node is no longer needed. */
1199 ieee80211_release_node(ic, ni);
1200 splx(s)spllower(s);
1201}
1202
1203void
1204otus_rxeof(struct usbd_xfer *xfer, void *priv, usbd_status status)
1205{
1206 struct mbuf_list ml = MBUF_LIST_INITIALIZER(){ ((void *)0), ((void *)0), 0 };
1207 struct otus_rx_data *data = priv;
1208 struct otus_softc *sc = data->sc;
1209 caddr_t buf = data->buf;
1210 struct ar_rx_head *head;
1211 uint16_t hlen;
1212 int len;
1213
1214 if (__predict_false(status != USBD_NORMAL_COMPLETION)__builtin_expect(((status != USBD_NORMAL_COMPLETION) != 0), 0
)
) {
1215 DPRINTF(("RX status=%d\n", status));
1216 if (status == USBD_STALLED)
1217 usbd_clear_endpoint_stall_async(sc->data_rx_pipe);
1218 if (status != USBD_CANCELLED)
1219 goto resubmit;
1220 return;
1221 }
1222 usbd_get_xfer_status(xfer, NULL((void *)0), NULL((void *)0), &len, NULL((void *)0));
1223
1224 while (len >= sizeof (*head)) {
1225 head = (struct ar_rx_head *)buf;
1226 if (__predict_false(head->tag != htole16(AR_RX_HEAD_TAG))__builtin_expect(((head->tag != ((__uint16_t)(0x4e00))) !=
0), 0)
) {
1227 DPRINTF(("tag not valid 0x%x\n", letoh16(head->tag)));
1228 break;
1229 }
1230 hlen = letoh16(head->len)((__uint16_t)(head->len));
1231 if (__predict_false(sizeof (*head) + hlen > len)__builtin_expect(((sizeof (*head) + hlen > len) != 0), 0)) {
1232 DPRINTF(("xfer too short %d/%d\n", len, hlen));
1233 break;
1234 }
1235 /* Process sub-xfer. */
1236 otus_sub_rxeof(sc, (uint8_t *)&head[1], hlen, &ml);
1237
1238 /* Next sub-xfer is aligned on a 32-bit boundary. */
1239 hlen = (sizeof (*head) + hlen + 3) & ~3;
1240 buf += hlen;
1241 len -= hlen;
1242 }
1243 if_input(&sc->sc_ic.ic_ific_ac.ac_if, &ml);
1244
1245 resubmit:
1246 usbd_setup_xfer(xfer, sc->data_rx_pipe, data, data->buf, OTUS_RXBUFSZ(8 * 1024),
1247 USBD_SHORT_XFER_OK0x04, USBD_NO_TIMEOUT0, otus_rxeof);
1248 (void)usbd_transfer(data->xfer);
1249}
1250
1251void
1252otus_txeof(struct usbd_xfer *xfer, void *priv, usbd_status status)
1253{
1254 struct otus_tx_data *data = priv;
1255 struct otus_softc *sc = data->sc;
1256 struct ieee80211com *ic = &sc->sc_ic;
1257 struct ifnet *ifp = &ic->ic_ific_ac.ac_if;
1258 int s;
1259
1260 s = splnet()splraise(0x4);
1261 sc->tx_queued--;
1262 if (__predict_false(status != USBD_NORMAL_COMPLETION)__builtin_expect(((status != USBD_NORMAL_COMPLETION) != 0), 0
)
) {
1263 DPRINTF(("TX status=%d\n", status));
1264 if (status == USBD_STALLED)
1265 usbd_clear_endpoint_stall_async(sc->data_tx_pipe);
1266 ifp->if_oerrorsif_data.ifi_oerrors++;
1267 splx(s)spllower(s);
1268 return;
1269 }
1270 sc->sc_tx_timer = 0;
1271 ifq_clr_oactive(&ifp->if_snd);
1272 otus_start(ifp);
1273 splx(s)spllower(s);
1274}
1275
1276int
1277otus_tx(struct otus_softc *sc, struct mbuf *m, struct ieee80211_node *ni)
1278{
1279 struct ieee80211com *ic = &sc->sc_ic;
1280 struct otus_node *on = (void *)ni;
1281 struct otus_tx_data *data;
1282 struct ieee80211_frame *wh;
1283 struct ieee80211_key *k;
1284 struct ar_tx_head *head;
1285 uint32_t phyctl;
1286 uint16_t macctl, qos;
1287 uint8_t tid, qid;
1288 int error, ridx, hasqos, xferlen;
1289
1290 wh = mtod(m, struct ieee80211_frame *)((struct ieee80211_frame *)((m)->m_hdr.mh_data));
1291 if (wh->i_fc[1] & IEEE80211_FC1_PROTECTED0x40) {
1292 k = ieee80211_get_txkey(ic, wh, ni);
1293 if ((m = ieee80211_encrypt(ic, m, k)) == NULL((void *)0))
1294 return ENOBUFS55;
1295 wh = mtod(m, struct ieee80211_frame *)((struct ieee80211_frame *)((m)->m_hdr.mh_data));
1296 }
1297
1298 if ((hasqos = ieee80211_has_qos(wh))) {
1299 qos = ieee80211_get_qos(wh);
1300 tid = qos & IEEE80211_QOS_TID0x000f;
1301 qid = ieee80211_up_to_ac(ic, tid);
1302 } else {
1303 qos = 0;
1304 qid = EDCA_AC_BE;
1305 }
1306
1307 /* Pickup a rate index. */
1308 if (IEEE80211_IS_MULTICAST(wh->i_addr1)(*(wh->i_addr1) & 0x01) ||
1309 (wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK0x0c) != IEEE80211_FC0_TYPE_DATA0x08)
1310 ridx = (ic->ic_curmode == IEEE80211_MODE_11A) ?
1311 OTUS_RIDX_OFDM64 : OTUS_RIDX_CCK10;
1312 else if (ic->ic_fixed_rate != -1)
1313 ridx = sc->fixed_ridx;
1314 else
1315 ridx = on->ridx[ni->ni_txrate];
1316
1317 phyctl = 0;
1318 macctl = AR_TX_MAC_BACKOFF(1 << 3) | AR_TX_MAC_HW_DUR(1 << 9) | AR_TX_MAC_QID(qid)((qid) << 10);
1319
1320 if (IEEE80211_IS_MULTICAST(wh->i_addr1)(*(wh->i_addr1) & 0x01) ||
1321 (hasqos && ((qos & IEEE80211_QOS_ACK_POLICY_MASK0x0060) ==
1322 IEEE80211_QOS_ACK_POLICY_NOACK0x0020)))
1323 macctl |= AR_TX_MAC_NOACK(1 << 2);
1324
1325 if (!IEEE80211_IS_MULTICAST(wh->i_addr1)(*(wh->i_addr1) & 0x01)) {
1326 if (m->m_pkthdrM_dat.MH.MH_pkthdr.len + IEEE80211_CRC_LEN4 >= ic->ic_rtsthreshold)
1327 macctl |= AR_TX_MAC_RTS(1 << 0);
1328 else if ((ic->ic_flags & IEEE80211_F_USEPROT0x00100000) &&
1329 ridx >= OTUS_RIDX_OFDM64) {
1330 if (ic->ic_protmode == IEEE80211_PROT_CTSONLY)
1331 macctl |= AR_TX_MAC_CTS(1 << 1);
1332 else if (ic->ic_protmode == IEEE80211_PROT_RTSCTS)
1333 macctl |= AR_TX_MAC_RTS(1 << 0);
1334 }
1335 }
1336
1337 phyctl |= AR_TX_PHY_MCS(otus_rates[ridx].mcs)((otus_rates[ridx].mcs) << 18);
1338 if (ridx >= OTUS_RIDX_OFDM64) {
1339 phyctl |= AR_TX_PHY_MT_OFDM1;
1340 if (ridx <= OTUS_RIDX_OFDM248)
1341 phyctl |= AR_TX_PHY_ANTMSK(sc->txmask)((sc->txmask) << 15);
1342 else
1343 phyctl |= AR_TX_PHY_ANTMSK(1)((1) << 15);
1344 } else { /* CCK */
1345 phyctl |= AR_TX_PHY_MT_CCK0;
1346 phyctl |= AR_TX_PHY_ANTMSK(sc->txmask)((sc->txmask) << 15);
1347 }
1348
1349 /* Update rate control stats for frames that are ACK'ed. */
1350 if (!(macctl & AR_TX_MAC_NOACK(1 << 2)))
1351 ((struct otus_node *)ni)->amn.amn_txcnt++;
1352
1353 data = &sc->tx_data[sc->tx_cur];
1354 /* Fill Tx descriptor. */
1355 head = (struct ar_tx_head *)data->buf;
1356 head->len = htole16(m->m_pkthdr.len + IEEE80211_CRC_LEN)((__uint16_t)(m->M_dat.MH.MH_pkthdr.len + 4));
1357 head->macctl = htole16(macctl)((__uint16_t)(macctl));
1358 head->phyctl = htole32(phyctl)((__uint32_t)(phyctl));
1359
1360#if NBPFILTER1 > 0
1361 if (__predict_false(sc->sc_drvbpf != NULL)__builtin_expect(((sc->sc_drvbpf != ((void *)0)) != 0), 0)) {
1362 struct otus_tx_radiotap_header *tap = &sc->sc_txtapsc_txtapu.th;
1363 struct mbuf mb;
1364
1365 tap->wt_flags = 0;
1366 tap->wt_rate = otus_rates[ridx].rate;
1367 tap->wt_chan_freq = htole16(ic->ic_bss->ni_chan->ic_freq)((__uint16_t)(ic->ic_bss->ni_chan->ic_freq));
1368 tap->wt_chan_flags = htole16(ic->ic_bss->ni_chan->ic_flags)((__uint16_t)(ic->ic_bss->ni_chan->ic_flags));
1369
1370 mb.m_datam_hdr.mh_data = (caddr_t)tap;
1371 mb.m_lenm_hdr.mh_len = sc->sc_txtap_len;
1372 mb.m_nextm_hdr.mh_next = m;
1373 mb.m_nextpktm_hdr.mh_nextpkt = NULL((void *)0);
1374 mb.m_typem_hdr.mh_type = 0;
1375 mb.m_flagsm_hdr.mh_flags = 0;
1376 bpf_mtap(sc->sc_drvbpf, &mb, BPF_DIRECTION_OUT(1 << 1));
1377 }
1378#endif
1379
1380 xferlen = sizeof (*head) + m->m_pkthdrM_dat.MH.MH_pkthdr.len;
1381 m_copydata(m, 0, m->m_pkthdrM_dat.MH.MH_pkthdr.len, &head[1]);
1382 m_freem(m);
1383
1384 DPRINTFN(5, ("tx queued=%d len=%d mac=0x%04x phy=0x%08x rate=%d\n",
1385 sc->tx_queued, head->len, head->macctl, head->phyctl,
1386 otus_rates[ridx].rate));
1387 usbd_setup_xfer(data->xfer, sc->data_tx_pipe, data, data->buf, xferlen,
1388 USBD_FORCE_SHORT_XFER0x08 | USBD_NO_COPY0x01, OTUS_TX_TIMEOUT1000, otus_txeof);
1389 error = usbd_transfer(data->xfer);
1390 if (__predict_false(error != USBD_IN_PROGRESS && error != 0)__builtin_expect(((error != USBD_IN_PROGRESS && error
!= 0) != 0), 0)
)
1391 return error;
1392
1393 ieee80211_release_node(ic, ni);
1394
1395 sc->tx_queued++;
1396 sc->tx_cur = (sc->tx_cur + 1) % OTUS_TX_DATA_LIST_COUNT8;
1397
1398 return 0;
1399}
1400
1401void
1402otus_start(struct ifnet *ifp)
1403{
1404 struct otus_softc *sc = ifp->if_softc;
1405 struct ieee80211com *ic = &sc->sc_ic;
1406 struct ieee80211_node *ni;
1407 struct mbuf *m;
1408
1409 if (!(ifp->if_flags & IFF_RUNNING0x40) || ifq_is_oactive(&ifp->if_snd))
1410 return;
1411
1412 for (;;) {
1413 if (sc->tx_queued >= OTUS_TX_DATA_LIST_COUNT8) {
1414 ifq_set_oactive(&ifp->if_snd);
1415 break;
1416 }
1417 /* Send pending management frames first. */
1418 m = mq_dequeue(&ic->ic_mgtq);
1419 if (m != NULL((void *)0)) {
1420 ni = m->m_pkthdrM_dat.MH.MH_pkthdr.ph_cookie;
1421 goto sendit;
1422 }
1423 if (ic->ic_state != IEEE80211_S_RUN)
1424 break;
1425
1426 /* Encapsulate and send data frames. */
1427 m = ifq_dequeue(&ifp->if_snd);
1428 if (m == NULL((void *)0))
1429 break;
1430#if NBPFILTER1 > 0
1431 if (ifp->if_bpf != NULL((void *)0))
1432 bpf_mtap(ifp->if_bpf, m, BPF_DIRECTION_OUT(1 << 1));
1433#endif
1434 if ((m = ieee80211_encap(ifp, m, &ni)) == NULL((void *)0))
1435 continue;
1436sendit:
1437#if NBPFILTER1 > 0
1438 if (ic->ic_rawbpf != NULL((void *)0))
1439 bpf_mtap(ic->ic_rawbpf, m, BPF_DIRECTION_OUT(1 << 1));
1440#endif
1441 if (otus_tx(sc, m, ni) != 0) {
1442 ieee80211_release_node(ic, ni);
1443 ifp->if_oerrorsif_data.ifi_oerrors++;
1444 continue;
1445 }
1446
1447 sc->sc_tx_timer = 5;
1448 ifp->if_timer = 1;
1449 }
1450}
1451
1452void
1453otus_watchdog(struct ifnet *ifp)
1454{
1455 struct otus_softc *sc = ifp->if_softc;
1456
1457 ifp->if_timer = 0;
1458
1459 if (sc->sc_tx_timer > 0) {
1460 if (--sc->sc_tx_timer == 0) {
1461 printf("%s: device timeout\n", sc->sc_dev.dv_xname);
1462 /* otus_init(ifp); XXX needs a process context! */
1463 ifp->if_oerrorsif_data.ifi_oerrors++;
1464 return;
1465 }
1466 ifp->if_timer = 1;
1467 }
1468 ieee80211_watchdog(ifp);
1469}
1470
1471int
1472otus_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
1473{
1474 struct otus_softc *sc = ifp->if_softc;
1475 struct ieee80211com *ic = &sc->sc_ic;
1476 int s, error = 0;
1477
1478 if (usbd_is_dying(sc->sc_udev))
1479 return ENXIO6;
1480
1481 usbd_ref_incr(sc->sc_udev);
1482
1483 s = splnet()splraise(0x4);
1484
1485 switch (cmd) {
1486 case SIOCSIFADDR((unsigned long)0x80000000 | ((sizeof(struct ifreq) & 0x1fff
) << 16) | ((('i')) << 8) | ((12)))
:
1487 ifp->if_flags |= IFF_UP0x1;
1488 /* FALLTHROUGH */
1489 case SIOCSIFFLAGS((unsigned long)0x80000000 | ((sizeof(struct ifreq) & 0x1fff
) << 16) | ((('i')) << 8) | ((16)))
:
1490 if (ifp->if_flags & IFF_UP0x1) {
1491 if ((ifp->if_flags & IFF_RUNNING0x40) &&
1492 ((ifp->if_flags ^ sc->sc_if_flags) &
1493 (IFF_ALLMULTI0x200 | IFF_PROMISC0x100)) != 0) {
1494 otus_set_multi(sc);
1495 } else if (!(ifp->if_flags & IFF_RUNNING0x40))
1496 otus_init(ifp);
1497
1498 } else if (ifp->if_flags & IFF_RUNNING0x40)
1499 otus_stop(ifp);
1500
1501 sc->sc_if_flags = ifp->if_flags;
1502 break;
1503 case SIOCS80211CHANNEL((unsigned long)0x80000000 | ((sizeof(struct ieee80211chanreq
) & 0x1fff) << 16) | ((('i')) << 8) | ((238))
)
:
1504 error = ieee80211_ioctl(ifp, cmd, data);
1505 if (error == ENETRESET52 &&
1506 ic->ic_opmode == IEEE80211_M_MONITOR) {
1507 if ((ifp->if_flags & (IFF_UP0x1 | IFF_RUNNING0x40)) ==
1508 (IFF_UP0x1 | IFF_RUNNING0x40))
1509 otus_set_chan(sc, ic->ic_ibss_chan, 0);
1510 error = 0;
1511 }
1512 break;
1513 default:
1514 error = ieee80211_ioctl(ifp, cmd, data);
1515 }
1516
1517 if (error == ENETRESET52) {
1518 if ((ifp->if_flags & (IFF_UP0x1 | IFF_RUNNING0x40)) ==
1519 (IFF_UP0x1 | IFF_RUNNING0x40))
1520 otus_init(ifp);
1521 error = 0;
1522 }
1523
1524 splx(s)spllower(s);
1525
1526 usbd_ref_decr(sc->sc_udev);
1527
1528 return error;
1529}
1530
1531int
1532otus_set_multi(struct otus_softc *sc)
1533{
1534 struct arpcom *ac = &sc->sc_ic.ic_ac;
1535 struct ifnet *ifp = &ac->ac_if;
1536 struct ether_multi *enm;
1537 struct ether_multistep step;
1538 uint32_t lo, hi;
1539 uint8_t bit;
1540
1541 if (ac->ac_multirangecnt > 0)
1542 ifp->if_flags |= IFF_ALLMULTI0x200;
1543
1544 if ((ifp->if_flags & (IFF_ALLMULTI0x200 | IFF_PROMISC0x100)) != 0) {
1545 lo = hi = 0xffffffff;
1546 goto done;
1547 }
1548 lo = hi = 0;
1549 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)
;
1550 while (enm != NULL((void *)0)) {
1551 bit = enm->enm_addrlo[5] >> 2;
1552 if (bit < 32)
1553 lo |= 1 << bit;
1554 else
1555 hi |= 1 << (bit - 32);
1556 ETHER_NEXT_MULTI(step, enm)do { if (((enm) = (step).e_enm) != ((void *)0)) (step).e_enm =
(((enm))->enm_list.le_next); } while ( 0)
;
1557 }
1558 done:
1559 hi |= 1U << 31; /* Make sure the broadcast bit is set. */
1560 otus_write(sc, AR_MAC_REG_GROUP_HASH_TBL_L(0x1c3000 + 0x624), lo);
1561 otus_write(sc, AR_MAC_REG_GROUP_HASH_TBL_H(0x1c3000 + 0x628), hi);
1562 return otus_write_barrier(sc);
1563}
1564
1565void
1566otus_updateedca(struct ieee80211com *ic)
1567{
1568 /* Do it in a process context. */
1569 otus_do_async(ic->ic_softcic_ac.ac_if.if_softc, otus_updateedca_cb, NULL((void *)0), 0);
1570}
1571
1572void
1573otus_updateedca_cb(struct otus_softc *sc, void *arg)
1574{
1575#define EXP2(val) ((1 << (val)) - 1)
1576#define AIFS(val) ((val) * 9 + 10)
1577 struct ieee80211com *ic = &sc->sc_ic;
1578 const struct ieee80211_edca_ac_params *edca;
1579 int s;
1580
1581 s = splnet()splraise(0x4);
1582
1583 edca = (ic->ic_flags & IEEE80211_F_QOS0x00080000) ?
1584 ic->ic_edca_ac : otus_edca_def;
1585
1586 /* Set CWmin/CWmax values. */
1587 otus_write(sc, AR_MAC_REG_AC0_CW(0x1c3000 + 0xb00),
1588 EXP2(edca[EDCA_AC_BE].ac_ecwmax) << 16 |
1589 EXP2(edca[EDCA_AC_BE].ac_ecwmin));
1590 otus_write(sc, AR_MAC_REG_AC1_CW(0x1c3000 + 0xb04),
1591 EXP2(edca[EDCA_AC_BK].ac_ecwmax) << 16 |
1592 EXP2(edca[EDCA_AC_BK].ac_ecwmin));
1593 otus_write(sc, AR_MAC_REG_AC2_CW(0x1c3000 + 0xb08),
1594 EXP2(edca[EDCA_AC_VI].ac_ecwmax) << 16 |
1595 EXP2(edca[EDCA_AC_VI].ac_ecwmin));
1596 otus_write(sc, AR_MAC_REG_AC3_CW(0x1c3000 + 0xb0c),
1597 EXP2(edca[EDCA_AC_VO].ac_ecwmax) << 16 |
1598 EXP2(edca[EDCA_AC_VO].ac_ecwmin));
1599 otus_write(sc, AR_MAC_REG_AC4_CW(0x1c3000 + 0xb10), /* Special TXQ. */
1600 EXP2(edca[EDCA_AC_VO].ac_ecwmax) << 16 |
1601 EXP2(edca[EDCA_AC_VO].ac_ecwmin));
1602
1603 /* Set AIFSN values. */
1604 otus_write(sc, AR_MAC_REG_AC1_AC0_AIFS(0x1c3000 + 0xb14),
1605 AIFS(edca[EDCA_AC_VI].ac_aifsn) << 24 |
1606 AIFS(edca[EDCA_AC_BK].ac_aifsn) << 12 |
1607 AIFS(edca[EDCA_AC_BE].ac_aifsn));
1608 otus_write(sc, AR_MAC_REG_AC3_AC2_AIFS(0x1c3000 + 0xb18),
1609 AIFS(edca[EDCA_AC_VO].ac_aifsn) << 16 | /* Special TXQ. */
1610 AIFS(edca[EDCA_AC_VO].ac_aifsn) << 4 |
1611 AIFS(edca[EDCA_AC_VI].ac_aifsn) >> 8);
1612
1613 /* Set TXOP limit. */
1614 otus_write(sc, AR_MAC_REG_AC1_AC0_TXOP(0x1c3000 + 0xb44),
1615 edca[EDCA_AC_BK].ac_txoplimit << 16 |
1616 edca[EDCA_AC_BE].ac_txoplimit);
1617 otus_write(sc, AR_MAC_REG_AC3_AC2_TXOP(0x1c3000 + 0xb48),
1618 edca[EDCA_AC_VO].ac_txoplimit << 16 |
1619 edca[EDCA_AC_VI].ac_txoplimit);
1620
1621 splx(s)spllower(s);
1622
1623 (void)otus_write_barrier(sc);
1624#undef AIFS
1625#undef EXP2
1626}
1627
1628void
1629otus_updateslot(struct ieee80211com *ic)
1630{
1631 /* Do it in a process context. */
1632 otus_do_async(ic->ic_softcic_ac.ac_if.if_softc, otus_updateslot_cb, NULL((void *)0), 0);
1633}
1634
1635void
1636otus_updateslot_cb(struct otus_softc *sc, void *arg)
1637{
1638 uint32_t slottime;
1639
1640 slottime = (sc->sc_ic.ic_flags & IEEE80211_F_SHSLOT0x00020000) ?
1641 IEEE80211_DUR_DS_SHSLOT9: IEEE80211_DUR_DS_SLOT20;
1642 otus_write(sc, AR_MAC_REG_SLOT_TIME(0x1c3000 + 0x6f0), slottime << 10);
1643 (void)otus_write_barrier(sc);
1644}
1645
1646int
1647otus_init_mac(struct otus_softc *sc)
1648{
1649 int error;
1650
1651 otus_write(sc, AR_MAC_REG_ACK_EXTENSION(0x1c3000 + 0x690), 0x40);
1652 otus_write(sc, AR_MAC_REG_RETRY_MAX(0x1c3000 + 0xb28), 0);
1653 otus_write(sc, AR_MAC_REG_SNIFFER(0x1c3000 + 0x674), 0x2000000);
1654 otus_write(sc, AR_MAC_REG_RX_THRESHOLD(0x1c3000 + 0x640), 0xc1f80);
1655 otus_write(sc, AR_MAC_REG_RX_PE_DELAY(0x1c3000 + 0x64c), 0x70);
1656 otus_write(sc, AR_MAC_REG_EIFS_AND_SIFS(0x1c3000 + 0x698), 0xa144000);
1657 otus_write(sc, AR_MAC_REG_SLOT_TIME(0x1c3000 + 0x6f0), 9 << 10);
1658 otus_write(sc, 0x1c3b2c, 0x19000000);
1659 /* NAV protects ACK only (in TXOP). */
1660 otus_write(sc, 0x1c3b38, 0x201);
1661 /* Set beacon Tx power to 0x7. */
1662 otus_write(sc, AR_MAC_REG_BCN_HT1(0x1c3000 + 0xda0), 0x8000170);
1663 otus_write(sc, AR_MAC_REG_BACKOFF_PROTECT(0x1c3000 + 0x63c), 0x105);
1664 otus_write(sc, 0x1c3b9c, 0x10000a);
1665 /* Filter any control frames, BAR is bit 24. */
1666 otus_write(sc, 0x1c368c, 0x0500ffff);
1667 otus_write(sc, 0x1c3c40, 0x1);
1668 otus_write(sc, AR_MAC_REG_BASIC_RATE(0x1c3000 + 0x630), 0x150f);
1669 otus_write(sc, AR_MAC_REG_MANDATORY_RATE(0x1c3000 + 0x634), 0x150f);
1670 otus_write(sc, AR_MAC_REG_RTS_CTS_RATE(0x1c3000 + 0x638), 0x10b01bb);
1671 otus_write(sc, 0x1c3694, 0x4003c1e);
1672 /* Enable LED0 and LED1. */
1673 otus_write(sc, 0x1d0100, 0x3);
1674 otus_write(sc, 0x1d0104, 0x3);
1675 /* Switch MAC to OTUS interface. */
1676 otus_write(sc, 0x1c3600, 0x3);
1677 otus_write(sc, 0x1c3c50, 0xffff);
1678 otus_write(sc, 0x1c3680, 0xf00008);
1679 /* Disable Rx timeout (workaround). */
1680 otus_write(sc, 0x1c362c, 0);
1681
1682 /* Set USB Rx stream mode maximum frame number to 2. */
1683 otus_write(sc, 0x1e1110, 0x4);
1684 /* Set USB Rx stream mode timeout to 10us. */
1685 otus_write(sc, 0x1e1114, 0x80);
1686
1687 /* Set clock frequency to 88/80MHz. */
1688 otus_write(sc, 0x1d4008, 0x73);
1689 /* Set WLAN DMA interrupt mode: generate intr per packet. */
1690 otus_write(sc, 0x1c3d7c, 0x110011);
1691 otus_write(sc, 0x1c3bb0, 0x4);
1692 otus_write(sc, AR_MAC_REG_TXOP_NOT_ENOUGH_INDICATION(0x1c3000 + 0xb30), 0x141e0f48);
1693
1694 /* Disable HW decryption for now. */
1695 otus_write(sc, 0x1c3678, 0x78);
1696
1697 if ((error = otus_write_barrier(sc)) != 0)
1698 return error;
1699
1700 /* Set default EDCA parameters. */
1701 otus_updateedca_cb(sc, NULL((void *)0));
1702
1703 return 0;
1704}
1705
1706/*
1707 * Return default value for PHY register based on current operating mode.
1708 */
1709uint32_t
1710otus_phy_get_def(struct otus_softc *sc, uint32_t reg)
1711{
1712 int i;
1713
1714 for (i = 0; i < nitems(ar5416_phy_regs)(sizeof((ar5416_phy_regs)) / sizeof((ar5416_phy_regs)[0])); i++)
1715 if (AR_PHY(ar5416_phy_regs[i])(0x1c5800 + (ar5416_phy_regs[i]) * 4) == reg)
1716 return sc->phy_vals[i];
1717 return 0; /* Register not found. */
1718}
1719
1720/*
1721 * Update PHY's programming based on vendor-specific data stored in EEPROM.
1722 * This is for FEM-type devices only.
1723 */
1724int
1725otus_set_board_values(struct otus_softc *sc, struct ieee80211_channel *c)
1726{
1727 const struct ModalEepHeader *eep;
1728 uint32_t tmp, offset;
1729
1730 if (IEEE80211_IS_CHAN_5GHZ(c)(((c)->ic_flags & 0x0100) != 0))
1731 eep = &sc->eeprom.modalHeader[0];
1732 else
1733 eep = &sc->eeprom.modalHeader[1];
1734
1735 /* Offset of chain 2. */
1736 offset = 2 * 0x1000;
1737
1738 tmp = letoh32(eep->antCtrlCommon)((__uint32_t)(eep->antCtrlCommon));
1739 otus_write(sc, AR_PHY_SWITCH_COM(0x1c5800 + 0x0164), tmp);
1740
1741 tmp = letoh32(eep->antCtrlChain[0])((__uint32_t)(eep->antCtrlChain[0]));
1742 otus_write(sc, AR_PHY_SWITCH_CHAIN_0(0x1c5800 + 0x0160), tmp);
1743
1744 tmp = letoh32(eep->antCtrlChain[1])((__uint32_t)(eep->antCtrlChain[1]));
1745 otus_write(sc, AR_PHY_SWITCH_CHAIN_0(0x1c5800 + 0x0160) + offset, tmp);
1746
1747 if (1 /* sc->sc_sco == AR_SCO_SCN */) {
1748 tmp = otus_phy_get_def(sc, AR_PHY_SETTLING(0x1c5800 + 0x0044));
1749 tmp &= ~(0x7f << 7);
1750 tmp |= (eep->switchSettling & 0x7f) << 7;
1751 otus_write(sc, AR_PHY_SETTLING(0x1c5800 + 0x0044), tmp);
1752 }
1753
1754 tmp = otus_phy_get_def(sc, AR_PHY_DESIRED_SZ(0x1c5800 + 0x0050));
1755 tmp &= ~0xffff;
1756 tmp |= eep->pgaDesiredSize << 8 | eep->adcDesiredSize;
1757 otus_write(sc, AR_PHY_DESIRED_SZ(0x1c5800 + 0x0050), tmp);
1758
1759 tmp = eep->txEndToXpaOff << 24 | eep->txEndToXpaOff << 16 |
1760 eep->txFrameToXpaOn << 8 | eep->txFrameToXpaOn;
1761 otus_write(sc, AR_PHY_RF_CTL4(0x1c5800 + 0x0034), tmp);
1762
1763 tmp = otus_phy_get_def(sc, AR_PHY_RF_CTL3(0x1c5800 + 0x0028));
1764 tmp &= ~(0xff << 16);
1765 tmp |= eep->txEndToRxOn << 16;
1766 otus_write(sc, AR_PHY_RF_CTL3(0x1c5800 + 0x0028), tmp);
1767
1768 tmp = otus_phy_get_def(sc, AR_PHY_CCA(0x1c5800 + 0x3064));
1769 tmp &= ~(0x7f << 12);
1770 tmp |= (eep->thresh62 & 0x7f) << 12;
1771 otus_write(sc, AR_PHY_CCA(0x1c5800 + 0x3064), tmp);
1772
1773 tmp = otus_phy_get_def(sc, AR_PHY_RXGAIN(0x1c5800 + 0x0048));
1774 tmp &= ~(0x3f << 12);
1775 tmp |= (eep->txRxAttenCh[0] & 0x3f) << 12;
1776 otus_write(sc, AR_PHY_RXGAIN(0x1c5800 + 0x0048), tmp);
1777
1778 tmp = otus_phy_get_def(sc, AR_PHY_RXGAIN(0x1c5800 + 0x0048) + offset);
1779 tmp &= ~(0x3f << 12);
1780 tmp |= (eep->txRxAttenCh[1] & 0x3f) << 12;
1781 otus_write(sc, AR_PHY_RXGAIN(0x1c5800 + 0x0048) + offset, tmp);
1782
1783 tmp = otus_phy_get_def(sc, AR_PHY_GAIN_2GHZ(0x1c5800 + 0x0a0c));
1784 tmp &= ~(0x3f << 18);
1785 tmp |= (eep->rxTxMarginCh[0] & 0x3f) << 18;
1786 if (IEEE80211_IS_CHAN_5GHZ(c)(((c)->ic_flags & 0x0100) != 0)) {
1787 tmp &= ~(0xf << 10);
1788 tmp |= (eep->bswMargin[0] & 0xf) << 10;
1789 }
1790 otus_write(sc, AR_PHY_GAIN_2GHZ(0x1c5800 + 0x0a0c), tmp);
1791
1792 tmp = otus_phy_get_def(sc, AR_PHY_GAIN_2GHZ(0x1c5800 + 0x0a0c) + offset);
1793 tmp &= ~(0x3f << 18);
1794 tmp |= (eep->rxTxMarginCh[1] & 0x3f) << 18;
1795 otus_write(sc, AR_PHY_GAIN_2GHZ(0x1c5800 + 0x0a0c) + offset, tmp);
1796
1797 tmp = otus_phy_get_def(sc, AR_PHY_TIMING_CTRL4(0x1c5800 + 0x0120));
1798 tmp &= ~(0x3f << 5 | 0x1f);
1799 tmp |= (eep->iqCalICh[0] & 0x3f) << 5 | (eep->iqCalQCh[0] & 0x1f);
1800 otus_write(sc, AR_PHY_TIMING_CTRL4(0x1c5800 + 0x0120), tmp);
1801
1802 tmp = otus_phy_get_def(sc, AR_PHY_TIMING_CTRL4(0x1c5800 + 0x0120) + offset);
1803 tmp &= ~(0x3f << 5 | 0x1f);
1804 tmp |= (eep->iqCalICh[1] & 0x3f) << 5 | (eep->iqCalQCh[1] & 0x1f);
1805 otus_write(sc, AR_PHY_TIMING_CTRL4(0x1c5800 + 0x0120) + offset, tmp);
1806
1807 tmp = otus_phy_get_def(sc, AR_PHY_TPCRG1(0x1c5800 + 0x0a58));
1808 tmp &= ~(0xf << 16);
1809 tmp |= (eep->xpd & 0xf) << 16;
1810 otus_write(sc, AR_PHY_TPCRG1(0x1c5800 + 0x0a58), tmp);
1811
1812 return otus_write_barrier(sc);
1813}
1814
1815int
1816otus_program_phy(struct otus_softc *sc, struct ieee80211_channel *c)
1817{
1818 const uint32_t *vals;
1819 int error, i;
1820
1821 /* Select PHY programming based on band and bandwidth. */
1822 if (IEEE80211_IS_CHAN_2GHZ(c)(((c)->ic_flags & 0x0080) != 0))
1823 vals = ar5416_phy_vals_2ghz_20mhz;
1824 else
1825 vals = ar5416_phy_vals_5ghz_20mhz;
1826 for (i = 0; i < nitems(ar5416_phy_regs)(sizeof((ar5416_phy_regs)) / sizeof((ar5416_phy_regs)[0])); i++)
1827 otus_write(sc, AR_PHY(ar5416_phy_regs[i])(0x1c5800 + (ar5416_phy_regs[i]) * 4), vals[i]);
1828 sc->phy_vals = vals;
1829
1830 if (sc->eeprom.baseEepHeader.deviceType == 0x80) /* FEM */
1831 if ((error = otus_set_board_values(sc, c)) != 0)
1832 return error;
1833
1834 /* Initial Tx power settings. */
1835 otus_write(sc, AR_PHY_POWER_TX_RATE_MAX(0x1c5800 + 0x013c), 0x7f);
1836 otus_write(sc, AR_PHY_POWER_TX_RATE1(0x1c5800 + 0x0134), 0x3f3f3f3f);
1837 otus_write(sc, AR_PHY_POWER_TX_RATE2(0x1c5800 + 0x0138), 0x3f3f3f3f);
1838 otus_write(sc, AR_PHY_POWER_TX_RATE3(0x1c5800 + 0x0a34), 0x3f3f3f3f);
1839 otus_write(sc, AR_PHY_POWER_TX_RATE4(0x1c5800 + 0x0a38), 0x3f3f3f3f);
1840 otus_write(sc, AR_PHY_POWER_TX_RATE5(0x1c5800 + 0x0b8c), 0x3f3f3f3f);
1841 otus_write(sc, AR_PHY_POWER_TX_RATE6(0x1c5800 + 0x0b90), 0x3f3f3f3f);
1842 otus_write(sc, AR_PHY_POWER_TX_RATE7(0x1c5800 + 0x0bcc), 0x3f3f3f3f);
1843 otus_write(sc, AR_PHY_POWER_TX_RATE8(0x1c5800 + 0x0bd0), 0x3f3f3f3f);
1844 otus_write(sc, AR_PHY_POWER_TX_RATE9(0x1c5800 + 0x0bd4), 0x3f3f3f3f);
1845
1846 if (IEEE80211_IS_CHAN_2GHZ(c)(((c)->ic_flags & 0x0080) != 0))
1847 otus_write(sc, 0x1d4014, 0x5163);
1848 else
1849 otus_write(sc, 0x1d4014, 0x5143);
1850
1851 return otus_write_barrier(sc);
1852}
1853
1854static __inline uint8_t
1855otus_reverse_bits(uint8_t v)
1856{
1857 v = ((v >> 1) & 0x55) | ((v & 0x55) << 1);
1858 v = ((v >> 2) & 0x33) | ((v & 0x33) << 2);
1859 v = ((v >> 4) & 0x0f) | ((v & 0x0f) << 4);
1860 return v;
1861}
1862
1863int
1864otus_set_rf_bank4(struct otus_softc *sc, struct ieee80211_channel *c)
1865{
1866 uint8_t chansel, d0, d1;
1867 uint16_t data;
1868 int error;
1869
1870 d0 = 0;
1871 if (IEEE80211_IS_CHAN_5GHZ(c)(((c)->ic_flags & 0x0100) != 0)) {
1872 chansel = (c->ic_freq - 4800) / 5;
1873 if (chansel & 1)
1874 d0 |= AR_BANK4_AMODE_REFSEL(2)((2) << 2);
1875 else
1876 d0 |= AR_BANK4_AMODE_REFSEL(1)((1) << 2);
1877 } else {
1878 d0 |= AR_BANK4_AMODE_REFSEL(2)((2) << 2);
1879 if (c->ic_freq == 2484) { /* CH 14 */
1880 d0 |= AR_BANK4_BMODE_LF_SYNTH_FREQ(1 << 1);
1881 chansel = 10 + (c->ic_freq - 2274) / 5;
1882 } else
1883 chansel = 16 + (c->ic_freq - 2272) / 5;
1884 chansel <<= 2;
1885 }
1886 d0 |= AR_BANK4_ADDR(1)((1) << 5) | AR_BANK4_CHUP(1 << 0);
1887 d1 = otus_reverse_bits(chansel);
1888
1889 /* Write bits 0-4 of d0 and d1. */
1890 data = (d1 & 0x1f) << 5 | (d0 & 0x1f);
1891 otus_write(sc, AR_PHY(44)(0x1c5800 + (44) * 4), data);
1892 /* Write bits 5-7 of d0 and d1. */
1893 data = (d1 >> 5) << 5 | (d0 >> 5);
1894 otus_write(sc, AR_PHY(58)(0x1c5800 + (58) * 4), data);
1895
1896 if ((error = otus_write_barrier(sc)) == 0)
1897 usbd_delay_ms(sc->sc_udev, 10);
1898 return error;
1899}
1900
1901void
1902otus_get_delta_slope(uint32_t coeff, uint32_t *exponent, uint32_t *mantissa)
1903{
1904#define COEFF_SCALE_SHIFT 24
1905 uint32_t exp, man;
1906
1907 /* exponent = 14 - floor(log2(coeff)) */
1908 for (exp = 31; exp > 0; exp--)
1909 if (coeff & (1 << exp))
1910 break;
1911 KASSERT(exp != 0)((exp != 0) ? (void)0 : __assert("diagnostic ", "/usr/src/sys/dev/usb/if_otus.c"
, 1911, "exp != 0"))
;
1912 exp = 14 - (exp - COEFF_SCALE_SHIFT);
1913
1914 /* mantissa = floor(coeff * 2^exponent + 0.5) */
1915 man = coeff + (1 << (COEFF_SCALE_SHIFT - exp - 1));
1916
1917 *mantissa = man >> (COEFF_SCALE_SHIFT - exp);
1918 *exponent = exp - 16;
1919#undef COEFF_SCALE_SHIFT
1920}
1921
1922int
1923otus_set_chan(struct otus_softc *sc, struct ieee80211_channel *c, int assoc)
1924{
1925 struct ieee80211com *ic = &sc->sc_ic;
1926 struct ar_cmd_frequency cmd;
1927 struct ar_rsp_frequency rsp;
1928 const uint32_t *vals;
1929 uint32_t coeff, exp, man, tmp;
1930 uint8_t code;
1931 int error, chan, i;
1932
1933 chan = ieee80211_chan2ieee(ic, c);
1934 DPRINTF(("setting channel %d (%dMHz)\n", chan, c->ic_freq));
1935
1936 tmp = IEEE80211_IS_CHAN_2GHZ(c)(((c)->ic_flags & 0x0080) != 0) ? 0x105 : 0x104;
1937 otus_write(sc, AR_MAC_REG_DYNAMIC_SIFS_ACK(0x1c3000 + 0x658), tmp);
1938 if ((error = otus_write_barrier(sc)) != 0)
1939 return error;
1940
1941 /* Disable BB Heavy Clip. */
1942 otus_write(sc, AR_PHY_HEAVY_CLIP_ENABLE(0x1c5800 + 0x01e0), 0x200);
1943 if ((error = otus_write_barrier(sc)) != 0)
1944 return error;
1945
1946 /* XXX Is that FREQ_START ? */
1947 error = otus_cmd(sc, AR_CMD_FREQ_STRAT0x33, NULL((void *)0), 0, NULL((void *)0));
1948 if (error != 0)
1949 return error;
1950
1951 /* Reprogram PHY and RF on channel band or bandwidth changes. */
1952 if (sc->bb_reset || c->ic_flags != sc->sc_curchan->ic_flags) {
1953 DPRINTF(("band switch\n"));
1954
1955 /* Cold/Warm reset BB/ADDA. */
1956 otus_write(sc, 0x1d4004, sc->bb_reset ? 0x800 : 0x400);
1957 if ((error = otus_write_barrier(sc)) != 0)
1958 return error;
1959 otus_write(sc, 0x1d4004, 0);
1960 if ((error = otus_write_barrier(sc)) != 0)
1961 return error;
1962 sc->bb_reset = 0;
1963
1964 if ((error = otus_program_phy(sc, c)) != 0) {
1965 printf("%s: could not program PHY\n",
1966 sc->sc_dev.dv_xname);
1967 return error;
1968 }
1969
1970 /* Select RF programming based on band. */
1971 if (IEEE80211_IS_CHAN_5GHZ(c)(((c)->ic_flags & 0x0100) != 0))
1972 vals = ar5416_banks_vals_5ghz;
1973 else
1974 vals = ar5416_banks_vals_2ghz;
1975 for (i = 0; i < nitems(ar5416_banks_regs)(sizeof((ar5416_banks_regs)) / sizeof((ar5416_banks_regs)[0])
)
; i++)
1976 otus_write(sc, AR_PHY(ar5416_banks_regs[i])(0x1c5800 + (ar5416_banks_regs[i]) * 4), vals[i]);
1977 if ((error = otus_write_barrier(sc)) != 0) {
1978 printf("%s: could not program RF\n",
1979 sc->sc_dev.dv_xname);
1980 return error;
1981 }
1982 code = AR_CMD_RF_INIT0x31;
1983 } else {
1984 code = AR_CMD_FREQUENCY0x30;
1985 }
1986
1987 if ((error = otus_set_rf_bank4(sc, c)) != 0)
1988 return error;
1989
1990 tmp = (sc->txmask == 0x5) ? 0x340 : 0x240;
1991 otus_write(sc, AR_PHY_TURBO(0x1c5800 + 0x0004), tmp);
1992 if ((error = otus_write_barrier(sc)) != 0)
1993 return error;
1994
1995 /* Send firmware command to set channel. */
1996 cmd.freq = htole32((uint32_t)c->ic_freq * 1000)((__uint32_t)((uint32_t)c->ic_freq * 1000));
1997 cmd.dynht2040 = htole32(0)((__uint32_t)(0));
1998 cmd.htena = htole32(1)((__uint32_t)(1));
1999 /* Set Delta Slope (exponent and mantissa). */
2000 coeff = (100 << 24) / c->ic_freq;
2001 otus_get_delta_slope(coeff, &exp, &man);
2002 cmd.dsc_exp = htole32(exp)((__uint32_t)(exp));
2003 cmd.dsc_man = htole32(man)((__uint32_t)(man));
2004 DPRINTF(("ds coeff=%u exp=%u man=%u\n", coeff, exp, man));
2005 /* For Short GI, coeff is 9/10 that of normal coeff. */
2006 coeff = (9 * coeff) / 10;
2007 otus_get_delta_slope(coeff, &exp, &man);
2008 cmd.dsc_shgi_exp = htole32(exp)((__uint32_t)(exp));
2009 cmd.dsc_shgi_man = htole32(man)((__uint32_t)(man));
2010 DPRINTF(("ds shgi coeff=%u exp=%u man=%u\n", coeff, exp, man));
2011 /* Set wait time for AGC and noise calibration (100 or 200ms). */
2012 cmd.check_loop_count = assoc ? htole32(2000)((__uint32_t)(2000)) : htole32(1000)((__uint32_t)(1000));
2013 DPRINTF(("%s\n", (code == AR_CMD_RF_INIT) ? "RF_INIT" : "FREQUENCY"));
2014 error = otus_cmd(sc, code, &cmd, sizeof cmd, &rsp);
2015 if (error != 0)
2016 return error;
2017 if ((rsp.status & htole32(AR_CAL_ERR_AGC | AR_CAL_ERR_NF_VAL)((__uint32_t)((1 << 0) | (1 << 2)))) != 0) {
2018 DPRINTF(("status=0x%x\n", letoh32(rsp.status)));
2019 /* Force cold reset on next channel. */
2020 sc->bb_reset = 1;
2021 }
2022#ifdef OTUS_DEBUG
2023 if (otus_debug) {
2024 printf("calibration status=0x%x\n", letoh32(rsp.status)((__uint32_t)(rsp.status)));
2025 for (i = 0; i < 2; i++) { /* 2 Rx chains */
2026 /* Sign-extend 9-bit NF values. */
2027 printf("noisefloor chain %d=%d\n", i,
2028 (((int32_t)letoh32(rsp.nf[i])((__uint32_t)(rsp.nf[i]))) << 4) >> 23);
2029 printf("noisefloor ext chain %d=%d\n", i,
2030 ((int32_t)letoh32(rsp.nf_ext[i])((__uint32_t)(rsp.nf_ext[i]))) >> 23);
2031 }
2032 }
2033#endif
2034 sc->sc_curchan = c;
2035 return 0;
2036}
2037
2038#ifdef notyet
2039int
2040otus_set_key(struct ieee80211com *ic, struct ieee80211_node *ni,
2041 struct ieee80211_key *k)
2042{
2043 struct otus_softc *sc = ic->ic_softcic_ac.ac_if.if_softc;
2044 struct otus_cmd_key cmd;
2045
2046 /* Defer setting of WEP keys until interface is brought up. */
2047 if ((ic->ic_ific_ac.ac_if.if_flags & (IFF_UP0x1 | IFF_RUNNING0x40)) !=
2048 (IFF_UP0x1 | IFF_RUNNING0x40))
2049 return 0;
2050
2051 /* Do it in a process context. */
2052 cmd.key = *k;
2053 cmd.ni = *ni;
2054 otus_do_async(sc, otus_set_key_cb, &cmd, sizeof cmd);
2055 sc->sc_key_tasks++
2056 return EBUSY16;
2057}
2058
2059void
2060otus_set_key_cb(struct otus_softc *sc, void *arg)
2061{
2062 struct otus_cmd_key *cmd = arg;
2063 struct ieee80211_key *k = &cmd->key;
2064 struct ar_cmd_ekey key;
2065 uint16_t cipher;
2066 int error;
2067
2068 sc->sc_keys_tasks--;
2069
2070 memset(&key, 0, sizeof key)__builtin_memset((&key), (0), (sizeof key));
2071 if (k->k_flags & IEEE80211_KEY_GROUP0x00000001) {
2072 key.uid = htole16(k->k_id)((__uint16_t)(k->k_id));
2073 IEEE80211_ADDR_COPY(key.macaddr, sc->sc_ic.ic_myaddr)__builtin_memcpy((key.macaddr), (sc->sc_ic.ic_myaddr), (6)
)
;
2074 key.macaddr[0] |= 0x80;
2075 } else {
2076 key.uid = htole16(OTUS_UID(cmd->associd))((__uint16_t)((((cmd->associd) &~ 0xc000) + 4)));
2077 IEEE80211_ADDR_COPY(key.macaddr, ni->ni_macaddr)__builtin_memcpy((key.macaddr), (ni->ni_macaddr), (6));
2078 }
2079 key.kix = htole16(0)((__uint16_t)(0));
2080 /* Map net80211 cipher to hardware. */
2081 switch (k->k_cipher) {
2082 case IEEE80211_CIPHER_WEP40:
2083 cipher = AR_CIPHER_WEP641;
2084 break;
2085 case IEEE80211_CIPHER_WEP104:
2086 cipher = AR_CIPHER_WEP1285;
2087 break;
2088 case IEEE80211_CIPHER_TKIP:
2089 cipher = AR_CIPHER_TKIP2;
2090 break;
2091 case IEEE80211_CIPHER_CCMP:
2092 cipher = AR_CIPHER_AES4;
2093 break;
2094 default:
2095 IEEE80211_SEND_MGMT(ic, cmd->ni, IEEE80211_FC0_SUBTYPE_DEAUTH,((*(ic)->ic_send_mgmt)(ic, cmd->ni, 0xc0, IEEE80211_REASON_AUTH_LEAVE
, 0))
2096 IEEE80211_REASON_AUTH_LEAVE)((*(ic)->ic_send_mgmt)(ic, cmd->ni, 0xc0, IEEE80211_REASON_AUTH_LEAVE
, 0))
;
2097 ieee80211_new_state(ic, IEEE80211_S_SCAN, -1)(((ic)->ic_newstate)((ic), (IEEE80211_S_SCAN), (-1)));
2098 return;
2099 }
2100 key.cipher = htole16(cipher)((__uint16_t)(cipher));
2101 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))))
;
2102 error = otus_cmd(sc, AR_CMD_EKEY0x28, &key, sizeof key, NULL((void *)0));
2103 if (error != 0 || k->k_cipher != IEEE80211_CIPHER_TKIP) {
2104 IEEE80211_SEND_MGMT(ic, cmd->ni, IEEE80211_FC0_SUBTYPE_DEAUTH,((*(ic)->ic_send_mgmt)(ic, cmd->ni, 0xc0, IEEE80211_REASON_AUTH_LEAVE
, 0))
2105 IEEE80211_REASON_AUTH_LEAVE)((*(ic)->ic_send_mgmt)(ic, cmd->ni, 0xc0, IEEE80211_REASON_AUTH_LEAVE
, 0))
;
2106 ieee80211_new_state(ic, IEEE80211_S_SCAN, -1)(((ic)->ic_newstate)((ic), (IEEE80211_S_SCAN), (-1)));
2107 return;
2108 }
2109
2110 /* TKIP: set Tx/Rx MIC Key. */
2111 key.kix = htole16(1)((__uint16_t)(1));
2112 memcpy(key.key, k->k_key + 16, 16)__builtin_memcpy((key.key), (k->k_key + 16), (16));
2113 (void)otus_cmd(sc, AR_CMD_EKEY0x28, &key, sizeof key, NULL((void *)0));
2114
2115 if (sc->sc_key_tasks == 0) {
2116 DPRINTF(("marking port %s valid\n",
2117 ether_sprintf(cmd->ni->ni_macaddr)));
2118 cmd->ni->ni_port_valid = 1;
2119 ieee80211_set_link_state(ic, LINK_STATE_UP4);
2120 }
2121}
2122
2123void
2124otus_delete_key(struct ieee80211com *ic, struct ieee80211_node *ni,
2125 struct ieee80211_key *k)
2126{
2127 struct otus_softc *sc = ic->ic_softcic_ac.ac_if.if_softc;
2128 struct otus_cmd_key cmd;
2129
2130 if (!(ic->ic_ific_ac.ac_if.if_flags & IFF_RUNNING0x40) ||
2131 ic->ic_state != IEEE80211_S_RUN)
2132 return; /* Nothing to do. */
2133
2134 /* Do it in a process context. */
2135 cmd.key = *k;
2136 cmd.associd = (ni != NULL((void *)0)) ? ni->ni_associd : 0;
2137 otus_do_async(sc, otus_delete_key_cb, &cmd, sizeof cmd);
2138}
2139
2140void
2141otus_delete_key_cb(struct otus_softc *sc, void *arg)
2142{
2143 struct otus_cmd_key *cmd = arg;
2144 struct ieee80211_key *k = &cmd->key;
2145 uint32_t uid;
2146
2147 if (k->k_flags & IEEE80211_KEY_GROUP0x00000001)
2148 uid = htole32(k->k_id)((__uint32_t)(k->k_id));
2149 else
2150 uid = htole32(OTUS_UID(cmd->associd))((__uint32_t)((((cmd->associd) &~ 0xc000) + 4)));
2151 (void)otus_cmd(sc, AR_CMD_DKEY0x29, &uid, sizeof uid, NULL((void *)0));
2152}
2153#endif
2154
2155void
2156otus_calibrate_to(void *arg)
2157{
2158 struct otus_softc *sc = arg;
2159 struct ieee80211com *ic = &sc->sc_ic;
2160 struct ieee80211_node *ni;
2161 int s;
2162
2163 if (usbd_is_dying(sc->sc_udev))
2164 return;
2165
2166 usbd_ref_incr(sc->sc_udev);
2167
2168 s = splnet()splraise(0x4);
2169 ni = ic->ic_bss;
2170 ieee80211_amrr_choose(&sc->amrr, ni, &((struct otus_node *)ni)->amn);
2171 splx(s)spllower(s);
2172
2173 if (!usbd_is_dying(sc->sc_udev))
2174 timeout_add_sec(&sc->calib_to, 1);
2175
2176 usbd_ref_decr(sc->sc_udev);
2177}
2178
2179int
2180otus_set_bssid(struct otus_softc *sc, const uint8_t *bssid)
2181{
2182 otus_write(sc, AR_MAC_REG_BSSID_L(0x1c3000 + 0x618),
2183 bssid[0] | bssid[1] << 8 | bssid[2] << 16 | bssid[3] << 24);
2184 otus_write(sc, AR_MAC_REG_BSSID_H(0x1c3000 + 0x61c),
2185 bssid[4] | bssid[5] << 8);
2186 return otus_write_barrier(sc);
2187}
2188
2189int
2190otus_set_macaddr(struct otus_softc *sc, const uint8_t *addr)
2191{
2192 otus_write(sc, AR_MAC_REG_MAC_ADDR_L(0x1c3000 + 0x610),
2193 addr[0] | addr[1] << 8 | addr[2] << 16 | addr[3] << 24);
2194 otus_write(sc, AR_MAC_REG_MAC_ADDR_H(0x1c3000 + 0x614),
2195 addr[4] | addr[5] << 8);
2196 return otus_write_barrier(sc);
2197}
2198
2199/* Default single-LED. */
2200void
2201otus_led_newstate_type1(struct otus_softc *sc)
2202{
2203 /* TBD */
2204}
2205
2206/* NETGEAR, dual-LED. */
2207void
2208otus_led_newstate_type2(struct otus_softc *sc)
2209{
2210 /* TBD */
2211}
2212
2213/* NETGEAR, single-LED/3 colors (blue, red, purple.) */
2214void
2215otus_led_newstate_type3(struct otus_softc *sc)
2216{
2217 struct ieee80211com *ic = &sc->sc_ic;
2218 uint32_t state = sc->led_state;
2219
2220 if (ic->ic_state == IEEE80211_S_INIT) {
2221 state = 0; /* LED off. */
2222 } else if (ic->ic_state == IEEE80211_S_RUN) {
2223 /* Associated, LED always on. */
2224 if (IEEE80211_IS_CHAN_2GHZ(sc->sc_curchan)(((sc->sc_curchan)->ic_flags & 0x0080) != 0))
2225 state = AR_LED0_ON(1 << 0); /* 2GHz=>Red. */
2226 else
2227 state = AR_LED1_ON(1 << 1); /* 5GHz=>Blue. */
2228 } else {
2229 /* Scanning, blink LED. */
2230 state ^= AR_LED0_ON(1 << 0) | AR_LED1_ON(1 << 1);
2231 if (IEEE80211_IS_CHAN_2GHZ(sc->sc_curchan)(((sc->sc_curchan)->ic_flags & 0x0080) != 0))
2232 state &= ~AR_LED1_ON(1 << 1);
2233 else
2234 state &= ~AR_LED0_ON(1 << 0);
2235 }
2236 if (state != sc->led_state) {
2237 otus_write(sc, 0x1d0104, state);
2238 if (otus_write_barrier(sc) == 0)
2239 sc->led_state = state;
2240 }
2241}
2242
2243int
2244otus_init(struct ifnet *ifp)
2245{
2246 struct otus_softc *sc = ifp->if_softc;
2247 struct ieee80211com *ic = &sc->sc_ic;
2248 int error;
2249
2250 /* Init host command ring. */
2251 sc->cmdq.cur = sc->cmdq.next = sc->cmdq.queued = 0;
2252
2253 if ((error = otus_init_mac(sc)) != 0) {
2254 printf("%s: could not initialize MAC\n", sc->sc_dev.dv_xname);
2255 return error;
2256 }
2257
2258 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))
;
2259 (void)otus_set_macaddr(sc, ic->ic_myaddr);
2260
2261 switch (ic->ic_opmode) {
2262#ifdef notyet
2263#ifndef IEEE80211_STA_ONLY
2264 case IEEE80211_M_HOSTAP:
2265 otus_write(sc, 0x1c3700, 0x0f0000a1);
2266 otus_write(sc, 0x1c3c40, 0x1);
2267 break;
2268 case IEEE80211_M_IBSS:
2269 otus_write(sc, 0x1c3700, 0x0f000000);
2270 otus_write(sc, 0x1c3c40, 0x1);
2271 break;
2272#endif
2273#endif
2274 case IEEE80211_M_STA:
2275 otus_write(sc, 0x1c3700, 0x0f000002);
2276 otus_write(sc, 0x1c3c40, 0x1);
2277 break;
2278 default:
2279 break;
2280 }
2281 otus_write(sc, AR_MAC_REG_SNIFFER(0x1c3000 + 0x674),
2282 (ic->ic_opmode == IEEE80211_M_MONITOR) ? 0x2000001 : 0x2000000);
2283 (void)otus_write_barrier(sc);
2284
2285 sc->bb_reset = 1; /* Force cold reset. */
2286 ic->ic_bss->ni_chan = ic->ic_ibss_chan;
2287 if ((error = otus_set_chan(sc, ic->ic_ibss_chan, 0)) != 0) {
2288 printf("%s: could not set channel\n", sc->sc_dev.dv_xname);
2289 return error;
2290 }
2291
2292 /* Start Rx. */
2293 otus_write(sc, AR_MAC_REG_DMA_TRIGGER(0x1c3000 + 0xd30), AR_DMA_TRIGGER_RXQ0x100);
2294 (void)otus_write_barrier(sc);
2295
2296 ifp->if_flags |= IFF_RUNNING0x40;
2297 ifq_clr_oactive(&ifp->if_snd);
2298
2299 if (ic->ic_opmode == IEEE80211_M_MONITOR)
2300 ieee80211_new_state(ic, IEEE80211_S_RUN, -1)(((ic)->ic_newstate)((ic), (IEEE80211_S_RUN), (-1)));
2301 else
2302 ieee80211_new_state(ic, IEEE80211_S_SCAN, -1)(((ic)->ic_newstate)((ic), (IEEE80211_S_SCAN), (-1)));
2303
2304 return 0;
2305}
2306
2307void
2308otus_stop(struct ifnet *ifp)
2309{
2310 struct otus_softc *sc = ifp->if_softc;
2311 struct ieee80211com *ic = &sc->sc_ic;
2312 int s;
2313
2314 sc->sc_tx_timer = 0;
2315 ifp->if_timer = 0;
2316 ifp->if_flags &= ~IFF_RUNNING0x40;
2317 ifq_clr_oactive(&ifp->if_snd);
2318
2319 timeout_del(&sc->scan_to);
2320 timeout_del(&sc->calib_to);
2321
2322 s = splusb()splraise(0x2);
2323 ieee80211_new_state(ic, IEEE80211_S_INIT, -1)(((ic)->ic_newstate)((ic), (IEEE80211_S_INIT), (-1)));
2324 /* Wait for all queued asynchronous commands to complete. */
2325 usb_wait_task(sc->sc_udev, &sc->sc_task);
2326 splx(s)spllower(s);
2327
2328 /* Stop Rx. */
2329 otus_write(sc, AR_MAC_REG_DMA_TRIGGER(0x1c3000 + 0xd30), 0);
2330 (void)otus_write_barrier(sc);
2331
2332 sc->tx_queued = 0;
2333}