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