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