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