Bug Summary

File:dev/usb/if_rsu.c
Warning:line 370, column 12
The left operand of '!=' is a garbage value

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_rsu.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_rsu.c
1/* $OpenBSD: if_rsu.c,v 1.52 2023/03/08 04:43:08 guenther 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)
1
Assuming field 'cut' is equal to 3
2
Taking false branch
222 sc->cut = (sc->cut >> 1) + 1;
223
224 error = rsu_read_rom(sc);
225 if (error != 0) {
3
Assuming 'error' is equal to 0
4
Taking false branch
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)
5
Calling 'rsu_open_pipes'
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(0x2);
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;
6
'error' declared without an initial value
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)
7
Assuming field 'npipes' is not equal to 4
8
Taking false branch
353 sc->qid2idx = rsu_qid2idx_4ep;
354 else if (sc->npipes == 6)
9
Assuming field 'npipes' is not equal to 6
10
Taking false branch
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++) {
11
Assuming the condition is true
12
'?' condition is true
13
Assuming the condition is false
14
Loop condition is false. Execution continues on line 370
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)
15
The left operand of '!=' is a garbage value
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(0x2);
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(0x2);
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(0x2);
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
773void
774rsu_calib_cb(struct rsu_softc *sc, void *arg)
775{
776 uint32_t reg;
777
778#ifdef notyet
779 /* Read WPS PBC status. */
780 rsu_write_1(sc, R92S_MAC_PINMUX_CTRL(0x01e0 + 0x011),
781 R92S_GPIOMUX_EN0x08 | SM(R92S_GPIOSEL_GPIO, R92S_GPIOSEL_GPIO_JTAG)(((0) << 0) & 0x03));
782 rsu_write_1(sc, R92S_GPIO_IO_SEL(0x01e0 + 0x00e),
783 rsu_read_1(sc, R92S_GPIO_IO_SEL(0x01e0 + 0x00e)) & ~R92S_GPIO_WPS0x10);
784 reg = rsu_read_1(sc, R92S_GPIO_CTRL(0x01e0 + 0x00c));
785 if (reg != 0xff && (reg & R92S_GPIO_WPS0x10))
786 DPRINTF(("WPS PBC is pushed\n"));
787#endif
788 /* Read current signal level. */
789 if (rsu_fw_iocmd(sc, 0xf4000001) == 0) {
790 reg = rsu_read_4(sc, R92S_IOCMD_DATA0x0374);
791 DPRINTFN(8, ("RSSI=%d%%\n", reg >> 4));
792 }
793
794 if (!usbd_is_dying(sc->sc_udev))
795 timeout_add_sec(&sc->calib_to, 2);
796}
797
798int
799rsu_newstate(struct ieee80211com *ic, enum ieee80211_state nstate, int arg)
800{
801 struct rsu_softc *sc = ic->ic_softcic_ac.ac_if.if_softc;
802 struct rsu_cmd_newstate cmd;
803
804 /* Do it in a process context. */
805 cmd.state = nstate;
806 cmd.arg = arg;
807 rsu_do_async(sc, rsu_newstate_cb, &cmd, sizeof(cmd));
808 return (0);
809}
810
811void
812rsu_newstate_cb(struct rsu_softc *sc, void *arg)
813{
814 struct rsu_cmd_newstate *cmd = arg;
815 struct ieee80211com *ic = &sc->sc_ic;
816 struct ifnet *ifp = &ic->ic_ific_ac.ac_if;
817 enum ieee80211_state ostate;
818 int error, s;
819
820 s = splnet()splraise(0x4);
821 ostate = ic->ic_state;
822
823 if (ostate == IEEE80211_S_RUN) {
824 /* Stop calibration. */
825 timeout_del(&sc->calib_to);
826 /* Disassociate from our current BSS. */
827 (void)rsu_disconnect(sc);
828 }
829 switch (cmd->state) {
830 case IEEE80211_S_INIT:
831 break;
832 case IEEE80211_S_SCAN:
833 error = rsu_site_survey(sc);
834 if (error != 0) {
835 printf("%s: could not send site survey command\n",
836 sc->sc_dev.dv_xname);
837 }
838 if (ifp->if_flags & IFF_DEBUG0x4)
839 printf("%s: %s -> %s\n", ifp->if_xname,
840 ieee80211_state_name[ic->ic_state],
841 ieee80211_state_name[cmd->state]);
842 ic->ic_state = cmd->state;
843 splx(s)spllower(s);
844 return;
845 case IEEE80211_S_AUTH:
846 ic->ic_bss->ni_rsn_supp_state = RSNA_SUPP_INITIALIZE;
847 error = rsu_join_bss(sc, ic->ic_bss);
848 if (error != 0) {
849 printf("%s: could not send join command\n",
850 sc->sc_dev.dv_xname);
851 ieee80211_begin_scan(&ic->ic_ific_ac.ac_if);
852 splx(s)spllower(s);
853 return;
854 }
855 if (ifp->if_flags & IFF_DEBUG0x4)
856 printf("%s: %s -> %s\n", ifp->if_xname,
857 ieee80211_state_name[ic->ic_state],
858 ieee80211_state_name[cmd->state]);
859 ic->ic_state = cmd->state;
860 if (ic->ic_flags & IEEE80211_F_RSNON0x00200000)
861 ic->ic_bss->ni_rsn_supp_state = RSNA_SUPP_PTKSTART;
862 splx(s)spllower(s);
863 return;
864 case IEEE80211_S_ASSOC:
865 /* No-op for this driver. See rsu_event_join_bss(). */
866 if (ifp->if_flags & IFF_DEBUG0x4)
867 printf("%s: %s -> %s\n", ifp->if_xname,
868 ieee80211_state_name[ic->ic_state],
869 ieee80211_state_name[cmd->state]);
870 ic->ic_state = cmd->state;
871 splx(s)spllower(s);
872 return;
873 case IEEE80211_S_RUN:
874 /* Indicate highest supported rate. */
875 ic->ic_bss->ni_txrate = ic->ic_bss->ni_rates.rs_nrates - 1;
876
877 /* Start periodic calibration. */
878 if (!usbd_is_dying(sc->sc_udev))
879 timeout_add_sec(&sc->calib_to, 2);
880 break;
881 }
882 (void)sc->sc_newstate(ic, cmd->state, cmd->arg);
883 splx(s)spllower(s);
884}
885
886int
887rsu_set_key(struct ieee80211com *ic, struct ieee80211_node *ni,
888 struct ieee80211_key *k)
889{
890 struct rsu_softc *sc = ic->ic_softcic_ac.ac_if.if_softc;
891 struct rsu_cmd_key cmd;
892
893 /* Defer setting of WEP keys until interface is brought up. */
894 if ((ic->ic_ific_ac.ac_if.if_flags & (IFF_UP0x1 | IFF_RUNNING0x40)) !=
895 (IFF_UP0x1 | IFF_RUNNING0x40))
896 return (0);
897
898 /* Do it in a process context. */
899 cmd.key = *k;
900 cmd.ni = ni;
901 rsu_do_async(sc, rsu_set_key_cb, &cmd, sizeof(cmd));
902 sc->sc_key_tasks++;
903 return EBUSY16;
904}
905
906void
907rsu_set_key_cb(struct rsu_softc *sc, void *arg)
908{
909 struct rsu_cmd_key *cmd = arg;
910 struct ieee80211com *ic = &sc->sc_ic;
911 struct ieee80211_key *k = &cmd->key;
912 struct r92s_fw_cmd_set_key key;
913
914 sc->sc_key_tasks--;
915
916 memset(&key, 0, sizeof(key))__builtin_memset((&key), (0), (sizeof(key)));
917 /* Map net80211 cipher to HW crypto algorithm. */
918 switch (k->k_cipher) {
919 case IEEE80211_CIPHER_WEP40:
920 key.algo = R92S_KEY_ALGO_WEP401;
921 break;
922 case IEEE80211_CIPHER_WEP104:
923 key.algo = R92S_KEY_ALGO_WEP1045;
924 break;
925 case IEEE80211_CIPHER_TKIP:
926 key.algo = R92S_KEY_ALGO_TKIP2;
927 break;
928 case IEEE80211_CIPHER_CCMP:
929 key.algo = R92S_KEY_ALGO_AES4;
930 break;
931 default:
932 IEEE80211_SEND_MGMT(ic, cmd->ni, IEEE80211_FC0_SUBTYPE_DEAUTH,((*(ic)->ic_send_mgmt)(ic, cmd->ni, 0xc0, IEEE80211_REASON_AUTH_LEAVE
, 0))
933 IEEE80211_REASON_AUTH_LEAVE)((*(ic)->ic_send_mgmt)(ic, cmd->ni, 0xc0, IEEE80211_REASON_AUTH_LEAVE
, 0))
;
934 ieee80211_new_state(ic, IEEE80211_S_SCAN, -1)(((ic)->ic_newstate)((ic), (IEEE80211_S_SCAN), (-1)));
935 return;
936 }
937 key.id = k->k_id;
938 key.grpkey = (k->k_flags & IEEE80211_KEY_GROUP0x00000001) != 0;
939 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)))))
;
940 (void)rsu_fw_cmd(sc, R92S_CMD_SET_KEY20, &key, sizeof(key));
941
942 if (sc->sc_key_tasks == 0) {
943 DPRINTF(("marking port %s valid\n",
944 ether_sprintf(cmd->ni->ni_macaddr)));
945 cmd->ni->ni_port_valid = 1;
946 ieee80211_set_link_state(ic, LINK_STATE_UP4);
947 }
948}
949
950void
951rsu_delete_key(struct ieee80211com *ic, struct ieee80211_node *ni,
952 struct ieee80211_key *k)
953{
954 struct rsu_softc *sc = ic->ic_softcic_ac.ac_if.if_softc;
955 struct rsu_cmd_key cmd;
956
957 if (!(ic->ic_ific_ac.ac_if.if_flags & IFF_RUNNING0x40) ||
958 ic->ic_state != IEEE80211_S_RUN)
959 return; /* Nothing to do. */
960
961 /* Do it in a process context. */
962 cmd.key = *k;
963 rsu_do_async(sc, rsu_delete_key_cb, &cmd, sizeof(cmd));
964}
965
966void
967rsu_delete_key_cb(struct rsu_softc *sc, void *arg)
968{
969 struct rsu_cmd_key *cmd = arg;
970 struct ieee80211_key *k = &cmd->key;
971 struct r92s_fw_cmd_set_key key;
972
973 memset(&key, 0, sizeof(key))__builtin_memset((&key), (0), (sizeof(key)));
974 key.id = k->k_id;
975 (void)rsu_fw_cmd(sc, R92S_CMD_SET_KEY20, &key, sizeof(key));
976}
977
978int
979rsu_site_survey(struct rsu_softc *sc)
980{
981 struct ieee80211com *ic = &sc->sc_ic;
982 struct r92s_fw_cmd_sitesurvey cmd;
983
984 memset(&cmd, 0, sizeof(cmd))__builtin_memset((&cmd), (0), (sizeof(cmd)));
985 if ((ic->ic_flags & IEEE80211_F_ASCAN0x00000001) || sc->scan_pass == 1)
986 cmd.active = htole32(1)((__uint32_t)(1));
987 cmd.limit = htole32(48)((__uint32_t)(48));
988 if (sc->scan_pass == 1) {
989 /* Do a directed scan for second pass. */
990 cmd.ssidlen = htole32(ic->ic_des_esslen)((__uint32_t)(ic->ic_des_esslen));
991 memcpy(cmd.ssid, ic->ic_des_essid, ic->ic_des_esslen)__builtin_memcpy((cmd.ssid), (ic->ic_des_essid), (ic->ic_des_esslen
))
;
992 }
993 DPRINTF(("sending site survey command, pass=%d\n", sc->scan_pass));
994 return (rsu_fw_cmd(sc, R92S_CMD_SITE_SURVEY18, &cmd, sizeof(cmd)));
995}
996
997int
998rsu_join_bss(struct rsu_softc *sc, struct ieee80211_node *ni)
999{
1000 struct ieee80211com *ic = &sc->sc_ic;
1001 struct ndis_wlan_bssid_ex *bss;
1002 struct ndis_802_11_fixed_ies *fixed;
1003 struct r92s_fw_cmd_auth auth;
1004 uint8_t buf[sizeof(*bss) + 128], *frm;
1005 uint8_t opmode;
1006 int error;
1007
1008 /* Let the FW decide the opmode based on the capinfo field. */
1009 opmode = NDIS802_11AUTOUNKNOWN2;
1010 DPRINTF(("setting operating mode to %d\n", opmode));
1011 error = rsu_fw_cmd(sc, R92S_CMD_SET_OPMODE17, &opmode, sizeof(opmode));
1012 if (error != 0)
1013 return (error);
1014
1015 memset(&auth, 0, sizeof(auth))__builtin_memset((&auth), (0), (sizeof(auth)));
1016 if (ic->ic_flags & IEEE80211_F_RSNON0x00200000) {
1017 auth.mode = R92S_AUTHMODE_WPA2;
1018 auth.dot1x = ieee80211_is_8021x_akm(ni->ni_rsnakms);
1019 } else
1020 auth.mode = R92S_AUTHMODE_OPEN0;
1021 DPRINTF(("setting auth mode to %d\n", auth.mode));
1022 error = rsu_fw_cmd(sc, R92S_CMD_SET_AUTH19, &auth, sizeof(auth));
1023 if (error != 0)
1024 return (error);
1025
1026 memset(buf, 0, sizeof(buf))__builtin_memset((buf), (0), (sizeof(buf)));
1027 bss = (struct ndis_wlan_bssid_ex *)buf;
1028 IEEE80211_ADDR_COPY(bss->macaddr, ni->ni_bssid)__builtin_memcpy((bss->macaddr), (ni->ni_bssid), (6));
1029 bss->ssid.ssidlen = htole32(ni->ni_esslen)((__uint32_t)(ni->ni_esslen));
1030 memcpy(bss->ssid.ssid, ni->ni_essid, ni->ni_esslen)__builtin_memcpy((bss->ssid.ssid), (ni->ni_essid), (ni->
ni_esslen))
;
1031 if (ic->ic_flags & (IEEE80211_F_WEPON0x00000100 | IEEE80211_F_RSNON0x00200000))
1032 bss->privacy = htole32(1)((__uint32_t)(1));
1033 bss->rssi = htole32(ni->ni_rssi)((__uint32_t)(ni->ni_rssi));
1034 if (ic->ic_curmode == IEEE80211_MODE_11B)
1035 bss->networktype = htole32(NDIS802_11DS)((__uint32_t)(1));
1036 else
1037 bss->networktype = htole32(NDIS802_11OFDM24)((__uint32_t)(3));
1038 bss->config.len = htole32(sizeof(bss->config))((__uint32_t)(sizeof(bss->config)));
1039 bss->config.bintval = htole32(ni->ni_intval)((__uint32_t)(ni->ni_intval));
1040 bss->config.dsconfig = htole32(ieee80211_chan2ieee(ic, ni->ni_chan))((__uint32_t)(ieee80211_chan2ieee(ic, ni->ni_chan)));
1041 bss->inframode = htole32(NDIS802_11INFRASTRUCTURE)((__uint32_t)(1));
1042 memcpy(bss->supprates, ni->ni_rates.rs_rates,__builtin_memcpy((bss->supprates), (ni->ni_rates.rs_rates
), (ni->ni_rates.rs_nrates))
1043 ni->ni_rates.rs_nrates)__builtin_memcpy((bss->supprates), (ni->ni_rates.rs_rates
), (ni->ni_rates.rs_nrates))
;
1044 /* Write the fixed fields of the beacon frame. */
1045 fixed = (struct ndis_802_11_fixed_ies *)&bss[1];
1046 memcpy(&fixed->tstamp, ni->ni_tstamp, 8)__builtin_memcpy((&fixed->tstamp), (ni->ni_tstamp),
(8))
;
1047 fixed->bintval = htole16(ni->ni_intval)((__uint16_t)(ni->ni_intval));
1048 fixed->capabilities = htole16(ni->ni_capinfo)((__uint16_t)(ni->ni_capinfo));
1049 /* Write IEs to be included in the association request. */
1050 frm = (uint8_t *)&fixed[1];
1051 if ((ic->ic_flags & IEEE80211_F_RSNON0x00200000) &&
1052 (ni->ni_rsnprotos & IEEE80211_PROTO_RSN(1 << 0)))
1053 frm = ieee80211_add_rsn(frm, ic, ni);
1054 if (ni->ni_flags & IEEE80211_NODE_QOS0x0002)
1055 frm = ieee80211_add_qos_capability(frm, ic);
1056 if (ni->ni_flags & IEEE80211_NODE_HT0x0400)
1057 frm = ieee80211_add_htcaps(frm, ic);
1058 if ((ic->ic_flags & IEEE80211_F_RSNON0x00200000) &&
1059 (ni->ni_rsnprotos & IEEE80211_PROTO_WPA(1 << 1)))
1060 frm = ieee80211_add_wpa(frm, ic, ni);
1061 bss->ieslen = htole32(frm - (uint8_t *)fixed)((__uint32_t)(frm - (uint8_t *)fixed));
1062 bss->len = htole32(((frm - buf) + 3) & ~3)((__uint32_t)(((frm - buf) + 3) & ~3));
1063 DPRINTF(("sending join bss command to %s chan %d\n",
1064 ether_sprintf(bss->macaddr), letoh32(bss->config.dsconfig)));
1065 return (rsu_fw_cmd(sc, R92S_CMD_JOIN_BSS14, buf, sizeof(buf)));
1066}
1067
1068int
1069rsu_disconnect(struct rsu_softc *sc)
1070{
1071 uint32_t zero = 0; /* :-) */
1072
1073 /* Disassociate from our current BSS. */
1074 DPRINTF(("sending disconnect command\n"));
1075 return (rsu_fw_cmd(sc, R92S_CMD_DISCONNECT15, &zero, sizeof(zero)));
1076}
1077
1078void
1079rsu_event_survey(struct rsu_softc *sc, uint8_t *buf, int len)
1080{
1081 struct ieee80211com *ic = &sc->sc_ic;
1082 struct ifnet *ifp = &ic->ic_ific_ac.ac_if;
1083 struct ieee80211_rxinfo rxi;
1084 struct ieee80211_node *ni;
1085 struct ieee80211_frame *wh;
1086 struct ndis_wlan_bssid_ex *bss;
1087 struct mbuf *m;
1088 uint32_t pktlen, ieslen;
1089
1090 if (__predict_false(len < sizeof(*bss))__builtin_expect(((len < sizeof(*bss)) != 0), 0))
1091 return;
1092 bss = (struct ndis_wlan_bssid_ex *)buf;
1093 ieslen = letoh32(bss->ieslen)((__uint32_t)(bss->ieslen));
1094 if (ieslen > len - sizeof(*bss))
1095 return;
1096
1097 DPRINTFN(2, ("found BSS %s: len=%d chan=%d inframode=%d "
1098 "networktype=%d privacy=%d\n",
1099 ether_sprintf(bss->macaddr), letoh32(bss->len),
1100 letoh32(bss->config.dsconfig), letoh32(bss->inframode),
1101 letoh32(bss->networktype), letoh32(bss->privacy)));
1102
1103 /* Build a fake beacon frame to let net80211 do all the parsing. */
1104 pktlen = sizeof(*wh) + ieslen;
1105 if (__predict_false(pktlen > MCLBYTES)__builtin_expect(((pktlen > (1 << 11)) != 0), 0))
1106 return;
1107 MGETHDR(m, M_DONTWAIT, MT_DATA)m = m_gethdr((0x0002), (1));
1108 if (__predict_false(m == NULL)__builtin_expect(((m == ((void *)0)) != 0), 0))
1109 return;
1110 if (pktlen > MHLEN((256 - sizeof(struct m_hdr)) - sizeof(struct pkthdr))) {
1111 MCLGET(m, M_DONTWAIT)(void) m_clget((m), (0x0002), (1 << 11));
1112 if (!(m->m_flagsm_hdr.mh_flags & M_EXT0x0001)) {
1113 m_free(m);
1114 return;
1115 }
1116 }
1117 wh = mtod(m, struct ieee80211_frame *)((struct ieee80211_frame *)((m)->m_hdr.mh_data));
1118 wh->i_fc[0] = IEEE80211_FC0_VERSION_00x00 | IEEE80211_FC0_TYPE_MGT0x00 |
1119 IEEE80211_FC0_SUBTYPE_BEACON0x80;
1120 wh->i_fc[1] = IEEE80211_FC1_DIR_NODS0x00;
1121 *(uint16_t *)wh->i_dur = 0;
1122 IEEE80211_ADDR_COPY(wh->i_addr1, etherbroadcastaddr)__builtin_memcpy((wh->i_addr1), (etherbroadcastaddr), (6));
1123 IEEE80211_ADDR_COPY(wh->i_addr2, bss->macaddr)__builtin_memcpy((wh->i_addr2), (bss->macaddr), (6));
1124 IEEE80211_ADDR_COPY(wh->i_addr3, bss->macaddr)__builtin_memcpy((wh->i_addr3), (bss->macaddr), (6));
1125 *(uint16_t *)wh->i_seq = 0;
1126 memcpy(&wh[1], (uint8_t *)&bss[1], ieslen)__builtin_memcpy((&wh[1]), ((uint8_t *)&bss[1]), (ieslen
))
;
1127
1128 /* Finalize mbuf. */
1129 m->m_pkthdrM_dat.MH.MH_pkthdr.len = m->m_lenm_hdr.mh_len = pktlen;
1130
1131 ni = ieee80211_find_rxnode(ic, wh);
1132 memset(&rxi, 0, sizeof(rxi))__builtin_memset((&rxi), (0), (sizeof(rxi)));
1133 rxi.rxi_rssi = letoh32(bss->rssi)((__uint32_t)(bss->rssi));
1134 ieee80211_input(ifp, m, ni, &rxi);
1135 /* Node is no longer needed. */
1136 ieee80211_release_node(ic, ni);
1137}
1138
1139void
1140rsu_event_join_bss(struct rsu_softc *sc, uint8_t *buf, int len)
1141{
1142 struct ieee80211com *ic = &sc->sc_ic;
1143 struct ieee80211_node *ni = ic->ic_bss;
1144 struct r92s_event_join_bss *rsp;
1145 int res;
1146
1147 if (__predict_false(len < sizeof(*rsp))__builtin_expect(((len < sizeof(*rsp)) != 0), 0))
1148 return;
1149 rsp = (struct r92s_event_join_bss *)buf;
1150 res = (int)letoh32(rsp->join_res)((__uint32_t)(rsp->join_res));
1151
1152 DPRINTF(("Rx join BSS event len=%d res=%d\n", len, res));
1153 if (res <= 0) {
1154 ic->ic_stats.is_rx_auth_fail++;
1155 ieee80211_new_state(ic, IEEE80211_S_SCAN, -1)(((ic)->ic_newstate)((ic), (IEEE80211_S_SCAN), (-1)));
1156 return;
1157 }
1158 DPRINTF(("associated with %s associd=%d\n",
1159 ether_sprintf(rsp->bss.macaddr), letoh32(rsp->associd)));
1160
1161 ni->ni_associd = letoh32(rsp->associd)((__uint32_t)(rsp->associd)) | 0xc000;
1162 if (ic->ic_flags & IEEE80211_F_WEPON0x00000100)
1163 ni->ni_flags |= IEEE80211_NODE_TXRXPROT(0x0010 | 0x0008);
1164
1165 /* Force an ASSOC->RUN transition. AUTH->RUN is invalid. */
1166 ic->ic_state = IEEE80211_S_ASSOC;
1167 ieee80211_new_state(ic, IEEE80211_S_RUN,(((ic)->ic_newstate)((ic), (IEEE80211_S_RUN), (0x10)))
1168 IEEE80211_FC0_SUBTYPE_ASSOC_RESP)(((ic)->ic_newstate)((ic), (IEEE80211_S_RUN), (0x10)));
1169}
1170
1171void
1172rsu_rx_event(struct rsu_softc *sc, uint8_t code, uint8_t *buf, int len)
1173{
1174 struct ieee80211com *ic = &sc->sc_ic;
1175 struct ifnet *ifp = &ic->ic_ific_ac.ac_if;
1176
1177 DPRINTFN(4, ("Rx event code=%d len=%d\n", code, len));
1178 switch (code) {
1179 case R92S_EVT_SURVEY8:
1180 if (ic->ic_state == IEEE80211_S_SCAN)
1181 rsu_event_survey(sc, buf, len);
1182 break;
1183 case R92S_EVT_SURVEY_DONE9:
1184 DPRINTF(("site survey pass %d done, found %d BSS\n",
1185 sc->scan_pass, letoh32(*(uint32_t *)buf)));
1186 if (ic->ic_state != IEEE80211_S_SCAN)
1187 break; /* Ignore if not scanning. */
1188 if (sc->scan_pass == 0 && ic->ic_des_esslen != 0) {
1189 /* Schedule a directed scan for hidden APs. */
1190 sc->scan_pass = 1;
1191 ieee80211_new_state(ic, IEEE80211_S_SCAN, -1)(((ic)->ic_newstate)((ic), (IEEE80211_S_SCAN), (-1)));
1192 break;
1193 }
1194 ieee80211_end_scan(ifp);
1195 sc->scan_pass = 0;
1196 break;
1197 case R92S_EVT_JOIN_BSS10:
1198 if (ic->ic_state == IEEE80211_S_AUTH)
1199 rsu_event_join_bss(sc, buf, len);
1200 break;
1201 case R92S_EVT_DEL_STA12:
1202 DPRINTF(("disassociated from %s\n", ether_sprintf(buf)));
1203 if (ic->ic_state == IEEE80211_S_RUN &&
1204 IEEE80211_ADDR_EQ(ic->ic_bss->ni_bssid, buf)(__builtin_memcmp((ic->ic_bss->ni_bssid), (buf), (6)) ==
0)
)
1205 ieee80211_new_state(ic, IEEE80211_S_SCAN, -1)(((ic)->ic_newstate)((ic), (IEEE80211_S_SCAN), (-1)));
1206 break;
1207 case R92S_EVT_WPS_PBC24:
1208 DPRINTF(("WPS PBC pushed.\n"));
1209 break;
1210 case R92S_EVT_FWDBG19:
1211 if (ifp->if_flags & IFF_DEBUG0x4) {
1212 buf[60] = '\0';
1213 printf("FWDBG: %s\n", (char *)buf);
1214 }
1215 break;
1216 }
1217}
1218
1219void
1220rsu_rx_multi_event(struct rsu_softc *sc, uint8_t *buf, int len)
1221{
1222 struct r92s_fw_cmd_hdr *cmd;
1223 int cmdsz;
1224
1225 DPRINTFN(6, ("Rx events len=%d\n", len));
1226
1227 /* Skip Rx status. */
1228 buf += sizeof(struct r92s_rx_stat);
1229 len -= sizeof(struct r92s_rx_stat);
1230
1231 /* Process all events. */
1232 for (;;) {
1233 /* Check that command header fits. */
1234 if (__predict_false(len < sizeof(*cmd))__builtin_expect(((len < sizeof(*cmd)) != 0), 0))
1235 break;
1236 cmd = (struct r92s_fw_cmd_hdr *)buf;
1237 /* Check that command payload fits. */
1238 cmdsz = letoh16(cmd->len)((__uint16_t)(cmd->len));
1239 if (__predict_false(len < sizeof(*cmd) + cmdsz)__builtin_expect(((len < sizeof(*cmd) + cmdsz) != 0), 0))
1240 break;
1241 if (cmdsz > len)
1242 break;
1243
1244 /* Process firmware event. */
1245 rsu_rx_event(sc, cmd->code, (uint8_t *)&cmd[1], cmdsz);
1246
1247 if (!(cmd->seq & R92S_FW_CMD_MORE0x80))
1248 break;
1249 buf += sizeof(*cmd) + cmdsz;
1250 len -= sizeof(*cmd) + cmdsz;
1251 }
1252}
1253
1254int8_t
1255rsu_get_rssi(struct rsu_softc *sc, int rate, void *physt)
1256{
1257 static const int8_t cckoff[] = { 14, -2, -20, -40 };
1258 struct r92s_rx_phystat *phy;
1259 struct r92s_rx_cck *cck;
1260 uint8_t rpt;
1261 int8_t rssi;
1262
1263 if (rate <= 3) {
1264 cck = (struct r92s_rx_cck *)physt;
1265 rpt = (cck->agc_rpt >> 6) & 0x3;
1266 rssi = cck->agc_rpt & 0x3e;
1267 rssi = cckoff[rpt] - rssi;
1268 } else { /* OFDM/HT. */
1269 phy = (struct r92s_rx_phystat *)physt;
1270 rssi = ((letoh32(phy->phydw1)((__uint32_t)(phy->phydw1)) >> 1) & 0x7f) - 106;
1271 }
1272 return (rssi);
1273}
1274
1275void
1276rsu_rx_frame(struct rsu_softc *sc, uint8_t *buf, int pktlen,
1277 struct mbuf_list *ml)
1278{
1279 struct ieee80211com *ic = &sc->sc_ic;
1280 struct ifnet *ifp = &ic->ic_ific_ac.ac_if;
1281 struct ieee80211_rxinfo rxi;
1282 struct ieee80211_frame *wh;
1283 struct ieee80211_node *ni;
1284 struct r92s_rx_stat *stat;
1285 uint32_t rxdw0, rxdw3;
1286 struct mbuf *m;
1287 uint8_t rate;
1288 int8_t rssi = 0;
1289 int s, infosz;
1290
1291 stat = (struct r92s_rx_stat *)buf;
1292 rxdw0 = letoh32(stat->rxdw0)((__uint32_t)(stat->rxdw0));
1293 rxdw3 = letoh32(stat->rxdw3)((__uint32_t)(stat->rxdw3));
1294
1295 if (__predict_false(rxdw0 & R92S_RXDW0_CRCERR)__builtin_expect(((rxdw0 & 0x00004000) != 0), 0)) {
1296 ifp->if_ierrorsif_data.ifi_ierrors++;
1297 return;
1298 }
1299 if (__predict_false(pktlen < sizeof(*wh) || pktlen > MCLBYTES)__builtin_expect(((pktlen < sizeof(*wh) || pktlen > (1 <<
11)) != 0), 0)
) {
1300 ifp->if_ierrorsif_data.ifi_ierrors++;
1301 return;
1302 }
1303
1304 rate = MS(rxdw3, R92S_RXDW3_RATE)(((rxdw3) & 0x0000003f) >> 0);
1305 infosz = MS(rxdw0, R92S_RXDW0_INFOSZ)(((rxdw0) & 0x000f0000) >> 16) * 8;
1306
1307 /* Get RSSI from PHY status descriptor if present. */
1308 if (infosz != 0)
1309 rssi = rsu_get_rssi(sc, rate, &stat[1]);
1310
1311 DPRINTFN(5, ("Rx frame len=%d rate=%d infosz=%d rssi=%d\n",
1312 pktlen, rate, infosz, rssi));
1313
1314 MGETHDR(m, M_DONTWAIT, MT_DATA)m = m_gethdr((0x0002), (1));
1315 if (__predict_false(m == NULL)__builtin_expect(((m == ((void *)0)) != 0), 0)) {
1316 ifp->if_ierrorsif_data.ifi_ierrors++;
1317 return;
1318 }
1319 if (pktlen > MHLEN((256 - sizeof(struct m_hdr)) - sizeof(struct pkthdr))) {
1320 MCLGET(m, M_DONTWAIT)(void) m_clget((m), (0x0002), (1 << 11));
1321 if (__predict_false(!(m->m_flags & M_EXT))__builtin_expect(((!(m->m_hdr.mh_flags & 0x0001)) != 0
), 0)
) {
1322 ifp->if_ierrorsif_data.ifi_ierrors++;
1323 m_freem(m);
1324 return;
1325 }
1326 }
1327 /* Finalize mbuf. */
1328 /* Hardware does Rx TCP checksum offload. */
1329 if (rxdw3 & R92S_RXDW3_TCPCHKVALID0x00002000) {
1330 if (__predict_true(rxdw3 & R92S_RXDW3_TCPCHKRPT)__builtin_expect(((rxdw3 & 0x00000800) != 0), 1))
1331 m->m_pkthdrM_dat.MH.MH_pkthdr.csum_flags |= M_TCP_CSUM_IN_OK0x0020;
1332 else
1333 m->m_pkthdrM_dat.MH.MH_pkthdr.csum_flags |= M_TCP_CSUM_IN_BAD0x0040;
1334 }
1335 wh = (struct ieee80211_frame *)((uint8_t *)&stat[1] + infosz);
1336 memcpy(mtod(m, uint8_t *), wh, pktlen)__builtin_memcpy((((uint8_t *)((m)->m_hdr.mh_data))), (wh)
, (pktlen))
;
1337 m->m_pkthdrM_dat.MH.MH_pkthdr.len = m->m_lenm_hdr.mh_len = pktlen;
1338
1339 s = splnet()splraise(0x4);
1340#if NBPFILTER1 > 0
1341 if (__predict_false(sc->sc_drvbpf != NULL)__builtin_expect(((sc->sc_drvbpf != ((void *)0)) != 0), 0)) {
1342 struct rsu_rx_radiotap_header *tap = &sc->sc_rxtapsc_rxtapu.th;
1343 struct mbuf mb;
1344
1345 tap->wr_flags = 0;
1346 /* Map HW rate index to 802.11 rate. */
1347 tap->wr_flags = 2;
1348 if (!(rxdw3 & R92S_RXDW3_HTC0x00004000)) {
1349 switch (rate) {
1350 /* CCK. */
1351 case 0: tap->wr_rate = 2; break;
1352 case 1: tap->wr_rate = 4; break;
1353 case 2: tap->wr_rate = 11; break;
1354 case 3: tap->wr_rate = 22; break;
1355 /* OFDM. */
1356 case 4: tap->wr_rate = 12; break;
1357 case 5: tap->wr_rate = 18; break;
1358 case 6: tap->wr_rate = 24; break;
1359 case 7: tap->wr_rate = 36; break;
1360 case 8: tap->wr_rate = 48; break;
1361 case 9: tap->wr_rate = 72; break;
1362 case 10: tap->wr_rate = 96; break;
1363 case 11: tap->wr_rate = 108; break;
1364 }
1365 } else if (rate >= 12) { /* MCS0~15. */
1366 /* Bit 7 set means HT MCS instead of rate. */
1367 tap->wr_rate = 0x80 | (rate - 12);
1368 }
1369 tap->wr_dbm_antsignal = rssi;
1370 tap->wr_chan_freq = htole16(ic->ic_bss->ni_chan->ic_freq)((__uint16_t)(ic->ic_bss->ni_chan->ic_freq));
1371 tap->wr_chan_flags = htole16(ic->ic_bss->ni_chan->ic_flags)((__uint16_t)(ic->ic_bss->ni_chan->ic_flags));
1372
1373 mb.m_datam_hdr.mh_data = (caddr_t)tap;
1374 mb.m_lenm_hdr.mh_len = sc->sc_rxtap_len;
1375 mb.m_nextm_hdr.mh_next = m;
1376 mb.m_nextpktm_hdr.mh_nextpkt = NULL((void *)0);
1377 mb.m_typem_hdr.mh_type = 0;
1378 mb.m_flagsm_hdr.mh_flags = 0;
1379 bpf_mtap(sc->sc_drvbpf, &mb, BPF_DIRECTION_IN(1 << 0));
1380 }
1381#endif
1382
1383 ni = ieee80211_find_rxnode(ic, wh);
1384 memset(&rxi, 0, sizeof(rxi))__builtin_memset((&rxi), (0), (sizeof(rxi)));
1385 rxi.rxi_rssi = rssi;
1386 ieee80211_inputm(ifp, m, ni, &rxi, ml);
1387 /* Node is no longer needed. */
1388 ieee80211_release_node(ic, ni);
1389 splx(s)spllower(s);
1390}
1391
1392void
1393rsu_rx_multi_frame(struct rsu_softc *sc, uint8_t *buf, int len)
1394{
1395 struct mbuf_list ml = MBUF_LIST_INITIALIZER(){ ((void *)0), ((void *)0), 0 };
1396 struct r92s_rx_stat *stat;
1397 uint32_t rxdw0;
1398 int totlen, pktlen, infosz, npkts;
1399
1400 /* Get the number of encapsulated frames. */
1401 stat = (struct r92s_rx_stat *)buf;
1402 npkts = MS(letoh32(stat->rxdw2), R92S_RXDW2_PKTCNT)(((((__uint32_t)(stat->rxdw2))) & 0x00ff0000) >>
16)
;
1403 DPRINTFN(6, ("Rx %d frames in one chunk\n", npkts));
1404
1405 /* Process all of them. */
1406 while (npkts-- > 0) {
1407 if (__predict_false(len < sizeof(*stat))__builtin_expect(((len < sizeof(*stat)) != 0), 0))
1408 break;
1409 stat = (struct r92s_rx_stat *)buf;
1410 rxdw0 = letoh32(stat->rxdw0)((__uint32_t)(stat->rxdw0));
1411
1412 pktlen = MS(rxdw0, R92S_RXDW0_PKTLEN)(((rxdw0) & 0x00003fff) >> 0);
1413 if (__predict_false(pktlen == 0)__builtin_expect(((pktlen == 0) != 0), 0))
1414 break;
1415
1416 infosz = MS(rxdw0, R92S_RXDW0_INFOSZ)(((rxdw0) & 0x000f0000) >> 16) * 8;
1417
1418 /* Make sure everything fits in xfer. */
1419 totlen = sizeof(*stat) + infosz + pktlen;
1420 if (__predict_false(totlen > len)__builtin_expect(((totlen > len) != 0), 0))
1421 break;
1422
1423 /* Process 802.11 frame. */
1424 rsu_rx_frame(sc, buf, pktlen, &ml);
1425
1426 /* Next chunk is 128-byte aligned. */
1427 totlen = (totlen + 127) & ~127;
1428 buf += totlen;
1429 len -= totlen;
1430 }
1431 if_input(&sc->sc_ic.ic_ific_ac.ac_if, &ml);
1432}
1433
1434void
1435rsu_rxeof(struct usbd_xfer *xfer, void *priv, usbd_status status)
1436{
1437 struct rsu_rx_data *data = priv;
1438 struct rsu_softc *sc = data->sc;
1439 struct r92s_rx_stat *stat;
1440 struct ifnet *ifp = &sc->sc_ic.ic_ific_ac.ac_if;
1441 int len;
1442
1443 if (__predict_false(status != USBD_NORMAL_COMPLETION)__builtin_expect(((status != USBD_NORMAL_COMPLETION) != 0), 0
)
) {
1444 DPRINTF(("RX status=%d\n", status));
1445 if (status == USBD_STALLED)
1446 usbd_clear_endpoint_stall_async(data->pipe);
1447 if (status != USBD_CANCELLED)
1448 goto resubmit;
1449 return;
1450 }
1451 usbd_get_xfer_status(xfer, NULL((void *)0), NULL((void *)0), &len, NULL((void *)0));
1452
1453 if (__predict_false(len < sizeof(*stat))__builtin_expect(((len < sizeof(*stat)) != 0), 0)) {
1454 DPRINTF(("xfer too short %d\n", len));
1455 ifp->if_ierrorsif_data.ifi_ierrors++;
1456 goto resubmit;
1457 }
1458 if (len > RSU_RXBUFSZ(8 * 1024)) {
1459 DPRINTF(("xfer too large %d\n", len));
1460 ifp->if_ierrorsif_data.ifi_ierrors++;
1461 goto resubmit;
1462 }
1463
1464 /* Determine if it is a firmware C2H event or an 802.11 frame. */
1465 stat = (struct r92s_rx_stat *)data->buf;
1466 if ((letoh32(stat->rxdw1)((__uint32_t)(stat->rxdw1)) & 0x1ff) == 0x1ff)
1467 rsu_rx_multi_event(sc, data->buf, len);
1468 else
1469 rsu_rx_multi_frame(sc, data->buf, len);
1470
1471 resubmit:
1472 /* Setup a new transfer. */
1473 usbd_setup_xfer(xfer, data->pipe, data, data->buf, RSU_RXBUFSZ(8 * 1024),
1474 USBD_SHORT_XFER_OK0x04 | USBD_NO_COPY0x01, USBD_NO_TIMEOUT0, rsu_rxeof);
1475 (void)usbd_transfer(xfer);
1476}
1477
1478void
1479rsu_txeof(struct usbd_xfer *xfer, void *priv, usbd_status status)
1480{
1481 struct rsu_tx_data *data = priv;
1482 struct rsu_softc *sc = data->sc;
1483 struct ifnet *ifp = &sc->sc_ic.ic_ific_ac.ac_if;
1484 int s;
1485
1486 s = splnet()splraise(0x4);
1487 /* Put this Tx buffer back to our free list. */
1488 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)
;
1489
1490 if (__predict_false(status != USBD_NORMAL_COMPLETION)__builtin_expect(((status != USBD_NORMAL_COMPLETION) != 0), 0
)
) {
1491 DPRINTF(("TX status=%d\n", status));
1492 if (status == USBD_STALLED)
1493 usbd_clear_endpoint_stall_async(data->pipe);
1494 ifp->if_oerrorsif_data.ifi_oerrors++;
1495 splx(s)spllower(s);
1496 return;
1497 }
1498 sc->sc_tx_timer = 0;
1499
1500 /* We just released a Tx buffer, notify Tx. */
1501 if (ifq_is_oactive(&ifp->if_snd)) {
1502 ifq_clr_oactive(&ifp->if_snd);
1503 rsu_start(ifp);
1504 }
1505 splx(s)spllower(s);
1506}
1507
1508int
1509rsu_tx(struct rsu_softc *sc, struct mbuf *m, struct ieee80211_node *ni)
1510{
1511 struct ieee80211com *ic = &sc->sc_ic;
1512 struct ieee80211_frame *wh;
1513 struct ieee80211_key *k = NULL((void *)0);
1514 struct rsu_tx_data *data;
1515 struct r92s_tx_desc *txd;
1516 struct usbd_pipe *pipe;
1517 uint16_t qos;
1518 uint8_t type, qid, tid = 0;
1519 int hasqos, xferlen, error;
1520
1521 wh = mtod(m, struct ieee80211_frame *)((struct ieee80211_frame *)((m)->m_hdr.mh_data));
1522 type = wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK0x0c;
1523
1524 if (wh->i_fc[1] & IEEE80211_FC1_PROTECTED0x40) {
1525 k = ieee80211_get_txkey(ic, wh, ni);
1526 if ((m = ieee80211_encrypt(ic, m, k)) == NULL((void *)0))
1527 return (ENOBUFS55);
1528 wh = mtod(m, struct ieee80211_frame *)((struct ieee80211_frame *)((m)->m_hdr.mh_data));
1529 }
1530 if ((hasqos = ieee80211_has_qos(wh))) {
1531 qos = ieee80211_get_qos(wh);
1532 tid = qos & IEEE80211_QOS_TID0x000f;
1533 qid = rsu_ac2qid[ieee80211_up_to_ac(ic, tid)];
1534 } else
1535 qid = RSU_QID_BE5;
1536
1537 /* Get the USB pipe to use for this queue id. */
1538 pipe = sc->pipe[sc->qid2idx[qid]];
1539
1540 /* Grab a Tx buffer from our free list. */
1541 data = TAILQ_FIRST(&sc->tx_free_list)((&sc->tx_free_list)->tqh_first);
1542 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)
;
1543
1544 /* Fill Tx descriptor. */
1545 txd = (struct r92s_tx_desc *)data->buf;
1546 memset(txd, 0, sizeof(*txd))__builtin_memset((txd), (0), (sizeof(*txd)));
1547
1548 txd->txdw0 |= htole32(((__uint32_t)((((m->M_dat.MH.MH_pkthdr.len) << 0) &
0x0000ffff) | (((sizeof(*txd)) << 16) & 0x00ff0000
) | 0x80000000 | 0x08000000 | 0x04000000))
1549 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))
1550 SM(R92S_TXDW0_OFFSET, sizeof(*txd)) |((__uint32_t)((((m->M_dat.MH.MH_pkthdr.len) << 0) &
0x0000ffff) | (((sizeof(*txd)) << 16) & 0x00ff0000
) | 0x80000000 | 0x08000000 | 0x04000000))
1551 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))
;
1552
1553 txd->txdw1 |= htole32(((__uint32_t)((((5) << 0) & 0x0000001f) | (((0x03) <<
8) & 0x00001f00)))
1554 SM(R92S_TXDW1_MACID, R92S_MACID_BSS) |((__uint32_t)((((5) << 0) & 0x0000001f) | (((0x03) <<
8) & 0x00001f00)))
1555 SM(R92S_TXDW1_QSEL, R92S_TXDW1_QSEL_BE))((__uint32_t)((((5) << 0) & 0x0000001f) | (((0x03) <<
8) & 0x00001f00)))
;
1556 if (!hasqos)
1557 txd->txdw1 |= htole32(R92S_TXDW1_NONQOS)((__uint32_t)(0x00010000));
1558#ifdef notyet
1559 if (k != NULL((void *)0)) {
1560 switch (k->k_cipher) {
1561 case IEEE80211_CIPHER_WEP40:
1562 case IEEE80211_CIPHER_WEP104:
1563 cipher = R92S_TXDW1_CIPHER_WEP1;
1564 break;
1565 case IEEE80211_CIPHER_TKIP:
1566 cipher = R92S_TXDW1_CIPHER_TKIP2;
1567 break;
1568 case IEEE80211_CIPHER_CCMP:
1569 cipher = R92S_TXDW1_CIPHER_AES3;
1570 break;
1571 default:
1572 cipher = R92S_TXDW1_CIPHER_NONE;
1573 }
1574 txd->txdw1 |= htole32(((__uint32_t)((((cipher) << 22) & 0x00c00000) | (((
k->k_id) << 17) & 0x00060000)))
1575 SM(R92S_TXDW1_CIPHER, cipher) |((__uint32_t)((((cipher) << 22) & 0x00c00000) | (((
k->k_id) << 17) & 0x00060000)))
1576 SM(R92S_TXDW1_KEYIDX, k->k_id))((__uint32_t)((((cipher) << 22) & 0x00c00000) | (((
k->k_id) << 17) & 0x00060000)))
;
1577 }
1578#endif
1579 txd->txdw2 |= htole32(R92S_TXDW2_BK)((__uint32_t)(0x40000000));
1580 if (IEEE80211_IS_MULTICAST(wh->i_addr1)(*(wh->i_addr1) & 0x01))
1581 txd->txdw2 |= htole32(R92S_TXDW2_BMCAST)((__uint32_t)(0x00000080));
1582 /*
1583 * Firmware will use and increment the sequence number for the
1584 * specified TID.
1585 */
1586 txd->txdw3 |= htole32(SM(R92S_TXDW3_SEQ, tid))((__uint32_t)((((tid) << 16) & 0x0fff0000)));
1587
1588#if NBPFILTER1 > 0
1589 if (__predict_false(sc->sc_drvbpf != NULL)__builtin_expect(((sc->sc_drvbpf != ((void *)0)) != 0), 0)) {
1590 struct rsu_tx_radiotap_header *tap = &sc->sc_txtapsc_txtapu.th;
1591 struct mbuf mb;
1592
1593 tap->wt_flags = 0;
1594 tap->wt_chan_freq = htole16(ic->ic_bss->ni_chan->ic_freq)((__uint16_t)(ic->ic_bss->ni_chan->ic_freq));
1595 tap->wt_chan_flags = htole16(ic->ic_bss->ni_chan->ic_flags)((__uint16_t)(ic->ic_bss->ni_chan->ic_flags));
1596
1597 mb.m_datam_hdr.mh_data = (caddr_t)tap;
1598 mb.m_lenm_hdr.mh_len = sc->sc_txtap_len;
1599 mb.m_nextm_hdr.mh_next = m;
1600 mb.m_nextpktm_hdr.mh_nextpkt = NULL((void *)0);
1601 mb.m_typem_hdr.mh_type = 0;
1602 mb.m_flagsm_hdr.mh_flags = 0;
1603 bpf_mtap(sc->sc_drvbpf, &mb, BPF_DIRECTION_OUT(1 << 1));
1604 }
1605#endif
1606
1607 xferlen = sizeof(*txd) + m->m_pkthdrM_dat.MH.MH_pkthdr.len;
1608 m_copydata(m, 0, m->m_pkthdrM_dat.MH.MH_pkthdr.len, &txd[1]);
1609 m_freem(m);
1610
1611 data->pipe = pipe;
1612 usbd_setup_xfer(data->xfer, pipe, data, data->buf, xferlen,
1613 USBD_FORCE_SHORT_XFER0x08 | USBD_NO_COPY0x01, RSU_TX_TIMEOUT5000,
1614 rsu_txeof);
1615 error = usbd_transfer(data->xfer);
1616 if (__predict_false(error != USBD_IN_PROGRESS && error != 0)__builtin_expect(((error != USBD_IN_PROGRESS && error
!= 0) != 0), 0)
) {
1617 /* Put this Tx buffer back to our free list. */
1618 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)
;
1619 return (error);
1620 }
1621 ieee80211_release_node(ic, ni);
1622 return (0);
1623}
1624
1625int
1626rsu_send_mgmt(struct ieee80211com *ic, struct ieee80211_node *ni, int type,
1627 int arg1, int arg2)
1628{
1629 return (EOPNOTSUPP45);
1630}
1631
1632void
1633rsu_start(struct ifnet *ifp)
1634{
1635 struct rsu_softc *sc = ifp->if_softc;
1636 struct ieee80211com *ic = &sc->sc_ic;
1637 struct ieee80211_node *ni;
1638 struct mbuf *m;
1639
1640 if (!(ifp->if_flags & IFF_RUNNING0x40) || ifq_is_oactive(&ifp->if_snd))
1641 return;
1642
1643 for (;;) {
1644 if (TAILQ_EMPTY(&sc->tx_free_list)(((&sc->tx_free_list)->tqh_first) == ((void *)0))) {
1645 ifq_set_oactive(&ifp->if_snd);
1646 break;
1647 }
1648 if (ic->ic_state != IEEE80211_S_RUN)
1649 break;
1650
1651 /* Encapsulate and send data frames. */
1652 m = ifq_dequeue(&ifp->if_snd);
1653 if (m == NULL((void *)0))
1654 break;
1655#if NBPFILTER1 > 0
1656 if (ifp->if_bpf != NULL((void *)0))
1657 bpf_mtap(ifp->if_bpf, m, BPF_DIRECTION_OUT(1 << 1));
1658#endif
1659 if ((m = ieee80211_encap(ifp, m, &ni)) == NULL((void *)0))
1660 continue;
1661
1662#if NBPFILTER1 > 0
1663 if (ic->ic_rawbpf != NULL((void *)0))
1664 bpf_mtap(ic->ic_rawbpf, m, BPF_DIRECTION_OUT(1 << 1));
1665#endif
1666 if (rsu_tx(sc, m, ni) != 0) {
1667 ieee80211_release_node(ic, ni);
1668 ifp->if_oerrorsif_data.ifi_oerrors++;
1669 continue;
1670 }
1671
1672 sc->sc_tx_timer = 5;
1673 ifp->if_timer = 1;
1674 }
1675}
1676
1677void
1678rsu_watchdog(struct ifnet *ifp)
1679{
1680 struct rsu_softc *sc = ifp->if_softc;
1681
1682 ifp->if_timer = 0;
1683
1684 if (sc->sc_tx_timer > 0) {
1685 if (--sc->sc_tx_timer == 0) {
1686 printf("%s: device timeout\n", sc->sc_dev.dv_xname);
1687 /* rsu_init(ifp); XXX needs a process context! */
1688 ifp->if_oerrorsif_data.ifi_oerrors++;
1689 return;
1690 }
1691 ifp->if_timer = 1;
1692 }
1693 ieee80211_watchdog(ifp);
1694}
1695
1696int
1697rsu_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
1698{
1699 struct rsu_softc *sc = ifp->if_softc;
1700 int s, error = 0;
1701
1702 if (usbd_is_dying(sc->sc_udev))
1703 return ENXIO6;
1704
1705 usbd_ref_incr(sc->sc_udev);
1706
1707 s = splnet()splraise(0x4);
1708
1709 switch (cmd) {
1710 case SIOCSIFADDR((unsigned long)0x80000000 | ((sizeof(struct ifreq) & 0x1fff
) << 16) | ((('i')) << 8) | ((12)))
:
1711 ifp->if_flags |= IFF_UP0x1;
1712 /* FALLTHROUGH */
1713 case SIOCSIFFLAGS((unsigned long)0x80000000 | ((sizeof(struct ifreq) & 0x1fff
) << 16) | ((('i')) << 8) | ((16)))
:
1714 if (ifp->if_flags & IFF_UP0x1) {
1715 if (!(ifp->if_flags & IFF_RUNNING0x40))
1716 rsu_init(ifp);
1717 } else {
1718 if (ifp->if_flags & IFF_RUNNING0x40)
1719 rsu_stop(ifp);
1720 }
1721 break;
1722 default:
1723 error = ieee80211_ioctl(ifp, cmd, data);
1724 }
1725
1726 if (error == ENETRESET52) {
1727 if ((ifp->if_flags & (IFF_UP0x1 | IFF_RUNNING0x40)) ==
1728 (IFF_UP0x1 | IFF_RUNNING0x40)) {
1729 rsu_stop(ifp);
1730 rsu_init(ifp);
1731 }
1732 error = 0;
1733 }
1734 splx(s)spllower(s);
1735
1736 usbd_ref_decr(sc->sc_udev);
1737
1738 return (error);
1739}
1740
1741/*
1742 * Power on sequence for A-cut adapters.
1743 */
1744void
1745rsu_power_on_acut(struct rsu_softc *sc)
1746{
1747 uint32_t reg;
1748
1749 rsu_write_1(sc, R92S_SPS0_CTRL(0x0000 + 0x011) + 1, 0x53);
1750 rsu_write_1(sc, R92S_SPS0_CTRL(0x0000 + 0x011) + 0, 0x57);
1751
1752 /* Enable AFE macro block's bandgap and Mbias. */
1753 rsu_write_1(sc, R92S_AFE_MISC(0x0000 + 0x010),
1754 rsu_read_1(sc, R92S_AFE_MISC(0x0000 + 0x010)) |
1755 R92S_AFE_MISC_BGEN0x01 | R92S_AFE_MISC_MBEN0x02);
1756 /* Enable LDOA15 block. */
1757 rsu_write_1(sc, R92S_LDOA15_CTRL(0x0000 + 0x020),
1758 rsu_read_1(sc, R92S_LDOA15_CTRL(0x0000 + 0x020)) | R92S_LDA15_EN0x01);
1759
1760 rsu_write_1(sc, R92S_SPS1_CTRL(0x0000 + 0x018),
1761 rsu_read_1(sc, R92S_SPS1_CTRL(0x0000 + 0x018)) | R92S_SPS1_LDEN0x01);
1762 usbd_delay_ms(sc->sc_udev, 2);
1763 /* Enable switch regulator block. */
1764 rsu_write_1(sc, R92S_SPS1_CTRL(0x0000 + 0x018),
1765 rsu_read_1(sc, R92S_SPS1_CTRL(0x0000 + 0x018)) | R92S_SPS1_SWEN0x02);
1766
1767 rsu_write_4(sc, R92S_SPS1_CTRL(0x0000 + 0x018), 0x00a7b267);
1768
1769 rsu_write_1(sc, R92S_SYS_ISO_CTRL(0x0000 + 0x000) + 1,
1770 rsu_read_1(sc, R92S_SYS_ISO_CTRL(0x0000 + 0x000) + 1) | 0x08);
1771
1772 rsu_write_1(sc, R92S_SYS_FUNC_EN(0x0000 + 0x002) + 1,
1773 rsu_read_1(sc, R92S_SYS_FUNC_EN(0x0000 + 0x002) + 1) | 0x20);
1774
1775 rsu_write_1(sc, R92S_SYS_ISO_CTRL(0x0000 + 0x000) + 1,
1776 rsu_read_1(sc, R92S_SYS_ISO_CTRL(0x0000 + 0x000) + 1) & ~0x90);
1777
1778 /* Enable AFE clock. */
1779 rsu_write_1(sc, R92S_AFE_XTAL_CTRL(0x0000 + 0x026) + 1,
1780 rsu_read_1(sc, R92S_AFE_XTAL_CTRL(0x0000 + 0x026) + 1) & ~0x04);
1781 /* Enable AFE PLL macro block. */
1782 rsu_write_1(sc, R92S_AFE_PLL_CTRL(0x0000 + 0x028),
1783 rsu_read_1(sc, R92S_AFE_PLL_CTRL(0x0000 + 0x028)) | 0x11);
1784 /* Attach AFE PLL to MACTOP/BB. */
1785 rsu_write_1(sc, R92S_SYS_ISO_CTRL(0x0000 + 0x000),
1786 rsu_read_1(sc, R92S_SYS_ISO_CTRL(0x0000 + 0x000)) & ~0x11);
1787
1788 /* Switch to 40MHz clock instead of 80MHz. */
1789 rsu_write_2(sc, R92S_SYS_CLKR(0x0000 + 0x008),
1790 rsu_read_2(sc, R92S_SYS_CLKR(0x0000 + 0x008)) & ~R92S_SYS_CLKSEL0x0001);
1791
1792 /* Enable MAC clock. */
1793 rsu_write_2(sc, R92S_SYS_CLKR(0x0000 + 0x008),
1794 rsu_read_2(sc, R92S_SYS_CLKR(0x0000 + 0x008)) |
1795 R92S_MAC_CLK_EN0x0800 | R92S_SYS_CLK_EN0x1000);
1796
1797 rsu_write_1(sc, R92S_PMC_FSM(0x0000 + 0x004), 0x02);
1798
1799 /* Enable digital core and IOREG R/W. */
1800 rsu_write_1(sc, R92S_SYS_FUNC_EN(0x0000 + 0x002) + 1,
1801 rsu_read_1(sc, R92S_SYS_FUNC_EN(0x0000 + 0x002) + 1) | 0x08);
1802
1803 rsu_write_1(sc, R92S_SYS_FUNC_EN(0x0000 + 0x002) + 1,
1804 rsu_read_1(sc, R92S_SYS_FUNC_EN(0x0000 + 0x002) + 1) | 0x80);
1805
1806 /* Switch the control path to firmware. */
1807 reg = rsu_read_2(sc, R92S_SYS_CLKR(0x0000 + 0x008));
1808 reg = (reg & ~R92S_SWHW_SEL0x4000) | R92S_FWHW_SEL0x8000;
1809 rsu_write_2(sc, R92S_SYS_CLKR(0x0000 + 0x008), reg);
1810
1811 rsu_write_2(sc, R92S_CR(0x0040 + 0x000), 0x37fc);
1812
1813 /* Fix USB RX FIFO issue. */
1814 rsu_write_1(sc, 0xfe5c,
1815 rsu_read_1(sc, 0xfe5c) | 0x80);
1816 rsu_write_1(sc, 0x00ab,
1817 rsu_read_1(sc, 0x00ab) | 0xc0);
1818
1819 rsu_write_1(sc, R92S_SYS_CLKR(0x0000 + 0x008),
1820 rsu_read_1(sc, R92S_SYS_CLKR(0x0000 + 0x008)) & ~R92S_SYS_CPU_CLKSEL0x0004);
1821}
1822
1823/*
1824 * Power on sequence for B-cut and C-cut adapters.
1825 */
1826void
1827rsu_power_on_bcut(struct rsu_softc *sc)
1828{
1829 uint32_t reg;
1830 int ntries;
1831
1832 /* Prevent eFuse leakage. */
1833 rsu_write_1(sc, 0x37, 0xb0);
1834 usbd_delay_ms(sc->sc_udev, 10);
1835 rsu_write_1(sc, 0x37, 0x30);
1836
1837 /* Switch the control path to hardware. */
1838 reg = rsu_read_2(sc, R92S_SYS_CLKR(0x0000 + 0x008));
1839 if (reg & R92S_FWHW_SEL0x8000) {
1840 rsu_write_2(sc, R92S_SYS_CLKR(0x0000 + 0x008),
1841 reg & ~(R92S_SWHW_SEL0x4000 | R92S_FWHW_SEL0x8000));
1842 }
1843 rsu_write_1(sc, R92S_SYS_FUNC_EN(0x0000 + 0x002) + 1,
1844 rsu_read_1(sc, R92S_SYS_FUNC_EN(0x0000 + 0x002) + 1) & ~0x8c);
1845 DELAY(1000)(*delay_func)(1000);
1846
1847 rsu_write_1(sc, R92S_SPS0_CTRL(0x0000 + 0x011) + 1, 0x53);
1848 rsu_write_1(sc, R92S_SPS0_CTRL(0x0000 + 0x011) + 0, 0x57);
1849
1850 reg = rsu_read_1(sc, R92S_AFE_MISC(0x0000 + 0x010));
1851 rsu_write_1(sc, R92S_AFE_MISC(0x0000 + 0x010), reg | R92S_AFE_MISC_BGEN0x01);
1852 rsu_write_1(sc, R92S_AFE_MISC(0x0000 + 0x010), reg | R92S_AFE_MISC_BGEN0x01 |
1853 R92S_AFE_MISC_MBEN0x02 | R92S_AFE_MISC_I32_EN0x08);
1854
1855 /* Enable PLL. */
1856 rsu_write_1(sc, R92S_LDOA15_CTRL(0x0000 + 0x020),
1857 rsu_read_1(sc, R92S_LDOA15_CTRL(0x0000 + 0x020)) | R92S_LDA15_EN0x01);
1858
1859 rsu_write_1(sc, R92S_LDOV12D_CTRL(0x0000 + 0x021),
1860 rsu_read_1(sc, R92S_LDOV12D_CTRL(0x0000 + 0x021)) | R92S_LDV12_EN0x01);
1861
1862 rsu_write_1(sc, R92S_SYS_ISO_CTRL(0x0000 + 0x000) + 1,
1863 rsu_read_1(sc, R92S_SYS_ISO_CTRL(0x0000 + 0x000) + 1) | 0x08);
1864
1865 rsu_write_1(sc, R92S_SYS_FUNC_EN(0x0000 + 0x002) + 1,
1866 rsu_read_1(sc, R92S_SYS_FUNC_EN(0x0000 + 0x002) + 1) | 0x20);
1867
1868 /* Support 64KB IMEM. */
1869 rsu_write_1(sc, R92S_SYS_ISO_CTRL(0x0000 + 0x000) + 1,
1870 rsu_read_1(sc, R92S_SYS_ISO_CTRL(0x0000 + 0x000) + 1) & ~0x97);
1871
1872 /* Enable AFE clock. */
1873 rsu_write_1(sc, R92S_AFE_XTAL_CTRL(0x0000 + 0x026) + 1,
1874 rsu_read_1(sc, R92S_AFE_XTAL_CTRL(0x0000 + 0x026) + 1) & ~0x04);
1875 /* Enable AFE PLL macro block. */
1876 reg = rsu_read_1(sc, R92S_AFE_PLL_CTRL(0x0000 + 0x028));
1877 rsu_write_1(sc, R92S_AFE_PLL_CTRL(0x0000 + 0x028), reg | 0x11);
1878 DELAY(500)(*delay_func)(500);
1879 rsu_write_1(sc, R92S_AFE_PLL_CTRL(0x0000 + 0x028), reg | 0x51);
1880 DELAY(500)(*delay_func)(500);
1881 rsu_write_1(sc, R92S_AFE_PLL_CTRL(0x0000 + 0x028), reg | 0x11);
1882 DELAY(500)(*delay_func)(500);
1883
1884 /* Attach AFE PLL to MACTOP/BB. */
1885 rsu_write_1(sc, R92S_SYS_ISO_CTRL(0x0000 + 0x000),
1886 rsu_read_1(sc, R92S_SYS_ISO_CTRL(0x0000 + 0x000)) & ~0x11);
1887
1888 /* Switch to 40MHz clock. */
1889 rsu_write_1(sc, R92S_SYS_CLKR(0x0000 + 0x008), 0x00);
1890 /* Disable CPU clock and 80MHz SSC. */
1891 rsu_write_1(sc, R92S_SYS_CLKR(0x0000 + 0x008),
1892 rsu_read_1(sc, R92S_SYS_CLKR(0x0000 + 0x008)) | 0xa0);
1893 /* Enable MAC clock. */
1894 rsu_write_2(sc, R92S_SYS_CLKR(0x0000 + 0x008),
1895 rsu_read_2(sc, R92S_SYS_CLKR(0x0000 + 0x008)) |
1896 R92S_MAC_CLK_EN0x0800 | R92S_SYS_CLK_EN0x1000);
1897
1898 rsu_write_1(sc, R92S_PMC_FSM(0x0000 + 0x004), 0x02);
1899
1900 /* Enable digital core and IOREG R/W. */
1901 rsu_write_1(sc, R92S_SYS_FUNC_EN(0x0000 + 0x002) + 1,
1902 rsu_read_1(sc, R92S_SYS_FUNC_EN(0x0000 + 0x002) + 1) | 0x08);
1903
1904 rsu_write_1(sc, R92S_SYS_FUNC_EN(0x0000 + 0x002) + 1,
1905 rsu_read_1(sc, R92S_SYS_FUNC_EN(0x0000 + 0x002) + 1) | 0x80);
1906
1907 /* Switch the control path to firmware. */
1908 reg = rsu_read_2(sc, R92S_SYS_CLKR(0x0000 + 0x008));
1909 reg = (reg & ~R92S_SWHW_SEL0x4000) | R92S_FWHW_SEL0x8000;
1910 rsu_write_2(sc, R92S_SYS_CLKR(0x0000 + 0x008), reg);
1911
1912 rsu_write_2(sc, R92S_CR(0x0040 + 0x000), 0x37fc);
1913
1914 /* Fix USB RX FIFO issue. */
1915 rsu_write_1(sc, 0xfe5c,
1916 rsu_read_1(sc, 0xfe5c) | 0x80);
1917
1918 rsu_write_1(sc, R92S_SYS_CLKR(0x0000 + 0x008),
1919 rsu_read_1(sc, R92S_SYS_CLKR(0x0000 + 0x008)) & ~R92S_SYS_CPU_CLKSEL0x0004);
1920
1921 rsu_write_1(sc, 0xfe1c, 0x80);
1922
1923 /* Make sure TxDMA is ready to download firmware. */
1924 for (ntries = 0; ntries < 20; ntries++) {
1925 reg = rsu_read_1(sc, R92S_TCR(0x0040 + 0x004));
1926 if ((reg & (R92S_TCR_IMEM_CHK_RPT0x02 | R92S_TCR_EMEM_CHK_RPT0x08)) ==
1927 (R92S_TCR_IMEM_CHK_RPT0x02 | R92S_TCR_EMEM_CHK_RPT0x08))
1928 break;
1929 DELAY(5)(*delay_func)(5);
1930 }
1931 if (ntries == 20) {
1932 /* Reset TxDMA. */
1933 reg = rsu_read_1(sc, R92S_CR(0x0040 + 0x000));
1934 rsu_write_1(sc, R92S_CR(0x0040 + 0x000), reg & ~R92S_CR_TXDMA_EN0x10);
1935 DELAY(2)(*delay_func)(2);
1936 rsu_write_1(sc, R92S_CR(0x0040 + 0x000), reg | R92S_CR_TXDMA_EN0x10);
1937 }
1938}
1939
1940void
1941rsu_power_off(struct rsu_softc *sc)
1942{
1943 /* Turn RF off. */
1944 rsu_write_1(sc, R92S_RF_CTRL(0x0000 + 0x01f), 0x00);
1945 usbd_delay_ms(sc->sc_udev, 5);
1946
1947 /* Turn MAC off. */
1948 /* Switch control path. */
1949 rsu_write_1(sc, R92S_SYS_CLKR(0x0000 + 0x008) + 1, 0x38);
1950 /* Reset MACTOP. */
1951 rsu_write_1(sc, R92S_SYS_FUNC_EN(0x0000 + 0x002) + 1, 0x70);
1952 rsu_write_1(sc, R92S_PMC_FSM(0x0000 + 0x004), 0x06);
1953 rsu_write_1(sc, R92S_SYS_ISO_CTRL(0x0000 + 0x000) + 0, 0xf9);
1954 rsu_write_1(sc, R92S_SYS_ISO_CTRL(0x0000 + 0x000) + 1, 0xe8);
1955
1956 /* Disable AFE PLL. */
1957 rsu_write_1(sc, R92S_AFE_PLL_CTRL(0x0000 + 0x028), 0x00);
1958 /* Disable A15V. */
1959 rsu_write_1(sc, R92S_LDOA15_CTRL(0x0000 + 0x020), 0x54);
1960 /* Disable eFuse 1.2V. */
1961 rsu_write_1(sc, R92S_SYS_FUNC_EN(0x0000 + 0x002) + 1, 0x50);
1962 rsu_write_1(sc, R92S_LDOV12D_CTRL(0x0000 + 0x021), 0x24);
1963 /* Enable AFE macro block's bandgap and Mbias. */
1964 rsu_write_1(sc, R92S_AFE_MISC(0x0000 + 0x010), 0x30);
1965 /* Disable 1.6V LDO. */
1966 rsu_write_1(sc, R92S_SPS0_CTRL(0x0000 + 0x011) + 0, 0x56);
1967 rsu_write_1(sc, R92S_SPS0_CTRL(0x0000 + 0x011) + 1, 0x43);
1968}
1969
1970int
1971rsu_fw_loadsection(struct rsu_softc *sc, uint8_t *buf, int len)
1972{
1973 struct rsu_tx_data *data;
1974 struct r92s_tx_desc *txd;
1975 struct usbd_pipe *pipe;
1976 int mlen, error;
1977
1978 data = sc->fwcmd_data;
1979 pipe = sc->pipe[sc->qid2idx[RSU_QID_VO3]];
1980 txd = (struct r92s_tx_desc *)data->buf;
1981 while (len > 0) {
1982 memset(txd, 0, sizeof(*txd))__builtin_memset((txd), (0), (sizeof(*txd)));
1983 if (len <= RSU_TXBUFSZ((sizeof(struct r92s_tx_desc) + (2300 + 4 + (3 + 1 + 4)) + 3)
& ~3)
- sizeof(*txd)) {
1984 /* Last chunk. */
1985 txd->txdw0 |= htole32(R92S_TXDW0_LINIP)((__uint32_t)(0x10000000));
1986 mlen = len;
1987 } else
1988 mlen = RSU_TXBUFSZ((sizeof(struct r92s_tx_desc) + (2300 + 4 + (3 + 1 + 4)) + 3)
& ~3)
- sizeof(*txd);
1989 txd->txdw0 |= htole32(SM(R92S_TXDW0_PKTLEN, mlen))((__uint32_t)((((mlen) << 0) & 0x0000ffff)));
1990 memcpy(&txd[1], buf, mlen)__builtin_memcpy((&txd[1]), (buf), (mlen));
1991
1992 usbd_setup_xfer(data->xfer, pipe, NULL((void *)0), data->buf,
1993 sizeof(*txd) + mlen,
1994 USBD_SHORT_XFER_OK0x04 | USBD_NO_COPY0x01 | USBD_SYNCHRONOUS0x02,
1995 RSU_TX_TIMEOUT5000, NULL((void *)0));
1996 error = usbd_transfer(data->xfer);
1997 if (error != 0)
1998 return (error);
1999 buf += mlen;
2000 len -= mlen;
2001 }
2002 return (0);
2003}
2004
2005int
2006rsu_load_firmware(struct rsu_softc *sc)
2007{
2008 struct ieee80211com *ic = &sc->sc_ic;
2009 struct r92s_fw_hdr *hdr;
2010 struct r92s_fw_priv *dmem;
2011 uint8_t *imem, *emem;
2012 int imemsz, ememsz;
2013 u_char *fw;
2014 size_t size;
2015 uint32_t reg;
2016 int ntries, error;
2017
2018 /* Read firmware image from the filesystem. */
2019 if ((error = loadfirmware("rsu-rtl8712", &fw, &size)) != 0) {
2020 printf("%s: failed loadfirmware of file %s (error %d)\n",
2021 sc->sc_dev.dv_xname, "rsu-rtl8712", error);
2022 return (error);
2023 }
2024 if (size < sizeof(*hdr)) {
2025 printf("%s: firmware too short\n", sc->sc_dev.dv_xname);
2026 error = EINVAL22;
2027 goto fail;
2028 }
2029 hdr = (struct r92s_fw_hdr *)fw;
2030 if (hdr->signature != htole16(0x8712)((__uint16_t)(0x8712)) &&
2031 hdr->signature != htole16(0x8192)((__uint16_t)(0x8192))) {
2032 printf("%s: invalid firmware signature 0x%x\n",
2033 sc->sc_dev.dv_xname, letoh16(hdr->signature)((__uint16_t)(hdr->signature)));
2034 error = EINVAL22;
2035 goto fail;
2036 }
2037 DPRINTF(("FW V%d %02x-%02x %02x:%02x\n", letoh16(hdr->version),
2038 hdr->month, hdr->day, hdr->hour, hdr->minute));
2039
2040 /* Make sure that driver and firmware are in sync. */
2041 if (hdr->privsz != htole32(sizeof(*dmem))((__uint32_t)(sizeof(*dmem)))) {
2042 printf("%s: unsupported firmware image\n",
2043 sc->sc_dev.dv_xname);
2044 error = EINVAL22;
2045 goto fail;
2046 }
2047 /* Get FW sections sizes. */
2048 imemsz = letoh32(hdr->imemsz)((__uint32_t)(hdr->imemsz));
2049 ememsz = letoh32(hdr->sramsz)((__uint32_t)(hdr->sramsz));
2050 /* Check that all FW sections fit in image. */
2051 if (size < sizeof(*hdr) + imemsz + ememsz) {
2052 printf("%s: firmware too short\n", sc->sc_dev.dv_xname);
2053 error = EINVAL22;
2054 goto fail;
2055 }
2056 imem = (uint8_t *)&hdr[1];
2057 emem = imem + imemsz;
2058
2059 /* Load IMEM section. */
2060 error = rsu_fw_loadsection(sc, imem, imemsz);
2061 if (error != 0) {
2062 printf("%s: could not load firmware section %s\n",
2063 sc->sc_dev.dv_xname, "IMEM");
2064 goto fail;
2065 }
2066 /* Wait for load to complete. */
2067 for (ntries = 0; ntries < 10; ntries++) {
2068 reg = rsu_read_2(sc, R92S_TCR(0x0040 + 0x004));
2069 if (reg & R92S_TCR_IMEM_CODE_DONE0x01)
2070 break;
2071 DELAY(10)(*delay_func)(10);
2072 }
2073 if (ntries == 10 || !(reg & R92S_TCR_IMEM_CHK_RPT0x02)) {
2074 printf("%s: timeout waiting for %s transfer\n",
2075 sc->sc_dev.dv_xname, "IMEM");
2076 error = ETIMEDOUT60;
2077 goto fail;
2078 }
2079
2080 /* Load EMEM section. */
2081 error = rsu_fw_loadsection(sc, emem, ememsz);
2082 if (error != 0) {
2083 printf("%s: could not load firmware section %s\n",
2084 sc->sc_dev.dv_xname, "EMEM");
2085 goto fail;
2086 }
2087 /* Wait for load to complete. */
2088 for (ntries = 0; ntries < 10; ntries++) {
2089 reg = rsu_read_2(sc, R92S_TCR(0x0040 + 0x004));
2090 if (reg & R92S_TCR_EMEM_CODE_DONE0x04)
2091 break;
2092 DELAY(10)(*delay_func)(10);
2093 }
2094 if (ntries == 10 || !(reg & R92S_TCR_EMEM_CHK_RPT0x08)) {
2095 printf("%s: timeout waiting for %s transfer\n",
2096 sc->sc_dev.dv_xname, "EMEM");
2097 error = ETIMEDOUT60;
2098 goto fail;
2099 }
2100
2101 /* Enable CPU. */
2102 rsu_write_1(sc, R92S_SYS_CLKR(0x0000 + 0x008),
2103 rsu_read_1(sc, R92S_SYS_CLKR(0x0000 + 0x008)) | R92S_SYS_CPU_CLKSEL0x0004);
2104 if (!(rsu_read_1(sc, R92S_SYS_CLKR(0x0000 + 0x008)) & R92S_SYS_CPU_CLKSEL0x0004)) {
2105 printf("%s: could not enable system clock\n",
2106 sc->sc_dev.dv_xname);
2107 error = EIO5;
2108 goto fail;
2109 }
2110 rsu_write_2(sc, R92S_SYS_FUNC_EN(0x0000 + 0x002),
2111 rsu_read_2(sc, R92S_SYS_FUNC_EN(0x0000 + 0x002)) | R92S_FEN_CPUEN0x0400);
2112 if (!(rsu_read_2(sc, R92S_SYS_FUNC_EN(0x0000 + 0x002)) & R92S_FEN_CPUEN0x0400)) {
2113 printf("%s: could not enable microcontroller\n",
2114 sc->sc_dev.dv_xname);
2115 error = EIO5;
2116 goto fail;
2117 }
2118 /* Wait for CPU to initialize. */
2119 for (ntries = 0; ntries < 100; ntries++) {
2120 if (rsu_read_2(sc, R92S_TCR(0x0040 + 0x004)) & R92S_TCR_IMEM_RDY0x20)
2121 break;
2122 DELAY(1000)(*delay_func)(1000);
2123 }
2124 if (ntries == 100) {
2125 printf("%s: timeout waiting for microcontroller\n",
2126 sc->sc_dev.dv_xname);
2127 error = ETIMEDOUT60;
2128 goto fail;
2129 }
2130
2131 /* Update DMEM section before loading. */
2132 dmem = &hdr->priv;
2133 memset(dmem, 0, sizeof(*dmem))__builtin_memset((dmem), (0), (sizeof(*dmem)));
2134 dmem->hci_sel = R92S_HCI_SEL_USB0x02 | R92S_HCI_SEL_81720x10;
2135 dmem->nendpoints = sc->npipes;
2136 dmem->rf_config = 0x12; /* 1T2R */
2137 dmem->vcs_type = R92S_VCS_TYPE_AUTO2;
2138 dmem->vcs_mode = R92S_VCS_MODE_RTS_CTS1;
2139 dmem->bw40_en = (ic->ic_htcaps & IEEE80211_HTCAP_CBW20_400x00000002) != 0;
2140 dmem->turbo_mode = 1;
2141 /* Load DMEM section. */
2142 error = rsu_fw_loadsection(sc, (uint8_t *)dmem, sizeof(*dmem));
2143 if (error != 0) {
2144 printf("%s: could not load firmware section %s\n",
2145 sc->sc_dev.dv_xname, "DMEM");
2146 goto fail;
2147 }
2148 /* Wait for load to complete. */
2149 for (ntries = 0; ntries < 100; ntries++) {
2150 if (rsu_read_2(sc, R92S_TCR(0x0040 + 0x004)) & R92S_TCR_DMEM_CODE_DONE0x10)
2151 break;
2152 DELAY(1000)(*delay_func)(1000);
2153 }
2154 if (ntries == 100) {
2155 printf("%s: timeout waiting for %s transfer\n",
2156 sc->sc_dev.dv_xname, "DMEM");
2157 error = ETIMEDOUT60;
2158 goto fail;
2159 }
2160 /* Wait for firmware readiness. */
2161 for (ntries = 0; ntries < 60; ntries++) {
2162 if (!(rsu_read_2(sc, R92S_TCR(0x0040 + 0x004)) & R92S_TCR_FWRDY0x80))
2163 break;
2164 DELAY(1000)(*delay_func)(1000);
2165 }
2166 if (ntries == 60) {
2167 printf("%s: timeout waiting for firmware readiness\n",
2168 sc->sc_dev.dv_xname);
2169 error = ETIMEDOUT60;
2170 goto fail;
2171 }
2172 fail:
2173 free(fw, M_DEVBUF2, size);
2174 return (error);
2175}
2176
2177int
2178rsu_init(struct ifnet *ifp)
2179{
2180 struct rsu_softc *sc = ifp->if_softc;
2181 struct ieee80211com *ic = &sc->sc_ic;
2182 struct r92s_set_pwr_mode cmd;
2183 struct rsu_rx_data *data;
2184 int i, error;
2185
2186 /* Init host async commands ring. */
2187 sc->cmdq.cur = sc->cmdq.next = sc->cmdq.queued = 0;
2188
2189 /* Allocate Tx/Rx buffers. */
2190 error = rsu_alloc_rx_list(sc);
2191 if (error != 0) {
2192 printf("%s: could not allocate Rx buffers\n",
2193 sc->sc_dev.dv_xname);
2194 goto fail;
2195 }
2196 error = rsu_alloc_tx_list(sc);
2197 if (error != 0) {
2198 printf("%s: could not allocate Tx buffers\n",
2199 sc->sc_dev.dv_xname);
2200 goto fail;
2201 }
2202 /* Reserve one Tx buffer for firmware commands. */
2203 sc->fwcmd_data = TAILQ_FIRST(&sc->tx_free_list)((&sc->tx_free_list)->tqh_first);
2204 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)
;
2205
2206 /* Power on adapter. */
2207 if (sc->cut == 1)
2208 rsu_power_on_acut(sc);
2209 else
2210 rsu_power_on_bcut(sc);
2211 /* Load firmware. */
2212 error = rsu_load_firmware(sc);
2213 if (error != 0)
2214 goto fail;
2215
2216 /* Enable Rx TCP checksum offload. */
2217 rsu_write_4(sc, R92S_RCR(0x0040 + 0x008),
2218 rsu_read_4(sc, R92S_RCR(0x0040 + 0x008)) | 0x04000000);
2219 /* Append PHY status. */
2220 rsu_write_4(sc, R92S_RCR(0x0040 + 0x008),
2221 rsu_read_4(sc, R92S_RCR(0x0040 + 0x008)) | 0x02000000);
2222
2223 rsu_write_4(sc, R92S_CR(0x0040 + 0x000),
2224 rsu_read_4(sc, R92S_CR(0x0040 + 0x000)) & ~0xff000000);
2225
2226 /* Use 128 bytes pages. */
2227 rsu_write_1(sc, 0x00b5,
2228 rsu_read_1(sc, 0x00b5) | 0x01);
2229 /* Enable USB Rx aggregation. */
2230 rsu_write_1(sc, 0x00bd,
2231 rsu_read_1(sc, 0x00bd) | 0x80);
2232 /* Set USB Rx aggregation threshold. */
2233 rsu_write_1(sc, 0x00d9, 0x01);
2234 /* Set USB Rx aggregation timeout (1.7ms/4). */
2235 rsu_write_1(sc, 0xfe5b, 0x04);
2236 /* Fix USB Rx FIFO issue. */
2237 rsu_write_1(sc, 0xfe5c,
2238 rsu_read_1(sc, 0xfe5c) | 0x80);
2239
2240 /* Set MAC address. */
2241 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))
;
2242 rsu_write_region_1(sc, R92S_MACID(0x0050 + 0x000), ic->ic_myaddr, IEEE80211_ADDR_LEN6);
2243
2244 /* Queue Rx xfers (XXX C2H pipe for 11-pipe configurations?) */
2245 for (i = 0; i < RSU_RX_LIST_COUNT1; i++) {
2246 data = &sc->rx_data[i];
2247
2248 data->pipe = sc->pipe[sc->qid2idx[RSU_QID_RXOFF7]];
2249 usbd_setup_xfer(data->xfer, data->pipe, data, data->buf,
2250 RSU_RXBUFSZ(8 * 1024), USBD_SHORT_XFER_OK0x04 | USBD_NO_COPY0x01,
2251 USBD_NO_TIMEOUT0, rsu_rxeof);
2252 error = usbd_transfer(data->xfer);
2253 if (error != 0 && error != USBD_IN_PROGRESS)
2254 goto fail;
2255 }
2256
2257 /* NB: it really takes that long for firmware to boot. */
2258 usbd_delay_ms(sc->sc_udev, 1500);
2259
2260 DPRINTF(("setting MAC address to %s\n", ether_sprintf(ic->ic_myaddr)));
2261 error = rsu_fw_cmd(sc, R92S_CMD_SET_MAC_ADDRESS58, ic->ic_myaddr,
2262 IEEE80211_ADDR_LEN6);
2263 if (error != 0) {
2264 printf("%s: could not set MAC address\n", sc->sc_dev.dv_xname);
2265 goto fail;
2266 }
2267
2268 rsu_write_1(sc, R92S_USB_HRPWM0xfe58,
2269 R92S_USB_HRPWM_PS_ST_ACTIVE0x08 | R92S_USB_HRPWM_PS_ALL_ON0x04);
2270
2271 memset(&cmd, 0, sizeof(cmd))__builtin_memset((&cmd), (0), (sizeof(cmd)));
2272 cmd.mode = R92S_PS_MODE_ACTIVE0;
2273 DPRINTF(("setting ps mode to %d\n", cmd.mode));
2274 error = rsu_fw_cmd(sc, R92S_CMD_SET_PWR_MODE36, &cmd, sizeof(cmd));
2275 if (error != 0) {
2276 printf("%s: could not set PS mode\n", sc->sc_dev.dv_xname);
2277 goto fail;
2278 }
2279
2280 if (ic->ic_htcaps & IEEE80211_HTCAP_CBW20_400x00000002) {
2281 /* Enable 40MHz mode. */
2282 error = rsu_fw_iocmd(sc,
2283 SM(R92S_IOCMD_CLASS, 0xf4)(((0xf4) << 24) & 0xff000000) |
2284 SM(R92S_IOCMD_INDEX, 0x00)(((0x00) << 0) & 0x000000ff) |
2285 SM(R92S_IOCMD_VALUE, 0x0007)(((0x0007) << 8) & 0x00ffff00));
2286 if (error != 0) {
2287 printf("%s: could not enable 40MHz mode\n",
2288 sc->sc_dev.dv_xname);
2289 goto fail;
2290 }
2291 }
2292
2293 /* Set default channel. */
2294 ic->ic_bss->ni_chan = ic->ic_ibss_chan;
2295
2296 /* We're ready to go. */
2297 ifp->if_flags |= IFF_RUNNING0x40;
2298 ifq_clr_oactive(&ifp->if_snd);
2299
2300#ifdef notyet
2301 if (ic->ic_flags & IEEE80211_F_WEPON0x00000100) {
2302 /* Install WEP keys. */
2303 for (i = 0; i < IEEE80211_WEP_NKID4; i++)
2304 rsu_set_key(ic, NULL((void *)0), &ic->ic_nw_keys[i]);
2305 rsu_wait_async(sc);
2306 }
2307#endif
2308
2309 sc->scan_pass = 0;
2310 ieee80211_begin_scan(ifp);
2311 return (0);
2312 fail:
2313 rsu_stop(ifp);
2314 return (error);
2315}
2316
2317void
2318rsu_stop(struct ifnet *ifp)
2319{
2320 struct rsu_softc *sc = ifp->if_softc;
2321 struct ieee80211com *ic = &sc->sc_ic;
2322 int i, s;
2323
2324 sc->sc_tx_timer = 0;
2325 ifp->if_timer = 0;
2326 ifp->if_flags &= ~IFF_RUNNING0x40;
2327 ifq_clr_oactive(&ifp->if_snd);
2328
2329 s = splusb()splraise(0x2);
2330 ieee80211_new_state(ic, IEEE80211_S_INIT, -1)(((ic)->ic_newstate)((ic), (IEEE80211_S_INIT), (-1)));
2331 /* Wait for all async commands to complete. */
2332 rsu_wait_async(sc);
2333 splx(s)spllower(s);
2334
2335 timeout_del(&sc->calib_to);
2336
2337 /* Power off adapter. */
2338 rsu_power_off(sc);
2339
2340 /* Abort Tx/Rx. */
2341 for (i = 0; i < sc->npipes; i++)
2342 usbd_abort_pipe(sc->pipe[i]);
2343
2344 /* Free Tx/Rx buffers. */
2345 rsu_free_tx_list(sc);
2346 rsu_free_rx_list(sc);
2347}