[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ]

FreeBSD/Linux Kernel Cross Reference
sys/dev/usb/if_rum.c

Version: -  FREEBSD  -  FREEBSD7  -  FREEBSD70  -  FREEBSD6  -  FREEBSD64  -  FREEBSD63  -  FREEBSD62  -  FREEBSD61  -  FREEBSD60  -  FREEBSD5  -  FREEBSD55  -  FREEBSD54  -  FREEBSD53  -  FREEBSD52  -  FREEBSD51  -  FREEBSD50  -  FREEBSD4  -  FREEBSD3  -  FREEBSD22  -  linux-2.6  -  linux-2.4.22  -  MK83  -  MK84  -  PLAN9  -  DFBSD  -  NETBSD  -  NETBSD5  -  NETBSD4  -  NETBSD3  -  NETBSD20  -  OPENBSD  -  xnu-517  -  xnu-792  -  xnu-792.6.70  -  xnu-1228  -  OPENSOLARIS  -  minix-3-1-1  -  TRUSTEDBSD-SEBSD  -  FREEBSD-LIBC  -  FREEBSD7-LIBC  -  FREEBSD6-LIBC  -  GLIBC27 
SearchContext: -  none  -  excerpts  -  bigexcerpts 

  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 }