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