usb/107642: [patch]Ralink Technology RT2501USB/RT2601USB chipset
driver
Valery V.Chikalov
valera at chikalov.dp.ua
Thu Feb 1 12:30:26 UTC 2007
The following reply was made to PR usb/107642; it has been noted by GNATS.
From: "Valery V.Chikalov" <valera at chikalov.dp.ua>
To: bug-followup at FreeBSD.org, valera at chikalov.dp.ua
Cc:
Subject: Re: usb/107642: [patch]Ralink Technology RT2501USB/RT2601USB chipset
driver
Date: Thu, 01 Feb 2007 13:50:42 +0200
This is a multi-part message in MIME format.
--------------070401030006070808060902
Content-Type: text/plain; charset=KOI8-R
Content-Transfer-Encoding: 7bit
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1
patch fixed, reworked to fit to CURRENT
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.5 (MingW32)
Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org
iD8DBQFFwdP9760S3kDvEC4RAgXLAJ9sgZLzeFCjpw4Rcs2tWN3wNL0IYgCgvTum
C77ikV7d5l0cIQIk7XUS0Zg=
=S4Ye
-----END PGP SIGNATURE-----
--------------070401030006070808060902
Content-Type: text/plain;
name="rum.patch.txt"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline;
filename="rum.patch.txt"
? sys/modules/rt2573/rum-rt2573
Index: sys/dev/usb/if_rum.c
===================================================================
RCS file: sys/dev/usb/if_rum.c
diff -N sys/dev/usb/if_rum.c
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ sys/dev/usb/if_rum.c 1 Feb 2007 11:26:03 -0000
@@ -0,0 +1,2315 @@
+/* $OpenBSD: if_rum.c,v 1.40 2006/09/18 16:20:20 damien Exp $ */
+/* $NetBSD: if_rum.c,v 1.2 2006/11/01 08:39:25 xtraeme Exp $ */
+
+/*-
+ * Copyright (c) 2005, 2006 Damien Bergamini <damien.bergamini at free.fr>
+ * Copyright (c) 2006 Niall O'Higgins <niallo at openbsd.org>
+ * Copyright (c) 2006, 2007 Valery V.Chikalov <valera at chikalov.dp.ua>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*-
+ * Ralink Technology RT2501USB/RT2601USB chipset driver
+ * http://www.ralinktech.com/
+ */
+
+#if defined(__NetBSD__)
+#include "opt_ns.h"
+#endif
+#if defined(__NetBSD__)
+#include "bpfilter.h"
+#endif
+#if defined(__FreeBSD__)
+#define NBPFILTER 1
+#endif
+#if defined(__NetBSD__)
+#include "rnd.h"
+#endif
+
+#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 <sys/linker.h>
+#include <sys/firmware.h>
+
+#include <machine/bus.h>
+#include <machine/resource.h>
+#include <machine/clock.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_radiotap.h>
+
+#include <netinet/in.h>
+#include <netinet/in_systm.h>
+#include <netinet/in_var.h>
+#include <netinet/ip.h>
+#include <netinet/if_ether.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>
+
+#ifdef USB_DEBUG
+#define RUM_DEBUG
+#endif
+
+#ifdef RUM_DEBUG
+#define DPRINTF(x) do { if (rum_debug) logprintf x; } while (0)
+#define DPRINTFN(n, x) do { if (rum_debug >= (n)) logprintf x; } while (0)
+int rum_debug = 0;
+#else
+#define DPRINTF(x)
+#define DPRINTFN(n, x)
+#endif
+
+/* various supported device vendors/products */
+static const struct usb_devno rum_devs[] = {
+ { USB_VENDOR_ABOCOM, USB_PRODUCT_ABOCOM_RT2573 },
+ { USB_VENDOR_ASUS, USB_PRODUCT_ASUS_RT2573 },
+ { USB_VENDOR_BELKIN, USB_PRODUCT_BELKIN_F5D7050A },
+ { USB_VENDOR_BELKIN, USB_PRODUCT_BELKIN_F5D9050V3 },
+ { USB_VENDOR_LINKSYS4, USB_PRODUCT_LINKSYS4_WUSB54GC },
+ { USB_VENDOR_CONCEPTRONIC2, USB_PRODUCT_CONCEPTRONIC2_C54RU2 },
+ { 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_GIGABYTE, USB_PRODUCT_GIGABYTE_GNWB01GS },
+ { USB_VENDOR_GIGASET, USB_PRODUCT_GIGASET_RT2573 },
+ { USB_VENDOR_GOODWAY, USB_PRODUCT_GOODWAY_RT2573 },
+ { USB_VENDOR_HUAWEI3COM, USB_PRODUCT_HUAWEI3COM_RT2573 },
+ { USB_VENDOR_MSI, USB_PRODUCT_MSI_RT2573 },
+ { USB_VENDOR_MSI, USB_PRODUCT_MSI_RT2573_2 },
+ { USB_VENDOR_MSI, USB_PRODUCT_MSI_RT2573_3 },
+ { 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_RT2671 },
+ { USB_VENDOR_SITECOMEU, USB_PRODUCT_SITECOMEU_WL113R2 },
+ { USB_VENDOR_SITECOMEU, USB_PRODUCT_SITECOMEU_WL172 },
+ { USB_VENDOR_SURECOM, USB_PRODUCT_SURECOM_RT2573 }
+};
+
+MODULE_DEPEND(rum, wlan, 1, 1, 1);
+MODULE_DEPEND(rum, firmware, 1, 1, 1);
+
+static void rum_attachhook(void *);
+
+static void rum_start(struct ifnet *);
+static void rum_watchdog(struct ifnet *);
+
+static int rum_ioctl(struct ifnet *, u_long, caddr_t);
+
+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_txeof(usbd_xfer_handle, usbd_private_handle, usbd_status);
+static void rum_rxeof(usbd_xfer_handle, usbd_private_handle, usbd_status);
+
+static int rum_media_change(struct ifnet *);
+static void rum_task(void *);
+static void rum_next_scan(void *);
+static int rum_newstate(struct ieee80211com *, enum ieee80211_state, int);
+static uint8_t rum_rxrate(struct rum_rx_desc *);
+static int rum_ack_rate(struct ieee80211com *, int);
+static uint16_t rum_txtime(int, int, uint32_t);
+static uint8_t rum_plcp_signal(int);
+static void rum_setup_tx_desc(struct rum_softc *, struct rum_tx_desc *, uint32_t, uint16_t, int, int);
+static int rum_tx_mgt(struct rum_softc *, struct mbuf *, struct ieee80211_node *);
+static int rum_tx_data(struct rum_softc *, struct mbuf *, struct ieee80211_node *);
+
+static void rum_read_eeprom(struct rum_softc *);
+static void rum_eeprom_read(struct rum_softc *, uint16_t, void *, int);
+static uint32_t rum_read(struct rum_softc *, uint16_t);
+static void rum_read_multi(struct rum_softc *, uint16_t, void *, int);
+static void rum_write(struct rum_softc *, uint16_t, uint32_t);
+static void rum_write_multi(struct rum_softc *, uint16_t, void *, size_t);
+
+static int rum_bbp_init(struct rum_softc *);
+static void rum_bbp_write(struct rum_softc *, uint8_t, uint8_t);
+static uint8_t rum_bbp_read(struct rum_softc *, uint8_t);
+
+static const char *rum_get_rf(int);
+static void rum_rf_write(struct rum_softc *, uint8_t, uint32_t);
+static void rum_select_antenna(struct rum_softc *);
+static void rum_enable_mrr(struct rum_softc *);
+static void rum_set_txpreamble(struct rum_softc *);
+static void rum_set_basicrates(struct rum_softc *);
+static void rum_select_band(struct rum_softc *, struct ieee80211_channel *);
+static void rum_set_chan(struct rum_softc *, struct ieee80211_channel *);
+static void rum_enable_tsf_sync(struct rum_softc *);
+static void rum_update_slot(struct rum_softc *);
+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 void rum_init(void *);
+static void rum_stop(struct ifnet *);
+static int rum_load_microcode(struct rum_softc *, const u_char *, size_t);
+static int rum_prepare_beacon(struct rum_softc *);
+
+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 status);
+static void rum_ratectl(struct rum_amrr *, struct ieee80211_node *);
+
+/*
+ * Supported rates for 802.11a/b/g modes (in 500Kbps unit).
+ */
+static const struct ieee80211_rateset rum_rateset_11a =
+ { 8, { 12, 18, 24, 36, 48, 72, 96, 108 } };
+
+static const struct ieee80211_rateset rum_rateset_11b =
+ { 4, { 2, 4, 11, 22 } };
+
+static const struct ieee80211_rateset rum_rateset_11g =
+ { 12, { 2, 4, 11, 22, 12, 18, 24, 36, 48, 72, 96, 108 } };
+
+static const struct {
+ uint32_t reg;
+ uint32_t val;
+} rum_def_mac[] = {
+ RT2573_DEF_MAC
+};
+
+static const struct {
+ uint8_t reg;
+ uint8_t val;
+} rum_def_bbp[] = {
+ RT2573_DEF_BBP
+};
+
+static const struct rfprog {
+ uint8_t chan;
+ uint32_t r1, r2, r3, r4;
+} rum_rf5226[] = {
+ RT2573_RF5226
+}, rum_rf5225[] = {
+ RT2573_RF5225
+};
+
+USB_DECLARE_DRIVER(rum);
+
+USB_MATCH(rum)
+{
+ USB_MATCH_START(rum, uaa);
+
+ if (uaa->iface != NULL)
+ return UMATCH_NONE;
+
+ return (usb_lookup(rum_devs, uaa->vendor, uaa->product) != NULL) ?
+ UMATCH_VENDOR_PRODUCT : UMATCH_NONE;
+}
+
+static void
+rum_attachhook(void *xsc)
+{
+ struct rum_softc *sc = xsc;
+ const char *name = "rt2573";
+ struct firmware *fp;
+
+ fp = firmware_get(name);
+
+ if (fp == NULL || fp->datasize == 0) {
+ printf("%s: failed loadfirmware of file %s\n",
+ device_get_nameunit(sc->sc_dev), name);
+ return;
+ } else {
+ //MYDEBUG
+ printf("%s: firmware loaded: name: %s, size:%d\n", device_get_nameunit(sc->sc_dev), fp->name, fp->datasize);
+ }
+
+ if (rum_load_microcode(sc, fp->data, fp->datasize) != 0) {
+ printf("%s: could not load 8051 microcode\n",
+ device_get_nameunit(sc->sc_dev));
+ }
+
+}
+
+USB_ATTACH(rum)
+{
+ USB_ATTACH_START(rum, sc, uaa);
+ struct ieee80211com *ic = &sc->sc_ic;
+ struct ifnet *ifp = NULL;
+ usb_interface_descriptor_t *id;
+ usb_endpoint_descriptor_t *ed;
+ usbd_status error;
+ char devinfo[1024];
+ int i, ntries;
+ uint32_t tmp;
+
+ sc->sc_udev = uaa->device;
+ sc->sc_flags = 0;
+
+ usbd_devinfo(sc->sc_udev, 0, devinfo);
+ USB_ATTACH_SETUP;
+ printf("%s: %s\n", device_get_nameunit(sc->sc_dev), devinfo);
+
+ if (usbd_set_config_no(sc->sc_udev, RT2573_CONFIG_NO, 0) != 0) {
+ printf("%s: could not set configuration no\n",
+ device_get_nameunit(sc->sc_dev));
+ USB_ATTACH_ERROR_RETURN;
+ }
+
+ /* get the first interface handle */
+ error = usbd_device2interface_handle(sc->sc_udev, RT2573_IFACE_INDEX,
+ &sc->sc_iface);
+ if (error != 0) {
+ printf("%s: could not get interface handle\n",
+ device_get_nameunit(sc->sc_dev));
+ USB_ATTACH_ERROR_RETURN;
+ }
+
+ /*
+ * 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) {
+ printf("%s: no endpoint descriptor for iface %d\n",
+ device_get_nameunit(sc->sc_dev), i);
+ USB_ATTACH_ERROR_RETURN;
+ }
+
+ 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) {
+ printf("%s: missing endpoint\n", device_get_nameunit(sc->sc_dev));
+ USB_ATTACH_ERROR_RETURN;
+ }
+
+ usb_init_task(&sc->sc_task, rum_task, sc);
+ callout_init(&sc->scan_ch, debug_mpsafenet ? CALLOUT_MPSAFE : 0);
+ callout_init(&sc->amrr_ch, 0);
+
+ /* retrieve RT2573 rev. no */
+ for (ntries = 0; ntries < 1000; ntries++) {
+ if ((tmp = rum_read(sc, RT2573_MAC_CSR0)) != 0)
+ break;
+ DELAY(1000);
+ }
+ if (ntries == 1000) {
+ printf("%s: timeout waiting for chip to settle\n",
+ device_get_nameunit(sc->sc_dev));
+ USB_ATTACH_ERROR_RETURN;
+ }
+
+ /* retrieve MAC address and various other things from EEPROM */
+ rum_read_eeprom(sc);
+
+ printf("%s: MAC/BBP RT%04x (rev 0x%05x), RF %s, address %s\n",
+ device_get_nameunit(sc->sc_dev), sc->macbbp_rev, tmp,
+ rum_get_rf(sc->rf_rev), ether_sprintf(ic->ic_myaddr));
+
+ ifp = sc->sc_ifp = if_alloc(IFT_ETHER);
+ if (ifp == NULL) {
+ printf("%s: can not if_alloc()\n", device_get_nameunit(sc->sc_dev));
+ USB_ATTACH_ERROR_RETURN;
+ }
+
+#if 1
+ rum_attachhook(sc);
+#endif
+
+ ic->ic_ifp = ifp;
+ ic->ic_phytype = IEEE80211_T_OFDM; /* not only, but not used */
+ ic->ic_opmode = IEEE80211_M_STA; /* default to BSS mode */
+ ic->ic_state = IEEE80211_S_INIT;
+
+ /* set device capabilities */
+ ic->ic_caps =
+ IEEE80211_C_IBSS | /* IBSS mode supported */
+ IEEE80211_C_MONITOR | /* monitor mode supported */
+ IEEE80211_C_HOSTAP | /* HostAp mode supported */
+ IEEE80211_C_TXPMGT | /* tx power management */
+ IEEE80211_C_SHPREAMBLE | /* short preamble supported */
+ IEEE80211_C_SHSLOT | /* short slot time supported */
+ IEEE80211_C_WPA; /* 802.11i */
+
+ if (sc->rf_rev == RT2573_RF_5225 || sc->rf_rev == RT2573_RF_5226) {
+ /* set supported .11a rates */
+ ic->ic_sup_rates[IEEE80211_MODE_11A] = rum_rateset_11a;
+
+ /* set supported .11a channels */
+ for (i = 34; i <= 46; i += 4) {
+ ic->ic_channels[i].ic_freq =
+ ieee80211_ieee2mhz(i, IEEE80211_CHAN_5GHZ);
+ ic->ic_channels[i].ic_flags = IEEE80211_CHAN_A;
+ }
+ for (i = 36; i <= 64; i += 4) {
+ ic->ic_channels[i].ic_freq =
+ ieee80211_ieee2mhz(i, IEEE80211_CHAN_5GHZ);
+ ic->ic_channels[i].ic_flags = IEEE80211_CHAN_A;
+ }
+ for (i = 100; i <= 140; i += 4) {
+ ic->ic_channels[i].ic_freq =
+ ieee80211_ieee2mhz(i, IEEE80211_CHAN_5GHZ);
+ ic->ic_channels[i].ic_flags = IEEE80211_CHAN_A;
+ }
+ for (i = 149; i <= 165; i += 4) {
+ ic->ic_channels[i].ic_freq =
+ ieee80211_ieee2mhz(i, IEEE80211_CHAN_5GHZ);
+ ic->ic_channels[i].ic_flags = IEEE80211_CHAN_A;
+ }
+ }
+
+ /* set supported .11b and .11g rates */
+ ic->ic_sup_rates[IEEE80211_MODE_11B] = rum_rateset_11b;
+ ic->ic_sup_rates[IEEE80211_MODE_11G] = rum_rateset_11g;
+
+ /* set supported .11b and .11g channels (1 through 14) */
+ for (i = 1; i <= 14; i++) {
+ ic->ic_channels[i].ic_freq =
+ ieee80211_ieee2mhz(i, IEEE80211_CHAN_2GHZ);
+ ic->ic_channels[i].ic_flags =
+ IEEE80211_CHAN_CCK | IEEE80211_CHAN_OFDM |
+ IEEE80211_CHAN_DYN | IEEE80211_CHAN_2GHZ;
+ }
+
+ ifp->if_softc = sc;
+ if_initname(ifp, "rum", device_get_unit(sc->sc_dev));
+ ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
+ ifp->if_init = rum_init;
+ ifp->if_ioctl = rum_ioctl;
+ ifp->if_start = rum_start;
+ ifp->if_watchdog = rum_watchdog;
+ IFQ_SET_MAXLEN(&ifp->if_snd, IFQ_MAXLEN);
+ IFQ_SET_READY(&ifp->if_snd);
+
+// if_attach(ifp);
+ ieee80211_ifattach(ic);
+
+ /* override state transition machine */
+ sc->sc_newstate = ic->ic_newstate;
+ ic->ic_newstate = rum_newstate;
+ ieee80211_media_init(ic, rum_media_change, ieee80211_media_status);
+
+#if NBPFILTER > 0
+ bpfattach2(ifp, DLT_IEEE802_11_RADIO,
+ sizeof (struct ieee80211_frame) + IEEE80211_RADIOTAP_HDRLEN, &sc->sc_drvbpf);
+
+ sc->sc_rxtap_len = sizeof sc->sc_rxtapu;
+ sc->sc_rxtap.wr_ihdr.it_len = htole16(sc->sc_rxtap_len);
+ sc->sc_rxtap.wr_ihdr.it_present = htole32(RT2573_RX_RADIOTAP_PRESENT);
+
+ sc->sc_txtap_len = sizeof sc->sc_txtapu;
+ sc->sc_txtap.wt_ihdr.it_len = htole16(sc->sc_txtap_len);
+ sc->sc_txtap.wt_ihdr.it_present = htole32(RT2573_TX_RADIOTAP_PRESENT);
+#endif
+
+ ieee80211_announce(ic);
+
+ usbd_add_drv_event(USB_EVENT_DRIVER_ATTACH, sc->sc_udev,
+ USBDEV(sc->sc_dev));
+
+ USB_ATTACH_SUCCESS_RETURN;
+}
+
+USB_DETACH(rum)
+{
+ USB_DETACH_START(rum, sc);
+ struct ieee80211com *ic = &sc->sc_ic;
+ struct ifnet *ifp = sc->sc_ifp;
+ int s;
+
+ s = splusb();
+
+ rum_stop(ifp);
+ usb_rem_task(sc->sc_udev, &sc->sc_task);
+ callout_stop(&sc->scan_ch);
+ callout_stop(&sc->amrr_ch);
+
+ if (sc->amrr_xfer != NULL) {
+ usbd_free_xfer(sc->amrr_xfer);
+ sc->amrr_xfer = NULL;
+ }
+
+ 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);
+ }
+
+ rum_free_rx_list(sc);
+ rum_free_tx_list(sc);
+
+#if NBPFILTER > 0
+ bpfdetach(ifp);
+#endif
+ ieee80211_ifdetach(ic); /* free all nodes */
+ if_detach(ifp);
+
+ splx(s);
+
+ usbd_add_drv_event(USB_EVENT_DRIVER_DETACH, sc->sc_udev,
+ USBDEV(sc->sc_dev));
+
+ return 0;
+}
+
+static int
+rum_alloc_tx_list(struct rum_softc *sc)
+{
+ struct rum_tx_data *data;
+ int i, error;
+
+ sc->tx_queued = 0;
+
+ for (i = 0; i < RT2573_TX_LIST_COUNT; i++) {
+ data = &sc->tx_data[i];
+
+ data->sc = sc;
+
+ data->xfer = usbd_alloc_xfer(sc->sc_udev);
+ if (data->xfer == NULL) {
+ printf("%s: could not allocate tx xfer\n",
+ device_get_nameunit(sc->sc_dev));
+ error = ENOMEM;
+ goto fail;
+ }
+
+ data->buf = usbd_alloc_buffer(data->xfer,
+ RT2573_TX_DESC_SIZE + MCLBYTES);
+ if (data->buf == NULL) {
+ printf("%s: could not allocate tx buffer\n",
+ device_get_nameunit(sc->sc_dev));
+ error = ENOMEM;
+ goto fail;
+ }
+
+ /* clean Tx descriptor */
+ bzero(data->buf, RT2573_TX_DESC_SIZE);
+ }
+
+ return 0;
+
+fail: rum_free_tx_list(sc);
+ return error;
+}
+
+static void
+rum_free_tx_list(struct rum_softc *sc)
+{
+ struct rum_tx_data *data;
+ int i;
+
+ for (i = 0; i < RT2573_TX_LIST_COUNT; i++) {
+ data = &sc->tx_data[i];
+
+ if (data->xfer != NULL) {
+ usbd_free_xfer(data->xfer);
+ data->xfer = 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 < RT2573_RX_LIST_COUNT; i++) {
+ data = &sc->rx_data[i];
+
+ data->sc = sc;
+
+ data->xfer = usbd_alloc_xfer(sc->sc_udev);
+ if (data->xfer == NULL) {
+ printf("%s: could not allocate rx xfer\n",
+ device_get_nameunit(sc->sc_dev));
+ error = ENOMEM;
+ goto fail;
+ }
+
+ if (usbd_alloc_buffer(data->xfer, MCLBYTES) == NULL) {
+ printf("%s: could not allocate rx buffer\n",
+ device_get_nameunit(sc->sc_dev));
+ error = ENOMEM;
+ goto fail;
+ }
+
+ MGETHDR(data->m, M_DONTWAIT, MT_DATA);
+ if (data->m == NULL) {
+ printf("%s: could not allocate rx mbuf\n",
+ device_get_nameunit(sc->sc_dev));
+ error = ENOMEM;
+ goto fail;
+ }
+
+ MCLGET(data->m, M_DONTWAIT);
+ if (!(data->m->m_flags & M_EXT)) {
+ printf("%s: could not allocate rx mbuf cluster\n",
+ device_get_nameunit(sc->sc_dev));
+ error = ENOMEM;
+ goto fail;
+ }
+
+ data->buf = mtod(data->m, uint8_t *);
+ }
+
+ return 0;
+
+fail: rum_free_tx_list(sc);
+ return error;
+}
+
+static void
+rum_free_rx_list(struct rum_softc *sc)
+{
+ struct rum_rx_data *data;
+ int i;
+
+ for (i = 0; i < RT2573_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 int
+rum_media_change(struct ifnet *ifp)
+{
+ struct rum_softc *sc = ifp->if_softc;
+ int error;
+
+ error = ieee80211_media_change(ifp);
+ if (error != ENETRESET)
+ return error;
+
+ if ((ifp->if_flags & IFF_UP) &&
+ (ifp->if_drv_flags & IFF_DRV_RUNNING))
+ rum_init(sc);
+
+ return 0;
+}
+
+/*
+ * This function is called periodically (every 200ms) during scanning to
+ * switch from one channel to another.
+ */
+static void
+rum_next_scan(void *arg)
+{
+ struct rum_softc *sc = arg;
+ struct ieee80211com *ic = &sc->sc_ic;
+
+ if (ic->ic_state == IEEE80211_S_SCAN)
+ ieee80211_next_scan(ic);
+}
+
+static void
+rum_task(void *arg)
+{
+ struct rum_softc *sc = arg;
+ struct ieee80211com *ic = &sc->sc_ic;
+ enum ieee80211_state ostate;
+ struct ieee80211_node *ni;
+ uint32_t tmp;
+
+ ostate = ic->ic_state;
+
+ switch (sc->sc_state) {
+ case IEEE80211_S_INIT:
+ if (ostate == IEEE80211_S_RUN) {
+ /* abort TSF synchronization */
+ tmp = rum_read(sc, RT2573_TXRX_CSR9);
+ rum_write(sc, RT2573_TXRX_CSR9, tmp & ~0x00ffffff);
+ }
+ break;
+
+ case IEEE80211_S_SCAN:
+ rum_set_chan(sc, ic->ic_curchan);
+ callout_reset(&sc->scan_ch, hz / 5, rum_next_scan, sc);
+ break;
+
+ case IEEE80211_S_AUTH:
+ rum_set_chan(sc, ic->ic_curchan);
+ break;
+
+ case IEEE80211_S_ASSOC:
+ rum_set_chan(sc, ic->ic_curchan);
+ break;
+
+ case IEEE80211_S_RUN:
+ rum_set_chan(sc, ic->ic_curchan);
+
+ ni = ic->ic_bss;
+
+ if (ic->ic_opmode != IEEE80211_M_MONITOR) {
+ rum_update_slot(sc);
+ rum_enable_mrr(sc);
+ rum_set_txpreamble(sc);
+ rum_set_basicrates(sc);
+ rum_set_bssid(sc, ni->ni_bssid);
+ }
+
+ if (ic->ic_opmode == IEEE80211_M_HOSTAP ||
+ ic->ic_opmode == IEEE80211_M_IBSS)
+ rum_prepare_beacon(sc);
+
+ if (ic->ic_opmode != IEEE80211_M_MONITOR)
+ rum_enable_tsf_sync(sc);
+
+ /* enable automatic rate adaptation in STA mode */
+ if (ic->ic_opmode == IEEE80211_M_STA &&
+ ic->ic_fixed_rate == IEEE80211_FIXED_RATE_NONE)
+ rum_amrr_start(sc, ni);
+
+ break;
+ }
+
+ sc->sc_newstate(ic, sc->sc_state, -1);
+}
+
+static int
+rum_newstate(struct ieee80211com *ic, enum ieee80211_state nstate, int arg)
+{
+ struct rum_softc *sc = ic->ic_ifp->if_softc;
+
+ usb_rem_task(sc->sc_udev, &sc->sc_task);
+ callout_stop(&sc->scan_ch);
+ callout_stop(&sc->amrr_ch);
+
+ /* do it in a process context */
+ sc->sc_state = nstate;
+ usb_add_task(sc->sc_udev, &sc->sc_task, USB_TASKQ_DRIVER);
+
+ return 0;
+}
+
+/* quickly determine if a given rate is CCK or OFDM */
+#define RUM_RATE_IS_OFDM(rate) ((rate) >= 12 && (rate) != 22)
+
+#define RUM_ACK_SIZE 14 /* 10 + 4(FCS) */
+#define RUM_CTS_SIZE 14 /* 10 + 4(FCS) */
+
+static void
+rum_txeof(usbd_xfer_handle xfer, usbd_private_handle priv, usbd_status status)
+{
+ struct rum_tx_data *data = priv;
+ struct rum_softc *sc = data->sc;
+ struct ifnet *ifp = sc->sc_ifp;
+ int s;
+
+ if (status != USBD_NORMAL_COMPLETION) {
+ if (status == USBD_NOT_STARTED || status == USBD_CANCELLED)
+ return;
+
+ printf("%s: could not transmit buffer: %s\n",
+ device_get_nameunit(sc->sc_dev), usbd_errstr(status));
+
+ if (status == USBD_STALLED)
+ usbd_clear_endpoint_stall_async(sc->sc_tx_pipeh);
+
+ ifp->if_oerrors++;
+ return;
+ }
+
+ s = splnet();
+
+ m_freem(data->m);
+ data->m = NULL;
+ ieee80211_free_node(data->ni);
+ data->ni = NULL;
+
+ sc->tx_queued--;
+ ifp->if_opackets++;
+
+ DPRINTFN(10, ("tx done\n"));
+
+ sc->sc_tx_timer = 0;
+ ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
+ rum_start(ifp);
+
+ splx(s);
+}
+
+static void
+rum_rxeof(usbd_xfer_handle xfer, usbd_private_handle priv, usbd_status status)
+{
+ struct rum_rx_data *data = priv;
+ struct rum_softc *sc = data->sc;
+ struct ieee80211com *ic = &sc->sc_ic;
+ struct ifnet *ifp = sc->sc_ifp;
+ struct rum_rx_desc *desc;
+ struct ieee80211_frame *wh;
+ struct ieee80211_node *ni;
+ struct mbuf *mnew, *m;
+ int s, len;
+
+ if (status != USBD_NORMAL_COMPLETION) {
+ if (status == USBD_NOT_STARTED || status == USBD_CANCELLED)
+ return;
+
+ if (status == USBD_STALLED)
+ usbd_clear_endpoint_stall_async(sc->sc_rx_pipeh);
+ goto skip;
+ }
+
+ usbd_get_xfer_status(xfer, NULL, NULL, &len, NULL);
+
+ 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;
+ }
+
+ desc = (struct rum_rx_desc *)data->buf;
+
+ if (le32toh(desc->flags) & RT2573_RX_CRC_ERROR) {
+ /*
+ * This should not happen since we did not request to receive
+ * those frames when we filled RT2573_TXRX_CSR0.
+ */
+ DPRINTFN(5, ("CRC error\n"));
+ ifp->if_ierrors++;
+ goto skip;
+ }
+
+ MGETHDR(mnew, M_DONTWAIT, MT_DATA);
+ if (mnew == NULL) {
+ printf("%s: could not allocate rx mbuf\n",
+ device_get_nameunit(sc->sc_dev));
+ ifp->if_ierrors++;
+ goto skip;
+ }
+
+ MCLGET(mnew, M_DONTWAIT);
+ if (!(mnew->m_flags & M_EXT)) {
+ printf("%s: could not allocate rx mbuf cluster\n",
+ device_get_nameunit(sc->sc_dev));
+ m_freem(mnew);
+ ifp->if_ierrors++;
+ goto skip;
+ }
+
+ m = data->m;
+ data->m = mnew;
+ data->buf = mtod(data->m, uint8_t *);
+
+ /* finalize mbuf */
+ m->m_pkthdr.rcvif = ifp;
+ m->m_data = (caddr_t)(desc + 1);
+ m->m_pkthdr.len = m->m_len = (le32toh(desc->flags) >> 16) & 0xfff;
+
+ s = splnet();
+
+ if (sc->sc_drvbpf != NULL) {
+ struct rum_rx_radiotap_header *tap = &sc->sc_rxtap;
+
+ tap->wr_flags = IEEE80211_RADIOTAP_F_FCS;
+ tap->wr_rate = rum_rxrate(desc);
+ 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 = desc->rssi;
+
+ bpf_mtap2(sc->sc_drvbpf, tap, sc->sc_rxtap_len, m);
+ }
+
+ wh = mtod(m, struct ieee80211_frame *);
+ ni = ieee80211_find_rxnode(ic, (struct ieee80211_frame_min *)wh);
+
+ /* send the frame to the 802.11 layer */
+ ieee80211_input(ic, m, ni, desc->rssi, 0);
+
+ /* node is no longer needed */
+ ieee80211_free_node(ni);
+
+ splx(s);
+
+ DPRINTFN(15, ("rx done\n"));
+
+skip: /* setup a new transfer */
+ usbd_setup_xfer(xfer, sc->sc_rx_pipeh, data, data->buf, MCLBYTES,
+ USBD_SHORT_XFER_OK, USBD_NO_TIMEOUT, rum_rxeof);
+ usbd_transfer(xfer);
+}
+
+/*
+ * This function is only used by the Rx radiotap code. It returns the rate at
+ * which a given frame was received.
+ */
+static uint8_t
+rum_rxrate(struct rum_rx_desc *desc)
+{
+ if (le32toh(desc->flags) & RT2573_RX_OFDM) {
+ /* reverse function of rum_plcp_signal */
+ switch (desc->rate) {
+ case 0xb: return 12;
+ case 0xf: return 18;
+ case 0xa: return 24;
+ case 0xe: return 36;
+ case 0x9: return 48;
+ case 0xd: return 72;
+ case 0x8: return 96;
+ case 0xc: return 108;
+ }
+ } else {
+ if (desc->rate == 10)
+ return 2;
+ if (desc->rate == 20)
+ return 4;
+ if (desc->rate == 55)
+ return 11;
+ if (desc->rate == 110)
+ return 22;
+ }
+ return 2; /* should not get there */
+}
+
+/*
+ * Return the expected ack rate for a frame transmitted at rate `rate'.
+ * XXX: this should depend on the destination node basic rate set.
+ */
+static int
+rum_ack_rate(struct ieee80211com *ic, int rate)
+{
+ switch (rate) {
+ /* CCK rates */
+ case 2:
+ return 2;
+ case 4:
+ case 11:
+ case 22:
+ return (ic->ic_curmode == IEEE80211_MODE_11B) ? 4 : rate;
+
+ /* OFDM rates */
+ case 12:
+ case 18:
+ return 12;
+ case 24:
+ case 36:
+ return 24;
+ case 48:
+ case 72:
+ case 96:
+ case 108:
+ return 48;
+ }
+
+ /* default to 1Mbps */
+ return 2;
+}
+
+/*
+ * Compute the duration (in us) needed to transmit `len' bytes at rate `rate'.
+ * The function automatically determines the operating mode depending on the
+ * given rate. `flags' indicates whether short preamble is in use or not.
+ */
+static uint16_t
+rum_txtime(int len, int rate, uint32_t flags)
+{
+ uint16_t txtime;
+
+ if (RUM_RATE_IS_OFDM(rate)) {
+ /* IEEE Std 802.11a-1999, pp. 37 */
+ txtime = (8 + 4 * len + 3 + rate - 1) / rate;
+ txtime = 16 + 4 + 4 * txtime + 6;
+ } else {
+ /* IEEE Std 802.11b-1999, pp. 28 */
+ txtime = (16 * len + rate - 1) / rate;
+ if (rate != 2 && (flags & IEEE80211_F_SHPREAMBLE))
+ txtime += 72 + 24;
+ else
+ txtime += 144 + 48;
+ }
+ return txtime;
+}
+
+static uint8_t
+rum_plcp_signal(int rate)
+{
+ switch (rate) {
+ /* CCK rates (returned values are device-dependent) */
+ case 2: return 0x0;
+ case 4: return 0x1;
+ case 11: return 0x2;
+ case 22: return 0x3;
+
+ /* OFDM rates (cf IEEE Std 802.11a-1999, pp. 14 Table 80) */
+ case 12: return 0xb;
+ case 18: return 0xf;
+ case 24: return 0xa;
+ case 36: return 0xe;
+ case 48: return 0x9;
+ case 72: return 0xd;
+ case 96: return 0x8;
+ case 108: return 0xc;
+
+ /* unsupported rates (should not get there) */
+ default: return 0xff;
+ }
+}
+
+static void
+rum_setup_tx_desc(struct rum_softc *sc, struct rum_tx_desc *desc,
+ uint32_t flags, uint16_t xflags, int len, int rate)
+{
+ struct ieee80211com *ic = &sc->sc_ic;
+ uint16_t plcp_length;
+ int remainder;
+
+ desc->flags = htole32(flags);
+ desc->flags |= htole32(RT2573_TX_VALID);
+ desc->flags |= htole32(len << 16);
+
+ desc->xflags = htole16(xflags);
+
+ desc->wme = htole16(
+ RT2573_QID(0) |
+ RT2573_AIFSN(2) |
+ RT2573_LOGCWMIN(4) |
+ RT2573_LOGCWMAX(10));
+
+ /* setup PLCP fields */
+ desc->plcp_signal = rum_plcp_signal(rate);
+ desc->plcp_service = 4;
+
+ len += IEEE80211_CRC_LEN;
+ if (RUM_RATE_IS_OFDM(rate)) {
+ desc->flags |= htole32(RT2573_TX_OFDM);
+
+ plcp_length = len & 0xfff;
+ desc->plcp_length_hi = plcp_length >> 6;
+ desc->plcp_length_lo = plcp_length & 0x3f;
+ } else {
+ plcp_length = (16 * len + rate - 1) / rate;
+ if (rate == 22) {
+ remainder = (16 * len) % 22;
+ if (remainder != 0 && remainder < 7)
+ desc->plcp_service |= RT2573_PLCP_LENGEXT;
+ }
+ desc->plcp_length_hi = plcp_length >> 8;
+ desc->plcp_length_lo = plcp_length & 0xff;
+
+ if (rate != 2 && (ic->ic_flags & IEEE80211_F_SHPREAMBLE))
+ desc->plcp_signal |= 0x08;
+ }
+}
+
+#define RUM_TX_TIMEOUT 5000
+
+static int
+rum_tx_mgt(struct rum_softc *sc, struct mbuf *m0, struct ieee80211_node *ni)
+{
+ struct ieee80211com *ic = &sc->sc_ic;
+ struct rum_tx_desc *desc;
+ struct rum_tx_data *data;
+ struct ieee80211_frame *wh;
+ uint32_t flags = 0;
+ uint16_t dur;
+ usbd_status error;
+ int xferlen, rate;
+
+ data = &sc->tx_data[0];
+ desc = (struct rum_tx_desc *)data->buf;
+
+ rate = IEEE80211_IS_CHAN_5GHZ(ic->ic_curchan) ? 12 : 2;
+
+ data->m = m0;
+ data->ni = ni;
+
+ wh = mtod(m0, struct ieee80211_frame *);
+
+ if (!IEEE80211_IS_MULTICAST(wh->i_addr1)) {
+ flags |= RT2573_TX_ACK;
+
+ dur = rum_txtime(RUM_ACK_SIZE, rum_ack_rate(ic, rate),
+ ic->ic_flags) + sc->sifs;
+ *(uint16_t *)wh->i_dur = htole16(dur);
+
+ /* tell hardware to set timestamp in probe responses */
+ if ((wh->i_fc[0] &
+ (IEEE80211_FC0_TYPE_MASK | IEEE80211_FC0_SUBTYPE_MASK)) ==
+ (IEEE80211_FC0_TYPE_MGT | IEEE80211_FC0_SUBTYPE_PROBE_RESP))
+ flags |= RT2573_TX_TIMESTAMP;
+ }
+
+#if NBPFILTER > 0
+ if (sc->sc_drvbpf != NULL) {
+ struct rum_tx_radiotap_header *tap = &sc->sc_txtap;
+
+ tap->wt_flags = 0;
+ tap->wt_rate = rate;
+ tap->wt_chan_freq = htole16(ic->ic_curchan->ic_freq);
+ tap->wt_chan_flags = htole16(ic->ic_curchan->ic_flags);
+ tap->wt_antenna = sc->tx_ant;
+
+ bpf_mtap2(sc->sc_drvbpf, tap, sc->sc_txtap_len, m0);
+ }
+#endif
+
+ m_copydata(m0, 0, m0->m_pkthdr.len, data->buf + RT2573_TX_DESC_SIZE);
+ rum_setup_tx_desc(sc, desc, flags, 0, m0->m_pkthdr.len, rate);
+
+ /* align end on a 4-bytes boundary */
+ xferlen = (RT2573_TX_DESC_SIZE + m0->m_pkthdr.len + 3) & ~3;
+
+ /*
+ * No space left in the last URB to store the extra 4 bytes, force
+ * sending of another URB.
+ */
+ if ((xferlen % 64) == 0)
+ xferlen += 4;
+
+ DPRINTFN(10, ("sending msg frame len=%u rate=%u xfer len=%u\n",
+ m0->m_pkthdr.len + RT2573_TX_DESC_SIZE, rate, xferlen));
+
+ usbd_setup_xfer(data->xfer, sc->sc_tx_pipeh, data, data->buf, xferlen,
+ USBD_FORCE_SHORT_XFER | USBD_NO_COPY, RUM_TX_TIMEOUT, rum_txeof);
+
+ error = usbd_transfer(data->xfer);
+ if (error != USBD_NORMAL_COMPLETION && error != USBD_IN_PROGRESS) {
+ m_freem(m0);
+ return error;
+ }
+
+ sc->tx_queued++;
+
+ return 0;
+}
+
+static int
+rum_tx_data(struct rum_softc *sc, struct mbuf *m0, struct ieee80211_node *ni)
+{
+ struct ieee80211com *ic = &sc->sc_ic;
+ struct rum_tx_desc *desc;
+ struct rum_tx_data *data;
+ struct ieee80211_frame *wh;
+ struct ieee80211_key *k;
+ uint32_t flags = 0;
+ uint16_t dur;
+ usbd_status error;
+ int xferlen, rate;
+
+ wh = mtod(m0, struct ieee80211_frame *);
+
+ if (ic->ic_fixed_rate != IEEE80211_FIXED_RATE_NONE)
+ rate = ic->ic_bss->ni_rates.rs_rates[ic->ic_fixed_rate];
+ else
+ rate = ni->ni_rates.rs_rates[ni->ni_txrate];
+ rate &= IEEE80211_RATE_VAL;
+
+ if (wh->i_fc[1] & IEEE80211_FC1_WEP) {
+ k = ieee80211_crypto_encap(ic, ni, m0);
+ if (k == NULL) {
+ m_freem(m0);
+ return ENOBUFS;
+ }
+
+ /* packet header may have moved, reset our local pointer */
+ wh = mtod(m0, struct ieee80211_frame *);
+ }
+
+ data = &sc->tx_data[0];
+ desc = (struct rum_tx_desc *)data->buf;
+
+ data->m = m0;
+ data->ni = ni;
+
+ if (!IEEE80211_IS_MULTICAST(wh->i_addr1)) {
+ flags |= RT2573_TX_ACK;
+
+ dur = rum_txtime(RUM_ACK_SIZE, rum_ack_rate(ic, rate),
+ ic->ic_flags) + sc->sifs;
+ *(uint16_t *)wh->i_dur = htole16(dur);
+ }
+
+#if NBPFILTER > 0
+ if (sc->sc_drvbpf != NULL) {
+ struct rum_tx_radiotap_header *tap = &sc->sc_txtap;
+
+ tap->wt_flags = 0;
+ tap->wt_rate = rate;
+ tap->wt_chan_freq = htole16(ic->ic_curchan->ic_freq);
+ tap->wt_chan_flags = htole16(ic->ic_curchan->ic_flags);
+ tap->wt_antenna = sc->tx_ant;
+
+ bpf_mtap2(sc->sc_drvbpf, tap, sc->sc_txtap_len, m0);
+ }
+#endif
+
+ m_copydata(m0, 0, m0->m_pkthdr.len, data->buf + RT2573_TX_DESC_SIZE);
+ rum_setup_tx_desc(sc, desc, flags, 0, m0->m_pkthdr.len, rate);
+
+ /* align end on a 4-bytes boundary */
+ xferlen = (RT2573_TX_DESC_SIZE + m0->m_pkthdr.len + 3) & ~3;
+
+ /*
+ * No space left in the last URB to store the extra 4 bytes, force
+ * sending of another URB.
+ */
+ if ((xferlen % 64) == 0)
+ xferlen += 4;
+
+ DPRINTFN(10, ("sending data frame len=%u rate=%u xfer len=%u\n",
+ m0->m_pkthdr.len + RT2573_TX_DESC_SIZE, rate, xferlen));
+
+ usbd_setup_xfer(data->xfer, sc->sc_tx_pipeh, data, data->buf, xferlen,
+ USBD_FORCE_SHORT_XFER | USBD_NO_COPY, RUM_TX_TIMEOUT, rum_txeof);
+
+ error = usbd_transfer(data->xfer);
+ if (error != USBD_NORMAL_COMPLETION && error != USBD_IN_PROGRESS) {
+ m_freem(m0);
+ return error;
+ }
+
+ sc->tx_queued++;
+
+ return 0;
+}
+
+static void
+rum_start(struct ifnet *ifp)
+{
+ struct rum_softc *sc = ifp->if_softc;
+ struct ieee80211com *ic = &sc->sc_ic;
+ struct mbuf *m0;
+ struct ether_header *eh;
+ struct ieee80211_node *ni;
+
+ for (;;) {
+ IF_POLL(&ic->ic_mgtq, m0);
+ if (m0 != NULL) {
+ if (sc->tx_queued >= RT2573_TX_LIST_COUNT) {
+ ifp->if_drv_flags |= IFF_DRV_OACTIVE;
+ break;
+ }
+ IF_DEQUEUE(&ic->ic_mgtq, m0);
+
+ ni = (struct ieee80211_node *)m0->m_pkthdr.rcvif;
+ m0->m_pkthdr.rcvif = NULL;
+
+ if (ic->ic_rawbpf != NULL)
+ bpf_mtap(ic->ic_rawbpf, m0);
+
+ if (rum_tx_mgt(sc, m0, ni) != 0)
+ break;
+
+ } else {
+ if (ic->ic_state != IEEE80211_S_RUN)
+ break;
+ IFQ_POLL(&ifp->if_snd, m0);
+ if (m0 == NULL)
+ break;
+ if (sc->tx_queued >= RT2573_TX_LIST_COUNT) {
+//FIXME
+ ifp->if_drv_flags |= IFF_DRV_OACTIVE;
+ break;
+ }
+ IFQ_DEQUEUE(&ifp->if_snd, m0);
+ if (m0->m_len < sizeof(struct ether_header) &&
+ !(m0 = m_pullup(m0, sizeof(struct ether_header))))
+ continue;
+
+ eh = mtod(m0, struct ether_header *);
+ ni = ieee80211_find_txnode(ic, eh->ether_dhost);
+ if (ni == NULL) {
+ m_freem(m0);
+ continue;
+ }
+ if (ifp->if_bpf != NULL)
+ bpf_mtap(ifp->if_bpf, m0);
+ m0 = ieee80211_encap(ic, m0, ni);
+ if (m0 == NULL) {
+ ieee80211_free_node(ni);
+ continue;
+ }
+
+ if (ic->ic_rawbpf != NULL)
+ bpf_mtap(ic->ic_rawbpf, m0);
+
+ if (rum_tx_data(sc, m0, ni) != 0) {
+ ieee80211_free_node(ni);
+ ifp->if_oerrors++;
+ break;
+ }
+ }
+
+ sc->sc_tx_timer = 5;
+ ifp->if_timer = 1;
+ }
+}
+
+static void
+rum_watchdog(struct ifnet *ifp)
+{
+ struct rum_softc *sc = ifp->if_softc;
+ struct ieee80211com *ic = &sc->sc_ic;
+
+ ifp->if_timer = 0;
+
+ if (sc->sc_tx_timer > 0) {
+ if (--sc->sc_tx_timer == 0) {
+ printf("%s: device timeout\n", device_get_nameunit(sc->sc_dev));
+ /*rum_init(ifp); XXX needs a process context! */
+ ifp->if_oerrors++;
+ return;
+ }
+ ifp->if_timer = 1;
+ }
+
+ ieee80211_watchdog(ic);
+}
+
+static int
+rum_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
+{
+ struct rum_softc *sc = ifp->if_softc;
+ struct ieee80211com *ic = &sc->sc_ic;
+ int s, error = 0;
+
+ s = splnet();
+
+ switch (cmd) {
+ case SIOCSIFFLAGS:
+ if (ifp->if_flags & IFF_UP) {
+ if (ifp->if_drv_flags & IFF_DRV_RUNNING)
+ rum_update_promisc(sc);
+ else
+ rum_init(sc);
+ } else {
+ if (ifp->if_drv_flags & IFF_DRV_RUNNING)
+ rum_stop(ifp);
+ }
+ break;
+
+ default:
+ error = ieee80211_ioctl(ic, cmd, data);
+ }
+
+ if (error == ENETRESET) {
+ if ((ifp->if_flags & IFF_UP) &&
+ (ifp->if_drv_flags & IFF_DRV_RUNNING))
+ rum_init(sc);
+ error = 0;
+ }
+
+ splx(s);
+
+ return error;
+}
+
+static void
+rum_eeprom_read(struct rum_softc *sc, uint16_t addr, void *buf, int len)
+{
+ usb_device_request_t req;
+ usbd_status error;
+
+ req.bmRequestType = UT_READ_VENDOR_DEVICE;
+ req.bRequest = RT2573_READ_EEPROM;
+ USETW(req.wValue, 0);
+ USETW(req.wIndex, addr);
+ USETW(req.wLength, len);
+
+ error = usbd_do_request(sc->sc_udev, &req, buf);
+ if (error != 0) {
+ printf("%s: could not read EEPROM: %s\n",
+ device_get_nameunit(sc->sc_dev), usbd_errstr(error));
+ }
+}
+
+static uint32_t
+rum_read(struct rum_softc *sc, uint16_t reg)
+{
+ uint32_t val;
+
+ rum_read_multi(sc, reg, &val, sizeof val);
+
+ return le32toh(val);
+}
+
+static void
+rum_read_multi(struct rum_softc *sc, uint16_t reg, void *buf, int len)
+{
+ usb_device_request_t req;
+ usbd_status error;
+
+ req.bmRequestType = UT_READ_VENDOR_DEVICE;
+ req.bRequest = RT2573_READ_MULTI_MAC;
+ USETW(req.wValue, 0);
+ USETW(req.wIndex, reg);
+ USETW(req.wLength, len);
+
+ error = usbd_do_request(sc->sc_udev, &req, buf);
+ if (error != 0) {
+ printf("%s: could not multi read MAC register: %s\n",
+ device_get_nameunit(sc->sc_dev), usbd_errstr(error));
+ }
+}
+
+static void
+rum_write(struct rum_softc *sc, uint16_t reg, uint32_t val)
+{
+ uint32_t tmp = htole32(val);
+
+ rum_write_multi(sc, reg, &tmp, sizeof tmp);
+}
+
+static void
+rum_write_multi(struct rum_softc *sc, uint16_t reg, void *buf, size_t len)
+{
+ usb_device_request_t req;
+ usbd_status error;
+
+ req.bmRequestType = UT_WRITE_VENDOR_DEVICE;
+ req.bRequest = RT2573_WRITE_MULTI_MAC;
+ USETW(req.wValue, 0);
+ USETW(req.wIndex, reg);
+ USETW(req.wLength, len);
+
+ error = usbd_do_request(sc->sc_udev, &req, buf);
+ if (error != 0) {
+ printf("%s: could not multi write MAC register: %s\n",
+ device_get_nameunit(sc->sc_dev), usbd_errstr(error));
+ }
+}
+
+static void
+rum_bbp_write(struct rum_softc *sc, uint8_t reg, uint8_t val)
+{
+ uint32_t tmp;
+ int ntries;
+
+ for (ntries = 0; ntries < 5; ntries++) {
+ if (!(rum_read(sc, RT2573_PHY_CSR3) & RT2573_BBP_BUSY))
+ break;
+ }
+ if (ntries == 5) {
+ printf("%s: could not write to BBP\n", device_get_nameunit(sc->sc_dev));
+ return;
+ }
+
+ tmp = RT2573_BBP_BUSY | (reg & 0x7f) << 8 | val;
+ rum_write(sc, RT2573_PHY_CSR3, tmp);
+}
+
+static uint8_t
+rum_bbp_read(struct rum_softc *sc, uint8_t reg)
+{
+ uint32_t val;
+ int ntries;
+
+ for (ntries = 0; ntries < 5; ntries++) {
+ if (!(rum_read(sc, RT2573_PHY_CSR3) & RT2573_BBP_BUSY))
+ break;
+ }
+ if (ntries == 5) {
+ printf("%s: could not read BBP\n", device_get_nameunit(sc->sc_dev));
+ return 0;
+ }
+
+ val = RT2573_BBP_BUSY | RT2573_BBP_READ | reg << 8;
+ rum_write(sc, RT2573_PHY_CSR3, val);
+
+ for (ntries = 0; ntries < 100; ntries++) {
+ val = rum_read(sc, RT2573_PHY_CSR3);
+ if (!(val & RT2573_BBP_BUSY))
+ return val & 0xff;
+ DELAY(1);
+ }
+
+ printf("%s: could not read BBP\n", device_get_nameunit(sc->sc_dev));
+ return 0;
+}
+
+static void
+rum_rf_write(struct rum_softc *sc, uint8_t reg, uint32_t val)
+{
+ uint32_t tmp;
+ int ntries;
+
+ for (ntries = 0; ntries < 5; ntries++) {
+ if (!(rum_read(sc, RT2573_PHY_CSR4) & RT2573_RF_BUSY))
+ break;
+ }
+ if (ntries == 5) {
+ printf("%s: could not write to RF\n", device_get_nameunit(sc->sc_dev));
+ return;
+ }
+
+ tmp = RT2573_RF_BUSY | RT2573_RF_20BIT | (val & 0xfffff) << 2 |
+ (reg & 3);
+ rum_write(sc, RT2573_PHY_CSR4, tmp);
+
+ /* remember last written value in sc */
+ sc->rf_regs[reg] = val;
+
+ DPRINTFN(15, ("RF R[%u] <- 0x%05x\n", reg & 3, val & 0xfffff));
+}
+
+static void
+rum_select_antenna(struct rum_softc *sc)
+{
+ uint8_t bbp4, bbp77;
+ uint32_t tmp;
+
+ bbp4 = rum_bbp_read(sc, 4);
+ bbp77 = rum_bbp_read(sc, 77);
+
+ /* TBD */
+
+ /* make sure Rx is disabled before switching antenna */
+ tmp = rum_read(sc, RT2573_TXRX_CSR0);
+ rum_write(sc, RT2573_TXRX_CSR0, tmp | RT2573_DISABLE_RX);
+
+ rum_bbp_write(sc, 4, bbp4);
+ rum_bbp_write(sc, 77, bbp77);
+
+ rum_write(sc, RT2573_TXRX_CSR0, tmp);
+}
+
+/*
+ * Enable multi-rate retries for frames sent at OFDM rates.
+ * In 802.11b/g mode, allow fallback to CCK rates.
+ */
+static void
+rum_enable_mrr(struct rum_softc *sc)
+{
+ struct ieee80211com *ic = &sc->sc_ic;
+ uint32_t tmp;
+
+ tmp = rum_read(sc, RT2573_TXRX_CSR4);
+
+ tmp &= ~RT2573_MRR_CCK_FALLBACK;
+ if (!IEEE80211_IS_CHAN_5GHZ(ic->ic_curchan))
+ tmp |= RT2573_MRR_CCK_FALLBACK;
+ tmp |= RT2573_MRR_ENABLED;
+
+ rum_write(sc, RT2573_TXRX_CSR4, tmp);
+}
+
+static void
+rum_set_txpreamble(struct rum_softc *sc)
+{
+ uint32_t tmp;
+
+ tmp = rum_read(sc, RT2573_TXRX_CSR4);
+
+ tmp &= ~RT2573_SHORT_PREAMBLE;
+ if (sc->sc_ic.ic_flags & IEEE80211_F_SHPREAMBLE)
+ tmp |= RT2573_SHORT_PREAMBLE;
+
+ rum_write(sc, RT2573_TXRX_CSR4, tmp);
+}
+
+static void
+rum_set_basicrates(struct rum_softc *sc)
+{
+ struct ieee80211com *ic = &sc->sc_ic;
+
+ /* update basic rate set */
+ if (ic->ic_curmode == IEEE80211_MODE_11B) {
+ /* 11b basic rates: 1, 2Mbps */
+ rum_write(sc, RT2573_TXRX_CSR5, 0x3);
+ } else if (IEEE80211_IS_CHAN_5GHZ(ic->ic_bss->ni_chan)) {
+ /* 11a basic rates: 6, 12, 24Mbps */
+ rum_write(sc, RT2573_TXRX_CSR5, 0x150);
+ } else {
+ /* 11g basic rates: 1, 2, 5.5, 11, 6, 12, 24Mbps */
+ rum_write(sc, RT2573_TXRX_CSR5, 0x15f);
+ }
+}
+
+/*
+ * Reprogram MAC/BBP to switch to a new band. Values taken from the reference
+ * driver.
+ */
+static void
+rum_select_band(struct rum_softc *sc, struct ieee80211_channel *c)
+{
+ uint8_t bbp17, bbp35, bbp96, bbp97, bbp98, bbp104;
+ uint32_t tmp;
+
+ /* update all BBP registers that depend on the band */
+ bbp17 = 0x20; bbp96 = 0x48; bbp104 = 0x2c;
+ bbp35 = 0x50; bbp97 = 0x48; bbp98 = 0x48;
+ if (IEEE80211_IS_CHAN_5GHZ(c)) {
+ bbp17 += 0x08; bbp96 += 0x10; bbp104 += 0x0c;
+ bbp35 += 0x10; bbp97 += 0x10; bbp98 += 0x10;
+ }
+ if ((IEEE80211_IS_CHAN_2GHZ(c) && sc->ext_2ghz_lna) ||
+ (IEEE80211_IS_CHAN_5GHZ(c) && sc->ext_5ghz_lna)) {
+ bbp17 += 0x10; bbp96 += 0x10; bbp104 += 0x10;
+ }
+
+ sc->bbp17 = bbp17;
+ rum_bbp_write(sc, 17, bbp17);
+ rum_bbp_write(sc, 96, bbp96);
+ rum_bbp_write(sc, 104, bbp104);
+
+ if ((IEEE80211_IS_CHAN_2GHZ(c) && sc->ext_2ghz_lna) ||
+ (IEEE80211_IS_CHAN_5GHZ(c) && sc->ext_5ghz_lna)) {
+ rum_bbp_write(sc, 75, 0x80);
+ rum_bbp_write(sc, 86, 0x80);
+ rum_bbp_write(sc, 88, 0x80);
+ }
+
+ rum_bbp_write(sc, 35, bbp35);
+ rum_bbp_write(sc, 97, bbp97);
+ rum_bbp_write(sc, 98, bbp98);
+
+ tmp = rum_read(sc, RT2573_PHY_CSR0);
+ tmp &= ~(RT2573_PA_PE_2GHZ | RT2573_PA_PE_5GHZ);
+ if (IEEE80211_IS_CHAN_2GHZ(c))
+ tmp |= RT2573_PA_PE_2GHZ;
+ else
+ tmp |= RT2573_PA_PE_5GHZ;
+ rum_write(sc, RT2573_PHY_CSR0, tmp);
+
+ /* 802.11a uses a 16 microseconds short interframe space */
+ sc->sifs = IEEE80211_IS_CHAN_5GHZ(c) ? 16 : 10;
+}
+
+static void
+rum_set_chan(struct rum_softc *sc, struct ieee80211_channel *c)
+{
+ struct ieee80211com *ic = &sc->sc_ic;
+ const struct rfprog *rfprog;
+ uint8_t bbp3, bbp94 = RT2573_BBPR94_DEFAULT;
+ int8_t power;
+ u_int i, chan;
+
+ chan = ieee80211_chan2ieee(ic, c);
+ if (chan == 0 || chan == IEEE80211_CHAN_ANY)
+ return;
+
+ /* select the appropriate RF settings based on what EEPROM says */
+ rfprog = (sc->rf_rev == RT2573_RF_5225 ||
+ sc->rf_rev == RT2573_RF_2527) ? rum_rf5225 : rum_rf5226;
+
+ /* find the settings for this channel (we know it exists) */
+ for (i = 0; rfprog[i].chan != chan; i++);
+
+ power = sc->txpow[i];
+ if (power < 0) {
+ bbp94 += power;
+ power = 0;
+ } else if (power > 31) {
+ bbp94 += power - 31;
+ power = 31;
+ }
+
+ /*
+ * If we are switching from the 2GHz band to the 5GHz band or
+ * vice-versa, BBP registers need to be reprogrammed.
+ */
+ if (c->ic_flags != ic->ic_curchan->ic_flags) {
+ rum_select_band(sc, c);
+ rum_select_antenna(sc);
+ }
+ ic->ic_curchan = c;
+
+ rum_rf_write(sc, RT2573_RF1, rfprog[i].r1);
+ rum_rf_write(sc, RT2573_RF2, rfprog[i].r2);
+ rum_rf_write(sc, RT2573_RF3, rfprog[i].r3 | power << 7);
+ rum_rf_write(sc, RT2573_RF4, rfprog[i].r4 | sc->rffreq << 10);
+
+ rum_rf_write(sc, RT2573_RF1, rfprog[i].r1);
+ rum_rf_write(sc, RT2573_RF2, rfprog[i].r2);
+ rum_rf_write(sc, RT2573_RF3, rfprog[i].r3 | power << 7 | 1);
+ rum_rf_write(sc, RT2573_RF4, rfprog[i].r4 | sc->rffreq << 10);
+
+ rum_rf_write(sc, RT2573_RF1, rfprog[i].r1);
+ rum_rf_write(sc, RT2573_RF2, rfprog[i].r2);
+ rum_rf_write(sc, RT2573_RF3, rfprog[i].r3 | power << 7);
+ rum_rf_write(sc, RT2573_RF4, rfprog[i].r4 | sc->rffreq << 10);
+
+ DELAY(10);
+
+ /* enable smart mode for MIMO-capable RFs */
+ bbp3 = rum_bbp_read(sc, 3);
+
+ bbp3 &= ~RT2573_SMART_MODE;
+ if (sc->rf_rev == RT2573_RF_5225 || sc->rf_rev == RT2573_RF_2527)
+ bbp3 |= RT2573_SMART_MODE;
+
+ rum_bbp_write(sc, 3, bbp3);
+
+ if (bbp94 != RT2573_BBPR94_DEFAULT)
+ rum_bbp_write(sc, 94, bbp94);
+}
+
+/*
+ * Enable TSF synchronization and tell h/w to start sending beacons for IBSS
+ * and HostAP operating modes.
+ */
+static void
+rum_enable_tsf_sync(struct rum_softc *sc)
+{
+ struct ieee80211com *ic = &sc->sc_ic;
+ uint32_t tmp;
+
+ if (ic->ic_opmode != IEEE80211_M_STA) {
+ /*
+ * Change default 16ms TBTT adjustment to 8ms.
+ * Must be done before enabling beacon generation.
+ */
+ rum_write(sc, RT2573_TXRX_CSR10, 1 << 12 | 8);
+ }
+
+ tmp = rum_read(sc, RT2573_TXRX_CSR9) & 0xff000000;
+
+ /* set beacon interval (in 1/16ms unit) */
+ tmp |= ic->ic_bss->ni_intval * 16;
+
+ tmp |= RT2573_TSF_TICKING | RT2573_ENABLE_TBTT;
+ if (ic->ic_opmode == IEEE80211_M_STA)
+ tmp |= RT2573_TSF_MODE(1);
+ else
+ tmp |= RT2573_TSF_MODE(2) | RT2573_GENERATE_BEACON;
+
+ rum_write(sc, RT2573_TXRX_CSR9, tmp);
+}
+
+static void
+rum_update_slot(struct rum_softc *sc)
+{
+ struct ieee80211com *ic = &sc->sc_ic;
+ uint8_t slottime;
+ uint32_t tmp;
+
+ slottime = (ic->ic_flags & IEEE80211_F_SHSLOT) ? 9 : 20;
+
+ tmp = rum_read(sc, RT2573_MAC_CSR9);
+ tmp = (tmp & ~0xff) | slottime;
+ rum_write(sc, RT2573_MAC_CSR9, tmp);
+
+ DPRINTF(("setting slot time to %uus\n", slottime));
+}
+
+static void
+rum_set_bssid(struct rum_softc *sc, const uint8_t *bssid)
+{
+ uint32_t tmp;
+
+ tmp = bssid[0] | bssid[1] << 8 | bssid[2] << 16 | bssid[3] << 24;
+ rum_write(sc, RT2573_MAC_CSR4, tmp);
+
+ tmp = bssid[4] | bssid[5] << 8 | RT2573_ONE_BSSID << 16;
+ rum_write(sc, RT2573_MAC_CSR5, tmp);
+}
+
+static void
+rum_set_macaddr(struct rum_softc *sc, const uint8_t *addr)
+{
+ uint32_t tmp;
+
+ tmp = addr[0] | addr[1] << 8 | addr[2] << 16 | addr[3] << 24;
+ rum_write(sc, RT2573_MAC_CSR2, tmp);
+
+ tmp = addr[4] | addr[5] << 8 | 0xff << 16;
+ rum_write(sc, RT2573_MAC_CSR3, tmp);
+}
+
+static void
+rum_update_promisc(struct rum_softc *sc)
+{
+ struct ifnet *ifp = sc->sc_ic.ic_ifp;
+ uint32_t tmp;
+
+ tmp = rum_read(sc, RT2573_TXRX_CSR0);
+
+ tmp &= ~RT2573_DROP_NOT_TO_ME;
+ if (!(ifp->if_flags & IFF_PROMISC))
+ tmp |= RT2573_DROP_NOT_TO_ME;
+
+ rum_write(sc, RT2573_TXRX_CSR0, tmp);
+
+ DPRINTF(("%s promiscuous mode\n", (ifp->if_flags & IFF_PROMISC) ?
+ "entering" : "leaving"));
+}
+
+static const char *
+rum_get_rf(int rev)
+{
+ switch (rev) {
+ case RT2573_RF_2527: return "RT2527 (MIMO XR)";
+ case RT2573_RF_2528: return "RT2528";
+ case RT2573_RF_5225: return "RT5225 (MIMO XR)";
+ case RT2573_RF_5226: return "RT5226";
+ default: return "unknown";
+ }
+}
+
+static void
+rum_read_eeprom(struct rum_softc *sc)
+{
+ struct ieee80211com *ic = &sc->sc_ic;
+ uint16_t val;
+#ifdef RUM_DEBUG
+ int i;
+#endif
+
+ /* read MAC/BBP type */
+ rum_eeprom_read(sc, RT2573_EEPROM_MACBBP, &val, 2);
+ sc->macbbp_rev = le16toh(val);
+
+ /* read MAC address */
+ rum_eeprom_read(sc, RT2573_EEPROM_ADDRESS, ic->ic_myaddr, 6);
+
+ rum_eeprom_read(sc, RT2573_EEPROM_ANTENNA, &val, 2);
+ val = le16toh(val);
+ sc->rf_rev = (val >> 11) & 0x1f;
+ sc->hw_radio = (val >> 10) & 0x1;
+ sc->rx_ant = (val >> 4) & 0x3;
+ sc->tx_ant = (val >> 2) & 0x3;
+ sc->nb_ant = val & 0x3;
+
+ DPRINTF(("RF revision=%d\n", sc->rf_rev));
+
+ rum_eeprom_read(sc, RT2573_EEPROM_CONFIG2, &val, 2);
+ val = le16toh(val);
+ sc->ext_5ghz_lna = (val >> 6) & 0x1;
+ sc->ext_2ghz_lna = (val >> 4) & 0x1;
+
+ DPRINTF(("External 2GHz LNA=%d\nExternal 5GHz LNA=%d\n",
+ sc->ext_2ghz_lna, sc->ext_5ghz_lna));
+
+ rum_eeprom_read(sc, RT2573_EEPROM_RSSI_2GHZ_OFFSET, &val, 2);
+ val = le16toh(val);
+ if ((val & 0xff) != 0xff)
+ sc->rssi_2ghz_corr = (int8_t)(val & 0xff); /* signed */
+
+ rum_eeprom_read(sc, RT2573_EEPROM_RSSI_5GHZ_OFFSET, &val, 2);
+ val = le16toh(val);
+ if ((val & 0xff) != 0xff)
+ sc->rssi_5ghz_corr = (int8_t)(val & 0xff); /* signed */
+
+ DPRINTF(("RSSI 2GHz corr=%d\nRSSI 5GHz corr=%d\n",
+ sc->rssi_2ghz_corr, sc->rssi_5ghz_corr));
+
+ rum_eeprom_read(sc, RT2573_EEPROM_FREQ_OFFSET, &val, 2);
+ val = le16toh(val);
+ if ((val & 0xff) != 0xff)
+ sc->rffreq = val & 0xff;
+
+ DPRINTF(("RF freq=%d\n", sc->rffreq));
+
+ /* read Tx power for all a/b/g channels */
+ rum_eeprom_read(sc, RT2573_EEPROM_TXPOWER, sc->txpow, 14);
+ /* XXX default Tx power for 802.11a channels */
+ memset(sc->txpow + 14, 24, sizeof (sc->txpow) - 14);
+#ifdef RUM_DEBUG
+ for (i = 0; i < 14; i++)
+ DPRINTF(("Channel=%d Tx power=%d\n", i + 1, sc->txpow[i]));
+#endif
+
+ /* read default values for BBP registers */
+ rum_eeprom_read(sc, RT2573_EEPROM_BBP_BASE, sc->bbp_prom, 2 * 16);
+#ifdef RUM_DEBUG
+ for (i = 0; i < 14; i++) {
+ if (sc->bbp_prom[i].reg == 0 || sc->bbp_prom[i].reg == 0xff)
+ continue;
+ DPRINTF(("BBP R%d=%02x\n", sc->bbp_prom[i].reg,
+ sc->bbp_prom[i].val));
+ }
+#endif
+}
+
+static int
+rum_bbp_init(struct rum_softc *sc)
+{
+#define N(a) (sizeof (a) / sizeof ((a)[0]))
+ int i, ntries;
+ uint8_t val;
+
+ /* wait for BBP to be ready */
+ for (ntries = 0; ntries < 100; ntries++) {
+ val = rum_bbp_read(sc, 0);
+ if (val != 0 && val != 0xff)
+ break;
+ DELAY(1000);
+ }
+ if (ntries == 100) {
+ printf("%s: timeout waiting for BBP\n",
+ device_get_nameunit(sc->sc_dev));
+ return EIO;
+ }
+
+ /* initialize BBP registers to default values */
+ for (i = 0; i < N(rum_def_bbp); i++)
+ rum_bbp_write(sc, rum_def_bbp[i].reg, rum_def_bbp[i].val);
+
+ /* write vendor-specific BBP values (from EEPROM) */
+ for (i = 0; i < 16; i++) {
+ if (sc->bbp_prom[i].reg == 0 || sc->bbp_prom[i].reg == 0xff)
+ continue;
+ rum_bbp_write(sc, sc->bbp_prom[i].reg, sc->bbp_prom[i].val);
+ }
+
+ return 0;
+#undef N
+}
+
+static void
+rum_init(void *priv)
+{
+#define N(a) (sizeof (a) / sizeof ((a)[0]))
+ struct rum_softc *sc = priv;
+ struct ieee80211com *ic = &sc->sc_ic;
+ struct ifnet *ifp = ic->ic_ifp;
+ struct rum_rx_data *data;
+ uint32_t tmp;
+ usbd_status error = 0;
+ int i, ntries;
+
+// if ((sc->sc_flags & RT2573_FWLOADED) == 0) {
+// rum_attachhook(sc);
+// }
+
+ rum_stop(ifp);
+
+ /* initialize MAC registers to default values */
+ for (i = 0; i < N(rum_def_mac); i++)
+ rum_write(sc, rum_def_mac[i].reg, rum_def_mac[i].val);
+
+ /* set host ready */
+ rum_write(sc, RT2573_MAC_CSR1, 3);
+ rum_write(sc, RT2573_MAC_CSR1, 0);
+
+ /* wait for BBP/RF to wakeup */
+ for (ntries = 0; ntries < 1000; ntries++) {
+ if (rum_read(sc, RT2573_MAC_CSR12) & 8)
+ break;
+ rum_write(sc, RT2573_MAC_CSR12, 4); /* force wakeup */
+ DELAY(1000);
+ }
+ if (ntries == 1000) {
+ printf("%s: timeout waiting for BBP/RF to wakeup\n",
+ device_get_nameunit(sc->sc_dev));
+ goto fail;
+ }
+
+ if ((error = rum_bbp_init(sc)) != 0)
+ goto fail;
+
+ /* select default channel */
+ rum_select_band(sc, ic->ic_curchan);
+ rum_select_antenna(sc);
+ rum_set_chan(sc, ic->ic_curchan);
+
+ /* clear STA registers */
+ rum_read_multi(sc, RT2573_STA_CSR0, sc->sta, sizeof sc->sta);
+
+ IEEE80211_ADDR_COPY(ic->ic_myaddr, IF_LLADDR(ifp));
+ rum_set_macaddr(sc, ic->ic_myaddr);
+
+ /* initialize ASIC */
+ rum_write(sc, RT2573_MAC_CSR1, 4);
+
+ /*
+ * Allocate xfer for AMRR statistics requests.
+ */
+ sc->amrr_xfer = usbd_alloc_xfer(sc->sc_udev);
+ if (sc->amrr_xfer == NULL) {
+ printf("%s: could not allocate AMRR xfer\n",
+ device_get_nameunit(sc->sc_dev));
+ goto fail;
+ }
+
+ /*
+ * Open Tx and Rx USB bulk pipes.
+ */
+ error = usbd_open_pipe(sc->sc_iface, sc->sc_tx_no, USBD_EXCLUSIVE_USE,
+ &sc->sc_tx_pipeh);
+ if (error != 0) {
+ printf("%s: could not open Tx pipe: %s\n",
+ device_get_nameunit(sc->sc_dev), usbd_errstr(error));
+ goto fail;
+ }
+
+ error = usbd_open_pipe(sc->sc_iface, sc->sc_rx_no, USBD_EXCLUSIVE_USE,
+ &sc->sc_rx_pipeh);
+ if (error != 0) {
+ printf("%s: could not open Rx pipe: %s\n",
+ device_get_nameunit(sc->sc_dev), usbd_errstr(error));
+ goto fail;
+ }
+
+ /*
+ * Allocate Tx and Rx xfer queues.
+ */
+ error = rum_alloc_tx_list(sc);
+ if (error != 0) {
+ printf("%s: could not allocate Tx list\n",
+ device_get_nameunit(sc->sc_dev));
+ goto fail;
+ }
+
+ error = rum_alloc_rx_list(sc);
+ if (error != 0) {
+ printf("%s: could not allocate Rx list\n",
+ device_get_nameunit(sc->sc_dev));
+ goto fail;
+ }
+
+ /*
+ * Start up the receive pipe.
+ */
+ for (i = 0; i < RT2573_RX_LIST_COUNT; i++) {
+ data = &sc->rx_data[i];
+
+ usbd_setup_xfer(data->xfer, sc->sc_rx_pipeh, data, data->buf,
+ MCLBYTES, USBD_SHORT_XFER_OK, USBD_NO_TIMEOUT, rum_rxeof);
+ usbd_transfer(data->xfer);
+ }
+
+ /* update Rx filter */
+ tmp = rum_read(sc, RT2573_TXRX_CSR0) & 0xffff;
+
+ tmp |= RT2573_DROP_PHY_ERROR | RT2573_DROP_CRC_ERROR;
+ if (ic->ic_opmode != IEEE80211_M_MONITOR) {
+ tmp |= RT2573_DROP_CTL | RT2573_DROP_VER_ERROR |
+ RT2573_DROP_ACKCTS;
+ if (ic->ic_opmode != IEEE80211_M_HOSTAP)
+ tmp |= RT2573_DROP_TODS;
+ if (!(ifp->if_flags & IFF_PROMISC))
+ tmp |= RT2573_DROP_NOT_TO_ME;
+ }
+ rum_write(sc, RT2573_TXRX_CSR0, tmp);
+
+ ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
+ ifp->if_drv_flags |= IFF_DRV_RUNNING;
+
+ if (ic->ic_opmode == IEEE80211_M_MONITOR)
+ ieee80211_new_state(ic, IEEE80211_S_RUN, -1);
+ else
+ ieee80211_new_state(ic, IEEE80211_S_SCAN, -1);
+
+ return;
+
+fail: rum_stop(ifp);
+ return;
+#undef N
+}
+
+static void
+rum_stop(struct ifnet *ifp)
+{
+ struct rum_softc *sc = ifp->if_softc;
+ struct ieee80211com *ic = &sc->sc_ic;
+ uint32_t tmp;
+
+ ieee80211_new_state(ic, IEEE80211_S_INIT, -1); /* free all nodes */
+
+ sc->sc_tx_timer = 0;
+ ifp->if_timer = 0;
+ ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE);
+
+ /* disable Rx */
+ tmp = rum_read(sc, RT2573_TXRX_CSR0);
+ rum_write(sc, RT2573_TXRX_CSR0, tmp | RT2573_DISABLE_RX);
+
+ /* reset ASIC */
+ rum_write(sc, RT2573_MAC_CSR1, 3);
+ rum_write(sc, RT2573_MAC_CSR1, 0);
+
+ if (sc->sc_rx_pipeh != NULL) {
+ usbd_abort_pipe(sc->sc_rx_pipeh);
+ usbd_close_pipe(sc->sc_rx_pipeh);
+ sc->sc_rx_pipeh = NULL;
+ }
+
+ if (sc->sc_tx_pipeh != NULL) {
+ usbd_abort_pipe(sc->sc_tx_pipeh);
+ usbd_close_pipe(sc->sc_tx_pipeh);
+ sc->sc_tx_pipeh = NULL;
+ }
+
+ rum_free_rx_list(sc);
+ rum_free_tx_list(sc);
+}
+
+static int
+rum_load_microcode(struct rum_softc *sc, const u_char *ucode, size_t size)
+{
+ usb_device_request_t req;
+ uint16_t reg = RT2573_MCU_CODE_BASE;
+ usbd_status error;
+
+ /* copy firmware image into NIC */
+ for (; size >= 4; reg += 4, ucode += 4, size -= 4)
+ rum_write(sc, reg, UGETDW(ucode));
+
+ req.bmRequestType = UT_WRITE_VENDOR_DEVICE;
+ req.bRequest = RT2573_MCU_CNTL;
+ USETW(req.wValue, RT2573_MCU_RUN);
+ USETW(req.wIndex, 0);
+ USETW(req.wLength, 0);
+
+ error = usbd_do_request(sc->sc_udev, &req, NULL);
+ if (error != 0) {
+ printf("%s: could not run firmware: %s\n",
+ device_get_nameunit(sc->sc_dev), usbd_errstr(error));
+ }
+ return error;
+}
+
+static int
+rum_prepare_beacon(struct rum_softc *sc)
+{
+ struct ieee80211com *ic = &sc->sc_ic;
+ struct rum_tx_desc desc;
+ struct mbuf *m0;
+ int rate;
+
+ m0 = ieee80211_beacon_alloc(ic, ic->ic_bss, &sc->sc_bo);
+ if (m0 == NULL) {
+ printf("%s: could not allocate beacon frame\n",
+ device_get_nameunit(sc->sc_dev));
+ return ENOBUFS;
+ }
+
+ /* send beacons at the lowest available rate */
+ rate = IEEE80211_IS_CHAN_5GHZ(ic->ic_curchan) ? 12 : 2;
+
+ rum_setup_tx_desc(sc, &desc, RT2573_TX_TIMESTAMP, RT2573_TX_HWSEQ,
+ m0->m_pkthdr.len, rate);
+
+ /* copy the first 24 bytes of Tx descriptor into NIC memory */
+ rum_write_multi(sc, RT2573_HW_BEACON_BASE0, (uint8_t *)&desc, 24);
+
+ /* copy beacon header and payload into NIC memory */
+ rum_write_multi(sc, RT2573_HW_BEACON_BASE0 + 24, mtod(m0, uint8_t *),
+ m0->m_pkthdr.len);
+
+ m_freem(m0);
+
+ return 0;
+}
+
+#define RUM_AMRR_MIN_SUCCESS_THRESHOLD 1
+#define RUM_AMRR_MAX_SUCCESS_THRESHOLD 10
+
+static void
+rum_amrr_start(struct rum_softc *sc, struct ieee80211_node *ni)
+{
+ struct rum_amrr *amrr = &sc->amrr;
+ int i;
+
+ /* clear statistic registers (STA_CSR0 to STA_CSR5) */
+ rum_read_multi(sc, RT2573_STA_CSR0, sc->sta, sizeof sc->sta);
+
+ amrr->success = 0;
+ amrr->recovery = 0;
+ amrr->txcnt = amrr->retrycnt = 0;
+ amrr->success_threshold = RUM_AMRR_MIN_SUCCESS_THRESHOLD;
+
+// ieee80211_amrr_node_init(&sc->amrr, &sc->amn);
+
+ /* set rate to some reasonable initial value */
+ for (i = ni->ni_rates.rs_nrates - 1;
+ i > 0 && (ni->ni_rates.rs_rates[i] & IEEE80211_RATE_VAL) > 72;
+ i--);
+ ni->ni_txrate = i;
+
+ callout_reset(&sc->amrr_ch, hz, rum_amrr_timeout, sc);
+}
+
+static void
+rum_amrr_timeout(void *arg)
+{
+ struct rum_softc *sc = arg;
+ usb_device_request_t req;
+ int s;
+
+ s = splusb();
+
+ /*
+ * Asynchronously read statistic registers (cleared by read).
+ */
+ req.bmRequestType = UT_READ_VENDOR_DEVICE;
+ req.bRequest = RT2573_READ_MULTI_MAC;
+ USETW(req.wValue, 0);
+ USETW(req.wIndex, RT2573_STA_CSR0);
+ USETW(req.wLength, sizeof sc->sta);
+
+ usbd_setup_default_xfer(sc->amrr_xfer, sc->sc_udev, sc,
+ USBD_DEFAULT_TIMEOUT, &req, sc->sta, sizeof sc->sta, 0,
+ rum_amrr_update);
+ (void)usbd_transfer(sc->amrr_xfer);
+
+ splx(s);
+}
+
+static void
+rum_amrr_update(usbd_xfer_handle xfer, usbd_private_handle priv,
+ usbd_status status)
+{
+ struct rum_softc *sc = (struct rum_softc *)priv;
+ struct rum_amrr *amrr = &sc->amrr;
+ struct ifnet *ifp = sc->sc_ifp; //FIXME1
+
+ if (status != USBD_NORMAL_COMPLETION) {
+ device_printf(sc->sc_dev, "could not retrieve Tx statistics - "
+ "cancelling automatic rate control\n");
+ return;
+ }
+
+ /* count TX retry-fail as Tx errors */
+ ifp->if_oerrors += le32toh(sc->sta[5]) >> 16;
+
+ amrr->retrycnt =
+ (le32toh(sc->sta[4]) >> 16) + /* TX one-retry ok count */
+ (le32toh(sc->sta[5]) & 0xffff) + /* TX more-retry ok count */
+ (le32toh(sc->sta[5]) >> 16); /* TX retry-fail count */
+
+ amrr->txcnt =
+ amrr->retrycnt +
+ (le32toh(sc->sta[4]) & 0xffff); /* TX no-retry ok count */
+
+ rum_ratectl(amrr, sc->sc_ic.ic_bss);
+
+ callout_reset(&sc->amrr_ch, hz, rum_amrr_timeout, sc);
+}
+
+/*-
+ * Naive implementation of the Adaptive Multi Rate Retry algorithm:
+ * "IEEE 802.11 Rate Adaptation: A Practical Approach"
+ * Mathieu Lacage, Hossein Manshaei, Thierry Turletti
+ * INRIA Sophia - Projet Planete
+ * http://www-sop.inria.fr/rapports/sophia/RR-5208.html
+ *
+ * This algorithm is particularly well suited for rum since it does not
+ * require per-frame retry statistics. Note however that since h/w does
+ * not provide per-frame stats, we can't do per-node rate adaptation and
+ * thus automatic rate adaptation is only enabled in STA operating mode.
+ */
+#define is_success(amrr) \
+ ((amrr)->retrycnt < (amrr)->txcnt / 10)
+#define is_failure(amrr) \
+ ((amrr)->retrycnt > (amrr)->txcnt / 3)
+#define is_enough(amrr) \
+ ((amrr)->txcnt > 10)
+#define is_min_rate(ni) \
+ ((ni)->ni_txrate == 0)
+#define is_max_rate(ni) \
+ ((ni)->ni_txrate == (ni)->ni_rates.rs_nrates - 1)
+#define increase_rate(ni) \
+ ((ni)->ni_txrate++)
+#define decrease_rate(ni) \
+ ((ni)->ni_txrate--)
+#define reset_cnt(amrr) \
+ do { (amrr)->txcnt = (amrr)->retrycnt = 0; } while (0)
+static void
+rum_ratectl(struct rum_amrr *amrr, struct ieee80211_node *ni)
+{
+ int need_change = 0;
+
+ if (is_success(amrr) && is_enough(amrr)) {
+ amrr->success++;
+ if (amrr->success >= amrr->success_threshold &&
+ !is_max_rate(ni)) {
+ amrr->recovery = 1;
+ amrr->success = 0;
+ increase_rate(ni);
+ need_change = 1;
+ } else {
+ amrr->recovery = 0;
+ }
+ } else if (is_failure(amrr)) {
+ amrr->success = 0;
+ if (!is_min_rate(ni)) {
+ if (amrr->recovery) {
+ amrr->success_threshold *= 2;
+ if (amrr->success_threshold >
+ RUM_AMRR_MAX_SUCCESS_THRESHOLD)
+ amrr->success_threshold =
+ RUM_AMRR_MAX_SUCCESS_THRESHOLD;
+ } else {
+ amrr->success_threshold =
+ RUM_AMRR_MIN_SUCCESS_THRESHOLD;
+ }
+ decrease_rate(ni);
+ need_change = 1;
+ }
+ amrr->recovery = 0; /* original paper was incorrect */
+ }
+
+ if (is_enough(amrr) || need_change)
+ reset_cnt(amrr);
+}
+
+
+/*
+int
+rum_activate(device_ptr_t self, enum devact act)
+{
+ switch (act) {
+ case DVACT_ACTIVATE:
+ return EOPNOTSUPP;
+
+ case DVACT_DEACTIVATE:
+ //if_deactivate(&sc->sc_ic.ic_if);
+ break;
+ }
+
+ return 0;
+}
+*/
+
+DRIVER_MODULE(rum, uhub, rum_driver, rum_devclass, usbd_driver_load, 0);
Index: sys/dev/usb/if_rumreg.h
===================================================================
RCS file: sys/dev/usb/if_rumreg.h
diff -N sys/dev/usb/if_rumreg.h
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ sys/dev/usb/if_rumreg.h 1 Feb 2007 11:26:03 -0000
@@ -0,0 +1,390 @@
+/* $OpenBSD: if_rumreg.h,v 1.12 2006/08/09 08:21:08 damien Exp $ */
+
+/*-
+ * Copyright (c) 2005, 2006 Damien Bergamini <damien.bergamini at free.fr>
+ * Copyright (c) 2006 Niall O'Higgins <niallo at openbsd.org>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#define RT2573_TX_DESC_SIZE (sizeof (struct rum_tx_desc))
+#define RT2573_RX_DESC_SIZE (sizeof (struct rum_rx_desc))
+
+#define RT2573_CONFIG_NO 1
+#define RT2573_IFACE_INDEX 0
+
+#define RT2573_MCU_CNTL 0x01
+#define RT2573_WRITE_MAC 0x02
+#define RT2573_READ_MAC 0x03
+#define RT2573_WRITE_MULTI_MAC 0x06
+#define RT2573_READ_MULTI_MAC 0x07
+#define RT2573_READ_EEPROM 0x09
+#define RT2573_WRITE_LED 0x0a
+
+/*
+ * Control and status registers.
+ */
+#define RT2573_AIFSN_CSR 0x0400
+#define RT2573_CWMIN_CSR 0x0404
+#define RT2573_CWMAX_CSR 0x0408
+#define RT2573_MCU_CODE_BASE 0x0800
+#define RT2573_HW_BEACON_BASE0 0x2400
+#define RT2573_MAC_CSR0 0x3000
+#define RT2573_MAC_CSR1 0x3004
+#define RT2573_MAC_CSR2 0x3008
+#define RT2573_MAC_CSR3 0x300c
+#define RT2573_MAC_CSR4 0x3010
+#define RT2573_MAC_CSR5 0x3014
+#define RT2573_MAC_CSR6 0x3018
+#define RT2573_MAC_CSR7 0x301c
+#define RT2573_MAC_CSR8 0x3020
+#define RT2573_MAC_CSR9 0x3024
+#define RT2573_MAC_CSR10 0x3028
+#define RT2573_MAC_CSR11 0x302c
+#define RT2573_MAC_CSR12 0x3030
+#define RT2573_MAC_CSR13 0x3034
+#define RT2573_MAC_CSR14 0x3038
+#define RT2573_MAC_CSR15 0x303c
+#define RT2573_TXRX_CSR0 0x3040
+#define RT2573_TXRX_CSR1 0x3044
+#define RT2573_TXRX_CSR2 0x3048
+#define RT2573_TXRX_CSR3 0x304c
+#define RT2573_TXRX_CSR4 0x3050
+#define RT2573_TXRX_CSR5 0x3054
+#define RT2573_TXRX_CSR6 0x3058
+#define RT2573_TXRX_CSR7 0x305c
+#define RT2573_TXRX_CSR8 0x3060
+#define RT2573_TXRX_CSR9 0x3064
+#define RT2573_TXRX_CSR10 0x3068
+#define RT2573_TXRX_CSR11 0x306c
+#define RT2573_TXRX_CSR12 0x3070
+#define RT2573_TXRX_CSR13 0x3074
+#define RT2573_TXRX_CSR14 0x3078
+#define RT2573_TXRX_CSR15 0x307c
+#define RT2573_PHY_CSR0 0x3080
+#define RT2573_PHY_CSR1 0x3084
+#define RT2573_PHY_CSR2 0x3088
+#define RT2573_PHY_CSR3 0x308c
+#define RT2573_PHY_CSR4 0x3090
+#define RT2573_PHY_CSR5 0x3094
+#define RT2573_PHY_CSR6 0x3098
+#define RT2573_PHY_CSR7 0x309c
+#define RT2573_SEC_CSR0 0x30a0
+#define RT2573_SEC_CSR1 0x30a4
+#define RT2573_SEC_CSR2 0x30a8
+#define RT2573_SEC_CSR3 0x30ac
+#define RT2573_SEC_CSR4 0x30b0
+#define RT2573_SEC_CSR5 0x30b4
+#define RT2573_STA_CSR0 0x30c0
+#define RT2573_STA_CSR1 0x30c4
+#define RT2573_STA_CSR2 0x30c8
+#define RT2573_STA_CSR3 0x30cc
+#define RT2573_STA_CSR4 0x30d0
+#define RT2573_STA_CSR5 0x30d4
+
+
+/* possible flags for register RT2573_MAC_CSR1 */
+#define RT2573_RESET_ASIC (1 << 0)
+#define RT2573_RESET_BBP (1 << 1)
+#define RT2573_HOST_READY (1 << 2)
+
+/* possible flags for register MAC_CSR5 */
+#define RT2573_ONE_BSSID 3
+
+/* possible flags for register TXRX_CSR0 */
+/* Tx filter flags are in the low 16 bits */
+#define RT2573_AUTO_TX_SEQ (1 << 15)
+/* Rx filter flags are in the high 16 bits */
+#define RT2573_DISABLE_RX (1 << 16)
+#define RT2573_DROP_CRC_ERROR (1 << 17)
+#define RT2573_DROP_PHY_ERROR (1 << 18)
+#define RT2573_DROP_CTL (1 << 19)
+#define RT2573_DROP_NOT_TO_ME (1 << 20)
+#define RT2573_DROP_TODS (1 << 21)
+#define RT2573_DROP_VER_ERROR (1 << 22)
+#define RT2573_DROP_MULTICAST (1 << 23)
+#define RT2573_DROP_BROADCAST (1 << 24)
+#define RT2573_DROP_ACKCTS (1 << 25)
+
+/* possible flags for register TXRX_CSR4 */
+#define RT2573_SHORT_PREAMBLE (1 << 18)
+#define RT2573_MRR_ENABLED (1 << 19)
+#define RT2573_MRR_CCK_FALLBACK (1 << 22)
+
+/* possible flags for register TXRX_CSR9 */
+#define RT2573_TSF_TICKING (1 << 16)
+#define RT2573_TSF_MODE(x) (((x) & 0x3) << 17)
+/* TBTT stands for Target Beacon Transmission Time */
+#define RT2573_ENABLE_TBTT (1 << 19)
+#define RT2573_GENERATE_BEACON (1 << 20)
+
+/* possible flags for register PHY_CSR0 */
+#define RT2573_PA_PE_2GHZ (1 << 16)
+#define RT2573_PA_PE_5GHZ (1 << 17)
+
+/* possible flags for register PHY_CSR3 */
+#define RT2573_BBP_READ (1 << 15)
+#define RT2573_BBP_BUSY (1 << 16)
+/* possible flags for register PHY_CSR4 */
+#define RT2573_RF_20BIT (20 << 24)
+#define RT2573_RF_BUSY (1 << 31)
+
+/* LED values */
+#define RT2573_LED_RADIO (1 << 8)
+#define RT2573_LED_G (1 << 9)
+#define RT2573_LED_A (1 << 10)
+#define RT2573_LED_ON 0x1e1e
+#define RT2573_LED_OFF 0x0
+
+#define RT2573_MCU_RUN (1 << 3)
+
+#define RT2573_SMART_MODE (1 << 0)
+
+#define RT2573_BBPR94_DEFAULT 6
+
+#define RT2573_BBP_WRITE (1 << 15)
+
+/* dual-band RF */
+#define RT2573_RF_5226 1
+#define RT2573_RF_5225 3
+/* single-band RF */
+#define RT2573_RF_2528 2
+#define RT2573_RF_2527 4
+
+#define RT2573_BBP_VERSION 0
+
+struct rum_tx_desc {
+ uint32_t flags;
+#define RT2573_TX_BURST (1 << 0)
+#define RT2573_TX_VALID (1 << 1)
+#define RT2573_TX_MORE_FRAG (1 << 2)
+#define RT2573_TX_ACK (1 << 3)
+#define RT2573_TX_TIMESTAMP (1 << 4)
+#define RT2573_TX_OFDM (1 << 5)
+#define RT2573_TX_IFS_SIFS (1 << 6)
+#define RT2573_TX_LONG_RETRY (1 << 7)
+
+ uint16_t wme;
+#define RT2573_QID(v) (v)
+#define RT2573_AIFSN(v) ((v) << 4)
+#define RT2573_LOGCWMIN(v) ((v) << 8)
+#define RT2573_LOGCWMAX(v) ((v) << 12)
+
+ uint16_t xflags;
+#define RT2573_TX_HWSEQ (1 << 12)
+
+ uint8_t plcp_signal;
+ uint8_t plcp_service;
+#define RT2573_PLCP_LENGEXT 0x80
+
+ uint8_t plcp_length_lo;
+ uint8_t plcp_length_hi;
+
+ uint32_t iv;
+ uint32_t eiv;
+
+ uint8_t offset;
+ uint8_t qid;
+ uint8_t txpower;
+#define RT2573_DEFAULT_TXPOWER 0
+
+ uint8_t reserved;
+} __packed;
+
+struct rum_rx_desc {
+ uint32_t flags;
+#define RT2573_RX_BUSY (1 << 0)
+#define RT2573_RX_DROP (1 << 1)
+#define RT2573_RX_CRC_ERROR (1 << 6)
+#define RT2573_RX_OFDM (1 << 7)
+
+ uint8_t rate;
+ uint8_t rssi;
+ uint8_t reserved1;
+ uint8_t offset;
+ uint32_t iv;
+ uint32_t eiv;
+ uint32_t reserved2[2];
+} __packed;
+
+#define RT2573_RF1 0
+#define RT2573_RF2 2
+#define RT2573_RF3 1
+#define RT2573_RF4 3
+
+#define RT2573_EEPROM_MACBBP 0x0000
+#define RT2573_EEPROM_ADDRESS 0x0004
+#define RT2573_EEPROM_ANTENNA 0x0020
+#define RT2573_EEPROM_CONFIG2 0x0022
+#define RT2573_EEPROM_BBP_BASE 0x0026
+#define RT2573_EEPROM_TXPOWER 0x0046
+#define RT2573_EEPROM_FREQ_OFFSET 0x005e
+#define RT2573_EEPROM_RSSI_2GHZ_OFFSET 0x009a
+#define RT2573_EEPROM_RSSI_5GHZ_OFFSET 0x009c
+
+/*
+ * Default values for MAC registers; values taken from the reference driver.
+ */
+#define RT2573_DEF_MAC \
+ { RT2573_TXRX_CSR0, 0x025fb032 }, \
+ { RT2573_TXRX_CSR1, 0x9eaa9eaf }, \
+ { RT2573_TXRX_CSR2, 0x8a8b8c8d }, \
+ { RT2573_TXRX_CSR3, 0x00858687 }, \
+ { RT2573_TXRX_CSR7, 0x2e31353b }, \
+ { RT2573_TXRX_CSR8, 0x2a2a2a2c }, \
+ { RT2573_TXRX_CSR15, 0x0000000f }, \
+ { RT2573_MAC_CSR6, 0x00000fff }, \
+ { RT2573_MAC_CSR8, 0x016c030a }, \
+ { RT2573_MAC_CSR10, 0x00000718 }, \
+ { RT2573_MAC_CSR12, 0x00000004 }, \
+ { RT2573_MAC_CSR13, 0x00007f00 }, \
+ { RT2573_SEC_CSR0, 0x00000000 }, \
+ { RT2573_SEC_CSR1, 0x00000000 }, \
+ { RT2573_SEC_CSR5, 0x00000000 }, \
+ { RT2573_PHY_CSR1, 0x000023b0 }, \
+ { RT2573_PHY_CSR5, 0x00040a06 }, \
+ { RT2573_PHY_CSR6, 0x00080606 }, \
+ { RT2573_PHY_CSR7, 0x00000408 }, \
+ { RT2573_AIFSN_CSR, 0x00002273 }, \
+ { RT2573_CWMIN_CSR, 0x00002344 }, \
+ { RT2573_CWMAX_CSR, 0x000034aa }
+
+/*
+ * Default values for BBP registers; values taken from the reference driver.
+ */
+#define RT2573_DEF_BBP \
+ { 3, 0x80 }, \
+ { 15, 0x30 }, \
+ { 17, 0x20 }, \
+ { 21, 0xc8 }, \
+ { 22, 0x38 }, \
+ { 23, 0x06 }, \
+ { 24, 0xfe }, \
+ { 25, 0x0a }, \
+ { 26, 0x0d }, \
+ { 32, 0x0b }, \
+ { 34, 0x12 }, \
+ { 37, 0x07 }, \
+ { 39, 0xf8 }, \
+ { 41, 0x60 }, \
+ { 53, 0x10 }, \
+ { 54, 0x18 }, \
+ { 60, 0x10 }, \
+ { 61, 0x04 }, \
+ { 62, 0x04 }, \
+ { 75, 0xfe }, \
+ { 86, 0xfe }, \
+ { 88, 0xfe }, \
+ { 90, 0x0f }, \
+ { 99, 0x00 }, \
+ { 102, 0x16 }, \
+ { 107, 0x04 }
+
+/*
+ * Default settings for RF registers; values taken from the reference driver.
+ */
+#define RT2573_RF5226 \
+ { 1, 0x00b03, 0x001e1, 0x1a014, 0x30282 }, \
+ { 2, 0x00b03, 0x001e1, 0x1a014, 0x30287 }, \
+ { 3, 0x00b03, 0x001e2, 0x1a014, 0x30282 }, \
+ { 4, 0x00b03, 0x001e2, 0x1a014, 0x30287 }, \
+ { 5, 0x00b03, 0x001e3, 0x1a014, 0x30282 }, \
+ { 6, 0x00b03, 0x001e3, 0x1a014, 0x30287 }, \
+ { 7, 0x00b03, 0x001e4, 0x1a014, 0x30282 }, \
+ { 8, 0x00b03, 0x001e4, 0x1a014, 0x30287 }, \
+ { 9, 0x00b03, 0x001e5, 0x1a014, 0x30282 }, \
+ { 10, 0x00b03, 0x001e5, 0x1a014, 0x30287 }, \
+ { 11, 0x00b03, 0x001e6, 0x1a014, 0x30282 }, \
+ { 12, 0x00b03, 0x001e6, 0x1a014, 0x30287 }, \
+ { 13, 0x00b03, 0x001e7, 0x1a014, 0x30282 }, \
+ { 14, 0x00b03, 0x001e8, 0x1a014, 0x30284 }, \
+ \
+ { 34, 0x00b03, 0x20266, 0x36014, 0x30282 }, \
+ { 38, 0x00b03, 0x20267, 0x36014, 0x30284 }, \
+ { 42, 0x00b03, 0x20268, 0x36014, 0x30286 }, \
+ { 46, 0x00b03, 0x20269, 0x36014, 0x30288 }, \
+ \
+ { 36, 0x00b03, 0x00266, 0x26014, 0x30288 }, \
+ { 40, 0x00b03, 0x00268, 0x26014, 0x30280 }, \
+ { 44, 0x00b03, 0x00269, 0x26014, 0x30282 }, \
+ { 48, 0x00b03, 0x0026a, 0x26014, 0x30284 }, \
+ { 52, 0x00b03, 0x0026b, 0x26014, 0x30286 }, \
+ { 56, 0x00b03, 0x0026c, 0x26014, 0x30288 }, \
+ { 60, 0x00b03, 0x0026e, 0x26014, 0x30280 }, \
+ { 64, 0x00b03, 0x0026f, 0x26014, 0x30282 }, \
+ \
+ { 100, 0x00b03, 0x0028a, 0x2e014, 0x30280 }, \
+ { 104, 0x00b03, 0x0028b, 0x2e014, 0x30282 }, \
+ { 108, 0x00b03, 0x0028c, 0x2e014, 0x30284 }, \
+ { 112, 0x00b03, 0x0028d, 0x2e014, 0x30286 }, \
+ { 116, 0x00b03, 0x0028e, 0x2e014, 0x30288 }, \
+ { 120, 0x00b03, 0x002a0, 0x2e014, 0x30280 }, \
+ { 124, 0x00b03, 0x002a1, 0x2e014, 0x30282 }, \
+ { 128, 0x00b03, 0x002a2, 0x2e014, 0x30284 }, \
+ { 132, 0x00b03, 0x002a3, 0x2e014, 0x30286 }, \
+ { 136, 0x00b03, 0x002a4, 0x2e014, 0x30288 }, \
+ { 140, 0x00b03, 0x002a6, 0x2e014, 0x30280 }, \
+ \
+ { 149, 0x00b03, 0x002a8, 0x2e014, 0x30287 }, \
+ { 153, 0x00b03, 0x002a9, 0x2e014, 0x30289 }, \
+ { 157, 0x00b03, 0x002ab, 0x2e014, 0x30281 }, \
+ { 161, 0x00b03, 0x002ac, 0x2e014, 0x30283 }, \
+ { 165, 0x00b03, 0x002ad, 0x2e014, 0x30285 }
+
+#define RT2573_RF5225 \
+ { 1, 0x00b33, 0x011e1, 0x1a014, 0x30282 }, \
+ { 2, 0x00b33, 0x011e1, 0x1a014, 0x30287 }, \
+ { 3, 0x00b33, 0x011e2, 0x1a014, 0x30282 }, \
+ { 4, 0x00b33, 0x011e2, 0x1a014, 0x30287 }, \
+ { 5, 0x00b33, 0x011e3, 0x1a014, 0x30282 }, \
+ { 6, 0x00b33, 0x011e3, 0x1a014, 0x30287 }, \
+ { 7, 0x00b33, 0x011e4, 0x1a014, 0x30282 }, \
+ { 8, 0x00b33, 0x011e4, 0x1a014, 0x30287 }, \
+ { 9, 0x00b33, 0x011e5, 0x1a014, 0x30282 }, \
+ { 10, 0x00b33, 0x011e5, 0x1a014, 0x30287 }, \
+ { 11, 0x00b33, 0x011e6, 0x1a014, 0x30282 }, \
+ { 12, 0x00b33, 0x011e6, 0x1a014, 0x30287 }, \
+ { 13, 0x00b33, 0x011e7, 0x1a014, 0x30282 }, \
+ { 14, 0x00b33, 0x011e8, 0x1a014, 0x30284 }, \
+ \
+ { 34, 0x00b33, 0x01266, 0x26014, 0x30282 }, \
+ { 38, 0x00b33, 0x01267, 0x26014, 0x30284 }, \
+ { 42, 0x00b33, 0x01268, 0x26014, 0x30286 }, \
+ { 46, 0x00b33, 0x01269, 0x26014, 0x30288 }, \
+ \
+ { 36, 0x00b33, 0x01266, 0x26014, 0x30288 }, \
+ { 40, 0x00b33, 0x01268, 0x26014, 0x30280 }, \
+ { 44, 0x00b33, 0x01269, 0x26014, 0x30282 }, \
+ { 48, 0x00b33, 0x0126a, 0x26014, 0x30284 }, \
+ { 52, 0x00b33, 0x0126b, 0x26014, 0x30286 }, \
+ { 56, 0x00b33, 0x0126c, 0x26014, 0x30288 }, \
+ { 60, 0x00b33, 0x0126e, 0x26014, 0x30280 }, \
+ { 64, 0x00b33, 0x0126f, 0x26014, 0x30282 }, \
+ \
+ { 100, 0x00b33, 0x0128a, 0x2e014, 0x30280 }, \
+ { 104, 0x00b33, 0x0128b, 0x2e014, 0x30282 }, \
+ { 108, 0x00b33, 0x0128c, 0x2e014, 0x30284 }, \
+ { 112, 0x00b33, 0x0128d, 0x2e014, 0x30286 }, \
+ { 116, 0x00b33, 0x0128e, 0x2e014, 0x30288 }, \
+ { 120, 0x00b33, 0x012a0, 0x2e014, 0x30280 }, \
+ { 124, 0x00b33, 0x012a1, 0x2e014, 0x30282 }, \
+ { 128, 0x00b33, 0x012a2, 0x2e014, 0x30284 }, \
+ { 132, 0x00b33, 0x012a3, 0x2e014, 0x30286 }, \
+ { 136, 0x00b33, 0x012a4, 0x2e014, 0x30288 }, \
+ { 140, 0x00b33, 0x012a6, 0x2e014, 0x30280 }, \
+ \
+ { 149, 0x00b33, 0x012a8, 0x2e014, 0x30287 }, \
+ { 153, 0x00b33, 0x012a9, 0x2e014, 0x30289 }, \
+ { 157, 0x00b33, 0x012ab, 0x2e014, 0x30281 }, \
+ { 161, 0x00b33, 0x012ac, 0x2e014, 0x30283 }, \
+ { 165, 0x00b33, 0x012ad, 0x2e014, 0x30285 }
Index: sys/dev/usb/if_rumvar.h
===================================================================
RCS file: sys/dev/usb/if_rumvar.h
diff -N sys/dev/usb/if_rumvar.h
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ sys/dev/usb/if_rumvar.h 1 Feb 2007 11:26:03 -0000
@@ -0,0 +1,158 @@
+/* $OpenBSD: if_rumvar.h,v 1.6 2006/08/18 15:11:12 damien Exp $ */
+
+/*-
+ * Copyright (c) 2005, 2006 Damien Bergamini <damien.bergamini at free.fr>
+ * Copyright (c) 2006 Niall O'Higgins <niallo at openbsd.org>
+ * Copyright (c) 2006, 2007 Valery V.Chikalov <valera at chikalov.dp.ua>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#define RT2573_RX_LIST_COUNT 1
+#define RT2573_TX_LIST_COUNT 1
+
+struct rum_rx_radiotap_header {
+ struct ieee80211_radiotap_header wr_ihdr;
+ uint8_t wr_flags;
+ uint8_t wr_rate;
+ uint16_t wr_chan_freq;
+ uint16_t wr_chan_flags;
+ uint8_t wr_antenna;
+ uint8_t wr_antsignal;
+} __packed;
+
+#define RT2573_RX_RADIOTAP_PRESENT \
+ ((1 << IEEE80211_RADIOTAP_FLAGS) | \
+ (1 << IEEE80211_RADIOTAP_RATE) | \
+ (1 << IEEE80211_RADIOTAP_CHANNEL) | \
+ (1 << IEEE80211_RADIOTAP_ANTENNA) | \
+ (1 << IEEE80211_RADIOTAP_DB_ANTSIGNAL))
+
+struct rum_tx_radiotap_header {
+ struct ieee80211_radiotap_header wt_ihdr;
+ uint8_t wt_flags;
+ uint8_t wt_rate;
+ uint16_t wt_chan_freq;
+ uint16_t wt_chan_flags;
+ uint8_t wt_antenna;
+} __packed;
+
+#define RT2573_TX_RADIOTAP_PRESENT \
+ ((1 << IEEE80211_RADIOTAP_FLAGS) | \
+ (1 << IEEE80211_RADIOTAP_RATE) | \
+ (1 << IEEE80211_RADIOTAP_CHANNEL) | \
+ (1 << IEEE80211_RADIOTAP_ANTENNA))
+
+struct rum_softc;
+
+struct rum_tx_data {
+ struct rum_softc *sc;
+ usbd_xfer_handle xfer;
+ uint8_t *buf;
+ struct mbuf *m;
+ struct ieee80211_node *ni;
+};
+
+struct rum_rx_data {
+ struct rum_softc *sc;
+ usbd_xfer_handle xfer;
+ uint8_t *buf;
+ struct mbuf *m;
+};
+
+struct rum_amrr {
+ int txcnt;
+ int retrycnt;
+ int success;
+ int success_threshold;
+ int recovery;
+};
+
+struct rum_softc {
+ device_t sc_dev;
+ struct ifnet *sc_ifp;
+ struct ieee80211com sc_ic;
+ int (*sc_newstate)(struct ieee80211com *,
+ enum ieee80211_state, int);
+
+ usbd_device_handle sc_udev;
+ usbd_interface_handle sc_iface;
+ int sc_flags;
+#define RT2573_FWLOADED (1 << 0)
+
+ struct ieee80211_channel *sc_curchan;
+
+ int sc_rx_no;
+ int sc_tx_no;
+
+ uint16_t macbbp_rev;
+ uint8_t rf_rev;
+ uint8_t rffreq;
+
+ usbd_xfer_handle amrr_xfer;
+
+ usbd_pipe_handle sc_rx_pipeh;
+ usbd_pipe_handle sc_tx_pipeh;
+
+ enum ieee80211_state sc_state;
+ struct usb_task sc_task;
+
+ struct rum_amrr amrr;
+
+ struct rum_rx_data rx_data[RT2573_RX_LIST_COUNT];
+ struct rum_tx_data tx_data[RT2573_TX_LIST_COUNT];
+ int tx_queued;
+
+ struct ieee80211_beacon_offsets sc_bo;
+
+ struct callout scan_ch;
+ struct callout amrr_ch;
+
+ int sc_tx_timer;
+
+ uint32_t sta[6];
+ uint32_t rf_regs[4];
+ uint8_t txpow[44];
+
+ struct {
+ uint8_t val;
+ uint8_t reg;
+ } __packed bbp_prom[16];
+
+ int hw_radio;
+ int rx_ant;
+ int tx_ant;
+ int nb_ant;
+ int ext_2ghz_lna;
+ int ext_5ghz_lna;
+ int rssi_2ghz_corr;
+ int rssi_5ghz_corr;
+ int sifs;
+ uint8_t bbp17;
+
+ struct bpf_if *sc_drvbpf;
+
+ union {
+ struct rum_rx_radiotap_header th;
+ uint8_t pad[64];
+ } sc_rxtapu;
+#define sc_rxtap sc_rxtapu.th
+ int sc_rxtap_len;
+
+ union {
+ struct rum_tx_radiotap_header th;
+ uint8_t pad[64];
+ } sc_txtapu;
+#define sc_txtap sc_txtapu.th
+ int sc_txtap_len;
+};
Index: sys/dev/usb/usbdevs
===================================================================
RCS file: /home/ncvs/src/sys/dev/usb/usbdevs,v
retrieving revision 1.285
diff -u -r1.285 usbdevs
--- sys/dev/usb/usbdevs 28 Jan 2007 10:46:32 -0000 1.285
+++ sys/dev/usb/usbdevs 1 Feb 2007 11:26:05 -0000
@@ -1,4 +1,4 @@
-$FreeBSD: src/sys/dev/usb/usbdevs,v 1.285 2007/01/28 10:46:32 takawata Exp $
+$FreeBSD: src/sys/dev/usb/usbdevs,v 1.232.2.16 2006/08/20 05:20:07 imp Exp $
/* $NetBSD: usbdevs,v 1.392 2004/12/29 08:38:44 imp Exp $ */
/*-
@@ -355,6 +355,7 @@
vendor DIGITALSTREAM 0x074e Digital Stream
vendor AUREAL 0x0755 Aureal
vendor MIDIMAN 0x0763 Midiman
+vendor SURECOM 0x0769 Surecom Technology
vendor LINKSYS2 0x077b Linksys
vendor GRIFFIN 0x077d Griffin
vendor SANDISK 0x0781 SanDisk
@@ -383,6 +384,7 @@
vendor AVERMEDIA 0x07ca AVerMedia
vendor SIIG 0x07cc SIIG
vendor CASIO 0x07cf CASIO
+vendor DLINK2 0x07d1 D-Link
vendor APTIO 0x07d2 Aptio
vendor ARASAN 0x07da Arasan
vendor ALLIEDCABLE 0x07e6 Allied Cable
@@ -486,6 +488,7 @@
vendor ACDC 0x0d7e ACDC
vendor ABC 0x0d8c ABC
vendor CONCEPTRONIC 0x0d8e Conceptronic
+vendor SITECOMEU 0x0df6 Sitecom Europe
vendor MSI 0x0db0 Micro Star International
vendor HAWKING 0x0e66 Hawking
vendor GMATE 0x0e7e G.Mate, Inc
@@ -515,9 +518,11 @@
vendor BELKIN2 0x1293 Belkin
vendor AINCOMM 0x12fd Aincomm
vendor MOBILITY 0x1342 Mobility
+vendor DICKSMITH 0x1371 Dick Smith Electronics
vendor LINKSYS4 0x13b1 Linksys
vendor SHARK 0x13d2 Shark
vendor RADIOSHACK 0x1453 Radio Shack
+vendor HUAWEI3COM 0x1472 Huawei 3Com
vendor SILICOM 0x1485 Silicom
vendor RALINK 0x148f Ralink Technology
vendor IMAGINATION 0x149a Imagination Technologies
@@ -527,14 +532,17 @@
vendor SOHOWARE 0x15e8 SOHOware
vendor UMAX 0x1606 UMAX
vendor INSIDEOUT 0x1608 Inside Out Networks
+vendor GOODWAY 0x1631 Good Way Technology
vendor ENTREGA 0x1645 Entrega
vendor ACTIONTEC 0x1668 Actiontec
vendor ATHEROS 0x168c Atheros Communications
vendor GIGASET 0x1690 Gigaset
vendor GLOBALSUN 0x16ab Global Sun Technology
vendor CMOTECH 0x16d8 CMOTECH CO., LTD.
+vendor QCOM 0x18e8 Qcom
vendor LINKSYS3 0x1915 Linksys
vendor DLINK 0x2001 D-Link
+vendor PLANEX2 0x2019 Planex Communications
vendor ERICSSON 0x2282 Ericsson
vendor MOTOROLA2 0x22b8 Motorola
vendor TRIPPLITE 0x2478 Tripp-Lite
@@ -555,7 +563,7 @@
vendor ONSPEC2 0x55aa OnSpec
vendor ZINWELL 0x5a57 Zinwell
vendor SITECOM 0x6189 Sitecom
-vendor ARKMICRO 0x6547 Arkmicro Technologies
+vendor ARKMICRO 0x6547 Arkmicro Technologies
vendor INTEL 0x8086 Intel
vendor HP2 0xf003 Hewlett Packard
@@ -590,6 +598,7 @@
product ABOCOM XX8 0x4102 XX8
product ABOCOM XX9 0x4104 XX9
product ABOCOM XX10 0xabc1 XX10
+product ABOCOM RT2573 0xb21d RT2573
/* Accton products */
product ACCTON USB320_EC 0x1046 USB320-EC Ethernet
@@ -688,7 +697,7 @@
product APPLE IPODNANO 0x120a iPod Nano
/* Arkmicro Technologies */
-product ARKMICRO ARK3116 0x0232 ARK3116 Serial
+product ARKMICRO ARK3116 0x0232 ARK3116 Serial
/* Asahi Optical products */
product ASAHIOPTICAL OPTIO230 0x0004 Digital camera
@@ -699,6 +708,7 @@
/* ASUS products */
product ASUS WL167G 0x1707 WL-167g wireless adapter
+product ASUS RT2573 0x1723 RT2573
/* ATen products */
product ATEN UC1284 0x2001 Parallel printer
@@ -736,9 +746,12 @@
product BELKIN F5U109 0x0109 F5U109 Serial
product BELKIN F5U208 0x0208 F5U208 VideoBus II
product BELKIN F5U409 0x0409 F5U409 Serial
-product BELKIN F6C550AVR 0x0551 F6C550-AVR UPS
+product BELKIN F6C550AVR 0x0551 F6C550-AVR UPS
product BELKIN F5U120 0x1203 F5U120-PC Hub
product BELKIN F5D7050 0x7050 F5D7050 wireless adapter
+product BELKIN F5D7050A 0x705a F5D705A 54g USB Network Adapter
+product BELKIN F5D9050V3 0x905b F5D9050 ver 3
+
/* Billionton products */
product BILLIONTON USB100 0x0986 USB100N 10/100 FastEthernet
@@ -838,7 +851,7 @@
/* Cypress Semiconductor products */
product CYPRESS MOUSE 0x0001 mouse
product CYPRESS THERMO 0x0002 thermometer
-product CYPRESS WISPY 0x0bad MetaGeek Wi-Spy
+product CYPRESS WISPY 0x0bad MetaGeek Wi-Spy
product CYPRESS FMRADIO 0x1002 FM Radio
product CYPRESS SLIM_HUB 0x6560 Slim Hub
@@ -859,6 +872,10 @@
/* Diamond products */
product DIAMOND RIO500USB 0x0001 Rio 500 USB
+/* Dick Smith Electronics (really C-Net) products */
+product DICKSMITH RT2573 0x9022 RT2573
+product DICKSMITH CWD854F 0x9032 C-Net CWD-854 rev F
+
/* Digi International products */
product DIGI ACCELEPORT2 0x0002 AccelePort USB 2
product DIGI ACCELEPORT4 0x0004 AccelePort USB 4
@@ -884,6 +901,8 @@
product DLINK DSB650TX3 0x400b 10/100 ethernet
product DLINK DSB650TX2 0x4102 10/100 ethernet
product DLINK DSB650 0xabc1 10/100 ethernet
+product DLINK2 DWLG122C1 0x3c03 DWL-G122 rev C1
+product DLINK2 WUA1340 0x3c04 WUA-1340
/* EIZO products */
product EIZO HUB 0x0000 hub
@@ -941,11 +960,11 @@
product EPSON 1670 0x011f Perfection 1670 scanner
product EPSON 1270 0x0120 Perfection 1270 scanner
product EPSON 2480 0x0121 Perfection 2480 scanner
-product EPSON 3590 0x0122 Perfection 3590 scanner
-product EPSON 4990 0x012a Perfection 4990 Photo scanner
+product EPSON 3590 0x0122 Perfection 3590 scanner
+product EPSON 4990 0x012a Perfection 4990 Photo scanner
product EPSON 3500 0x080e CX-3500/3600/3650 MFP
product EPSON RX425 0x080f Stylus Photo RX425 scanner
-product EPSON 4200 0x0820 CX4200 MP scanner
+product EPSON 4200 0x0820 CX4200 MP scanner
/* e-TEK Labs products */
product ETEK 1COM 0x8007 Serial
@@ -993,6 +1012,7 @@
product GIGABYTE GNBR402W 0x8002 GN-BR402W
product GIGABYTE GNWLBM101 0x8003 GN-WLBM101
product GIGABYTE GNWBKG 0x8007 GN-WBKG
+product GIGABYTE GNWB01GS 0x8008 GN-WB01GS
/* Gigaset products */
product GIGASET WLAN 0x0701 WLAN
@@ -1083,6 +1103,12 @@
/* HP products */
product HP2 C500 0x6002 PhotoSmart C500
+/* HUAWEI products */
+product HUAWEI3COM RT2573 0x0009 RT2573
+
+/* Good Way Technology products */
+product GOODWAY RT2573 0xc019 RT2573
+
/* IBM Corporation */
product IBM USBCDROMDRIVE 0x4427 USB CD-ROM Drive
@@ -1226,6 +1252,7 @@
product LINKSYS4 WUSB54G 0x000d WUSB54G wireless adapter
product LINKSYS4 WUSB54GP 0x0011 WUSB54GP wireless adapter
product LINKSYS4 HU200TS 0x001a HU200TS wireless adapter
+product LINKSYS4 WUSB54GC 0x0020 WUSB54GC
/* Logitech products */
product LOGITECH M2452 0x0203 M2452 keyboard
@@ -1241,11 +1268,11 @@
product LOGITECH WMMOUSE 0xc004 WingMan Gaming Mouse
product LOGITECH BD58 0xc00c BD58 mouse
product LOGITECH UN58A 0xc030 iFeel Mouse
-product LOGITECH UN53B 0xc032 iFeel MouseMan
+product LOGITECH UN53B 0xc032 iFeel MouseMan
product LOGITECH WMPAD 0xc208 WingMan GamePad Extreme
product LOGITECH WMRPAD 0xc20a WingMan RumblePad
product LOGITECH WMJOY 0xc281 WingMan Force joystick
-product LOGITECH BB13 0xc401 USB-PS/2 Trackball
+product LOGITECH BB13 0xc401 USB-PS/2 Trackball
product LOGITECH RK53 0xc501 Cordless mouse
product LOGITECH RB6 0xc503 Cordless keyboard
product LOGITECH MX700 0xc506 Cordless optical mouse
@@ -1301,6 +1328,9 @@
product MSI RT2570 0x6861 RT2570
product MSI RT2570_2 0x6865 RT2570
product MSI RT2570_3 0x6869 RT2570
+product MSI RT2573 0x6877 RT2573
+product MSI RT2573_2 0xa861 RT2573
+product MSI RT2573_3 0xa874 RT2573
/* Microsoft products */
product MICROSOFT SIDEPREC 0x0008 SideWinder Precision Pro
@@ -1387,7 +1417,7 @@
/* Netgear products */
product NETGEAR EA101 0x1001 Ethernet
-product NETGEAR FA101 0x1020 Ethernet 10/100, USB1.1
+product NETGEAR FA101 0x1020 Ethernet 10/100, USB1.1
product NETGEAR FA120 0x1040 USB 2.0 Ethernet
product NETGEAR3 WG111T 0x4250 WG111T
product NETGEAR3 WG111T_NF 0x4251 WG111T (no firmware)
@@ -1401,7 +1431,7 @@
product NIKON LS40 0x4000 CoolScan LS40 ED
/* NovaTech Products */
-product NOVATECH NV902 0x9020 NovaTech NV-902W
+product NOVATECH NV902 0x9020 NovaTech NV-902W
/* Olympus products */
product OLYMPUS C1 0x0102 C-1 Digital Camera
@@ -1428,7 +1458,7 @@
product PALM ZIRE 0x0070 Palm Zire
/* Panasonic products */
-product PANASONIC KXL840AN 0x0d01 CD-R Drive KXL-840AN
+product PANASONIC KXL840AN 0x0d01 CD-R Drive KXL-840AN
product PANASONIC KXLRW32AN 0x0d09 CD-R Drive KXL-RW32AN
product PANASONIC KXLCB20AN 0x0d0a CD-R Drive KXL-CB20AN
product PANASONIC KXLCB35AN 0x0d0e DVD-ROM & CD-R/RW
@@ -1456,6 +1486,10 @@
/* P.I. Engineering products */
product PIENGINEERING PS2USB 0x020b PS2 to Mac USB Adapter
+/* Planex Communications products */
+product PLANEX2 GWUSMM 0xed02 GW-USMM
+
+
/* Plextor Corp. */
product PLEXTOR 40_12_40U 0x0011 PlexWriter 40/12/40U
@@ -1498,6 +1532,10 @@
/* Putercom products */
product PUTERCOM UPA100 0x047e USB-1284 BRIDGE
+/* Qcom products */
+product QCOM RT2573 0x6196 RT2573
+product QCOM RT2573_2 0x6229 RT2573
+
/* Qualcomm products */
product QUALCOMM CDMA_MSM 0x3196 CDMA Technologies MSM modem
product QUALCOMM2 CDMA_MSM 0x6000 CDMA Technologies MSM phone
@@ -1517,6 +1555,8 @@
/* Ralink Technology products */
product RALINK RT2570 0x1706 RT2500USB wireless adapter
product RALINK RT2570_2 0x2570 RT2500USB wireless adapter
+product RALINK RT2573 0x2573 RT2573
+product RALINK RT2671 0x2671 RT2671
/* ReakTek products */
product REALTEK USBKR100 0x8150 USBKR100 USB Ethernet (GREEN HOUSE)
@@ -1589,7 +1629,7 @@
product SIIG2 US2308 0x0421 Serial
/* Silicom products */
-product SILICOM GPE 0x0002 Psion Gold Port Ethernet
+product SILICOM GPE 0x0002 Psion Gold Port Ethernet
/* Silicon Portals Inc. */
product SILICONPORTALS YAPPH_NF 0x0200 YAP Phone (no firmware)
@@ -1602,6 +1642,11 @@
product SITECOM LN029 0x182d USB 2.0 Ethernet
product SITECOM SERIAL 0x2068 USB to serial cable (v2)
+/* Sitecom Europe products */
+product SITECOMEU WL172 0x90ac WL-172
+product SITECOMEU WL113R2 0x9712 WL-113 rev 2
+
+
/* SmartBridges products */
product SMARTBRIDGES SMARTLINK 0x0001 SmartLink USB ethernet
product SMARTBRIDGES SMARTNIC 0x0003 smartNIC 2 PnP ethernet
@@ -1667,6 +1712,9 @@
product DIAMOND2 RIO600USB 0x5001 Rio 600 USB
product DIAMOND2 RIO800USB 0x5002 Rio 800 USB
+/* Surecom Technology products */
+product SURECOM RT2573 0x31f3 RT2573
+
/* System TALKS, Inc. */
product SYSTEMTALKS SGCX2UL 0x1920 SGC-X2UL
Index: sys/modules/rt2573/Makefile
===================================================================
RCS file: sys/modules/rt2573/Makefile
diff -N sys/modules/rt2573/Makefile
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ sys/modules/rt2573/Makefile 1 Feb 2007 11:26:11 -0000
@@ -0,0 +1,3 @@
+KMOD= rt2573
+FIRMWS= rum-rt2573:rt2573:100
+.include <bsd.kmod.mk>
Index: sys/modules/rum/Makefile
===================================================================
RCS file: sys/modules/rum/Makefile
diff -N sys/modules/rum/Makefile
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ sys/modules/rum/Makefile 1 Feb 2007 11:26:11 -0000
@@ -0,0 +1,8 @@
+# $FreeBSD: src/sys/modules/ural/Makefile,v 1.1 2005/04/18 18:47:38 damien Exp $
+
+.PATH: ${.CURDIR}/../../dev/usb
+
+KMOD = if_rum
+SRCS = if_rum.c opt_bdg.h opt_usb.h device_if.h bus_if.h usbdevs.h
+
+.include <bsd.kmod.mk>
--------------070401030006070808060902--
More information about the freebsd-usb
mailing list