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