LCOV - code coverage report
Current view: top level - dev/usb - if_rum.c (source / functions) Hit Total Coverage
Test: 6.4 Lines: 0 1105 0.0 %
Date: 2018-10-19 03:25:38 Functions: 0 53 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*      $OpenBSD: if_rum.c,v 1.123 2017/10/26 15:00:28 mpi Exp $        */
       2             : 
       3             : /*-
       4             :  * Copyright (c) 2005-2007 Damien Bergamini <damien.bergamini@free.fr>
       5             :  * Copyright (c) 2006 Niall O'Higgins <niallo@openbsd.org>
       6             :  *
       7             :  * Permission to use, copy, modify, and distribute this software for any
       8             :  * purpose with or without fee is hereby granted, provided that the above
       9             :  * copyright notice and this permission notice appear in all copies.
      10             :  *
      11             :  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
      12             :  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
      13             :  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
      14             :  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
      15             :  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
      16             :  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
      17             :  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
      18             :  */
      19             : 
      20             : /*-
      21             :  * Ralink Technology RT2501USB/RT2601USB chipset driver
      22             :  * http://www.ralinktech.com.tw/
      23             :  */
      24             : 
      25             : #include "bpfilter.h"
      26             : 
      27             : #include <sys/param.h>
      28             : #include <sys/sockio.h>
      29             : #include <sys/mbuf.h>
      30             : #include <sys/kernel.h>
      31             : #include <sys/socket.h>
      32             : #include <sys/systm.h>
      33             : #include <sys/timeout.h>
      34             : #include <sys/conf.h>
      35             : #include <sys/device.h>
      36             : #include <sys/endian.h>
      37             : 
      38             : #include <machine/intr.h>
      39             : 
      40             : #if NBPFILTER > 0
      41             : #include <net/bpf.h>
      42             : #endif
      43             : #include <net/if.h>
      44             : #include <net/if_dl.h>
      45             : #include <net/if_media.h>
      46             : 
      47             : #include <netinet/in.h>
      48             : #include <netinet/if_ether.h>
      49             : 
      50             : #include <net80211/ieee80211_var.h>
      51             : #include <net80211/ieee80211_amrr.h>
      52             : #include <net80211/ieee80211_radiotap.h>
      53             : 
      54             : #include <dev/usb/usb.h>
      55             : #include <dev/usb/usbdi.h>
      56             : #include <dev/usb/usbdi_util.h>
      57             : #include <dev/usb/usbdevs.h>
      58             : 
      59             : #include <dev/usb/if_rumreg.h>
      60             : #include <dev/usb/if_rumvar.h>
      61             : 
      62             : #ifdef RUM_DEBUG
      63             : #define DPRINTF(x)      do { if (rum_debug) printf x; } while (0)
      64             : #define DPRINTFN(n, x)  do { if (rum_debug >= (n)) printf x; } while (0)
      65             : int rum_debug = 0;
      66             : #else
      67             : #define DPRINTF(x)
      68             : #define DPRINTFN(n, x)
      69             : #endif
      70             : 
      71             : /* various supported device vendors/products */
      72             : static const struct usb_devno rum_devs[] = {
      73             :         { USB_VENDOR_ABOCOM,            USB_PRODUCT_ABOCOM_HWU54DM },
      74             :         { USB_VENDOR_ABOCOM,            USB_PRODUCT_ABOCOM_RT2573_2 },
      75             :         { USB_VENDOR_ABOCOM,            USB_PRODUCT_ABOCOM_RT2573_3 },
      76             :         { USB_VENDOR_ABOCOM,            USB_PRODUCT_ABOCOM_RT2573_4 },
      77             :         { USB_VENDOR_ABOCOM,            USB_PRODUCT_ABOCOM_WUG2700 },
      78             :         { USB_VENDOR_AMIT,              USB_PRODUCT_AMIT_CGWLUSB2GO },
      79             :         { USB_VENDOR_ASUS,              USB_PRODUCT_ASUS_RT2573_1 },
      80             :         { USB_VENDOR_ASUS,              USB_PRODUCT_ASUS_RT2573_2 },
      81             :         { USB_VENDOR_BELKIN,            USB_PRODUCT_BELKIN_F5D7050A },
      82             :         { USB_VENDOR_BELKIN,            USB_PRODUCT_BELKIN_F5D9050V3 },
      83             :         { USB_VENDOR_BELKIN,            USB_PRODUCT_BELKIN_F5D9050C },
      84             :         { USB_VENDOR_CISCOLINKSYS,      USB_PRODUCT_CISCOLINKSYS_WUSB200 },
      85             :         { USB_VENDOR_CISCOLINKSYS,      USB_PRODUCT_CISCOLINKSYS_WUSB54GC },
      86             :         { USB_VENDOR_CISCOLINKSYS,      USB_PRODUCT_CISCOLINKSYS_WUSB54GR },
      87             :         { USB_VENDOR_CONCEPTRONIC2,     USB_PRODUCT_CONCEPTRONIC2_C54RU2 },
      88             :         { USB_VENDOR_CONCEPTRONIC2,     USB_PRODUCT_CONCEPTRONIC2_RT2573 },
      89             :         { USB_VENDOR_COREGA,            USB_PRODUCT_COREGA_CGWLUSB2GL },
      90             :         { USB_VENDOR_COREGA,            USB_PRODUCT_COREGA_CGWLUSB2GPX },
      91             :         { USB_VENDOR_DICKSMITH,         USB_PRODUCT_DICKSMITH_CWD854F },
      92             :         { USB_VENDOR_DICKSMITH,         USB_PRODUCT_DICKSMITH_RT2573 },
      93             :         { USB_VENDOR_DLINK2,            USB_PRODUCT_DLINK2_DWA111 },
      94             :         { USB_VENDOR_DLINK2,            USB_PRODUCT_DLINK2_DWA110 },
      95             :         { USB_VENDOR_DLINK2,            USB_PRODUCT_DLINK2_DWLG122C1 },
      96             :         { USB_VENDOR_DLINK2,            USB_PRODUCT_DLINK2_WUA1340 },
      97             :         { USB_VENDOR_EDIMAX,            USB_PRODUCT_EDIMAX_EW7318 },
      98             :         { USB_VENDOR_EDIMAX,            USB_PRODUCT_EDIMAX_EW7618 },
      99             :         { USB_VENDOR_GIGABYTE,          USB_PRODUCT_GIGABYTE_GNWB01GS },
     100             :         { USB_VENDOR_GIGABYTE,          USB_PRODUCT_GIGABYTE_GNWI05GS },
     101             :         { USB_VENDOR_GIGASET,           USB_PRODUCT_GIGASET_RT2573 },
     102             :         { USB_VENDOR_GOODWAY,           USB_PRODUCT_GOODWAY_RT2573 },
     103             :         { USB_VENDOR_GUILLEMOT,         USB_PRODUCT_GUILLEMOT_HWGUSB254LB },
     104             :         { USB_VENDOR_GUILLEMOT,         USB_PRODUCT_GUILLEMOT_HWGUSB254V2AP },
     105             :         { USB_VENDOR_HUAWEI3COM,        USB_PRODUCT_HUAWEI3COM_WUB320G },
     106             :         { USB_VENDOR_MELCO,             USB_PRODUCT_MELCO_G54HP },
     107             :         { USB_VENDOR_MELCO,             USB_PRODUCT_MELCO_SG54HP },
     108             :         { USB_VENDOR_MELCO,             USB_PRODUCT_MELCO_SG54HG },
     109             :         { USB_VENDOR_MSI,               USB_PRODUCT_MSI_RT2573_1 },
     110             :         { USB_VENDOR_MSI,               USB_PRODUCT_MSI_RT2573_2 },
     111             :         { USB_VENDOR_MSI,               USB_PRODUCT_MSI_RT2573_3 },
     112             :         { USB_VENDOR_MSI,               USB_PRODUCT_MSI_RT2573_4 },
     113             :         { USB_VENDOR_NOVATECH,          USB_PRODUCT_NOVATECH_RT2573 },
     114             :         { USB_VENDOR_PLANEX2,           USB_PRODUCT_PLANEX2_GWUS54HP },
     115             :         { USB_VENDOR_PLANEX2,           USB_PRODUCT_PLANEX2_GWUS54MINI2 },
     116             :         { USB_VENDOR_PLANEX2,           USB_PRODUCT_PLANEX2_GWUSMM },
     117             :         { USB_VENDOR_QCOM,              USB_PRODUCT_QCOM_RT2573 },
     118             :         { USB_VENDOR_QCOM,              USB_PRODUCT_QCOM_RT2573_2 },
     119             :         { USB_VENDOR_QCOM,              USB_PRODUCT_QCOM_RT2573_3 },
     120             :         { USB_VENDOR_RALINK,            USB_PRODUCT_RALINK_RT2573 },
     121             :         { USB_VENDOR_RALINK,            USB_PRODUCT_RALINK_RT2573_2 },
     122             :         { USB_VENDOR_RALINK,            USB_PRODUCT_RALINK_RT2671 },
     123             :         { USB_VENDOR_SITECOMEU,         USB_PRODUCT_SITECOMEU_WL113R2 },
     124             :         { USB_VENDOR_SITECOMEU,         USB_PRODUCT_SITECOMEU_WL172 },
     125             :         { USB_VENDOR_SURECOM,           USB_PRODUCT_SURECOM_RT2573 },
     126             :         { USB_VENDOR_SPARKLAN,          USB_PRODUCT_SPARKLAN_RT2573 },
     127             :         { USB_VENDOR_ZYXEL,             USB_PRODUCT_ZYXEL_RT2573 }
     128             : };
     129             : 
     130             : void            rum_attachhook(struct device *);
     131             : int             rum_alloc_tx_list(struct rum_softc *);
     132             : void            rum_free_tx_list(struct rum_softc *);
     133             : int             rum_alloc_rx_list(struct rum_softc *);
     134             : void            rum_free_rx_list(struct rum_softc *);
     135             : int             rum_media_change(struct ifnet *);
     136             : void            rum_next_scan(void *);
     137             : void            rum_task(void *);
     138             : int             rum_newstate(struct ieee80211com *, enum ieee80211_state, int);
     139             : void            rum_txeof(struct usbd_xfer *, void *, usbd_status);
     140             : void            rum_rxeof(struct usbd_xfer *, void *, usbd_status);
     141             : #if NBPFILTER > 0
     142             : uint8_t         rum_rxrate(const struct rum_rx_desc *);
     143             : #endif
     144             : int             rum_ack_rate(struct ieee80211com *, int);
     145             : uint16_t        rum_txtime(int, int, uint32_t);
     146             : uint8_t         rum_plcp_signal(int);
     147             : void            rum_setup_tx_desc(struct rum_softc *, struct rum_tx_desc *,
     148             :                     uint32_t, uint16_t, int, int);
     149             : int             rum_tx_data(struct rum_softc *, struct mbuf *,
     150             :                     struct ieee80211_node *);
     151             : void            rum_start(struct ifnet *);
     152             : void            rum_watchdog(struct ifnet *);
     153             : int             rum_ioctl(struct ifnet *, u_long, caddr_t);
     154             : void            rum_eeprom_read(struct rum_softc *, uint16_t, void *, int);
     155             : uint32_t        rum_read(struct rum_softc *, uint16_t);
     156             : void            rum_read_multi(struct rum_softc *, uint16_t, void *, int);
     157             : void            rum_write(struct rum_softc *, uint16_t, uint32_t);
     158             : void            rum_write_multi(struct rum_softc *, uint16_t, void *, size_t);
     159             : void            rum_bbp_write(struct rum_softc *, uint8_t, uint8_t);
     160             : uint8_t         rum_bbp_read(struct rum_softc *, uint8_t);
     161             : void            rum_rf_write(struct rum_softc *, uint8_t, uint32_t);
     162             : void            rum_select_antenna(struct rum_softc *);
     163             : void            rum_enable_mrr(struct rum_softc *);
     164             : void            rum_set_txpreamble(struct rum_softc *);
     165             : void            rum_set_basicrates(struct rum_softc *);
     166             : void            rum_select_band(struct rum_softc *,
     167             :                     struct ieee80211_channel *);
     168             : void            rum_set_chan(struct rum_softc *, struct ieee80211_channel *);
     169             : void            rum_enable_tsf_sync(struct rum_softc *);
     170             : void            rum_update_slot(struct rum_softc *);
     171             : void            rum_set_bssid(struct rum_softc *, const uint8_t *);
     172             : void            rum_set_macaddr(struct rum_softc *, const uint8_t *);
     173             : void            rum_update_promisc(struct rum_softc *);
     174             : const char      *rum_get_rf(int);
     175             : void            rum_read_eeprom(struct rum_softc *);
     176             : int             rum_bbp_init(struct rum_softc *);
     177             : int             rum_init(struct ifnet *);
     178             : void            rum_stop(struct ifnet *, int);
     179             : int             rum_load_microcode(struct rum_softc *, const u_char *, size_t);
     180             : #ifndef IEEE80211_STA_ONLY
     181             : int             rum_prepare_beacon(struct rum_softc *);
     182             : #endif
     183             : void            rum_newassoc(struct ieee80211com *, struct ieee80211_node *,
     184             :                     int);
     185             : void            rum_amrr_start(struct rum_softc *, struct ieee80211_node *);
     186             : void            rum_amrr_timeout(void *);
     187             : void            rum_amrr_update(struct usbd_xfer *, void *,
     188             :                     usbd_status status);
     189             : 
     190             : static const struct {
     191             :         uint32_t        reg;
     192             :         uint32_t        val;
     193             : } rum_def_mac[] = {
     194             :         RT2573_DEF_MAC
     195             : };
     196             : 
     197             : static const struct {
     198             :         uint8_t reg;
     199             :         uint8_t val;
     200             : } rum_def_bbp[] = {
     201             :         RT2573_DEF_BBP
     202             : };
     203             : 
     204             : static const struct rfprog {
     205             :         uint8_t         chan;
     206             :         uint32_t        r1, r2, r3, r4;
     207             : }  rum_rf5226[] = {
     208             :         RT2573_RF5226
     209             : }, rum_rf5225[] = {
     210             :         RT2573_RF5225
     211             : };
     212             : 
     213             : int rum_match(struct device *, void *, void *);
     214             : void rum_attach(struct device *, struct device *, void *);
     215             : int rum_detach(struct device *, int);
     216             : 
     217             : struct cfdriver rum_cd = {
     218             :         NULL, "rum", DV_IFNET
     219             : };
     220             : 
     221             : const struct cfattach rum_ca = {
     222             :         sizeof(struct rum_softc), rum_match, rum_attach, rum_detach
     223             : };
     224             : 
     225             : int
     226           0 : rum_match(struct device *parent, void *match, void *aux)
     227             : {
     228           0 :         struct usb_attach_arg *uaa = aux;
     229             : 
     230           0 :         if (uaa->iface == NULL || uaa->configno != 1)
     231           0 :                 return UMATCH_NONE;
     232             : 
     233           0 :         return (usb_lookup(rum_devs, uaa->vendor, uaa->product) != NULL) ?
     234             :             UMATCH_VENDOR_PRODUCT_CONF_IFACE : UMATCH_NONE;
     235           0 : }
     236             : 
     237             : void
     238           0 : rum_attachhook(struct device *self)
     239             : {
     240           0 :         struct rum_softc *sc = (struct rum_softc *)self;
     241             :         const char *name = "rum-rt2573";
     242           0 :         u_char *ucode;
     243           0 :         size_t size;
     244             :         int error;
     245             : 
     246           0 :         if ((error = loadfirmware(name, &ucode, &size)) != 0) {
     247           0 :                 printf("%s: failed loadfirmware of file %s (error %d)\n",
     248           0 :                     sc->sc_dev.dv_xname, name, error);
     249           0 :                 return;
     250             :         }
     251             : 
     252           0 :         if (rum_load_microcode(sc, ucode, size) != 0) {
     253           0 :                 printf("%s: could not load 8051 microcode\n",
     254           0 :                     sc->sc_dev.dv_xname);
     255           0 :         }
     256             : 
     257           0 :         free(ucode, M_DEVBUF, size);
     258           0 : }
     259             : 
     260             : void
     261           0 : rum_attach(struct device *parent, struct device *self, void *aux)
     262             : {
     263           0 :         struct rum_softc *sc = (struct rum_softc *)self;
     264           0 :         struct usb_attach_arg *uaa = aux;
     265           0 :         struct ieee80211com *ic = &sc->sc_ic;
     266           0 :         struct ifnet *ifp = &ic->ic_if;
     267             :         usb_interface_descriptor_t *id;
     268             :         usb_endpoint_descriptor_t *ed;
     269             :         int i, ntries;
     270             :         uint32_t tmp;
     271             : 
     272           0 :         sc->sc_udev = uaa->device;
     273           0 :         sc->sc_iface = uaa->iface;
     274             : 
     275             :         /*
     276             :          * Find endpoints.
     277             :          */
     278           0 :         id = usbd_get_interface_descriptor(sc->sc_iface);
     279             : 
     280           0 :         sc->sc_rx_no = sc->sc_tx_no = -1;
     281           0 :         for (i = 0; i < id->bNumEndpoints; i++) {
     282           0 :                 ed = usbd_interface2endpoint_descriptor(sc->sc_iface, i);
     283           0 :                 if (ed == NULL) {
     284           0 :                         printf("%s: no endpoint descriptor for iface %d\n",
     285           0 :                             sc->sc_dev.dv_xname, i);
     286           0 :                         return;
     287             :                 }
     288             : 
     289           0 :                 if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN &&
     290           0 :                     UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK)
     291           0 :                         sc->sc_rx_no = ed->bEndpointAddress;
     292           0 :                 else if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_OUT &&
     293           0 :                     UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK)
     294           0 :                         sc->sc_tx_no = ed->bEndpointAddress;
     295             :         }
     296           0 :         if (sc->sc_rx_no == -1 || sc->sc_tx_no == -1) {
     297           0 :                 printf("%s: missing endpoint\n", sc->sc_dev.dv_xname);
     298           0 :                 return;
     299             :         }
     300             : 
     301           0 :         usb_init_task(&sc->sc_task, rum_task, sc, USB_TASK_TYPE_GENERIC);
     302           0 :         timeout_set(&sc->scan_to, rum_next_scan, sc);
     303             : 
     304           0 :         sc->amrr.amrr_min_success_threshold =  1;
     305           0 :         sc->amrr.amrr_max_success_threshold = 10;
     306           0 :         timeout_set(&sc->amrr_to, rum_amrr_timeout, sc);
     307             : 
     308             :         /* retrieve RT2573 rev. no */
     309           0 :         for (ntries = 0; ntries < 1000; ntries++) {
     310           0 :                 if ((tmp = rum_read(sc, RT2573_MAC_CSR0)) != 0)
     311             :                         break;
     312           0 :                 DELAY(1000);
     313             :         }
     314           0 :         if (ntries == 1000) {
     315           0 :                 printf("%s: timeout waiting for chip to settle\n",
     316           0 :                     sc->sc_dev.dv_xname);
     317           0 :                 return;
     318             :         }
     319             : 
     320             :         /* retrieve MAC address and various other things from EEPROM */
     321           0 :         rum_read_eeprom(sc);
     322             : 
     323           0 :         printf("%s: MAC/BBP RT%04x (rev 0x%05x), RF %s, address %s\n",
     324           0 :             sc->sc_dev.dv_xname, sc->macbbp_rev, tmp,
     325           0 :             rum_get_rf(sc->rf_rev), ether_sprintf(ic->ic_myaddr));
     326             : 
     327           0 :         config_mountroot(self, rum_attachhook);
     328             : 
     329           0 :         ic->ic_phytype = IEEE80211_T_OFDM;   /* not only, but not used */
     330           0 :         ic->ic_opmode = IEEE80211_M_STA;     /* default to BSS mode */
     331           0 :         ic->ic_state = IEEE80211_S_INIT;
     332             : 
     333             :         /* set device capabilities */
     334           0 :         ic->ic_caps =
     335             :             IEEE80211_C_MONITOR |       /* monitor mode supported */
     336             : #ifndef IEEE80211_STA_ONLY
     337             :             IEEE80211_C_IBSS |          /* IBSS mode supported */
     338             :             IEEE80211_C_HOSTAP |        /* HostAp mode supported */
     339             : #endif
     340             :             IEEE80211_C_TXPMGT |        /* tx power management */
     341             :             IEEE80211_C_SHPREAMBLE |    /* short preamble supported */
     342             :             IEEE80211_C_SHSLOT |        /* short slot time supported */
     343             :             IEEE80211_C_WEP |           /* s/w WEP */
     344             :             IEEE80211_C_RSN;            /* WPA/RSN */
     345             : 
     346           0 :         if (sc->rf_rev == RT2573_RF_5225 || sc->rf_rev == RT2573_RF_5226) {
     347             :                 /* set supported .11a rates */
     348           0 :                 ic->ic_sup_rates[IEEE80211_MODE_11A] =
     349           0 :                     ieee80211_std_rateset_11a;
     350             : 
     351             :                 /* set supported .11a channels */
     352           0 :                 for (i = 34; i <= 46; i += 4) {
     353           0 :                         ic->ic_channels[i].ic_freq =
     354           0 :                             ieee80211_ieee2mhz(i, IEEE80211_CHAN_5GHZ);
     355           0 :                         ic->ic_channels[i].ic_flags = IEEE80211_CHAN_A;
     356             :                 }
     357           0 :                 for (i = 36; i <= 64; i += 4) {
     358           0 :                         ic->ic_channels[i].ic_freq =
     359           0 :                             ieee80211_ieee2mhz(i, IEEE80211_CHAN_5GHZ);
     360           0 :                         ic->ic_channels[i].ic_flags = IEEE80211_CHAN_A;
     361             :                 }
     362           0 :                 for (i = 100; i <= 140; i += 4) {
     363           0 :                         ic->ic_channels[i].ic_freq =
     364           0 :                             ieee80211_ieee2mhz(i, IEEE80211_CHAN_5GHZ);
     365           0 :                         ic->ic_channels[i].ic_flags = IEEE80211_CHAN_A;
     366             :                 }
     367           0 :                 for (i = 149; i <= 165; i += 4) {
     368           0 :                         ic->ic_channels[i].ic_freq =
     369           0 :                             ieee80211_ieee2mhz(i, IEEE80211_CHAN_5GHZ);
     370           0 :                         ic->ic_channels[i].ic_flags = IEEE80211_CHAN_A;
     371             :                 }
     372             :         }
     373             : 
     374             :         /* set supported .11b and .11g rates */
     375           0 :         ic->ic_sup_rates[IEEE80211_MODE_11B] = ieee80211_std_rateset_11b;
     376           0 :         ic->ic_sup_rates[IEEE80211_MODE_11G] = ieee80211_std_rateset_11g;
     377             : 
     378             :         /* set supported .11b and .11g channels (1 through 14) */
     379           0 :         for (i = 1; i <= 14; i++) {
     380           0 :                 ic->ic_channels[i].ic_freq =
     381           0 :                     ieee80211_ieee2mhz(i, IEEE80211_CHAN_2GHZ);
     382           0 :                 ic->ic_channels[i].ic_flags =
     383             :                     IEEE80211_CHAN_CCK | IEEE80211_CHAN_OFDM |
     384             :                     IEEE80211_CHAN_DYN | IEEE80211_CHAN_2GHZ;
     385             :         }
     386             : 
     387           0 :         ifp->if_softc = sc;
     388           0 :         ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
     389           0 :         ifp->if_ioctl = rum_ioctl;
     390           0 :         ifp->if_start = rum_start;
     391           0 :         ifp->if_watchdog = rum_watchdog;
     392           0 :         memcpy(ifp->if_xname, sc->sc_dev.dv_xname, IFNAMSIZ);
     393             : 
     394           0 :         if_attach(ifp);
     395           0 :         ieee80211_ifattach(ifp);
     396           0 :         ic->ic_newassoc = rum_newassoc;
     397             : 
     398             :         /* override state transition machine */
     399           0 :         sc->sc_newstate = ic->ic_newstate;
     400           0 :         ic->ic_newstate = rum_newstate;
     401           0 :         ieee80211_media_init(ifp, rum_media_change, ieee80211_media_status);
     402             : 
     403             : #if NBPFILTER > 0
     404           0 :         bpfattach(&sc->sc_drvbpf, ifp, DLT_IEEE802_11_RADIO,
     405             :             sizeof (struct ieee80211_frame) + IEEE80211_RADIOTAP_HDRLEN);
     406             : 
     407           0 :         sc->sc_rxtap_len = sizeof sc->sc_rxtapu;
     408           0 :         sc->sc_rxtap.wr_ihdr.it_len = htole16(sc->sc_rxtap_len);
     409           0 :         sc->sc_rxtap.wr_ihdr.it_present = htole32(RT2573_RX_RADIOTAP_PRESENT);
     410             : 
     411           0 :         sc->sc_txtap_len = sizeof sc->sc_txtapu;
     412           0 :         sc->sc_txtap.wt_ihdr.it_len = htole16(sc->sc_txtap_len);
     413           0 :         sc->sc_txtap.wt_ihdr.it_present = htole32(RT2573_TX_RADIOTAP_PRESENT);
     414             : #endif
     415           0 : }
     416             : 
     417             : int
     418           0 : rum_detach(struct device *self, int flags)
     419             : {
     420           0 :         struct rum_softc *sc = (struct rum_softc *)self;
     421           0 :         struct ifnet *ifp = &sc->sc_ic.ic_if;
     422             :         int s;
     423             : 
     424           0 :         s = splusb();
     425             : 
     426           0 :         if (timeout_initialized(&sc->scan_to))
     427           0 :                 timeout_del(&sc->scan_to);
     428           0 :         if (timeout_initialized(&sc->amrr_to))
     429           0 :                 timeout_del(&sc->amrr_to);
     430             : 
     431           0 :         usb_rem_wait_task(sc->sc_udev, &sc->sc_task);
     432             : 
     433           0 :         usbd_ref_wait(sc->sc_udev);
     434             : 
     435           0 :         if (ifp->if_softc != NULL) {
     436           0 :                 ieee80211_ifdetach(ifp);        /* free all nodes */
     437           0 :                 if_detach(ifp);
     438           0 :         }
     439             : 
     440           0 :         if (sc->amrr_xfer != NULL) {
     441           0 :                 usbd_free_xfer(sc->amrr_xfer);
     442           0 :                 sc->amrr_xfer = NULL;
     443           0 :         }
     444           0 :         if (sc->sc_rx_pipeh != NULL) {
     445           0 :                 usbd_abort_pipe(sc->sc_rx_pipeh);
     446           0 :                 usbd_close_pipe(sc->sc_rx_pipeh);
     447           0 :         }
     448           0 :         if (sc->sc_tx_pipeh != NULL) {
     449           0 :                 usbd_abort_pipe(sc->sc_tx_pipeh);
     450           0 :                 usbd_close_pipe(sc->sc_tx_pipeh);
     451           0 :         }
     452             : 
     453           0 :         rum_free_rx_list(sc);
     454           0 :         rum_free_tx_list(sc);
     455             : 
     456           0 :         splx(s);
     457             : 
     458           0 :         return 0;
     459             : }
     460             : 
     461             : int
     462           0 : rum_alloc_tx_list(struct rum_softc *sc)
     463             : {
     464             :         int i, error;
     465             : 
     466           0 :         sc->tx_cur = sc->tx_queued = 0;
     467             : 
     468           0 :         for (i = 0; i < RUM_TX_LIST_COUNT; i++) {
     469           0 :                 struct rum_tx_data *data = &sc->tx_data[i];
     470             : 
     471           0 :                 data->sc = sc;
     472             : 
     473           0 :                 data->xfer = usbd_alloc_xfer(sc->sc_udev);
     474           0 :                 if (data->xfer == NULL) {
     475           0 :                         printf("%s: could not allocate tx xfer\n",
     476           0 :                             sc->sc_dev.dv_xname);
     477             :                         error = ENOMEM;
     478           0 :                         goto fail;
     479             :                 }
     480           0 :                 data->buf = usbd_alloc_buffer(data->xfer,
     481             :                     RT2573_TX_DESC_SIZE + IEEE80211_MAX_LEN);
     482           0 :                 if (data->buf == NULL) {
     483           0 :                         printf("%s: could not allocate tx buffer\n",
     484           0 :                             sc->sc_dev.dv_xname);
     485             :                         error = ENOMEM;
     486           0 :                         goto fail;
     487             :                 }
     488             :                 /* clean Tx descriptor */
     489           0 :                 bzero(data->buf, RT2573_TX_DESC_SIZE);
     490           0 :         }
     491             : 
     492           0 :         return 0;
     493             : 
     494           0 : fail:   rum_free_tx_list(sc);
     495           0 :         return error;
     496           0 : }
     497             : 
     498             : void
     499           0 : rum_free_tx_list(struct rum_softc *sc)
     500             : {
     501             :         int i;
     502             : 
     503           0 :         for (i = 0; i < RUM_TX_LIST_COUNT; i++) {
     504           0 :                 struct rum_tx_data *data = &sc->tx_data[i];
     505             : 
     506           0 :                 if (data->xfer != NULL) {
     507           0 :                         usbd_free_xfer(data->xfer);
     508           0 :                         data->xfer = NULL;
     509           0 :                 }
     510             :                 /*
     511             :                  * The node has already been freed at that point so don't call
     512             :                  * ieee80211_release_node() here.
     513             :                  */
     514           0 :                 data->ni = NULL;
     515             :         }
     516           0 : }
     517             : 
     518             : int
     519           0 : rum_alloc_rx_list(struct rum_softc *sc)
     520             : {
     521             :         int i, error;
     522             : 
     523           0 :         for (i = 0; i < RUM_RX_LIST_COUNT; i++) {
     524           0 :                 struct rum_rx_data *data = &sc->rx_data[i];
     525             : 
     526           0 :                 data->sc = sc;
     527             : 
     528           0 :                 data->xfer = usbd_alloc_xfer(sc->sc_udev);
     529           0 :                 if (data->xfer == NULL) {
     530           0 :                         printf("%s: could not allocate rx xfer\n",
     531           0 :                             sc->sc_dev.dv_xname);
     532             :                         error = ENOMEM;
     533           0 :                         goto fail;
     534             :                 }
     535           0 :                 if (usbd_alloc_buffer(data->xfer, MCLBYTES) == NULL) {
     536           0 :                         printf("%s: could not allocate rx buffer\n",
     537           0 :                             sc->sc_dev.dv_xname);
     538             :                         error = ENOMEM;
     539           0 :                         goto fail;
     540             :                 }
     541             : 
     542           0 :                 MGETHDR(data->m, M_DONTWAIT, MT_DATA);
     543           0 :                 if (data->m == NULL) {
     544           0 :                         printf("%s: could not allocate rx mbuf\n",
     545           0 :                             sc->sc_dev.dv_xname);
     546             :                         error = ENOMEM;
     547           0 :                         goto fail;
     548             :                 }
     549           0 :                 MCLGET(data->m, M_DONTWAIT);
     550           0 :                 if (!(data->m->m_flags & M_EXT)) {
     551           0 :                         printf("%s: could not allocate rx mbuf cluster\n",
     552           0 :                             sc->sc_dev.dv_xname);
     553             :                         error = ENOMEM;
     554           0 :                         goto fail;
     555             :                 }
     556           0 :                 data->buf = mtod(data->m, uint8_t *);
     557           0 :         }
     558             : 
     559           0 :         return 0;
     560             : 
     561           0 : fail:   rum_free_rx_list(sc);
     562           0 :         return error;
     563           0 : }
     564             : 
     565             : void
     566           0 : rum_free_rx_list(struct rum_softc *sc)
     567             : {
     568             :         int i;
     569             : 
     570           0 :         for (i = 0; i < RUM_RX_LIST_COUNT; i++) {
     571           0 :                 struct rum_rx_data *data = &sc->rx_data[i];
     572             : 
     573           0 :                 if (data->xfer != NULL) {
     574           0 :                         usbd_free_xfer(data->xfer);
     575           0 :                         data->xfer = NULL;
     576           0 :                 }
     577           0 :                 if (data->m != NULL) {
     578           0 :                         m_freem(data->m);
     579           0 :                         data->m = NULL;
     580           0 :                 }
     581             :         }
     582           0 : }
     583             : 
     584             : int
     585           0 : rum_media_change(struct ifnet *ifp)
     586             : {
     587             :         int error;
     588             : 
     589           0 :         error = ieee80211_media_change(ifp);
     590           0 :         if (error != ENETRESET)
     591           0 :                 return error;
     592             : 
     593           0 :         if ((ifp->if_flags & (IFF_UP | IFF_RUNNING)) == (IFF_UP | IFF_RUNNING))
     594           0 :                 rum_init(ifp);
     595             : 
     596           0 :         return 0;
     597           0 : }
     598             : 
     599             : /*
     600             :  * This function is called periodically (every 200ms) during scanning to
     601             :  * switch from one channel to another.
     602             :  */
     603             : void
     604           0 : rum_next_scan(void *arg)
     605             : {
     606           0 :         struct rum_softc *sc = arg;
     607           0 :         struct ieee80211com *ic = &sc->sc_ic;
     608           0 :         struct ifnet *ifp = &ic->ic_if;
     609             : 
     610           0 :         if (usbd_is_dying(sc->sc_udev))
     611           0 :                 return;
     612             : 
     613           0 :         usbd_ref_incr(sc->sc_udev);
     614             : 
     615           0 :         if (ic->ic_state == IEEE80211_S_SCAN)
     616           0 :                 ieee80211_next_scan(ifp);
     617             : 
     618           0 :         usbd_ref_decr(sc->sc_udev);
     619           0 : }
     620             : 
     621             : void
     622           0 : rum_task(void *arg)
     623             : {
     624           0 :         struct rum_softc *sc = arg;
     625           0 :         struct ieee80211com *ic = &sc->sc_ic;
     626             :         enum ieee80211_state ostate;
     627             :         struct ieee80211_node *ni;
     628             :         uint32_t tmp;
     629             : 
     630           0 :         if (usbd_is_dying(sc->sc_udev))
     631           0 :                 return;
     632             : 
     633           0 :         ostate = ic->ic_state;
     634             : 
     635           0 :         switch (sc->sc_state) {
     636             :         case IEEE80211_S_INIT:
     637           0 :                 if (ostate == IEEE80211_S_RUN) {
     638             :                         /* abort TSF synchronization */
     639           0 :                         tmp = rum_read(sc, RT2573_TXRX_CSR9);
     640           0 :                         rum_write(sc, RT2573_TXRX_CSR9, tmp & ~0x00ffffff);
     641           0 :                 }
     642             :                 break;
     643             : 
     644             :         case IEEE80211_S_SCAN:
     645           0 :                 rum_set_chan(sc, ic->ic_bss->ni_chan);
     646           0 :                 if (!usbd_is_dying(sc->sc_udev))
     647           0 :                         timeout_add_msec(&sc->scan_to, 200);
     648             :                 break;
     649             : 
     650             :         case IEEE80211_S_AUTH:
     651           0 :                 rum_set_chan(sc, ic->ic_bss->ni_chan);
     652           0 :                 break;
     653             : 
     654             :         case IEEE80211_S_ASSOC:
     655           0 :                 rum_set_chan(sc, ic->ic_bss->ni_chan);
     656           0 :                 break;
     657             : 
     658             :         case IEEE80211_S_RUN:
     659           0 :                 rum_set_chan(sc, ic->ic_bss->ni_chan);
     660             : 
     661           0 :                 ni = ic->ic_bss;
     662             : 
     663           0 :                 if (ic->ic_opmode != IEEE80211_M_MONITOR) {
     664           0 :                         rum_update_slot(sc);
     665           0 :                         rum_enable_mrr(sc);
     666           0 :                         rum_set_txpreamble(sc);
     667           0 :                         rum_set_basicrates(sc);
     668           0 :                         rum_set_bssid(sc, ni->ni_bssid);
     669           0 :                 }
     670             : 
     671             : #ifndef IEEE80211_STA_ONLY
     672           0 :                 if (ic->ic_opmode == IEEE80211_M_HOSTAP ||
     673           0 :                     ic->ic_opmode == IEEE80211_M_IBSS)
     674           0 :                         rum_prepare_beacon(sc);
     675             : #endif
     676             : 
     677           0 :                 if (ic->ic_opmode != IEEE80211_M_MONITOR)
     678           0 :                         rum_enable_tsf_sync(sc);
     679             : 
     680           0 :                 if (ic->ic_opmode == IEEE80211_M_STA) {
     681             :                         /* fake a join to init the tx rate */
     682           0 :                         rum_newassoc(ic, ic->ic_bss, 1);
     683             : 
     684             :                         /* enable automatic rate control in STA mode */
     685           0 :                         if (ic->ic_fixed_rate == -1)
     686           0 :                                 rum_amrr_start(sc, ni);
     687             :                 }
     688             :                 break;
     689             :         }
     690             : 
     691           0 :         sc->sc_newstate(ic, sc->sc_state, sc->sc_arg);
     692           0 : }
     693             : 
     694             : int
     695           0 : rum_newstate(struct ieee80211com *ic, enum ieee80211_state nstate, int arg)
     696             : {
     697           0 :         struct rum_softc *sc = ic->ic_if.if_softc;
     698             : 
     699           0 :         usb_rem_task(sc->sc_udev, &sc->sc_task);
     700           0 :         timeout_del(&sc->scan_to);
     701           0 :         timeout_del(&sc->amrr_to);
     702             : 
     703             :         /* do it in a process context */
     704           0 :         sc->sc_state = nstate;
     705           0 :         sc->sc_arg = arg;
     706           0 :         usb_add_task(sc->sc_udev, &sc->sc_task);
     707           0 :         return 0;
     708             : }
     709             : 
     710             : /* quickly determine if a given rate is CCK or OFDM */
     711             : #define RUM_RATE_IS_OFDM(rate)  ((rate) >= 12 && (rate) != 22)
     712             : 
     713             : #define RUM_ACK_SIZE    14      /* 10 + 4(FCS) */
     714             : #define RUM_CTS_SIZE    14      /* 10 + 4(FCS) */
     715             : 
     716             : void
     717           0 : rum_txeof(struct usbd_xfer *xfer, void *priv, usbd_status status)
     718             : {
     719           0 :         struct rum_tx_data *data = priv;
     720           0 :         struct rum_softc *sc = data->sc;
     721           0 :         struct ieee80211com *ic = &sc->sc_ic;
     722           0 :         struct ifnet *ifp = &ic->ic_if;
     723             :         int s;
     724             : 
     725           0 :         if (status != USBD_NORMAL_COMPLETION) {
     726           0 :                 if (status == USBD_NOT_STARTED || status == USBD_CANCELLED)
     727           0 :                         return;
     728             : 
     729           0 :                 printf("%s: could not transmit buffer: %s\n",
     730           0 :                     sc->sc_dev.dv_xname, usbd_errstr(status));
     731             : 
     732           0 :                 if (status == USBD_STALLED)
     733           0 :                         usbd_clear_endpoint_stall_async(sc->sc_tx_pipeh);
     734             : 
     735           0 :                 ifp->if_oerrors++;
     736           0 :                 return;
     737             :         }
     738             : 
     739           0 :         s = splnet();
     740             : 
     741           0 :         ieee80211_release_node(ic, data->ni);
     742           0 :         data->ni = NULL;
     743             : 
     744           0 :         sc->tx_queued--;
     745             : 
     746             :         DPRINTFN(10, ("tx done\n"));
     747             : 
     748           0 :         sc->sc_tx_timer = 0;
     749           0 :         ifq_clr_oactive(&ifp->if_snd);
     750           0 :         rum_start(ifp);
     751             : 
     752           0 :         splx(s);
     753           0 : }
     754             : 
     755             : void
     756           0 : rum_rxeof(struct usbd_xfer *xfer, void *priv, usbd_status status)
     757             : {
     758           0 :         struct rum_rx_data *data = priv;
     759           0 :         struct rum_softc *sc = data->sc;
     760           0 :         struct ieee80211com *ic = &sc->sc_ic;
     761           0 :         struct ifnet *ifp = &ic->ic_if;
     762             :         const struct rum_rx_desc *desc;
     763             :         struct ieee80211_frame *wh;
     764           0 :         struct ieee80211_rxinfo rxi;
     765             :         struct ieee80211_node *ni;
     766             :         struct mbuf *mnew, *m;
     767           0 :         int s, len;
     768             : 
     769           0 :         if (status != USBD_NORMAL_COMPLETION) {
     770           0 :                 if (status == USBD_NOT_STARTED || status == USBD_CANCELLED)
     771           0 :                         return;
     772             : 
     773           0 :                 if (status == USBD_STALLED)
     774           0 :                         usbd_clear_endpoint_stall_async(sc->sc_rx_pipeh);
     775             :                 goto skip;
     776             :         }
     777             : 
     778           0 :         usbd_get_xfer_status(xfer, NULL, NULL, &len, NULL);
     779             : 
     780           0 :         if (len < RT2573_RX_DESC_SIZE + sizeof (struct ieee80211_frame_min)) {
     781             :                 DPRINTF(("%s: xfer too short %d\n", sc->sc_dev.dv_xname,
     782             :                     len));
     783           0 :                 ifp->if_ierrors++;
     784           0 :                 goto skip;
     785             :         }
     786             : 
     787           0 :         desc = (const struct rum_rx_desc *)data->buf;
     788             : 
     789           0 :         if (letoh32(desc->flags) & RT2573_RX_CRC_ERROR) {
     790             :                 /*
     791             :                  * This should not happen since we did not request to receive
     792             :                  * those frames when we filled RT2573_TXRX_CSR0.
     793             :                  */
     794             :                 DPRINTFN(5, ("CRC error\n"));
     795           0 :                 ifp->if_ierrors++;
     796           0 :                 goto skip;
     797             :         }
     798             : 
     799           0 :         MGETHDR(mnew, M_DONTWAIT, MT_DATA);
     800           0 :         if (mnew == NULL) {
     801           0 :                 printf("%s: could not allocate rx mbuf\n",
     802           0 :                     sc->sc_dev.dv_xname);
     803           0 :                 ifp->if_ierrors++;
     804           0 :                 goto skip;
     805             :         }
     806           0 :         MCLGET(mnew, M_DONTWAIT);
     807           0 :         if (!(mnew->m_flags & M_EXT)) {
     808           0 :                 printf("%s: could not allocate rx mbuf cluster\n",
     809           0 :                     sc->sc_dev.dv_xname);
     810           0 :                 m_freem(mnew);
     811           0 :                 ifp->if_ierrors++;
     812           0 :                 goto skip;
     813             :         }
     814           0 :         m = data->m;
     815           0 :         data->m = mnew;
     816           0 :         data->buf = mtod(data->m, uint8_t *);
     817             : 
     818             :         /* finalize mbuf */
     819           0 :         m->m_data = (caddr_t)(desc + 1);
     820           0 :         m->m_pkthdr.len = m->m_len = (letoh32(desc->flags) >> 16) & 0xfff;
     821             : 
     822           0 :         s = splnet();
     823             : 
     824             : #if NBPFILTER > 0
     825           0 :         if (sc->sc_drvbpf != NULL) {
     826           0 :                 struct mbuf mb;
     827           0 :                 struct rum_rx_radiotap_header *tap = &sc->sc_rxtap;
     828             : 
     829           0 :                 tap->wr_flags = 0;
     830           0 :                 tap->wr_rate = rum_rxrate(desc);
     831           0 :                 tap->wr_chan_freq = htole16(ic->ic_bss->ni_chan->ic_freq);
     832           0 :                 tap->wr_chan_flags = htole16(ic->ic_bss->ni_chan->ic_flags);
     833           0 :                 tap->wr_antenna = sc->rx_ant;
     834           0 :                 tap->wr_antsignal = desc->rssi;
     835             : 
     836           0 :                 mb.m_data = (caddr_t)tap;
     837           0 :                 mb.m_len = sc->sc_rxtap_len;
     838           0 :                 mb.m_next = m;
     839           0 :                 mb.m_nextpkt = NULL;
     840           0 :                 mb.m_type = 0;
     841           0 :                 mb.m_flags = 0;
     842           0 :                 bpf_mtap(sc->sc_drvbpf, &mb, BPF_DIRECTION_IN);
     843           0 :         }
     844             : #endif
     845             : 
     846           0 :         wh = mtod(m, struct ieee80211_frame *);
     847           0 :         ni = ieee80211_find_rxnode(ic, wh);
     848             : 
     849             :         /* send the frame to the 802.11 layer */
     850           0 :         rxi.rxi_flags = 0;
     851           0 :         rxi.rxi_rssi = desc->rssi;
     852           0 :         rxi.rxi_tstamp = 0;     /* unused */
     853           0 :         ieee80211_input(ifp, m, ni, &rxi);
     854             : 
     855             :         /* node is no longer needed */
     856           0 :         ieee80211_release_node(ic, ni);
     857             : 
     858           0 :         splx(s);
     859             : 
     860             :         DPRINTFN(15, ("rx done\n"));
     861             : 
     862             : skip:   /* setup a new transfer */
     863           0 :         usbd_setup_xfer(xfer, sc->sc_rx_pipeh, data, data->buf, MCLBYTES,
     864             :             USBD_SHORT_XFER_OK, USBD_NO_TIMEOUT, rum_rxeof);
     865           0 :         (void)usbd_transfer(xfer);
     866           0 : }
     867             : 
     868             : /*
     869             :  * This function is only used by the Rx radiotap code. It returns the rate at
     870             :  * which a given frame was received.
     871             :  */
     872             : #if NBPFILTER > 0
     873             : uint8_t
     874           0 : rum_rxrate(const struct rum_rx_desc *desc)
     875             : {
     876           0 :         if (letoh32(desc->flags) & RT2573_RX_OFDM) {
     877             :                 /* reverse function of rum_plcp_signal */
     878           0 :                 switch (desc->rate) {
     879           0 :                 case 0xb:       return 12;
     880           0 :                 case 0xf:       return 18;
     881           0 :                 case 0xa:       return 24;
     882           0 :                 case 0xe:       return 36;
     883           0 :                 case 0x9:       return 48;
     884           0 :                 case 0xd:       return 72;
     885           0 :                 case 0x8:       return 96;
     886           0 :                 case 0xc:       return 108;
     887             :                 }
     888             :         } else {
     889           0 :                 if (desc->rate == 10)
     890           0 :                         return 2;
     891           0 :                 if (desc->rate == 20)
     892           0 :                         return 4;
     893           0 :                 if (desc->rate == 55)
     894           0 :                         return 11;
     895           0 :                 if (desc->rate == 110)
     896           0 :                         return 22;
     897             :         }
     898           0 :         return 2;       /* should not get there */
     899           0 : }
     900             : #endif
     901             : 
     902             : /*
     903             :  * Return the expected ack rate for a frame transmitted at rate `rate'.
     904             :  */
     905             : int
     906           0 : rum_ack_rate(struct ieee80211com *ic, int rate)
     907             : {
     908           0 :         switch (rate) {
     909             :         /* CCK rates */
     910             :         case 2:
     911           0 :                 return 2;
     912             :         case 4:
     913             :         case 11:
     914             :         case 22:
     915           0 :                 return (ic->ic_curmode == IEEE80211_MODE_11B) ? 4 : rate;
     916             : 
     917             :         /* OFDM rates */
     918             :         case 12:
     919             :         case 18:
     920           0 :                 return 12;
     921             :         case 24:
     922             :         case 36:
     923           0 :                 return 24;
     924             :         case 48:
     925             :         case 72:
     926             :         case 96:
     927             :         case 108:
     928           0 :                 return 48;
     929             :         }
     930             : 
     931             :         /* default to 1Mbps */
     932           0 :         return 2;
     933           0 : }
     934             : 
     935             : /*
     936             :  * Compute the duration (in us) needed to transmit `len' bytes at rate `rate'.
     937             :  * The function automatically determines the operating mode depending on the
     938             :  * given rate. `flags' indicates whether short preamble is in use or not.
     939             :  */
     940             : uint16_t
     941           0 : rum_txtime(int len, int rate, uint32_t flags)
     942             : {
     943             :         uint16_t txtime;
     944             : 
     945           0 :         if (RUM_RATE_IS_OFDM(rate)) {
     946             :                 /* IEEE Std 802.11a-1999, pp. 37 */
     947           0 :                 txtime = (8 + 4 * len + 3 + rate - 1) / rate;
     948           0 :                 txtime = 16 + 4 + 4 * txtime + 6;
     949           0 :         } else {
     950             :                 /* IEEE Std 802.11b-1999, pp. 28 */
     951           0 :                 txtime = (16 * len + rate - 1) / rate;
     952           0 :                 if (rate != 2 && (flags & IEEE80211_F_SHPREAMBLE))
     953           0 :                         txtime +=  72 + 24;
     954             :                 else
     955           0 :                         txtime += 144 + 48;
     956             :         }
     957           0 :         return txtime;
     958             : }
     959             : 
     960             : uint8_t
     961           0 : rum_plcp_signal(int rate)
     962             : {
     963           0 :         switch (rate) {
     964             :         /* CCK rates (returned values are device-dependent) */
     965           0 :         case 2:         return 0x0;
     966           0 :         case 4:         return 0x1;
     967           0 :         case 11:        return 0x2;
     968           0 :         case 22:        return 0x3;
     969             : 
     970             :         /* OFDM rates (cf IEEE Std 802.11a-1999, pp. 14 Table 80) */
     971           0 :         case 12:        return 0xb;
     972           0 :         case 18:        return 0xf;
     973           0 :         case 24:        return 0xa;
     974           0 :         case 36:        return 0xe;
     975           0 :         case 48:        return 0x9;
     976           0 :         case 72:        return 0xd;
     977           0 :         case 96:        return 0x8;
     978           0 :         case 108:       return 0xc;
     979             : 
     980             :         /* unsupported rates (should not get there) */
     981           0 :         default:        return 0xff;
     982             :         }
     983           0 : }
     984             : 
     985             : void
     986           0 : rum_setup_tx_desc(struct rum_softc *sc, struct rum_tx_desc *desc,
     987             :     uint32_t flags, uint16_t xflags, int len, int rate)
     988             : {
     989           0 :         struct ieee80211com *ic = &sc->sc_ic;
     990             :         uint16_t plcp_length;
     991             :         int remainder;
     992             : 
     993           0 :         desc->flags = htole32(flags);
     994           0 :         desc->flags |= htole32(RT2573_TX_VALID);
     995           0 :         desc->flags |= htole32(len << 16);
     996             : 
     997           0 :         desc->xflags = htole16(xflags);
     998             : 
     999           0 :         desc->wme = htole16(
    1000             :             RT2573_QID(0) |
    1001             :             RT2573_AIFSN(2) |
    1002             :             RT2573_LOGCWMIN(4) |
    1003             :             RT2573_LOGCWMAX(10));
    1004             : 
    1005             :         /* setup PLCP fields */
    1006           0 :         desc->plcp_signal  = rum_plcp_signal(rate);
    1007           0 :         desc->plcp_service = 4;
    1008             : 
    1009           0 :         len += IEEE80211_CRC_LEN;
    1010           0 :         if (RUM_RATE_IS_OFDM(rate)) {
    1011           0 :                 desc->flags |= htole32(RT2573_TX_OFDM);
    1012             : 
    1013           0 :                 plcp_length = len & 0xfff;
    1014           0 :                 desc->plcp_length_hi = plcp_length >> 6;
    1015           0 :                 desc->plcp_length_lo = plcp_length & 0x3f;
    1016           0 :         } else {
    1017           0 :                 plcp_length = (16 * len + rate - 1) / rate;
    1018           0 :                 if (rate == 22) {
    1019           0 :                         remainder = (16 * len) % 22;
    1020           0 :                         if (remainder != 0 && remainder < 7)
    1021           0 :                                 desc->plcp_service |= RT2573_PLCP_LENGEXT;
    1022             :                 }
    1023           0 :                 desc->plcp_length_hi = plcp_length >> 8;
    1024           0 :                 desc->plcp_length_lo = plcp_length & 0xff;
    1025             : 
    1026           0 :                 if (rate != 2 && (ic->ic_flags & IEEE80211_F_SHPREAMBLE))
    1027           0 :                         desc->plcp_signal |= 0x08;
    1028             :         }
    1029           0 : }
    1030             : 
    1031             : #define RUM_TX_TIMEOUT  5000
    1032             : 
    1033             : int
    1034           0 : rum_tx_data(struct rum_softc *sc, struct mbuf *m0, struct ieee80211_node *ni)
    1035             : {
    1036           0 :         struct ieee80211com *ic = &sc->sc_ic;
    1037             :         struct rum_tx_desc *desc;
    1038             :         struct rum_tx_data *data;
    1039             :         struct ieee80211_frame *wh;
    1040             :         struct ieee80211_key *k;
    1041             :         uint32_t flags = 0;
    1042             :         uint16_t dur;
    1043             :         usbd_status error;
    1044             :         int rate, xferlen, pktlen, needrts = 0, needcts = 0;
    1045             : 
    1046           0 :         wh = mtod(m0, struct ieee80211_frame *);
    1047             : 
    1048           0 :         if (wh->i_fc[1] & IEEE80211_FC1_PROTECTED) {
    1049           0 :                 k = ieee80211_get_txkey(ic, wh, ni);
    1050             : 
    1051           0 :                 if ((m0 = ieee80211_encrypt(ic, m0, k)) == NULL)
    1052           0 :                         return ENOBUFS;
    1053             : 
    1054             :                 /* packet header may have moved, reset our local pointer */
    1055           0 :                 wh = mtod(m0, struct ieee80211_frame *);
    1056           0 :         }
    1057             : 
    1058             :         /* compute actual packet length (including CRC and crypto overhead) */
    1059           0 :         pktlen = m0->m_pkthdr.len + IEEE80211_CRC_LEN;
    1060             : 
    1061             :         /* pickup a rate */
    1062           0 :         if (IEEE80211_IS_MULTICAST(wh->i_addr1) ||
    1063           0 :             ((wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK) ==
    1064             :              IEEE80211_FC0_TYPE_MGT)) {
    1065             :                 /* mgmt/multicast frames are sent at the lowest avail. rate */
    1066           0 :                 rate = ni->ni_rates.rs_rates[0];
    1067           0 :         } else if (ic->ic_fixed_rate != -1) {
    1068           0 :                 rate = ic->ic_sup_rates[ic->ic_curmode].
    1069           0 :                     rs_rates[ic->ic_fixed_rate];
    1070           0 :         } else
    1071           0 :                 rate = ni->ni_rates.rs_rates[ni->ni_txrate];
    1072           0 :         if (rate == 0)
    1073           0 :                 rate = 2;       /* XXX should not happen */
    1074           0 :         rate &= IEEE80211_RATE_VAL;
    1075             : 
    1076             :         /* check if RTS/CTS or CTS-to-self protection must be used */
    1077           0 :         if (!IEEE80211_IS_MULTICAST(wh->i_addr1)) {
    1078             :                 /* multicast frames are not sent at OFDM rates in 802.11b/g */
    1079           0 :                 if (pktlen > ic->ic_rtsthreshold) {
    1080             :                         needrts = 1;    /* RTS/CTS based on frame length */
    1081           0 :                 } else if ((ic->ic_flags & IEEE80211_F_USEPROT) &&
    1082           0 :                     RUM_RATE_IS_OFDM(rate)) {
    1083           0 :                         if (ic->ic_protmode == IEEE80211_PROT_CTSONLY)
    1084           0 :                                 needcts = 1;    /* CTS-to-self */
    1085           0 :                         else if (ic->ic_protmode == IEEE80211_PROT_RTSCTS)
    1086           0 :                                 needrts = 1;    /* RTS/CTS */
    1087             :                 }
    1088             :         }
    1089           0 :         if (needrts || needcts) {
    1090             :                 struct mbuf *mprot;
    1091             :                 int protrate, ackrate;
    1092             :                 uint16_t dur;
    1093             : 
    1094           0 :                 protrate = IEEE80211_IS_CHAN_5GHZ(ni->ni_chan) ? 12 : 2;
    1095           0 :                 ackrate  = rum_ack_rate(ic, rate);
    1096             : 
    1097           0 :                 dur = rum_txtime(pktlen, rate, ic->ic_flags) +
    1098           0 :                       rum_txtime(RUM_ACK_SIZE, ackrate, ic->ic_flags) +
    1099           0 :                       2 * sc->sifs;
    1100           0 :                 if (needrts) {
    1101           0 :                         dur += rum_txtime(RUM_CTS_SIZE, rum_ack_rate(ic,
    1102           0 :                             protrate), ic->ic_flags) + sc->sifs;
    1103           0 :                         mprot = ieee80211_get_rts(ic, wh, dur);
    1104           0 :                 } else {
    1105           0 :                         mprot = ieee80211_get_cts_to_self(ic, dur);
    1106             :                 }
    1107           0 :                 if (mprot == NULL) {
    1108           0 :                         printf("%s: could not allocate protection frame\n",
    1109           0 :                             sc->sc_dev.dv_xname);
    1110           0 :                         m_freem(m0);
    1111           0 :                         return ENOBUFS;
    1112             :                 }
    1113             : 
    1114           0 :                 data = &sc->tx_data[sc->tx_cur];
    1115           0 :                 desc = (struct rum_tx_desc *)data->buf;
    1116             : 
    1117             :                 /* avoid multiple free() of the same node for each fragment */
    1118           0 :                 data->ni = ieee80211_ref_node(ni);
    1119             : 
    1120           0 :                 m_copydata(mprot, 0, mprot->m_pkthdr.len,
    1121           0 :                     data->buf + RT2573_TX_DESC_SIZE);
    1122           0 :                 rum_setup_tx_desc(sc, desc,
    1123           0 :                     (needrts ? RT2573_TX_NEED_ACK : 0) | RT2573_TX_MORE_FRAG,
    1124           0 :                     0, mprot->m_pkthdr.len, protrate);
    1125             : 
    1126             :                 /* no roundup necessary here */
    1127           0 :                 xferlen = RT2573_TX_DESC_SIZE + mprot->m_pkthdr.len;
    1128             : 
    1129             :                 /* XXX may want to pass the protection frame to BPF */
    1130             : 
    1131             :                 /* mbuf is no longer needed */
    1132           0 :                 m_freem(mprot);
    1133             : 
    1134           0 :                 usbd_setup_xfer(data->xfer, sc->sc_tx_pipeh, data, data->buf,
    1135             :                     xferlen, USBD_FORCE_SHORT_XFER | USBD_NO_COPY,
    1136             :                     RUM_TX_TIMEOUT, rum_txeof);
    1137           0 :                 error = usbd_transfer(data->xfer);
    1138           0 :                 if (error != 0 && error != USBD_IN_PROGRESS) {
    1139           0 :                         m_freem(m0);
    1140           0 :                         return error;
    1141             :                 }
    1142             : 
    1143           0 :                 sc->tx_queued++;
    1144           0 :                 sc->tx_cur = (sc->tx_cur + 1) % RUM_TX_LIST_COUNT;
    1145             : 
    1146             :                 flags |= RT2573_TX_LONG_RETRY | RT2573_TX_IFS_SIFS;
    1147           0 :         }
    1148             : 
    1149           0 :         data = &sc->tx_data[sc->tx_cur];
    1150           0 :         desc = (struct rum_tx_desc *)data->buf;
    1151             : 
    1152           0 :         data->ni = ni;
    1153             : 
    1154           0 :         if (!IEEE80211_IS_MULTICAST(wh->i_addr1)) {
    1155           0 :                 flags |= RT2573_TX_NEED_ACK;
    1156             : 
    1157           0 :                 dur = rum_txtime(RUM_ACK_SIZE, rum_ack_rate(ic, rate),
    1158           0 :                     ic->ic_flags) + sc->sifs;
    1159           0 :                 *(uint16_t *)wh->i_dur = htole16(dur);
    1160             : 
    1161             : #ifndef IEEE80211_STA_ONLY
    1162             :                 /* tell hardware to set timestamp in probe responses */
    1163           0 :                 if ((wh->i_fc[0] &
    1164           0 :                     (IEEE80211_FC0_TYPE_MASK | IEEE80211_FC0_SUBTYPE_MASK)) ==
    1165             :                     (IEEE80211_FC0_TYPE_MGT | IEEE80211_FC0_SUBTYPE_PROBE_RESP))
    1166           0 :                         flags |= RT2573_TX_TIMESTAMP;
    1167             : #endif
    1168             :         }
    1169             : 
    1170             : #if NBPFILTER > 0
    1171           0 :         if (sc->sc_drvbpf != NULL) {
    1172           0 :                 struct mbuf mb;
    1173           0 :                 struct rum_tx_radiotap_header *tap = &sc->sc_txtap;
    1174             : 
    1175           0 :                 tap->wt_flags = 0;
    1176           0 :                 tap->wt_rate = rate;
    1177           0 :                 tap->wt_chan_freq = htole16(ic->ic_bss->ni_chan->ic_freq);
    1178           0 :                 tap->wt_chan_flags = htole16(ic->ic_bss->ni_chan->ic_flags);
    1179           0 :                 tap->wt_antenna = sc->tx_ant;
    1180             : 
    1181           0 :                 mb.m_data = (caddr_t)tap;
    1182           0 :                 mb.m_len = sc->sc_txtap_len;
    1183           0 :                 mb.m_next = m0;
    1184           0 :                 mb.m_nextpkt = NULL;
    1185           0 :                 mb.m_type = 0;
    1186           0 :                 mb.m_flags = 0;
    1187           0 :                 bpf_mtap(sc->sc_drvbpf, &mb, BPF_DIRECTION_OUT);
    1188           0 :         }
    1189             : #endif
    1190             : 
    1191           0 :         m_copydata(m0, 0, m0->m_pkthdr.len, data->buf + RT2573_TX_DESC_SIZE);
    1192           0 :         rum_setup_tx_desc(sc, desc, flags, 0, m0->m_pkthdr.len, rate);
    1193             : 
    1194             :         /* align end on a 4-bytes boundary */
    1195           0 :         xferlen = (RT2573_TX_DESC_SIZE + m0->m_pkthdr.len + 3) & ~3;
    1196             : 
    1197             :         /*
    1198             :          * No space left in the last URB to store the extra 4 bytes, force
    1199             :          * sending of another URB.
    1200             :          */
    1201           0 :         if ((xferlen % 64) == 0)
    1202           0 :                 xferlen += 4;
    1203             : 
    1204             :         DPRINTFN(10, ("sending frame len=%u rate=%u xfer len=%u\n",
    1205             :             m0->m_pkthdr.len + RT2573_TX_DESC_SIZE, rate, xferlen));
    1206             : 
    1207             :         /* mbuf is no longer needed */
    1208           0 :         m_freem(m0);
    1209             : 
    1210           0 :         usbd_setup_xfer(data->xfer, sc->sc_tx_pipeh, data, data->buf, xferlen,
    1211             :             USBD_FORCE_SHORT_XFER | USBD_NO_COPY, RUM_TX_TIMEOUT, rum_txeof);
    1212           0 :         error = usbd_transfer(data->xfer);
    1213           0 :         if (error != 0 && error != USBD_IN_PROGRESS)
    1214           0 :                 return error;
    1215             : 
    1216           0 :         sc->tx_queued++;
    1217           0 :         sc->tx_cur = (sc->tx_cur + 1) % RUM_TX_LIST_COUNT;
    1218             : 
    1219           0 :         return 0;
    1220           0 : }
    1221             : 
    1222             : void
    1223           0 : rum_start(struct ifnet *ifp)
    1224             : {
    1225           0 :         struct rum_softc *sc = ifp->if_softc;
    1226           0 :         struct ieee80211com *ic = &sc->sc_ic;
    1227           0 :         struct ieee80211_node *ni;
    1228             :         struct mbuf *m0;
    1229             : 
    1230             :         /*
    1231             :          * net80211 may still try to send management frames even if the
    1232             :          * IFF_RUNNING flag is not set...
    1233             :          */
    1234           0 :         if (!(ifp->if_flags & IFF_RUNNING) || ifq_is_oactive(&ifp->if_snd))
    1235           0 :                 return;
    1236             : 
    1237           0 :         for (;;) {
    1238           0 :                 if (sc->tx_queued >= RUM_TX_LIST_COUNT - 1) {
    1239           0 :                         ifq_set_oactive(&ifp->if_snd);
    1240           0 :                         break;
    1241             :                 }
    1242             : 
    1243           0 :                 m0 = mq_dequeue(&ic->ic_mgtq);
    1244           0 :                 if (m0 != NULL) {
    1245           0 :                         ni = m0->m_pkthdr.ph_cookie;
    1246             : #if NBPFILTER > 0
    1247           0 :                         if (ic->ic_rawbpf != NULL)
    1248           0 :                                 bpf_mtap(ic->ic_rawbpf, m0, BPF_DIRECTION_OUT);
    1249             : #endif
    1250           0 :                         if (rum_tx_data(sc, m0, ni) != 0)
    1251             :                                 break;
    1252             : 
    1253             :                 } else {
    1254           0 :                         if (ic->ic_state != IEEE80211_S_RUN)
    1255             :                                 break;
    1256             : 
    1257           0 :                         IFQ_DEQUEUE(&ifp->if_snd, m0);
    1258           0 :                         if (m0 == NULL)
    1259             :                                 break;
    1260             : #if NBPFILTER > 0
    1261           0 :                         if (ifp->if_bpf != NULL)
    1262           0 :                                 bpf_mtap(ifp->if_bpf, m0, BPF_DIRECTION_OUT);
    1263             : #endif
    1264           0 :                         m0 = ieee80211_encap(ifp, m0, &ni);
    1265           0 :                         if (m0 == NULL)
    1266           0 :                                 continue;
    1267             : #if NBPFILTER > 0
    1268           0 :                         if (ic->ic_rawbpf != NULL)
    1269           0 :                                 bpf_mtap(ic->ic_rawbpf, m0, BPF_DIRECTION_OUT);
    1270             : #endif
    1271           0 :                         if (rum_tx_data(sc, m0, ni) != 0) {
    1272           0 :                                 if (ni != NULL)
    1273           0 :                                         ieee80211_release_node(ic, ni);
    1274           0 :                                 ifp->if_oerrors++;
    1275           0 :                                 break;
    1276             :                         }
    1277             :                 }
    1278             : 
    1279           0 :                 sc->sc_tx_timer = 5;
    1280           0 :                 ifp->if_timer = 1;
    1281             :         }
    1282           0 : }
    1283             : 
    1284             : void
    1285           0 : rum_watchdog(struct ifnet *ifp)
    1286             : {
    1287           0 :         struct rum_softc *sc = ifp->if_softc;
    1288             : 
    1289           0 :         ifp->if_timer = 0;
    1290             : 
    1291           0 :         if (sc->sc_tx_timer > 0) {
    1292           0 :                 if (--sc->sc_tx_timer == 0) {
    1293           0 :                         printf("%s: device timeout\n", sc->sc_dev.dv_xname);
    1294             :                         /*rum_init(ifp); XXX needs a process context! */
    1295           0 :                         ifp->if_oerrors++;
    1296           0 :                         return;
    1297             :                 }
    1298           0 :                 ifp->if_timer = 1;
    1299           0 :         }
    1300             : 
    1301           0 :         ieee80211_watchdog(ifp);
    1302           0 : }
    1303             : 
    1304             : int
    1305           0 : rum_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
    1306             : {
    1307           0 :         struct rum_softc *sc = ifp->if_softc;
    1308           0 :         struct ieee80211com *ic = &sc->sc_ic;
    1309             :         int s, error = 0;
    1310             : 
    1311           0 :         if (usbd_is_dying(sc->sc_udev))
    1312           0 :                 return ENXIO;
    1313             : 
    1314           0 :         usbd_ref_incr(sc->sc_udev);
    1315             : 
    1316           0 :         s = splnet();
    1317             : 
    1318           0 :         switch (cmd) {
    1319             :         case SIOCSIFADDR:
    1320           0 :                 ifp->if_flags |= IFF_UP;
    1321             :                 /* FALLTHROUGH */
    1322             :         case SIOCSIFFLAGS:
    1323           0 :                 if (ifp->if_flags & IFF_UP) {
    1324           0 :                         if (ifp->if_flags & IFF_RUNNING)
    1325           0 :                                 rum_update_promisc(sc);
    1326             :                         else
    1327           0 :                                 rum_init(ifp);
    1328             :                 } else {
    1329           0 :                         if (ifp->if_flags & IFF_RUNNING)
    1330           0 :                                 rum_stop(ifp, 1);
    1331             :                 }
    1332             :                 break;
    1333             : 
    1334             :         case SIOCS80211CHANNEL:
    1335             :                 /*
    1336             :                  * This allows for fast channel switching in monitor mode
    1337             :                  * (used by kismet). In IBSS mode, we must explicitly reset
    1338             :                  * the interface to generate a new beacon frame.
    1339             :                  */
    1340           0 :                 error = ieee80211_ioctl(ifp, cmd, data);
    1341           0 :                 if (error == ENETRESET &&
    1342           0 :                     ic->ic_opmode == IEEE80211_M_MONITOR) {
    1343           0 :                         if ((ifp->if_flags & (IFF_UP | IFF_RUNNING)) ==
    1344             :                             (IFF_UP | IFF_RUNNING))
    1345           0 :                                 rum_set_chan(sc, ic->ic_ibss_chan);
    1346             :                         error = 0;
    1347           0 :                 }
    1348             :                 break;
    1349             : 
    1350             :         default:
    1351           0 :                 error = ieee80211_ioctl(ifp, cmd, data);
    1352           0 :         }
    1353             : 
    1354           0 :         if (error == ENETRESET) {
    1355           0 :                 if ((ifp->if_flags & (IFF_UP | IFF_RUNNING)) ==
    1356             :                     (IFF_UP | IFF_RUNNING))
    1357           0 :                         rum_init(ifp);
    1358             :                 error = 0;
    1359           0 :         }
    1360             : 
    1361           0 :         splx(s);
    1362             : 
    1363           0 :         usbd_ref_decr(sc->sc_udev);
    1364             : 
    1365           0 :         return error;
    1366           0 : }
    1367             : 
    1368             : void
    1369           0 : rum_eeprom_read(struct rum_softc *sc, uint16_t addr, void *buf, int len)
    1370             : {
    1371           0 :         usb_device_request_t req;
    1372             :         usbd_status error;
    1373             : 
    1374           0 :         req.bmRequestType = UT_READ_VENDOR_DEVICE;
    1375           0 :         req.bRequest = RT2573_READ_EEPROM;
    1376           0 :         USETW(req.wValue, 0);
    1377           0 :         USETW(req.wIndex, addr);
    1378           0 :         USETW(req.wLength, len);
    1379             : 
    1380           0 :         error = usbd_do_request(sc->sc_udev, &req, buf);
    1381           0 :         if (error != 0) {
    1382           0 :                 printf("%s: could not read EEPROM: %s\n",
    1383           0 :                     sc->sc_dev.dv_xname, usbd_errstr(error));
    1384           0 :         }
    1385           0 : }
    1386             : 
    1387             : uint32_t
    1388           0 : rum_read(struct rum_softc *sc, uint16_t reg)
    1389             : {
    1390           0 :         uint32_t val;
    1391             : 
    1392           0 :         rum_read_multi(sc, reg, &val, sizeof val);
    1393             : 
    1394           0 :         return letoh32(val);
    1395           0 : }
    1396             : 
    1397             : void
    1398           0 : rum_read_multi(struct rum_softc *sc, uint16_t reg, void *buf, int len)
    1399             : {
    1400           0 :         usb_device_request_t req;
    1401             :         usbd_status error;
    1402             : 
    1403           0 :         req.bmRequestType = UT_READ_VENDOR_DEVICE;
    1404           0 :         req.bRequest = RT2573_READ_MULTI_MAC;
    1405           0 :         USETW(req.wValue, 0);
    1406           0 :         USETW(req.wIndex, reg);
    1407           0 :         USETW(req.wLength, len);
    1408             : 
    1409           0 :         error = usbd_do_request(sc->sc_udev, &req, buf);
    1410           0 :         if (error != 0) {
    1411           0 :                 printf("%s: could not multi read MAC register: %s\n",
    1412           0 :                     sc->sc_dev.dv_xname, usbd_errstr(error));
    1413           0 :         }
    1414           0 : }
    1415             : 
    1416             : void
    1417           0 : rum_write(struct rum_softc *sc, uint16_t reg, uint32_t val)
    1418             : {
    1419           0 :         uint32_t tmp = htole32(val);
    1420             : 
    1421           0 :         rum_write_multi(sc, reg, &tmp, sizeof tmp);
    1422           0 : }
    1423             : 
    1424             : void
    1425           0 : rum_write_multi(struct rum_softc *sc, uint16_t reg, void *buf, size_t len)
    1426             : {
    1427           0 :         usb_device_request_t req;
    1428             :         usbd_status error;
    1429             :         int offset;
    1430             : 
    1431           0 :         req.bmRequestType = UT_WRITE_VENDOR_DEVICE;
    1432           0 :         req.bRequest = RT2573_WRITE_MULTI_MAC;
    1433           0 :         USETW(req.wValue, 0);
    1434             : 
    1435             :         /* write at most 64 bytes at a time */
    1436           0 :         for (offset = 0; offset < len; offset += 64) {
    1437           0 :                 USETW(req.wIndex, reg + offset);
    1438           0 :                 USETW(req.wLength, MIN(len - offset, 64));
    1439             : 
    1440           0 :                 error = usbd_do_request(sc->sc_udev, &req, buf + offset);
    1441           0 :                 if (error != 0) {
    1442           0 :                         printf("%s: could not multi write MAC register: %s\n",
    1443           0 :                             sc->sc_dev.dv_xname, usbd_errstr(error));
    1444           0 :                 }
    1445             :         }
    1446           0 : }
    1447             : 
    1448             : void
    1449           0 : rum_bbp_write(struct rum_softc *sc, uint8_t reg, uint8_t val)
    1450             : {
    1451             :         uint32_t tmp;
    1452             :         int ntries;
    1453             : 
    1454           0 :         for (ntries = 0; ntries < 5; ntries++) {
    1455           0 :                 if (!(rum_read(sc, RT2573_PHY_CSR3) & RT2573_BBP_BUSY))
    1456             :                         break;
    1457             :         }
    1458           0 :         if (ntries == 5) {
    1459           0 :                 printf("%s: could not write to BBP\n", sc->sc_dev.dv_xname);
    1460           0 :                 return;
    1461             :         }
    1462             : 
    1463           0 :         tmp = RT2573_BBP_BUSY | (reg & 0x7f) << 8 | val;
    1464           0 :         rum_write(sc, RT2573_PHY_CSR3, tmp);
    1465           0 : }
    1466             : 
    1467             : uint8_t
    1468           0 : rum_bbp_read(struct rum_softc *sc, uint8_t reg)
    1469             : {
    1470             :         uint32_t val;
    1471             :         int ntries;
    1472             : 
    1473           0 :         for (ntries = 0; ntries < 5; ntries++) {
    1474           0 :                 if (!(rum_read(sc, RT2573_PHY_CSR3) & RT2573_BBP_BUSY))
    1475             :                         break;
    1476             :         }
    1477           0 :         if (ntries == 5) {
    1478           0 :                 printf("%s: could not read BBP\n", sc->sc_dev.dv_xname);
    1479           0 :                 return 0;
    1480             :         }
    1481             : 
    1482           0 :         val = RT2573_BBP_BUSY | RT2573_BBP_READ | reg << 8;
    1483           0 :         rum_write(sc, RT2573_PHY_CSR3, val);
    1484             : 
    1485           0 :         for (ntries = 0; ntries < 100; ntries++) {
    1486           0 :                 val = rum_read(sc, RT2573_PHY_CSR3);
    1487           0 :                 if (!(val & RT2573_BBP_BUSY))
    1488           0 :                         return val & 0xff;
    1489           0 :                 DELAY(1);
    1490             :         }
    1491             : 
    1492           0 :         printf("%s: could not read BBP\n", sc->sc_dev.dv_xname);
    1493           0 :         return 0;
    1494           0 : }
    1495             : 
    1496             : void
    1497           0 : rum_rf_write(struct rum_softc *sc, uint8_t reg, uint32_t val)
    1498             : {
    1499             :         uint32_t tmp;
    1500             :         int ntries;
    1501             : 
    1502           0 :         for (ntries = 0; ntries < 5; ntries++) {
    1503           0 :                 if (!(rum_read(sc, RT2573_PHY_CSR4) & RT2573_RF_BUSY))
    1504             :                         break;
    1505             :         }
    1506           0 :         if (ntries == 5) {
    1507           0 :                 printf("%s: could not write to RF\n", sc->sc_dev.dv_xname);
    1508           0 :                 return;
    1509             :         }
    1510             : 
    1511           0 :         tmp = RT2573_RF_BUSY | RT2573_RF_20BIT | (val & 0xfffff) << 2 |
    1512           0 :             (reg & 3);
    1513           0 :         rum_write(sc, RT2573_PHY_CSR4, tmp);
    1514             : 
    1515             :         /* remember last written value in sc */
    1516           0 :         sc->rf_regs[reg] = val;
    1517             : 
    1518             :         DPRINTFN(15, ("RF R[%u] <- 0x%05x\n", reg & 3, val & 0xfffff));
    1519           0 : }
    1520             : 
    1521             : void
    1522           0 : rum_select_antenna(struct rum_softc *sc)
    1523             : {
    1524             :         uint8_t bbp4, bbp77;
    1525             :         uint32_t tmp;
    1526             : 
    1527           0 :         bbp4  = rum_bbp_read(sc, 4);
    1528           0 :         bbp77 = rum_bbp_read(sc, 77);
    1529             : 
    1530             :         /* TBD */
    1531             : 
    1532             :         /* make sure Rx is disabled before switching antenna */
    1533           0 :         tmp = rum_read(sc, RT2573_TXRX_CSR0);
    1534           0 :         rum_write(sc, RT2573_TXRX_CSR0, tmp | RT2573_DISABLE_RX);
    1535             : 
    1536           0 :         rum_bbp_write(sc,  4, bbp4);
    1537           0 :         rum_bbp_write(sc, 77, bbp77);
    1538             : 
    1539           0 :         rum_write(sc, RT2573_TXRX_CSR0, tmp);
    1540           0 : }
    1541             : 
    1542             : /*
    1543             :  * Enable multi-rate retries for frames sent at OFDM rates.
    1544             :  * In 802.11b/g mode, allow fallback to CCK rates.
    1545             :  */
    1546             : void
    1547           0 : rum_enable_mrr(struct rum_softc *sc)
    1548             : {
    1549           0 :         struct ieee80211com *ic = &sc->sc_ic;
    1550             :         uint32_t tmp;
    1551             : 
    1552           0 :         tmp = rum_read(sc, RT2573_TXRX_CSR4);
    1553             : 
    1554           0 :         tmp &= ~RT2573_MRR_CCK_FALLBACK;
    1555           0 :         if (!IEEE80211_IS_CHAN_5GHZ(ic->ic_bss->ni_chan))
    1556           0 :                 tmp |= RT2573_MRR_CCK_FALLBACK;
    1557           0 :         tmp |= RT2573_MRR_ENABLED;
    1558             : 
    1559           0 :         rum_write(sc, RT2573_TXRX_CSR4, tmp);
    1560           0 : }
    1561             : 
    1562             : void
    1563           0 : rum_set_txpreamble(struct rum_softc *sc)
    1564             : {
    1565             :         uint32_t tmp;
    1566             : 
    1567           0 :         tmp = rum_read(sc, RT2573_TXRX_CSR4);
    1568             : 
    1569           0 :         tmp &= ~RT2573_SHORT_PREAMBLE;
    1570           0 :         if (sc->sc_ic.ic_flags & IEEE80211_F_SHPREAMBLE)
    1571           0 :                 tmp |= RT2573_SHORT_PREAMBLE;
    1572             : 
    1573           0 :         rum_write(sc, RT2573_TXRX_CSR4, tmp);
    1574           0 : }
    1575             : 
    1576             : void
    1577           0 : rum_set_basicrates(struct rum_softc *sc)
    1578             : {
    1579           0 :         struct ieee80211com *ic = &sc->sc_ic;
    1580             : 
    1581             :         /* update basic rate set */
    1582           0 :         if (ic->ic_curmode == IEEE80211_MODE_11B) {
    1583             :                 /* 11b basic rates: 1, 2Mbps */
    1584           0 :                 rum_write(sc, RT2573_TXRX_CSR5, 0x3);
    1585           0 :         } else if (ic->ic_curmode == IEEE80211_MODE_11A) {
    1586             :                 /* 11a basic rates: 6, 12, 24Mbps */
    1587           0 :                 rum_write(sc, RT2573_TXRX_CSR5, 0x150);
    1588           0 :         } else {
    1589             :                 /* 11b/g basic rates: 1, 2, 5.5, 11Mbps */
    1590           0 :                 rum_write(sc, RT2573_TXRX_CSR5, 0xf);
    1591             :         }
    1592           0 : }
    1593             : 
    1594             : /*
    1595             :  * Reprogram MAC/BBP to switch to a new band.  Values taken from the reference
    1596             :  * driver.
    1597             :  */
    1598             : void
    1599           0 : rum_select_band(struct rum_softc *sc, struct ieee80211_channel *c)
    1600             : {
    1601             :         uint8_t bbp17, bbp35, bbp96, bbp97, bbp98, bbp104;
    1602             :         uint32_t tmp;
    1603             : 
    1604             :         /* update all BBP registers that depend on the band */
    1605             :         bbp17 = 0x20; bbp96 = 0x48; bbp104 = 0x2c;
    1606             :         bbp35 = 0x50; bbp97 = 0x48; bbp98  = 0x48;
    1607           0 :         if (IEEE80211_IS_CHAN_5GHZ(c)) {
    1608             :                 bbp17 += 0x08; bbp96 += 0x10; bbp104 += 0x0c;
    1609             :                 bbp35 += 0x10; bbp97 += 0x10; bbp98  += 0x10;
    1610           0 :         }
    1611           0 :         if ((IEEE80211_IS_CHAN_2GHZ(c) && sc->ext_2ghz_lna) ||
    1612           0 :             (IEEE80211_IS_CHAN_5GHZ(c) && sc->ext_5ghz_lna)) {
    1613           0 :                 bbp17 += 0x10; bbp96 += 0x10; bbp104 += 0x10;
    1614           0 :         }
    1615             : 
    1616           0 :         sc->bbp17 = bbp17;
    1617           0 :         rum_bbp_write(sc,  17, bbp17);
    1618           0 :         rum_bbp_write(sc,  96, bbp96);
    1619           0 :         rum_bbp_write(sc, 104, bbp104);
    1620             : 
    1621           0 :         if ((IEEE80211_IS_CHAN_2GHZ(c) && sc->ext_2ghz_lna) ||
    1622           0 :             (IEEE80211_IS_CHAN_5GHZ(c) && sc->ext_5ghz_lna)) {
    1623           0 :                 rum_bbp_write(sc, 75, 0x80);
    1624           0 :                 rum_bbp_write(sc, 86, 0x80);
    1625           0 :                 rum_bbp_write(sc, 88, 0x80);
    1626           0 :         }
    1627             : 
    1628           0 :         rum_bbp_write(sc, 35, bbp35);
    1629           0 :         rum_bbp_write(sc, 97, bbp97);
    1630           0 :         rum_bbp_write(sc, 98, bbp98);
    1631             : 
    1632           0 :         tmp = rum_read(sc, RT2573_PHY_CSR0);
    1633           0 :         tmp &= ~(RT2573_PA_PE_2GHZ | RT2573_PA_PE_5GHZ);
    1634           0 :         if (IEEE80211_IS_CHAN_2GHZ(c))
    1635           0 :                 tmp |= RT2573_PA_PE_2GHZ;
    1636             :         else
    1637           0 :                 tmp |= RT2573_PA_PE_5GHZ;
    1638           0 :         rum_write(sc, RT2573_PHY_CSR0, tmp);
    1639             : 
    1640             :         /* 802.11a uses a 16 microseconds short interframe space */
    1641           0 :         sc->sifs = IEEE80211_IS_CHAN_5GHZ(c) ? 16 : 10;
    1642           0 : }
    1643             : 
    1644             : void
    1645           0 : rum_set_chan(struct rum_softc *sc, struct ieee80211_channel *c)
    1646             : {
    1647           0 :         struct ieee80211com *ic = &sc->sc_ic;
    1648             :         const struct rfprog *rfprog;
    1649             :         uint8_t bbp3, bbp94 = RT2573_BBPR94_DEFAULT;
    1650             :         int8_t power;
    1651             :         u_int i, chan;
    1652             : 
    1653           0 :         chan = ieee80211_chan2ieee(ic, c);
    1654           0 :         if (chan == 0 || chan == IEEE80211_CHAN_ANY)
    1655           0 :                 return;
    1656             : 
    1657             :         /* select the appropriate RF settings based on what EEPROM says */
    1658           0 :         rfprog = (sc->rf_rev == RT2573_RF_5225 ||
    1659           0 :                   sc->rf_rev == RT2573_RF_2527) ? rum_rf5225 : rum_rf5226;
    1660             : 
    1661             :         /* find the settings for this channel (we know it exists) */
    1662           0 :         for (i = 0; rfprog[i].chan != chan; i++);
    1663             : 
    1664           0 :         power = sc->txpow[i];
    1665           0 :         if (power < 0) {
    1666           0 :                 bbp94 += power;
    1667             :                 power = 0;
    1668           0 :         } else if (power > 31) {
    1669           0 :                 bbp94 += power - 31;
    1670             :                 power = 31;
    1671           0 :         }
    1672             : 
    1673             :         /*
    1674             :          * If we are switching from the 2GHz band to the 5GHz band or
    1675             :          * vice-versa, BBP registers need to be reprogrammed.
    1676             :          */
    1677           0 :         if (c->ic_flags != sc->sc_curchan->ic_flags) {
    1678           0 :                 rum_select_band(sc, c);
    1679           0 :                 rum_select_antenna(sc);
    1680           0 :         }
    1681           0 :         sc->sc_curchan = c;
    1682             : 
    1683           0 :         rum_rf_write(sc, RT2573_RF1, rfprog[i].r1);
    1684           0 :         rum_rf_write(sc, RT2573_RF2, rfprog[i].r2);
    1685           0 :         rum_rf_write(sc, RT2573_RF3, rfprog[i].r3 | power << 7);
    1686           0 :         rum_rf_write(sc, RT2573_RF4, rfprog[i].r4 | sc->rffreq << 10);
    1687             : 
    1688           0 :         rum_rf_write(sc, RT2573_RF1, rfprog[i].r1);
    1689           0 :         rum_rf_write(sc, RT2573_RF2, rfprog[i].r2);
    1690           0 :         rum_rf_write(sc, RT2573_RF3, rfprog[i].r3 | power << 7 | 1);
    1691           0 :         rum_rf_write(sc, RT2573_RF4, rfprog[i].r4 | sc->rffreq << 10);
    1692             : 
    1693           0 :         rum_rf_write(sc, RT2573_RF1, rfprog[i].r1);
    1694           0 :         rum_rf_write(sc, RT2573_RF2, rfprog[i].r2);
    1695           0 :         rum_rf_write(sc, RT2573_RF3, rfprog[i].r3 | power << 7);
    1696           0 :         rum_rf_write(sc, RT2573_RF4, rfprog[i].r4 | sc->rffreq << 10);
    1697             : 
    1698           0 :         DELAY(10);
    1699             : 
    1700             :         /* enable smart mode for MIMO-capable RFs */
    1701           0 :         bbp3 = rum_bbp_read(sc, 3);
    1702             : 
    1703           0 :         bbp3 &= ~RT2573_SMART_MODE;
    1704           0 :         if (sc->rf_rev == RT2573_RF_5225 || sc->rf_rev == RT2573_RF_2527)
    1705           0 :                 bbp3 |= RT2573_SMART_MODE;
    1706             : 
    1707           0 :         rum_bbp_write(sc, 3, bbp3);
    1708             : 
    1709           0 :         if (bbp94 != RT2573_BBPR94_DEFAULT)
    1710           0 :                 rum_bbp_write(sc, 94, bbp94);
    1711           0 : }
    1712             : 
    1713             : /*
    1714             :  * Enable TSF synchronization and tell h/w to start sending beacons for IBSS
    1715             :  * and HostAP operating modes.
    1716             :  */
    1717             : void
    1718           0 : rum_enable_tsf_sync(struct rum_softc *sc)
    1719             : {
    1720           0 :         struct ieee80211com *ic = &sc->sc_ic;
    1721             :         uint32_t tmp;
    1722             : 
    1723             : #ifndef IEEE80211_STA_ONLY
    1724           0 :         if (ic->ic_opmode != IEEE80211_M_STA) {
    1725             :                 /*
    1726             :                  * Change default 16ms TBTT adjustment to 8ms.
    1727             :                  * Must be done before enabling beacon generation.
    1728             :                  */
    1729           0 :                 rum_write(sc, RT2573_TXRX_CSR10, 1 << 12 | 8);
    1730           0 :         }
    1731             : #endif
    1732             : 
    1733           0 :         tmp = rum_read(sc, RT2573_TXRX_CSR9) & 0xff000000;
    1734             : 
    1735             :         /* set beacon interval (in 1/16ms unit) */
    1736           0 :         tmp |= ic->ic_bss->ni_intval * 16;
    1737             : 
    1738           0 :         tmp |= RT2573_TSF_TICKING | RT2573_ENABLE_TBTT;
    1739           0 :         if (ic->ic_opmode == IEEE80211_M_STA)
    1740           0 :                 tmp |= RT2573_TSF_MODE(1);
    1741             : #ifndef IEEE80211_STA_ONLY
    1742             :         else
    1743           0 :                 tmp |= RT2573_TSF_MODE(2) | RT2573_GENERATE_BEACON;
    1744             : #endif
    1745           0 :         rum_write(sc, RT2573_TXRX_CSR9, tmp);
    1746           0 : }
    1747             : 
    1748             : void
    1749           0 : rum_update_slot(struct rum_softc *sc)
    1750             : {
    1751           0 :         struct ieee80211com *ic = &sc->sc_ic;
    1752             :         uint8_t slottime;
    1753             :         uint32_t tmp;
    1754             : 
    1755           0 :         slottime = (ic->ic_flags & IEEE80211_F_SHSLOT) ?
    1756             :             IEEE80211_DUR_DS_SHSLOT : IEEE80211_DUR_DS_SLOT;
    1757             : 
    1758           0 :         tmp = rum_read(sc, RT2573_MAC_CSR9);
    1759           0 :         tmp = (tmp & ~0xff) | slottime;
    1760           0 :         rum_write(sc, RT2573_MAC_CSR9, tmp);
    1761             : 
    1762             :         DPRINTF(("setting slot time to %uus\n", slottime));
    1763           0 : }
    1764             : 
    1765             : void
    1766           0 : rum_set_bssid(struct rum_softc *sc, const uint8_t *bssid)
    1767             : {
    1768             :         uint32_t tmp;
    1769             : 
    1770           0 :         tmp = bssid[0] | bssid[1] << 8 | bssid[2] << 16 | bssid[3] << 24;
    1771           0 :         rum_write(sc, RT2573_MAC_CSR4, tmp);
    1772             : 
    1773           0 :         tmp = bssid[4] | bssid[5] << 8 | RT2573_ONE_BSSID << 16;
    1774           0 :         rum_write(sc, RT2573_MAC_CSR5, tmp);
    1775           0 : }
    1776             : 
    1777             : void
    1778           0 : rum_set_macaddr(struct rum_softc *sc, const uint8_t *addr)
    1779             : {
    1780             :         uint32_t tmp;
    1781             : 
    1782           0 :         tmp = addr[0] | addr[1] << 8 | addr[2] << 16 | addr[3] << 24;
    1783           0 :         rum_write(sc, RT2573_MAC_CSR2, tmp);
    1784             : 
    1785           0 :         tmp = addr[4] | addr[5] << 8 | 0xff << 16;
    1786           0 :         rum_write(sc, RT2573_MAC_CSR3, tmp);
    1787           0 : }
    1788             : 
    1789             : void
    1790           0 : rum_update_promisc(struct rum_softc *sc)
    1791             : {
    1792           0 :         struct ifnet *ifp = &sc->sc_ic.ic_if;
    1793             :         uint32_t tmp;
    1794             : 
    1795           0 :         tmp = rum_read(sc, RT2573_TXRX_CSR0);
    1796             : 
    1797           0 :         tmp &= ~RT2573_DROP_NOT_TO_ME;
    1798           0 :         if (!(ifp->if_flags & IFF_PROMISC))
    1799           0 :                 tmp |= RT2573_DROP_NOT_TO_ME;
    1800             : 
    1801           0 :         rum_write(sc, RT2573_TXRX_CSR0, tmp);
    1802             : 
    1803             :         DPRINTF(("%s promiscuous mode\n", (ifp->if_flags & IFF_PROMISC) ?
    1804             :             "entering" : "leaving"));
    1805           0 : }
    1806             : 
    1807             : const char *
    1808           0 : rum_get_rf(int rev)
    1809             : {
    1810           0 :         switch (rev) {
    1811           0 :         case RT2573_RF_2527:    return "RT2527 (MIMO XR)";
    1812           0 :         case RT2573_RF_2528:    return "RT2528";
    1813           0 :         case RT2573_RF_5225:    return "RT5225 (MIMO XR)";
    1814           0 :         case RT2573_RF_5226:    return "RT5226";
    1815           0 :         default:                return "unknown";
    1816             :         }
    1817           0 : }
    1818             : 
    1819             : void
    1820           0 : rum_read_eeprom(struct rum_softc *sc)
    1821             : {
    1822           0 :         struct ieee80211com *ic = &sc->sc_ic;
    1823           0 :         uint16_t val;
    1824             : #ifdef RUM_DEBUG
    1825             :         int i;
    1826             : #endif
    1827             : 
    1828             :         /* read MAC/BBP type */
    1829           0 :         rum_eeprom_read(sc, RT2573_EEPROM_MACBBP, &val, 2);
    1830           0 :         sc->macbbp_rev = letoh16(val);
    1831             : 
    1832             :         /* read MAC address */
    1833           0 :         rum_eeprom_read(sc, RT2573_EEPROM_ADDRESS, ic->ic_myaddr, 6);
    1834             : 
    1835           0 :         rum_eeprom_read(sc, RT2573_EEPROM_ANTENNA, &val, 2);
    1836           0 :         val = letoh16(val);
    1837           0 :         sc->rf_rev =   (val >> 11) & 0x1f;
    1838           0 :         sc->hw_radio = (val >> 10) & 0x1;
    1839           0 :         sc->rx_ant =   (val >> 4)  & 0x3;
    1840           0 :         sc->tx_ant =   (val >> 2)  & 0x3;
    1841           0 :         sc->nb_ant =   val & 0x3;
    1842             : 
    1843             :         DPRINTF(("RF revision=%d\n", sc->rf_rev));
    1844             : 
    1845           0 :         rum_eeprom_read(sc, RT2573_EEPROM_CONFIG2, &val, 2);
    1846           0 :         val = letoh16(val);
    1847           0 :         sc->ext_5ghz_lna = (val >> 6) & 0x1;
    1848           0 :         sc->ext_2ghz_lna = (val >> 4) & 0x1;
    1849             : 
    1850             :         DPRINTF(("External 2GHz LNA=%d\nExternal 5GHz LNA=%d\n",
    1851             :             sc->ext_2ghz_lna, sc->ext_5ghz_lna));
    1852             : 
    1853           0 :         rum_eeprom_read(sc, RT2573_EEPROM_RSSI_2GHZ_OFFSET, &val, 2);
    1854           0 :         val = letoh16(val);
    1855           0 :         if ((val & 0xff) != 0xff)
    1856           0 :                 sc->rssi_2ghz_corr = (int8_t)(val & 0xff);       /* signed */
    1857             : 
    1858           0 :         rum_eeprom_read(sc, RT2573_EEPROM_RSSI_5GHZ_OFFSET, &val, 2);
    1859           0 :         val = letoh16(val);
    1860           0 :         if ((val & 0xff) != 0xff)
    1861           0 :                 sc->rssi_5ghz_corr = (int8_t)(val & 0xff);       /* signed */
    1862             : 
    1863             :         DPRINTF(("RSSI 2GHz corr=%d\nRSSI 5GHz corr=%d\n",
    1864             :             sc->rssi_2ghz_corr, sc->rssi_5ghz_corr));
    1865             : 
    1866           0 :         rum_eeprom_read(sc, RT2573_EEPROM_FREQ_OFFSET, &val, 2);
    1867           0 :         val = letoh16(val);
    1868           0 :         if ((val & 0xff) != 0xff)
    1869           0 :                 sc->rffreq = val & 0xff;
    1870             : 
    1871             :         DPRINTF(("RF freq=%d\n", sc->rffreq));
    1872             : 
    1873             :         /* read Tx power for all a/b/g channels */
    1874           0 :         rum_eeprom_read(sc, RT2573_EEPROM_TXPOWER, sc->txpow, 14);
    1875             :         /* XXX default Tx power for 802.11a channels */
    1876           0 :         memset(sc->txpow + 14, 24, sizeof (sc->txpow) - 14);
    1877             : #ifdef RUM_DEBUG
    1878             :         for (i = 0; i < 14; i++)
    1879             :                 DPRINTF(("Channel=%d Tx power=%d\n", i + 1,  sc->txpow[i]));
    1880             : #endif
    1881             : 
    1882             :         /* read default values for BBP registers */
    1883           0 :         rum_eeprom_read(sc, RT2573_EEPROM_BBP_BASE, sc->bbp_prom, 2 * 16);
    1884             : #ifdef RUM_DEBUG
    1885             :         for (i = 0; i < 14; i++) {
    1886             :                 if (sc->bbp_prom[i].reg == 0 || sc->bbp_prom[i].reg == 0xff)
    1887             :                         continue;
    1888             :                 DPRINTF(("BBP R%d=%02x\n", sc->bbp_prom[i].reg,
    1889             :                     sc->bbp_prom[i].val));
    1890             :         }
    1891             : #endif
    1892           0 : }
    1893             : 
    1894             : int
    1895           0 : rum_bbp_init(struct rum_softc *sc)
    1896             : {
    1897             :         int i, ntries;
    1898             : 
    1899             :         /* wait for BBP to be ready */
    1900           0 :         for (ntries = 0; ntries < 100; ntries++) {
    1901           0 :                 const uint8_t val = rum_bbp_read(sc, 0);
    1902           0 :                 if (val != 0 && val != 0xff)
    1903           0 :                         break;
    1904           0 :                 DELAY(1000);
    1905           0 :         }
    1906           0 :         if (ntries == 100) {
    1907           0 :                 printf("%s: timeout waiting for BBP\n",
    1908           0 :                     sc->sc_dev.dv_xname);
    1909           0 :                 return EIO;
    1910             :         }
    1911             : 
    1912             :         /* initialize BBP registers to default values */
    1913           0 :         for (i = 0; i < nitems(rum_def_bbp); i++)
    1914           0 :                 rum_bbp_write(sc, rum_def_bbp[i].reg, rum_def_bbp[i].val);
    1915             : 
    1916             :         /* write vendor-specific BBP values (from EEPROM) */
    1917           0 :         for (i = 0; i < 16; i++) {
    1918           0 :                 if (sc->bbp_prom[i].reg == 0 || sc->bbp_prom[i].reg == 0xff)
    1919             :                         continue;
    1920           0 :                 rum_bbp_write(sc, sc->bbp_prom[i].reg, sc->bbp_prom[i].val);
    1921           0 :         }
    1922             : 
    1923           0 :         return 0;
    1924           0 : }
    1925             : 
    1926             : int
    1927           0 : rum_init(struct ifnet *ifp)
    1928             : {
    1929           0 :         struct rum_softc *sc = ifp->if_softc;
    1930           0 :         struct ieee80211com *ic = &sc->sc_ic;
    1931             :         uint32_t tmp;
    1932             :         usbd_status error;
    1933             :         int i, ntries;
    1934             : 
    1935           0 :         rum_stop(ifp, 0);
    1936             : 
    1937             :         /* initialize MAC registers to default values */
    1938           0 :         for (i = 0; i < nitems(rum_def_mac); i++)
    1939           0 :                 rum_write(sc, rum_def_mac[i].reg, rum_def_mac[i].val);
    1940             : 
    1941             :         /* set host ready */
    1942           0 :         rum_write(sc, RT2573_MAC_CSR1, 3);
    1943           0 :         rum_write(sc, RT2573_MAC_CSR1, 0);
    1944             : 
    1945             :         /* wait for BBP/RF to wakeup */
    1946           0 :         for (ntries = 0; ntries < 1000; ntries++) {
    1947           0 :                 if (rum_read(sc, RT2573_MAC_CSR12) & 8)
    1948             :                         break;
    1949           0 :                 rum_write(sc, RT2573_MAC_CSR12, 4);     /* force wakeup */
    1950           0 :                 DELAY(1000);
    1951             :         }
    1952           0 :         if (ntries == 1000) {
    1953           0 :                 printf("%s: timeout waiting for BBP/RF to wakeup\n",
    1954           0 :                     sc->sc_dev.dv_xname);
    1955             :                 error = ENODEV;
    1956           0 :                 goto fail;
    1957             :         }
    1958             : 
    1959           0 :         if ((error = rum_bbp_init(sc)) != 0)
    1960             :                 goto fail;
    1961             : 
    1962             :         /* select default channel */
    1963           0 :         sc->sc_curchan = ic->ic_bss->ni_chan = ic->ic_ibss_chan;
    1964           0 :         rum_select_band(sc, sc->sc_curchan);
    1965           0 :         rum_select_antenna(sc);
    1966           0 :         rum_set_chan(sc, sc->sc_curchan);
    1967             : 
    1968             :         /* clear STA registers */
    1969           0 :         rum_read_multi(sc, RT2573_STA_CSR0, sc->sta, sizeof sc->sta);
    1970             : 
    1971           0 :         IEEE80211_ADDR_COPY(ic->ic_myaddr, LLADDR(ifp->if_sadl));
    1972           0 :         rum_set_macaddr(sc, ic->ic_myaddr);
    1973             : 
    1974             :         /* initialize ASIC */
    1975           0 :         rum_write(sc, RT2573_MAC_CSR1, 4);
    1976             : 
    1977             :         /*
    1978             :          * Allocate xfer for AMRR statistics requests.
    1979             :          */
    1980           0 :         sc->amrr_xfer = usbd_alloc_xfer(sc->sc_udev);
    1981           0 :         if (sc->amrr_xfer == NULL) {
    1982           0 :                 printf("%s: could not allocate AMRR xfer\n",
    1983           0 :                     sc->sc_dev.dv_xname);
    1984           0 :                 goto fail;
    1985             :         }
    1986             : 
    1987             :         /*
    1988             :          * Open Tx and Rx USB bulk pipes.
    1989             :          */
    1990           0 :         error = usbd_open_pipe(sc->sc_iface, sc->sc_tx_no, USBD_EXCLUSIVE_USE,
    1991           0 :             &sc->sc_tx_pipeh);
    1992           0 :         if (error != 0) {
    1993           0 :                 printf("%s: could not open Tx pipe: %s\n",
    1994           0 :                     sc->sc_dev.dv_xname, usbd_errstr(error));
    1995           0 :                 goto fail;
    1996             :         }
    1997           0 :         error = usbd_open_pipe(sc->sc_iface, sc->sc_rx_no, USBD_EXCLUSIVE_USE,
    1998           0 :             &sc->sc_rx_pipeh);
    1999           0 :         if (error != 0) {
    2000           0 :                 printf("%s: could not open Rx pipe: %s\n",
    2001           0 :                     sc->sc_dev.dv_xname, usbd_errstr(error));
    2002           0 :                 goto fail;
    2003             :         }
    2004             : 
    2005             :         /*
    2006             :          * Allocate Tx and Rx xfer queues.
    2007             :          */
    2008           0 :         error = rum_alloc_tx_list(sc);
    2009           0 :         if (error != 0) {
    2010           0 :                 printf("%s: could not allocate Tx list\n",
    2011           0 :                     sc->sc_dev.dv_xname);
    2012           0 :                 goto fail;
    2013             :         }
    2014           0 :         error = rum_alloc_rx_list(sc);
    2015           0 :         if (error != 0) {
    2016           0 :                 printf("%s: could not allocate Rx list\n",
    2017           0 :                     sc->sc_dev.dv_xname);
    2018           0 :                 goto fail;
    2019             :         }
    2020             : 
    2021             :         /*
    2022             :          * Start up the receive pipe.
    2023             :          */
    2024           0 :         for (i = 0; i < RUM_RX_LIST_COUNT; i++) {
    2025           0 :                 struct rum_rx_data *data = &sc->rx_data[i];
    2026             : 
    2027           0 :                 usbd_setup_xfer(data->xfer, sc->sc_rx_pipeh, data, data->buf,
    2028             :                     MCLBYTES, USBD_SHORT_XFER_OK, USBD_NO_TIMEOUT, rum_rxeof);
    2029           0 :                 error = usbd_transfer(data->xfer);
    2030           0 :                 if (error != 0 && error != USBD_IN_PROGRESS) {
    2031           0 :                         printf("%s: could not queue Rx transfer\n",
    2032           0 :                             sc->sc_dev.dv_xname);
    2033           0 :                         goto fail;
    2034             :                 }
    2035           0 :         }
    2036             : 
    2037             :         /* update Rx filter */
    2038           0 :         tmp = rum_read(sc, RT2573_TXRX_CSR0) & 0xffff;
    2039             : 
    2040           0 :         tmp |= RT2573_DROP_PHY_ERROR | RT2573_DROP_CRC_ERROR;
    2041           0 :         if (ic->ic_opmode != IEEE80211_M_MONITOR) {
    2042           0 :                 tmp |= RT2573_DROP_CTL | RT2573_DROP_VER_ERROR |
    2043             :                        RT2573_DROP_ACKCTS;
    2044             : #ifndef IEEE80211_STA_ONLY
    2045           0 :                 if (ic->ic_opmode != IEEE80211_M_HOSTAP)
    2046             : #endif
    2047           0 :                         tmp |= RT2573_DROP_TODS;
    2048           0 :                 if (!(ifp->if_flags & IFF_PROMISC))
    2049           0 :                         tmp |= RT2573_DROP_NOT_TO_ME;
    2050             :         }
    2051           0 :         rum_write(sc, RT2573_TXRX_CSR0, tmp);
    2052             : 
    2053           0 :         ifq_clr_oactive(&ifp->if_snd);
    2054           0 :         ifp->if_flags |= IFF_RUNNING;
    2055             : 
    2056           0 :         if (ic->ic_opmode == IEEE80211_M_MONITOR)
    2057           0 :                 ieee80211_new_state(ic, IEEE80211_S_RUN, -1);
    2058             :         else
    2059           0 :                 ieee80211_new_state(ic, IEEE80211_S_SCAN, -1);
    2060             : 
    2061           0 :         return 0;
    2062             : 
    2063           0 : fail:   rum_stop(ifp, 1);
    2064           0 :         return error;
    2065           0 : }
    2066             : 
    2067             : void
    2068           0 : rum_stop(struct ifnet *ifp, int disable)
    2069             : {
    2070           0 :         struct rum_softc *sc = ifp->if_softc;
    2071           0 :         struct ieee80211com *ic = &sc->sc_ic;
    2072             :         uint32_t tmp;
    2073             : 
    2074           0 :         sc->sc_tx_timer = 0;
    2075           0 :         ifp->if_timer = 0;
    2076           0 :         ifp->if_flags &= ~IFF_RUNNING;
    2077           0 :         ifq_clr_oactive(&ifp->if_snd);
    2078             : 
    2079           0 :         ieee80211_new_state(ic, IEEE80211_S_INIT, -1);  /* free all nodes */
    2080             : 
    2081             :         /* disable Rx */
    2082           0 :         tmp = rum_read(sc, RT2573_TXRX_CSR0);
    2083           0 :         rum_write(sc, RT2573_TXRX_CSR0, tmp | RT2573_DISABLE_RX);
    2084             : 
    2085             :         /* reset ASIC */
    2086           0 :         rum_write(sc, RT2573_MAC_CSR1, 3);
    2087           0 :         rum_write(sc, RT2573_MAC_CSR1, 0);
    2088             : 
    2089           0 :         if (sc->amrr_xfer != NULL) {
    2090           0 :                 usbd_free_xfer(sc->amrr_xfer);
    2091           0 :                 sc->amrr_xfer = NULL;
    2092           0 :         }
    2093           0 :         if (sc->sc_rx_pipeh != NULL) {
    2094           0 :                 usbd_abort_pipe(sc->sc_rx_pipeh);
    2095           0 :                 usbd_close_pipe(sc->sc_rx_pipeh);
    2096           0 :                 sc->sc_rx_pipeh = NULL;
    2097           0 :         }
    2098           0 :         if (sc->sc_tx_pipeh != NULL) {
    2099           0 :                 usbd_abort_pipe(sc->sc_tx_pipeh);
    2100           0 :                 usbd_close_pipe(sc->sc_tx_pipeh);
    2101           0 :                 sc->sc_tx_pipeh = NULL;
    2102           0 :         }
    2103             : 
    2104           0 :         rum_free_rx_list(sc);
    2105           0 :         rum_free_tx_list(sc);
    2106           0 : }
    2107             : 
    2108             : int
    2109           0 : rum_load_microcode(struct rum_softc *sc, const u_char *ucode, size_t size)
    2110             : {
    2111           0 :         usb_device_request_t req;
    2112             :         uint16_t reg = RT2573_MCU_CODE_BASE;
    2113             :         usbd_status error;
    2114             : 
    2115             :         /* copy firmware image into NIC */
    2116           0 :         for (; size >= 4; reg += 4, ucode += 4, size -= 4)
    2117           0 :                 rum_write(sc, reg, UGETDW(ucode));
    2118             : 
    2119           0 :         req.bmRequestType = UT_WRITE_VENDOR_DEVICE;
    2120           0 :         req.bRequest = RT2573_MCU_CNTL;
    2121           0 :         USETW(req.wValue, RT2573_MCU_RUN);
    2122           0 :         USETW(req.wIndex, 0);
    2123           0 :         USETW(req.wLength, 0);
    2124             : 
    2125           0 :         error = usbd_do_request(sc->sc_udev, &req, NULL);
    2126           0 :         if (error != 0) {
    2127           0 :                 printf("%s: could not run firmware: %s\n",
    2128           0 :                     sc->sc_dev.dv_xname, usbd_errstr(error));
    2129           0 :         }
    2130           0 :         return error;
    2131           0 : }
    2132             : 
    2133             : #ifndef IEEE80211_STA_ONLY
    2134             : int
    2135           0 : rum_prepare_beacon(struct rum_softc *sc)
    2136             : {
    2137           0 :         struct ieee80211com *ic = &sc->sc_ic;
    2138           0 :         struct rum_tx_desc desc;
    2139             :         struct mbuf *m0;
    2140             :         int rate;
    2141             : 
    2142           0 :         m0 = ieee80211_beacon_alloc(ic, ic->ic_bss);
    2143           0 :         if (m0 == NULL) {
    2144           0 :                 printf("%s: could not allocate beacon frame\n",
    2145           0 :                     sc->sc_dev.dv_xname);
    2146           0 :                 return ENOBUFS;
    2147             :         }
    2148             : 
    2149             :         /* send beacons at the lowest available rate */
    2150           0 :         rate = IEEE80211_IS_CHAN_5GHZ(ic->ic_bss->ni_chan) ? 12 : 2;
    2151             : 
    2152           0 :         rum_setup_tx_desc(sc, &desc, RT2573_TX_TIMESTAMP, RT2573_TX_HWSEQ,
    2153           0 :             m0->m_pkthdr.len, rate);
    2154             : 
    2155             :         /* copy the first 24 bytes of Tx descriptor into NIC memory */
    2156           0 :         rum_write_multi(sc, RT2573_HW_BEACON_BASE0, (uint8_t *)&desc, 24);
    2157             : 
    2158             :         /* copy beacon header and payload into NIC memory */
    2159           0 :         rum_write_multi(sc, RT2573_HW_BEACON_BASE0 + 24, mtod(m0, uint8_t *),
    2160           0 :             m0->m_pkthdr.len);
    2161             : 
    2162           0 :         m_freem(m0);
    2163             : 
    2164           0 :         return 0;
    2165           0 : }
    2166             : #endif
    2167             : 
    2168             : void
    2169           0 : rum_newassoc(struct ieee80211com *ic, struct ieee80211_node *ni, int isnew)
    2170             : {
    2171             :         /* start with lowest Tx rate */
    2172           0 :         ni->ni_txrate = 0;
    2173           0 : }
    2174             : 
    2175             : void
    2176           0 : rum_amrr_start(struct rum_softc *sc, struct ieee80211_node *ni)
    2177             : {
    2178             :         int i;
    2179             : 
    2180             :         /* clear statistic registers (STA_CSR0 to STA_CSR5) */
    2181           0 :         rum_read_multi(sc, RT2573_STA_CSR0, sc->sta, sizeof sc->sta);
    2182             : 
    2183           0 :         ieee80211_amrr_node_init(&sc->amrr, &sc->amn);
    2184             : 
    2185             :         /* set rate to some reasonable initial value */
    2186           0 :         for (i = ni->ni_rates.rs_nrates - 1;
    2187           0 :              i > 0 && (ni->ni_rates.rs_rates[i] & IEEE80211_RATE_VAL) > 72;
    2188           0 :              i--);
    2189           0 :         ni->ni_txrate = i;
    2190             : 
    2191           0 :         if (!usbd_is_dying(sc->sc_udev))
    2192           0 :                 timeout_add_sec(&sc->amrr_to, 1);
    2193           0 : }
    2194             : 
    2195             : void
    2196           0 : rum_amrr_timeout(void *arg)
    2197             : {
    2198           0 :         struct rum_softc *sc = arg;
    2199           0 :         usb_device_request_t req;
    2200             : 
    2201           0 :         if (usbd_is_dying(sc->sc_udev))
    2202           0 :                 return;
    2203             : 
    2204             :         /*
    2205             :          * Asynchronously read statistic registers (cleared by read).
    2206             :          */
    2207           0 :         req.bmRequestType = UT_READ_VENDOR_DEVICE;
    2208           0 :         req.bRequest = RT2573_READ_MULTI_MAC;
    2209           0 :         USETW(req.wValue, 0);
    2210           0 :         USETW(req.wIndex, RT2573_STA_CSR0);
    2211           0 :         USETW(req.wLength, sizeof sc->sta);
    2212             : 
    2213           0 :         usbd_setup_default_xfer(sc->amrr_xfer, sc->sc_udev, sc,
    2214           0 :             USBD_DEFAULT_TIMEOUT, &req, sc->sta, sizeof sc->sta, 0,
    2215             :             rum_amrr_update);
    2216           0 :         (void)usbd_transfer(sc->amrr_xfer);
    2217           0 : }
    2218             : 
    2219             : void
    2220           0 : rum_amrr_update(struct usbd_xfer *xfer, void *priv,
    2221             :     usbd_status status)
    2222             : {
    2223           0 :         struct rum_softc *sc = (struct rum_softc *)priv;
    2224           0 :         struct ifnet *ifp = &sc->sc_ic.ic_if;
    2225             : 
    2226           0 :         if (status != USBD_NORMAL_COMPLETION) {
    2227           0 :                 printf("%s: could not retrieve Tx statistics - cancelling "
    2228           0 :                     "automatic rate control\n", sc->sc_dev.dv_xname);
    2229           0 :                 return;
    2230             :         }
    2231             : 
    2232             :         /* count TX retry-fail as Tx errors */
    2233           0 :         ifp->if_oerrors += letoh32(sc->sta[5]) >> 16;
    2234             : 
    2235           0 :         sc->amn.amn_retrycnt =
    2236           0 :             (letoh32(sc->sta[4]) >> 16) +      /* TX one-retry ok count */
    2237           0 :             (letoh32(sc->sta[5]) & 0xffff) +     /* TX more-retry ok count */
    2238           0 :             (letoh32(sc->sta[5]) >> 16);       /* TX retry-fail count */
    2239             : 
    2240           0 :         sc->amn.amn_txcnt =
    2241           0 :             sc->amn.amn_retrycnt +
    2242           0 :             (letoh32(sc->sta[4]) & 0xffff);      /* TX no-retry ok count */
    2243             : 
    2244           0 :         ieee80211_amrr_choose(&sc->amrr, sc->sc_ic.ic_bss, &sc->amn);
    2245             : 
    2246           0 :         if (!usbd_is_dying(sc->sc_udev))
    2247           0 :                 timeout_add_sec(&sc->amrr_to, 1);
    2248           0 : }

Generated by: LCOV version 1.13