1 /* $NetBSD: if_otus.c,v 1.45 2020/06/11 09:51:37 martin Exp $ */
2 /* $OpenBSD: if_otus.c,v 1.18 2010/08/27 17:08:00 jsg Exp $ */
3
4 /*-
5 * Copyright (c) 2009 Damien Bergamini <damien.bergamini@free.fr>
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 * Driver for Atheros AR9001U chipset.
22 * http://www.atheros.com/pt/bulletins/AR9001USBBulletin.pdf
23 */
24
25 #include <sys/cdefs.h>
26 __KERNEL_RCSID(0, "$NetBSD: if_otus.c,v 1.45 2020/06/11 09:51:37 martin Exp $");
27
28 #ifdef _KERNEL_OPT
29 #include "opt_usb.h"
30 #endif
31
32 #include <sys/param.h>
33 #include <sys/sockio.h>
34 #include <sys/mbuf.h>
35 #include <sys/kernel.h>
36 #include <sys/kmem.h>
37 #include <sys/kthread.h>
38 #include <sys/systm.h>
39 #include <sys/callout.h>
40 #include <sys/device.h>
41 #include <sys/proc.h>
42 #include <sys/bus.h>
43 #include <sys/endian.h>
44 #include <sys/intr.h>
45
46 #include <net/bpf.h>
47 #include <net/if.h>
48 #include <net/if_arp.h>
49 #include <net/if_dl.h>
50 #include <net/if_ether.h>
51 #include <net/if_media.h>
52 #include <net/if_types.h>
53
54 #include <netinet/in.h>
55 #include <netinet/in_systm.h>
56 #include <netinet/in_var.h>
57 #include <netinet/ip.h>
58
59 #include <net80211/ieee80211_var.h>
60 #include <net80211/ieee80211_amrr.h>
61 #include <net80211/ieee80211_radiotap.h>
62
63 #include <dev/firmload.h>
64
65 #include <dev/usb/usb.h>
66 #include <dev/usb/usbdi.h>
67 #include <dev/usb/usbdi_util.h>
68 #include <dev/usb/usbdivar.h>
69 #include <dev/usb/usbdevs.h>
70
71 #include <dev/usb/if_otusreg.h>
72 #include <dev/usb/if_otusvar.h>
73
74 #ifdef OTUS_DEBUG
75
76 #define DBG_INIT __BIT(0)
77 #define DBG_FN __BIT(1)
78 #define DBG_TX __BIT(2)
79 #define DBG_RX __BIT(3)
80 #define DBG_STM __BIT(4)
81 #define DBG_CHAN __BIT(5)
82 #define DBG_REG __BIT(6)
83 #define DBG_CMD __BIT(7)
84 #define DBG_ALL 0xffffffffU
85 #define DBG_NO_SC (struct otus_softc *)NULL
86
87 unsigned int otus_debug = 0;
88 #define DPRINTFN(n, s, ...) do { \
89 if (otus_debug & (n)) { \
90 if ((s) != NULL) \
91 printf("%s: ", device_xname((s)->sc_dev)); \
92 else \
93 printf("otus0: "); \
94 printf("%s: ", __func__); \
95 printf(__VA_ARGS__); \
96 } \
97 } while (0)
98
99 #else /* ! OTUS_DEBUG */
100
101 #define DPRINTFN(n, ...) \
102 do { } while (0)
103
104 #endif /* OTUS_DEBUG */
105
106 Static int otus_match(device_t, cfdata_t, void *);
107 Static void otus_attach(device_t, device_t, void *);
108 Static int otus_detach(device_t, int);
109 Static int otus_activate(device_t, devact_t);
110 Static void otus_attachhook(device_t);
111 Static void otus_get_chanlist(struct otus_softc *);
112 Static int otus_load_firmware(struct otus_softc *, const char *,
113 uint32_t);
114 Static int otus_open_pipes(struct otus_softc *);
115 Static void otus_close_pipes(struct otus_softc *);
116 Static int otus_alloc_tx_cmd(struct otus_softc *);
117 Static void otus_free_tx_cmd(struct otus_softc *);
118 Static int otus_alloc_tx_data_list(struct otus_softc *);
119 Static void otus_free_tx_data_list(struct otus_softc *);
120 Static int otus_alloc_rx_data_list(struct otus_softc *);
121 Static void otus_free_rx_data_list(struct otus_softc *);
122 Static void otus_next_scan(void *);
123 Static void otus_task(void *);
124 Static void otus_do_async(struct otus_softc *,
125 void (*)(struct otus_softc *, void *), void *, int);
126 Static int otus_newstate(struct ieee80211com *, enum ieee80211_state,
127 int);
128 Static void otus_newstate_cb(struct otus_softc *, void *);
129 Static int otus_cmd(struct otus_softc *, uint8_t, const void *, int,
130 void *);
131 Static void otus_write(struct otus_softc *, uint32_t, uint32_t);
132 Static int otus_write_barrier(struct otus_softc *);
133 Static struct ieee80211_node *otus_node_alloc(struct ieee80211_node_table *);
134 Static int otus_media_change(struct ifnet *);
135 Static int otus_read_eeprom(struct otus_softc *);
136 Static void otus_newassoc(struct ieee80211_node *, int);
137 Static void otus_intr(struct usbd_xfer *, void *, usbd_status);
138 Static void otus_cmd_rxeof(struct otus_softc *, uint8_t *, int);
139 Static void otus_sub_rxeof(struct otus_softc *, uint8_t *, int);
140 Static void otus_rxeof(struct usbd_xfer *, void *, usbd_status);
141 Static void otus_txeof(struct usbd_xfer *, void *, usbd_status);
142 Static int otus_tx(struct otus_softc *, struct mbuf *,
143 struct ieee80211_node *, struct otus_tx_data *);
144 Static void otus_start(struct ifnet *);
145 Static void otus_watchdog(struct ifnet *);
146 Static int otus_ioctl(struct ifnet *, u_long, void *);
147 Static int otus_set_multi(struct otus_softc *);
148 #ifdef HAVE_EDCA
149 Static void otus_updateedca(struct ieee80211com *);
150 Static void otus_updateedca_cb(struct otus_softc *, void *);
151 #endif
152 Static void otus_updateedca_cb_locked(struct otus_softc *);
153 Static void otus_updateslot(struct ifnet *);
154 Static void otus_updateslot_cb(struct otus_softc *, void *);
155 Static void otus_updateslot_cb_locked(struct otus_softc *);
156 Static int otus_init_mac(struct otus_softc *);
157 Static uint32_t otus_phy_get_def(struct otus_softc *, uint32_t);
158 Static int otus_set_board_values(struct otus_softc *,
159 struct ieee80211_channel *);
160 Static int otus_program_phy(struct otus_softc *,
161 struct ieee80211_channel *);
162 Static int otus_set_rf_bank4(struct otus_softc *,
163 struct ieee80211_channel *);
164 Static void otus_get_delta_slope(uint32_t, uint32_t *, uint32_t *);
165 Static int otus_set_chan(struct otus_softc *, struct ieee80211_channel *,
166 int);
167 #ifdef notyet
168 Static int otus_set_key(struct ieee80211com *, struct ieee80211_node *,
169 struct ieee80211_key *);
170 Static void otus_set_key_cb(struct otus_softc *, void *);
171 Static void otus_delete_key(struct ieee80211com *, struct ieee80211_node *,
172 struct ieee80211_key *);
173 Static void otus_delete_key_cb(struct otus_softc *, void *);
174 #endif /* notyet */
175 Static void otus_calib_to(void *);
176 Static int otus_set_bssid(struct otus_softc *, const uint8_t *);
177 Static int otus_set_macaddr(struct otus_softc *, const uint8_t *);
178 #ifdef notyet
179 Static void otus_led_newstate_type1(struct otus_softc *);
180 Static void otus_led_newstate_type2(struct otus_softc *);
181 #endif /* notyet */
182 Static void otus_led_newstate_type3(struct otus_softc *);
183 Static int otus_init(struct ifnet *);
184 Static void otus_stop(struct ifnet *);
185 Static void otus_wait_async(struct otus_softc *);
186
187 /* List of supported channels. */
188 static const uint8_t ar_chans[] = {
189 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
190 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124,
191 128, 132, 136, 140, 149, 153, 157, 161, 165, 34, 38, 42, 46
192 };
193
194 /*
195 * This data is automatically generated from the "otus.ini" file.
196 * It is stored in a different way though, to reduce kernel's .rodata
197 * section overhead (5.1KB instead of 8.5KB).
198 */
199
200 /* NB: apply AR_PHY(). */
201 static const uint16_t ar5416_phy_regs[] = {
202 0x000, 0x001, 0x002, 0x003, 0x004, 0x005, 0x006, 0x007, 0x008,
203 0x009, 0x00a, 0x00b, 0x00c, 0x00d, 0x00e, 0x00f, 0x010, 0x011,
204 0x012, 0x013, 0x014, 0x015, 0x016, 0x017, 0x018, 0x01a, 0x01b,
205 0x040, 0x041, 0x042, 0x043, 0x045, 0x046, 0x047, 0x048, 0x049,
206 0x04a, 0x04b, 0x04d, 0x04e, 0x04f, 0x051, 0x052, 0x053, 0x055,
207 0x056, 0x058, 0x059, 0x05c, 0x05d, 0x05e, 0x05f, 0x060, 0x061,
208 0x062, 0x063, 0x064, 0x065, 0x066, 0x067, 0x068, 0x069, 0x06a,
209 0x06b, 0x06c, 0x06d, 0x070, 0x071, 0x072, 0x073, 0x074, 0x075,
210 0x076, 0x077, 0x078, 0x079, 0x07a, 0x07b, 0x07c, 0x07f, 0x080,
211 0x081, 0x082, 0x083, 0x084, 0x085, 0x086, 0x087, 0x088, 0x089,
212 0x08a, 0x08b, 0x08c, 0x08d, 0x08e, 0x08f, 0x090, 0x091, 0x092,
213 0x093, 0x094, 0x095, 0x096, 0x097, 0x098, 0x099, 0x09a, 0x09b,
214 0x09c, 0x09d, 0x09e, 0x09f, 0x0a0, 0x0a1, 0x0a2, 0x0a3, 0x0a4,
215 0x0a5, 0x0a6, 0x0a7, 0x0a8, 0x0a9, 0x0aa, 0x0ab, 0x0ac, 0x0ad,
216 0x0ae, 0x0af, 0x0b0, 0x0b1, 0x0b2, 0x0b3, 0x0b4, 0x0b5, 0x0b6,
217 0x0b7, 0x0b8, 0x0b9, 0x0ba, 0x0bb, 0x0bc, 0x0bd, 0x0be, 0x0bf,
218 0x0c0, 0x0c1, 0x0c2, 0x0c3, 0x0c4, 0x0c5, 0x0c6, 0x0c7, 0x0c8,
219 0x0c9, 0x0ca, 0x0cb, 0x0cc, 0x0cd, 0x0ce, 0x0cf, 0x0d0, 0x0d1,
220 0x0d2, 0x0d3, 0x0d4, 0x0d5, 0x0d6, 0x0d7, 0x0d8, 0x0d9, 0x0da,
221 0x0db, 0x0dc, 0x0dd, 0x0de, 0x0df, 0x0e0, 0x0e1, 0x0e2, 0x0e3,
222 0x0e4, 0x0e5, 0x0e6, 0x0e7, 0x0e8, 0x0e9, 0x0ea, 0x0eb, 0x0ec,
223 0x0ed, 0x0ee, 0x0ef, 0x0f0, 0x0f1, 0x0f2, 0x0f3, 0x0f4, 0x0f5,
224 0x0f6, 0x0f7, 0x0f8, 0x0f9, 0x0fa, 0x0fb, 0x0fc, 0x0fd, 0x0fe,
225 0x0ff, 0x100, 0x103, 0x104, 0x105, 0x106, 0x107, 0x108, 0x109,
226 0x10a, 0x10b, 0x10c, 0x10d, 0x10e, 0x10f, 0x13c, 0x13d, 0x13e,
227 0x13f, 0x280, 0x281, 0x282, 0x283, 0x284, 0x285, 0x286, 0x287,
228 0x288, 0x289, 0x28a, 0x28b, 0x28c, 0x28d, 0x28e, 0x28f, 0x290,
229 0x291, 0x292, 0x293, 0x294, 0x295, 0x296, 0x297, 0x298, 0x299,
230 0x29a, 0x29b, 0x29d, 0x29e, 0x29f, 0x2c0, 0x2c1, 0x2c2, 0x2c3,
231 0x2c4, 0x2c5, 0x2c6, 0x2c7, 0x2c8, 0x2c9, 0x2ca, 0x2cb, 0x2cc,
232 0x2cd, 0x2ce, 0x2cf, 0x2d0, 0x2d1, 0x2d2, 0x2d3, 0x2d4, 0x2d5,
233 0x2d6, 0x2e2, 0x2e3, 0x2e4, 0x2e5, 0x2e6, 0x2e7, 0x2e8, 0x2e9,
234 0x2ea, 0x2eb, 0x2ec, 0x2ed, 0x2ee, 0x2ef, 0x2f0, 0x2f1, 0x2f2,
235 0x2f3, 0x2f4, 0x2f5, 0x2f6, 0x2f7, 0x2f8, 0x412, 0x448, 0x458,
236 0x683, 0x69b, 0x812, 0x848, 0x858, 0xa83, 0xa9b, 0xc19, 0xc57,
237 0xc5a, 0xc6f, 0xe9c, 0xed7, 0xed8, 0xed9, 0xeda, 0xedb, 0xedc,
238 0xedd, 0xede, 0xedf, 0xee0, 0xee1
239 };
240
241 static const uint32_t ar5416_phy_vals_5ghz_20mhz[] = {
242 0x00000007, 0x00000300, 0x00000000, 0xad848e19, 0x7d14e000,
243 0x9c0a9f6b, 0x00000090, 0x00000000, 0x02020200, 0x00000e0e,
244 0x0a020001, 0x0000a000, 0x00000000, 0x00000e0e, 0x00000007,
245 0x00200400, 0x206a002e, 0x1372161e, 0x001a6a65, 0x1284233c,
246 0x6c48b4e4, 0x00000859, 0x7ec80d2e, 0x31395c5e, 0x0004dd10,
247 0x409a4190, 0x050cb081, 0x00000000, 0x00000000, 0x00000000,
248 0x00000000, 0x000007d0, 0x00000118, 0x10000fff, 0x0510081c,
249 0xd0058a15, 0x00000001, 0x00000004, 0x3f3f3f3f, 0x3f3f3f3f,
250 0x0000007f, 0xdfb81020, 0x9280b212, 0x00020028, 0x5d50e188,
251 0x00081fff, 0x00009b40, 0x00001120, 0x190fb515, 0x00000000,
252 0x00000001, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
253 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
254 0x00000000, 0x00000007, 0x001fff00, 0x006f00c4, 0x03051000,
255 0x00000820, 0x038919be, 0x06336f77, 0x60f6532c, 0x08f186c8,
256 0x00046384, 0x00000000, 0x00000000, 0x00000000, 0x00000200,
257 0x64646464, 0x3c787878, 0x000000aa, 0x00000000, 0x00001042,
258 0x00000000, 0x00000040, 0x00000080, 0x000001a1, 0x000001e1,
259 0x00000021, 0x00000061, 0x00000168, 0x000001a8, 0x000001e8,
260 0x00000028, 0x00000068, 0x00000189, 0x000001c9, 0x00000009,
261 0x00000049, 0x00000089, 0x00000170, 0x000001b0, 0x000001f0,
262 0x00000030, 0x00000070, 0x00000191, 0x000001d1, 0x00000011,
263 0x00000051, 0x00000091, 0x000001b8, 0x000001f8, 0x00000038,
264 0x00000078, 0x00000199, 0x000001d9, 0x00000019, 0x00000059,
265 0x00000099, 0x000000d9, 0x000000f9, 0x000000f9, 0x000000f9,
266 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9,
267 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9,
268 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9,
269 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9,
270 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, 0x00000000,
271 0x00000001, 0x00000002, 0x00000003, 0x00000004, 0x00000005,
272 0x00000008, 0x00000009, 0x0000000a, 0x0000000b, 0x0000000c,
273 0x0000000d, 0x00000010, 0x00000011, 0x00000012, 0x00000013,
274 0x00000014, 0x00000015, 0x00000018, 0x00000019, 0x0000001a,
275 0x0000001b, 0x0000001c, 0x0000001d, 0x00000020, 0x00000021,
276 0x00000022, 0x00000023, 0x00000024, 0x00000025, 0x00000028,
277 0x00000029, 0x0000002a, 0x0000002b, 0x0000002c, 0x0000002d,
278 0x00000030, 0x00000031, 0x00000032, 0x00000033, 0x00000034,
279 0x00000035, 0x00000035, 0x00000035, 0x00000035, 0x00000035,
280 0x00000035, 0x00000035, 0x00000035, 0x00000035, 0x00000035,
281 0x00000035, 0x00000035, 0x00000035, 0x00000035, 0x00000035,
282 0x00000035, 0x00000035, 0x00000035, 0x00000035, 0x00000035,
283 0x00000035, 0x00000010, 0x0000001a, 0x00000000, 0x00000000,
284 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
285 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
286 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
287 0x00000000, 0x00000008, 0x00000440, 0xd6be4788, 0x012e8160,
288 0x40806333, 0x00106c10, 0x009c4060, 0x1883800a, 0x018830c6,
289 0x00000400, 0x000009b5, 0x00000000, 0x00000108, 0x3f3f3f3f,
290 0x3f3f3f3f, 0x13c889af, 0x38490a20, 0x00007bb6, 0x0fff3ffc,
291 0x00000001, 0x0000a000, 0x00000000, 0x0cc75380, 0x0f0f0f01,
292 0xdfa91f01, 0x00418a11, 0x00000000, 0x09249126, 0x0a1a9caa,
293 0x1ce739ce, 0x051701ce, 0x18010000, 0x30032602, 0x48073e06,
294 0x560b4c0a, 0x641a600f, 0x7a4f6e1b, 0x8c5b7e5a, 0x9d0f96cf,
295 0xb51fa69f, 0xcb3fbd07, 0x0000d7bf, 0x00000000, 0x00000000,
296 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
297 0x3fffffff, 0x3fffffff, 0x3fffffff, 0x0003ffff, 0x79a8aa1f,
298 0x08000000, 0x3f3f3f3f, 0x3f3f3f3f, 0x1ce739ce, 0x000001ce,
299 0x00000007, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
300 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
301 0x00000000, 0x00000000, 0x3f3f3f3f, 0x3f3f3f3f, 0x3f3f3f3f,
302 0x00000000, 0x1ce739ce, 0x000000c0, 0x00180a65, 0x0510001c,
303 0x00009b40, 0x012e8160, 0x09249126, 0x00180a65, 0x0510001c,
304 0x00009b40, 0x012e8160, 0x09249126, 0x0001c600, 0x004b6a8e,
305 0x000003ce, 0x00181400, 0x00820820, 0x066c420f, 0x0f282207,
306 0x17601685, 0x1f801104, 0x37a00c03, 0x3fc40883, 0x57c00803,
307 0x5fd80682, 0x7fe00482, 0x7f3c7bba, 0xf3307ff0
308 };
309
310 #ifdef notyet
311 static const uint32_t ar5416_phy_vals_5ghz_40mhz[] = {
312 0x00000007, 0x000003c4, 0x00000000, 0xad848e19, 0x7d14e000,
313 0x9c0a9f6b, 0x00000090, 0x00000000, 0x02020200, 0x00000e0e,
314 0x0a020001, 0x0000a000, 0x00000000, 0x00000e0e, 0x00000007,
315 0x00200400, 0x206a002e, 0x13721c1e, 0x001a6a65, 0x1284233c,
316 0x6c48b4e4, 0x00000859, 0x7ec80d2e, 0x31395c5e, 0x0004dd10,
317 0x409a4190, 0x050cb081, 0x00000000, 0x00000000, 0x00000000,
318 0x00000000, 0x000007d0, 0x00000230, 0x10000fff, 0x0510081c,
319 0xd0058a15, 0x00000001, 0x00000004, 0x3f3f3f3f, 0x3f3f3f3f,
320 0x0000007f, 0xdfb81020, 0x9280b212, 0x00020028, 0x5d50e188,
321 0x00081fff, 0x00009b40, 0x00001120, 0x190fb515, 0x00000000,
322 0x00000001, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
323 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
324 0x00000000, 0x00000007, 0x001fff00, 0x006f00c4, 0x03051000,
325 0x00000820, 0x038919be, 0x06336f77, 0x60f6532c, 0x08f186c8,
326 0x00046384, 0x00000000, 0x00000000, 0x00000000, 0x00000200,
327 0x64646464, 0x3c787878, 0x000000aa, 0x00000000, 0x00001042,
328 0x00000000, 0x00000040, 0x00000080, 0x000001a1, 0x000001e1,
329 0x00000021, 0x00000061, 0x00000168, 0x000001a8, 0x000001e8,
330 0x00000028, 0x00000068, 0x00000189, 0x000001c9, 0x00000009,
331 0x00000049, 0x00000089, 0x00000170, 0x000001b0, 0x000001f0,
332 0x00000030, 0x00000070, 0x00000191, 0x000001d1, 0x00000011,
333 0x00000051, 0x00000091, 0x000001b8, 0x000001f8, 0x00000038,
334 0x00000078, 0x00000199, 0x000001d9, 0x00000019, 0x00000059,
335 0x00000099, 0x000000d9, 0x000000f9, 0x000000f9, 0x000000f9,
336 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9,
337 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9,
338 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9,
339 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9,
340 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, 0x00000000,
341 0x00000001, 0x00000002, 0x00000003, 0x00000004, 0x00000005,
342 0x00000008, 0x00000009, 0x0000000a, 0x0000000b, 0x0000000c,
343 0x0000000d, 0x00000010, 0x00000011, 0x00000012, 0x00000013,
344 0x00000014, 0x00000015, 0x00000018, 0x00000019, 0x0000001a,
345 0x0000001b, 0x0000001c, 0x0000001d, 0x00000020, 0x00000021,
346 0x00000022, 0x00000023, 0x00000024, 0x00000025, 0x00000028,
347 0x00000029, 0x0000002a, 0x0000002b, 0x0000002c, 0x0000002d,
348 0x00000030, 0x00000031, 0x00000032, 0x00000033, 0x00000034,
349 0x00000035, 0x00000035, 0x00000035, 0x00000035, 0x00000035,
350 0x00000035, 0x00000035, 0x00000035, 0x00000035, 0x00000035,
351 0x00000035, 0x00000035, 0x00000035, 0x00000035, 0x00000035,
352 0x00000035, 0x00000035, 0x00000035, 0x00000035, 0x00000035,
353 0x00000035, 0x00000010, 0x0000001a, 0x00000000, 0x00000000,
354 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
355 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
356 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
357 0x00000000, 0x00000008, 0x00000440, 0xd6be4788, 0x012e8160,
358 0x40806333, 0x00106c10, 0x009c4060, 0x1883800a, 0x018830c6,
359 0x00000400, 0x000009b5, 0x00000000, 0x00000210, 0x3f3f3f3f,
360 0x3f3f3f3f, 0x13c889af, 0x38490a20, 0x00007bb6, 0x0fff3ffc,
361 0x00000001, 0x0000a000, 0x00000000, 0x0cc75380, 0x0f0f0f01,
362 0xdfa91f01, 0x00418a11, 0x00000000, 0x09249126, 0x0a1a9caa,
363 0x1ce739ce, 0x051701ce, 0x18010000, 0x30032602, 0x48073e06,
364 0x560b4c0a, 0x641a600f, 0x7a4f6e1b, 0x8c5b7e5a, 0x9d0f96cf,
365 0xb51fa69f, 0xcb3fbcbf, 0x0000d7bf, 0x00000000, 0x00000000,
366 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
367 0x3fffffff, 0x3fffffff, 0x3fffffff, 0x0003ffff, 0x79a8aa1f,
368 0x08000000, 0x3f3f3f3f, 0x3f3f3f3f, 0x1ce739ce, 0x000001ce,
369 0x00000007, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
370 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
371 0x00000000, 0x00000000, 0x3f3f3f3f, 0x3f3f3f3f, 0x3f3f3f3f,
372 0x00000000, 0x1ce739ce, 0x000000c0, 0x00180a65, 0x0510001c,
373 0x00009b40, 0x012e8160, 0x09249126, 0x00180a65, 0x0510001c,
374 0x00009b40, 0x012e8160, 0x09249126, 0x0001c600, 0x004b6a8e,
375 0x000003ce, 0x00181400, 0x00820820, 0x066c420f, 0x0f282207,
376 0x17601685, 0x1f801104, 0x37a00c03, 0x3fc40883, 0x57c00803,
377 0x5fd80682, 0x7fe00482, 0x7f3c7bba, 0xf3307ff0
378 };
379 #endif
380
381 #ifdef notyet
382 static const uint32_t ar5416_phy_vals_2ghz_40mhz[] = {
383 0x00000007, 0x000003c4, 0x00000000, 0xad848e19, 0x7d14e000,
384 0x9c0a9f6b, 0x00000090, 0x00000000, 0x02020200, 0x00000e0e,
385 0x0a020001, 0x0000a000, 0x00000000, 0x00000e0e, 0x00000007,
386 0x00200400, 0x206a002e, 0x13721c24, 0x00197a68, 0x1284233c,
387 0x6c48b0e4, 0x00000859, 0x7ec80d2e, 0x31395c5e, 0x0004dd20,
388 0x409a4190, 0x050cb081, 0x00000000, 0x00000000, 0x00000000,
389 0x00000000, 0x00000898, 0x00000268, 0x10000fff, 0x0510001c,
390 0xd0058a15, 0x00000001, 0x00000004, 0x3f3f3f3f, 0x3f3f3f3f,
391 0x0000007f, 0xdfb81020, 0x9280b212, 0x00020028, 0x5d50e188,
392 0x00081fff, 0x00009b40, 0x00001120, 0x190fb515, 0x00000000,
393 0x00000001, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
394 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
395 0x00000000, 0x00000007, 0x001fff00, 0x006f00c4, 0x03051000,
396 0x00000820, 0x038919be, 0x06336f77, 0x60f6532c, 0x08f186c8,
397 0x00046384, 0x00000000, 0x00000000, 0x00000000, 0x00000200,
398 0x64646464, 0x3c787878, 0x000000aa, 0x00000000, 0x00001042,
399 0x00000000, 0x00000040, 0x00000080, 0x00000141, 0x00000181,
400 0x000001c1, 0x00000001, 0x00000041, 0x000001a8, 0x000001e8,
401 0x00000028, 0x00000068, 0x000000a8, 0x00000169, 0x000001a9,
402 0x000001e9, 0x00000029, 0x00000069, 0x00000190, 0x000001d0,
403 0x00000010, 0x00000050, 0x00000090, 0x00000151, 0x00000191,
404 0x000001d1, 0x00000011, 0x00000051, 0x00000198, 0x000001d8,
405 0x00000018, 0x00000058, 0x00000098, 0x00000159, 0x00000199,
406 0x000001d9, 0x00000019, 0x00000059, 0x00000099, 0x000000d9,
407 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9,
408 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9,
409 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9,
410 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9,
411 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, 0x00000000,
412 0x00000001, 0x00000002, 0x00000003, 0x00000004, 0x00000005,
413 0x00000008, 0x00000009, 0x0000000a, 0x0000000b, 0x0000000c,
414 0x0000000d, 0x00000010, 0x00000011, 0x00000012, 0x00000013,
415 0x00000014, 0x00000015, 0x00000018, 0x00000019, 0x0000001a,
416 0x0000001b, 0x0000001c, 0x0000001d, 0x00000020, 0x00000021,
417 0x00000022, 0x00000023, 0x00000024, 0x00000025, 0x00000028,
418 0x00000029, 0x0000002a, 0x0000002b, 0x0000002c, 0x0000002d,
419 0x00000030, 0x00000031, 0x00000032, 0x00000033, 0x00000034,
420 0x00000035, 0x00000035, 0x00000035, 0x00000035, 0x00000035,
421 0x00000035, 0x00000035, 0x00000035, 0x00000035, 0x00000035,
422 0x00000035, 0x00000035, 0x00000035, 0x00000035, 0x00000035,
423 0x00000035, 0x00000035, 0x00000035, 0x00000035, 0x00000035,
424 0x00000035, 0x00000010, 0x0000001a, 0x00000000, 0x00000000,
425 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
426 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
427 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
428 0x00000000, 0x0000000e, 0x00000440, 0xd03e4788, 0x012a8160,
429 0x40806333, 0x00106c10, 0x009c4060, 0x1883800a, 0x018830c6,
430 0x00000400, 0x000009b5, 0x00000000, 0x00000210, 0x3f3f3f3f,
431 0x3f3f3f3f, 0x13c889af, 0x38490a20, 0x00007bb6, 0x0fff3ffc,
432 0x00000001, 0x0000a000, 0x00000000, 0x0cc75380, 0x0f0f0f01,
433 0xdfa91f01, 0x00418a11, 0x00000000, 0x09249126, 0x0a1a7caa,
434 0x1ce739ce, 0x051701ce, 0x18010000, 0x2e032402, 0x4a0a3c06,
435 0x621a540b, 0x764f6c1b, 0x845b7a5a, 0x950f8ccf, 0xa5cf9b4f,
436 0xbddfaf1f, 0xd1ffc93f, 0x00000000, 0x00000000, 0x00000000,
437 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
438 0x3fffffff, 0x3fffffff, 0x3fffffff, 0x0003ffff, 0x79a8aa1f,
439 0x08000000, 0x3f3f3f3f, 0x3f3f3f3f, 0x1ce739ce, 0x000001ce,
440 0x00000007, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
441 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
442 0x00000000, 0x00000000, 0x3f3f3f3f, 0x3f3f3f3f, 0x3f3f3f3f,
443 0x00000000, 0x1ce739ce, 0x000000c0, 0x00180a68, 0x0510001c,
444 0x00009b40, 0x012a8160, 0x09249126, 0x00180a68, 0x0510001c,
445 0x00009b40, 0x012a8160, 0x09249126, 0x0001c600, 0x004b6a8e,
446 0x000003ce, 0x00181400, 0x00820820, 0x066c420f, 0x0f282207,
447 0x17601685, 0x1f801104, 0x37a00c03, 0x3fc40883, 0x57c00803,
448 0x5fd80682, 0x7fe00482, 0x7f3c7bba, 0xf3307ff0
449 };
450 #endif
451
452 static const uint32_t ar5416_phy_vals_2ghz_20mhz[] = {
453 0x00000007, 0x00000300, 0x00000000, 0xad848e19, 0x7d14e000,
454 0x9c0a9f6b, 0x00000090, 0x00000000, 0x02020200, 0x00000e0e,
455 0x0a020001, 0x0000a000, 0x00000000, 0x00000e0e, 0x00000007,
456 0x00200400, 0x206a002e, 0x137216a4, 0x00197a68, 0x1284233c,
457 0x6c48b0e4, 0x00000859, 0x7ec80d2e, 0x31395c5e, 0x0004dd20,
458 0x409a4190, 0x050cb081, 0x00000000, 0x00000000, 0x00000000,
459 0x00000000, 0x00000898, 0x00000134, 0x10000fff, 0x0510001c,
460 0xd0058a15, 0x00000001, 0x00000004, 0x3f3f3f3f, 0x3f3f3f3f,
461 0x0000007f, 0xdfb81020, 0x9280b212, 0x00020028, 0x5d50e188,
462 0x00081fff, 0x00009b40, 0x00001120, 0x190fb515, 0x00000000,
463 0x00000001, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
464 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
465 0x00000000, 0x00000007, 0x001fff00, 0x006f00c4, 0x03051000,
466 0x00000820, 0x038919be, 0x06336f77, 0x60f6532c, 0x08f186c8,
467 0x00046384, 0x00000000, 0x00000000, 0x00000000, 0x00000200,
468 0x64646464, 0x3c787878, 0x000000aa, 0x00000000, 0x00001042,
469 0x00000000, 0x00000040, 0x00000080, 0x00000141, 0x00000181,
470 0x000001c1, 0x00000001, 0x00000041, 0x000001a8, 0x000001e8,
471 0x00000028, 0x00000068, 0x000000a8, 0x00000169, 0x000001a9,
472 0x000001e9, 0x00000029, 0x00000069, 0x00000190, 0x000001d0,
473 0x00000010, 0x00000050, 0x00000090, 0x00000151, 0x00000191,
474 0x000001d1, 0x00000011, 0x00000051, 0x00000198, 0x000001d8,
475 0x00000018, 0x00000058, 0x00000098, 0x00000159, 0x00000199,
476 0x000001d9, 0x00000019, 0x00000059, 0x00000099, 0x000000d9,
477 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9,
478 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9,
479 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9,
480 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9,
481 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, 0x00000000,
482 0x00000001, 0x00000002, 0x00000003, 0x00000004, 0x00000005,
483 0x00000008, 0x00000009, 0x0000000a, 0x0000000b, 0x0000000c,
484 0x0000000d, 0x00000010, 0x00000011, 0x00000012, 0x00000013,
485 0x00000014, 0x00000015, 0x00000018, 0x00000019, 0x0000001a,
486 0x0000001b, 0x0000001c, 0x0000001d, 0x00000020, 0x00000021,
487 0x00000022, 0x00000023, 0x00000024, 0x00000025, 0x00000028,
488 0x00000029, 0x0000002a, 0x0000002b, 0x0000002c, 0x0000002d,
489 0x00000030, 0x00000031, 0x00000032, 0x00000033, 0x00000034,
490 0x00000035, 0x00000035, 0x00000035, 0x00000035, 0x00000035,
491 0x00000035, 0x00000035, 0x00000035, 0x00000035, 0x00000035,
492 0x00000035, 0x00000035, 0x00000035, 0x00000035, 0x00000035,
493 0x00000035, 0x00000035, 0x00000035, 0x00000035, 0x00000035,
494 0x00000035, 0x00000010, 0x0000001a, 0x00000000, 0x00000000,
495 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
496 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
497 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
498 0x00000000, 0x0000000e, 0x00000440, 0xd03e4788, 0x012a8160,
499 0x40806333, 0x00106c10, 0x009c4060, 0x1883800a, 0x018830c6,
500 0x00000400, 0x000009b5, 0x00000000, 0x00000108, 0x3f3f3f3f,
501 0x3f3f3f3f, 0x13c889af, 0x38490a20, 0x00007bb6, 0x0fff3ffc,
502 0x00000001, 0x0000a000, 0x00000000, 0x0cc75380, 0x0f0f0f01,
503 0xdfa91f01, 0x00418a11, 0x00000000, 0x09249126, 0x0a1a7caa,
504 0x1ce739ce, 0x051701ce, 0x18010000, 0x2e032402, 0x4a0a3c06,
505 0x621a540b, 0x764f6c1b, 0x845b7a5a, 0x950f8ccf, 0xa5cf9b4f,
506 0xbddfaf1f, 0xd1ffc93f, 0x00000000, 0x00000000, 0x00000000,
507 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
508 0x3fffffff, 0x3fffffff, 0x3fffffff, 0x0003ffff, 0x79a8aa1f,
509 0x08000000, 0x3f3f3f3f, 0x3f3f3f3f, 0x1ce739ce, 0x000001ce,
510 0x00000007, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
511 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
512 0x00000000, 0x00000000, 0x3f3f3f3f, 0x3f3f3f3f, 0x3f3f3f3f,
513 0x00000000, 0x1ce739ce, 0x000000c0, 0x00180a68, 0x0510001c,
514 0x00009b40, 0x012a8160, 0x09249126, 0x00180a68, 0x0510001c,
515 0x00009b40, 0x012a8160, 0x09249126, 0x0001c600, 0x004b6a8e,
516 0x000003ce, 0x00181400, 0x00820820, 0x066c420f, 0x0f282207,
517 0x17601685, 0x1f801104, 0x37a00c03, 0x3fc40883, 0x57c00803,
518 0x5fd80682, 0x7fe00482, 0x7f3c7bba, 0xf3307ff0
519 };
520
521 /* NB: apply AR_PHY(). */
522 static const uint8_t ar5416_banks_regs[] = {
523 0x2c, 0x38, 0x2c, 0x3b, 0x2c, 0x38, 0x3c, 0x2c, 0x3a, 0x2c, 0x39,
524 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c,
525 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c,
526 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c,
527 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c,
528 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x38, 0x2c, 0x2c,
529 0x2c, 0x3c
530 };
531
532 static const uint32_t ar5416_banks_vals_5ghz[] = {
533 0x1e5795e5, 0x02008020, 0x02108421, 0x00000008, 0x0e73ff17,
534 0x00000420, 0x01400018, 0x000001a1, 0x00000001, 0x00000013,
535 0x00000002, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
536 0x00000000, 0x00004000, 0x00006c00, 0x00002c00, 0x00004800,
537 0x00004000, 0x00006000, 0x00001000, 0x00004000, 0x00007c00,
538 0x00007c00, 0x00007c00, 0x00007c00, 0x00007c00, 0x00087c00,
539 0x00007c00, 0x00005400, 0x00000c00, 0x00001800, 0x00007c00,
540 0x00006c00, 0x00006c00, 0x00007c00, 0x00002c00, 0x00003c00,
541 0x00003800, 0x00001c00, 0x00000800, 0x00000408, 0x00004c15,
542 0x00004188, 0x0000201e, 0x00010408, 0x00000801, 0x00000c08,
543 0x0000181e, 0x00001016, 0x00002800, 0x00004010, 0x0000081c,
544 0x00000115, 0x00000015, 0x00000066, 0x0000001c, 0x00000000,
545 0x00000004, 0x00000015, 0x0000001f, 0x00000000, 0x000000a0,
546 0x00000000, 0x00000040, 0x0000001c
547 };
548
549 static const uint32_t ar5416_banks_vals_2ghz[] = {
550 0x1e5795e5, 0x02008020, 0x02108421, 0x00000008, 0x0e73ff17,
551 0x00000420, 0x01c00018, 0x000001a1, 0x00000001, 0x00000013,
552 0x00000002, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
553 0x00000000, 0x00004000, 0x00006c00, 0x00002c00, 0x00004800,
554 0x00004000, 0x00006000, 0x00001000, 0x00004000, 0x00007c00,
555 0x00007c00, 0x00007c00, 0x00007c00, 0x00007c00, 0x00087c00,
556 0x00007c00, 0x00005400, 0x00000c00, 0x00001800, 0x00007c00,
557 0x00006c00, 0x00006c00, 0x00007c00, 0x00002c00, 0x00003c00,
558 0x00003800, 0x00001c00, 0x00000800, 0x00000408, 0x00004c15,
559 0x00004188, 0x0000201e, 0x00010408, 0x00000801, 0x00000c08,
560 0x0000181e, 0x00001016, 0x00002800, 0x00004010, 0x0000081c,
561 0x00000115, 0x00000015, 0x00000066, 0x0000001c, 0x00000000,
562 0x00000004, 0x00000015, 0x0000001f, 0x00000400, 0x000000a0,
563 0x00000000, 0x00000040, 0x0000001c
564 };
565
566 static const struct usb_devno otus_devs[] = {
567 { USB_VENDOR_ACCTON, USB_PRODUCT_ACCTON_WN7512 },
568 { USB_VENDOR_ATHEROS2, USB_PRODUCT_ATHEROS2_3CRUSBN275 },
569 { USB_VENDOR_ATHEROS2, USB_PRODUCT_ATHEROS2_TG121N },
570 { USB_VENDOR_ATHEROS2, USB_PRODUCT_ATHEROS2_AR9170 },
571 { USB_VENDOR_ATHEROS2, USB_PRODUCT_ATHEROS2_WN612 },
572 { USB_VENDOR_ATHEROS2, USB_PRODUCT_ATHEROS2_WN821NV2 },
573 { USB_VENDOR_AVM, USB_PRODUCT_AVM_FRITZWLAN },
574 { USB_VENDOR_CACE, USB_PRODUCT_CACE_AIRPCAPNX },
575 { USB_VENDOR_DLINK2, USB_PRODUCT_DLINK2_DWA130D1 },
576 { USB_VENDOR_DLINK2, USB_PRODUCT_DLINK2_DWA160A1 },
577 { USB_VENDOR_DLINK2, USB_PRODUCT_DLINK2_DWA160A2 },
578 { USB_VENDOR_IODATA, USB_PRODUCT_IODATA_WNGDNUS2 },
579 { USB_VENDOR_NEC, USB_PRODUCT_NEC_WL300NUG },
580 { USB_VENDOR_NETGEAR, USB_PRODUCT_NETGEAR_WN111V2 },
581 { USB_VENDOR_NETGEAR, USB_PRODUCT_NETGEAR_WNA1000 },
582 { USB_VENDOR_NETGEAR, USB_PRODUCT_NETGEAR_WNDA3100 },
583 { USB_VENDOR_PLANEX2, USB_PRODUCT_PLANEX2_GW_US300 },
584 { USB_VENDOR_WISTRONNEWEB, USB_PRODUCT_WISTRONNEWEB_O8494 },
585 { USB_VENDOR_WISTRONNEWEB, USB_PRODUCT_WISTRONNEWEB_WNC0600 },
586 { USB_VENDOR_ZCOM, USB_PRODUCT_ZCOM_UB81 },
587 { USB_VENDOR_ZCOM, USB_PRODUCT_ZCOM_UB82 },
588 { USB_VENDOR_ZYDAS, USB_PRODUCT_ZYDAS_ZD1221 },
589 { USB_VENDOR_ZYXEL, USB_PRODUCT_ZYXEL_NWD271N }
590 };
591
592 CFATTACH_DECL_NEW(otus, sizeof(struct otus_softc), otus_match, otus_attach,
593 otus_detach, otus_activate);
594
595 Static int
otus_match(device_t parent,cfdata_t match,void * aux)596 otus_match(device_t parent, cfdata_t match, void *aux)
597 {
598 struct usb_attach_arg *uaa;
599
600 uaa = aux;
601
602 DPRINTFN(DBG_FN, DBG_NO_SC,
603 "otus_match: vendor=%#x product=%#x revision=%#x\n",
604 uaa->uaa_vendor, uaa->uaa_product, uaa->uaa_release);
605
606 return usb_lookup(otus_devs, uaa->uaa_vendor, uaa->uaa_product) != NULL ?
607 UMATCH_VENDOR_PRODUCT : UMATCH_NONE;
608 }
609
610 Static void
otus_attach(device_t parent,device_t self,void * aux)611 otus_attach(device_t parent, device_t self, void *aux)
612 {
613 struct otus_softc *sc;
614 struct usb_attach_arg *uaa;
615 char *devinfop;
616 int error;
617
618 sc = device_private(self);
619
620 DPRINTFN(DBG_FN, sc, "\n");
621
622 sc->sc_dev = self;
623 uaa = aux;
624 sc->sc_udev = uaa->uaa_device;
625
626 aprint_naive("\n");
627 aprint_normal("\n");
628
629 devinfop = usbd_devinfo_alloc(sc->sc_udev, 0);
630 aprint_normal_dev(sc->sc_dev, "%s\n", devinfop);
631 usbd_devinfo_free(devinfop);
632
633 cv_init(&sc->sc_task_cv, "otustsk");
634 cv_init(&sc->sc_cmd_cv, "otuscmd");
635 mutex_init(&sc->sc_cmd_mtx, MUTEX_DEFAULT, IPL_NONE);
636 mutex_init(&sc->sc_task_mtx, MUTEX_DEFAULT, IPL_NET);
637 mutex_init(&sc->sc_tx_mtx, MUTEX_DEFAULT, IPL_NONE);
638 mutex_init(&sc->sc_write_mtx, MUTEX_DEFAULT, IPL_NONE);
639
640 usb_init_task(&sc->sc_task, otus_task, sc, 0);
641
642 callout_init(&sc->sc_scan_to, 0);
643 callout_setfunc(&sc->sc_scan_to, otus_next_scan, sc);
644 callout_init(&sc->sc_calib_to, 0);
645 callout_setfunc(&sc->sc_calib_to, otus_calib_to, sc);
646
647 sc->sc_amrr.amrr_min_success_threshold = 1;
648 sc->sc_amrr.amrr_max_success_threshold = 10;
649
650 if (usbd_set_config_no(sc->sc_udev, 1, 0) != 0) {
651 aprint_error_dev(sc->sc_dev,
652 "could not set configuration no\n");
653 return;
654 }
655
656 /* Get the first interface handle. */
657 error = usbd_device2interface_handle(sc->sc_udev, 0, &sc->sc_iface);
658 if (error != 0) {
659 aprint_error_dev(sc->sc_dev,
660 "could not get interface handle\n");
661 return;
662 }
663
664 if ((error = otus_open_pipes(sc)) != 0) {
665 aprint_error_dev(sc->sc_dev, "could not open pipes\n");
666 return;
667 }
668
669 /*
670 * We need the firmware loaded from file system to complete the attach.
671 */
672 config_mountroot(self, otus_attachhook);
673
674 usbd_add_drv_event(USB_EVENT_DRIVER_ATTACH, sc->sc_udev, sc->sc_dev);
675 }
676
677 Static void
otus_wait_async(struct otus_softc * sc)678 otus_wait_async(struct otus_softc *sc)
679 {
680
681 DPRINTFN(DBG_FN, sc, "\n");
682
683 mutex_spin_enter(&sc->sc_task_mtx);
684 while (sc->sc_cmdq.queued > 0)
685 cv_wait(&sc->sc_task_cv, &sc->sc_task_mtx);
686 mutex_spin_exit(&sc->sc_task_mtx);
687 }
688
689 Static int
otus_detach(device_t self,int flags)690 otus_detach(device_t self, int flags)
691 {
692 struct otus_softc *sc;
693 struct ifnet *ifp;
694 int s;
695
696 sc = device_private(self);
697
698 DPRINTFN(DBG_FN, sc, "\n");
699
700 s = splusb();
701
702 sc->sc_dying = 1;
703
704 ifp = sc->sc_ic.ic_ifp;
705 if (ifp != NULL) /* Failed to attach properly */
706 otus_stop(ifp);
707
708 usb_rem_task_wait(sc->sc_udev, &sc->sc_task, USB_TASKQ_DRIVER, NULL);
709 callout_destroy(&sc->sc_scan_to);
710 callout_destroy(&sc->sc_calib_to);
711
712 if (ifp && ifp->if_flags != 0) { /* if_attach() has been called. */
713 ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE);
714 bpf_detach(ifp);
715 ieee80211_ifdetach(&sc->sc_ic);
716 if_detach(ifp);
717 }
718 otus_close_pipes(sc);
719 splx(s);
720
721 usbd_add_drv_event(USB_EVENT_DRIVER_DETACH, sc->sc_udev, sc->sc_dev);
722
723 mutex_destroy(&sc->sc_write_mtx);
724 mutex_destroy(&sc->sc_tx_mtx);
725 mutex_destroy(&sc->sc_task_mtx);
726 mutex_destroy(&sc->sc_cmd_mtx);
727 cv_destroy(&sc->sc_task_cv);
728 cv_destroy(&sc->sc_cmd_cv);
729
730 return 0;
731 }
732
733 Static int
otus_activate(device_t self,devact_t act)734 otus_activate(device_t self, devact_t act)
735 {
736 struct otus_softc *sc;
737
738 sc = device_private(self);
739
740 DPRINTFN(DBG_FN, sc, "%d\n", act);
741
742 switch (act) {
743 case DVACT_DEACTIVATE:
744 sc->sc_dying = 1;
745 if_deactivate(sc->sc_ic.ic_ifp);
746 return 0;
747 default:
748 return EOPNOTSUPP;
749 }
750 }
751
752 Static void
otus_attachhook(device_t arg)753 otus_attachhook(device_t arg)
754 {
755 struct otus_softc *sc;
756 struct ieee80211com *ic;
757 struct ifnet *ifp;
758 usb_device_request_t req;
759 uint32_t in, out;
760 int error;
761
762 sc = device_private(arg);
763
764 DPRINTFN(DBG_FN, sc, "\n");
765
766 ic = &sc->sc_ic;
767 ifp = &sc->sc_if;
768
769 error = otus_load_firmware(sc, "otus-init", AR_FW_INIT_ADDR);
770 if (error != 0) {
771 aprint_error_dev(sc->sc_dev, "could not load init firmware\n");
772 return;
773 }
774 usbd_delay_ms(sc->sc_udev, 1000);
775
776 error = otus_load_firmware(sc, "otus-main", AR_FW_MAIN_ADDR);
777 if (error != 0) {
778 aprint_error_dev(sc->sc_dev, "could not load main firmware\n");
779 return;
780 }
781
782 /* Tell device that firmware transfer is complete. */
783 req.bmRequestType = UT_WRITE_VENDOR_DEVICE;
784 req.bRequest = AR_FW_DOWNLOAD_COMPLETE;
785 USETW(req.wValue, 0);
786 USETW(req.wIndex, 0);
787 USETW(req.wLength, 0);
788 if (usbd_do_request(sc->sc_udev, &req, NULL) != 0) {
789 aprint_error_dev(sc->sc_dev,
790 "firmware initialization failed\n");
791 return;
792 }
793
794 /* Send an ECHO command to check that everything is settled. */
795 in = 0xbadc0ffe;
796 if (otus_cmd(sc, AR_CMD_ECHO, &in, sizeof(in), &out) != 0) {
797 aprint_error_dev(sc->sc_dev, "echo command failed\n");
798 return;
799 }
800 if (in != out) {
801 aprint_error_dev(sc->sc_dev,
802 "echo reply mismatch: 0x%08x!=0x%08x\n", in, out);
803 return;
804 }
805
806 /* Read entire EEPROM. */
807 if (otus_read_eeprom(sc) != 0) {
808 aprint_error_dev(sc->sc_dev, "could not read EEPROM\n");
809 return;
810 }
811
812 sc->sc_txmask = sc->sc_eeprom.baseEepHeader.txMask;
813 sc->sc_rxmask = sc->sc_eeprom.baseEepHeader.rxMask;
814 sc->sc_capflags = sc->sc_eeprom.baseEepHeader.opCapFlags;
815 IEEE80211_ADDR_COPY(ic->ic_myaddr, sc->sc_eeprom.baseEepHeader.macAddr);
816 sc->sc_led_newstate = otus_led_newstate_type3; /* XXX */
817
818 aprint_normal_dev(sc->sc_dev,
819 "MAC/BBP AR9170, RF AR%X, MIMO %dT%dR, address %s\n",
820 (sc->sc_capflags & AR5416_OPFLAGS_11A) ?
821 0x9104 : ((sc->sc_txmask == 0x5) ? 0x9102 : 0x9101),
822 (sc->sc_txmask == 0x5) ? 2 : 1, (sc->sc_rxmask == 0x5) ? 2 : 1,
823 ether_sprintf(ic->ic_myaddr));
824
825 /*
826 * Setup the 802.11 device.
827 */
828 ic->ic_ifp = ifp;
829 ic->ic_phytype = IEEE80211_T_OFDM; /* not only, but not used */
830 ic->ic_opmode = IEEE80211_M_STA; /* default to BSS mode */
831 ic->ic_state = IEEE80211_S_INIT;
832
833 /* Set device capabilities. */
834 ic->ic_caps =
835 IEEE80211_C_MONITOR | /* monitor mode supported */
836 IEEE80211_C_SHPREAMBLE | /* short preamble supported */
837 IEEE80211_C_SHSLOT | /* short slot time supported */
838 IEEE80211_C_WPA; /* 802.11i */
839
840 if (sc->sc_eeprom.baseEepHeader.opCapFlags & AR5416_OPFLAGS_11G) {
841 /* Set supported .11b and .11g rates. */
842 ic->ic_sup_rates[IEEE80211_MODE_11B] =
843 ieee80211_std_rateset_11b;
844 ic->ic_sup_rates[IEEE80211_MODE_11G] =
845 ieee80211_std_rateset_11g;
846 }
847 if (sc->sc_eeprom.baseEepHeader.opCapFlags & AR5416_OPFLAGS_11A) {
848 /* Set supported .11a rates. */
849 ic->ic_sup_rates[IEEE80211_MODE_11A] =
850 ieee80211_std_rateset_11a;
851 }
852
853 /* Build the list of supported channels. */
854 otus_get_chanlist(sc);
855
856 ifp->if_softc = sc;
857 ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
858 ifp->if_init = otus_init;
859 ifp->if_ioctl = otus_ioctl;
860 ifp->if_start = otus_start;
861 ifp->if_watchdog = otus_watchdog;
862 IFQ_SET_READY(&ifp->if_snd);
863 memcpy(ifp->if_xname, device_xname(sc->sc_dev), IFNAMSIZ);
864
865 if_attach(ifp);
866
867 ieee80211_ifattach(ic);
868
869 ic->ic_node_alloc = otus_node_alloc;
870 ic->ic_newassoc = otus_newassoc;
871 ic->ic_updateslot = otus_updateslot;
872 #ifdef HAVE_EDCA
873 ic->ic_updateedca = otus_updateedca;
874 #endif /* HAVE_EDCA */
875 #ifdef notyet
876 ic->ic_set_key = otus_set_key;
877 ic->ic_delete_key = otus_delete_key;
878 #endif /* notyet */
879
880 /* Override state transition machine. */
881 sc->sc_newstate = ic->ic_newstate;
882 ic->ic_newstate = otus_newstate;
883
884 /* XXX media locking needs revisiting */
885 mutex_init(&sc->sc_media_mtx, MUTEX_DEFAULT, IPL_SOFTUSB);
886 ieee80211_media_init_with_lock(ic,
887 otus_media_change, ieee80211_media_status, &sc->sc_media_mtx);
888
889 bpf_attach2(ifp, DLT_IEEE802_11_RADIO,
890 sizeof(struct ieee80211_frame) + IEEE80211_RADIOTAP_HDRLEN,
891 &sc->sc_drvbpf);
892
893 sc->sc_rxtap_len = sizeof(sc->sc_rxtapu);
894 sc->sc_rxtap.wr_ihdr.it_len = htole16(sc->sc_rxtap_len);
895 sc->sc_rxtap.wr_ihdr.it_present = htole32(OTUS_RX_RADIOTAP_PRESENT);
896
897 sc->sc_txtap_len = sizeof(sc->sc_txtapu);
898 sc->sc_txtap.wt_ihdr.it_len = htole16(sc->sc_txtap_len);
899 sc->sc_txtap.wt_ihdr.it_present = htole32(OTUS_TX_RADIOTAP_PRESENT);
900
901 ieee80211_announce(ic);
902 }
903
904 Static void
otus_get_chanlist(struct otus_softc * sc)905 otus_get_chanlist(struct otus_softc *sc)
906 {
907 struct ieee80211com *ic;
908 uint8_t chan;
909 int i;
910
911 #ifdef OTUS_DEBUG
912 /* XXX regulatory domain. */
913 uint16_t domain = le16toh(sc->sc_eeprom.baseEepHeader.regDmn[0]);
914
915 DPRINTFN(DBG_FN | DBG_INIT, sc, "regdomain=0x%04x\n", domain);
916 #endif
917
918 ic = &sc->sc_ic;
919 if (sc->sc_eeprom.baseEepHeader.opCapFlags & AR5416_OPFLAGS_11G) {
920 for (i = 0; i < 14; i++) {
921 chan = ar_chans[i];
922 ic->ic_channels[chan].ic_freq =
923 ieee80211_ieee2mhz(chan, IEEE80211_CHAN_2GHZ);
924 ic->ic_channels[chan].ic_flags =
925 IEEE80211_CHAN_CCK | IEEE80211_CHAN_OFDM |
926 IEEE80211_CHAN_DYN | IEEE80211_CHAN_2GHZ;
927 }
928 }
929 if (sc->sc_eeprom.baseEepHeader.opCapFlags & AR5416_OPFLAGS_11A) {
930 for (i = 14; i < __arraycount(ar_chans); i++) {
931 chan = ar_chans[i];
932 ic->ic_channels[chan].ic_freq =
933 ieee80211_ieee2mhz(chan, IEEE80211_CHAN_5GHZ);
934 ic->ic_channels[chan].ic_flags = IEEE80211_CHAN_A;
935 }
936 }
937 }
938
939 Static int
otus_load_firmware(struct otus_softc * sc,const char * name,uint32_t addr)940 otus_load_firmware(struct otus_softc *sc, const char *name, uint32_t addr)
941 {
942 usb_device_request_t req;
943 firmware_handle_t fh;
944 uint8_t *ptr;
945 uint8_t *fw;
946 size_t size;
947 int mlen, error;
948
949 DPRINTFN(DBG_FN, sc, "\n");
950
951 if ((error = firmware_open("if_otus", name, &fh)) != 0)
952 return error;
953
954 size = firmware_get_size(fh);
955 if ((fw = firmware_malloc(size)) == NULL) {
956 firmware_close(fh);
957 return ENOMEM;
958 }
959 if ((error = firmware_read(fh, 0, fw, size)) != 0)
960 firmware_free(fw, size);
961 firmware_close(fh);
962 if (error)
963 return error;
964
965 req.bmRequestType = UT_WRITE_VENDOR_DEVICE;
966 req.bRequest = AR_FW_DOWNLOAD;
967 USETW(req.wIndex, 0);
968
969 ptr = fw;
970 addr >>= 8;
971 while (size > 0) {
972 mlen = MIN(size, 4096);
973
974 USETW(req.wValue, addr);
975 USETW(req.wLength, mlen);
976 if (usbd_do_request(sc->sc_udev, &req, ptr) != 0) {
977 error = EIO;
978 break;
979 }
980 addr += mlen >> 8;
981 ptr += mlen;
982 size -= mlen;
983 }
984 free(fw, M_DEVBUF);
985 return error;
986 }
987
988 Static int
otus_open_pipes(struct otus_softc * sc)989 otus_open_pipes(struct otus_softc *sc)
990 {
991 usb_endpoint_descriptor_t *ed;
992 int i, error;
993
994 DPRINTFN(DBG_FN, sc, "\n");
995
996 error = usbd_open_pipe(sc->sc_iface, AR_EPT_BULK_RX_NO, 0,
997 &sc->sc_data_rx_pipe);
998 if (error != 0) {
999 aprint_error_dev(sc->sc_dev, "could not open Rx bulk pipe\n");
1000 goto fail;
1001 }
1002
1003 ed = usbd_get_endpoint_descriptor(sc->sc_iface, AR_EPT_INTR_RX_NO);
1004 if (ed == NULL) {
1005 aprint_error_dev(sc->sc_dev,
1006 "could not retrieve Rx intr pipe descriptor\n");
1007 goto fail;
1008 }
1009 sc->sc_ibuf_size = UGETW(ed->wMaxPacketSize);
1010 if (sc->sc_ibuf_size == 0) {
1011 aprint_error_dev(sc->sc_dev,
1012 "invalid Rx intr pipe descriptor\n");
1013 goto fail;
1014 }
1015 sc->sc_ibuf = kmem_alloc(sc->sc_ibuf_size, KM_SLEEP);
1016 error = usbd_open_pipe_intr(sc->sc_iface, AR_EPT_INTR_RX_NO,
1017 USBD_SHORT_XFER_OK, &sc->sc_cmd_rx_pipe, sc, sc->sc_ibuf,
1018 sc->sc_ibuf_size, otus_intr, USBD_DEFAULT_INTERVAL);
1019 if (error != 0) {
1020 aprint_error_dev(sc->sc_dev, "could not open Rx intr pipe\n");
1021 goto fail;
1022 }
1023
1024 error = usbd_open_pipe(sc->sc_iface, AR_EPT_BULK_TX_NO, 0,
1025 &sc->sc_data_tx_pipe);
1026 if (error != 0) {
1027 aprint_error_dev(sc->sc_dev, "could not open Tx bulk pipe\n");
1028 goto fail;
1029 }
1030
1031 error = usbd_open_pipe(sc->sc_iface, AR_EPT_INTR_TX_NO, 0,
1032 &sc->sc_cmd_tx_pipe);
1033 if (error != 0) {
1034 aprint_error_dev(sc->sc_dev, "could not open Tx intr pipe\n");
1035 goto fail;
1036 }
1037
1038 if (otus_alloc_tx_cmd(sc) != 0) {
1039 aprint_error_dev(sc->sc_dev,
1040 "could not allocate command xfer\n");
1041 goto fail;
1042 }
1043
1044 if (otus_alloc_tx_data_list(sc)) {
1045 aprint_error_dev(sc->sc_dev, "could not allocate Tx xfers\n");
1046 goto fail;
1047 }
1048
1049 if (otus_alloc_rx_data_list(sc)) {
1050 aprint_error_dev(sc->sc_dev, "could not allocate Rx xfers\n");
1051 goto fail;
1052 }
1053
1054 for (i = 0; i < OTUS_RX_DATA_LIST_COUNT; i++) {
1055 struct otus_rx_data *data = &sc->sc_rx_data[i];
1056
1057 usbd_setup_xfer(data->xfer, data, data->buf, OTUS_RXBUFSZ,
1058 USBD_SHORT_XFER_OK, USBD_NO_TIMEOUT, otus_rxeof);
1059 error = usbd_transfer(data->xfer);
1060 if (error != USBD_IN_PROGRESS && error != 0) {
1061 aprint_error_dev(sc->sc_dev,
1062 "could not queue Rx xfer\n");
1063 goto fail;
1064 }
1065 }
1066 return 0;
1067
1068 fail: otus_close_pipes(sc);
1069 return error;
1070 }
1071
1072 Static void
otus_close_pipes(struct otus_softc * sc)1073 otus_close_pipes(struct otus_softc *sc)
1074 {
1075
1076 DPRINTFN(DBG_FN, sc, "\n");
1077
1078 otus_free_tx_cmd(sc);
1079 otus_free_tx_data_list(sc);
1080 otus_free_rx_data_list(sc);
1081
1082 if (sc->sc_data_rx_pipe != NULL)
1083 usbd_close_pipe(sc->sc_data_rx_pipe);
1084 if (sc->sc_cmd_rx_pipe != NULL) {
1085 usbd_abort_pipe(sc->sc_cmd_rx_pipe);
1086 usbd_close_pipe(sc->sc_cmd_rx_pipe);
1087 }
1088 if (sc->sc_ibuf != NULL)
1089 kmem_free(sc->sc_ibuf, sc->sc_ibuf_size);
1090 if (sc->sc_data_tx_pipe != NULL)
1091 usbd_close_pipe(sc->sc_data_tx_pipe);
1092 if (sc->sc_cmd_tx_pipe != NULL)
1093 usbd_close_pipe(sc->sc_cmd_tx_pipe);
1094 }
1095
1096 Static int
otus_alloc_tx_cmd(struct otus_softc * sc)1097 otus_alloc_tx_cmd(struct otus_softc *sc)
1098 {
1099 struct otus_tx_cmd *cmd;
1100
1101 DPRINTFN(DBG_FN, sc, "\n");
1102
1103 cmd = &sc->sc_tx_cmd;
1104
1105 int error = usbd_create_xfer(sc->sc_cmd_tx_pipe, OTUS_MAX_TXCMDSZ,
1106 USBD_FORCE_SHORT_XFER, 0, &cmd->xfer);
1107 if (error)
1108 return error;
1109
1110 cmd->buf = usbd_get_buffer(cmd->xfer);
1111
1112 return 0;
1113 }
1114
1115 Static void
otus_free_tx_cmd(struct otus_softc * sc)1116 otus_free_tx_cmd(struct otus_softc *sc)
1117 {
1118
1119 DPRINTFN(DBG_FN, sc, "\n");
1120
1121 if (sc->sc_cmd_tx_pipe == NULL)
1122 return;
1123
1124 /* Make sure no transfers are pending. */
1125 usbd_abort_pipe(sc->sc_cmd_tx_pipe);
1126
1127 mutex_enter(&sc->sc_cmd_mtx);
1128 if (sc->sc_tx_cmd.xfer != NULL)
1129 usbd_destroy_xfer(sc->sc_tx_cmd.xfer);
1130 sc->sc_tx_cmd.xfer = NULL;
1131 sc->sc_tx_cmd.buf = NULL;
1132 mutex_exit(&sc->sc_cmd_mtx);
1133 }
1134
1135 Static int
otus_alloc_tx_data_list(struct otus_softc * sc)1136 otus_alloc_tx_data_list(struct otus_softc *sc)
1137 {
1138 struct otus_tx_data *data;
1139 int i, error;
1140
1141 DPRINTFN(DBG_FN, sc, "\n");
1142
1143 mutex_enter(&sc->sc_tx_mtx);
1144 error = 0;
1145 TAILQ_INIT(&sc->sc_tx_free_list);
1146 for (i = 0; i < OTUS_TX_DATA_LIST_COUNT; i++) {
1147 data = &sc->sc_tx_data[i];
1148
1149 data->sc = sc; /* Backpointer for callbacks. */
1150
1151 error = usbd_create_xfer(sc->sc_data_tx_pipe, OTUS_TXBUFSZ,
1152 USBD_FORCE_SHORT_XFER, 0, &data->xfer);
1153 if (error) {
1154 aprint_error_dev(sc->sc_dev,
1155 "could not allocate xfer\n");
1156 break;
1157 }
1158 data->buf = usbd_get_buffer(data->xfer);
1159 /* Append this Tx buffer to our free list. */
1160 TAILQ_INSERT_TAIL(&sc->sc_tx_free_list, data, next);
1161 }
1162 if (error != 0)
1163 otus_free_tx_data_list(sc);
1164 mutex_exit(&sc->sc_tx_mtx);
1165 return error;
1166 }
1167
1168 Static void
otus_free_tx_data_list(struct otus_softc * sc)1169 otus_free_tx_data_list(struct otus_softc *sc)
1170 {
1171 int i;
1172
1173 DPRINTFN(DBG_FN, sc, "\n");
1174
1175 if (sc->sc_data_tx_pipe == NULL)
1176 return;
1177
1178 /* Make sure no transfers are pending. */
1179 usbd_abort_pipe(sc->sc_data_tx_pipe);
1180
1181 for (i = 0; i < OTUS_TX_DATA_LIST_COUNT; i++) {
1182 if (sc->sc_tx_data[i].xfer != NULL)
1183 usbd_destroy_xfer(sc->sc_tx_data[i].xfer);
1184 }
1185 }
1186
1187 Static int
otus_alloc_rx_data_list(struct otus_softc * sc)1188 otus_alloc_rx_data_list(struct otus_softc *sc)
1189 {
1190 struct otus_rx_data *data;
1191 int i, error;
1192
1193 DPRINTFN(DBG_FN, sc, "\n");
1194
1195 for (i = 0; i < OTUS_RX_DATA_LIST_COUNT; i++) {
1196 data = &sc->sc_rx_data[i];
1197
1198 data->sc = sc; /* Backpointer for callbacks. */
1199
1200 error = usbd_create_xfer(sc->sc_data_rx_pipe, OTUS_RXBUFSZ,
1201 0, 0, &data->xfer);
1202
1203 if (error) {
1204 aprint_error_dev(sc->sc_dev,
1205 "could not allocate xfer\n");
1206 goto fail;
1207 }
1208 data->buf = usbd_get_buffer(data->xfer);
1209 }
1210 return 0;
1211
1212 fail: otus_free_rx_data_list(sc);
1213 return error;
1214 }
1215
1216 Static void
otus_free_rx_data_list(struct otus_softc * sc)1217 otus_free_rx_data_list(struct otus_softc *sc)
1218 {
1219 int i;
1220
1221 DPRINTFN(DBG_FN, sc, "\n");
1222
1223 if (sc->sc_data_rx_pipe == NULL)
1224 return;
1225
1226 /* Make sure no transfers are pending. */
1227 usbd_abort_pipe(sc->sc_data_rx_pipe);
1228
1229 for (i = 0; i < OTUS_RX_DATA_LIST_COUNT; i++)
1230 if (sc->sc_rx_data[i].xfer != NULL)
1231 usbd_destroy_xfer(sc->sc_rx_data[i].xfer);
1232 }
1233
1234 Static void
otus_next_scan(void * arg)1235 otus_next_scan(void *arg)
1236 {
1237 struct otus_softc *sc;
1238
1239 sc = arg;
1240
1241 DPRINTFN(DBG_FN, sc, "\n");
1242
1243 if (sc->sc_dying)
1244 return;
1245
1246 if (sc->sc_ic.ic_state == IEEE80211_S_SCAN)
1247 ieee80211_next_scan(&sc->sc_ic);
1248 }
1249
1250 Static void
otus_task(void * arg)1251 otus_task(void *arg)
1252 {
1253 struct otus_softc *sc;
1254 struct otus_host_cmd_ring *ring;
1255 struct otus_host_cmd *cmd;
1256
1257 sc = arg;
1258
1259 DPRINTFN(DBG_FN, sc, "\n");
1260
1261 /* Process host commands. */
1262 mutex_spin_enter(&sc->sc_task_mtx);
1263 ring = &sc->sc_cmdq;
1264 while (ring->next != ring->cur) {
1265 cmd = &ring->cmd[ring->next];
1266 mutex_spin_exit(&sc->sc_task_mtx);
1267
1268 /* Callback. */
1269 DPRINTFN(DBG_CMD, sc, "cb=%p queued=%d\n", cmd->cb,
1270 ring->queued);
1271 cmd->cb(sc, cmd->data);
1272
1273 mutex_spin_enter(&sc->sc_task_mtx);
1274 ring->queued--;
1275 ring->next = (ring->next + 1) % OTUS_HOST_CMD_RING_COUNT;
1276 }
1277 cv_signal(&sc->sc_task_cv);
1278 mutex_spin_exit(&sc->sc_task_mtx);
1279 }
1280
1281 Static void
otus_do_async(struct otus_softc * sc,void (* cb)(struct otus_softc *,void *),void * arg,int len)1282 otus_do_async(struct otus_softc *sc, void (*cb)(struct otus_softc *, void *),
1283 void *arg, int len)
1284 {
1285 struct otus_host_cmd_ring *ring;
1286 struct otus_host_cmd *cmd;
1287 bool sched = false;
1288
1289 DPRINTFN(DBG_FN, sc, "cb=%p\n", cb);
1290
1291 mutex_spin_enter(&sc->sc_task_mtx);
1292 ring = &sc->sc_cmdq;
1293 cmd = &ring->cmd[ring->cur];
1294 cmd->cb = cb;
1295 KASSERT(len <= sizeof(cmd->data));
1296 memcpy(cmd->data, arg, len);
1297 ring->cur = (ring->cur + 1) % OTUS_HOST_CMD_RING_COUNT;
1298
1299 /* If there is no pending command already, schedule a task. */
1300 if (++ring->queued == 1) {
1301 sched = true;
1302 }
1303 cv_signal(&sc->sc_task_cv);
1304 mutex_spin_exit(&sc->sc_task_mtx);
1305 if (sched)
1306 usb_add_task(sc->sc_udev, &sc->sc_task, USB_TASKQ_DRIVER);
1307 }
1308
1309 Static int
otus_newstate(struct ieee80211com * ic,enum ieee80211_state nstate,int arg)1310 otus_newstate(struct ieee80211com *ic, enum ieee80211_state nstate, int arg)
1311 {
1312 struct otus_softc *sc;
1313 struct otus_cmd_newstate cmd;
1314
1315 sc = ic->ic_ifp->if_softc;
1316
1317 DPRINTFN(DBG_FN | DBG_STM, sc, "nstate=%s(%d), arg=%d\n",
1318 ieee80211_state_name[nstate], nstate, arg);
1319
1320 /* Do it in a process context. */
1321 cmd.state = nstate;
1322 cmd.arg = arg;
1323 otus_do_async(sc, otus_newstate_cb, &cmd, sizeof(cmd));
1324 return 0;
1325 }
1326
1327 Static void
otus_newstate_cb(struct otus_softc * sc,void * arg)1328 otus_newstate_cb(struct otus_softc *sc, void *arg)
1329 {
1330 struct otus_cmd_newstate *cmd;
1331 struct ieee80211com *ic;
1332 struct ieee80211_node *ni;
1333 enum ieee80211_state nstate;
1334 int s;
1335
1336 cmd = arg;
1337 ic = &sc->sc_ic;
1338 ni = ic->ic_bss;
1339 nstate = cmd->state;
1340
1341 #ifdef OTUS_DEBUG
1342 enum ieee80211_state ostate = ostate = ic->ic_state;
1343 DPRINTFN(DBG_FN | DBG_STM, sc, "%s(%d)->%s(%d)\n",
1344 ieee80211_state_name[ostate], ostate,
1345 ieee80211_state_name[nstate], nstate);
1346 #endif
1347
1348 s = splnet();
1349
1350 callout_halt(&sc->sc_scan_to, NULL);
1351 callout_halt(&sc->sc_calib_to, NULL);
1352
1353 mutex_enter(&sc->sc_write_mtx);
1354
1355 switch (nstate) {
1356 case IEEE80211_S_INIT:
1357 break;
1358
1359 case IEEE80211_S_SCAN:
1360 otus_set_chan(sc, ic->ic_curchan, 0);
1361 if (!sc->sc_dying)
1362 callout_schedule(&sc->sc_scan_to, hz / 5);
1363 break;
1364
1365 case IEEE80211_S_AUTH:
1366 case IEEE80211_S_ASSOC:
1367 otus_set_chan(sc, ic->ic_curchan, 0);
1368 break;
1369
1370 case IEEE80211_S_RUN:
1371 otus_set_chan(sc, ic->ic_curchan, 1);
1372
1373 switch (ic->ic_opmode) {
1374 case IEEE80211_M_STA:
1375 otus_updateslot_cb_locked(sc);
1376 otus_set_bssid(sc, ni->ni_bssid);
1377
1378 /* Fake a join to init the Tx rate. */
1379 otus_newassoc(ni, 1);
1380
1381 /* Start calibration timer. */
1382 if (!sc->sc_dying)
1383 callout_schedule(&sc->sc_calib_to, hz);
1384 break;
1385
1386 case IEEE80211_M_IBSS:
1387 case IEEE80211_M_AHDEMO:
1388 case IEEE80211_M_HOSTAP:
1389 case IEEE80211_M_MONITOR:
1390 break;
1391 }
1392 break;
1393 }
1394 (void)sc->sc_newstate(ic, nstate, cmd->arg);
1395 sc->sc_led_newstate(sc);
1396 mutex_exit(&sc->sc_write_mtx);
1397
1398 splx(s);
1399 }
1400
1401 Static int
otus_cmd(struct otus_softc * sc,uint8_t code,const void * idata,int ilen,void * odata)1402 otus_cmd(struct otus_softc *sc, uint8_t code, const void *idata, int ilen,
1403 void *odata)
1404 {
1405 struct otus_tx_cmd *cmd;
1406 struct ar_cmd_hdr *hdr;
1407 int xferlen, error;
1408
1409 DPRINTFN(DBG_FN, sc, "\n");
1410
1411 cmd = &sc->sc_tx_cmd;
1412
1413 mutex_enter(&sc->sc_cmd_mtx);
1414
1415 /* Always bulk-out a multiple of 4 bytes. */
1416 xferlen = roundup2(sizeof(*hdr) + ilen, 4);
1417
1418 hdr = (void *)cmd->buf;
1419 if (hdr == NULL) { /* we may have been freed while detaching */
1420 mutex_exit(&sc->sc_cmd_mtx);
1421 DPRINTFN(DBG_CMD, sc, "tx_cmd freed with commands pending\n");
1422 return 0;
1423 }
1424 hdr->code = code;
1425 hdr->len = ilen;
1426 hdr->token = ++cmd->token; /* Don't care about endianness. */
1427 KASSERT(sizeof(hdr) + ilen <= OTUS_MAX_TXCMDSZ);
1428 memcpy(cmd->buf + sizeof(hdr[0]), idata, ilen);
1429
1430 DPRINTFN(DBG_CMD, sc, "sending command code=0x%02x len=%d token=%d\n",
1431 code, ilen, hdr->token);
1432
1433 cmd->odata = odata;
1434 cmd->done = 0;
1435 usbd_setup_xfer(cmd->xfer, cmd, cmd->buf, xferlen,
1436 USBD_FORCE_SHORT_XFER, OTUS_CMD_TIMEOUT, NULL);
1437 error = usbd_sync_transfer(cmd->xfer);
1438 if (error != 0) {
1439 mutex_exit(&sc->sc_cmd_mtx);
1440 #if defined(DIAGNOSTIC) || defined(OTUS_DEBUG) /* XXX: kill some noise */
1441 aprint_error_dev(sc->sc_dev,
1442 "could not send command %#x (error=%s)\n",
1443 code, usbd_errstr(error));
1444 #endif
1445 return EIO;
1446 }
1447 if (!cmd->done)
1448 error = cv_timedwait_sig(&sc->sc_cmd_cv, &sc->sc_cmd_mtx, hz);
1449 cmd->odata = NULL; /* In case answer is received too late. */
1450 mutex_exit(&sc->sc_cmd_mtx);
1451 if (error != 0) {
1452 aprint_error_dev(sc->sc_dev,
1453 "timeout waiting for command 0x%02x reply\n", code);
1454 }
1455 return error;
1456 }
1457
1458 Static void
otus_write(struct otus_softc * sc,uint32_t reg,uint32_t val)1459 otus_write(struct otus_softc *sc, uint32_t reg, uint32_t val)
1460 {
1461
1462 DPRINTFN(DBG_FN | DBG_REG, sc, "reg=%#x, val=%#x\n", reg, val);
1463
1464 KASSERT(mutex_owned(&sc->sc_write_mtx));
1465 KASSERT(sc->sc_write_idx < __arraycount(sc->sc_write_buf));
1466
1467 sc->sc_write_buf[sc->sc_write_idx].reg = htole32(reg);
1468 sc->sc_write_buf[sc->sc_write_idx].val = htole32(val);
1469
1470 if (++sc->sc_write_idx >= __arraycount(sc->sc_write_buf))
1471 (void)otus_write_barrier(sc);
1472 }
1473
1474 Static int
otus_write_barrier(struct otus_softc * sc)1475 otus_write_barrier(struct otus_softc *sc)
1476 {
1477 int error;
1478
1479 DPRINTFN(DBG_FN, sc, "\n");
1480
1481 KASSERT(mutex_owned(&sc->sc_write_mtx));
1482 KASSERT(sc->sc_write_idx <= __arraycount(sc->sc_write_buf));
1483
1484 if (sc->sc_write_idx == 0)
1485 return 0; /* Nothing to flush. */
1486
1487 error = otus_cmd(sc, AR_CMD_WREG, sc->sc_write_buf,
1488 sizeof(sc->sc_write_buf[0]) * sc->sc_write_idx, NULL);
1489
1490 sc->sc_write_idx = 0;
1491 if (error)
1492 DPRINTFN(DBG_REG, sc, "error=%d\n", error);
1493 return error;
1494 }
1495
1496 Static struct ieee80211_node *
otus_node_alloc(struct ieee80211_node_table * ntp)1497 otus_node_alloc(struct ieee80211_node_table *ntp)
1498 {
1499 struct otus_node *on;
1500
1501 DPRINTFN(DBG_FN, DBG_NO_SC, "\n");
1502
1503 on = malloc(sizeof(*on), M_DEVBUF, M_NOWAIT | M_ZERO);
1504 return on ? &on->ni : NULL;
1505 }
1506
1507 Static int
otus_media_change(struct ifnet * ifp)1508 otus_media_change(struct ifnet *ifp)
1509 {
1510 struct otus_softc *sc;
1511 struct ieee80211com *ic;
1512 uint8_t rate, ridx;
1513 int error;
1514
1515 sc = ifp->if_softc;
1516
1517 DPRINTFN(DBG_FN, sc, "\n");
1518
1519 error = ieee80211_media_change(ifp);
1520 if (error != ENETRESET)
1521 return error;
1522
1523 ic = &sc->sc_ic;
1524 if (ic->ic_fixed_rate != -1) {
1525 rate = ic->ic_sup_rates[ic->ic_curmode].
1526 rs_rates[ic->ic_fixed_rate] & IEEE80211_RATE_VAL;
1527 for (ridx = 0; ridx <= OTUS_RIDX_MAX; ridx++)
1528 if (otus_rates[ridx].rate == rate)
1529 break;
1530 sc->sc_fixed_ridx = ridx;
1531 }
1532
1533 if ((ifp->if_flags & (IFF_UP | IFF_RUNNING)) == (IFF_UP | IFF_RUNNING))
1534 error = otus_init(ifp);
1535
1536 return error;
1537 }
1538
1539 Static int
otus_read_eeprom(struct otus_softc * sc)1540 otus_read_eeprom(struct otus_softc *sc)
1541 {
1542 uint32_t regs[8], reg;
1543 uint8_t *eep;
1544 int i, j, error;
1545
1546 DPRINTFN(DBG_FN, sc, "\n");
1547
1548 KASSERT(sizeof(sc->sc_eeprom) % 32 == 0);
1549
1550 /* Read EEPROM by blocks of 32 bytes. */
1551 eep = (uint8_t *)&sc->sc_eeprom;
1552 reg = AR_EEPROM_OFFSET;
1553 for (i = 0; i < sizeof(sc->sc_eeprom) / 32; i++) {
1554 for (j = 0; j < 8; j++, reg += 4)
1555 regs[j] = htole32(reg);
1556 error = otus_cmd(sc, AR_CMD_RREG, regs, sizeof(regs), eep);
1557 if (error != 0)
1558 break;
1559 eep += 32;
1560 }
1561 return error;
1562 }
1563
1564 Static void
otus_newassoc(struct ieee80211_node * ni,int isnew)1565 otus_newassoc(struct ieee80211_node *ni, int isnew)
1566 {
1567 struct ieee80211_rateset *rs;
1568 struct otus_softc *sc;
1569 struct otus_node *on;
1570 uint8_t rate;
1571 int ridx, i;
1572
1573 sc = ni->ni_ic->ic_ifp->if_softc;
1574
1575 DPRINTFN(DBG_FN, sc, "isnew=%d addr=%s\n",
1576 isnew, ether_sprintf(ni->ni_macaddr));
1577
1578 on = (void *)ni;
1579 ieee80211_amrr_node_init(&sc->sc_amrr, &on->amn);
1580 /* Start at lowest available bit-rate, AMRR will raise. */
1581 ni->ni_txrate = 0;
1582 rs = &ni->ni_rates;
1583 for (i = 0; i < rs->rs_nrates; i++) {
1584 rate = rs->rs_rates[i] & IEEE80211_RATE_VAL;
1585 /* Convert 802.11 rate to hardware rate index. */
1586 for (ridx = 0; ridx <= OTUS_RIDX_MAX; ridx++)
1587 if (otus_rates[ridx].rate == rate)
1588 break;
1589 on->ridx[i] = ridx;
1590 DPRINTFN(DBG_INIT, sc, "rate=0x%02x ridx=%d\n",
1591 rs->rs_rates[i], on->ridx[i]);
1592 }
1593 }
1594
1595 /* ARGSUSED */
1596 Static void
otus_intr(struct usbd_xfer * xfer,void * priv,usbd_status status)1597 otus_intr(struct usbd_xfer *xfer, void *priv, usbd_status status)
1598 {
1599 #if 0
1600 struct otus_softc *sc;
1601 int len;
1602
1603 sc = priv;
1604
1605 DPRINTFN(DBG_FN, sc, "\n");
1606
1607 /*
1608 * The Rx intr pipe is unused with current firmware. Notifications
1609 * and replies to commands are sent through the Rx bulk pipe instead
1610 * (with a magic PLCP header.)
1611 */
1612 if (__predict_false(status != USBD_NORMAL_COMPLETION)) {
1613 DPRINTFN(DBG_INTR, sc, "status=%d\n", status);
1614 if (status == USBD_STALLED)
1615 usbd_clear_endpoint_stall_async(sc->sc_cmd_rx_pipe);
1616 return;
1617 }
1618 usbd_get_xfer_status(xfer, NULL, NULL, &len, NULL);
1619
1620 otus_cmd_rxeof(sc, sc->sc_ibuf, len);
1621 #endif
1622 }
1623
1624 Static void
otus_cmd_rxeof(struct otus_softc * sc,uint8_t * buf,int len)1625 otus_cmd_rxeof(struct otus_softc *sc, uint8_t *buf, int len)
1626 {
1627 struct ieee80211com *ic;
1628 struct otus_tx_cmd *cmd;
1629 struct ar_cmd_hdr *hdr;
1630 int s;
1631
1632 DPRINTFN(DBG_FN, sc, "\n");
1633
1634 ic = &sc->sc_ic;
1635
1636 if (__predict_false(len < sizeof(*hdr))) {
1637 DPRINTFN(DBG_RX, sc, "cmd too small %d\n", len);
1638 return;
1639 }
1640 hdr = (void *)buf;
1641 if (__predict_false(sizeof(*hdr) + hdr->len > len ||
1642 sizeof(*hdr) + hdr->len > 64)) {
1643 DPRINTFN(DBG_RX, sc, "cmd too large %d\n", hdr->len);
1644 return;
1645 }
1646
1647 if ((hdr->code & 0xc0) != 0xc0) {
1648 DPRINTFN(DBG_RX, sc, "received reply code=0x%02x len=%d token=%d\n",
1649 hdr->code, hdr->len, hdr->token);
1650 mutex_enter(&sc->sc_cmd_mtx);
1651 cmd = &sc->sc_tx_cmd;
1652 if (__predict_false(hdr->token != cmd->token)) {
1653 mutex_exit(&sc->sc_cmd_mtx);
1654 return;
1655 }
1656 /* Copy answer into caller's supplied buffer. */
1657 if (cmd->odata != NULL)
1658 memcpy(cmd->odata, &hdr[1], hdr->len);
1659 cmd->done = 1;
1660 cv_signal(&sc->sc_cmd_cv);
1661 mutex_exit(&sc->sc_cmd_mtx);
1662 return;
1663 }
1664
1665 /* Received unsolicited notification. */
1666 DPRINTFN(DBG_RX, sc, "received notification code=0x%02x len=%d\n",
1667 hdr->code, hdr->len);
1668 switch (hdr->code & 0x3f) {
1669 case AR_EVT_BEACON:
1670 break;
1671 case AR_EVT_TX_COMP:
1672 {
1673 struct ar_evt_tx_comp *tx;
1674 struct ieee80211_node *ni;
1675 struct otus_node *on;
1676
1677 tx = (void *)&hdr[1];
1678
1679 DPRINTFN(DBG_RX, sc, "tx completed %s status=%d phy=%#x\n",
1680 ether_sprintf(tx->macaddr), le16toh(tx->status),
1681 le32toh(tx->phy));
1682 s = splnet();
1683 #ifdef notyet
1684 #ifndef IEEE80211_STA_ONLY
1685 if (ic->ic_opmode != IEEE80211_M_STA) {
1686 ni = ieee80211_find_node(ic, tx->macaddr);
1687 if (__predict_false(ni == NULL)) {
1688 splx(s);
1689 break;
1690 }
1691 } else
1692 #endif
1693 #endif
1694 ni = ic->ic_bss;
1695 /* Update rate control statistics. */
1696 on = (void *)ni;
1697 /* NB: we do not set the TX_MAC_RATE_PROBING flag. */
1698 if (__predict_true(tx->status != 0))
1699 on->amn.amn_retrycnt++;
1700 splx(s);
1701 break;
1702 }
1703 case AR_EVT_TBTT:
1704 break;
1705 }
1706 }
1707
1708 Static void
otus_sub_rxeof(struct otus_softc * sc,uint8_t * buf,int len)1709 otus_sub_rxeof(struct otus_softc *sc, uint8_t *buf, int len)
1710 {
1711 struct ieee80211com *ic;
1712 struct ifnet *ifp;
1713 struct ieee80211_node *ni;
1714 struct ar_rx_tail *tail;
1715 struct ieee80211_frame *wh;
1716 struct mbuf *m;
1717 uint8_t *plcp;
1718 int s, mlen, align;
1719
1720 DPRINTFN(DBG_FN, sc, "\n");
1721
1722 ic = &sc->sc_ic;
1723 ifp = ic->ic_ifp;
1724
1725 if (__predict_false(len < AR_PLCP_HDR_LEN)) {
1726 DPRINTFN(DBG_RX, sc, "sub-xfer too short %d\n", len);
1727 return;
1728 }
1729 plcp = buf;
1730
1731 /* All bits in the PLCP header are set to 1 for non-MPDU. */
1732 if (memcmp(plcp, AR_PLCP_HDR_INTR, AR_PLCP_HDR_LEN) == 0) {
1733 otus_cmd_rxeof(sc, plcp + AR_PLCP_HDR_LEN,
1734 len - AR_PLCP_HDR_LEN);
1735 return;
1736 }
1737
1738 /* Received MPDU. */
1739 if (__predict_false(len < AR_PLCP_HDR_LEN + sizeof(*tail))) {
1740 DPRINTFN(DBG_RX, sc, "MPDU too short %d\n", len);
1741 if_statinc(ifp, if_ierrors);
1742 return;
1743 }
1744 tail = (void *)(plcp + len - sizeof(*tail));
1745 wh = (void *)(plcp + AR_PLCP_HDR_LEN);
1746
1747 /* Discard error frames. */
1748 if (__predict_false((tail->error & sc->sc_rx_error_msk) != 0)) {
1749 DPRINTFN(DBG_RX, sc, "error frame 0x%02x\n", tail->error);
1750 if (tail->error & AR_RX_ERROR_FCS) {
1751 DPRINTFN(DBG_RX, sc, "bad FCS\n");
1752 } else if (tail->error & AR_RX_ERROR_MMIC) {
1753 /* Report Michael MIC failures to net80211. */
1754 ieee80211_notify_michael_failure(ic, wh, 0 /* XXX: keyix */);
1755 }
1756 if_statinc(ifp, if_ierrors);
1757 return;
1758 }
1759 /* Compute MPDU's length. */
1760 mlen = len - AR_PLCP_HDR_LEN - sizeof(*tail);
1761 if (__predict_false(mlen < IEEE80211_CRC_LEN)) {
1762 if_statinc(ifp, if_ierrors);
1763 return;
1764 }
1765 mlen -= IEEE80211_CRC_LEN; /* strip 802.11 FCS */
1766 /* Make sure there's room for an 802.11 header. */
1767 /*
1768 * XXX: This will drop most control packets. Do we really
1769 * want this in IEEE80211_M_MONITOR mode?
1770 */
1771 if (__predict_false(mlen < sizeof(*wh))) {
1772 if_statinc(ifp, if_ierrors);
1773 return;
1774 }
1775
1776 /* Provide a 32-bit aligned protocol header to the stack. */
1777 align = (ieee80211_has_qos(wh) ^ ieee80211_has_addr4(wh)) ? 2 : 0;
1778
1779 MGETHDR(m, M_DONTWAIT, MT_DATA);
1780 if (__predict_false(m == NULL)) {
1781 if_statinc(ifp, if_ierrors);
1782 return;
1783 }
1784 if (align + mlen > MHLEN) {
1785 if (__predict_true(align + mlen <= MCLBYTES))
1786 MCLGET(m, M_DONTWAIT);
1787 if (__predict_false(!(m->m_flags & M_EXT))) {
1788 if_statinc(ifp, if_ierrors);
1789 m_freem(m);
1790 return;
1791 }
1792 }
1793 /* Finalize mbuf. */
1794 m_set_rcvif(m, ifp);
1795 m->m_data += align;
1796 memcpy(mtod(m, void *), wh, mlen);
1797 m->m_pkthdr.len = m->m_len = mlen;
1798
1799 s = splnet();
1800 if (__predict_false(sc->sc_drvbpf != NULL)) {
1801 struct otus_rx_radiotap_header *tap;
1802
1803 tap = &sc->sc_rxtap;
1804 tap->wr_flags = 0;
1805 tap->wr_chan_freq = htole16(ic->ic_curchan->ic_freq);
1806 tap->wr_chan_flags = htole16(ic->ic_curchan->ic_flags);
1807 tap->wr_antsignal = tail->rssi;
1808 tap->wr_rate = 2; /* In case it can't be found below. */
1809 switch (tail->status & AR_RX_STATUS_MT_MASK) {
1810 case AR_RX_STATUS_MT_CCK:
1811 switch (plcp[0]) {
1812 case 10: tap->wr_rate = 2; break;
1813 case 20: tap->wr_rate = 4; break;
1814 case 55: tap->wr_rate = 11; break;
1815 case 110: tap->wr_rate = 22; break;
1816 }
1817 if (tail->status & AR_RX_STATUS_SHPREAMBLE)
1818 tap->wr_flags |= IEEE80211_RADIOTAP_F_SHORTPRE;
1819 break;
1820 case AR_RX_STATUS_MT_OFDM:
1821 switch (plcp[0] & 0xf) {
1822 case 0xb: tap->wr_rate = 12; break;
1823 case 0xf: tap->wr_rate = 18; break;
1824 case 0xa: tap->wr_rate = 24; break;
1825 case 0xe: tap->wr_rate = 36; break;
1826 case 0x9: tap->wr_rate = 48; break;
1827 case 0xd: tap->wr_rate = 72; break;
1828 case 0x8: tap->wr_rate = 96; break;
1829 case 0xc: tap->wr_rate = 108; break;
1830 }
1831 break;
1832 }
1833 bpf_mtap2(sc->sc_drvbpf, tap, sc->sc_rxtap_len, m, BPF_D_IN);
1834 }
1835
1836 ni = ieee80211_find_rxnode(ic, (struct ieee80211_frame_min *)wh);
1837
1838 /* push the frame up to the 802.11 stack */
1839 ieee80211_input(ic, m, ni, tail->rssi, 0);
1840
1841 /* Node is no longer needed. */
1842 ieee80211_free_node(ni);
1843 splx(s);
1844 }
1845
1846 Static void
otus_rxeof(struct usbd_xfer * xfer,void * priv,usbd_status status)1847 otus_rxeof(struct usbd_xfer *xfer, void *priv, usbd_status status)
1848 {
1849 struct otus_rx_data *data;
1850 struct otus_softc *sc;
1851 uint8_t *buf;
1852 struct ar_rx_head *head;
1853 uint16_t hlen;
1854 int len;
1855
1856 data = priv;
1857 sc = data->sc;
1858
1859 DPRINTFN(DBG_FN, sc, "\n");
1860
1861 buf = data->buf;
1862
1863 if (__predict_false(status != USBD_NORMAL_COMPLETION)) {
1864 DPRINTFN(DBG_RX, sc, "RX status=%d\n", status);
1865 if (status == USBD_STALLED)
1866 usbd_clear_endpoint_stall_async(sc->sc_data_rx_pipe);
1867 else if (status != USBD_CANCELLED) {
1868 DPRINTFN(DBG_RX, sc,
1869 "otus_rxeof: goto resubmit: status=%d\n", status);
1870 goto resubmit;
1871 }
1872 return;
1873 }
1874 usbd_get_xfer_status(xfer, NULL, NULL, &len, NULL);
1875
1876 while (len >= sizeof(*head)) {
1877 head = (void *)buf;
1878 if (__predict_false(head->tag != htole16(AR_RX_HEAD_TAG))) {
1879 DPRINTFN(DBG_RX, sc, "tag not valid %#x\n",
1880 le16toh(head->tag));
1881 break;
1882 }
1883 hlen = le16toh(head->len);
1884 if (__predict_false(sizeof(*head) + hlen > len)) {
1885 DPRINTFN(DBG_RX, sc, "xfer too short %d/%d\n",
1886 len, hlen);
1887 break;
1888 }
1889 /* Process sub-xfer. */
1890 otus_sub_rxeof(sc, (uint8_t *)&head[1], hlen);
1891
1892 /* Next sub-xfer is aligned on a 32-bit boundary. */
1893 hlen = roundup2(sizeof(*head) + hlen, 4);
1894 buf += hlen;
1895 len -= hlen;
1896 }
1897
1898 resubmit:
1899 usbd_setup_xfer(xfer, data, data->buf, OTUS_RXBUFSZ,
1900 USBD_SHORT_XFER_OK, USBD_NO_TIMEOUT, otus_rxeof);
1901 (void)usbd_transfer(data->xfer);
1902 }
1903
1904 Static void
otus_txeof(struct usbd_xfer * xfer,void * priv,usbd_status status)1905 otus_txeof(struct usbd_xfer *xfer, void *priv, usbd_status status)
1906 {
1907 struct otus_tx_data *data;
1908 struct otus_softc *sc;
1909 struct ieee80211com *ic;
1910 struct ifnet *ifp;
1911 int s;
1912
1913 data = priv;
1914 sc = data->sc;
1915
1916 DPRINTFN(DBG_FN, sc, "\n");
1917
1918 /* Put this Tx buffer back to the free list. */
1919 mutex_enter(&sc->sc_tx_mtx);
1920 TAILQ_INSERT_TAIL(&sc->sc_tx_free_list, data, next);
1921 mutex_exit(&sc->sc_tx_mtx);
1922
1923 ic = &sc->sc_ic;
1924 ifp = ic->ic_ifp;
1925 if (__predict_false(status != USBD_NORMAL_COMPLETION)) {
1926 DPRINTFN(DBG_TX, sc, "TX status=%d\n", status);
1927 if (status == USBD_STALLED)
1928 usbd_clear_endpoint_stall_async(sc->sc_data_tx_pipe);
1929 if_statinc(ifp, if_oerrors);
1930 return;
1931 }
1932 if_statinc(ifp, if_opackets);
1933
1934 s = splnet();
1935 sc->sc_tx_timer = 0;
1936 ifp->if_flags &= ~IFF_OACTIVE; /* XXX: do after freeing Tx buffer? */
1937 otus_start(ifp);
1938 splx(s);
1939 }
1940
1941 Static int
otus_tx(struct otus_softc * sc,struct mbuf * m,struct ieee80211_node * ni,struct otus_tx_data * data)1942 otus_tx(struct otus_softc *sc, struct mbuf *m, struct ieee80211_node *ni,
1943 struct otus_tx_data *data)
1944 {
1945 struct ieee80211com *ic;
1946 struct otus_node *on;
1947 struct ieee80211_frame *wh;
1948 struct ieee80211_key *k;
1949 struct ar_tx_head *head;
1950 uint32_t phyctl;
1951 uint16_t macctl, qos;
1952 uint8_t qid;
1953 int error, ridx, hasqos, xferlen;
1954
1955 DPRINTFN(DBG_FN, sc, "\n");
1956
1957 ic = &sc->sc_ic;
1958 on = (void *)ni;
1959
1960 wh = mtod(m, struct ieee80211_frame *);
1961 if ((wh->i_fc[1] & IEEE80211_FC1_PROTECTED)) {
1962 /* XXX: derived from upgt_tx_task() and ural_tx_data() */
1963 k = ieee80211_crypto_encap(ic, ni, m);
1964 if (k == NULL)
1965 return ENOBUFS;
1966
1967 /* Packet header may have moved, reset our local pointer. */
1968 wh = mtod(m, struct ieee80211_frame *);
1969 }
1970
1971 #ifdef HAVE_EDCA
1972 if ((hasqos = ieee80211_has_qos(wh))) {
1973 qos = ieee80211_get_qos(wh);
1974 qid = ieee80211_up_to_ac(ic, qos & IEEE80211_QOS_TID);
1975 } else {
1976 qos = 0;
1977 qid = WME_AC_BE;
1978 }
1979 #else
1980 hasqos = 0;
1981 qos = 0;
1982 qid = WME_AC_BE;
1983 #endif
1984
1985 /* Pickup a rate index. */
1986 if (IEEE80211_IS_MULTICAST(wh->i_addr1) ||
1987 (wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK) != IEEE80211_FC0_TYPE_DATA)
1988 ridx = (ic->ic_curmode == IEEE80211_MODE_11A) ?
1989 OTUS_RIDX_OFDM6 : OTUS_RIDX_CCK1;
1990 else if (ic->ic_fixed_rate != -1)
1991 ridx = sc->sc_fixed_ridx;
1992 else
1993 ridx = on->ridx[ni->ni_txrate];
1994
1995 phyctl = 0;
1996 macctl = AR_TX_MAC_BACKOFF | AR_TX_MAC_HW_DUR | AR_TX_MAC_QID(qid);
1997
1998 if (IEEE80211_IS_MULTICAST(wh->i_addr1) ||
1999 (hasqos && ((qos & IEEE80211_QOS_ACKPOLICY_MASK) ==
2000 IEEE80211_QOS_ACKPOLICY_NOACK)))
2001 macctl |= AR_TX_MAC_NOACK;
2002
2003 if (!IEEE80211_IS_MULTICAST(wh->i_addr1)) {
2004 if (m->m_pkthdr.len + IEEE80211_CRC_LEN >= ic->ic_rtsthreshold)
2005 macctl |= AR_TX_MAC_RTS;
2006 else if ((ic->ic_flags & IEEE80211_F_USEPROT) &&
2007 ridx >= OTUS_RIDX_OFDM6) {
2008 if (ic->ic_protmode == IEEE80211_PROT_CTSONLY)
2009 macctl |= AR_TX_MAC_CTS;
2010 else if (ic->ic_protmode == IEEE80211_PROT_RTSCTS)
2011 macctl |= AR_TX_MAC_RTS;
2012 }
2013 }
2014
2015 phyctl |= AR_TX_PHY_MCS(otus_rates[ridx].mcs);
2016 if (ridx >= OTUS_RIDX_OFDM6) {
2017 phyctl |= AR_TX_PHY_MT_OFDM;
2018 if (ridx <= OTUS_RIDX_OFDM24)
2019 phyctl |= AR_TX_PHY_ANTMSK(sc->sc_txmask);
2020 else
2021 phyctl |= AR_TX_PHY_ANTMSK(1);
2022 } else { /* CCK */
2023 phyctl |= AR_TX_PHY_MT_CCK;
2024 phyctl |= AR_TX_PHY_ANTMSK(sc->sc_txmask);
2025 }
2026
2027 /* Update rate control stats for frames that are ACK'ed. */
2028 if (!(macctl & AR_TX_MAC_NOACK))
2029 on->amn.amn_txcnt++;
2030
2031 /* Fill Tx descriptor. */
2032 head = (void *)data->buf;
2033 head->len = htole16(m->m_pkthdr.len + IEEE80211_CRC_LEN);
2034 head->macctl = htole16(macctl);
2035 head->phyctl = htole32(phyctl);
2036
2037 if (__predict_false(sc->sc_drvbpf != NULL)) {
2038 struct otus_tx_radiotap_header *tap = &sc->sc_txtap;
2039
2040 tap->wt_flags = 0;
2041 if (wh->i_fc[1] & IEEE80211_FC1_WEP)
2042 tap->wt_flags |= IEEE80211_RADIOTAP_F_WEP;
2043 tap->wt_rate = otus_rates[ridx].rate;
2044 tap->wt_chan_freq = htole16(ic->ic_curchan->ic_freq);
2045 tap->wt_chan_flags = htole16(ic->ic_curchan->ic_flags);
2046
2047 bpf_mtap2(sc->sc_drvbpf, tap, sc->sc_txtap_len, m, BPF_D_OUT);
2048 }
2049
2050 xferlen = sizeof(*head) + m->m_pkthdr.len;
2051 m_copydata(m, 0, m->m_pkthdr.len, (void *)&head[1]);
2052
2053 DPRINTFN(DBG_TX, sc, "queued len=%d mac=0x%04x phy=0x%08x rate=%d\n",
2054 head->len, head->macctl, head->phyctl, otus_rates[ridx].rate);
2055
2056 usbd_setup_xfer(data->xfer, data, data->buf, xferlen,
2057 USBD_FORCE_SHORT_XFER, OTUS_TX_TIMEOUT, otus_txeof);
2058 error = usbd_transfer(data->xfer);
2059 if (__predict_false(
2060 error != USBD_NORMAL_COMPLETION &&
2061 error != USBD_IN_PROGRESS)) {
2062 DPRINTFN(DBG_TX, sc, "transfer failed %d\n", error);
2063 return error;
2064 }
2065 return 0;
2066 }
2067
2068 Static void
otus_start(struct ifnet * ifp)2069 otus_start(struct ifnet *ifp)
2070 {
2071 struct otus_softc *sc;
2072 struct ieee80211com *ic;
2073 struct otus_tx_data *data;
2074 struct ether_header *eh;
2075 struct ieee80211_node *ni;
2076 struct mbuf *m;
2077
2078 if ((ifp->if_flags & (IFF_RUNNING | IFF_OACTIVE)) != IFF_RUNNING)
2079 return;
2080
2081 sc = ifp->if_softc;
2082 ic = &sc->sc_ic;
2083
2084 DPRINTFN(DBG_FN, sc, "\n");
2085
2086 data = NULL;
2087 for (;;) {
2088 /*
2089 * Grab a Tx buffer if we don't already have one. If
2090 * one isn't available, bail out.
2091 * NB: We must obtain this Tx buffer _before_
2092 * dequeueing anything as one may not be available
2093 * later. Both must be done inside a single lock.
2094 */
2095 mutex_enter(&sc->sc_tx_mtx);
2096 if (data == NULL && !TAILQ_EMPTY(&sc->sc_tx_free_list)) {
2097 data = TAILQ_FIRST(&sc->sc_tx_free_list);
2098 TAILQ_REMOVE(&sc->sc_tx_free_list, data, next);
2099 }
2100 mutex_exit(&sc->sc_tx_mtx);
2101
2102 if (data == NULL) {
2103 ifp->if_flags |= IFF_OACTIVE;
2104 DPRINTFN(DBG_TX, sc, "empty sc_tx_free_list\n");
2105 return;
2106 }
2107
2108 /* Send pending management frames first. */
2109 IF_DEQUEUE(&ic->ic_mgtq, m);
2110 if (m != NULL) {
2111 ni = M_GETCTX(m, struct ieee80211_node *);
2112 M_CLEARCTX(m);
2113 goto sendit;
2114 }
2115
2116 if (ic->ic_state != IEEE80211_S_RUN)
2117 break;
2118
2119 /* Encapsulate and send data frames. */
2120 IFQ_DEQUEUE(&ifp->if_snd, m);
2121 if (m == NULL)
2122 break;
2123
2124 if (m->m_len < (int)sizeof(*eh) &&
2125 (m = m_pullup(m, sizeof(*eh))) == NULL) {
2126 if_statinc(ifp, if_oerrors);
2127 continue;
2128 }
2129
2130 eh = mtod(m, struct ether_header *);
2131 ni = ieee80211_find_txnode(ic, eh->ether_dhost);
2132 if (ni == NULL) {
2133 m_freem(m);
2134 if_statinc(ifp, if_oerrors);
2135 continue;
2136 }
2137
2138 bpf_mtap(ifp, m, BPF_D_OUT);
2139
2140 if ((m = ieee80211_encap(ic, m, ni)) == NULL) {
2141 /* original m was freed by ieee80211_encap() */
2142 ieee80211_free_node(ni);
2143 if_statinc(ifp, if_oerrors);
2144 continue;
2145 }
2146 sendit:
2147 bpf_mtap3(ic->ic_rawbpf, m, BPF_D_OUT);
2148
2149 if (otus_tx(sc, m, ni, data) != 0) {
2150 m_freem(m);
2151 ieee80211_free_node(ni);
2152 if_statinc(ifp, if_oerrors);
2153 continue;
2154 }
2155
2156 data = NULL; /* we're finished with this data buffer */
2157 m_freem(m);
2158 ieee80211_free_node(ni);
2159 sc->sc_tx_timer = 5;
2160 ifp->if_timer = 1;
2161 }
2162
2163 /*
2164 * If here, we have a Tx buffer, but ran out of mbufs to
2165 * transmit. Put the Tx buffer back to the free list.
2166 */
2167 mutex_enter(&sc->sc_tx_mtx);
2168 TAILQ_INSERT_TAIL(&sc->sc_tx_free_list, data, next);
2169 mutex_exit(&sc->sc_tx_mtx);
2170 }
2171
2172 Static void
otus_watchdog(struct ifnet * ifp)2173 otus_watchdog(struct ifnet *ifp)
2174 {
2175 struct otus_softc *sc;
2176
2177 sc = ifp->if_softc;
2178
2179 DPRINTFN(DBG_FN, sc, "\n");
2180
2181 ifp->if_timer = 0;
2182
2183 if (sc->sc_tx_timer > 0) {
2184 if (--sc->sc_tx_timer == 0) {
2185 aprint_error_dev(sc->sc_dev, "device timeout\n");
2186 /* otus_init(ifp); XXX needs a process context! */
2187 if_statinc(ifp, if_oerrors);
2188 return;
2189 }
2190 ifp->if_timer = 1;
2191 }
2192 ieee80211_watchdog(&sc->sc_ic);
2193 }
2194
2195 Static int
otus_ioctl(struct ifnet * ifp,u_long cmd,void * data)2196 otus_ioctl(struct ifnet *ifp, u_long cmd, void *data)
2197 {
2198 struct otus_softc *sc;
2199 struct ieee80211com *ic;
2200 int s, error = 0;
2201
2202 sc = ifp->if_softc;
2203
2204 DPRINTFN(DBG_FN, sc, "%#lx\n", cmd);
2205
2206 ic = &sc->sc_ic;
2207
2208 s = splnet();
2209
2210 switch (cmd) {
2211 case SIOCSIFADDR:
2212 ifp->if_flags |= IFF_UP;
2213 #ifdef INET
2214 struct ifaddr *ifa = data;
2215 if (ifa->ifa_addr->sa_family == AF_INET)
2216 arp_ifinit(&ic->ic_ac, ifa);
2217 #endif
2218 /* FALLTHROUGH */
2219 case SIOCSIFFLAGS:
2220 if ((error = ifioctl_common(ifp, cmd, data)) != 0)
2221 break;
2222
2223 switch (ifp->if_flags & (IFF_UP | IFF_RUNNING)) {
2224 case IFF_UP | IFF_RUNNING:
2225 if (((ifp->if_flags ^ sc->sc_if_flags) &
2226 (IFF_ALLMULTI | IFF_PROMISC)) != 0)
2227 otus_set_multi(sc);
2228 break;
2229 case IFF_UP:
2230 otus_init(ifp);
2231 break;
2232
2233 case IFF_RUNNING:
2234 otus_stop(ifp);
2235 break;
2236 case 0:
2237 default:
2238 break;
2239 }
2240 sc->sc_if_flags = ifp->if_flags;
2241 break;
2242
2243 case SIOCADDMULTI:
2244 case SIOCDELMULTI:
2245 if ((error = ether_ioctl(ifp, cmd, data)) == ENETRESET) {
2246 /* setup multicast filter, etc */
2247 /* XXX: ??? */
2248 error = 0;
2249 }
2250 break;
2251
2252 case SIOCS80211CHANNEL:
2253 /*
2254 * This allows for fast channel switching in monitor mode
2255 * (used by kismet). In IBSS mode, we must explicitly reset
2256 * the interface to generate a new beacon frame.
2257 */
2258 error = ieee80211_ioctl(ic, cmd, data);
2259
2260 DPRINTFN(DBG_CHAN, sc,
2261 "ic_curchan=%d ic_ibss_chan=%d ic_des_chan=%d ni_chan=%d error=%d\n",
2262 ieee80211_chan2ieee(ic, ic->ic_curchan),
2263 ieee80211_chan2ieee(ic, ic->ic_ibss_chan),
2264 ieee80211_chan2ieee(ic, ic->ic_des_chan),
2265 ieee80211_chan2ieee(ic, ic->ic_bss->ni_chan),
2266 error);
2267
2268 if (error == ENETRESET &&
2269 ic->ic_opmode == IEEE80211_M_MONITOR) {
2270 if ((ifp->if_flags & (IFF_UP | IFF_RUNNING)) ==
2271 (IFF_UP | IFF_RUNNING)) {
2272 mutex_enter(&sc->sc_write_mtx);
2273 otus_set_chan(sc, ic->ic_curchan, 0);
2274 mutex_exit(&sc->sc_write_mtx);
2275 }
2276 error = 0;
2277 }
2278 break;
2279
2280 default:
2281 error = ieee80211_ioctl(ic, cmd, data);
2282 }
2283 if (error == ENETRESET) {
2284 if ((ifp->if_flags & (IFF_UP | IFF_RUNNING)) ==
2285 (IFF_UP | IFF_RUNNING))
2286 otus_init(ifp);
2287 error = 0;
2288 }
2289 splx(s);
2290 return error;
2291 }
2292
2293 Static int
otus_set_multi(struct otus_softc * sc)2294 otus_set_multi(struct otus_softc *sc)
2295 {
2296 struct ethercom *ec = &sc->sc_ec;
2297 struct ifnet *ifp;
2298 struct ether_multi *enm;
2299 struct ether_multistep step;
2300 uint32_t lo, hi;
2301 uint8_t bit;
2302 int error;
2303
2304 DPRINTFN(DBG_FN, sc, "\n");
2305
2306 ifp = sc->sc_ic.ic_ifp;
2307 if ((ifp->if_flags & (IFF_ALLMULTI | IFF_PROMISC)) != 0) {
2308 lo = hi = 0xffffffff;
2309 goto done;
2310 }
2311 lo = hi = 0;
2312 ETHER_LOCK(ec);
2313 ETHER_FIRST_MULTI(step, ec, enm);
2314 while (enm != NULL) {
2315 if (bcmp(enm->enm_addrlo, enm->enm_addrhi, ETHER_ADDR_LEN)) {
2316 ifp->if_flags |= IFF_ALLMULTI;
2317 lo = hi = 0xffffffff;
2318 goto done;
2319 }
2320 bit = enm->enm_addrlo[5] >> 2;
2321 if (bit < 32)
2322 lo |= 1 << bit;
2323 else
2324 hi |= 1 << (bit - 32);
2325 ETHER_NEXT_MULTI(step, enm);
2326 }
2327 done:
2328 ETHER_UNLOCK(ec);
2329 mutex_enter(&sc->sc_write_mtx);
2330 hi |= 1 << 31; /* Make sure the broadcast bit is set. */
2331 otus_write(sc, AR_MAC_REG_GROUP_HASH_TBL_L, lo);
2332 otus_write(sc, AR_MAC_REG_GROUP_HASH_TBL_H, hi);
2333 error = otus_write_barrier(sc);
2334 mutex_exit(&sc->sc_write_mtx);
2335 return error;
2336 }
2337
2338 #ifdef HAVE_EDCA
2339 Static void
otus_updateedca(struct ieee80211com * ic)2340 otus_updateedca(struct ieee80211com *ic)
2341 {
2342
2343 DPRINTFN(DBG_FN, DBG_NO_SC, "\n");
2344
2345 /* Do it in a process context. */
2346 otus_do_async(ic->ic_ifp->if_softc, otus_updateedca_cb, NULL, 0);
2347 }
2348
2349 Static void
otus_updateedca_cb(struct otus_softc * sc,void * arg __used)2350 otus_updateedca_cb(struct otus_softc *sc, void *arg __used)
2351 {
2352
2353 DPRINTFN(DBG_FN, sc, "\n");
2354
2355 mutex_enter(&sc->sc_write_mtx);
2356 otus_updateedca_cb_locked(sc);
2357 mutex_exit(&sc->sc_write_mtx);
2358 }
2359 #endif
2360
2361 Static void
otus_updateedca_cb_locked(struct otus_softc * sc)2362 otus_updateedca_cb_locked(struct otus_softc *sc)
2363 {
2364 #ifdef HAVE_EDCA
2365 struct ieee80211com *ic;
2366 #endif
2367 const struct ieee80211_edca_ac_params *edca;
2368 int s;
2369
2370 DPRINTFN(DBG_FN, sc, "\n");
2371
2372 KASSERT(mutex_owned(&sc->sc_write_mtx));
2373
2374 s = splnet();
2375
2376 #ifdef HAVE_EDCA
2377 ic = &sc->sc_ic;
2378 edca = (ic->ic_flags & IEEE80211_F_QOS) ?
2379 ic->ic_edca_ac : otus_edca_def;
2380 #else
2381 edca = otus_edca_def;
2382 #endif /* HAVE_EDCA */
2383
2384 #define EXP2(val) ((1 << (val)) - 1)
2385 #define AIFS(val) ((val) * 9 + 10)
2386
2387 /* Set CWmin/CWmax values. */
2388 otus_write(sc, AR_MAC_REG_AC0_CW,
2389 EXP2(edca[WME_AC_BE].ac_ecwmax) << 16 |
2390 EXP2(edca[WME_AC_BE].ac_ecwmin));
2391 otus_write(sc, AR_MAC_REG_AC1_CW,
2392 EXP2(edca[WME_AC_BK].ac_ecwmax) << 16 |
2393 EXP2(edca[WME_AC_BK].ac_ecwmin));
2394 otus_write(sc, AR_MAC_REG_AC2_CW,
2395 EXP2(edca[WME_AC_VI].ac_ecwmax) << 16 |
2396 EXP2(edca[WME_AC_VI].ac_ecwmin));
2397 otus_write(sc, AR_MAC_REG_AC3_CW,
2398 EXP2(edca[WME_AC_VO].ac_ecwmax) << 16 |
2399 EXP2(edca[WME_AC_VO].ac_ecwmin));
2400 otus_write(sc, AR_MAC_REG_AC4_CW, /* Special TXQ. */
2401 EXP2(edca[WME_AC_VO].ac_ecwmax) << 16 |
2402 EXP2(edca[WME_AC_VO].ac_ecwmin));
2403
2404 /* Set AIFSN values. */
2405 otus_write(sc, AR_MAC_REG_AC1_AC0_AIFS,
2406 AIFS(edca[WME_AC_VI].ac_aifsn) << 24 |
2407 AIFS(edca[WME_AC_BK].ac_aifsn) << 12 |
2408 AIFS(edca[WME_AC_BE].ac_aifsn));
2409 otus_write(sc, AR_MAC_REG_AC3_AC2_AIFS,
2410 AIFS(edca[WME_AC_VO].ac_aifsn) << 16 | /* Special TXQ. */
2411 AIFS(edca[WME_AC_VO].ac_aifsn) << 4 |
2412 AIFS(edca[WME_AC_VI].ac_aifsn) >> 8);
2413
2414 /* Set TXOP limit. */
2415 otus_write(sc, AR_MAC_REG_AC1_AC0_TXOP,
2416 edca[WME_AC_BK].ac_txoplimit << 16 |
2417 edca[WME_AC_BE].ac_txoplimit);
2418 otus_write(sc, AR_MAC_REG_AC3_AC2_TXOP,
2419 edca[WME_AC_VO].ac_txoplimit << 16 |
2420 edca[WME_AC_VI].ac_txoplimit);
2421 #undef AIFS
2422 #undef EXP2
2423
2424 splx(s);
2425
2426 (void)otus_write_barrier(sc);
2427 }
2428
2429 Static void
otus_updateslot(struct ifnet * ifp)2430 otus_updateslot(struct ifnet *ifp)
2431 {
2432 struct otus_softc *sc;
2433
2434 sc = ifp->if_softc;
2435
2436 DPRINTFN(DBG_FN, sc, "\n");
2437
2438 /* Do it in a process context. */
2439 otus_do_async(sc, otus_updateslot_cb, NULL, 0);
2440 }
2441
2442 /* ARGSUSED */
2443 Static void
otus_updateslot_cb(struct otus_softc * sc,void * arg)2444 otus_updateslot_cb(struct otus_softc *sc, void *arg)
2445 {
2446
2447 DPRINTFN(DBG_FN, sc, "\n");
2448
2449 mutex_enter(&sc->sc_write_mtx);
2450 otus_updateslot_cb_locked(sc);
2451 mutex_exit(&sc->sc_write_mtx);
2452 }
2453
2454 Static void
otus_updateslot_cb_locked(struct otus_softc * sc)2455 otus_updateslot_cb_locked(struct otus_softc *sc)
2456 {
2457 uint32_t slottime;
2458
2459 DPRINTFN(DBG_FN, sc, "\n");
2460
2461 KASSERT(mutex_owned(&sc->sc_write_mtx));
2462
2463 slottime = (sc->sc_ic.ic_flags & IEEE80211_F_SHSLOT) ? 9 : 20;
2464 otus_write(sc, AR_MAC_REG_SLOT_TIME, slottime << 10);
2465 (void)otus_write_barrier(sc);
2466 }
2467
2468 Static int
otus_init_mac(struct otus_softc * sc)2469 otus_init_mac(struct otus_softc *sc)
2470 {
2471 int error;
2472
2473 DPRINTFN(DBG_FN | DBG_INIT, sc, "\n");
2474
2475 KASSERT(mutex_owned(&sc->sc_write_mtx));
2476
2477 otus_write(sc, AR_MAC_REG_ACK_EXTENSION, 0x40);
2478 otus_write(sc, AR_MAC_REG_RETRY_MAX, 0);
2479 otus_write(sc, AR_MAC_REG_SNIFFER, AR_MAC_REG_SNIFFER_DEFAULTS);
2480 otus_write(sc, AR_MAC_REG_RX_THRESHOLD, 0xc1f80);
2481 otus_write(sc, AR_MAC_REG_RX_PE_DELAY, 0x70);
2482 otus_write(sc, AR_MAC_REG_EIFS_AND_SIFS, 0xa144000);
2483 otus_write(sc, AR_MAC_REG_SLOT_TIME, 9 << 10);
2484
2485 /* CF-END mode */
2486 otus_write(sc, 0x1c3b2c, 0x19000000);
2487
2488 /* NAV protects ACK only (in TXOP). */
2489 otus_write(sc, 0x1c3b38, 0x201);
2490
2491 /* Set beacon PHY CTRL's TPC to 0x7, TA1=1 */
2492 /* OTUS set AM to 0x1 */
2493 otus_write(sc, AR_MAC_REG_BCN_HT1, 0x8000170);
2494
2495 otus_write(sc, AR_MAC_REG_BACKOFF_PROTECT, 0x105);
2496
2497 /* AGG test code*/
2498 /* Aggregation MAX number and timeout */
2499 otus_write(sc, AR_MAC_REG_AMPDU_FACTOR, 0x10000a);
2500
2501 /* Filter any control frames, BAR is bit 24. */
2502 otus_write(sc, AR_MAC_REG_FRAMETYPE_FILTER, AR_MAC_REG_FTF_DEFAULTS);
2503
2504 /* Enable deaggregator, response in sniffer mode */
2505 otus_write(sc, 0x1c3c40, 0x1 | 1 << 30); /* XXX: was 0x1 */
2506
2507 /* rate sets */
2508 otus_write(sc, AR_MAC_REG_BASIC_RATE, 0x150f);
2509 otus_write(sc, AR_MAC_REG_MANDATORY_RATE, 0x150f);
2510 otus_write(sc, AR_MAC_REG_RTS_CTS_RATE, 0x10b01bb);
2511
2512 /* MIMO response control */
2513 otus_write(sc, 0x1c3694, 0x4003c1e); /* bit 26~28 otus-AM */
2514
2515 /* Switch MAC to OTUS interface. */
2516 otus_write(sc, 0x1c3600, 0x3);
2517
2518 otus_write(sc, AR_MAC_REG_AMPDU_RX_THRESH, 0xffff);
2519
2520 /* set PHY register read timeout (??) */
2521 otus_write(sc, AR_MAC_REG_MISC_680, 0xf00008);
2522
2523 /* Disable Rx TimeOut, workaround for BB. */
2524 otus_write(sc, AR_MAC_REG_RX_TIMEOUT, 0x0);
2525
2526 /* Set clock frequency to 88/80MHz. */
2527 otus_write(sc, AR_PWR_REG_CLOCK_SEL,
2528 AR_PWR_CLK_AHB_80_88MHZ | AR_PWR_CLK_DAC_160_INV_DLY);
2529
2530 /* Set WLAN DMA interrupt mode: generate intr per packet. */
2531 otus_write(sc, AR_MAC_REG_TXRX_MPI, 0x110011);
2532
2533 otus_write(sc, AR_MAC_REG_FCS_SELECT, AR_MAC_FCS_FIFO_PROT);
2534
2535 /* Disables the CF_END frame, undocumented register */
2536 otus_write(sc, AR_MAC_REG_TXOP_NOT_ENOUGH_INDICATION, 0x141e0f48);
2537
2538 /* Disable HW decryption for now. */
2539 otus_write(sc, AR_MAC_REG_ENCRYPTION,
2540 AR_MAC_REG_ENCRYPTION_DEFAULTS | AR_MAC_REG_ENCRYPTION_RX_SOFTWARE);
2541
2542 /*
2543 * XXX: should these be elsewhere?
2544 */
2545 /* Enable LED0 and LED1. */
2546 otus_write(sc, AR_GPIO_REG_PORT_TYPE, 3);
2547 otus_write(sc, AR_GPIO_REG_DATA,
2548 AR_GPIO_REG_DATA_LED0_ON | AR_GPIO_REG_DATA_LED1_ON);
2549
2550 /* Set USB Rx stream mode maximum frame number to 2. */
2551 otus_write(sc, AR_USB_REG_MAX_AGG_UPLOAD, (1 << 2));
2552
2553 /* Set USB Rx stream mode timeout to 10us. */
2554 otus_write(sc, AR_USB_REG_UPLOAD_TIME_CTL, 0x80);
2555
2556 if ((error = otus_write_barrier(sc)) != 0)
2557 return error;
2558
2559 /* Set default EDCA parameters. */
2560 otus_updateedca_cb_locked(sc);
2561 return 0;
2562 }
2563
2564 /*
2565 * Return default value for PHY register based on current operating mode.
2566 */
2567 Static uint32_t
otus_phy_get_def(struct otus_softc * sc,uint32_t reg)2568 otus_phy_get_def(struct otus_softc *sc, uint32_t reg)
2569 {
2570 int i;
2571
2572 DPRINTFN(DBG_FN, sc, "\n");
2573
2574 for (i = 0; i < __arraycount(ar5416_phy_regs); i++)
2575 if (AR_PHY(ar5416_phy_regs[i]) == reg)
2576 return sc->sc_phy_vals[i];
2577 return 0; /* Register not found. */
2578 }
2579
2580 /*
2581 * Update PHY's programming based on vendor-specific data stored in EEPROM.
2582 * This is for FEM-type devices only.
2583 */
2584 Static int
otus_set_board_values(struct otus_softc * sc,struct ieee80211_channel * c)2585 otus_set_board_values(struct otus_softc *sc, struct ieee80211_channel *c)
2586 {
2587 const struct ModalEepHeader *eep;
2588 uint32_t tmp, offset;
2589
2590 DPRINTFN(DBG_FN, sc, "\n");
2591
2592 if (IEEE80211_IS_CHAN_5GHZ(c))
2593 eep = &sc->sc_eeprom.modalHeader[0];
2594 else
2595 eep = &sc->sc_eeprom.modalHeader[1];
2596
2597 /* Offset of chain 2. */
2598 offset = 2 * 0x1000;
2599
2600 tmp = le32toh(eep->antCtrlCommon);
2601 otus_write(sc, AR_PHY_SWITCH_COM, tmp);
2602
2603 tmp = le32toh(eep->antCtrlChain[0]);
2604 otus_write(sc, AR_PHY_SWITCH_CHAIN_0, tmp);
2605
2606 tmp = le32toh(eep->antCtrlChain[1]);
2607 otus_write(sc, AR_PHY_SWITCH_CHAIN_0 + offset, tmp);
2608
2609 if (1 /* sc->sc_sco == AR_SCO_SCN */) {
2610 tmp = otus_phy_get_def(sc, AR_PHY_SETTLING);
2611 tmp &= ~(0x7f << 7);
2612 tmp |= (eep->switchSettling & 0x7f) << 7;
2613 otus_write(sc, AR_PHY_SETTLING, tmp);
2614 }
2615
2616 tmp = otus_phy_get_def(sc, AR_PHY_DESIRED_SZ);
2617 tmp &= ~0xffff;
2618 tmp |= eep->pgaDesiredSize << 8 | eep->adcDesiredSize;
2619 otus_write(sc, AR_PHY_DESIRED_SZ, tmp);
2620
2621 tmp = eep->txEndToXpaOff << 24 | eep->txEndToXpaOff << 16 |
2622 eep->txFrameToXpaOn << 8 | eep->txFrameToXpaOn;
2623 otus_write(sc, AR_PHY_RF_CTL4, tmp);
2624
2625 tmp = otus_phy_get_def(sc, AR_PHY_RF_CTL3);
2626 tmp &= ~(0xff << 16);
2627 tmp |= eep->txEndToRxOn << 16;
2628 otus_write(sc, AR_PHY_RF_CTL3, tmp);
2629
2630 tmp = otus_phy_get_def(sc, AR_PHY_CCA);
2631 tmp &= ~(0x7f << 12);
2632 tmp |= (eep->thresh62 & 0x7f) << 12;
2633 otus_write(sc, AR_PHY_CCA, tmp);
2634
2635 tmp = otus_phy_get_def(sc, AR_PHY_RXGAIN);
2636 tmp &= ~(0x3f << 12);
2637 tmp |= (eep->txRxAttenCh[0] & 0x3f) << 12;
2638 otus_write(sc, AR_PHY_RXGAIN, tmp);
2639
2640 tmp = otus_phy_get_def(sc, AR_PHY_RXGAIN + offset);
2641 tmp &= ~(0x3f << 12);
2642 tmp |= (eep->txRxAttenCh[1] & 0x3f) << 12;
2643 otus_write(sc, AR_PHY_RXGAIN + offset, tmp);
2644
2645 tmp = otus_phy_get_def(sc, AR_PHY_GAIN_2GHZ);
2646 tmp &= ~(0x3f << 18);
2647 tmp |= (eep->rxTxMarginCh[0] & 0x3f) << 18;
2648 if (IEEE80211_IS_CHAN_5GHZ(c)) {
2649 tmp &= ~(0xf << 10);
2650 tmp |= (eep->bswMargin[0] & 0xf) << 10;
2651 }
2652 otus_write(sc, AR_PHY_GAIN_2GHZ, tmp);
2653
2654 tmp = otus_phy_get_def(sc, AR_PHY_GAIN_2GHZ + offset);
2655 tmp &= ~(0x3f << 18);
2656 tmp |= (eep->rxTxMarginCh[1] & 0x3f) << 18;
2657 otus_write(sc, AR_PHY_GAIN_2GHZ + offset, tmp);
2658
2659 tmp = otus_phy_get_def(sc, AR_PHY_TIMING_CTRL4);
2660 tmp &= ~(0x3f << 5 | 0x1f);
2661 tmp |= (eep->iqCalICh[0] & 0x3f) << 5 | (eep->iqCalQCh[0] & 0x1f);
2662 otus_write(sc, AR_PHY_TIMING_CTRL4, tmp);
2663
2664 tmp = otus_phy_get_def(sc, AR_PHY_TIMING_CTRL4 + offset);
2665 tmp &= ~(0x3f << 5 | 0x1f);
2666 tmp |= (eep->iqCalICh[1] & 0x3f) << 5 | (eep->iqCalQCh[1] & 0x1f);
2667 otus_write(sc, AR_PHY_TIMING_CTRL4 + offset, tmp);
2668
2669 tmp = otus_phy_get_def(sc, AR_PHY_TPCRG1);
2670 tmp &= ~(0xf << 16);
2671 tmp |= (eep->xpd & 0xf) << 16;
2672 otus_write(sc, AR_PHY_TPCRG1, tmp);
2673
2674 return otus_write_barrier(sc);
2675 }
2676
2677 Static int
otus_program_phy(struct otus_softc * sc,struct ieee80211_channel * c)2678 otus_program_phy(struct otus_softc *sc, struct ieee80211_channel *c)
2679 {
2680 const uint32_t *vals;
2681 int error, i;
2682
2683 DPRINTFN(DBG_FN, sc, "\n");
2684
2685 /* Select PHY programming based on band and bandwidth. */
2686 if (IEEE80211_IS_CHAN_2GHZ(c))
2687 vals = ar5416_phy_vals_2ghz_20mhz;
2688 else
2689 vals = ar5416_phy_vals_5ghz_20mhz;
2690 for (i = 0; i < __arraycount(ar5416_phy_regs); i++)
2691 otus_write(sc, AR_PHY(ar5416_phy_regs[i]), vals[i]);
2692 sc->sc_phy_vals = vals;
2693
2694 if (sc->sc_eeprom.baseEepHeader.deviceType == 0x80) /* FEM */
2695 if ((error = otus_set_board_values(sc, c)) != 0)
2696 return error;
2697
2698 /* Initial Tx power settings. */
2699 otus_write(sc, AR_PHY_POWER_TX_RATE_MAX, 0x7f);
2700 otus_write(sc, AR_PHY_POWER_TX_RATE1, 0x3f3f3f3f);
2701 otus_write(sc, AR_PHY_POWER_TX_RATE2, 0x3f3f3f3f);
2702 otus_write(sc, AR_PHY_POWER_TX_RATE3, 0x3f3f3f3f);
2703 otus_write(sc, AR_PHY_POWER_TX_RATE4, 0x3f3f3f3f);
2704 otus_write(sc, AR_PHY_POWER_TX_RATE5, 0x3f3f3f3f);
2705 otus_write(sc, AR_PHY_POWER_TX_RATE6, 0x3f3f3f3f);
2706 otus_write(sc, AR_PHY_POWER_TX_RATE7, 0x3f3f3f3f);
2707 otus_write(sc, AR_PHY_POWER_TX_RATE8, 0x3f3f3f3f);
2708 otus_write(sc, AR_PHY_POWER_TX_RATE9, 0x3f3f3f3f);
2709
2710 if (IEEE80211_IS_CHAN_2GHZ(c))
2711 otus_write(sc, 0x1d4014, 0x5163);
2712 else
2713 otus_write(sc, 0x1d4014, 0x5143);
2714
2715 return otus_write_barrier(sc);
2716 }
2717
2718 static __inline uint8_t
otus_reverse_bits(uint8_t v)2719 otus_reverse_bits(uint8_t v)
2720 {
2721
2722 v = ((v >> 1) & 0x55) | ((v & 0x55) << 1);
2723 v = ((v >> 2) & 0x33) | ((v & 0x33) << 2);
2724 v = ((v >> 4) & 0x0f) | ((v & 0x0f) << 4);
2725 return v;
2726 }
2727
2728 Static int
otus_set_rf_bank4(struct otus_softc * sc,struct ieee80211_channel * c)2729 otus_set_rf_bank4(struct otus_softc *sc, struct ieee80211_channel *c)
2730 {
2731 uint8_t chansel, d0, d1;
2732 uint16_t data;
2733 int error;
2734
2735 DPRINTFN(DBG_FN, sc, "\n");
2736
2737 d0 = 0;
2738 if (IEEE80211_IS_CHAN_5GHZ(c)) {
2739 chansel = (c->ic_freq - 4800) / 5;
2740 if (chansel & 1)
2741 d0 |= AR_BANK4_AMODE_REFSEL(2);
2742 else
2743 d0 |= AR_BANK4_AMODE_REFSEL(1);
2744 } else {
2745 d0 |= AR_BANK4_AMODE_REFSEL(2);
2746 if (c->ic_freq == 2484) { /* CH 14 */
2747 d0 |= AR_BANK4_BMODE_LF_SYNTH_FREQ;
2748 chansel = 10 + (c->ic_freq - 2274) / 5;
2749 } else
2750 chansel = 16 + (c->ic_freq - 2272) / 5;
2751 chansel <<= 2;
2752 }
2753 d0 |= AR_BANK4_ADDR(1) | AR_BANK4_CHUP;
2754 d1 = otus_reverse_bits(chansel);
2755
2756 /* Write bits 0-4 of d0 and d1. */
2757 data = (d1 & 0x1f) << 5 | (d0 & 0x1f);
2758 otus_write(sc, AR_PHY(44), data);
2759 /* Write bits 5-7 of d0 and d1. */
2760 data = (d1 >> 5) << 5 | (d0 >> 5);
2761 otus_write(sc, AR_PHY(58), data);
2762
2763 if ((error = otus_write_barrier(sc)) == 0)
2764 usbd_delay_ms(sc->sc_udev, 10);
2765
2766 return error;
2767 }
2768
2769 Static void
otus_get_delta_slope(uint32_t coeff,uint32_t * exponent,uint32_t * mantissa)2770 otus_get_delta_slope(uint32_t coeff, uint32_t *exponent, uint32_t *mantissa)
2771 {
2772 #define COEFF_SCALE_SHIFT 24
2773 uint32_t exp, man;
2774
2775 DPRINTFN(DBG_FN, DBG_NO_SC, "\n");
2776
2777 /* exponent = 14 - floor(log2(coeff)) */
2778 for (exp = 31; exp > 0; exp--)
2779 if (coeff & (1 << exp))
2780 break;
2781 KASSERT(exp != 0);
2782 exp = 14 - (exp - COEFF_SCALE_SHIFT);
2783
2784 /* mantissa = floor(coeff * 2^exponent + 0.5) */
2785 man = coeff + (1 << (COEFF_SCALE_SHIFT - exp - 1));
2786
2787 *mantissa = man >> (COEFF_SCALE_SHIFT - exp);
2788 *exponent = exp - 16;
2789 #undef COEFF_SCALE_SHIFT
2790 }
2791
2792 Static int
otus_set_chan(struct otus_softc * sc,struct ieee80211_channel * c,int assoc)2793 otus_set_chan(struct otus_softc *sc, struct ieee80211_channel *c, int assoc)
2794 {
2795 struct ar_cmd_frequency cmd;
2796 struct ar_rsp_frequency rsp;
2797 const uint32_t *vals;
2798 uint32_t coeff, exp, man, tmp;
2799 uint8_t code;
2800 int error, i;
2801
2802 DPRINTFN(DBG_FN, sc, "\n");
2803
2804
2805 #ifdef OTUS_DEBUG
2806 struct ieee80211com *ic = &sc->sc_ic;
2807 int chan = ieee80211_chan2ieee(ic, c);
2808
2809 DPRINTFN(DBG_CHAN, sc, "setting channel %d (%dMHz)\n",
2810 chan, c->ic_freq);
2811 #endif
2812
2813 tmp = IEEE80211_IS_CHAN_2GHZ(c) ? 0x105 : 0x104;
2814 otus_write(sc, AR_MAC_REG_DYNAMIC_SIFS_ACK, tmp);
2815 if ((error = otus_write_barrier(sc)) != 0)
2816 return error;
2817
2818 /* Disable BB Heavy Clip. */
2819 otus_write(sc, AR_PHY_HEAVY_CLIP_ENABLE, 0x200);
2820 if ((error = otus_write_barrier(sc)) != 0)
2821 return error;
2822
2823 /* XXX Is that FREQ_START ? */
2824 error = otus_cmd(sc, AR_CMD_FREQ_STRAT, NULL, 0, NULL);
2825 if (error != 0)
2826 return error;
2827
2828 /* Reprogram PHY and RF on channel band or bandwidth changes. */
2829 if (sc->sc_bb_reset || c->ic_flags != sc->sc_curchan->ic_flags) {
2830 DPRINTFN(DBG_CHAN, sc, "band switch\n");
2831
2832 /* Cold/Warm reset BB/ADDA. */
2833 otus_write(sc, 0x1d4004, sc->sc_bb_reset ? 0x800 : 0x400);
2834 if ((error = otus_write_barrier(sc)) != 0)
2835 return error;
2836
2837 otus_write(sc, 0x1d4004, 0);
2838 if ((error = otus_write_barrier(sc)) != 0)
2839 return error;
2840 sc->sc_bb_reset = 0;
2841
2842 if ((error = otus_program_phy(sc, c)) != 0) {
2843 aprint_error_dev(sc->sc_dev,
2844 "could not program PHY\n");
2845 return error;
2846 }
2847
2848 /* Select RF programming based on band. */
2849 if (IEEE80211_IS_CHAN_5GHZ(c))
2850 vals = ar5416_banks_vals_5ghz;
2851 else
2852 vals = ar5416_banks_vals_2ghz;
2853 for (i = 0; i < __arraycount(ar5416_banks_regs); i++)
2854 otus_write(sc, AR_PHY(ar5416_banks_regs[i]), vals[i]);
2855 if ((error = otus_write_barrier(sc)) != 0) {
2856 aprint_error_dev(sc->sc_dev, "could not program RF\n");
2857 return error;
2858 }
2859 code = AR_CMD_RF_INIT;
2860 } else {
2861 code = AR_CMD_FREQUENCY;
2862 }
2863
2864 if ((error = otus_set_rf_bank4(sc, c)) != 0)
2865 return error;
2866
2867 tmp = (sc->sc_txmask == 0x5) ? 0x340 : 0x240;
2868 otus_write(sc, AR_PHY_TURBO, tmp);
2869 if ((error = otus_write_barrier(sc)) != 0)
2870 return error;
2871
2872 /* Send firmware command to set channel. */
2873 cmd.freq = htole32((uint32_t)c->ic_freq * 1000);
2874 cmd.dynht2040 = htole32(0);
2875 cmd.htena = htole32(1);
2876
2877 /* Set Delta Slope (exponent and mantissa). */
2878 coeff = (100 << 24) / c->ic_freq;
2879 otus_get_delta_slope(coeff, &exp, &man);
2880 cmd.dsc_exp = htole32(exp);
2881 cmd.dsc_man = htole32(man);
2882 DPRINTFN(DBG_CHAN, sc, "ds coeff=%u exp=%u man=%u\n",
2883 coeff, exp, man);
2884
2885 /* For Short GI, coeff is 9/10 that of normal coeff. */
2886 coeff = (9 * coeff) / 10;
2887 otus_get_delta_slope(coeff, &exp, &man);
2888 cmd.dsc_shgi_exp = htole32(exp);
2889 cmd.dsc_shgi_man = htole32(man);
2890 DPRINTFN(DBG_CHAN, sc, "ds shgi coeff=%u exp=%u man=%u\n",
2891 coeff, exp, man);
2892
2893 /* Set wait time for AGC and noise calibration (100 or 200ms). */
2894 cmd.check_loop_count = assoc ? htole32(2000) : htole32(1000);
2895 DPRINTFN(DBG_CHAN, sc, "%s\n",
2896 code == AR_CMD_RF_INIT ? "RF_INIT" : "FREQUENCY");
2897 error = otus_cmd(sc, code, &cmd, sizeof(cmd), &rsp);
2898 if (error != 0)
2899 return error;
2900
2901 if ((rsp.status & htole32(AR_CAL_ERR_AGC | AR_CAL_ERR_NF_VAL)) != 0) {
2902 DPRINTFN(DBG_CHAN, sc, "status=%#x\n", le32toh(rsp.status));
2903 /* Force cold reset on next channel. */
2904 sc->sc_bb_reset = 1;
2905 }
2906
2907 #ifdef OTUS_DEBUG
2908 if (otus_debug & DBG_CHAN) {
2909 DPRINTFN(DBG_CHAN, sc, "calibration status=%#x\n",
2910 le32toh(rsp.status));
2911 for (i = 0; i < 2; i++) { /* 2 Rx chains */
2912 /* Sign-extend 9-bit NF values. */
2913 DPRINTFN(DBG_CHAN, sc, "noisefloor chain %d=%d\n",
2914 i, (((int32_t)le32toh(rsp.nf[i])) << 4) >> 23);
2915 DPRINTFN(DBG_CHAN, sc, "noisefloor ext chain %d=%d\n",
2916 i, ((int32_t)le32toh(rsp.nf_ext[i])) >> 23);
2917 }
2918 }
2919 #endif
2920 sc->sc_curchan = c;
2921 return 0;
2922 }
2923
2924 #ifdef notyet
2925 Static int
otus_set_key(struct ieee80211com * ic,struct ieee80211_node * ni,struct ieee80211_key * k)2926 otus_set_key(struct ieee80211com *ic, struct ieee80211_node *ni,
2927 struct ieee80211_key *k)
2928 {
2929 struct otus_softc *sc;
2930 struct otus_cmd_key cmd;
2931
2932 sc = ic->ic_ifp->if_softc;
2933
2934 DPRINTFN(DBG_FN, sc, "\n");
2935
2936 /* Defer setting of WEP keys until interface is brought up. */
2937 if ((ic->ic_ifp->if_flags & (IFF_UP | IFF_RUNNING)) !=
2938 (IFF_UP | IFF_RUNNING))
2939 return 0;
2940
2941 /* Do it in a process context. */
2942 cmd.key = *k;
2943 cmd.associd = (ni != NULL) ? ni->ni_associd : 0;
2944 otus_do_async(sc, otus_set_key_cb, &cmd, sizeof(cmd));
2945 return 0;
2946 }
2947
2948 Static void
otus_set_key_cb(struct otus_softc * sc,void * arg)2949 otus_set_key_cb(struct otus_softc *sc, void *arg)
2950 {
2951 struct otus_cmd_key *cmd;
2952 struct ieee80211_key *k;
2953 struct ar_cmd_ekey key;
2954 uint16_t cipher;
2955 int error;
2956
2957 DPRINTFN(DBG_FN, sc, "\n");
2958
2959 cmd = arg;
2960 k = &cmd->key;
2961
2962 memset(&key, 0, sizeof(key));
2963 if (k->k_flags & IEEE80211_KEY_GROUP) {
2964 key.uid = htole16(k->k_id);
2965 IEEE80211_ADDR_COPY(key.macaddr, sc->sc_ic.ic_myaddr);
2966 key.macaddr[0] |= 0x80;
2967 } else {
2968 key.uid = htole16(OTUS_UID(cmd->associd));
2969 IEEE80211_ADDR_COPY(key.macaddr, ni->ni_macaddr);
2970 }
2971 key.kix = htole16(0);
2972 /* Map net80211 cipher to hardware. */
2973 switch (k->k_cipher) {
2974 case IEEE80211_CIPHER_WEP40:
2975 cipher = AR_CIPHER_WEP64;
2976 break;
2977 case IEEE80211_CIPHER_WEP104:
2978 cipher = AR_CIPHER_WEP128;
2979 break;
2980 case IEEE80211_CIPHER_TKIP:
2981 cipher = AR_CIPHER_TKIP;
2982 break;
2983 case IEEE80211_CIPHER_CCMP:
2984 cipher = AR_CIPHER_AES;
2985 break;
2986 default:
2987 return;
2988 }
2989 key.cipher = htole16(cipher);
2990 memcpy(key.key, k->k_key, MIN(k->k_len, 16));
2991 error = otus_cmd(sc, AR_CMD_EKEY, &key, sizeof(key), NULL);
2992 if (error != 0 || k->k_cipher != IEEE80211_CIPHER_TKIP)
2993 return;
2994
2995 /* TKIP: set Tx/Rx MIC Key. */
2996 key.kix = htole16(1);
2997 memcpy(key.key, k->k_key + 16, 16);
2998 (void)otus_cmd(sc, AR_CMD_EKEY, &key, sizeof(key), NULL);
2999 }
3000
3001 Static void
otus_delete_key(struct ieee80211com * ic,struct ieee80211_node * ni,struct ieee80211_key * k)3002 otus_delete_key(struct ieee80211com *ic, struct ieee80211_node *ni,
3003 struct ieee80211_key *k)
3004 {
3005 struct otus_softc *sc;
3006 struct otus_cmd_key cmd;
3007
3008 sc = ic->ic_ifp->if_softc;
3009
3010 DPRINTFN(DBG_FN, sc, "\n");
3011
3012 if (!(ic->ic_ifp->if_flags & IFF_RUNNING) ||
3013 ic->ic_state != IEEE80211_S_RUN)
3014 return; /* Nothing to do. */
3015
3016 /* Do it in a process context. */
3017 cmd.key = *k;
3018 cmd.associd = (ni != NULL) ? ni->ni_associd : 0;
3019 otus_do_async(sc, otus_delete_key_cb, &cmd, sizeof(cmd));
3020 }
3021
3022 Static void
otus_delete_key_cb(struct otus_softc * sc,void * arg)3023 otus_delete_key_cb(struct otus_softc *sc, void *arg)
3024 {
3025 struct otus_cmd_key *cmd;
3026 struct ieee80211_key *k;
3027 uint32_t uid;
3028
3029 DPRINTFN(DBG_FN, sc, "\n");
3030
3031 cmd = arg;
3032 k = &cmd->key;
3033 if (k->k_flags & IEEE80211_KEY_GROUP)
3034 uid = htole32(k->k_id);
3035 else
3036 uid = htole32(OTUS_UID(cmd->associd));
3037 (void)otus_cmd(sc, AR_CMD_DKEY, &uid, sizeof(uid), NULL);
3038 }
3039 #endif /* notyet */
3040
3041 Static void
otus_calib_to(void * arg)3042 otus_calib_to(void *arg)
3043 {
3044 struct otus_softc *sc;
3045 struct ieee80211com *ic;
3046 struct ieee80211_node *ni;
3047 struct otus_node *on;
3048 int s;
3049
3050 sc = arg;
3051
3052 DPRINTFN(DBG_FN, sc, "\n");
3053
3054 if (sc->sc_dying)
3055 return;
3056
3057 s = splnet();
3058 ic = &sc->sc_ic;
3059 ni = ic->ic_bss;
3060 on = (void *)ni;
3061 ieee80211_amrr_choose(&sc->sc_amrr, ni, &on->amn);
3062 splx(s);
3063
3064 if (!sc->sc_dying)
3065 callout_schedule(&sc->sc_calib_to, hz);
3066 }
3067
3068 Static int
otus_set_bssid(struct otus_softc * sc,const uint8_t * bssid)3069 otus_set_bssid(struct otus_softc *sc, const uint8_t *bssid)
3070 {
3071
3072 DPRINTFN(DBG_FN, sc, "\n");
3073
3074 KASSERT(mutex_owned(&sc->sc_write_mtx));
3075
3076 otus_write(sc, AR_MAC_REG_BSSID_L,
3077 bssid[0] | bssid[1] << 8 | bssid[2] << 16 | bssid[3] << 24);
3078 otus_write(sc, AR_MAC_REG_BSSID_H,
3079 bssid[4] | bssid[5] << 8);
3080 return otus_write_barrier(sc);
3081 }
3082
3083 Static int
otus_set_macaddr(struct otus_softc * sc,const uint8_t * addr)3084 otus_set_macaddr(struct otus_softc *sc, const uint8_t *addr)
3085 {
3086
3087 DPRINTFN(DBG_FN, sc, "\n");
3088
3089 KASSERT(mutex_owned(&sc->sc_write_mtx));
3090
3091 otus_write(sc, AR_MAC_REG_MAC_ADDR_L,
3092 addr[0] | addr[1] << 8 | addr[2] << 16 | addr[3] << 24);
3093 otus_write(sc, AR_MAC_REG_MAC_ADDR_H,
3094 addr[4] | addr[5] << 8);
3095 return otus_write_barrier(sc);
3096 }
3097
3098 #ifdef notyet
3099 /* Default single-LED. */
3100 Static void
otus_led_newstate_type1(struct otus_softc * sc)3101 otus_led_newstate_type1(struct otus_softc *sc)
3102 {
3103
3104 DPRINTFN(DBG_FN, sc, "\n");
3105
3106 /* TBD */
3107 }
3108
3109 /* NETGEAR, dual-LED. */
3110 Static void
otus_led_newstate_type2(struct otus_softc * sc)3111 otus_led_newstate_type2(struct otus_softc *sc)
3112 {
3113
3114 DPRINTFN(DBG_FN, sc, "\n");
3115
3116 /* TBD */
3117 }
3118 #endif /* notyet */
3119
3120 /*
3121 * NETGEAR, single-LED/3 colors (blue, red, purple.)
3122 */
3123 Static void
otus_led_newstate_type3(struct otus_softc * sc)3124 otus_led_newstate_type3(struct otus_softc *sc)
3125 {
3126 struct ieee80211com *ic;
3127 uint32_t led_state;
3128
3129 DPRINTFN(DBG_FN, sc, "\n");
3130
3131 ic = &sc->sc_ic;
3132 led_state = sc->sc_led_state;
3133 switch (ic->ic_state) {
3134 case IEEE80211_S_INIT:
3135 led_state = 0;
3136 break;
3137 case IEEE80211_S_SCAN:
3138 led_state ^= AR_GPIO_REG_DATA_LED0_ON | AR_GPIO_REG_DATA_LED1_ON;
3139 led_state &= ~(IEEE80211_IS_CHAN_2GHZ(sc->sc_curchan) ?
3140 AR_GPIO_REG_DATA_LED1_ON : AR_GPIO_REG_DATA_LED0_ON);
3141 break;
3142 case IEEE80211_S_AUTH:
3143 case IEEE80211_S_ASSOC:
3144 /* XXX: Turn both LEDs on for AUTH and ASSOC? */
3145 led_state = AR_GPIO_REG_DATA_LED0_ON | AR_GPIO_REG_DATA_LED1_ON;
3146 break;
3147 case IEEE80211_S_RUN:
3148 led_state = IEEE80211_IS_CHAN_2GHZ(sc->sc_curchan) ?
3149 AR_GPIO_REG_DATA_LED0_ON : AR_GPIO_REG_DATA_LED1_ON;
3150 break;
3151 }
3152 if (led_state != sc->sc_led_state) {
3153 otus_write(sc, AR_GPIO_REG_DATA, led_state);
3154 if (otus_write_barrier(sc) == 0)
3155 sc->sc_led_state = led_state;
3156 }
3157 }
3158
3159 Static int
otus_init(struct ifnet * ifp)3160 otus_init(struct ifnet *ifp)
3161 {
3162 struct otus_softc *sc;
3163 struct ieee80211com *ic;
3164 uint32_t filter, pm_mode, sniffer;
3165 int error;
3166
3167 sc = ifp->if_softc;
3168
3169 DPRINTFN(DBG_FN | DBG_INIT, sc, "\n");
3170
3171 ic = &sc->sc_ic;
3172
3173 mutex_enter(&sc->sc_write_mtx);
3174
3175 /* Init host command ring. */
3176 mutex_spin_enter(&sc->sc_task_mtx);
3177 sc->sc_cmdq.cur = sc->sc_cmdq.next = sc->sc_cmdq.queued = 0;
3178 mutex_spin_exit(&sc->sc_task_mtx);
3179
3180 if ((error = otus_init_mac(sc)) != 0) {
3181 mutex_exit(&sc->sc_write_mtx);
3182 aprint_error_dev(sc->sc_dev, "could not initialize MAC\n");
3183 return error;
3184 }
3185
3186 IEEE80211_ADDR_COPY(ic->ic_myaddr, CLLADDR(ifp->if_sadl));
3187 (void)otus_set_macaddr(sc, ic->ic_myaddr);
3188
3189 pm_mode = AR_MAC_REG_POWERMGT_DEFAULTS;
3190 sniffer = AR_MAC_REG_SNIFFER_DEFAULTS;
3191 filter = AR_MAC_REG_FTF_DEFAULTS;
3192 sc->sc_rx_error_msk = ~0;
3193
3194 switch (ic->ic_opmode) {
3195 #ifdef notyet
3196 #ifndef IEEE80211_STA_ONLY
3197 case IEEE80211_M_HOSTAP:
3198 pm_mode |= AR_MAC_REG_POWERMGT_AP;
3199 break;
3200 case IEEE80211_M_IBSS:
3201 pm_mode |= AR_MAC_REG_POWERMGT_IBSS; /* XXX: was 0x0 */
3202 break;
3203 #endif
3204 #endif
3205 case IEEE80211_M_STA:
3206 pm_mode |= AR_MAC_REG_POWERMGT_STA;
3207 break;
3208 case IEEE80211_M_MONITOR:
3209 sc->sc_rx_error_msk = ~AR_RX_ERROR_BAD_RA;
3210 filter = AR_MAC_REG_FTF_MONITOR;
3211 sniffer |= AR_MAC_REG_SNIFFER_ENABLE_PROMISC;
3212 break;
3213 default:
3214 aprint_error_dev(sc->sc_dev, "bad opmode: %d", ic->ic_opmode);
3215 return EOPNOTSUPP; /* XXX: ??? */
3216 }
3217 otus_write(sc, AR_MAC_REG_POWERMANAGEMENT, pm_mode);
3218 otus_write(sc, AR_MAC_REG_FRAMETYPE_FILTER, filter);
3219 otus_write(sc, AR_MAC_REG_SNIFFER, sniffer);
3220 (void)otus_write_barrier(sc);
3221
3222 sc->sc_bb_reset = 1; /* Force cold reset. */
3223 if ((error = otus_set_chan(sc, ic->ic_curchan, 0)) != 0) {
3224 mutex_exit(&sc->sc_write_mtx);
3225 aprint_error_dev(sc->sc_dev, "could not set channel\n");
3226 return error;
3227 }
3228
3229 /* Start Rx. */
3230 otus_write(sc, AR_MAC_REG_DMA, AR_MAC_REG_DMA_ENABLE);
3231 (void)otus_write_barrier(sc);
3232 mutex_exit(&sc->sc_write_mtx);
3233
3234 ifp->if_flags &= ~IFF_OACTIVE;
3235 ifp->if_flags |= IFF_RUNNING;
3236
3237 if (ic->ic_opmode == IEEE80211_M_MONITOR)
3238 ieee80211_new_state(ic, IEEE80211_S_RUN, -1);
3239 else
3240 ieee80211_new_state(ic, IEEE80211_S_SCAN, -1);
3241
3242 return 0;
3243 }
3244
3245 Static void
otus_stop(struct ifnet * ifp)3246 otus_stop(struct ifnet *ifp)
3247 {
3248 struct otus_softc *sc;
3249 struct ieee80211com *ic;
3250 int s;
3251
3252 sc = ifp->if_softc;
3253
3254 DPRINTFN(DBG_FN, sc, "\n");
3255
3256 ic = &sc->sc_ic;
3257
3258 sc->sc_tx_timer = 0;
3259 ifp->if_timer = 0;
3260 ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE);
3261
3262 callout_halt(&sc->sc_scan_to, NULL);
3263 callout_halt(&sc->sc_calib_to, NULL);
3264
3265 s = splusb();
3266 ieee80211_new_state(ic, IEEE80211_S_INIT, -1);
3267 otus_wait_async(sc);
3268 splx(s);
3269
3270 /* Stop Rx. */
3271 mutex_enter(&sc->sc_write_mtx);
3272 otus_write(sc, AR_MAC_REG_DMA, AR_MAC_REG_DMA_OFF);
3273 (void)otus_write_barrier(sc);
3274 mutex_exit(&sc->sc_write_mtx);
3275 }
3276