if_otus.c revision 1.43 1 /* $NetBSD: if_otus.c,v 1.43 2020/03/14 02:35:33 christos Exp $ */
2 /* $OpenBSD: if_otus.c,v 1.18 2010/08/27 17:08:00 jsg Exp $ */
3
4 /*-
5 * Copyright (c) 2009 Damien Bergamini <damien.bergamini (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.43 2020/03/14 02:35:33 christos 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=%#x product=%#x revision=%#x\n",
604 uaa->uaa_vendor, uaa->uaa_product, uaa->uaa_release);
605
606 return usb_lookup(otus_devs, uaa->uaa_vendor, uaa->uaa_product) != NULL ?
607 UMATCH_VENDOR_PRODUCT : UMATCH_NONE;
608 }
609
610 Static void
611 otus_attach(device_t parent, device_t self, void *aux)
612 {
613 struct otus_softc *sc;
614 struct usb_attach_arg *uaa;
615 char *devinfop;
616 int error;
617
618 sc = device_private(self);
619
620 DPRINTFN(DBG_FN, sc, "\n");
621
622 sc->sc_dev = self;
623 uaa = aux;
624 sc->sc_udev = uaa->uaa_device;
625
626 aprint_naive("\n");
627 aprint_normal("\n");
628
629 devinfop = usbd_devinfo_alloc(sc->sc_udev, 0);
630 aprint_normal_dev(sc->sc_dev, "%s\n", devinfop);
631 usbd_devinfo_free(devinfop);
632
633 cv_init(&sc->sc_task_cv, "otustsk");
634 cv_init(&sc->sc_cmd_cv, "otuscmd");
635 mutex_init(&sc->sc_cmd_mtx, MUTEX_DEFAULT, IPL_NONE);
636 mutex_init(&sc->sc_task_mtx, MUTEX_DEFAULT, IPL_NET);
637 mutex_init(&sc->sc_tx_mtx, MUTEX_DEFAULT, IPL_NONE);
638 mutex_init(&sc->sc_write_mtx, MUTEX_DEFAULT, IPL_NONE);
639
640 usb_init_task(&sc->sc_task, otus_task, sc, 0);
641
642 callout_init(&sc->sc_scan_to, 0);
643 callout_setfunc(&sc->sc_scan_to, otus_next_scan, sc);
644 callout_init(&sc->sc_calib_to, 0);
645 callout_setfunc(&sc->sc_calib_to, otus_calib_to, sc);
646
647 sc->sc_amrr.amrr_min_success_threshold = 1;
648 sc->sc_amrr.amrr_max_success_threshold = 10;
649
650 if (usbd_set_config_no(sc->sc_udev, 1, 0) != 0) {
651 aprint_error_dev(sc->sc_dev,
652 "could not set configuration no\n");
653 return;
654 }
655
656 /* Get the first interface handle. */
657 error = usbd_device2interface_handle(sc->sc_udev, 0, &sc->sc_iface);
658 if (error != 0) {
659 aprint_error_dev(sc->sc_dev,
660 "could not get interface handle\n");
661 return;
662 }
663
664 if ((error = otus_open_pipes(sc)) != 0) {
665 aprint_error_dev(sc->sc_dev, "could not open pipes\n");
666 return;
667 }
668
669 /*
670 * We need the firmware loaded from file system to complete the attach.
671 */
672 config_mountroot(self, otus_attachhook);
673
674 usbd_add_drv_event(USB_EVENT_DRIVER_ATTACH, sc->sc_udev, sc->sc_dev);
675 }
676
677 Static void
678 otus_wait_async(struct otus_softc *sc)
679 {
680
681 DPRINTFN(DBG_FN, sc, "\n");
682
683 mutex_spin_enter(&sc->sc_task_mtx);
684 while (sc->sc_cmdq.queued > 0)
685 cv_wait(&sc->sc_task_cv, &sc->sc_task_mtx);
686 mutex_spin_exit(&sc->sc_task_mtx);
687 }
688
689 Static int
690 otus_detach(device_t self, int flags)
691 {
692 struct otus_softc *sc;
693 struct ifnet *ifp;
694 int s;
695
696 sc = device_private(self);
697
698 DPRINTFN(DBG_FN, sc, "\n");
699
700 s = splusb();
701
702 sc->sc_dying = 1;
703
704 ifp = sc->sc_ic.ic_ifp;
705 if (ifp != NULL) /* Failed to attach properly */
706 otus_stop(ifp);
707
708 usb_rem_task_wait(sc->sc_udev, &sc->sc_task, USB_TASKQ_DRIVER, NULL);
709 callout_destroy(&sc->sc_scan_to);
710 callout_destroy(&sc->sc_calib_to);
711
712 if (ifp && ifp->if_flags != 0) { /* if_attach() has been called. */
713 ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE);
714 bpf_detach(ifp);
715 ieee80211_ifdetach(&sc->sc_ic);
716 if_detach(ifp);
717 }
718 otus_close_pipes(sc);
719 splx(s);
720
721 usbd_add_drv_event(USB_EVENT_DRIVER_DETACH, sc->sc_udev, sc->sc_dev);
722
723 mutex_destroy(&sc->sc_write_mtx);
724 mutex_destroy(&sc->sc_tx_mtx);
725 mutex_destroy(&sc->sc_task_mtx);
726 mutex_destroy(&sc->sc_cmd_mtx);
727 cv_destroy(&sc->sc_task_cv);
728 cv_destroy(&sc->sc_cmd_cv);
729
730 return 0;
731 }
732
733 Static int
734 otus_activate(device_t self, devact_t act)
735 {
736 struct otus_softc *sc;
737
738 sc = device_private(self);
739
740 DPRINTFN(DBG_FN, sc, "%d\n", act);
741
742 switch (act) {
743 case DVACT_DEACTIVATE:
744 sc->sc_dying = 1;
745 if_deactivate(sc->sc_ic.ic_ifp);
746 return 0;
747 default:
748 return EOPNOTSUPP;
749 }
750 }
751
752 Static void
753 otus_attachhook(device_t arg)
754 {
755 struct otus_softc *sc;
756 struct ieee80211com *ic;
757 struct ifnet *ifp;
758 usb_device_request_t req;
759 uint32_t in, out;
760 int error;
761
762 sc = device_private(arg);
763
764 DPRINTFN(DBG_FN, sc, "\n");
765
766 ic = &sc->sc_ic;
767 ifp = &sc->sc_if;
768
769 error = otus_load_firmware(sc, "otus-init", AR_FW_INIT_ADDR);
770 if (error != 0) {
771 aprint_error_dev(sc->sc_dev, "could not load init firmware\n");
772 return;
773 }
774 usbd_delay_ms(sc->sc_udev, 1000);
775
776 error = otus_load_firmware(sc, "otus-main", AR_FW_MAIN_ADDR);
777 if (error != 0) {
778 aprint_error_dev(sc->sc_dev, "could not load main firmware\n");
779 return;
780 }
781
782 /* Tell device that firmware transfer is complete. */
783 req.bmRequestType = UT_WRITE_VENDOR_DEVICE;
784 req.bRequest = AR_FW_DOWNLOAD_COMPLETE;
785 USETW(req.wValue, 0);
786 USETW(req.wIndex, 0);
787 USETW(req.wLength, 0);
788 if (usbd_do_request(sc->sc_udev, &req, NULL) != 0) {
789 aprint_error_dev(sc->sc_dev,
790 "firmware initialization failed\n");
791 return;
792 }
793
794 /* Send an ECHO command to check that everything is settled. */
795 in = 0xbadc0ffe;
796 if (otus_cmd(sc, AR_CMD_ECHO, &in, sizeof(in), &out) != 0) {
797 aprint_error_dev(sc->sc_dev, "echo command failed\n");
798 return;
799 }
800 if (in != out) {
801 aprint_error_dev(sc->sc_dev,
802 "echo reply mismatch: 0x%08x!=0x%08x\n", in, out);
803 return;
804 }
805
806 /* Read entire EEPROM. */
807 if (otus_read_eeprom(sc) != 0) {
808 aprint_error_dev(sc->sc_dev, "could not read EEPROM\n");
809 return;
810 }
811
812 sc->sc_txmask = sc->sc_eeprom.baseEepHeader.txMask;
813 sc->sc_rxmask = sc->sc_eeprom.baseEepHeader.rxMask;
814 sc->sc_capflags = sc->sc_eeprom.baseEepHeader.opCapFlags;
815 IEEE80211_ADDR_COPY(ic->ic_myaddr, sc->sc_eeprom.baseEepHeader.macAddr);
816 sc->sc_led_newstate = otus_led_newstate_type3; /* XXX */
817
818 aprint_normal_dev(sc->sc_dev,
819 "MAC/BBP AR9170, RF AR%X, MIMO %dT%dR, address %s\n",
820 (sc->sc_capflags & AR5416_OPFLAGS_11A) ?
821 0x9104 : ((sc->sc_txmask == 0x5) ? 0x9102 : 0x9101),
822 (sc->sc_txmask == 0x5) ? 2 : 1, (sc->sc_rxmask == 0x5) ? 2 : 1,
823 ether_sprintf(ic->ic_myaddr));
824
825 /*
826 * Setup the 802.11 device.
827 */
828 ic->ic_ifp = ifp;
829 ic->ic_phytype = IEEE80211_T_OFDM; /* not only, but not used */
830 ic->ic_opmode = IEEE80211_M_STA; /* default to BSS mode */
831 ic->ic_state = IEEE80211_S_INIT;
832
833 /* Set device capabilities. */
834 ic->ic_caps =
835 IEEE80211_C_MONITOR | /* monitor mode supported */
836 IEEE80211_C_SHPREAMBLE | /* short preamble supported */
837 IEEE80211_C_SHSLOT | /* short slot time supported */
838 IEEE80211_C_WPA; /* 802.11i */
839
840 if (sc->sc_eeprom.baseEepHeader.opCapFlags & AR5416_OPFLAGS_11G) {
841 /* Set supported .11b and .11g rates. */
842 ic->ic_sup_rates[IEEE80211_MODE_11B] =
843 ieee80211_std_rateset_11b;
844 ic->ic_sup_rates[IEEE80211_MODE_11G] =
845 ieee80211_std_rateset_11g;
846 }
847 if (sc->sc_eeprom.baseEepHeader.opCapFlags & AR5416_OPFLAGS_11A) {
848 /* Set supported .11a rates. */
849 ic->ic_sup_rates[IEEE80211_MODE_11A] =
850 ieee80211_std_rateset_11a;
851 }
852
853 /* Build the list of supported channels. */
854 otus_get_chanlist(sc);
855
856 ifp->if_softc = sc;
857 ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
858 ifp->if_init = otus_init;
859 ifp->if_ioctl = otus_ioctl;
860 ifp->if_start = otus_start;
861 ifp->if_watchdog = otus_watchdog;
862 IFQ_SET_READY(&ifp->if_snd);
863 memcpy(ifp->if_xname, device_xname(sc->sc_dev), IFNAMSIZ);
864
865 if_attach(ifp);
866
867 ieee80211_ifattach(ic);
868
869 ic->ic_node_alloc = otus_node_alloc;
870 ic->ic_newassoc = otus_newassoc;
871 ic->ic_updateslot = otus_updateslot;
872 #ifdef HAVE_EDCA
873 ic->ic_updateedca = otus_updateedca;
874 #endif /* HAVE_EDCA */
875 #ifdef notyet
876 ic->ic_set_key = otus_set_key;
877 ic->ic_delete_key = otus_delete_key;
878 #endif /* notyet */
879
880 /* Override state transition machine. */
881 sc->sc_newstate = ic->ic_newstate;
882 ic->ic_newstate = otus_newstate;
883 ieee80211_media_init(ic, otus_media_change, ieee80211_media_status);
884
885 bpf_attach2(ifp, DLT_IEEE802_11_RADIO,
886 sizeof(struct ieee80211_frame) + IEEE80211_RADIOTAP_HDRLEN,
887 &sc->sc_drvbpf);
888
889 sc->sc_rxtap_len = sizeof(sc->sc_rxtapu);
890 sc->sc_rxtap.wr_ihdr.it_len = htole16(sc->sc_rxtap_len);
891 sc->sc_rxtap.wr_ihdr.it_present = htole32(OTUS_RX_RADIOTAP_PRESENT);
892
893 sc->sc_txtap_len = sizeof(sc->sc_txtapu);
894 sc->sc_txtap.wt_ihdr.it_len = htole16(sc->sc_txtap_len);
895 sc->sc_txtap.wt_ihdr.it_present = htole32(OTUS_TX_RADIOTAP_PRESENT);
896
897 ieee80211_announce(ic);
898 }
899
900 Static void
901 otus_get_chanlist(struct otus_softc *sc)
902 {
903 struct ieee80211com *ic;
904 uint8_t chan;
905 int i;
906
907 #ifdef OTUS_DEBUG
908 /* XXX regulatory domain. */
909 uint16_t domain = le16toh(sc->sc_eeprom.baseEepHeader.regDmn[0]);
910
911 DPRINTFN(DBG_FN | DBG_INIT, sc, "regdomain=0x%04x\n", domain);
912 #endif
913
914 ic = &sc->sc_ic;
915 if (sc->sc_eeprom.baseEepHeader.opCapFlags & AR5416_OPFLAGS_11G) {
916 for (i = 0; i < 14; i++) {
917 chan = ar_chans[i];
918 ic->ic_channels[chan].ic_freq =
919 ieee80211_ieee2mhz(chan, IEEE80211_CHAN_2GHZ);
920 ic->ic_channels[chan].ic_flags =
921 IEEE80211_CHAN_CCK | IEEE80211_CHAN_OFDM |
922 IEEE80211_CHAN_DYN | IEEE80211_CHAN_2GHZ;
923 }
924 }
925 if (sc->sc_eeprom.baseEepHeader.opCapFlags & AR5416_OPFLAGS_11A) {
926 for (i = 14; i < __arraycount(ar_chans); i++) {
927 chan = ar_chans[i];
928 ic->ic_channels[chan].ic_freq =
929 ieee80211_ieee2mhz(chan, IEEE80211_CHAN_5GHZ);
930 ic->ic_channels[chan].ic_flags = IEEE80211_CHAN_A;
931 }
932 }
933 }
934
935 Static int
936 otus_load_firmware(struct otus_softc *sc, const char *name, uint32_t addr)
937 {
938 usb_device_request_t req;
939 firmware_handle_t fh;
940 uint8_t *ptr;
941 uint8_t *fw;
942 size_t size;
943 int mlen, error;
944
945 DPRINTFN(DBG_FN, sc, "\n");
946
947 if ((error = firmware_open("if_otus", name, &fh)) != 0)
948 return error;
949
950 size = firmware_get_size(fh);
951 if ((fw = firmware_malloc(size)) == NULL) {
952 firmware_close(fh);
953 return ENOMEM;
954 }
955 if ((error = firmware_read(fh, 0, fw, size)) != 0)
956 firmware_free(fw, size);
957 firmware_close(fh);
958 if (error)
959 return error;
960
961 req.bmRequestType = UT_WRITE_VENDOR_DEVICE;
962 req.bRequest = AR_FW_DOWNLOAD;
963 USETW(req.wIndex, 0);
964
965 ptr = fw;
966 addr >>= 8;
967 while (size > 0) {
968 mlen = MIN(size, 4096);
969
970 USETW(req.wValue, addr);
971 USETW(req.wLength, mlen);
972 if (usbd_do_request(sc->sc_udev, &req, ptr) != 0) {
973 error = EIO;
974 break;
975 }
976 addr += mlen >> 8;
977 ptr += mlen;
978 size -= mlen;
979 }
980 free(fw, M_DEVBUF);
981 return error;
982 }
983
984 Static int
985 otus_open_pipes(struct otus_softc *sc)
986 {
987 usb_endpoint_descriptor_t *ed;
988 int i, error;
989
990 DPRINTFN(DBG_FN, sc, "\n");
991
992 error = usbd_open_pipe(sc->sc_iface, AR_EPT_BULK_RX_NO, 0,
993 &sc->sc_data_rx_pipe);
994 if (error != 0) {
995 aprint_error_dev(sc->sc_dev, "could not open Rx bulk pipe\n");
996 goto fail;
997 }
998
999 ed = usbd_get_endpoint_descriptor(sc->sc_iface, AR_EPT_INTR_RX_NO);
1000 if (ed == NULL) {
1001 aprint_error_dev(sc->sc_dev,
1002 "could not retrieve Rx intr pipe descriptor\n");
1003 goto fail;
1004 }
1005 sc->sc_ibuf_size = UGETW(ed->wMaxPacketSize);
1006 if (sc->sc_ibuf_size == 0) {
1007 aprint_error_dev(sc->sc_dev,
1008 "invalid Rx intr pipe descriptor\n");
1009 goto fail;
1010 }
1011 sc->sc_ibuf = kmem_alloc(sc->sc_ibuf_size, KM_SLEEP);
1012 error = usbd_open_pipe_intr(sc->sc_iface, AR_EPT_INTR_RX_NO,
1013 USBD_SHORT_XFER_OK, &sc->sc_cmd_rx_pipe, sc, sc->sc_ibuf,
1014 sc->sc_ibuf_size, otus_intr, USBD_DEFAULT_INTERVAL);
1015 if (error != 0) {
1016 aprint_error_dev(sc->sc_dev, "could not open Rx intr pipe\n");
1017 goto fail;
1018 }
1019
1020 error = usbd_open_pipe(sc->sc_iface, AR_EPT_BULK_TX_NO, 0,
1021 &sc->sc_data_tx_pipe);
1022 if (error != 0) {
1023 aprint_error_dev(sc->sc_dev, "could not open Tx bulk pipe\n");
1024 goto fail;
1025 }
1026
1027 error = usbd_open_pipe(sc->sc_iface, AR_EPT_INTR_TX_NO, 0,
1028 &sc->sc_cmd_tx_pipe);
1029 if (error != 0) {
1030 aprint_error_dev(sc->sc_dev, "could not open Tx intr pipe\n");
1031 goto fail;
1032 }
1033
1034 if (otus_alloc_tx_cmd(sc) != 0) {
1035 aprint_error_dev(sc->sc_dev,
1036 "could not allocate command xfer\n");
1037 goto fail;
1038 }
1039
1040 if (otus_alloc_tx_data_list(sc)) {
1041 aprint_error_dev(sc->sc_dev, "could not allocate Tx xfers\n");
1042 goto fail;
1043 }
1044
1045 if (otus_alloc_rx_data_list(sc)) {
1046 aprint_error_dev(sc->sc_dev, "could not allocate Rx xfers\n");
1047 goto fail;
1048 }
1049
1050 for (i = 0; i < OTUS_RX_DATA_LIST_COUNT; i++) {
1051 struct otus_rx_data *data = &sc->sc_rx_data[i];
1052
1053 usbd_setup_xfer(data->xfer, data, data->buf, OTUS_RXBUFSZ,
1054 USBD_SHORT_XFER_OK, USBD_NO_TIMEOUT, otus_rxeof);
1055 error = usbd_transfer(data->xfer);
1056 if (error != USBD_IN_PROGRESS && error != 0) {
1057 aprint_error_dev(sc->sc_dev,
1058 "could not queue Rx xfer\n");
1059 goto fail;
1060 }
1061 }
1062 return 0;
1063
1064 fail: otus_close_pipes(sc);
1065 return error;
1066 }
1067
1068 Static void
1069 otus_close_pipes(struct otus_softc *sc)
1070 {
1071
1072 DPRINTFN(DBG_FN, sc, "\n");
1073
1074 otus_free_tx_cmd(sc);
1075 otus_free_tx_data_list(sc);
1076 otus_free_rx_data_list(sc);
1077
1078 if (sc->sc_data_rx_pipe != NULL)
1079 usbd_close_pipe(sc->sc_data_rx_pipe);
1080 if (sc->sc_cmd_rx_pipe != NULL) {
1081 usbd_abort_pipe(sc->sc_cmd_rx_pipe);
1082 usbd_close_pipe(sc->sc_cmd_rx_pipe);
1083 }
1084 if (sc->sc_ibuf != NULL)
1085 kmem_free(sc->sc_ibuf, sc->sc_ibuf_size);
1086 if (sc->sc_data_tx_pipe != NULL)
1087 usbd_close_pipe(sc->sc_data_tx_pipe);
1088 if (sc->sc_cmd_tx_pipe != NULL)
1089 usbd_close_pipe(sc->sc_cmd_tx_pipe);
1090 }
1091
1092 Static int
1093 otus_alloc_tx_cmd(struct otus_softc *sc)
1094 {
1095 struct otus_tx_cmd *cmd;
1096
1097 DPRINTFN(DBG_FN, sc, "\n");
1098
1099 cmd = &sc->sc_tx_cmd;
1100
1101 int error = usbd_create_xfer(sc->sc_cmd_tx_pipe, OTUS_MAX_TXCMDSZ,
1102 USBD_FORCE_SHORT_XFER, 0, &cmd->xfer);
1103 if (error)
1104 return error;
1105
1106 cmd->buf = usbd_get_buffer(cmd->xfer);
1107
1108 return 0;
1109 }
1110
1111 Static void
1112 otus_free_tx_cmd(struct otus_softc *sc)
1113 {
1114
1115 DPRINTFN(DBG_FN, sc, "\n");
1116
1117 if (sc->sc_cmd_tx_pipe == NULL)
1118 return;
1119
1120 /* Make sure no transfers are pending. */
1121 usbd_abort_pipe(sc->sc_cmd_tx_pipe);
1122
1123 mutex_enter(&sc->sc_cmd_mtx);
1124 if (sc->sc_tx_cmd.xfer != NULL)
1125 usbd_destroy_xfer(sc->sc_tx_cmd.xfer);
1126 sc->sc_tx_cmd.xfer = NULL;
1127 sc->sc_tx_cmd.buf = NULL;
1128 mutex_exit(&sc->sc_cmd_mtx);
1129 }
1130
1131 Static int
1132 otus_alloc_tx_data_list(struct otus_softc *sc)
1133 {
1134 struct otus_tx_data *data;
1135 int i, error;
1136
1137 DPRINTFN(DBG_FN, sc, "\n");
1138
1139 mutex_enter(&sc->sc_tx_mtx);
1140 error = 0;
1141 TAILQ_INIT(&sc->sc_tx_free_list);
1142 for (i = 0; i < OTUS_TX_DATA_LIST_COUNT; i++) {
1143 data = &sc->sc_tx_data[i];
1144
1145 data->sc = sc; /* Backpointer for callbacks. */
1146
1147 error = usbd_create_xfer(sc->sc_data_tx_pipe, OTUS_TXBUFSZ,
1148 USBD_FORCE_SHORT_XFER, 0, &data->xfer);
1149 if (error) {
1150 aprint_error_dev(sc->sc_dev,
1151 "could not allocate xfer\n");
1152 break;
1153 }
1154 data->buf = usbd_get_buffer(data->xfer);
1155 /* Append this Tx buffer to our free list. */
1156 TAILQ_INSERT_TAIL(&sc->sc_tx_free_list, data, next);
1157 }
1158 if (error != 0)
1159 otus_free_tx_data_list(sc);
1160 mutex_exit(&sc->sc_tx_mtx);
1161 return error;
1162 }
1163
1164 Static void
1165 otus_free_tx_data_list(struct otus_softc *sc)
1166 {
1167 int i;
1168
1169 DPRINTFN(DBG_FN, sc, "\n");
1170
1171 if (sc->sc_data_tx_pipe == NULL)
1172 return;
1173
1174 /* Make sure no transfers are pending. */
1175 usbd_abort_pipe(sc->sc_data_tx_pipe);
1176
1177 for (i = 0; i < OTUS_TX_DATA_LIST_COUNT; i++) {
1178 if (sc->sc_tx_data[i].xfer != NULL)
1179 usbd_destroy_xfer(sc->sc_tx_data[i].xfer);
1180 }
1181 }
1182
1183 Static int
1184 otus_alloc_rx_data_list(struct otus_softc *sc)
1185 {
1186 struct otus_rx_data *data;
1187 int i, error;
1188
1189 DPRINTFN(DBG_FN, sc, "\n");
1190
1191 for (i = 0; i < OTUS_RX_DATA_LIST_COUNT; i++) {
1192 data = &sc->sc_rx_data[i];
1193
1194 data->sc = sc; /* Backpointer for callbacks. */
1195
1196 error = usbd_create_xfer(sc->sc_data_rx_pipe, OTUS_RXBUFSZ,
1197 0, 0, &data->xfer);
1198
1199 if (error) {
1200 aprint_error_dev(sc->sc_dev,
1201 "could not allocate xfer\n");
1202 goto fail;
1203 }
1204 data->buf = usbd_get_buffer(data->xfer);
1205 }
1206 return 0;
1207
1208 fail: otus_free_rx_data_list(sc);
1209 return error;
1210 }
1211
1212 Static void
1213 otus_free_rx_data_list(struct otus_softc *sc)
1214 {
1215 int i;
1216
1217 DPRINTFN(DBG_FN, sc, "\n");
1218
1219 if (sc->sc_data_rx_pipe == NULL)
1220 return;
1221
1222 /* Make sure no transfers are pending. */
1223 usbd_abort_pipe(sc->sc_data_rx_pipe);
1224
1225 for (i = 0; i < OTUS_RX_DATA_LIST_COUNT; i++)
1226 if (sc->sc_rx_data[i].xfer != NULL)
1227 usbd_destroy_xfer(sc->sc_rx_data[i].xfer);
1228 }
1229
1230 Static void
1231 otus_next_scan(void *arg)
1232 {
1233 struct otus_softc *sc;
1234
1235 sc = arg;
1236
1237 DPRINTFN(DBG_FN, sc, "\n");
1238
1239 if (sc->sc_dying)
1240 return;
1241
1242 if (sc->sc_ic.ic_state == IEEE80211_S_SCAN)
1243 ieee80211_next_scan(&sc->sc_ic);
1244 }
1245
1246 Static void
1247 otus_task(void *arg)
1248 {
1249 struct otus_softc *sc;
1250 struct otus_host_cmd_ring *ring;
1251 struct otus_host_cmd *cmd;
1252
1253 sc = arg;
1254
1255 DPRINTFN(DBG_FN, sc, "\n");
1256
1257 /* Process host commands. */
1258 mutex_spin_enter(&sc->sc_task_mtx);
1259 ring = &sc->sc_cmdq;
1260 while (ring->next != ring->cur) {
1261 cmd = &ring->cmd[ring->next];
1262 mutex_spin_exit(&sc->sc_task_mtx);
1263
1264 /* Callback. */
1265 DPRINTFN(DBG_CMD, sc, "cb=%p queued=%d\n", cmd->cb,
1266 ring->queued);
1267 cmd->cb(sc, cmd->data);
1268
1269 mutex_spin_enter(&sc->sc_task_mtx);
1270 ring->queued--;
1271 ring->next = (ring->next + 1) % OTUS_HOST_CMD_RING_COUNT;
1272 }
1273 cv_signal(&sc->sc_task_cv);
1274 mutex_spin_exit(&sc->sc_task_mtx);
1275 }
1276
1277 Static void
1278 otus_do_async(struct otus_softc *sc, void (*cb)(struct otus_softc *, void *),
1279 void *arg, int len)
1280 {
1281 struct otus_host_cmd_ring *ring;
1282 struct otus_host_cmd *cmd;
1283 bool sched = false;
1284
1285 DPRINTFN(DBG_FN, sc, "cb=%p\n", cb);
1286
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 sched = true;
1298 }
1299 cv_signal(&sc->sc_task_cv);
1300 mutex_spin_exit(&sc->sc_task_mtx);
1301 if (sched)
1302 usb_add_task(sc->sc_udev, &sc->sc_task, USB_TASKQ_DRIVER);
1303 }
1304
1305 Static int
1306 otus_newstate(struct ieee80211com *ic, enum ieee80211_state nstate, int arg)
1307 {
1308 struct otus_softc *sc;
1309 struct otus_cmd_newstate cmd;
1310
1311 sc = ic->ic_ifp->if_softc;
1312
1313 DPRINTFN(DBG_FN | DBG_STM, sc, "nstate=%s(%d), arg=%d\n",
1314 ieee80211_state_name[nstate], nstate, arg);
1315
1316 /* Do it in a process context. */
1317 cmd.state = nstate;
1318 cmd.arg = arg;
1319 otus_do_async(sc, otus_newstate_cb, &cmd, sizeof(cmd));
1320 return 0;
1321 }
1322
1323 Static void
1324 otus_newstate_cb(struct otus_softc *sc, void *arg)
1325 {
1326 struct otus_cmd_newstate *cmd;
1327 struct ieee80211com *ic;
1328 struct ieee80211_node *ni;
1329 enum ieee80211_state nstate;
1330 int s;
1331
1332 cmd = arg;
1333 ic = &sc->sc_ic;
1334 ni = ic->ic_bss;
1335 nstate = cmd->state;
1336
1337 #ifdef OTUS_DEBUG
1338 enum ieee80211_state ostate = ostate = ic->ic_state;
1339 DPRINTFN(DBG_FN | DBG_STM, sc, "%s(%d)->%s(%d)\n",
1340 ieee80211_state_name[ostate], ostate,
1341 ieee80211_state_name[nstate], nstate);
1342 #endif
1343
1344 s = splnet();
1345
1346 callout_halt(&sc->sc_scan_to, NULL);
1347 callout_halt(&sc->sc_calib_to, NULL);
1348
1349 mutex_enter(&sc->sc_write_mtx);
1350
1351 switch (nstate) {
1352 case IEEE80211_S_INIT:
1353 break;
1354
1355 case IEEE80211_S_SCAN:
1356 otus_set_chan(sc, ic->ic_curchan, 0);
1357 if (!sc->sc_dying)
1358 callout_schedule(&sc->sc_scan_to, hz / 5);
1359 break;
1360
1361 case IEEE80211_S_AUTH:
1362 case IEEE80211_S_ASSOC:
1363 otus_set_chan(sc, ic->ic_curchan, 0);
1364 break;
1365
1366 case IEEE80211_S_RUN:
1367 otus_set_chan(sc, ic->ic_curchan, 1);
1368
1369 switch (ic->ic_opmode) {
1370 case IEEE80211_M_STA:
1371 otus_updateslot_cb_locked(sc);
1372 otus_set_bssid(sc, ni->ni_bssid);
1373
1374 /* Fake a join to init the Tx rate. */
1375 otus_newassoc(ni, 1);
1376
1377 /* Start calibration timer. */
1378 if (!sc->sc_dying)
1379 callout_schedule(&sc->sc_calib_to, hz);
1380 break;
1381
1382 case IEEE80211_M_IBSS:
1383 case IEEE80211_M_AHDEMO:
1384 case IEEE80211_M_HOSTAP:
1385 case IEEE80211_M_MONITOR:
1386 break;
1387 }
1388 break;
1389 }
1390 (void)sc->sc_newstate(ic, nstate, cmd->arg);
1391 sc->sc_led_newstate(sc);
1392 mutex_exit(&sc->sc_write_mtx);
1393
1394 splx(s);
1395 }
1396
1397 Static int
1398 otus_cmd(struct otus_softc *sc, uint8_t code, const void *idata, int ilen,
1399 void *odata)
1400 {
1401 struct otus_tx_cmd *cmd;
1402 struct ar_cmd_hdr *hdr;
1403 int xferlen, error;
1404
1405 DPRINTFN(DBG_FN, sc, "\n");
1406
1407 cmd = &sc->sc_tx_cmd;
1408
1409 mutex_enter(&sc->sc_cmd_mtx);
1410
1411 /* Always bulk-out a multiple of 4 bytes. */
1412 xferlen = roundup2(sizeof(*hdr) + ilen, 4);
1413
1414 hdr = (void *)cmd->buf;
1415 if (hdr == NULL) { /* we may have been freed while detaching */
1416 mutex_exit(&sc->sc_cmd_mtx);
1417 DPRINTFN(DBG_CMD, sc, "tx_cmd freed with commands pending\n");
1418 return 0;
1419 }
1420 hdr->code = code;
1421 hdr->len = ilen;
1422 hdr->token = ++cmd->token; /* Don't care about endianness. */
1423 KASSERT(sizeof(hdr) + ilen <= OTUS_MAX_TXCMDSZ);
1424 memcpy(cmd->buf + sizeof(hdr[0]), idata, ilen);
1425
1426 DPRINTFN(DBG_CMD, sc, "sending command code=0x%02x len=%d token=%d\n",
1427 code, ilen, hdr->token);
1428
1429 cmd->odata = odata;
1430 cmd->done = 0;
1431 usbd_setup_xfer(cmd->xfer, cmd, cmd->buf, xferlen,
1432 USBD_FORCE_SHORT_XFER, OTUS_CMD_TIMEOUT, NULL);
1433 error = usbd_sync_transfer(cmd->xfer);
1434 if (error != 0) {
1435 mutex_exit(&sc->sc_cmd_mtx);
1436 #if defined(DIAGNOSTIC) || defined(OTUS_DEBUG) /* XXX: kill some noise */
1437 aprint_error_dev(sc->sc_dev,
1438 "could not send command %#x (error=%s)\n",
1439 code, usbd_errstr(error));
1440 #endif
1441 return EIO;
1442 }
1443 if (!cmd->done)
1444 error = cv_timedwait_sig(&sc->sc_cmd_cv, &sc->sc_cmd_mtx, hz);
1445 cmd->odata = NULL; /* In case answer is received too late. */
1446 mutex_exit(&sc->sc_cmd_mtx);
1447 if (error != 0) {
1448 aprint_error_dev(sc->sc_dev,
1449 "timeout waiting for command 0x%02x reply\n", code);
1450 }
1451 return error;
1452 }
1453
1454 Static void
1455 otus_write(struct otus_softc *sc, uint32_t reg, uint32_t val)
1456 {
1457
1458 DPRINTFN(DBG_FN | DBG_REG, sc, "reg=%#x, val=%#x\n", reg, val);
1459
1460 KASSERT(mutex_owned(&sc->sc_write_mtx));
1461 KASSERT(sc->sc_write_idx < __arraycount(sc->sc_write_buf));
1462
1463 sc->sc_write_buf[sc->sc_write_idx].reg = htole32(reg);
1464 sc->sc_write_buf[sc->sc_write_idx].val = htole32(val);
1465
1466 if (++sc->sc_write_idx >= __arraycount(sc->sc_write_buf))
1467 (void)otus_write_barrier(sc);
1468 }
1469
1470 Static int
1471 otus_write_barrier(struct otus_softc *sc)
1472 {
1473 int error;
1474
1475 DPRINTFN(DBG_FN, sc, "\n");
1476
1477 KASSERT(mutex_owned(&sc->sc_write_mtx));
1478 KASSERT(sc->sc_write_idx <= __arraycount(sc->sc_write_buf));
1479
1480 if (sc->sc_write_idx == 0)
1481 return 0; /* Nothing to flush. */
1482
1483 error = otus_cmd(sc, AR_CMD_WREG, sc->sc_write_buf,
1484 sizeof(sc->sc_write_buf[0]) * sc->sc_write_idx, NULL);
1485
1486 sc->sc_write_idx = 0;
1487 if (error)
1488 DPRINTFN(DBG_REG, sc, "error=%d\n", error);
1489 return error;
1490 }
1491
1492 Static struct ieee80211_node *
1493 otus_node_alloc(struct ieee80211_node_table *ntp)
1494 {
1495 struct otus_node *on;
1496
1497 DPRINTFN(DBG_FN, DBG_NO_SC, "\n");
1498
1499 on = malloc(sizeof(*on), M_DEVBUF, M_NOWAIT | M_ZERO);
1500 return on ? &on->ni : NULL;
1501 }
1502
1503 Static int
1504 otus_media_change(struct ifnet *ifp)
1505 {
1506 struct otus_softc *sc;
1507 struct ieee80211com *ic;
1508 uint8_t rate, ridx;
1509 int error;
1510
1511 sc = ifp->if_softc;
1512
1513 DPRINTFN(DBG_FN, sc, "\n");
1514
1515 error = ieee80211_media_change(ifp);
1516 if (error != ENETRESET)
1517 return error;
1518
1519 ic = &sc->sc_ic;
1520 if (ic->ic_fixed_rate != -1) {
1521 rate = ic->ic_sup_rates[ic->ic_curmode].
1522 rs_rates[ic->ic_fixed_rate] & IEEE80211_RATE_VAL;
1523 for (ridx = 0; ridx <= OTUS_RIDX_MAX; ridx++)
1524 if (otus_rates[ridx].rate == rate)
1525 break;
1526 sc->sc_fixed_ridx = ridx;
1527 }
1528
1529 if ((ifp->if_flags & (IFF_UP | IFF_RUNNING)) == (IFF_UP | IFF_RUNNING))
1530 error = otus_init(ifp);
1531
1532 return error;
1533 }
1534
1535 Static int
1536 otus_read_eeprom(struct otus_softc *sc)
1537 {
1538 uint32_t regs[8], reg;
1539 uint8_t *eep;
1540 int i, j, error;
1541
1542 DPRINTFN(DBG_FN, sc, "\n");
1543
1544 KASSERT(sizeof(sc->sc_eeprom) % 32 == 0);
1545
1546 /* Read EEPROM by blocks of 32 bytes. */
1547 eep = (uint8_t *)&sc->sc_eeprom;
1548 reg = AR_EEPROM_OFFSET;
1549 for (i = 0; i < sizeof(sc->sc_eeprom) / 32; i++) {
1550 for (j = 0; j < 8; j++, reg += 4)
1551 regs[j] = htole32(reg);
1552 error = otus_cmd(sc, AR_CMD_RREG, regs, sizeof(regs), eep);
1553 if (error != 0)
1554 break;
1555 eep += 32;
1556 }
1557 return error;
1558 }
1559
1560 Static void
1561 otus_newassoc(struct ieee80211_node *ni, int isnew)
1562 {
1563 struct ieee80211_rateset *rs;
1564 struct otus_softc *sc;
1565 struct otus_node *on;
1566 uint8_t rate;
1567 int ridx, i;
1568
1569 sc = ni->ni_ic->ic_ifp->if_softc;
1570
1571 DPRINTFN(DBG_FN, sc, "isnew=%d addr=%s\n",
1572 isnew, ether_sprintf(ni->ni_macaddr));
1573
1574 on = (void *)ni;
1575 ieee80211_amrr_node_init(&sc->sc_amrr, &on->amn);
1576 /* Start at lowest available bit-rate, AMRR will raise. */
1577 ni->ni_txrate = 0;
1578 rs = &ni->ni_rates;
1579 for (i = 0; i < rs->rs_nrates; i++) {
1580 rate = rs->rs_rates[i] & IEEE80211_RATE_VAL;
1581 /* Convert 802.11 rate to hardware rate index. */
1582 for (ridx = 0; ridx <= OTUS_RIDX_MAX; ridx++)
1583 if (otus_rates[ridx].rate == rate)
1584 break;
1585 on->ridx[i] = ridx;
1586 DPRINTFN(DBG_INIT, sc, "rate=0x%02x ridx=%d\n",
1587 rs->rs_rates[i], on->ridx[i]);
1588 }
1589 }
1590
1591 /* ARGSUSED */
1592 Static void
1593 otus_intr(struct usbd_xfer *xfer, void *priv, usbd_status status)
1594 {
1595 #if 0
1596 struct otus_softc *sc;
1597 int len;
1598
1599 sc = priv;
1600
1601 DPRINTFN(DBG_FN, sc, "\n");
1602
1603 /*
1604 * The Rx intr pipe is unused with current firmware. Notifications
1605 * and replies to commands are sent through the Rx bulk pipe instead
1606 * (with a magic PLCP header.)
1607 */
1608 if (__predict_false(status != USBD_NORMAL_COMPLETION)) {
1609 DPRINTFN(DBG_INTR, sc, "status=%d\n", status);
1610 if (status == USBD_STALLED)
1611 usbd_clear_endpoint_stall_async(sc->sc_cmd_rx_pipe);
1612 return;
1613 }
1614 usbd_get_xfer_status(xfer, NULL, NULL, &len, NULL);
1615
1616 otus_cmd_rxeof(sc, sc->sc_ibuf, len);
1617 #endif
1618 }
1619
1620 Static void
1621 otus_cmd_rxeof(struct otus_softc *sc, uint8_t *buf, int len)
1622 {
1623 struct ieee80211com *ic;
1624 struct otus_tx_cmd *cmd;
1625 struct ar_cmd_hdr *hdr;
1626 int s;
1627
1628 DPRINTFN(DBG_FN, sc, "\n");
1629
1630 ic = &sc->sc_ic;
1631
1632 if (__predict_false(len < sizeof(*hdr))) {
1633 DPRINTFN(DBG_RX, sc, "cmd too small %d\n", len);
1634 return;
1635 }
1636 hdr = (void *)buf;
1637 if (__predict_false(sizeof(*hdr) + hdr->len > len ||
1638 sizeof(*hdr) + hdr->len > 64)) {
1639 DPRINTFN(DBG_RX, sc, "cmd too large %d\n", hdr->len);
1640 return;
1641 }
1642
1643 if ((hdr->code & 0xc0) != 0xc0) {
1644 DPRINTFN(DBG_RX, sc, "received reply code=0x%02x len=%d token=%d\n",
1645 hdr->code, hdr->len, hdr->token);
1646 mutex_enter(&sc->sc_cmd_mtx);
1647 cmd = &sc->sc_tx_cmd;
1648 if (__predict_false(hdr->token != cmd->token)) {
1649 mutex_exit(&sc->sc_cmd_mtx);
1650 return;
1651 }
1652 /* Copy answer into caller's supplied buffer. */
1653 if (cmd->odata != NULL)
1654 memcpy(cmd->odata, &hdr[1], hdr->len);
1655 cmd->done = 1;
1656 cv_signal(&sc->sc_cmd_cv);
1657 mutex_exit(&sc->sc_cmd_mtx);
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=%#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 if_statinc(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 if_statinc(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 if_statinc(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 if_statinc(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 if_statinc(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 %#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 if_statinc(ifp, if_oerrors);
1921 return;
1922 }
1923 if_statinc(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 if_statinc(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 if_statinc(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 if_statinc(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 if_statinc(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 if_statinc(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, "%#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=%#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=%#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