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