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