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