Bug Summary

File:dev/usb/if_rsu.c
Warning:line 791, column 3
Value stored to 'reg' 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_rsu.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_rsu.c
1/* $OpenBSD: if_rsu.c,v 1.50 2021/10/04 01:33:42 kevlo Exp $ */
2
3/*-
4 * Copyright (c) 2010 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 Realtek RTL8188SU/RTL8191SU/RTL8192SU.
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_radiotap.h>
50
51#include <dev/usb/usb.h>
52#include <dev/usb/usbdi.h>
53#include <dev/usb/usbdi_util.h>
54#include <dev/usb/usbdevs.h>
55
56#include <dev/usb/if_rsureg.h>
57
58#ifdef RSU_DEBUG
59#define DPRINTF(x) do { if (rsu_debug) printf x; } while (0)
60#define DPRINTFN(n, x) do { if (rsu_debug >= (n)) printf x; } while (0)
61int rsu_debug = 4;
62#else
63#define DPRINTF(x)
64#define DPRINTFN(n, x)
65#endif
66
67/*
68 * NB: When updating this list of devices, beware to also update the list
69 * of devices that have HT support disabled below, if applicable.
70 */
71static const struct usb_devno rsu_devs[] = {
72 { USB_VENDOR_ACCTON0x083a, USB_PRODUCT_ACCTON_RTL8192SU0xc512 },
73 { USB_VENDOR_ASUS0x0b05, USB_PRODUCT_ASUS_USBN100x1786 },
74 { USB_VENDOR_ASUS0x0b05, USB_PRODUCT_ASUS_RTL8192SU_10x1791 },
75 { USB_VENDOR_AZUREWAVE0x13d3, USB_PRODUCT_AZUREWAVE_RTL8192SU_10x3306 },
76 { USB_VENDOR_AZUREWAVE0x13d3, USB_PRODUCT_AZUREWAVE_RTL8192SU_20x3309 },
77 { USB_VENDOR_AZUREWAVE0x13d3, USB_PRODUCT_AZUREWAVE_RTL8192SU_30x3310 },
78 { USB_VENDOR_AZUREWAVE0x13d3, USB_PRODUCT_AZUREWAVE_RTL8192SU_40x3311 },
79 { USB_VENDOR_AZUREWAVE0x13d3, USB_PRODUCT_AZUREWAVE_RTL8192SU_50x3325 },
80 { USB_VENDOR_BELKIN0x050d, USB_PRODUCT_BELKIN_RTL8192SU_10x815f },
81 { USB_VENDOR_BELKIN0x050d, USB_PRODUCT_BELKIN_RTL8192SU_20x845a },
82 { USB_VENDOR_BELKIN0x050d, USB_PRODUCT_BELKIN_RTL8192SU_30x945a },
83 { USB_VENDOR_CONCEPTRONIC20x14b2, USB_PRODUCT_CONCEPTRONIC2_RTL8192SU_10x3300 },
84 { USB_VENDOR_CONCEPTRONIC20x14b2, USB_PRODUCT_CONCEPTRONIC2_RTL8192SU_20x3301 },
85 { USB_VENDOR_CONCEPTRONIC20x14b2, USB_PRODUCT_CONCEPTRONIC2_RTL8192SU_30x3302 },
86 { USB_VENDOR_COREGA0x07aa, USB_PRODUCT_COREGA_RTL8192SU0x0047 },
87 { USB_VENDOR_DLINK20x07d1, USB_PRODUCT_DLINK2_DWA131A10x3303 },
88 { USB_VENDOR_DLINK20x07d1, USB_PRODUCT_DLINK2_RTL8192SU_10x3300 },
89 { USB_VENDOR_DLINK20x07d1, USB_PRODUCT_DLINK2_RTL8192SU_20x3302 },
90 { USB_VENDOR_EDIMAX0x7392, USB_PRODUCT_EDIMAX_RTL8192SU_10x7611 },
91 { USB_VENDOR_EDIMAX0x7392, USB_PRODUCT_EDIMAX_RTL8192SU_20x7612 },
92 { USB_VENDOR_EDIMAX0x7392, USB_PRODUCT_EDIMAX_RTL8192SU_30x7622 },
93 { USB_VENDOR_GUILLEMOT0x06f8, USB_PRODUCT_GUILLEMOT_HWGUN540xe032 },
94 { USB_VENDOR_GUILLEMOT0x06f8, USB_PRODUCT_GUILLEMOT_HWNUM3000xe031 },
95 { USB_VENDOR_HAWKING0x0e66, USB_PRODUCT_HAWKING_RTL8192SU_10x0015 },
96 { USB_VENDOR_HAWKING0x0e66, USB_PRODUCT_HAWKING_RTL8192SU_20x0016 },
97 { USB_VENDOR_PLANEX20x2019, USB_PRODUCT_PLANEX2_GWUSNANO0xab28 },
98 { USB_VENDOR_REALTEK0x0bda, USB_PRODUCT_REALTEK_RTL81710x8171 },
99 { USB_VENDOR_REALTEK0x0bda, USB_PRODUCT_REALTEK_RTL81720x8172 },
100 { USB_VENDOR_REALTEK0x0bda, USB_PRODUCT_REALTEK_RTL81730x8173 },
101 { USB_VENDOR_REALTEK0x0bda, USB_PRODUCT_REALTEK_RTL81740x8174 },
102 { USB_VENDOR_REALTEK0x0bda, USB_PRODUCT_REALTEK_RTL8192SU0xc512 },
103 { USB_VENDOR_REALTEK0x0bda, USB_PRODUCT_REALTEK_RTL87120x8712 },
104 { USB_VENDOR_REALTEK0x0bda, USB_PRODUCT_REALTEK_RTL87130x8713 },
105 { USB_VENDOR_SENAO0x1740, USB_PRODUCT_SENAO_RTL8192SU_10x9603 },
106 { USB_VENDOR_SENAO0x1740, USB_PRODUCT_SENAO_RTL8192SU_20x9605 },
107 { USB_VENDOR_SITECOMEU0x0df6, USB_PRODUCT_SITECOMEU_WL349V10x004b },
108 { USB_VENDOR_SITECOMEU0x0df6, USB_PRODUCT_SITECOMEU_WL3530x0045 },
109 { USB_VENDOR_SWEEX20x177f, USB_PRODUCT_SWEEX2_LW1540x0154 }
110};
111
112/* List of devices that have HT support disabled. */
113static const struct usb_devno rsu_devs_noht[] = {
114 { USB_VENDOR_ASUS0x0b05, USB_PRODUCT_ASUS_RTL8192SU_10x1791 },
115 { USB_VENDOR_AZUREWAVE0x13d3, USB_PRODUCT_AZUREWAVE_RTL8192SU_40x3311 }
116};
117
118int rsu_match(struct device *, void *, void *);
119void rsu_attach(struct device *, struct device *, void *);
120int rsu_detach(struct device *, int);
121int rsu_open_pipes(struct rsu_softc *);
122void rsu_close_pipes(struct rsu_softc *);
123int rsu_alloc_rx_list(struct rsu_softc *);
124void rsu_free_rx_list(struct rsu_softc *);
125int rsu_alloc_tx_list(struct rsu_softc *);
126void rsu_free_tx_list(struct rsu_softc *);
127void rsu_task(void *);
128void rsu_do_async(struct rsu_softc *,
129 void (*)(struct rsu_softc *, void *), void *, int);
130void rsu_wait_async(struct rsu_softc *);
131int rsu_write_region_1(struct rsu_softc *, uint16_t, uint8_t *,
132 int);
133void rsu_write_1(struct rsu_softc *, uint16_t, uint8_t);
134void rsu_write_2(struct rsu_softc *, uint16_t, uint16_t);
135void rsu_write_4(struct rsu_softc *, uint16_t, uint32_t);
136int rsu_read_region_1(struct rsu_softc *, uint16_t, uint8_t *,
137 int);
138uint8_t rsu_read_1(struct rsu_softc *, uint16_t);
139uint16_t rsu_read_2(struct rsu_softc *, uint16_t);
140uint32_t rsu_read_4(struct rsu_softc *, uint16_t);
141int rsu_fw_iocmd(struct rsu_softc *, uint32_t);
142uint8_t rsu_efuse_read_1(struct rsu_softc *, uint16_t);
143int rsu_read_rom(struct rsu_softc *);
144int rsu_fw_cmd(struct rsu_softc *, uint8_t, void *, int);
145int rsu_media_change(struct ifnet *);
146void rsu_calib_to(void *);
147void rsu_calib_cb(struct rsu_softc *, void *);
148int rsu_newstate(struct ieee80211com *, enum ieee80211_state, int);
149void rsu_newstate_cb(struct rsu_softc *, void *);
150int rsu_set_key(struct ieee80211com *, struct ieee80211_node *,
151 struct ieee80211_key *);
152void rsu_set_key_cb(struct rsu_softc *, void *);
153void rsu_delete_key(struct ieee80211com *, struct ieee80211_node *,
154 struct ieee80211_key *);
155void rsu_delete_key_cb(struct rsu_softc *, void *);
156int rsu_site_survey(struct rsu_softc *);
157int rsu_join_bss(struct rsu_softc *, struct ieee80211_node *);
158int rsu_disconnect(struct rsu_softc *);
159void rsu_event_survey(struct rsu_softc *, uint8_t *, int);
160void rsu_event_join_bss(struct rsu_softc *, uint8_t *, int);
161void rsu_rx_event(struct rsu_softc *, uint8_t, uint8_t *, int);
162void rsu_rx_multi_event(struct rsu_softc *, uint8_t *, int);
163int8_t rsu_get_rssi(struct rsu_softc *, int, void *);
164void rsu_rx_frame(struct rsu_softc *, uint8_t *, int,
165 struct mbuf_list *);
166void rsu_rx_multi_frame(struct rsu_softc *, uint8_t *, int);
167void rsu_rxeof(struct usbd_xfer *, void *, usbd_status);
168void rsu_txeof(struct usbd_xfer *, void *, usbd_status);
169int rsu_tx(struct rsu_softc *, struct mbuf *,
170 struct ieee80211_node *);
171int rsu_send_mgmt(struct ieee80211com *, struct ieee80211_node *,
172 int, int, int);
173void rsu_start(struct ifnet *);
174void rsu_watchdog(struct ifnet *);
175int rsu_ioctl(struct ifnet *, u_long, caddr_t);
176void rsu_power_on_acut(struct rsu_softc *);
177void rsu_power_on_bcut(struct rsu_softc *);
178void rsu_power_off(struct rsu_softc *);
179int rsu_fw_loadsection(struct rsu_softc *, uint8_t *, int);
180int rsu_load_firmware(struct rsu_softc *);
181int rsu_init(struct ifnet *);
182void rsu_stop(struct ifnet *);
183
184struct cfdriver rsu_cd = {
185 NULL((void *)0), "rsu", DV_IFNET
186};
187
188const struct cfattach rsu_ca = {
189 sizeof(struct rsu_softc), rsu_match, rsu_attach, rsu_detach,
190};
191
192int
193rsu_match(struct device *parent, void *match, void *aux)
194{
195 struct usb_attach_arg *uaa = aux;
196
197 if (uaa->iface == NULL((void *)0) || uaa->configno != 1)
198 return (UMATCH_NONE0);
199
200 return ((usb_lookup(rsu_devs, uaa->vendor, uaa->product)usbd_match_device((const struct usb_devno *)(rsu_devs), sizeof
(rsu_devs) / sizeof ((rsu_devs)[0]), sizeof ((rsu_devs)[0]),
(uaa->vendor), (uaa->product))
!= NULL((void *)0)) ?
201 UMATCH_VENDOR_PRODUCT_CONF_IFACE8 : UMATCH_NONE0);
202}
203
204void
205rsu_attach(struct device *parent, struct device *self, void *aux)
206{
207 struct rsu_softc *sc = (struct rsu_softc *)self;
208 struct usb_attach_arg *uaa = aux;
209 struct ieee80211com *ic = &sc->sc_ic;
210 struct ifnet *ifp = &ic->ic_ific_ac.ac_if;
211 int i, error;
212
213 sc->sc_udev = uaa->device;
214 sc->sc_iface = uaa->iface;
215
216 usb_init_task(&sc->sc_task, rsu_task, sc, USB_TASK_TYPE_GENERIC)((&sc->sc_task)->fun = (rsu_task), (&sc->sc_task
)->arg = (sc), (&sc->sc_task)->type = (0), (&
sc->sc_task)->state = 0x0)
;
217 timeout_set(&sc->calib_to, rsu_calib_to, sc);
218
219 /* Read chip revision. */
220 sc->cut = MS(rsu_read_4(sc, R92S_PMC_FSM), R92S_PMC_FSM_CUT)(((rsu_read_4(sc, (0x0000 + 0x004))) & 0x000f8000) >>
15)
;
221 if (sc->cut != 3)
222 sc->cut = (sc->cut >> 1) + 1;
223
224 error = rsu_read_rom(sc);
225 if (error != 0) {
226 printf("%s: could not read ROM\n", sc->sc_dev.dv_xname);
227 return;
228 }
229 IEEE80211_ADDR_COPY(ic->ic_myaddr, &sc->rom[0x12])__builtin_memcpy((ic->ic_myaddr), (&sc->rom[0x12]),
(6))
;
230
231 printf("%s: MAC/BB RTL8712 cut %d, address %s\n",
232 sc->sc_dev.dv_xname, sc->cut, ether_sprintf(ic->ic_myaddr));
233
234 if (rsu_open_pipes(sc) != 0)
235 return;
236
237 ic->ic_phytype = IEEE80211_T_OFDM; /* Not only, but not used. */
238 ic->ic_opmode = IEEE80211_M_STA; /* Default to BSS mode. */
239 ic->ic_state = IEEE80211_S_INIT;
240
241 /* Set device capabilities. */
242 ic->ic_caps =
243 IEEE80211_C_SCANALL0x00000400 | /* Hardware scan. */
244 IEEE80211_C_SHPREAMBLE0x00000100 | /* Short preamble supported. */
245 IEEE80211_C_SHSLOT0x00000080 | /* Short slot time supported. */
246 IEEE80211_C_WEP0x00000001 | /* WEP. */
247 IEEE80211_C_RSN0x00001000; /* WPA/RSN. */
248 /* Check if HT support is present. */
249 if (usb_lookup(rsu_devs_noht, uaa->vendor, uaa->product)usbd_match_device((const struct usb_devno *)(rsu_devs_noht), sizeof
(rsu_devs_noht) / sizeof ((rsu_devs_noht)[0]), sizeof ((rsu_devs_noht
)[0]), (uaa->vendor), (uaa->product))
== NULL((void *)0)) {
250#ifdef notyet
251 /* Set HT capabilities. */
252 ic->ic_htcaps =
253 IEEE80211_HTCAP_CBW20_400x00000002 |
254 IEEE80211_HTCAP_DSSSCCK400x00001000;
255 /* Set supported HT rates. */
256 for (i = 0; i < 2; i++)
257 ic->ic_sup_mcs[i] = 0xff;
258#endif
259 }
260
261 /* Set supported .11b and .11g rates. */
262 ic->ic_sup_rates[IEEE80211_MODE_11B] = ieee80211_std_rateset_11b;
263 ic->ic_sup_rates[IEEE80211_MODE_11G] = ieee80211_std_rateset_11g;
264
265 /* Set supported .11b and .11g channels (1 through 14). */
266 for (i = 1; i <= 14; i++) {
267 ic->ic_channels[i].ic_freq =
268 ieee80211_ieee2mhz(i, IEEE80211_CHAN_2GHZ0x0080);
269 ic->ic_channels[i].ic_flags =
270 IEEE80211_CHAN_CCK0x0020 | IEEE80211_CHAN_OFDM0x0040 |
271 IEEE80211_CHAN_DYN0x0400 | IEEE80211_CHAN_2GHZ0x0080;
272 }
273
274 ifp->if_softc = sc;
275 ifp->if_flags = IFF_BROADCAST0x2 | IFF_SIMPLEX0x800 | IFF_MULTICAST0x8000;
276 ifp->if_ioctl = rsu_ioctl;
277 ifp->if_start = rsu_start;
278 ifp->if_watchdog = rsu_watchdog;
279 memcpy(ifp->if_xname, sc->sc_dev.dv_xname, IFNAMSIZ)__builtin_memcpy((ifp->if_xname), (sc->sc_dev.dv_xname)
, (16))
;
280
281 if_attach(ifp);
282 ieee80211_ifattach(ifp);
283#ifdef notyet
284 ic->ic_set_key = rsu_set_key;
285 ic->ic_delete_key = rsu_delete_key;
286#endif
287 /* Override state transition machine. */
288 sc->sc_newstate = ic->ic_newstate;
289 ic->ic_newstate = rsu_newstate;
290 ic->ic_send_mgmt = rsu_send_mgmt;
291 ieee80211_media_init(ifp, rsu_media_change, ieee80211_media_status);
292
293#if NBPFILTER1 > 0
294 bpfattach(&sc->sc_drvbpf, ifp, DLT_IEEE802_11_RADIO127,
295 sizeof(struct ieee80211_frame) + IEEE80211_RADIOTAP_HDRLEN64);
296
297 sc->sc_rxtap_len = sizeof(sc->sc_rxtapu);
298 sc->sc_rxtapsc_rxtapu.th.wr_ihdr.it_len = htole16(sc->sc_rxtap_len)((__uint16_t)(sc->sc_rxtap_len));
299 sc->sc_rxtapsc_rxtapu.th.wr_ihdr.it_present = htole32(RSU_RX_RADIOTAP_PRESENT)((__uint32_t)((1 << IEEE80211_RADIOTAP_FLAGS | 1 <<
IEEE80211_RADIOTAP_RATE | 1 << IEEE80211_RADIOTAP_CHANNEL
| 1 << IEEE80211_RADIOTAP_DBM_ANTSIGNAL)))
;
300
301 sc->sc_txtap_len = sizeof(sc->sc_txtapu);
302 sc->sc_txtapsc_txtapu.th.wt_ihdr.it_len = htole16(sc->sc_txtap_len)((__uint16_t)(sc->sc_txtap_len));
303 sc->sc_txtapsc_txtapu.th.wt_ihdr.it_present = htole32(RSU_TX_RADIOTAP_PRESENT)((__uint32_t)((1 << IEEE80211_RADIOTAP_FLAGS | 1 <<
IEEE80211_RADIOTAP_CHANNEL)))
;
304#endif
305}
306
307int
308rsu_detach(struct device *self, int flags)
309{
310 struct rsu_softc *sc = (struct rsu_softc *)self;
311 struct ifnet *ifp = &sc->sc_ic.ic_ific_ac.ac_if;
312 int s;
313
314 s = splusb()splraise(0x5);
315
316 if (timeout_initialized(&sc->calib_to)((&sc->calib_to)->to_flags & 0x04))
317 timeout_del(&sc->calib_to);
318
319 /* Wait for all async commands to complete. */
320 usb_rem_wait_task(sc->sc_udev, &sc->sc_task);
321
322 usbd_ref_wait(sc->sc_udev);
323
324 if (ifp->if_softc != NULL((void *)0)) {
325 ieee80211_ifdetach(ifp);
326 if_detach(ifp);
327 }
328
329 /* Abort and close Tx/Rx pipes. */
330 rsu_close_pipes(sc);
331
332 /* Free Tx/Rx buffers. */
333 rsu_free_tx_list(sc);
334 rsu_free_rx_list(sc);
335 splx(s)spllower(s);
336
337 return (0);
338}
339
340int
341rsu_open_pipes(struct rsu_softc *sc)
342{
343 usb_interface_descriptor_t *id;
344 int i, error;
345
346 /*
347 * Determine the number of Tx/Rx endpoints (there are chips with
348 * 4, 6 or 11 endpoints).
349 */
350 id = usbd_get_interface_descriptor(sc->sc_iface);
351 sc->npipes = id->bNumEndpoints;
352 if (sc->npipes == 4)
353 sc->qid2idx = rsu_qid2idx_4ep;
354 else if (sc->npipes == 6)
355 sc->qid2idx = rsu_qid2idx_6ep;
356 else /* Assume npipes==11; will fail below otherwise. */
357 sc->qid2idx = rsu_qid2idx_11ep;
358 DPRINTF(("%d endpoints configuration\n", sc->npipes));
359
360 /* Open all pipes. */
361 for (i = 0; i < MIN(sc->npipes, nitems(r92s_epaddr))(((sc->npipes)<((sizeof((r92s_epaddr)) / sizeof((r92s_epaddr
)[0]))))?(sc->npipes):((sizeof((r92s_epaddr)) / sizeof((r92s_epaddr
)[0]))))
; i++) {
362 error = usbd_open_pipe(sc->sc_iface, r92s_epaddr[i], 0,
363 &sc->pipe[i]);
364 if (error != 0) {
365 printf("%s: could not open bulk pipe 0x%02x\n",
366 sc->sc_dev.dv_xname, r92s_epaddr[i]);
367 break;
368 }
369 }
370 if (error != 0)
371 rsu_close_pipes(sc);
372 return (error);
373}
374
375void
376rsu_close_pipes(struct rsu_softc *sc)
377{
378 int i;
379
380 /* Close all pipes. */
381 for (i = 0; i < sc->npipes; i++) {
382 if (sc->pipe[i] == NULL((void *)0))
383 continue;
384 usbd_close_pipe(sc->pipe[i]);
385 }
386}
387
388int
389rsu_alloc_rx_list(struct rsu_softc *sc)
390{
391 struct rsu_rx_data *data;
392 int i, error = 0;
393
394 for (i = 0; i < RSU_RX_LIST_COUNT1; i++) {
395 data = &sc->rx_data[i];
396
397 data->sc = sc; /* Backpointer for callbacks. */
398
399 data->xfer = usbd_alloc_xfer(sc->sc_udev);
400 if (data->xfer == NULL((void *)0)) {
401 printf("%s: could not allocate xfer\n",
402 sc->sc_dev.dv_xname);
403 error = ENOMEM12;
404 break;
405 }
406 data->buf = usbd_alloc_buffer(data->xfer, RSU_RXBUFSZ(8 * 1024));
407 if (data->buf == NULL((void *)0)) {
408 printf("%s: could not allocate xfer buffer\n",
409 sc->sc_dev.dv_xname);
410 error = ENOMEM12;
411 break;
412 }
413 }
414 if (error != 0)
415 rsu_free_rx_list(sc);
416 return (error);
417}
418
419void
420rsu_free_rx_list(struct rsu_softc *sc)
421{
422 int i;
423
424 /* NB: Caller must abort pipe first. */
425 for (i = 0; i < RSU_RX_LIST_COUNT1; i++) {
426 if (sc->rx_data[i].xfer != NULL((void *)0))
427 usbd_free_xfer(sc->rx_data[i].xfer);
428 sc->rx_data[i].xfer = NULL((void *)0);
429 }
430}
431
432int
433rsu_alloc_tx_list(struct rsu_softc *sc)
434{
435 struct rsu_tx_data *data;
436 int i, error = 0;
437
438 TAILQ_INIT(&sc->tx_free_list)do { (&sc->tx_free_list)->tqh_first = ((void *)0); (
&sc->tx_free_list)->tqh_last = &(&sc->tx_free_list
)->tqh_first; } while (0)
;
439 for (i = 0; i < RSU_TX_LIST_COUNT(8 + 1); i++) {
440 data = &sc->tx_data[i];
441
442 data->sc = sc; /* Backpointer for callbacks. */
443
444 data->xfer = usbd_alloc_xfer(sc->sc_udev);
445 if (data->xfer == NULL((void *)0)) {
446 printf("%s: could not allocate xfer\n",
447 sc->sc_dev.dv_xname);
448 error = ENOMEM12;
449 break;
450 }
451 data->buf = usbd_alloc_buffer(data->xfer, RSU_TXBUFSZ((sizeof(struct r92s_tx_desc) + (2300 + 4 + (3 + 1 + 4)) + 3)
& ~3)
);
452 if (data->buf == NULL((void *)0)) {
453 printf("%s: could not allocate xfer buffer\n",
454 sc->sc_dev.dv_xname);
455 error = ENOMEM12;
456 break;
457 }
458 /* Append this Tx buffer to our free list. */
459 TAILQ_INSERT_TAIL(&sc->tx_free_list, data, next)do { (data)->next.tqe_next = ((void *)0); (data)->next.
tqe_prev = (&sc->tx_free_list)->tqh_last; *(&sc
->tx_free_list)->tqh_last = (data); (&sc->tx_free_list
)->tqh_last = &(data)->next.tqe_next; } while (0)
;
460 }
461 if (error != 0)
462 rsu_free_tx_list(sc);
463 return (error);
464}
465
466void
467rsu_free_tx_list(struct rsu_softc *sc)
468{
469 int i;
470
471 /* NB: Caller must abort pipe first. */
472 for (i = 0; i < RSU_TX_LIST_COUNT(8 + 1); i++) {
473 if (sc->tx_data[i].xfer != NULL((void *)0))
474 usbd_free_xfer(sc->tx_data[i].xfer);
475 sc->tx_data[i].xfer = NULL((void *)0);
476 }
477}
478
479void
480rsu_task(void *arg)
481{
482 struct rsu_softc *sc = arg;
483 struct rsu_host_cmd_ring *ring = &sc->cmdq;
484 struct rsu_host_cmd *cmd;
485 int s;
486
487 /* Process host commands. */
488 s = splusb()splraise(0x5);
489 while (ring->next != ring->cur) {
490 cmd = &ring->cmd[ring->next];
491 splx(s)spllower(s);
492 /* Invoke callback. */
493 cmd->cb(sc, cmd->data);
494 s = splusb()splraise(0x5);
495 ring->queued--;
496 ring->next = (ring->next + 1) % RSU_HOST_CMD_RING_COUNT32;
497 }
498 splx(s)spllower(s);
499}
500
501void
502rsu_do_async(struct rsu_softc *sc,
503 void (*cb)(struct rsu_softc *, void *), void *arg, int len)
504{
505 struct rsu_host_cmd_ring *ring = &sc->cmdq;
506 struct rsu_host_cmd *cmd;
507 int s;
508
509 s = splusb()splraise(0x5);
510 cmd = &ring->cmd[ring->cur];
511 cmd->cb = cb;
512 KASSERT(len <= sizeof(cmd->data))((len <= sizeof(cmd->data)) ? (void)0 : __assert("diagnostic "
, "/usr/src/sys/dev/usb/if_rsu.c", 512, "len <= sizeof(cmd->data)"
))
;
513 memcpy(cmd->data, arg, len)__builtin_memcpy((cmd->data), (arg), (len));
514 ring->cur = (ring->cur + 1) % RSU_HOST_CMD_RING_COUNT32;
515
516 /* If there is no pending command already, schedule a task. */
517 if (++ring->queued == 1)
518 usb_add_task(sc->sc_udev, &sc->sc_task);
519 splx(s)spllower(s);
520}
521
522void
523rsu_wait_async(struct rsu_softc *sc)
524{
525 /* Wait for all queued asynchronous commands to complete. */
526 usb_wait_task(sc->sc_udev, &sc->sc_task);
527}
528
529int
530rsu_write_region_1(struct rsu_softc *sc, uint16_t addr, uint8_t *buf,
531 int len)
532{
533 usb_device_request_t req;
534
535 req.bmRequestType = UT_WRITE_VENDOR_DEVICE(0x00 | 0x40 | 0x00);
536 req.bRequest = R92S_REQ_REGS0x05;
537 USETW(req.wValue, addr)(*(u_int16_t *)(req.wValue) = (addr));
538 USETW(req.wIndex, 0)(*(u_int16_t *)(req.wIndex) = (0));
539 USETW(req.wLength, len)(*(u_int16_t *)(req.wLength) = (len));
540 return (usbd_do_request(sc->sc_udev, &req, buf));
541}
542
543void
544rsu_write_1(struct rsu_softc *sc, uint16_t addr, uint8_t val)
545{
546 rsu_write_region_1(sc, addr, &val, 1);
547}
548
549void
550rsu_write_2(struct rsu_softc *sc, uint16_t addr, uint16_t val)
551{
552 val = htole16(val)((__uint16_t)(val));
553 rsu_write_region_1(sc, addr, (uint8_t *)&val, 2);
554}
555
556void
557rsu_write_4(struct rsu_softc *sc, uint16_t addr, uint32_t val)
558{
559 val = htole32(val)((__uint32_t)(val));
560 rsu_write_region_1(sc, addr, (uint8_t *)&val, 4);
561}
562
563int
564rsu_read_region_1(struct rsu_softc *sc, uint16_t addr, uint8_t *buf,
565 int len)
566{
567 usb_device_request_t req;
568
569 req.bmRequestType = UT_READ_VENDOR_DEVICE(0x80 | 0x40 | 0x00);
570 req.bRequest = R92S_REQ_REGS0x05;
571 USETW(req.wValue, addr)(*(u_int16_t *)(req.wValue) = (addr));
572 USETW(req.wIndex, 0)(*(u_int16_t *)(req.wIndex) = (0));
573 USETW(req.wLength, len)(*(u_int16_t *)(req.wLength) = (len));
574 return (usbd_do_request(sc->sc_udev, &req, buf));
575}
576
577uint8_t
578rsu_read_1(struct rsu_softc *sc, uint16_t addr)
579{
580 uint8_t val;
581
582 if (rsu_read_region_1(sc, addr, &val, 1) != 0)
583 return (0xff);
584 return (val);
585}
586
587uint16_t
588rsu_read_2(struct rsu_softc *sc, uint16_t addr)
589{
590 uint16_t val;
591
592 if (rsu_read_region_1(sc, addr, (uint8_t *)&val, 2) != 0)
593 return (0xffff);
594 return (letoh16(val)((__uint16_t)(val)));
595}
596
597uint32_t
598rsu_read_4(struct rsu_softc *sc, uint16_t addr)
599{
600 uint32_t val;
601
602 if (rsu_read_region_1(sc, addr, (uint8_t *)&val, 4) != 0)
603 return (0xffffffff);
604 return (letoh32(val)((__uint32_t)(val)));
605}
606
607int
608rsu_fw_iocmd(struct rsu_softc *sc, uint32_t iocmd)
609{
610 int ntries;
611
612 rsu_write_4(sc, R92S_IOCMD_CTRL0x0370, iocmd);
613 DELAY(100)(*delay_func)(100);
614 for (ntries = 0; ntries < 50; ntries++) {
615 if (rsu_read_4(sc, R92S_IOCMD_CTRL0x0370) == 0)
616 return (0);
617 DELAY(10)(*delay_func)(10);
618 }
619 return (ETIMEDOUT60);
620}
621
622uint8_t
623rsu_efuse_read_1(struct rsu_softc *sc, uint16_t addr)
624{
625 uint32_t reg;
626 int ntries;
627
628 reg = rsu_read_4(sc, R92S_EFUSE_CTRL(0x0000 + 0x030));
629 reg = RW(reg, R92S_EFUSE_CTRL_ADDR, addr)(((reg) & ~0x0003ff00) | (((addr) << 8) & 0x0003ff00
))
;
630 reg &= ~R92S_EFUSE_CTRL_VALID0x80000000;
631 rsu_write_4(sc, R92S_EFUSE_CTRL(0x0000 + 0x030), reg);
632 /* Wait for read operation to complete. */
633 for (ntries = 0; ntries < 100; ntries++) {
634 reg = rsu_read_4(sc, R92S_EFUSE_CTRL(0x0000 + 0x030));
635 if (reg & R92S_EFUSE_CTRL_VALID0x80000000)
636 return (MS(reg, R92S_EFUSE_CTRL_DATA)(((reg) & 0x000000ff) >> 0));
637 DELAY(5)(*delay_func)(5);
638 }
639 printf("%s: could not read efuse byte at address 0x%x\n",
640 sc->sc_dev.dv_xname, addr);
641 return (0xff);
642}
643
644int
645rsu_read_rom(struct rsu_softc *sc)
646{
647 uint8_t *rom = sc->rom;
648 uint16_t addr = 0;
649 uint32_t reg;
650 uint8_t off, msk;
651 int i;
652
653 /* Make sure that ROM type is eFuse and that autoload succeeded. */
654 reg = rsu_read_1(sc, R92S_EE_9346CR(0x0000 + 0x00a));
655 if ((reg & (R92S_9356SEL0x10 | R92S_EEPROM_EN0x20)) != R92S_EEPROM_EN0x20)
656 return (EIO5);
657
658 /* Turn on 2.5V to prevent eFuse leakage. */
659 reg = rsu_read_1(sc, R92S_EFUSE_TEST(0x0000 + 0x034) + 3);
660 rsu_write_1(sc, R92S_EFUSE_TEST(0x0000 + 0x034) + 3, reg | 0x80);
661 DELAY(1000)(*delay_func)(1000);
662 rsu_write_1(sc, R92S_EFUSE_TEST(0x0000 + 0x034) + 3, reg & ~0x80);
663
664 /* Read full ROM image. */
665 memset(&sc->rom, 0xff, sizeof(sc->rom))__builtin_memset((&sc->rom), (0xff), (sizeof(sc->rom
)))
;
666 while (addr < 512) {
667 reg = rsu_efuse_read_1(sc, addr);
668 if (reg == 0xff)
669 break;
670 addr++;
671 off = reg >> 4;
672 msk = reg & 0xf;
673 for (i = 0; i < 4; i++) {
674 if (msk & (1 << i))
675 continue;
676 rom[off * 8 + i * 2 + 0] =
677 rsu_efuse_read_1(sc, addr);
678 addr++;
679 rom[off * 8 + i * 2 + 1] =
680 rsu_efuse_read_1(sc, addr);
681 addr++;
682 }
683 }
684#ifdef RSU_DEBUG
685 if (rsu_debug >= 5) {
686 /* Dump ROM content. */
687 printf("\n");
688 for (i = 0; i < sizeof(sc->rom); i++)
689 printf("%02x:", rom[i]);
690 printf("\n");
691 }
692#endif
693 return (0);
694}
695
696int
697rsu_fw_cmd(struct rsu_softc *sc, uint8_t code, void *buf, int len)
698{
699 struct rsu_tx_data *data;
700 struct r92s_tx_desc *txd;
701 struct r92s_fw_cmd_hdr *cmd;
702 struct usbd_pipe *pipe;
703 int cmdsz, xferlen;
704
705 data = sc->fwcmd_data;
706
707 /* Round-up command length to a multiple of 8 bytes. */
708 cmdsz = (len + 7) & ~7;
709
710 xferlen = sizeof(*txd) + sizeof(*cmd) + cmdsz;
711 KASSERT(xferlen <= RSU_TXBUFSZ)((xferlen <= ((sizeof(struct r92s_tx_desc) + (2300 + 4 + (
3 + 1 + 4)) + 3) & ~3)) ? (void)0 : __assert("diagnostic "
, "/usr/src/sys/dev/usb/if_rsu.c", 711, "xferlen <= RSU_TXBUFSZ"
))
;
712 memset(data->buf, 0, xferlen)__builtin_memset((data->buf), (0), (xferlen));
713
714 /* Setup Tx descriptor. */
715 txd = (struct r92s_tx_desc *)data->buf;
716 txd->txdw0 = htole32(((__uint32_t)((((sizeof(*txd)) << 16) & 0x00ff0000)
| (((sizeof(*cmd) + cmdsz) << 0) & 0x0000ffff) | 0x80000000
| 0x08000000 | 0x04000000))
717 SM(R92S_TXDW0_OFFSET, sizeof(*txd)) |((__uint32_t)((((sizeof(*txd)) << 16) & 0x00ff0000)
| (((sizeof(*cmd) + cmdsz) << 0) & 0x0000ffff) | 0x80000000
| 0x08000000 | 0x04000000))
718 SM(R92S_TXDW0_PKTLEN, sizeof(*cmd) + cmdsz) |((__uint32_t)((((sizeof(*txd)) << 16) & 0x00ff0000)
| (((sizeof(*cmd) + cmdsz) << 0) & 0x0000ffff) | 0x80000000
| 0x08000000 | 0x04000000))
719 R92S_TXDW0_OWN | R92S_TXDW0_FSG | R92S_TXDW0_LSG)((__uint32_t)((((sizeof(*txd)) << 16) & 0x00ff0000)
| (((sizeof(*cmd) + cmdsz) << 0) & 0x0000ffff) | 0x80000000
| 0x08000000 | 0x04000000))
;
720 txd->txdw1 = htole32(SM(R92S_TXDW1_QSEL, R92S_TXDW1_QSEL_H2C))((__uint32_t)((((0x1f) << 8) & 0x00001f00)));
721
722 /* Setup command header. */
723 cmd = (struct r92s_fw_cmd_hdr *)&txd[1];
724 cmd->len = htole16(cmdsz)((__uint16_t)(cmdsz));
725 cmd->code = code;
726 cmd->seq = sc->cmd_seq;
727 sc->cmd_seq = (sc->cmd_seq + 1) & 0x7f;
728
729 /* Copy command payload. */
730 memcpy(&cmd[1], buf, len)__builtin_memcpy((&cmd[1]), (buf), (len));
731
732 DPRINTFN(2, ("Tx cmd code=%d len=%d\n", code, cmdsz));
733 pipe = sc->pipe[sc->qid2idx[RSU_QID_H2C8]];
734 usbd_setup_xfer(data->xfer, pipe, NULL((void *)0), data->buf, xferlen,
735 USBD_SHORT_XFER_OK0x04 | USBD_NO_COPY0x01 | USBD_SYNCHRONOUS0x02,
736 RSU_CMD_TIMEOUT2000, NULL((void *)0));
737 return (usbd_transfer(data->xfer));
738}
739
740int
741rsu_media_change(struct ifnet *ifp)
742{
743 int error;
744
745 error = ieee80211_media_change(ifp);
746 if (error != ENETRESET52)
747 return (error);
748
749 if ((ifp->if_flags & (IFF_UP0x1 | IFF_RUNNING0x40)) ==
750 (IFF_UP0x1 | IFF_RUNNING0x40)) {
751 rsu_stop(ifp);
752 error = rsu_init(ifp);
753 }
754 return (error);
755}
756
757void
758rsu_calib_to(void *arg)
759{
760 struct rsu_softc *sc = arg;
761
762 if (usbd_is_dying(sc->sc_udev))
763 return;
764
765 usbd_ref_incr(sc->sc_udev);
766
767 /* Do it in a process context. */
768 rsu_do_async(sc, rsu_calib_cb, NULL((void *)0), 0);
769
770 usbd_ref_decr(sc->sc_udev);
771}
772
773/* ARGSUSED */
774void
775rsu_calib_cb(struct rsu_softc *sc, void *arg)
776{
777 uint32_t reg;
778
779#ifdef notyet
780 /* Read WPS PBC status. */
781 rsu_write_1(sc, R92S_MAC_PINMUX_CTRL(0x01e0 + 0x011),
782 R92S_GPIOMUX_EN0x08 | SM(R92S_GPIOSEL_GPIO, R92S_GPIOSEL_GPIO_JTAG)(((0) << 0) & 0x03));
783 rsu_write_1(sc, R92S_GPIO_IO_SEL(0x01e0 + 0x00e),
784 rsu_read_1(sc, R92S_GPIO_IO_SEL(0x01e0 + 0x00e)) & ~R92S_GPIO_WPS0x10);
785 reg = rsu_read_1(sc, R92S_GPIO_CTRL(0x01e0 + 0x00c));
786 if (reg != 0xff && (reg & R92S_GPIO_WPS0x10))
787 DPRINTF(("WPS PBC is pushed\n"));
788#endif
789 /* Read current signal level. */
790 if (rsu_fw_iocmd(sc, 0xf4000001) == 0) {
791 reg = rsu_read_4(sc, R92S_IOCMD_DATA0x0374);
Value stored to 'reg' is never read
792 DPRINTFN(8, ("RSSI=%d%%\n", reg >> 4));
793 }
794
795 if (!usbd_is_dying(sc->sc_udev))
796 timeout_add_sec(&sc->calib_to, 2);
797}
798
799int
800rsu_newstate(struct ieee80211com *ic, enum ieee80211_state nstate, int arg)
801{
802 struct rsu_softc *sc = ic->ic_softcic_ac.ac_if.if_softc;
803 struct rsu_cmd_newstate cmd;
804
805 /* Do it in a process context. */
806 cmd.state = nstate;
807 cmd.arg = arg;
808 rsu_do_async(sc, rsu_newstate_cb, &cmd, sizeof(cmd));
809 return (0);
810}
811
812void
813rsu_newstate_cb(struct rsu_softc *sc, void *arg)
814{
815 struct rsu_cmd_newstate *cmd = arg;
816 struct ieee80211com *ic = &sc->sc_ic;
817 struct ifnet *ifp = &ic->ic_ific_ac.ac_if;
818 enum ieee80211_state ostate;
819 int error, s;
820
821 s = splnet()splraise(0x7);
822 ostate = ic->ic_state;
823
824 if (ostate == IEEE80211_S_RUN) {
825 /* Stop calibration. */
826 timeout_del(&sc->calib_to);
827 /* Disassociate from our current BSS. */
828 (void)rsu_disconnect(sc);
829 }
830 switch (cmd->state) {
831 case IEEE80211_S_INIT:
832 break;
833 case IEEE80211_S_SCAN:
834 error = rsu_site_survey(sc);
835 if (error != 0) {
836 printf("%s: could not send site survey command\n",
837 sc->sc_dev.dv_xname);
838 }
839 if (ifp->if_flags & IFF_DEBUG0x4)
840 printf("%s: %s -> %s\n", ifp->if_xname,
841 ieee80211_state_name[ic->ic_state],
842 ieee80211_state_name[cmd->state]);
843 ic->ic_state = cmd->state;
844 splx(s)spllower(s);
845 return;
846 case IEEE80211_S_AUTH:
847 ic->ic_bss->ni_rsn_supp_state = RSNA_SUPP_INITIALIZE;
848 error = rsu_join_bss(sc, ic->ic_bss);
849 if (error != 0) {
850 printf("%s: could not send join command\n",
851 sc->sc_dev.dv_xname);
852 ieee80211_begin_scan(&ic->ic_ific_ac.ac_if);
853 splx(s)spllower(s);
854 return;
855 }
856 if (ifp->if_flags & IFF_DEBUG0x4)
857 printf("%s: %s -> %s\n", ifp->if_xname,
858 ieee80211_state_name[ic->ic_state],
859 ieee80211_state_name[cmd->state]);
860 ic->ic_state = cmd->state;
861 if (ic->ic_flags & IEEE80211_F_RSNON0x00200000)
862 ic->ic_bss->ni_rsn_supp_state = RSNA_SUPP_PTKSTART;
863 splx(s)spllower(s);
864 return;
865 case IEEE80211_S_ASSOC:
866 /* No-op for this driver. See rsu_event_join_bss(). */
867 if (ifp->if_flags & IFF_DEBUG0x4)
868 printf("%s: %s -> %s\n", ifp->if_xname,
869 ieee80211_state_name[ic->ic_state],
870 ieee80211_state_name[cmd->state]);
871 ic->ic_state = cmd->state;
872 splx(s)spllower(s);
873 return;
874 case IEEE80211_S_RUN:
875 /* Indicate highest supported rate. */
876 ic->ic_bss->ni_txrate = ic->ic_bss->ni_rates.rs_nrates - 1;
877
878 /* Start periodic calibration. */
879 if (!usbd_is_dying(sc->sc_udev))
880 timeout_add_sec(&sc->calib_to, 2);
881 break;
882 }
883 (void)sc->sc_newstate(ic, cmd->state, cmd->arg);
884 splx(s)spllower(s);
885}
886
887int
888rsu_set_key(struct ieee80211com *ic, struct ieee80211_node *ni,
889 struct ieee80211_key *k)
890{
891 struct rsu_softc *sc = ic->ic_softcic_ac.ac_if.if_softc;
892 struct rsu_cmd_key cmd;
893
894 /* Defer setting of WEP keys until interface is brought up. */
895 if ((ic->ic_ific_ac.ac_if.if_flags & (IFF_UP0x1 | IFF_RUNNING0x40)) !=
896 (IFF_UP0x1 | IFF_RUNNING0x40))
897 return (0);
898
899 /* Do it in a process context. */
900 cmd.key = *k;
901 cmd.ni = ni;
902 rsu_do_async(sc, rsu_set_key_cb, &cmd, sizeof(cmd));
903 sc->sc_key_tasks++;
904 return EBUSY16;
905}
906
907void
908rsu_set_key_cb(struct rsu_softc *sc, void *arg)
909{
910 struct rsu_cmd_key *cmd = arg;
911 struct ieee80211com *ic = &sc->sc_ic;
912 struct ieee80211_key *k = &cmd->key;
913 struct r92s_fw_cmd_set_key key;
914
915 sc->sc_key_tasks--;
916
917 memset(&key, 0, sizeof(key))__builtin_memset((&key), (0), (sizeof(key)));
918 /* Map net80211 cipher to HW crypto algorithm. */
919 switch (k->k_cipher) {
920 case IEEE80211_CIPHER_WEP40:
921 key.algo = R92S_KEY_ALGO_WEP401;
922 break;
923 case IEEE80211_CIPHER_WEP104:
924 key.algo = R92S_KEY_ALGO_WEP1045;
925 break;
926 case IEEE80211_CIPHER_TKIP:
927 key.algo = R92S_KEY_ALGO_TKIP2;
928 break;
929 case IEEE80211_CIPHER_CCMP:
930 key.algo = R92S_KEY_ALGO_AES4;
931 break;
932 default:
933 IEEE80211_SEND_MGMT(ic, cmd->ni, IEEE80211_FC0_SUBTYPE_DEAUTH,((*(ic)->ic_send_mgmt)(ic, cmd->ni, 0xc0, IEEE80211_REASON_AUTH_LEAVE
, 0))
934 IEEE80211_REASON_AUTH_LEAVE)((*(ic)->ic_send_mgmt)(ic, cmd->ni, 0xc0, IEEE80211_REASON_AUTH_LEAVE
, 0))
;
935 ieee80211_new_state(ic, IEEE80211_S_SCAN, -1)(((ic)->ic_newstate)((ic), (IEEE80211_S_SCAN), (-1)));
936 return;
937 }
938 key.id = k->k_id;
939 key.grpkey = (k->k_flags & IEEE80211_KEY_GROUP0x00000001) != 0;
940 memcpy(key.key, k->k_key, MIN(k->k_len, sizeof(key.key)))__builtin_memcpy((key.key), (k->k_key), ((((k->k_len)<
(sizeof(key.key)))?(k->k_len):(sizeof(key.key)))))
;
941 (void)rsu_fw_cmd(sc, R92S_CMD_SET_KEY20, &key, sizeof(key));
942
943 if (sc->sc_key_tasks == 0) {
944 DPRINTF(("marking port %s valid\n",
945 ether_sprintf(cmd->ni->ni_macaddr)));
946 cmd->ni->ni_port_valid = 1;
947 ieee80211_set_link_state(ic, LINK_STATE_UP4);
948 }
949}
950
951/* ARGSUSED */
952void
953rsu_delete_key(struct ieee80211com *ic, struct ieee80211_node *ni,
954 struct ieee80211_key *k)
955{
956 struct rsu_softc *sc = ic->ic_softcic_ac.ac_if.if_softc;
957 struct rsu_cmd_key cmd;
958
959 if (!(ic->ic_ific_ac.ac_if.if_flags & IFF_RUNNING0x40) ||
960 ic->ic_state != IEEE80211_S_RUN)
961 return; /* Nothing to do. */
962
963 /* Do it in a process context. */
964 cmd.key = *k;
965 rsu_do_async(sc, rsu_delete_key_cb, &cmd, sizeof(cmd));
966}
967
968void
969rsu_delete_key_cb(struct rsu_softc *sc, void *arg)
970{
971 struct rsu_cmd_key *cmd = arg;
972 struct ieee80211_key *k = &cmd->key;
973 struct r92s_fw_cmd_set_key key;
974
975 memset(&key, 0, sizeof(key))__builtin_memset((&key), (0), (sizeof(key)));
976 key.id = k->k_id;
977 (void)rsu_fw_cmd(sc, R92S_CMD_SET_KEY20, &key, sizeof(key));
978}
979
980int
981rsu_site_survey(struct rsu_softc *sc)
982{
983 struct ieee80211com *ic = &sc->sc_ic;
984 struct r92s_fw_cmd_sitesurvey cmd;
985
986 memset(&cmd, 0, sizeof(cmd))__builtin_memset((&cmd), (0), (sizeof(cmd)));
987 if ((ic->ic_flags & IEEE80211_F_ASCAN0x00000001) || sc->scan_pass == 1)
988 cmd.active = htole32(1)((__uint32_t)(1));
989 cmd.limit = htole32(48)((__uint32_t)(48));
990 if (sc->scan_pass == 1) {
991 /* Do a directed scan for second pass. */
992 cmd.ssidlen = htole32(ic->ic_des_esslen)((__uint32_t)(ic->ic_des_esslen));
993 memcpy(cmd.ssid, ic->ic_des_essid, ic->ic_des_esslen)__builtin_memcpy((cmd.ssid), (ic->ic_des_essid), (ic->ic_des_esslen
))
;
994 }
995 DPRINTF(("sending site survey command, pass=%d\n", sc->scan_pass));
996 return (rsu_fw_cmd(sc, R92S_CMD_SITE_SURVEY18, &cmd, sizeof(cmd)));
997}
998
999int
1000rsu_join_bss(struct rsu_softc *sc, struct ieee80211_node *ni)
1001{
1002 struct ieee80211com *ic = &sc->sc_ic;
1003 struct ndis_wlan_bssid_ex *bss;
1004 struct ndis_802_11_fixed_ies *fixed;
1005 struct r92s_fw_cmd_auth auth;
1006 uint8_t buf[sizeof(*bss) + 128], *frm;
1007 uint8_t opmode;
1008 int error;
1009
1010 /* Let the FW decide the opmode based on the capinfo field. */
1011 opmode = NDIS802_11AUTOUNKNOWN2;
1012 DPRINTF(("setting operating mode to %d\n", opmode));
1013 error = rsu_fw_cmd(sc, R92S_CMD_SET_OPMODE17, &opmode, sizeof(opmode));
1014 if (error != 0)
1015 return (error);
1016
1017 memset(&auth, 0, sizeof(auth))__builtin_memset((&auth), (0), (sizeof(auth)));
1018 if (ic->ic_flags & IEEE80211_F_RSNON0x00200000) {
1019 auth.mode = R92S_AUTHMODE_WPA2;
1020 auth.dot1x = ieee80211_is_8021x_akm(ni->ni_rsnakms);
1021 } else
1022 auth.mode = R92S_AUTHMODE_OPEN0;
1023 DPRINTF(("setting auth mode to %d\n", auth.mode));
1024 error = rsu_fw_cmd(sc, R92S_CMD_SET_AUTH19, &auth, sizeof(auth));
1025 if (error != 0)
1026 return (error);
1027
1028 memset(buf, 0, sizeof(buf))__builtin_memset((buf), (0), (sizeof(buf)));
1029 bss = (struct ndis_wlan_bssid_ex *)buf;
1030 IEEE80211_ADDR_COPY(bss->macaddr, ni->ni_bssid)__builtin_memcpy((bss->macaddr), (ni->ni_bssid), (6));
1031 bss->ssid.ssidlen = htole32(ni->ni_esslen)((__uint32_t)(ni->ni_esslen));
1032 memcpy(bss->ssid.ssid, ni->ni_essid, ni->ni_esslen)__builtin_memcpy((bss->ssid.ssid), (ni->ni_essid), (ni->
ni_esslen))
;
1033 if (ic->ic_flags & (IEEE80211_F_WEPON0x00000100 | IEEE80211_F_RSNON0x00200000))
1034 bss->privacy = htole32(1)((__uint32_t)(1));
1035 bss->rssi = htole32(ni->ni_rssi)((__uint32_t)(ni->ni_rssi));
1036 if (ic->ic_curmode == IEEE80211_MODE_11B)
1037 bss->networktype = htole32(NDIS802_11DS)((__uint32_t)(1));
1038 else
1039 bss->networktype = htole32(NDIS802_11OFDM24)((__uint32_t)(3));
1040 bss->config.len = htole32(sizeof(bss->config))((__uint32_t)(sizeof(bss->config)));
1041 bss->config.bintval = htole32(ni->ni_intval)((__uint32_t)(ni->ni_intval));
1042 bss->config.dsconfig = htole32(ieee80211_chan2ieee(ic, ni->ni_chan))((__uint32_t)(ieee80211_chan2ieee(ic, ni->ni_chan)));
1043 bss->inframode = htole32(NDIS802_11INFRASTRUCTURE)((__uint32_t)(1));
1044 memcpy(bss->supprates, ni->ni_rates.rs_rates,__builtin_memcpy((bss->supprates), (ni->ni_rates.rs_rates
), (ni->ni_rates.rs_nrates))
1045 ni->ni_rates.rs_nrates)__builtin_memcpy((bss->supprates), (ni->ni_rates.rs_rates
), (ni->ni_rates.rs_nrates))
;
1046 /* Write the fixed fields of the beacon frame. */
1047 fixed = (struct ndis_802_11_fixed_ies *)&bss[1];
1048 memcpy(&fixed->tstamp, ni->ni_tstamp, 8)__builtin_memcpy((&fixed->tstamp), (ni->ni_tstamp),
(8))
;
1049 fixed->bintval = htole16(ni->ni_intval)((__uint16_t)(ni->ni_intval));
1050 fixed->capabilities = htole16(ni->ni_capinfo)((__uint16_t)(ni->ni_capinfo));
1051 /* Write IEs to be included in the association request. */
1052 frm = (uint8_t *)&fixed[1];
1053 if ((ic->ic_flags & IEEE80211_F_RSNON0x00200000) &&
1054 (ni->ni_rsnprotos & IEEE80211_PROTO_RSN(1 << 0)))
1055 frm = ieee80211_add_rsn(frm, ic, ni);
1056 if (ni->ni_flags & IEEE80211_NODE_QOS0x0002)
1057 frm = ieee80211_add_qos_capability(frm, ic);
1058 if (ni->ni_flags & IEEE80211_NODE_HT0x0400)
1059 frm = ieee80211_add_htcaps(frm, ic);
1060 if ((ic->ic_flags & IEEE80211_F_RSNON0x00200000) &&
1061 (ni->ni_rsnprotos & IEEE80211_PROTO_WPA(1 << 1)))
1062 frm = ieee80211_add_wpa(frm, ic, ni);
1063 bss->ieslen = htole32(frm - (uint8_t *)fixed)((__uint32_t)(frm - (uint8_t *)fixed));
1064 bss->len = htole32(((frm - buf) + 3) & ~3)((__uint32_t)(((frm - buf) + 3) & ~3));
1065 DPRINTF(("sending join bss command to %s chan %d\n",
1066 ether_sprintf(bss->macaddr), letoh32(bss->config.dsconfig)));
1067 return (rsu_fw_cmd(sc, R92S_CMD_JOIN_BSS14, buf, sizeof(buf)));
1068}
1069
1070int
1071rsu_disconnect(struct rsu_softc *sc)
1072{
1073 uint32_t zero = 0; /* :-) */
1074
1075 /* Disassociate from our current BSS. */
1076 DPRINTF(("sending disconnect command\n"));
1077 return (rsu_fw_cmd(sc, R92S_CMD_DISCONNECT15, &zero, sizeof(zero)));
1078}
1079
1080void
1081rsu_event_survey(struct rsu_softc *sc, uint8_t *buf, int len)
1082{
1083 struct ieee80211com *ic = &sc->sc_ic;
1084 struct ifnet *ifp = &ic->ic_ific_ac.ac_if;
1085 struct ieee80211_rxinfo rxi;
1086 struct ieee80211_node *ni;
1087 struct ieee80211_frame *wh;
1088 struct ndis_wlan_bssid_ex *bss;
1089 struct mbuf *m;
1090 uint32_t pktlen, ieslen;
1091
1092 if (__predict_false(len < sizeof(*bss))__builtin_expect(((len < sizeof(*bss)) != 0), 0))
1093 return;
1094 bss = (struct ndis_wlan_bssid_ex *)buf;
1095 ieslen = letoh32(bss->ieslen)((__uint32_t)(bss->ieslen));
1096 if (ieslen > len - sizeof(*bss))
1097 return;
1098
1099 DPRINTFN(2, ("found BSS %s: len=%d chan=%d inframode=%d "
1100 "networktype=%d privacy=%d\n",
1101 ether_sprintf(bss->macaddr), letoh32(bss->len),
1102 letoh32(bss->config.dsconfig), letoh32(bss->inframode),
1103 letoh32(bss->networktype), letoh32(bss->privacy)));
1104
1105 /* Build a fake beacon frame to let net80211 do all the parsing. */
1106 pktlen = sizeof(*wh) + ieslen;
1107 if (__predict_false(pktlen > MCLBYTES)__builtin_expect(((pktlen > (1 << 11)) != 0), 0))
1108 return;
1109 MGETHDR(m, M_DONTWAIT, MT_DATA)m = m_gethdr((0x0002), (1));
1110 if (__predict_false(m == NULL)__builtin_expect(((m == ((void *)0)) != 0), 0))
1111 return;
1112 if (pktlen > MHLEN((256 - sizeof(struct m_hdr)) - sizeof(struct pkthdr))) {
1113 MCLGET(m, M_DONTWAIT)(void) m_clget((m), (0x0002), (1 << 11));
1114 if (!(m->m_flagsm_hdr.mh_flags & M_EXT0x0001)) {
1115 m_free(m);
1116 return;
1117 }
1118 }
1119 wh = mtod(m, struct ieee80211_frame *)((struct ieee80211_frame *)((m)->m_hdr.mh_data));
1120 wh->i_fc[0] = IEEE80211_FC0_VERSION_00x00 | IEEE80211_FC0_TYPE_MGT0x00 |
1121 IEEE80211_FC0_SUBTYPE_BEACON0x80;
1122 wh->i_fc[1] = IEEE80211_FC1_DIR_NODS0x00;
1123 *(uint16_t *)wh->i_dur = 0;
1124 IEEE80211_ADDR_COPY(wh->i_addr1, etherbroadcastaddr)__builtin_memcpy((wh->i_addr1), (etherbroadcastaddr), (6));
1125 IEEE80211_ADDR_COPY(wh->i_addr2, bss->macaddr)__builtin_memcpy((wh->i_addr2), (bss->macaddr), (6));
1126 IEEE80211_ADDR_COPY(wh->i_addr3, bss->macaddr)__builtin_memcpy((wh->i_addr3), (bss->macaddr), (6));
1127 *(uint16_t *)wh->i_seq = 0;
1128 memcpy(&wh[1], (uint8_t *)&bss[1], ieslen)__builtin_memcpy((&wh[1]), ((uint8_t *)&bss[1]), (ieslen
))
;
1129
1130 /* Finalize mbuf. */
1131 m->m_pkthdrM_dat.MH.MH_pkthdr.len = m->m_lenm_hdr.mh_len = pktlen;
1132
1133 ni = ieee80211_find_rxnode(ic, wh);
1134 rxi.rxi_flags = 0;
1135 rxi.rxi_rssi = letoh32(bss->rssi)((__uint32_t)(bss->rssi));
1136 rxi.rxi_tstamp = 0;
1137 ieee80211_input(ifp, m, ni, &rxi);
1138 /* Node is no longer needed. */
1139 ieee80211_release_node(ic, ni);
1140}
1141
1142void
1143rsu_event_join_bss(struct rsu_softc *sc, uint8_t *buf, int len)
1144{
1145 struct ieee80211com *ic = &sc->sc_ic;
1146 struct ieee80211_node *ni = ic->ic_bss;
1147 struct r92s_event_join_bss *rsp;
1148 int res;
1149
1150 if (__predict_false(len < sizeof(*rsp))__builtin_expect(((len < sizeof(*rsp)) != 0), 0))
1151 return;
1152 rsp = (struct r92s_event_join_bss *)buf;
1153 res = (int)letoh32(rsp->join_res)((__uint32_t)(rsp->join_res));
1154
1155 DPRINTF(("Rx join BSS event len=%d res=%d\n", len, res));
1156 if (res <= 0) {
1157 ic->ic_stats.is_rx_auth_fail++;
1158 ieee80211_new_state(ic, IEEE80211_S_SCAN, -1)(((ic)->ic_newstate)((ic), (IEEE80211_S_SCAN), (-1)));
1159 return;
1160 }
1161 DPRINTF(("associated with %s associd=%d\n",
1162 ether_sprintf(rsp->bss.macaddr), letoh32(rsp->associd)));
1163
1164 ni->ni_associd = letoh32(rsp->associd)((__uint32_t)(rsp->associd)) | 0xc000;
1165 if (ic->ic_flags & IEEE80211_F_WEPON0x00000100)
1166 ni->ni_flags |= IEEE80211_NODE_TXRXPROT(0x0010 | 0x0008);
1167
1168 /* Force an ASSOC->RUN transition. AUTH->RUN is invalid. */
1169 ic->ic_state = IEEE80211_S_ASSOC;
1170 ieee80211_new_state(ic, IEEE80211_S_RUN,(((ic)->ic_newstate)((ic), (IEEE80211_S_RUN), (0x10)))
1171 IEEE80211_FC0_SUBTYPE_ASSOC_RESP)(((ic)->ic_newstate)((ic), (IEEE80211_S_RUN), (0x10)));
1172}
1173
1174void
1175rsu_rx_event(struct rsu_softc *sc, uint8_t code, uint8_t *buf, int len)
1176{
1177 struct ieee80211com *ic = &sc->sc_ic;
1178 struct ifnet *ifp = &ic->ic_ific_ac.ac_if;
1179
1180 DPRINTFN(4, ("Rx event code=%d len=%d\n", code, len));
1181 switch (code) {
1182 case R92S_EVT_SURVEY8:
1183 if (ic->ic_state == IEEE80211_S_SCAN)
1184 rsu_event_survey(sc, buf, len);
1185 break;
1186 case R92S_EVT_SURVEY_DONE9:
1187 DPRINTF(("site survey pass %d done, found %d BSS\n",
1188 sc->scan_pass, letoh32(*(uint32_t *)buf)));
1189 if (ic->ic_state != IEEE80211_S_SCAN)
1190 break; /* Ignore if not scanning. */
1191 if (sc->scan_pass == 0 && ic->ic_des_esslen != 0) {
1192 /* Schedule a directed scan for hidden APs. */
1193 sc->scan_pass = 1;
1194 ieee80211_new_state(ic, IEEE80211_S_SCAN, -1)(((ic)->ic_newstate)((ic), (IEEE80211_S_SCAN), (-1)));
1195 break;
1196 }
1197 ieee80211_end_scan(ifp);
1198 sc->scan_pass = 0;
1199 break;
1200 case R92S_EVT_JOIN_BSS10:
1201 if (ic->ic_state == IEEE80211_S_AUTH)
1202 rsu_event_join_bss(sc, buf, len);
1203 break;
1204 case R92S_EVT_DEL_STA12:
1205 DPRINTF(("disassociated from %s\n", ether_sprintf(buf)));
1206 if (ic->ic_state == IEEE80211_S_RUN &&
1207 IEEE80211_ADDR_EQ(ic->ic_bss->ni_bssid, buf)(__builtin_memcmp((ic->ic_bss->ni_bssid), (buf), (6)) ==
0)
)
1208 ieee80211_new_state(ic, IEEE80211_S_SCAN, -1)(((ic)->ic_newstate)((ic), (IEEE80211_S_SCAN), (-1)));
1209 break;
1210 case R92S_EVT_WPS_PBC24:
1211 DPRINTF(("WPS PBC pushed.\n"));
1212 break;
1213 case R92S_EVT_FWDBG19:
1214 if (ifp->if_flags & IFF_DEBUG0x4) {
1215 buf[60] = '\0';
1216 printf("FWDBG: %s\n", (char *)buf);
1217 }
1218 break;
1219 }
1220}
1221
1222void
1223rsu_rx_multi_event(struct rsu_softc *sc, uint8_t *buf, int len)
1224{
1225 struct r92s_fw_cmd_hdr *cmd;
1226 int cmdsz;
1227
1228 DPRINTFN(6, ("Rx events len=%d\n", len));
1229
1230 /* Skip Rx status. */
1231 buf += sizeof(struct r92s_rx_stat);
1232 len -= sizeof(struct r92s_rx_stat);
1233
1234 /* Process all events. */
1235 for (;;) {
1236 /* Check that command header fits. */
1237 if (__predict_false(len < sizeof(*cmd))__builtin_expect(((len < sizeof(*cmd)) != 0), 0))
1238 break;
1239 cmd = (struct r92s_fw_cmd_hdr *)buf;
1240 /* Check that command payload fits. */
1241 cmdsz = letoh16(cmd->len)((__uint16_t)(cmd->len));
1242 if (__predict_false(len < sizeof(*cmd) + cmdsz)__builtin_expect(((len < sizeof(*cmd) + cmdsz) != 0), 0))
1243 break;
1244 if (cmdsz > len)
1245 break;
1246
1247 /* Process firmware event. */
1248 rsu_rx_event(sc, cmd->code, (uint8_t *)&cmd[1], cmdsz);
1249
1250 if (!(cmd->seq & R92S_FW_CMD_MORE0x80))
1251 break;
1252 buf += sizeof(*cmd) + cmdsz;
1253 len -= sizeof(*cmd) + cmdsz;
1254 }
1255}
1256
1257int8_t
1258rsu_get_rssi(struct rsu_softc *sc, int rate, void *physt)
1259{
1260 static const int8_t cckoff[] = { 14, -2, -20, -40 };
1261 struct r92s_rx_phystat *phy;
1262 struct r92s_rx_cck *cck;
1263 uint8_t rpt;
1264 int8_t rssi;
1265
1266 if (rate <= 3) {
1267 cck = (struct r92s_rx_cck *)physt;
1268 rpt = (cck->agc_rpt >> 6) & 0x3;
1269 rssi = cck->agc_rpt & 0x3e;
1270 rssi = cckoff[rpt] - rssi;
1271 } else { /* OFDM/HT. */
1272 phy = (struct r92s_rx_phystat *)physt;
1273 rssi = ((letoh32(phy->phydw1)((__uint32_t)(phy->phydw1)) >> 1) & 0x7f) - 106;
1274 }
1275 return (rssi);
1276}
1277
1278void
1279rsu_rx_frame(struct rsu_softc *sc, uint8_t *buf, int pktlen,
1280 struct mbuf_list *ml)
1281{
1282 struct ieee80211com *ic = &sc->sc_ic;
1283 struct ifnet *ifp = &ic->ic_ific_ac.ac_if;
1284 struct ieee80211_rxinfo rxi;
1285 struct ieee80211_frame *wh;
1286 struct ieee80211_node *ni;
1287 struct r92s_rx_stat *stat;
1288 uint32_t rxdw0, rxdw3;
1289 struct mbuf *m;
1290 uint8_t rate;
1291 int8_t rssi = 0;
1292 int s, infosz;
1293
1294 stat = (struct r92s_rx_stat *)buf;
1295 rxdw0 = letoh32(stat->rxdw0)((__uint32_t)(stat->rxdw0));
1296 rxdw3 = letoh32(stat->rxdw3)((__uint32_t)(stat->rxdw3));
1297
1298 if (__predict_false(rxdw0 & R92S_RXDW0_CRCERR)__builtin_expect(((rxdw0 & 0x00004000) != 0), 0)) {
1299 ifp->if_ierrorsif_data.ifi_ierrors++;
1300 return;
1301 }
1302 if (__predict_false(pktlen < sizeof(*wh) || pktlen > MCLBYTES)__builtin_expect(((pktlen < sizeof(*wh) || pktlen > (1 <<
11)) != 0), 0)
) {
1303 ifp->if_ierrorsif_data.ifi_ierrors++;
1304 return;
1305 }
1306
1307 rate = MS(rxdw3, R92S_RXDW3_RATE)(((rxdw3) & 0x0000003f) >> 0);
1308 infosz = MS(rxdw0, R92S_RXDW0_INFOSZ)(((rxdw0) & 0x000f0000) >> 16) * 8;
1309
1310 /* Get RSSI from PHY status descriptor if present. */
1311 if (infosz != 0)
1312 rssi = rsu_get_rssi(sc, rate, &stat[1]);
1313
1314 DPRINTFN(5, ("Rx frame len=%d rate=%d infosz=%d rssi=%d\n",
1315 pktlen, rate, infosz, rssi));
1316
1317 MGETHDR(m, M_DONTWAIT, MT_DATA)m = m_gethdr((0x0002), (1));
1318 if (__predict_false(m == NULL)__builtin_expect(((m == ((void *)0)) != 0), 0)) {
1319 ifp->if_ierrorsif_data.ifi_ierrors++;
1320 return;
1321 }
1322 if (pktlen > MHLEN((256 - sizeof(struct m_hdr)) - sizeof(struct pkthdr))) {
1323 MCLGET(m, M_DONTWAIT)(void) m_clget((m), (0x0002), (1 << 11));
1324 if (__predict_false(!(m->m_flags & M_EXT))__builtin_expect(((!(m->m_hdr.mh_flags & 0x0001)) != 0
), 0)
) {
1325 ifp->if_ierrorsif_data.ifi_ierrors++;
1326 m_freem(m);
1327 return;
1328 }
1329 }
1330 /* Finalize mbuf. */
1331 /* Hardware does Rx TCP checksum offload. */
1332 if (rxdw3 & R92S_RXDW3_TCPCHKVALID0x00002000) {
1333 if (__predict_true(rxdw3 & R92S_RXDW3_TCPCHKRPT)__builtin_expect(((rxdw3 & 0x00000800) != 0), 1))
1334 m->m_pkthdrM_dat.MH.MH_pkthdr.csum_flags |= M_TCP_CSUM_IN_OK0x0020;
1335 else
1336 m->m_pkthdrM_dat.MH.MH_pkthdr.csum_flags |= M_TCP_CSUM_IN_BAD0x0040;
1337 }
1338 wh = (struct ieee80211_frame *)((uint8_t *)&stat[1] + infosz);
1339 memcpy(mtod(m, uint8_t *), wh, pktlen)__builtin_memcpy((((uint8_t *)((m)->m_hdr.mh_data))), (wh)
, (pktlen))
;
1340 m->m_pkthdrM_dat.MH.MH_pkthdr.len = m->m_lenm_hdr.mh_len = pktlen;
1341
1342 s = splnet()splraise(0x7);
1343#if NBPFILTER1 > 0
1344 if (__predict_false(sc->sc_drvbpf != NULL)__builtin_expect(((sc->sc_drvbpf != ((void *)0)) != 0), 0)) {
1345 struct rsu_rx_radiotap_header *tap = &sc->sc_rxtapsc_rxtapu.th;
1346 struct mbuf mb;
1347
1348 tap->wr_flags = 0;
1349 /* Map HW rate index to 802.11 rate. */
1350 tap->wr_flags = 2;
1351 if (!(rxdw3 & R92S_RXDW3_HTC0x00004000)) {
1352 switch (rate) {
1353 /* CCK. */
1354 case 0: tap->wr_rate = 2; break;
1355 case 1: tap->wr_rate = 4; break;
1356 case 2: tap->wr_rate = 11; break;
1357 case 3: tap->wr_rate = 22; break;
1358 /* OFDM. */
1359 case 4: tap->wr_rate = 12; break;
1360 case 5: tap->wr_rate = 18; break;
1361 case 6: tap->wr_rate = 24; break;
1362 case 7: tap->wr_rate = 36; break;
1363 case 8: tap->wr_rate = 48; break;
1364 case 9: tap->wr_rate = 72; break;
1365 case 10: tap->wr_rate = 96; break;
1366 case 11: tap->wr_rate = 108; break;
1367 }
1368 } else if (rate >= 12) { /* MCS0~15. */
1369 /* Bit 7 set means HT MCS instead of rate. */
1370 tap->wr_rate = 0x80 | (rate - 12);
1371 }
1372 tap->wr_dbm_antsignal = rssi;
1373 tap->wr_chan_freq = htole16(ic->ic_bss->ni_chan->ic_freq)((__uint16_t)(ic->ic_bss->ni_chan->ic_freq));
1374 tap->wr_chan_flags = htole16(ic->ic_bss->ni_chan->ic_flags)((__uint16_t)(ic->ic_bss->ni_chan->ic_flags));
1375
1376 mb.m_datam_hdr.mh_data = (caddr_t)tap;
1377 mb.m_lenm_hdr.mh_len = sc->sc_rxtap_len;
1378 mb.m_nextm_hdr.mh_next = m;
1379 mb.m_nextpktm_hdr.mh_nextpkt = NULL((void *)0);
1380 mb.m_typem_hdr.mh_type = 0;
1381 mb.m_flagsm_hdr.mh_flags = 0;
1382 bpf_mtap(sc->sc_drvbpf, &mb, BPF_DIRECTION_IN(1 << 0));
1383 }
1384#endif
1385
1386 ni = ieee80211_find_rxnode(ic, wh);
1387 rxi.rxi_flags = 0;
1388 rxi.rxi_rssi = rssi;
1389 rxi.rxi_tstamp = 0; /* Unused. */
1390 ieee80211_inputm(ifp, m, ni, &rxi, ml);
1391 /* Node is no longer needed. */
1392 ieee80211_release_node(ic, ni);
1393 splx(s)spllower(s);
1394}
1395
1396void
1397rsu_rx_multi_frame(struct rsu_softc *sc, uint8_t *buf, int len)
1398{
1399 struct mbuf_list ml = MBUF_LIST_INITIALIZER(){ ((void *)0), ((void *)0), 0 };
1400 struct r92s_rx_stat *stat;
1401 uint32_t rxdw0;
1402 int totlen, pktlen, infosz, npkts;
1403
1404 /* Get the number of encapsulated frames. */
1405 stat = (struct r92s_rx_stat *)buf;
1406 npkts = MS(letoh32(stat->rxdw2), R92S_RXDW2_PKTCNT)(((((__uint32_t)(stat->rxdw2))) & 0x00ff0000) >>
16)
;
1407 DPRINTFN(6, ("Rx %d frames in one chunk\n", npkts));
1408
1409 /* Process all of them. */
1410 while (npkts-- > 0) {
1411 if (__predict_false(len < sizeof(*stat))__builtin_expect(((len < sizeof(*stat)) != 0), 0))
1412 break;
1413 stat = (struct r92s_rx_stat *)buf;
1414 rxdw0 = letoh32(stat->rxdw0)((__uint32_t)(stat->rxdw0));
1415
1416 pktlen = MS(rxdw0, R92S_RXDW0_PKTLEN)(((rxdw0) & 0x00003fff) >> 0);
1417 if (__predict_false(pktlen == 0)__builtin_expect(((pktlen == 0) != 0), 0))
1418 break;
1419
1420 infosz = MS(rxdw0, R92S_RXDW0_INFOSZ)(((rxdw0) & 0x000f0000) >> 16) * 8;
1421
1422 /* Make sure everything fits in xfer. */
1423 totlen = sizeof(*stat) + infosz + pktlen;
1424 if (__predict_false(totlen > len)__builtin_expect(((totlen > len) != 0), 0))
1425 break;
1426
1427 /* Process 802.11 frame. */
1428 rsu_rx_frame(sc, buf, pktlen, &ml);
1429
1430 /* Next chunk is 128-byte aligned. */
1431 totlen = (totlen + 127) & ~127;
1432 buf += totlen;
1433 len -= totlen;
1434 }
1435 if_input(&sc->sc_ic.ic_ific_ac.ac_if, &ml);
1436}
1437
1438void
1439rsu_rxeof(struct usbd_xfer *xfer, void *priv, usbd_status status)
1440{
1441 struct rsu_rx_data *data = priv;
1442 struct rsu_softc *sc = data->sc;
1443 struct r92s_rx_stat *stat;
1444 struct ifnet *ifp = &sc->sc_ic.ic_ific_ac.ac_if;
1445 int len;
1446
1447 if (__predict_false(status != USBD_NORMAL_COMPLETION)__builtin_expect(((status != USBD_NORMAL_COMPLETION) != 0), 0
)
) {
1448 DPRINTF(("RX status=%d\n", status));
1449 if (status == USBD_STALLED)
1450 usbd_clear_endpoint_stall_async(data->pipe);
1451 if (status != USBD_CANCELLED)
1452 goto resubmit;
1453 return;
1454 }
1455 usbd_get_xfer_status(xfer, NULL((void *)0), NULL((void *)0), &len, NULL((void *)0));
1456
1457 if (__predict_false(len < sizeof(*stat))__builtin_expect(((len < sizeof(*stat)) != 0), 0)) {
1458 DPRINTF(("xfer too short %d\n", len));
1459 ifp->if_ierrorsif_data.ifi_ierrors++;
1460 goto resubmit;
1461 }
1462 if (len > RSU_RXBUFSZ(8 * 1024)) {
1463 DPRINTF(("xfer too large %d\n", len));
1464 ifp->if_ierrorsif_data.ifi_ierrors++;
1465 goto resubmit;
1466 }
1467
1468 /* Determine if it is a firmware C2H event or an 802.11 frame. */
1469 stat = (struct r92s_rx_stat *)data->buf;
1470 if ((letoh32(stat->rxdw1)((__uint32_t)(stat->rxdw1)) & 0x1ff) == 0x1ff)
1471 rsu_rx_multi_event(sc, data->buf, len);
1472 else
1473 rsu_rx_multi_frame(sc, data->buf, len);
1474
1475 resubmit:
1476 /* Setup a new transfer. */
1477 usbd_setup_xfer(xfer, data->pipe, data, data->buf, RSU_RXBUFSZ(8 * 1024),
1478 USBD_SHORT_XFER_OK0x04 | USBD_NO_COPY0x01, USBD_NO_TIMEOUT0, rsu_rxeof);
1479 (void)usbd_transfer(xfer);
1480}
1481
1482void
1483rsu_txeof(struct usbd_xfer *xfer, void *priv, usbd_status status)
1484{
1485 struct rsu_tx_data *data = priv;
1486 struct rsu_softc *sc = data->sc;
1487 struct ifnet *ifp = &sc->sc_ic.ic_ific_ac.ac_if;
1488 int s;
1489
1490 s = splnet()splraise(0x7);
1491 /* Put this Tx buffer back to our free list. */
1492 TAILQ_INSERT_TAIL(&sc->tx_free_list, data, next)do { (data)->next.tqe_next = ((void *)0); (data)->next.
tqe_prev = (&sc->tx_free_list)->tqh_last; *(&sc
->tx_free_list)->tqh_last = (data); (&sc->tx_free_list
)->tqh_last = &(data)->next.tqe_next; } while (0)
;
1493
1494 if (__predict_false(status != USBD_NORMAL_COMPLETION)__builtin_expect(((status != USBD_NORMAL_COMPLETION) != 0), 0
)
) {
1495 DPRINTF(("TX status=%d\n", status));
1496 if (status == USBD_STALLED)
1497 usbd_clear_endpoint_stall_async(data->pipe);
1498 ifp->if_oerrorsif_data.ifi_oerrors++;
1499 splx(s)spllower(s);
1500 return;
1501 }
1502 sc->sc_tx_timer = 0;
1503
1504 /* We just released a Tx buffer, notify Tx. */
1505 if (ifq_is_oactive(&ifp->if_snd)) {
1506 ifq_clr_oactive(&ifp->if_snd);
1507 rsu_start(ifp);
1508 }
1509 splx(s)spllower(s);
1510}
1511
1512int
1513rsu_tx(struct rsu_softc *sc, struct mbuf *m, struct ieee80211_node *ni)
1514{
1515 struct ieee80211com *ic = &sc->sc_ic;
1516 struct ieee80211_frame *wh;
1517 struct ieee80211_key *k = NULL((void *)0);
1518 struct rsu_tx_data *data;
1519 struct r92s_tx_desc *txd;
1520 struct usbd_pipe *pipe;
1521 uint16_t qos;
1522 uint8_t type, qid, tid = 0;
1523 int hasqos, xferlen, error;
1524
1525 wh = mtod(m, struct ieee80211_frame *)((struct ieee80211_frame *)((m)->m_hdr.mh_data));
1526 type = wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK0x0c;
1527
1528 if (wh->i_fc[1] & IEEE80211_FC1_PROTECTED0x40) {
1529 k = ieee80211_get_txkey(ic, wh, ni);
1530 if ((m = ieee80211_encrypt(ic, m, k)) == NULL((void *)0))
1531 return (ENOBUFS55);
1532 wh = mtod(m, struct ieee80211_frame *)((struct ieee80211_frame *)((m)->m_hdr.mh_data));
1533 }
1534 if ((hasqos = ieee80211_has_qos(wh))) {
1535 qos = ieee80211_get_qos(wh);
1536 tid = qos & IEEE80211_QOS_TID0x000f;
1537 qid = rsu_ac2qid[ieee80211_up_to_ac(ic, tid)];
1538 } else
1539 qid = RSU_QID_BE5;
1540
1541 /* Get the USB pipe to use for this queue id. */
1542 pipe = sc->pipe[sc->qid2idx[qid]];
1543
1544 /* Grab a Tx buffer from our free list. */
1545 data = TAILQ_FIRST(&sc->tx_free_list)((&sc->tx_free_list)->tqh_first);
1546 TAILQ_REMOVE(&sc->tx_free_list, data, next)do { if (((data)->next.tqe_next) != ((void *)0)) (data)->
next.tqe_next->next.tqe_prev = (data)->next.tqe_prev; else
(&sc->tx_free_list)->tqh_last = (data)->next.tqe_prev
; *(data)->next.tqe_prev = (data)->next.tqe_next; ((data
)->next.tqe_prev) = ((void *)-1); ((data)->next.tqe_next
) = ((void *)-1); } while (0)
;
1547
1548 /* Fill Tx descriptor. */
1549 txd = (struct r92s_tx_desc *)data->buf;
1550 memset(txd, 0, sizeof(*txd))__builtin_memset((txd), (0), (sizeof(*txd)));
1551
1552 txd->txdw0 |= htole32(((__uint32_t)((((m->M_dat.MH.MH_pkthdr.len) << 0) &
0x0000ffff) | (((sizeof(*txd)) << 16) & 0x00ff0000
) | 0x80000000 | 0x08000000 | 0x04000000))
1553 SM(R92S_TXDW0_PKTLEN, m->m_pkthdr.len) |((__uint32_t)((((m->M_dat.MH.MH_pkthdr.len) << 0) &
0x0000ffff) | (((sizeof(*txd)) << 16) & 0x00ff0000
) | 0x80000000 | 0x08000000 | 0x04000000))
1554 SM(R92S_TXDW0_OFFSET, sizeof(*txd)) |((__uint32_t)((((m->M_dat.MH.MH_pkthdr.len) << 0) &
0x0000ffff) | (((sizeof(*txd)) << 16) & 0x00ff0000
) | 0x80000000 | 0x08000000 | 0x04000000))
1555 R92S_TXDW0_OWN | R92S_TXDW0_FSG | R92S_TXDW0_LSG)((__uint32_t)((((m->M_dat.MH.MH_pkthdr.len) << 0) &
0x0000ffff) | (((sizeof(*txd)) << 16) & 0x00ff0000
) | 0x80000000 | 0x08000000 | 0x04000000))
;
1556
1557 txd->txdw1 |= htole32(((__uint32_t)((((5) << 0) & 0x0000001f) | (((0x03) <<
8) & 0x00001f00)))
1558 SM(R92S_TXDW1_MACID, R92S_MACID_BSS) |((__uint32_t)((((5) << 0) & 0x0000001f) | (((0x03) <<
8) & 0x00001f00)))
1559 SM(R92S_TXDW1_QSEL, R92S_TXDW1_QSEL_BE))((__uint32_t)((((5) << 0) & 0x0000001f) | (((0x03) <<
8) & 0x00001f00)))
;
1560 if (!hasqos)
1561 txd->txdw1 |= htole32(R92S_TXDW1_NONQOS)((__uint32_t)(0x00010000));
1562#ifdef notyet
1563 if (k != NULL((void *)0)) {
1564 switch (k->k_cipher) {
1565 case IEEE80211_CIPHER_WEP40:
1566 case IEEE80211_CIPHER_WEP104:
1567 cipher = R92S_TXDW1_CIPHER_WEP1;
1568 break;
1569 case IEEE80211_CIPHER_TKIP:
1570 cipher = R92S_TXDW1_CIPHER_TKIP2;
1571 break;
1572 case IEEE80211_CIPHER_CCMP:
1573 cipher = R92S_TXDW1_CIPHER_AES3;
1574 break;
1575 default:
1576 cipher = R92S_TXDW1_CIPHER_NONE;
1577 }
1578 txd->txdw1 |= htole32(((__uint32_t)((((cipher) << 22) & 0x00c00000) | (((
k->k_id) << 17) & 0x00060000)))
1579 SM(R92S_TXDW1_CIPHER, cipher) |((__uint32_t)((((cipher) << 22) & 0x00c00000) | (((
k->k_id) << 17) & 0x00060000)))
1580 SM(R92S_TXDW1_KEYIDX, k->k_id))((__uint32_t)((((cipher) << 22) & 0x00c00000) | (((
k->k_id) << 17) & 0x00060000)))
;
1581 }
1582#endif
1583 txd->txdw2 |= htole32(R92S_TXDW2_BK)((__uint32_t)(0x40000000));
1584 if (IEEE80211_IS_MULTICAST(wh->i_addr1)(*(wh->i_addr1) & 0x01))
1585 txd->txdw2 |= htole32(R92S_TXDW2_BMCAST)((__uint32_t)(0x00000080));
1586 /*
1587 * Firmware will use and increment the sequence number for the
1588 * specified TID.
1589 */
1590 txd->txdw3 |= htole32(SM(R92S_TXDW3_SEQ, tid))((__uint32_t)((((tid) << 16) & 0x0fff0000)));
1591
1592#if NBPFILTER1 > 0
1593 if (__predict_false(sc->sc_drvbpf != NULL)__builtin_expect(((sc->sc_drvbpf != ((void *)0)) != 0), 0)) {
1594 struct rsu_tx_radiotap_header *tap = &sc->sc_txtapsc_txtapu.th;
1595 struct mbuf mb;
1596
1597 tap->wt_flags = 0;
1598 tap->wt_chan_freq = htole16(ic->ic_bss->ni_chan->ic_freq)((__uint16_t)(ic->ic_bss->ni_chan->ic_freq));
1599 tap->wt_chan_flags = htole16(ic->ic_bss->ni_chan->ic_flags)((__uint16_t)(ic->ic_bss->ni_chan->ic_flags));
1600
1601 mb.m_datam_hdr.mh_data = (caddr_t)tap;
1602 mb.m_lenm_hdr.mh_len = sc->sc_txtap_len;
1603 mb.m_nextm_hdr.mh_next = m;
1604 mb.m_nextpktm_hdr.mh_nextpkt = NULL((void *)0);
1605 mb.m_typem_hdr.mh_type = 0;
1606 mb.m_flagsm_hdr.mh_flags = 0;
1607 bpf_mtap(sc->sc_drvbpf, &mb, BPF_DIRECTION_OUT(1 << 1));
1608 }
1609#endif
1610
1611 xferlen = sizeof(*txd) + m->m_pkthdrM_dat.MH.MH_pkthdr.len;
1612 m_copydata(m, 0, m->m_pkthdrM_dat.MH.MH_pkthdr.len, &txd[1]);
1613 m_freem(m);
1614
1615 data->pipe = pipe;
1616 usbd_setup_xfer(data->xfer, pipe, data, data->buf, xferlen,
1617 USBD_FORCE_SHORT_XFER0x08 | USBD_NO_COPY0x01, RSU_TX_TIMEOUT5000,
1618 rsu_txeof);
1619 error = usbd_transfer(data->xfer);
1620 if (__predict_false(error != USBD_IN_PROGRESS && error != 0)__builtin_expect(((error != USBD_IN_PROGRESS && error
!= 0) != 0), 0)
) {
1621 /* Put this Tx buffer back to our free list. */
1622 TAILQ_INSERT_TAIL(&sc->tx_free_list, data, next)do { (data)->next.tqe_next = ((void *)0); (data)->next.
tqe_prev = (&sc->tx_free_list)->tqh_last; *(&sc
->tx_free_list)->tqh_last = (data); (&sc->tx_free_list
)->tqh_last = &(data)->next.tqe_next; } while (0)
;
1623 return (error);
1624 }
1625 ieee80211_release_node(ic, ni);
1626 return (0);
1627}
1628
1629/* ARGSUSED */
1630int
1631rsu_send_mgmt(struct ieee80211com *ic, struct ieee80211_node *ni, int type,
1632 int arg1, int arg2)
1633{
1634 return (EOPNOTSUPP45);
1635}
1636
1637void
1638rsu_start(struct ifnet *ifp)
1639{
1640 struct rsu_softc *sc = ifp->if_softc;
1641 struct ieee80211com *ic = &sc->sc_ic;
1642 struct ieee80211_node *ni;
1643 struct mbuf *m;
1644
1645 if (!(ifp->if_flags & IFF_RUNNING0x40) || ifq_is_oactive(&ifp->if_snd))
1646 return;
1647
1648 for (;;) {
1649 if (TAILQ_EMPTY(&sc->tx_free_list)(((&sc->tx_free_list)->tqh_first) == ((void *)0))) {
1650 ifq_set_oactive(&ifp->if_snd);
1651 break;
1652 }
1653 if (ic->ic_state != IEEE80211_S_RUN)
1654 break;
1655
1656 /* Encapsulate and send data frames. */
1657 m = ifq_dequeue(&ifp->if_snd);
1658 if (m == NULL((void *)0))
1659 break;
1660#if NBPFILTER1 > 0
1661 if (ifp->if_bpf != NULL((void *)0))
1662 bpf_mtap(ifp->if_bpf, m, BPF_DIRECTION_OUT(1 << 1));
1663#endif
1664 if ((m = ieee80211_encap(ifp, m, &ni)) == NULL((void *)0))
1665 continue;
1666
1667#if NBPFILTER1 > 0
1668 if (ic->ic_rawbpf != NULL((void *)0))
1669 bpf_mtap(ic->ic_rawbpf, m, BPF_DIRECTION_OUT(1 << 1));
1670#endif
1671 if (rsu_tx(sc, m, ni) != 0) {
1672 ieee80211_release_node(ic, ni);
1673 ifp->if_oerrorsif_data.ifi_oerrors++;
1674 continue;
1675 }
1676
1677 sc->sc_tx_timer = 5;
1678 ifp->if_timer = 1;
1679 }
1680}
1681
1682void
1683rsu_watchdog(struct ifnet *ifp)
1684{
1685 struct rsu_softc *sc = ifp->if_softc;
1686
1687 ifp->if_timer = 0;
1688
1689 if (sc->sc_tx_timer > 0) {
1690 if (--sc->sc_tx_timer == 0) {
1691 printf("%s: device timeout\n", sc->sc_dev.dv_xname);
1692 /* rsu_init(ifp); XXX needs a process context! */
1693 ifp->if_oerrorsif_data.ifi_oerrors++;
1694 return;
1695 }
1696 ifp->if_timer = 1;
1697 }
1698 ieee80211_watchdog(ifp);
1699}
1700
1701int
1702rsu_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
1703{
1704 struct rsu_softc *sc = ifp->if_softc;
1705 int s, error = 0;
1706
1707 if (usbd_is_dying(sc->sc_udev))
1708 return ENXIO6;
1709
1710 usbd_ref_incr(sc->sc_udev);
1711
1712 s = splnet()splraise(0x7);
1713
1714 switch (cmd) {
1715 case SIOCSIFADDR((unsigned long)0x80000000 | ((sizeof(struct ifreq) & 0x1fff
) << 16) | ((('i')) << 8) | ((12)))
:
1716 ifp->if_flags |= IFF_UP0x1;
1717 /* FALLTHROUGH */
1718 case SIOCSIFFLAGS((unsigned long)0x80000000 | ((sizeof(struct ifreq) & 0x1fff
) << 16) | ((('i')) << 8) | ((16)))
:
1719 if (ifp->if_flags & IFF_UP0x1) {
1720 if (!(ifp->if_flags & IFF_RUNNING0x40))
1721 rsu_init(ifp);
1722 } else {
1723 if (ifp->if_flags & IFF_RUNNING0x40)
1724 rsu_stop(ifp);
1725 }
1726 break;
1727 default:
1728 error = ieee80211_ioctl(ifp, cmd, data);
1729 }
1730
1731 if (error == ENETRESET52) {
1732 if ((ifp->if_flags & (IFF_UP0x1 | IFF_RUNNING0x40)) ==
1733 (IFF_UP0x1 | IFF_RUNNING0x40)) {
1734 rsu_stop(ifp);
1735 rsu_init(ifp);
1736 }
1737 error = 0;
1738 }
1739 splx(s)spllower(s);
1740
1741 usbd_ref_decr(sc->sc_udev);
1742
1743 return (error);
1744}
1745
1746/*
1747 * Power on sequence for A-cut adapters.
1748 */
1749void
1750rsu_power_on_acut(struct rsu_softc *sc)
1751{
1752 uint32_t reg;
1753
1754 rsu_write_1(sc, R92S_SPS0_CTRL(0x0000 + 0x011) + 1, 0x53);
1755 rsu_write_1(sc, R92S_SPS0_CTRL(0x0000 + 0x011) + 0, 0x57);
1756
1757 /* Enable AFE macro block's bandgap and Mbias. */
1758 rsu_write_1(sc, R92S_AFE_MISC(0x0000 + 0x010),
1759 rsu_read_1(sc, R92S_AFE_MISC(0x0000 + 0x010)) |
1760 R92S_AFE_MISC_BGEN0x01 | R92S_AFE_MISC_MBEN0x02);
1761 /* Enable LDOA15 block. */
1762 rsu_write_1(sc, R92S_LDOA15_CTRL(0x0000 + 0x020),
1763 rsu_read_1(sc, R92S_LDOA15_CTRL(0x0000 + 0x020)) | R92S_LDA15_EN0x01);
1764
1765 rsu_write_1(sc, R92S_SPS1_CTRL(0x0000 + 0x018),
1766 rsu_read_1(sc, R92S_SPS1_CTRL(0x0000 + 0x018)) | R92S_SPS1_LDEN0x01);
1767 usbd_delay_ms(sc->sc_udev, 2);
1768 /* Enable switch regulator block. */
1769 rsu_write_1(sc, R92S_SPS1_CTRL(0x0000 + 0x018),
1770 rsu_read_1(sc, R92S_SPS1_CTRL(0x0000 + 0x018)) | R92S_SPS1_SWEN0x02);
1771
1772 rsu_write_4(sc, R92S_SPS1_CTRL(0x0000 + 0x018), 0x00a7b267);
1773
1774 rsu_write_1(sc, R92S_SYS_ISO_CTRL(0x0000 + 0x000) + 1,
1775 rsu_read_1(sc, R92S_SYS_ISO_CTRL(0x0000 + 0x000) + 1) | 0x08);
1776
1777 rsu_write_1(sc, R92S_SYS_FUNC_EN(0x0000 + 0x002) + 1,
1778 rsu_read_1(sc, R92S_SYS_FUNC_EN(0x0000 + 0x002) + 1) | 0x20);
1779
1780 rsu_write_1(sc, R92S_SYS_ISO_CTRL(0x0000 + 0x000) + 1,
1781 rsu_read_1(sc, R92S_SYS_ISO_CTRL(0x0000 + 0x000) + 1) & ~0x90);
1782
1783 /* Enable AFE clock. */
1784 rsu_write_1(sc, R92S_AFE_XTAL_CTRL(0x0000 + 0x026) + 1,
1785 rsu_read_1(sc, R92S_AFE_XTAL_CTRL(0x0000 + 0x026) + 1) & ~0x04);
1786 /* Enable AFE PLL macro block. */
1787 rsu_write_1(sc, R92S_AFE_PLL_CTRL(0x0000 + 0x028),
1788 rsu_read_1(sc, R92S_AFE_PLL_CTRL(0x0000 + 0x028)) | 0x11);
1789 /* Attach AFE PLL to MACTOP/BB. */
1790 rsu_write_1(sc, R92S_SYS_ISO_CTRL(0x0000 + 0x000),
1791 rsu_read_1(sc, R92S_SYS_ISO_CTRL(0x0000 + 0x000)) & ~0x11);
1792
1793 /* Switch to 40MHz clock instead of 80MHz. */
1794 rsu_write_2(sc, R92S_SYS_CLKR(0x0000 + 0x008),
1795 rsu_read_2(sc, R92S_SYS_CLKR(0x0000 + 0x008)) & ~R92S_SYS_CLKSEL0x0001);
1796
1797 /* Enable MAC clock. */
1798 rsu_write_2(sc, R92S_SYS_CLKR(0x0000 + 0x008),
1799 rsu_read_2(sc, R92S_SYS_CLKR(0x0000 + 0x008)) |
1800 R92S_MAC_CLK_EN0x0800 | R92S_SYS_CLK_EN0x1000);
1801
1802 rsu_write_1(sc, R92S_PMC_FSM(0x0000 + 0x004), 0x02);
1803
1804 /* Enable digital core and IOREG R/W. */
1805 rsu_write_1(sc, R92S_SYS_FUNC_EN(0x0000 + 0x002) + 1,
1806 rsu_read_1(sc, R92S_SYS_FUNC_EN(0x0000 + 0x002) + 1) | 0x08);
1807
1808 rsu_write_1(sc, R92S_SYS_FUNC_EN(0x0000 + 0x002) + 1,
1809 rsu_read_1(sc, R92S_SYS_FUNC_EN(0x0000 + 0x002) + 1) | 0x80);
1810
1811 /* Switch the control path to firmware. */
1812 reg = rsu_read_2(sc, R92S_SYS_CLKR(0x0000 + 0x008));
1813 reg = (reg & ~R92S_SWHW_SEL0x4000) | R92S_FWHW_SEL0x8000;
1814 rsu_write_2(sc, R92S_SYS_CLKR(0x0000 + 0x008), reg);
1815
1816 rsu_write_2(sc, R92S_CR(0x0040 + 0x000), 0x37fc);
1817
1818 /* Fix USB RX FIFO issue. */
1819 rsu_write_1(sc, 0xfe5c,
1820 rsu_read_1(sc, 0xfe5c) | 0x80);
1821 rsu_write_1(sc, 0x00ab,
1822 rsu_read_1(sc, 0x00ab) | 0xc0);
1823
1824 rsu_write_1(sc, R92S_SYS_CLKR(0x0000 + 0x008),
1825 rsu_read_1(sc, R92S_SYS_CLKR(0x0000 + 0x008)) & ~R92S_SYS_CPU_CLKSEL0x0004);
1826}
1827
1828/*
1829 * Power on sequence for B-cut and C-cut adapters.
1830 */
1831void
1832rsu_power_on_bcut(struct rsu_softc *sc)
1833{
1834 uint32_t reg;
1835 int ntries;
1836
1837 /* Prevent eFuse leakage. */
1838 rsu_write_1(sc, 0x37, 0xb0);
1839 usbd_delay_ms(sc->sc_udev, 10);
1840 rsu_write_1(sc, 0x37, 0x30);
1841
1842 /* Switch the control path to hardware. */
1843 reg = rsu_read_2(sc, R92S_SYS_CLKR(0x0000 + 0x008));
1844 if (reg & R92S_FWHW_SEL0x8000) {
1845 rsu_write_2(sc, R92S_SYS_CLKR(0x0000 + 0x008),
1846 reg & ~(R92S_SWHW_SEL0x4000 | R92S_FWHW_SEL0x8000));
1847 }
1848 rsu_write_1(sc, R92S_SYS_FUNC_EN(0x0000 + 0x002) + 1,
1849 rsu_read_1(sc, R92S_SYS_FUNC_EN(0x0000 + 0x002) + 1) & ~0x8c);
1850 DELAY(1000)(*delay_func)(1000);
1851
1852 rsu_write_1(sc, R92S_SPS0_CTRL(0x0000 + 0x011) + 1, 0x53);
1853 rsu_write_1(sc, R92S_SPS0_CTRL(0x0000 + 0x011) + 0, 0x57);
1854
1855 reg = rsu_read_1(sc, R92S_AFE_MISC(0x0000 + 0x010));
1856 rsu_write_1(sc, R92S_AFE_MISC(0x0000 + 0x010), reg | R92S_AFE_MISC_BGEN0x01);
1857 rsu_write_1(sc, R92S_AFE_MISC(0x0000 + 0x010), reg | R92S_AFE_MISC_BGEN0x01 |
1858 R92S_AFE_MISC_MBEN0x02 | R92S_AFE_MISC_I32_EN0x08);
1859
1860 /* Enable PLL. */
1861 rsu_write_1(sc, R92S_LDOA15_CTRL(0x0000 + 0x020),
1862 rsu_read_1(sc, R92S_LDOA15_CTRL(0x0000 + 0x020)) | R92S_LDA15_EN0x01);
1863
1864 rsu_write_1(sc, R92S_LDOV12D_CTRL(0x0000 + 0x021),
1865 rsu_read_1(sc, R92S_LDOV12D_CTRL(0x0000 + 0x021)) | R92S_LDV12_EN0x01);
1866
1867 rsu_write_1(sc, R92S_SYS_ISO_CTRL(0x0000 + 0x000) + 1,
1868 rsu_read_1(sc, R92S_SYS_ISO_CTRL(0x0000 + 0x000) + 1) | 0x08);
1869
1870 rsu_write_1(sc, R92S_SYS_FUNC_EN(0x0000 + 0x002) + 1,
1871 rsu_read_1(sc, R92S_SYS_FUNC_EN(0x0000 + 0x002) + 1) | 0x20);
1872
1873 /* Support 64KB IMEM. */
1874 rsu_write_1(sc, R92S_SYS_ISO_CTRL(0x0000 + 0x000) + 1,
1875 rsu_read_1(sc, R92S_SYS_ISO_CTRL(0x0000 + 0x000) + 1) & ~0x97);
1876
1877 /* Enable AFE clock. */
1878 rsu_write_1(sc, R92S_AFE_XTAL_CTRL(0x0000 + 0x026) + 1,
1879 rsu_read_1(sc, R92S_AFE_XTAL_CTRL(0x0000 + 0x026) + 1) & ~0x04);
1880 /* Enable AFE PLL macro block. */
1881 reg = rsu_read_1(sc, R92S_AFE_PLL_CTRL(0x0000 + 0x028));
1882 rsu_write_1(sc, R92S_AFE_PLL_CTRL(0x0000 + 0x028), reg | 0x11);
1883 DELAY(500)(*delay_func)(500);
1884 rsu_write_1(sc, R92S_AFE_PLL_CTRL(0x0000 + 0x028), reg | 0x51);
1885 DELAY(500)(*delay_func)(500);
1886 rsu_write_1(sc, R92S_AFE_PLL_CTRL(0x0000 + 0x028), reg | 0x11);
1887 DELAY(500)(*delay_func)(500);
1888
1889 /* Attach AFE PLL to MACTOP/BB. */
1890 rsu_write_1(sc, R92S_SYS_ISO_CTRL(0x0000 + 0x000),
1891 rsu_read_1(sc, R92S_SYS_ISO_CTRL(0x0000 + 0x000)) & ~0x11);
1892
1893 /* Switch to 40MHz clock. */
1894 rsu_write_1(sc, R92S_SYS_CLKR(0x0000 + 0x008), 0x00);
1895 /* Disable CPU clock and 80MHz SSC. */
1896 rsu_write_1(sc, R92S_SYS_CLKR(0x0000 + 0x008),
1897 rsu_read_1(sc, R92S_SYS_CLKR(0x0000 + 0x008)) | 0xa0);
1898 /* Enable MAC clock. */
1899 rsu_write_2(sc, R92S_SYS_CLKR(0x0000 + 0x008),
1900 rsu_read_2(sc, R92S_SYS_CLKR(0x0000 + 0x008)) |
1901 R92S_MAC_CLK_EN0x0800 | R92S_SYS_CLK_EN0x1000);
1902
1903 rsu_write_1(sc, R92S_PMC_FSM(0x0000 + 0x004), 0x02);
1904
1905 /* Enable digital core and IOREG R/W. */
1906 rsu_write_1(sc, R92S_SYS_FUNC_EN(0x0000 + 0x002) + 1,
1907 rsu_read_1(sc, R92S_SYS_FUNC_EN(0x0000 + 0x002) + 1) | 0x08);
1908
1909 rsu_write_1(sc, R92S_SYS_FUNC_EN(0x0000 + 0x002) + 1,
1910 rsu_read_1(sc, R92S_SYS_FUNC_EN(0x0000 + 0x002) + 1) | 0x80);
1911
1912 /* Switch the control path to firmware. */
1913 reg = rsu_read_2(sc, R92S_SYS_CLKR(0x0000 + 0x008));
1914 reg = (reg & ~R92S_SWHW_SEL0x4000) | R92S_FWHW_SEL0x8000;
1915 rsu_write_2(sc, R92S_SYS_CLKR(0x0000 + 0x008), reg);
1916
1917 rsu_write_2(sc, R92S_CR(0x0040 + 0x000), 0x37fc);
1918
1919 /* Fix USB RX FIFO issue. */
1920 rsu_write_1(sc, 0xfe5c,
1921 rsu_read_1(sc, 0xfe5c) | 0x80);
1922
1923 rsu_write_1(sc, R92S_SYS_CLKR(0x0000 + 0x008),
1924 rsu_read_1(sc, R92S_SYS_CLKR(0x0000 + 0x008)) & ~R92S_SYS_CPU_CLKSEL0x0004);
1925
1926 rsu_write_1(sc, 0xfe1c, 0x80);
1927
1928 /* Make sure TxDMA is ready to download firmware. */
1929 for (ntries = 0; ntries < 20; ntries++) {
1930 reg = rsu_read_1(sc, R92S_TCR(0x0040 + 0x004));
1931 if ((reg & (R92S_TCR_IMEM_CHK_RPT0x02 | R92S_TCR_EMEM_CHK_RPT0x08)) ==
1932 (R92S_TCR_IMEM_CHK_RPT0x02 | R92S_TCR_EMEM_CHK_RPT0x08))
1933 break;
1934 DELAY(5)(*delay_func)(5);
1935 }
1936 if (ntries == 20) {
1937 /* Reset TxDMA. */
1938 reg = rsu_read_1(sc, R92S_CR(0x0040 + 0x000));
1939 rsu_write_1(sc, R92S_CR(0x0040 + 0x000), reg & ~R92S_CR_TXDMA_EN0x10);
1940 DELAY(2)(*delay_func)(2);
1941 rsu_write_1(sc, R92S_CR(0x0040 + 0x000), reg | R92S_CR_TXDMA_EN0x10);
1942 }
1943}
1944
1945void
1946rsu_power_off(struct rsu_softc *sc)
1947{
1948 /* Turn RF off. */
1949 rsu_write_1(sc, R92S_RF_CTRL(0x0000 + 0x01f), 0x00);
1950 usbd_delay_ms(sc->sc_udev, 5);
1951
1952 /* Turn MAC off. */
1953 /* Switch control path. */
1954 rsu_write_1(sc, R92S_SYS_CLKR(0x0000 + 0x008) + 1, 0x38);
1955 /* Reset MACTOP. */
1956 rsu_write_1(sc, R92S_SYS_FUNC_EN(0x0000 + 0x002) + 1, 0x70);
1957 rsu_write_1(sc, R92S_PMC_FSM(0x0000 + 0x004), 0x06);
1958 rsu_write_1(sc, R92S_SYS_ISO_CTRL(0x0000 + 0x000) + 0, 0xf9);
1959 rsu_write_1(sc, R92S_SYS_ISO_CTRL(0x0000 + 0x000) + 1, 0xe8);
1960
1961 /* Disable AFE PLL. */
1962 rsu_write_1(sc, R92S_AFE_PLL_CTRL(0x0000 + 0x028), 0x00);
1963 /* Disable A15V. */
1964 rsu_write_1(sc, R92S_LDOA15_CTRL(0x0000 + 0x020), 0x54);
1965 /* Disable eFuse 1.2V. */
1966 rsu_write_1(sc, R92S_SYS_FUNC_EN(0x0000 + 0x002) + 1, 0x50);
1967 rsu_write_1(sc, R92S_LDOV12D_CTRL(0x0000 + 0x021), 0x24);
1968 /* Enable AFE macro block's bandgap and Mbias. */
1969 rsu_write_1(sc, R92S_AFE_MISC(0x0000 + 0x010), 0x30);
1970 /* Disable 1.6V LDO. */
1971 rsu_write_1(sc, R92S_SPS0_CTRL(0x0000 + 0x011) + 0, 0x56);
1972 rsu_write_1(sc, R92S_SPS0_CTRL(0x0000 + 0x011) + 1, 0x43);
1973}
1974
1975int
1976rsu_fw_loadsection(struct rsu_softc *sc, uint8_t *buf, int len)
1977{
1978 struct rsu_tx_data *data;
1979 struct r92s_tx_desc *txd;
1980 struct usbd_pipe *pipe;
1981 int mlen, error;
1982
1983 data = sc->fwcmd_data;
1984 pipe = sc->pipe[sc->qid2idx[RSU_QID_VO3]];
1985 txd = (struct r92s_tx_desc *)data->buf;
1986 while (len > 0) {
1987 memset(txd, 0, sizeof(*txd))__builtin_memset((txd), (0), (sizeof(*txd)));
1988 if (len <= RSU_TXBUFSZ((sizeof(struct r92s_tx_desc) + (2300 + 4 + (3 + 1 + 4)) + 3)
& ~3)
- sizeof(*txd)) {
1989 /* Last chunk. */
1990 txd->txdw0 |= htole32(R92S_TXDW0_LINIP)((__uint32_t)(0x10000000));
1991 mlen = len;
1992 } else
1993 mlen = RSU_TXBUFSZ((sizeof(struct r92s_tx_desc) + (2300 + 4 + (3 + 1 + 4)) + 3)
& ~3)
- sizeof(*txd);
1994 txd->txdw0 |= htole32(SM(R92S_TXDW0_PKTLEN, mlen))((__uint32_t)((((mlen) << 0) & 0x0000ffff)));
1995 memcpy(&txd[1], buf, mlen)__builtin_memcpy((&txd[1]), (buf), (mlen));
1996
1997 usbd_setup_xfer(data->xfer, pipe, NULL((void *)0), data->buf,
1998 sizeof(*txd) + mlen,
1999 USBD_SHORT_XFER_OK0x04 | USBD_NO_COPY0x01 | USBD_SYNCHRONOUS0x02,
2000 RSU_TX_TIMEOUT5000, NULL((void *)0));
2001 error = usbd_transfer(data->xfer);
2002 if (error != 0)
2003 return (error);
2004 buf += mlen;
2005 len -= mlen;
2006 }
2007 return (0);
2008}
2009
2010int
2011rsu_load_firmware(struct rsu_softc *sc)
2012{
2013 struct ieee80211com *ic = &sc->sc_ic;
2014 struct r92s_fw_hdr *hdr;
2015 struct r92s_fw_priv *dmem;
2016 uint8_t *imem, *emem;
2017 int imemsz, ememsz;
2018 u_char *fw;
2019 size_t size;
2020 uint32_t reg;
2021 int ntries, error;
2022
2023 /* Read firmware image from the filesystem. */
2024 if ((error = loadfirmware("rsu-rtl8712", &fw, &size)) != 0) {
2025 printf("%s: failed loadfirmware of file %s (error %d)\n",
2026 sc->sc_dev.dv_xname, "rsu-rtl8712", error);
2027 return (error);
2028 }
2029 if (size < sizeof(*hdr)) {
2030 printf("%s: firmware too short\n", sc->sc_dev.dv_xname);
2031 error = EINVAL22;
2032 goto fail;
2033 }
2034 hdr = (struct r92s_fw_hdr *)fw;
2035 if (hdr->signature != htole16(0x8712)((__uint16_t)(0x8712)) &&
2036 hdr->signature != htole16(0x8192)((__uint16_t)(0x8192))) {
2037 printf("%s: invalid firmware signature 0x%x\n",
2038 sc->sc_dev.dv_xname, letoh16(hdr->signature)((__uint16_t)(hdr->signature)));
2039 error = EINVAL22;
2040 goto fail;
2041 }
2042 DPRINTF(("FW V%d %02x-%02x %02x:%02x\n", letoh16(hdr->version),
2043 hdr->month, hdr->day, hdr->hour, hdr->minute));
2044
2045 /* Make sure that driver and firmware are in sync. */
2046 if (hdr->privsz != htole32(sizeof(*dmem))((__uint32_t)(sizeof(*dmem)))) {
2047 printf("%s: unsupported firmware image\n",
2048 sc->sc_dev.dv_xname);
2049 error = EINVAL22;
2050 goto fail;
2051 }
2052 /* Get FW sections sizes. */
2053 imemsz = letoh32(hdr->imemsz)((__uint32_t)(hdr->imemsz));
2054 ememsz = letoh32(hdr->sramsz)((__uint32_t)(hdr->sramsz));
2055 /* Check that all FW sections fit in image. */
2056 if (size < sizeof(*hdr) + imemsz + ememsz) {
2057 printf("%s: firmware too short\n", sc->sc_dev.dv_xname);
2058 error = EINVAL22;
2059 goto fail;
2060 }
2061 imem = (uint8_t *)&hdr[1];
2062 emem = imem + imemsz;
2063
2064 /* Load IMEM section. */
2065 error = rsu_fw_loadsection(sc, imem, imemsz);
2066 if (error != 0) {
2067 printf("%s: could not load firmware section %s\n",
2068 sc->sc_dev.dv_xname, "IMEM");
2069 goto fail;
2070 }
2071 /* Wait for load to complete. */
2072 for (ntries = 0; ntries < 10; ntries++) {
2073 reg = rsu_read_2(sc, R92S_TCR(0x0040 + 0x004));
2074 if (reg & R92S_TCR_IMEM_CODE_DONE0x01)
2075 break;
2076 DELAY(10)(*delay_func)(10);
2077 }
2078 if (ntries == 10 || !(reg & R92S_TCR_IMEM_CHK_RPT0x02)) {
2079 printf("%s: timeout waiting for %s transfer\n",
2080 sc->sc_dev.dv_xname, "IMEM");
2081 error = ETIMEDOUT60;
2082 goto fail;
2083 }
2084
2085 /* Load EMEM section. */
2086 error = rsu_fw_loadsection(sc, emem, ememsz);
2087 if (error != 0) {
2088 printf("%s: could not load firmware section %s\n",
2089 sc->sc_dev.dv_xname, "EMEM");
2090 goto fail;
2091 }
2092 /* Wait for load to complete. */
2093 for (ntries = 0; ntries < 10; ntries++) {
2094 reg = rsu_read_2(sc, R92S_TCR(0x0040 + 0x004));
2095 if (reg & R92S_TCR_EMEM_CODE_DONE0x04)
2096 break;
2097 DELAY(10)(*delay_func)(10);
2098 }
2099 if (ntries == 10 || !(reg & R92S_TCR_EMEM_CHK_RPT0x08)) {
2100 printf("%s: timeout waiting for %s transfer\n",
2101 sc->sc_dev.dv_xname, "EMEM");
2102 error = ETIMEDOUT60;
2103 goto fail;
2104 }
2105
2106 /* Enable CPU. */
2107 rsu_write_1(sc, R92S_SYS_CLKR(0x0000 + 0x008),
2108 rsu_read_1(sc, R92S_SYS_CLKR(0x0000 + 0x008)) | R92S_SYS_CPU_CLKSEL0x0004);
2109 if (!(rsu_read_1(sc, R92S_SYS_CLKR(0x0000 + 0x008)) & R92S_SYS_CPU_CLKSEL0x0004)) {
2110 printf("%s: could not enable system clock\n",
2111 sc->sc_dev.dv_xname);
2112 error = EIO5;
2113 goto fail;
2114 }
2115 rsu_write_2(sc, R92S_SYS_FUNC_EN(0x0000 + 0x002),
2116 rsu_read_2(sc, R92S_SYS_FUNC_EN(0x0000 + 0x002)) | R92S_FEN_CPUEN0x0400);
2117 if (!(rsu_read_2(sc, R92S_SYS_FUNC_EN(0x0000 + 0x002)) & R92S_FEN_CPUEN0x0400)) {
2118 printf("%s: could not enable microcontroller\n",
2119 sc->sc_dev.dv_xname);
2120 error = EIO5;
2121 goto fail;
2122 }
2123 /* Wait for CPU to initialize. */
2124 for (ntries = 0; ntries < 100; ntries++) {
2125 if (rsu_read_2(sc, R92S_TCR(0x0040 + 0x004)) & R92S_TCR_IMEM_RDY0x20)
2126 break;
2127 DELAY(1000)(*delay_func)(1000);
2128 }
2129 if (ntries == 100) {
2130 printf("%s: timeout waiting for microcontroller\n",
2131 sc->sc_dev.dv_xname);
2132 error = ETIMEDOUT60;
2133 goto fail;
2134 }
2135
2136 /* Update DMEM section before loading. */
2137 dmem = &hdr->priv;
2138 memset(dmem, 0, sizeof(*dmem))__builtin_memset((dmem), (0), (sizeof(*dmem)));
2139 dmem->hci_sel = R92S_HCI_SEL_USB0x02 | R92S_HCI_SEL_81720x10;
2140 dmem->nendpoints = sc->npipes;
2141 dmem->rf_config = 0x12; /* 1T2R */
2142 dmem->vcs_type = R92S_VCS_TYPE_AUTO2;
2143 dmem->vcs_mode = R92S_VCS_MODE_RTS_CTS1;
2144 dmem->bw40_en = (ic->ic_htcaps & IEEE80211_HTCAP_CBW20_400x00000002) != 0;
2145 dmem->turbo_mode = 1;
2146 /* Load DMEM section. */
2147 error = rsu_fw_loadsection(sc, (uint8_t *)dmem, sizeof(*dmem));
2148 if (error != 0) {
2149 printf("%s: could not load firmware section %s\n",
2150 sc->sc_dev.dv_xname, "DMEM");
2151 goto fail;
2152 }
2153 /* Wait for load to complete. */
2154 for (ntries = 0; ntries < 100; ntries++) {
2155 if (rsu_read_2(sc, R92S_TCR(0x0040 + 0x004)) & R92S_TCR_DMEM_CODE_DONE0x10)
2156 break;
2157 DELAY(1000)(*delay_func)(1000);
2158 }
2159 if (ntries == 100) {
2160 printf("%s: timeout waiting for %s transfer\n",
2161 sc->sc_dev.dv_xname, "DMEM");
2162 error = ETIMEDOUT60;
2163 goto fail;
2164 }
2165 /* Wait for firmware readiness. */
2166 for (ntries = 0; ntries < 60; ntries++) {
2167 if (!(rsu_read_2(sc, R92S_TCR(0x0040 + 0x004)) & R92S_TCR_FWRDY0x80))
2168 break;
2169 DELAY(1000)(*delay_func)(1000);
2170 }
2171 if (ntries == 60) {
2172 printf("%s: timeout waiting for firmware readiness\n",
2173 sc->sc_dev.dv_xname);
2174 error = ETIMEDOUT60;
2175 goto fail;
2176 }
2177 fail:
2178 free(fw, M_DEVBUF2, size);
2179 return (error);
2180}
2181
2182int
2183rsu_init(struct ifnet *ifp)
2184{
2185 struct rsu_softc *sc = ifp->if_softc;
2186 struct ieee80211com *ic = &sc->sc_ic;
2187 struct r92s_set_pwr_mode cmd;
2188 struct rsu_rx_data *data;
2189 int i, error;
2190
2191 /* Init host async commands ring. */
2192 sc->cmdq.cur = sc->cmdq.next = sc->cmdq.queued = 0;
2193
2194 /* Allocate Tx/Rx buffers. */
2195 error = rsu_alloc_rx_list(sc);
2196 if (error != 0) {
2197 printf("%s: could not allocate Rx buffers\n",
2198 sc->sc_dev.dv_xname);
2199 goto fail;
2200 }
2201 error = rsu_alloc_tx_list(sc);
2202 if (error != 0) {
2203 printf("%s: could not allocate Tx buffers\n",
2204 sc->sc_dev.dv_xname);
2205 goto fail;
2206 }
2207 /* Reserve one Tx buffer for firmware commands. */
2208 sc->fwcmd_data = TAILQ_FIRST(&sc->tx_free_list)((&sc->tx_free_list)->tqh_first);
2209 TAILQ_REMOVE(&sc->tx_free_list, sc->fwcmd_data, next)do { if (((sc->fwcmd_data)->next.tqe_next) != ((void *)
0)) (sc->fwcmd_data)->next.tqe_next->next.tqe_prev =
(sc->fwcmd_data)->next.tqe_prev; else (&sc->tx_free_list
)->tqh_last = (sc->fwcmd_data)->next.tqe_prev; *(sc->
fwcmd_data)->next.tqe_prev = (sc->fwcmd_data)->next.
tqe_next; ((sc->fwcmd_data)->next.tqe_prev) = ((void *)
-1); ((sc->fwcmd_data)->next.tqe_next) = ((void *)-1); }
while (0)
;
2210
2211 /* Power on adapter. */
2212 if (sc->cut == 1)
2213 rsu_power_on_acut(sc);
2214 else
2215 rsu_power_on_bcut(sc);
2216 /* Load firmware. */
2217 error = rsu_load_firmware(sc);
2218 if (error != 0)
2219 goto fail;
2220
2221 /* Enable Rx TCP checksum offload. */
2222 rsu_write_4(sc, R92S_RCR(0x0040 + 0x008),
2223 rsu_read_4(sc, R92S_RCR(0x0040 + 0x008)) | 0x04000000);
2224 /* Append PHY status. */
2225 rsu_write_4(sc, R92S_RCR(0x0040 + 0x008),
2226 rsu_read_4(sc, R92S_RCR(0x0040 + 0x008)) | 0x02000000);
2227
2228 rsu_write_4(sc, R92S_CR(0x0040 + 0x000),
2229 rsu_read_4(sc, R92S_CR(0x0040 + 0x000)) & ~0xff000000);
2230
2231 /* Use 128 bytes pages. */
2232 rsu_write_1(sc, 0x00b5,
2233 rsu_read_1(sc, 0x00b5) | 0x01);
2234 /* Enable USB Rx aggregation. */
2235 rsu_write_1(sc, 0x00bd,
2236 rsu_read_1(sc, 0x00bd) | 0x80);
2237 /* Set USB Rx aggregation threshold. */
2238 rsu_write_1(sc, 0x00d9, 0x01);
2239 /* Set USB Rx aggregation timeout (1.7ms/4). */
2240 rsu_write_1(sc, 0xfe5b, 0x04);
2241 /* Fix USB Rx FIFO issue. */
2242 rsu_write_1(sc, 0xfe5c,
2243 rsu_read_1(sc, 0xfe5c) | 0x80);
2244
2245 /* Set MAC address. */
2246 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))
;
2247 rsu_write_region_1(sc, R92S_MACID(0x0050 + 0x000), ic->ic_myaddr, IEEE80211_ADDR_LEN6);
2248
2249 /* Queue Rx xfers (XXX C2H pipe for 11-pipe configurations?) */
2250 for (i = 0; i < RSU_RX_LIST_COUNT1; i++) {
2251 data = &sc->rx_data[i];
2252
2253 data->pipe = sc->pipe[sc->qid2idx[RSU_QID_RXOFF7]];
2254 usbd_setup_xfer(data->xfer, data->pipe, data, data->buf,
2255 RSU_RXBUFSZ(8 * 1024), USBD_SHORT_XFER_OK0x04 | USBD_NO_COPY0x01,
2256 USBD_NO_TIMEOUT0, rsu_rxeof);
2257 error = usbd_transfer(data->xfer);
2258 if (error != 0 && error != USBD_IN_PROGRESS)
2259 goto fail;
2260 }
2261
2262 /* NB: it really takes that long for firmware to boot. */
2263 usbd_delay_ms(sc->sc_udev, 1500);
2264
2265 DPRINTF(("setting MAC address to %s\n", ether_sprintf(ic->ic_myaddr)));
2266 error = rsu_fw_cmd(sc, R92S_CMD_SET_MAC_ADDRESS58, ic->ic_myaddr,
2267 IEEE80211_ADDR_LEN6);
2268 if (error != 0) {
2269 printf("%s: could not set MAC address\n", sc->sc_dev.dv_xname);
2270 goto fail;
2271 }
2272
2273 rsu_write_1(sc, R92S_USB_HRPWM0xfe58,
2274 R92S_USB_HRPWM_PS_ST_ACTIVE0x08 | R92S_USB_HRPWM_PS_ALL_ON0x04);
2275
2276 memset(&cmd, 0, sizeof(cmd))__builtin_memset((&cmd), (0), (sizeof(cmd)));
2277 cmd.mode = R92S_PS_MODE_ACTIVE0;
2278 DPRINTF(("setting ps mode to %d\n", cmd.mode));
2279 error = rsu_fw_cmd(sc, R92S_CMD_SET_PWR_MODE36, &cmd, sizeof(cmd));
2280 if (error != 0) {
2281 printf("%s: could not set PS mode\n", sc->sc_dev.dv_xname);
2282 goto fail;
2283 }
2284
2285 if (ic->ic_htcaps & IEEE80211_HTCAP_CBW20_400x00000002) {
2286 /* Enable 40MHz mode. */
2287 error = rsu_fw_iocmd(sc,
2288 SM(R92S_IOCMD_CLASS, 0xf4)(((0xf4) << 24) & 0xff000000) |
2289 SM(R92S_IOCMD_INDEX, 0x00)(((0x00) << 0) & 0x000000ff) |
2290 SM(R92S_IOCMD_VALUE, 0x0007)(((0x0007) << 8) & 0x00ffff00));
2291 if (error != 0) {
2292 printf("%s: could not enable 40MHz mode\n",
2293 sc->sc_dev.dv_xname);
2294 goto fail;
2295 }
2296 }
2297
2298 /* Set default channel. */
2299 ic->ic_bss->ni_chan = ic->ic_ibss_chan;
2300
2301 /* We're ready to go. */
2302 ifp->if_flags |= IFF_RUNNING0x40;
2303 ifq_clr_oactive(&ifp->if_snd);
2304
2305#ifdef notyet
2306 if (ic->ic_flags & IEEE80211_F_WEPON0x00000100) {
2307 /* Install WEP keys. */
2308 for (i = 0; i < IEEE80211_WEP_NKID4; i++)
2309 rsu_set_key(ic, NULL((void *)0), &ic->ic_nw_keys[i]);
2310 rsu_wait_async(sc);
2311 }
2312#endif
2313
2314 sc->scan_pass = 0;
2315 ieee80211_begin_scan(ifp);
2316 return (0);
2317 fail:
2318 rsu_stop(ifp);
2319 return (error);
2320}
2321
2322void
2323rsu_stop(struct ifnet *ifp)
2324{
2325 struct rsu_softc *sc = ifp->if_softc;
2326 struct ieee80211com *ic = &sc->sc_ic;
2327 int i, s;
2328
2329 sc->sc_tx_timer = 0;
2330 ifp->if_timer = 0;
2331 ifp->if_flags &= ~IFF_RUNNING0x40;
2332 ifq_clr_oactive(&ifp->if_snd);
2333
2334 s = splusb()splraise(0x5);
2335 ieee80211_new_state(ic, IEEE80211_S_INIT, -1)(((ic)->ic_newstate)((ic), (IEEE80211_S_INIT), (-1)));
2336 /* Wait for all async commands to complete. */
2337 rsu_wait_async(sc);
2338 splx(s)spllower(s);
2339
2340 timeout_del(&sc->calib_to);
2341
2342 /* Power off adapter. */
2343 rsu_power_off(sc);
2344
2345 /* Abort Tx/Rx. */
2346 for (i = 0; i < sc->npipes; i++)
2347 usbd_abort_pipe(sc->pipe[i]);
2348
2349 /* Free Tx/Rx buffers. */
2350 rsu_free_tx_list(sc);
2351 rsu_free_rx_list(sc);
2352}