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