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