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