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