svn commit: r187756 - user/thompsa/usb/sys/dev/usb2/wlan
Andrew Thompson
thompsa at FreeBSD.org
Mon Jan 26 17:32:13 PST 2009
Author: thompsa
Date: Tue Jan 27 01:32:13 2009
New Revision: 187756
URL: http://svn.freebsd.org/changeset/base/187756
Log:
Convert over to the USB2 API.
Modified:
user/thompsa/usb/sys/dev/usb2/wlan/if_rum2.c
user/thompsa/usb/sys/dev/usb2/wlan/if_rumvar.h
user/thompsa/usb/sys/dev/usb2/wlan/if_ural2.c
user/thompsa/usb/sys/dev/usb2/wlan/if_uralreg.h
user/thompsa/usb/sys/dev/usb2/wlan/if_uralvar.h
user/thompsa/usb/sys/dev/usb2/wlan/if_zyd2.c
user/thompsa/usb/sys/dev/usb2/wlan/if_zydreg.h
Modified: user/thompsa/usb/sys/dev/usb2/wlan/if_rum2.c
==============================================================================
--- user/thompsa/usb/sys/dev/usb2/wlan/if_rum2.c Tue Jan 27 01:31:52 2009 (r187755)
+++ user/thompsa/usb/sys/dev/usb2/wlan/if_rum2.c Tue Jan 27 01:32:13 2009 (r187756)
@@ -3,6 +3,7 @@
/*-
* Copyright (c) 2005-2007 Damien Bergamini <damien.bergamini at free.fr>
* Copyright (c) 2006 Niall O'Higgins <niallo at openbsd.org>
+ * Copyright (c) 2007-2008 Hans Petter Selasky <hselasky at freebsd.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@@ -25,129 +26,113 @@ __FBSDID("$FreeBSD$");
* http://www.ralinktech.com.tw/
*/
-#include <sys/param.h>
-#include <sys/sysctl.h>
-#include <sys/sockio.h>
-#include <sys/mbuf.h>
-#include <sys/kernel.h>
-#include <sys/socket.h>
-#include <sys/systm.h>
-#include <sys/malloc.h>
-#include <sys/module.h>
-#include <sys/bus.h>
-#include <sys/endian.h>
-
-#include <machine/bus.h>
-#include <machine/resource.h>
-#include <sys/rman.h>
-
-#include <net/bpf.h>
-#include <net/if.h>
-#include <net/if_arp.h>
-#include <net/ethernet.h>
-#include <net/if_dl.h>
-#include <net/if_media.h>
-#include <net/if_types.h>
-
-#include <net80211/ieee80211_var.h>
-#include <net80211/ieee80211_amrr.h>
-#include <net80211/ieee80211_phy.h>
-#include <net80211/ieee80211_radiotap.h>
-#include <net80211/ieee80211_regdomain.h>
-
-#include <dev/usb/usb.h>
-#include <dev/usb/usbdi.h>
-#include <dev/usb/usbdi_util.h>
-#include "usbdevs.h"
-
-#include <dev/usb/if_rumreg.h>
-#include <dev/usb/if_rumvar.h>
-#include <dev/usb/rt2573_ucode.h>
-
-#ifdef USB_DEBUG
-#define DPRINTF(x) do { if (rumdebug > 0) printf x; } while (0)
-#define DPRINTFN(n, x) do { if (rumdebug >= (n)) printf x; } while (0)
-int rumdebug = 0;
-SYSCTL_NODE(_hw_usb, OID_AUTO, rum, CTLFLAG_RW, 0, "USB rum");
-SYSCTL_INT(_hw_usb_rum, OID_AUTO, debug, CTLFLAG_RW, &rumdebug, 0,
- "rum debug level");
-#else
-#define DPRINTF(x)
-#define DPRINTFN(n, x)
+#include <dev/usb2/include/usb2_devid.h>
+#include <dev/usb2/include/usb2_standard.h>
+#include <dev/usb2/include/usb2_mfunc.h>
+#include <dev/usb2/include/usb2_error.h>
+
+#define USB_DEBUG_VAR rum_debug
+
+#include <dev/usb2/core/usb2_core.h>
+#include <dev/usb2/core/usb2_lookup.h>
+#include <dev/usb2/core/usb2_process.h>
+#include <dev/usb2/core/usb2_debug.h>
+#include <dev/usb2/core/usb2_request.h>
+#include <dev/usb2/core/usb2_busdma.h>
+#include <dev/usb2/core/usb2_util.h>
+
+#include <dev/usb2/wlan/usb2_wlan.h>
+#include <dev/usb2/wlan/if_rumreg.h>
+#include <dev/usb2/wlan/if_rumvar.h>
+#include <dev/usb2/wlan/if_rumfw.h>
+
+#if USB_DEBUG
+static int rum_debug = 0;
+
+SYSCTL_NODE(_hw_usb2, OID_AUTO, rum, CTLFLAG_RW, 0, "USB rum");
+SYSCTL_INT(_hw_usb2_rum, OID_AUTO, debug, CTLFLAG_RW, &rum_debug, 0,
+ "Debug level");
#endif
-/* various supported device vendors/products */
-static const struct usb_devno rum_devs[] = {
- { USB_VENDOR_ABOCOM, USB_PRODUCT_ABOCOM_HWU54DM },
- { USB_VENDOR_ABOCOM, USB_PRODUCT_ABOCOM_RT2573_2 },
- { USB_VENDOR_ABOCOM, USB_PRODUCT_ABOCOM_RT2573_3 },
- { USB_VENDOR_ABOCOM, USB_PRODUCT_ABOCOM_RT2573_4 },
- { USB_VENDOR_ABOCOM, USB_PRODUCT_ABOCOM_WUG2700 },
- { USB_VENDOR_AMIT, USB_PRODUCT_AMIT_CGWLUSB2GO },
- { USB_VENDOR_ASUS, USB_PRODUCT_ASUS_RT2573_1 },
- { USB_VENDOR_ASUS, USB_PRODUCT_ASUS_RT2573_2 },
- { USB_VENDOR_BELKIN, USB_PRODUCT_BELKIN_F5D7050A },
- { USB_VENDOR_BELKIN, USB_PRODUCT_BELKIN_F5D9050V3 },
- { USB_VENDOR_CISCOLINKSYS, USB_PRODUCT_CISCOLINKSYS_WUSB54GC },
- { USB_VENDOR_CISCOLINKSYS, USB_PRODUCT_CISCOLINKSYS_WUSB54GR },
- { USB_VENDOR_CONCEPTRONIC2, USB_PRODUCT_CONCEPTRONIC2_C54RU2 },
- { USB_VENDOR_COREGA, USB_PRODUCT_COREGA_CGWLUSB2GL },
- { USB_VENDOR_COREGA, USB_PRODUCT_COREGA_CGWLUSB2GPX },
- { USB_VENDOR_DICKSMITH, USB_PRODUCT_DICKSMITH_CWD854F },
- { USB_VENDOR_DICKSMITH, USB_PRODUCT_DICKSMITH_RT2573 },
- { USB_VENDOR_DLINK2, USB_PRODUCT_DLINK2_DWLG122C1 },
- { USB_VENDOR_DLINK2, USB_PRODUCT_DLINK2_WUA1340 },
- { USB_VENDOR_DLINK2, USB_PRODUCT_DLINK2_DWA111 },
- { USB_VENDOR_DLINK2, USB_PRODUCT_DLINK2_DWA110 },
- { USB_VENDOR_GIGABYTE, USB_PRODUCT_GIGABYTE_GNWB01GS },
- { USB_VENDOR_GIGABYTE, USB_PRODUCT_GIGABYTE_GNWI05GS },
- { USB_VENDOR_GIGASET, USB_PRODUCT_GIGASET_RT2573 },
- { USB_VENDOR_GOODWAY, USB_PRODUCT_GOODWAY_RT2573 },
- { USB_VENDOR_GUILLEMOT, USB_PRODUCT_GUILLEMOT_HWGUSB254LB },
- { USB_VENDOR_GUILLEMOT, USB_PRODUCT_GUILLEMOT_HWGUSB254V2AP },
- { USB_VENDOR_HUAWEI3COM, USB_PRODUCT_HUAWEI3COM_WUB320G },
- { USB_VENDOR_MELCO, USB_PRODUCT_MELCO_G54HP },
- { USB_VENDOR_MELCO, USB_PRODUCT_MELCO_SG54HP },
- { USB_VENDOR_MSI, USB_PRODUCT_MSI_RT2573_1 },
- { USB_VENDOR_MSI, USB_PRODUCT_MSI_RT2573_2 },
- { USB_VENDOR_MSI, USB_PRODUCT_MSI_RT2573_3 },
- { USB_VENDOR_MSI, USB_PRODUCT_MSI_RT2573_4 },
- { USB_VENDOR_NOVATECH, USB_PRODUCT_NOVATECH_RT2573 },
- { USB_VENDOR_PLANEX2, USB_PRODUCT_PLANEX2_GWUS54HP },
- { USB_VENDOR_PLANEX2, USB_PRODUCT_PLANEX2_GWUS54MINI2 },
- { USB_VENDOR_PLANEX2, USB_PRODUCT_PLANEX2_GWUSMM },
- { USB_VENDOR_QCOM, USB_PRODUCT_QCOM_RT2573 },
- { USB_VENDOR_QCOM, USB_PRODUCT_QCOM_RT2573_2 },
- { USB_VENDOR_RALINK, USB_PRODUCT_RALINK_RT2573 },
- { USB_VENDOR_RALINK, USB_PRODUCT_RALINK_RT2573_2 },
- { USB_VENDOR_RALINK, USB_PRODUCT_RALINK_RT2671 },
- { USB_VENDOR_SITECOMEU, USB_PRODUCT_SITECOMEU_WL113R2 },
- { USB_VENDOR_SITECOMEU, USB_PRODUCT_SITECOMEU_WL172 },
- { USB_VENDOR_SPARKLAN, USB_PRODUCT_SPARKLAN_RT2573 },
- { USB_VENDOR_SURECOM, USB_PRODUCT_SURECOM_RT2573 }
+static const struct usb2_device_id rum_devs[] = {
+ { USB_VP(USB_VENDOR_ABOCOM, USB_PRODUCT_ABOCOM_HWU54DM) },
+ { USB_VP(USB_VENDOR_ABOCOM, USB_PRODUCT_ABOCOM_RT2573_2) },
+ { USB_VP(USB_VENDOR_ABOCOM, USB_PRODUCT_ABOCOM_RT2573_3) },
+ { USB_VP(USB_VENDOR_ABOCOM, USB_PRODUCT_ABOCOM_RT2573_4) },
+ { USB_VP(USB_VENDOR_ABOCOM, USB_PRODUCT_ABOCOM_WUG2700) },
+ { USB_VP(USB_VENDOR_AMIT, USB_PRODUCT_AMIT_CGWLUSB2GO) },
+ { USB_VP(USB_VENDOR_ASUS, USB_PRODUCT_ASUS_RT2573_1) },
+ { USB_VP(USB_VENDOR_ASUS, USB_PRODUCT_ASUS_RT2573_2) },
+ { USB_VP(USB_VENDOR_BELKIN, USB_PRODUCT_BELKIN_F5D7050A) },
+ { USB_VP(USB_VENDOR_BELKIN, USB_PRODUCT_BELKIN_F5D9050V3) },
+ { USB_VP(USB_VENDOR_CISCOLINKSYS, USB_PRODUCT_CISCOLINKSYS_WUSB54GC) },
+ { USB_VP(USB_VENDOR_CISCOLINKSYS, USB_PRODUCT_CISCOLINKSYS_WUSB54GR) },
+ { USB_VP(USB_VENDOR_CONCEPTRONIC2, USB_PRODUCT_CONCEPTRONIC2_C54RU2) },
+ { USB_VP(USB_VENDOR_COREGA, USB_PRODUCT_COREGA_CGWLUSB2GL) },
+ { USB_VP(USB_VENDOR_COREGA, USB_PRODUCT_COREGA_CGWLUSB2GPX) },
+ { USB_VP(USB_VENDOR_DICKSMITH, USB_PRODUCT_DICKSMITH_CWD854F) },
+ { USB_VP(USB_VENDOR_DICKSMITH, USB_PRODUCT_DICKSMITH_RT2573) },
+ { USB_VP(USB_VENDOR_DLINK2, USB_PRODUCT_DLINK2_DWLG122C1) },
+ { USB_VP(USB_VENDOR_DLINK2, USB_PRODUCT_DLINK2_WUA1340) },
+ { USB_VP(USB_VENDOR_DLINK2, USB_PRODUCT_DLINK2_DWA111) },
+ { USB_VP(USB_VENDOR_DLINK2, USB_PRODUCT_DLINK2_DWA110) },
+ { USB_VP(USB_VENDOR_GIGABYTE, USB_PRODUCT_GIGABYTE_GNWB01GS) },
+ { USB_VP(USB_VENDOR_GIGABYTE, USB_PRODUCT_GIGABYTE_GNWI05GS) },
+ { USB_VP(USB_VENDOR_GIGASET, USB_PRODUCT_GIGASET_RT2573) },
+ { USB_VP(USB_VENDOR_GOODWAY, USB_PRODUCT_GOODWAY_RT2573) },
+ { USB_VP(USB_VENDOR_GUILLEMOT, USB_PRODUCT_GUILLEMOT_HWGUSB254LB) },
+ { USB_VP(USB_VENDOR_GUILLEMOT, USB_PRODUCT_GUILLEMOT_HWGUSB254V2AP) },
+ { USB_VP(USB_VENDOR_HUAWEI3COM, USB_PRODUCT_HUAWEI3COM_WUB320G) },
+ { USB_VP(USB_VENDOR_MELCO, USB_PRODUCT_MELCO_G54HP) },
+ { USB_VP(USB_VENDOR_MELCO, USB_PRODUCT_MELCO_SG54HP) },
+ { USB_VP(USB_VENDOR_MSI, USB_PRODUCT_MSI_RT2573_1) },
+ { USB_VP(USB_VENDOR_MSI, USB_PRODUCT_MSI_RT2573_2) },
+ { USB_VP(USB_VENDOR_MSI, USB_PRODUCT_MSI_RT2573_3) },
+ { USB_VP(USB_VENDOR_MSI, USB_PRODUCT_MSI_RT2573_4) },
+ { USB_VP(USB_VENDOR_NOVATECH, USB_PRODUCT_NOVATECH_RT2573) },
+ { USB_VP(USB_VENDOR_PLANEX2, USB_PRODUCT_PLANEX2_GWUS54HP) },
+ { USB_VP(USB_VENDOR_PLANEX2, USB_PRODUCT_PLANEX2_GWUS54MINI2) },
+ { USB_VP(USB_VENDOR_PLANEX2, USB_PRODUCT_PLANEX2_GWUSMM) },
+ { USB_VP(USB_VENDOR_QCOM, USB_PRODUCT_QCOM_RT2573) },
+ { USB_VP(USB_VENDOR_QCOM, USB_PRODUCT_QCOM_RT2573_2) },
+ { USB_VP(USB_VENDOR_RALINK, USB_PRODUCT_RALINK_RT2573) },
+ { USB_VP(USB_VENDOR_RALINK, USB_PRODUCT_RALINK_RT2573_2) },
+ { USB_VP(USB_VENDOR_RALINK, USB_PRODUCT_RALINK_RT2671) },
+ { USB_VP(USB_VENDOR_SITECOMEU, USB_PRODUCT_SITECOMEU_WL113R2) },
+ { USB_VP(USB_VENDOR_SITECOMEU, USB_PRODUCT_SITECOMEU_WL172) },
+ { USB_VP(USB_VENDOR_SPARKLAN, USB_PRODUCT_SPARKLAN_RT2573) },
+ { USB_VP(USB_VENDOR_SURECOM, USB_PRODUCT_SURECOM_RT2573) },
};
MODULE_DEPEND(rum, wlan, 1, 1, 1);
MODULE_DEPEND(rum, wlan_amrr, 1, 1, 1);
-MODULE_DEPEND(rum, usb, 1, 1, 1);
+MODULE_DEPEND(rum, usb2_wlan, 1, 1, 1);
+MODULE_DEPEND(rum, usb2_core, 1, 1, 1);
+
+static device_probe_t rum_match;
+static device_attach_t rum_attach;
+static device_detach_t rum_detach;
+
+static usb2_callback_t rum_bulk_read_callback;
+static usb2_callback_t rum_bulk_read_clear_stall_callback;
+static usb2_callback_t rum_bulk_write_callback;
+static usb2_callback_t rum_bulk_write_clear_stall_callback;
+
+static usb2_task_fn_t rum_task;
+static usb2_task_fn_t rum_scantask;
+static usb2_task_fn_t rum_promisctask;
+static usb2_task_fn_t rum_amrr_task;
static struct ieee80211vap *rum_vap_create(struct ieee80211com *,
const char name[IFNAMSIZ], int unit, int opmode,
int flags, const uint8_t bssid[IEEE80211_ADDR_LEN],
const uint8_t mac[IEEE80211_ADDR_LEN]);
static void rum_vap_delete(struct ieee80211vap *);
+static void rum_tx_free(struct rum_tx_data *, int);
static int rum_alloc_tx_list(struct rum_softc *);
static void rum_free_tx_list(struct rum_softc *);
-static int rum_alloc_rx_list(struct rum_softc *);
-static void rum_free_rx_list(struct rum_softc *);
-static void rum_task(void *);
-static void rum_scantask(void *);
static int rum_newstate(struct ieee80211vap *,
enum ieee80211_state, int);
-static void rum_txeof(usbd_xfer_handle, usbd_private_handle,
- usbd_status);
-static void rum_rxeof(usbd_xfer_handle, usbd_private_handle,
- usbd_status);
static void rum_setup_tx_desc(struct rum_softc *,
struct rum_tx_desc *, uint32_t, uint16_t, int,
int);
@@ -159,7 +144,6 @@ static int rum_tx_raw(struct rum_softc
static int rum_tx_data(struct rum_softc *, struct mbuf *,
struct ieee80211_node *);
static void rum_start(struct ifnet *);
-static void rum_watchdog(void *);
static int rum_ioctl(struct ifnet *, u_long, caddr_t);
static void rum_eeprom_read(struct rum_softc *, uint16_t, void *,
int);
@@ -184,7 +168,6 @@ static void rum_enable_tsf_sync(struct
static void rum_update_slot(struct ifnet *);
static void rum_set_bssid(struct rum_softc *, const uint8_t *);
static void rum_set_macaddr(struct rum_softc *, const uint8_t *);
-static void rum_update_promisc(struct rum_softc *);
static const char *rum_get_rf(int);
static void rum_read_eeprom(struct rum_softc *);
static int rum_bbp_init(struct rum_softc *);
@@ -207,8 +190,6 @@ static int rum_get_rssi(struct rum_soft
static void rum_amrr_start(struct rum_softc *,
struct ieee80211_node *);
static void rum_amrr_timeout(void *);
-static void rum_amrr_update(usbd_xfer_handle, usbd_private_handle,
- usbd_status);
static const struct {
uint32_t reg;
@@ -369,89 +350,110 @@ static const struct rfprog {
{ 165, 0x00b33, 0x012ad, 0x2e014, 0x30285 }
};
+static const struct usb2_config rum_config[RUM_N_TRANSFER] = {
+ [RUM_BULK_DT_WR] = {
+ .type = UE_BULK,
+ .endpoint = UE_ADDR_ANY,
+ .direction = UE_DIR_OUT,
+ .mh.bufsize = (MCLBYTES + RT2573_TX_DESC_SIZE + 8),
+ .mh.flags = {.pipe_bof = 1,.force_short_xfer = 1,},
+ .mh.callback = rum_bulk_write_callback,
+ .mh.timeout = 5000, /* ms */
+ },
+
+ [RUM_BULK_DT_RD] = {
+ .type = UE_BULK,
+ .endpoint = UE_ADDR_ANY,
+ .direction = UE_DIR_IN,
+ .mh.bufsize = (MCLBYTES + RT2573_RX_DESC_SIZE),
+ .mh.flags = {.pipe_bof = 1,.short_xfer_ok = 1,},
+ .mh.callback = rum_bulk_read_callback,
+ },
+
+ [RUM_BULK_CS_WR] = {
+ .type = UE_CONTROL,
+ .endpoint = 0x00, /* Control pipe */
+ .direction = UE_DIR_ANY,
+ .mh.bufsize = sizeof(struct usb2_device_request),
+ .mh.callback = rum_bulk_write_clear_stall_callback,
+ .mh.timeout = 1000, /* 1 second */
+ .mh.interval = 50, /* 50ms */
+ },
+
+ [RUM_BULK_CS_RD] = {
+ .type = UE_CONTROL,
+ .endpoint = 0x00, /* Control pipe */
+ .direction = UE_DIR_ANY,
+ .mh.bufsize = sizeof(struct usb2_device_request),
+ .mh.callback = rum_bulk_read_clear_stall_callback,
+ .mh.timeout = 1000, /* 1 second */
+ .mh.interval = 50, /* 50ms */
+ },
+};
+
static int
rum_match(device_t self)
{
- struct usb_attach_arg *uaa = device_get_ivars(self);
+ struct usb2_attach_arg *uaa = device_get_ivars(self);
- if (uaa->iface != NULL)
- return UMATCH_NONE;
+ if (uaa->usb2_mode != USB_MODE_HOST)
+ return (ENXIO);
+ if (uaa->info.bConfigIndex != 0)
+ return (ENXIO);
+ if (uaa->info.bIfaceIndex != RT2573_IFACE_INDEX)
+ return (ENXIO);
- return (usb_lookup(rum_devs, uaa->vendor, uaa->product) != NULL) ?
- UMATCH_VENDOR_PRODUCT : UMATCH_NONE;
+ return (usb2_lookup_id_by_uaa(rum_devs, sizeof(rum_devs), uaa));
}
static int
rum_attach(device_t self)
{
+ struct usb2_attach_arg *uaa = device_get_ivars(self);
struct rum_softc *sc = device_get_softc(self);
- struct usb_attach_arg *uaa = device_get_ivars(self);
struct ieee80211com *ic;
struct ifnet *ifp;
const uint8_t *ucode = NULL;
- usb_interface_descriptor_t *id;
- usb_endpoint_descriptor_t *ed;
- usbd_status error;
- int i, ntries, size;
- uint8_t bands;
+ uint8_t bands, iface_index;
uint32_t tmp;
+ int error, ntries, size;
+ if (sc == NULL)
+ return (ENOMEM);
+
+ device_set_usb2_desc(self);
sc->sc_udev = uaa->device;
sc->sc_dev = self;
- if (usbd_set_config_no(sc->sc_udev, RT2573_CONFIG_NO, 0) != 0) {
- device_printf(self, "could not set configuration no\n");
- return ENXIO;
- }
-
- /* get the first interface handle */
- error = usbd_device2interface_handle(sc->sc_udev, RT2573_IFACE_INDEX,
- &sc->sc_iface);
- if (error != 0) {
- device_printf(self, "could not get interface handle\n");
- return ENXIO;
- }
-
- /*
- * Find endpoints.
- */
- id = usbd_get_interface_descriptor(sc->sc_iface);
-
- sc->sc_rx_no = sc->sc_tx_no = -1;
- for (i = 0; i < id->bNumEndpoints; i++) {
- ed = usbd_interface2endpoint_descriptor(sc->sc_iface, i);
- if (ed == NULL) {
- device_printf(self,
- "no endpoint descriptor for iface %d\n", i);
- return ENXIO;
- }
-
- if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN &&
- UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK)
- sc->sc_rx_no = ed->bEndpointAddress;
- else if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_OUT &&
- UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK)
- sc->sc_tx_no = ed->bEndpointAddress;
- }
- if (sc->sc_rx_no == -1 || sc->sc_tx_no == -1) {
- device_printf(self, "missing endpoint\n");
- return ENXIO;
+ mtx_init(&sc->sc_mtx, device_get_nameunit(self),
+ MTX_NETWORK_LOCK, MTX_DEF);
+ USB_TASK_INIT(&sc->sc_task, rum_task, sc, NULL);
+ USB_TASK_INIT(&sc->sc_promisctask, rum_promisctask, sc, &sc->sc_mtx);
+ USB_TASK_INIT(&sc->sc_scantask, rum_scantask, sc, &sc->sc_mtx);
+
+ iface_index = RT2573_IFACE_INDEX;
+ error = usb2_transfer_setup(uaa->device, &iface_index,
+ sc->sc_xfer, rum_config, RUM_N_TRANSFER, sc, &sc->sc_mtx);
+ if (error) {
+ device_printf(self, "could not allocate USB transfers, "
+ "err=%s\n", usb2_errstr(error));
+ goto detach;
+ }
+ error = usb2_proc_create(&sc->sc_tq, USB_PRI_MED,
+ device_get_nameunit(self));
+ if (error) {
+ device_printf(self, "could not setup config thread!\n");
+ goto detach;
}
ifp = sc->sc_ifp = if_alloc(IFT_IEEE80211);
if (ifp == NULL) {
- device_printf(self, "can not if_alloc()\n");
- return ENXIO;
+ device_printf(sc->sc_dev, "can not if_alloc()\n");
+ goto detach;
}
ic = ifp->if_l2com;
- mtx_init(&sc->sc_mtx, device_get_nameunit(sc->sc_dev), MTX_NETWORK_LOCK,
- MTX_DEF | MTX_RECURSE);
-
- usb_init_task(&sc->sc_task, rum_task, sc);
- usb_init_task(&sc->sc_scantask, rum_scantask, sc);
- callout_init(&sc->watchdog_ch, 0);
-
+ RUM_LOCK(sc);
/* retrieve RT2573 rev. no */
for (ntries = 0; ntries < 1000; ntries++) {
if ((tmp = rum_read(sc, RT2573_MAC_CSR0)) != 0)
@@ -460,7 +462,8 @@ rum_attach(device_t self)
}
if (ntries == 1000) {
device_printf(self, "timeout waiting for chip to settle\n");
- goto bad;
+ RUM_UNLOCK(sc);
+ goto detach;
}
/* retrieve MAC address and various other things from EEPROM */
@@ -474,13 +477,14 @@ rum_attach(device_t self)
error = rum_load_microcode(sc, ucode, size);
if (error != 0) {
device_printf(self, "could not load 8051 microcode\n");
- goto bad;
+ RUM_UNLOCK(sc);
+ goto detach;
}
+ RUM_UNLOCK(sc);
ifp->if_softc = sc;
if_initname(ifp, "rum", device_get_unit(sc->sc_dev));
- ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST |
- IFF_NEEDSGIANT; /* USB stack is still under Giant lock */
+ ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
ifp->if_init = rum_init;
ifp->if_ioctl = rum_ioctl;
ifp->if_start = rum_start;
@@ -539,10 +543,9 @@ rum_attach(device_t self)
ieee80211_announce(ic);
return 0;
-bad:
- mtx_destroy(&sc->sc_mtx);
- if_free(ifp);
- return ENXIO;
+detach:
+ rum_detach(self);
+ return (ENXIO); /* failure */
}
static int
@@ -552,35 +555,23 @@ rum_detach(device_t self)
struct ifnet *ifp = sc->sc_ifp;
struct ieee80211com *ic = ifp->if_l2com;
+ RUM_LOCK(sc);
+ sc->sc_flags |= RUM_FLAG_DETACH;
rum_stop(sc);
- bpfdetach(ifp);
- ieee80211_ifdetach(ic);
-
- usb_rem_task(sc->sc_udev, &sc->sc_task);
- usb_rem_task(sc->sc_udev, &sc->sc_scantask);
- callout_stop(&sc->watchdog_ch);
-
- if (sc->amrr_xfer != NULL) {
- usbd_free_xfer(sc->amrr_xfer);
- sc->amrr_xfer = NULL;
- }
+ RUM_UNLOCK(sc);
- if (sc->sc_rx_pipeh != NULL) {
- usbd_abort_pipe(sc->sc_rx_pipeh);
- usbd_close_pipe(sc->sc_rx_pipeh);
- }
- if (sc->sc_tx_pipeh != NULL) {
- usbd_abort_pipe(sc->sc_tx_pipeh);
- usbd_close_pipe(sc->sc_tx_pipeh);
+ /* stop all USB transfers first */
+ usb2_transfer_unsetup(sc->sc_xfer, RUM_N_TRANSFER);
+ usb2_proc_free(&sc->sc_tq);
+
+ if (ifp) {
+ bpfdetach(ifp);
+ ieee80211_ifdetach(ic);
+ if_free(ifp);
}
-
- rum_free_rx_list(sc);
- rum_free_tx_list(sc);
-
- if_free(ifp);
mtx_destroy(&sc->sc_mtx);
- return 0;
+ return (0);
}
static struct ieee80211vap *
@@ -589,6 +580,7 @@ rum_vap_create(struct ieee80211com *ic,
const uint8_t bssid[IEEE80211_ADDR_LEN],
const uint8_t mac[IEEE80211_ADDR_LEN])
{
+ struct rum_softc *sc = ic->ic_ifp->if_softc;
struct rum_vap *rvp;
struct ieee80211vap *vap;
@@ -607,7 +599,9 @@ rum_vap_create(struct ieee80211com *ic,
rvp->newstate = vap->iv_newstate;
vap->iv_newstate = rum_newstate;
- callout_init(&rvp->amrr_ch, 0);
+ rvp->sc = sc;
+ usb2_callout_init_mtx(&rvp->amrr_ch, &sc->sc_mtx, 0);
+ USB_TASK_INIT(&rvp->amrr_task, rum_amrr_task, rvp, &sc->sc_mtx);
ieee80211_amrr_init(&rvp->amrr, vap,
IEEE80211_AMRR_MIN_SUCCESS_THRESHOLD,
IEEE80211_AMRR_MAX_SUCCESS_THRESHOLD,
@@ -623,49 +617,58 @@ static void
rum_vap_delete(struct ieee80211vap *vap)
{
struct rum_vap *rvp = RUM_VAP(vap);
+ struct rum_softc *sc = rvp->sc;
- callout_stop(&rvp->amrr_ch);
+ RUM_LOCK(sc);
+ usb2_callout_stop(&rvp->amrr_ch);
+ RUM_UNLOCK(sc);
ieee80211_amrr_cleanup(&rvp->amrr);
ieee80211_vap_detach(vap);
free(rvp, M_80211_VAP);
}
+static void
+rum_tx_free(struct rum_tx_data *data, int txerr)
+{
+ struct rum_softc *sc = data->sc;
+
+ if (data->m != NULL) {
+ if (data->m->m_flags & M_TXCB)
+ ieee80211_process_callback(data->ni, data->m,
+ txerr ? ETIMEDOUT : 0);
+ m_freem(data->m);
+ data->m = NULL;
+
+ ieee80211_free_node(data->ni);
+ data->ni = NULL;
+ }
+ STAILQ_INSERT_TAIL(&sc->tx_free, data, next);
+ sc->tx_nfree++;
+}
+
static int
rum_alloc_tx_list(struct rum_softc *sc)
{
struct rum_tx_data *data;
- int i, error;
+ int i;
- sc->tx_queued = sc->tx_cur = 0;
+ sc->tx_data = malloc(sizeof(struct rum_tx_data) * RUM_TX_LIST_COUNT,
+ M_USB, M_NOWAIT|M_ZERO);
+ if (sc->tx_data == NULL)
+ return (ENOMEM);
+
+ sc->tx_nfree = 0;
+ STAILQ_INIT(&sc->tx_q);
+ STAILQ_INIT(&sc->tx_free);
for (i = 0; i < RUM_TX_LIST_COUNT; i++) {
data = &sc->tx_data[i];
data->sc = sc;
-
- data->xfer = usbd_alloc_xfer(sc->sc_udev);
- if (data->xfer == NULL) {
- device_printf(sc->sc_dev,
- "could not allocate tx xfer\n");
- error = ENOMEM;
- goto fail;
- }
- data->buf = usbd_alloc_buffer(data->xfer,
- RT2573_TX_DESC_SIZE + MCLBYTES);
- if (data->buf == NULL) {
- device_printf(sc->sc_dev,
- "could not allocate tx buffer\n");
- error = ENOMEM;
- goto fail;
- }
- /* clean Tx descriptor */
- bzero(data->buf, RT2573_TX_DESC_SIZE);
+ STAILQ_INSERT_TAIL(&sc->tx_free, data, next);
+ sc->tx_nfree++;
}
-
return 0;
-
-fail: rum_free_tx_list(sc);
- return error;
}
static void
@@ -674,85 +677,27 @@ rum_free_tx_list(struct rum_softc *sc)
struct rum_tx_data *data;
int i;
+ if (sc->tx_data == NULL)
+ return;
+
for (i = 0; i < RUM_TX_LIST_COUNT; i++) {
data = &sc->tx_data[i];
- if (data->xfer != NULL) {
- usbd_free_xfer(data->xfer);
- data->xfer = NULL;
+ if (data->m != NULL) {
+ m_freem(data->m);
+ data->m = NULL;
}
-
if (data->ni != NULL) {
ieee80211_free_node(data->ni);
data->ni = NULL;
}
}
-}
-
-static int
-rum_alloc_rx_list(struct rum_softc *sc)
-{
- struct rum_rx_data *data;
- int i, error;
-
- for (i = 0; i < RUM_RX_LIST_COUNT; i++) {
- data = &sc->rx_data[i];
-
- data->sc = sc;
-
- data->xfer = usbd_alloc_xfer(sc->sc_udev);
- if (data->xfer == NULL) {
- device_printf(sc->sc_dev,
- "could not allocate rx xfer\n");
- error = ENOMEM;
- goto fail;
- }
- if (usbd_alloc_buffer(data->xfer, MCLBYTES) == NULL) {
- device_printf(sc->sc_dev,
- "could not allocate rx buffer\n");
- error = ENOMEM;
- goto fail;
- }
-
- data->m = m_getcl(M_DONTWAIT, MT_DATA, M_PKTHDR);
- if (data->m == NULL) {
- device_printf(sc->sc_dev,
- "could not allocate rx mbuf\n");
- error = ENOMEM;
- goto fail;
- }
-
- data->buf = mtod(data->m, uint8_t *);
- }
-
- return 0;
-
-fail: rum_free_rx_list(sc);
- return error;
+ free(sc->tx_data, M_USB);
+ sc->tx_data = NULL;
}
static void
-rum_free_rx_list(struct rum_softc *sc)
-{
- struct rum_rx_data *data;
- int i;
-
- for (i = 0; i < RUM_RX_LIST_COUNT; i++) {
- data = &sc->rx_data[i];
-
- if (data->xfer != NULL) {
- usbd_free_xfer(data->xfer);
- data->xfer = NULL;
- }
- if (data->m != NULL) {
- m_freem(data->m);
- data->m = NULL;
- }
- }
-}
-
-static void
-rum_task(void *arg)
+rum_task(void *arg, struct usb2_task *task)
{
struct rum_softc *sc = arg;
struct ifnet *ifp = sc->sc_ifp;
@@ -764,10 +709,12 @@ rum_task(void *arg)
struct ieee80211_node *ni;
uint32_t tmp;
+ if (sc->sc_flags & RUM_FLAG_DETACH)
+ return;
+
ostate = vap->iv_state;
RUM_LOCK(sc);
-
switch (sc->sc_state) {
case IEEE80211_S_INIT:
if (ostate == IEEE80211_S_RUN) {
@@ -803,7 +750,6 @@ rum_task(void *arg)
default:
break;
}
-
RUM_UNLOCK(sc);
IEEE80211_LOCK(ic);
@@ -820,152 +766,264 @@ rum_newstate(struct ieee80211vap *vap, e
struct ieee80211com *ic = vap->iv_ic;
struct rum_softc *sc = ic->ic_ifp->if_softc;
- usb_rem_task(sc->sc_udev, &sc->sc_task);
- usb_rem_task(sc->sc_udev, &sc->sc_scantask);
- callout_stop(&rvp->amrr_ch);
+ DPRINTF("%s -> %s\n",
+ ieee80211_state_name[vap->iv_state],
+ ieee80211_state_name[nstate]);
+
+ RUM_LOCK(sc);
+ usb2_callout_stop(&rvp->amrr_ch);
/* do it in a process context */
sc->sc_state = nstate;
sc->sc_arg = arg;
+ RUM_UNLOCK(sc);
if (nstate == IEEE80211_S_INIT) {
rvp->newstate(vap, nstate, arg);
return 0;
} else {
- usb_add_task(sc->sc_udev, &sc->sc_task, USB_TASKQ_DRIVER);
+ usb2_proc_enqueue(&sc->sc_tq, &sc->sc_task);
return EINPROGRESS;
}
}
static void
-rum_txeof(usbd_xfer_handle xfer, usbd_private_handle priv, usbd_status status)
+rum_bulk_write_callback(struct usb2_xfer *xfer)
{
- struct rum_tx_data *data = priv;
- struct rum_softc *sc = data->sc;
+ struct rum_softc *sc = xfer->priv_sc;
struct ifnet *ifp = sc->sc_ifp;
+ struct ieee80211com *ic = ifp->if_l2com;
+ struct ieee80211_channel *c = ic->ic_curchan;
+ struct rum_tx_data *data;
+ struct mbuf *m;
+ int len;
- if (data->m != NULL && data->m->m_flags & M_TXCB)
- ieee80211_process_callback(data->ni, data->m, 0/*XXX*/);
+ switch (USB_GET_STATE(xfer)) {
+ case USB_ST_TRANSFERRED:
+ DPRINTFN(11, "transfer complete, %d bytes\n", xfer->actlen);
+
+ /* free resources */
+ data = xfer->priv_fifo;
+ rum_tx_free(data, 0);
+ xfer->priv_fifo = NULL;
+
+ ifp->if_opackets++;
+ ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
+
+ /* FALLTHROUGH */
+ case USB_ST_SETUP:
+ if (sc->sc_flags & RUM_FLAG_WRITE_STALL) {
+ usb2_transfer_start(sc->sc_xfer[RUM_BULK_CS_WR]);
+ break;
+ }
+#if 0
+ if (sc->sc_flags & RUM_FLAG_WAIT_COMMAND) {
+ /*
+ * don't send anything while a command is pending !
+ */
+ break;
+ }
+#endif
- if (status != USBD_NORMAL_COMPLETION) {
- if (status == USBD_NOT_STARTED || status == USBD_CANCELLED)
- return;
+ data = STAILQ_FIRST(&sc->tx_q);
+ if (data) {
+ STAILQ_REMOVE_HEAD(&sc->tx_q, next);
+ m = data->m;
+
+ if (m->m_pkthdr.len > (MCLBYTES + RT2573_TX_DESC_SIZE)) {
+ DPRINTFN(0, "data overflow, %u bytes\n",
+ m->m_pkthdr.len);
+ m->m_pkthdr.len = (MCLBYTES + RT2573_TX_DESC_SIZE);
+ }
+ usb2_copy_in(xfer->frbuffers, 0, &data->desc,
+ RT2573_TX_DESC_SIZE);
+ usb2_m_copy_in(xfer->frbuffers, RT2573_TX_DESC_SIZE, m,
+ 0, m->m_pkthdr.len);
+
+ if (bpf_peers_present(ifp->if_bpf)) {
+ struct rum_tx_radiotap_header *tap = &sc->sc_txtap;
+
+ tap->wt_flags = 0;
+ tap->wt_rate = data->rate;
+ tap->wt_chan_freq = htole16(c->ic_freq);
+ tap->wt_chan_flags = htole16(c->ic_flags);
+ tap->wt_antenna = sc->tx_ant;
- device_printf(sc->sc_dev, "could not transmit buffer: %s\n",
- usbd_errstr(status));
+ bpf_mtap2(ifp->if_bpf, tap, sc->sc_txtap_len, m);
+ }
- if (status == USBD_STALLED)
- usbd_clear_endpoint_stall_async(sc->sc_tx_pipeh);
+ /* align end on a 4-bytes boundary */
+ len = (RT2573_TX_DESC_SIZE + m->m_pkthdr.len + 3) & ~3;
+ if ((len % 64) == 0)
+ len += 4;
- ifp->if_oerrors++;
- return;
- }
+ DPRINTFN(11, "sending frame len=%u xferlen=%u\n",
+ m->m_pkthdr.len, len);
- m_freem(data->m);
- data->m = NULL;
- ieee80211_free_node(data->ni);
- data->ni = NULL;
+ xfer->frlengths[0] = len;
+ xfer->priv_fifo = data;
- sc->tx_queued--;
- ifp->if_opackets++;
+ usb2_start_hardware(xfer);
+ }
+ break;
+
+ default: /* Error */
+ DPRINTFN(11, "transfer error, %s\n",
+ usb2_errstr(xfer->error));
+
+ if (xfer->error == USB_ERR_STALLED) {
+ /* try to clear stall first */
+ sc->sc_flags |= RUM_FLAG_WRITE_STALL;
+ usb2_transfer_start(sc->sc_xfer[RUM_BULK_CS_WR]);
+ return;
+ }
+ if (xfer->error == USB_ERR_TIMEOUT)
+ device_printf(sc->sc_dev, "device timeout\n");
- DPRINTFN(10, ("tx done\n"));
+ ifp->if_oerrors++;
+ data = xfer->priv_fifo;
+ if (data != NULL) {
+ rum_tx_free(data, xfer->error);
+ xfer->priv_fifo = NULL;
+ }
+ break;
+ }
+}
- sc->sc_tx_timer = 0;
- ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
- rum_start(ifp);
+static void
+rum_bulk_write_clear_stall_callback(struct usb2_xfer *xfer)
+{
+ struct rum_softc *sc = xfer->priv_sc;
+ struct usb2_xfer *xfer_other = sc->sc_xfer[RUM_BULK_DT_WR];
+
+ if (usb2_clear_stall_callback(xfer, xfer_other)) {
+ DPRINTF("stall cleared\n");
+ sc->sc_flags &= ~RUM_FLAG_WRITE_STALL;
+ usb2_transfer_start(xfer_other);
+ }
}
static void
-rum_rxeof(usbd_xfer_handle xfer, usbd_private_handle priv, usbd_status status)
+rum_bulk_read_callback(struct usb2_xfer *xfer)
{
- struct rum_rx_data *data = priv;
- struct rum_softc *sc = data->sc;
+ struct rum_softc *sc = xfer->priv_sc;
struct ifnet *ifp = sc->sc_ifp;
struct ieee80211com *ic = ifp->if_l2com;
- struct rum_rx_desc *desc;
struct ieee80211_node *ni;
- struct mbuf *mnew, *m;
- int len, rssi;
-
- if (status != USBD_NORMAL_COMPLETION) {
- if (status == USBD_NOT_STARTED || status == USBD_CANCELLED)
- return;
+ struct mbuf *m = NULL;
+ uint32_t flags;
+ uint8_t rssi = 0;
+ int len;
- if (status == USBD_STALLED)
- usbd_clear_endpoint_stall_async(sc->sc_rx_pipeh);
- goto skip;
- }
+ switch (USB_GET_STATE(xfer)) {
+ case USB_ST_TRANSFERRED:
- usbd_get_xfer_status(xfer, NULL, NULL, &len, NULL);
+ DPRINTFN(15, "rx done, actlen=%d\n", xfer->actlen);
- if (len < RT2573_RX_DESC_SIZE + sizeof (struct ieee80211_frame_min)) {
- DPRINTF(("%s: xfer too short %d\n",
- device_get_nameunit(sc->sc_dev), len));
- ifp->if_ierrors++;
- goto skip;
- }
+ len = xfer->actlen;
+ if (len < RT2573_RX_DESC_SIZE + IEEE80211_MIN_LEN) {
+ DPRINTF("%s: xfer too short %d\n",
+ device_get_nameunit(sc->sc_dev), len);
+ ifp->if_ierrors++;
+ goto tr_setup;
+ }
+
+ len -= RT2573_RX_DESC_SIZE;
+ usb2_copy_out(xfer->frbuffers, 0, &sc->sc_rx_desc,
+ RT2573_RX_DESC_SIZE);
+
+ rssi = rum_get_rssi(sc, sc->sc_rx_desc.rssi);
+ flags = le32toh(sc->sc_rx_desc.flags);
+ if (flags & RT2573_RX_CRC_ERROR) {
+ /*
+ * This should not happen since we did not
+ * request to receive those frames when we
+ * filled RUM_TXRX_CSR2:
+ */
+ DPRINTFN(5, "PHY or CRC error\n");
+ ifp->if_ierrors++;
+ goto tr_setup;
+ }
- desc = (struct rum_rx_desc *)data->buf;
+ m = m_getcl(M_DONTWAIT, MT_DATA, M_PKTHDR);
+ if (m == NULL) {
+ DPRINTF("could not allocate mbuf\n");
+ ifp->if_ierrors++;
+ goto tr_setup;
+ }
+ usb2_copy_out(xfer->frbuffers, RT2573_RX_DESC_SIZE,
+ mtod(m, uint8_t *), len);
+
+ /* finalize mbuf */
+ m->m_pkthdr.rcvif = ifp;
+ m->m_pkthdr.len = m->m_len = (flags >> 16) & 0xfff;
+
+ if (bpf_peers_present(ifp->if_bpf)) {
+ struct rum_rx_radiotap_header *tap = &sc->sc_rxtap;
+
+ tap->wr_flags = IEEE80211_RADIOTAP_F_FCS;
+ tap->wr_rate = ieee80211_plcp2rate(sc->sc_rx_desc.rate,
+ (flags & RT2573_RX_OFDM) ?
+ IEEE80211_T_OFDM : IEEE80211_T_CCK);
+ tap->wr_chan_freq = htole16(ic->ic_curchan->ic_freq);
+ tap->wr_chan_flags = htole16(ic->ic_curchan->ic_flags);
+ tap->wr_antenna = sc->rx_ant;
+ tap->wr_antsignal = rssi;
+
+ bpf_mtap2(ifp->if_bpf, tap, sc->sc_rxtap_len, m);
+ }
+ /* FALLTHROUGH */
+ case USB_ST_SETUP:
+tr_setup:
+ if (sc->sc_flags & RUM_FLAG_READ_STALL) {
+ usb2_transfer_start(sc->sc_xfer[RUM_BULK_CS_RD]);
*** DIFF OUTPUT TRUNCATED AT 1000 LINES ***
More information about the svn-src-user
mailing list