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