FreeBSD/Linux Kernel Cross Reference
sys/dev/usb/if_rum.c
1 /* $FreeBSD: src/sys/dev/usb/if_rum.c,v 1.26 2008/08/19 01:44:56 kevlo Exp $ */
2
3 /*-
4 * Copyright (c) 2005-2007 Damien Bergamini <damien.bergamini@free.fr>
5 * Copyright (c) 2006 Niall O'Higgins <niallo@openbsd.org>
6 *
7 * Permission to use, copy, modify, and distribute this software for any
8 * purpose with or without fee is hereby granted, provided that the above
9 * copyright notice and this permission notice appear in all copies.
10 *
11 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18 */
19
20 #include <sys/cdefs.h>
21 __FBSDID("$FreeBSD: src/sys/dev/usb/if_rum.c,v 1.26 2008/08/19 01:44:56 kevlo Exp $");
22
23 /*-
24 * Ralink Technology RT2501USB/RT2601USB chipset driver
25 * http://www.ralinktech.com.tw/
26 */
27
28 #include <sys/param.h>
29 #include <sys/sysctl.h>
30 #include <sys/sockio.h>
31 #include <sys/mbuf.h>
32 #include <sys/kernel.h>
33 #include <sys/socket.h>
34 #include <sys/systm.h>
35 #include <sys/malloc.h>
36 #include <sys/module.h>
37 #include <sys/bus.h>
38 #include <sys/endian.h>
39
40 #include <machine/bus.h>
41 #include <machine/resource.h>
42 #include <sys/rman.h>
43
44 #include <net/bpf.h>
45 #include <net/if.h>
46 #include <net/if_arp.h>
47 #include <net/ethernet.h>
48 #include <net/if_dl.h>
49 #include <net/if_media.h>
50 #include <net/if_types.h>
51
52 #include <net80211/ieee80211_var.h>
53 #include <net80211/ieee80211_amrr.h>
54 #include <net80211/ieee80211_phy.h>
55 #include <net80211/ieee80211_radiotap.h>
56 #include <net80211/ieee80211_regdomain.h>
57
58 #include <dev/usb/usb.h>
59 #include <dev/usb/usbdi.h>
60 #include <dev/usb/usbdi_util.h>
61 #include "usbdevs.h"
62
63 #include <dev/usb/if_rumreg.h>
64 #include <dev/usb/if_rumvar.h>
65 #include <dev/usb/rt2573_ucode.h>
66
67 #ifdef USB_DEBUG
68 #define DPRINTF(x) do { if (rumdebug > 0) printf x; } while (0)
69 #define DPRINTFN(n, x) do { if (rumdebug >= (n)) printf x; } while (0)
70 int rumdebug = 0;
71 SYSCTL_NODE(_hw_usb, OID_AUTO, rum, CTLFLAG_RW, 0, "USB rum");
72 SYSCTL_INT(_hw_usb_rum, OID_AUTO, debug, CTLFLAG_RW, &rumdebug, 0,
73 "rum debug level");
74 #else
75 #define DPRINTF(x)
76 #define DPRINTFN(n, x)
77 #endif
78
79 /* various supported device vendors/products */
80 static const struct usb_devno rum_devs[] = {
81 { USB_VENDOR_ABOCOM, USB_PRODUCT_ABOCOM_HWU54DM },
82 { USB_VENDOR_ABOCOM, USB_PRODUCT_ABOCOM_RT2573_2 },
83 { USB_VENDOR_ABOCOM, USB_PRODUCT_ABOCOM_RT2573_3 },
84 { USB_VENDOR_ABOCOM, USB_PRODUCT_ABOCOM_RT2573_4 },
85 { USB_VENDOR_ABOCOM, USB_PRODUCT_ABOCOM_WUG2700 },
86 { USB_VENDOR_AMIT, USB_PRODUCT_AMIT_CGWLUSB2GO },
87 { USB_VENDOR_ASUS, USB_PRODUCT_ASUS_RT2573_1 },
88 { USB_VENDOR_ASUS, USB_PRODUCT_ASUS_RT2573_2 },
89 { USB_VENDOR_BELKIN, USB_PRODUCT_BELKIN_F5D7050A },
90 { USB_VENDOR_BELKIN, USB_PRODUCT_BELKIN_F5D9050V3 },
91 { USB_VENDOR_CISCOLINKSYS, USB_PRODUCT_CISCOLINKSYS_WUSB54GC },
92 { USB_VENDOR_CISCOLINKSYS, USB_PRODUCT_CISCOLINKSYS_WUSB54GR },
93 { USB_VENDOR_CONCEPTRONIC2, USB_PRODUCT_CONCEPTRONIC2_C54RU2 },
94 { USB_VENDOR_COREGA, USB_PRODUCT_COREGA_CGWLUSB2GL },
95 { USB_VENDOR_COREGA, USB_PRODUCT_COREGA_CGWLUSB2GPX },
96 { USB_VENDOR_DICKSMITH, USB_PRODUCT_DICKSMITH_CWD854F },
97 { USB_VENDOR_DICKSMITH, USB_PRODUCT_DICKSMITH_RT2573 },
98 { USB_VENDOR_DLINK2, USB_PRODUCT_DLINK2_DWLG122C1 },
99 { USB_VENDOR_DLINK2, USB_PRODUCT_DLINK2_WUA1340 },
100 { USB_VENDOR_DLINK2, USB_PRODUCT_DLINK2_DWA111 },
101 { USB_VENDOR_DLINK2, USB_PRODUCT_DLINK2_DWA110 },
102 { USB_VENDOR_GIGABYTE, USB_PRODUCT_GIGABYTE_GNWB01GS },
103 { USB_VENDOR_GIGABYTE, USB_PRODUCT_GIGABYTE_GNWI05GS },
104 { USB_VENDOR_GIGASET, USB_PRODUCT_GIGASET_RT2573 },
105 { USB_VENDOR_GOODWAY, USB_PRODUCT_GOODWAY_RT2573 },
106 { USB_VENDOR_GUILLEMOT, USB_PRODUCT_GUILLEMOT_HWGUSB254LB },
107 { USB_VENDOR_GUILLEMOT, USB_PRODUCT_GUILLEMOT_HWGUSB254V2AP },
108 { USB_VENDOR_HUAWEI3COM, USB_PRODUCT_HUAWEI3COM_WUB320G },
109 { USB_VENDOR_MELCO, USB_PRODUCT_MELCO_G54HP },
110 { USB_VENDOR_MELCO, USB_PRODUCT_MELCO_SG54HP },
111 { USB_VENDOR_MSI, USB_PRODUCT_MSI_RT2573_1 },
112 { USB_VENDOR_MSI, USB_PRODUCT_MSI_RT2573_2 },
113 { USB_VENDOR_MSI, USB_PRODUCT_MSI_RT2573_3 },
114 { USB_VENDOR_MSI, USB_PRODUCT_MSI_RT2573_4 },
115 { USB_VENDOR_NOVATECH, USB_PRODUCT_NOVATECH_RT2573 },
116 { USB_VENDOR_PLANEX2, USB_PRODUCT_PLANEX2_GWUS54HP },
117 { USB_VENDOR_PLANEX2, USB_PRODUCT_PLANEX2_GWUS54MINI2 },
118 { USB_VENDOR_PLANEX2, USB_PRODUCT_PLANEX2_GWUSMM },
119 { USB_VENDOR_QCOM, USB_PRODUCT_QCOM_RT2573 },
120 { USB_VENDOR_QCOM, USB_PRODUCT_QCOM_RT2573_2 },
121 { USB_VENDOR_RALINK, USB_PRODUCT_RALINK_RT2573 },
122 { USB_VENDOR_RALINK, USB_PRODUCT_RALINK_RT2573_2 },
123 { USB_VENDOR_RALINK, USB_PRODUCT_RALINK_RT2671 },
124 { USB_VENDOR_SITECOMEU, USB_PRODUCT_SITECOMEU_WL113R2 },
125 { USB_VENDOR_SITECOMEU, USB_PRODUCT_SITECOMEU_WL172 },
126 { USB_VENDOR_SPARKLAN, USB_PRODUCT_SPARKLAN_RT2573 },
127 { USB_VENDOR_SURECOM, USB_PRODUCT_SURECOM_RT2573 }
128 };
129
130 MODULE_DEPEND(rum, wlan, 1, 1, 1);
131 MODULE_DEPEND(rum, wlan_amrr, 1, 1, 1);
132 MODULE_DEPEND(rum, usb, 1, 1, 1);
133
134 static struct ieee80211vap *rum_vap_create(struct ieee80211com *,
135 const char name[IFNAMSIZ], int unit, int opmode,
136 int flags, const uint8_t bssid[IEEE80211_ADDR_LEN],
137 const uint8_t mac[IEEE80211_ADDR_LEN]);
138 static void rum_vap_delete(struct ieee80211vap *);
139 static int rum_alloc_tx_list(struct rum_softc *);
140 static void rum_free_tx_list(struct rum_softc *);
141 static int rum_alloc_rx_list(struct rum_softc *);
142 static void rum_free_rx_list(struct rum_softc *);
143 static void rum_task(void *);
144 static void rum_scantask(void *);
145 static int rum_newstate(struct ieee80211vap *,
146 enum ieee80211_state, int);
147 static void rum_txeof(usbd_xfer_handle, usbd_private_handle,
148 usbd_status);
149 static void rum_rxeof(usbd_xfer_handle, usbd_private_handle,
150 usbd_status);
151 static void rum_setup_tx_desc(struct rum_softc *,
152 struct rum_tx_desc *, uint32_t, uint16_t, int,
153 int);
154 static int rum_tx_mgt(struct rum_softc *, struct mbuf *,
155 struct ieee80211_node *);
156 static int rum_tx_raw(struct rum_softc *, struct mbuf *,
157 struct ieee80211_node *,
158 const struct ieee80211_bpf_params *);
159 static int rum_tx_data(struct rum_softc *, struct mbuf *,
160 struct ieee80211_node *);
161 static void rum_start(struct ifnet *);
162 static void rum_watchdog(void *);
163 static int rum_ioctl(struct ifnet *, u_long, caddr_t);
164 static void rum_eeprom_read(struct rum_softc *, uint16_t, void *,
165 int);
166 static uint32_t rum_read(struct rum_softc *, uint16_t);
167 static void rum_read_multi(struct rum_softc *, uint16_t, void *,
168 int);
169 static void rum_write(struct rum_softc *, uint16_t, uint32_t);
170 static void rum_write_multi(struct rum_softc *, uint16_t, void *,
171 size_t);
172 static void rum_bbp_write(struct rum_softc *, uint8_t, uint8_t);
173 static uint8_t rum_bbp_read(struct rum_softc *, uint8_t);
174 static void rum_rf_write(struct rum_softc *, uint8_t, uint32_t);
175 static void rum_select_antenna(struct rum_softc *);
176 static void rum_enable_mrr(struct rum_softc *);
177 static void rum_set_txpreamble(struct rum_softc *);
178 static void rum_set_basicrates(struct rum_softc *);
179 static void rum_select_band(struct rum_softc *,
180 struct ieee80211_channel *);
181 static void rum_set_chan(struct rum_softc *,
182 struct ieee80211_channel *);
183 static void rum_enable_tsf_sync(struct rum_softc *);
184 static void rum_update_slot(struct ifnet *);
185 static void rum_set_bssid(struct rum_softc *, const uint8_t *);
186 static void rum_set_macaddr(struct rum_softc *, const uint8_t *);
187 static void rum_update_promisc(struct rum_softc *);
188 static const char *rum_get_rf(int);
189 static void rum_read_eeprom(struct rum_softc *);
190 static int rum_bbp_init(struct rum_softc *);
191 static void rum_init_locked(struct rum_softc *);
192 static void rum_init(void *);
193 static void rum_stop(void *);
194 static int rum_load_microcode(struct rum_softc *, const u_char *,
195 size_t);
196 static int rum_prepare_beacon(struct rum_softc *,
197 struct ieee80211vap *);
198 static int rum_raw_xmit(struct ieee80211_node *, struct mbuf *,
199 const struct ieee80211_bpf_params *);
200 static struct ieee80211_node *rum_node_alloc(struct ieee80211vap *,
201 const uint8_t mac[IEEE80211_ADDR_LEN]);
202 static void rum_newassoc(struct ieee80211_node *, int);
203 static void rum_scan_start(struct ieee80211com *);
204 static void rum_scan_end(struct ieee80211com *);
205 static void rum_set_channel(struct ieee80211com *);
206 static int rum_get_rssi(struct rum_softc *, uint8_t);
207 static void rum_amrr_start(struct rum_softc *,
208 struct ieee80211_node *);
209 static void rum_amrr_timeout(void *);
210 static void rum_amrr_update(usbd_xfer_handle, usbd_private_handle,
211 usbd_status);
212
213 static const struct {
214 uint32_t reg;
215 uint32_t val;
216 } rum_def_mac[] = {
217 { RT2573_TXRX_CSR0, 0x025fb032 },
218 { RT2573_TXRX_CSR1, 0x9eaa9eaf },
219 { RT2573_TXRX_CSR2, 0x8a8b8c8d },
220 { RT2573_TXRX_CSR3, 0x00858687 },
221 { RT2573_TXRX_CSR7, 0x2e31353b },
222 { RT2573_TXRX_CSR8, 0x2a2a2a2c },
223 { RT2573_TXRX_CSR15, 0x0000000f },
224 { RT2573_MAC_CSR6, 0x00000fff },
225 { RT2573_MAC_CSR8, 0x016c030a },
226 { RT2573_MAC_CSR10, 0x00000718 },
227 { RT2573_MAC_CSR12, 0x00000004 },
228 { RT2573_MAC_CSR13, 0x00007f00 },
229 { RT2573_SEC_CSR0, 0x00000000 },
230 { RT2573_SEC_CSR1, 0x00000000 },
231 { RT2573_SEC_CSR5, 0x00000000 },
232 { RT2573_PHY_CSR1, 0x000023b0 },
233 { RT2573_PHY_CSR5, 0x00040a06 },
234 { RT2573_PHY_CSR6, 0x00080606 },
235 { RT2573_PHY_CSR7, 0x00000408 },
236 { RT2573_AIFSN_CSR, 0x00002273 },
237 { RT2573_CWMIN_CSR, 0x00002344 },
238 { RT2573_CWMAX_CSR, 0x000034aa }
239 };
240
241 static const struct {
242 uint8_t reg;
243 uint8_t val;
244 } rum_def_bbp[] = {
245 { 3, 0x80 },
246 { 15, 0x30 },
247 { 17, 0x20 },
248 { 21, 0xc8 },
249 { 22, 0x38 },
250 { 23, 0x06 },
251 { 24, 0xfe },
252 { 25, 0x0a },
253 { 26, 0x0d },
254 { 32, 0x0b },
255 { 34, 0x12 },
256 { 37, 0x07 },
257 { 39, 0xf8 },
258 { 41, 0x60 },
259 { 53, 0x10 },
260 { 54, 0x18 },
261 { 60, 0x10 },
262 { 61, 0x04 },
263 { 62, 0x04 },
264 { 75, 0xfe },
265 { 86, 0xfe },
266 { 88, 0xfe },
267 { 90, 0x0f },
268 { 99, 0x00 },
269 { 102, 0x16 },
270 { 107, 0x04 }
271 };
272
273 static const struct rfprog {
274 uint8_t chan;
275 uint32_t r1, r2, r3, r4;
276 } rum_rf5226[] = {
277 { 1, 0x00b03, 0x001e1, 0x1a014, 0x30282 },
278 { 2, 0x00b03, 0x001e1, 0x1a014, 0x30287 },
279 { 3, 0x00b03, 0x001e2, 0x1a014, 0x30282 },
280 { 4, 0x00b03, 0x001e2, 0x1a014, 0x30287 },
281 { 5, 0x00b03, 0x001e3, 0x1a014, 0x30282 },
282 { 6, 0x00b03, 0x001e3, 0x1a014, 0x30287 },
283 { 7, 0x00b03, 0x001e4, 0x1a014, 0x30282 },
284 { 8, 0x00b03, 0x001e4, 0x1a014, 0x30287 },
285 { 9, 0x00b03, 0x001e5, 0x1a014, 0x30282 },
286 { 10, 0x00b03, 0x001e5, 0x1a014, 0x30287 },
287 { 11, 0x00b03, 0x001e6, 0x1a014, 0x30282 },
288 { 12, 0x00b03, 0x001e6, 0x1a014, 0x30287 },
289 { 13, 0x00b03, 0x001e7, 0x1a014, 0x30282 },
290 { 14, 0x00b03, 0x001e8, 0x1a014, 0x30284 },
291
292 { 34, 0x00b03, 0x20266, 0x36014, 0x30282 },
293 { 38, 0x00b03, 0x20267, 0x36014, 0x30284 },
294 { 42, 0x00b03, 0x20268, 0x36014, 0x30286 },
295 { 46, 0x00b03, 0x20269, 0x36014, 0x30288 },
296
297 { 36, 0x00b03, 0x00266, 0x26014, 0x30288 },
298 { 40, 0x00b03, 0x00268, 0x26014, 0x30280 },
299 { 44, 0x00b03, 0x00269, 0x26014, 0x30282 },
300 { 48, 0x00b03, 0x0026a, 0x26014, 0x30284 },
301 { 52, 0x00b03, 0x0026b, 0x26014, 0x30286 },
302 { 56, 0x00b03, 0x0026c, 0x26014, 0x30288 },
303 { 60, 0x00b03, 0x0026e, 0x26014, 0x30280 },
304 { 64, 0x00b03, 0x0026f, 0x26014, 0x30282 },
305
306 { 100, 0x00b03, 0x0028a, 0x2e014, 0x30280 },
307 { 104, 0x00b03, 0x0028b, 0x2e014, 0x30282 },
308 { 108, 0x00b03, 0x0028c, 0x2e014, 0x30284 },
309 { 112, 0x00b03, 0x0028d, 0x2e014, 0x30286 },
310 { 116, 0x00b03, 0x0028e, 0x2e014, 0x30288 },
311 { 120, 0x00b03, 0x002a0, 0x2e014, 0x30280 },
312 { 124, 0x00b03, 0x002a1, 0x2e014, 0x30282 },
313 { 128, 0x00b03, 0x002a2, 0x2e014, 0x30284 },
314 { 132, 0x00b03, 0x002a3, 0x2e014, 0x30286 },
315 { 136, 0x00b03, 0x002a4, 0x2e014, 0x30288 },
316 { 140, 0x00b03, 0x002a6, 0x2e014, 0x30280 },
317
318 { 149, 0x00b03, 0x002a8, 0x2e014, 0x30287 },
319 { 153, 0x00b03, 0x002a9, 0x2e014, 0x30289 },
320 { 157, 0x00b03, 0x002ab, 0x2e014, 0x30281 },
321 { 161, 0x00b03, 0x002ac, 0x2e014, 0x30283 },
322 { 165, 0x00b03, 0x002ad, 0x2e014, 0x30285 }
323 }, rum_rf5225[] = {
324 { 1, 0x00b33, 0x011e1, 0x1a014, 0x30282 },
325 { 2, 0x00b33, 0x011e1, 0x1a014, 0x30287 },
326 { 3, 0x00b33, 0x011e2, 0x1a014, 0x30282 },
327 { 4, 0x00b33, 0x011e2, 0x1a014, 0x30287 },
328 { 5, 0x00b33, 0x011e3, 0x1a014, 0x30282 },
329 { 6, 0x00b33, 0x011e3, 0x1a014, 0x30287 },
330 { 7, 0x00b33, 0x011e4, 0x1a014, 0x30282 },
331 { 8, 0x00b33, 0x011e4, 0x1a014, 0x30287 },
332 { 9, 0x00b33, 0x011e5, 0x1a014, 0x30282 },
333 { 10, 0x00b33, 0x011e5, 0x1a014, 0x30287 },
334 { 11, 0x00b33, 0x011e6, 0x1a014, 0x30282 },
335 { 12, 0x00b33, 0x011e6, 0x1a014, 0x30287 },
336 { 13, 0x00b33, 0x011e7, 0x1a014, 0x30282 },
337 { 14, 0x00b33, 0x011e8, 0x1a014, 0x30284 },
338
339 { 34, 0x00b33, 0x01266, 0x26014, 0x30282 },
340 { 38, 0x00b33, 0x01267, 0x26014, 0x30284 },
341 { 42, 0x00b33, 0x01268, 0x26014, 0x30286 },
342 { 46, 0x00b33, 0x01269, 0x26014, 0x30288 },
343
344 { 36, 0x00b33, 0x01266, 0x26014, 0x30288 },
345 { 40, 0x00b33, 0x01268, 0x26014, 0x30280 },
346 { 44, 0x00b33, 0x01269, 0x26014, 0x30282 },
347 { 48, 0x00b33, 0x0126a, 0x26014, 0x30284 },
348 { 52, 0x00b33, 0x0126b, 0x26014, 0x30286 },
349 { 56, 0x00b33, 0x0126c, 0x26014, 0x30288 },
350 { 60, 0x00b33, 0x0126e, 0x26014, 0x30280 },
351 { 64, 0x00b33, 0x0126f, 0x26014, 0x30282 },
352
353 { 100, 0x00b33, 0x0128a, 0x2e014, 0x30280 },
354 { 104, 0x00b33, 0x0128b, 0x2e014, 0x30282 },
355 { 108, 0x00b33, 0x0128c, 0x2e014, 0x30284 },
356 { 112, 0x00b33, 0x0128d, 0x2e014, 0x30286 },
357 { 116, 0x00b33, 0x0128e, 0x2e014, 0x30288 },
358 { 120, 0x00b33, 0x012a0, 0x2e014, 0x30280 },
359 { 124, 0x00b33, 0x012a1, 0x2e014, 0x30282 },
360 { 128, 0x00b33, 0x012a2, 0x2e014, 0x30284 },
361 { 132, 0x00b33, 0x012a3, 0x2e014, 0x30286 },
362 { 136, 0x00b33, 0x012a4, 0x2e014, 0x30288 },
363 { 140, 0x00b33, 0x012a6, 0x2e014, 0x30280 },
364
365 { 149, 0x00b33, 0x012a8, 0x2e014, 0x30287 },
366 { 153, 0x00b33, 0x012a9, 0x2e014, 0x30289 },
367 { 157, 0x00b33, 0x012ab, 0x2e014, 0x30281 },
368 { 161, 0x00b33, 0x012ac, 0x2e014, 0x30283 },
369 { 165, 0x00b33, 0x012ad, 0x2e014, 0x30285 }
370 };
371
372 static int
373 rum_match(device_t self)
374 {
375 struct usb_attach_arg *uaa = device_get_ivars(self);
376
377 if (uaa->iface != NULL)
378 return UMATCH_NONE;
379
380 return (usb_lookup(rum_devs, uaa->vendor, uaa->product) != NULL) ?
381 UMATCH_VENDOR_PRODUCT : UMATCH_NONE;
382 }
383
384 static int
385 rum_attach(device_t self)
386 {
387 struct rum_softc *sc = device_get_softc(self);
388 struct usb_attach_arg *uaa = device_get_ivars(self);
389 struct ieee80211com *ic;
390 struct ifnet *ifp;
391 const uint8_t *ucode = NULL;
392 usb_interface_descriptor_t *id;
393 usb_endpoint_descriptor_t *ed;
394 usbd_status error;
395 int i, ntries, size;
396 uint8_t bands;
397 uint32_t tmp;
398
399 sc->sc_udev = uaa->device;
400 sc->sc_dev = self;
401
402 if (usbd_set_config_no(sc->sc_udev, RT2573_CONFIG_NO, 0) != 0) {
403 device_printf(self, "could not set configuration no\n");
404 return ENXIO;
405 }
406
407 /* get the first interface handle */
408 error = usbd_device2interface_handle(sc->sc_udev, RT2573_IFACE_INDEX,
409 &sc->sc_iface);
410 if (error != 0) {
411 device_printf(self, "could not get interface handle\n");
412 return ENXIO;
413 }
414
415 /*
416 * Find endpoints.
417 */
418 id = usbd_get_interface_descriptor(sc->sc_iface);
419
420 sc->sc_rx_no = sc->sc_tx_no = -1;
421 for (i = 0; i < id->bNumEndpoints; i++) {
422 ed = usbd_interface2endpoint_descriptor(sc->sc_iface, i);
423 if (ed == NULL) {
424 device_printf(self,
425 "no endpoint descriptor for iface %d\n", i);
426 return ENXIO;
427 }
428
429 if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN &&
430 UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK)
431 sc->sc_rx_no = ed->bEndpointAddress;
432 else if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_OUT &&
433 UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK)
434 sc->sc_tx_no = ed->bEndpointAddress;
435 }
436 if (sc->sc_rx_no == -1 || sc->sc_tx_no == -1) {
437 device_printf(self, "missing endpoint\n");
438 return ENXIO;
439 }
440
441 ifp = sc->sc_ifp = if_alloc(IFT_IEEE80211);
442 if (ifp == NULL) {
443 device_printf(self, "can not if_alloc()\n");
444 return ENXIO;
445 }
446 ic = ifp->if_l2com;
447
448 mtx_init(&sc->sc_mtx, device_get_nameunit(sc->sc_dev), MTX_NETWORK_LOCK,
449 MTX_DEF | MTX_RECURSE);
450
451 usb_init_task(&sc->sc_task, rum_task, sc);
452 usb_init_task(&sc->sc_scantask, rum_scantask, sc);
453 callout_init(&sc->watchdog_ch, 0);
454
455 /* retrieve RT2573 rev. no */
456 for (ntries = 0; ntries < 1000; ntries++) {
457 if ((tmp = rum_read(sc, RT2573_MAC_CSR0)) != 0)
458 break;
459 DELAY(1000);
460 }
461 if (ntries == 1000) {
462 device_printf(self, "timeout waiting for chip to settle\n");
463 goto bad;
464 }
465
466 /* retrieve MAC address and various other things from EEPROM */
467 rum_read_eeprom(sc);
468
469 device_printf(self, "MAC/BBP RT2573 (rev 0x%05x), RF %s\n",
470 tmp, rum_get_rf(sc->rf_rev));
471
472 ucode = rt2573_ucode;
473 size = sizeof rt2573_ucode;
474 error = rum_load_microcode(sc, ucode, size);
475 if (error != 0) {
476 device_printf(self, "could not load 8051 microcode\n");
477 goto bad;
478 }
479
480 ifp->if_softc = sc;
481 if_initname(ifp, "rum", device_get_unit(sc->sc_dev));
482 ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST |
483 IFF_NEEDSGIANT; /* USB stack is still under Giant lock */
484 ifp->if_init = rum_init;
485 ifp->if_ioctl = rum_ioctl;
486 ifp->if_start = rum_start;
487 IFQ_SET_MAXLEN(&ifp->if_snd, IFQ_MAXLEN);
488 ifp->if_snd.ifq_drv_maxlen = IFQ_MAXLEN;
489 IFQ_SET_READY(&ifp->if_snd);
490
491 ic->ic_ifp = ifp;
492 ic->ic_phytype = IEEE80211_T_OFDM; /* not only, but not used */
493
494 /* set device capabilities */
495 ic->ic_caps =
496 IEEE80211_C_STA /* station mode supported */
497 | IEEE80211_C_IBSS /* IBSS mode supported */
498 | IEEE80211_C_MONITOR /* monitor mode supported */
499 | IEEE80211_C_HOSTAP /* HostAp mode supported */
500 | IEEE80211_C_TXPMGT /* tx power management */
501 | IEEE80211_C_SHPREAMBLE /* short preamble supported */
502 | IEEE80211_C_SHSLOT /* short slot time supported */
503 | IEEE80211_C_BGSCAN /* bg scanning supported */
504 | IEEE80211_C_WPA /* 802.11i */
505 ;
506
507 bands = 0;
508 setbit(&bands, IEEE80211_MODE_11B);
509 setbit(&bands, IEEE80211_MODE_11G);
510 if (sc->rf_rev == RT2573_RF_5225 || sc->rf_rev == RT2573_RF_5226)
511 setbit(&bands, IEEE80211_MODE_11A);
512 ieee80211_init_channels(ic, NULL, &bands);
513
514 ieee80211_ifattach(ic);
515 ic->ic_newassoc = rum_newassoc;
516 ic->ic_raw_xmit = rum_raw_xmit;
517 ic->ic_node_alloc = rum_node_alloc;
518 ic->ic_scan_start = rum_scan_start;
519 ic->ic_scan_end = rum_scan_end;
520 ic->ic_set_channel = rum_set_channel;
521
522 ic->ic_vap_create = rum_vap_create;
523 ic->ic_vap_delete = rum_vap_delete;
524
525 sc->sc_rates = ieee80211_get_ratetable(ic->ic_curchan);
526
527 bpfattach(ifp, DLT_IEEE802_11_RADIO,
528 sizeof (struct ieee80211_frame) + sizeof(sc->sc_txtap));
529
530 sc->sc_rxtap_len = sizeof sc->sc_rxtap;
531 sc->sc_rxtap.wr_ihdr.it_len = htole16(sc->sc_rxtap_len);
532 sc->sc_rxtap.wr_ihdr.it_present = htole32(RT2573_RX_RADIOTAP_PRESENT);
533
534 sc->sc_txtap_len = sizeof sc->sc_txtap;
535 sc->sc_txtap.wt_ihdr.it_len = htole16(sc->sc_txtap_len);
536 sc->sc_txtap.wt_ihdr.it_present = htole32(RT2573_TX_RADIOTAP_PRESENT);
537
538 if (bootverbose)
539 ieee80211_announce(ic);
540
541 return 0;
542 bad:
543 mtx_destroy(&sc->sc_mtx);
544 if_free(ifp);
545 return ENXIO;
546 }
547
548 static int
549 rum_detach(device_t self)
550 {
551 struct rum_softc *sc = device_get_softc(self);
552 struct ifnet *ifp = sc->sc_ifp;
553 struct ieee80211com *ic = ifp->if_l2com;
554
555 rum_stop(sc);
556 bpfdetach(ifp);
557 ieee80211_ifdetach(ic);
558
559 usb_rem_task(sc->sc_udev, &sc->sc_task);
560 usb_rem_task(sc->sc_udev, &sc->sc_scantask);
561 callout_stop(&sc->watchdog_ch);
562
563 if (sc->amrr_xfer != NULL) {
564 usbd_free_xfer(sc->amrr_xfer);
565 sc->amrr_xfer = NULL;
566 }
567
568 if (sc->sc_rx_pipeh != NULL) {
569 usbd_abort_pipe(sc->sc_rx_pipeh);
570 usbd_close_pipe(sc->sc_rx_pipeh);
571 }
572 if (sc->sc_tx_pipeh != NULL) {
573 usbd_abort_pipe(sc->sc_tx_pipeh);
574 usbd_close_pipe(sc->sc_tx_pipeh);
575 }
576
577 rum_free_rx_list(sc);
578 rum_free_tx_list(sc);
579
580 if_free(ifp);
581 mtx_destroy(&sc->sc_mtx);
582
583 return 0;
584 }
585
586 static struct ieee80211vap *
587 rum_vap_create(struct ieee80211com *ic,
588 const char name[IFNAMSIZ], int unit, int opmode, int flags,
589 const uint8_t bssid[IEEE80211_ADDR_LEN],
590 const uint8_t mac[IEEE80211_ADDR_LEN])
591 {
592 struct rum_vap *rvp;
593 struct ieee80211vap *vap;
594
595 if (!TAILQ_EMPTY(&ic->ic_vaps)) /* only one at a time */
596 return NULL;
597 rvp = (struct rum_vap *) malloc(sizeof(struct rum_vap),
598 M_80211_VAP, M_NOWAIT | M_ZERO);
599 if (rvp == NULL)
600 return NULL;
601 vap = &rvp->vap;
602 /* enable s/w bmiss handling for sta mode */
603 ieee80211_vap_setup(ic, vap, name, unit, opmode,
604 flags | IEEE80211_CLONE_NOBEACONS, bssid, mac);
605
606 /* override state transition machine */
607 rvp->newstate = vap->iv_newstate;
608 vap->iv_newstate = rum_newstate;
609
610 callout_init(&rvp->amrr_ch, 0);
611 ieee80211_amrr_init(&rvp->amrr, vap,
612 IEEE80211_AMRR_MIN_SUCCESS_THRESHOLD,
613 IEEE80211_AMRR_MAX_SUCCESS_THRESHOLD,
614 1000 /* 1 sec */);
615
616 /* complete setup */
617 ieee80211_vap_attach(vap, ieee80211_media_change, ieee80211_media_status);
618 ic->ic_opmode = opmode;
619 return vap;
620 }
621
622 static void
623 rum_vap_delete(struct ieee80211vap *vap)
624 {
625 struct rum_vap *rvp = RUM_VAP(vap);
626
627 callout_stop(&rvp->amrr_ch);
628 ieee80211_amrr_cleanup(&rvp->amrr);
629 ieee80211_vap_detach(vap);
630 free(rvp, M_80211_VAP);
631 }
632
633 static int
634 rum_alloc_tx_list(struct rum_softc *sc)
635 {
636 struct rum_tx_data *data;
637 int i, error;
638
639 sc->tx_queued = sc->tx_cur = 0;
640
641 for (i = 0; i < RUM_TX_LIST_COUNT; i++) {
642 data = &sc->tx_data[i];
643
644 data->sc = sc;
645
646 data->xfer = usbd_alloc_xfer(sc->sc_udev);
647 if (data->xfer == NULL) {
648 device_printf(sc->sc_dev,
649 "could not allocate tx xfer\n");
650 error = ENOMEM;
651 goto fail;
652 }
653 data->buf = usbd_alloc_buffer(data->xfer,
654 RT2573_TX_DESC_SIZE + MCLBYTES);
655 if (data->buf == NULL) {
656 device_printf(sc->sc_dev,
657 "could not allocate tx buffer\n");
658 error = ENOMEM;
659 goto fail;
660 }
661 /* clean Tx descriptor */
662 bzero(data->buf, RT2573_TX_DESC_SIZE);
663 }
664
665 return 0;
666
667 fail: rum_free_tx_list(sc);
668 return error;
669 }
670
671 static void
672 rum_free_tx_list(struct rum_softc *sc)
673 {
674 struct rum_tx_data *data;
675 int i;
676
677 for (i = 0; i < RUM_TX_LIST_COUNT; i++) {
678 data = &sc->tx_data[i];
679
680 if (data->xfer != NULL) {
681 usbd_free_xfer(data->xfer);
682 data->xfer = NULL;
683 }
684
685 if (data->ni != NULL) {
686 ieee80211_free_node(data->ni);
687 data->ni = NULL;
688 }
689 }
690 }
691
692 static int
693 rum_alloc_rx_list(struct rum_softc *sc)
694 {
695 struct rum_rx_data *data;
696 int i, error;
697
698 for (i = 0; i < RUM_RX_LIST_COUNT; i++) {
699 data = &sc->rx_data[i];
700
701 data->sc = sc;
702
703 data->xfer = usbd_alloc_xfer(sc->sc_udev);
704 if (data->xfer == NULL) {
705 device_printf(sc->sc_dev,
706 "could not allocate rx xfer\n");
707 error = ENOMEM;
708 goto fail;
709 }
710 if (usbd_alloc_buffer(data->xfer, MCLBYTES) == NULL) {
711 device_printf(sc->sc_dev,
712 "could not allocate rx buffer\n");
713 error = ENOMEM;
714 goto fail;
715 }
716
717 data->m = m_getcl(M_DONTWAIT, MT_DATA, M_PKTHDR);
718 if (data->m == NULL) {
719 device_printf(sc->sc_dev,
720 "could not allocate rx mbuf\n");
721 error = ENOMEM;
722 goto fail;
723 }
724
725 data->buf = mtod(data->m, uint8_t *);
726 }
727
728 return 0;
729
730 fail: rum_free_rx_list(sc);
731 return error;
732 }
733
734 static void
735 rum_free_rx_list(struct rum_softc *sc)
736 {
737 struct rum_rx_data *data;
738 int i;
739
740 for (i = 0; i < RUM_RX_LIST_COUNT; i++) {
741 data = &sc->rx_data[i];
742
743 if (data->xfer != NULL) {
744 usbd_free_xfer(data->xfer);
745 data->xfer = NULL;
746 }
747 if (data->m != NULL) {
748 m_freem(data->m);
749 data->m = NULL;
750 }
751 }
752 }
753
754 static void
755 rum_task(void *arg)
756 {
757 struct rum_softc *sc = arg;
758 struct ifnet *ifp = sc->sc_ifp;
759 struct ieee80211com *ic = ifp->if_l2com;
760 struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
761 struct rum_vap *rvp = RUM_VAP(vap);
762 const struct ieee80211_txparam *tp;
763 enum ieee80211_state ostate;
764 struct ieee80211_node *ni;
765 uint32_t tmp;
766
767 ostate = vap->iv_state;
768
769 RUM_LOCK(sc);
770
771 switch (sc->sc_state) {
772 case IEEE80211_S_INIT:
773 if (ostate == IEEE80211_S_RUN) {
774 /* abort TSF synchronization */
775 tmp = rum_read(sc, RT2573_TXRX_CSR9);
776 rum_write(sc, RT2573_TXRX_CSR9, tmp & ~0x00ffffff);
777 }
778 break;
779
780 case IEEE80211_S_RUN:
781 ni = vap->iv_bss;
782
783 if (vap->iv_opmode != IEEE80211_M_MONITOR) {
784 rum_update_slot(ic->ic_ifp);
785 rum_enable_mrr(sc);
786 rum_set_txpreamble(sc);
787 rum_set_basicrates(sc);
788 rum_set_bssid(sc, ni->ni_bssid);
789 }
790
791 if (vap->iv_opmode == IEEE80211_M_HOSTAP ||
792 vap->iv_opmode == IEEE80211_M_IBSS)
793 rum_prepare_beacon(sc, vap);
794
795 if (vap->iv_opmode != IEEE80211_M_MONITOR)
796 rum_enable_tsf_sync(sc);
797
798 /* enable automatic rate adaptation */
799 tp = &vap->iv_txparms[ieee80211_chan2mode(ic->ic_bsschan)];
800 if (tp->ucastrate == IEEE80211_FIXED_RATE_NONE)
801 rum_amrr_start(sc, ni);
802 break;
803 default:
804 break;
805 }
806
807 RUM_UNLOCK(sc);
808
809 IEEE80211_LOCK(ic);
810 rvp->newstate(vap, sc->sc_state, sc->sc_arg);
811 if (vap->iv_newstate_cb != NULL)
812 vap->iv_newstate_cb(vap, sc->sc_state, sc->sc_arg);
813 IEEE80211_UNLOCK(ic);
814 }
815
816 static int
817 rum_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg)
818 {
819 struct rum_vap *rvp = RUM_VAP(vap);
820 struct ieee80211com *ic = vap->iv_ic;
821 struct rum_softc *sc = ic->ic_ifp->if_softc;
822
823 usb_rem_task(sc->sc_udev, &sc->sc_task);
824 usb_rem_task(sc->sc_udev, &sc->sc_scantask);
825 callout_stop(&rvp->amrr_ch);
826
827 /* do it in a process context */
828 sc->sc_state = nstate;
829 sc->sc_arg = arg;
830
831 if (nstate == IEEE80211_S_INIT) {
832 rvp->newstate(vap, nstate, arg);
833 return 0;
834 } else {
835 usb_add_task(sc->sc_udev, &sc->sc_task, USB_TASKQ_DRIVER);
836 return EINPROGRESS;
837 }
838 }
|