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