if_otus.c revision 1.25.6.7 1 /* $NetBSD: if_otus.c,v 1.25.6.7 2016/05/29 08:44:31 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.7 2016/05/29 08:44:31 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->uaa_vendor, uaa->uaa_product, uaa->uaa_release);
601
602 return usb_lookup(otus_devs, uaa->uaa_vendor, uaa->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->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 cv_init(&sc->sc_task_cv, "otustsk");
630 cv_init(&sc->sc_cmd_cv, "otuscmd");
631 mutex_init(&sc->sc_cmd_mtx, MUTEX_DEFAULT, IPL_NONE);
632 mutex_init(&sc->sc_task_mtx, MUTEX_DEFAULT, IPL_NET);
633 mutex_init(&sc->sc_tx_mtx, MUTEX_DEFAULT, IPL_NONE);
634 mutex_init(&sc->sc_write_mtx, MUTEX_DEFAULT, IPL_NONE);
635
636 usb_init_task(&sc->sc_task, otus_task, sc, 0);
637
638 callout_init(&sc->sc_scan_to, 0);
639 callout_setfunc(&sc->sc_scan_to, otus_next_scan, sc);
640 callout_init(&sc->sc_calib_to, 0);
641 callout_setfunc(&sc->sc_calib_to, otus_calib_to, sc);
642
643 sc->sc_amrr.amrr_min_success_threshold = 1;
644 sc->sc_amrr.amrr_max_success_threshold = 10;
645
646 if (usbd_set_config_no(sc->sc_udev, 1, 0) != 0) {
647 aprint_error_dev(sc->sc_dev,
648 "could not set configuration no\n");
649 return;
650 }
651
652 /* Get the first interface handle. */
653 error = usbd_device2interface_handle(sc->sc_udev, 0, &sc->sc_iface);
654 if (error != 0) {
655 aprint_error_dev(sc->sc_dev,
656 "could not get interface handle\n");
657 return;
658 }
659
660 if ((error = otus_open_pipes(sc)) != 0) {
661 aprint_error_dev(sc->sc_dev, "could not open pipes\n");
662 return;
663 }
664
665 /*
666 * We need the firmware loaded from file system to complete the attach.
667 */
668 config_mountroot(self, otus_attachhook);
669
670 usbd_add_drv_event(USB_EVENT_DRIVER_ATTACH, sc->sc_udev, sc->sc_dev);
671 }
672
673 Static void
674 otus_wait_async(struct otus_softc *sc)
675 {
676
677 DPRINTFN(DBG_FN, sc, "\n");
678
679 mutex_spin_enter(&sc->sc_task_mtx);
680 while (sc->sc_cmdq.queued > 0)
681 cv_wait(&sc->sc_task_cv, &sc->sc_task_mtx);
682 mutex_spin_exit(&sc->sc_task_mtx);
683 }
684
685 Static int
686 otus_detach(device_t self, int flags)
687 {
688 struct otus_softc *sc;
689 struct ifnet *ifp;
690 int s;
691
692 sc = device_private(self);
693
694 DPRINTFN(DBG_FN, sc, "\n");
695
696 s = splusb();
697
698 sc->sc_dying = 1;
699
700 ifp = sc->sc_ic.ic_ifp;
701 if (ifp != NULL) /* Failed to attach properly */
702 otus_stop(ifp);
703
704 usb_rem_task(sc->sc_udev, &sc->sc_task);
705 callout_destroy(&sc->sc_scan_to);
706 callout_destroy(&sc->sc_calib_to);
707
708 if (ifp && ifp->if_flags != 0) { /* if_attach() has been called. */
709 ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE);
710 bpf_detach(ifp);
711 ieee80211_ifdetach(&sc->sc_ic);
712 if_detach(ifp);
713 }
714 otus_close_pipes(sc);
715 splx(s);
716
717 usbd_add_drv_event(USB_EVENT_DRIVER_DETACH, sc->sc_udev, sc->sc_dev);
718
719 mutex_destroy(&sc->sc_write_mtx);
720 mutex_destroy(&sc->sc_tx_mtx);
721 mutex_destroy(&sc->sc_task_mtx);
722 mutex_destroy(&sc->sc_cmd_mtx);
723 cv_destroy(&sc->sc_task_cv);
724 cv_destroy(&sc->sc_cmd_cv);
725
726 return 0;
727 }
728
729 Static int
730 otus_activate(device_t self, devact_t act)
731 {
732 struct otus_softc *sc;
733
734 sc = device_private(self);
735
736 DPRINTFN(DBG_FN, sc, "%d\n", act);
737
738 switch (act) {
739 case DVACT_DEACTIVATE:
740 sc->sc_dying = 1;
741 if_deactivate(sc->sc_ic.ic_ifp);
742 return 0;
743 default:
744 return EOPNOTSUPP;
745 }
746 }
747
748 Static void
749 otus_attachhook(device_t arg)
750 {
751 struct otus_softc *sc;
752 struct ieee80211com *ic;
753 struct ifnet *ifp;
754 usb_device_request_t req;
755 uint32_t in, out;
756 int error;
757
758 sc = device_private(arg);
759
760 DPRINTFN(DBG_FN, sc, "\n");
761
762 ic = &sc->sc_ic;
763 ifp = &sc->sc_if;
764
765 error = otus_load_firmware(sc, "otus-init", AR_FW_INIT_ADDR);
766 if (error != 0) {
767 aprint_error_dev(sc->sc_dev, "could not load init firmware\n");
768 return;
769 }
770 usbd_delay_ms(sc->sc_udev, 1000);
771
772 error = otus_load_firmware(sc, "otus-main", AR_FW_MAIN_ADDR);
773 if (error != 0) {
774 aprint_error_dev(sc->sc_dev, "could not load main firmware\n");
775 return;
776 }
777
778 /* Tell device that firmware transfer is complete. */
779 req.bmRequestType = UT_WRITE_VENDOR_DEVICE;
780 req.bRequest = AR_FW_DOWNLOAD_COMPLETE;
781 USETW(req.wValue, 0);
782 USETW(req.wIndex, 0);
783 USETW(req.wLength, 0);
784 if (usbd_do_request(sc->sc_udev, &req, NULL) != 0) {
785 aprint_error_dev(sc->sc_dev,
786 "firmware initialization failed\n");
787 return;
788 }
789
790 /* Send an ECHO command to check that everything is settled. */
791 in = 0xbadc0ffe;
792 if (otus_cmd(sc, AR_CMD_ECHO, &in, sizeof(in), &out) != 0) {
793 aprint_error_dev(sc->sc_dev, "echo command failed\n");
794 return;
795 }
796 if (in != out) {
797 aprint_error_dev(sc->sc_dev,
798 "echo reply mismatch: 0x%08x!=0x%08x\n", in, out);
799 return;
800 }
801
802 /* Read entire EEPROM. */
803 if (otus_read_eeprom(sc) != 0) {
804 aprint_error_dev(sc->sc_dev, "could not read EEPROM\n");
805 return;
806 }
807
808 sc->sc_txmask = sc->sc_eeprom.baseEepHeader.txMask;
809 sc->sc_rxmask = sc->sc_eeprom.baseEepHeader.rxMask;
810 sc->sc_capflags = sc->sc_eeprom.baseEepHeader.opCapFlags;
811 IEEE80211_ADDR_COPY(ic->ic_myaddr, sc->sc_eeprom.baseEepHeader.macAddr);
812 sc->sc_led_newstate = otus_led_newstate_type3; /* XXX */
813
814 aprint_normal_dev(sc->sc_dev,
815 "MAC/BBP AR9170, RF AR%X, MIMO %dT%dR, address %s\n",
816 (sc->sc_capflags & AR5416_OPFLAGS_11A) ?
817 0x9104 : ((sc->sc_txmask == 0x5) ? 0x9102 : 0x9101),
818 (sc->sc_txmask == 0x5) ? 2 : 1, (sc->sc_rxmask == 0x5) ? 2 : 1,
819 ether_sprintf(ic->ic_myaddr));
820
821 /*
822 * Setup the 802.11 device.
823 */
824 ic->ic_ifp = ifp;
825 ic->ic_phytype = IEEE80211_T_OFDM; /* not only, but not used */
826 ic->ic_opmode = IEEE80211_M_STA; /* default to BSS mode */
827 ic->ic_state = IEEE80211_S_INIT;
828
829 /* Set device capabilities. */
830 ic->ic_caps =
831 IEEE80211_C_MONITOR | /* monitor mode supported */
832 IEEE80211_C_SHPREAMBLE | /* short preamble supported */
833 IEEE80211_C_SHSLOT | /* short slot time supported */
834 IEEE80211_C_WPA; /* 802.11i */
835
836 if (sc->sc_eeprom.baseEepHeader.opCapFlags & AR5416_OPFLAGS_11G) {
837 /* Set supported .11b and .11g rates. */
838 ic->ic_sup_rates[IEEE80211_MODE_11B] =
839 ieee80211_std_rateset_11b;
840 ic->ic_sup_rates[IEEE80211_MODE_11G] =
841 ieee80211_std_rateset_11g;
842 }
843 if (sc->sc_eeprom.baseEepHeader.opCapFlags & AR5416_OPFLAGS_11A) {
844 /* Set supported .11a rates. */
845 ic->ic_sup_rates[IEEE80211_MODE_11A] =
846 ieee80211_std_rateset_11a;
847 }
848
849 /* Build the list of supported channels. */
850 otus_get_chanlist(sc);
851
852 ifp->if_softc = sc;
853 ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
854 ifp->if_init = otus_init;
855 ifp->if_ioctl = otus_ioctl;
856 ifp->if_start = otus_start;
857 ifp->if_watchdog = otus_watchdog;
858 IFQ_SET_READY(&ifp->if_snd);
859 memcpy(ifp->if_xname, device_xname(sc->sc_dev), IFNAMSIZ);
860
861 if_attach(ifp);
862
863 ieee80211_ifattach(ic);
864
865 ic->ic_node_alloc = otus_node_alloc;
866 ic->ic_newassoc = otus_newassoc;
867 ic->ic_updateslot = otus_updateslot;
868 #ifdef HAVE_EDCA
869 ic->ic_updateedca = otus_updateedca;
870 #endif /* HAVE_EDCA */
871 #ifdef notyet
872 ic->ic_set_key = otus_set_key;
873 ic->ic_delete_key = otus_delete_key;
874 #endif /* notyet */
875
876 /* Override state transition machine. */
877 sc->sc_newstate = ic->ic_newstate;
878 ic->ic_newstate = otus_newstate;
879 ieee80211_media_init(ic, otus_media_change, ieee80211_media_status);
880
881 bpf_attach2(ifp, DLT_IEEE802_11_RADIO,
882 sizeof(struct ieee80211_frame) + IEEE80211_RADIOTAP_HDRLEN,
883 &sc->sc_drvbpf);
884
885 sc->sc_rxtap_len = sizeof(sc->sc_rxtapu);
886 sc->sc_rxtap.wr_ihdr.it_len = htole16(sc->sc_rxtap_len);
887 sc->sc_rxtap.wr_ihdr.it_present = htole32(OTUS_RX_RADIOTAP_PRESENT);
888
889 sc->sc_txtap_len = sizeof(sc->sc_txtapu);
890 sc->sc_txtap.wt_ihdr.it_len = htole16(sc->sc_txtap_len);
891 sc->sc_txtap.wt_ihdr.it_present = htole32(OTUS_TX_RADIOTAP_PRESENT);
892
893 ieee80211_announce(ic);
894 }
895
896 Static void
897 otus_get_chanlist(struct otus_softc *sc)
898 {
899 struct ieee80211com *ic;
900 uint8_t chan;
901 int i;
902
903 #ifdef OTUS_DEBUG
904 /* XXX regulatory domain. */
905 uint16_t domain = le16toh(sc->sc_eeprom.baseEepHeader.regDmn[0]);
906
907 DPRINTFN(DBG_FN|DBG_INIT, sc, "regdomain=0x%04x\n", domain);
908 #endif
909
910 ic = &sc->sc_ic;
911 if (sc->sc_eeprom.baseEepHeader.opCapFlags & AR5416_OPFLAGS_11G) {
912 for (i = 0; i < 14; i++) {
913 chan = ar_chans[i];
914 ic->ic_channels[chan].ic_freq =
915 ieee80211_ieee2mhz(chan, IEEE80211_CHAN_2GHZ);
916 ic->ic_channels[chan].ic_flags =
917 IEEE80211_CHAN_CCK | IEEE80211_CHAN_OFDM |
918 IEEE80211_CHAN_DYN | IEEE80211_CHAN_2GHZ;
919 }
920 }
921 if (sc->sc_eeprom.baseEepHeader.opCapFlags & AR5416_OPFLAGS_11A) {
922 for (i = 14; i < __arraycount(ar_chans); i++) {
923 chan = ar_chans[i];
924 ic->ic_channels[chan].ic_freq =
925 ieee80211_ieee2mhz(chan, IEEE80211_CHAN_5GHZ);
926 ic->ic_channels[chan].ic_flags = IEEE80211_CHAN_A;
927 }
928 }
929 }
930
931 Static int
932 otus_load_firmware(struct otus_softc *sc, const char *name, uint32_t addr)
933 {
934 usb_device_request_t req;
935 firmware_handle_t fh;
936 uint8_t *ptr;
937 uint8_t *fw;
938 size_t size;
939 int mlen, error;
940
941 DPRINTFN(DBG_FN, sc, "\n");
942
943 if ((error = firmware_open("if_otus", name, &fh)) != 0)
944 return error;
945
946 size = firmware_get_size(fh);
947 if ((fw = firmware_malloc(size)) == NULL) {
948 firmware_close(fh);
949 return ENOMEM;
950 }
951 if ((error = firmware_read(fh, 0, fw, size)) != 0)
952 firmware_free(fw, size);
953 firmware_close(fh);
954 if (error)
955 return error;
956
957 req.bmRequestType = UT_WRITE_VENDOR_DEVICE;
958 req.bRequest = AR_FW_DOWNLOAD;
959 USETW(req.wIndex, 0);
960
961 ptr = fw;
962 addr >>= 8;
963 while (size > 0) {
964 mlen = MIN(size, 4096);
965
966 USETW(req.wValue, addr);
967 USETW(req.wLength, mlen);
968 if (usbd_do_request(sc->sc_udev, &req, ptr) != 0) {
969 error = EIO;
970 break;
971 }
972 addr += mlen >> 8;
973 ptr += mlen;
974 size -= mlen;
975 }
976 free(fw, M_DEVBUF);
977 return error;
978 }
979
980 Static int
981 otus_open_pipes(struct otus_softc *sc)
982 {
983 usb_endpoint_descriptor_t *ed;
984 int i, error;
985
986 DPRINTFN(DBG_FN, sc, "\n");
987
988 error = usbd_open_pipe(sc->sc_iface, AR_EPT_BULK_RX_NO, 0,
989 &sc->sc_data_rx_pipe);
990 if (error != 0) {
991 aprint_error_dev(sc->sc_dev, "could not open Rx bulk pipe\n");
992 goto fail;
993 }
994
995 ed = usbd_get_endpoint_descriptor(sc->sc_iface, AR_EPT_INTR_RX_NO);
996 if (ed == NULL) {
997 aprint_error_dev(sc->sc_dev,
998 "could not retrieve Rx intr pipe descriptor\n");
999 goto fail;
1000 }
1001 sc->sc_ibuf_size = UGETW(ed->wMaxPacketSize);
1002 if (sc->sc_ibuf_size == 0) {
1003 aprint_error_dev(sc->sc_dev,
1004 "invalid Rx intr pipe descriptor\n");
1005 goto fail;
1006 }
1007 sc->sc_ibuf = kmem_alloc(sc->sc_ibuf_size, KM_SLEEP);
1008 if (sc->sc_ibuf == NULL) {
1009 aprint_error_dev(sc->sc_dev,
1010 "could not allocate Rx intr buffer\n");
1011 goto fail;
1012 }
1013 error = usbd_open_pipe_intr(sc->sc_iface, AR_EPT_INTR_RX_NO,
1014 USBD_SHORT_XFER_OK, &sc->sc_cmd_rx_pipe, sc, sc->sc_ibuf,
1015 sc->sc_ibuf_size, otus_intr, USBD_DEFAULT_INTERVAL);
1016 if (error != 0) {
1017 aprint_error_dev(sc->sc_dev, "could not open Rx intr pipe\n");
1018 goto fail;
1019 }
1020
1021 error = usbd_open_pipe(sc->sc_iface, AR_EPT_BULK_TX_NO, 0,
1022 &sc->sc_data_tx_pipe);
1023 if (error != 0) {
1024 aprint_error_dev(sc->sc_dev, "could not open Tx bulk pipe\n");
1025 goto fail;
1026 }
1027
1028 error = usbd_open_pipe(sc->sc_iface, AR_EPT_INTR_TX_NO, 0,
1029 &sc->sc_cmd_tx_pipe);
1030 if (error != 0) {
1031 aprint_error_dev(sc->sc_dev, "could not open Tx intr pipe\n");
1032 goto fail;
1033 }
1034
1035 if (otus_alloc_tx_cmd(sc) != 0) {
1036 aprint_error_dev(sc->sc_dev,
1037 "could not allocate command xfer\n");
1038 goto fail;
1039 }
1040
1041 if (otus_alloc_tx_data_list(sc)) {
1042 aprint_error_dev(sc->sc_dev, "could not allocate Tx xfers\n");
1043 goto fail;
1044 }
1045
1046 if (otus_alloc_rx_data_list(sc)) {
1047 aprint_error_dev(sc->sc_dev, "could not allocate Rx xfers\n");
1048 goto fail;
1049 }
1050
1051 for (i = 0; i < OTUS_RX_DATA_LIST_COUNT; i++) {
1052 struct otus_rx_data *data = &sc->sc_rx_data[i];
1053
1054 usbd_setup_xfer(data->xfer, data, data->buf, OTUS_RXBUFSZ,
1055 USBD_SHORT_XFER_OK, USBD_NO_TIMEOUT, otus_rxeof);
1056 error = usbd_transfer(data->xfer);
1057 if (error != USBD_IN_PROGRESS && error != 0) {
1058 aprint_error_dev(sc->sc_dev,
1059 "could not queue Rx xfer\n");
1060 goto fail;
1061 }
1062 }
1063 return 0;
1064
1065 fail: otus_close_pipes(sc);
1066 return error;
1067 }
1068
1069 Static void
1070 otus_close_pipes(struct otus_softc *sc)
1071 {
1072
1073 DPRINTFN(DBG_FN, sc, "\n");
1074
1075 otus_free_tx_cmd(sc);
1076 otus_free_tx_data_list(sc);
1077 otus_free_rx_data_list(sc);
1078
1079 if (sc->sc_data_rx_pipe != NULL)
1080 usbd_close_pipe(sc->sc_data_rx_pipe);
1081 if (sc->sc_cmd_rx_pipe != NULL) {
1082 usbd_abort_pipe(sc->sc_cmd_rx_pipe);
1083 usbd_close_pipe(sc->sc_cmd_rx_pipe);
1084 }
1085 if (sc->sc_ibuf != NULL)
1086 kmem_free(sc->sc_ibuf, sc->sc_ibuf_size);
1087 if (sc->sc_data_tx_pipe != NULL)
1088 usbd_close_pipe(sc->sc_data_tx_pipe);
1089 if (sc->sc_cmd_tx_pipe != NULL)
1090 usbd_close_pipe(sc->sc_cmd_tx_pipe);
1091 }
1092
1093 Static int
1094 otus_alloc_tx_cmd(struct otus_softc *sc)
1095 {
1096 struct otus_tx_cmd *cmd;
1097
1098 DPRINTFN(DBG_FN, sc, "\n");
1099
1100 cmd = &sc->sc_tx_cmd;
1101
1102 int error = usbd_create_xfer(sc->sc_cmd_tx_pipe, OTUS_MAX_TXCMDSZ,
1103 USBD_FORCE_SHORT_XFER, 0, &cmd->xfer);
1104 if (error)
1105 return error;
1106
1107 cmd->buf = usbd_get_buffer(cmd->xfer);
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_destroy_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 error = usbd_create_xfer(sc->sc_data_tx_pipe, OTUS_TXBUFSZ,
1146 USBD_FORCE_SHORT_XFER, 0, &data->xfer);
1147 if (error) {
1148 aprint_error_dev(sc->sc_dev,
1149 "could not allocate xfer\n");
1150 break;
1151 }
1152 data->buf = usbd_get_buffer(data->xfer);
1153 /* Append this Tx buffer to our free list. */
1154 TAILQ_INSERT_TAIL(&sc->sc_tx_free_list, data, next);
1155 }
1156 if (error != 0)
1157 otus_free_tx_data_list(sc);
1158 mutex_exit(&sc->sc_tx_mtx);
1159 return error;
1160 }
1161
1162 Static void
1163 otus_free_tx_data_list(struct otus_softc *sc)
1164 {
1165 int i;
1166
1167 DPRINTFN(DBG_FN, sc, "\n");
1168
1169 /* Make sure no transfers are pending. */
1170 usbd_abort_pipe(sc->sc_data_tx_pipe);
1171
1172 for (i = 0; i < OTUS_TX_DATA_LIST_COUNT; i++) {
1173 if (sc->sc_tx_data[i].xfer != NULL)
1174 usbd_destroy_xfer(sc->sc_tx_data[i].xfer);
1175 }
1176 }
1177
1178 Static int
1179 otus_alloc_rx_data_list(struct otus_softc *sc)
1180 {
1181 struct otus_rx_data *data;
1182 int i, error;
1183
1184 DPRINTFN(DBG_FN, sc, "\n");
1185
1186 for (i = 0; i < OTUS_RX_DATA_LIST_COUNT; i++) {
1187 data = &sc->sc_rx_data[i];
1188
1189 data->sc = sc; /* Backpointer for callbacks. */
1190
1191 error = usbd_create_xfer(sc->sc_data_rx_pipe, OTUS_RXBUFSZ,
1192 USBD_SHORT_XFER_OK, 0, &data->xfer);
1193
1194 if (error) {
1195 aprint_error_dev(sc->sc_dev,
1196 "could not allocate xfer\n");
1197 goto fail;
1198 }
1199 data->buf = usbd_get_buffer(data->xfer);
1200 }
1201 return 0;
1202
1203 fail: otus_free_rx_data_list(sc);
1204 return error;
1205 }
1206
1207 Static void
1208 otus_free_rx_data_list(struct otus_softc *sc)
1209 {
1210 int i;
1211
1212 DPRINTFN(DBG_FN, sc, "\n");
1213
1214 /* Make sure no transfers are pending. */
1215 usbd_abort_pipe(sc->sc_data_rx_pipe);
1216
1217 for (i = 0; i < OTUS_RX_DATA_LIST_COUNT; i++)
1218 if (sc->sc_rx_data[i].xfer != NULL)
1219 usbd_destroy_xfer(sc->sc_rx_data[i].xfer);
1220 }
1221
1222 Static void
1223 otus_next_scan(void *arg)
1224 {
1225 struct otus_softc *sc;
1226
1227 sc = arg;
1228
1229 DPRINTFN(DBG_FN, sc, "\n");
1230
1231 if (sc->sc_dying)
1232 return;
1233
1234 if (sc->sc_ic.ic_state == IEEE80211_S_SCAN)
1235 ieee80211_next_scan(&sc->sc_ic);
1236 }
1237
1238 Static void
1239 otus_task(void *arg)
1240 {
1241 struct otus_softc *sc;
1242 struct otus_host_cmd_ring *ring;
1243 struct otus_host_cmd *cmd;
1244
1245 sc = arg;
1246
1247 DPRINTFN(DBG_FN, sc, "\n");
1248
1249 /* Process host commands. */
1250 mutex_spin_enter(&sc->sc_task_mtx);
1251 ring = &sc->sc_cmdq;
1252 while (ring->next != ring->cur) {
1253 cmd = &ring->cmd[ring->next];
1254 mutex_spin_exit(&sc->sc_task_mtx);
1255
1256 /* Callback. */
1257 DPRINTFN(DBG_CMD, sc, "cb=%p queued=%d\n", cmd->cb,
1258 ring->queued);
1259 cmd->cb(sc, cmd->data);
1260
1261 mutex_spin_enter(&sc->sc_task_mtx);
1262 ring->queued--;
1263 ring->next = (ring->next + 1) % OTUS_HOST_CMD_RING_COUNT;
1264 }
1265 cv_signal(&sc->sc_task_cv);
1266 mutex_spin_exit(&sc->sc_task_mtx);
1267 }
1268
1269 Static void
1270 otus_do_async(struct otus_softc *sc, void (*cb)(struct otus_softc *, void *),
1271 void *arg, int len)
1272 {
1273 struct otus_host_cmd_ring *ring;
1274 struct otus_host_cmd *cmd;
1275 bool sched = false;
1276
1277 DPRINTFN(DBG_FN, sc, "cb=%p\n", cb);
1278
1279 mutex_spin_enter(&sc->sc_task_mtx);
1280 ring = &sc->sc_cmdq;
1281 cmd = &ring->cmd[ring->cur];
1282 cmd->cb = cb;
1283 KASSERT(len <= sizeof(cmd->data));
1284 memcpy(cmd->data, arg, len);
1285 ring->cur = (ring->cur + 1) % OTUS_HOST_CMD_RING_COUNT;
1286
1287 /* If there is no pending command already, schedule a task. */
1288 if (++ring->queued == 1) {
1289 sched = true;
1290 }
1291 cv_signal(&sc->sc_task_cv);
1292 mutex_spin_exit(&sc->sc_task_mtx);
1293 if (sched)
1294 usb_add_task(sc->sc_udev, &sc->sc_task, USB_TASKQ_DRIVER);
1295 }
1296
1297 Static int
1298 otus_newstate(struct ieee80211com *ic, enum ieee80211_state nstate, int arg)
1299 {
1300 struct otus_softc *sc;
1301 struct otus_cmd_newstate cmd;
1302
1303 sc = ic->ic_ifp->if_softc;
1304
1305 DPRINTFN(DBG_FN|DBG_STM, sc, "nstate=%s(%d), arg=%d\n",
1306 ieee80211_state_name[nstate], nstate, arg);
1307
1308 /* Do it in a process context. */
1309 cmd.state = nstate;
1310 cmd.arg = arg;
1311 otus_do_async(sc, otus_newstate_cb, &cmd, sizeof(cmd));
1312 return 0;
1313 }
1314
1315 Static void
1316 otus_newstate_cb(struct otus_softc *sc, void *arg)
1317 {
1318 struct otus_cmd_newstate *cmd;
1319 struct ieee80211com *ic;
1320 struct ieee80211_node *ni;
1321 enum ieee80211_state nstate;
1322 int s;
1323
1324 cmd = arg;
1325 ic = &sc->sc_ic;
1326 ni = ic->ic_bss;
1327 nstate = cmd->state;
1328
1329 #ifdef OTUS_DEBUG
1330 enum ieee80211_state ostate = ostate = ic->ic_state;
1331 DPRINTFN(DBG_FN|DBG_STM, sc, "%s(%d)->%s(%d)\n",
1332 ieee80211_state_name[ostate], ostate,
1333 ieee80211_state_name[nstate], nstate);
1334 #endif
1335
1336 s = splnet();
1337
1338 callout_halt(&sc->sc_scan_to, NULL);
1339 callout_halt(&sc->sc_calib_to, NULL);
1340
1341 mutex_enter(&sc->sc_write_mtx);
1342
1343 switch (nstate) {
1344 case IEEE80211_S_INIT:
1345 break;
1346
1347 case IEEE80211_S_SCAN:
1348 otus_set_chan(sc, ic->ic_curchan, 0);
1349 if (!sc->sc_dying)
1350 callout_schedule(&sc->sc_scan_to, hz / 5);
1351 break;
1352
1353 case IEEE80211_S_AUTH:
1354 case IEEE80211_S_ASSOC:
1355 otus_set_chan(sc, ic->ic_curchan, 0);
1356 break;
1357
1358 case IEEE80211_S_RUN:
1359 otus_set_chan(sc, ic->ic_curchan, 1);
1360
1361 switch (ic->ic_opmode) {
1362 case IEEE80211_M_STA:
1363 otus_updateslot_cb_locked(sc);
1364 otus_set_bssid(sc, ni->ni_bssid);
1365
1366 /* Fake a join to init the Tx rate. */
1367 otus_newassoc(ni, 1);
1368
1369 /* Start calibration timer. */
1370 if (!sc->sc_dying)
1371 callout_schedule(&sc->sc_calib_to, hz);
1372 break;
1373
1374 case IEEE80211_M_IBSS:
1375 case IEEE80211_M_AHDEMO:
1376 case IEEE80211_M_HOSTAP:
1377 case IEEE80211_M_MONITOR:
1378 break;
1379 }
1380 break;
1381 }
1382 (void)sc->sc_newstate(ic, nstate, cmd->arg);
1383 sc->sc_led_newstate(sc);
1384 mutex_exit(&sc->sc_write_mtx);
1385
1386 splx(s);
1387 }
1388
1389 Static int
1390 otus_cmd(struct otus_softc *sc, uint8_t code, const void *idata, int ilen,
1391 void *odata)
1392 {
1393 struct otus_tx_cmd *cmd;
1394 struct ar_cmd_hdr *hdr;
1395 int xferlen, error;
1396
1397 DPRINTFN(DBG_FN, sc, "\n");
1398
1399 cmd = &sc->sc_tx_cmd;
1400
1401 mutex_enter(&sc->sc_cmd_mtx);
1402
1403 /* Always bulk-out a multiple of 4 bytes. */
1404 xferlen = roundup2(sizeof(*hdr) + ilen, 4);
1405
1406 hdr = (void *)cmd->buf;
1407 if (hdr == NULL) { /* we may have been freed while detaching */
1408 mutex_exit(&sc->sc_cmd_mtx);
1409 DPRINTFN(DBG_CMD, sc, "tx_cmd freed with commands pending\n");
1410 return 0;
1411 }
1412 hdr->code = code;
1413 hdr->len = ilen;
1414 hdr->token = ++cmd->token; /* Don't care about endianness. */
1415 KASSERT(sizeof(hdr) + ilen <= OTUS_MAX_TXCMDSZ);
1416 memcpy(cmd->buf + sizeof(hdr[0]), idata, ilen);
1417
1418 DPRINTFN(DBG_CMD, sc, "sending command code=0x%02x len=%d token=%d\n",
1419 code, ilen, hdr->token);
1420
1421 cmd->odata = odata;
1422 cmd->done = 0;
1423 usbd_setup_xfer(cmd->xfer, cmd, cmd->buf, xferlen,
1424 USBD_FORCE_SHORT_XFER, OTUS_CMD_TIMEOUT, NULL);
1425 error = usbd_sync_transfer(cmd->xfer);
1426 if (error != 0) {
1427 mutex_exit(&sc->sc_cmd_mtx);
1428 #if defined(DIAGNOSTIC) || defined(OTUS_DEBUG) /* XXX: kill some noise */
1429 aprint_error_dev(sc->sc_dev,
1430 "could not send command 0x%x (error=%s)\n",
1431 code, usbd_errstr(error));
1432 #endif
1433 return EIO;
1434 }
1435 if (!cmd->done)
1436 error = cv_timedwait_sig(&sc->sc_cmd_cv, &sc->sc_cmd_mtx, hz);
1437 cmd->odata = NULL; /* In case answer is received too late. */
1438 mutex_exit(&sc->sc_cmd_mtx);
1439 if (error != 0) {
1440 aprint_error_dev(sc->sc_dev,
1441 "timeout waiting for command 0x%02x reply\n", code);
1442 }
1443 return error;
1444 }
1445
1446 Static void
1447 otus_write(struct otus_softc *sc, uint32_t reg, uint32_t val)
1448 {
1449
1450 DPRINTFN(DBG_FN|DBG_REG, sc, "reg=0x%x, val=0x%x\n", reg, val);
1451
1452 KASSERT(mutex_owned(&sc->sc_write_mtx));
1453 KASSERT(sc->sc_write_idx < __arraycount(sc->sc_write_buf));
1454
1455 sc->sc_write_buf[sc->sc_write_idx].reg = htole32(reg);
1456 sc->sc_write_buf[sc->sc_write_idx].val = htole32(val);
1457
1458 if (++sc->sc_write_idx >= __arraycount(sc->sc_write_buf))
1459 (void)otus_write_barrier(sc);
1460 }
1461
1462 Static int
1463 otus_write_barrier(struct otus_softc *sc)
1464 {
1465 int error;
1466
1467 DPRINTFN(DBG_FN, sc, "\n");
1468
1469 KASSERT(mutex_owned(&sc->sc_write_mtx));
1470 KASSERT(sc->sc_write_idx <= __arraycount(sc->sc_write_buf));
1471
1472 if (sc->sc_write_idx == 0)
1473 return 0; /* Nothing to flush. */
1474
1475 error = otus_cmd(sc, AR_CMD_WREG, sc->sc_write_buf,
1476 sizeof(sc->sc_write_buf[0]) * sc->sc_write_idx, NULL);
1477
1478 sc->sc_write_idx = 0;
1479 if (error)
1480 DPRINTFN(DBG_REG, sc, "error=%d\n", error);
1481 return error;
1482 }
1483
1484 Static struct ieee80211_node *
1485 otus_node_alloc(struct ieee80211_node_table *ntp)
1486 {
1487 struct otus_node *on;
1488
1489 DPRINTFN(DBG_FN, DBG_NO_SC, "\n");
1490
1491 on = malloc(sizeof(*on), M_DEVBUF, M_NOWAIT | M_ZERO);
1492 return &on->ni;
1493 }
1494
1495 Static int
1496 otus_media_change(struct ifnet *ifp)
1497 {
1498 struct otus_softc *sc;
1499 struct ieee80211com *ic;
1500 uint8_t rate, ridx;
1501 int error;
1502
1503 sc = ifp->if_softc;
1504
1505 DPRINTFN(DBG_FN, sc, "\n");
1506
1507 error = ieee80211_media_change(ifp);
1508 if (error != ENETRESET)
1509 return error;
1510
1511 ic = &sc->sc_ic;
1512 if (ic->ic_fixed_rate != -1) {
1513 rate = ic->ic_sup_rates[ic->ic_curmode].
1514 rs_rates[ic->ic_fixed_rate] & IEEE80211_RATE_VAL;
1515 for (ridx = 0; ridx <= OTUS_RIDX_MAX; ridx++)
1516 if (otus_rates[ridx].rate == rate)
1517 break;
1518 sc->sc_fixed_ridx = ridx;
1519 }
1520
1521 if ((ifp->if_flags & (IFF_UP | IFF_RUNNING)) == (IFF_UP | IFF_RUNNING))
1522 error = otus_init(ifp);
1523
1524 return error;
1525 }
1526
1527 Static int
1528 otus_read_eeprom(struct otus_softc *sc)
1529 {
1530 uint32_t regs[8], reg;
1531 uint8_t *eep;
1532 int i, j, error;
1533
1534 DPRINTFN(DBG_FN, sc, "\n");
1535
1536 KASSERT(sizeof(sc->sc_eeprom) % 32 == 0);
1537
1538 /* Read EEPROM by blocks of 32 bytes. */
1539 eep = (uint8_t *)&sc->sc_eeprom;
1540 reg = AR_EEPROM_OFFSET;
1541 for (i = 0; i < sizeof(sc->sc_eeprom) / 32; i++) {
1542 for (j = 0; j < 8; j++, reg += 4)
1543 regs[j] = htole32(reg);
1544 error = otus_cmd(sc, AR_CMD_RREG, regs, sizeof(regs), eep);
1545 if (error != 0)
1546 break;
1547 eep += 32;
1548 }
1549 return error;
1550 }
1551
1552 Static void
1553 otus_newassoc(struct ieee80211_node *ni, int isnew)
1554 {
1555 struct ieee80211_rateset *rs;
1556 struct otus_softc *sc;
1557 struct otus_node *on;
1558 uint8_t rate;
1559 int ridx, i;
1560
1561 sc = ni->ni_ic->ic_ifp->if_softc;
1562
1563 DPRINTFN(DBG_FN, sc, "isnew=%d addr=%s\n",
1564 isnew, ether_sprintf(ni->ni_macaddr));
1565
1566 on = (void *)ni;
1567 ieee80211_amrr_node_init(&sc->sc_amrr, &on->amn);
1568 /* Start at lowest available bit-rate, AMRR will raise. */
1569 ni->ni_txrate = 0;
1570 rs = &ni->ni_rates;
1571 for (i = 0; i < rs->rs_nrates; i++) {
1572 rate = rs->rs_rates[i] & IEEE80211_RATE_VAL;
1573 /* Convert 802.11 rate to hardware rate index. */
1574 for (ridx = 0; ridx <= OTUS_RIDX_MAX; ridx++)
1575 if (otus_rates[ridx].rate == rate)
1576 break;
1577 on->ridx[i] = ridx;
1578 DPRINTFN(DBG_INIT, sc, "rate=0x%02x ridx=%d\n",
1579 rs->rs_rates[i], on->ridx[i]);
1580 }
1581 }
1582
1583 /* ARGSUSED */
1584 Static void
1585 otus_intr(struct usbd_xfer *xfer, void *priv, usbd_status status)
1586 {
1587 #if 0
1588 struct otus_softc *sc;
1589 int len;
1590
1591 sc = priv;
1592
1593 DPRINTFN(DBG_FN, sc, "\n");
1594
1595 /*
1596 * The Rx intr pipe is unused with current firmware. Notifications
1597 * and replies to commands are sent through the Rx bulk pipe instead
1598 * (with a magic PLCP header.)
1599 */
1600 if (__predict_false(status != USBD_NORMAL_COMPLETION)) {
1601 DPRINTFN(DBG_INTR, sc, "status=%d\n", status);
1602 if (status == USBD_STALLED)
1603 usbd_clear_endpoint_stall_async(sc->sc_cmd_rx_pipe);
1604 return;
1605 }
1606 usbd_get_xfer_status(xfer, NULL, NULL, &len, NULL);
1607
1608 otus_cmd_rxeof(sc, sc->sc_ibuf, len);
1609 #endif
1610 }
1611
1612 Static void
1613 otus_cmd_rxeof(struct otus_softc *sc, uint8_t *buf, int len)
1614 {
1615 struct ieee80211com *ic;
1616 struct otus_tx_cmd *cmd;
1617 struct ar_cmd_hdr *hdr;
1618 int s;
1619
1620 DPRINTFN(DBG_FN, sc, "\n");
1621
1622 ic = &sc->sc_ic;
1623
1624 if (__predict_false(len < sizeof(*hdr))) {
1625 DPRINTFN(DBG_RX, sc, "cmd too small %d\n", len);
1626 return;
1627 }
1628 hdr = (void *)buf;
1629 if (__predict_false(sizeof(*hdr) + hdr->len > len ||
1630 sizeof(*hdr) + hdr->len > 64)) {
1631 DPRINTFN(DBG_RX, sc, "cmd too large %d\n", hdr->len);
1632 return;
1633 }
1634
1635 if ((hdr->code & 0xc0) != 0xc0) {
1636 DPRINTFN(DBG_RX, sc, "received reply code=0x%02x len=%d token=%d\n",
1637 hdr->code, hdr->len, hdr->token);
1638 mutex_enter(&sc->sc_cmd_mtx);
1639 cmd = &sc->sc_tx_cmd;
1640 if (__predict_false(hdr->token != cmd->token)) {
1641 mutex_exit(&sc->sc_cmd_mtx);
1642 return;
1643 }
1644 /* Copy answer into caller's supplied buffer. */
1645 if (cmd->odata != NULL)
1646 memcpy(cmd->odata, &hdr[1], hdr->len);
1647 cmd->done = 1;
1648 cv_signal(&sc->sc_cmd_cv);
1649 mutex_exit(&sc->sc_cmd_mtx);
1650 return;
1651 }
1652
1653 /* Received unsolicited notification. */
1654 DPRINTFN(DBG_RX, sc, "received notification code=0x%02x len=%d\n",
1655 hdr->code, hdr->len);
1656 switch (hdr->code & 0x3f) {
1657 case AR_EVT_BEACON:
1658 break;
1659 case AR_EVT_TX_COMP:
1660 {
1661 struct ar_evt_tx_comp *tx;
1662 struct ieee80211_node *ni;
1663 struct otus_node *on;
1664
1665 tx = (void *)&hdr[1];
1666
1667 DPRINTFN(DBG_RX, sc, "tx completed %s status=%d phy=0x%x\n",
1668 ether_sprintf(tx->macaddr), le16toh(tx->status),
1669 le32toh(tx->phy));
1670 s = splnet();
1671 #ifdef notyet
1672 #ifndef IEEE80211_STA_ONLY
1673 if (ic->ic_opmode != IEEE80211_M_STA) {
1674 ni = ieee80211_find_node(ic, tx->macaddr);
1675 if (__predict_false(ni == NULL)) {
1676 splx(s);
1677 break;
1678 }
1679 } else
1680 #endif
1681 #endif
1682 ni = ic->ic_bss;
1683 /* Update rate control statistics. */
1684 on = (void *)ni;
1685 /* NB: we do not set the TX_MAC_RATE_PROBING flag. */
1686 if (__predict_true(tx->status != 0))
1687 on->amn.amn_retrycnt++;
1688 splx(s);
1689 break;
1690 }
1691 case AR_EVT_TBTT:
1692 break;
1693 }
1694 }
1695
1696 Static void
1697 otus_sub_rxeof(struct otus_softc *sc, uint8_t *buf, int len)
1698 {
1699 struct ieee80211com *ic;
1700 struct ifnet *ifp;
1701 struct ieee80211_node *ni;
1702 struct ar_rx_tail *tail;
1703 struct ieee80211_frame *wh;
1704 struct mbuf *m;
1705 uint8_t *plcp;
1706 int s, mlen, align;
1707
1708 DPRINTFN(DBG_FN, sc, "\n");
1709
1710 ic = &sc->sc_ic;
1711 ifp = ic->ic_ifp;
1712
1713 if (__predict_false(len < AR_PLCP_HDR_LEN)) {
1714 DPRINTFN(DBG_RX, sc, "sub-xfer too short %d\n", len);
1715 return;
1716 }
1717 plcp = buf;
1718
1719 /* All bits in the PLCP header are set to 1 for non-MPDU. */
1720 if (memcmp(plcp, AR_PLCP_HDR_INTR, AR_PLCP_HDR_LEN) == 0) {
1721 otus_cmd_rxeof(sc, plcp + AR_PLCP_HDR_LEN,
1722 len - AR_PLCP_HDR_LEN);
1723 return;
1724 }
1725
1726 /* Received MPDU. */
1727 if (__predict_false(len < AR_PLCP_HDR_LEN + sizeof(*tail))) {
1728 DPRINTFN(DBG_RX, sc, "MPDU too short %d\n", len);
1729 ifp->if_ierrors++;
1730 return;
1731 }
1732 tail = (void *)(plcp + len - sizeof(*tail));
1733 wh = (void *)(plcp + AR_PLCP_HDR_LEN);
1734
1735 /* Discard error frames. */
1736 if (__predict_false((tail->error & sc->sc_rx_error_msk) != 0)) {
1737 DPRINTFN(DBG_RX, sc, "error frame 0x%02x\n", tail->error);
1738 if (tail->error & AR_RX_ERROR_FCS) {
1739 DPRINTFN(DBG_RX, sc, "bad FCS\n");
1740 } else if (tail->error & AR_RX_ERROR_MMIC) {
1741 /* Report Michael MIC failures to net80211. */
1742 ieee80211_notify_michael_failure(ic, wh, 0 /* XXX: keyix */);
1743 }
1744 ifp->if_ierrors++;
1745 return;
1746 }
1747 /* Compute MPDU's length. */
1748 mlen = len - AR_PLCP_HDR_LEN - sizeof(*tail);
1749 mlen -= IEEE80211_CRC_LEN; /* strip 802.11 FCS */
1750 /* Make sure there's room for an 802.11 header. */
1751 /*
1752 * XXX: This will drop most control packets. Do we really
1753 * want this in IEEE80211_M_MONITOR mode?
1754 */
1755 if (__predict_false(mlen < sizeof(*wh))) {
1756 ifp->if_ierrors++;
1757 return;
1758 }
1759
1760 /* Provide a 32-bit aligned protocol header to the stack. */
1761 align = (ieee80211_has_qos(wh) ^ ieee80211_has_addr4(wh)) ? 2 : 0;
1762
1763 MGETHDR(m, M_DONTWAIT, MT_DATA);
1764 if (__predict_false(m == NULL)) {
1765 ifp->if_ierrors++;
1766 return;
1767 }
1768 if (align + mlen > MHLEN) {
1769 MCLGET(m, M_DONTWAIT);
1770 if (__predict_false(!(m->m_flags & M_EXT))) {
1771 ifp->if_ierrors++;
1772 m_freem(m);
1773 return;
1774 }
1775 }
1776 /* Finalize mbuf. */
1777 m->m_pkthdr.rcvif = ifp;
1778 m->m_data += align;
1779 memcpy(mtod(m, void *), wh, mlen);
1780 m->m_pkthdr.len = m->m_len = mlen;
1781
1782 s = splnet();
1783 if (__predict_false(sc->sc_drvbpf != NULL)) {
1784 struct otus_rx_radiotap_header *tap;
1785
1786 tap = &sc->sc_rxtap;
1787 tap->wr_flags = 0;
1788 tap->wr_chan_freq = htole16(ic->ic_curchan->ic_freq);
1789 tap->wr_chan_flags = htole16(ic->ic_curchan->ic_flags);
1790 tap->wr_antsignal = tail->rssi;
1791 tap->wr_rate = 2; /* In case it can't be found below. */
1792 switch (tail->status & AR_RX_STATUS_MT_MASK) {
1793 case AR_RX_STATUS_MT_CCK:
1794 switch (plcp[0]) {
1795 case 10: tap->wr_rate = 2; break;
1796 case 20: tap->wr_rate = 4; break;
1797 case 55: tap->wr_rate = 11; break;
1798 case 110: tap->wr_rate = 22; break;
1799 }
1800 if (tail->status & AR_RX_STATUS_SHPREAMBLE)
1801 tap->wr_flags |= IEEE80211_RADIOTAP_F_SHORTPRE;
1802 break;
1803 case AR_RX_STATUS_MT_OFDM:
1804 switch (plcp[0] & 0xf) {
1805 case 0xb: tap->wr_rate = 12; break;
1806 case 0xf: tap->wr_rate = 18; break;
1807 case 0xa: tap->wr_rate = 24; break;
1808 case 0xe: tap->wr_rate = 36; break;
1809 case 0x9: tap->wr_rate = 48; break;
1810 case 0xd: tap->wr_rate = 72; break;
1811 case 0x8: tap->wr_rate = 96; break;
1812 case 0xc: tap->wr_rate = 108; break;
1813 }
1814 break;
1815 }
1816 bpf_mtap2(sc->sc_drvbpf, tap, sc->sc_rxtap_len, m);
1817 }
1818
1819 ni = ieee80211_find_rxnode(ic, (struct ieee80211_frame_min *)wh);
1820
1821 /* push the frame up to the 802.11 stack */
1822 ieee80211_input(ic, m, ni, tail->rssi, 0);
1823
1824 /* Node is no longer needed. */
1825 ieee80211_free_node(ni);
1826 splx(s);
1827 }
1828
1829 Static void
1830 otus_rxeof(struct usbd_xfer *xfer, void *priv, usbd_status status)
1831 {
1832 struct otus_rx_data *data;
1833 struct otus_softc *sc;
1834 uint8_t *buf;
1835 struct ar_rx_head *head;
1836 uint16_t hlen;
1837 int len;
1838
1839 data = priv;
1840 sc = data->sc;
1841
1842 DPRINTFN(DBG_FN, sc, "\n");
1843
1844 buf = data->buf;
1845
1846 if (__predict_false(status != USBD_NORMAL_COMPLETION)) {
1847 DPRINTFN(DBG_RX, sc, "RX status=%d\n", status);
1848 if (status == USBD_STALLED)
1849 usbd_clear_endpoint_stall_async(sc->sc_data_rx_pipe);
1850 else if (status != USBD_CANCELLED) {
1851 DPRINTFN(DBG_RX, sc,
1852 "otus_rxeof: goto resubmit: status=%d\n", status);
1853 goto resubmit;
1854 }
1855 return;
1856 }
1857 usbd_get_xfer_status(xfer, NULL, NULL, &len, NULL);
1858
1859 while (len >= sizeof(*head)) {
1860 head = (void *)buf;
1861 if (__predict_false(head->tag != htole16(AR_RX_HEAD_TAG))) {
1862 DPRINTFN(DBG_RX, sc, "tag not valid 0x%x\n",
1863 le16toh(head->tag));
1864 break;
1865 }
1866 hlen = le16toh(head->len);
1867 if (__predict_false(sizeof(*head) + hlen > len)) {
1868 DPRINTFN(DBG_RX, sc, "xfer too short %d/%d\n",
1869 len, hlen);
1870 break;
1871 }
1872 /* Process sub-xfer. */
1873 otus_sub_rxeof(sc, (uint8_t *)&head[1], hlen);
1874
1875 /* Next sub-xfer is aligned on a 32-bit boundary. */
1876 hlen = roundup2(sizeof(*head) + hlen, 4);
1877 buf += hlen;
1878 len -= hlen;
1879 }
1880
1881 resubmit:
1882 usbd_setup_xfer(xfer, data, data->buf, OTUS_RXBUFSZ,
1883 USBD_SHORT_XFER_OK, USBD_NO_TIMEOUT, otus_rxeof);
1884 (void)usbd_transfer(data->xfer);
1885 }
1886
1887 Static void
1888 otus_txeof(struct usbd_xfer *xfer, void *priv, usbd_status status)
1889 {
1890 struct otus_tx_data *data;
1891 struct otus_softc *sc;
1892 struct ieee80211com *ic;
1893 struct ifnet *ifp;
1894 int s;
1895
1896 data = priv;
1897 sc = data->sc;
1898
1899 DPRINTFN(DBG_FN, sc, "\n");
1900
1901 /* Put this Tx buffer back to the free list. */
1902 mutex_enter(&sc->sc_tx_mtx);
1903 TAILQ_INSERT_TAIL(&sc->sc_tx_free_list, data, next);
1904 mutex_exit(&sc->sc_tx_mtx);
1905
1906 ic = &sc->sc_ic;
1907 ifp = ic->ic_ifp;
1908 if (__predict_false(status != USBD_NORMAL_COMPLETION)) {
1909 DPRINTFN(DBG_TX, sc, "TX status=%d\n", status);
1910 if (status == USBD_STALLED)
1911 usbd_clear_endpoint_stall_async(sc->sc_data_tx_pipe);
1912 ifp->if_oerrors++;
1913 return;
1914 }
1915 ifp->if_opackets++;
1916
1917 s = splnet();
1918 sc->sc_tx_timer = 0;
1919 ifp->if_flags &= ~IFF_OACTIVE; /* XXX: do after freeing Tx buffer? */
1920 otus_start(ifp);
1921 splx(s);
1922 }
1923
1924 Static int
1925 otus_tx(struct otus_softc *sc, struct mbuf *m, struct ieee80211_node *ni,
1926 struct otus_tx_data *data)
1927 {
1928 struct ieee80211com *ic;
1929 struct otus_node *on;
1930 struct ieee80211_frame *wh;
1931 struct ieee80211_key *k;
1932 struct ar_tx_head *head;
1933 uint32_t phyctl;
1934 uint16_t macctl, qos;
1935 uint8_t qid;
1936 int error, ridx, hasqos, xferlen;
1937
1938 DPRINTFN(DBG_FN, sc, "\n");
1939
1940 ic = &sc->sc_ic;
1941 on = (void *)ni;
1942
1943 wh = mtod(m, struct ieee80211_frame *);
1944 if ((wh->i_fc[1] & IEEE80211_FC1_PROTECTED)) {
1945 /* XXX: derived from upgt_tx_task() and ural_tx_data() */
1946 k = ieee80211_crypto_encap(ic, ni, m);
1947 if (k == NULL)
1948 return ENOBUFS;
1949
1950 /* Packet header may have moved, reset our local pointer. */
1951 wh = mtod(m, struct ieee80211_frame *);
1952 }
1953
1954 #ifdef HAVE_EDCA
1955 if ((hasqos = ieee80211_has_qos(wh))) {
1956 qos = ieee80211_get_qos(wh);
1957 qid = ieee80211_up_to_ac(ic, qos & IEEE80211_QOS_TID);
1958 } else {
1959 qos = 0;
1960 qid = WME_AC_BE;
1961 }
1962 #else
1963 hasqos = 0;
1964 qos = 0;
1965 qid = WME_AC_BE;
1966 #endif
1967
1968 /* Pickup a rate index. */
1969 if (IEEE80211_IS_MULTICAST(wh->i_addr1) ||
1970 (wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK) != IEEE80211_FC0_TYPE_DATA)
1971 ridx = (ic->ic_curmode == IEEE80211_MODE_11A) ?
1972 OTUS_RIDX_OFDM6 : OTUS_RIDX_CCK1;
1973 else if (ic->ic_fixed_rate != -1)
1974 ridx = sc->sc_fixed_ridx;
1975 else
1976 ridx = on->ridx[ni->ni_txrate];
1977
1978 phyctl = 0;
1979 macctl = AR_TX_MAC_BACKOFF | AR_TX_MAC_HW_DUR | AR_TX_MAC_QID(qid);
1980
1981 if (IEEE80211_IS_MULTICAST(wh->i_addr1) ||
1982 (hasqos && ((qos & IEEE80211_QOS_ACKPOLICY_MASK) ==
1983 IEEE80211_QOS_ACKPOLICY_NOACK)))
1984 macctl |= AR_TX_MAC_NOACK;
1985
1986 if (!IEEE80211_IS_MULTICAST(wh->i_addr1)) {
1987 if (m->m_pkthdr.len + IEEE80211_CRC_LEN >= ic->ic_rtsthreshold)
1988 macctl |= AR_TX_MAC_RTS;
1989 else if ((ic->ic_flags & IEEE80211_F_USEPROT) &&
1990 ridx >= OTUS_RIDX_OFDM6) {
1991 if (ic->ic_protmode == IEEE80211_PROT_CTSONLY)
1992 macctl |= AR_TX_MAC_CTS;
1993 else if (ic->ic_protmode == IEEE80211_PROT_RTSCTS)
1994 macctl |= AR_TX_MAC_RTS;
1995 }
1996 }
1997
1998 phyctl |= AR_TX_PHY_MCS(otus_rates[ridx].mcs);
1999 if (ridx >= OTUS_RIDX_OFDM6) {
2000 phyctl |= AR_TX_PHY_MT_OFDM;
2001 if (ridx <= OTUS_RIDX_OFDM24)
2002 phyctl |= AR_TX_PHY_ANTMSK(sc->sc_txmask);
2003 else
2004 phyctl |= AR_TX_PHY_ANTMSK(1);
2005 } else { /* CCK */
2006 phyctl |= AR_TX_PHY_MT_CCK;
2007 phyctl |= AR_TX_PHY_ANTMSK(sc->sc_txmask);
2008 }
2009
2010 /* Update rate control stats for frames that are ACK'ed. */
2011 if (!(macctl & AR_TX_MAC_NOACK))
2012 on->amn.amn_txcnt++;
2013
2014 /* Fill Tx descriptor. */
2015 head = (void *)data->buf;
2016 head->len = htole16(m->m_pkthdr.len + IEEE80211_CRC_LEN);
2017 head->macctl = htole16(macctl);
2018 head->phyctl = htole32(phyctl);
2019
2020 if (__predict_false(sc->sc_drvbpf != NULL)) {
2021 struct otus_tx_radiotap_header *tap = &sc->sc_txtap;
2022
2023 tap->wt_flags = 0;
2024 if (wh->i_fc[1] & IEEE80211_FC1_WEP)
2025 tap->wt_flags |= IEEE80211_RADIOTAP_F_WEP;
2026 tap->wt_rate = otus_rates[ridx].rate;
2027 tap->wt_chan_freq = htole16(ic->ic_curchan->ic_freq);
2028 tap->wt_chan_flags = htole16(ic->ic_curchan->ic_flags);
2029
2030 bpf_mtap2(sc->sc_drvbpf, tap, sc->sc_txtap_len, m);
2031 }
2032
2033 xferlen = sizeof(*head) + m->m_pkthdr.len;
2034 m_copydata(m, 0, m->m_pkthdr.len, (void *)&head[1]);
2035
2036 DPRINTFN(DBG_TX, sc, "queued len=%d mac=0x%04x phy=0x%08x rate=%d\n",
2037 head->len, head->macctl, head->phyctl, otus_rates[ridx].rate);
2038
2039 usbd_setup_xfer(data->xfer, data, data->buf, xferlen,
2040 USBD_FORCE_SHORT_XFER, OTUS_TX_TIMEOUT, otus_txeof);
2041 error = usbd_transfer(data->xfer);
2042 if (__predict_false(
2043 error != USBD_NORMAL_COMPLETION &&
2044 error != USBD_IN_PROGRESS)) {
2045 DPRINTFN(DBG_TX, sc, "transfer failed %d\n", error);
2046 return error;
2047 }
2048 return 0;
2049 }
2050
2051 Static void
2052 otus_start(struct ifnet *ifp)
2053 {
2054 struct otus_softc *sc;
2055 struct ieee80211com *ic;
2056 struct otus_tx_data *data;
2057 struct ether_header *eh;
2058 struct ieee80211_node *ni;
2059 struct mbuf *m;
2060
2061 if ((ifp->if_flags & (IFF_RUNNING | IFF_OACTIVE)) != IFF_RUNNING)
2062 return;
2063
2064 sc = ifp->if_softc;
2065 ic = &sc->sc_ic;
2066
2067 DPRINTFN(DBG_FN, sc, "\n");
2068
2069 data = NULL;
2070 for (;;) {
2071 /*
2072 * Grab a Tx buffer if we don't already have one. If
2073 * one isn't available, bail out.
2074 * NB: We must obtain this Tx buffer _before_
2075 * dequeueing anything as one may not be available
2076 * later. Both must be done inside a single lock.
2077 */
2078 mutex_enter(&sc->sc_tx_mtx);
2079 if (data == NULL && !TAILQ_EMPTY(&sc->sc_tx_free_list)) {
2080 data = TAILQ_FIRST(&sc->sc_tx_free_list);
2081 TAILQ_REMOVE(&sc->sc_tx_free_list, data, next);
2082 }
2083 mutex_exit(&sc->sc_tx_mtx);
2084
2085 if (data == NULL) {
2086 ifp->if_flags |= IFF_OACTIVE;
2087 DPRINTFN(DBG_TX, sc, "empty sc_tx_free_list\n");
2088 return;
2089 }
2090
2091 /* Send pending management frames first. */
2092 IF_DEQUEUE(&ic->ic_mgtq, m);
2093 if (m != NULL) {
2094 ni = M_GETCTX(m, struct ieee80211_node *);
2095 M_CLEARCTX(m);
2096 goto sendit;
2097 }
2098
2099 if (ic->ic_state != IEEE80211_S_RUN)
2100 break;
2101
2102 /* Encapsulate and send data frames. */
2103 IFQ_DEQUEUE(&ifp->if_snd, m);
2104 if (m == NULL)
2105 break;
2106
2107 if (m->m_len < (int)sizeof(*eh) &&
2108 (m = m_pullup(m, sizeof(*eh))) == NULL) {
2109 ifp->if_oerrors++;
2110 continue;
2111 }
2112
2113 eh = mtod(m, struct ether_header *);
2114 ni = ieee80211_find_txnode(ic, eh->ether_dhost);
2115 if (ni == NULL) {
2116 m_freem(m);
2117 ifp->if_oerrors++;
2118 continue;
2119 }
2120
2121 bpf_mtap(ifp, m);
2122
2123 if ((m = ieee80211_encap(ic, m, ni)) == NULL) {
2124 /* original m was freed by ieee80211_encap() */
2125 ieee80211_free_node(ni);
2126 ifp->if_oerrors++;
2127 continue;
2128 }
2129 sendit:
2130 bpf_mtap3(ic->ic_rawbpf, m);
2131
2132 if (otus_tx(sc, m, ni, data) != 0) {
2133 m_freem(m);
2134 ieee80211_free_node(ni);
2135 ifp->if_oerrors++;
2136 continue;
2137 }
2138
2139 data = NULL; /* we're finished with this data buffer */
2140 m_freem(m);
2141 ieee80211_free_node(ni);
2142 sc->sc_tx_timer = 5;
2143 ifp->if_timer = 1;
2144 }
2145
2146 /*
2147 * If here, we have a Tx buffer, but ran out of mbufs to
2148 * transmit. Put the Tx buffer back to the free list.
2149 */
2150 mutex_enter(&sc->sc_tx_mtx);
2151 TAILQ_INSERT_TAIL(&sc->sc_tx_free_list, data, next);
2152 mutex_exit(&sc->sc_tx_mtx);
2153 }
2154
2155 Static void
2156 otus_watchdog(struct ifnet *ifp)
2157 {
2158 struct otus_softc *sc;
2159
2160 sc = ifp->if_softc;
2161
2162 DPRINTFN(DBG_FN, sc, "\n");
2163
2164 ifp->if_timer = 0;
2165
2166 if (sc->sc_tx_timer > 0) {
2167 if (--sc->sc_tx_timer == 0) {
2168 aprint_error_dev(sc->sc_dev, "device timeout\n");
2169 /* otus_init(ifp); XXX needs a process context! */
2170 ifp->if_oerrors++;
2171 return;
2172 }
2173 ifp->if_timer = 1;
2174 }
2175 ieee80211_watchdog(&sc->sc_ic);
2176 }
2177
2178 Static int
2179 otus_ioctl(struct ifnet *ifp, u_long cmd, void *data)
2180 {
2181 struct otus_softc *sc;
2182 struct ieee80211com *ic;
2183 int s, error = 0;
2184
2185 sc = ifp->if_softc;
2186
2187 DPRINTFN(DBG_FN, sc, "0x%lx\n", cmd);
2188
2189 ic = &sc->sc_ic;
2190
2191 s = splnet();
2192
2193 switch (cmd) {
2194 case SIOCSIFADDR:
2195 ifp->if_flags |= IFF_UP;
2196 #ifdef INET
2197 struct ifaddr *ifa = data;
2198 if (ifa->ifa_addr->sa_family == AF_INET)
2199 arp_ifinit(&ic->ic_ac, ifa);
2200 #endif
2201 /* FALLTHROUGH */
2202 case SIOCSIFFLAGS:
2203 if ((error = ifioctl_common(ifp, cmd, data)) != 0)
2204 break;
2205
2206 switch (ifp->if_flags & (IFF_UP | IFF_RUNNING)) {
2207 case IFF_UP | IFF_RUNNING:
2208 if (((ifp->if_flags ^ sc->sc_if_flags) &
2209 (IFF_ALLMULTI | IFF_PROMISC)) != 0)
2210 otus_set_multi(sc);
2211 break;
2212 case IFF_UP:
2213 otus_init(ifp);
2214 break;
2215
2216 case IFF_RUNNING:
2217 otus_stop(ifp);
2218 break;
2219 case 0:
2220 default:
2221 break;
2222 }
2223 sc->sc_if_flags = ifp->if_flags;
2224 break;
2225
2226 case SIOCADDMULTI:
2227 case SIOCDELMULTI:
2228 if ((error = ether_ioctl(ifp, cmd, data)) == ENETRESET) {
2229 /* setup multicast filter, etc */
2230 /* XXX: ??? */
2231 error = 0;
2232 }
2233 break;
2234
2235 case SIOCS80211CHANNEL:
2236 /*
2237 * This allows for fast channel switching in monitor mode
2238 * (used by kismet). In IBSS mode, we must explicitly reset
2239 * the interface to generate a new beacon frame.
2240 */
2241 error = ieee80211_ioctl(ic, cmd, data);
2242
2243 DPRINTFN(DBG_CHAN, sc,
2244 "ic_curchan=%d ic_ibss_chan=%d ic_des_chan=%d ni_chan=%d error=%d\n",
2245 ieee80211_chan2ieee(ic, ic->ic_curchan),
2246 ieee80211_chan2ieee(ic, ic->ic_ibss_chan),
2247 ieee80211_chan2ieee(ic, ic->ic_des_chan),
2248 ieee80211_chan2ieee(ic, ic->ic_bss->ni_chan),
2249 error);
2250
2251 if (error == ENETRESET &&
2252 ic->ic_opmode == IEEE80211_M_MONITOR) {
2253 if ((ifp->if_flags & (IFF_UP | IFF_RUNNING)) ==
2254 (IFF_UP | IFF_RUNNING)) {
2255 mutex_enter(&sc->sc_write_mtx);
2256 otus_set_chan(sc, ic->ic_curchan, 0);
2257 mutex_exit(&sc->sc_write_mtx);
2258 }
2259 error = 0;
2260 }
2261 break;
2262
2263 default:
2264 error = ieee80211_ioctl(ic, cmd, data);
2265 }
2266 if (error == ENETRESET) {
2267 if ((ifp->if_flags & (IFF_UP | IFF_RUNNING)) ==
2268 (IFF_UP | IFF_RUNNING))
2269 otus_init(ifp);
2270 error = 0;
2271 }
2272 splx(s);
2273 return error;
2274 }
2275
2276 Static int
2277 otus_set_multi(struct otus_softc *sc)
2278 {
2279 struct ifnet *ifp;
2280 struct ether_multi *enm;
2281 struct ether_multistep step;
2282 uint32_t lo, hi;
2283 uint8_t bit;
2284 int error;
2285
2286 DPRINTFN(DBG_FN, sc, "\n");
2287
2288 ifp = sc->sc_ic.ic_ifp;
2289 if ((ifp->if_flags & (IFF_ALLMULTI | IFF_PROMISC)) != 0) {
2290 lo = hi = 0xffffffff;
2291 goto done;
2292 }
2293 lo = hi = 0;
2294 ETHER_FIRST_MULTI(step, &sc->sc_ec, enm);
2295 while (enm != NULL) {
2296 if (bcmp(enm->enm_addrlo, enm->enm_addrhi, ETHER_ADDR_LEN)) {
2297 ifp->if_flags |= IFF_ALLMULTI;
2298 lo = hi = 0xffffffff;
2299 goto done;
2300 }
2301 bit = enm->enm_addrlo[5] >> 2;
2302 if (bit < 32)
2303 lo |= 1 << bit;
2304 else
2305 hi |= 1 << (bit - 32);
2306 ETHER_NEXT_MULTI(step, enm);
2307 }
2308 done:
2309 mutex_enter(&sc->sc_write_mtx);
2310 hi |= 1 << 31; /* Make sure the broadcast bit is set. */
2311 otus_write(sc, AR_MAC_REG_GROUP_HASH_TBL_L, lo);
2312 otus_write(sc, AR_MAC_REG_GROUP_HASH_TBL_H, hi);
2313 error = otus_write_barrier(sc);
2314 mutex_exit(&sc->sc_write_mtx);
2315 return error;
2316 }
2317
2318 #ifdef HAVE_EDCA
2319 Static void
2320 otus_updateedca(struct ieee80211com *ic)
2321 {
2322
2323 DPRINTFN(DBG_FN, DBG_NO_SC, "\n");
2324
2325 /* Do it in a process context. */
2326 otus_do_async(ic->ic_ifp->if_softc, otus_updateedca_cb, NULL, 0);
2327 }
2328
2329 Static void
2330 otus_updateedca_cb(struct otus_softc *sc, void *arg __used)
2331 {
2332
2333 DPRINTFN(DBG_FN, sc, "\n");
2334
2335 mutex_enter(&sc->sc_write_mtx);
2336 otus_updateedca_cb_locked(sc);
2337 mutex_exit(&sc->sc_write_mtx);
2338 }
2339 #endif
2340
2341 Static void
2342 otus_updateedca_cb_locked(struct otus_softc *sc)
2343 {
2344 #ifdef HAVE_EDCA
2345 struct ieee80211com *ic;
2346 #endif
2347 const struct ieee80211_edca_ac_params *edca;
2348 int s;
2349
2350 DPRINTFN(DBG_FN, sc, "\n");
2351
2352 KASSERT(mutex_owned(&sc->sc_write_mtx));
2353
2354 s = splnet();
2355
2356 #ifdef HAVE_EDCA
2357 ic = &sc->sc_ic;
2358 edca = (ic->ic_flags & IEEE80211_F_QOS) ?
2359 ic->ic_edca_ac : otus_edca_def;
2360 #else
2361 edca = otus_edca_def;
2362 #endif /* HAVE_EDCA */
2363
2364 #define EXP2(val) ((1 << (val)) - 1)
2365 #define AIFS(val) ((val) * 9 + 10)
2366
2367 /* Set CWmin/CWmax values. */
2368 otus_write(sc, AR_MAC_REG_AC0_CW,
2369 EXP2(edca[WME_AC_BE].ac_ecwmax) << 16 |
2370 EXP2(edca[WME_AC_BE].ac_ecwmin));
2371 otus_write(sc, AR_MAC_REG_AC1_CW,
2372 EXP2(edca[WME_AC_BK].ac_ecwmax) << 16 |
2373 EXP2(edca[WME_AC_BK].ac_ecwmin));
2374 otus_write(sc, AR_MAC_REG_AC2_CW,
2375 EXP2(edca[WME_AC_VI].ac_ecwmax) << 16 |
2376 EXP2(edca[WME_AC_VI].ac_ecwmin));
2377 otus_write(sc, AR_MAC_REG_AC3_CW,
2378 EXP2(edca[WME_AC_VO].ac_ecwmax) << 16 |
2379 EXP2(edca[WME_AC_VO].ac_ecwmin));
2380 otus_write(sc, AR_MAC_REG_AC4_CW, /* Special TXQ. */
2381 EXP2(edca[WME_AC_VO].ac_ecwmax) << 16 |
2382 EXP2(edca[WME_AC_VO].ac_ecwmin));
2383
2384 /* Set AIFSN values. */
2385 otus_write(sc, AR_MAC_REG_AC1_AC0_AIFS,
2386 AIFS(edca[WME_AC_VI].ac_aifsn) << 24 |
2387 AIFS(edca[WME_AC_BK].ac_aifsn) << 12 |
2388 AIFS(edca[WME_AC_BE].ac_aifsn));
2389 otus_write(sc, AR_MAC_REG_AC3_AC2_AIFS,
2390 AIFS(edca[WME_AC_VO].ac_aifsn) << 16 | /* Special TXQ. */
2391 AIFS(edca[WME_AC_VO].ac_aifsn) << 4 |
2392 AIFS(edca[WME_AC_VI].ac_aifsn) >> 8);
2393
2394 /* Set TXOP limit. */
2395 otus_write(sc, AR_MAC_REG_AC1_AC0_TXOP,
2396 edca[WME_AC_BK].ac_txoplimit << 16 |
2397 edca[WME_AC_BE].ac_txoplimit);
2398 otus_write(sc, AR_MAC_REG_AC3_AC2_TXOP,
2399 edca[WME_AC_VO].ac_txoplimit << 16 |
2400 edca[WME_AC_VI].ac_txoplimit);
2401 #undef AIFS
2402 #undef EXP2
2403
2404 splx(s);
2405
2406 (void)otus_write_barrier(sc);
2407 }
2408
2409 Static void
2410 otus_updateslot(struct ifnet *ifp)
2411 {
2412 struct otus_softc *sc;
2413
2414 sc = ifp->if_softc;
2415
2416 DPRINTFN(DBG_FN, sc, "\n");
2417
2418 /* Do it in a process context. */
2419 otus_do_async(sc, otus_updateslot_cb, NULL, 0);
2420 }
2421
2422 /* ARGSUSED */
2423 Static void
2424 otus_updateslot_cb(struct otus_softc *sc, void *arg)
2425 {
2426
2427 DPRINTFN(DBG_FN, sc, "\n");
2428
2429 mutex_enter(&sc->sc_write_mtx);
2430 otus_updateslot_cb_locked(sc);
2431 mutex_exit(&sc->sc_write_mtx);
2432 }
2433
2434 Static void
2435 otus_updateslot_cb_locked(struct otus_softc *sc)
2436 {
2437 uint32_t slottime;
2438
2439 DPRINTFN(DBG_FN, sc, "\n");
2440
2441 KASSERT(mutex_owned(&sc->sc_write_mtx));
2442
2443 slottime = (sc->sc_ic.ic_flags & IEEE80211_F_SHSLOT) ? 9 : 20;
2444 otus_write(sc, AR_MAC_REG_SLOT_TIME, slottime << 10);
2445 (void)otus_write_barrier(sc);
2446 }
2447
2448 Static int
2449 otus_init_mac(struct otus_softc *sc)
2450 {
2451 int error;
2452
2453 DPRINTFN(DBG_FN|DBG_INIT, sc, "\n");
2454
2455 KASSERT(mutex_owned(&sc->sc_write_mtx));
2456
2457 otus_write(sc, AR_MAC_REG_ACK_EXTENSION, 0x40);
2458 otus_write(sc, AR_MAC_REG_RETRY_MAX, 0);
2459 otus_write(sc, AR_MAC_REG_SNIFFER, AR_MAC_REG_SNIFFER_DEFAULTS);
2460 otus_write(sc, AR_MAC_REG_RX_THRESHOLD, 0xc1f80);
2461 otus_write(sc, AR_MAC_REG_RX_PE_DELAY, 0x70);
2462 otus_write(sc, AR_MAC_REG_EIFS_AND_SIFS, 0xa144000);
2463 otus_write(sc, AR_MAC_REG_SLOT_TIME, 9 << 10);
2464
2465 /* CF-END mode */
2466 otus_write(sc, 0x1c3b2c, 0x19000000);
2467
2468 /* NAV protects ACK only (in TXOP). */
2469 otus_write(sc, 0x1c3b38, 0x201);
2470
2471 /* Set beacon PHY CTRL's TPC to 0x7, TA1=1 */
2472 /* OTUS set AM to 0x1 */
2473 otus_write(sc, AR_MAC_REG_BCN_HT1, 0x8000170);
2474
2475 otus_write(sc, AR_MAC_REG_BACKOFF_PROTECT, 0x105);
2476
2477 /* AGG test code*/
2478 /* Aggregation MAX number and timeout */
2479 otus_write(sc, AR_MAC_REG_AMPDU_FACTOR, 0x10000a);
2480
2481 /* Filter any control frames, BAR is bit 24. */
2482 otus_write(sc, AR_MAC_REG_FRAMETYPE_FILTER, AR_MAC_REG_FTF_DEFAULTS);
2483
2484 /* Enable deaggregator, response in sniffer mode */
2485 otus_write(sc, 0x1c3c40, 0x1 | 1 << 30); /* XXX: was 0x1 */
2486
2487 /* rate sets */
2488 otus_write(sc, AR_MAC_REG_BASIC_RATE, 0x150f);
2489 otus_write(sc, AR_MAC_REG_MANDATORY_RATE, 0x150f);
2490 otus_write(sc, AR_MAC_REG_RTS_CTS_RATE, 0x10b01bb);
2491
2492 /* MIMO response control */
2493 otus_write(sc, 0x1c3694, 0x4003c1e); /* bit 26~28 otus-AM */
2494
2495 /* Switch MAC to OTUS interface. */
2496 otus_write(sc, 0x1c3600, 0x3);
2497
2498 otus_write(sc, AR_MAC_REG_AMPDU_RX_THRESH, 0xffff);
2499
2500 /* set PHY register read timeout (??) */
2501 otus_write(sc, AR_MAC_REG_MISC_680, 0xf00008);
2502
2503 /* Disable Rx TimeOut, workaround for BB. */
2504 otus_write(sc, AR_MAC_REG_RX_TIMEOUT, 0x0);
2505
2506 /* Set clock frequency to 88/80MHz. */
2507 otus_write(sc, AR_PWR_REG_CLOCK_SEL,
2508 AR_PWR_CLK_AHB_80_88MHZ | AR_PWR_CLK_DAC_160_INV_DLY);
2509
2510 /* Set WLAN DMA interrupt mode: generate intr per packet. */
2511 otus_write(sc, AR_MAC_REG_TXRX_MPI, 0x110011);
2512
2513 otus_write(sc, AR_MAC_REG_FCS_SELECT, AR_MAC_FCS_FIFO_PROT);
2514
2515 /* Disables the CF_END frame, undocumented register */
2516 otus_write(sc, AR_MAC_REG_TXOP_NOT_ENOUGH_INDICATION, 0x141e0f48);
2517
2518 /* Disable HW decryption for now. */
2519 otus_write(sc, AR_MAC_REG_ENCRYPTION,
2520 AR_MAC_REG_ENCRYPTION_DEFAULTS | AR_MAC_REG_ENCRYPTION_RX_SOFTWARE);
2521
2522 /*
2523 * XXX: should these be elsewhere?
2524 */
2525 /* Enable LED0 and LED1. */
2526 otus_write(sc, AR_GPIO_REG_PORT_TYPE, 3);
2527 otus_write(sc, AR_GPIO_REG_DATA,
2528 AR_GPIO_REG_DATA_LED0_ON | AR_GPIO_REG_DATA_LED1_ON);
2529
2530 /* Set USB Rx stream mode maximum frame number to 2. */
2531 otus_write(sc, AR_USB_REG_MAX_AGG_UPLOAD, (1 << 2));
2532
2533 /* Set USB Rx stream mode timeout to 10us. */
2534 otus_write(sc, AR_USB_REG_UPLOAD_TIME_CTL, 0x80);
2535
2536 if ((error = otus_write_barrier(sc)) != 0)
2537 return error;
2538
2539 /* Set default EDCA parameters. */
2540 otus_updateedca_cb_locked(sc);
2541 return 0;
2542 }
2543
2544 /*
2545 * Return default value for PHY register based on current operating mode.
2546 */
2547 Static uint32_t
2548 otus_phy_get_def(struct otus_softc *sc, uint32_t reg)
2549 {
2550 int i;
2551
2552 DPRINTFN(DBG_FN, sc, "\n");
2553
2554 for (i = 0; i < __arraycount(ar5416_phy_regs); i++)
2555 if (AR_PHY(ar5416_phy_regs[i]) == reg)
2556 return sc->sc_phy_vals[i];
2557 return 0; /* Register not found. */
2558 }
2559
2560 /*
2561 * Update PHY's programming based on vendor-specific data stored in EEPROM.
2562 * This is for FEM-type devices only.
2563 */
2564 Static int
2565 otus_set_board_values(struct otus_softc *sc, struct ieee80211_channel *c)
2566 {
2567 const struct ModalEepHeader *eep;
2568 uint32_t tmp, offset;
2569
2570 DPRINTFN(DBG_FN, sc, "\n");
2571
2572 if (IEEE80211_IS_CHAN_5GHZ(c))
2573 eep = &sc->sc_eeprom.modalHeader[0];
2574 else
2575 eep = &sc->sc_eeprom.modalHeader[1];
2576
2577 /* Offset of chain 2. */
2578 offset = 2 * 0x1000;
2579
2580 tmp = le32toh(eep->antCtrlCommon);
2581 otus_write(sc, AR_PHY_SWITCH_COM, tmp);
2582
2583 tmp = le32toh(eep->antCtrlChain[0]);
2584 otus_write(sc, AR_PHY_SWITCH_CHAIN_0, tmp);
2585
2586 tmp = le32toh(eep->antCtrlChain[1]);
2587 otus_write(sc, AR_PHY_SWITCH_CHAIN_0 + offset, tmp);
2588
2589 if (1 /* sc->sc_sco == AR_SCO_SCN */) {
2590 tmp = otus_phy_get_def(sc, AR_PHY_SETTLING);
2591 tmp &= ~(0x7f << 7);
2592 tmp |= (eep->switchSettling & 0x7f) << 7;
2593 otus_write(sc, AR_PHY_SETTLING, tmp);
2594 }
2595
2596 tmp = otus_phy_get_def(sc, AR_PHY_DESIRED_SZ);
2597 tmp &= ~0xffff;
2598 tmp |= eep->pgaDesiredSize << 8 | eep->adcDesiredSize;
2599 otus_write(sc, AR_PHY_DESIRED_SZ, tmp);
2600
2601 tmp = eep->txEndToXpaOff << 24 | eep->txEndToXpaOff << 16 |
2602 eep->txFrameToXpaOn << 8 | eep->txFrameToXpaOn;
2603 otus_write(sc, AR_PHY_RF_CTL4, tmp);
2604
2605 tmp = otus_phy_get_def(sc, AR_PHY_RF_CTL3);
2606 tmp &= ~(0xff << 16);
2607 tmp |= eep->txEndToRxOn << 16;
2608 otus_write(sc, AR_PHY_RF_CTL3, tmp);
2609
2610 tmp = otus_phy_get_def(sc, AR_PHY_CCA);
2611 tmp &= ~(0x7f << 12);
2612 tmp |= (eep->thresh62 & 0x7f) << 12;
2613 otus_write(sc, AR_PHY_CCA, tmp);
2614
2615 tmp = otus_phy_get_def(sc, AR_PHY_RXGAIN);
2616 tmp &= ~(0x3f << 12);
2617 tmp |= (eep->txRxAttenCh[0] & 0x3f) << 12;
2618 otus_write(sc, AR_PHY_RXGAIN, tmp);
2619
2620 tmp = otus_phy_get_def(sc, AR_PHY_RXGAIN + offset);
2621 tmp &= ~(0x3f << 12);
2622 tmp |= (eep->txRxAttenCh[1] & 0x3f) << 12;
2623 otus_write(sc, AR_PHY_RXGAIN + offset, tmp);
2624
2625 tmp = otus_phy_get_def(sc, AR_PHY_GAIN_2GHZ);
2626 tmp &= ~(0x3f << 18);
2627 tmp |= (eep->rxTxMarginCh[0] & 0x3f) << 18;
2628 if (IEEE80211_IS_CHAN_5GHZ(c)) {
2629 tmp &= ~(0xf << 10);
2630 tmp |= (eep->bswMargin[0] & 0xf) << 10;
2631 }
2632 otus_write(sc, AR_PHY_GAIN_2GHZ, tmp);
2633
2634 tmp = otus_phy_get_def(sc, AR_PHY_GAIN_2GHZ + offset);
2635 tmp &= ~(0x3f << 18);
2636 tmp |= (eep->rxTxMarginCh[1] & 0x3f) << 18;
2637 otus_write(sc, AR_PHY_GAIN_2GHZ + offset, tmp);
2638
2639 tmp = otus_phy_get_def(sc, AR_PHY_TIMING_CTRL4);
2640 tmp &= ~(0x3f << 5 | 0x1f);
2641 tmp |= (eep->iqCalICh[0] & 0x3f) << 5 | (eep->iqCalQCh[0] & 0x1f);
2642 otus_write(sc, AR_PHY_TIMING_CTRL4, tmp);
2643
2644 tmp = otus_phy_get_def(sc, AR_PHY_TIMING_CTRL4 + offset);
2645 tmp &= ~(0x3f << 5 | 0x1f);
2646 tmp |= (eep->iqCalICh[1] & 0x3f) << 5 | (eep->iqCalQCh[1] & 0x1f);
2647 otus_write(sc, AR_PHY_TIMING_CTRL4 + offset, tmp);
2648
2649 tmp = otus_phy_get_def(sc, AR_PHY_TPCRG1);
2650 tmp &= ~(0xf << 16);
2651 tmp |= (eep->xpd & 0xf) << 16;
2652 otus_write(sc, AR_PHY_TPCRG1, tmp);
2653
2654 return otus_write_barrier(sc);
2655 }
2656
2657 Static int
2658 otus_program_phy(struct otus_softc *sc, struct ieee80211_channel *c)
2659 {
2660 const uint32_t *vals;
2661 int error, i;
2662
2663 DPRINTFN(DBG_FN, sc, "\n");
2664
2665 /* Select PHY programming based on band and bandwidth. */
2666 if (IEEE80211_IS_CHAN_2GHZ(c))
2667 vals = ar5416_phy_vals_2ghz_20mhz;
2668 else
2669 vals = ar5416_phy_vals_5ghz_20mhz;
2670 for (i = 0; i < __arraycount(ar5416_phy_regs); i++)
2671 otus_write(sc, AR_PHY(ar5416_phy_regs[i]), vals[i]);
2672 sc->sc_phy_vals = vals;
2673
2674 if (sc->sc_eeprom.baseEepHeader.deviceType == 0x80) /* FEM */
2675 if ((error = otus_set_board_values(sc, c)) != 0)
2676 return error;
2677
2678 /* Initial Tx power settings. */
2679 otus_write(sc, AR_PHY_POWER_TX_RATE_MAX, 0x7f);
2680 otus_write(sc, AR_PHY_POWER_TX_RATE1, 0x3f3f3f3f);
2681 otus_write(sc, AR_PHY_POWER_TX_RATE2, 0x3f3f3f3f);
2682 otus_write(sc, AR_PHY_POWER_TX_RATE3, 0x3f3f3f3f);
2683 otus_write(sc, AR_PHY_POWER_TX_RATE4, 0x3f3f3f3f);
2684 otus_write(sc, AR_PHY_POWER_TX_RATE5, 0x3f3f3f3f);
2685 otus_write(sc, AR_PHY_POWER_TX_RATE6, 0x3f3f3f3f);
2686 otus_write(sc, AR_PHY_POWER_TX_RATE7, 0x3f3f3f3f);
2687 otus_write(sc, AR_PHY_POWER_TX_RATE8, 0x3f3f3f3f);
2688 otus_write(sc, AR_PHY_POWER_TX_RATE9, 0x3f3f3f3f);
2689
2690 if (IEEE80211_IS_CHAN_2GHZ(c))
2691 otus_write(sc, 0x1d4014, 0x5163);
2692 else
2693 otus_write(sc, 0x1d4014, 0x5143);
2694
2695 return otus_write_barrier(sc);
2696 }
2697
2698 static __inline uint8_t
2699 otus_reverse_bits(uint8_t v)
2700 {
2701
2702 v = ((v >> 1) & 0x55) | ((v & 0x55) << 1);
2703 v = ((v >> 2) & 0x33) | ((v & 0x33) << 2);
2704 v = ((v >> 4) & 0x0f) | ((v & 0x0f) << 4);
2705 return v;
2706 }
2707
2708 Static int
2709 otus_set_rf_bank4(struct otus_softc *sc, struct ieee80211_channel *c)
2710 {
2711 uint8_t chansel, d0, d1;
2712 uint16_t data;
2713 int error;
2714
2715 DPRINTFN(DBG_FN, sc, "\n");
2716
2717 d0 = 0;
2718 if (IEEE80211_IS_CHAN_5GHZ(c)) {
2719 chansel = (c->ic_freq - 4800) / 5;
2720 if (chansel & 1)
2721 d0 |= AR_BANK4_AMODE_REFSEL(2);
2722 else
2723 d0 |= AR_BANK4_AMODE_REFSEL(1);
2724 } else {
2725 d0 |= AR_BANK4_AMODE_REFSEL(2);
2726 if (c->ic_freq == 2484) { /* CH 14 */
2727 d0 |= AR_BANK4_BMODE_LF_SYNTH_FREQ;
2728 chansel = 10 + (c->ic_freq - 2274) / 5;
2729 } else
2730 chansel = 16 + (c->ic_freq - 2272) / 5;
2731 chansel <<= 2;
2732 }
2733 d0 |= AR_BANK4_ADDR(1) | AR_BANK4_CHUP;
2734 d1 = otus_reverse_bits(chansel);
2735
2736 /* Write bits 0-4 of d0 and d1. */
2737 data = (d1 & 0x1f) << 5 | (d0 & 0x1f);
2738 otus_write(sc, AR_PHY(44), data);
2739 /* Write bits 5-7 of d0 and d1. */
2740 data = (d1 >> 5) << 5 | (d0 >> 5);
2741 otus_write(sc, AR_PHY(58), data);
2742
2743 if ((error = otus_write_barrier(sc)) == 0)
2744 usbd_delay_ms(sc->sc_udev, 10);
2745
2746 return error;
2747 }
2748
2749 Static void
2750 otus_get_delta_slope(uint32_t coeff, uint32_t *exponent, uint32_t *mantissa)
2751 {
2752 #define COEFF_SCALE_SHIFT 24
2753 uint32_t exp, man;
2754
2755 DPRINTFN(DBG_FN, DBG_NO_SC, "\n");
2756
2757 /* exponent = 14 - floor(log2(coeff)) */
2758 for (exp = 31; exp > 0; exp--)
2759 if (coeff & (1 << exp))
2760 break;
2761 KASSERT(exp != 0);
2762 exp = 14 - (exp - COEFF_SCALE_SHIFT);
2763
2764 /* mantissa = floor(coeff * 2^exponent + 0.5) */
2765 man = coeff + (1 << (COEFF_SCALE_SHIFT - exp - 1));
2766
2767 *mantissa = man >> (COEFF_SCALE_SHIFT - exp);
2768 *exponent = exp - 16;
2769 #undef COEFF_SCALE_SHIFT
2770 }
2771
2772 Static int
2773 otus_set_chan(struct otus_softc *sc, struct ieee80211_channel *c, int assoc)
2774 {
2775 struct ar_cmd_frequency cmd;
2776 struct ar_rsp_frequency rsp;
2777 const uint32_t *vals;
2778 uint32_t coeff, exp, man, tmp;
2779 uint8_t code;
2780 int error, i;
2781
2782 DPRINTFN(DBG_FN, sc, "\n");
2783
2784
2785 #ifdef OTUS_DEBUG
2786 struct ieee80211com *ic = &sc->sc_ic;
2787 int chan = ieee80211_chan2ieee(ic, c);
2788
2789 DPRINTFN(DBG_CHAN, sc, "setting channel %d (%dMHz)\n",
2790 chan, c->ic_freq);
2791 #endif
2792
2793 tmp = IEEE80211_IS_CHAN_2GHZ(c) ? 0x105 : 0x104;
2794 otus_write(sc, AR_MAC_REG_DYNAMIC_SIFS_ACK, tmp);
2795 if ((error = otus_write_barrier(sc)) != 0)
2796 return error;
2797
2798 /* Disable BB Heavy Clip. */
2799 otus_write(sc, AR_PHY_HEAVY_CLIP_ENABLE, 0x200);
2800 if ((error = otus_write_barrier(sc)) != 0)
2801 return error;
2802
2803 /* XXX Is that FREQ_START ? */
2804 error = otus_cmd(sc, AR_CMD_FREQ_STRAT, NULL, 0, NULL);
2805 if (error != 0)
2806 return error;
2807
2808 /* Reprogram PHY and RF on channel band or bandwidth changes. */
2809 if (sc->sc_bb_reset || c->ic_flags != sc->sc_curchan->ic_flags) {
2810 DPRINTFN(DBG_CHAN, sc, "band switch\n");
2811
2812 /* Cold/Warm reset BB/ADDA. */
2813 otus_write(sc, 0x1d4004, sc->sc_bb_reset ? 0x800 : 0x400);
2814 if ((error = otus_write_barrier(sc)) != 0)
2815 return error;
2816
2817 otus_write(sc, 0x1d4004, 0);
2818 if ((error = otus_write_barrier(sc)) != 0)
2819 return error;
2820 sc->sc_bb_reset = 0;
2821
2822 if ((error = otus_program_phy(sc, c)) != 0) {
2823 aprint_error_dev(sc->sc_dev,
2824 "could not program PHY\n");
2825 return error;
2826 }
2827
2828 /* Select RF programming based on band. */
2829 if (IEEE80211_IS_CHAN_5GHZ(c))
2830 vals = ar5416_banks_vals_5ghz;
2831 else
2832 vals = ar5416_banks_vals_2ghz;
2833 for (i = 0; i < __arraycount(ar5416_banks_regs); i++)
2834 otus_write(sc, AR_PHY(ar5416_banks_regs[i]), vals[i]);
2835 if ((error = otus_write_barrier(sc)) != 0) {
2836 aprint_error_dev(sc->sc_dev, "could not program RF\n");
2837 return error;
2838 }
2839 code = AR_CMD_RF_INIT;
2840 } else {
2841 code = AR_CMD_FREQUENCY;
2842 }
2843
2844 if ((error = otus_set_rf_bank4(sc, c)) != 0)
2845 return error;
2846
2847 tmp = (sc->sc_txmask == 0x5) ? 0x340 : 0x240;
2848 otus_write(sc, AR_PHY_TURBO, tmp);
2849 if ((error = otus_write_barrier(sc)) != 0)
2850 return error;
2851
2852 /* Send firmware command to set channel. */
2853 cmd.freq = htole32((uint32_t)c->ic_freq * 1000);
2854 cmd.dynht2040 = htole32(0);
2855 cmd.htena = htole32(1);
2856
2857 /* Set Delta Slope (exponent and mantissa). */
2858 coeff = (100 << 24) / c->ic_freq;
2859 otus_get_delta_slope(coeff, &exp, &man);
2860 cmd.dsc_exp = htole32(exp);
2861 cmd.dsc_man = htole32(man);
2862 DPRINTFN(DBG_CHAN, sc, "ds coeff=%u exp=%u man=%u\n",
2863 coeff, exp, man);
2864
2865 /* For Short GI, coeff is 9/10 that of normal coeff. */
2866 coeff = (9 * coeff) / 10;
2867 otus_get_delta_slope(coeff, &exp, &man);
2868 cmd.dsc_shgi_exp = htole32(exp);
2869 cmd.dsc_shgi_man = htole32(man);
2870 DPRINTFN(DBG_CHAN, sc, "ds shgi coeff=%u exp=%u man=%u\n",
2871 coeff, exp, man);
2872
2873 /* Set wait time for AGC and noise calibration (100 or 200ms). */
2874 cmd.check_loop_count = assoc ? htole32(2000) : htole32(1000);
2875 DPRINTFN(DBG_CHAN, sc, "%s\n",
2876 code == AR_CMD_RF_INIT ? "RF_INIT" : "FREQUENCY");
2877 error = otus_cmd(sc, code, &cmd, sizeof(cmd), &rsp);
2878 if (error != 0)
2879 return error;
2880
2881 if ((rsp.status & htole32(AR_CAL_ERR_AGC | AR_CAL_ERR_NF_VAL)) != 0) {
2882 DPRINTFN(DBG_CHAN, sc, "status=0x%x\n", le32toh(rsp.status));
2883 /* Force cold reset on next channel. */
2884 sc->sc_bb_reset = 1;
2885 }
2886
2887 #ifdef OTUS_DEBUG
2888 if (otus_debug & DBG_CHAN) {
2889 DPRINTFN(DBG_CHAN, sc, "calibration status=0x%x\n",
2890 le32toh(rsp.status));
2891 for (i = 0; i < 2; i++) { /* 2 Rx chains */
2892 /* Sign-extend 9-bit NF values. */
2893 DPRINTFN(DBG_CHAN, sc, "noisefloor chain %d=%d\n",
2894 i, (((int32_t)le32toh(rsp.nf[i])) << 4) >> 23);
2895 DPRINTFN(DBG_CHAN, sc, "noisefloor ext chain %d=%d\n",
2896 i, ((int32_t)le32toh(rsp.nf_ext[i])) >> 23);
2897 }
2898 }
2899 #endif
2900 sc->sc_curchan = c;
2901 return 0;
2902 }
2903
2904 #ifdef notyet
2905 Static int
2906 otus_set_key(struct ieee80211com *ic, struct ieee80211_node *ni,
2907 struct ieee80211_key *k)
2908 {
2909 struct otus_softc *sc;
2910 struct otus_cmd_key cmd;
2911
2912 sc = ic->ic_ifp->if_softc;
2913
2914 DPRINTFN(DBG_FN, sc, "\n");
2915
2916 /* Defer setting of WEP keys until interface is brought up. */
2917 if ((ic->ic_ifp->if_flags & (IFF_UP | IFF_RUNNING)) !=
2918 (IFF_UP | IFF_RUNNING))
2919 return 0;
2920
2921 /* Do it in a process context. */
2922 cmd.key = *k;
2923 cmd.associd = (ni != NULL) ? ni->ni_associd : 0;
2924 otus_do_async(sc, otus_set_key_cb, &cmd, sizeof(cmd));
2925 return 0;
2926 }
2927
2928 Static void
2929 otus_set_key_cb(struct otus_softc *sc, void *arg)
2930 {
2931 struct otus_cmd_key *cmd;
2932 struct ieee80211_key *k;
2933 struct ar_cmd_ekey key;
2934 uint16_t cipher;
2935 int error;
2936
2937 DPRINTFN(DBG_FN, sc, "\n");
2938
2939 cmd = arg;
2940 k = &cmd->key;
2941
2942 memset(&key, 0, sizeof(key));
2943 if (k->k_flags & IEEE80211_KEY_GROUP) {
2944 key.uid = htole16(k->k_id);
2945 IEEE80211_ADDR_COPY(key.macaddr, sc->sc_ic.ic_myaddr);
2946 key.macaddr[0] |= 0x80;
2947 } else {
2948 key.uid = htole16(OTUS_UID(cmd->associd));
2949 IEEE80211_ADDR_COPY(key.macaddr, ni->ni_macaddr);
2950 }
2951 key.kix = htole16(0);
2952 /* Map net80211 cipher to hardware. */
2953 switch (k->k_cipher) {
2954 case IEEE80211_CIPHER_WEP40:
2955 cipher = AR_CIPHER_WEP64;
2956 break;
2957 case IEEE80211_CIPHER_WEP104:
2958 cipher = AR_CIPHER_WEP128;
2959 break;
2960 case IEEE80211_CIPHER_TKIP:
2961 cipher = AR_CIPHER_TKIP;
2962 break;
2963 case IEEE80211_CIPHER_CCMP:
2964 cipher = AR_CIPHER_AES;
2965 break;
2966 default:
2967 return;
2968 }
2969 key.cipher = htole16(cipher);
2970 memcpy(key.key, k->k_key, MIN(k->k_len, 16));
2971 error = otus_cmd(sc, AR_CMD_EKEY, &key, sizeof(key), NULL);
2972 if (error != 0 || k->k_cipher != IEEE80211_CIPHER_TKIP)
2973 return;
2974
2975 /* TKIP: set Tx/Rx MIC Key. */
2976 key.kix = htole16(1);
2977 memcpy(key.key, k->k_key + 16, 16);
2978 (void)otus_cmd(sc, AR_CMD_EKEY, &key, sizeof(key), NULL);
2979 }
2980
2981 Static void
2982 otus_delete_key(struct ieee80211com *ic, struct ieee80211_node *ni,
2983 struct ieee80211_key *k)
2984 {
2985 struct otus_softc *sc;
2986 struct otus_cmd_key cmd;
2987
2988 sc = ic->ic_ifp->if_softc;
2989
2990 DPRINTFN(DBG_FN, sc, "\n");
2991
2992 if (!(ic->ic_ifp->if_flags & IFF_RUNNING) ||
2993 ic->ic_state != IEEE80211_S_RUN)
2994 return; /* Nothing to do. */
2995
2996 /* Do it in a process context. */
2997 cmd.key = *k;
2998 cmd.associd = (ni != NULL) ? ni->ni_associd : 0;
2999 otus_do_async(sc, otus_delete_key_cb, &cmd, sizeof(cmd));
3000 }
3001
3002 Static void
3003 otus_delete_key_cb(struct otus_softc *sc, void *arg)
3004 {
3005 struct otus_cmd_key *cmd;
3006 struct ieee80211_key *k;
3007 uint32_t uid;
3008
3009 DPRINTFN(DBG_FN, sc, "\n");
3010
3011 cmd = arg;
3012 k = &cmd->key;
3013 if (k->k_flags & IEEE80211_KEY_GROUP)
3014 uid = htole32(k->k_id);
3015 else
3016 uid = htole32(OTUS_UID(cmd->associd));
3017 (void)otus_cmd(sc, AR_CMD_DKEY, &uid, sizeof(uid), NULL);
3018 }
3019 #endif /* notyet */
3020
3021 Static void
3022 otus_calib_to(void *arg)
3023 {
3024 struct otus_softc *sc;
3025 struct ieee80211com *ic;
3026 struct ieee80211_node *ni;
3027 struct otus_node *on;
3028 int s;
3029
3030 sc = arg;
3031
3032 DPRINTFN(DBG_FN, sc, "\n");
3033
3034 if (sc->sc_dying)
3035 return;
3036
3037 s = splnet();
3038 ic = &sc->sc_ic;
3039 ni = ic->ic_bss;
3040 on = (void *)ni;
3041 ieee80211_amrr_choose(&sc->sc_amrr, ni, &on->amn);
3042 splx(s);
3043
3044 if (!sc->sc_dying)
3045 callout_schedule(&sc->sc_calib_to, hz);
3046 }
3047
3048 Static int
3049 otus_set_bssid(struct otus_softc *sc, const uint8_t *bssid)
3050 {
3051
3052 DPRINTFN(DBG_FN, sc, "\n");
3053
3054 KASSERT(mutex_owned(&sc->sc_write_mtx));
3055
3056 otus_write(sc, AR_MAC_REG_BSSID_L,
3057 bssid[0] | bssid[1] << 8 | bssid[2] << 16 | bssid[3] << 24);
3058 otus_write(sc, AR_MAC_REG_BSSID_H,
3059 bssid[4] | bssid[5] << 8);
3060 return otus_write_barrier(sc);
3061 }
3062
3063 Static int
3064 otus_set_macaddr(struct otus_softc *sc, const uint8_t *addr)
3065 {
3066
3067 DPRINTFN(DBG_FN, sc, "\n");
3068
3069 KASSERT(mutex_owned(&sc->sc_write_mtx));
3070
3071 otus_write(sc, AR_MAC_REG_MAC_ADDR_L,
3072 addr[0] | addr[1] << 8 | addr[2] << 16 | addr[3] << 24);
3073 otus_write(sc, AR_MAC_REG_MAC_ADDR_H,
3074 addr[4] | addr[5] << 8);
3075 return otus_write_barrier(sc);
3076 }
3077
3078 #ifdef notyet
3079 /* Default single-LED. */
3080 Static void
3081 otus_led_newstate_type1(struct otus_softc *sc)
3082 {
3083
3084 DPRINTFN(DBG_FN, sc, "\n");
3085
3086 /* TBD */
3087 }
3088
3089 /* NETGEAR, dual-LED. */
3090 Static void
3091 otus_led_newstate_type2(struct otus_softc *sc)
3092 {
3093
3094 DPRINTFN(DBG_FN, sc, "\n");
3095
3096 /* TBD */
3097 }
3098 #endif /* notyet */
3099
3100 /*
3101 * NETGEAR, single-LED/3 colors (blue, red, purple.)
3102 */
3103 Static void
3104 otus_led_newstate_type3(struct otus_softc *sc)
3105 {
3106 struct ieee80211com *ic;
3107 uint32_t led_state;
3108
3109 DPRINTFN(DBG_FN, sc, "\n");
3110
3111 ic = &sc->sc_ic;
3112 led_state = sc->sc_led_state;
3113 switch(ic->ic_state) {
3114 case IEEE80211_S_INIT:
3115 led_state = 0;
3116 break;
3117 case IEEE80211_S_SCAN:
3118 led_state ^= AR_GPIO_REG_DATA_LED0_ON | AR_GPIO_REG_DATA_LED1_ON;
3119 led_state &= ~(IEEE80211_IS_CHAN_2GHZ(sc->sc_curchan) ?
3120 AR_GPIO_REG_DATA_LED1_ON : AR_GPIO_REG_DATA_LED0_ON);
3121 break;
3122 case IEEE80211_S_AUTH:
3123 case IEEE80211_S_ASSOC:
3124 /* XXX: Turn both LEDs on for AUTH and ASSOC? */
3125 led_state = AR_GPIO_REG_DATA_LED0_ON | AR_GPIO_REG_DATA_LED1_ON;
3126 break;
3127 case IEEE80211_S_RUN:
3128 led_state = IEEE80211_IS_CHAN_2GHZ(sc->sc_curchan) ?
3129 AR_GPIO_REG_DATA_LED0_ON : AR_GPIO_REG_DATA_LED1_ON;
3130 break;
3131 }
3132 if (led_state != sc->sc_led_state) {
3133 otus_write(sc, AR_GPIO_REG_DATA, led_state);
3134 if (otus_write_barrier(sc) == 0)
3135 sc->sc_led_state = led_state;
3136 }
3137 }
3138
3139 Static int
3140 otus_init(struct ifnet *ifp)
3141 {
3142 struct otus_softc *sc;
3143 struct ieee80211com *ic;
3144 uint32_t filter, pm_mode, sniffer;
3145 int error;
3146
3147 sc = ifp->if_softc;
3148
3149 DPRINTFN(DBG_FN|DBG_INIT, sc, "\n");
3150
3151 ic = &sc->sc_ic;
3152
3153 mutex_enter(&sc->sc_write_mtx);
3154
3155 /* Init host command ring. */
3156 mutex_spin_enter(&sc->sc_task_mtx);
3157 sc->sc_cmdq.cur = sc->sc_cmdq.next = sc->sc_cmdq.queued = 0;
3158 mutex_spin_exit(&sc->sc_task_mtx);
3159
3160 if ((error = otus_init_mac(sc)) != 0) {
3161 mutex_exit(&sc->sc_write_mtx);
3162 aprint_error_dev(sc->sc_dev, "could not initialize MAC\n");
3163 return error;
3164 }
3165
3166 IEEE80211_ADDR_COPY(ic->ic_myaddr, CLLADDR(ifp->if_sadl));
3167 (void)otus_set_macaddr(sc, ic->ic_myaddr);
3168
3169 pm_mode = AR_MAC_REG_POWERMGT_DEFAULTS;
3170 sniffer = AR_MAC_REG_SNIFFER_DEFAULTS;
3171 filter = AR_MAC_REG_FTF_DEFAULTS;
3172 sc->sc_rx_error_msk = ~0;
3173
3174 switch (ic->ic_opmode) {
3175 #ifdef notyet
3176 #ifndef IEEE80211_STA_ONLY
3177 case IEEE80211_M_HOSTAP:
3178 pm_mode |= AR_MAC_REG_POWERMGT_AP;
3179 break;
3180 case IEEE80211_M_IBSS:
3181 pm_mode |= AR_MAC_REG_POWERMGT_IBSS; /* XXX: was 0x0 */
3182 break;
3183 #endif
3184 #endif
3185 case IEEE80211_M_STA:
3186 pm_mode |= AR_MAC_REG_POWERMGT_STA;
3187 break;
3188 case IEEE80211_M_MONITOR:
3189 sc->sc_rx_error_msk = ~AR_RX_ERROR_BAD_RA;
3190 filter = AR_MAC_REG_FTF_MONITOR;
3191 sniffer |= AR_MAC_REG_SNIFFER_ENABLE_PROMISC;
3192 break;
3193 default:
3194 aprint_error_dev(sc->sc_dev, "bad opmode: %d", ic->ic_opmode);
3195 return EOPNOTSUPP; /* XXX: ??? */
3196 }
3197 otus_write(sc, AR_MAC_REG_POWERMANAGEMENT, pm_mode);
3198 otus_write(sc, AR_MAC_REG_FRAMETYPE_FILTER, filter);
3199 otus_write(sc, AR_MAC_REG_SNIFFER, sniffer);
3200 (void)otus_write_barrier(sc);
3201
3202 sc->sc_bb_reset = 1; /* Force cold reset. */
3203 if ((error = otus_set_chan(sc, ic->ic_curchan, 0)) != 0) {
3204 mutex_exit(&sc->sc_write_mtx);
3205 aprint_error_dev(sc->sc_dev, "could not set channel\n");
3206 return error;
3207 }
3208
3209 /* Start Rx. */
3210 otus_write(sc, AR_MAC_REG_DMA, AR_MAC_REG_DMA_ENABLE);
3211 (void)otus_write_barrier(sc);
3212 mutex_exit(&sc->sc_write_mtx);
3213
3214 ifp->if_flags &= ~IFF_OACTIVE;
3215 ifp->if_flags |= IFF_RUNNING;
3216
3217 if (ic->ic_opmode == IEEE80211_M_MONITOR)
3218 ieee80211_new_state(ic, IEEE80211_S_RUN, -1);
3219 else
3220 ieee80211_new_state(ic, IEEE80211_S_SCAN, -1);
3221
3222 return 0;
3223 }
3224
3225 Static void
3226 otus_stop(struct ifnet *ifp)
3227 {
3228 struct otus_softc *sc;
3229 struct ieee80211com *ic;
3230 int s;
3231
3232 sc = ifp->if_softc;
3233
3234 DPRINTFN(DBG_FN, sc, "\n");
3235
3236 ic = &sc->sc_ic;
3237
3238 sc->sc_tx_timer = 0;
3239 ifp->if_timer = 0;
3240 ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE);
3241
3242 callout_halt(&sc->sc_scan_to, NULL);
3243 callout_halt(&sc->sc_calib_to, NULL);
3244
3245 s = splusb();
3246 ieee80211_new_state(ic, IEEE80211_S_INIT, -1);
3247 otus_wait_async(sc);
3248 splx(s);
3249
3250 /* Stop Rx. */
3251 mutex_enter(&sc->sc_write_mtx);
3252 otus_write(sc, AR_MAC_REG_DMA, AR_MAC_REG_DMA_OFF);
3253 (void)otus_write_barrier(sc);
3254 mutex_exit(&sc->sc_write_mtx);
3255 }
3256