if_otus.c revision 1.44 1 /* $NetBSD: if_otus.c,v 1.44 2020/03/15 23:04:50 thorpej 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 (at) 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.44 2020/03/15 23:04:50 thorpej 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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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 *
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
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
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
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
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
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
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 mlen -= IEEE80211_CRC_LEN; /* strip 802.11 FCS */
1762 /* Make sure there's room for an 802.11 header. */
1763 /*
1764 * XXX: This will drop most control packets. Do we really
1765 * want this in IEEE80211_M_MONITOR mode?
1766 */
1767 if (__predict_false(mlen < sizeof(*wh))) {
1768 if_statinc(ifp, if_ierrors);
1769 return;
1770 }
1771
1772 /* Provide a 32-bit aligned protocol header to the stack. */
1773 align = (ieee80211_has_qos(wh) ^ ieee80211_has_addr4(wh)) ? 2 : 0;
1774
1775 MGETHDR(m, M_DONTWAIT, MT_DATA);
1776 if (__predict_false(m == NULL)) {
1777 if_statinc(ifp, if_ierrors);
1778 return;
1779 }
1780 if (align + mlen > MHLEN) {
1781 MCLGET(m, M_DONTWAIT);
1782 if (__predict_false(!(m->m_flags & M_EXT))) {
1783 if_statinc(ifp, if_ierrors);
1784 m_freem(m);
1785 return;
1786 }
1787 }
1788 /* Finalize mbuf. */
1789 m_set_rcvif(m, ifp);
1790 m->m_data += align;
1791 memcpy(mtod(m, void *), wh, mlen);
1792 m->m_pkthdr.len = m->m_len = mlen;
1793
1794 s = splnet();
1795 if (__predict_false(sc->sc_drvbpf != NULL)) {
1796 struct otus_rx_radiotap_header *tap;
1797
1798 tap = &sc->sc_rxtap;
1799 tap->wr_flags = 0;
1800 tap->wr_chan_freq = htole16(ic->ic_curchan->ic_freq);
1801 tap->wr_chan_flags = htole16(ic->ic_curchan->ic_flags);
1802 tap->wr_antsignal = tail->rssi;
1803 tap->wr_rate = 2; /* In case it can't be found below. */
1804 switch (tail->status & AR_RX_STATUS_MT_MASK) {
1805 case AR_RX_STATUS_MT_CCK:
1806 switch (plcp[0]) {
1807 case 10: tap->wr_rate = 2; break;
1808 case 20: tap->wr_rate = 4; break;
1809 case 55: tap->wr_rate = 11; break;
1810 case 110: tap->wr_rate = 22; break;
1811 }
1812 if (tail->status & AR_RX_STATUS_SHPREAMBLE)
1813 tap->wr_flags |= IEEE80211_RADIOTAP_F_SHORTPRE;
1814 break;
1815 case AR_RX_STATUS_MT_OFDM:
1816 switch (plcp[0] & 0xf) {
1817 case 0xb: tap->wr_rate = 12; break;
1818 case 0xf: tap->wr_rate = 18; break;
1819 case 0xa: tap->wr_rate = 24; break;
1820 case 0xe: tap->wr_rate = 36; break;
1821 case 0x9: tap->wr_rate = 48; break;
1822 case 0xd: tap->wr_rate = 72; break;
1823 case 0x8: tap->wr_rate = 96; break;
1824 case 0xc: tap->wr_rate = 108; break;
1825 }
1826 break;
1827 }
1828 bpf_mtap2(sc->sc_drvbpf, tap, sc->sc_rxtap_len, m, BPF_D_IN);
1829 }
1830
1831 ni = ieee80211_find_rxnode(ic, (struct ieee80211_frame_min *)wh);
1832
1833 /* push the frame up to the 802.11 stack */
1834 ieee80211_input(ic, m, ni, tail->rssi, 0);
1835
1836 /* Node is no longer needed. */
1837 ieee80211_free_node(ni);
1838 splx(s);
1839 }
1840
1841 Static void
1842 otus_rxeof(struct usbd_xfer *xfer, void *priv, usbd_status status)
1843 {
1844 struct otus_rx_data *data;
1845 struct otus_softc *sc;
1846 uint8_t *buf;
1847 struct ar_rx_head *head;
1848 uint16_t hlen;
1849 int len;
1850
1851 data = priv;
1852 sc = data->sc;
1853
1854 DPRINTFN(DBG_FN, sc, "\n");
1855
1856 buf = data->buf;
1857
1858 if (__predict_false(status != USBD_NORMAL_COMPLETION)) {
1859 DPRINTFN(DBG_RX, sc, "RX status=%d\n", status);
1860 if (status == USBD_STALLED)
1861 usbd_clear_endpoint_stall_async(sc->sc_data_rx_pipe);
1862 else if (status != USBD_CANCELLED) {
1863 DPRINTFN(DBG_RX, sc,
1864 "otus_rxeof: goto resubmit: status=%d\n", status);
1865 goto resubmit;
1866 }
1867 return;
1868 }
1869 usbd_get_xfer_status(xfer, NULL, NULL, &len, NULL);
1870
1871 while (len >= sizeof(*head)) {
1872 head = (void *)buf;
1873 if (__predict_false(head->tag != htole16(AR_RX_HEAD_TAG))) {
1874 DPRINTFN(DBG_RX, sc, "tag not valid %#x\n",
1875 le16toh(head->tag));
1876 break;
1877 }
1878 hlen = le16toh(head->len);
1879 if (__predict_false(sizeof(*head) + hlen > len)) {
1880 DPRINTFN(DBG_RX, sc, "xfer too short %d/%d\n",
1881 len, hlen);
1882 break;
1883 }
1884 /* Process sub-xfer. */
1885 otus_sub_rxeof(sc, (uint8_t *)&head[1], hlen);
1886
1887 /* Next sub-xfer is aligned on a 32-bit boundary. */
1888 hlen = roundup2(sizeof(*head) + hlen, 4);
1889 buf += hlen;
1890 len -= hlen;
1891 }
1892
1893 resubmit:
1894 usbd_setup_xfer(xfer, data, data->buf, OTUS_RXBUFSZ,
1895 USBD_SHORT_XFER_OK, USBD_NO_TIMEOUT, otus_rxeof);
1896 (void)usbd_transfer(data->xfer);
1897 }
1898
1899 Static void
1900 otus_txeof(struct usbd_xfer *xfer, void *priv, usbd_status status)
1901 {
1902 struct otus_tx_data *data;
1903 struct otus_softc *sc;
1904 struct ieee80211com *ic;
1905 struct ifnet *ifp;
1906 int s;
1907
1908 data = priv;
1909 sc = data->sc;
1910
1911 DPRINTFN(DBG_FN, sc, "\n");
1912
1913 /* Put this Tx buffer back to the free list. */
1914 mutex_enter(&sc->sc_tx_mtx);
1915 TAILQ_INSERT_TAIL(&sc->sc_tx_free_list, data, next);
1916 mutex_exit(&sc->sc_tx_mtx);
1917
1918 ic = &sc->sc_ic;
1919 ifp = ic->ic_ifp;
1920 if (__predict_false(status != USBD_NORMAL_COMPLETION)) {
1921 DPRINTFN(DBG_TX, sc, "TX status=%d\n", status);
1922 if (status == USBD_STALLED)
1923 usbd_clear_endpoint_stall_async(sc->sc_data_tx_pipe);
1924 if_statinc(ifp, if_oerrors);
1925 return;
1926 }
1927 if_statinc(ifp, if_opackets);
1928
1929 s = splnet();
1930 sc->sc_tx_timer = 0;
1931 ifp->if_flags &= ~IFF_OACTIVE; /* XXX: do after freeing Tx buffer? */
1932 otus_start(ifp);
1933 splx(s);
1934 }
1935
1936 Static int
1937 otus_tx(struct otus_softc *sc, struct mbuf *m, struct ieee80211_node *ni,
1938 struct otus_tx_data *data)
1939 {
1940 struct ieee80211com *ic;
1941 struct otus_node *on;
1942 struct ieee80211_frame *wh;
1943 struct ieee80211_key *k;
1944 struct ar_tx_head *head;
1945 uint32_t phyctl;
1946 uint16_t macctl, qos;
1947 uint8_t qid;
1948 int error, ridx, hasqos, xferlen;
1949
1950 DPRINTFN(DBG_FN, sc, "\n");
1951
1952 ic = &sc->sc_ic;
1953 on = (void *)ni;
1954
1955 wh = mtod(m, struct ieee80211_frame *);
1956 if ((wh->i_fc[1] & IEEE80211_FC1_PROTECTED)) {
1957 /* XXX: derived from upgt_tx_task() and ural_tx_data() */
1958 k = ieee80211_crypto_encap(ic, ni, m);
1959 if (k == NULL)
1960 return ENOBUFS;
1961
1962 /* Packet header may have moved, reset our local pointer. */
1963 wh = mtod(m, struct ieee80211_frame *);
1964 }
1965
1966 #ifdef HAVE_EDCA
1967 if ((hasqos = ieee80211_has_qos(wh))) {
1968 qos = ieee80211_get_qos(wh);
1969 qid = ieee80211_up_to_ac(ic, qos & IEEE80211_QOS_TID);
1970 } else {
1971 qos = 0;
1972 qid = WME_AC_BE;
1973 }
1974 #else
1975 hasqos = 0;
1976 qos = 0;
1977 qid = WME_AC_BE;
1978 #endif
1979
1980 /* Pickup a rate index. */
1981 if (IEEE80211_IS_MULTICAST(wh->i_addr1) ||
1982 (wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK) != IEEE80211_FC0_TYPE_DATA)
1983 ridx = (ic->ic_curmode == IEEE80211_MODE_11A) ?
1984 OTUS_RIDX_OFDM6 : OTUS_RIDX_CCK1;
1985 else if (ic->ic_fixed_rate != -1)
1986 ridx = sc->sc_fixed_ridx;
1987 else
1988 ridx = on->ridx[ni->ni_txrate];
1989
1990 phyctl = 0;
1991 macctl = AR_TX_MAC_BACKOFF | AR_TX_MAC_HW_DUR | AR_TX_MAC_QID(qid);
1992
1993 if (IEEE80211_IS_MULTICAST(wh->i_addr1) ||
1994 (hasqos && ((qos & IEEE80211_QOS_ACKPOLICY_MASK) ==
1995 IEEE80211_QOS_ACKPOLICY_NOACK)))
1996 macctl |= AR_TX_MAC_NOACK;
1997
1998 if (!IEEE80211_IS_MULTICAST(wh->i_addr1)) {
1999 if (m->m_pkthdr.len + IEEE80211_CRC_LEN >= ic->ic_rtsthreshold)
2000 macctl |= AR_TX_MAC_RTS;
2001 else if ((ic->ic_flags & IEEE80211_F_USEPROT) &&
2002 ridx >= OTUS_RIDX_OFDM6) {
2003 if (ic->ic_protmode == IEEE80211_PROT_CTSONLY)
2004 macctl |= AR_TX_MAC_CTS;
2005 else if (ic->ic_protmode == IEEE80211_PROT_RTSCTS)
2006 macctl |= AR_TX_MAC_RTS;
2007 }
2008 }
2009
2010 phyctl |= AR_TX_PHY_MCS(otus_rates[ridx].mcs);
2011 if (ridx >= OTUS_RIDX_OFDM6) {
2012 phyctl |= AR_TX_PHY_MT_OFDM;
2013 if (ridx <= OTUS_RIDX_OFDM24)
2014 phyctl |= AR_TX_PHY_ANTMSK(sc->sc_txmask);
2015 else
2016 phyctl |= AR_TX_PHY_ANTMSK(1);
2017 } else { /* CCK */
2018 phyctl |= AR_TX_PHY_MT_CCK;
2019 phyctl |= AR_TX_PHY_ANTMSK(sc->sc_txmask);
2020 }
2021
2022 /* Update rate control stats for frames that are ACK'ed. */
2023 if (!(macctl & AR_TX_MAC_NOACK))
2024 on->amn.amn_txcnt++;
2025
2026 /* Fill Tx descriptor. */
2027 head = (void *)data->buf;
2028 head->len = htole16(m->m_pkthdr.len + IEEE80211_CRC_LEN);
2029 head->macctl = htole16(macctl);
2030 head->phyctl = htole32(phyctl);
2031
2032 if (__predict_false(sc->sc_drvbpf != NULL)) {
2033 struct otus_tx_radiotap_header *tap = &sc->sc_txtap;
2034
2035 tap->wt_flags = 0;
2036 if (wh->i_fc[1] & IEEE80211_FC1_WEP)
2037 tap->wt_flags |= IEEE80211_RADIOTAP_F_WEP;
2038 tap->wt_rate = otus_rates[ridx].rate;
2039 tap->wt_chan_freq = htole16(ic->ic_curchan->ic_freq);
2040 tap->wt_chan_flags = htole16(ic->ic_curchan->ic_flags);
2041
2042 bpf_mtap2(sc->sc_drvbpf, tap, sc->sc_txtap_len, m, BPF_D_OUT);
2043 }
2044
2045 xferlen = sizeof(*head) + m->m_pkthdr.len;
2046 m_copydata(m, 0, m->m_pkthdr.len, (void *)&head[1]);
2047
2048 DPRINTFN(DBG_TX, sc, "queued len=%d mac=0x%04x phy=0x%08x rate=%d\n",
2049 head->len, head->macctl, head->phyctl, otus_rates[ridx].rate);
2050
2051 usbd_setup_xfer(data->xfer, data, data->buf, xferlen,
2052 USBD_FORCE_SHORT_XFER, OTUS_TX_TIMEOUT, otus_txeof);
2053 error = usbd_transfer(data->xfer);
2054 if (__predict_false(
2055 error != USBD_NORMAL_COMPLETION &&
2056 error != USBD_IN_PROGRESS)) {
2057 DPRINTFN(DBG_TX, sc, "transfer failed %d\n", error);
2058 return error;
2059 }
2060 return 0;
2061 }
2062
2063 Static void
2064 otus_start(struct ifnet *ifp)
2065 {
2066 struct otus_softc *sc;
2067 struct ieee80211com *ic;
2068 struct otus_tx_data *data;
2069 struct ether_header *eh;
2070 struct ieee80211_node *ni;
2071 struct mbuf *m;
2072
2073 if ((ifp->if_flags & (IFF_RUNNING | IFF_OACTIVE)) != IFF_RUNNING)
2074 return;
2075
2076 sc = ifp->if_softc;
2077 ic = &sc->sc_ic;
2078
2079 DPRINTFN(DBG_FN, sc, "\n");
2080
2081 data = NULL;
2082 for (;;) {
2083 /*
2084 * Grab a Tx buffer if we don't already have one. If
2085 * one isn't available, bail out.
2086 * NB: We must obtain this Tx buffer _before_
2087 * dequeueing anything as one may not be available
2088 * later. Both must be done inside a single lock.
2089 */
2090 mutex_enter(&sc->sc_tx_mtx);
2091 if (data == NULL && !TAILQ_EMPTY(&sc->sc_tx_free_list)) {
2092 data = TAILQ_FIRST(&sc->sc_tx_free_list);
2093 TAILQ_REMOVE(&sc->sc_tx_free_list, data, next);
2094 }
2095 mutex_exit(&sc->sc_tx_mtx);
2096
2097 if (data == NULL) {
2098 ifp->if_flags |= IFF_OACTIVE;
2099 DPRINTFN(DBG_TX, sc, "empty sc_tx_free_list\n");
2100 return;
2101 }
2102
2103 /* Send pending management frames first. */
2104 IF_DEQUEUE(&ic->ic_mgtq, m);
2105 if (m != NULL) {
2106 ni = M_GETCTX(m, struct ieee80211_node *);
2107 M_CLEARCTX(m);
2108 goto sendit;
2109 }
2110
2111 if (ic->ic_state != IEEE80211_S_RUN)
2112 break;
2113
2114 /* Encapsulate and send data frames. */
2115 IFQ_DEQUEUE(&ifp->if_snd, m);
2116 if (m == NULL)
2117 break;
2118
2119 if (m->m_len < (int)sizeof(*eh) &&
2120 (m = m_pullup(m, sizeof(*eh))) == NULL) {
2121 if_statinc(ifp, if_oerrors);
2122 continue;
2123 }
2124
2125 eh = mtod(m, struct ether_header *);
2126 ni = ieee80211_find_txnode(ic, eh->ether_dhost);
2127 if (ni == NULL) {
2128 m_freem(m);
2129 if_statinc(ifp, if_oerrors);
2130 continue;
2131 }
2132
2133 bpf_mtap(ifp, m, BPF_D_OUT);
2134
2135 if ((m = ieee80211_encap(ic, m, ni)) == NULL) {
2136 /* original m was freed by ieee80211_encap() */
2137 ieee80211_free_node(ni);
2138 if_statinc(ifp, if_oerrors);
2139 continue;
2140 }
2141 sendit:
2142 bpf_mtap3(ic->ic_rawbpf, m, BPF_D_OUT);
2143
2144 if (otus_tx(sc, m, ni, data) != 0) {
2145 m_freem(m);
2146 ieee80211_free_node(ni);
2147 if_statinc(ifp, if_oerrors);
2148 continue;
2149 }
2150
2151 data = NULL; /* we're finished with this data buffer */
2152 m_freem(m);
2153 ieee80211_free_node(ni);
2154 sc->sc_tx_timer = 5;
2155 ifp->if_timer = 1;
2156 }
2157
2158 /*
2159 * If here, we have a Tx buffer, but ran out of mbufs to
2160 * transmit. Put the Tx buffer back to the free list.
2161 */
2162 mutex_enter(&sc->sc_tx_mtx);
2163 TAILQ_INSERT_TAIL(&sc->sc_tx_free_list, data, next);
2164 mutex_exit(&sc->sc_tx_mtx);
2165 }
2166
2167 Static void
2168 otus_watchdog(struct ifnet *ifp)
2169 {
2170 struct otus_softc *sc;
2171
2172 sc = ifp->if_softc;
2173
2174 DPRINTFN(DBG_FN, sc, "\n");
2175
2176 ifp->if_timer = 0;
2177
2178 if (sc->sc_tx_timer > 0) {
2179 if (--sc->sc_tx_timer == 0) {
2180 aprint_error_dev(sc->sc_dev, "device timeout\n");
2181 /* otus_init(ifp); XXX needs a process context! */
2182 if_statinc(ifp, if_oerrors);
2183 return;
2184 }
2185 ifp->if_timer = 1;
2186 }
2187 ieee80211_watchdog(&sc->sc_ic);
2188 }
2189
2190 Static int
2191 otus_ioctl(struct ifnet *ifp, u_long cmd, void *data)
2192 {
2193 struct otus_softc *sc;
2194 struct ieee80211com *ic;
2195 int s, error = 0;
2196
2197 sc = ifp->if_softc;
2198
2199 DPRINTFN(DBG_FN, sc, "%#lx\n", cmd);
2200
2201 ic = &sc->sc_ic;
2202
2203 s = splnet();
2204
2205 switch (cmd) {
2206 case SIOCSIFADDR:
2207 ifp->if_flags |= IFF_UP;
2208 #ifdef INET
2209 struct ifaddr *ifa = data;
2210 if (ifa->ifa_addr->sa_family == AF_INET)
2211 arp_ifinit(&ic->ic_ac, ifa);
2212 #endif
2213 /* FALLTHROUGH */
2214 case SIOCSIFFLAGS:
2215 if ((error = ifioctl_common(ifp, cmd, data)) != 0)
2216 break;
2217
2218 switch (ifp->if_flags & (IFF_UP | IFF_RUNNING)) {
2219 case IFF_UP | IFF_RUNNING:
2220 if (((ifp->if_flags ^ sc->sc_if_flags) &
2221 (IFF_ALLMULTI | IFF_PROMISC)) != 0)
2222 otus_set_multi(sc);
2223 break;
2224 case IFF_UP:
2225 otus_init(ifp);
2226 break;
2227
2228 case IFF_RUNNING:
2229 otus_stop(ifp);
2230 break;
2231 case 0:
2232 default:
2233 break;
2234 }
2235 sc->sc_if_flags = ifp->if_flags;
2236 break;
2237
2238 case SIOCADDMULTI:
2239 case SIOCDELMULTI:
2240 if ((error = ether_ioctl(ifp, cmd, data)) == ENETRESET) {
2241 /* setup multicast filter, etc */
2242 /* XXX: ??? */
2243 error = 0;
2244 }
2245 break;
2246
2247 case SIOCS80211CHANNEL:
2248 /*
2249 * This allows for fast channel switching in monitor mode
2250 * (used by kismet). In IBSS mode, we must explicitly reset
2251 * the interface to generate a new beacon frame.
2252 */
2253 error = ieee80211_ioctl(ic, cmd, data);
2254
2255 DPRINTFN(DBG_CHAN, sc,
2256 "ic_curchan=%d ic_ibss_chan=%d ic_des_chan=%d ni_chan=%d error=%d\n",
2257 ieee80211_chan2ieee(ic, ic->ic_curchan),
2258 ieee80211_chan2ieee(ic, ic->ic_ibss_chan),
2259 ieee80211_chan2ieee(ic, ic->ic_des_chan),
2260 ieee80211_chan2ieee(ic, ic->ic_bss->ni_chan),
2261 error);
2262
2263 if (error == ENETRESET &&
2264 ic->ic_opmode == IEEE80211_M_MONITOR) {
2265 if ((ifp->if_flags & (IFF_UP | IFF_RUNNING)) ==
2266 (IFF_UP | IFF_RUNNING)) {
2267 mutex_enter(&sc->sc_write_mtx);
2268 otus_set_chan(sc, ic->ic_curchan, 0);
2269 mutex_exit(&sc->sc_write_mtx);
2270 }
2271 error = 0;
2272 }
2273 break;
2274
2275 default:
2276 error = ieee80211_ioctl(ic, cmd, data);
2277 }
2278 if (error == ENETRESET) {
2279 if ((ifp->if_flags & (IFF_UP | IFF_RUNNING)) ==
2280 (IFF_UP | IFF_RUNNING))
2281 otus_init(ifp);
2282 error = 0;
2283 }
2284 splx(s);
2285 return error;
2286 }
2287
2288 Static int
2289 otus_set_multi(struct otus_softc *sc)
2290 {
2291 struct ethercom *ec = &sc->sc_ec;
2292 struct ifnet *ifp;
2293 struct ether_multi *enm;
2294 struct ether_multistep step;
2295 uint32_t lo, hi;
2296 uint8_t bit;
2297 int error;
2298
2299 DPRINTFN(DBG_FN, sc, "\n");
2300
2301 ifp = sc->sc_ic.ic_ifp;
2302 if ((ifp->if_flags & (IFF_ALLMULTI | IFF_PROMISC)) != 0) {
2303 lo = hi = 0xffffffff;
2304 goto done;
2305 }
2306 lo = hi = 0;
2307 ETHER_LOCK(ec);
2308 ETHER_FIRST_MULTI(step, ec, enm);
2309 while (enm != NULL) {
2310 if (bcmp(enm->enm_addrlo, enm->enm_addrhi, ETHER_ADDR_LEN)) {
2311 ifp->if_flags |= IFF_ALLMULTI;
2312 lo = hi = 0xffffffff;
2313 goto done;
2314 }
2315 bit = enm->enm_addrlo[5] >> 2;
2316 if (bit < 32)
2317 lo |= 1 << bit;
2318 else
2319 hi |= 1 << (bit - 32);
2320 ETHER_NEXT_MULTI(step, enm);
2321 }
2322 done:
2323 ETHER_UNLOCK(ec);
2324 mutex_enter(&sc->sc_write_mtx);
2325 hi |= 1 << 31; /* Make sure the broadcast bit is set. */
2326 otus_write(sc, AR_MAC_REG_GROUP_HASH_TBL_L, lo);
2327 otus_write(sc, AR_MAC_REG_GROUP_HASH_TBL_H, hi);
2328 error = otus_write_barrier(sc);
2329 mutex_exit(&sc->sc_write_mtx);
2330 return error;
2331 }
2332
2333 #ifdef HAVE_EDCA
2334 Static void
2335 otus_updateedca(struct ieee80211com *ic)
2336 {
2337
2338 DPRINTFN(DBG_FN, DBG_NO_SC, "\n");
2339
2340 /* Do it in a process context. */
2341 otus_do_async(ic->ic_ifp->if_softc, otus_updateedca_cb, NULL, 0);
2342 }
2343
2344 Static void
2345 otus_updateedca_cb(struct otus_softc *sc, void *arg __used)
2346 {
2347
2348 DPRINTFN(DBG_FN, sc, "\n");
2349
2350 mutex_enter(&sc->sc_write_mtx);
2351 otus_updateedca_cb_locked(sc);
2352 mutex_exit(&sc->sc_write_mtx);
2353 }
2354 #endif
2355
2356 Static void
2357 otus_updateedca_cb_locked(struct otus_softc *sc)
2358 {
2359 #ifdef HAVE_EDCA
2360 struct ieee80211com *ic;
2361 #endif
2362 const struct ieee80211_edca_ac_params *edca;
2363 int s;
2364
2365 DPRINTFN(DBG_FN, sc, "\n");
2366
2367 KASSERT(mutex_owned(&sc->sc_write_mtx));
2368
2369 s = splnet();
2370
2371 #ifdef HAVE_EDCA
2372 ic = &sc->sc_ic;
2373 edca = (ic->ic_flags & IEEE80211_F_QOS) ?
2374 ic->ic_edca_ac : otus_edca_def;
2375 #else
2376 edca = otus_edca_def;
2377 #endif /* HAVE_EDCA */
2378
2379 #define EXP2(val) ((1 << (val)) - 1)
2380 #define AIFS(val) ((val) * 9 + 10)
2381
2382 /* Set CWmin/CWmax values. */
2383 otus_write(sc, AR_MAC_REG_AC0_CW,
2384 EXP2(edca[WME_AC_BE].ac_ecwmax) << 16 |
2385 EXP2(edca[WME_AC_BE].ac_ecwmin));
2386 otus_write(sc, AR_MAC_REG_AC1_CW,
2387 EXP2(edca[WME_AC_BK].ac_ecwmax) << 16 |
2388 EXP2(edca[WME_AC_BK].ac_ecwmin));
2389 otus_write(sc, AR_MAC_REG_AC2_CW,
2390 EXP2(edca[WME_AC_VI].ac_ecwmax) << 16 |
2391 EXP2(edca[WME_AC_VI].ac_ecwmin));
2392 otus_write(sc, AR_MAC_REG_AC3_CW,
2393 EXP2(edca[WME_AC_VO].ac_ecwmax) << 16 |
2394 EXP2(edca[WME_AC_VO].ac_ecwmin));
2395 otus_write(sc, AR_MAC_REG_AC4_CW, /* Special TXQ. */
2396 EXP2(edca[WME_AC_VO].ac_ecwmax) << 16 |
2397 EXP2(edca[WME_AC_VO].ac_ecwmin));
2398
2399 /* Set AIFSN values. */
2400 otus_write(sc, AR_MAC_REG_AC1_AC0_AIFS,
2401 AIFS(edca[WME_AC_VI].ac_aifsn) << 24 |
2402 AIFS(edca[WME_AC_BK].ac_aifsn) << 12 |
2403 AIFS(edca[WME_AC_BE].ac_aifsn));
2404 otus_write(sc, AR_MAC_REG_AC3_AC2_AIFS,
2405 AIFS(edca[WME_AC_VO].ac_aifsn) << 16 | /* Special TXQ. */
2406 AIFS(edca[WME_AC_VO].ac_aifsn) << 4 |
2407 AIFS(edca[WME_AC_VI].ac_aifsn) >> 8);
2408
2409 /* Set TXOP limit. */
2410 otus_write(sc, AR_MAC_REG_AC1_AC0_TXOP,
2411 edca[WME_AC_BK].ac_txoplimit << 16 |
2412 edca[WME_AC_BE].ac_txoplimit);
2413 otus_write(sc, AR_MAC_REG_AC3_AC2_TXOP,
2414 edca[WME_AC_VO].ac_txoplimit << 16 |
2415 edca[WME_AC_VI].ac_txoplimit);
2416 #undef AIFS
2417 #undef EXP2
2418
2419 splx(s);
2420
2421 (void)otus_write_barrier(sc);
2422 }
2423
2424 Static void
2425 otus_updateslot(struct ifnet *ifp)
2426 {
2427 struct otus_softc *sc;
2428
2429 sc = ifp->if_softc;
2430
2431 DPRINTFN(DBG_FN, sc, "\n");
2432
2433 /* Do it in a process context. */
2434 otus_do_async(sc, otus_updateslot_cb, NULL, 0);
2435 }
2436
2437 /* ARGSUSED */
2438 Static void
2439 otus_updateslot_cb(struct otus_softc *sc, void *arg)
2440 {
2441
2442 DPRINTFN(DBG_FN, sc, "\n");
2443
2444 mutex_enter(&sc->sc_write_mtx);
2445 otus_updateslot_cb_locked(sc);
2446 mutex_exit(&sc->sc_write_mtx);
2447 }
2448
2449 Static void
2450 otus_updateslot_cb_locked(struct otus_softc *sc)
2451 {
2452 uint32_t slottime;
2453
2454 DPRINTFN(DBG_FN, sc, "\n");
2455
2456 KASSERT(mutex_owned(&sc->sc_write_mtx));
2457
2458 slottime = (sc->sc_ic.ic_flags & IEEE80211_F_SHSLOT) ? 9 : 20;
2459 otus_write(sc, AR_MAC_REG_SLOT_TIME, slottime << 10);
2460 (void)otus_write_barrier(sc);
2461 }
2462
2463 Static int
2464 otus_init_mac(struct otus_softc *sc)
2465 {
2466 int error;
2467
2468 DPRINTFN(DBG_FN | DBG_INIT, sc, "\n");
2469
2470 KASSERT(mutex_owned(&sc->sc_write_mtx));
2471
2472 otus_write(sc, AR_MAC_REG_ACK_EXTENSION, 0x40);
2473 otus_write(sc, AR_MAC_REG_RETRY_MAX, 0);
2474 otus_write(sc, AR_MAC_REG_SNIFFER, AR_MAC_REG_SNIFFER_DEFAULTS);
2475 otus_write(sc, AR_MAC_REG_RX_THRESHOLD, 0xc1f80);
2476 otus_write(sc, AR_MAC_REG_RX_PE_DELAY, 0x70);
2477 otus_write(sc, AR_MAC_REG_EIFS_AND_SIFS, 0xa144000);
2478 otus_write(sc, AR_MAC_REG_SLOT_TIME, 9 << 10);
2479
2480 /* CF-END mode */
2481 otus_write(sc, 0x1c3b2c, 0x19000000);
2482
2483 /* NAV protects ACK only (in TXOP). */
2484 otus_write(sc, 0x1c3b38, 0x201);
2485
2486 /* Set beacon PHY CTRL's TPC to 0x7, TA1=1 */
2487 /* OTUS set AM to 0x1 */
2488 otus_write(sc, AR_MAC_REG_BCN_HT1, 0x8000170);
2489
2490 otus_write(sc, AR_MAC_REG_BACKOFF_PROTECT, 0x105);
2491
2492 /* AGG test code*/
2493 /* Aggregation MAX number and timeout */
2494 otus_write(sc, AR_MAC_REG_AMPDU_FACTOR, 0x10000a);
2495
2496 /* Filter any control frames, BAR is bit 24. */
2497 otus_write(sc, AR_MAC_REG_FRAMETYPE_FILTER, AR_MAC_REG_FTF_DEFAULTS);
2498
2499 /* Enable deaggregator, response in sniffer mode */
2500 otus_write(sc, 0x1c3c40, 0x1 | 1 << 30); /* XXX: was 0x1 */
2501
2502 /* rate sets */
2503 otus_write(sc, AR_MAC_REG_BASIC_RATE, 0x150f);
2504 otus_write(sc, AR_MAC_REG_MANDATORY_RATE, 0x150f);
2505 otus_write(sc, AR_MAC_REG_RTS_CTS_RATE, 0x10b01bb);
2506
2507 /* MIMO response control */
2508 otus_write(sc, 0x1c3694, 0x4003c1e); /* bit 26~28 otus-AM */
2509
2510 /* Switch MAC to OTUS interface. */
2511 otus_write(sc, 0x1c3600, 0x3);
2512
2513 otus_write(sc, AR_MAC_REG_AMPDU_RX_THRESH, 0xffff);
2514
2515 /* set PHY register read timeout (??) */
2516 otus_write(sc, AR_MAC_REG_MISC_680, 0xf00008);
2517
2518 /* Disable Rx TimeOut, workaround for BB. */
2519 otus_write(sc, AR_MAC_REG_RX_TIMEOUT, 0x0);
2520
2521 /* Set clock frequency to 88/80MHz. */
2522 otus_write(sc, AR_PWR_REG_CLOCK_SEL,
2523 AR_PWR_CLK_AHB_80_88MHZ | AR_PWR_CLK_DAC_160_INV_DLY);
2524
2525 /* Set WLAN DMA interrupt mode: generate intr per packet. */
2526 otus_write(sc, AR_MAC_REG_TXRX_MPI, 0x110011);
2527
2528 otus_write(sc, AR_MAC_REG_FCS_SELECT, AR_MAC_FCS_FIFO_PROT);
2529
2530 /* Disables the CF_END frame, undocumented register */
2531 otus_write(sc, AR_MAC_REG_TXOP_NOT_ENOUGH_INDICATION, 0x141e0f48);
2532
2533 /* Disable HW decryption for now. */
2534 otus_write(sc, AR_MAC_REG_ENCRYPTION,
2535 AR_MAC_REG_ENCRYPTION_DEFAULTS | AR_MAC_REG_ENCRYPTION_RX_SOFTWARE);
2536
2537 /*
2538 * XXX: should these be elsewhere?
2539 */
2540 /* Enable LED0 and LED1. */
2541 otus_write(sc, AR_GPIO_REG_PORT_TYPE, 3);
2542 otus_write(sc, AR_GPIO_REG_DATA,
2543 AR_GPIO_REG_DATA_LED0_ON | AR_GPIO_REG_DATA_LED1_ON);
2544
2545 /* Set USB Rx stream mode maximum frame number to 2. */
2546 otus_write(sc, AR_USB_REG_MAX_AGG_UPLOAD, (1 << 2));
2547
2548 /* Set USB Rx stream mode timeout to 10us. */
2549 otus_write(sc, AR_USB_REG_UPLOAD_TIME_CTL, 0x80);
2550
2551 if ((error = otus_write_barrier(sc)) != 0)
2552 return error;
2553
2554 /* Set default EDCA parameters. */
2555 otus_updateedca_cb_locked(sc);
2556 return 0;
2557 }
2558
2559 /*
2560 * Return default value for PHY register based on current operating mode.
2561 */
2562 Static uint32_t
2563 otus_phy_get_def(struct otus_softc *sc, uint32_t reg)
2564 {
2565 int i;
2566
2567 DPRINTFN(DBG_FN, sc, "\n");
2568
2569 for (i = 0; i < __arraycount(ar5416_phy_regs); i++)
2570 if (AR_PHY(ar5416_phy_regs[i]) == reg)
2571 return sc->sc_phy_vals[i];
2572 return 0; /* Register not found. */
2573 }
2574
2575 /*
2576 * Update PHY's programming based on vendor-specific data stored in EEPROM.
2577 * This is for FEM-type devices only.
2578 */
2579 Static int
2580 otus_set_board_values(struct otus_softc *sc, struct ieee80211_channel *c)
2581 {
2582 const struct ModalEepHeader *eep;
2583 uint32_t tmp, offset;
2584
2585 DPRINTFN(DBG_FN, sc, "\n");
2586
2587 if (IEEE80211_IS_CHAN_5GHZ(c))
2588 eep = &sc->sc_eeprom.modalHeader[0];
2589 else
2590 eep = &sc->sc_eeprom.modalHeader[1];
2591
2592 /* Offset of chain 2. */
2593 offset = 2 * 0x1000;
2594
2595 tmp = le32toh(eep->antCtrlCommon);
2596 otus_write(sc, AR_PHY_SWITCH_COM, tmp);
2597
2598 tmp = le32toh(eep->antCtrlChain[0]);
2599 otus_write(sc, AR_PHY_SWITCH_CHAIN_0, tmp);
2600
2601 tmp = le32toh(eep->antCtrlChain[1]);
2602 otus_write(sc, AR_PHY_SWITCH_CHAIN_0 + offset, tmp);
2603
2604 if (1 /* sc->sc_sco == AR_SCO_SCN */) {
2605 tmp = otus_phy_get_def(sc, AR_PHY_SETTLING);
2606 tmp &= ~(0x7f << 7);
2607 tmp |= (eep->switchSettling & 0x7f) << 7;
2608 otus_write(sc, AR_PHY_SETTLING, tmp);
2609 }
2610
2611 tmp = otus_phy_get_def(sc, AR_PHY_DESIRED_SZ);
2612 tmp &= ~0xffff;
2613 tmp |= eep->pgaDesiredSize << 8 | eep->adcDesiredSize;
2614 otus_write(sc, AR_PHY_DESIRED_SZ, tmp);
2615
2616 tmp = eep->txEndToXpaOff << 24 | eep->txEndToXpaOff << 16 |
2617 eep->txFrameToXpaOn << 8 | eep->txFrameToXpaOn;
2618 otus_write(sc, AR_PHY_RF_CTL4, tmp);
2619
2620 tmp = otus_phy_get_def(sc, AR_PHY_RF_CTL3);
2621 tmp &= ~(0xff << 16);
2622 tmp |= eep->txEndToRxOn << 16;
2623 otus_write(sc, AR_PHY_RF_CTL3, tmp);
2624
2625 tmp = otus_phy_get_def(sc, AR_PHY_CCA);
2626 tmp &= ~(0x7f << 12);
2627 tmp |= (eep->thresh62 & 0x7f) << 12;
2628 otus_write(sc, AR_PHY_CCA, tmp);
2629
2630 tmp = otus_phy_get_def(sc, AR_PHY_RXGAIN);
2631 tmp &= ~(0x3f << 12);
2632 tmp |= (eep->txRxAttenCh[0] & 0x3f) << 12;
2633 otus_write(sc, AR_PHY_RXGAIN, tmp);
2634
2635 tmp = otus_phy_get_def(sc, AR_PHY_RXGAIN + offset);
2636 tmp &= ~(0x3f << 12);
2637 tmp |= (eep->txRxAttenCh[1] & 0x3f) << 12;
2638 otus_write(sc, AR_PHY_RXGAIN + offset, tmp);
2639
2640 tmp = otus_phy_get_def(sc, AR_PHY_GAIN_2GHZ);
2641 tmp &= ~(0x3f << 18);
2642 tmp |= (eep->rxTxMarginCh[0] & 0x3f) << 18;
2643 if (IEEE80211_IS_CHAN_5GHZ(c)) {
2644 tmp &= ~(0xf << 10);
2645 tmp |= (eep->bswMargin[0] & 0xf) << 10;
2646 }
2647 otus_write(sc, AR_PHY_GAIN_2GHZ, tmp);
2648
2649 tmp = otus_phy_get_def(sc, AR_PHY_GAIN_2GHZ + offset);
2650 tmp &= ~(0x3f << 18);
2651 tmp |= (eep->rxTxMarginCh[1] & 0x3f) << 18;
2652 otus_write(sc, AR_PHY_GAIN_2GHZ + offset, tmp);
2653
2654 tmp = otus_phy_get_def(sc, AR_PHY_TIMING_CTRL4);
2655 tmp &= ~(0x3f << 5 | 0x1f);
2656 tmp |= (eep->iqCalICh[0] & 0x3f) << 5 | (eep->iqCalQCh[0] & 0x1f);
2657 otus_write(sc, AR_PHY_TIMING_CTRL4, tmp);
2658
2659 tmp = otus_phy_get_def(sc, AR_PHY_TIMING_CTRL4 + offset);
2660 tmp &= ~(0x3f << 5 | 0x1f);
2661 tmp |= (eep->iqCalICh[1] & 0x3f) << 5 | (eep->iqCalQCh[1] & 0x1f);
2662 otus_write(sc, AR_PHY_TIMING_CTRL4 + offset, tmp);
2663
2664 tmp = otus_phy_get_def(sc, AR_PHY_TPCRG1);
2665 tmp &= ~(0xf << 16);
2666 tmp |= (eep->xpd & 0xf) << 16;
2667 otus_write(sc, AR_PHY_TPCRG1, tmp);
2668
2669 return otus_write_barrier(sc);
2670 }
2671
2672 Static int
2673 otus_program_phy(struct otus_softc *sc, struct ieee80211_channel *c)
2674 {
2675 const uint32_t *vals;
2676 int error, i;
2677
2678 DPRINTFN(DBG_FN, sc, "\n");
2679
2680 /* Select PHY programming based on band and bandwidth. */
2681 if (IEEE80211_IS_CHAN_2GHZ(c))
2682 vals = ar5416_phy_vals_2ghz_20mhz;
2683 else
2684 vals = ar5416_phy_vals_5ghz_20mhz;
2685 for (i = 0; i < __arraycount(ar5416_phy_regs); i++)
2686 otus_write(sc, AR_PHY(ar5416_phy_regs[i]), vals[i]);
2687 sc->sc_phy_vals = vals;
2688
2689 if (sc->sc_eeprom.baseEepHeader.deviceType == 0x80) /* FEM */
2690 if ((error = otus_set_board_values(sc, c)) != 0)
2691 return error;
2692
2693 /* Initial Tx power settings. */
2694 otus_write(sc, AR_PHY_POWER_TX_RATE_MAX, 0x7f);
2695 otus_write(sc, AR_PHY_POWER_TX_RATE1, 0x3f3f3f3f);
2696 otus_write(sc, AR_PHY_POWER_TX_RATE2, 0x3f3f3f3f);
2697 otus_write(sc, AR_PHY_POWER_TX_RATE3, 0x3f3f3f3f);
2698 otus_write(sc, AR_PHY_POWER_TX_RATE4, 0x3f3f3f3f);
2699 otus_write(sc, AR_PHY_POWER_TX_RATE5, 0x3f3f3f3f);
2700 otus_write(sc, AR_PHY_POWER_TX_RATE6, 0x3f3f3f3f);
2701 otus_write(sc, AR_PHY_POWER_TX_RATE7, 0x3f3f3f3f);
2702 otus_write(sc, AR_PHY_POWER_TX_RATE8, 0x3f3f3f3f);
2703 otus_write(sc, AR_PHY_POWER_TX_RATE9, 0x3f3f3f3f);
2704
2705 if (IEEE80211_IS_CHAN_2GHZ(c))
2706 otus_write(sc, 0x1d4014, 0x5163);
2707 else
2708 otus_write(sc, 0x1d4014, 0x5143);
2709
2710 return otus_write_barrier(sc);
2711 }
2712
2713 static __inline uint8_t
2714 otus_reverse_bits(uint8_t v)
2715 {
2716
2717 v = ((v >> 1) & 0x55) | ((v & 0x55) << 1);
2718 v = ((v >> 2) & 0x33) | ((v & 0x33) << 2);
2719 v = ((v >> 4) & 0x0f) | ((v & 0x0f) << 4);
2720 return v;
2721 }
2722
2723 Static int
2724 otus_set_rf_bank4(struct otus_softc *sc, struct ieee80211_channel *c)
2725 {
2726 uint8_t chansel, d0, d1;
2727 uint16_t data;
2728 int error;
2729
2730 DPRINTFN(DBG_FN, sc, "\n");
2731
2732 d0 = 0;
2733 if (IEEE80211_IS_CHAN_5GHZ(c)) {
2734 chansel = (c->ic_freq - 4800) / 5;
2735 if (chansel & 1)
2736 d0 |= AR_BANK4_AMODE_REFSEL(2);
2737 else
2738 d0 |= AR_BANK4_AMODE_REFSEL(1);
2739 } else {
2740 d0 |= AR_BANK4_AMODE_REFSEL(2);
2741 if (c->ic_freq == 2484) { /* CH 14 */
2742 d0 |= AR_BANK4_BMODE_LF_SYNTH_FREQ;
2743 chansel = 10 + (c->ic_freq - 2274) / 5;
2744 } else
2745 chansel = 16 + (c->ic_freq - 2272) / 5;
2746 chansel <<= 2;
2747 }
2748 d0 |= AR_BANK4_ADDR(1) | AR_BANK4_CHUP;
2749 d1 = otus_reverse_bits(chansel);
2750
2751 /* Write bits 0-4 of d0 and d1. */
2752 data = (d1 & 0x1f) << 5 | (d0 & 0x1f);
2753 otus_write(sc, AR_PHY(44), data);
2754 /* Write bits 5-7 of d0 and d1. */
2755 data = (d1 >> 5) << 5 | (d0 >> 5);
2756 otus_write(sc, AR_PHY(58), data);
2757
2758 if ((error = otus_write_barrier(sc)) == 0)
2759 usbd_delay_ms(sc->sc_udev, 10);
2760
2761 return error;
2762 }
2763
2764 Static void
2765 otus_get_delta_slope(uint32_t coeff, uint32_t *exponent, uint32_t *mantissa)
2766 {
2767 #define COEFF_SCALE_SHIFT 24
2768 uint32_t exp, man;
2769
2770 DPRINTFN(DBG_FN, DBG_NO_SC, "\n");
2771
2772 /* exponent = 14 - floor(log2(coeff)) */
2773 for (exp = 31; exp > 0; exp--)
2774 if (coeff & (1 << exp))
2775 break;
2776 KASSERT(exp != 0);
2777 exp = 14 - (exp - COEFF_SCALE_SHIFT);
2778
2779 /* mantissa = floor(coeff * 2^exponent + 0.5) */
2780 man = coeff + (1 << (COEFF_SCALE_SHIFT - exp - 1));
2781
2782 *mantissa = man >> (COEFF_SCALE_SHIFT - exp);
2783 *exponent = exp - 16;
2784 #undef COEFF_SCALE_SHIFT
2785 }
2786
2787 Static int
2788 otus_set_chan(struct otus_softc *sc, struct ieee80211_channel *c, int assoc)
2789 {
2790 struct ar_cmd_frequency cmd;
2791 struct ar_rsp_frequency rsp;
2792 const uint32_t *vals;
2793 uint32_t coeff, exp, man, tmp;
2794 uint8_t code;
2795 int error, i;
2796
2797 DPRINTFN(DBG_FN, sc, "\n");
2798
2799
2800 #ifdef OTUS_DEBUG
2801 struct ieee80211com *ic = &sc->sc_ic;
2802 int chan = ieee80211_chan2ieee(ic, c);
2803
2804 DPRINTFN(DBG_CHAN, sc, "setting channel %d (%dMHz)\n",
2805 chan, c->ic_freq);
2806 #endif
2807
2808 tmp = IEEE80211_IS_CHAN_2GHZ(c) ? 0x105 : 0x104;
2809 otus_write(sc, AR_MAC_REG_DYNAMIC_SIFS_ACK, tmp);
2810 if ((error = otus_write_barrier(sc)) != 0)
2811 return error;
2812
2813 /* Disable BB Heavy Clip. */
2814 otus_write(sc, AR_PHY_HEAVY_CLIP_ENABLE, 0x200);
2815 if ((error = otus_write_barrier(sc)) != 0)
2816 return error;
2817
2818 /* XXX Is that FREQ_START ? */
2819 error = otus_cmd(sc, AR_CMD_FREQ_STRAT, NULL, 0, NULL);
2820 if (error != 0)
2821 return error;
2822
2823 /* Reprogram PHY and RF on channel band or bandwidth changes. */
2824 if (sc->sc_bb_reset || c->ic_flags != sc->sc_curchan->ic_flags) {
2825 DPRINTFN(DBG_CHAN, sc, "band switch\n");
2826
2827 /* Cold/Warm reset BB/ADDA. */
2828 otus_write(sc, 0x1d4004, sc->sc_bb_reset ? 0x800 : 0x400);
2829 if ((error = otus_write_barrier(sc)) != 0)
2830 return error;
2831
2832 otus_write(sc, 0x1d4004, 0);
2833 if ((error = otus_write_barrier(sc)) != 0)
2834 return error;
2835 sc->sc_bb_reset = 0;
2836
2837 if ((error = otus_program_phy(sc, c)) != 0) {
2838 aprint_error_dev(sc->sc_dev,
2839 "could not program PHY\n");
2840 return error;
2841 }
2842
2843 /* Select RF programming based on band. */
2844 if (IEEE80211_IS_CHAN_5GHZ(c))
2845 vals = ar5416_banks_vals_5ghz;
2846 else
2847 vals = ar5416_banks_vals_2ghz;
2848 for (i = 0; i < __arraycount(ar5416_banks_regs); i++)
2849 otus_write(sc, AR_PHY(ar5416_banks_regs[i]), vals[i]);
2850 if ((error = otus_write_barrier(sc)) != 0) {
2851 aprint_error_dev(sc->sc_dev, "could not program RF\n");
2852 return error;
2853 }
2854 code = AR_CMD_RF_INIT;
2855 } else {
2856 code = AR_CMD_FREQUENCY;
2857 }
2858
2859 if ((error = otus_set_rf_bank4(sc, c)) != 0)
2860 return error;
2861
2862 tmp = (sc->sc_txmask == 0x5) ? 0x340 : 0x240;
2863 otus_write(sc, AR_PHY_TURBO, tmp);
2864 if ((error = otus_write_barrier(sc)) != 0)
2865 return error;
2866
2867 /* Send firmware command to set channel. */
2868 cmd.freq = htole32((uint32_t)c->ic_freq * 1000);
2869 cmd.dynht2040 = htole32(0);
2870 cmd.htena = htole32(1);
2871
2872 /* Set Delta Slope (exponent and mantissa). */
2873 coeff = (100 << 24) / c->ic_freq;
2874 otus_get_delta_slope(coeff, &exp, &man);
2875 cmd.dsc_exp = htole32(exp);
2876 cmd.dsc_man = htole32(man);
2877 DPRINTFN(DBG_CHAN, sc, "ds coeff=%u exp=%u man=%u\n",
2878 coeff, exp, man);
2879
2880 /* For Short GI, coeff is 9/10 that of normal coeff. */
2881 coeff = (9 * coeff) / 10;
2882 otus_get_delta_slope(coeff, &exp, &man);
2883 cmd.dsc_shgi_exp = htole32(exp);
2884 cmd.dsc_shgi_man = htole32(man);
2885 DPRINTFN(DBG_CHAN, sc, "ds shgi coeff=%u exp=%u man=%u\n",
2886 coeff, exp, man);
2887
2888 /* Set wait time for AGC and noise calibration (100 or 200ms). */
2889 cmd.check_loop_count = assoc ? htole32(2000) : htole32(1000);
2890 DPRINTFN(DBG_CHAN, sc, "%s\n",
2891 code == AR_CMD_RF_INIT ? "RF_INIT" : "FREQUENCY");
2892 error = otus_cmd(sc, code, &cmd, sizeof(cmd), &rsp);
2893 if (error != 0)
2894 return error;
2895
2896 if ((rsp.status & htole32(AR_CAL_ERR_AGC | AR_CAL_ERR_NF_VAL)) != 0) {
2897 DPRINTFN(DBG_CHAN, sc, "status=%#x\n", le32toh(rsp.status));
2898 /* Force cold reset on next channel. */
2899 sc->sc_bb_reset = 1;
2900 }
2901
2902 #ifdef OTUS_DEBUG
2903 if (otus_debug & DBG_CHAN) {
2904 DPRINTFN(DBG_CHAN, sc, "calibration status=%#x\n",
2905 le32toh(rsp.status));
2906 for (i = 0; i < 2; i++) { /* 2 Rx chains */
2907 /* Sign-extend 9-bit NF values. */
2908 DPRINTFN(DBG_CHAN, sc, "noisefloor chain %d=%d\n",
2909 i, (((int32_t)le32toh(rsp.nf[i])) << 4) >> 23);
2910 DPRINTFN(DBG_CHAN, sc, "noisefloor ext chain %d=%d\n",
2911 i, ((int32_t)le32toh(rsp.nf_ext[i])) >> 23);
2912 }
2913 }
2914 #endif
2915 sc->sc_curchan = c;
2916 return 0;
2917 }
2918
2919 #ifdef notyet
2920 Static int
2921 otus_set_key(struct ieee80211com *ic, struct ieee80211_node *ni,
2922 struct ieee80211_key *k)
2923 {
2924 struct otus_softc *sc;
2925 struct otus_cmd_key cmd;
2926
2927 sc = ic->ic_ifp->if_softc;
2928
2929 DPRINTFN(DBG_FN, sc, "\n");
2930
2931 /* Defer setting of WEP keys until interface is brought up. */
2932 if ((ic->ic_ifp->if_flags & (IFF_UP | IFF_RUNNING)) !=
2933 (IFF_UP | IFF_RUNNING))
2934 return 0;
2935
2936 /* Do it in a process context. */
2937 cmd.key = *k;
2938 cmd.associd = (ni != NULL) ? ni->ni_associd : 0;
2939 otus_do_async(sc, otus_set_key_cb, &cmd, sizeof(cmd));
2940 return 0;
2941 }
2942
2943 Static void
2944 otus_set_key_cb(struct otus_softc *sc, void *arg)
2945 {
2946 struct otus_cmd_key *cmd;
2947 struct ieee80211_key *k;
2948 struct ar_cmd_ekey key;
2949 uint16_t cipher;
2950 int error;
2951
2952 DPRINTFN(DBG_FN, sc, "\n");
2953
2954 cmd = arg;
2955 k = &cmd->key;
2956
2957 memset(&key, 0, sizeof(key));
2958 if (k->k_flags & IEEE80211_KEY_GROUP) {
2959 key.uid = htole16(k->k_id);
2960 IEEE80211_ADDR_COPY(key.macaddr, sc->sc_ic.ic_myaddr);
2961 key.macaddr[0] |= 0x80;
2962 } else {
2963 key.uid = htole16(OTUS_UID(cmd->associd));
2964 IEEE80211_ADDR_COPY(key.macaddr, ni->ni_macaddr);
2965 }
2966 key.kix = htole16(0);
2967 /* Map net80211 cipher to hardware. */
2968 switch (k->k_cipher) {
2969 case IEEE80211_CIPHER_WEP40:
2970 cipher = AR_CIPHER_WEP64;
2971 break;
2972 case IEEE80211_CIPHER_WEP104:
2973 cipher = AR_CIPHER_WEP128;
2974 break;
2975 case IEEE80211_CIPHER_TKIP:
2976 cipher = AR_CIPHER_TKIP;
2977 break;
2978 case IEEE80211_CIPHER_CCMP:
2979 cipher = AR_CIPHER_AES;
2980 break;
2981 default:
2982 return;
2983 }
2984 key.cipher = htole16(cipher);
2985 memcpy(key.key, k->k_key, MIN(k->k_len, 16));
2986 error = otus_cmd(sc, AR_CMD_EKEY, &key, sizeof(key), NULL);
2987 if (error != 0 || k->k_cipher != IEEE80211_CIPHER_TKIP)
2988 return;
2989
2990 /* TKIP: set Tx/Rx MIC Key. */
2991 key.kix = htole16(1);
2992 memcpy(key.key, k->k_key + 16, 16);
2993 (void)otus_cmd(sc, AR_CMD_EKEY, &key, sizeof(key), NULL);
2994 }
2995
2996 Static void
2997 otus_delete_key(struct ieee80211com *ic, struct ieee80211_node *ni,
2998 struct ieee80211_key *k)
2999 {
3000 struct otus_softc *sc;
3001 struct otus_cmd_key cmd;
3002
3003 sc = ic->ic_ifp->if_softc;
3004
3005 DPRINTFN(DBG_FN, sc, "\n");
3006
3007 if (!(ic->ic_ifp->if_flags & IFF_RUNNING) ||
3008 ic->ic_state != IEEE80211_S_RUN)
3009 return; /* Nothing to do. */
3010
3011 /* Do it in a process context. */
3012 cmd.key = *k;
3013 cmd.associd = (ni != NULL) ? ni->ni_associd : 0;
3014 otus_do_async(sc, otus_delete_key_cb, &cmd, sizeof(cmd));
3015 }
3016
3017 Static void
3018 otus_delete_key_cb(struct otus_softc *sc, void *arg)
3019 {
3020 struct otus_cmd_key *cmd;
3021 struct ieee80211_key *k;
3022 uint32_t uid;
3023
3024 DPRINTFN(DBG_FN, sc, "\n");
3025
3026 cmd = arg;
3027 k = &cmd->key;
3028 if (k->k_flags & IEEE80211_KEY_GROUP)
3029 uid = htole32(k->k_id);
3030 else
3031 uid = htole32(OTUS_UID(cmd->associd));
3032 (void)otus_cmd(sc, AR_CMD_DKEY, &uid, sizeof(uid), NULL);
3033 }
3034 #endif /* notyet */
3035
3036 Static void
3037 otus_calib_to(void *arg)
3038 {
3039 struct otus_softc *sc;
3040 struct ieee80211com *ic;
3041 struct ieee80211_node *ni;
3042 struct otus_node *on;
3043 int s;
3044
3045 sc = arg;
3046
3047 DPRINTFN(DBG_FN, sc, "\n");
3048
3049 if (sc->sc_dying)
3050 return;
3051
3052 s = splnet();
3053 ic = &sc->sc_ic;
3054 ni = ic->ic_bss;
3055 on = (void *)ni;
3056 ieee80211_amrr_choose(&sc->sc_amrr, ni, &on->amn);
3057 splx(s);
3058
3059 if (!sc->sc_dying)
3060 callout_schedule(&sc->sc_calib_to, hz);
3061 }
3062
3063 Static int
3064 otus_set_bssid(struct otus_softc *sc, const uint8_t *bssid)
3065 {
3066
3067 DPRINTFN(DBG_FN, sc, "\n");
3068
3069 KASSERT(mutex_owned(&sc->sc_write_mtx));
3070
3071 otus_write(sc, AR_MAC_REG_BSSID_L,
3072 bssid[0] | bssid[1] << 8 | bssid[2] << 16 | bssid[3] << 24);
3073 otus_write(sc, AR_MAC_REG_BSSID_H,
3074 bssid[4] | bssid[5] << 8);
3075 return otus_write_barrier(sc);
3076 }
3077
3078 Static int
3079 otus_set_macaddr(struct otus_softc *sc, const uint8_t *addr)
3080 {
3081
3082 DPRINTFN(DBG_FN, sc, "\n");
3083
3084 KASSERT(mutex_owned(&sc->sc_write_mtx));
3085
3086 otus_write(sc, AR_MAC_REG_MAC_ADDR_L,
3087 addr[0] | addr[1] << 8 | addr[2] << 16 | addr[3] << 24);
3088 otus_write(sc, AR_MAC_REG_MAC_ADDR_H,
3089 addr[4] | addr[5] << 8);
3090 return otus_write_barrier(sc);
3091 }
3092
3093 #ifdef notyet
3094 /* Default single-LED. */
3095 Static void
3096 otus_led_newstate_type1(struct otus_softc *sc)
3097 {
3098
3099 DPRINTFN(DBG_FN, sc, "\n");
3100
3101 /* TBD */
3102 }
3103
3104 /* NETGEAR, dual-LED. */
3105 Static void
3106 otus_led_newstate_type2(struct otus_softc *sc)
3107 {
3108
3109 DPRINTFN(DBG_FN, sc, "\n");
3110
3111 /* TBD */
3112 }
3113 #endif /* notyet */
3114
3115 /*
3116 * NETGEAR, single-LED/3 colors (blue, red, purple.)
3117 */
3118 Static void
3119 otus_led_newstate_type3(struct otus_softc *sc)
3120 {
3121 struct ieee80211com *ic;
3122 uint32_t led_state;
3123
3124 DPRINTFN(DBG_FN, sc, "\n");
3125
3126 ic = &sc->sc_ic;
3127 led_state = sc->sc_led_state;
3128 switch (ic->ic_state) {
3129 case IEEE80211_S_INIT:
3130 led_state = 0;
3131 break;
3132 case IEEE80211_S_SCAN:
3133 led_state ^= AR_GPIO_REG_DATA_LED0_ON | AR_GPIO_REG_DATA_LED1_ON;
3134 led_state &= ~(IEEE80211_IS_CHAN_2GHZ(sc->sc_curchan) ?
3135 AR_GPIO_REG_DATA_LED1_ON : AR_GPIO_REG_DATA_LED0_ON);
3136 break;
3137 case IEEE80211_S_AUTH:
3138 case IEEE80211_S_ASSOC:
3139 /* XXX: Turn both LEDs on for AUTH and ASSOC? */
3140 led_state = AR_GPIO_REG_DATA_LED0_ON | AR_GPIO_REG_DATA_LED1_ON;
3141 break;
3142 case IEEE80211_S_RUN:
3143 led_state = IEEE80211_IS_CHAN_2GHZ(sc->sc_curchan) ?
3144 AR_GPIO_REG_DATA_LED0_ON : AR_GPIO_REG_DATA_LED1_ON;
3145 break;
3146 }
3147 if (led_state != sc->sc_led_state) {
3148 otus_write(sc, AR_GPIO_REG_DATA, led_state);
3149 if (otus_write_barrier(sc) == 0)
3150 sc->sc_led_state = led_state;
3151 }
3152 }
3153
3154 Static int
3155 otus_init(struct ifnet *ifp)
3156 {
3157 struct otus_softc *sc;
3158 struct ieee80211com *ic;
3159 uint32_t filter, pm_mode, sniffer;
3160 int error;
3161
3162 sc = ifp->if_softc;
3163
3164 DPRINTFN(DBG_FN | DBG_INIT, sc, "\n");
3165
3166 ic = &sc->sc_ic;
3167
3168 mutex_enter(&sc->sc_write_mtx);
3169
3170 /* Init host command ring. */
3171 mutex_spin_enter(&sc->sc_task_mtx);
3172 sc->sc_cmdq.cur = sc->sc_cmdq.next = sc->sc_cmdq.queued = 0;
3173 mutex_spin_exit(&sc->sc_task_mtx);
3174
3175 if ((error = otus_init_mac(sc)) != 0) {
3176 mutex_exit(&sc->sc_write_mtx);
3177 aprint_error_dev(sc->sc_dev, "could not initialize MAC\n");
3178 return error;
3179 }
3180
3181 IEEE80211_ADDR_COPY(ic->ic_myaddr, CLLADDR(ifp->if_sadl));
3182 (void)otus_set_macaddr(sc, ic->ic_myaddr);
3183
3184 pm_mode = AR_MAC_REG_POWERMGT_DEFAULTS;
3185 sniffer = AR_MAC_REG_SNIFFER_DEFAULTS;
3186 filter = AR_MAC_REG_FTF_DEFAULTS;
3187 sc->sc_rx_error_msk = ~0;
3188
3189 switch (ic->ic_opmode) {
3190 #ifdef notyet
3191 #ifndef IEEE80211_STA_ONLY
3192 case IEEE80211_M_HOSTAP:
3193 pm_mode |= AR_MAC_REG_POWERMGT_AP;
3194 break;
3195 case IEEE80211_M_IBSS:
3196 pm_mode |= AR_MAC_REG_POWERMGT_IBSS; /* XXX: was 0x0 */
3197 break;
3198 #endif
3199 #endif
3200 case IEEE80211_M_STA:
3201 pm_mode |= AR_MAC_REG_POWERMGT_STA;
3202 break;
3203 case IEEE80211_M_MONITOR:
3204 sc->sc_rx_error_msk = ~AR_RX_ERROR_BAD_RA;
3205 filter = AR_MAC_REG_FTF_MONITOR;
3206 sniffer |= AR_MAC_REG_SNIFFER_ENABLE_PROMISC;
3207 break;
3208 default:
3209 aprint_error_dev(sc->sc_dev, "bad opmode: %d", ic->ic_opmode);
3210 return EOPNOTSUPP; /* XXX: ??? */
3211 }
3212 otus_write(sc, AR_MAC_REG_POWERMANAGEMENT, pm_mode);
3213 otus_write(sc, AR_MAC_REG_FRAMETYPE_FILTER, filter);
3214 otus_write(sc, AR_MAC_REG_SNIFFER, sniffer);
3215 (void)otus_write_barrier(sc);
3216
3217 sc->sc_bb_reset = 1; /* Force cold reset. */
3218 if ((error = otus_set_chan(sc, ic->ic_curchan, 0)) != 0) {
3219 mutex_exit(&sc->sc_write_mtx);
3220 aprint_error_dev(sc->sc_dev, "could not set channel\n");
3221 return error;
3222 }
3223
3224 /* Start Rx. */
3225 otus_write(sc, AR_MAC_REG_DMA, AR_MAC_REG_DMA_ENABLE);
3226 (void)otus_write_barrier(sc);
3227 mutex_exit(&sc->sc_write_mtx);
3228
3229 ifp->if_flags &= ~IFF_OACTIVE;
3230 ifp->if_flags |= IFF_RUNNING;
3231
3232 if (ic->ic_opmode == IEEE80211_M_MONITOR)
3233 ieee80211_new_state(ic, IEEE80211_S_RUN, -1);
3234 else
3235 ieee80211_new_state(ic, IEEE80211_S_SCAN, -1);
3236
3237 return 0;
3238 }
3239
3240 Static void
3241 otus_stop(struct ifnet *ifp)
3242 {
3243 struct otus_softc *sc;
3244 struct ieee80211com *ic;
3245 int s;
3246
3247 sc = ifp->if_softc;
3248
3249 DPRINTFN(DBG_FN, sc, "\n");
3250
3251 ic = &sc->sc_ic;
3252
3253 sc->sc_tx_timer = 0;
3254 ifp->if_timer = 0;
3255 ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE);
3256
3257 callout_halt(&sc->sc_scan_to, NULL);
3258 callout_halt(&sc->sc_calib_to, NULL);
3259
3260 s = splusb();
3261 ieee80211_new_state(ic, IEEE80211_S_INIT, -1);
3262 otus_wait_async(sc);
3263 splx(s);
3264
3265 /* Stop Rx. */
3266 mutex_enter(&sc->sc_write_mtx);
3267 otus_write(sc, AR_MAC_REG_DMA, AR_MAC_REG_DMA_OFF);
3268 (void)otus_write_barrier(sc);
3269 mutex_exit(&sc->sc_write_mtx);
3270 }
3271