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