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

          Line data    Source code
       1             : /*      $OpenBSD: if_otus.c,v 1.60 2017/10/26 15:00:28 mpi Exp $        */
       2             : 
       3             : /*-
       4             :  * Copyright (c) 2009 Damien Bergamini <damien.bergamini@free.fr>
       5             :  *
       6             :  * Permission to use, copy, modify, and distribute this software for any
       7             :  * purpose with or without fee is hereby granted, provided that the above
       8             :  * copyright notice and this permission notice appear in all copies.
       9             :  *
      10             :  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
      11             :  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
      12             :  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
      13             :  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
      14             :  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
      15             :  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
      16             :  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
      17             :  */
      18             : 
      19             : /*
      20             :  * Driver for Atheros AR9001U chipset.
      21             :  */
      22             : 
      23             : #include "bpfilter.h"
      24             : 
      25             : #include <sys/param.h>
      26             : #include <sys/sockio.h>
      27             : #include <sys/mbuf.h>
      28             : #include <sys/kernel.h>
      29             : #include <sys/socket.h>
      30             : #include <sys/systm.h>
      31             : #include <sys/timeout.h>
      32             : #include <sys/conf.h>
      33             : #include <sys/device.h>
      34             : #include <sys/endian.h>
      35             : 
      36             : #include <machine/intr.h>
      37             : 
      38             : #if NBPFILTER > 0
      39             : #include <net/bpf.h>
      40             : #endif
      41             : #include <net/if.h>
      42             : #include <net/if_dl.h>
      43             : #include <net/if_media.h>
      44             : 
      45             : #include <netinet/in.h>
      46             : #include <netinet/if_ether.h>
      47             : 
      48             : #include <net80211/ieee80211_var.h>
      49             : #include <net80211/ieee80211_amrr.h>
      50             : #include <net80211/ieee80211_radiotap.h>
      51             : 
      52             : #include <dev/usb/usb.h>
      53             : #include <dev/usb/usbdi.h>
      54             : #include <dev/usb/usbdi_util.h>
      55             : #include <dev/usb/usbdevs.h>
      56             : 
      57             : #include <dev/usb/if_otusreg.h>
      58             : 
      59             : #ifdef OTUS_DEBUG
      60             : #define DPRINTF(x)      do { if (otus_debug) printf x; } while (0)
      61             : #define DPRINTFN(n, x)  do { if (otus_debug >= (n)) printf x; } while (0)
      62             : int otus_debug = 1;
      63             : #else
      64             : #define DPRINTF(x)
      65             : #define DPRINTFN(n, x)
      66             : #endif
      67             : 
      68             : static const struct usb_devno otus_devs[] = {
      69             :         { USB_VENDOR_ACCTON,            USB_PRODUCT_ACCTON_WN7512 },
      70             :         { USB_VENDOR_ATHEROS2,          USB_PRODUCT_ATHEROS2_3CRUSBN275 },
      71             :         { USB_VENDOR_ATHEROS2,          USB_PRODUCT_ATHEROS2_TG121N },
      72             :         { USB_VENDOR_ATHEROS2,          USB_PRODUCT_ATHEROS2_AR9170 },
      73             :         { USB_VENDOR_ATHEROS2,          USB_PRODUCT_ATHEROS2_WN612 },
      74             :         { USB_VENDOR_ATHEROS2,          USB_PRODUCT_ATHEROS2_WN821NV2 },
      75             :         { USB_VENDOR_AVM,               USB_PRODUCT_AVM_FRITZWLAN },
      76             :         { USB_VENDOR_CACE,              USB_PRODUCT_CACE_AIRPCAPNX },
      77             :         { USB_VENDOR_DLINK2,            USB_PRODUCT_DLINK2_DWA130D1 },
      78             :         { USB_VENDOR_DLINK2,            USB_PRODUCT_DLINK2_DWA160A1 },
      79             :         { USB_VENDOR_DLINK2,            USB_PRODUCT_DLINK2_DWA160A2 },
      80             :         { USB_VENDOR_IODATA,            USB_PRODUCT_IODATA_WNGDNUS2 },
      81             :         { USB_VENDOR_NEC,               USB_PRODUCT_NEC_WL300NUG },
      82             :         { USB_VENDOR_NETGEAR,           USB_PRODUCT_NETGEAR_WN111V2 },
      83             :         { USB_VENDOR_NETGEAR,           USB_PRODUCT_NETGEAR_WNA1000 },
      84             :         { USB_VENDOR_NETGEAR,           USB_PRODUCT_NETGEAR_WNDA3100 },
      85             :         { USB_VENDOR_PLANEX2,           USB_PRODUCT_PLANEX2_GW_US300 },
      86             :         { USB_VENDOR_WISTRONNEWEB,      USB_PRODUCT_WISTRONNEWEB_O8494 },
      87             :         { USB_VENDOR_WISTRONNEWEB,      USB_PRODUCT_WISTRONNEWEB_WNC0600 },
      88             :         { USB_VENDOR_ZCOM,              USB_PRODUCT_ZCOM_UB81 },
      89             :         { USB_VENDOR_ZCOM,              USB_PRODUCT_ZCOM_UB82 },
      90             :         { USB_VENDOR_ZYDAS,             USB_PRODUCT_ZYDAS_ZD1221 },
      91             :         { USB_VENDOR_ZYXEL,             USB_PRODUCT_ZYXEL_NWD271N }
      92             : };
      93             : 
      94             : int             otus_match(struct device *, void *, void *);
      95             : void            otus_attach(struct device *, struct device *, void *);
      96             : int             otus_detach(struct device *, int);
      97             : void            otus_attachhook(struct device *);
      98             : void            otus_get_chanlist(struct otus_softc *);
      99             : int             otus_load_firmware(struct otus_softc *, const char *,
     100             :                     uint32_t);
     101             : int             otus_open_pipes(struct otus_softc *);
     102             : void            otus_close_pipes(struct otus_softc *);
     103             : int             otus_alloc_tx_cmd(struct otus_softc *);
     104             : void            otus_free_tx_cmd(struct otus_softc *);
     105             : int             otus_alloc_tx_data_list(struct otus_softc *);
     106             : void            otus_free_tx_data_list(struct otus_softc *);
     107             : int             otus_alloc_rx_data_list(struct otus_softc *);
     108             : void            otus_free_rx_data_list(struct otus_softc *);
     109             : void            otus_next_scan(void *);
     110             : void            otus_task(void *);
     111             : void            otus_do_async(struct otus_softc *,
     112             :                     void (*)(struct otus_softc *, void *), void *, int);
     113             : int             otus_newstate(struct ieee80211com *, enum ieee80211_state,
     114             :                     int);
     115             : void            otus_newstate_cb(struct otus_softc *, void *);
     116             : int             otus_cmd(struct otus_softc *, uint8_t, const void *, int,
     117             :                     void *);
     118             : void            otus_write(struct otus_softc *, uint32_t, uint32_t);
     119             : int             otus_write_barrier(struct otus_softc *);
     120             : struct          ieee80211_node *otus_node_alloc(struct ieee80211com *);
     121             : int             otus_media_change(struct ifnet *);
     122             : int             otus_read_eeprom(struct otus_softc *);
     123             : void            otus_newassoc(struct ieee80211com *, struct ieee80211_node *,
     124             :                     int);
     125             : void            otus_intr(struct usbd_xfer *, void *, usbd_status);
     126             : void            otus_cmd_rxeof(struct otus_softc *, uint8_t *, int);
     127             : void            otus_sub_rxeof(struct otus_softc *, uint8_t *, int);
     128             : void            otus_rxeof(struct usbd_xfer *, void *, usbd_status);
     129             : void            otus_txeof(struct usbd_xfer *, void *, usbd_status);
     130             : int             otus_tx(struct otus_softc *, struct mbuf *,
     131             :                     struct ieee80211_node *);
     132             : void            otus_start(struct ifnet *);
     133             : void            otus_watchdog(struct ifnet *);
     134             : int             otus_ioctl(struct ifnet *, u_long, caddr_t);
     135             : int             otus_set_multi(struct otus_softc *);
     136             : void            otus_updateedca(struct ieee80211com *);
     137             : void            otus_updateedca_cb(struct otus_softc *, void *);
     138             : void            otus_updateslot(struct ieee80211com *);
     139             : void            otus_updateslot_cb(struct otus_softc *, void *);
     140             : int             otus_init_mac(struct otus_softc *);
     141             : uint32_t        otus_phy_get_def(struct otus_softc *, uint32_t);
     142             : int             otus_set_board_values(struct otus_softc *,
     143             :                     struct ieee80211_channel *);
     144             : int             otus_program_phy(struct otus_softc *,
     145             :                     struct ieee80211_channel *);
     146             : int             otus_set_rf_bank4(struct otus_softc *,
     147             :                     struct ieee80211_channel *);
     148             : void            otus_get_delta_slope(uint32_t, uint32_t *, uint32_t *);
     149             : int             otus_set_chan(struct otus_softc *, struct ieee80211_channel *,
     150             :                     int);
     151             : int             otus_set_key(struct ieee80211com *, struct ieee80211_node *,
     152             :                     struct ieee80211_key *);
     153             : void            otus_set_key_cb(struct otus_softc *, void *);
     154             : void            otus_delete_key(struct ieee80211com *, struct ieee80211_node *,
     155             :                     struct ieee80211_key *);
     156             : void            otus_delete_key_cb(struct otus_softc *, void *);
     157             : void            otus_calibrate_to(void *);
     158             : int             otus_set_bssid(struct otus_softc *, const uint8_t *);
     159             : int             otus_set_macaddr(struct otus_softc *, const uint8_t *);
     160             : void            otus_led_newstate_type1(struct otus_softc *);
     161             : void            otus_led_newstate_type2(struct otus_softc *);
     162             : void            otus_led_newstate_type3(struct otus_softc *);
     163             : int             otus_init(struct ifnet *);
     164             : void            otus_stop(struct ifnet *);
     165             : 
     166             : struct cfdriver otus_cd = {
     167             :         NULL, "otus", DV_IFNET
     168             : };
     169             : 
     170             : const struct cfattach otus_ca = {
     171             :         sizeof (struct otus_softc), otus_match, otus_attach, otus_detach
     172             : };
     173             : 
     174             : int
     175           0 : otus_match(struct device *parent, void *match, void *aux)
     176             : {
     177           0 :         struct usb_attach_arg *uaa = aux;
     178             : 
     179           0 :         if (uaa->iface == NULL || uaa->configno != 1)
     180           0 :                 return UMATCH_NONE;
     181             : 
     182           0 :         return (usb_lookup(otus_devs, uaa->vendor, uaa->product) != NULL) ?
     183             :             UMATCH_VENDOR_PRODUCT : UMATCH_NONE;
     184           0 : }
     185             : 
     186             : void
     187           0 : otus_attach(struct device *parent, struct device *self, void *aux)
     188             : {
     189           0 :         struct otus_softc *sc = (struct otus_softc *)self;
     190           0 :         struct usb_attach_arg *uaa = aux;
     191             :         int error;
     192             : 
     193           0 :         sc->sc_udev = uaa->device;
     194             : 
     195           0 :         usb_init_task(&sc->sc_task, otus_task, sc, USB_TASK_TYPE_GENERIC);
     196           0 :         timeout_set(&sc->scan_to, otus_next_scan, sc);
     197           0 :         timeout_set(&sc->calib_to, otus_calibrate_to, sc);
     198             : 
     199           0 :         sc->amrr.amrr_min_success_threshold =  1;
     200           0 :         sc->amrr.amrr_max_success_threshold = 10;
     201             : 
     202             :         /* Get the first interface handle. */
     203           0 :         error = usbd_device2interface_handle(sc->sc_udev, 0, &sc->sc_iface);
     204           0 :         if (error != 0) {
     205           0 :                 printf("%s: could not get interface handle\n",
     206           0 :                     sc->sc_dev.dv_xname);
     207           0 :                 return;
     208             :         }
     209             : 
     210           0 :         if ((error = otus_open_pipes(sc)) != 0) {
     211           0 :                 printf("%s: could not open pipes\n", sc->sc_dev.dv_xname);
     212           0 :                 return;
     213             :         }
     214             : 
     215           0 :         config_mountroot(self, otus_attachhook);
     216           0 : }
     217             : 
     218             : int
     219           0 : otus_detach(struct device *self, int flags)
     220             : {
     221           0 :         struct otus_softc *sc = (struct otus_softc *)self;
     222           0 :         struct ifnet *ifp = &sc->sc_ic.ic_if;
     223             :         int s;
     224             : 
     225           0 :         s = splusb();
     226             : 
     227           0 :         if (timeout_initialized(&sc->scan_to))
     228           0 :                 timeout_del(&sc->scan_to);
     229           0 :         if (timeout_initialized(&sc->calib_to))
     230           0 :                 timeout_del(&sc->calib_to);
     231             : 
     232             :         /* Wait for all queued asynchronous commands to complete. */
     233           0 :         usb_rem_wait_task(sc->sc_udev, &sc->sc_task);
     234             : 
     235           0 :         usbd_ref_wait(sc->sc_udev);
     236             : 
     237           0 :         if (ifp->if_softc != NULL) {
     238           0 :                 ifp->if_flags &= ~IFF_RUNNING;
     239           0 :                 ifq_clr_oactive(&ifp->if_snd);
     240           0 :                 ieee80211_ifdetach(ifp);
     241           0 :                 if_detach(ifp);
     242           0 :         }
     243             : 
     244           0 :         otus_close_pipes(sc);
     245             : 
     246           0 :         splx(s);
     247             : 
     248           0 :         return 0;
     249             : }
     250             : 
     251             : void
     252           0 : otus_attachhook(struct device *self)
     253             : {
     254           0 :         struct otus_softc *sc = (struct otus_softc *)self;
     255           0 :         struct ieee80211com *ic = &sc->sc_ic;
     256           0 :         struct ifnet *ifp = &ic->ic_if;
     257           0 :         usb_device_request_t req;
     258           0 :         uint32_t in, out;
     259             :         int error;
     260             : 
     261           0 :         error = otus_load_firmware(sc, "otus-init", AR_FW_INIT_ADDR);
     262           0 :         if (error != 0) {
     263           0 :                 printf("%s: could not load %s firmware\n",
     264           0 :                     sc->sc_dev.dv_xname, "init");
     265           0 :                 return;
     266             :         }
     267             : 
     268           0 :         usbd_delay_ms(sc->sc_udev, 1000);
     269             : 
     270           0 :         error = otus_load_firmware(sc, "otus-main", AR_FW_MAIN_ADDR);
     271           0 :         if (error != 0) {
     272           0 :                 printf("%s: could not load %s firmware\n",
     273           0 :                     sc->sc_dev.dv_xname, "main");
     274           0 :                 return;
     275             :         }
     276             : 
     277             :         /* Tell device that firmware transfer is complete. */
     278           0 :         req.bmRequestType = UT_WRITE_VENDOR_DEVICE;
     279           0 :         req.bRequest = AR_FW_DOWNLOAD_COMPLETE;
     280           0 :         USETW(req.wValue, 0);
     281           0 :         USETW(req.wIndex, 0);
     282           0 :         USETW(req.wLength, 0);
     283           0 :         if (usbd_do_request(sc->sc_udev, &req, NULL) != 0) {
     284           0 :                 printf("%s: firmware initialization failed\n",
     285           0 :                     sc->sc_dev.dv_xname);
     286           0 :                 return;
     287             :         }
     288             : 
     289             :         /* Send an ECHO command to check that everything is settled. */
     290           0 :         in = 0xbadc0ffe;
     291           0 :         if (otus_cmd(sc, AR_CMD_ECHO, &in, sizeof in, &out) != 0) {
     292           0 :                 printf("%s: echo command failed\n", sc->sc_dev.dv_xname);
     293           0 :                 return;
     294             :         }
     295           0 :         if (in != out) {
     296           0 :                 printf("%s: echo reply mismatch: 0x%08x!=0x%08x\n",
     297           0 :                     sc->sc_dev.dv_xname, in, out);
     298           0 :                 return;
     299             :         }
     300             : 
     301             :         /* Read entire EEPROM. */
     302           0 :         if (otus_read_eeprom(sc) != 0) {
     303           0 :                 printf("%s: could not read EEPROM\n", sc->sc_dev.dv_xname);
     304           0 :                 return;
     305             :         }
     306             : 
     307           0 :         sc->txmask = sc->eeprom.baseEepHeader.txMask;
     308           0 :         sc->rxmask = sc->eeprom.baseEepHeader.rxMask;
     309           0 :         sc->capflags = sc->eeprom.baseEepHeader.opCapFlags;
     310           0 :         IEEE80211_ADDR_COPY(ic->ic_myaddr, sc->eeprom.baseEepHeader.macAddr);
     311           0 :         sc->sc_led_newstate = otus_led_newstate_type3;       /* XXX */
     312             : 
     313           0 :         printf("%s: MAC/BBP AR9170, RF AR%X, MIMO %dT%dR, address %s\n",
     314           0 :             sc->sc_dev.dv_xname, (sc->capflags & AR5416_OPFLAGS_11A) ?
     315           0 :                 0x9104 : ((sc->txmask == 0x5) ? 0x9102 : 0x9101),
     316           0 :             (sc->txmask == 0x5) ? 2 : 1, (sc->rxmask == 0x5) ? 2 : 1,
     317           0 :             ether_sprintf(ic->ic_myaddr));
     318             : 
     319           0 :         ic->ic_phytype = IEEE80211_T_OFDM;   /* not only, but not used */
     320           0 :         ic->ic_opmode = IEEE80211_M_STA;     /* default to BSS mode */
     321           0 :         ic->ic_state = IEEE80211_S_INIT;
     322             : 
     323             :         /* Set device capabilities. */
     324           0 :         ic->ic_caps =
     325             :             IEEE80211_C_MONITOR |       /* monitor mode supported */
     326             :             IEEE80211_C_SHPREAMBLE |    /* short preamble supported */
     327             :             IEEE80211_C_SHSLOT |        /* short slot time supported */
     328             :             IEEE80211_C_WEP |           /* WEP */
     329             :             IEEE80211_C_RSN;            /* WPA/RSN */
     330             : 
     331           0 :         if (sc->eeprom.baseEepHeader.opCapFlags & AR5416_OPFLAGS_11G) {
     332             :                 /* Set supported .11b and .11g rates. */
     333           0 :                 ic->ic_sup_rates[IEEE80211_MODE_11B] =
     334           0 :                     ieee80211_std_rateset_11b;
     335           0 :                 ic->ic_sup_rates[IEEE80211_MODE_11G] =
     336           0 :                     ieee80211_std_rateset_11g;
     337           0 :         }
     338           0 :         if (sc->eeprom.baseEepHeader.opCapFlags & AR5416_OPFLAGS_11A) {
     339             :                 /* Set supported .11a rates. */
     340           0 :                 ic->ic_sup_rates[IEEE80211_MODE_11A] =
     341           0 :                     ieee80211_std_rateset_11a;
     342           0 :         }
     343             : 
     344             :         /* Build the list of supported channels. */
     345           0 :         otus_get_chanlist(sc);
     346             : 
     347           0 :         ifp->if_softc = sc;
     348           0 :         ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
     349           0 :         ifp->if_ioctl = otus_ioctl;
     350           0 :         ifp->if_start = otus_start;
     351           0 :         ifp->if_watchdog = otus_watchdog;
     352           0 :         memcpy(ifp->if_xname, sc->sc_dev.dv_xname, IFNAMSIZ);
     353             : 
     354           0 :         if_attach(ifp);
     355           0 :         ieee80211_ifattach(ifp);
     356           0 :         ic->ic_node_alloc = otus_node_alloc;
     357           0 :         ic->ic_newassoc = otus_newassoc;
     358           0 :         ic->ic_updateslot = otus_updateslot;
     359           0 :         ic->ic_updateedca = otus_updateedca;
     360             : #ifdef notyet
     361             :         ic->ic_set_key = otus_set_key;
     362             :         ic->ic_delete_key = otus_delete_key;
     363             : #endif
     364             :         /* Override state transition machine. */
     365           0 :         sc->sc_newstate = ic->ic_newstate;
     366           0 :         ic->ic_newstate = otus_newstate;
     367           0 :         ieee80211_media_init(ifp, otus_media_change, ieee80211_media_status);
     368             : 
     369             : #if NBPFILTER > 0
     370           0 :         bpfattach(&sc->sc_drvbpf, ifp, DLT_IEEE802_11_RADIO,
     371             :             sizeof (struct ieee80211_frame) + IEEE80211_RADIOTAP_HDRLEN);
     372             : 
     373           0 :         sc->sc_rxtap_len = sizeof sc->sc_rxtapu;
     374           0 :         sc->sc_rxtap.wr_ihdr.it_len = htole16(sc->sc_rxtap_len);
     375           0 :         sc->sc_rxtap.wr_ihdr.it_present = htole32(OTUS_RX_RADIOTAP_PRESENT);
     376             : 
     377           0 :         sc->sc_txtap_len = sizeof sc->sc_txtapu;
     378           0 :         sc->sc_txtap.wt_ihdr.it_len = htole16(sc->sc_txtap_len);
     379           0 :         sc->sc_txtap.wt_ihdr.it_present = htole32(OTUS_TX_RADIOTAP_PRESENT);
     380             : #endif
     381           0 : }
     382             : 
     383             : void
     384           0 : otus_get_chanlist(struct otus_softc *sc)
     385             : {
     386           0 :         struct ieee80211com *ic = &sc->sc_ic;
     387             :         uint16_t domain;
     388             :         uint8_t chan;
     389             :         int i;
     390             : 
     391             :         /* XXX regulatory domain. */
     392           0 :         domain = letoh16(sc->eeprom.baseEepHeader.regDmn[0]);
     393             :         DPRINTF(("regdomain=0x%04x\n", domain));
     394             : 
     395           0 :         if (sc->eeprom.baseEepHeader.opCapFlags & AR5416_OPFLAGS_11G) {
     396           0 :                 for (i = 0; i < 14; i++) {
     397           0 :                         chan = ar_chans[i];
     398           0 :                         ic->ic_channels[chan].ic_freq =
     399           0 :                             ieee80211_ieee2mhz(chan, IEEE80211_CHAN_2GHZ);
     400           0 :                         ic->ic_channels[chan].ic_flags =
     401             :                             IEEE80211_CHAN_CCK | IEEE80211_CHAN_OFDM |
     402             :                             IEEE80211_CHAN_DYN | IEEE80211_CHAN_2GHZ;
     403             :                 }
     404             :         }
     405           0 :         if (sc->eeprom.baseEepHeader.opCapFlags & AR5416_OPFLAGS_11A) {
     406           0 :                 for (i = 14; i < nitems(ar_chans); i++) {
     407           0 :                         chan = ar_chans[i];
     408           0 :                         ic->ic_channels[chan].ic_freq =
     409           0 :                             ieee80211_ieee2mhz(chan, IEEE80211_CHAN_5GHZ);
     410           0 :                         ic->ic_channels[chan].ic_flags = IEEE80211_CHAN_A;
     411             :                 }
     412             :         }
     413           0 : }
     414             : 
     415             : int
     416           0 : otus_load_firmware(struct otus_softc *sc, const char *name, uint32_t addr)
     417             : {
     418           0 :         usb_device_request_t req;
     419           0 :         size_t fwsize, size;
     420           0 :         u_char *fw, *ptr;
     421             :         int mlen, error;
     422             : 
     423             :         /* Read firmware image from the filesystem. */
     424           0 :         if ((error = loadfirmware(name, &fw, &fwsize)) != 0) {
     425           0 :                 printf("%s: failed loadfirmware of file %s (error %d)\n",
     426           0 :                     sc->sc_dev.dv_xname, name, error);
     427           0 :                 return error;
     428             :         }
     429           0 :         req.bmRequestType = UT_WRITE_VENDOR_DEVICE;
     430           0 :         req.bRequest = AR_FW_DOWNLOAD;
     431           0 :         USETW(req.wIndex, 0);
     432             : 
     433           0 :         ptr = fw;
     434           0 :         size = fwsize;
     435           0 :         addr >>= 8;
     436           0 :         while (size > 0) {
     437           0 :                 mlen = MIN(size, 4096);
     438             : 
     439           0 :                 USETW(req.wValue, addr);
     440           0 :                 USETW(req.wLength, mlen);
     441           0 :                 if (usbd_do_request(sc->sc_udev, &req, ptr) != 0) {
     442             :                         error = EIO;
     443           0 :                         break;
     444             :                 }
     445           0 :                 addr += mlen >> 8;
     446           0 :                 ptr  += mlen;
     447           0 :                 size -= mlen;
     448             :         }
     449           0 :         free(fw, M_DEVBUF, fwsize);
     450           0 :         return error;
     451           0 : }
     452             : 
     453             : int
     454           0 : otus_open_pipes(struct otus_softc *sc)
     455             : {
     456             :         usb_endpoint_descriptor_t *ed;
     457             :         int i, isize, error;
     458             : 
     459           0 :         error = usbd_open_pipe(sc->sc_iface, AR_EPT_BULK_RX_NO, 0,
     460           0 :             &sc->data_rx_pipe);
     461           0 :         if (error != 0) {
     462           0 :                 printf("%s: could not open Rx bulk pipe\n",
     463           0 :                     sc->sc_dev.dv_xname);
     464           0 :                 goto fail;
     465             :         }
     466             : 
     467           0 :         ed = usbd_get_endpoint_descriptor(sc->sc_iface, AR_EPT_INTR_RX_NO);
     468           0 :         if (ed == NULL) {
     469           0 :                 printf("%s: could not retrieve Rx intr pipe descriptor\n",
     470           0 :                     sc->sc_dev.dv_xname);
     471           0 :                 goto fail;
     472             :         }
     473           0 :         isize = UGETW(ed->wMaxPacketSize);
     474           0 :         if (isize == 0) {
     475           0 :                 printf("%s: invalid Rx intr pipe descriptor\n",
     476           0 :                     sc->sc_dev.dv_xname);
     477           0 :                 goto fail;
     478             :         }
     479           0 :         sc->ibuf = malloc(isize, M_USBDEV, M_NOWAIT);
     480           0 :         if (sc->ibuf == NULL) {
     481           0 :                 printf("%s: could not allocate Rx intr buffer\n",
     482           0 :                     sc->sc_dev.dv_xname);
     483           0 :                 goto fail;
     484             :         }
     485           0 :         sc->ibuflen = isize;
     486           0 :         error = usbd_open_pipe_intr(sc->sc_iface, AR_EPT_INTR_RX_NO,
     487           0 :             USBD_SHORT_XFER_OK, &sc->cmd_rx_pipe, sc, sc->ibuf, isize,
     488             :             otus_intr, USBD_DEFAULT_INTERVAL);
     489           0 :         if (error != 0) {
     490           0 :                 printf("%s: could not open Rx intr pipe\n",
     491           0 :                     sc->sc_dev.dv_xname);
     492           0 :                 goto fail;
     493             :         }
     494             : 
     495           0 :         error = usbd_open_pipe(sc->sc_iface, AR_EPT_BULK_TX_NO, 0,
     496           0 :             &sc->data_tx_pipe);
     497           0 :         if (error != 0) {
     498           0 :                 printf("%s: could not open Tx bulk pipe\n",
     499           0 :                     sc->sc_dev.dv_xname);
     500           0 :                 goto fail;
     501             :         }
     502             : 
     503           0 :         error = usbd_open_pipe(sc->sc_iface, AR_EPT_INTR_TX_NO, 0,
     504           0 :             &sc->cmd_tx_pipe);
     505           0 :         if (error != 0) {
     506           0 :                 printf("%s: could not open Tx intr pipe\n",
     507           0 :                     sc->sc_dev.dv_xname);
     508           0 :                 goto fail;
     509             :         }
     510             : 
     511           0 :         if (otus_alloc_tx_cmd(sc) != 0) {
     512           0 :                 printf("%s: could not allocate command xfer\n",
     513           0 :                     sc->sc_dev.dv_xname);
     514           0 :                 goto fail;
     515             :         }
     516             : 
     517           0 :         if (otus_alloc_tx_data_list(sc) != 0) {
     518           0 :                 printf("%s: could not allocate Tx xfers\n",
     519           0 :                     sc->sc_dev.dv_xname);
     520           0 :                 goto fail;
     521             :         }
     522             : 
     523           0 :         if (otus_alloc_rx_data_list(sc) != 0) {
     524           0 :                 printf("%s: could not allocate Rx xfers\n",
     525           0 :                     sc->sc_dev.dv_xname);
     526           0 :                 goto fail;
     527             :         }
     528             : 
     529           0 :         for (i = 0; i < OTUS_RX_DATA_LIST_COUNT; i++) {
     530           0 :                 struct otus_rx_data *data = &sc->rx_data[i];
     531             : 
     532           0 :                 usbd_setup_xfer(data->xfer, sc->data_rx_pipe, data, data->buf,
     533             :                     OTUS_RXBUFSZ, USBD_SHORT_XFER_OK | USBD_NO_COPY,
     534             :                     USBD_NO_TIMEOUT, otus_rxeof);
     535           0 :                 error = usbd_transfer(data->xfer);
     536           0 :                 if (error != USBD_IN_PROGRESS && error != 0) {
     537           0 :                         printf("%s: could not queue Rx xfer\n",
     538           0 :                             sc->sc_dev.dv_xname);
     539           0 :                         goto fail;
     540             :                 }
     541           0 :         }
     542           0 :         return 0;
     543             : 
     544           0 :  fail:  otus_close_pipes(sc);
     545           0 :         return error;
     546           0 : }
     547             : 
     548             : void
     549           0 : otus_close_pipes(struct otus_softc *sc)
     550             : {
     551           0 :         otus_free_tx_cmd(sc);
     552           0 :         otus_free_tx_data_list(sc);
     553           0 :         otus_free_rx_data_list(sc);
     554             : 
     555           0 :         if (sc->data_rx_pipe != NULL)
     556           0 :                 usbd_close_pipe(sc->data_rx_pipe);
     557           0 :         if (sc->cmd_rx_pipe != NULL) {
     558           0 :                 usbd_abort_pipe(sc->cmd_rx_pipe);
     559           0 :                 usbd_close_pipe(sc->cmd_rx_pipe);
     560           0 :         }
     561           0 :         if (sc->ibuf != NULL)
     562           0 :                 free(sc->ibuf, M_USBDEV, sc->ibuflen);
     563           0 :         if (sc->data_tx_pipe != NULL)
     564           0 :                 usbd_close_pipe(sc->data_tx_pipe);
     565           0 :         if (sc->cmd_tx_pipe != NULL)
     566           0 :                 usbd_close_pipe(sc->cmd_tx_pipe);
     567           0 : }
     568             : 
     569             : int
     570           0 : otus_alloc_tx_cmd(struct otus_softc *sc)
     571             : {
     572           0 :         struct otus_tx_cmd *cmd = &sc->tx_cmd;
     573             : 
     574           0 :         cmd->xfer = usbd_alloc_xfer(sc->sc_udev);
     575           0 :         if (cmd->xfer == NULL) {
     576           0 :                 printf("%s: could not allocate xfer\n",
     577           0 :                     sc->sc_dev.dv_xname);
     578           0 :                 return ENOMEM;
     579             :         }
     580           0 :         cmd->buf = usbd_alloc_buffer(cmd->xfer, OTUS_MAX_TXCMDSZ);
     581           0 :         if (cmd->buf == NULL) {
     582           0 :                 printf("%s: could not allocate xfer buffer\n",
     583           0 :                     sc->sc_dev.dv_xname);
     584           0 :                 usbd_free_xfer(cmd->xfer);
     585           0 :                 return ENOMEM;
     586             :         }
     587           0 :         return 0;
     588           0 : }
     589             : 
     590             : void
     591           0 : otus_free_tx_cmd(struct otus_softc *sc)
     592             : {
     593             :         /* Make sure no transfers are pending. */
     594           0 :         usbd_abort_pipe(sc->cmd_tx_pipe);
     595             : 
     596           0 :         if (sc->tx_cmd.xfer != NULL)
     597           0 :                 usbd_free_xfer(sc->tx_cmd.xfer);
     598           0 : }
     599             : 
     600             : int
     601           0 : otus_alloc_tx_data_list(struct otus_softc *sc)
     602             : {
     603             :         struct otus_tx_data *data;
     604             :         int i, error;
     605             : 
     606           0 :         for (i = 0; i < OTUS_TX_DATA_LIST_COUNT; i++) {
     607           0 :                 data = &sc->tx_data[i];
     608             : 
     609           0 :                 data->sc = sc;  /* Backpointer for callbacks. */
     610             : 
     611           0 :                 data->xfer = usbd_alloc_xfer(sc->sc_udev);
     612           0 :                 if (data->xfer == NULL) {
     613           0 :                         printf("%s: could not allocate xfer\n",
     614           0 :                             sc->sc_dev.dv_xname);
     615             :                         error = ENOMEM;
     616           0 :                         goto fail;
     617             :                 }
     618           0 :                 data->buf = usbd_alloc_buffer(data->xfer, OTUS_TXBUFSZ);
     619           0 :                 if (data->buf == NULL) {
     620           0 :                         printf("%s: could not allocate xfer buffer\n",
     621           0 :                             sc->sc_dev.dv_xname);
     622             :                         error = ENOMEM;
     623           0 :                         goto fail;
     624             :                 }
     625             :         }
     626           0 :         return 0;
     627             : 
     628           0 : fail:   otus_free_tx_data_list(sc);
     629           0 :         return error;
     630           0 : }
     631             : 
     632             : void
     633           0 : otus_free_tx_data_list(struct otus_softc *sc)
     634             : {
     635             :         int i;
     636             : 
     637             :         /* Make sure no transfers are pending. */
     638           0 :         usbd_abort_pipe(sc->data_tx_pipe);
     639             : 
     640           0 :         for (i = 0; i < OTUS_TX_DATA_LIST_COUNT; i++)
     641           0 :                 if (sc->tx_data[i].xfer != NULL)
     642           0 :                         usbd_free_xfer(sc->tx_data[i].xfer);
     643           0 : }
     644             : 
     645             : int
     646           0 : otus_alloc_rx_data_list(struct otus_softc *sc)
     647             : {
     648             :         struct otus_rx_data *data;
     649             :         int i, error;
     650             : 
     651           0 :         for (i = 0; i < OTUS_RX_DATA_LIST_COUNT; i++) {
     652           0 :                 data = &sc->rx_data[i];
     653             : 
     654           0 :                 data->sc = sc;       /* Backpointer for callbacks. */
     655             : 
     656           0 :                 data->xfer = usbd_alloc_xfer(sc->sc_udev);
     657           0 :                 if (data->xfer == NULL) {
     658           0 :                         printf("%s: could not allocate xfer\n",
     659           0 :                             sc->sc_dev.dv_xname);
     660             :                         error = ENOMEM;
     661           0 :                         goto fail;
     662             :                 }
     663           0 :                 data->buf = usbd_alloc_buffer(data->xfer, OTUS_RXBUFSZ);
     664           0 :                 if (data->buf == NULL) {
     665           0 :                         printf("%s: could not allocate xfer buffer\n",
     666           0 :                             sc->sc_dev.dv_xname);
     667             :                         error = ENOMEM;
     668           0 :                         goto fail;
     669             :                 }
     670             :         }
     671           0 :         return 0;
     672             : 
     673           0 : fail:   otus_free_rx_data_list(sc);
     674           0 :         return error;
     675           0 : }
     676             : 
     677             : void
     678           0 : otus_free_rx_data_list(struct otus_softc *sc)
     679             : {
     680             :         int i;
     681             : 
     682             :         /* Make sure no transfers are pending. */
     683           0 :         usbd_abort_pipe(sc->data_rx_pipe);
     684             : 
     685           0 :         for (i = 0; i < OTUS_RX_DATA_LIST_COUNT; i++)
     686           0 :                 if (sc->rx_data[i].xfer != NULL)
     687           0 :                         usbd_free_xfer(sc->rx_data[i].xfer);
     688           0 : }
     689             : 
     690             : void
     691           0 : otus_next_scan(void *arg)
     692             : {
     693           0 :         struct otus_softc *sc = arg;
     694             : 
     695           0 :         if (usbd_is_dying(sc->sc_udev))
     696           0 :                 return;
     697             : 
     698           0 :         usbd_ref_incr(sc->sc_udev);
     699             : 
     700           0 :         if (sc->sc_ic.ic_state == IEEE80211_S_SCAN)
     701           0 :                 ieee80211_next_scan(&sc->sc_ic.ic_if);
     702             : 
     703           0 :         usbd_ref_decr(sc->sc_udev);
     704           0 : }
     705             : 
     706             : void
     707           0 : otus_task(void *arg)
     708             : {
     709           0 :         struct otus_softc *sc = arg;
     710           0 :         struct otus_host_cmd_ring *ring = &sc->cmdq;
     711             :         struct otus_host_cmd *cmd;
     712             :         int s;
     713             : 
     714             :         /* Process host commands. */
     715           0 :         s = splusb();
     716           0 :         while (ring->next != ring->cur) {
     717           0 :                 cmd = &ring->cmd[ring->next];
     718           0 :                 splx(s);
     719             :                 /* Callback. */
     720           0 :                 cmd->cb(sc, cmd->data);
     721           0 :                 s = splusb();
     722           0 :                 ring->queued--;
     723           0 :                 ring->next = (ring->next + 1) % OTUS_HOST_CMD_RING_COUNT;
     724             :         }
     725           0 :         splx(s);
     726           0 : }
     727             : 
     728             : void
     729           0 : otus_do_async(struct otus_softc *sc, void (*cb)(struct otus_softc *, void *),
     730             :     void *arg, int len)
     731             : {
     732           0 :         struct otus_host_cmd_ring *ring = &sc->cmdq;
     733             :         struct otus_host_cmd *cmd;
     734             :         int s;
     735             : 
     736           0 :         s = splusb();
     737           0 :         cmd = &ring->cmd[ring->cur];
     738           0 :         cmd->cb = cb;
     739           0 :         KASSERT(len <= sizeof (cmd->data));
     740           0 :         memcpy(cmd->data, arg, len);
     741           0 :         ring->cur = (ring->cur + 1) % OTUS_HOST_CMD_RING_COUNT;
     742             : 
     743             :         /* If there is no pending command already, schedule a task. */
     744           0 :         if (++ring->queued == 1)
     745           0 :                 usb_add_task(sc->sc_udev, &sc->sc_task);
     746           0 :         splx(s);
     747           0 : }
     748             : 
     749             : int
     750           0 : otus_newstate(struct ieee80211com *ic, enum ieee80211_state nstate, int arg)
     751             : {
     752           0 :         struct otus_softc *sc = ic->ic_softc;
     753           0 :         struct otus_cmd_newstate cmd;
     754             : 
     755             :         /* Do it in a process context. */
     756           0 :         cmd.state = nstate;
     757           0 :         cmd.arg = arg;
     758           0 :         otus_do_async(sc, otus_newstate_cb, &cmd, sizeof cmd);
     759           0 :         return 0;
     760           0 : }
     761             : 
     762             : void
     763           0 : otus_newstate_cb(struct otus_softc *sc, void *arg)
     764             : {
     765           0 :         struct otus_cmd_newstate *cmd = arg;
     766           0 :         struct ieee80211com *ic = &sc->sc_ic;
     767             :         struct ieee80211_node *ni;
     768             :         int s;
     769             : 
     770           0 :         s = splnet();
     771             : 
     772           0 :         switch (cmd->state) {
     773             :         case IEEE80211_S_INIT:
     774             :                 break;
     775             : 
     776             :         case IEEE80211_S_SCAN:
     777           0 :                 (void)otus_set_chan(sc, ic->ic_bss->ni_chan, 0);
     778           0 :                 if (!usbd_is_dying(sc->sc_udev))
     779           0 :                         timeout_add_msec(&sc->scan_to, 200);
     780             :                 break;
     781             : 
     782             :         case IEEE80211_S_AUTH:
     783             :         case IEEE80211_S_ASSOC:
     784           0 :                 (void)otus_set_chan(sc, ic->ic_bss->ni_chan, 0);
     785           0 :                 break;
     786             : 
     787             :         case IEEE80211_S_RUN:
     788           0 :                 (void)otus_set_chan(sc, ic->ic_bss->ni_chan, 1);
     789             : 
     790           0 :                 ni = ic->ic_bss;
     791             : 
     792           0 :                 if (ic->ic_opmode == IEEE80211_M_STA) {
     793           0 :                         otus_updateslot(ic);
     794           0 :                         otus_set_bssid(sc, ni->ni_bssid);
     795             : 
     796             :                         /* Fake a join to init the Tx rate. */
     797           0 :                         otus_newassoc(ic, ni, 1);
     798             : 
     799             :                         /* Start calibration timer. */
     800           0 :                         if (!usbd_is_dying(sc->sc_udev))
     801           0 :                                 timeout_add_sec(&sc->calib_to, 1);
     802             :                 }
     803             :                 break;
     804             :         }
     805             : 
     806           0 :         sc->sc_led_newstate(sc);
     807           0 :         (void)sc->sc_newstate(ic, cmd->state, cmd->arg);
     808             : 
     809           0 :         splx(s);
     810           0 : }
     811             : 
     812             : int
     813           0 : otus_cmd(struct otus_softc *sc, uint8_t code, const void *idata, int ilen,
     814             :     void *odata)
     815             : {
     816           0 :         struct otus_tx_cmd *cmd = &sc->tx_cmd;
     817             :         struct ar_cmd_hdr *hdr;
     818             :         int s, xferlen, error;
     819             : 
     820             :         /* Always bulk-out a multiple of 4 bytes. */
     821           0 :         xferlen = (sizeof (*hdr) + ilen + 3) & ~3;
     822             : 
     823           0 :         hdr = (struct ar_cmd_hdr *)cmd->buf;
     824           0 :         hdr->code  = code;
     825           0 :         hdr->len   = ilen;
     826           0 :         hdr->token = ++cmd->token;        /* Don't care about endianness. */
     827           0 :         memcpy((uint8_t *)&hdr[1], idata, ilen);
     828             : 
     829             :         DPRINTFN(2, ("sending command code=0x%02x len=%d token=%d\n",
     830             :             code, ilen, hdr->token));
     831             : 
     832           0 :         s = splusb();
     833           0 :         cmd->odata = odata;
     834           0 :         cmd->done = 0;
     835             : 
     836           0 :         usbd_setup_xfer(cmd->xfer, sc->cmd_tx_pipe, cmd, cmd->buf, xferlen,
     837             :             USBD_FORCE_SHORT_XFER | USBD_NO_COPY | USBD_SYNCHRONOUS,
     838             :             OTUS_CMD_TIMEOUT, NULL);
     839           0 :         error = usbd_transfer(cmd->xfer);
     840           0 :         if (error != 0) {
     841           0 :                 splx(s);
     842           0 :                 printf("%s: could not send command 0x%x (error=%s)\n",
     843           0 :                     sc->sc_dev.dv_xname, code, usbd_errstr(error));
     844           0 :                 return EIO;
     845             :         }
     846           0 :         if (!cmd->done)
     847           0 :                 error = tsleep(cmd, PCATCH, "otuscmd", hz);
     848           0 :         cmd->odata = NULL;   /* In case answer is received too late. */
     849           0 :         splx(s);
     850           0 :         if (error != 0) {
     851           0 :                 printf("%s: timeout waiting for command 0x%02x reply\n",
     852           0 :                     sc->sc_dev.dv_xname, code);
     853           0 :         }
     854           0 :         return error;
     855           0 : }
     856             : 
     857             : void
     858           0 : otus_write(struct otus_softc *sc, uint32_t reg, uint32_t val)
     859             : {
     860           0 :         sc->write_buf[sc->write_idx].reg = htole32(reg);
     861           0 :         sc->write_buf[sc->write_idx].val = htole32(val);
     862             : 
     863           0 :         if (++sc->write_idx > AR_MAX_WRITE_IDX)
     864           0 :                 (void)otus_write_barrier(sc);
     865           0 : }
     866             : 
     867             : int
     868           0 : otus_write_barrier(struct otus_softc *sc)
     869             : {
     870             :         int error;
     871             : 
     872           0 :         if (sc->write_idx == 0)
     873           0 :                 return 0;       /* Nothing to flush. */
     874             : 
     875           0 :         error = otus_cmd(sc, AR_CMD_WREG, sc->write_buf,
     876           0 :             sizeof (sc->write_buf[0]) * sc->write_idx, NULL);
     877           0 :         sc->write_idx = 0;
     878           0 :         return error;
     879           0 : }
     880             : 
     881             : struct ieee80211_node *
     882           0 : otus_node_alloc(struct ieee80211com *ic)
     883             : {
     884           0 :         return malloc(sizeof (struct otus_node), M_DEVBUF, M_NOWAIT | M_ZERO);
     885             : }
     886             : 
     887             : int
     888           0 : otus_media_change(struct ifnet *ifp)
     889             : {
     890           0 :         struct otus_softc *sc = ifp->if_softc;
     891           0 :         struct ieee80211com *ic = &sc->sc_ic;
     892             :         uint8_t rate, ridx;
     893             :         int error;
     894             : 
     895           0 :         error = ieee80211_media_change(ifp);
     896           0 :         if (error != ENETRESET)
     897           0 :                 return error;
     898             : 
     899           0 :         if (ic->ic_fixed_rate != -1) {
     900           0 :                 rate = ic->ic_sup_rates[ic->ic_curmode].
     901           0 :                     rs_rates[ic->ic_fixed_rate] & IEEE80211_RATE_VAL;
     902           0 :                 for (ridx = 0; ridx <= OTUS_RIDX_MAX; ridx++)
     903           0 :                         if (otus_rates[ridx].rate == rate)
     904             :                                 break;
     905           0 :                 sc->fixed_ridx = ridx;
     906           0 :         }
     907             : 
     908           0 :         if ((ifp->if_flags & (IFF_UP | IFF_RUNNING)) == (IFF_UP | IFF_RUNNING))
     909           0 :                 error = otus_init(ifp);
     910             : 
     911           0 :         return error;
     912           0 : }
     913             : 
     914             : int
     915           0 : otus_read_eeprom(struct otus_softc *sc)
     916             : {
     917           0 :         uint32_t regs[8], reg;
     918             :         uint8_t *eep;
     919             :         int i, j, error;
     920             : 
     921             :         /* Read EEPROM by blocks of 32 bytes. */
     922           0 :         eep = (uint8_t *)&sc->eeprom;
     923             :         reg = AR_EEPROM_OFFSET;
     924           0 :         for (i = 0; i < sizeof (sc->eeprom) / 32; i++) {
     925           0 :                 for (j = 0; j < 8; j++, reg += 4)
     926           0 :                         regs[j] = htole32(reg);
     927           0 :                 error = otus_cmd(sc, AR_CMD_RREG, regs, sizeof regs, eep);
     928           0 :                 if (error != 0)
     929             :                         break;
     930           0 :                 eep += 32;
     931             :         }
     932           0 :         return error;
     933           0 : }
     934             : 
     935             : void
     936           0 : otus_newassoc(struct ieee80211com *ic, struct ieee80211_node *ni, int isnew)
     937             : {
     938           0 :         struct otus_softc *sc = ic->ic_softc;
     939           0 :         struct otus_node *on = (void *)ni;
     940           0 :         struct ieee80211_rateset *rs = &ni->ni_rates;
     941             :         uint8_t rate;
     942             :         int ridx, i;
     943             : 
     944             :         DPRINTF(("new assoc isnew=%d addr=%s\n",
     945             :             isnew, ether_sprintf(ni->ni_macaddr)));
     946             : 
     947           0 :         ieee80211_amrr_node_init(&sc->amrr, &on->amn);
     948             :         /* Start at lowest available bit-rate, AMRR will raise. */
     949           0 :         ni->ni_txrate = 0;
     950             : 
     951           0 :         for (i = 0; i < rs->rs_nrates; i++) {
     952           0 :                 rate = rs->rs_rates[i] & IEEE80211_RATE_VAL;
     953             :                 /* Convert 802.11 rate to hardware rate index. */
     954           0 :                 for (ridx = 0; ridx <= OTUS_RIDX_MAX; ridx++)
     955           0 :                         if (otus_rates[ridx].rate == rate)
     956             :                                 break;
     957           0 :                 on->ridx[i] = ridx;
     958             :                 DPRINTF(("rate=0x%02x ridx=%d\n",
     959             :                     rs->rs_rates[i], on->ridx[i]));
     960             :         }
     961           0 : }
     962             : 
     963             : /* ARGSUSED */
     964             : void
     965           0 : otus_intr(struct usbd_xfer *xfer, void *priv, usbd_status status)
     966             : {
     967             : #if 0
     968             :         struct otus_softc *sc = priv;
     969             :         int len;
     970             : 
     971             :         /*
     972             :          * The Rx intr pipe is unused with current firmware.  Notifications
     973             :          * and replies to commands are sent through the Rx bulk pipe instead
     974             :          * (with a magic PLCP header.)
     975             :          */
     976             :         if (__predict_false(status != USBD_NORMAL_COMPLETION)) {
     977             :                 DPRINTF(("intr status=%d\n", status));
     978             :                 if (status == USBD_STALLED)
     979             :                         usbd_clear_endpoint_stall_async(sc->cmd_rx_pipe);
     980             :                 return;
     981             :         }
     982             :         usbd_get_xfer_status(xfer, NULL, NULL, &len, NULL);
     983             : 
     984             :         otus_cmd_rxeof(sc, sc->ibuf, len);
     985             : #endif
     986           0 : }
     987             : 
     988             : void
     989           0 : otus_cmd_rxeof(struct otus_softc *sc, uint8_t *buf, int len)
     990             : {
     991           0 :         struct ieee80211com *ic = &sc->sc_ic;
     992             :         struct otus_tx_cmd *cmd;
     993             :         struct ar_cmd_hdr *hdr;
     994             :         int s;
     995             : 
     996           0 :         if (__predict_false(len < sizeof (*hdr))) {
     997             :                 DPRINTF(("cmd too small %d\n", len));
     998           0 :                 return;
     999             :         }
    1000           0 :         hdr = (struct ar_cmd_hdr *)buf;
    1001           0 :         if (__predict_false(sizeof (*hdr) + hdr->len > len ||
    1002             :             sizeof (*hdr) + hdr->len > 64)) {
    1003             :                 DPRINTF(("cmd too large %d\n", hdr->len));
    1004           0 :                 return;
    1005             :         }
    1006             : 
    1007           0 :         if ((hdr->code & 0xc0) != 0xc0) {
    1008             :                 DPRINTFN(2, ("received reply code=0x%02x len=%d token=%d\n",
    1009             :                     hdr->code, hdr->len, hdr->token));
    1010           0 :                 cmd = &sc->tx_cmd;
    1011           0 :                 if (__predict_false(hdr->token != cmd->token))
    1012           0 :                         return;
    1013             :                 /* Copy answer into caller's supplied buffer. */
    1014           0 :                 if (cmd->odata != NULL)
    1015           0 :                         memcpy(cmd->odata, &hdr[1], hdr->len);
    1016           0 :                 cmd->done = 1;
    1017           0 :                 wakeup(cmd);
    1018           0 :                 return;
    1019             :         }
    1020             : 
    1021             :         /* Received unsolicited notification. */
    1022             :         DPRINTF(("received notification code=0x%02x len=%d\n",
    1023             :             hdr->code, hdr->len));
    1024           0 :         switch (hdr->code & 0x3f) {
    1025             :         case AR_EVT_BEACON:
    1026             :                 break;
    1027             :         case AR_EVT_TX_COMP:
    1028             :         {
    1029           0 :                 struct ar_evt_tx_comp *tx = (struct ar_evt_tx_comp *)&hdr[1];
    1030             :                 struct ieee80211_node *ni;
    1031             :                 struct otus_node *on;
    1032             : 
    1033             :                 DPRINTF(("tx completed %s status=%d phy=0x%x\n",
    1034             :                     ether_sprintf(tx->macaddr), letoh16(tx->status),
    1035             :                     letoh32(tx->phy)));
    1036           0 :                 s = splnet();
    1037             : #ifdef notyet
    1038             : #ifndef IEEE80211_STA_ONLY
    1039             :                 if (ic->ic_opmode != IEEE80211_M_STA) {
    1040             :                         ni = ieee80211_find_node(ic, tx->macaddr);
    1041             :                         if (__predict_false(ni == NULL)) {
    1042             :                                 splx(s);
    1043             :                                 break;
    1044             :                         }
    1045             :                 } else
    1046             : #endif
    1047             : #endif
    1048           0 :                         ni = ic->ic_bss;
    1049             :                 /* Update rate control statistics. */
    1050           0 :                 on = (void *)ni;
    1051             :                 /* NB: we do not set the TX_MAC_RATE_PROBING flag. */
    1052           0 :                 if (__predict_true(tx->status != 0))
    1053           0 :                         on->amn.amn_retrycnt++;
    1054           0 :                 splx(s);
    1055             :                 break;
    1056             :         }
    1057             :         case AR_EVT_TBTT:
    1058             :                 break;
    1059             :         }
    1060           0 : }
    1061             : 
    1062             : void
    1063           0 : otus_sub_rxeof(struct otus_softc *sc, uint8_t *buf, int len)
    1064             : {
    1065           0 :         struct ieee80211com *ic = &sc->sc_ic;
    1066           0 :         struct ifnet *ifp = &ic->ic_if;
    1067           0 :         struct ieee80211_rxinfo rxi;
    1068             :         struct ieee80211_node *ni;
    1069             :         struct ar_rx_tail *tail;
    1070             :         struct ieee80211_frame *wh;
    1071             :         struct mbuf *m;
    1072             :         uint8_t *plcp;
    1073             :         int s, mlen, align;
    1074             : 
    1075           0 :         if (__predict_false(len < AR_PLCP_HDR_LEN)) {
    1076             :                 DPRINTF(("sub-xfer too short %d\n", len));
    1077           0 :                 return;
    1078             :         }
    1079             :         plcp = buf;
    1080             : 
    1081             :         /* All bits in the PLCP header are set to 1 for non-MPDU. */
    1082           0 :         if (memcmp(plcp, AR_PLCP_HDR_INTR, AR_PLCP_HDR_LEN) == 0) {
    1083           0 :                 otus_cmd_rxeof(sc, plcp + AR_PLCP_HDR_LEN,
    1084           0 :                     len - AR_PLCP_HDR_LEN);
    1085           0 :                 return;
    1086             :         }
    1087             : 
    1088             :         /* Received MPDU. */
    1089           0 :         if (__predict_false(len < AR_PLCP_HDR_LEN + sizeof (*tail))) {
    1090             :                 DPRINTF(("MPDU too short %d\n", len));
    1091           0 :                 ifp->if_ierrors++;
    1092           0 :                 return;
    1093             :         }
    1094           0 :         tail = (struct ar_rx_tail *)(plcp + len - sizeof (*tail));
    1095             : 
    1096             :         /* Discard error frames. */
    1097           0 :         if (__predict_false(tail->error != 0)) {
    1098             :                 DPRINTF(("error frame 0x%02x\n", tail->error));
    1099           0 :                 if (tail->error & AR_RX_ERROR_FCS) {
    1100             :                         DPRINTFN(3, ("bad FCS\n"));
    1101           0 :                 } else if (tail->error & AR_RX_ERROR_MMIC) {
    1102             :                         /* Report Michael MIC failures to net80211. */
    1103           0 :                         ic->ic_stats.is_rx_locmicfail++;
    1104           0 :                         ieee80211_michael_mic_failure(ic, 0);
    1105           0 :                 }
    1106           0 :                 ifp->if_ierrors++;
    1107           0 :                 return;
    1108             :         }
    1109             :         /* Compute MPDU's length. */
    1110           0 :         mlen = len - AR_PLCP_HDR_LEN - sizeof (*tail);
    1111             :         /* Make sure there's room for an 802.11 header + FCS. */
    1112           0 :         if (__predict_false(mlen < IEEE80211_MIN_LEN)) {
    1113           0 :                 ifp->if_ierrors++;
    1114           0 :                 return;
    1115             :         }
    1116           0 :         mlen -= IEEE80211_CRC_LEN;      /* strip 802.11 FCS */
    1117           0 :         if (mlen > MCLBYTES) {
    1118             :                 DPRINTF(("frame too large: %d\n", mlen));
    1119           0 :                 ifp->if_ierrors++;
    1120           0 :                 return;
    1121             :         }
    1122             : 
    1123           0 :         wh = (struct ieee80211_frame *)(plcp + AR_PLCP_HDR_LEN);
    1124             :         /* Provide a 32-bit aligned protocol header to the stack. */
    1125           0 :         align = (ieee80211_has_qos(wh) ^ ieee80211_has_addr4(wh)) ? 2 : 0;
    1126             : 
    1127           0 :         MGETHDR(m, M_DONTWAIT, MT_DATA);
    1128           0 :         if (__predict_false(m == NULL)) {
    1129           0 :                 ifp->if_ierrors++;
    1130           0 :                 return;
    1131             :         }
    1132           0 :         if (align + mlen > MHLEN) {
    1133           0 :                 MCLGET(m, M_DONTWAIT);
    1134           0 :                 if (__predict_false(!(m->m_flags & M_EXT))) {
    1135           0 :                         ifp->if_ierrors++;
    1136           0 :                         m_freem(m);
    1137           0 :                         return;
    1138             :                 }
    1139             :         }
    1140             :         /* Finalize mbuf. */
    1141           0 :         m->m_data += align;
    1142           0 :         memcpy(mtod(m, caddr_t), wh, mlen);
    1143           0 :         m->m_pkthdr.len = m->m_len = mlen;
    1144             : 
    1145             : #if NBPFILTER > 0
    1146           0 :         if (__predict_false(sc->sc_drvbpf != NULL)) {
    1147           0 :                 struct otus_rx_radiotap_header *tap = &sc->sc_rxtap;
    1148           0 :                 struct mbuf mb;
    1149             : 
    1150           0 :                 tap->wr_flags = 0;
    1151           0 :                 tap->wr_chan_freq = htole16(ic->ic_ibss_chan->ic_freq);
    1152           0 :                 tap->wr_chan_flags = htole16(ic->ic_ibss_chan->ic_flags);
    1153           0 :                 tap->wr_antsignal = tail->rssi;
    1154           0 :                 tap->wr_rate = 2;    /* In case it can't be found below. */
    1155           0 :                 switch (tail->status & AR_RX_STATUS_MT_MASK) {
    1156             :                 case AR_RX_STATUS_MT_CCK:
    1157           0 :                         switch (plcp[0]) {
    1158           0 :                         case  10: tap->wr_rate =   2; break;
    1159           0 :                         case  20: tap->wr_rate =   4; break;
    1160           0 :                         case  55: tap->wr_rate =  11; break;
    1161           0 :                         case 110: tap->wr_rate =  22; break;
    1162             :                         }
    1163           0 :                         if (tail->status & AR_RX_STATUS_SHPREAMBLE)
    1164           0 :                                 tap->wr_flags |= IEEE80211_RADIOTAP_F_SHORTPRE;
    1165             :                         break;
    1166             :                 case AR_RX_STATUS_MT_OFDM:
    1167           0 :                         switch (plcp[0] & 0xf) {
    1168           0 :                         case 0xb: tap->wr_rate =  12; break;
    1169           0 :                         case 0xf: tap->wr_rate =  18; break;
    1170           0 :                         case 0xa: tap->wr_rate =  24; break;
    1171           0 :                         case 0xe: tap->wr_rate =  36; break;
    1172           0 :                         case 0x9: tap->wr_rate =  48; break;
    1173           0 :                         case 0xd: tap->wr_rate =  72; break;
    1174           0 :                         case 0x8: tap->wr_rate =  96; break;
    1175           0 :                         case 0xc: tap->wr_rate = 108; break;
    1176             :                         }
    1177             :                         break;
    1178             :                 }
    1179           0 :                 mb.m_data = (caddr_t)tap;
    1180           0 :                 mb.m_len = sc->sc_rxtap_len;
    1181           0 :                 mb.m_next = m;
    1182           0 :                 mb.m_nextpkt = NULL;
    1183           0 :                 mb.m_type = 0;
    1184           0 :                 mb.m_flags = 0;
    1185           0 :                 bpf_mtap(sc->sc_drvbpf, &mb, BPF_DIRECTION_IN);
    1186           0 :         }
    1187             : #endif
    1188             : 
    1189           0 :         s = splnet();
    1190           0 :         ni = ieee80211_find_rxnode(ic, wh);
    1191           0 :         rxi.rxi_flags = 0;
    1192           0 :         rxi.rxi_rssi = tail->rssi;
    1193           0 :         rxi.rxi_tstamp = 0;     /* unused */
    1194           0 :         ieee80211_input(ifp, m, ni, &rxi);
    1195             : 
    1196             :         /* Node is no longer needed. */
    1197           0 :         ieee80211_release_node(ic, ni);
    1198           0 :         splx(s);
    1199           0 : }
    1200             : 
    1201             : void
    1202           0 : otus_rxeof(struct usbd_xfer *xfer, void *priv, usbd_status status)
    1203             : {
    1204           0 :         struct otus_rx_data *data = priv;
    1205           0 :         struct otus_softc *sc = data->sc;
    1206           0 :         caddr_t buf = data->buf;
    1207             :         struct ar_rx_head *head;
    1208             :         uint16_t hlen;
    1209           0 :         int len;
    1210             : 
    1211           0 :         if (__predict_false(status != USBD_NORMAL_COMPLETION)) {
    1212             :                 DPRINTF(("RX status=%d\n", status));
    1213           0 :                 if (status == USBD_STALLED)
    1214           0 :                         usbd_clear_endpoint_stall_async(sc->data_rx_pipe);
    1215           0 :                 if (status != USBD_CANCELLED)
    1216             :                         goto resubmit;
    1217           0 :                 return;
    1218             :         }
    1219           0 :         usbd_get_xfer_status(xfer, NULL, NULL, &len, NULL);
    1220             : 
    1221           0 :         while (len >= sizeof (*head)) {
    1222           0 :                 head = (struct ar_rx_head *)buf;
    1223           0 :                 if (__predict_false(head->tag != htole16(AR_RX_HEAD_TAG))) {
    1224             :                         DPRINTF(("tag not valid 0x%x\n", letoh16(head->tag)));
    1225             :                         break;
    1226             :                 }
    1227           0 :                 hlen = letoh16(head->len);
    1228           0 :                 if (__predict_false(sizeof (*head) + hlen > len)) {
    1229             :                         DPRINTF(("xfer too short %d/%d\n", len, hlen));
    1230             :                         break;
    1231             :                 }
    1232             :                 /* Process sub-xfer. */
    1233           0 :                 otus_sub_rxeof(sc, (uint8_t *)&head[1], hlen);
    1234             : 
    1235             :                 /* Next sub-xfer is aligned on a 32-bit boundary. */
    1236           0 :                 hlen = (sizeof (*head) + hlen + 3) & ~3;
    1237           0 :                 buf += hlen;
    1238           0 :                 len -= hlen;
    1239             :         }
    1240             : 
    1241             :  resubmit:
    1242           0 :         usbd_setup_xfer(xfer, sc->data_rx_pipe, data, data->buf, OTUS_RXBUFSZ,
    1243             :             USBD_SHORT_XFER_OK, USBD_NO_TIMEOUT, otus_rxeof);
    1244           0 :         (void)usbd_transfer(data->xfer);
    1245           0 : }
    1246             : 
    1247             : void
    1248           0 : otus_txeof(struct usbd_xfer *xfer, void *priv, usbd_status status)
    1249             : {
    1250           0 :         struct otus_tx_data *data = priv;
    1251           0 :         struct otus_softc *sc = data->sc;
    1252           0 :         struct ieee80211com *ic = &sc->sc_ic;
    1253           0 :         struct ifnet *ifp = &ic->ic_if;
    1254             :         int s;
    1255             : 
    1256           0 :         s = splnet();
    1257           0 :         sc->tx_queued--;
    1258           0 :         if (__predict_false(status != USBD_NORMAL_COMPLETION)) {
    1259             :                 DPRINTF(("TX status=%d\n", status));
    1260           0 :                 if (status == USBD_STALLED)
    1261           0 :                         usbd_clear_endpoint_stall_async(sc->data_tx_pipe);
    1262           0 :                 ifp->if_oerrors++;
    1263           0 :                 splx(s);
    1264           0 :                 return;
    1265             :         }
    1266           0 :         sc->sc_tx_timer = 0;
    1267           0 :         ifq_clr_oactive(&ifp->if_snd);
    1268           0 :         otus_start(ifp);
    1269           0 :         splx(s);
    1270           0 : }
    1271             : 
    1272             : int
    1273           0 : otus_tx(struct otus_softc *sc, struct mbuf *m, struct ieee80211_node *ni)
    1274             : {
    1275           0 :         struct ieee80211com *ic = &sc->sc_ic;
    1276           0 :         struct otus_node *on = (void *)ni;
    1277             :         struct otus_tx_data *data;
    1278             :         struct ieee80211_frame *wh;
    1279             :         struct ieee80211_key *k;
    1280             :         struct ar_tx_head *head;
    1281             :         uint32_t phyctl;
    1282             :         uint16_t macctl, qos;
    1283             :         uint8_t tid, qid;
    1284             :         int error, ridx, hasqos, xferlen;
    1285             : 
    1286           0 :         wh = mtod(m, struct ieee80211_frame *);
    1287           0 :         if (wh->i_fc[1] & IEEE80211_FC1_PROTECTED) {
    1288           0 :                 k = ieee80211_get_txkey(ic, wh, ni);
    1289           0 :                 if ((m = ieee80211_encrypt(ic, m, k)) == NULL)
    1290           0 :                         return ENOBUFS;
    1291           0 :                 wh = mtod(m, struct ieee80211_frame *);
    1292           0 :         }
    1293             : 
    1294           0 :         if ((hasqos = ieee80211_has_qos(wh))) {
    1295           0 :                 qos = ieee80211_get_qos(wh);
    1296           0 :                 tid = qos & IEEE80211_QOS_TID;
    1297           0 :                 qid = ieee80211_up_to_ac(ic, tid);
    1298           0 :         } else {
    1299             :                 qos = 0;
    1300             :                 qid = EDCA_AC_BE;
    1301             :         }
    1302             : 
    1303             :         /* Pickup a rate index. */
    1304           0 :         if (IEEE80211_IS_MULTICAST(wh->i_addr1) ||
    1305           0 :             (wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK) != IEEE80211_FC0_TYPE_DATA)
    1306           0 :                 ridx = (ic->ic_curmode == IEEE80211_MODE_11A) ?
    1307             :                     OTUS_RIDX_OFDM6 : OTUS_RIDX_CCK1;
    1308           0 :         else if (ic->ic_fixed_rate != -1)
    1309           0 :                 ridx = sc->fixed_ridx;
    1310             :         else
    1311           0 :                 ridx = on->ridx[ni->ni_txrate];
    1312             : 
    1313             :         phyctl = 0;
    1314           0 :         macctl = AR_TX_MAC_BACKOFF | AR_TX_MAC_HW_DUR | AR_TX_MAC_QID(qid);
    1315             : 
    1316           0 :         if (IEEE80211_IS_MULTICAST(wh->i_addr1) ||
    1317           0 :             (hasqos && ((qos & IEEE80211_QOS_ACK_POLICY_MASK) ==
    1318             :              IEEE80211_QOS_ACK_POLICY_NOACK)))
    1319           0 :                 macctl |= AR_TX_MAC_NOACK;
    1320             : 
    1321           0 :         if (!IEEE80211_IS_MULTICAST(wh->i_addr1)) {
    1322           0 :                 if (m->m_pkthdr.len + IEEE80211_CRC_LEN >= ic->ic_rtsthreshold)
    1323           0 :                         macctl |= AR_TX_MAC_RTS;
    1324           0 :                 else if ((ic->ic_flags & IEEE80211_F_USEPROT) &&
    1325           0 :                     ridx >= OTUS_RIDX_OFDM6) {
    1326           0 :                         if (ic->ic_protmode == IEEE80211_PROT_CTSONLY)
    1327           0 :                                 macctl |= AR_TX_MAC_CTS;
    1328           0 :                         else if (ic->ic_protmode == IEEE80211_PROT_RTSCTS)
    1329           0 :                                 macctl |= AR_TX_MAC_RTS;
    1330             :                 }
    1331             :         }
    1332             : 
    1333           0 :         phyctl |= AR_TX_PHY_MCS(otus_rates[ridx].mcs);
    1334           0 :         if (ridx >= OTUS_RIDX_OFDM6) {
    1335           0 :                 phyctl |= AR_TX_PHY_MT_OFDM;
    1336           0 :                 if (ridx <= OTUS_RIDX_OFDM24)
    1337           0 :                         phyctl |= AR_TX_PHY_ANTMSK(sc->txmask);
    1338             :                 else
    1339           0 :                         phyctl |= AR_TX_PHY_ANTMSK(1);
    1340             :         } else {        /* CCK */
    1341             :                 phyctl |= AR_TX_PHY_MT_CCK;
    1342           0 :                 phyctl |= AR_TX_PHY_ANTMSK(sc->txmask);
    1343             :         }
    1344             : 
    1345             :         /* Update rate control stats for frames that are ACK'ed. */
    1346           0 :         if (!(macctl & AR_TX_MAC_NOACK))
    1347           0 :                 ((struct otus_node *)ni)->amn.amn_txcnt++;
    1348             : 
    1349           0 :         data = &sc->tx_data[sc->tx_cur];
    1350             :         /* Fill Tx descriptor. */
    1351           0 :         head = (struct ar_tx_head *)data->buf;
    1352           0 :         head->len = htole16(m->m_pkthdr.len + IEEE80211_CRC_LEN);
    1353           0 :         head->macctl = htole16(macctl);
    1354           0 :         head->phyctl = htole32(phyctl);
    1355             : 
    1356             : #if NBPFILTER > 0
    1357           0 :         if (__predict_false(sc->sc_drvbpf != NULL)) {
    1358           0 :                 struct otus_tx_radiotap_header *tap = &sc->sc_txtap;
    1359           0 :                 struct mbuf mb;
    1360             : 
    1361           0 :                 tap->wt_flags = 0;
    1362           0 :                 tap->wt_rate = otus_rates[ridx].rate;
    1363           0 :                 tap->wt_chan_freq = htole16(ic->ic_bss->ni_chan->ic_freq);
    1364           0 :                 tap->wt_chan_flags = htole16(ic->ic_bss->ni_chan->ic_flags);
    1365             : 
    1366           0 :                 mb.m_data = (caddr_t)tap;
    1367           0 :                 mb.m_len = sc->sc_txtap_len;
    1368           0 :                 mb.m_next = m;
    1369           0 :                 mb.m_nextpkt = NULL;
    1370           0 :                 mb.m_type = 0;
    1371           0 :                 mb.m_flags = 0;
    1372           0 :                 bpf_mtap(sc->sc_drvbpf, &mb, BPF_DIRECTION_OUT);
    1373           0 :         }
    1374             : #endif
    1375             : 
    1376           0 :         xferlen = sizeof (*head) + m->m_pkthdr.len;
    1377           0 :         m_copydata(m, 0, m->m_pkthdr.len, (caddr_t)&head[1]);
    1378           0 :         m_freem(m);
    1379             : 
    1380             :         DPRINTFN(5, ("tx queued=%d len=%d mac=0x%04x phy=0x%08x rate=%d\n",
    1381             :             sc->tx_queued, head->len, head->macctl, head->phyctl,
    1382             :             otus_rates[ridx].rate));
    1383           0 :         usbd_setup_xfer(data->xfer, sc->data_tx_pipe, data, data->buf, xferlen,
    1384             :             USBD_FORCE_SHORT_XFER | USBD_NO_COPY, OTUS_TX_TIMEOUT, otus_txeof);
    1385           0 :         error = usbd_transfer(data->xfer);
    1386           0 :         if (__predict_false(error != USBD_IN_PROGRESS && error != 0))
    1387           0 :                 return error;
    1388             : 
    1389           0 :         ieee80211_release_node(ic, ni);
    1390             : 
    1391           0 :         sc->tx_queued++;
    1392           0 :         sc->tx_cur = (sc->tx_cur + 1) % OTUS_TX_DATA_LIST_COUNT;
    1393             : 
    1394           0 :         return 0;
    1395           0 : }
    1396             : 
    1397             : void
    1398           0 : otus_start(struct ifnet *ifp)
    1399             : {
    1400           0 :         struct otus_softc *sc = ifp->if_softc;
    1401           0 :         struct ieee80211com *ic = &sc->sc_ic;
    1402           0 :         struct ieee80211_node *ni;
    1403             :         struct mbuf *m;
    1404             : 
    1405           0 :         if (!(ifp->if_flags & IFF_RUNNING) || ifq_is_oactive(&ifp->if_snd))
    1406           0 :                 return;
    1407             : 
    1408           0 :         for (;;) {
    1409           0 :                 if (sc->tx_queued >= OTUS_TX_DATA_LIST_COUNT) {
    1410           0 :                         ifq_set_oactive(&ifp->if_snd);
    1411           0 :                         break;
    1412             :                 }
    1413             :                 /* Send pending management frames first. */
    1414           0 :                 m = mq_dequeue(&ic->ic_mgtq);
    1415           0 :                 if (m != NULL) {
    1416           0 :                         ni = m->m_pkthdr.ph_cookie;
    1417           0 :                         goto sendit;
    1418             :                 }
    1419           0 :                 if (ic->ic_state != IEEE80211_S_RUN)
    1420             :                         break;
    1421             : 
    1422             :                 /* Encapsulate and send data frames. */
    1423           0 :                 IFQ_DEQUEUE(&ifp->if_snd, m);
    1424           0 :                 if (m == NULL)
    1425             :                         break;
    1426             : #if NBPFILTER > 0
    1427           0 :                 if (ifp->if_bpf != NULL)
    1428           0 :                         bpf_mtap(ifp->if_bpf, m, BPF_DIRECTION_OUT);
    1429             : #endif
    1430           0 :                 if ((m = ieee80211_encap(ifp, m, &ni)) == NULL)
    1431           0 :                         continue;
    1432             : sendit:
    1433             : #if NBPFILTER > 0
    1434           0 :                 if (ic->ic_rawbpf != NULL)
    1435           0 :                         bpf_mtap(ic->ic_rawbpf, m, BPF_DIRECTION_OUT);
    1436             : #endif
    1437           0 :                 if (otus_tx(sc, m, ni) != 0) {
    1438           0 :                         ieee80211_release_node(ic, ni);
    1439           0 :                         ifp->if_oerrors++;
    1440           0 :                         continue;
    1441             :                 }
    1442             : 
    1443           0 :                 sc->sc_tx_timer = 5;
    1444           0 :                 ifp->if_timer = 1;
    1445             :         }
    1446           0 : }
    1447             : 
    1448             : void
    1449           0 : otus_watchdog(struct ifnet *ifp)
    1450             : {
    1451           0 :         struct otus_softc *sc = ifp->if_softc;
    1452             : 
    1453           0 :         ifp->if_timer = 0;
    1454             : 
    1455           0 :         if (sc->sc_tx_timer > 0) {
    1456           0 :                 if (--sc->sc_tx_timer == 0) {
    1457           0 :                         printf("%s: device timeout\n", sc->sc_dev.dv_xname);
    1458             :                         /* otus_init(ifp); XXX needs a process context! */
    1459           0 :                         ifp->if_oerrors++;
    1460           0 :                         return;
    1461             :                 }
    1462           0 :                 ifp->if_timer = 1;
    1463           0 :         }
    1464           0 :         ieee80211_watchdog(ifp);
    1465           0 : }
    1466             : 
    1467             : int
    1468           0 : otus_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
    1469             : {
    1470           0 :         struct otus_softc *sc = ifp->if_softc;
    1471           0 :         struct ieee80211com *ic = &sc->sc_ic;
    1472             :         int s, error = 0;
    1473             : 
    1474           0 :         if (usbd_is_dying(sc->sc_udev))
    1475           0 :                 return ENXIO;
    1476             : 
    1477           0 :         usbd_ref_incr(sc->sc_udev);
    1478             : 
    1479           0 :         s = splnet();
    1480             : 
    1481           0 :         switch (cmd) {
    1482             :         case SIOCSIFADDR:
    1483           0 :                 ifp->if_flags |= IFF_UP;
    1484             :                 /* FALLTHROUGH */
    1485             :         case SIOCSIFFLAGS:
    1486           0 :                 if (ifp->if_flags & IFF_UP) {
    1487           0 :                         if ((ifp->if_flags & IFF_RUNNING) &&
    1488           0 :                             ((ifp->if_flags ^ sc->sc_if_flags) &
    1489           0 :                              (IFF_ALLMULTI | IFF_PROMISC)) != 0) {
    1490           0 :                                 otus_set_multi(sc);
    1491           0 :                         } else if (!(ifp->if_flags & IFF_RUNNING))
    1492           0 :                                 otus_init(ifp);
    1493             : 
    1494           0 :                 } else if (ifp->if_flags & IFF_RUNNING)
    1495           0 :                         otus_stop(ifp);
    1496             : 
    1497           0 :                 sc->sc_if_flags = ifp->if_flags;
    1498           0 :                 break;
    1499             :         case SIOCS80211CHANNEL:
    1500           0 :                 error = ieee80211_ioctl(ifp, cmd, data);
    1501           0 :                 if (error == ENETRESET &&
    1502           0 :                     ic->ic_opmode == IEEE80211_M_MONITOR) {
    1503           0 :                         if ((ifp->if_flags & (IFF_UP | IFF_RUNNING)) ==
    1504             :                             (IFF_UP | IFF_RUNNING))
    1505           0 :                                 otus_set_chan(sc, ic->ic_ibss_chan, 0);
    1506             :                         error = 0;
    1507           0 :                 }
    1508             :                 break;
    1509             :         default:
    1510           0 :                 error = ieee80211_ioctl(ifp, cmd, data);
    1511           0 :         }
    1512             : 
    1513           0 :         if (error == ENETRESET) {
    1514           0 :                 if ((ifp->if_flags & (IFF_UP | IFF_RUNNING)) ==
    1515             :                     (IFF_UP | IFF_RUNNING))
    1516           0 :                         otus_init(ifp);
    1517             :                 error = 0;
    1518           0 :         }
    1519             : 
    1520           0 :         splx(s);
    1521             : 
    1522           0 :         usbd_ref_decr(sc->sc_udev);
    1523             : 
    1524           0 :         return error;
    1525           0 : }
    1526             : 
    1527             : int
    1528           0 : otus_set_multi(struct otus_softc *sc)
    1529             : {
    1530           0 :         struct arpcom *ac = &sc->sc_ic.ic_ac;
    1531           0 :         struct ifnet *ifp = &ac->ac_if;
    1532             :         struct ether_multi *enm;
    1533             :         struct ether_multistep step;
    1534             :         uint32_t lo, hi;
    1535             :         uint8_t bit;
    1536             : 
    1537           0 :         if (ac->ac_multirangecnt > 0)
    1538           0 :                 ifp->if_flags |= IFF_ALLMULTI;
    1539             : 
    1540           0 :         if ((ifp->if_flags & (IFF_ALLMULTI | IFF_PROMISC)) != 0) {
    1541             :                 lo = hi = 0xffffffff;
    1542           0 :                 goto done;
    1543             :         }
    1544             :         lo = hi = 0;
    1545           0 :         ETHER_FIRST_MULTI(step, ac, enm);
    1546           0 :         while (enm != NULL) {
    1547           0 :                 bit = enm->enm_addrlo[5] >> 2;
    1548           0 :                 if (bit < 32)
    1549           0 :                         lo |= 1 << bit;
    1550             :                 else
    1551           0 :                         hi |= 1 << (bit - 32);
    1552           0 :                 ETHER_NEXT_MULTI(step, enm);
    1553             :         }
    1554             :  done:
    1555           0 :         hi |= 1U << 31;   /* Make sure the broadcast bit is set. */
    1556           0 :         otus_write(sc, AR_MAC_REG_GROUP_HASH_TBL_L, lo);
    1557           0 :         otus_write(sc, AR_MAC_REG_GROUP_HASH_TBL_H, hi);
    1558           0 :         return otus_write_barrier(sc);
    1559             : }
    1560             : 
    1561             : void
    1562           0 : otus_updateedca(struct ieee80211com *ic)
    1563             : {
    1564             :         /* Do it in a process context. */
    1565           0 :         otus_do_async(ic->ic_softc, otus_updateedca_cb, NULL, 0);
    1566           0 : }
    1567             : 
    1568             : /* ARGSUSED */
    1569             : void
    1570           0 : otus_updateedca_cb(struct otus_softc *sc, void *arg)
    1571             : {
    1572             : #define EXP2(val)       ((1 << (val)) - 1)
    1573             : #define AIFS(val)       ((val) * 9 + 10)
    1574           0 :         struct ieee80211com *ic = &sc->sc_ic;
    1575             :         const struct ieee80211_edca_ac_params *edca;
    1576             :         int s;
    1577             : 
    1578           0 :         s = splnet();
    1579             : 
    1580           0 :         edca = (ic->ic_flags & IEEE80211_F_QOS) ?
    1581           0 :             ic->ic_edca_ac : otus_edca_def;
    1582             : 
    1583             :         /* Set CWmin/CWmax values. */
    1584           0 :         otus_write(sc, AR_MAC_REG_AC0_CW,
    1585           0 :             EXP2(edca[EDCA_AC_BE].ac_ecwmax) << 16 |
    1586           0 :             EXP2(edca[EDCA_AC_BE].ac_ecwmin));
    1587           0 :         otus_write(sc, AR_MAC_REG_AC1_CW,
    1588           0 :             EXP2(edca[EDCA_AC_BK].ac_ecwmax) << 16 |
    1589           0 :             EXP2(edca[EDCA_AC_BK].ac_ecwmin));
    1590           0 :         otus_write(sc, AR_MAC_REG_AC2_CW,
    1591           0 :             EXP2(edca[EDCA_AC_VI].ac_ecwmax) << 16 |
    1592           0 :             EXP2(edca[EDCA_AC_VI].ac_ecwmin));
    1593           0 :         otus_write(sc, AR_MAC_REG_AC3_CW,
    1594           0 :             EXP2(edca[EDCA_AC_VO].ac_ecwmax) << 16 |
    1595           0 :             EXP2(edca[EDCA_AC_VO].ac_ecwmin));
    1596           0 :         otus_write(sc, AR_MAC_REG_AC4_CW,               /* Special TXQ. */
    1597           0 :             EXP2(edca[EDCA_AC_VO].ac_ecwmax) << 16 |
    1598           0 :             EXP2(edca[EDCA_AC_VO].ac_ecwmin));
    1599             : 
    1600             :         /* Set AIFSN values. */
    1601           0 :         otus_write(sc, AR_MAC_REG_AC1_AC0_AIFS,
    1602           0 :             AIFS(edca[EDCA_AC_VI].ac_aifsn) << 24 |
    1603           0 :             AIFS(edca[EDCA_AC_BK].ac_aifsn) << 12 |
    1604           0 :             AIFS(edca[EDCA_AC_BE].ac_aifsn));
    1605           0 :         otus_write(sc, AR_MAC_REG_AC3_AC2_AIFS,
    1606           0 :             AIFS(edca[EDCA_AC_VO].ac_aifsn) << 16 |       /* Special TXQ. */
    1607           0 :             AIFS(edca[EDCA_AC_VO].ac_aifsn) <<  4 |
    1608           0 :             AIFS(edca[EDCA_AC_VI].ac_aifsn) >>  8);
    1609             : 
    1610             :         /* Set TXOP limit. */
    1611           0 :         otus_write(sc, AR_MAC_REG_AC1_AC0_TXOP,
    1612           0 :             edca[EDCA_AC_BK].ac_txoplimit << 16 |
    1613           0 :             edca[EDCA_AC_BE].ac_txoplimit);
    1614           0 :         otus_write(sc, AR_MAC_REG_AC3_AC2_TXOP,
    1615           0 :             edca[EDCA_AC_VO].ac_txoplimit << 16 |
    1616           0 :             edca[EDCA_AC_VI].ac_txoplimit);
    1617             : 
    1618           0 :         splx(s);
    1619             : 
    1620           0 :         (void)otus_write_barrier(sc);
    1621             : #undef AIFS
    1622             : #undef EXP2
    1623           0 : }
    1624             : 
    1625             : void
    1626           0 : otus_updateslot(struct ieee80211com *ic)
    1627             : {
    1628             :         /* Do it in a process context. */
    1629           0 :         otus_do_async(ic->ic_softc, otus_updateslot_cb, NULL, 0);
    1630           0 : }
    1631             : 
    1632             : /* ARGSUSED */
    1633             : void
    1634           0 : otus_updateslot_cb(struct otus_softc *sc, void *arg)
    1635             : {
    1636             :         uint32_t slottime;
    1637             : 
    1638           0 :         slottime = (sc->sc_ic.ic_flags & IEEE80211_F_SHSLOT) ?
    1639             :             IEEE80211_DUR_DS_SHSLOT: IEEE80211_DUR_DS_SLOT;
    1640           0 :         otus_write(sc, AR_MAC_REG_SLOT_TIME, slottime << 10);
    1641           0 :         (void)otus_write_barrier(sc);
    1642           0 : }
    1643             : 
    1644             : int
    1645           0 : otus_init_mac(struct otus_softc *sc)
    1646             : {
    1647             :         int error;
    1648             : 
    1649           0 :         otus_write(sc, AR_MAC_REG_ACK_EXTENSION, 0x40);
    1650           0 :         otus_write(sc, AR_MAC_REG_RETRY_MAX, 0);
    1651           0 :         otus_write(sc, AR_MAC_REG_SNIFFER, 0x2000000);
    1652           0 :         otus_write(sc, AR_MAC_REG_RX_THRESHOLD, 0xc1f80);
    1653           0 :         otus_write(sc, AR_MAC_REG_RX_PE_DELAY, 0x70);
    1654           0 :         otus_write(sc, AR_MAC_REG_EIFS_AND_SIFS, 0xa144000);
    1655           0 :         otus_write(sc, AR_MAC_REG_SLOT_TIME, 9 << 10);
    1656           0 :         otus_write(sc, 0x1c3b2c, 0x19000000);
    1657             :         /* NAV protects ACK only (in TXOP). */
    1658           0 :         otus_write(sc, 0x1c3b38, 0x201);
    1659             :         /* Set beacon Tx power to 0x7. */
    1660           0 :         otus_write(sc, AR_MAC_REG_BCN_HT1, 0x8000170);
    1661           0 :         otus_write(sc, AR_MAC_REG_BACKOFF_PROTECT, 0x105);
    1662           0 :         otus_write(sc, 0x1c3b9c, 0x10000a);
    1663             :         /* Filter any control frames, BAR is bit 24. */
    1664           0 :         otus_write(sc, 0x1c368c, 0x0500ffff);
    1665           0 :         otus_write(sc, 0x1c3c40, 0x1);
    1666           0 :         otus_write(sc, AR_MAC_REG_BASIC_RATE, 0x150f);
    1667           0 :         otus_write(sc, AR_MAC_REG_MANDATORY_RATE, 0x150f);
    1668           0 :         otus_write(sc, AR_MAC_REG_RTS_CTS_RATE, 0x10b01bb);
    1669           0 :         otus_write(sc, 0x1c3694, 0x4003c1e);
    1670             :         /* Enable LED0 and LED1. */
    1671           0 :         otus_write(sc, 0x1d0100, 0x3);
    1672           0 :         otus_write(sc, 0x1d0104, 0x3);
    1673             :         /* Switch MAC to OTUS interface. */
    1674           0 :         otus_write(sc, 0x1c3600, 0x3);
    1675           0 :         otus_write(sc, 0x1c3c50, 0xffff);
    1676           0 :         otus_write(sc, 0x1c3680, 0xf00008);
    1677             :         /* Disable Rx timeout (workaround). */
    1678           0 :         otus_write(sc, 0x1c362c, 0);
    1679             : 
    1680             :         /* Set USB Rx stream mode maximum frame number to 2. */
    1681           0 :         otus_write(sc, 0x1e1110, 0x4);
    1682             :         /* Set USB Rx stream mode timeout to 10us. */
    1683           0 :         otus_write(sc, 0x1e1114, 0x80);
    1684             : 
    1685             :         /* Set clock frequency to 88/80MHz. */
    1686           0 :         otus_write(sc, 0x1d4008, 0x73);
    1687             :         /* Set WLAN DMA interrupt mode: generate intr per packet. */
    1688           0 :         otus_write(sc, 0x1c3d7c, 0x110011);
    1689           0 :         otus_write(sc, 0x1c3bb0, 0x4);
    1690           0 :         otus_write(sc, AR_MAC_REG_TXOP_NOT_ENOUGH_INDICATION, 0x141e0f48);
    1691             : 
    1692             :         /* Disable HW decryption for now. */
    1693           0 :         otus_write(sc, 0x1c3678, 0x78);
    1694             : 
    1695           0 :         if ((error = otus_write_barrier(sc)) != 0)
    1696           0 :                 return error;
    1697             : 
    1698             :         /* Set default EDCA parameters. */
    1699           0 :         otus_updateedca_cb(sc, NULL);
    1700             : 
    1701           0 :         return 0;
    1702           0 : }
    1703             : 
    1704             : /*
    1705             :  * Return default value for PHY register based on current operating mode.
    1706             :  */
    1707             : uint32_t
    1708           0 : otus_phy_get_def(struct otus_softc *sc, uint32_t reg)
    1709             : {
    1710             :         int i;
    1711             : 
    1712           0 :         for (i = 0; i < nitems(ar5416_phy_regs); i++)
    1713           0 :                 if (AR_PHY(ar5416_phy_regs[i]) == reg)
    1714           0 :                         return sc->phy_vals[i];
    1715           0 :         return 0;       /* Register not found. */
    1716           0 : }
    1717             : 
    1718             : /*
    1719             :  * Update PHY's programming based on vendor-specific data stored in EEPROM.
    1720             :  * This is for FEM-type devices only.
    1721             :  */
    1722             : int
    1723           0 : otus_set_board_values(struct otus_softc *sc, struct ieee80211_channel *c)
    1724             : {
    1725             :         const struct ModalEepHeader *eep;
    1726             :         uint32_t tmp, offset;
    1727             : 
    1728           0 :         if (IEEE80211_IS_CHAN_5GHZ(c))
    1729           0 :                 eep = &sc->eeprom.modalHeader[0];
    1730             :         else
    1731           0 :                 eep = &sc->eeprom.modalHeader[1];
    1732             : 
    1733             :         /* Offset of chain 2. */
    1734             :         offset = 2 * 0x1000;
    1735             : 
    1736           0 :         tmp = letoh32(eep->antCtrlCommon);
    1737           0 :         otus_write(sc, AR_PHY_SWITCH_COM, tmp);
    1738             : 
    1739           0 :         tmp = letoh32(eep->antCtrlChain[0]);
    1740           0 :         otus_write(sc, AR_PHY_SWITCH_CHAIN_0, tmp);
    1741             : 
    1742           0 :         tmp = letoh32(eep->antCtrlChain[1]);
    1743           0 :         otus_write(sc, AR_PHY_SWITCH_CHAIN_0 + offset, tmp);
    1744             : 
    1745             :         if (1 /* sc->sc_sco == AR_SCO_SCN */) {
    1746           0 :                 tmp = otus_phy_get_def(sc, AR_PHY_SETTLING);
    1747           0 :                 tmp &= ~(0x7f << 7);
    1748           0 :                 tmp |= (eep->switchSettling & 0x7f) << 7;
    1749           0 :                 otus_write(sc, AR_PHY_SETTLING, tmp);
    1750             :         }
    1751             : 
    1752           0 :         tmp = otus_phy_get_def(sc, AR_PHY_DESIRED_SZ);
    1753           0 :         tmp &= ~0xffff;
    1754           0 :         tmp |= eep->pgaDesiredSize << 8 | eep->adcDesiredSize;
    1755           0 :         otus_write(sc, AR_PHY_DESIRED_SZ, tmp);
    1756             : 
    1757           0 :         tmp = eep->txEndToXpaOff << 24 | eep->txEndToXpaOff << 16 |
    1758           0 :               eep->txFrameToXpaOn << 8 | eep->txFrameToXpaOn;
    1759           0 :         otus_write(sc, AR_PHY_RF_CTL4, tmp);
    1760             : 
    1761           0 :         tmp = otus_phy_get_def(sc, AR_PHY_RF_CTL3);
    1762           0 :         tmp &= ~(0xff << 16);
    1763           0 :         tmp |= eep->txEndToRxOn << 16;
    1764           0 :         otus_write(sc, AR_PHY_RF_CTL3, tmp);
    1765             : 
    1766           0 :         tmp = otus_phy_get_def(sc, AR_PHY_CCA);
    1767           0 :         tmp &= ~(0x7f << 12);
    1768           0 :         tmp |= (eep->thresh62 & 0x7f) << 12;
    1769           0 :         otus_write(sc, AR_PHY_CCA, tmp);
    1770             : 
    1771           0 :         tmp = otus_phy_get_def(sc, AR_PHY_RXGAIN);
    1772           0 :         tmp &= ~(0x3f << 12);
    1773           0 :         tmp |= (eep->txRxAttenCh[0] & 0x3f) << 12;
    1774           0 :         otus_write(sc, AR_PHY_RXGAIN, tmp);
    1775             : 
    1776           0 :         tmp = otus_phy_get_def(sc, AR_PHY_RXGAIN + offset);
    1777           0 :         tmp &= ~(0x3f << 12);
    1778           0 :         tmp |= (eep->txRxAttenCh[1] & 0x3f) << 12;
    1779           0 :         otus_write(sc, AR_PHY_RXGAIN + offset, tmp);
    1780             : 
    1781           0 :         tmp = otus_phy_get_def(sc, AR_PHY_GAIN_2GHZ);
    1782           0 :         tmp &= ~(0x3f << 18);
    1783           0 :         tmp |= (eep->rxTxMarginCh[0] & 0x3f) << 18;
    1784           0 :         if (IEEE80211_IS_CHAN_5GHZ(c)) {
    1785           0 :                 tmp &= ~(0xf << 10);
    1786           0 :                 tmp |= (eep->bswMargin[0] & 0xf) << 10;
    1787           0 :         }
    1788           0 :         otus_write(sc, AR_PHY_GAIN_2GHZ, tmp);
    1789             : 
    1790           0 :         tmp = otus_phy_get_def(sc, AR_PHY_GAIN_2GHZ + offset);
    1791           0 :         tmp &= ~(0x3f << 18);
    1792           0 :         tmp |= (eep->rxTxMarginCh[1] & 0x3f) << 18;
    1793           0 :         otus_write(sc, AR_PHY_GAIN_2GHZ + offset, tmp);
    1794             : 
    1795           0 :         tmp = otus_phy_get_def(sc, AR_PHY_TIMING_CTRL4);
    1796           0 :         tmp &= ~(0x3f << 5 | 0x1f);
    1797           0 :         tmp |= (eep->iqCalICh[0] & 0x3f) << 5 | (eep->iqCalQCh[0] & 0x1f);
    1798           0 :         otus_write(sc, AR_PHY_TIMING_CTRL4, tmp);
    1799             : 
    1800           0 :         tmp = otus_phy_get_def(sc, AR_PHY_TIMING_CTRL4 + offset);
    1801           0 :         tmp &= ~(0x3f << 5 | 0x1f);
    1802           0 :         tmp |= (eep->iqCalICh[1] & 0x3f) << 5 | (eep->iqCalQCh[1] & 0x1f);
    1803           0 :         otus_write(sc, AR_PHY_TIMING_CTRL4 + offset, tmp);
    1804             : 
    1805           0 :         tmp = otus_phy_get_def(sc, AR_PHY_TPCRG1);
    1806           0 :         tmp &= ~(0xf << 16);
    1807           0 :         tmp |= (eep->xpd & 0xf) << 16;
    1808           0 :         otus_write(sc, AR_PHY_TPCRG1, tmp);
    1809             : 
    1810           0 :         return otus_write_barrier(sc);
    1811             : }
    1812             : 
    1813             : int
    1814           0 : otus_program_phy(struct otus_softc *sc, struct ieee80211_channel *c)
    1815             : {
    1816             :         const uint32_t *vals;
    1817             :         int error, i;
    1818             : 
    1819             :         /* Select PHY programming based on band and bandwidth. */
    1820           0 :         if (IEEE80211_IS_CHAN_2GHZ(c))
    1821           0 :                 vals = ar5416_phy_vals_2ghz_20mhz;
    1822             :         else
    1823             :                 vals = ar5416_phy_vals_5ghz_20mhz;
    1824           0 :         for (i = 0; i < nitems(ar5416_phy_regs); i++)
    1825           0 :                 otus_write(sc, AR_PHY(ar5416_phy_regs[i]), vals[i]);
    1826           0 :         sc->phy_vals = vals;
    1827             : 
    1828           0 :         if (sc->eeprom.baseEepHeader.deviceType == 0x80)     /* FEM */
    1829           0 :                 if ((error = otus_set_board_values(sc, c)) != 0)
    1830           0 :                         return error;
    1831             : 
    1832             :         /* Initial Tx power settings. */
    1833           0 :         otus_write(sc, AR_PHY_POWER_TX_RATE_MAX, 0x7f);
    1834           0 :         otus_write(sc, AR_PHY_POWER_TX_RATE1, 0x3f3f3f3f);
    1835           0 :         otus_write(sc, AR_PHY_POWER_TX_RATE2, 0x3f3f3f3f);
    1836           0 :         otus_write(sc, AR_PHY_POWER_TX_RATE3, 0x3f3f3f3f);
    1837           0 :         otus_write(sc, AR_PHY_POWER_TX_RATE4, 0x3f3f3f3f);
    1838           0 :         otus_write(sc, AR_PHY_POWER_TX_RATE5, 0x3f3f3f3f);
    1839           0 :         otus_write(sc, AR_PHY_POWER_TX_RATE6, 0x3f3f3f3f);
    1840           0 :         otus_write(sc, AR_PHY_POWER_TX_RATE7, 0x3f3f3f3f);
    1841           0 :         otus_write(sc, AR_PHY_POWER_TX_RATE8, 0x3f3f3f3f);
    1842           0 :         otus_write(sc, AR_PHY_POWER_TX_RATE9, 0x3f3f3f3f);
    1843             : 
    1844           0 :         if (IEEE80211_IS_CHAN_2GHZ(c))
    1845           0 :                 otus_write(sc, 0x1d4014, 0x5163);
    1846             :         else
    1847           0 :                 otus_write(sc, 0x1d4014, 0x5143);
    1848             : 
    1849           0 :         return otus_write_barrier(sc);
    1850           0 : }
    1851             : 
    1852             : static __inline uint8_t
    1853           0 : otus_reverse_bits(uint8_t v)
    1854             : {
    1855           0 :         v = ((v >> 1) & 0x55) | ((v & 0x55) << 1);
    1856           0 :         v = ((v >> 2) & 0x33) | ((v & 0x33) << 2);
    1857           0 :         v = ((v >> 4) & 0x0f) | ((v & 0x0f) << 4);
    1858           0 :         return v;
    1859             : }
    1860             : 
    1861             : int
    1862           0 : otus_set_rf_bank4(struct otus_softc *sc, struct ieee80211_channel *c)
    1863             : {
    1864             :         uint8_t chansel, d0, d1;
    1865             :         uint16_t data;
    1866             :         int error;
    1867             : 
    1868             :         d0 = 0;
    1869           0 :         if (IEEE80211_IS_CHAN_5GHZ(c)) {
    1870           0 :                 chansel = (c->ic_freq - 4800) / 5;
    1871           0 :                 if (chansel & 1)
    1872           0 :                         d0 |= AR_BANK4_AMODE_REFSEL(2);
    1873             :                 else
    1874             :                         d0 |= AR_BANK4_AMODE_REFSEL(1);
    1875             :         } else {
    1876             :                 d0 |= AR_BANK4_AMODE_REFSEL(2);
    1877           0 :                 if (c->ic_freq == 2484) {    /* CH 14 */
    1878             :                         d0 |= AR_BANK4_BMODE_LF_SYNTH_FREQ;
    1879           0 :                         chansel = 10 + (c->ic_freq - 2274) / 5;
    1880           0 :                 } else
    1881           0 :                         chansel = 16 + (c->ic_freq - 2272) / 5;
    1882           0 :                 chansel <<= 2;
    1883             :         }
    1884           0 :         d0 |= AR_BANK4_ADDR(1) | AR_BANK4_CHUP;
    1885           0 :         d1 = otus_reverse_bits(chansel);
    1886             : 
    1887             :         /* Write bits 0-4 of d0 and d1. */
    1888           0 :         data = (d1 & 0x1f) << 5 | (d0 & 0x1f);
    1889           0 :         otus_write(sc, AR_PHY(44), data);
    1890             :         /* Write bits 5-7 of d0 and d1. */
    1891           0 :         data = (d1 >> 5) << 5 | (d0 >> 5);
    1892           0 :         otus_write(sc, AR_PHY(58), data);
    1893             : 
    1894           0 :         if ((error = otus_write_barrier(sc)) == 0)
    1895           0 :                 usbd_delay_ms(sc->sc_udev, 10);
    1896           0 :         return error;
    1897             : }
    1898             : 
    1899             : void
    1900           0 : otus_get_delta_slope(uint32_t coeff, uint32_t *exponent, uint32_t *mantissa)
    1901             : {
    1902             : #define COEFF_SCALE_SHIFT       24
    1903             :         uint32_t exp, man;
    1904             : 
    1905             :         /* exponent = 14 - floor(log2(coeff)) */
    1906           0 :         for (exp = 31; exp > 0; exp--)
    1907           0 :                 if (coeff & (1 << exp))
    1908             :                         break;
    1909           0 :         KASSERT(exp != 0);
    1910           0 :         exp = 14 - (exp - COEFF_SCALE_SHIFT);
    1911             : 
    1912             :         /* mantissa = floor(coeff * 2^exponent + 0.5) */
    1913           0 :         man = coeff + (1 << (COEFF_SCALE_SHIFT - exp - 1));
    1914             : 
    1915           0 :         *mantissa = man >> (COEFF_SCALE_SHIFT - exp);
    1916           0 :         *exponent = exp - 16;
    1917             : #undef COEFF_SCALE_SHIFT
    1918           0 : }
    1919             : 
    1920             : int
    1921           0 : otus_set_chan(struct otus_softc *sc, struct ieee80211_channel *c, int assoc)
    1922             : {
    1923           0 :         struct ieee80211com *ic = &sc->sc_ic;
    1924           0 :         struct ar_cmd_frequency cmd;
    1925           0 :         struct ar_rsp_frequency rsp;
    1926             :         const uint32_t *vals;
    1927           0 :         uint32_t coeff, exp, man, tmp;
    1928             :         uint8_t code;
    1929             :         int error, chan, i;
    1930             : 
    1931           0 :         chan = ieee80211_chan2ieee(ic, c);
    1932             :         DPRINTF(("setting channel %d (%dMHz)\n", chan, c->ic_freq));
    1933             : 
    1934           0 :         tmp = IEEE80211_IS_CHAN_2GHZ(c) ? 0x105 : 0x104;
    1935           0 :         otus_write(sc, AR_MAC_REG_DYNAMIC_SIFS_ACK, tmp);
    1936           0 :         if ((error = otus_write_barrier(sc)) != 0)
    1937           0 :                 return error;
    1938             : 
    1939             :         /* Disable BB Heavy Clip. */
    1940           0 :         otus_write(sc, AR_PHY_HEAVY_CLIP_ENABLE, 0x200);
    1941           0 :         if ((error = otus_write_barrier(sc)) != 0)
    1942           0 :                 return error;
    1943             : 
    1944             :         /* XXX Is that FREQ_START ? */
    1945           0 :         error = otus_cmd(sc, AR_CMD_FREQ_STRAT, NULL, 0, NULL);
    1946           0 :         if (error != 0)
    1947           0 :                 return error;
    1948             : 
    1949             :         /* Reprogram PHY and RF on channel band or bandwidth changes. */
    1950           0 :         if (sc->bb_reset || c->ic_flags != sc->sc_curchan->ic_flags) {
    1951             :                 DPRINTF(("band switch\n"));
    1952             : 
    1953             :                 /* Cold/Warm reset BB/ADDA. */
    1954           0 :                 otus_write(sc, 0x1d4004, sc->bb_reset ? 0x800 : 0x400);
    1955           0 :                 if ((error = otus_write_barrier(sc)) != 0)
    1956           0 :                         return error;
    1957           0 :                 otus_write(sc, 0x1d4004, 0);
    1958           0 :                 if ((error = otus_write_barrier(sc)) != 0)
    1959           0 :                         return error;
    1960           0 :                 sc->bb_reset = 0;
    1961             : 
    1962           0 :                 if ((error = otus_program_phy(sc, c)) != 0) {
    1963           0 :                         printf("%s: could not program PHY\n",
    1964           0 :                             sc->sc_dev.dv_xname);
    1965           0 :                         return error;
    1966             :                 }
    1967             : 
    1968             :                 /* Select RF programming based on band. */
    1969           0 :                 if (IEEE80211_IS_CHAN_5GHZ(c))
    1970           0 :                         vals = ar5416_banks_vals_5ghz;
    1971             :                 else
    1972             :                         vals = ar5416_banks_vals_2ghz;
    1973           0 :                 for (i = 0; i < nitems(ar5416_banks_regs); i++)
    1974           0 :                         otus_write(sc, AR_PHY(ar5416_banks_regs[i]), vals[i]);
    1975           0 :                 if ((error = otus_write_barrier(sc)) != 0) {
    1976           0 :                         printf("%s: could not program RF\n",
    1977           0 :                             sc->sc_dev.dv_xname);
    1978           0 :                         return error;
    1979             :                 }
    1980             :                 code = AR_CMD_RF_INIT;
    1981           0 :         } else {
    1982             :                 code = AR_CMD_FREQUENCY;
    1983             :         }
    1984             : 
    1985           0 :         if ((error = otus_set_rf_bank4(sc, c)) != 0)
    1986           0 :                 return error;
    1987             : 
    1988           0 :         tmp = (sc->txmask == 0x5) ? 0x340 : 0x240;
    1989           0 :         otus_write(sc, AR_PHY_TURBO, tmp);
    1990           0 :         if ((error = otus_write_barrier(sc)) != 0)
    1991           0 :                 return error;
    1992             : 
    1993             :         /* Send firmware command to set channel. */
    1994           0 :         cmd.freq = htole32((uint32_t)c->ic_freq * 1000);
    1995           0 :         cmd.dynht2040 = htole32(0);
    1996           0 :         cmd.htena = htole32(1);
    1997             :         /* Set Delta Slope (exponent and mantissa). */
    1998           0 :         coeff = (100 << 24) / c->ic_freq;
    1999           0 :         otus_get_delta_slope(coeff, &exp, &man);
    2000           0 :         cmd.dsc_exp = htole32(exp);
    2001           0 :         cmd.dsc_man = htole32(man);
    2002             :         DPRINTF(("ds coeff=%u exp=%u man=%u\n", coeff, exp, man));
    2003             :         /* For Short GI, coeff is 9/10 that of normal coeff. */
    2004           0 :         coeff = (9 * coeff) / 10;
    2005           0 :         otus_get_delta_slope(coeff, &exp, &man);
    2006           0 :         cmd.dsc_shgi_exp = htole32(exp);
    2007           0 :         cmd.dsc_shgi_man = htole32(man);
    2008             :         DPRINTF(("ds shgi coeff=%u exp=%u man=%u\n", coeff, exp, man));
    2009             :         /* Set wait time for AGC and noise calibration (100 or 200ms). */
    2010           0 :         cmd.check_loop_count = assoc ? htole32(2000) : htole32(1000);
    2011             :         DPRINTF(("%s\n", (code == AR_CMD_RF_INIT) ? "RF_INIT" : "FREQUENCY"));
    2012           0 :         error = otus_cmd(sc, code, &cmd, sizeof cmd, &rsp);
    2013           0 :         if (error != 0)
    2014           0 :                 return error;
    2015           0 :         if ((rsp.status & htole32(AR_CAL_ERR_AGC | AR_CAL_ERR_NF_VAL)) != 0) {
    2016             :                 DPRINTF(("status=0x%x\n", letoh32(rsp.status)));
    2017             :                 /* Force cold reset on next channel. */
    2018           0 :                 sc->bb_reset = 1;
    2019           0 :         }
    2020             : #ifdef OTUS_DEBUG
    2021             :         if (otus_debug) {
    2022             :                 printf("calibration status=0x%x\n", letoh32(rsp.status));
    2023             :                 for (i = 0; i < 2; i++) {    /* 2 Rx chains */
    2024             :                         /* Sign-extend 9-bit NF values. */
    2025             :                         printf("noisefloor chain %d=%d\n", i,
    2026             :                             (((int32_t)letoh32(rsp.nf[i])) << 4) >> 23);
    2027             :                         printf("noisefloor ext chain %d=%d\n", i,
    2028             :                             ((int32_t)letoh32(rsp.nf_ext[i])) >> 23);
    2029             :                 }
    2030             :         }
    2031             : #endif
    2032           0 :         sc->sc_curchan = c;
    2033           0 :         return 0;
    2034           0 : }
    2035             : 
    2036             : #ifdef notyet
    2037             : int
    2038             : otus_set_key(struct ieee80211com *ic, struct ieee80211_node *ni,
    2039             :     struct ieee80211_key *k)
    2040             : {
    2041             :         struct otus_softc *sc = ic->ic_softc;
    2042             :         struct otus_cmd_key cmd;
    2043             : 
    2044             :         /* Defer setting of WEP keys until interface is brought up. */
    2045             :         if ((ic->ic_if.if_flags & (IFF_UP | IFF_RUNNING)) !=
    2046             :             (IFF_UP | IFF_RUNNING))
    2047             :                 return 0;
    2048             : 
    2049             :         /* Do it in a process context. */
    2050             :         cmd.key = *k;
    2051             :         cmd.associd = (ni != NULL) ? ni->ni_associd : 0;
    2052             :         otus_do_async(sc, otus_set_key_cb, &cmd, sizeof cmd);
    2053             :         return 0;
    2054             : }
    2055             : 
    2056             : void
    2057             : otus_set_key_cb(struct otus_softc *sc, void *arg)
    2058             : {
    2059             :         struct otus_cmd_key *cmd = arg;
    2060             :         struct ieee80211_key *k = &cmd->key;
    2061             :         struct ar_cmd_ekey key;
    2062             :         uint16_t cipher;
    2063             :         int error;
    2064             : 
    2065             :         memset(&key, 0, sizeof key);
    2066             :         if (k->k_flags & IEEE80211_KEY_GROUP) {
    2067             :                 key.uid = htole16(k->k_id);
    2068             :                 IEEE80211_ADDR_COPY(key.macaddr, sc->sc_ic.ic_myaddr);
    2069             :                 key.macaddr[0] |= 0x80;
    2070             :         } else {
    2071             :                 key.uid = htole16(OTUS_UID(cmd->associd));
    2072             :                 IEEE80211_ADDR_COPY(key.macaddr, ni->ni_macaddr);
    2073             :         }
    2074             :         key.kix = htole16(0);
    2075             :         /* Map net80211 cipher to hardware. */
    2076             :         switch (k->k_cipher) {
    2077             :         case IEEE80211_CIPHER_WEP40:
    2078             :                 cipher = AR_CIPHER_WEP64;
    2079             :                 break;
    2080             :         case IEEE80211_CIPHER_WEP104:
    2081             :                 cipher = AR_CIPHER_WEP128;
    2082             :                 break;
    2083             :         case IEEE80211_CIPHER_TKIP:
    2084             :                 cipher = AR_CIPHER_TKIP;
    2085             :                 break;
    2086             :         case IEEE80211_CIPHER_CCMP:
    2087             :                 cipher = AR_CIPHER_AES;
    2088             :                 break;
    2089             :         default:
    2090             :                 return;
    2091             :         }
    2092             :         key.cipher = htole16(cipher);
    2093             :         memcpy(key.key, k->k_key, MIN(k->k_len, 16));
    2094             :         error = otus_cmd(sc, AR_CMD_EKEY, &key, sizeof key, NULL);
    2095             :         if (error != 0 || k->k_cipher != IEEE80211_CIPHER_TKIP)
    2096             :                 return;
    2097             : 
    2098             :         /* TKIP: set Tx/Rx MIC Key. */
    2099             :         key.kix = htole16(1);
    2100             :         memcpy(key.key, k->k_key + 16, 16);
    2101             :         (void)otus_cmd(sc, AR_CMD_EKEY, &key, sizeof key, NULL);
    2102             : }
    2103             : 
    2104             : void
    2105             : otus_delete_key(struct ieee80211com *ic, struct ieee80211_node *ni,
    2106             :     struct ieee80211_key *k)
    2107             : {
    2108             :         struct otus_softc *sc = ic->ic_softc;
    2109             :         struct otus_cmd_key cmd;
    2110             : 
    2111             :         if (!(ic->ic_if.if_flags & IFF_RUNNING) ||
    2112             :             ic->ic_state != IEEE80211_S_RUN)
    2113             :                 return; /* Nothing to do. */
    2114             : 
    2115             :         /* Do it in a process context. */
    2116             :         cmd.key = *k;
    2117             :         cmd.associd = (ni != NULL) ? ni->ni_associd : 0;
    2118             :         otus_do_async(sc, otus_delete_key_cb, &cmd, sizeof cmd);
    2119             : }
    2120             : 
    2121             : void
    2122             : otus_delete_key_cb(struct otus_softc *sc, void *arg)
    2123             : {
    2124             :         struct otus_cmd_key *cmd = arg;
    2125             :         struct ieee80211_key *k = &cmd->key;
    2126             :         uint32_t uid;
    2127             : 
    2128             :         if (k->k_flags & IEEE80211_KEY_GROUP)
    2129             :                 uid = htole32(k->k_id);
    2130             :         else
    2131             :                 uid = htole32(OTUS_UID(cmd->associd));
    2132             :         (void)otus_cmd(sc, AR_CMD_DKEY, &uid, sizeof uid, NULL);
    2133             : }
    2134             : #endif
    2135             : 
    2136             : void
    2137           0 : otus_calibrate_to(void *arg)
    2138             : {
    2139           0 :         struct otus_softc *sc = arg;
    2140           0 :         struct ieee80211com *ic = &sc->sc_ic;
    2141             :         struct ieee80211_node *ni;
    2142             :         int s;
    2143             : 
    2144           0 :         if (usbd_is_dying(sc->sc_udev))
    2145           0 :                 return;
    2146             : 
    2147           0 :         usbd_ref_incr(sc->sc_udev);
    2148             : 
    2149           0 :         s = splnet();
    2150           0 :         ni = ic->ic_bss;
    2151           0 :         ieee80211_amrr_choose(&sc->amrr, ni, &((struct otus_node *)ni)->amn);
    2152           0 :         splx(s);
    2153             : 
    2154           0 :         if (!usbd_is_dying(sc->sc_udev))
    2155           0 :                 timeout_add_sec(&sc->calib_to, 1);
    2156             : 
    2157           0 :         usbd_ref_decr(sc->sc_udev);
    2158           0 : }
    2159             : 
    2160             : int
    2161           0 : otus_set_bssid(struct otus_softc *sc, const uint8_t *bssid)
    2162             : {
    2163           0 :         otus_write(sc, AR_MAC_REG_BSSID_L,
    2164           0 :             bssid[0] | bssid[1] << 8 | bssid[2] << 16 | bssid[3] << 24);
    2165           0 :         otus_write(sc, AR_MAC_REG_BSSID_H,
    2166           0 :             bssid[4] | bssid[5] << 8);
    2167           0 :         return otus_write_barrier(sc);
    2168             : }
    2169             : 
    2170             : int
    2171           0 : otus_set_macaddr(struct otus_softc *sc, const uint8_t *addr)
    2172             : {
    2173           0 :         otus_write(sc, AR_MAC_REG_MAC_ADDR_L,
    2174           0 :             addr[0] | addr[1] << 8 | addr[2] << 16 | addr[3] << 24);
    2175           0 :         otus_write(sc, AR_MAC_REG_MAC_ADDR_H,
    2176           0 :             addr[4] | addr[5] << 8);
    2177           0 :         return otus_write_barrier(sc);
    2178             : }
    2179             : 
    2180             : /* Default single-LED. */
    2181             : void
    2182           0 : otus_led_newstate_type1(struct otus_softc *sc)
    2183             : {
    2184             :         /* TBD */
    2185           0 : }
    2186             : 
    2187             : /* NETGEAR, dual-LED. */
    2188             : void
    2189           0 : otus_led_newstate_type2(struct otus_softc *sc)
    2190             : {
    2191             :         /* TBD */
    2192           0 : }
    2193             : 
    2194             : /* NETGEAR, single-LED/3 colors (blue, red, purple.) */
    2195             : void
    2196           0 : otus_led_newstate_type3(struct otus_softc *sc)
    2197             : {
    2198           0 :         struct ieee80211com *ic = &sc->sc_ic;
    2199           0 :         uint32_t state = sc->led_state;
    2200             : 
    2201           0 :         if (ic->ic_state == IEEE80211_S_INIT) {
    2202             :                 state = 0;      /* LED off. */
    2203           0 :         } else if (ic->ic_state == IEEE80211_S_RUN) {
    2204             :                 /* Associated, LED always on. */
    2205           0 :                 if (IEEE80211_IS_CHAN_2GHZ(sc->sc_curchan))
    2206           0 :                         state = AR_LED0_ON;     /* 2GHz=>Red. */
    2207             :                 else
    2208             :                         state = AR_LED1_ON;     /* 5GHz=>Blue. */
    2209             :         } else {
    2210             :                 /* Scanning, blink LED. */
    2211           0 :                 state ^= AR_LED0_ON | AR_LED1_ON;
    2212           0 :                 if (IEEE80211_IS_CHAN_2GHZ(sc->sc_curchan))
    2213           0 :                         state &= ~AR_LED1_ON;
    2214             :                 else
    2215           0 :                         state &= ~AR_LED0_ON;
    2216             :         }
    2217           0 :         if (state != sc->led_state) {
    2218           0 :                 otus_write(sc, 0x1d0104, state);
    2219           0 :                 if (otus_write_barrier(sc) == 0)
    2220           0 :                         sc->led_state = state;
    2221             :         }
    2222           0 : }
    2223             : 
    2224             : int
    2225           0 : otus_init(struct ifnet *ifp)
    2226             : {
    2227           0 :         struct otus_softc *sc = ifp->if_softc;
    2228           0 :         struct ieee80211com *ic = &sc->sc_ic;
    2229             :         int error;
    2230             : 
    2231             :         /* Init host command ring. */
    2232           0 :         sc->cmdq.cur = sc->cmdq.next = sc->cmdq.queued = 0;
    2233             : 
    2234           0 :         if ((error = otus_init_mac(sc)) != 0) {
    2235           0 :                 printf("%s: could not initialize MAC\n", sc->sc_dev.dv_xname);
    2236           0 :                 return error;
    2237             :         }
    2238             : 
    2239           0 :         IEEE80211_ADDR_COPY(ic->ic_myaddr, LLADDR(ifp->if_sadl));
    2240           0 :         (void)otus_set_macaddr(sc, ic->ic_myaddr);
    2241             : 
    2242           0 :         switch (ic->ic_opmode) {
    2243             : #ifdef notyet
    2244             : #ifndef IEEE80211_STA_ONLY
    2245             :         case IEEE80211_M_HOSTAP:
    2246             :                 otus_write(sc, 0x1c3700, 0x0f0000a1);
    2247             :                 otus_write(sc, 0x1c3c40, 0x1);
    2248             :                 break;
    2249             :         case IEEE80211_M_IBSS:
    2250             :                 otus_write(sc, 0x1c3700, 0x0f000000);
    2251             :                 otus_write(sc, 0x1c3c40, 0x1);
    2252             :                 break;
    2253             : #endif
    2254             : #endif
    2255             :         case IEEE80211_M_STA:
    2256           0 :                 otus_write(sc, 0x1c3700, 0x0f000002);
    2257           0 :                 otus_write(sc, 0x1c3c40, 0x1);
    2258           0 :                 break;
    2259             :         default:
    2260             :                 break;
    2261             :         }
    2262           0 :         otus_write(sc, AR_MAC_REG_SNIFFER,
    2263           0 :             (ic->ic_opmode == IEEE80211_M_MONITOR) ? 0x2000001 : 0x2000000);
    2264           0 :         (void)otus_write_barrier(sc);
    2265             : 
    2266           0 :         sc->bb_reset = 1;    /* Force cold reset. */
    2267           0 :         ic->ic_bss->ni_chan = ic->ic_ibss_chan;
    2268           0 :         if ((error = otus_set_chan(sc, ic->ic_ibss_chan, 0)) != 0) {
    2269           0 :                 printf("%s: could not set channel\n", sc->sc_dev.dv_xname);
    2270           0 :                 return error;
    2271             :         }
    2272             : 
    2273             :         /* Start Rx. */
    2274           0 :         otus_write(sc, 0x1c3d30, 0x100);
    2275           0 :         (void)otus_write_barrier(sc);
    2276             : 
    2277           0 :         ifp->if_flags |= IFF_RUNNING;
    2278           0 :         ifq_clr_oactive(&ifp->if_snd);
    2279             : 
    2280           0 :         if (ic->ic_opmode == IEEE80211_M_MONITOR)
    2281           0 :                 ieee80211_new_state(ic, IEEE80211_S_RUN, -1);
    2282             :         else
    2283           0 :                 ieee80211_new_state(ic, IEEE80211_S_SCAN, -1);
    2284             : 
    2285           0 :         return 0;
    2286           0 : }
    2287             : 
    2288             : void
    2289           0 : otus_stop(struct ifnet *ifp)
    2290             : {
    2291           0 :         struct otus_softc *sc = ifp->if_softc;
    2292           0 :         struct ieee80211com *ic = &sc->sc_ic;
    2293             :         int s;
    2294             : 
    2295           0 :         sc->sc_tx_timer = 0;
    2296           0 :         ifp->if_timer = 0;
    2297           0 :         ifp->if_flags &= ~IFF_RUNNING;
    2298           0 :         ifq_clr_oactive(&ifp->if_snd);
    2299             : 
    2300           0 :         timeout_del(&sc->scan_to);
    2301           0 :         timeout_del(&sc->calib_to);
    2302             : 
    2303           0 :         s = splusb();
    2304           0 :         ieee80211_new_state(ic, IEEE80211_S_INIT, -1);
    2305             :         /* Wait for all queued asynchronous commands to complete. */
    2306           0 :         usb_wait_task(sc->sc_udev, &sc->sc_task);
    2307           0 :         splx(s);
    2308             : 
    2309             :         /* Stop Rx. */
    2310           0 :         otus_write(sc, 0x1c3d30, 0);
    2311           0 :         (void)otus_write_barrier(sc);
    2312             : 
    2313           0 :         sc->tx_queued = 0;
    2314           0 : }

Generated by: LCOV version 1.13