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

          Line data    Source code
       1             : /*      $OpenBSD: if_uath.c,v 1.82 2017/10/26 15:00:28 mpi Exp $        */
       2             : 
       3             : /*-
       4             :  * Copyright (c) 2006
       5             :  *      Damien Bergamini <damien.bergamini@free.fr>
       6             :  *
       7             :  * Permission to use, copy, modify, and distribute this software for any
       8             :  * purpose with or without fee is hereby granted, provided that the above
       9             :  * copyright notice and this permission notice appear in all copies.
      10             :  *
      11             :  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
      12             :  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
      13             :  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
      14             :  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
      15             :  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
      16             :  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
      17             :  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
      18             :  */
      19             : 
      20             : /*-
      21             :  * Driver for Atheros AR5005UG/AR5005UX chipsets.
      22             :  *
      23             :  * IMPORTANT NOTICE:
      24             :  * This driver was written without any documentation or support from Atheros
      25             :  * Communications. It is based on a black-box analysis of the Windows binary
      26             :  * driver. It handles both pre and post-firmware devices.
      27             :  */
      28             : 
      29             : #include "bpfilter.h"
      30             : 
      31             : #include <sys/param.h>
      32             : #include <sys/sockio.h>
      33             : #include <sys/mbuf.h>
      34             : #include <sys/kernel.h>
      35             : #include <sys/socket.h>
      36             : #include <sys/systm.h>
      37             : #include <sys/timeout.h>
      38             : #include <sys/conf.h>
      39             : #include <sys/device.h>
      40             : #include <sys/endian.h>
      41             : 
      42             : #include <machine/bus.h>
      43             : #include <machine/intr.h>
      44             : 
      45             : #if NBPFILTER > 0
      46             : #include <net/bpf.h>
      47             : #endif
      48             : #include <net/if.h>
      49             : #include <net/if_dl.h>
      50             : #include <net/if_media.h>
      51             : 
      52             : #include <netinet/in.h>
      53             : #include <netinet/if_ether.h>
      54             : 
      55             : #include <net80211/ieee80211_var.h>
      56             : #include <net80211/ieee80211_radiotap.h>
      57             : 
      58             : #include <dev/usb/usb.h>
      59             : #include <dev/usb/usbdi.h>
      60             : #include <dev/usb/usbdivar.h>     /* needs_reattach() */
      61             : #include <dev/usb/usbdi_util.h>
      62             : #include <dev/usb/usbdevs.h>
      63             : 
      64             : #include <dev/usb/if_uathreg.h>
      65             : #include <dev/usb/if_uathvar.h>
      66             : 
      67             : #ifdef UATH_DEBUG
      68             : #define DPRINTF(x)      do { if (uath_debug) printf x; } while (0)
      69             : #define DPRINTFN(n, x)  do { if (uath_debug >= (n)) printf x; } while (0)
      70             : int uath_debug = 1;
      71             : #else
      72             : #define DPRINTF(x)
      73             : #define DPRINTFN(n, x)
      74             : #endif
      75             : 
      76             : /*-
      77             :  * Various supported device vendors/products.
      78             :  * UB51: AR5005UG 802.11b/g, UB52: AR5005UX 802.11a/b/g
      79             :  */
      80             : #define UATH_DEV(v, p, f)                                               \
      81             :         { { USB_VENDOR_##v, USB_PRODUCT_##v##_##p }, (f) },             \
      82             :         { { USB_VENDOR_##v, USB_PRODUCT_##v##_##p##_NF },               \
      83             :             (f) | UATH_FLAG_PRE_FIRMWARE }
      84             : #define UATH_DEV_UG(v, p)       UATH_DEV(v, p, 0)
      85             : #define UATH_DEV_UX(v, p)       UATH_DEV(v, p, UATH_FLAG_ABG)
      86             : static const struct uath_type {
      87             :         struct usb_devno        dev;
      88             :         unsigned int            flags;
      89             : #define UATH_FLAG_PRE_FIRMWARE  (1 << 0)
      90             : #define UATH_FLAG_ABG           (1 << 1)
      91             : } uath_devs[] = {
      92             :         UATH_DEV_UG(ACCTON,             SMCWUSBTG2),
      93             :         UATH_DEV_UG(ATHEROS,            AR5523),
      94             :         UATH_DEV_UG(ATHEROS2,           AR5523_1),
      95             :         UATH_DEV_UG(ATHEROS2,           AR5523_2),
      96             :         UATH_DEV_UX(ATHEROS2,           AR5523_3),
      97             :         UATH_DEV_UG(CONCEPTRONIC,       AR5523_1),
      98             :         UATH_DEV_UX(CONCEPTRONIC,       AR5523_2),
      99             :         UATH_DEV_UX(DLINK,              DWLAG122),
     100             :         UATH_DEV_UX(DLINK,              DWLAG132),      
     101             :         UATH_DEV_UG(DLINK,              DWLG132),
     102             :         UATH_DEV_UG(DLINK2,             WUA2340),
     103             :         UATH_DEV_UG(GIGASET,            AR5523),
     104             :         UATH_DEV_UG(GIGASET,            SMCWUSBTG),
     105             :         UATH_DEV_UG(GLOBALSUN,          AR5523_1),
     106             :         UATH_DEV_UX(GLOBALSUN,          AR5523_2),
     107             :         UATH_DEV_UG(IODATA,             USBWNG54US),
     108             :         UATH_DEV_UG(MELCO,              WLIU2KAMG54),
     109             :         UATH_DEV_UX(NETGEAR,            WG111U),
     110             :         UATH_DEV_UG(NETGEAR3,           WG111T),
     111             :         UATH_DEV_UG(NETGEAR3,           WPN111),
     112             :         UATH_DEV_UG(PHILIPS,            SNU6500),
     113             :         UATH_DEV_UX(UMEDIA,             AR5523_2),
     114             :         UATH_DEV_UG(UMEDIA,             TEW444UBEU),
     115             :         UATH_DEV_UG(WISTRONNEWEB,       AR5523_1),
     116             :         UATH_DEV_UX(WISTRONNEWEB,       AR5523_2),
     117             :         UATH_DEV_UG(ZCOM,               AR5523),
     118             : 
     119             :         /* Devices that share one of the IDs above. */
     120             :         { { USB_VENDOR_NETGEAR3, USB_PRODUCT_NETGEAR3_WG111T_1 }, 0 }           \
     121             : };
     122             : #define uath_lookup(v, p)       \
     123             :         ((const struct uath_type *)usb_lookup(uath_devs, v, p))
     124             : 
     125             : void    uath_attachhook(struct device *);
     126             : int     uath_open_pipes(struct uath_softc *);
     127             : void    uath_close_pipes(struct uath_softc *);
     128             : int     uath_alloc_tx_data_list(struct uath_softc *);
     129             : void    uath_free_tx_data_list(struct uath_softc *);
     130             : int     uath_alloc_rx_data_list(struct uath_softc *);
     131             : void    uath_free_rx_data_list(struct uath_softc *);
     132             : int     uath_alloc_tx_cmd_list(struct uath_softc *);
     133             : void    uath_free_tx_cmd_list(struct uath_softc *);
     134             : int     uath_alloc_rx_cmd_list(struct uath_softc *);
     135             : void    uath_free_rx_cmd_list(struct uath_softc *);
     136             : int     uath_media_change(struct ifnet *);
     137             : void    uath_stat(void *);
     138             : void    uath_next_scan(void *);
     139             : void    uath_task(void *);
     140             : int     uath_newstate(struct ieee80211com *, enum ieee80211_state, int);
     141             : #ifdef UATH_DEBUG
     142             : void    uath_dump_cmd(const uint8_t *, int, char);
     143             : #endif
     144             : int     uath_cmd(struct uath_softc *, uint32_t, const void *, int, void *,
     145             :             int);
     146             : int     uath_cmd_write(struct uath_softc *, uint32_t, const void *, int, int);
     147             : int     uath_cmd_read(struct uath_softc *, uint32_t, const void *, int, void *,
     148             :             int);
     149             : int     uath_write_reg(struct uath_softc *, uint32_t, uint32_t);
     150             : int     uath_write_multi(struct uath_softc *, uint32_t, const void *, int);
     151             : int     uath_read_reg(struct uath_softc *, uint32_t, uint32_t *);
     152             : int     uath_read_eeprom(struct uath_softc *, uint32_t, void *);
     153             : void    uath_cmd_rxeof(struct usbd_xfer *, void *, usbd_status);
     154             : void    uath_data_rxeof(struct usbd_xfer *, void *, usbd_status);
     155             : void    uath_data_txeof(struct usbd_xfer *, void *, usbd_status);
     156             : int     uath_tx_null(struct uath_softc *);
     157             : int     uath_tx_data(struct uath_softc *, struct mbuf *,
     158             :             struct ieee80211_node *);
     159             : void    uath_start(struct ifnet *);
     160             : void    uath_watchdog(struct ifnet *);
     161             : int     uath_ioctl(struct ifnet *, u_long, caddr_t);
     162             : int     uath_query_eeprom(struct uath_softc *);
     163             : int     uath_reset(struct uath_softc *);
     164             : int     uath_reset_tx_queues(struct uath_softc *);
     165             : int     uath_wme_init(struct uath_softc *);
     166             : int     uath_set_chan(struct uath_softc *, struct ieee80211_channel *);
     167             : int     uath_set_key(struct uath_softc *, const struct ieee80211_key *, int);
     168             : int     uath_set_keys(struct uath_softc *);
     169             : int     uath_set_rates(struct uath_softc *, const struct ieee80211_rateset *);
     170             : int     uath_set_rxfilter(struct uath_softc *, uint32_t, uint32_t);
     171             : int     uath_set_led(struct uath_softc *, int, int);
     172             : int     uath_switch_channel(struct uath_softc *, struct ieee80211_channel *);
     173             : int     uath_init(struct ifnet *);
     174             : void    uath_stop(struct ifnet *, int);
     175             : int     uath_loadfirmware(struct uath_softc *, const u_char *, int);
     176             : 
     177             : int uath_match(struct device *, void *, void *);
     178             : void uath_attach(struct device *, struct device *, void *);
     179             : int uath_detach(struct device *, int);
     180             : 
     181             : struct cfdriver uath_cd = {
     182             :         NULL, "uath", DV_IFNET
     183             : };
     184             : 
     185             : const struct cfattach uath_ca = {
     186             :         sizeof(struct uath_softc), uath_match, uath_attach, uath_detach
     187             : };
     188             : 
     189             : int
     190           0 : uath_match(struct device *parent, void *match, void *aux)
     191             : {
     192           0 :         struct usb_attach_arg *uaa = aux;
     193             : 
     194           0 :         if (uaa->iface == NULL || uaa->configno != UATH_CONFIG_NO)
     195           0 :                 return UMATCH_NONE;
     196             : 
     197           0 :         return (uath_lookup(uaa->vendor, uaa->product) != NULL) ?
     198             :             UMATCH_VENDOR_PRODUCT : UMATCH_NONE;
     199           0 : }
     200             : 
     201             : void
     202           0 : uath_attachhook(struct device *self)
     203             : {
     204           0 :         struct uath_softc *sc = (struct uath_softc *)self;
     205           0 :         u_char *fw;
     206           0 :         size_t size;
     207             :         int error;
     208             : 
     209           0 :         if ((error = loadfirmware("uath-ar5523", &fw, &size)) != 0) {
     210           0 :                 printf("%s: error %d, could not read firmware %s\n",
     211           0 :                     sc->sc_dev.dv_xname, error, "uath-ar5523");
     212           0 :                 return;
     213             :         }
     214             : 
     215           0 :         error = uath_loadfirmware(sc, fw, size);
     216           0 :         free(fw, M_DEVBUF, size);
     217             : 
     218           0 :         if (error == 0) {
     219             :                 /*
     220             :                  * Hack alert: the device doesn't always gracefully detach
     221             :                  * from the bus after a firmware upload.  We need to force
     222             :                  * a port reset and a re-exploration on the parent hub.
     223             :                  */
     224           0 :                 usbd_reset_port(sc->sc_uhub, sc->sc_port);
     225           0 :                 usb_needs_reattach(sc->sc_udev);
     226           0 :         } else {
     227           0 :                 printf("%s: could not load firmware (error=%s)\n",
     228           0 :                     sc->sc_dev.dv_xname, usbd_errstr(error));
     229             :         }
     230           0 : }
     231             : 
     232             : void
     233           0 : uath_attach(struct device *parent, struct device *self, void *aux)
     234             : {
     235           0 :         struct uath_softc *sc = (struct uath_softc *)self;
     236           0 :         struct usb_attach_arg *uaa = aux;
     237           0 :         struct ieee80211com *ic = &sc->sc_ic;
     238           0 :         struct ifnet *ifp = &ic->ic_if;
     239             :         usbd_status error;
     240             :         int i;
     241             : 
     242           0 :         sc->sc_udev = uaa->device;
     243           0 :         sc->sc_uhub = uaa->device->myhub;
     244           0 :         sc->sc_port = uaa->port;
     245             : 
     246           0 :         sc->sc_flags = uath_lookup(uaa->vendor, uaa->product)->flags;
     247             : 
     248             :         /* get the first interface handle */
     249           0 :         error = usbd_device2interface_handle(sc->sc_udev, UATH_IFACE_INDEX,
     250           0 :             &sc->sc_iface);
     251           0 :         if (error != 0) {
     252           0 :                 printf("%s: could not get interface handle\n",
     253           0 :                     sc->sc_dev.dv_xname);
     254           0 :                 return;
     255             :         }
     256             : 
     257             :         /*
     258             :          * We must open the pipes early because they're used to upload the
     259             :          * firmware (pre-firmware devices) or to send firmware commands.
     260             :          */
     261           0 :         if (uath_open_pipes(sc) != 0) {
     262           0 :                 printf("%s: could not open pipes\n", sc->sc_dev.dv_xname);
     263           0 :                 return;
     264             :         }
     265             : 
     266           0 :         if (sc->sc_flags & UATH_FLAG_PRE_FIRMWARE) {
     267           0 :                 config_mountroot(self, uath_attachhook);
     268           0 :                 return;
     269             :         }
     270             : 
     271             :         /*
     272             :          * Only post-firmware devices here.
     273             :          */
     274           0 :         usb_init_task(&sc->sc_task, uath_task, sc, USB_TASK_TYPE_GENERIC);
     275           0 :         timeout_set(&sc->scan_to, uath_next_scan, sc);
     276           0 :         timeout_set(&sc->stat_to, uath_stat, sc);
     277             : 
     278             :         /*
     279             :          * Allocate xfers for firmware commands.
     280             :          */
     281           0 :         if (uath_alloc_tx_cmd_list(sc) != 0) {
     282           0 :                 printf("%s: could not allocate Tx command list\n",
     283           0 :                     sc->sc_dev.dv_xname);
     284           0 :                 goto fail;
     285             :         }
     286           0 :         if (uath_alloc_rx_cmd_list(sc) != 0) {
     287           0 :                 printf("%s: could not allocate Rx command list\n",
     288           0 :                     sc->sc_dev.dv_xname);
     289           0 :                 goto fail;
     290             :         }
     291             : 
     292             :         /*
     293             :          * Queue Rx command xfers.
     294             :          */
     295           0 :         for (i = 0; i < UATH_RX_CMD_LIST_COUNT; i++) {
     296           0 :                 struct uath_rx_cmd *cmd = &sc->rx_cmd[i];
     297             : 
     298           0 :                 usbd_setup_xfer(cmd->xfer, sc->cmd_rx_pipe, cmd, cmd->buf,
     299             :                     UATH_MAX_RXCMDSZ, USBD_SHORT_XFER_OK | USBD_NO_COPY,
     300             :                     USBD_NO_TIMEOUT, uath_cmd_rxeof);
     301           0 :                 error = usbd_transfer(cmd->xfer);
     302           0 :                 if (error != USBD_IN_PROGRESS && error != 0) {
     303           0 :                         printf("%s: could not queue Rx command xfer\n",
     304           0 :                             sc->sc_dev.dv_xname);
     305           0 :                         goto fail;
     306             :                 }
     307           0 :         }
     308             : 
     309             :         /*
     310             :          * We're now ready to send/receive firmware commands.
     311             :          */
     312           0 :         if (uath_reset(sc) != 0) {
     313           0 :                 printf("%s: could not initialize adapter\n",
     314           0 :                     sc->sc_dev.dv_xname);
     315           0 :                 goto fail;
     316             :         }
     317           0 :         if (uath_query_eeprom(sc) != 0) {
     318           0 :                 printf("%s: could not read EEPROM\n", sc->sc_dev.dv_xname);
     319           0 :                 goto fail;
     320             :         }
     321             : 
     322           0 :         printf("%s: MAC/BBP AR5523, RF AR%c112, address %s\n",
     323           0 :             sc->sc_dev.dv_xname, (sc->sc_flags & UATH_FLAG_ABG) ? '5': '2',
     324           0 :             ether_sprintf(ic->ic_myaddr));
     325             : 
     326             :         /*
     327             :          * Allocate xfers for Tx/Rx data pipes.
     328             :          */
     329           0 :         if (uath_alloc_tx_data_list(sc) != 0) {
     330           0 :                 printf("%s: could not allocate Tx data list\n",
     331             :                     sc->sc_dev.dv_xname);
     332           0 :                 goto fail;
     333             :         }
     334           0 :         if (uath_alloc_rx_data_list(sc) != 0) {
     335           0 :                 printf("%s: could not allocate Rx data list\n",
     336             :                     sc->sc_dev.dv_xname);
     337           0 :                 goto fail;
     338             :         }
     339             : 
     340           0 :         ic->ic_phytype = IEEE80211_T_OFDM;   /* not only, but not used */
     341           0 :         ic->ic_opmode = IEEE80211_M_STA;     /* default to BSS mode */
     342           0 :         ic->ic_state = IEEE80211_S_INIT;
     343             : 
     344             :         /* set device capabilities */
     345           0 :         ic->ic_caps =
     346             :             IEEE80211_C_MONITOR |       /* monitor mode supported */
     347             :             IEEE80211_C_TXPMGT |        /* tx power management */
     348             :             IEEE80211_C_SHPREAMBLE |    /* short preamble supported */
     349             :             IEEE80211_C_SHSLOT |        /* short slot time supported */
     350             :             IEEE80211_C_WEP;            /* h/w WEP */
     351             : 
     352             :         /* set supported .11b and .11g rates */
     353           0 :         ic->ic_sup_rates[IEEE80211_MODE_11B] = ieee80211_std_rateset_11b;
     354           0 :         ic->ic_sup_rates[IEEE80211_MODE_11G] = ieee80211_std_rateset_11g;
     355             : 
     356             :         /* set supported .11b and .11g channels (1 through 14) */
     357           0 :         for (i = 1; i <= 14; i++) {
     358           0 :                 ic->ic_channels[i].ic_freq =
     359           0 :                     ieee80211_ieee2mhz(i, IEEE80211_CHAN_2GHZ);
     360           0 :                 ic->ic_channels[i].ic_flags =
     361             :                     IEEE80211_CHAN_CCK | IEEE80211_CHAN_OFDM |
     362             :                     IEEE80211_CHAN_DYN | IEEE80211_CHAN_2GHZ;
     363             :         }
     364             : 
     365           0 :         ifp->if_softc = sc;
     366           0 :         ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
     367           0 :         ifp->if_ioctl = uath_ioctl;
     368           0 :         ifp->if_start = uath_start;
     369           0 :         ifp->if_watchdog = uath_watchdog;
     370           0 :         memcpy(ifp->if_xname, sc->sc_dev.dv_xname, IFNAMSIZ);
     371             : 
     372           0 :         if_attach(ifp);
     373           0 :         ieee80211_ifattach(ifp);
     374             : 
     375             :         /* override state transition machine */
     376           0 :         sc->sc_newstate = ic->ic_newstate;
     377           0 :         ic->ic_newstate = uath_newstate;
     378           0 :         ieee80211_media_init(ifp, uath_media_change, ieee80211_media_status);
     379             : 
     380             : #if NBPFILTER > 0
     381           0 :         bpfattach(&sc->sc_drvbpf, ifp, DLT_IEEE802_11_RADIO,
     382             :             sizeof (struct ieee80211_frame) + IEEE80211_RADIOTAP_HDRLEN);
     383             : 
     384           0 :         sc->sc_rxtap_len = sizeof sc->sc_rxtapu;
     385           0 :         sc->sc_rxtap.wr_ihdr.it_len = htole16(sc->sc_rxtap_len);
     386           0 :         sc->sc_rxtap.wr_ihdr.it_present = htole32(UATH_RX_RADIOTAP_PRESENT);
     387             : 
     388           0 :         sc->sc_txtap_len = sizeof sc->sc_txtapu;
     389           0 :         sc->sc_txtap.wt_ihdr.it_len = htole16(sc->sc_txtap_len);
     390           0 :         sc->sc_txtap.wt_ihdr.it_present = htole32(UATH_TX_RADIOTAP_PRESENT);
     391             : #endif
     392             : 
     393           0 :         return;
     394             : 
     395           0 : fail:   uath_close_pipes(sc);
     396           0 :         uath_free_tx_data_list(sc);
     397           0 :         uath_free_rx_cmd_list(sc);
     398           0 :         uath_free_tx_cmd_list(sc);
     399           0 :         usbd_deactivate(sc->sc_udev);
     400           0 : }
     401             : 
     402             : int
     403           0 : uath_detach(struct device *self, int flags)
     404             : {
     405           0 :         struct uath_softc *sc = (struct uath_softc *)self;
     406           0 :         struct ifnet *ifp = &sc->sc_ic.ic_if;
     407             :         int s;
     408             : 
     409           0 :         s = splnet();
     410             : 
     411           0 :         if (sc->sc_flags & UATH_FLAG_PRE_FIRMWARE) {
     412           0 :                 uath_close_pipes(sc);
     413           0 :                 splx(s);
     414           0 :                 return 0;
     415             :         }
     416             : 
     417             :         /* post-firmware device */
     418             : 
     419           0 :         usb_rem_task(sc->sc_udev, &sc->sc_task);
     420           0 :         if (timeout_initialized(&sc->scan_to))
     421           0 :                 timeout_del(&sc->scan_to);
     422           0 :         if (timeout_initialized(&sc->stat_to))
     423           0 :                 timeout_del(&sc->stat_to);
     424             : 
     425             :         /* close Tx/Rx pipes */
     426           0 :         uath_close_pipes(sc);
     427             : 
     428             :         /* free xfers */
     429           0 :         uath_free_tx_data_list(sc);
     430           0 :         uath_free_rx_data_list(sc);
     431           0 :         uath_free_tx_cmd_list(sc);
     432           0 :         uath_free_rx_cmd_list(sc);
     433             : 
     434           0 :         if (ifp->if_softc != NULL) {
     435           0 :                 ieee80211_ifdetach(ifp);        /* free all nodes */
     436           0 :                 if_detach(ifp);
     437           0 :         }
     438             : 
     439           0 :         splx(s);
     440             : 
     441           0 :         return 0;
     442           0 : }
     443             : 
     444             : int
     445           0 : uath_open_pipes(struct uath_softc *sc)
     446             : {
     447             :         int error;
     448             : 
     449             :         /*
     450             :          * XXX pipes numbers are hardcoded because we don't have any way
     451             :          * to distinguish the data pipes from the firmware command pipes
     452             :          * (both are bulk pipes) using the endpoints descriptors.
     453             :          */
     454           0 :         error = usbd_open_pipe(sc->sc_iface, 0x01, USBD_EXCLUSIVE_USE,
     455           0 :             &sc->cmd_tx_pipe);
     456           0 :         if (error != 0) {
     457           0 :                 printf("%s: could not open Tx command pipe: %s\n",
     458           0 :                     sc->sc_dev.dv_xname, usbd_errstr(error));
     459           0 :                 goto fail;
     460             :         }
     461             : 
     462           0 :         error = usbd_open_pipe(sc->sc_iface, 0x02, USBD_EXCLUSIVE_USE,
     463           0 :             &sc->data_tx_pipe);
     464           0 :         if (error != 0) {
     465           0 :                 printf("%s: could not open Tx data pipe: %s\n",
     466           0 :                     sc->sc_dev.dv_xname, usbd_errstr(error));
     467           0 :                 goto fail;
     468             :         }
     469             : 
     470           0 :         error = usbd_open_pipe(sc->sc_iface, 0x81, USBD_EXCLUSIVE_USE,
     471           0 :             &sc->cmd_rx_pipe);
     472           0 :         if (error != 0) {
     473           0 :                 printf("%s: could not open Rx command pipe: %s\n",
     474           0 :                     sc->sc_dev.dv_xname, usbd_errstr(error));
     475           0 :                 goto fail;
     476             :         }
     477             : 
     478           0 :         error = usbd_open_pipe(sc->sc_iface, 0x82, USBD_EXCLUSIVE_USE,
     479           0 :             &sc->data_rx_pipe);
     480           0 :         if (error != 0) {
     481           0 :                 printf("%s: could not open Rx data pipe: %s\n",
     482           0 :                     sc->sc_dev.dv_xname, usbd_errstr(error));
     483           0 :                 goto fail;
     484             :         }
     485             : 
     486           0 :         return 0;
     487             : 
     488           0 : fail:   uath_close_pipes(sc);
     489           0 :         return error;
     490           0 : }
     491             : 
     492             : void
     493           0 : uath_close_pipes(struct uath_softc *sc)
     494             : {
     495           0 :         if (sc->data_tx_pipe != NULL) {
     496           0 :                 usbd_close_pipe(sc->data_tx_pipe);
     497           0 :                 sc->data_tx_pipe = NULL;
     498           0 :         }
     499             : 
     500           0 :         if (sc->data_rx_pipe != NULL) {
     501           0 :                 usbd_close_pipe(sc->data_rx_pipe);
     502           0 :                 sc->data_rx_pipe = NULL;
     503           0 :         }
     504             : 
     505           0 :         if (sc->cmd_tx_pipe != NULL) {
     506           0 :                 usbd_close_pipe(sc->cmd_tx_pipe);
     507           0 :                 sc->cmd_tx_pipe = NULL;
     508           0 :         }
     509             : 
     510           0 :         if (sc->cmd_rx_pipe != NULL) {
     511           0 :                 usbd_close_pipe(sc->cmd_rx_pipe);
     512           0 :                 sc->cmd_rx_pipe = NULL;
     513           0 :         }
     514           0 : }
     515             : 
     516             : int
     517           0 : uath_alloc_tx_data_list(struct uath_softc *sc)
     518             : {
     519             :         int i, error;
     520             : 
     521           0 :         for (i = 0; i < UATH_TX_DATA_LIST_COUNT; i++) {
     522           0 :                 struct uath_tx_data *data = &sc->tx_data[i];
     523             : 
     524           0 :                 data->sc = sc;       /* backpointer for callbacks */
     525             : 
     526           0 :                 data->xfer = usbd_alloc_xfer(sc->sc_udev);
     527           0 :                 if (data->xfer == NULL) {
     528           0 :                         printf("%s: could not allocate xfer\n",
     529           0 :                             sc->sc_dev.dv_xname);
     530             :                         error = ENOMEM;
     531           0 :                         goto fail;
     532             :                 }
     533           0 :                 data->buf = usbd_alloc_buffer(data->xfer, UATH_MAX_TXBUFSZ);
     534           0 :                 if (data->buf == NULL) {
     535           0 :                         printf("%s: could not allocate xfer buffer\n",
     536           0 :                             sc->sc_dev.dv_xname);
     537             :                         error = ENOMEM;
     538           0 :                         goto fail;
     539             :                 }
     540           0 :         }
     541           0 :         return 0;
     542             : 
     543           0 : fail:   uath_free_tx_data_list(sc);
     544           0 :         return error;
     545           0 : }
     546             : 
     547             : void
     548           0 : uath_free_tx_data_list(struct uath_softc *sc)
     549             : {
     550             :         int i;
     551             : 
     552           0 :         for (i = 0; i < UATH_TX_DATA_LIST_COUNT; i++)
     553           0 :                 if (sc->tx_data[i].xfer != NULL) {
     554           0 :                         usbd_free_xfer(sc->tx_data[i].xfer);
     555           0 :                         sc->tx_data[i].xfer = NULL;
     556           0 :                 }
     557           0 : }
     558             : 
     559             : int
     560           0 : uath_alloc_rx_data_list(struct uath_softc *sc)
     561             : {
     562             :         int i, error;
     563             : 
     564           0 :         for (i = 0; i < UATH_RX_DATA_LIST_COUNT; i++) {
     565           0 :                 struct uath_rx_data *data = &sc->rx_data[i];
     566             : 
     567           0 :                 data->sc = sc;       /* backpointer for callbacks */
     568             : 
     569           0 :                 data->xfer = usbd_alloc_xfer(sc->sc_udev);
     570           0 :                 if (data->xfer == NULL) {
     571           0 :                         printf("%s: could not allocate xfer\n",
     572           0 :                             sc->sc_dev.dv_xname);
     573             :                         error = ENOMEM;
     574           0 :                         goto fail;
     575             :                 }
     576           0 :                 if (usbd_alloc_buffer(data->xfer, sc->rxbufsz) == NULL) {
     577           0 :                         printf("%s: could not allocate xfer buffer\n",
     578           0 :                             sc->sc_dev.dv_xname);
     579             :                         error = ENOMEM;
     580           0 :                         goto fail;
     581             :                 }
     582             : 
     583           0 :                 MGETHDR(data->m, M_DONTWAIT, MT_DATA);
     584           0 :                 if (data->m == NULL) {
     585           0 :                         printf("%s: could not allocate rx mbuf\n",
     586           0 :                             sc->sc_dev.dv_xname);
     587             :                         error = ENOMEM;
     588           0 :                         goto fail;
     589             :                 }
     590           0 :                 MCLGETI(data->m, M_DONTWAIT, NULL, sc->rxbufsz);
     591           0 :                 if (!(data->m->m_flags & M_EXT)) {
     592           0 :                         printf("%s: could not allocate rx mbuf cluster\n",
     593           0 :                             sc->sc_dev.dv_xname);
     594             :                         error = ENOMEM;
     595           0 :                         goto fail;
     596             :                 }
     597             : 
     598           0 :                 data->buf = mtod(data->m, uint8_t *);
     599           0 :         }
     600           0 :         return 0;
     601             : 
     602           0 : fail:   uath_free_rx_data_list(sc);
     603           0 :         return error;
     604           0 : }
     605             : 
     606             : void
     607           0 : uath_free_rx_data_list(struct uath_softc *sc)
     608             : {
     609             :         int i;
     610             : 
     611           0 :         for (i = 0; i < UATH_RX_DATA_LIST_COUNT; i++) {
     612           0 :                 struct uath_rx_data *data = &sc->rx_data[i];
     613             : 
     614           0 :                 if (data->xfer != NULL) {
     615           0 :                         usbd_free_xfer(data->xfer);
     616           0 :                         data->xfer = NULL;
     617           0 :                 }
     618             : 
     619           0 :                 if (data->m != NULL) {
     620           0 :                         m_freem(data->m);
     621           0 :                         data->m = NULL;
     622           0 :                 }
     623             :         }
     624           0 : }
     625             : 
     626             : int
     627           0 : uath_alloc_tx_cmd_list(struct uath_softc *sc)
     628             : {
     629             :         int i, error;
     630             : 
     631           0 :         for (i = 0; i < UATH_TX_CMD_LIST_COUNT; i++) {
     632           0 :                 struct uath_tx_cmd *cmd = &sc->tx_cmd[i];
     633             : 
     634           0 :                 cmd->sc = sc;        /* backpointer for callbacks */
     635             : 
     636           0 :                 cmd->xfer = usbd_alloc_xfer(sc->sc_udev);
     637           0 :                 if (cmd->xfer == NULL) {
     638           0 :                         printf("%s: could not allocate xfer\n",
     639           0 :                             sc->sc_dev.dv_xname);
     640             :                         error = ENOMEM;
     641           0 :                         goto fail;
     642             :                 }
     643           0 :                 cmd->buf = usbd_alloc_buffer(cmd->xfer, UATH_MAX_TXCMDSZ);
     644           0 :                 if (cmd->buf == NULL) {
     645           0 :                         printf("%s: could not allocate xfer buffer\n",
     646           0 :                             sc->sc_dev.dv_xname);
     647             :                         error = ENOMEM;
     648           0 :                         goto fail;
     649             :                 }
     650           0 :         }
     651           0 :         return 0;
     652             : 
     653           0 : fail:   uath_free_tx_cmd_list(sc);
     654           0 :         return error;
     655           0 : }
     656             : 
     657             : void
     658           0 : uath_free_tx_cmd_list(struct uath_softc *sc)
     659             : {
     660             :         int i;
     661             : 
     662           0 :         for (i = 0; i < UATH_TX_CMD_LIST_COUNT; i++)
     663           0 :                 if (sc->tx_cmd[i].xfer != NULL) {
     664           0 :                         usbd_free_xfer(sc->tx_cmd[i].xfer);
     665           0 :                         sc->tx_cmd[i].xfer = NULL;
     666           0 :                 }
     667           0 : }
     668             : 
     669             : int
     670           0 : uath_alloc_rx_cmd_list(struct uath_softc *sc)
     671             : {
     672             :         int i, error;
     673             : 
     674           0 :         for (i = 0; i < UATH_RX_CMD_LIST_COUNT; i++) {
     675           0 :                 struct uath_rx_cmd *cmd = &sc->rx_cmd[i];
     676             : 
     677           0 :                 cmd->sc = sc;        /* backpointer for callbacks */
     678             : 
     679           0 :                 cmd->xfer = usbd_alloc_xfer(sc->sc_udev);
     680           0 :                 if (cmd->xfer == NULL) {
     681           0 :                         printf("%s: could not allocate xfer\n",
     682           0 :                             sc->sc_dev.dv_xname);
     683             :                         error = ENOMEM;
     684           0 :                         goto fail;
     685             :                 }
     686           0 :                 cmd->buf = usbd_alloc_buffer(cmd->xfer, UATH_MAX_RXCMDSZ);
     687           0 :                 if (cmd->buf == NULL) {
     688           0 :                         printf("%s: could not allocate xfer buffer\n",
     689           0 :                             sc->sc_dev.dv_xname);
     690             :                         error = ENOMEM;
     691           0 :                         goto fail;
     692             :                 }
     693           0 :         }
     694           0 :         return 0;
     695             : 
     696           0 : fail:   uath_free_rx_cmd_list(sc);
     697           0 :         return error;
     698           0 : }
     699             : 
     700             : void
     701           0 : uath_free_rx_cmd_list(struct uath_softc *sc)
     702             : {
     703             :         int i;
     704             : 
     705           0 :         for (i = 0; i < UATH_RX_CMD_LIST_COUNT; i++)
     706           0 :                 if (sc->rx_cmd[i].xfer != NULL) {
     707           0 :                         usbd_free_xfer(sc->rx_cmd[i].xfer);
     708           0 :                         sc->rx_cmd[i].xfer = NULL;
     709           0 :                 }
     710           0 : }
     711             : 
     712             : int
     713           0 : uath_media_change(struct ifnet *ifp)
     714             : {
     715             :         int error;
     716             : 
     717           0 :         error = ieee80211_media_change(ifp);
     718           0 :         if (error != ENETRESET)
     719           0 :                 return error;
     720             : 
     721           0 :         if ((ifp->if_flags & (IFF_UP | IFF_RUNNING)) == (IFF_UP | IFF_RUNNING))
     722           0 :                 uath_init(ifp);
     723             : 
     724           0 :         return 0;
     725           0 : }
     726             : 
     727             : /*
     728             :  * This function is called periodically (every second) when associated to
     729             :  * query device statistics.
     730             :  */
     731             : void
     732           0 : uath_stat(void *arg)
     733             : {
     734           0 :         struct uath_softc *sc = arg;
     735             :         int error;
     736             : 
     737             :         /*
     738             :          * Send request for statistics asynchronously. The timer will be
     739             :          * restarted when we'll get the stats notification.
     740             :          */
     741           0 :         error = uath_cmd_write(sc, UATH_CMD_STATS, NULL, 0,
     742             :             UATH_CMD_FLAG_ASYNC);
     743           0 :         if (error != 0) {
     744           0 :                 printf("%s: could not query statistics (error=%d)\n",
     745           0 :                     sc->sc_dev.dv_xname, error);
     746           0 :         }
     747           0 : }
     748             : 
     749             : /*
     750             :  * This function is called periodically (every 250ms) during scanning to
     751             :  * switch from one channel to another.
     752             :  */
     753             : void
     754           0 : uath_next_scan(void *arg)
     755             : {
     756           0 :         struct uath_softc *sc = arg;
     757           0 :         struct ieee80211com *ic = &sc->sc_ic;
     758           0 :         struct ifnet *ifp = &ic->ic_if;
     759             : 
     760           0 :         if (ic->ic_state == IEEE80211_S_SCAN)
     761           0 :                 ieee80211_next_scan(ifp);
     762           0 : }
     763             : 
     764             : void
     765           0 : uath_task(void *arg)
     766             : {
     767           0 :         struct uath_softc *sc = arg;
     768           0 :         struct ieee80211com *ic = &sc->sc_ic;
     769             :         enum ieee80211_state ostate;
     770             : 
     771           0 :         ostate = ic->ic_state;
     772             : 
     773           0 :         switch (sc->sc_state) {
     774             :         case IEEE80211_S_INIT:
     775           0 :                 if (ostate == IEEE80211_S_RUN) {
     776             :                         /* turn link and activity LEDs off */
     777           0 :                         (void)uath_set_led(sc, UATH_LED_LINK, 0);
     778           0 :                         (void)uath_set_led(sc, UATH_LED_ACTIVITY, 0);
     779           0 :                 }
     780             :                 break;
     781             : 
     782             :         case IEEE80211_S_SCAN:
     783           0 :                 if (uath_switch_channel(sc, ic->ic_bss->ni_chan) != 0) {
     784           0 :                         printf("%s: could not switch channel\n",
     785           0 :                             sc->sc_dev.dv_xname);
     786           0 :                         break;
     787             :                 }
     788           0 :                 timeout_add_msec(&sc->scan_to, 250);
     789           0 :                 break;
     790             : 
     791             :         case IEEE80211_S_AUTH:
     792             :         {
     793           0 :                 struct ieee80211_node *ni = ic->ic_bss;
     794           0 :                 struct uath_cmd_bssid bssid;
     795           0 :                 struct uath_cmd_0b cmd0b;
     796           0 :                 struct uath_cmd_0c cmd0c;
     797             : 
     798           0 :                 if (uath_switch_channel(sc, ni->ni_chan) != 0) {
     799           0 :                         printf("%s: could not switch channel\n",
     800           0 :                             sc->sc_dev.dv_xname);
     801           0 :                         break;
     802             :                 }
     803             : 
     804           0 :                 (void)uath_cmd_write(sc, UATH_CMD_24, NULL, 0, 0);
     805             : 
     806           0 :                 bzero(&bssid, sizeof bssid);
     807           0 :                 bssid.len = htobe32(IEEE80211_ADDR_LEN);
     808           0 :                 IEEE80211_ADDR_COPY(bssid.bssid, ni->ni_bssid);
     809           0 :                 (void)uath_cmd_write(sc, UATH_CMD_SET_BSSID, &bssid,
     810             :                     sizeof bssid, 0);
     811             : 
     812           0 :                 bzero(&cmd0b, sizeof cmd0b);
     813           0 :                 cmd0b.code = htobe32(2);
     814           0 :                 cmd0b.size = htobe32(sizeof (cmd0b.data));
     815           0 :                 (void)uath_cmd_write(sc, UATH_CMD_0B, &cmd0b, sizeof cmd0b, 0);
     816             : 
     817           0 :                 bzero(&cmd0c, sizeof cmd0c);
     818           0 :                 cmd0c.magic1 = htobe32(2);
     819           0 :                 cmd0c.magic2 = htobe32(7);
     820           0 :                 cmd0c.magic3 = htobe32(1);
     821           0 :                 (void)uath_cmd_write(sc, UATH_CMD_0C, &cmd0c, sizeof cmd0c, 0);
     822             : 
     823           0 :                 if (uath_set_rates(sc, &ni->ni_rates) != 0) {
     824           0 :                         printf("%s: could not set negotiated rate set\n",
     825           0 :                             sc->sc_dev.dv_xname);
     826           0 :                         break;
     827             :                 }
     828           0 :                 break;
     829           0 :         }
     830             : 
     831             :         case IEEE80211_S_ASSOC:
     832             :                 break;
     833             : 
     834             :         case IEEE80211_S_RUN:
     835             :         {
     836           0 :                 struct ieee80211_node *ni = ic->ic_bss;
     837           0 :                 struct uath_cmd_bssid bssid;
     838           0 :                 struct uath_cmd_xled xled;
     839           0 :                 uint32_t val;
     840             : 
     841           0 :                 if (ic->ic_opmode == IEEE80211_M_MONITOR) {
     842             :                         /* make both LEDs blink while monitoring */
     843           0 :                         bzero(&xled, sizeof xled);
     844           0 :                         xled.which = htobe32(0);
     845           0 :                         xled.rate = htobe32(1);
     846           0 :                         xled.mode = htobe32(2);
     847           0 :                         (void)uath_cmd_write(sc, UATH_CMD_SET_XLED, &xled,
     848             :                             sizeof xled, 0);
     849           0 :                         break;
     850             :                 }
     851             : 
     852             :                 /*
     853             :                  * Tx rate is controlled by firmware, report the maximum
     854             :                  * negotiated rate in ifconfig output.
     855             :                  */
     856           0 :                 ni->ni_txrate = ni->ni_rates.rs_nrates - 1;
     857             : 
     858           0 :                 val = htobe32(1);
     859           0 :                 (void)uath_cmd_write(sc, UATH_CMD_2E, &val, sizeof val, 0);
     860             : 
     861           0 :                 bzero(&bssid, sizeof bssid);
     862           0 :                 bssid.flags1 = htobe32(0xc004);
     863           0 :                 bssid.flags2 = htobe32(0x003b);
     864           0 :                 bssid.len = htobe32(IEEE80211_ADDR_LEN);
     865           0 :                 IEEE80211_ADDR_COPY(bssid.bssid, ni->ni_bssid);
     866           0 :                 (void)uath_cmd_write(sc, UATH_CMD_SET_BSSID, &bssid,
     867             :                     sizeof bssid, 0);
     868             : 
     869             :                 /* turn link LED on */
     870           0 :                 (void)uath_set_led(sc, UATH_LED_LINK, 1);
     871             : 
     872             :                 /* make activity LED blink */
     873           0 :                 bzero(&xled, sizeof xled);
     874           0 :                 xled.which = htobe32(1);
     875           0 :                 xled.rate = htobe32(1);
     876           0 :                 xled.mode = htobe32(2);
     877           0 :                 (void)uath_cmd_write(sc, UATH_CMD_SET_XLED, &xled, sizeof xled,
     878             :                     0);
     879             : 
     880             :                 /* set state to associated */
     881           0 :                 val = htobe32(1);
     882           0 :                 (void)uath_cmd_write(sc, UATH_CMD_SET_STATE, &val, sizeof val,
     883             :                     0);
     884             : 
     885             :                 /* start statistics timer */
     886           0 :                 timeout_add_sec(&sc->stat_to, 1);
     887           0 :                 break;
     888           0 :         }
     889             :         }
     890           0 :         sc->sc_newstate(ic, sc->sc_state, sc->sc_arg);
     891           0 : }
     892             : 
     893             : int
     894           0 : uath_newstate(struct ieee80211com *ic, enum ieee80211_state nstate, int arg)
     895             : {
     896           0 :         struct uath_softc *sc = ic->ic_softc;
     897             : 
     898           0 :         usb_rem_task(sc->sc_udev, &sc->sc_task);
     899           0 :         timeout_del(&sc->scan_to);
     900           0 :         timeout_del(&sc->stat_to);
     901             : 
     902             :         /* do it in a process context */
     903           0 :         sc->sc_state = nstate;
     904           0 :         sc->sc_arg = arg;
     905           0 :         usb_add_task(sc->sc_udev, &sc->sc_task);
     906           0 :         return 0;
     907             : }
     908             : 
     909             : #ifdef UATH_DEBUG
     910             : void
     911             : uath_dump_cmd(const uint8_t *buf, int len, char prefix)
     912             : {
     913             :         int i;
     914             : 
     915             :         for (i = 0; i < len; i++) {
     916             :                 if ((i % 16) == 0)
     917             :                         printf("\n%c ", prefix);
     918             :                 else if ((i % 4) == 0)
     919             :                         printf(" ");
     920             :                 printf("%02x", buf[i]);
     921             :         }
     922             :         printf("\n");
     923             : }
     924             : #endif
     925             : 
     926             : /*
     927             :  * Low-level function to send read or write commands to the firmware.
     928             :  */
     929             : int
     930           0 : uath_cmd(struct uath_softc *sc, uint32_t code, const void *idata, int ilen,
     931             :     void *odata, int flags)
     932             : {
     933             :         struct uath_cmd_hdr *hdr;
     934             :         struct uath_tx_cmd *cmd;
     935             :         uint16_t xferflags;
     936             :         int s, xferlen, error;
     937             : 
     938             :         /* grab a xfer */
     939           0 :         cmd = &sc->tx_cmd[sc->cmd_idx];
     940             : 
     941             :         /* always bulk-out a multiple of 4 bytes */
     942           0 :         xferlen = (sizeof (struct uath_cmd_hdr) + ilen + 3) & ~3;
     943             : 
     944           0 :         hdr = (struct uath_cmd_hdr *)cmd->buf;
     945           0 :         bzero(hdr, sizeof (struct uath_cmd_hdr));
     946           0 :         hdr->len   = htobe32(xferlen);
     947           0 :         hdr->code  = htobe32(code);
     948           0 :         hdr->priv  = sc->cmd_idx; /* don't care about endianness */
     949           0 :         hdr->magic = htobe32((flags & UATH_CMD_FLAG_MAGIC) ? 1 << 24 : 0);
     950           0 :         bcopy(idata, (uint8_t *)(hdr + 1), ilen);
     951             : 
     952             : #ifdef UATH_DEBUG
     953             :         if (uath_debug >= 5) {
     954             :                 printf("sending command code=0x%02x flags=0x%x index=%u",
     955             :                     code, flags, sc->cmd_idx);
     956             :                 uath_dump_cmd(cmd->buf, xferlen, '+');
     957             :         }
     958             : #endif
     959             :         xferflags = USBD_FORCE_SHORT_XFER | USBD_NO_COPY;
     960           0 :         if (!(flags & UATH_CMD_FLAG_READ)) {
     961           0 :                 if (!(flags & UATH_CMD_FLAG_ASYNC))
     962           0 :                         xferflags |= USBD_SYNCHRONOUS;
     963             :         } else
     964           0 :                 s = splusb();
     965             : 
     966           0 :         cmd->odata = odata;
     967             : 
     968           0 :         usbd_setup_xfer(cmd->xfer, sc->cmd_tx_pipe, cmd, cmd->buf, xferlen,
     969             :             xferflags, UATH_CMD_TIMEOUT, NULL);
     970           0 :         error = usbd_transfer(cmd->xfer);
     971           0 :         if (error != USBD_IN_PROGRESS && error != 0) {
     972           0 :                 if (flags & UATH_CMD_FLAG_READ)
     973           0 :                         splx(s);
     974           0 :                 printf("%s: could not send command 0x%x (error=%s)\n",
     975           0 :                     sc->sc_dev.dv_xname, code, usbd_errstr(error));
     976           0 :                 return error;
     977             :         }
     978           0 :         sc->cmd_idx = (sc->cmd_idx + 1) % UATH_TX_CMD_LIST_COUNT;
     979             : 
     980           0 :         if (!(flags & UATH_CMD_FLAG_READ))
     981           0 :                 return 0;       /* write: don't wait for reply */
     982             : 
     983             :         /* wait at most two seconds for command reply */
     984           0 :         error = tsleep(cmd, PCATCH, "uathcmd", 2 * hz);
     985           0 :         cmd->odata = NULL;   /* in case answer is received too late */
     986           0 :         splx(s);
     987           0 :         if (error != 0) {
     988           0 :                 printf("%s: timeout waiting for command reply\n",
     989           0 :                     sc->sc_dev.dv_xname);
     990           0 :         }
     991           0 :         return error;
     992           0 : }
     993             : 
     994             : int
     995           0 : uath_cmd_write(struct uath_softc *sc, uint32_t code, const void *data, int len,
     996             :     int flags)
     997             : {
     998           0 :         flags &= ~UATH_CMD_FLAG_READ;
     999           0 :         return uath_cmd(sc, code, data, len, NULL, flags);
    1000             : }
    1001             : 
    1002             : int
    1003           0 : uath_cmd_read(struct uath_softc *sc, uint32_t code, const void *idata,
    1004             :     int ilen, void *odata, int flags)
    1005             : {
    1006           0 :         flags |= UATH_CMD_FLAG_READ;
    1007           0 :         return uath_cmd(sc, code, idata, ilen, odata, flags);
    1008             : }
    1009             : 
    1010             : int
    1011           0 : uath_write_reg(struct uath_softc *sc, uint32_t reg, uint32_t val)
    1012             : {
    1013           0 :         struct uath_write_mac write;
    1014             :         int error;
    1015             : 
    1016           0 :         write.reg = htobe32(reg);
    1017           0 :         write.len = htobe32(0); /* 0 = single write */
    1018           0 :         *(uint32_t *)write.data = htobe32(val);
    1019             : 
    1020           0 :         error = uath_cmd_write(sc, UATH_CMD_WRITE_MAC, &write,
    1021             :             3 * sizeof (uint32_t), 0);
    1022           0 :         if (error != 0) {
    1023           0 :                 printf("%s: could not write register 0x%02x\n",
    1024           0 :                     sc->sc_dev.dv_xname, reg);
    1025           0 :         }
    1026           0 :         return error;
    1027           0 : }
    1028             : 
    1029             : int
    1030           0 : uath_write_multi(struct uath_softc *sc, uint32_t reg, const void *data,
    1031             :     int len)
    1032             : {
    1033           0 :         struct uath_write_mac write;
    1034             :         int error;
    1035             : 
    1036           0 :         write.reg = htobe32(reg);
    1037           0 :         write.len = htobe32(len);
    1038           0 :         bcopy(data, write.data, len);
    1039             : 
    1040             :         /* properly handle the case where len is zero (reset) */
    1041           0 :         error = uath_cmd_write(sc, UATH_CMD_WRITE_MAC, &write,
    1042           0 :             (len == 0) ? sizeof (uint32_t) : 2 * sizeof (uint32_t) + len, 0);
    1043           0 :         if (error != 0) {
    1044           0 :                 printf("%s: could not write %d bytes to register 0x%02x\n",
    1045           0 :                     sc->sc_dev.dv_xname, len, reg);
    1046           0 :         }
    1047           0 :         return error;
    1048           0 : }
    1049             : 
    1050             : int
    1051           0 : uath_read_reg(struct uath_softc *sc, uint32_t reg, uint32_t *val)
    1052             : {
    1053           0 :         struct uath_read_mac read;
    1054             :         int error;
    1055             : 
    1056           0 :         reg = htobe32(reg);
    1057           0 :         error = uath_cmd_read(sc, UATH_CMD_READ_MAC, &reg, sizeof reg, &read,
    1058             :             0);
    1059           0 :         if (error != 0) {
    1060           0 :                 printf("%s: could not read register 0x%02x\n",
    1061           0 :                     sc->sc_dev.dv_xname, betoh32(reg));
    1062           0 :                 return error;
    1063             :         }
    1064           0 :         *val = betoh32(*(uint32_t *)read.data);
    1065           0 :         return error;
    1066           0 : }
    1067             : 
    1068             : int
    1069           0 : uath_read_eeprom(struct uath_softc *sc, uint32_t reg, void *odata)
    1070             : {
    1071           0 :         struct uath_read_mac read;
    1072             :         int len, error;
    1073             : 
    1074           0 :         reg = htobe32(reg);
    1075           0 :         error = uath_cmd_read(sc, UATH_CMD_READ_EEPROM, &reg, sizeof reg,
    1076             :             &read, 0);
    1077           0 :         if (error != 0) {
    1078           0 :                 printf("%s: could not read EEPROM offset 0x%02x\n",
    1079           0 :                     sc->sc_dev.dv_xname, betoh32(reg));
    1080           0 :                 return error;
    1081             :         }
    1082           0 :         len = betoh32(read.len);
    1083           0 :         bcopy(read.data, odata, (len == 0) ? sizeof (uint32_t) : len);
    1084           0 :         return error;
    1085           0 : }
    1086             : 
    1087             : void
    1088           0 : uath_cmd_rxeof(struct usbd_xfer *xfer, void *priv,
    1089             :     usbd_status status)
    1090             : {
    1091           0 :         struct uath_rx_cmd *cmd = priv;
    1092           0 :         struct uath_softc *sc = cmd->sc;
    1093             :         struct uath_cmd_hdr *hdr;
    1094             : 
    1095           0 :         if (status != USBD_NORMAL_COMPLETION) {
    1096           0 :                 if (status == USBD_STALLED)
    1097           0 :                         usbd_clear_endpoint_stall_async(sc->cmd_rx_pipe);
    1098           0 :                 return;
    1099             :         }
    1100             : 
    1101           0 :         hdr = (struct uath_cmd_hdr *)cmd->buf;
    1102             : 
    1103             : #ifdef UATH_DEBUG
    1104             :         if (uath_debug >= 5) {
    1105             :                 printf("received command code=0x%x index=%u len=%u",
    1106             :                     betoh32(hdr->code), hdr->priv, betoh32(hdr->len));
    1107             :                 uath_dump_cmd(cmd->buf, betoh32(hdr->len), '-');
    1108             :         }
    1109             : #endif
    1110             : 
    1111           0 :         switch (betoh32(hdr->code) & 0xff) {
    1112             :         /* reply to a read command */
    1113             :         default:
    1114             :         {
    1115           0 :                 struct uath_tx_cmd *txcmd = &sc->tx_cmd[hdr->priv];
    1116             : 
    1117           0 :                 if (txcmd->odata != NULL) {
    1118             :                         /* copy answer into caller's supplied buffer */
    1119           0 :                         bcopy((uint8_t *)(hdr + 1), txcmd->odata,
    1120           0 :                             betoh32(hdr->len) - sizeof (struct uath_cmd_hdr));
    1121           0 :                 }
    1122           0 :                 wakeup(txcmd);  /* wake up caller */
    1123             :                 break;
    1124             :         }
    1125             :         /* spontaneous firmware notifications */
    1126             :         case UATH_NOTIF_READY:
    1127             :                 DPRINTF(("received device ready notification\n"));
    1128           0 :                 wakeup(UATH_COND_INIT(sc));
    1129           0 :                 break;
    1130             : 
    1131             :         case UATH_NOTIF_TX:
    1132             :                 /* this notification is sent when UATH_TX_NOTIFY is set */
    1133             :                 DPRINTF(("received Tx notification\n"));
    1134             :                 break;
    1135             : 
    1136             :         case UATH_NOTIF_STATS:
    1137             :                 DPRINTFN(2, ("received device statistics\n"));
    1138           0 :                 timeout_add_sec(&sc->stat_to, 1);
    1139           0 :                 break;
    1140             :         }
    1141             : 
    1142             :         /* setup a new transfer */
    1143           0 :         usbd_setup_xfer(xfer, sc->cmd_rx_pipe, cmd, cmd->buf, UATH_MAX_RXCMDSZ,
    1144             :             USBD_SHORT_XFER_OK | USBD_NO_COPY, USBD_NO_TIMEOUT,
    1145             :             uath_cmd_rxeof);
    1146           0 :         (void)usbd_transfer(xfer);
    1147           0 : }
    1148             : 
    1149             : void
    1150           0 : uath_data_rxeof(struct usbd_xfer *xfer, void *priv,
    1151             :     usbd_status status)
    1152             : {
    1153           0 :         struct uath_rx_data *data = priv;
    1154           0 :         struct uath_softc *sc = data->sc;
    1155           0 :         struct ieee80211com *ic = &sc->sc_ic;
    1156           0 :         struct ifnet *ifp = &ic->ic_if;
    1157             :         struct ieee80211_frame *wh;
    1158           0 :         struct ieee80211_rxinfo rxi;
    1159             :         struct ieee80211_node *ni;
    1160             :         struct uath_rx_desc *desc;
    1161             :         struct mbuf *mnew, *m;
    1162             :         uint32_t hdr;
    1163           0 :         int s, len;
    1164             : 
    1165           0 :         if (status != USBD_NORMAL_COMPLETION) {
    1166           0 :                 if (status == USBD_NOT_STARTED || status == USBD_CANCELLED)
    1167           0 :                         return;
    1168             : 
    1169           0 :                 if (status == USBD_STALLED)
    1170           0 :                         usbd_clear_endpoint_stall_async(sc->data_rx_pipe);
    1171             : 
    1172           0 :                 ifp->if_ierrors++;
    1173           0 :                 return;
    1174             :         }
    1175           0 :         usbd_get_xfer_status(xfer, NULL, NULL, &len, NULL);
    1176             : 
    1177           0 :         if (len < UATH_MIN_RXBUFSZ) {
    1178             :                 DPRINTF(("wrong xfer size (len=%d)\n", len));
    1179           0 :                 ifp->if_ierrors++;
    1180           0 :                 goto skip;
    1181             :         }
    1182             : 
    1183           0 :         hdr = betoh32(*(uint32_t *)data->buf);
    1184             : 
    1185             :         /* Rx descriptor is located at the end, 32-bit aligned */
    1186           0 :         desc = (struct uath_rx_desc *)
    1187           0 :             (data->buf + len - sizeof (struct uath_rx_desc));
    1188             : 
    1189           0 :         if (betoh32(desc->len) > sc->rxbufsz) {
    1190             :                 DPRINTF(("bad descriptor (len=%d)\n", betoh32(desc->len)));
    1191           0 :                 ifp->if_ierrors++;
    1192           0 :                 goto skip;
    1193             :         }
    1194             : 
    1195             :         /* there's probably a "bad CRC" flag somewhere in the descriptor.. */
    1196             : 
    1197           0 :         MGETHDR(mnew, M_DONTWAIT, MT_DATA);
    1198           0 :         if (mnew == NULL) {
    1199           0 :                 printf("%s: could not allocate rx mbuf\n",
    1200           0 :                     sc->sc_dev.dv_xname);
    1201           0 :                 ifp->if_ierrors++;
    1202           0 :                 goto skip;
    1203             :         }
    1204           0 :         MCLGETI(mnew, M_DONTWAIT, NULL, sc->rxbufsz);
    1205           0 :         if (!(mnew->m_flags & M_EXT)) {
    1206           0 :                 printf("%s: could not allocate rx mbuf cluster\n",
    1207           0 :                     sc->sc_dev.dv_xname);
    1208           0 :                 m_freem(mnew);
    1209           0 :                 ifp->if_ierrors++;
    1210           0 :                 goto skip;
    1211             :         }
    1212             : 
    1213           0 :         m = data->m;
    1214           0 :         data->m = mnew;
    1215             : 
    1216             :         /* finalize mbuf */
    1217           0 :         m->m_data = data->buf + sizeof (uint32_t);
    1218           0 :         m->m_pkthdr.len = m->m_len = betoh32(desc->len) -
    1219           0 :             sizeof (struct uath_rx_desc) - IEEE80211_CRC_LEN;
    1220             : 
    1221           0 :         data->buf = mtod(data->m, uint8_t *);
    1222             : 
    1223           0 :         wh = mtod(m, struct ieee80211_frame *);
    1224           0 :         rxi.rxi_flags = 0;
    1225           0 :         if ((wh->i_fc[1] & IEEE80211_FC1_WEP) &&
    1226           0 :             ic->ic_opmode != IEEE80211_M_MONITOR) {
    1227             :                 /*
    1228             :                  * Hardware decrypts the frame itself but leaves the WEP bit
    1229             :                  * set in the 802.11 header and doesn't remove the IV and CRC
    1230             :                  * fields.
    1231             :                  */
    1232           0 :                 wh->i_fc[1] &= ~IEEE80211_FC1_WEP;
    1233           0 :                 memmove((caddr_t)wh + IEEE80211_WEP_IVLEN +
    1234             :                     IEEE80211_WEP_KIDLEN, wh, sizeof (struct ieee80211_frame));
    1235           0 :                 m_adj(m, IEEE80211_WEP_IVLEN + IEEE80211_WEP_KIDLEN);
    1236           0 :                 m_adj(m, -IEEE80211_WEP_CRCLEN);
    1237           0 :                 wh = mtod(m, struct ieee80211_frame *);
    1238             : 
    1239           0 :                 rxi.rxi_flags |= IEEE80211_RXI_HWDEC;
    1240           0 :         }
    1241             : 
    1242             : #if NBPFILTER > 0
    1243             :         /* there are a lot more fields in the Rx descriptor */
    1244           0 :         if (sc->sc_drvbpf != NULL) {
    1245           0 :                 struct mbuf mb;
    1246           0 :                 struct uath_rx_radiotap_header *tap = &sc->sc_rxtap;
    1247             : 
    1248           0 :                 tap->wr_flags = 0;
    1249           0 :                 tap->wr_chan_freq = htole16(betoh32(desc->freq));
    1250           0 :                 tap->wr_chan_flags = htole16(ic->ic_bss->ni_chan->ic_flags);
    1251           0 :                 tap->wr_dbm_antsignal = (int8_t)betoh32(desc->rssi);
    1252             : 
    1253           0 :                 mb.m_data = (caddr_t)tap;
    1254           0 :                 mb.m_len = sc->sc_rxtap_len;
    1255           0 :                 mb.m_next = m;
    1256           0 :                 mb.m_nextpkt = NULL;
    1257           0 :                 mb.m_type = 0;
    1258           0 :                 mb.m_flags = 0;
    1259           0 :                 bpf_mtap(sc->sc_drvbpf, &mb, BPF_DIRECTION_IN);
    1260           0 :         }
    1261             : #endif
    1262             : 
    1263           0 :         s = splnet();
    1264           0 :         ni = ieee80211_find_rxnode(ic, wh);
    1265           0 :         rxi.rxi_rssi = (int)betoh32(desc->rssi);
    1266           0 :         rxi.rxi_tstamp = 0;     /* unused */
    1267           0 :         ieee80211_input(ifp, m, ni, &rxi);
    1268             : 
    1269             :         /* node is no longer needed */
    1270           0 :         ieee80211_release_node(ic, ni);
    1271           0 :         splx(s);
    1272             : 
    1273             : skip:   /* setup a new transfer */
    1274           0 :         usbd_setup_xfer(xfer, sc->data_rx_pipe, data, data->buf, sc->rxbufsz,
    1275             :             USBD_SHORT_XFER_OK, USBD_NO_TIMEOUT, uath_data_rxeof);
    1276           0 :         (void)usbd_transfer(data->xfer);
    1277           0 : }
    1278             : 
    1279             : int
    1280           0 : uath_tx_null(struct uath_softc *sc)
    1281             : {
    1282             :         struct uath_tx_data *data;
    1283             :         struct uath_tx_desc *desc;
    1284             : 
    1285           0 :         data = &sc->tx_data[sc->data_idx];
    1286             : 
    1287           0 :         data->ni = NULL;
    1288             : 
    1289           0 :         *(uint32_t *)data->buf = UATH_MAKECTL(1, sizeof (struct uath_tx_desc));
    1290           0 :         desc = (struct uath_tx_desc *)(data->buf + sizeof (uint32_t));
    1291             : 
    1292           0 :         bzero(desc, sizeof (struct uath_tx_desc));
    1293           0 :         desc->len  = htobe32(sizeof (struct uath_tx_desc));
    1294           0 :         desc->type = htobe32(UATH_TX_NULL);
    1295             : 
    1296           0 :         usbd_setup_xfer(data->xfer, sc->data_tx_pipe, data, data->buf,
    1297             :             sizeof (uint32_t) + sizeof (struct uath_tx_desc), USBD_NO_COPY |
    1298             :             USBD_FORCE_SHORT_XFER | USBD_SYNCHRONOUS, UATH_DATA_TIMEOUT, NULL);
    1299           0 :         if (usbd_transfer(data->xfer) != 0)
    1300           0 :                 return EIO;
    1301             : 
    1302           0 :         sc->data_idx = (sc->data_idx + 1) % UATH_TX_DATA_LIST_COUNT;
    1303             : 
    1304           0 :         return uath_cmd_write(sc, UATH_CMD_0F, NULL, 0, UATH_CMD_FLAG_ASYNC);
    1305           0 : }
    1306             : 
    1307             : void
    1308           0 : uath_data_txeof(struct usbd_xfer *xfer, void *priv,
    1309             :     usbd_status status)
    1310             : {
    1311           0 :         struct uath_tx_data *data = priv;
    1312           0 :         struct uath_softc *sc = data->sc;
    1313           0 :         struct ieee80211com *ic = &sc->sc_ic;
    1314           0 :         struct ifnet *ifp = &ic->ic_if;
    1315             :         int s;
    1316             : 
    1317           0 :         if (status != USBD_NORMAL_COMPLETION) {
    1318           0 :                 if (status == USBD_NOT_STARTED || status == USBD_CANCELLED)
    1319           0 :                         return;
    1320             : 
    1321           0 :                 printf("%s: could not transmit buffer: %s\n",
    1322           0 :                     sc->sc_dev.dv_xname, usbd_errstr(status));
    1323             : 
    1324           0 :                 if (status == USBD_STALLED)
    1325           0 :                         usbd_clear_endpoint_stall_async(sc->data_tx_pipe);
    1326             : 
    1327           0 :                 ifp->if_oerrors++;
    1328           0 :                 return;
    1329             :         }
    1330             : 
    1331           0 :         s = splnet();
    1332             : 
    1333           0 :         ieee80211_release_node(ic, data->ni);
    1334           0 :         data->ni = NULL;
    1335             : 
    1336           0 :         sc->tx_queued--;
    1337             : 
    1338           0 :         sc->sc_tx_timer = 0;
    1339           0 :         ifq_clr_oactive(&ifp->if_snd);
    1340           0 :         uath_start(ifp);
    1341             : 
    1342           0 :         splx(s);
    1343           0 : }
    1344             : 
    1345             : int
    1346           0 : uath_tx_data(struct uath_softc *sc, struct mbuf *m0, struct ieee80211_node *ni)
    1347             : {
    1348           0 :         struct ieee80211com *ic = &sc->sc_ic;
    1349             :         struct uath_tx_data *data;
    1350             :         struct uath_tx_desc *desc;
    1351             :         const struct ieee80211_frame *wh;
    1352             :         int paylen, totlen, xferlen, error;
    1353             : 
    1354           0 :         data = &sc->tx_data[sc->data_idx];
    1355           0 :         desc = (struct uath_tx_desc *)(data->buf + sizeof (uint32_t));
    1356             : 
    1357           0 :         data->ni = ni;
    1358             : 
    1359             : #if NBPFILTER > 0
    1360           0 :         if (sc->sc_drvbpf != NULL) {
    1361           0 :                 struct mbuf mb;
    1362           0 :                 struct uath_tx_radiotap_header *tap = &sc->sc_txtap;
    1363             : 
    1364           0 :                 tap->wt_flags = 0;
    1365           0 :                 tap->wt_chan_freq = htole16(ic->ic_bss->ni_chan->ic_freq);
    1366           0 :                 tap->wt_chan_flags = htole16(ic->ic_bss->ni_chan->ic_flags);
    1367             : 
    1368           0 :                 mb.m_data = (caddr_t)tap;
    1369           0 :                 mb.m_len = sc->sc_txtap_len;
    1370           0 :                 mb.m_next = m0;
    1371           0 :                 mb.m_nextpkt = NULL;
    1372           0 :                 mb.m_type = 0;
    1373           0 :                 mb.m_flags = 0;
    1374           0 :                 bpf_mtap(sc->sc_drvbpf, &mb, BPF_DIRECTION_OUT);
    1375           0 :         }
    1376             : #endif
    1377             : 
    1378           0 :         paylen = m0->m_pkthdr.len;
    1379           0 :         xferlen = sizeof (uint32_t) + sizeof (struct uath_tx_desc) + paylen;
    1380             : 
    1381           0 :         wh = mtod(m0, struct ieee80211_frame *);
    1382           0 :         if (wh->i_fc[1] & IEEE80211_FC1_WEP) {
    1383           0 :                 uint8_t *frm = (uint8_t *)(desc + 1);
    1384             :                 uint32_t iv;
    1385             : 
    1386             :                 /* h/w WEP: it's up to the host to fill the IV field */
    1387           0 :                 bcopy(wh, frm, sizeof (struct ieee80211_frame));
    1388           0 :                 frm += sizeof (struct ieee80211_frame);
    1389             : 
    1390             :                 /* insert IV: code copied from net80211 */
    1391           0 :                 iv = (ic->ic_iv != 0) ? ic->ic_iv : arc4random();
    1392           0 :                 if (iv >= 0x03ff00 && (iv & 0xf8ff00) == 0x00ff00)
    1393           0 :                         iv += 0x000100;
    1394           0 :                 ic->ic_iv = iv + 1;
    1395             : 
    1396           0 :                 *frm++ = iv & 0xff;
    1397           0 :                 *frm++ = (iv >>  8) & 0xff;
    1398           0 :                 *frm++ = (iv >> 16) & 0xff;
    1399           0 :                 *frm++ = ic->ic_wep_txkey << 6;
    1400             : 
    1401           0 :                 m_copydata(m0, sizeof (struct ieee80211_frame),
    1402           0 :                     m0->m_pkthdr.len - sizeof (struct ieee80211_frame), frm);
    1403             : 
    1404           0 :                 paylen  += IEEE80211_WEP_IVLEN + IEEE80211_WEP_KIDLEN;
    1405           0 :                 xferlen += IEEE80211_WEP_IVLEN + IEEE80211_WEP_KIDLEN;
    1406           0 :                 totlen = xferlen + IEEE80211_WEP_CRCLEN;
    1407           0 :         } else {
    1408           0 :                 m_copydata(m0, 0, m0->m_pkthdr.len, (uint8_t *)(desc + 1));
    1409             :                 totlen = xferlen;
    1410             :         }
    1411             : 
    1412             :         /* fill Tx descriptor */
    1413           0 :         *(uint32_t *)data->buf = UATH_MAKECTL(1, xferlen - sizeof (uint32_t));
    1414             : 
    1415           0 :         desc->len    = htobe32(totlen);
    1416           0 :         desc->priv   = sc->data_idx;      /* don't care about endianness */
    1417           0 :         desc->paylen = htobe32(paylen);
    1418           0 :         desc->type   = htobe32(UATH_TX_DATA);
    1419           0 :         desc->flags  = htobe32(0);
    1420           0 :         if (IEEE80211_IS_MULTICAST(wh->i_addr1)) {
    1421           0 :                 desc->dest  = htobe32(UATH_ID_BROADCAST);
    1422           0 :                 desc->magic = htobe32(3);
    1423           0 :         } else {
    1424           0 :                 desc->dest  = htobe32(UATH_ID_BSS);
    1425           0 :                 desc->magic = htobe32(1);
    1426             :         }
    1427             : 
    1428           0 :         m_freem(m0);    /* mbuf is no longer needed */
    1429             : 
    1430             : #ifdef UATH_DEBUG
    1431             :         if (uath_debug >= 6) {
    1432             :                 printf("sending frame index=%u len=%d xferlen=%d",
    1433             :                     sc->data_idx, paylen, xferlen);
    1434             :                 uath_dump_cmd(data->buf, xferlen, '+');
    1435             :         }
    1436             : #endif
    1437           0 :         usbd_setup_xfer(data->xfer, sc->data_tx_pipe, data, data->buf, xferlen,
    1438             :             USBD_FORCE_SHORT_XFER | USBD_NO_COPY, UATH_DATA_TIMEOUT,
    1439             :             uath_data_txeof);
    1440           0 :         error = usbd_transfer(data->xfer);
    1441           0 :         if (error != USBD_IN_PROGRESS && error != 0) {
    1442           0 :                 ic->ic_if.if_oerrors++;
    1443           0 :                 return error;
    1444             :         }
    1445           0 :         sc->data_idx = (sc->data_idx + 1) % UATH_TX_DATA_LIST_COUNT;
    1446           0 :         sc->tx_queued++;
    1447             : 
    1448           0 :         return 0;
    1449           0 : }
    1450             : 
    1451             : void
    1452           0 : uath_start(struct ifnet *ifp)
    1453             : {
    1454           0 :         struct uath_softc *sc = ifp->if_softc;
    1455           0 :         struct ieee80211com *ic = &sc->sc_ic;
    1456           0 :         struct ieee80211_node *ni;
    1457             :         struct mbuf *m0;
    1458             : 
    1459             :         /*
    1460             :          * net80211 may still try to send management frames even if the
    1461             :          * IFF_RUNNING flag is not set...
    1462             :          */
    1463           0 :         if (!(ifp->if_flags & IFF_RUNNING) && ifq_is_oactive(&ifp->if_snd))
    1464           0 :                 return;
    1465             : 
    1466           0 :         for (;;) {
    1467           0 :                 if (sc->tx_queued >= UATH_TX_DATA_LIST_COUNT) {
    1468           0 :                         ifq_set_oactive(&ifp->if_snd);
    1469           0 :                         break;
    1470             :                 }
    1471             : 
    1472           0 :                 m0 = mq_dequeue(&ic->ic_mgtq);
    1473           0 :                 if (m0 != NULL) {
    1474           0 :                         ni = m0->m_pkthdr.ph_cookie;
    1475             : #if NBPFILTER > 0
    1476           0 :                         if (ic->ic_rawbpf != NULL)
    1477           0 :                                 bpf_mtap(ic->ic_rawbpf, m0, BPF_DIRECTION_OUT);
    1478             : #endif
    1479           0 :                         if (uath_tx_data(sc, m0, ni) != 0)
    1480             :                                 break;
    1481             :                 } else {
    1482           0 :                         if (ic->ic_state != IEEE80211_S_RUN)
    1483             :                                 break;
    1484             : 
    1485           0 :                         IFQ_DEQUEUE(&ifp->if_snd, m0);
    1486           0 :                         if (m0 == NULL)
    1487             :                                 break;
    1488             : #if NBPFILTER > 0
    1489           0 :                         if (ifp->if_bpf != NULL)
    1490           0 :                                 bpf_mtap(ifp->if_bpf, m0, BPF_DIRECTION_OUT);
    1491             : #endif
    1492           0 :                         m0 = ieee80211_encap(ifp, m0, &ni);
    1493           0 :                         if (m0 == NULL)
    1494           0 :                                 continue;
    1495             : #if NBPFILTER > 0
    1496           0 :                         if (ic->ic_rawbpf != NULL)
    1497           0 :                                 bpf_mtap(ic->ic_rawbpf, m0, BPF_DIRECTION_OUT);
    1498             : #endif
    1499           0 :                         if (uath_tx_data(sc, m0, ni) != 0) {
    1500           0 :                                 if (ni != NULL)
    1501           0 :                                         ieee80211_release_node(ic, ni);
    1502           0 :                                 ifp->if_oerrors++;
    1503           0 :                                 break;
    1504             :                         }
    1505             :                 }
    1506             : 
    1507           0 :                 sc->sc_tx_timer = 5;
    1508           0 :                 ifp->if_timer = 1;
    1509             :         }
    1510           0 : }
    1511             : 
    1512             : void
    1513           0 : uath_watchdog(struct ifnet *ifp)
    1514             : {
    1515           0 :         struct uath_softc *sc = ifp->if_softc;
    1516             : 
    1517           0 :         ifp->if_timer = 0;
    1518             : 
    1519           0 :         if (sc->sc_tx_timer > 0) {
    1520           0 :                 if (--sc->sc_tx_timer == 0) {
    1521           0 :                         printf("%s: device timeout\n", sc->sc_dev.dv_xname);
    1522             :                         /*uath_init(ifp); XXX needs a process context! */
    1523           0 :                         ifp->if_oerrors++;
    1524           0 :                         return;
    1525             :                 }
    1526           0 :                 ifp->if_timer = 1;
    1527           0 :         }
    1528             : 
    1529           0 :         ieee80211_watchdog(ifp);
    1530           0 : }
    1531             : 
    1532             : int
    1533           0 : uath_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
    1534             : {
    1535             :         int s, error = 0;
    1536             : 
    1537           0 :         s = splnet();
    1538             : 
    1539           0 :         switch (cmd) {
    1540             :         case SIOCSIFADDR:
    1541           0 :                 ifp->if_flags |= IFF_UP;
    1542             :                 /* FALLTHROUGH */
    1543             :         case SIOCSIFFLAGS:
    1544           0 :                 if (ifp->if_flags & IFF_UP) {
    1545           0 :                         if (!(ifp->if_flags & IFF_RUNNING))
    1546           0 :                                 uath_init(ifp);
    1547             :                 } else {
    1548           0 :                         if (ifp->if_flags & IFF_RUNNING)
    1549           0 :                                 uath_stop(ifp, 1);
    1550             :                 }
    1551             :                 break;
    1552             : 
    1553             :         default:
    1554           0 :                 error = ieee80211_ioctl(ifp, cmd, data);
    1555           0 :         }
    1556             : 
    1557           0 :         if (error == ENETRESET) {
    1558           0 :                 if ((ifp->if_flags & (IFF_UP | IFF_RUNNING)) ==
    1559             :                     (IFF_UP | IFF_RUNNING))
    1560           0 :                         uath_init(ifp);
    1561             :                 error = 0;
    1562           0 :         }
    1563             : 
    1564           0 :         splx(s);
    1565             : 
    1566           0 :         return error;
    1567             : }
    1568             : 
    1569             : int
    1570           0 : uath_query_eeprom(struct uath_softc *sc)
    1571             : {
    1572           0 :         uint32_t tmp;
    1573             :         int error;
    1574             : 
    1575             :         /* retrieve MAC address */
    1576           0 :         error = uath_read_eeprom(sc, UATH_EEPROM_MACADDR, sc->sc_ic.ic_myaddr);
    1577           0 :         if (error != 0) {
    1578           0 :                 printf("%s: could not read MAC address\n",
    1579           0 :                     sc->sc_dev.dv_xname);
    1580           0 :                 return error;
    1581             :         }
    1582             : 
    1583             :         /* retrieve the maximum frame size that the hardware can receive */
    1584           0 :         error = uath_read_eeprom(sc, UATH_EEPROM_RXBUFSZ, &tmp);
    1585           0 :         if (error != 0) {
    1586           0 :                 printf("%s: could not read maximum Rx buffer size\n",
    1587           0 :                     sc->sc_dev.dv_xname);
    1588           0 :                 return error;
    1589             :         }
    1590           0 :         sc->rxbufsz = betoh32(tmp) & 0xfff;
    1591             :         DPRINTF(("maximum Rx buffer size %d\n", sc->rxbufsz));
    1592           0 :         return 0;
    1593           0 : }
    1594             : 
    1595             : int
    1596           0 : uath_reset(struct uath_softc *sc)
    1597             : {
    1598           0 :         struct uath_cmd_setup setup;
    1599           0 :         uint32_t reg, val;
    1600             :         int s, error;
    1601             : 
    1602             :         /* init device with some voodoo incantations.. */
    1603           0 :         setup.magic1 = htobe32(1);
    1604           0 :         setup.magic2 = htobe32(5);
    1605           0 :         setup.magic3 = htobe32(200);
    1606           0 :         setup.magic4 = htobe32(27);
    1607           0 :         s = splusb();
    1608           0 :         error = uath_cmd_write(sc, UATH_CMD_SETUP, &setup, sizeof setup,
    1609             :             UATH_CMD_FLAG_ASYNC);
    1610             :         /* ..and wait until firmware notifies us that it is ready */
    1611           0 :         if (error == 0)
    1612           0 :                 error = tsleep(UATH_COND_INIT(sc), PCATCH, "uathinit", 5 * hz);
    1613           0 :         splx(s);
    1614           0 :         if (error != 0)
    1615           0 :                 return error;
    1616             : 
    1617             :         /* read PHY registers */
    1618           0 :         for (reg = 0x09; reg <= 0x24; reg++) {
    1619           0 :                 if (reg == 0x0b || reg == 0x0c)
    1620             :                         continue;
    1621           0 :                 DELAY(100);
    1622           0 :                 if ((error = uath_read_reg(sc, reg, &val)) != 0)
    1623           0 :                         return error;
    1624             :                 DPRINTFN(2, ("reg 0x%02x=0x%08x\n", reg, val));
    1625             :         }
    1626           0 :         return error;
    1627           0 : }
    1628             : 
    1629             : int
    1630           0 : uath_reset_tx_queues(struct uath_softc *sc)
    1631             : {
    1632             :         int ac, error;
    1633             : 
    1634           0 :         for (ac = 0; ac < 4; ac++) {
    1635           0 :                 const uint32_t qid = htobe32(UATH_AC_TO_QID(ac));
    1636             : 
    1637             :                 DPRINTF(("resetting Tx queue %d\n", UATH_AC_TO_QID(ac)));
    1638           0 :                 error = uath_cmd_write(sc, UATH_CMD_RESET_QUEUE, &qid,
    1639             :                     sizeof qid, 0);
    1640           0 :                 if (error != 0)
    1641           0 :                         break;
    1642           0 :         }
    1643           0 :         return error;
    1644             : }
    1645             : 
    1646             : int
    1647           0 : uath_wme_init(struct uath_softc *sc)
    1648             : {
    1649           0 :         struct uath_qinfo qinfo;
    1650             :         int ac, error;
    1651             :         static const struct uath_wme_settings uath_wme_11g[4] = {
    1652             :                 { 7, 4, 10,  0, 0 },    /* Background */
    1653             :                 { 3, 4, 10,  0, 0 },    /* Best-Effort */
    1654             :                 { 3, 3,  4, 26, 0 },    /* Video */
    1655             :                 { 2, 2,  3, 47, 0 }     /* Voice */
    1656             :         };
    1657             : 
    1658           0 :         bzero(&qinfo, sizeof qinfo);
    1659           0 :         qinfo.size   = htobe32(32);
    1660           0 :         qinfo.magic1 = htobe32(1);      /* XXX ack policy? */
    1661           0 :         qinfo.magic2 = htobe32(1);
    1662           0 :         for (ac = 0; ac < 4; ac++) {
    1663           0 :                 qinfo.qid      = htobe32(UATH_AC_TO_QID(ac));
    1664           0 :                 qinfo.ac       = htobe32(ac);
    1665           0 :                 qinfo.aifsn    = htobe32(uath_wme_11g[ac].aifsn);
    1666           0 :                 qinfo.logcwmin = htobe32(uath_wme_11g[ac].logcwmin);
    1667           0 :                 qinfo.logcwmax = htobe32(uath_wme_11g[ac].logcwmax);
    1668           0 :                 qinfo.txop     = htobe32(UATH_TXOP_TO_US(
    1669             :                                      uath_wme_11g[ac].txop));
    1670           0 :                 qinfo.acm      = htobe32(uath_wme_11g[ac].acm);
    1671             : 
    1672             :                 DPRINTF(("setting up Tx queue %d\n", UATH_AC_TO_QID(ac)));
    1673           0 :                 error = uath_cmd_write(sc, UATH_CMD_SET_QUEUE, &qinfo,
    1674             :                     sizeof qinfo, 0);
    1675           0 :                 if (error != 0)
    1676             :                         break;
    1677             :         }
    1678           0 :         return error;
    1679           0 : }
    1680             : 
    1681             : int
    1682           0 : uath_set_chan(struct uath_softc *sc, struct ieee80211_channel *c)
    1683             : {
    1684           0 :         struct uath_set_chan chan;
    1685             : 
    1686           0 :         bzero(&chan, sizeof chan);
    1687           0 :         chan.flags  = htobe32(0x1400);
    1688           0 :         chan.freq   = htobe32(c->ic_freq);
    1689           0 :         chan.magic1 = htobe32(20);
    1690           0 :         chan.magic2 = htobe32(50);
    1691           0 :         chan.magic3 = htobe32(1);
    1692             : 
    1693             :         DPRINTF(("switching to channel %d\n",
    1694             :             ieee80211_chan2ieee(&sc->sc_ic, c)));
    1695           0 :         return uath_cmd_write(sc, UATH_CMD_SET_CHAN, &chan, sizeof chan, 0);
    1696           0 : }
    1697             : 
    1698             : int
    1699           0 : uath_set_key(struct uath_softc *sc, const struct ieee80211_key *k, int index)
    1700             : {
    1701           0 :         struct uath_cmd_crypto crypto;
    1702             :         int i;
    1703             : 
    1704           0 :         bzero(&crypto, sizeof crypto);
    1705           0 :         crypto.keyidx = htobe32(index);
    1706           0 :         crypto.magic1 = htobe32(1);
    1707           0 :         crypto.size   = htobe32(368);
    1708           0 :         crypto.mask   = htobe32(0xffff);
    1709           0 :         crypto.flags  = htobe32(0x80000068);
    1710           0 :         if (index != UATH_DEFAULT_KEY)
    1711           0 :                 crypto.flags |= htobe32(index << 16);
    1712           0 :         memset(crypto.magic2, 0xff, sizeof crypto.magic2);
    1713             : 
    1714             :         /*
    1715             :          * Each byte of the key must be XOR'ed with 10101010 before being
    1716             :          * transmitted to the firmware.
    1717             :          */
    1718           0 :         for (i = 0; i < k->k_len; i++)
    1719           0 :                 crypto.key[i] = k->k_key[i] ^ 0xaa;
    1720             : 
    1721             :         DPRINTF(("setting crypto key index=%d len=%d\n", index, k->k_len));
    1722           0 :         return uath_cmd_write(sc, UATH_CMD_CRYPTO, &crypto, sizeof crypto, 0);
    1723           0 : }
    1724             : 
    1725             : int
    1726           0 : uath_set_keys(struct uath_softc *sc)
    1727             : {
    1728           0 :         const struct ieee80211com *ic = &sc->sc_ic;
    1729             :         int i, error;
    1730             : 
    1731           0 :         for (i = 0; i < IEEE80211_WEP_NKID; i++) {
    1732           0 :                 const struct ieee80211_key *k = &ic->ic_nw_keys[i];
    1733             : 
    1734           0 :                 if (k->k_len > 0 && (error = uath_set_key(sc, k, i)) != 0)
    1735           0 :                         return error;
    1736           0 :         }
    1737           0 :         return uath_set_key(sc, &ic->ic_nw_keys[ic->ic_wep_txkey],
    1738             :             UATH_DEFAULT_KEY);
    1739           0 : }
    1740             : 
    1741             : int
    1742           0 : uath_set_rates(struct uath_softc *sc, const struct ieee80211_rateset *rs)
    1743             : {
    1744           0 :         struct uath_cmd_rates rates;
    1745             : 
    1746           0 :         bzero(&rates, sizeof rates);
    1747           0 :         rates.magic1 = htobe32(0x02);
    1748           0 :         rates.size   = htobe32(1 + sizeof rates.rates);
    1749           0 :         rates.nrates = rs->rs_nrates;
    1750           0 :         bcopy(rs->rs_rates, rates.rates, rs->rs_nrates);
    1751             : 
    1752             :         DPRINTF(("setting supported rates nrates=%d\n", rs->rs_nrates));
    1753           0 :         return uath_cmd_write(sc, UATH_CMD_SET_RATES, &rates, sizeof rates, 0);
    1754           0 : }
    1755             : 
    1756             : int
    1757           0 : uath_set_rxfilter(struct uath_softc *sc, uint32_t filter, uint32_t flags)
    1758             : {
    1759           0 :         struct uath_cmd_filter rxfilter;
    1760             : 
    1761           0 :         rxfilter.filter = htobe32(filter);
    1762           0 :         rxfilter.flags  = htobe32(flags);
    1763             : 
    1764             :         DPRINTF(("setting Rx filter=0x%x flags=0x%x\n", filter, flags));
    1765           0 :         return uath_cmd_write(sc, UATH_CMD_SET_FILTER, &rxfilter,
    1766             :             sizeof rxfilter, 0);
    1767           0 : }
    1768             : 
    1769             : int
    1770           0 : uath_set_led(struct uath_softc *sc, int which, int on)
    1771             : {
    1772           0 :         struct uath_cmd_led led;
    1773             : 
    1774           0 :         led.which = htobe32(which);
    1775           0 :         led.state = htobe32(on ? UATH_LED_ON : UATH_LED_OFF);
    1776             : 
    1777             :         DPRINTFN(2, ("switching %s led %s\n",
    1778             :             (which == UATH_LED_LINK) ? "link" : "activity",
    1779             :             on ? "on" : "off"));
    1780           0 :         return uath_cmd_write(sc, UATH_CMD_SET_LED, &led, sizeof led, 0);
    1781           0 : }
    1782             : 
    1783             : int
    1784           0 : uath_switch_channel(struct uath_softc *sc, struct ieee80211_channel *c)
    1785             : {
    1786           0 :         uint32_t val;
    1787             :         int error;
    1788             : 
    1789             :         /* set radio frequency */
    1790           0 :         if ((error = uath_set_chan(sc, c)) != 0) {
    1791           0 :                 printf("%s: could not set channel\n", sc->sc_dev.dv_xname);
    1792           0 :                 return error;
    1793             :         }
    1794             : 
    1795             :         /* reset Tx rings */
    1796           0 :         if ((error = uath_reset_tx_queues(sc)) != 0) {
    1797           0 :                 printf("%s: could not reset Tx queues\n",
    1798           0 :                     sc->sc_dev.dv_xname);
    1799           0 :                 return error;
    1800             :         }
    1801             : 
    1802             :         /* set Tx rings WME properties */
    1803           0 :         if ((error = uath_wme_init(sc)) != 0) {
    1804           0 :                 printf("%s: could not init Tx queues\n",
    1805           0 :                     sc->sc_dev.dv_xname);
    1806           0 :                 return error;
    1807             :         }
    1808             : 
    1809           0 :         val = htobe32(0);
    1810           0 :         error = uath_cmd_write(sc, UATH_CMD_SET_STATE, &val, sizeof val, 0);
    1811           0 :         if (error != 0) {
    1812           0 :                 printf("%s: could not set state\n", sc->sc_dev.dv_xname);
    1813           0 :                 return error;
    1814             :         }
    1815             : 
    1816           0 :         return uath_tx_null(sc);
    1817           0 : }
    1818             : 
    1819             : int
    1820           0 : uath_init(struct ifnet *ifp)
    1821             : {
    1822           0 :         struct uath_softc *sc = ifp->if_softc;
    1823           0 :         struct ieee80211com *ic = &sc->sc_ic;
    1824           0 :         struct uath_cmd_31 cmd31;
    1825           0 :         uint32_t val;
    1826             :         int i, error;
    1827             : 
    1828             :         /* reset data and command rings */
    1829           0 :         sc->tx_queued = sc->data_idx = sc->cmd_idx = 0;
    1830             : 
    1831           0 :         val = htobe32(0);
    1832           0 :         (void)uath_cmd_write(sc, UATH_CMD_02, &val, sizeof val, 0);
    1833             : 
    1834             :         /* set MAC address */
    1835           0 :         IEEE80211_ADDR_COPY(ic->ic_myaddr, LLADDR(ifp->if_sadl));
    1836           0 :         (void)uath_write_multi(sc, 0x13, ic->ic_myaddr, IEEE80211_ADDR_LEN);
    1837             : 
    1838           0 :         (void)uath_write_reg(sc, 0x02, 0x00000001);
    1839           0 :         (void)uath_write_reg(sc, 0x0e, 0x0000003f);
    1840           0 :         (void)uath_write_reg(sc, 0x10, 0x00000001);
    1841           0 :         (void)uath_write_reg(sc, 0x06, 0x0000001e);
    1842             : 
    1843             :         /*
    1844             :          * Queue Rx data xfers.
    1845             :          */
    1846           0 :         for (i = 0; i < UATH_RX_DATA_LIST_COUNT; i++) {
    1847           0 :                 struct uath_rx_data *data = &sc->rx_data[i];
    1848             : 
    1849           0 :                 usbd_setup_xfer(data->xfer, sc->data_rx_pipe, data, data->buf,
    1850           0 :                     sc->rxbufsz, USBD_SHORT_XFER_OK, USBD_NO_TIMEOUT,
    1851             :                     uath_data_rxeof);
    1852           0 :                 error = usbd_transfer(data->xfer);
    1853           0 :                 if (error != USBD_IN_PROGRESS && error != 0) {
    1854           0 :                         printf("%s: could not queue Rx transfer\n",
    1855           0 :                             sc->sc_dev.dv_xname);
    1856           0 :                         goto fail;
    1857             :                 }
    1858           0 :         }
    1859             : 
    1860           0 :         error = uath_cmd_read(sc, UATH_CMD_07, NULL, 0, &val,
    1861             :             UATH_CMD_FLAG_MAGIC);
    1862           0 :         if (error != 0) {
    1863           0 :                 printf("%s: could not send read command 07h\n",
    1864           0 :                     sc->sc_dev.dv_xname);
    1865           0 :                 goto fail;
    1866             :         }
    1867             :         DPRINTF(("command 07h return code: %x\n", betoh32(val)));
    1868             : 
    1869             :         /* set default channel */
    1870           0 :         ic->ic_bss->ni_chan = ic->ic_ibss_chan;
    1871           0 :         if ((error = uath_set_chan(sc, ic->ic_bss->ni_chan)) != 0) {
    1872           0 :                 printf("%s: could not set channel\n", sc->sc_dev.dv_xname);
    1873           0 :                 goto fail;
    1874             :         }
    1875             : 
    1876           0 :         if ((error = uath_wme_init(sc)) != 0) {
    1877           0 :                 printf("%s: could not setup WME parameters\n",
    1878           0 :                     sc->sc_dev.dv_xname);
    1879           0 :                 goto fail;
    1880             :         }
    1881             : 
    1882             :         /* init MAC registers */
    1883           0 :         (void)uath_write_reg(sc, 0x19, 0x00000000);
    1884           0 :         (void)uath_write_reg(sc, 0x1a, 0x0000003c);
    1885           0 :         (void)uath_write_reg(sc, 0x1b, 0x0000003c);
    1886           0 :         (void)uath_write_reg(sc, 0x1c, 0x00000000);
    1887           0 :         (void)uath_write_reg(sc, 0x1e, 0x00000000);
    1888           0 :         (void)uath_write_reg(sc, 0x1f, 0x00000003);
    1889           0 :         (void)uath_write_reg(sc, 0x0c, 0x00000000);
    1890           0 :         (void)uath_write_reg(sc, 0x0f, 0x00000002);
    1891           0 :         (void)uath_write_reg(sc, 0x0a, 0x00000007);     /* XXX retry? */
    1892           0 :         (void)uath_write_reg(sc, 0x09, ic->ic_rtsthreshold);
    1893             : 
    1894           0 :         val = htobe32(4);
    1895           0 :         (void)uath_cmd_write(sc, UATH_CMD_27, &val, sizeof val, 0);
    1896           0 :         (void)uath_cmd_write(sc, UATH_CMD_27, &val, sizeof val, 0);
    1897           0 :         (void)uath_cmd_write(sc, UATH_CMD_1B, NULL, 0, 0);
    1898             : 
    1899           0 :         if ((error = uath_set_keys(sc)) != 0) {
    1900           0 :                 printf("%s: could not set crypto keys\n",
    1901           0 :                     sc->sc_dev.dv_xname);
    1902           0 :                 goto fail;
    1903             :         }
    1904             : 
    1905             :         /* enable Rx */
    1906           0 :         (void)uath_set_rxfilter(sc, 0x0000, 4);
    1907           0 :         (void)uath_set_rxfilter(sc, 0x0817, 1);
    1908             : 
    1909           0 :         cmd31.magic1 = htobe32(0xffffffff);
    1910           0 :         cmd31.magic2 = htobe32(0xffffffff);
    1911           0 :         (void)uath_cmd_write(sc, UATH_CMD_31, &cmd31, sizeof cmd31, 0);
    1912             : 
    1913           0 :         ifp->if_flags |= IFF_RUNNING;
    1914           0 :         ifq_clr_oactive(&ifp->if_snd);
    1915             : 
    1916           0 :         if (ic->ic_opmode == IEEE80211_M_MONITOR)
    1917           0 :                 ieee80211_new_state(ic, IEEE80211_S_RUN, -1);
    1918             :         else
    1919           0 :                 ieee80211_new_state(ic, IEEE80211_S_SCAN, -1);
    1920             : 
    1921           0 :         return 0;
    1922             : 
    1923           0 : fail:   uath_stop(ifp, 1);
    1924           0 :         return error;
    1925           0 : }
    1926             : 
    1927             : void
    1928           0 : uath_stop(struct ifnet *ifp, int disable)
    1929             : {
    1930           0 :         struct uath_softc *sc = ifp->if_softc;
    1931           0 :         struct ieee80211com *ic = &sc->sc_ic;
    1932           0 :         uint32_t val;
    1933             :         int s;
    1934             : 
    1935           0 :         s = splusb();
    1936             : 
    1937           0 :         sc->sc_tx_timer = 0;
    1938           0 :         ifp->if_timer = 0;
    1939           0 :         ifp->if_flags &= ~IFF_RUNNING;
    1940           0 :         ifq_clr_oactive(&ifp->if_snd);
    1941             : 
    1942           0 :         ieee80211_new_state(ic, IEEE80211_S_INIT, -1);  /* free all nodes */
    1943             : 
    1944           0 :         val = htobe32(0);
    1945           0 :         (void)uath_cmd_write(sc, UATH_CMD_SET_STATE, &val, sizeof val, 0);
    1946           0 :         (void)uath_cmd_write(sc, UATH_CMD_RESET, NULL, 0, 0);
    1947             : 
    1948           0 :         val = htobe32(0);
    1949           0 :         (void)uath_cmd_write(sc, UATH_CMD_15, &val, sizeof val, 0);
    1950             : 
    1951             : #if 0
    1952             :         (void)uath_cmd_read(sc, UATH_CMD_SHUTDOWN, NULL, 0, NULL,
    1953             :             UATH_CMD_FLAG_MAGIC);
    1954             : #endif
    1955             : 
    1956             :         /* abort any pending transfers */
    1957           0 :         usbd_abort_pipe(sc->data_tx_pipe);
    1958           0 :         usbd_abort_pipe(sc->data_rx_pipe);
    1959           0 :         usbd_abort_pipe(sc->cmd_tx_pipe);
    1960             : 
    1961           0 :         splx(s);
    1962           0 : }
    1963             : 
    1964             : /*
    1965             :  * Load the MIPS R4000 microcode into the device.  Once the image is loaded,
    1966             :  * the device will detach itself from the bus and reattach later with a new
    1967             :  * product Id (a la ezusb).  XXX this could also be implemented in userland
    1968             :  * through /dev/ugen.
    1969             :  */
    1970             : int
    1971           0 : uath_loadfirmware(struct uath_softc *sc, const u_char *fw, int len)
    1972             : {
    1973             :         struct usbd_xfer *ctlxfer, *txxfer, *rxxfer;
    1974             :         struct uath_fwblock *txblock, *rxblock;
    1975             :         uint8_t *txdata;
    1976             :         int error = 0;
    1977             : 
    1978           0 :         if ((ctlxfer = usbd_alloc_xfer(sc->sc_udev)) == NULL) {
    1979           0 :                 printf("%s: could not allocate Tx control xfer\n",
    1980           0 :                     sc->sc_dev.dv_xname);
    1981             :                 error = USBD_NOMEM;
    1982           0 :                 goto fail1;
    1983             :         }
    1984           0 :         txblock = usbd_alloc_buffer(ctlxfer, sizeof (struct uath_fwblock));
    1985           0 :         if (txblock == NULL) {
    1986           0 :                 printf("%s: could not allocate Tx control block\n",
    1987           0 :                     sc->sc_dev.dv_xname);
    1988             :                 error = USBD_NOMEM;
    1989           0 :                 goto fail2;
    1990             :         }
    1991             : 
    1992           0 :         if ((txxfer = usbd_alloc_xfer(sc->sc_udev)) == NULL) {
    1993           0 :                 printf("%s: could not allocate Tx xfer\n",
    1994           0 :                     sc->sc_dev.dv_xname);
    1995             :                 error = USBD_NOMEM;
    1996           0 :                 goto fail2;
    1997             :         }
    1998           0 :         txdata = usbd_alloc_buffer(txxfer, UATH_MAX_FWBLOCK_SIZE);
    1999           0 :         if (txdata == NULL) {
    2000           0 :                 printf("%s: could not allocate Tx buffer\n",
    2001           0 :                     sc->sc_dev.dv_xname);
    2002             :                 error = USBD_NOMEM;
    2003           0 :                 goto fail3;
    2004             :         }
    2005             : 
    2006           0 :         if ((rxxfer = usbd_alloc_xfer(sc->sc_udev)) == NULL) {
    2007           0 :                 printf("%s: could not allocate Rx control xfer\n",
    2008           0 :                     sc->sc_dev.dv_xname);
    2009             :                 error = USBD_NOMEM;
    2010           0 :                 goto fail3;
    2011             :         }
    2012           0 :         rxblock = usbd_alloc_buffer(rxxfer, sizeof (struct uath_fwblock));
    2013           0 :         if (rxblock == NULL) {
    2014           0 :                 printf("%s: could not allocate Rx control block\n",
    2015           0 :                     sc->sc_dev.dv_xname);
    2016             :                 error = USBD_NOMEM;
    2017           0 :                 goto fail4;
    2018             :         }
    2019             : 
    2020           0 :         bzero(txblock, sizeof (struct uath_fwblock));
    2021           0 :         txblock->flags = htobe32(UATH_WRITE_BLOCK);
    2022           0 :         txblock->total = htobe32(len);
    2023             : 
    2024           0 :         while (len > 0) {
    2025           0 :                 int mlen = min(len, UATH_MAX_FWBLOCK_SIZE);
    2026             : 
    2027           0 :                 txblock->remain = htobe32(len - mlen);
    2028           0 :                 txblock->len = htobe32(mlen);
    2029             : 
    2030             :                 DPRINTF(("sending firmware block: %d bytes remaining\n",
    2031             :                     len - mlen));
    2032             : 
    2033             :                 /* send firmware block meta-data */
    2034           0 :                 usbd_setup_xfer(ctlxfer, sc->cmd_tx_pipe, sc, txblock,
    2035             :                     sizeof (struct uath_fwblock),
    2036             :                     USBD_NO_COPY | USBD_SYNCHRONOUS,
    2037             :                     UATH_CMD_TIMEOUT, NULL);
    2038           0 :                 if ((error = usbd_transfer(ctlxfer)) != 0) {
    2039           0 :                         printf("%s: could not send firmware block info\n",
    2040           0 :                             sc->sc_dev.dv_xname);
    2041           0 :                         break;
    2042             :                 }
    2043             : 
    2044             :                 /* send firmware block data */
    2045           0 :                 bcopy(fw, txdata, mlen);
    2046           0 :                 usbd_setup_xfer(txxfer, sc->data_tx_pipe, sc, txdata, mlen,
    2047             :                     USBD_NO_COPY | USBD_SYNCHRONOUS, UATH_DATA_TIMEOUT, NULL);
    2048           0 :                 if ((error = usbd_transfer(txxfer)) != 0) {
    2049           0 :                         printf("%s: could not send firmware block data\n",
    2050           0 :                             sc->sc_dev.dv_xname);
    2051           0 :                         break;
    2052             :                 }
    2053             : 
    2054             :                 /* wait for ack from firmware */
    2055           0 :                 usbd_setup_xfer(rxxfer, sc->cmd_rx_pipe, sc, rxblock,
    2056             :                     sizeof (struct uath_fwblock), USBD_SHORT_XFER_OK |
    2057             :                     USBD_NO_COPY | USBD_SYNCHRONOUS, UATH_CMD_TIMEOUT, NULL);
    2058           0 :                 if ((error = usbd_transfer(rxxfer)) != 0) {
    2059           0 :                         printf("%s: could not read firmware answer\n",
    2060           0 :                             sc->sc_dev.dv_xname);
    2061           0 :                         break;
    2062             :                 }
    2063             : 
    2064             :                 DPRINTFN(2, ("rxblock flags=0x%x total=%d\n",
    2065             :                     betoh32(rxblock->flags), betoh32(rxblock->rxtotal)));
    2066           0 :                 fw += mlen;
    2067             :                 len -= mlen;
    2068           0 :         }
    2069             : 
    2070           0 : fail4:  usbd_free_xfer(rxxfer);
    2071           0 : fail3:  usbd_free_xfer(txxfer);
    2072           0 : fail2:  usbd_free_xfer(ctlxfer);
    2073           0 : fail1:  return error;
    2074             : }

Generated by: LCOV version 1.13