Bug Summary

File:dev/usb/if_mtw.c
Warning:line 516, column 2
Value stored to 'txwisize' is never read

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_mtw.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_mtw.c
1/* $OpenBSD: if_mtw.c,v 1.8 2023/03/08 04:43:08 guenther Exp $ */
2/*
3 * Copyright (c) 2008-2010 Damien Bergamini <damien.bergamini@free.fr>
4 * Copyright (c) 2013-2014 Kevin Lo
5 * Copyright (c) 2021 James Hastings
6 *
7 * Permission to use, copy, modify, and distribute this software for any
8 * purpose with or without fee is hereby granted, provided that the above
9 * copyright notice and this permission notice appear in all copies.
10 *
11 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18 */
19
20/*
21 * MediaTek MT7601U 802.11b/g/n WLAN.
22 */
23
24#include "bpfilter.h"
25
26#include <sys/param.h>
27#include <sys/sockio.h>
28#include <sys/mbuf.h>
29#include <sys/kernel.h>
30#include <sys/socket.h>
31#include <sys/systm.h>
32#include <sys/timeout.h>
33#include <sys/conf.h>
34#include <sys/device.h>
35#include <sys/endian.h>
36
37#include <machine/intr.h>
38
39#if NBPFILTER1 > 0
40#include <net/bpf.h>
41#endif
42#include <net/if.h>
43#include <net/if_dl.h>
44#include <net/if_media.h>
45
46#include <netinet/in.h>
47#include <netinet/if_ether.h>
48
49#include <net80211/ieee80211_var.h>
50#include <net80211/ieee80211_amrr.h>
51#include <net80211/ieee80211_ra.h>
52#include <net80211/ieee80211_radiotap.h>
53
54#include <dev/usb/usb.h>
55#include <dev/usb/usbdi.h>
56#include <dev/usb/usbdi_util.h>
57#include <dev/usb/usbdevs.h>
58
59#include <dev/ic/mtwreg.h>
60#include <dev/usb/if_mtwvar.h>
61
62#ifdef MTW_DEBUG
63#define DPRINTF(x) do { if (mtw_debug) printf x; } while (0)
64#define DPRINTFN(n, x) do { if (mtw_debug >= (n)) printf x; } while (0)
65int mtw_debug = 0;
66#else
67#define DPRINTF(x)
68#define DPRINTFN(n, x)
69#endif
70
71#define USB_ID(v, p){ USB_VENDOR_v, USB_PRODUCT_v_p } { USB_VENDOR_##v, USB_PRODUCT_##v##_##p }
72static const struct usb_devno mtw_devs[] = {
73 USB_ID(ASUS, USBN10V2){ 0x0b05, 0x17d3 },
74 USB_ID(AZUREWAVE, MT7601_1){ 0x13d3, 0x3431 },
75 USB_ID(AZUREWAVE, MT7601_2){ 0x13d3, 0x3434 },
76 USB_ID(DLINK, DWA127B1){ 0x2001, 0x3d04 },
77 USB_ID(EDIMAX, EW7711UANV2){ 0x7392, 0x7710 },
78 USB_ID(MEDIATEK, MT7601_1){ 0x0e8d, 0x760a },
79 USB_ID(MEDIATEK, MT7601_2){ 0x0e8d, 0x760b },
80 USB_ID(RALINK, MT7601){ 0x148f, 0x7601 },
81 USB_ID(RALINK, MT7601_2){ 0x148f, 0x760a },
82 USB_ID(RALINK, MT7601_3){ 0x148f, 0x760b },
83 USB_ID(RALINK, MT7601_4){ 0x148f, 0x760c },
84 USB_ID(RALINK, MT7601_5){ 0x148f, 0x760d },
85 USB_ID(XIAOMI, MT7601U){ 0x2717, 0x4106 },
86};
87
88int mtw_match(struct device *, void *, void *);
89void mtw_attach(struct device *, struct device *, void *);
90int mtw_detach(struct device *, int);
91void mtw_attachhook(struct device *);
92int mtw_alloc_rx_ring(struct mtw_softc *, int);
93void mtw_free_rx_ring(struct mtw_softc *, int);
94int mtw_alloc_tx_ring(struct mtw_softc *, int);
95void mtw_free_tx_ring(struct mtw_softc *, int);
96int mtw_alloc_mcu_ring(struct mtw_softc *);
97void mtw_free_mcu_ring(struct mtw_softc *);
98int mtw_ucode_write(struct mtw_softc *, const uint8_t *,
99 uint32_t, uint32_t);
100void mtw_ucode_setup(struct mtw_softc *);
101int mtw_load_microcode(struct mtw_softc *);
102int mtw_reset(struct mtw_softc *);
103int mtw_read(struct mtw_softc *, uint16_t, uint32_t *);
104int mtw_read_cfg(struct mtw_softc *, uint16_t, uint32_t *);
105int mtw_read_region_1(struct mtw_softc *, uint16_t,
106 uint8_t *, int);
107int mtw_write_2(struct mtw_softc *, uint16_t, uint16_t);
108int mtw_write(struct mtw_softc *, uint16_t, uint32_t);
109int mtw_write_cfg(struct mtw_softc *, uint16_t, uint32_t);
110int mtw_write_ivb(struct mtw_softc *, const uint8_t *, uint16_t);
111int mtw_write_region_1(struct mtw_softc *, uint16_t,
112 uint8_t *, int);
113int mtw_set_region_4(struct mtw_softc *, uint16_t, uint32_t, int);
114int mtw_efuse_read_2(struct mtw_softc *, uint16_t, uint16_t *);
115int mtw_eeprom_read_2(struct mtw_softc *, uint16_t, uint16_t *);
116int mtw_rf_read(struct mtw_softc *, uint8_t, uint8_t, uint8_t *);
117int mtw_rf_write(struct mtw_softc *, uint8_t, uint8_t, uint8_t);
118int mtw_bbp_read(struct mtw_softc *, uint8_t, uint8_t *);
119int mtw_bbp_write(struct mtw_softc *, uint8_t, uint8_t);
120int mtw_usb_dma_read(struct mtw_softc *, uint32_t *);
121int mtw_usb_dma_write(struct mtw_softc *, uint32_t);
122int mtw_mcu_calibrate(struct mtw_softc *, int, uint32_t);
123int mtw_mcu_channel(struct mtw_softc *, uint32_t, uint32_t, uint32_t);
124int mtw_mcu_radio(struct mtw_softc *, int, uint32_t);
125int mtw_mcu_cmd(struct mtw_softc *, int, void *, int);
126const char * mtw_get_rf(int);
127void mtw_get_txpower(struct mtw_softc *);
128int mtw_read_eeprom(struct mtw_softc *);
129struct ieee80211_node *mtw_node_alloc(struct ieee80211com *);
130int mtw_media_change(struct ifnet *);
131void mtw_next_scan(void *);
132void mtw_task(void *);
133void mtw_do_async(struct mtw_softc *, void (*)(struct mtw_softc *,
134 void *), void *, int);
135int mtw_newstate(struct ieee80211com *, enum ieee80211_state, int);
136void mtw_newstate_cb(struct mtw_softc *, void *);
137void mtw_updateedca(struct ieee80211com *);
138void mtw_updateedca_cb(struct mtw_softc *, void *);
139void mtw_updateslot(struct ieee80211com *);
140void mtw_updateslot_cb(struct mtw_softc *, void *);
141int mtw_set_key(struct ieee80211com *, struct ieee80211_node *,
142 struct ieee80211_key *);
143void mtw_set_key_cb(struct mtw_softc *, void *);
144void mtw_delete_key(struct ieee80211com *, struct ieee80211_node *,
145 struct ieee80211_key *);
146void mtw_delete_key_cb(struct mtw_softc *, void *);
147void mtw_calibrate_to(void *);
148void mtw_calibrate_cb(struct mtw_softc *, void *);
149void mtw_newassoc(struct ieee80211com *, struct ieee80211_node *,
150 int);
151void mtw_rx_frame(struct mtw_softc *, uint8_t *, int,
152 struct mbuf_list *);
153void mtw_rxeof(struct usbd_xfer *, void *, usbd_status);
154void mtw_txeof(struct usbd_xfer *, void *, usbd_status);
155int mtw_tx(struct mtw_softc *, struct mbuf *,
156 struct ieee80211_node *);
157void mtw_start(struct ifnet *);
158void mtw_watchdog(struct ifnet *);
159int mtw_ioctl(struct ifnet *, u_long, caddr_t);
160void mtw_select_chan_group(struct mtw_softc *, int);
161void mt7601_set_agc(struct mtw_softc *, uint8_t);
162void mt7601_set_chan(struct mtw_softc *, u_int);
163int mtw_set_chan(struct mtw_softc *, struct ieee80211_channel *);
164void mtw_enable_tsf_sync(struct mtw_softc *);
165void mtw_abort_tsf_sync(struct mtw_softc *);
166void mtw_enable_mrr(struct mtw_softc *);
167void mtw_set_txrts(struct mtw_softc *);
168void mtw_set_txpreamble(struct mtw_softc *);
169void mtw_set_basicrates(struct mtw_softc *);
170void mtw_set_leds(struct mtw_softc *, uint16_t);
171void mtw_set_bssid(struct mtw_softc *, const uint8_t *);
172void mtw_set_macaddr(struct mtw_softc *, const uint8_t *);
173#if NBPFILTER1 > 0
174int8_t mtw_rssi2dbm(struct mtw_softc *, uint8_t, uint8_t);
175#endif
176int mt7601_bbp_init(struct mtw_softc *);
177int mt7601_rf_init(struct mtw_softc *);
178int mt7601_rf_setup(struct mtw_softc *);
179int mt7601_rf_temperature(struct mtw_softc *, int8_t *);
180int mt7601_r49_read(struct mtw_softc *, uint8_t, int8_t *);
181int mt7601_rxdc_cal(struct mtw_softc *);
182int mtw_wlan_enable(struct mtw_softc *, int);
183int mtw_txrx_enable(struct mtw_softc *);
184int mtw_init(struct ifnet *);
185void mtw_stop(struct ifnet *, int);
186
187struct cfdriver mtw_cd = {
188 NULL((void *)0), "mtw", DV_IFNET
189};
190
191const struct cfattach mtw_ca = {
192 sizeof (struct mtw_softc), mtw_match, mtw_attach, mtw_detach
193};
194
195static const struct {
196 uint32_t reg;
197 uint32_t val;
198} mt7601_def_mac[] = {
199 MT7601_DEF_MAC{ 0x041c, 0x18100800 }, { 0x0420, 0x38302820 }, { 0x0424, 0x58504840
}, { 0x0428, 0x78706860 }, { 0x1004, 0x0000000c }, { 0x1018,
0x000a3fff }, { 0x1030, 0x77777777 }, { 0x1034, 0x77777777 }
, { 0x1038, 0x77777777 }, { 0x103c, 0x77777777 }, { 0x1100, 0x33a41010
}, { 0x1104, 0x00000209 }, { 0x1118, 0x00422010 }, { 0x1128,
0x00000000 }, { 0x1204, 0x00000000 }, { 0x1208, 0x00000014 }
, { (0x1300 + (0) * 4), 0x000a4360 }, { (0x1300 + (1) * 4), 0x000a4700
}, { (0x1300 + (2) * 4), 0x00043338 }, { (0x1300 + (3) * 4),
0x0003222f }, { 0x1328, 0x33150f0f }, { 0x132c, 0x00000005 }
, { 0x1330, 0x00000402 }, { 0x1334, 0x00000000 }, { 0x1338, 0x00000000
}, { 0x1340, 0x0000583f }, { 0x1344, 0x01100020 }, { 0x1348,
0x000a2090 }, { 0x134c, 0x47d01f0f }, { 0x1350, 0x007f1820 }
, { 0x1358, 0xedcba980 }, { 0x1364, 0x07f40000 }, { 0x1368, 0x07f60000
}, { 0x136c, 0x01750003 }, { 0x1370, 0x03f50003 }, { 0x1374,
0x01750003 }, { 0x1378, 0x03f50003 }, { 0x1380, 0x002400ca }
, { 0x1384, 0x00000000 }, { 0x1388, 0x01010101 }, { 0x13a0, 0x003b0005
}, { 0x13a4, 0x00000000 }, { 0x13a8, 0x00006969 }, { 0x13ac,
0x6c6c6c6c }, { 0x13b0, 0x2f2f0005 }, { 0x13c0, 0x00000400 }
, { 0x13c8, 0x00060006 }, { 0x1400, 0x00015f97 }, { 0x1404, 0x00000003
}, { 0x1408, 0x0000015f }, { 0x140c, 0x00008003 }, { 0x040c,
0x0000009f }, { 0x0208, 0x00000030 }, { 0x0214, 0x00002273 }
, { 0x0218, 0x00002344 }, { 0x021c, 0x000034aa }, { 0x0250, 0x00000000
}, { 0x0400, 0x00080c00 }, { 0x0800, 0x00000001 }, { 0x120c,
0x00000000 }, { 0x1214, 0x010055ff }, { 0x1218, 0x00550055 }
, { 0x121c, 0x010055ff }, { 0x1220, 0x00550055 }, { 0x0a38, 0x00000000
}, { 0x101c, 0x00000000 }, { 0x0404, 0x7f723c1f }
200};
201
202static const struct {
203 uint8_t reg;
204 uint8_t val;
205} mt7601_def_bbp[] = {
206 MT7601_DEF_BBP{ 1, 0x04 }, { 4, 0x40 }, { 20, 0x06 }, { 31, 0x08 }, { 178, 0xff
}, { 66, 0x14 }, { 68, 0x8b }, { 69, 0x12 }, { 70, 0x09 }, {
73, 0x11 }, { 75, 0x60 }, { 76, 0x44 }, { 84, 0x9a }, { 86, 0x38
}, { 91, 0x07 }, { 92, 0x02 }, { 99, 0x50 }, { 101, 0x00 }, {
103, 0xc0 }, { 104, 0x92 }, { 105, 0x3c }, { 106, 0x03 }, { 128
, 0x12 }, { 142, 0x04 }, { 143, 0x37 }, { 142, 0x03 }, { 143,
0x99 }, { 160, 0xeb }, { 161, 0xc4 }, { 162, 0x77 }, { 163, 0xf9
}, { 164, 0x88 }, { 165, 0x80 }, { 166, 0xff }, { 167, 0xe4 }
, { 195, 0x00 }, { 196, 0x00 }, { 195, 0x01 }, { 196, 0x04 },
{ 195, 0x02 }, { 196, 0x20 }, { 195, 0x03 }, { 196, 0x0a }, {
195, 0x06 }, { 196, 0x16 }, { 195, 0x07 }, { 196, 0x05 }, { 195
, 0x08 }, { 196, 0x37 }, { 195, 0x0a }, { 196, 0x15 }, { 195,
0x0b }, { 196, 0x17 }, { 195, 0x0c }, { 196, 0x06 }, { 195, 0x0d
}, { 196, 0x09 }, { 195, 0x0e }, { 196, 0x05 }, { 195, 0x0f }
, { 196, 0x09 }, { 195, 0x10 }, { 196, 0x20 }, { 195, 0x20 },
{ 196, 0x17 }, { 195, 0x21 }, { 196, 0x06 }, { 195, 0x22 }, {
196, 0x09 }, { 195, 0x23 }, { 196, 0x17 }, { 195, 0x24 }, { 196
, 0x06 }, { 195, 0x25 }, { 196, 0x09 }, { 195, 0x26 }, { 196,
0x17 }, { 195, 0x27 }, { 196, 0x06 }, { 195, 0x28 }, { 196, 0x09
}, { 195, 0x29 }, { 196, 0x05 }, { 195, 0x2a }, { 196, 0x09 }
, { 195, 0x80 }, { 196, 0x8b }, { 195, 0x81 }, { 196, 0x12 },
{ 195, 0x82 }, { 196, 0x09 }, { 195, 0x83 }, { 196, 0x17 }, {
195, 0x84 }, { 196, 0x11 }, { 195, 0x85 }, { 196, 0x00 }, { 195
, 0x86 }, { 196, 0x00 }, { 195, 0x87 }, { 196, 0x18 }, { 195,
0x88 }, { 196, 0x60 }, { 195, 0x89 }, { 196, 0x44 }, { 195, 0x8a
}, { 196, 0x8b }, { 195, 0x8b }, { 196, 0x8b }, { 195, 0x8c }
, { 196, 0x8b }, { 195, 0x8d }, { 196, 0x8b }, { 195, 0x8e },
{ 196, 0x09 }, { 195, 0x8f }, { 196, 0x09 }, { 195, 0x90 }, {
196, 0x09 }, { 195, 0x91 }, { 196, 0x09 }, { 195, 0x92 }, { 196
, 0x11 }, { 195, 0x93 }, { 196, 0x11 }, { 195, 0x94 }, { 196,
0x11 }, { 195, 0x95 }, { 196, 0x11 }, { 47, 0x80 }, { 60, 0x80
}, { 150, 0xd2 }, { 151, 0x32 }, { 152, 0x23 }, { 153, 0x41 }
, { 154, 0x00 }, { 155, 0x4f }, { 253, 0x7e }, { 195, 0x30 },
{ 196, 0x32 }, { 195, 0x31 }, { 196, 0x23 }, { 195, 0x32 }, {
196, 0x45 }, { 195, 0x35 }, { 196, 0x4a }, { 195, 0x36 }, { 196
, 0x5a }, { 195, 0x37 }, { 196, 0x5a }
207};
208
209static const struct {
210 u_int chan;
211 uint8_t r17, r18, r19, r20;
212} mt7601_rf_chan[] = {
213 MT7601_RF_CHAN{ 1, 0x99, 0x99, 0x09, 0x50 }, { 2, 0x46, 0x44, 0x0a, 0x50 },
{ 3, 0xec, 0xee, 0x0a, 0x50 }, { 4, 0x99, 0x99, 0x0b, 0x50 }
, { 5, 0x46, 0x44, 0x08, 0x51 }, { 6, 0xec, 0xee, 0x08, 0x51 }
, { 7, 0x99, 0x99, 0x09, 0x51 }, { 8, 0x46, 0x44, 0x0a, 0x51 }
, { 9, 0xec, 0xee, 0x0a, 0x51 }, { 10, 0x99, 0x99, 0x0b, 0x51
}, { 11, 0x46, 0x44, 0x08, 0x52 }, { 12, 0xec, 0xee, 0x08, 0x52
}, { 13, 0x99, 0x99, 0x09, 0x52 }, { 14, 0x33, 0x33, 0x0b, 0x52
}
214};
215
216static const struct {
217 uint8_t reg;
218 uint8_t val;
219} mt7601_rf_bank0[] = {
220 MT7601_BANK0_RF{ 0, 0x02 }, { 1, 0x01 }, { 2, 0x11 }, { 3, 0xff }, { 4, 0x0a
}, { 5, 0x20 }, { 6, 0x00 }, { 7, 0x00 }, { 8, 0x00 }, { 9, 0x00
}, { 10, 0x00 }, { 11, 0x21 }, { 13, 0x00 }, { 14, 0x7c }, {
15, 0x22 }, { 16, 0x80 }, { 17, 0x99 }, { 18, 0x99 }, { 19, 0x09
}, { 20, 0x50 }, { 21, 0xb0 }, { 22, 0x00 }, { 23, 0xc5 }, {
24, 0xfc }, { 25, 0x40 }, { 26, 0x4d }, { 27, 0x02 }, { 28, 0x72
}, { 29, 0x01 }, { 30, 0x00 }, { 31, 0x00 }, { 32, 0x00 }, {
33, 0x00 }, { 34, 0x23 }, { 35, 0x01 }, { 36, 0x00 }, { 37, 0x00
}, { 38, 0x00 }, { 39, 0x20 }, { 40, 0x00 }, { 41, 0xd0 }, {
42, 0x1b }, { 43, 0x02 }, { 44, 0x00 }
221},mt7601_rf_bank4[] = {
222 MT7601_BANK4_RF{ 0, 0x01 }, { 1, 0x00 }, { 2, 0x00 }, { 3, 0x00 }, { 4, 0x00
}, { 5, 0x08 }, { 6, 0x00 }, { 7, 0x5b }, { 8, 0x52 }, { 9, 0xb6
}, { 10, 0x57 }, { 11, 0x33 }, { 12, 0x22 }, { 13, 0x3d }, {
14, 0x3e }, { 15, 0x13 }, { 16, 0x22 }, { 17, 0x23 }, { 18, 0x02
}, { 19, 0xa4 }, { 20, 0x01 }, { 21, 0x12 }, { 22, 0x80 }, {
23, 0xb3 }, { 24, 0x00 }, { 25, 0x00 }, { 26, 0x00 }, { 27, 0x00
}, { 28, 0x18 }, { 29, 0xee }, { 30, 0x6b }, { 31, 0x31 }, {
32, 0x5d }, { 33, 0x00 }, { 34, 0x96 }, { 35, 0x55 }, { 36, 0x08
}, { 37, 0xbb }, { 38, 0xb3 }, { 39, 0xb3 }, { 40, 0x03 }, {
41, 0x00 }, { 42, 0x00 }, { 43, 0xc5 }, { 44, 0xc5 }, { 45, 0xc5
}, { 46, 0x07 }, { 47, 0xa8 }, { 48, 0xef }, { 49, 0x1a }, {
54, 0x07 }, { 55, 0xa7 }, { 56, 0xcc }, { 57, 0x14 }, { 58, 0x07
}, { 59, 0xa8 }, { 60, 0xd7 }, { 61, 0x10 }, { 62, 0x1c }, {
63, 0x00 }
223},mt7601_rf_bank5[] = {
224 MT7601_BANK5_RF{ 0, 0x47 }, { 1, 0x00 }, { 2, 0x00 }, { 3, 0x08 }, { 4, 0x04
}, { 5, 0x20 }, { 6, 0x3a }, { 7, 0x3a }, { 8, 0x00 }, { 9, 0x00
}, { 10, 0x10 }, { 11, 0x10 }, { 12, 0x10 }, { 13, 0x10 }, {
14, 0x10 }, { 15, 0x20 }, { 16, 0x22 }, { 17, 0x7c }, { 18, 0x00
}, { 19, 0x00 }, { 20, 0x00 }, { 21, 0xf1 }, { 22, 0x11 }, {
23, 0x02 }, { 24, 0x41 }, { 25, 0x20 }, { 26, 0x00 }, { 27, 0xd7
}, { 28, 0xa2 }, { 29, 0x20 }, { 30, 0x49 }, { 31, 0x20 }, {
32, 0x04 }, { 33, 0xf1 }, { 34, 0xa1 }, { 35, 0x01 }, { 41, 0x00
}, { 42, 0x00 }, { 43, 0x00 }, { 44, 0x00 }, { 45, 0x00 }, {
46, 0x00 }, { 47, 0x00 }, { 48, 0x00 }, { 49, 0x00 }, { 50, 0x00
}, { 51, 0x00 }, { 52, 0x00 }, { 53, 0x00 }, { 54, 0x00 }, {
55, 0x00 }, { 56, 0x00 }, { 57, 0x00 }, { 58, 0x31 }, { 59, 0x31
}, { 60, 0x0a }, { 61, 0x02 }, { 62, 0x00 }, { 63, 0x00 }
225};
226
227int
228mtw_match(struct device *parent, void *match, void *aux)
229{
230 struct usb_attach_arg *uaa = aux;
231
232 if (uaa->iface == NULL((void *)0) || uaa->configno != 1)
233 return UMATCH_NONE0;
234
235 return (usb_lookup(mtw_devs, uaa->vendor, uaa->product)usbd_match_device((const struct usb_devno *)(mtw_devs), sizeof
(mtw_devs) / sizeof ((mtw_devs)[0]), sizeof ((mtw_devs)[0]),
(uaa->vendor), (uaa->product))
!= NULL((void *)0)) ?
236 UMATCH_VENDOR_PRODUCT_CONF_IFACE8 : UMATCH_NONE0;
237}
238
239void
240mtw_attach(struct device *parent, struct device *self, void *aux)
241{
242 struct mtw_softc *sc = (struct mtw_softc *)self;
243 struct usb_attach_arg *uaa = aux;
244 usb_interface_descriptor_t *id;
245 usb_endpoint_descriptor_t *ed;
246 int i, error, nrx, ntx, ntries;
247 uint32_t ver;
248
249 sc->sc_udev = uaa->device;
250 sc->sc_iface = uaa->iface;
251
252 /*
253 * Find all bulk endpoints.
254 */
255 nrx = ntx = 0;
256 id = usbd_get_interface_descriptor(sc->sc_iface);
257 for (i = 0; i < id->bNumEndpoints; i++) {
258 ed = usbd_interface2endpoint_descriptor(sc->sc_iface, i);
259 if (ed == NULL((void *)0) || UE_GET_XFERTYPE(ed->bmAttributes)((ed->bmAttributes) & 0x03) != UE_BULK0x02)
260 continue;
261
262 if (UE_GET_DIR(ed->bEndpointAddress)((ed->bEndpointAddress) & 0x80) == UE_DIR_IN0x80) {
263 sc->rxq[nrx].pipe_no = ed->bEndpointAddress;
264 nrx++;
265 } else if (ntx < 6) {
266 if (ntx == 0)
267 sc->txq[MTW_TXQ_MCU5].pipe_no =
268 ed->bEndpointAddress;
269 else
270 sc->txq[ntx - 1].pipe_no =
271 ed->bEndpointAddress;
272 ntx++;
273 }
274 }
275 /* make sure we've got them all */
276 if (nrx < 2 || ntx < 6) {
277 printf("%s: missing endpoint\n", sc->sc_dev.dv_xname);
278 return;
279 }
280
281 /* wait for the chip to settle */
282 for (ntries = 0; ntries < 100; ntries++) {
283 if ((error = mtw_read(sc, MTW_ASIC_VER0x0000, &ver)) != 0)
284 return;
285 if (ver != 0 && ver != 0xffffffff)
286 break;
287 DPRINTF(("%08x ", ver));
288 DELAY(10)(*delay_func)(10);
289 }
290 if (ntries == 100) {
291 printf("%s: timeout waiting for NIC to initialize\n",
292 sc->sc_dev.dv_xname);
293 return;
294 }
295
296 sc->asic_ver = ver >> 16;
297 sc->asic_rev = ver & 0xffff;
298
299 usb_init_task(&sc->sc_task, mtw_task, sc, USB_TASK_TYPE_GENERIC)((&sc->sc_task)->fun = (mtw_task), (&sc->sc_task
)->arg = (sc), (&sc->sc_task)->type = (0), (&
sc->sc_task)->state = 0x0)
;
300 timeout_set(&sc->scan_to, mtw_next_scan, sc);
301 timeout_set(&sc->calib_to, mtw_calibrate_to, sc);
302
303 sc->amrr.amrr_min_success_threshold = 1;
304 sc->amrr.amrr_max_success_threshold = 10;
305
306 config_mountroot(self, mtw_attachhook);
307}
308
309int
310mtw_detach(struct device *self, int flags)
311{
312 struct mtw_softc *sc = (struct mtw_softc *)self;
313 struct ifnet *ifp = &sc->sc_ic.ic_ific_ac.ac_if;
314 int qid, s;
315
316 s = splusb()splraise(0x2);
317
318 if (timeout_initialized(&sc->scan_to)((&sc->scan_to)->to_flags & 0x04))
319 timeout_del(&sc->scan_to);
320 if (timeout_initialized(&sc->calib_to)((&sc->calib_to)->to_flags & 0x04))
321 timeout_del(&sc->calib_to);
322
323 /* wait for all queued asynchronous commands to complete */
324 usb_rem_wait_task(sc->sc_udev, &sc->sc_task);
325
326 usbd_ref_wait(sc->sc_udev);
327
328 if (ifp->if_softc != NULL((void *)0)) {
329 ifp->if_flags &= ~IFF_RUNNING0x40;
330 ifq_clr_oactive(&ifp->if_snd);
331 ieee80211_ifdetach(ifp);
332 if_detach(ifp);
333 }
334
335 /* free rings and close pipes */
336 mtw_free_mcu_ring(sc);
337 for (qid = 0; qid < MTW_TXQ_COUNT6; qid++)
338 mtw_free_tx_ring(sc, qid);
339 mtw_free_rx_ring(sc, 0);
340 mtw_free_rx_ring(sc, 1);
341
342 splx(s)spllower(s);
343 return 0;
344}
345
346void
347mtw_attachhook(struct device *self)
348{
349 struct mtw_softc *sc = (struct mtw_softc *)self;
350 struct ieee80211com *ic = &sc->sc_ic;
351 struct ifnet *ifp = &ic->ic_ific_ac.ac_if;
352 uint32_t tmp;
353 int ntries, error, i;
354
355 if (usbd_is_dying(sc->sc_udev))
356 return;
357
358 /* enable WLAN core */
359 if ((error = mtw_wlan_enable(sc, 1)) != 0) {
360 printf("%s: could not enable WLAN core\n",
361 sc->sc_dev.dv_xname);
362 return;
363 }
364
365 /* load firmware */
366 if ((error = mtw_load_microcode(sc)) != 0) {
367 printf("%s: could not load microcode\n",
368 sc->sc_dev.dv_xname);
369 goto fail;
370 }
371
372 mtw_usb_dma_read(sc, &tmp);
373 mtw_usb_dma_write(sc, tmp | (MTW_USB_RX_EN(1U << 22) | MTW_USB_TX_EN(1U << 23)));
374
375 /* read MAC version */
376 for (ntries = 0; ntries < 100; ntries++) {
377 if ((error = mtw_read(sc, MTW_MAC_VER_ID0x1000, &tmp)) != 0)
378 goto fail;
379 if (tmp != 0 && tmp != 0xffffffff)
380 break;
381 DELAY(10)(*delay_func)(10);
382 }
383 if (ntries == 100) {
384 printf("%s: failed reading MAC\n", sc->sc_dev.dv_xname);
385 goto fail;
386 }
387
388 sc->mac_ver = tmp >> 16;
389 sc->mac_rev = tmp & 0xffff;
390
391 /* retrieve RF rev. no and various other things from EEPROM */
392 mtw_read_eeprom(sc);
393
394 printf("%s: MAC/BBP MT%04X (rev 0x%04X), RF %s (MIMO %dT%dR), "
395 "address %s\n", sc->sc_dev.dv_xname, sc->mac_ver,
396 sc->mac_rev, mtw_get_rf(sc->rf_rev), sc->ntxchains,
397 sc->nrxchains, ether_sprintf(ic->ic_myaddr));
398
399 ic->ic_phytype = IEEE80211_T_OFDM; /* not only, but not used */
400 ic->ic_opmode = IEEE80211_M_STA; /* default to BSS mode */
401 ic->ic_state = IEEE80211_S_INIT;
402
403 /* set device capabilities */
404 ic->ic_caps =
405 IEEE80211_C_MONITOR0x00000200 | /* monitor mode supported */
406 IEEE80211_C_SHPREAMBLE0x00000100 | /* short preamble supported */
407 IEEE80211_C_SHSLOT0x00000080 | /* short slot time supported */
408 IEEE80211_C_WEP0x00000001 | /* WEP */
409 IEEE80211_C_RSN0x00001000; /* WPA/RSN */
410
411 /* set supported .11b and .11g rates */
412 ic->ic_sup_rates[IEEE80211_MODE_11B] = ieee80211_std_rateset_11b;
413 ic->ic_sup_rates[IEEE80211_MODE_11G] = ieee80211_std_rateset_11g;
414
415 /* set supported .11b and .11g channels (1 through 14) */
416 for (i = 1; i <= 14; i++) {
417 ic->ic_channels[i].ic_freq =
418 ieee80211_ieee2mhz(i, IEEE80211_CHAN_2GHZ0x0080);
419 ic->ic_channels[i].ic_flags =
420 IEEE80211_CHAN_CCK0x0020 | IEEE80211_CHAN_OFDM0x0040 |
421 IEEE80211_CHAN_DYN0x0400 | IEEE80211_CHAN_2GHZ0x0080;
422 }
423
424 ifp->if_softc = sc;
425 ifp->if_flags = IFF_BROADCAST0x2 | IFF_SIMPLEX0x800 | IFF_MULTICAST0x8000;
426 ifp->if_ioctl = mtw_ioctl;
427 ifp->if_start = mtw_start;
428 ifp->if_watchdog = mtw_watchdog;
429 memcpy(ifp->if_xname, sc->sc_dev.dv_xname, IFNAMSIZ)__builtin_memcpy((ifp->if_xname), (sc->sc_dev.dv_xname)
, (16))
;
430
431 if_attach(ifp);
432 ieee80211_ifattach(ifp);
433 ic->ic_node_alloc = mtw_node_alloc;
434 ic->ic_newassoc = mtw_newassoc;
435 ic->ic_updateslot = mtw_updateslot;
436 ic->ic_updateedca = mtw_updateedca;
437 ic->ic_set_key = mtw_set_key;
438 ic->ic_delete_key = mtw_delete_key;
439
440 /* override 802.11 state transition machine */
441 sc->sc_newstate = ic->ic_newstate;
442 ic->ic_newstate = mtw_newstate;
443 ieee80211_media_init(ifp, mtw_media_change, ieee80211_media_status);
444
445#if NBPFILTER1 > 0
446 bpfattach(&sc->sc_drvbpf, ifp, DLT_IEEE802_11_RADIO127,
447 sizeof (struct ieee80211_frame) + IEEE80211_RADIOTAP_HDRLEN64);
448
449 sc->sc_rxtap_len = sizeof sc->sc_rxtapu;
450 sc->sc_rxtapsc_rxtapu.th.wr_ihdr.it_len = htole16(sc->sc_rxtap_len)((__uint16_t)(sc->sc_rxtap_len));
451 sc->sc_rxtapsc_rxtapu.th.wr_ihdr.it_present = htole32(MTW_RX_RADIOTAP_PRESENT)((__uint32_t)((1 << IEEE80211_RADIOTAP_FLAGS | 1 <<
IEEE80211_RADIOTAP_RATE | 1 << IEEE80211_RADIOTAP_CHANNEL
| 1 << IEEE80211_RADIOTAP_DBM_ANTSIGNAL | 1 << IEEE80211_RADIOTAP_ANTENNA
| 1 << IEEE80211_RADIOTAP_DB_ANTSIGNAL)))
;
452
453 sc->sc_txtap_len = sizeof sc->sc_txtapu;
454 sc->sc_txtapsc_txtapu.th.wt_ihdr.it_len = htole16(sc->sc_txtap_len)((__uint16_t)(sc->sc_txtap_len));
455 sc->sc_txtapsc_txtapu.th.wt_ihdr.it_present = htole32(MTW_TX_RADIOTAP_PRESENT)((__uint32_t)((1 << IEEE80211_RADIOTAP_FLAGS | 1 <<
IEEE80211_RADIOTAP_RATE | 1 << IEEE80211_RADIOTAP_CHANNEL
)))
;
456#endif
457fail:
458 return;
459}
460
461int
462mtw_alloc_rx_ring(struct mtw_softc *sc, int qid)
463{
464 struct mtw_rx_ring *rxq = &sc->rxq[qid];
465 int i, error;
466
467 if ((error = usbd_open_pipe(sc->sc_iface, rxq->pipe_no, 0,
468 &rxq->pipeh)) != 0)
469 goto fail;
470
471 for (i = 0; i < MTW_RX_RING_COUNT1; i++) {
472 struct mtw_rx_data *data = &rxq->data[i];
473
474 data->sc = sc; /* backpointer for callbacks */
475
476 data->xfer = usbd_alloc_xfer(sc->sc_udev);
477 if (data->xfer == NULL((void *)0)) {
478 error = ENOMEM12;
479 goto fail;
480 }
481 data->buf = usbd_alloc_buffer(data->xfer, MTW_MAX_RXSZ4096);
482 if (data->buf == NULL((void *)0)) {
483 error = ENOMEM12;
484 goto fail;
485 }
486 }
487 if (error != 0)
488fail: mtw_free_rx_ring(sc, 0);
489 return error;
490}
491
492void
493mtw_free_rx_ring(struct mtw_softc *sc, int qid)
494{
495 struct mtw_rx_ring *rxq = &sc->rxq[qid];
496 int i;
497
498 if (rxq->pipeh != NULL((void *)0)) {
499 usbd_close_pipe(rxq->pipeh);
500 rxq->pipeh = NULL((void *)0);
501 }
502 for (i = 0; i < MTW_RX_RING_COUNT1; i++) {
503 if (rxq->data[i].xfer != NULL((void *)0))
504 usbd_free_xfer(rxq->data[i].xfer);
505 rxq->data[i].xfer = NULL((void *)0);
506 }
507}
508
509int
510mtw_alloc_tx_ring(struct mtw_softc *sc, int qid)
511{
512 struct mtw_tx_ring *txq = &sc->txq[qid];
513 int i, error;
514 uint16_t txwisize;
515
516 txwisize = sizeof(struct mtw_txwi);
Value stored to 'txwisize' is never read
517
518 txq->cur = txq->queued = 0;
519
520 if ((error = usbd_open_pipe(sc->sc_iface, txq->pipe_no, 0,
521 &txq->pipeh)) != 0)
522 goto fail;
523
524 for (i = 0; i < MTW_TX_RING_COUNT8; i++) {
525 struct mtw_tx_data *data = &txq->data[i];
526
527 data->sc = sc; /* backpointer for callbacks */
528 data->qid = qid;
529
530 data->xfer = usbd_alloc_xfer(sc->sc_udev);
531 if (data->xfer == NULL((void *)0)) {
532 error = ENOMEM12;
533 goto fail;
534 }
535
536 data->buf = usbd_alloc_buffer(data->xfer, MTW_MAX_TXSZ(sizeof (struct mtw_txd) + sizeof (struct mtw_txwi) + (1 <<
11) + 11)
);
537 if (data->buf == NULL((void *)0)) {
538 error = ENOMEM12;
539 goto fail;
540 }
541
542 /* zeroize the TXD + TXWI part */
543 memset(data->buf, 0, MTW_MAX_TXSZ)__builtin_memset((data->buf), (0), ((sizeof (struct mtw_txd
) + sizeof (struct mtw_txwi) + (1 << 11) + 11)))
;
544 }
545 if (error != 0)
546fail: mtw_free_tx_ring(sc, qid);
547 return error;
548}
549
550void
551mtw_free_tx_ring(struct mtw_softc *sc, int qid)
552{
553 struct mtw_tx_ring *txq = &sc->txq[qid];
554 int i;
555
556 if (txq->pipeh != NULL((void *)0)) {
557 usbd_close_pipe(txq->pipeh);
558 txq->pipeh = NULL((void *)0);
559 }
560 for (i = 0; i < MTW_TX_RING_COUNT8; i++) {
561 if (txq->data[i].xfer != NULL((void *)0))
562 usbd_free_xfer(txq->data[i].xfer);
563 txq->data[i].xfer = NULL((void *)0);
564 }
565}
566
567int
568mtw_alloc_mcu_ring(struct mtw_softc *sc)
569{
570 struct mtw_tx_ring *ring = &sc->sc_mcu;
571 struct mtw_tx_data *data = &ring->data[0];
572 int error = 0;
573
574 ring->cur = ring->queued = 0;
575
576 data->sc = sc; /* backpointer for callbacks */
577 data->qid = 5;
578
579 data->xfer = usbd_alloc_xfer(sc->sc_udev);
580 if (data->xfer == NULL((void *)0)) {
581 error = ENOMEM12;
582 goto fail;
583 }
584
585 data->buf = usbd_alloc_buffer(data->xfer, MTW_MAX_TXSZ(sizeof (struct mtw_txd) + sizeof (struct mtw_txwi) + (1 <<
11) + 11)
);
586 if (data->buf == NULL((void *)0)) {
587 error = ENOMEM12;
588 goto fail;
589 }
590 /* zeroize the TXD */
591 memset(data->buf, 0, 4)__builtin_memset((data->buf), (0), (4));
592
593 if (error != 0)
594fail: mtw_free_mcu_ring(sc);
595 return error;
596
597
598}
599void
600mtw_free_mcu_ring(struct mtw_softc *sc)
601{
602 struct mtw_tx_ring *txq = &sc->sc_mcu;
603
604 if (txq->data[0].xfer != NULL((void *)0))
605 usbd_free_xfer(txq->data[0].xfer);
606 txq->data[0].xfer = NULL((void *)0);
607}
608
609int
610mtw_ucode_write(struct mtw_softc *sc, const uint8_t *fw, uint32_t len,
611 uint32_t offset)
612{
613 struct mtw_tx_ring *ring = &sc->txq[MTW_TXQ_MCU5];
614 struct usbd_xfer *xfer;
615 struct mtw_txd *txd;
616 uint8_t *buf;
617 uint32_t blksz, sent, tmp, xferlen;
618 int error;
619
620 blksz = 0x2000;
621 if (sc->asic_ver == 0x7612 && offset >= 0x90000)
622 blksz = 0x800; /* MT7612 ROM Patch */
623
624 xfer = usbd_alloc_xfer(sc->sc_udev);
625 if (xfer == NULL((void *)0)) {
626 error = ENOMEM12;
627 goto fail;
628 }
629 buf = usbd_alloc_buffer(xfer, blksz + 12);
630 if (buf == NULL((void *)0)) {
631 error = ENOMEM12;
632 goto fail;
633 }
634
635 sent = 0;
636 for (;;) {
637 xferlen = min(len - sent, blksz);
638 if (xferlen == 0)
639 break;
640
641 txd = (struct mtw_txd *)buf;
642 txd->len = htole16(xferlen)((__uint16_t)(xferlen));
643 txd->flags = htole16(MTW_TXD_DATA | MTW_TXD_MCU)((__uint16_t)((0 << 14) | (2 << 11)));
644
645 memcpy(buf + sizeof(struct mtw_txd), fw + sent, xferlen)__builtin_memcpy((buf + sizeof(struct mtw_txd)), (fw + sent),
(xferlen))
;
646 memset(buf + sizeof(struct mtw_txd) + xferlen, 0, MTW_DMA_PAD)__builtin_memset((buf + sizeof(struct mtw_txd) + xferlen), (0
), (4))
;
647 mtw_write_cfg(sc, MTW_MCU_DMA_ADDR0x0230, offset + sent);
648 mtw_write_cfg(sc, MTW_MCU_DMA_LEN0x0234, (xferlen << 16));
649
650 usbd_setup_xfer(xfer, ring->pipeh, NULL((void *)0), buf,
651 xferlen + sizeof(struct mtw_txd) + MTW_DMA_PAD4,
652 USBD_SHORT_XFER_OK0x04 | USBD_SYNCHRONOUS0x02 | USBD_NO_COPY0x01,
653 MTW_TX_TIMEOUT5000, NULL((void *)0));
654 if ((error = usbd_transfer(xfer)) != 0)
655 break;
656
657 mtw_read(sc, MTW_MCU_FW_IDX0x09a8, &tmp);
658 mtw_write(sc, MTW_MCU_FW_IDX0x09a8, tmp++);
659
660 sent += xferlen;
661 }
662fail:
663 if (xfer != NULL((void *)0)) {
664 usbd_free_xfer(xfer);
665 xfer = NULL((void *)0);
666 }
667 return error;
668}
669
670void
671mtw_ucode_setup(struct mtw_softc *sc)
672{
673 mtw_usb_dma_write(sc, (MTW_USB_TX_EN(1U << 23) | MTW_USB_RX_EN(1U << 22)));
674 mtw_write(sc, MTW_FCE_PSE_CTRL0x0800, 1);
675 mtw_write(sc, MTW_TX_CPU_FCE_BASE0x09a0, 0x400230);
676 mtw_write(sc, MTW_TX_CPU_FCE_MAX_COUNT0x09a4, 1);
677 mtw_write(sc, MTW_MCU_FW_IDX0x09a8, 1);
678 mtw_write(sc, MTW_FCE_PDMA0x09c4, 0x44);
679 mtw_write(sc, MTW_FCE_SKIP_FS0x0a6c, 3);
680}
681
682int
683mtw_load_microcode(struct mtw_softc *sc)
684{
685 const struct mtw_ucode_hdr *hdr;
686 const struct mtw_ucode *fw;
687 const char *fwname;
688 u_char *ucode;
689 size_t size;
690 uint32_t tmp, iofs, dofs;
691 int ntries, error;
692 int dlen, ilen;
693
694 /* is firmware already running? */
695 mtw_read_cfg(sc, MTW_MCU_DMA_ADDR0x0230, &tmp);
696 if (tmp == MTW_MCU_READY(1U << 0))
697 return 0;
698
699 /* open MCU pipe */
700 if ((error = usbd_open_pipe(sc->sc_iface, sc->txq[MTW_TXQ_MCU5].pipe_no,
701 0, &sc->txq[MTW_TXQ_MCU5].pipeh)) != 0)
702 return error;
703
704 if (sc->asic_ver == 0x7612) {
705 fwname = "mtw-mt7662u_rom_patch";
706
707 if ((error = loadfirmware(fwname, &ucode, &size)) != 0) {
708 printf("%s: failed loadfirmware of file %s (error %d)\n",
709 sc->sc_dev.dv_xname, fwname, error);
710 return error;
711 }
712 fw = (const struct mtw_ucode *) ucode + 0x1e;
713 ilen = size - 0x1e;
714
715 mtw_ucode_setup(sc);
716
717 if ((error = mtw_ucode_write(sc, fw->data, ilen, 0x90000)) != 0)
718 goto fail;
719
720 mtw_usb_dma_write(sc, 0x00e41814);
721 free(ucode, M_DEVBUF2, size);
722 }
723
724 fwname = "mtw-mt7601u";
725 iofs = 0x40;
726 dofs = 0;
727 if (sc->asic_ver == 0x7612) {
728 fwname = "mtw-mt7662u";
729 iofs = 0x80040;
730 dofs = 0x110800;
731 } else if (sc->asic_ver == 0x7610) {
732 fwname = "mtw-mt7610u";
733 dofs = 0x80000;
734 }
735
736 if ((error = loadfirmware(fwname, &ucode, &size)) != 0) {
737 printf("%s: failed loadfirmware of file %s (error %d)\n",
738 sc->sc_dev.dv_xname, fwname, error);
739 return error;
740 }
741
742 if (size < sizeof(struct mtw_ucode_hdr)) {
743 printf("%s: firmware header too short\n",
744 sc->sc_dev.dv_xname);
745 goto fail;
746 }
747
748 fw = (const struct mtw_ucode *) ucode;
749 hdr = (const struct mtw_ucode_hdr *) &fw->hdr;
750
751 if (size < sizeof(struct mtw_ucode_hdr) + letoh32(hdr->ilm_len)((__uint32_t)(hdr->ilm_len)) +
752 letoh32(hdr->dlm_len)((__uint32_t)(hdr->dlm_len))) {
753 printf("%s: firmware payload too short\n",
754 sc->sc_dev.dv_xname);
755 goto fail;
756 }
757
758 ilen = le32toh(hdr->ilm_len)((__uint32_t)(hdr->ilm_len)) - MTW_MCU_IVB_LEN0x40;
759 dlen = le32toh(hdr->dlm_len)((__uint32_t)(hdr->dlm_len));
760
761 if (ilen > size || dlen > size) {
762 printf("%s: firmware payload too large\n",
763 sc->sc_dev.dv_xname);
764 goto fail;
765 }
766
767 mtw_write(sc, MTW_FCE_PDMA0x09c4, 0);
768 mtw_write(sc, MTW_FCE_PSE_CTRL0x0800, 0);
769 mtw_ucode_setup(sc);
770
771 if ((error = mtw_ucode_write(sc, fw->data, ilen, iofs)) != 0)
772 goto fail;
773 if (dlen > 0 && dofs > 0) {
774 if ((error = mtw_ucode_write(sc, fw->data + ilen,
775 dlen, dofs)) != 0)
776 goto fail;
777 }
778
779 /* write interrupt vectors */
780 if (sc->asic_ver == 0x7612) {
781 /* MT7612 */
782 if ((error = mtw_ucode_write(sc, fw->ivb,
783 MTW_MCU_IVB_LEN0x40, 0x80000)) != 0)
784 goto fail;
785 mtw_write_cfg(sc, MTW_MCU_DMA_ADDR0x0230, 0x00095000);
786 mtw_write_ivb(sc, NULL((void *)0), 0);
787 } else {
788 /* MT7601/MT7610 */
789 if ((error = mtw_write_ivb(sc, fw->ivb,
790 MTW_MCU_IVB_LEN0x40)) != 0)
791 goto fail;
792 }
793
794 /* wait until microcontroller is ready */
795 usbd_delay_ms(sc->sc_udev, 10);
796
797 for (ntries = 0; ntries < 100; ntries++) {
798 if ((error = mtw_read_cfg(sc, MTW_MCU_DMA_ADDR0x0230, &tmp)) != 0)
799 return error;
800 if (tmp & MTW_MCU_READY(1U << 0))
801 break;
802 usbd_delay_ms(sc->sc_udev, 100);
803 }
804
805 if (ntries == 100) {
806 printf("%s: timeout waiting for MCU to initialize\n",
807 sc->sc_dev.dv_xname);
808 error = ETIMEDOUT60;
809 }
810
811 DPRINTF(("%s: loaded firmware ver %d.%d\n", sc->sc_dev.dv_xname,
812 le16toh(hdr->build_ver), le16toh(hdr->fw_ver)));
813fail:
814 free(ucode, M_DEVBUF2, size);
815 usbd_close_pipe(sc->txq[MTW_TXQ_MCU5].pipeh);
816 sc->txq[MTW_TXQ_MCU5].pipeh = NULL((void *)0);
817 return error;
818}
819
820int
821mtw_reset(struct mtw_softc *sc)
822{
823 usb_device_request_t req;
824
825 req.bmRequestType = UT_WRITE_VENDOR_DEVICE(0x00 | 0x40 | 0x00);
826 req.bRequest = MTW_RESET0x1;
827 USETW(req.wValue, 1)(*(u_int16_t *)(req.wValue) = (1));
828 USETW(req.wIndex, 0)(*(u_int16_t *)(req.wIndex) = (0));
829 USETW(req.wLength, 0)(*(u_int16_t *)(req.wLength) = (0));
830 return usbd_do_request(sc->sc_udev, &req, NULL((void *)0));
831}
832
833int
834mtw_read(struct mtw_softc *sc, uint16_t reg, uint32_t *val)
835{
836 uint32_t tmp;
837 int error;
838
839 error = mtw_read_region_1(sc, reg,
840 (uint8_t *)&tmp, sizeof tmp);
841 if (error == 0)
842 *val = letoh32(tmp)((__uint32_t)(tmp));
843 else
844 *val = 0xffffffff;
845 return error;
846}
847
848int
849mtw_read_cfg(struct mtw_softc *sc, uint16_t reg, uint32_t *val)
850{
851 usb_device_request_t req;
852 uint32_t tmp;
853 int error;
854
855 req.bmRequestType = UT_READ_VENDOR_DEVICE(0x80 | 0x40 | 0x00);
856 req.bRequest = MTW_READ_CFG0x47;
857 USETW(req.wValue, 0)(*(u_int16_t *)(req.wValue) = (0));
858 USETW(req.wIndex, reg)(*(u_int16_t *)(req.wIndex) = (reg));
859 USETW(req.wLength, 4)(*(u_int16_t *)(req.wLength) = (4));
860 error = usbd_do_request(sc->sc_udev, &req, &tmp);
861
862 if (error == 0)
863 *val = letoh32(tmp)((__uint32_t)(tmp));
864 else
865 *val = 0xffffffff;
866 return error;
867}
868
869int
870mtw_read_region_1(struct mtw_softc *sc, uint16_t reg,
871 uint8_t *buf, int len)
872{
873 usb_device_request_t req;
874
875 req.bmRequestType = UT_READ_VENDOR_DEVICE(0x80 | 0x40 | 0x00);
876 req.bRequest = MTW_READ_REGION_10x7;
877 USETW(req.wValue, 0)(*(u_int16_t *)(req.wValue) = (0));
878 USETW(req.wIndex, reg)(*(u_int16_t *)(req.wIndex) = (reg));
879 USETW(req.wLength, len)(*(u_int16_t *)(req.wLength) = (len));
880 return usbd_do_request(sc->sc_udev, &req, buf);
881}
882
883int
884mtw_write_2(struct mtw_softc *sc, uint16_t reg, uint16_t val)
885{
886 usb_device_request_t req;
887
888 req.bmRequestType = UT_WRITE_VENDOR_DEVICE(0x00 | 0x40 | 0x00);
889 req.bRequest = MTW_WRITE_20x2;
890 USETW(req.wValue, val)(*(u_int16_t *)(req.wValue) = (val));
891 USETW(req.wIndex, reg)(*(u_int16_t *)(req.wIndex) = (reg));
892 USETW(req.wLength, 0)(*(u_int16_t *)(req.wLength) = (0));
893 return usbd_do_request(sc->sc_udev, &req, NULL((void *)0));
894}
895
896int
897mtw_write(struct mtw_softc *sc, uint16_t reg, uint32_t val)
898{
899 int error;
900
901 if ((error = mtw_write_2(sc, reg, val & 0xffff)) == 0)
902 error = mtw_write_2(sc, reg + 2, val >> 16);
903 return error;
904}
905
906int
907mtw_write_cfg(struct mtw_softc *sc, uint16_t reg, uint32_t val)
908{
909 usb_device_request_t req;
910 int error;
911
912 req.bmRequestType = UT_WRITE_VENDOR_DEVICE(0x00 | 0x40 | 0x00);
913 req.bRequest = MTW_WRITE_CFG0x46;
914 USETW(req.wValue, 0)(*(u_int16_t *)(req.wValue) = (0));
915 USETW(req.wIndex, reg)(*(u_int16_t *)(req.wIndex) = (reg));
916 USETW(req.wLength, 4)(*(u_int16_t *)(req.wLength) = (4));
917 val = htole32(val)((__uint32_t)(val));
918 error = usbd_do_request(sc->sc_udev, &req, &val);
919 return error;
920}
921
922int
923mtw_write_ivb(struct mtw_softc *sc, const uint8_t *buf, uint16_t len)
924{
925 usb_device_request_t req;
926
927 req.bmRequestType = UT_WRITE_VENDOR_DEVICE(0x00 | 0x40 | 0x00);
928 req.bRequest = MTW_RESET0x1;
929 USETW(req.wValue, 0x12)(*(u_int16_t *)(req.wValue) = (0x12));
930 USETW(req.wIndex, 0)(*(u_int16_t *)(req.wIndex) = (0));
931 USETW(req.wLength, len)(*(u_int16_t *)(req.wLength) = (len));
932 return usbd_do_request(sc->sc_udev, &req, (void *)buf);
933}
934
935int
936mtw_write_region_1(struct mtw_softc *sc, uint16_t reg,
937 uint8_t *buf, int len)
938{
939 usb_device_request_t req;
940
941 req.bmRequestType = UT_WRITE_VENDOR_DEVICE(0x00 | 0x40 | 0x00);
942 req.bRequest = MTW_WRITE_REGION_10x6;
943 USETW(req.wValue, 0)(*(u_int16_t *)(req.wValue) = (0));
944 USETW(req.wIndex, reg)(*(u_int16_t *)(req.wIndex) = (reg));
945 USETW(req.wLength, len)(*(u_int16_t *)(req.wLength) = (len));
946 return usbd_do_request(sc->sc_udev, &req, buf);
947}
948
949int
950mtw_set_region_4(struct mtw_softc *sc, uint16_t reg, uint32_t val, int count)
951{
952 int error = 0;
953
954 for (; count > 0 && error == 0; count--, reg += 4)
955 error = mtw_write(sc, reg, val);
956 return error;
957}
958
959/* Read 16-bit from eFUSE ROM. */
960int
961mtw_efuse_read_2(struct mtw_softc *sc, uint16_t addr, uint16_t *val)
962{
963 uint32_t tmp;
964 uint16_t reg;
965 int error, ntries;
966
967 if ((error = mtw_read(sc, MTW_EFUSE_CTRL0x0024, &tmp)) != 0)
968 return error;
969
970 addr *= 2;
971 /*
972 * Read one 16-byte block into registers EFUSE_DATA[0-3]:
973 * DATA0: 3 2 1 0
974 * DATA1: 7 6 5 4
975 * DATA2: B A 9 8
976 * DATA3: F E D C
977 */
978 tmp &= ~(MTW_EFSROM_MODE_MASK0x000000c0 | MTW_EFSROM_AIN_MASK0x03ff0000);
979 tmp |= (addr & ~0xf) << MTW_EFSROM_AIN_SHIFT16 | MTW_EFSROM_KICK(1U << 30);
980 mtw_write(sc, MTW_EFUSE_CTRL0x0024, tmp);
981 for (ntries = 0; ntries < 100; ntries++) {
982 if ((error = mtw_read(sc, MTW_EFUSE_CTRL0x0024, &tmp)) != 0)
983 return error;
984 if (!(tmp & MTW_EFSROM_KICK(1U << 30)))
985 break;
986 DELAY(2)(*delay_func)(2);
987 }
988 if (ntries == 100)
989 return ETIMEDOUT60;
990
991 if ((tmp & MTW_EFUSE_AOUT_MASK0x0000003f) == MTW_EFUSE_AOUT_MASK0x0000003f) {
992 *val = 0xffff; /* address not found */
993 return 0;
994 }
995 /* determine to which 32-bit register our 16-bit word belongs */
996 reg = MTW_EFUSE_DATA00x0028 + (addr & 0xc);
997 if ((error = mtw_read(sc, reg, &tmp)) != 0)
998 return error;
999
1000 *val = (addr & 2) ? tmp >> 16 : tmp & 0xffff;
1001 return 0;
1002}
1003
1004int
1005mtw_eeprom_read_2(struct mtw_softc *sc, uint16_t addr, uint16_t *val)
1006{
1007 usb_device_request_t req;
1008 uint16_t tmp;
1009 int error;
1010
1011 addr *= 2;
1012 req.bmRequestType = UT_READ_VENDOR_DEVICE(0x80 | 0x40 | 0x00);
1013 req.bRequest = MTW_EEPROM_READ0x9;
1014 USETW(req.wValue, 0)(*(u_int16_t *)(req.wValue) = (0));
1015 USETW(req.wIndex, addr)(*(u_int16_t *)(req.wIndex) = (addr));
1016 USETW(req.wLength, sizeof tmp)(*(u_int16_t *)(req.wLength) = (sizeof tmp));
1017 error = usbd_do_request(sc->sc_udev, &req, &tmp);
1018 if (error == 0)
1019 *val = letoh16(tmp)((__uint16_t)(tmp));
1020 else
1021 *val = 0xffff;
1022 return error;
1023}
1024
1025static __inline int
1026mtw_srom_read(struct mtw_softc *sc, uint16_t addr, uint16_t *val)
1027{
1028 /* either eFUSE ROM or EEPROM */
1029 return sc->sc_srom_read(sc, addr, val);
1030}
1031
1032int
1033mtw_rf_read(struct mtw_softc *sc, uint8_t bank, uint8_t reg, uint8_t *val)
1034{
1035 uint32_t tmp;
1036 int error, ntries, shift;
1037
1038 for (ntries = 0; ntries < 100; ntries++) {
1039 if ((error = mtw_read(sc, MTW_RF_CSR0x0500, &tmp)) != 0)
1040 return error;
1041 if (!(tmp & MTW_RF_CSR_KICK(1U << 31)))
1042 break;
1043 }
1044 if (ntries == 100)
1045 return ETIMEDOUT60;
1046
1047 if (sc->mac_ver == 0x7601)
1048 shift = MT7601_BANK_SHIFT14;
1049 else
1050 shift = MT7610_BANK_SHIFT15;
1051
1052 tmp = MTW_RF_CSR_KICK(1U << 31) | (bank & 0xf) << shift | reg << 8;
1053 if ((error = mtw_write(sc, MTW_RF_CSR0x0500, tmp)) != 0)
1054 return error;
1055
1056 for (ntries = 0; ntries < 100; ntries++) {
1057 if ((error = mtw_read(sc, MTW_RF_CSR0x0500, &tmp)) != 0)
1058 return error;
1059 if (!(tmp & MTW_RF_CSR_KICK(1U << 31)))
1060 break;
1061 }
1062 if (ntries == 100)
1063 return ETIMEDOUT60;
1064
1065 *val = tmp & 0xff;
1066 return 0;
1067}
1068
1069int
1070mtw_rf_write(struct mtw_softc *sc, uint8_t bank, uint8_t reg, uint8_t val)
1071{
1072 uint32_t tmp;
1073 int error, ntries, shift;
1074
1075 for (ntries = 0; ntries < 10; ntries++) {
1076 if ((error = mtw_read(sc, MTW_RF_CSR0x0500, &tmp)) != 0)
1077 return error;
1078 if (!(tmp & MTW_RF_CSR_KICK(1U << 31)))
1079 break;
1080 }
1081 if (ntries == 10)
1082 return ETIMEDOUT60;
1083
1084 if (sc->mac_ver == 0x7601)
1085 shift = MT7601_BANK_SHIFT14;
1086 else
1087 shift = MT7610_BANK_SHIFT15;
1088
1089 tmp = MTW_RF_CSR_WRITE(1U << 30) | MTW_RF_CSR_KICK(1U << 31) | (bank & 0xf) << shift |
1090 reg << 8 | val;
1091 return mtw_write(sc, MTW_RF_CSR0x0500, tmp);
1092}
1093
1094int
1095mtw_bbp_read(struct mtw_softc *sc, uint8_t reg, uint8_t *val)
1096{
1097 uint32_t tmp;
1098 int ntries, error;
1099
1100 for (ntries = 0; ntries < 10; ntries++) {
1101 if ((error = mtw_read(sc, MTW_BBP_CSR0x101c, &tmp)) != 0)
1102 return error;
1103 if (!(tmp & MTW_BBP_CSR_KICK(1 << 17)))
1104 break;
1105 }
1106 if (ntries == 10)
1107 return ETIMEDOUT60;
1108
1109 tmp = MTW_BBP_CSR_READ(1 << 16) | MTW_BBP_CSR_KICK(1 << 17) | reg << MTW_BBP_ADDR_SHIFT8;
1110 if ((error = mtw_write(sc, MTW_BBP_CSR0x101c, tmp)) != 0)
1111 return error;
1112
1113 for (ntries = 0; ntries < 10; ntries++) {
1114 if ((error = mtw_read(sc, MTW_BBP_CSR0x101c, &tmp)) != 0)
1115 return error;
1116 if (!(tmp & MTW_BBP_CSR_KICK(1 << 17)))
1117 break;
1118 }
1119 if (ntries == 10)
1120 return ETIMEDOUT60;
1121
1122 *val = tmp & 0xff;
1123 return 0;
1124}
1125
1126int
1127mtw_bbp_write(struct mtw_softc *sc, uint8_t reg, uint8_t val)
1128{
1129 uint32_t tmp;
1130 int ntries, error;
1131
1132 for (ntries = 0; ntries < 10; ntries++) {
1133 if ((error = mtw_read(sc, MTW_BBP_CSR0x101c, &tmp)) != 0)
1134 return error;
1135 if (!(tmp & MTW_BBP_CSR_KICK(1 << 17)))
1136 break;
1137 }
1138 if (ntries == 10)
1139 return ETIMEDOUT60;
1140
1141 tmp = MTW_BBP_CSR_KICK(1 << 17) | reg << MTW_BBP_ADDR_SHIFT8 | val;
1142 return mtw_write(sc, MTW_BBP_CSR0x101c, tmp);
1143}
1144
1145int
1146mtw_usb_dma_read(struct mtw_softc *sc, uint32_t *val)
1147{
1148 if (sc->asic_ver == 0x7612)
1149 return mtw_read_cfg(sc, MTW_USB_U3DMA_CFG0x9018, val);
1150 else
1151 return mtw_read(sc, MTW_USB_DMA_CFG0x0238, val);
1152}
1153
1154int
1155mtw_usb_dma_write(struct mtw_softc *sc, uint32_t val)
1156{
1157 if (sc->asic_ver == 0x7612)
1158 return mtw_write_cfg(sc, MTW_USB_U3DMA_CFG0x9018, val);
1159 else
1160 return mtw_write(sc, MTW_USB_DMA_CFG0x0238, val);
1161}
1162
1163int
1164mtw_mcu_calibrate(struct mtw_softc *sc, int func, uint32_t val)
1165{
1166 struct mtw_mcu_cmd_8 cmd;
1167
1168 cmd.func = htole32(func)((__uint32_t)(func));
1169 cmd.val = htole32(val)((__uint32_t)(val));
1170 return mtw_mcu_cmd(sc, 31, &cmd, sizeof(struct mtw_mcu_cmd_8));
1171}
1172
1173int
1174mtw_mcu_channel(struct mtw_softc *sc, uint32_t r1, uint32_t r2, uint32_t r4)
1175{
1176 struct mtw_mcu_cmd_16 cmd;
1177
1178 cmd.r1 = htole32(r1)((__uint32_t)(r1));
1179 cmd.r2 = htole32(r2)((__uint32_t)(r2));
1180 cmd.r3 = 0;
1181 cmd.r4 = htole32(r4)((__uint32_t)(r4));
1182 return mtw_mcu_cmd(sc, 30, &cmd, sizeof(struct mtw_mcu_cmd_16));
1183}
1184
1185int
1186mtw_mcu_radio(struct mtw_softc *sc, int func, uint32_t val)
1187{
1188 struct mtw_mcu_cmd_16 cmd;
1189
1190 cmd.r1 = htole32(func)((__uint32_t)(func));
1191 cmd.r2 = htole32(val)((__uint32_t)(val));
1192 cmd.r3 = 0;
1193 cmd.r4 = 0;
1194 return mtw_mcu_cmd(sc, 20, &cmd, sizeof(struct mtw_mcu_cmd_16));
1195}
1196
1197int
1198mtw_mcu_cmd(struct mtw_softc *sc, int cmd, void *buf, int len)
1199{
1200 struct mtw_tx_ring *ring = &sc->sc_mcu;
1201 struct mtw_tx_data *data = &ring->data[0];
1202 struct mtw_txd *txd;
1203 int xferlen;
1204
1205 txd = (struct mtw_txd *)(data->buf);
1206 txd->len = htole16(len)((__uint16_t)(len));
1207 txd->flags = htole16(MTW_TXD_CMD | MTW_TXD_MCU |((__uint16_t)((1 << 14) | (2 << 11) | (cmd & 0x1f
) << 4 | (sc->cmd_seq & 0xf)))
1208 (cmd & 0x1f) << MTW_TXD_CMD_SHIFT | (sc->cmd_seq & 0xf))((__uint16_t)((1 << 14) | (2 << 11) | (cmd & 0x1f
) << 4 | (sc->cmd_seq & 0xf)))
;
1209
1210 memcpy(&txd[1], buf, len)__builtin_memcpy((&txd[1]), (buf), (len));
1211 memset(&txd[1] + len, 0, MTW_DMA_PAD)__builtin_memset((&txd[1] + len), (0), (4));
1212 xferlen = len + sizeof(struct mtw_txd) + MTW_DMA_PAD4;
1213
1214 usbd_setup_xfer(data->xfer, sc->txq[MTW_TXQ_MCU5].pipeh,
1215 NULL((void *)0), data->buf, xferlen,
1216 USBD_SHORT_XFER_OK0x04 | USBD_FORCE_SHORT_XFER0x08 | USBD_SYNCHRONOUS0x02,
1217 MTW_TX_TIMEOUT5000, NULL((void *)0));
1218 return usbd_transfer(data->xfer);
1219}
1220
1221/*
1222 * Add `delta' (signed) to each 4-bit sub-word of a 32-bit word.
1223 * Used to adjust per-rate Tx power registers.
1224 */
1225static __inline uint32_t
1226b4inc(uint32_t b32, int8_t delta)
1227{
1228 int8_t i, b4;
1229
1230 for (i = 0; i < 8; i++) {
1231 b4 = b32 & 0xf;
1232 b4 += delta;
1233 if (b4 < 0)
1234 b4 = 0;
1235 else if (b4 > 0xf)
1236 b4 = 0xf;
1237 b32 = b32 >> 4 | b4 << 28;
1238 }
1239 return b32;
1240}
1241
1242const char *
1243mtw_get_rf(int rev)
1244{
1245 switch (rev) {
1246 case MT7601_RF_76010x7601: return "MT7601";
1247 case MT7610_RF_76100x7610: return "MT7610";
1248 case MT7612_RF_76120x7612: return "MT7612";
1249 }
1250 return "unknown";
1251}
1252
1253void
1254mtw_get_txpower(struct mtw_softc *sc)
1255{
1256 uint16_t val;
1257 int i;
1258
1259 /* Read power settings for 2GHz channels. */
1260 for (i = 0; i < 14; i += 2) {
1261 mtw_srom_read(sc, MTW_EEPROM_PWR2GHZ_BASE10x29 + i / 2, &val);
1262 sc->txpow1[i + 0] = (int8_t)(val & 0xff);
1263 sc->txpow1[i + 1] = (int8_t)(val >> 8);
1264 mtw_srom_read(sc, MTW_EEPROM_PWR2GHZ_BASE20x30 + i / 2, &val);
1265 sc->txpow2[i + 0] = (int8_t)(val & 0xff);
1266 sc->txpow2[i + 1] = (int8_t)(val >> 8);
1267 }
1268 /* Fix broken Tx power entries. */
1269 for (i = 0; i < 14; i++) {
1270 if (sc->txpow1[i] < 0 || sc->txpow1[i] > 27)
1271 sc->txpow1[i] = 5;
1272 if (sc->txpow2[i] < 0 || sc->txpow2[i] > 27)
1273 sc->txpow2[i] = 5;
1274 DPRINTF(("chan %d: power1=%d, power2=%d\n",
1275 mt7601_rf_chan[i].chan, sc->txpow1[i], sc->txpow2[i]));
1276 }
1277#if 0
1278 /* Read power settings for 5GHz channels. */
1279 for (i = 0; i < 40; i += 2) {
1280 mtw_srom_read(sc, MTW_EEPROM_PWR5GHZ_BASE10x3c + i / 2, &val);
1281 sc->txpow1[i + 14] = (int8_t)(val & 0xff);
1282 sc->txpow1[i + 15] = (int8_t)(val >> 8);
1283
1284 mtw_srom_read(sc, MTW_EEPROM_PWR5GHZ_BASE20x53 + i / 2, &val);
1285 sc->txpow2[i + 14] = (int8_t)(val & 0xff);
1286 sc->txpow2[i + 15] = (int8_t)(val >> 8);
1287 }
1288 /* Fix broken Tx power entries. */
1289 for (i = 0; i < 40; i++ ) {
1290 if (sc->mac_ver != 0x5592) {
1291 if (sc->txpow1[14 + i] < -7 || sc->txpow1[14 + i] > 15)
1292 sc->txpow1[14 + i] = 5;
1293 if (sc->txpow2[14 + i] < -7 || sc->txpow2[14 + i] > 15)
1294 sc->txpow2[14 + i] = 5;
1295 }
1296 DPRINTF(("chan %d: power1=%d, power2=%d\n",
1297 mt7601_rf_chan[14 + i].chan, sc->txpow1[14 + i],
1298 sc->txpow2[14 + i]));
1299 }
1300#endif
1301}
1302
1303int
1304mtw_read_eeprom(struct mtw_softc *sc)
1305{
1306 struct ieee80211com *ic = &sc->sc_ic;
1307 int8_t delta_2ghz, delta_5ghz;
1308 uint16_t val;
1309 int ridx, ant;
1310
1311 sc->sc_srom_read = mtw_efuse_read_2;
1312
1313 /* read RF information */
1314 mtw_srom_read(sc, MTW_EEPROM_CHIPID0x00, &val);
1315 sc->rf_rev = val;
1316 mtw_srom_read(sc, MTW_EEPROM_ANTENNA0x1a, &val);
1317 sc->ntxchains = (val >> 4) & 0xf;
1318 sc->nrxchains = val & 0xf;
1319 DPRINTF(("EEPROM RF rev=0x%02x chains=%dT%dR\n",
1320 sc->rf_rev, sc->ntxchains, sc->nrxchains));
1321
1322 /* read ROM version */
1323 mtw_srom_read(sc, MTW_EEPROM_VERSION0x01, &val);
1324 DPRINTF(("EEPROM rev=%d, FAE=%d\n", val & 0xff, val >> 8));
1325
1326 /* read MAC address */
1327 mtw_srom_read(sc, MTW_EEPROM_MAC010x02, &val);
1328 ic->ic_myaddr[0] = val & 0xff;
1329 ic->ic_myaddr[1] = val >> 8;
1330 mtw_srom_read(sc, MTW_EEPROM_MAC230x03, &val);
1331 ic->ic_myaddr[2] = val & 0xff;
1332 ic->ic_myaddr[3] = val >> 8;
1333 mtw_srom_read(sc, MTW_EEPROM_MAC450x04, &val);
1334 ic->ic_myaddr[4] = val & 0xff;
1335 ic->ic_myaddr[5] = val >> 8;
1336#if 0
1337 printf("eFUSE ROM\n00: ");
1338 for (int i = 0; i < 256; i++) {
1339 if (((i % 8) == 0) && i > 0)
1340 printf("\n%02x: ", i);
1341 mtw_srom_read(sc, i, &val);
1342 printf(" %04x", val);
1343 }
1344 printf("\n");
1345#endif
1346 /* check if RF supports automatic Tx access gain control */
1347 mtw_srom_read(sc, MTW_EEPROM_CONFIG0x1b, &val);
1348 DPRINTF(("EEPROM CFG 0x%04x\n", val));
1349 if ((val & 0xff) != 0xff) {
1350 sc->ext_5ghz_lna = (val >> 3) & 1;
1351 sc->ext_2ghz_lna = (val >> 2) & 1;
1352 /* check if RF supports automatic Tx access gain control */
1353 sc->calib_2ghz = sc->calib_5ghz = (val >> 1) & 1;
1354 /* check if we have a hardware radio switch */
1355 sc->rfswitch = val & 1;
1356 }
1357
1358 /* read RF frequency offset from EEPROM */
1359 mtw_srom_read(sc, MTW_EEPROM_FREQ_OFFSET0x1d, &val);
1360 if ((val & 0xff) != 0xff)
1361 sc->rf_freq_offset = val;
1362 else
1363 sc->rf_freq_offset = 0;
1364 DPRINTF(("frequency offset 0x%x\n", sc->rf_freq_offset));
1365
1366 /* Read Tx power settings. */
1367 mtw_get_txpower(sc);
1368
1369 /* read Tx power compensation for each Tx rate */
1370 mtw_srom_read(sc, MTW_EEPROM_DELTAPWR0x28, &val);
1371 delta_2ghz = delta_5ghz = 0;
1372 if ((val & 0xff) != 0xff && (val & 0x80)) {
1373 delta_2ghz = val & 0xf;
1374 if (!(val & 0x40)) /* negative number */
1375 delta_2ghz = -delta_2ghz;
1376 }
1377 val >>= 8;
1378 if ((val & 0xff) != 0xff && (val & 0x80)) {
1379 delta_5ghz = val & 0xf;
1380 if (!(val & 0x40)) /* negative number */
1381 delta_5ghz = -delta_5ghz;
1382 }
1383 DPRINTF(("power compensation=%d (2GHz), %d (5GHz)\n",
1384 delta_2ghz, delta_5ghz));
1385
1386 for (ridx = 0; ridx < 5; ridx++) {
1387 uint32_t reg;
1388
1389 mtw_srom_read(sc, MTW_EEPROM_RPWR0x6f + ridx * 2, &val);
1390 reg = val;
1391 mtw_srom_read(sc, MTW_EEPROM_RPWR0x6f + ridx * 2 + 1, &val);
1392 reg |= (uint32_t)val << 16;
1393
1394 sc->txpow20mhz[ridx] = reg;
1395 sc->txpow40mhz_2ghz[ridx] = b4inc(reg, delta_2ghz);
1396 sc->txpow40mhz_5ghz[ridx] = b4inc(reg, delta_5ghz);
1397
1398 DPRINTF(("ridx %d: power 20MHz=0x%08x, 40MHz/2GHz=0x%08x, "
1399 "40MHz/5GHz=0x%08x\n", ridx, sc->txpow20mhz[ridx],
1400 sc->txpow40mhz_2ghz[ridx], sc->txpow40mhz_5ghz[ridx]));
1401 }
1402
1403 /* read RSSI offsets and LNA gains from EEPROM */
1404 val = 0;
1405 mtw_srom_read(sc, MTW_EEPROM_RSSI1_2GHZ0x23, &val);
1406 sc->rssi_2ghz[0] = val & 0xff; /* Ant A */
1407 sc->rssi_2ghz[1] = val >> 8; /* Ant B */
1408 mtw_srom_read(sc, MTW_EEPROM_RSSI2_2GHZ0x24, &val);
1409 /*
1410 * On RT3070 chips (limited to 2 Rx chains), this ROM
1411 * field contains the Tx mixer gain for the 2GHz band.
1412 */
1413 if ((val & 0xff) != 0xff)
1414 sc->txmixgain_2ghz = val & 0x7;
1415 DPRINTF(("tx mixer gain=%u (2GHz)\n", sc->txmixgain_2ghz));
1416 sc->lna[2] = val >> 8; /* channel group 2 */
1417 mtw_srom_read(sc, MTW_EEPROM_RSSI1_5GHZ0x25, &val);
1418 sc->rssi_5ghz[0] = val & 0xff; /* Ant A */
1419 sc->rssi_5ghz[1] = val >> 8; /* Ant B */
1420 mtw_srom_read(sc, MTW_EEPROM_RSSI2_5GHZ0x26, &val);
1421 sc->rssi_5ghz[2] = val & 0xff; /* Ant C */
1422
1423 sc->lna[3] = val >> 8; /* channel group 3 */
1424
1425 mtw_srom_read(sc, MTW_EEPROM_LNA0x22, &val);
1426 sc->lna[0] = val & 0xff; /* channel group 0 */
1427 sc->lna[1] = val >> 8; /* channel group 1 */
1428 DPRINTF(("LNA0 0x%x\n", sc->lna[0]));
1429
1430 /* fix broken 5GHz LNA entries */
1431 if (sc->lna[2] == 0 || sc->lna[2] == 0xff) {
1432 DPRINTF(("invalid LNA for channel group %d\n", 2));
1433 sc->lna[2] = sc->lna[1];
1434 }
1435 if (sc->lna[3] == 0 || sc->lna[3] == 0xff) {
1436 DPRINTF(("invalid LNA for channel group %d\n", 3));
1437 sc->lna[3] = sc->lna[1];
1438 }
1439
1440 /* fix broken RSSI offset entries */
1441 for (ant = 0; ant < 3; ant++) {
1442 if (sc->rssi_2ghz[ant] < -10 || sc->rssi_2ghz[ant] > 10) {
1443 DPRINTF(("invalid RSSI%d offset: %d (2GHz)\n",
1444 ant + 1, sc->rssi_2ghz[ant]));
1445 sc->rssi_2ghz[ant] = 0;
1446 }
1447 if (sc->rssi_5ghz[ant] < -10 || sc->rssi_5ghz[ant] > 10) {
1448 DPRINTF(("invalid RSSI%d offset: %d (5GHz)\n",
1449 ant + 1, sc->rssi_5ghz[ant]));
1450 sc->rssi_5ghz[ant] = 0;
1451 }
1452 }
1453 return 0;
1454}
1455
1456struct ieee80211_node *
1457mtw_node_alloc(struct ieee80211com *ic)
1458{
1459 struct mtw_node *mn;
1460
1461 mn = malloc(sizeof (struct mtw_node), M_USBDEV102, M_NOWAIT0x0002 | M_ZERO0x0008);
1462 return (struct ieee80211_node *)mn;
1463}
1464
1465int
1466mtw_media_change(struct ifnet *ifp)
1467{
1468 struct mtw_softc *sc = ifp->if_softc;
1469 struct ieee80211com *ic = &sc->sc_ic;
1470 uint8_t rate, ridx;
1471 int error;
1472
1473 error = ieee80211_media_change(ifp);
1474 if (error != ENETRESET52)
1475 return error;
1476
1477 if (ic->ic_fixed_rate != -1) {
1478 rate = ic->ic_sup_rates[ic->ic_curmode].
1479 rs_rates[ic->ic_fixed_rate] & IEEE80211_RATE_VAL0x7f;
1480 for (ridx = 0; ridx <= MTW_RIDX_MAX11; ridx++)
1481 if (rt2860_rates[ridx].rate == rate)
1482 break;
1483 sc->fixed_ridx = ridx;
1484 }
1485
1486 if ((ifp->if_flags & (IFF_UP0x1 | IFF_RUNNING0x40)) ==
1487 (IFF_UP0x1 | IFF_RUNNING0x40)) {
1488 mtw_stop(ifp, 0);
1489 error = mtw_init(ifp);
1490 }
1491 return error;
1492}
1493
1494void
1495mtw_next_scan(void *arg)
1496{
1497 struct mtw_softc *sc = arg;
1498 int s;
1499
1500 if (usbd_is_dying(sc->sc_udev))
1501 return;
1502
1503 usbd_ref_incr(sc->sc_udev);
1504
1505 s = splnet()splraise(0x4);
1506 if (sc->sc_ic.ic_state == IEEE80211_S_SCAN)
1507 ieee80211_next_scan(&sc->sc_ic.ic_ific_ac.ac_if);
1508 splx(s)spllower(s);
1509
1510 usbd_ref_decr(sc->sc_udev);
1511}
1512
1513void
1514mtw_task(void *arg)
1515{
1516 struct mtw_softc *sc = arg;
1517 struct mtw_host_cmd_ring *ring = &sc->cmdq;
1518 struct mtw_host_cmd *cmd;
1519 int s;
1520
1521 if (usbd_is_dying(sc->sc_udev))
1522 return;
1523
1524 /* process host commands */
1525 s = splusb()splraise(0x2);
1526 while (ring->next != ring->cur) {
1527 cmd = &ring->cmd[ring->next];
1528 splx(s)spllower(s);
1529 /* callback */
1530 cmd->cb(sc, cmd->data);
1531 s = splusb()splraise(0x2);
1532 ring->queued--;
1533 ring->next = (ring->next + 1) % MTW_HOST_CMD_RING_COUNT32;
1534 }
1535 splx(s)spllower(s);
1536}
1537
1538void
1539mtw_do_async(struct mtw_softc *sc, void (*cb)(struct mtw_softc *, void *),
1540 void *arg, int len)
1541{
1542 struct mtw_host_cmd_ring *ring = &sc->cmdq;
1543 struct mtw_host_cmd *cmd;
1544 int s;
1545
1546 if (usbd_is_dying(sc->sc_udev))
1547 return;
1548
1549 s = splusb()splraise(0x2);
1550 cmd = &ring->cmd[ring->cur];
1551 cmd->cb = cb;
1552 KASSERT(len <= sizeof (cmd->data))((len <= sizeof (cmd->data)) ? (void)0 : __assert("diagnostic "
, "/usr/src/sys/dev/usb/if_mtw.c", 1552, "len <= sizeof (cmd->data)"
))
;
1553 memcpy(cmd->data, arg, len)__builtin_memcpy((cmd->data), (arg), (len));
1554 ring->cur = (ring->cur + 1) % MTW_HOST_CMD_RING_COUNT32;
1555
1556 /* if there is no pending command already, schedule a task */
1557 if (++ring->queued == 1)
1558 usb_add_task(sc->sc_udev, &sc->sc_task);
1559 splx(s)spllower(s);
1560}
1561
1562int
1563mtw_newstate(struct ieee80211com *ic, enum ieee80211_state nstate, int arg)
1564{
1565 struct mtw_softc *sc = ic->ic_softcic_ac.ac_if.if_softc;
1566 struct mtw_cmd_newstate cmd;
1567
1568 /* do it in a process context */
1569 cmd.state = nstate;
1570 cmd.arg = arg;
1571 mtw_do_async(sc, mtw_newstate_cb, &cmd, sizeof cmd);
1572 return 0;
1573}
1574
1575void
1576mtw_newstate_cb(struct mtw_softc *sc, void *arg)
1577{
1578 struct mtw_cmd_newstate *cmd = arg;
1579 struct ieee80211com *ic = &sc->sc_ic;
1580 enum ieee80211_state ostate;
1581 struct ieee80211_node *ni;
1582 uint32_t sta[3];
1583 uint8_t wcid;
1584 int s;
1585
1586 s = splnet()splraise(0x4);
1587 ostate = ic->ic_state;
1588
1589 if (ostate == IEEE80211_S_RUN) {
1590 /* turn link LED on */
1591 mtw_set_leds(sc, MTW_LED_MODE_ON0);
1592 }
1593
1594 switch (cmd->state) {
1595 case IEEE80211_S_INIT:
1596 if (ostate == IEEE80211_S_RUN) {
1597 /* abort TSF synchronization */
1598 mtw_abort_tsf_sync(sc);
1599 }
1600 break;
1601
1602 case IEEE80211_S_SCAN:
1603 mtw_set_chan(sc, ic->ic_bss->ni_chan);
1604 if (!usbd_is_dying(sc->sc_udev))
1605 timeout_add_msec(&sc->scan_to, 200);
1606 break;
1607
1608 case IEEE80211_S_AUTH:
1609 case IEEE80211_S_ASSOC:
1610 mtw_set_chan(sc, ic->ic_bss->ni_chan);
1611 break;
1612
1613 case IEEE80211_S_RUN:
1614 mtw_set_chan(sc, ic->ic_bss->ni_chan);
1615
1616 ni = ic->ic_bss;
1617
1618 if (ic->ic_opmode != IEEE80211_M_MONITOR) {
1619 mtw_updateslot(ic);
1620 mtw_enable_mrr(sc);
1621 mtw_set_txpreamble(sc);
1622 mtw_set_basicrates(sc);
1623 mtw_set_bssid(sc, ni->ni_bssid);
1624 }
1625 if (ic->ic_opmode == IEEE80211_M_STA) {
1626 /* add BSS entry to the WCID table */
1627 wcid = MTW_AID2WCID(ni->ni_associd)(1 + ((ni->ni_associd) & 0x7));
1628 mtw_write_region_1(sc, MTW_WCID_ENTRY(wcid)(0x1800 + (wcid) * 8),
1629 ni->ni_macaddr, IEEE80211_ADDR_LEN6);
1630
1631 /* fake a join to init the tx rate */
1632 mtw_newassoc(ic, ni, 1);
1633 }
1634 if (ic->ic_opmode != IEEE80211_M_MONITOR) {
1635 mtw_enable_tsf_sync(sc);
1636
1637 /* clear statistic registers used by AMRR */
1638 mtw_read_region_1(sc, MTW_TX_STA_CNT00x170c,
1639 (uint8_t *)sta, sizeof sta);
1640 /* start calibration timer */
1641 if (!usbd_is_dying(sc->sc_udev))
1642 timeout_add_sec(&sc->calib_to, 1);
1643 }
1644
1645 /* turn link LED on */
1646 mtw_set_leds(sc, MTW_LED_MODE_BLINK_TX2);
1647 break;
1648 }
1649 (void)sc->sc_newstate(ic, cmd->state, cmd->arg);
1650 splx(s)spllower(s);
1651}
1652
1653void
1654mtw_updateedca(struct ieee80211com *ic)
1655{
1656 /* do it in a process context */
1657 mtw_do_async(ic->ic_softcic_ac.ac_if.if_softc, mtw_updateedca_cb, NULL((void *)0), 0);
1658}
1659
1660void
1661mtw_updateedca_cb(struct mtw_softc *sc, void *arg)
1662{
1663 struct ieee80211com *ic = &sc->sc_ic;
1664 int s, aci;
1665
1666 s = splnet()splraise(0x4);
1667 /* update MAC TX configuration registers */
1668 for (aci = 0; aci < EDCA_NUM_AC4; aci++) {
1669 mtw_write(sc, MTW_EDCA_AC_CFG(aci)(0x1300 + (aci) * 4),
1670 ic->ic_edca_ac[aci].ac_ecwmax << 16 |
1671 ic->ic_edca_ac[aci].ac_ecwmin << 12 |
1672 ic->ic_edca_ac[aci].ac_aifsn << 8 |
1673 ic->ic_edca_ac[aci].ac_txoplimit);
1674 }
1675
1676 /* update SCH/DMA registers too */
1677 mtw_write(sc, MTW_WMM_AIFSN_CFG0x0214,
1678 ic->ic_edca_ac[EDCA_AC_VO].ac_aifsn << 12 |
1679 ic->ic_edca_ac[EDCA_AC_VI].ac_aifsn << 8 |
1680 ic->ic_edca_ac[EDCA_AC_BK].ac_aifsn << 4 |
1681 ic->ic_edca_ac[EDCA_AC_BE].ac_aifsn);
1682 mtw_write(sc, MTW_WMM_CWMIN_CFG0x0218,
1683 ic->ic_edca_ac[EDCA_AC_VO].ac_ecwmin << 12 |
1684 ic->ic_edca_ac[EDCA_AC_VI].ac_ecwmin << 8 |
1685 ic->ic_edca_ac[EDCA_AC_BK].ac_ecwmin << 4 |
1686 ic->ic_edca_ac[EDCA_AC_BE].ac_ecwmin);
1687 mtw_write(sc, MTW_WMM_CWMAX_CFG0x021c,
1688 ic->ic_edca_ac[EDCA_AC_VO].ac_ecwmax << 12 |
1689 ic->ic_edca_ac[EDCA_AC_VI].ac_ecwmax << 8 |
1690 ic->ic_edca_ac[EDCA_AC_BK].ac_ecwmax << 4 |
1691 ic->ic_edca_ac[EDCA_AC_BE].ac_ecwmax);
1692 mtw_write(sc, MTW_WMM_TXOP0_CFG0x0220,
1693 ic->ic_edca_ac[EDCA_AC_BK].ac_txoplimit << 16 |
1694 ic->ic_edca_ac[EDCA_AC_BE].ac_txoplimit);
1695 mtw_write(sc, MTW_WMM_TXOP1_CFG0x0224,
1696 ic->ic_edca_ac[EDCA_AC_VO].ac_txoplimit << 16 |
1697 ic->ic_edca_ac[EDCA_AC_VI].ac_txoplimit);
1698 splx(s)spllower(s);
1699}
1700
1701void
1702mtw_updateslot(struct ieee80211com *ic)
1703{
1704 /* do it in a process context */
1705 mtw_do_async(ic->ic_softcic_ac.ac_if.if_softc, mtw_updateslot_cb, NULL((void *)0), 0);
1706}
1707
1708void
1709mtw_updateslot_cb(struct mtw_softc *sc, void *arg)
1710{
1711 uint32_t tmp;
1712
1713 mtw_read(sc, MTW_BKOFF_SLOT_CFG0x1104, &tmp);
1714 tmp &= ~0xff;
1715 tmp |= (sc->sc_ic.ic_flags & IEEE80211_F_SHSLOT0x00020000) ?
1716 IEEE80211_DUR_DS_SHSLOT9 : IEEE80211_DUR_DS_SLOT20;
1717 mtw_write(sc, MTW_BKOFF_SLOT_CFG0x1104, tmp);
1718}
1719
1720int
1721mtw_set_key(struct ieee80211com *ic, struct ieee80211_node *ni,
1722 struct ieee80211_key *k)
1723{
1724 struct mtw_softc *sc = ic->ic_softcic_ac.ac_if.if_softc;
1725 struct mtw_cmd_key cmd;
1726
1727 /* defer setting of WEP keys until interface is brought up */
1728 if ((ic->ic_ific_ac.ac_if.if_flags & (IFF_UP0x1 | IFF_RUNNING0x40)) !=
1729 (IFF_UP0x1 | IFF_RUNNING0x40))
1730 return 0;
1731
1732 /* do it in a process context */
1733 cmd.key = *k;
1734 cmd.ni = ni;
1735 mtw_do_async(sc, mtw_set_key_cb, &cmd, sizeof cmd);
1736 sc->sc_key_tasks++;
1737 return EBUSY16;
1738}
1739
1740void
1741mtw_set_key_cb(struct mtw_softc *sc, void *arg)
1742{
1743 struct ieee80211com *ic = &sc->sc_ic;
1744 struct mtw_cmd_key *cmd = arg;
1745 struct ieee80211_key *k = &cmd->key;
1746 uint32_t attr;
1747 uint16_t base;
1748 uint8_t mode, wcid, iv[8];
1749
1750 sc->sc_key_tasks--;
1751
1752 /* map net80211 cipher to RT2860 security mode */
1753 switch (k->k_cipher) {
1754 case IEEE80211_CIPHER_WEP40:
1755 mode = MTW_MODE_WEP401;
1756 break;
1757 case IEEE80211_CIPHER_WEP104:
1758 mode = MTW_MODE_WEP1042;
1759 break;
1760 case IEEE80211_CIPHER_TKIP:
1761 mode = MTW_MODE_TKIP3;
1762 break;
1763 case IEEE80211_CIPHER_CCMP:
1764 mode = MTW_MODE_AES_CCMP4;
1765 break;
1766 default:
1767 if (cmd->ni != NULL((void *)0)) {
1768 IEEE80211_SEND_MGMT(ic, cmd->ni,((*(ic)->ic_send_mgmt)(ic, cmd->ni, 0xc0, IEEE80211_REASON_AUTH_LEAVE
, 0))
1769 IEEE80211_FC0_SUBTYPE_DEAUTH,((*(ic)->ic_send_mgmt)(ic, cmd->ni, 0xc0, IEEE80211_REASON_AUTH_LEAVE
, 0))
1770 IEEE80211_REASON_AUTH_LEAVE)((*(ic)->ic_send_mgmt)(ic, cmd->ni, 0xc0, IEEE80211_REASON_AUTH_LEAVE
, 0))
;
1771 }
1772 ieee80211_new_state(ic, IEEE80211_S_SCAN, -1)(((ic)->ic_newstate)((ic), (IEEE80211_S_SCAN), (-1)));
1773 return;
1774 }
1775
1776 if (k->k_flags & IEEE80211_KEY_GROUP0x00000001) {
1777 wcid = 0; /* NB: update WCID0 for group keys */
1778 base = MTW_SKEY(0, k->k_id)((0 & 8) ? (0xb400 + (4 * ((0) & 7) + (k->k_id)) *
32) : (0xac00 + (4 * (0) + (k->k_id)) * 32))
;
1779 } else {
1780 wcid = (cmd->ni != NULL((void *)0)) ? MTW_AID2WCID(cmd->ni->ni_associd)(1 + ((cmd->ni->ni_associd) & 0x7)) : 0;
1781 base = MTW_PKEY(wcid)(0x8000 + (wcid) * 32);
1782 }
1783
1784 if (k->k_cipher == IEEE80211_CIPHER_TKIP) {
1785 mtw_write_region_1(sc, base, k->k_key, 16);
1786 mtw_write_region_1(sc, base + 16, &k->k_key[24], 8);
1787 mtw_write_region_1(sc, base + 24, &k->k_key[16], 8);
1788 } else {
1789 /* roundup len to 16-bit: XXX fix write_region_1() instead */
1790 mtw_write_region_1(sc, base, k->k_key, (k->k_len + 1) & ~1);
1791 }
1792
1793 if (!(k->k_flags & IEEE80211_KEY_GROUP0x00000001) ||
1794 (k->k_flags & IEEE80211_KEY_TX0x00000002)) {
1795 /* set initial packet number in IV+EIV */
1796 if (k->k_cipher == IEEE80211_CIPHER_WEP40 ||
1797 k->k_cipher == IEEE80211_CIPHER_WEP104) {
1798 memset(iv, 0, sizeof iv)__builtin_memset((iv), (0), (sizeof iv));
1799 iv[3] = sc->sc_ic.ic_def_txkey << 6;
1800 } else {
1801 if (k->k_cipher == IEEE80211_CIPHER_TKIP) {
1802 iv[0] = k->k_tsc >> 8;
1803 iv[1] = (iv[0] | 0x20) & 0x7f;
1804 iv[2] = k->k_tsc;
1805 } else /* CCMP */ {
1806 iv[0] = k->k_tsc;
1807 iv[1] = k->k_tsc >> 8;
1808 iv[2] = 0;
1809 }
1810 iv[3] = k->k_id << 6 | IEEE80211_WEP_EXTIV0x20;
1811 iv[4] = k->k_tsc >> 16;
1812 iv[5] = k->k_tsc >> 24;
1813 iv[6] = k->k_tsc >> 32;
1814 iv[7] = k->k_tsc >> 40;
1815 }
1816 mtw_write_region_1(sc, MTW_IVEIV(wcid)(0xa000 + (wcid) * 8), iv, 8);
1817 }
1818
1819 if (k->k_flags & IEEE80211_KEY_GROUP0x00000001) {
1820 /* install group key */
1821 mtw_read(sc, MTW_SKEY_MODE_0_70xb000, &attr);
1822 attr &= ~(0xf << (k->k_id * 4));
1823 attr |= mode << (k->k_id * 4);
1824 mtw_write(sc, MTW_SKEY_MODE_0_70xb000, attr);
1825
1826 if (k->k_cipher & (IEEE80211_CIPHER_WEP104 |
1827 IEEE80211_CIPHER_WEP40)) {
1828 mtw_read(sc, MTW_WCID_ATTR(wcid + 1)(0xa800 + (wcid + 1) * 4), &attr);
1829 attr = (attr & ~0xf) | (mode << 1);
1830 mtw_write(sc, MTW_WCID_ATTR(wcid + 1)(0xa800 + (wcid + 1) * 4), attr);
1831
1832 mtw_set_region_4(sc, MTW_IVEIV(0)(0xa000 + (0) * 8), 0, 4);
1833
1834 mtw_read(sc, MTW_WCID_ATTR(wcid)(0xa800 + (wcid) * 4), &attr);
1835 attr = (attr & ~0xf) | (mode << 1);
1836 mtw_write(sc, MTW_WCID_ATTR(wcid)(0xa800 + (wcid) * 4), attr);
1837 }
1838 } else {
1839 /* install pairwise key */
1840 mtw_read(sc, MTW_WCID_ATTR(wcid)(0xa800 + (wcid) * 4), &attr);
1841 attr = (attr & ~0xf) | (mode << 1) | MTW_RX_PKEY_EN(1 << 0);
1842 mtw_write(sc, MTW_WCID_ATTR(wcid)(0xa800 + (wcid) * 4), attr);
1843 }
1844
1845 if (sc->sc_key_tasks == 0) {
1846 if (cmd->ni != NULL((void *)0))
1847 cmd->ni->ni_port_valid = 1;
1848 ieee80211_set_link_state(ic, LINK_STATE_UP4);
1849 }
1850}
1851
1852void
1853mtw_delete_key(struct ieee80211com *ic, struct ieee80211_node *ni,
1854 struct ieee80211_key *k)
1855{
1856 struct mtw_softc *sc = ic->ic_softcic_ac.ac_if.if_softc;
1857 struct mtw_cmd_key cmd;
1858
1859 if (!(ic->ic_ific_ac.ac_if.if_flags & IFF_RUNNING0x40) ||
1860 ic->ic_state != IEEE80211_S_RUN)
1861 return; /* nothing to do */
1862
1863 /* do it in a process context */
1864 cmd.key = *k;
1865 cmd.ni = ni;
1866 mtw_do_async(sc, mtw_delete_key_cb, &cmd, sizeof cmd);
1867}
1868
1869void
1870mtw_delete_key_cb(struct mtw_softc *sc, void *arg)
1871{
1872 struct mtw_cmd_key *cmd = arg;
1873 struct ieee80211_key *k = &cmd->key;
1874 uint32_t attr;
1875 uint8_t wcid;
1876
1877 if (k->k_flags & IEEE80211_KEY_GROUP0x00000001) {
1878 /* remove group key */
1879 mtw_read(sc, MTW_SKEY_MODE_0_70xb000, &attr);
1880 attr &= ~(0xf << (k->k_id * 4));
1881 mtw_write(sc, MTW_SKEY_MODE_0_70xb000, attr);
1882
1883 } else {
1884 /* remove pairwise key */
1885 wcid = (cmd->ni != NULL((void *)0)) ? MTW_AID2WCID(cmd->ni->ni_associd)(1 + ((cmd->ni->ni_associd) & 0x7)) : 0;
1886 mtw_read(sc, MTW_WCID_ATTR(wcid)(0xa800 + (wcid) * 4), &attr);
1887 attr &= ~0xf;
1888 mtw_write(sc, MTW_WCID_ATTR(wcid)(0xa800 + (wcid) * 4), attr);
1889 }
1890}
1891
1892void
1893mtw_calibrate_to(void *arg)
1894{
1895 /* do it in a process context */
1896 mtw_do_async(arg, mtw_calibrate_cb, NULL((void *)0), 0);
1897 /* next timeout will be rescheduled in the calibration task */
1898}
1899
1900void
1901mtw_calibrate_cb(struct mtw_softc *sc, void *arg)
1902{
1903 struct ifnet *ifp = &sc->sc_ic.ic_ific_ac.ac_if;
1904 uint32_t sta[3];
1905 int s, error;
1906
1907 /* read statistic counters (clear on read) and update AMRR state */
1908 error = mtw_read_region_1(sc, MTW_TX_STA_CNT00x170c, (uint8_t *)sta,
1909 sizeof sta);
1910 if (error != 0)
1911 goto skip;
1912
1913 DPRINTF(("retrycnt=%d txcnt=%d failcnt=%d\n",
1914 letoh32(sta[1]) >> 16, letoh32(sta[1]) & 0xffff,
1915 letoh32(sta[0]) & 0xffff));
1916
1917 s = splnet()splraise(0x4);
1918 /* count failed TX as errors */
1919 ifp->if_oerrorsif_data.ifi_oerrors += letoh32(sta[0])((__uint32_t)(sta[0])) & 0xffff;
1920
1921 sc->amn.amn_retrycnt =
1922 (letoh32(sta[0])((__uint32_t)(sta[0])) & 0xffff) + /* failed TX count */
1923 (letoh32(sta[1])((__uint32_t)(sta[1])) >> 16); /* TX retransmission count */
1924
1925 sc->amn.amn_txcnt =
1926 sc->amn.amn_retrycnt +
1927 (letoh32(sta[1])((__uint32_t)(sta[1])) & 0xffff); /* successful TX count */
1928
1929 ieee80211_amrr_choose(&sc->amrr, sc->sc_ic.ic_bss, &sc->amn);
1930
1931 splx(s)spllower(s);
1932skip:
1933 if (!usbd_is_dying(sc->sc_udev))
1934 timeout_add_sec(&sc->calib_to, 1);
1935}
1936
1937void
1938mtw_newassoc(struct ieee80211com *ic, struct ieee80211_node *ni, int isnew)
1939{
1940 struct mtw_softc *sc = ic->ic_softcic_ac.ac_if.if_softc;
1941 struct mtw_node *mn = (void *)ni;
1942 struct ieee80211_rateset *rs = &ni->ni_rates;
1943 uint8_t rate;
1944 int ridx, i, j;
1945
1946 DPRINTF(("new assoc isnew=%d addr=%s\n",
1947 isnew, ether_sprintf(ni->ni_macaddr)));
1948
1949 ieee80211_amrr_node_init(&sc->amrr, &sc->amn);
1950
1951 /* start at lowest available bit-rate, AMRR will raise */
1952 ni->ni_txrate = 0;
1953
1954 for (i = 0; i < rs->rs_nrates; i++) {
1955 rate = rs->rs_rates[i] & IEEE80211_RATE_VAL0x7f;
1956 /* convert 802.11 rate to hardware rate index */
1957 for (ridx = 0; ridx < MTW_RIDX_MAX11; ridx++)
1958 if (rt2860_rates[ridx].rate == rate)
1959 break;
1960 mn->ridx[i] = ridx;
1961 /* determine rate of control response frames */
1962 for (j = i; j >= 0; j--) {
1963 if ((rs->rs_rates[j] & IEEE80211_RATE_BASIC0x80) &&
1964 rt2860_rates[mn->ridx[i]].phy ==
1965 rt2860_rates[mn->ridx[j]].phy)
1966 break;
1967 }
1968 if (j >= 0) {
1969 mn->ctl_ridx[i] = mn->ridx[j];
1970 } else {
1971 /* no basic rate found, use mandatory one */
1972 mn->ctl_ridx[i] = rt2860_rates[ridx].ctl_ridx;
1973 }
1974 DPRINTF(("rate=0x%02x ridx=%d ctl_ridx=%d\n",
1975 rs->rs_rates[i], mn->ridx[i], mn->ctl_ridx[i]));
1976 }
1977}
1978
1979/*
1980 * Return the Rx chain with the highest RSSI for a given frame.
1981 */
1982static __inline uint8_t
1983mtw_maxrssi_chain(struct mtw_softc *sc, const struct mtw_rxwi *rxwi)
1984{
1985 uint8_t rxchain = 0;
1986
1987 if (sc->nrxchains > 1) {
1988 if (rxwi->rssi[1] > rxwi->rssi[rxchain])
1989 rxchain = 1;
1990 }
1991 return rxchain;
1992}
1993
1994void
1995mtw_rx_frame(struct mtw_softc *sc, uint8_t *buf, int dmalen,
1996 struct mbuf_list *ml)
1997{
1998 struct ieee80211com *ic = &sc->sc_ic;
1999 struct ifnet *ifp = &ic->ic_ific_ac.ac_if;
2000 struct ieee80211_frame *wh;
2001 struct ieee80211_rxinfo rxi;
2002 struct ieee80211_node *ni;
2003 struct mtw_rxwi *rxwi;
2004 struct mbuf *m;
2005 uint32_t flags;
2006 uint16_t len;
2007#if NBPFILTER1 > 0
2008 uint16_t phy;
2009#endif
2010 uint16_t rxwisize;
2011 uint8_t ant, rssi;
2012 int s;
2013
2014 /* Rx Wireless Information */
2015 rxwi = (struct mtw_rxwi *)(buf);
2016 rxwisize = sizeof(struct mtw_rxwi);
2017 len = letoh16(rxwi->len)((__uint16_t)(rxwi->len)) & 0xfff;
2018
2019 if (__predict_false(len > dmalen)__builtin_expect(((len > dmalen) != 0), 0)) {
2020 DPRINTF(("bad RXWI length %u > %u\n", len, dmalen));
2021 return;
2022 }
2023 if (len > MCLBYTES(1 << 11)) {
2024 DPRINTF(("frame too large (length=%d)\n", len));
2025 ifp->if_ierrorsif_data.ifi_ierrors++;
2026 return;
2027 }
2028
2029 flags = letoh32(rxwi->flags)((__uint32_t)(rxwi->flags));
2030 if (__predict_false(flags & (MTW_RX_CRCERR | MTW_RX_ICVERR))__builtin_expect(((flags & ((1 << 8) | (1 << 9
))) != 0), 0)
) {
2031 ifp->if_ierrorsif_data.ifi_ierrors++;
2032 return;
2033 }
2034 if (__predict_false((flags & MTW_RX_MICERR))__builtin_expect((((flags & (1 << 10))) != 0), 0)) {
2035 /* report MIC failures to net80211 for TKIP */
2036 ic->ic_stats.is_rx_locmicfail++;
2037 ieee80211_michael_mic_failure(ic, 0/* XXX */);
2038 ifp->if_ierrorsif_data.ifi_ierrors++;
2039 return;
2040 }
2041
2042 wh = (struct ieee80211_frame *)(buf + rxwisize);
2043 memset(&rxi, 0, sizeof(rxi))__builtin_memset((&rxi), (0), (sizeof(rxi)));
2044 if (wh->i_fc[1] & IEEE80211_FC1_PROTECTED0x40) {
2045 wh->i_fc[1] &= ~IEEE80211_FC1_PROTECTED0x40;
2046 rxi.rxi_flags |= IEEE80211_RXI_HWDEC0x00000001;
2047 }
2048
2049 if (flags & MTW_RX_L2PAD(1 << 14)) {
2050 u_int hdrlen = ieee80211_get_hdrlen(wh);
2051 memmove((caddr_t)wh + 2, wh, hdrlen)__builtin_memmove(((caddr_t)wh + 2), (wh), (hdrlen));
2052 wh = (struct ieee80211_frame *)((caddr_t)wh + 2);
2053 }
2054
2055 /* could use m_devget but net80211 wants contig mgmt frames */
2056 MGETHDR(m, M_DONTWAIT, MT_DATA)m = m_gethdr((0x0002), (1));
2057 if (__predict_false(m == NULL)__builtin_expect(((m == ((void *)0)) != 0), 0)) {
2058 ifp->if_ierrorsif_data.ifi_ierrors++;
2059 return;
2060 }
2061 if (len > MHLEN((256 - sizeof(struct m_hdr)) - sizeof(struct pkthdr))) {
2062 MCLGET(m, M_DONTWAIT)(void) m_clget((m), (0x0002), (1 << 11));
2063 if (__predict_false(!(m->m_flags & M_EXT))__builtin_expect(((!(m->m_hdr.mh_flags & 0x0001)) != 0
), 0)
) {
2064 ifp->if_ierrorsif_data.ifi_ierrors++;
2065 m_freem(m);
2066 return;
2067 }
2068 }
2069 /* finalize mbuf */
2070 memcpy(mtod(m, caddr_t), wh, len)__builtin_memcpy((((caddr_t)((m)->m_hdr.mh_data))), (wh), (
len))
;
2071 m->m_pkthdrM_dat.MH.MH_pkthdr.len = m->m_lenm_hdr.mh_len = len;
2072
2073 ant = mtw_maxrssi_chain(sc, rxwi);
2074 rssi = rxwi->rssi[ant];
2075
2076#if NBPFILTER1 > 0
2077 if (__predict_false(sc->sc_drvbpf != NULL)__builtin_expect(((sc->sc_drvbpf != ((void *)0)) != 0), 0)) {
2078 struct mtw_rx_radiotap_header *tap = &sc->sc_rxtapsc_rxtapu.th;
2079 struct mbuf mb;
2080
2081 tap->wr_flags = 0;
2082 tap->wr_chan_freq = htole16(ic->ic_ibss_chan->ic_freq)((__uint16_t)(ic->ic_ibss_chan->ic_freq));
2083 tap->wr_chan_flags = htole16(ic->ic_ibss_chan->ic_flags)((__uint16_t)(ic->ic_ibss_chan->ic_flags));
2084 tap->wr_antsignal = rssi;
2085 tap->wr_antenna = ant;
2086 tap->wr_dbm_antsignal = mtw_rssi2dbm(sc, rssi, ant);
2087 tap->wr_rate = 2; /* in case it can't be found below */
2088 phy = letoh16(rxwi->phy)((__uint16_t)(rxwi->phy));
2089 switch (phy >> MT7601_PHY_SHIFT14) {
2090 case MTW_PHY_CCK:
2091 switch ((phy & MTW_PHY_MCS0x3f) & ~MTW_PHY_SHPRE(1 << 3)) {
2092 case 0: tap->wr_rate = 2; break;
2093 case 1: tap->wr_rate = 4; break;
2094 case 2: tap->wr_rate = 11; break;
2095 case 3: tap->wr_rate = 22; break;
2096 }
2097 if (phy & MTW_PHY_SHPRE(1 << 3))
2098 tap->wr_flags |= IEEE80211_RADIOTAP_F_SHORTPRE0x02;
2099 break;
2100 case MTW_PHY_OFDM:
2101 switch (phy & MTW_PHY_MCS0x3f) {
2102 case 0: tap->wr_rate = 12; break;
2103 case 1: tap->wr_rate = 18; break;
2104 case 2: tap->wr_rate = 24; break;
2105 case 3: tap->wr_rate = 36; break;
2106 case 4: tap->wr_rate = 48; break;
2107 case 5: tap->wr_rate = 72; break;
2108 case 6: tap->wr_rate = 96; break;
2109 case 7: tap->wr_rate = 108; break;
2110 }
2111 break;
2112 }
2113 mb.m_datam_hdr.mh_data = (caddr_t)tap;
2114 mb.m_lenm_hdr.mh_len = sc->sc_rxtap_len;
2115 mb.m_nextm_hdr.mh_next = m;
2116 mb.m_nextpktm_hdr.mh_nextpkt = NULL((void *)0);
2117 mb.m_typem_hdr.mh_type = 0;
2118 mb.m_flagsm_hdr.mh_flags = 0;
2119 bpf_mtap(sc->sc_drvbpf, &mb, BPF_DIRECTION_IN(1 << 0));
2120 }
2121#endif
2122
2123 s = splnet()splraise(0x4);
2124 ni = ieee80211_find_rxnode(ic, wh);
2125 rxi.rxi_rssi = rssi;
2126 ieee80211_inputm(ifp, m, ni, &rxi, ml);
2127
2128 /* node is no longer needed */
2129 ieee80211_release_node(ic, ni);
2130 splx(s)spllower(s);
2131}
2132
2133void
2134mtw_rxeof(struct usbd_xfer *xfer, void *priv, usbd_status status)
2135{
2136 struct mbuf_list ml = MBUF_LIST_INITIALIZER(){ ((void *)0), ((void *)0), 0 };
2137 struct mtw_rx_data *data = priv;
2138 struct mtw_softc *sc = data->sc;
2139 uint8_t *buf;
2140 uint32_t dmalen;
2141 int xferlen;
2142
2143 if (__predict_false(status != USBD_NORMAL_COMPLETION)__builtin_expect(((status != USBD_NORMAL_COMPLETION) != 0), 0
)
) {
2144 DPRINTF(("RX status=%d\n", status));
2145 if (status == USBD_STALLED)
2146 usbd_clear_endpoint_stall_async(sc->rxq[0].pipeh);
2147 if (status != USBD_CANCELLED)
2148 goto skip;
2149 return;
2150 }
2151
2152 usbd_get_xfer_status(xfer, NULL((void *)0), NULL((void *)0), &xferlen, NULL((void *)0));
2153
2154 if (__predict_false(xferlen < sizeof(uint32_t) +__builtin_expect(((xferlen < sizeof(uint32_t) + sizeof (struct
mtw_rxwi) + sizeof(struct mtw_rxd)) != 0), 0)
2155 sizeof (struct mtw_rxwi) + sizeof(struct mtw_rxd))__builtin_expect(((xferlen < sizeof(uint32_t) + sizeof (struct
mtw_rxwi) + sizeof(struct mtw_rxd)) != 0), 0)
) {
2156 DPRINTF(("RX xfer too short %d\n", xferlen));
2157 goto skip;
2158 }
2159
2160 /* HW can aggregate multiple 802.11 frames in a single USB xfer */
2161 buf = data->buf;
2162 while (xferlen > 8) {
2163 dmalen = letoh32(*(uint32_t *)buf)((__uint32_t)(*(uint32_t *)buf)) & MTW_RXD_LEN0x3fff;
2164 if (__predict_false(dmalen == 0 || (dmalen & 3) != 0)__builtin_expect(((dmalen == 0 || (dmalen & 3) != 0) != 0
), 0)
) {
2165 DPRINTF(("bad DMA length %u\n", dmalen));
2166 break;
2167 }
2168 if (__predict_false(dmalen + 8 > xferlen)__builtin_expect(((dmalen + 8 > xferlen) != 0), 0)) {
2169 DPRINTF(("bad DMA length %u > %d\n",
2170 dmalen + 8, xferlen));
2171 break;
2172 }
2173 mtw_rx_frame(sc, buf + sizeof(struct mtw_rxd), dmalen, &ml);
2174 buf += dmalen + 8;
2175 xferlen -= dmalen + 8;
2176 }
2177 if_input(&sc->sc_ic.ic_ific_ac.ac_if, &ml);
2178
2179skip: /* setup a new transfer */
2180 usbd_setup_xfer(xfer, sc->rxq[0].pipeh, data, data->buf, MTW_MAX_RXSZ4096,
2181 USBD_SHORT_XFER_OK0x04 | USBD_NO_COPY0x01, USBD_NO_TIMEOUT0, mtw_rxeof);
2182 (void)usbd_transfer(data->xfer);
2183}
2184
2185void
2186mtw_txeof(struct usbd_xfer *xfer, void *priv, usbd_status status)
2187{
2188 struct mtw_tx_data *data = priv;
2189 struct mtw_softc *sc = data->sc;
2190 struct mtw_tx_ring *txq = &sc->txq[data->qid];
2191 struct ifnet *ifp = &sc->sc_ic.ic_ific_ac.ac_if;
2192 int s;
2193
2194 if (usbd_is_dying(sc->sc_udev))
2195 return;
2196
2197 s = splnet()splraise(0x4);
2198 txq->queued--;
2199 sc->qfullmsk &= ~(1 << data->qid);
2200
2201 if (__predict_false(status != USBD_NORMAL_COMPLETION)__builtin_expect(((status != USBD_NORMAL_COMPLETION) != 0), 0
)
) {
2202 DPRINTF(("TX status=%d\n", status));
2203 if (status == USBD_STALLED)
2204 usbd_clear_endpoint_stall_async(txq->pipeh);
2205 ifp->if_oerrorsif_data.ifi_oerrors++;
2206 splx(s)spllower(s);
2207 return;
2208 }
2209
2210 sc->sc_tx_timer = 0;
2211
2212 if (ifq_is_oactive(&ifp->if_snd)) {
2213 ifq_clr_oactive(&ifp->if_snd);
2214 mtw_start(ifp);
2215 }
2216
2217 splx(s)spllower(s);
2218}
2219
2220int
2221mtw_tx(struct mtw_softc *sc, struct mbuf *m, struct ieee80211_node *ni)
2222{
2223 struct ieee80211com *ic = &sc->sc_ic;
2224 struct mtw_node *mn = (void *)ni;
2225 struct ieee80211_frame *wh;
2226 struct mtw_tx_ring *ring;
2227 struct mtw_tx_data *data;
2228 struct mtw_txd *txd;
2229 struct mtw_txwi *txwi;
2230 uint16_t qos, dur;
2231 uint16_t txwisize;
2232 uint8_t type, mcs, tid, qid;
2233 int error, hasqos, ridx, ctl_ridx, xferlen;
2234
2235 wh = mtod(m, struct ieee80211_frame *)((struct ieee80211_frame *)((m)->m_hdr.mh_data));
2236 type = wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK0x0c;
2237
2238 /* select queue */
2239 if ((hasqos = ieee80211_has_qos(wh))) {
2240 qos = ieee80211_get_qos(wh);
2241 tid = qos & IEEE80211_QOS_TID0x000f;
2242 qid = ieee80211_up_to_ac(ic, tid);
2243 } else {
2244 qos = 0;
2245 tid = 0;
2246 qid = EDCA_AC_BE;
2247 }
2248
2249 /* management frames go to MCU queue */
2250 if (type == IEEE80211_FC0_TYPE_MGT0x00)
2251 qid = MTW_TXQ_MCU5;
2252
2253 ring = &sc->txq[qid];
2254 data = &ring->data[ring->cur];
2255
2256 /* pickup a rate index */
2257 if (IEEE80211_IS_MULTICAST(wh->i_addr1)(*(wh->i_addr1) & 0x01) ||
2258 type != IEEE80211_FC0_TYPE_DATA0x08) {
2259 ridx = (ic->ic_curmode == IEEE80211_MODE_11A) ?
2260 MTW_RIDX_OFDM64 : MTW_RIDX_CCK10;
2261 ctl_ridx = rt2860_rates[ridx].ctl_ridx;
2262 } else if (ic->ic_fixed_rate != -1) {
2263 ridx = sc->fixed_ridx;
2264 ctl_ridx = rt2860_rates[ridx].ctl_ridx;
2265 } else {
2266 ridx = mn->ridx[ni->ni_txrate];
2267 ctl_ridx = mn->ctl_ridx[ni->ni_txrate];
2268 }
2269
2270 txwisize = sizeof(struct mtw_txwi);
2271 xferlen = txwisize + m->m_pkthdrM_dat.MH.MH_pkthdr.len;
2272
2273 /* roundup to 32-bit alignment */
2274 xferlen = (xferlen + 3) & ~3;
2275
2276 /* setup TX descriptor */
2277 txd = (struct mtw_txd *)data->buf;
2278 txd->flags = htole16(MTW_TXD_DATA | MTW_TXD_80211 |((__uint16_t)((0 << 14) | (1 << 3) | (0 << 11
) | (2 << 9)))
2279 MTW_TXD_WLAN | MTW_TXD_QSEL_EDCA)((__uint16_t)((0 << 14) | (1 << 3) | (0 << 11
) | (2 << 9)))
;
2280
2281 if (type != IEEE80211_FC0_TYPE_DATA0x08)
2282 txd->flags |= htole16(MTW_TXD_WIV)((__uint16_t)((1 << 8)));
2283 txd->len = htole16(xferlen)((__uint16_t)(xferlen));
2284 xferlen += sizeof(struct mtw_txd);
2285
2286 /* get MCS code from rate index */
2287 mcs = rt2860_rates[ridx].mcs;
2288
2289 /* setup TX Wireless Information */
2290 txwi = (struct mtw_txwi *)(txd + 1);
2291 txwi->flags = 0;
2292 txwi->xflags = hasqos ? 0 : MTW_TX_NSEQ(1 << 1);
2293 txwi->wcid = (type == IEEE80211_FC0_TYPE_DATA0x08) ?
2294 MTW_AID2WCID(ni->ni_associd)(1 + ((ni->ni_associd) & 0x7)) : 0xff;
2295 txwi->len = htole16(m->m_pkthdr.len)((__uint16_t)(m->M_dat.MH.MH_pkthdr.len));
2296 txwi->txop = MTW_TX_TXOP_BACKOFF3;
2297
2298 if (rt2860_rates[ridx].phy == IEEE80211_T_DS) {
2299 txwi->phy = htole16(MTW_PHY_CCK << MT7601_PHY_SHIFT)((__uint16_t)(MTW_PHY_CCK << 14));
2300 if (ridx != MTW_RIDX_CCK10 &&
2301 (ic->ic_flags & IEEE80211_F_SHPREAMBLE0x00040000))
2302 mcs |= MTW_PHY_SHPRE(1 << 3);
2303 } else if (rt2860_rates[ridx].phy == IEEE80211_T_OFDM)
2304 txwi->phy = htole16(MTW_PHY_OFDM << MT7601_PHY_SHIFT)((__uint16_t)(MTW_PHY_OFDM << 14));
2305 txwi->phy |= htole16(mcs)((__uint16_t)(mcs));
2306
2307 if (!IEEE80211_IS_MULTICAST(wh->i_addr1)(*(wh->i_addr1) & 0x01) &&
2308 (!hasqos || (qos & IEEE80211_QOS_ACK_POLICY_MASK0x0060) !=
2309 IEEE80211_QOS_ACK_POLICY_NOACK0x0020)) {
2310 txwi->xflags |= MTW_TX_ACK(1 << 0);
2311 if (ic->ic_flags & IEEE80211_F_SHPREAMBLE0x00040000)
2312 dur = rt2860_rates[ctl_ridx].sp_ack_dur;
2313 else
2314 dur = rt2860_rates[ctl_ridx].lp_ack_dur;
2315 *(uint16_t *)wh->i_dur = htole16(dur)((__uint16_t)(dur));
2316 }
2317
2318#if NBPFILTER1 > 0
2319 if (__predict_false(sc->sc_drvbpf != NULL)__builtin_expect(((sc->sc_drvbpf != ((void *)0)) != 0), 0)) {
2320 struct mtw_tx_radiotap_header *tap = &sc->sc_txtapsc_txtapu.th;
2321 struct mbuf mb;
2322
2323 tap->wt_flags = 0;
2324 tap->wt_rate = rt2860_rates[ridx].rate;
2325 tap->wt_chan_freq = htole16(ic->ic_bss->ni_chan->ic_freq)((__uint16_t)(ic->ic_bss->ni_chan->ic_freq));
2326 tap->wt_chan_flags = htole16(ic->ic_bss->ni_chan->ic_flags)((__uint16_t)(ic->ic_bss->ni_chan->ic_flags));
2327 if (mcs & MTW_PHY_SHPRE(1 << 3))
2328 tap->wt_flags |= IEEE80211_RADIOTAP_F_SHORTPRE0x02;
2329
2330 mb.m_datam_hdr.mh_data = (caddr_t)tap;
2331 mb.m_lenm_hdr.mh_len = sc->sc_txtap_len;
2332 mb.m_nextm_hdr.mh_next = m;
2333 mb.m_nextpktm_hdr.mh_nextpkt = NULL((void *)0);
2334 mb.m_typem_hdr.mh_type = 0;
2335 mb.m_flagsm_hdr.mh_flags = 0;
2336 bpf_mtap(sc->sc_drvbpf, &mb, BPF_DIRECTION_OUT(1 << 1));
2337 }
2338#endif
2339 /* copy payload */
2340 m_copydata(m, 0, m->m_pkthdrM_dat.MH.MH_pkthdr.len, (caddr_t)txwi + txwisize);
2341 m_freem(m);
2342
2343 /* 4-byte pad */
2344 memset(data->buf + xferlen, 0, MTW_DMA_PAD)__builtin_memset((data->buf + xferlen), (0), (4));
2345 xferlen += MTW_DMA_PAD4;
2346
2347 usbd_setup_xfer(data->xfer, ring->pipeh, data, data->buf,
2348 xferlen, USBD_FORCE_SHORT_XFER0x08 | USBD_NO_COPY0x01,
2349 MTW_TX_TIMEOUT5000, mtw_txeof);
2350 error = usbd_transfer(data->xfer);
2351 if (__predict_false(error != USBD_IN_PROGRESS && error != 0)__builtin_expect(((error != USBD_IN_PROGRESS && error
!= 0) != 0), 0)
)
2352 return error;
2353
2354 ieee80211_release_node(ic, ni);
2355
2356 ring->cur = (ring->cur + 1) % MTW_TX_RING_COUNT8;
2357 if (++ring->queued >= MTW_TX_RING_COUNT8)
2358 sc->qfullmsk |= 1 << qid;
2359 return 0;
2360}
2361
2362void
2363mtw_start(struct ifnet *ifp)
2364{
2365 struct mtw_softc *sc = ifp->if_softc;
2366 struct ieee80211com *ic = &sc->sc_ic;
2367 struct ieee80211_node *ni;
2368 struct mbuf *m;
2369
2370 if (!(ifp->if_flags & IFF_RUNNING0x40) || ifq_is_oactive(&ifp->if_snd))
2371 return;
2372
2373 for (;;) {
2374 if (sc->qfullmsk != 0) {
2375 ifq_set_oactive(&ifp->if_snd);
2376 break;
2377 }
2378
2379 /* send pending management frames first */
2380 m = mq_dequeue(&ic->ic_mgtq);
2381 if (m != NULL((void *)0)) {
2382 ni = m->m_pkthdrM_dat.MH.MH_pkthdr.ph_cookie;
2383 goto sendit;
2384 }
2385 if (ic->ic_state != IEEE80211_S_RUN)
2386 break;
2387
2388 /* encapsulate and send data frames */
2389 m = ifq_dequeue(&ifp->if_snd);
2390 if (m == NULL((void *)0))
2391 break;
2392#if NBPFILTER1 > 0
2393 if (ifp->if_bpf != NULL((void *)0))
2394 bpf_mtap(ifp->if_bpf, m, BPF_DIRECTION_OUT(1 << 1));
2395#endif
2396 if ((m = ieee80211_encap(ifp, m, &ni)) == NULL((void *)0))
2397 continue;
2398sendit:
2399#if NBPFILTER1 > 0
2400 if (ic->ic_rawbpf != NULL((void *)0))
2401 bpf_mtap(ic->ic_rawbpf, m, BPF_DIRECTION_OUT(1 << 1));
2402#endif
2403 if (mtw_tx(sc, m, ni) != 0) {
2404 ieee80211_release_node(ic, ni);
2405 ifp->if_oerrorsif_data.ifi_oerrors++;
2406 continue;
2407 }
2408
2409 sc->sc_tx_timer = 5;
2410 ifp->if_timer = 1;
2411 }
2412}
2413
2414void
2415mtw_watchdog(struct ifnet *ifp)
2416{
2417 struct mtw_softc *sc = ifp->if_softc;
2418
2419 ifp->if_timer = 0;
2420
2421 if (sc->sc_tx_timer > 0) {
2422 if (--sc->sc_tx_timer == 0) {
2423 printf("%s: device timeout\n", sc->sc_dev.dv_xname);
2424 /* mtw_init(ifp); XXX needs a process context! */
2425 ifp->if_oerrorsif_data.ifi_oerrors++;
2426 return;
2427 }
2428 ifp->if_timer = 1;
2429 }
2430
2431 ieee80211_watchdog(ifp);
2432}
2433
2434int
2435mtw_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
2436{
2437 struct mtw_softc *sc = ifp->if_softc;
2438 struct ieee80211com *ic = &sc->sc_ic;
2439 int s, error = 0;
2440
2441 if (usbd_is_dying(sc->sc_udev))
2442 return ENXIO6;
2443
2444 usbd_ref_incr(sc->sc_udev);
2445
2446 s = splnet()splraise(0x4);
2447
2448 switch (cmd) {
2449 case SIOCSIFADDR((unsigned long)0x80000000 | ((sizeof(struct ifreq) & 0x1fff
) << 16) | ((('i')) << 8) | ((12)))
:
2450 ifp->if_flags |= IFF_UP0x1;
2451 /* FALLTHROUGH */
2452 case SIOCSIFFLAGS((unsigned long)0x80000000 | ((sizeof(struct ifreq) & 0x1fff
) << 16) | ((('i')) << 8) | ((16)))
:
2453 if (ifp->if_flags & IFF_UP0x1) {
2454 if (!(ifp->if_flags & IFF_RUNNING0x40))
2455 mtw_init(ifp);
2456 } else {
2457 if (ifp->if_flags & IFF_RUNNING0x40)
2458 mtw_stop(ifp, 1);
2459 }
2460 break;
2461
2462 case SIOCS80211CHANNEL((unsigned long)0x80000000 | ((sizeof(struct ieee80211chanreq
) & 0x1fff) << 16) | ((('i')) << 8) | ((238))
)
:
2463 /*
2464 * This allows for fast channel switching in monitor mode
2465 * (used by kismet).
2466 */
2467 error = ieee80211_ioctl(ifp, cmd, data);
2468 if (error == ENETRESET52 &&
2469 ic->ic_opmode == IEEE80211_M_MONITOR) {
2470 if ((ifp->if_flags & (IFF_UP0x1 | IFF_RUNNING0x40)) ==
2471 (IFF_UP0x1 | IFF_RUNNING0x40))
2472 mtw_set_chan(sc, ic->ic_ibss_chan);
2473 error = 0;
2474 }
2475 break;
2476
2477 default:
2478 error = ieee80211_ioctl(ifp, cmd, data);
2479 }
2480
2481 if (error == ENETRESET52) {
2482 if ((ifp->if_flags & (IFF_UP0x1 | IFF_RUNNING0x40)) ==
2483 (IFF_UP0x1 | IFF_RUNNING0x40)) {
2484 mtw_stop(ifp, 0);
2485 error = mtw_init(ifp);
2486 } else
2487 error = 0;
2488 }
2489 splx(s)spllower(s);
2490
2491 usbd_ref_decr(sc->sc_udev);
2492
2493 return error;
2494}
2495
2496void
2497mtw_select_chan_group(struct mtw_softc *sc, int group)
2498{
2499 uint32_t tmp;
2500 uint8_t bbp;
2501
2502 /* Tx band 20MHz 2G */
2503 mtw_read(sc, MTW_TX_BAND_CFG0x132c, &tmp);
2504 tmp &= ~(MTW_TX_BAND_SEL_2G(1 << 2) | MTW_TX_BAND_SEL_5G(1 << 1) |
2505 MTW_TX_BAND_UPPER_40M(1 << 0));
2506 tmp |= (group == 0) ? MTW_TX_BAND_SEL_2G(1 << 2) : MTW_TX_BAND_SEL_5G(1 << 1);
2507 mtw_write(sc, MTW_TX_BAND_CFG0x132c, tmp);
2508
2509 /* select 20 MHz bandwidth */
2510 mtw_bbp_read(sc, 4, &bbp);
2511 bbp &= ~0x18;
2512 bbp |= 0x40;
2513 mtw_bbp_write(sc, 4, bbp);
2514
2515 /* calibrate BBP */
2516 mtw_bbp_write(sc, 69, 0x12);
2517 mtw_bbp_write(sc, 91, 0x07);
2518 mtw_bbp_write(sc, 195, 0x23);
2519 mtw_bbp_write(sc, 196, 0x17);
2520 mtw_bbp_write(sc, 195, 0x24);
2521 mtw_bbp_write(sc, 196, 0x06);
2522 mtw_bbp_write(sc, 195, 0x81);
2523 mtw_bbp_write(sc, 196, 0x12);
2524 mtw_bbp_write(sc, 195, 0x83);
2525 mtw_bbp_write(sc, 196, 0x17);
2526 mtw_rf_write(sc, 5, 8, 0x00);
2527 mtw_mcu_calibrate(sc, 0x6, 0x10001);
2528
2529 /* set initial AGC value */
2530 mt7601_set_agc(sc, 0x14);
2531}
2532
2533void
2534mt7601_set_agc(struct mtw_softc *sc, uint8_t agc)
2535{
2536 uint8_t bbp;
2537
2538 mtw_bbp_write(sc, 66, agc);
2539 mtw_bbp_write(sc, 195, 0x87);
2540 bbp = (agc & 0xf0) | 0x08;
2541 mtw_bbp_write(sc, 196, bbp);
2542}
2543
2544void
2545mt7601_set_chan(struct mtw_softc *sc, u_int chan)
2546{
2547 uint32_t tmp;
2548 uint8_t bbp, rf, txpow1;
2549 int i;
2550
2551 /* find the settings for this channel */
2552 for (i = 0; mt7601_rf_chan[i].chan != chan; i++)
2553
2554 mtw_rf_write(sc, 0, 17, mt7601_rf_chan[i].r17);
2555 mtw_rf_write(sc, 0, 18, mt7601_rf_chan[i].r18);
2556 mtw_rf_write(sc, 0, 19, mt7601_rf_chan[i].r19);
2557 mtw_rf_write(sc, 0, 20, mt7601_rf_chan[i].r20);
2558
2559 /* use Tx power values from EEPROM */
2560 txpow1 = sc->txpow1[i];
2561
2562 /* Tx automatic level control */
2563 mtw_read(sc, MTW_TX_ALC_CFG00x13b0, &tmp);
2564 tmp &= ~0x3f3f;
2565 tmp |= (txpow1 & 0x3f);
2566 mtw_write(sc, MTW_TX_ALC_CFG00x13b0, tmp);
2567
2568 /* LNA */
2569 mtw_bbp_write(sc, 62, 0x37 - sc->lna[0]);
2570 mtw_bbp_write(sc, 63, 0x37 - sc->lna[0]);
2571 mtw_bbp_write(sc, 64, 0x37 - sc->lna[0]);
2572
2573 /* VCO calibration */
2574 mtw_rf_write(sc, 0, 4, 0x0a);
2575 mtw_rf_write(sc, 0, 5, 0x20);
2576 mtw_rf_read(sc, 0, 4, &rf);
2577 mtw_rf_write(sc, 0, 4, rf | 0x80);
2578
2579 /* select 20 MHz bandwidth */
2580 mtw_bbp_read(sc, 4, &bbp);
2581 bbp &= ~0x18;
2582 bbp |= 0x40;
2583 mtw_bbp_write(sc, 4, bbp);
2584 mtw_bbp_write(sc, 178, 0xff);
2585}
2586
2587int
2588mtw_set_chan(struct mtw_softc *sc, struct ieee80211_channel *c)
2589{
2590 struct ieee80211com *ic = &sc->sc_ic;
2591 u_int chan, group;
2592
2593 chan = ieee80211_chan2ieee(ic, c);
2594 if (chan == 0 || chan == IEEE80211_CHAN_ANY0xffff)
2595 return EINVAL22;
2596
2597 /* determine channel group */
2598 if (chan <= 14)
2599 group = 0;
2600 else if (chan <= 64)
2601 group = 1;
2602 else if (chan <= 128)
2603 group = 2;
2604 else
2605 group = 3;
2606
2607 if (group != sc->sc_chan_group || !sc->sc_bw_calibrated)
2608 mtw_select_chan_group(sc, group);
2609
2610 sc->sc_chan_group = group;
2611
2612 /* chipset specific */
2613 if (sc->mac_ver == 0x7601)
2614 mt7601_set_chan(sc, chan);
2615
2616 DELAY(1000)(*delay_func)(1000);
2617 return 0;
2618}
2619
2620void
2621mtw_enable_tsf_sync(struct mtw_softc *sc)
2622{
2623 struct ieee80211com *ic = &sc->sc_ic;
2624 uint32_t tmp;
2625
2626 mtw_read(sc, MTW_BCN_TIME_CFG0x1114, &tmp);
2627 tmp &= ~0x1fffff;
2628 tmp |= ic->ic_bss->ni_intval * 16;
2629 tmp |= MTW_TSF_TIMER_EN(1 << 16) | MTW_TBTT_TIMER_EN(1 << 19);
2630
2631 /* local TSF is always updated with remote TSF on beacon reception */
2632 tmp |= 1 << MTW_TSF_SYNC_MODE_SHIFT17;
2633 mtw_write(sc, MTW_BCN_TIME_CFG0x1114, tmp);
2634}
2635
2636void
2637mtw_abort_tsf_sync(struct mtw_softc *sc)
2638{
2639 uint32_t tmp;
2640
2641 mtw_read(sc, MTW_BCN_TIME_CFG0x1114, &tmp);
2642 tmp &= ~(MTW_BCN_TX_EN(1 << 20) | MTW_TSF_TIMER_EN(1 << 16) | MTW_TBTT_TIMER_EN(1 << 19));
2643 mtw_write(sc, MTW_BCN_TIME_CFG0x1114, tmp);
2644}
2645
2646void
2647mtw_enable_mrr(struct mtw_softc *sc)
2648{
2649#define CCK(mcs) (mcs)
2650#define OFDM(mcs) (1 << 3 | (mcs))
2651 mtw_write(sc, MTW_LG_FBK_CFG00x135c,
2652 OFDM(6) << 28 | /* 54->48 */
2653 OFDM(5) << 24 | /* 48->36 */
2654 OFDM(4) << 20 | /* 36->24 */
2655 OFDM(3) << 16 | /* 24->18 */
2656 OFDM(2) << 12 | /* 18->12 */
2657 OFDM(1) << 8 | /* 12-> 9 */
2658 OFDM(0) << 4 | /* 9-> 6 */
2659 OFDM(0)); /* 6-> 6 */
2660
2661 mtw_write(sc, MTW_LG_FBK_CFG10x1360,
2662 CCK(2) << 12 | /* 11->5.5 */
2663 CCK(1) << 8 | /* 5.5-> 2 */
2664 CCK(0) << 4 | /* 2-> 1 */
2665 CCK(0)); /* 1-> 1 */
2666#undef OFDM
2667#undef CCK
2668}
2669
2670void
2671mtw_set_txrts(struct mtw_softc *sc)
2672{
2673 uint32_t tmp;
2674
2675 /* set RTS threshold */
2676 mtw_read(sc, MTW_TX_RTS_CFG0x1344, &tmp);
2677 tmp &= ~0xffff00;
2678 tmp |= 0x1000 << MTW_RTS_THRES_SHIFT8;
2679 mtw_write(sc, MTW_TX_RTS_CFG0x1344, tmp);
2680}
2681
2682void
2683mtw_set_txpreamble(struct mtw_softc *sc)
2684{
2685 uint32_t tmp;
2686
2687 mtw_read(sc, MTW_AUTO_RSP_CFG0x1404, &tmp);
2688 if (sc->sc_ic.ic_flags & IEEE80211_F_SHPREAMBLE0x00040000)
2689 tmp |= MTW_CCK_SHORT_EN(1 << 4);
2690 else
2691 tmp &= ~MTW_CCK_SHORT_EN(1 << 4);
2692 mtw_write(sc, MTW_AUTO_RSP_CFG0x1404, tmp);
2693}
2694
2695void
2696mtw_set_basicrates(struct mtw_softc *sc)
2697{
2698 struct ieee80211com *ic = &sc->sc_ic;
2699
2700 /* set basic rates mask */
2701 if (ic->ic_curmode == IEEE80211_MODE_11B)
2702 mtw_write(sc, MTW_LEGACY_BASIC_RATE0x1408, 0x003);
2703 else if (ic->ic_curmode == IEEE80211_MODE_11A)
2704 mtw_write(sc, MTW_LEGACY_BASIC_RATE0x1408, 0x150);
2705 else /* 11g */
2706 mtw_write(sc, MTW_LEGACY_BASIC_RATE0x1408, 0x17f);
2707}
2708
2709void
2710mtw_set_leds(struct mtw_softc *sc, uint16_t which)
2711{
2712 struct mtw_mcu_cmd_8 cmd;
2713
2714 cmd.func = htole32(0x1)((__uint32_t)(0x1));
2715 cmd.val = htole32(which)((__uint32_t)(which));
2716 mtw_mcu_cmd(sc, 16, &cmd, sizeof(struct mtw_mcu_cmd_8));
2717}
2718
2719void
2720mtw_set_bssid(struct mtw_softc *sc, const uint8_t *bssid)
2721{
2722 mtw_write(sc, MTW_MAC_BSSID_DW00x1010,
2723 bssid[0] | bssid[1] << 8 | bssid[2] << 16 | bssid[3] << 24);
2724 mtw_write(sc, MTW_MAC_BSSID_DW10x1014,
2725 bssid[4] | bssid[5] << 8);
2726}
2727
2728void
2729mtw_set_macaddr(struct mtw_softc *sc, const uint8_t *addr)
2730{
2731 mtw_write(sc, MTW_MAC_ADDR_DW00x1008,
2732 addr[0] | addr[1] << 8 | addr[2] << 16 | addr[3] << 24);
2733 mtw_write(sc, MTW_MAC_ADDR_DW10x100c,
2734 addr[4] | addr[5] << 8 | 0xff << 16);
2735}
2736
2737#if NBPFILTER1 > 0
2738int8_t
2739mtw_rssi2dbm(struct mtw_softc *sc, uint8_t rssi, uint8_t rxchain)
2740{
2741 struct ieee80211com *ic = &sc->sc_ic;
2742 struct ieee80211_channel *c = ic->ic_ibss_chan;
2743 int delta;
2744
2745 if (IEEE80211_IS_CHAN_5GHZ(c)(((c)->ic_flags & 0x0100) != 0)) {
2746 u_int chan = ieee80211_chan2ieee(ic, c);
2747 delta = sc->rssi_5ghz[rxchain];
2748
2749 /* determine channel group */
2750 if (chan <= 64)
2751 delta -= sc->lna[1];
2752 else if (chan <= 128)
2753 delta -= sc->lna[2];
2754 else
2755 delta -= sc->lna[3];
2756 } else
2757 delta = sc->rssi_2ghz[rxchain] - sc->lna[0];
2758
2759 return -12 - delta - rssi;
2760}
2761#endif
2762
2763int
2764mt7601_bbp_init(struct mtw_softc *sc)
2765{
2766 uint8_t bbp;
2767 int i, error, ntries;
2768
2769 /* wait for BBP to wake up */
2770 for (ntries = 0; ntries < 20; ntries++) {
2771 if ((error = mtw_bbp_read(sc, 0, &bbp)) != 0)
2772 return error;
2773 if (bbp != 0 && bbp != 0xff)
2774 break;
2775 }
2776
2777 if (ntries == 20)
2778 return ETIMEDOUT60;
2779
2780 mtw_bbp_read(sc, 3, &bbp);
2781 mtw_bbp_write(sc, 3, 0);
2782 mtw_bbp_read(sc, 105, &bbp);
2783 mtw_bbp_write(sc, 105, 0);
2784
2785 /* initialize BBP registers to default values */
2786 for (i = 0; i < nitems(mt7601_def_bbp)(sizeof((mt7601_def_bbp)) / sizeof((mt7601_def_bbp)[0])); i++) {
2787 if ((error = mtw_bbp_write(sc, mt7601_def_bbp[i].reg,
2788 mt7601_def_bbp[i].val)) != 0)
2789 return error;
2790 }
2791
2792 sc->sc_bw_calibrated = 0;
2793
2794 return 0;
2795}
2796
2797int
2798mt7601_rf_init(struct mtw_softc *sc)
2799{
2800 int i, error;
2801
2802 /* RF bank 0 */
2803 for (i = 0; i < nitems(mt7601_rf_bank0)(sizeof((mt7601_rf_bank0)) / sizeof((mt7601_rf_bank0)[0])); i++) {
2804 error = mtw_rf_write(sc, 0, mt7601_rf_bank0[i].reg,
2805 mt7601_rf_bank0[i].val);
2806 if (error != 0)
2807 return error;
2808 }
2809 /* RF bank 4 */
2810 for (i = 0; i < nitems(mt7601_rf_bank4)(sizeof((mt7601_rf_bank4)) / sizeof((mt7601_rf_bank4)[0])); i++) {
2811 error = mtw_rf_write(sc, 4, mt7601_rf_bank4[i].reg,
2812 mt7601_rf_bank4[i].val);
2813 if (error != 0)
2814 return error;
2815 }
2816 /* RF bank 5 */
2817 for (i = 0; i < nitems(mt7601_rf_bank5)(sizeof((mt7601_rf_bank5)) / sizeof((mt7601_rf_bank5)[0])); i++) {
2818 error = mtw_rf_write(sc, 5, mt7601_rf_bank5[i].reg,
2819 mt7601_rf_bank5[i].val);
2820 if (error != 0)
2821 return error;
2822 }
2823 return 0;
2824}
2825
2826int
2827mt7601_rf_setup(struct mtw_softc *sc)
2828{
2829 uint32_t tmp;
2830 uint8_t rf;
2831 int error;
2832
2833 if (sc->sc_rf_calibrated)
2834 return 0;
2835
2836 /* init RF registers */
2837 if ((error = mt7601_rf_init(sc)) != 0)
2838 return error;
2839
2840 /* init frequency offset */
2841 mtw_rf_write(sc, 0, 12, sc->rf_freq_offset);
2842 mtw_rf_read(sc, 0, 12, &rf);
2843
2844 /* read temperature */
2845 mt7601_rf_temperature(sc, &rf);
2846 sc->bbp_temp = rf;
2847 DPRINTF(("BBP temp 0x%x ", rf));
2848
2849 mtw_rf_read(sc, 0, 7, &rf);
2850 if ((error = mtw_mcu_calibrate(sc, 0x1, 0)) != 0)
2851 return error;
2852 usbd_delay_ms(sc->sc_udev, 100);
2853 mtw_rf_read(sc, 0, 7, &rf);
2854
2855 /* Calibrate VCO RF 0/4 */
2856 mtw_rf_write(sc, 0, 4, 0x0a);
2857 mtw_rf_write(sc, 0, 4, 0x20);
2858 mtw_rf_read(sc, 0, 4, &rf);
2859 mtw_rf_write(sc, 0, 4, rf | 0x80);
2860
2861 if ((error = mtw_mcu_calibrate(sc, 0x9, 0)) != 0)
2862 return error;
2863 if ((error = mt7601_rxdc_cal(sc)) != 0)
2864 return error;
2865 if ((error = mtw_mcu_calibrate(sc, 0x6, 1)) != 0)
2866 return error;
2867 if ((error = mtw_mcu_calibrate(sc, 0x6, 0)) != 0)
2868 return error;
2869 if ((error = mtw_mcu_calibrate(sc, 0x4, 0)) != 0)
2870 return error;
2871 if ((error = mtw_mcu_calibrate(sc, 0x5, 0)) != 0)
2872 return error;
2873
2874 mtw_read(sc, MTW_LDO_CFG00x006c, &tmp);
2875 tmp &= ~(1 << 4);
2876 tmp |= (1 << 2);
2877 mtw_write(sc, MTW_LDO_CFG00x006c, tmp);
2878
2879 if ((error = mtw_mcu_calibrate(sc, 0x8, 0)) != 0)
2880 return error;
2881 if ((error = mt7601_rxdc_cal(sc)) != 0)
2882 return error;
2883
2884 sc->sc_rf_calibrated = 1;
2885 return 0;
2886}
2887
2888int
2889mt7601_rf_temperature(struct mtw_softc *sc, int8_t *val)
2890{
2891 uint32_t rfb, rfs;
2892 uint8_t bbp;
2893 int ntries;
2894
2895 mtw_read(sc, MTW_RF_BYPASS00x0504, &rfb);
2896 mtw_read(sc, MTW_RF_SETTING00x050C, &rfs);
2897 mtw_write(sc, MTW_RF_BYPASS00x0504, 0);
2898 mtw_write(sc, MTW_RF_SETTING00x050C, 0x10);
2899 mtw_write(sc, MTW_RF_BYPASS00x0504, 0x10);
2900
2901 mtw_bbp_read(sc, 47, &bbp);
2902 bbp &= ~0x7f;
2903 bbp |= 0x10;
2904 mtw_bbp_write(sc, 47, bbp);
2905
2906 mtw_bbp_write(sc, 22, 0x40);
2907
2908 for (ntries = 0; ntries < 10; ntries++) {
2909 mtw_bbp_read(sc, 47, &bbp);
2910 if ((bbp & 0x10) == 0)
2911 break;
2912 }
2913 if (ntries == 10)
2914 return ETIMEDOUT60;
2915
2916 mt7601_r49_read(sc, MT7601_R47_TEMP(1 << 2), val);
2917
2918 mtw_bbp_write(sc, 22, 0);
2919
2920 mtw_bbp_read(sc, 21, &bbp);
2921 bbp |= 0x02;
2922 mtw_bbp_write(sc, 21, bbp);
2923 bbp &= ~0x02;
2924 mtw_bbp_write(sc, 21, bbp);
2925
2926 mtw_write(sc, MTW_RF_BYPASS00x0504, 0);
2927 mtw_write(sc, MTW_RF_SETTING00x050C, rfs);
2928 mtw_write(sc, MTW_RF_BYPASS00x0504, rfb);
2929 return 0;
2930}
2931
2932int
2933mt7601_r49_read(struct mtw_softc *sc, uint8_t flag, int8_t *val)
2934{
2935 uint8_t bbp;
2936
2937 mtw_bbp_read(sc, 47, &bbp);
2938 bbp = 0x90;
2939 mtw_bbp_write(sc, 47, bbp);
2940 bbp &= ~0x0f;
2941 bbp |= flag;
2942 mtw_bbp_write(sc, 47, bbp);
2943 return mtw_bbp_read(sc, 49, val);
2944}
2945
2946int
2947mt7601_rxdc_cal(struct mtw_softc *sc)
2948{
2949 uint32_t tmp;
2950 uint8_t bbp;
2951 int ntries;
2952
2953 mtw_read(sc, MTW_MAC_SYS_CTRL0x1004, &tmp);
2954 mtw_write(sc, MTW_MAC_SYS_CTRL0x1004, MTW_MAC_RX_EN(1 << 3));
2955 mtw_bbp_write(sc, 158, 0x8d);
2956 mtw_bbp_write(sc, 159, 0xfc);
2957 mtw_bbp_write(sc, 158, 0x8c);
2958 mtw_bbp_write(sc, 159, 0x4c);
2959
2960 for (ntries = 0; ntries < 20; ntries++) {
2961 DELAY(300)(*delay_func)(300);
2962 mtw_bbp_write(sc, 158, 0x8c);
2963 mtw_bbp_read(sc, 159, &bbp);
2964 if (bbp == 0x0c)
2965 break;
2966 }
2967
2968 if (ntries == 20)
2969 return ETIMEDOUT60;
2970
2971 mtw_write(sc, MTW_MAC_SYS_CTRL0x1004, 0);
2972 mtw_bbp_write(sc, 158, 0x8d);
2973 mtw_bbp_write(sc, 159, 0xe0);
2974 mtw_write(sc, MTW_MAC_SYS_CTRL0x1004, tmp);
2975 return 0;
2976}
2977
2978int
2979mtw_wlan_enable(struct mtw_softc *sc, int enable)
2980{
2981 uint32_t tmp;
2982 int error = 0;
2983
2984 if (enable) {
2985 mtw_read(sc, MTW_WLAN_CTRL0x0080, &tmp);
2986 if (sc->asic_ver == 0x7612)
2987 tmp &= ~0xfffff000;
2988
2989 tmp &= ~MTW_WLAN_CLK_EN(1U << 1);
2990 tmp |= MTW_WLAN_EN(1U << 0);
2991 mtw_write(sc, MTW_WLAN_CTRL0x0080, tmp);
2992 usbd_delay_ms(sc->sc_udev, 2);
2993
2994 tmp |= MTW_WLAN_CLK_EN(1U << 1);
2995 if (sc->asic_ver == 0x7612) {
2996 tmp |= (MTW_WLAN_RESET(1U << 3) | MTW_WLAN_RESET_RF(1U << 2));
2997 }
2998 mtw_write(sc, MTW_WLAN_CTRL0x0080, tmp);
2999 usbd_delay_ms(sc->sc_udev, 2);
3000
3001 mtw_read(sc, MTW_OSC_CTRL0x0038, &tmp);
3002 tmp |= MTW_OSC_EN(1U << 31);
3003 mtw_write(sc, MTW_OSC_CTRL0x0038, tmp);
3004 tmp |= MTW_OSC_CAL_REQ(1U << 30);
3005 mtw_write(sc, MTW_OSC_CTRL0x0038, tmp);
3006 } else {
3007 mtw_read(sc, MTW_WLAN_CTRL0x0080, &tmp);
3008 tmp &= ~(MTW_WLAN_CLK_EN(1U << 1) | MTW_WLAN_EN(1U << 0));
3009 mtw_write(sc, MTW_WLAN_CTRL0x0080, tmp);
3010
3011 mtw_read(sc, MTW_OSC_CTRL0x0038, &tmp);
3012 tmp &= ~MTW_OSC_EN(1U << 31);
3013 mtw_write(sc, MTW_OSC_CTRL0x0038, tmp);
3014 }
3015 return error;
3016}
3017
3018int
3019mtw_txrx_enable(struct mtw_softc *sc)
3020{
3021 uint32_t tmp;
3022 int error, ntries;
3023
3024 mtw_write(sc, MTW_MAC_SYS_CTRL0x1004, MTW_MAC_TX_EN(1 << 2));
3025 for (ntries = 0; ntries < 200; ntries++) {
3026 if ((error = mtw_read(sc, MTW_WPDMA_GLO_CFG0x0208, &tmp)) != 0)
3027 return error;
3028 if ((tmp & (MTW_TX_DMA_BUSY(1 << 1) | MTW_RX_DMA_BUSY(1 << 3))) == 0)
3029 break;
3030 DELAY(1000)(*delay_func)(1000);
3031 }
3032 if (ntries == 200)
3033 return ETIMEDOUT60;
3034
3035 DELAY(50)(*delay_func)(50);
3036
3037 tmp |= MTW_RX_DMA_EN(1 << 2) | MTW_TX_DMA_EN(1 << 0) | MTW_TX_WB_DDONE(1 << 6);
3038 mtw_write(sc, MTW_WPDMA_GLO_CFG0x0208, tmp);
3039
3040 /* enable Rx bulk aggregation (set timeout and limit) */
3041 tmp = MTW_USB_TX_EN(1U << 23) | MTW_USB_RX_EN(1U << 22) | MTW_USB_RX_AGG_EN(1U << 21) |
3042 MTW_USB_RX_AGG_TO(128)((128) & 0xff) | MTW_USB_RX_AGG_LMT(2)((2) << 8);
3043 mtw_write(sc, MTW_USB_DMA_CFG0x0238, tmp);
3044
3045 /* set Rx filter */
3046 tmp = MTW_DROP_CRC_ERR(1 << 0) | MTW_DROP_PHY_ERR(1 << 1);
3047 if (sc->sc_ic.ic_opmode != IEEE80211_M_MONITOR) {
3048 tmp |= MTW_DROP_UC_NOME(1 << 2) | MTW_DROP_DUPL(1 << 7) |
3049 MTW_DROP_CTS(1 << 11) | MTW_DROP_BA(1 << 14) | MTW_DROP_ACK(1 << 10) |
3050 MTW_DROP_VER_ERR(1 << 4) | MTW_DROP_CTRL_RSV(1 << 16) |
3051 MTW_DROP_CFACK(1 << 8) | MTW_DROP_CFEND(1 << 9);
3052 if (sc->sc_ic.ic_opmode == IEEE80211_M_STA)
3053 tmp |= MTW_DROP_RTS(1 << 12) | MTW_DROP_PSPOLL(1 << 13);
3054 }
3055 mtw_write(sc, MTW_RX_FILTR_CFG0x1400, tmp);
3056
3057 mtw_write(sc, MTW_MAC_SYS_CTRL0x1004,
3058 MTW_MAC_RX_EN(1 << 3) | MTW_MAC_TX_EN(1 << 2));
3059 return 0;
3060}
3061
3062int
3063mtw_init(struct ifnet *ifp)
3064{
3065 struct mtw_softc *sc = ifp->if_softc;
3066 struct ieee80211com *ic = &sc->sc_ic;
3067 uint32_t tmp;
3068 int i, error, ridx, ntries, qid;
3069
3070 if (usbd_is_dying(sc->sc_udev))
3071 return ENXIO6;
3072
3073 /* init Tx rings (4 EDCAs, 1 HCCA, 1 MGMT) */
3074 for (qid = 0; qid < MTW_TXQ_COUNT6; qid++) {
3075 if ((error = mtw_alloc_tx_ring(sc, qid)) != 0)
3076 goto fail;
3077 }
3078
3079 /* init Rx ring */
3080 if ((error = mtw_alloc_rx_ring(sc, 0)) != 0)
3081 goto fail;
3082
3083 /* init MCU Tx ring */
3084 if ((error = mtw_alloc_mcu_ring(sc)) != 0)
3085 goto fail;
3086
3087 /* init host command ring */
3088 sc->cmdq.cur = sc->cmdq.next = sc->cmdq.queued = 0;
3089
3090 for (ntries = 0; ntries < 100; ntries++) {
3091 if ((error = mtw_read(sc, MTW_WPDMA_GLO_CFG0x0208, &tmp)) != 0)
3092 goto fail;
3093 if ((tmp & (MTW_TX_DMA_BUSY(1 << 1) | MTW_RX_DMA_BUSY(1 << 3))) == 0)
3094 break;
3095 DELAY(1000)(*delay_func)(1000);
3096 }
3097 if (ntries == 100) {
3098 printf("%s: timeout waiting for DMA engine\n",
3099 sc->sc_dev.dv_xname);
3100 error = ETIMEDOUT60;
3101 goto fail;
3102 }
3103 tmp &= 0xff0;
3104 tmp |= MTW_TX_WB_DDONE(1 << 6);
3105 mtw_write(sc, MTW_WPDMA_GLO_CFG0x0208, tmp);
3106
3107 /* reset MAC and baseband */
3108 mtw_write(sc, MTW_MAC_SYS_CTRL0x1004, MTW_BBP_HRST(1 << 1) | MTW_MAC_SRST(1 << 0));
3109 mtw_write(sc, MTW_USB_DMA_CFG0x0238, 0);
3110 mtw_write(sc, MTW_MAC_SYS_CTRL0x1004, 0);
3111
3112 /* init MAC values */
3113 if (sc->mac_ver == 0x7601) {
3114 for (i = 0; i < nitems(mt7601_def_mac)(sizeof((mt7601_def_mac)) / sizeof((mt7601_def_mac)[0])); i++)
3115 mtw_write(sc, mt7601_def_mac[i].reg,
3116 mt7601_def_mac[i].val);
3117 }
3118
3119 /* wait while MAC is busy */
3120 for (ntries = 0; ntries < 100; ntries++) {
3121 if ((error = mtw_read(sc, MTW_MAC_STATUS_REG0x1200, &tmp)) != 0)
3122 goto fail;
3123 if (!(tmp & (MTW_RX_STATUS_BUSY(1 << 1) | MTW_TX_STATUS_BUSY(1 << 0))))
3124 break;
3125 DELAY(1000)(*delay_func)(1000);
3126 }
3127 if (ntries == 100) {
3128 error = ETIMEDOUT60;
3129 goto fail;
3130 }
3131
3132 /* set MAC address */
3133 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))
;
3134 mtw_set_macaddr(sc, ic->ic_myaddr);
3135
3136 /* clear WCID attribute table */
3137 mtw_set_region_4(sc, MTW_WCID_ATTR(0)(0xa800 + (0) * 4), 1, 8 * 32);
3138
3139 mtw_write(sc, 0x1648, 0x00830083);
3140 mtw_read(sc, MTW_FCE_L2_STUFF0x080c, &tmp);
3141 tmp &= ~MTW_L2S_WR_MPDU_LEN_EN(1 << 4);
3142 mtw_write(sc, MTW_FCE_L2_STUFF0x080c, tmp);
3143
3144 /* RTS config */
3145 mtw_set_txrts(sc);
3146
3147 /* clear Host to MCU mailbox */
3148 mtw_write(sc, MTW_BBP_CSR0x101c, 0);
3149 mtw_write(sc, MTW_H2M_MAILBOX0x7010, 0);
3150
3151 /* clear RX WCID search table */
3152 mtw_set_region_4(sc, MTW_WCID_ENTRY(0)(0x1800 + (0) * 8), 0xffffffff, 512);
3153
3154 /* abort TSF synchronization */
3155 mtw_abort_tsf_sync(sc);
3156
3157 mtw_read(sc, MTW_US_CYC_CNT0x02a4, &tmp);
3158 tmp = (tmp & ~0xff);
3159 if (sc->mac_ver == 0x7601)
3160 tmp |= 0x1e;
3161 mtw_write(sc, MTW_US_CYC_CNT0x02a4, tmp);
3162
3163 /* clear shared key table */
3164 mtw_set_region_4(sc, MTW_SKEY(0, 0)((0 & 8) ? (0xb400 + (4 * ((0) & 7) + (0)) * 32) : (0xac00
+ (4 * (0) + (0)) * 32))
, 0, 8 * 32);
3165
3166 /* clear IV/EIV table */
3167 mtw_set_region_4(sc, MTW_IVEIV(0)(0xa000 + (0) * 8), 0, 8 * 32);
3168
3169 /* clear shared key mode */
3170 mtw_write(sc, MTW_SKEY_MODE_0_70xb000, 0);
3171 mtw_write(sc, MTW_SKEY_MODE_8_150xb004, 0);
3172
3173 /* txop truncation */
3174 mtw_write(sc, MTW_TXOP_CTRL_CFG0x1340, 0x0000583f);
3175
3176 /* init Tx power for all Tx rates */
3177 for (ridx = 0; ridx < 5; ridx++) {
3178 if (sc->txpow20mhz[ridx] == 0xffffffff)
3179 continue;
3180 mtw_write(sc, MTW_TX_PWR_CFG(ridx)(0x1314 + (ridx) * 4), sc->txpow20mhz[ridx]);
3181 }
3182 mtw_write(sc, MTW_TX_PWR_CFG70x13d4, 0);
3183 mtw_write(sc, MTW_TX_PWR_CFG90x13dc, 0);
3184
3185 mtw_read(sc, MTW_CMB_CTRL0x0020, &tmp);
3186 tmp &= ~(1 << 18 | 1 << 14);
3187 mtw_write(sc, MTW_CMB_CTRL0x0020, tmp);
3188
3189 /* clear USB DMA */
3190 mtw_write(sc, MTW_USB_DMA_CFG0x0238, MTW_USB_TX_EN(1U << 23) | MTW_USB_RX_EN(1U << 22) |
3191 MTW_USB_RX_AGG_EN(1U << 21) | MTW_USB_TX_CLEAR(1U << 19) | MTW_USB_TXOP_HALT(1U << 20) |
3192 MTW_USB_RX_WL_DROP(1U << 25));
3193 usbd_delay_ms(sc->sc_udev, 50);
3194 mtw_read(sc, MTW_USB_DMA_CFG0x0238, &tmp);
3195 tmp &= ~(MTW_USB_TX_CLEAR(1U << 19) | MTW_USB_TXOP_HALT(1U << 20) |
3196 MTW_USB_RX_WL_DROP(1U << 25));
3197 mtw_write(sc, MTW_USB_DMA_CFG0x0238, tmp);
3198
3199 /* enable radio */
3200 mtw_mcu_radio(sc, 0x31, 0);
3201
3202 /* init RF registers */
3203 if (sc->mac_ver == 0x7601)
3204 mt7601_rf_init(sc);
3205
3206 /* init baseband registers */
3207 if (sc->mac_ver == 0x7601)
3208 error = mt7601_bbp_init(sc);
3209
3210 if (error != 0) {
3211 printf("%s: could not initialize BBP\n", sc->sc_dev.dv_xname);
3212 goto fail;
3213 }
3214
3215 /* setup and calibrate RF */
3216 if (sc->mac_ver == 0x7601)
3217 error = mt7601_rf_setup(sc);
3218
3219 if (error != 0) {
3220 printf("%s: could not initialize RF\n", sc->sc_dev.dv_xname);
3221 goto fail;
3222 }
3223
3224 /* select default channel */
3225 ic->ic_bss->ni_chan = ic->ic_ibss_chan;
3226 mtw_set_chan(sc, ic->ic_ibss_chan);
3227
3228 for (i = 0; i < MTW_RX_RING_COUNT1; i++) {
3229 struct mtw_rx_data *data = &sc->rxq[MTW_RXQ_WLAN0].data[i];
3230
3231 usbd_setup_xfer(data->xfer, sc->rxq[MTW_RXQ_WLAN0].pipeh,
3232 data, data->buf,
3233 MTW_MAX_RXSZ4096, USBD_SHORT_XFER_OK0x04 | USBD_NO_COPY0x01,
3234 USBD_NO_TIMEOUT0, mtw_rxeof);
3235 error = usbd_transfer(data->xfer);
3236 if (error != 0 && error != USBD_IN_PROGRESS)
3237 goto fail;
3238 }
3239
3240 if ((error = mtw_txrx_enable(sc)) != 0)
3241 goto fail;
3242
3243 /* init LEDs */
3244 mtw_set_leds(sc, MTW_LED_MODE_ON0);
3245
3246 ifp->if_flags |= IFF_RUNNING0x40;
3247 ifq_clr_oactive(&ifp->if_snd);
3248
3249 if (ic->ic_flags & IEEE80211_F_WEPON0x00000100) {
3250 /* install WEP keys */
3251 for (i = 0; i < IEEE80211_WEP_NKID4; i++) {
3252 if (ic->ic_nw_keys[i].k_cipher != IEEE80211_CIPHER_NONE)
3253 (void)mtw_set_key(ic, NULL((void *)0), &ic->ic_nw_keys[i]);
3254 }
3255 }
3256
3257 if (ic->ic_opmode == IEEE80211_M_MONITOR)
3258 ieee80211_new_state(ic, IEEE80211_S_RUN, -1)(((ic)->ic_newstate)((ic), (IEEE80211_S_RUN), (-1)));
3259 else
3260 ieee80211_new_state(ic, IEEE80211_S_SCAN, -1)(((ic)->ic_newstate)((ic), (IEEE80211_S_SCAN), (-1)));
3261
3262 if (error != 0)
3263fail: mtw_stop(ifp, 1);
3264 return error;
3265}
3266
3267void
3268mtw_stop(struct ifnet *ifp, int disable)
3269{
3270 struct mtw_softc *sc = ifp->if_softc;
3271 struct ieee80211com *ic = &sc->sc_ic;
3272 uint32_t tmp;
3273 int s, ntries, error, qid;
3274
3275 if (ifp->if_flags & IFF_RUNNING0x40)
3276 mtw_set_leds(sc, MTW_LED_MODE_ON0);
3277
3278 sc->sc_tx_timer = 0;
3279 ifp->if_timer = 0;
3280 ifp->if_flags &= ~IFF_RUNNING0x40;
3281 ifq_clr_oactive(&ifp->if_snd);
3282
3283 timeout_del(&sc->scan_to);
3284 timeout_del(&sc->calib_to);
3285
3286 s = splusb()splraise(0x2);
3287 ieee80211_new_state(ic, IEEE80211_S_INIT, -1)(((ic)->ic_newstate)((ic), (IEEE80211_S_INIT), (-1)));
3288 /* wait for all queued asynchronous commands to complete */
3289 usb_wait_task(sc->sc_udev, &sc->sc_task);
3290 splx(s)spllower(s);
3291
3292 /* Disable Tx/Rx DMA. */
3293 mtw_read(sc, MTW_WPDMA_GLO_CFG0x0208, &tmp);
3294 tmp &= ~(MTW_RX_DMA_EN(1 << 2) | MTW_TX_DMA_EN(1 << 0));
3295 mtw_write(sc, MTW_WPDMA_GLO_CFG0x0208, tmp);
3296 mtw_usb_dma_write(sc, 0);
3297
3298 for (ntries = 0; ntries < 100; ntries++) {
3299 if (mtw_read(sc, MTW_WPDMA_GLO_CFG0x0208, &tmp) != 0)
3300 break;
3301 if ((tmp & (MTW_TX_DMA_BUSY(1 << 1) | MTW_RX_DMA_BUSY(1 << 3))) == 0)
3302 break;
3303 DELAY(10)(*delay_func)(10);
3304 }
3305 if (ntries == 100) {
3306 printf("%s: timeout waiting for DMA engine\n",
3307 sc->sc_dev.dv_xname);
3308 }
3309
3310 /* stop MAC Tx/Rx */
3311 mtw_read(sc, MTW_MAC_SYS_CTRL0x1004, &tmp);
3312 tmp &= ~(MTW_MAC_RX_EN(1 << 3) | MTW_MAC_TX_EN(1 << 2));
3313 mtw_write(sc, MTW_MAC_SYS_CTRL0x1004, tmp);
3314
3315 /* disable RTS retry */
3316 mtw_read(sc, MTW_TX_RTS_CFG0x1344, &tmp);
3317 tmp &= ~0xff;
3318 mtw_write(sc, MTW_TX_RTS_CFG0x1344, tmp);
3319
3320 /* US_CYC_CFG */
3321 mtw_read(sc, MTW_US_CYC_CNT0x02a4, &tmp);
3322 tmp = (tmp & ~0xff);
3323 mtw_write(sc, MTW_US_CYC_CNT0x02a4, tmp);
3324
3325 /* stop PBF */
3326 mtw_read(sc, MTW_PBF_CFG0x0404, &tmp);
3327 tmp &= ~0x3;
3328 mtw_write(sc, MTW_PBF_CFG0x0404, tmp);
3329
3330 /* wait for pending Tx to complete */
3331 for (ntries = 0; ntries < 100; ntries++) {
3332 if ((error = mtw_read(sc, MTW_TXRXQ_PCNT0x0438, &tmp)) != 0)
3333 break;
3334 if ((tmp & MTW_TX2Q_PCNT_MASK0x00ff0000) == 0)
3335 break;
3336 }
3337 DELAY(1000)(*delay_func)(1000);
3338
3339 /* delete keys */
3340 for (qid = 0; qid < 4; qid++) {
3341 mtw_read(sc, MTW_SKEY_MODE_0_70xb000, &tmp);
3342 tmp &= ~(0xf << qid * 4);
3343 mtw_write(sc, MTW_SKEY_MODE_0_70xb000, tmp);
3344 }
3345
3346 if (disable) {
3347 /* disable radio */
3348 error = mtw_mcu_radio(sc, 0x30, 0x1);
3349 usbd_delay_ms(sc->sc_udev, 10);
3350 }
3351
3352 /* free Tx and Rx rings */
3353 sc->qfullmsk = 0;
3354 mtw_free_mcu_ring(sc);
3355 for (qid = 0; qid < MTW_TXQ_COUNT6; qid++)
3356 mtw_free_tx_ring(sc, qid);
3357 mtw_free_rx_ring(sc, 0);
3358}