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

          Line data    Source code
       1             : /*      $OpenBSD: if_athn_usb.c,v 1.51 2018/09/06 11:50:54 jsg Exp $    */
       2             : 
       3             : /*-
       4             :  * Copyright (c) 2011 Damien Bergamini <damien.bergamini@free.fr>
       5             :  * Copyright (c) 2018 Stefan Sperling <stsp@openbsd.org>
       6             :  *
       7             :  * Permission to use, copy, modify, and distribute this software for any
       8             :  * purpose with or without fee is hereby granted, provided that the above
       9             :  * copyright notice and this permission notice appear in all copies.
      10             :  *
      11             :  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
      12             :  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
      13             :  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
      14             :  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
      15             :  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
      16             :  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
      17             :  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
      18             :  */
      19             : 
      20             : /*
      21             :  * USB front-end for Atheros AR9271 and AR7010 chipsets.
      22             :  */
      23             : 
      24             : #include "bpfilter.h"
      25             : 
      26             : #include <sys/param.h>
      27             : #include <sys/sockio.h>
      28             : #include <sys/mbuf.h>
      29             : #include <sys/kernel.h>
      30             : #include <sys/socket.h>
      31             : #include <sys/systm.h>
      32             : #include <sys/timeout.h>
      33             : #include <sys/conf.h>
      34             : #include <sys/device.h>
      35             : #include <sys/endian.h>
      36             : 
      37             : #include <machine/bus.h>
      38             : #include <machine/intr.h>
      39             : 
      40             : #if NBPFILTER > 0
      41             : #include <net/bpf.h>
      42             : #endif
      43             : #include <net/if.h>
      44             : #include <net/if_dl.h>
      45             : #include <net/if_media.h>
      46             : 
      47             : #include <netinet/in.h>
      48             : #include <netinet/if_ether.h>
      49             : 
      50             : #include <net80211/ieee80211_var.h>
      51             : #include <net80211/ieee80211_amrr.h>
      52             : #include <net80211/ieee80211_mira.h>
      53             : #include <net80211/ieee80211_radiotap.h>
      54             : 
      55             : #include <dev/ic/athnreg.h>
      56             : #include <dev/ic/athnvar.h>
      57             : 
      58             : #include <dev/usb/usb.h>
      59             : #include <dev/usb/usbdi.h>
      60             : #include <dev/usb/usbdi_util.h>
      61             : #include <dev/usb/usbdevs.h>
      62             : 
      63             : #include <dev/usb/if_athn_usb.h>
      64             : 
      65             : static const struct athn_usb_type {
      66             :         struct usb_devno        devno;
      67             :         u_int                   flags;
      68             : } athn_usb_devs[] = {
      69             :         {{ USB_VENDOR_ACCTON, USB_PRODUCT_ACCTON_AR9280 },
      70             :            ATHN_USB_FLAG_AR7010 },
      71             :         {{ USB_VENDOR_ACTIONTEC, USB_PRODUCT_ACTIONTEC_AR9287 },
      72             :            ATHN_USB_FLAG_AR7010 },
      73             :         {{ USB_VENDOR_ATHEROS2, USB_PRODUCT_ATHEROS2_AR9271_1 }},
      74             :         {{ USB_VENDOR_ATHEROS2, USB_PRODUCT_ATHEROS2_AR9271_2 }},
      75             :         {{ USB_VENDOR_ATHEROS2, USB_PRODUCT_ATHEROS2_AR9271_3 }},
      76             :         {{ USB_VENDOR_ATHEROS2, USB_PRODUCT_ATHEROS2_AR9280 },
      77             :            ATHN_USB_FLAG_AR7010 },
      78             :         {{ USB_VENDOR_ATHEROS2, USB_PRODUCT_ATHEROS2_AR9287 },
      79             :            ATHN_USB_FLAG_AR7010 },
      80             :         {{ USB_VENDOR_AZUREWAVE, USB_PRODUCT_AZUREWAVE_AR9271_1 }},
      81             :         {{ USB_VENDOR_AZUREWAVE, USB_PRODUCT_AZUREWAVE_AR9271_2 }},
      82             :         {{ USB_VENDOR_AZUREWAVE, USB_PRODUCT_AZUREWAVE_AR9271_3 }},
      83             :         {{ USB_VENDOR_AZUREWAVE, USB_PRODUCT_AZUREWAVE_AR9271_4 }},
      84             :         {{ USB_VENDOR_AZUREWAVE, USB_PRODUCT_AZUREWAVE_AR9271_5 }},
      85             :         {{ USB_VENDOR_AZUREWAVE, USB_PRODUCT_AZUREWAVE_AR9271_6 }},
      86             :         {{ USB_VENDOR_DLINK2, USB_PRODUCT_DLINK2_AR9271 }},
      87             :         {{ USB_VENDOR_LITEON, USB_PRODUCT_LITEON_AR9271 }},
      88             :         {{ USB_VENDOR_NETGEAR, USB_PRODUCT_NETGEAR_WNA1100 }},
      89             :         {{ USB_VENDOR_NETGEAR, USB_PRODUCT_NETGEAR_WNDA3200 },
      90             :            ATHN_USB_FLAG_AR7010 },
      91             :         {{ USB_VENDOR_PANASONIC, USB_PRODUCT_PANASONIC_N5HBZ0000055 },
      92             :            ATHN_USB_FLAG_AR7010 },
      93             :         {{ USB_VENDOR_VIA, USB_PRODUCT_VIA_AR9271 }}
      94             : };
      95             : #define athn_usb_lookup(v, p)   \
      96             :         ((const struct athn_usb_type *)usb_lookup(athn_usb_devs, v, p))
      97             : 
      98             : int             athn_usb_match(struct device *, void *, void *);
      99             : void            athn_usb_attach(struct device *, struct device *, void *);
     100             : int             athn_usb_detach(struct device *, int);
     101             : void            athn_usb_attachhook(struct device *);
     102             : int             athn_usb_open_pipes(struct athn_usb_softc *);
     103             : void            athn_usb_close_pipes(struct athn_usb_softc *);
     104             : int             athn_usb_alloc_rx_list(struct athn_usb_softc *);
     105             : void            athn_usb_free_rx_list(struct athn_usb_softc *);
     106             : int             athn_usb_alloc_tx_list(struct athn_usb_softc *);
     107             : void            athn_usb_free_tx_list(struct athn_usb_softc *);
     108             : int             athn_usb_alloc_tx_cmd(struct athn_usb_softc *);
     109             : void            athn_usb_free_tx_cmd(struct athn_usb_softc *);
     110             : void            athn_usb_task(void *);
     111             : void            athn_usb_do_async(struct athn_usb_softc *,
     112             :                     void (*)(struct athn_usb_softc *, void *), void *, int);
     113             : void            athn_usb_wait_async(struct athn_usb_softc *);
     114             : int             athn_usb_load_firmware(struct athn_usb_softc *);
     115             : int             athn_usb_htc_msg(struct athn_usb_softc *, uint16_t, void *,
     116             :                     int);
     117             : int             athn_usb_htc_setup(struct athn_usb_softc *);
     118             : int             athn_usb_htc_connect_svc(struct athn_usb_softc *, uint16_t,
     119             :                     uint8_t, uint8_t, uint8_t *);
     120             : int             athn_usb_wmi_xcmd(struct athn_usb_softc *, uint16_t, void *,
     121             :                     int, void *);
     122             : int             athn_usb_read_rom(struct athn_softc *);
     123             : uint32_t        athn_usb_read(struct athn_softc *, uint32_t);
     124             : void            athn_usb_write(struct athn_softc *, uint32_t, uint32_t);
     125             : void            athn_usb_write_barrier(struct athn_softc *);
     126             : int             athn_usb_media_change(struct ifnet *);
     127             : void            athn_usb_next_scan(void *);
     128             : int             athn_usb_newstate(struct ieee80211com *, enum ieee80211_state,
     129             :                     int);
     130             : void            athn_usb_newstate_cb(struct athn_usb_softc *, void *);
     131             : void            athn_usb_newassoc(struct ieee80211com *,
     132             :                     struct ieee80211_node *, int);
     133             : void            athn_usb_newassoc_cb(struct athn_usb_softc *, void *);
     134             : struct ieee80211_node *athn_usb_node_alloc(struct ieee80211com *);
     135             : void            athn_usb_count_active_sta(void *, struct ieee80211_node *);
     136             : void            athn_usb_newauth_cb(struct athn_usb_softc *, void *);
     137             : int             athn_usb_newauth(struct ieee80211com *,
     138             :                     struct ieee80211_node *, int, uint16_t);
     139             : void            athn_usb_node_free(struct ieee80211com *,
     140             :                     struct ieee80211_node *);
     141             : void            athn_usb_node_free_cb(struct athn_usb_softc *, void *);
     142             : int             athn_usb_ampdu_tx_start(struct ieee80211com *,
     143             :                     struct ieee80211_node *, uint8_t);
     144             : void            athn_usb_ampdu_tx_start_cb(struct athn_usb_softc *, void *);
     145             : void            athn_usb_ampdu_tx_stop(struct ieee80211com *,
     146             :                     struct ieee80211_node *, uint8_t);
     147             : void            athn_usb_ampdu_tx_stop_cb(struct athn_usb_softc *, void *);
     148             : void            athn_usb_clean_nodes(void *, struct ieee80211_node *);
     149             : int             athn_usb_create_node(struct athn_usb_softc *,
     150             :                     struct ieee80211_node *);
     151             : int             athn_usb_node_set_rates(struct athn_usb_softc *,
     152             :                     struct ieee80211_node *);
     153             : int             athn_usb_remove_node(struct athn_usb_softc *,
     154             :                     struct ieee80211_node *);
     155             : void            athn_usb_rx_enable(struct athn_softc *);
     156             : int             athn_set_chan(struct athn_softc *, struct ieee80211_channel *,
     157             :                     struct ieee80211_channel *);
     158             : int             athn_usb_switch_chan(struct athn_softc *,
     159             :                     struct ieee80211_channel *, struct ieee80211_channel *);
     160             : void            athn_usb_updateedca(struct ieee80211com *);
     161             : void            athn_usb_updateedca_cb(struct athn_usb_softc *, void *);
     162             : void            athn_usb_updateslot(struct ieee80211com *);
     163             : void            athn_usb_updateslot_cb(struct athn_usb_softc *, void *);
     164             : int             athn_usb_set_key(struct ieee80211com *,
     165             :                     struct ieee80211_node *, struct ieee80211_key *);
     166             : void            athn_usb_set_key_cb(struct athn_usb_softc *, void *);
     167             : void            athn_usb_delete_key(struct ieee80211com *,
     168             :                     struct ieee80211_node *, struct ieee80211_key *);
     169             : void            athn_usb_delete_key_cb(struct athn_usb_softc *, void *);
     170             : void            athn_usb_bcneof(struct usbd_xfer *, void *,
     171             :                     usbd_status);
     172             : void            athn_usb_swba(struct athn_usb_softc *);
     173             : void            athn_usb_tx_status(void *, struct ieee80211_node *);
     174             : void            athn_usb_rx_wmi_ctrl(struct athn_usb_softc *, uint8_t *, int);
     175             : void            athn_usb_intr(struct usbd_xfer *, void *,
     176             :                     usbd_status);
     177             : void            athn_usb_rx_radiotap(struct athn_softc *, struct mbuf *,
     178             :                     struct ar_rx_status *);
     179             : void            athn_usb_rx_frame(struct athn_usb_softc *, struct mbuf *);
     180             : void            athn_usb_rxeof(struct usbd_xfer *, void *,
     181             :                     usbd_status);
     182             : void            athn_usb_txeof(struct usbd_xfer *, void *,
     183             :                     usbd_status);
     184             : int             athn_usb_tx(struct athn_softc *, struct mbuf *,
     185             :                     struct ieee80211_node *);
     186             : void            athn_usb_start(struct ifnet *);
     187             : void            athn_usb_watchdog(struct ifnet *);
     188             : int             athn_usb_ioctl(struct ifnet *, u_long, caddr_t);
     189             : int             athn_usb_init(struct ifnet *);
     190             : void            athn_usb_stop(struct ifnet *);
     191             : void            ar9271_load_ani(struct athn_softc *);
     192             : 
     193             : /* Shortcut. */
     194             : #define athn_usb_wmi_cmd(sc, cmd_id)    \
     195             :         athn_usb_wmi_xcmd(sc, cmd_id, NULL, 0, NULL)
     196             : 
     197             : /* Extern functions. */
     198             : void            athn_led_init(struct athn_softc *);
     199             : void            athn_set_led(struct athn_softc *, int);
     200             : void            athn_btcoex_init(struct athn_softc *);
     201             : void            athn_set_rxfilter(struct athn_softc *, uint32_t);
     202             : int             athn_reset(struct athn_softc *, int);
     203             : void            athn_init_pll(struct athn_softc *,
     204             :                     const struct ieee80211_channel *);
     205             : int             athn_set_power_awake(struct athn_softc *);
     206             : void            athn_set_power_sleep(struct athn_softc *);
     207             : void            athn_reset_key(struct athn_softc *, int);
     208             : int             athn_set_key(struct ieee80211com *, struct ieee80211_node *,
     209             :                     struct ieee80211_key *);
     210             : void            athn_delete_key(struct ieee80211com *, struct ieee80211_node *,
     211             :                     struct ieee80211_key *);
     212             : void            athn_rx_start(struct athn_softc *);
     213             : void            athn_set_sta_timers(struct athn_softc *);
     214             : void            athn_set_hostap_timers(struct athn_softc *);
     215             : void            athn_set_opmode(struct athn_softc *);
     216             : void            athn_set_bss(struct athn_softc *, struct ieee80211_node *);
     217             : int             athn_hw_reset(struct athn_softc *, struct ieee80211_channel *,
     218             :                     struct ieee80211_channel *, int);
     219             : void            athn_updateedca(struct ieee80211com *);
     220             : void            athn_updateslot(struct ieee80211com *);
     221             : 
     222             : const struct cfattach athn_usb_ca = {
     223             :         sizeof(struct athn_usb_softc),
     224             :         athn_usb_match,
     225             :         athn_usb_attach,
     226             :         athn_usb_detach
     227             : };
     228             : 
     229             : int
     230           0 : athn_usb_match(struct device *parent, void *match, void *aux)
     231             : {
     232           0 :         struct usb_attach_arg *uaa = aux;
     233             : 
     234           0 :         if (uaa->iface == NULL || uaa->configno != 1)
     235           0 :                 return (UMATCH_NONE);
     236             : 
     237           0 :         return ((athn_usb_lookup(uaa->vendor, uaa->product) != NULL) ?
     238             :             UMATCH_VENDOR_PRODUCT_CONF_IFACE : UMATCH_NONE);
     239           0 : }
     240             : 
     241             : void
     242           0 : athn_usb_attach(struct device *parent, struct device *self, void *aux)
     243             : {
     244           0 :         struct athn_usb_softc *usc = (struct athn_usb_softc *)self;
     245           0 :         struct athn_softc *sc = &usc->sc_sc;
     246           0 :         struct usb_attach_arg *uaa = aux;
     247             : 
     248           0 :         usc->sc_udev = uaa->device;
     249           0 :         usc->sc_iface = uaa->iface;
     250             : 
     251           0 :         usc->flags = athn_usb_lookup(uaa->vendor, uaa->product)->flags;
     252           0 :         sc->flags |= ATHN_FLAG_USB;
     253             : #ifdef notyet
     254             :         /* Check if it is a combo WiFi+Bluetooth (WB193) device. */
     255             :         if (strncmp(product, "wb193", 5) == 0)
     256             :                 sc->flags |= ATHN_FLAG_BTCOEX3WIRE;
     257             : #endif
     258             : 
     259           0 :         sc->ops.read = athn_usb_read;
     260           0 :         sc->ops.write = athn_usb_write;
     261           0 :         sc->ops.write_barrier = athn_usb_write_barrier;
     262             : 
     263           0 :         usb_init_task(&usc->sc_task, athn_usb_task, sc, USB_TASK_TYPE_GENERIC);
     264             : 
     265           0 :         if (athn_usb_open_pipes(usc) != 0)
     266           0 :                 return;
     267             : 
     268             :         /* Allocate xfer for firmware commands. */
     269           0 :         if (athn_usb_alloc_tx_cmd(usc) != 0)
     270           0 :                 return;
     271             : 
     272           0 :         config_mountroot(self, athn_usb_attachhook);
     273           0 : }
     274             : 
     275             : int
     276           0 : athn_usb_detach(struct device *self, int flags)
     277             : {
     278           0 :         struct athn_usb_softc *usc = (struct athn_usb_softc *)self;
     279           0 :         struct athn_softc *sc = &usc->sc_sc;
     280             : 
     281           0 :         if (usc->sc_athn_attached)
     282           0 :                 athn_detach(sc);
     283             : 
     284             :         /* Wait for all async commands to complete. */
     285           0 :         athn_usb_wait_async(usc);
     286             : 
     287           0 :         usbd_ref_wait(usc->sc_udev);
     288             : 
     289             :         /* Abort and close Tx/Rx pipes. */
     290           0 :         athn_usb_close_pipes(usc);
     291             : 
     292             :         /* Free Tx/Rx buffers. */
     293           0 :         athn_usb_free_tx_cmd(usc);
     294           0 :         athn_usb_free_tx_list(usc);
     295           0 :         athn_usb_free_rx_list(usc);
     296             : 
     297           0 :         return (0);
     298             : }
     299             : 
     300             : void
     301           0 : athn_usb_attachhook(struct device *self)
     302             : {
     303           0 :         struct athn_usb_softc *usc = (struct athn_usb_softc *)self;
     304           0 :         struct athn_softc *sc = &usc->sc_sc;
     305           0 :         struct athn_ops *ops = &sc->ops;
     306           0 :         struct ieee80211com *ic = &sc->sc_ic;
     307           0 :         struct ifnet *ifp = &ic->ic_if;
     308             :         int s, i, error;
     309             : 
     310             :         /* Load firmware. */
     311           0 :         error = athn_usb_load_firmware(usc);
     312           0 :         if (error != 0) {
     313           0 :                 printf("%s: could not load firmware\n", sc->sc_dev.dv_xname);
     314           0 :                 return;
     315             :         }
     316             : 
     317             :         /* Setup the host transport communication interface. */
     318           0 :         error = athn_usb_htc_setup(usc);
     319           0 :         if (error != 0)
     320           0 :                 return;
     321             : 
     322             :         /* We're now ready to attach the bus agnostic driver. */
     323           0 :         s = splnet();
     324           0 :         error = athn_attach(sc);
     325           0 :         if (error != 0) {
     326           0 :                 splx(s);
     327           0 :                 return;
     328             :         }
     329           0 :         usc->sc_athn_attached = 1;
     330             :         /* Override some operations for USB. */
     331           0 :         ifp->if_ioctl = athn_usb_ioctl;
     332           0 :         ifp->if_start = athn_usb_start;
     333           0 :         ifp->if_watchdog = athn_usb_watchdog;
     334           0 :         ic->ic_node_alloc = athn_usb_node_alloc;
     335           0 :         ic->ic_newauth = athn_usb_newauth;
     336           0 :         ic->ic_newassoc = athn_usb_newassoc;
     337             : #ifndef IEEE80211_STA_ONLY
     338           0 :         usc->sc_node_free = ic->ic_node_free;
     339           0 :         ic->ic_node_free = athn_usb_node_free;
     340             : #endif
     341           0 :         ic->ic_updateslot = athn_usb_updateslot;
     342           0 :         ic->ic_updateedca = athn_usb_updateedca;
     343             : #ifdef notyet
     344             :         ic->ic_set_key = athn_usb_set_key;
     345             :         ic->ic_delete_key = athn_usb_delete_key;
     346             :         ic->ic_ampdu_tx_start = athn_usb_ampdu_tx_start;
     347             :         ic->ic_ampdu_tx_stop = athn_usb_ampdu_tx_stop;
     348             : #endif
     349           0 :         ic->ic_newstate = athn_usb_newstate;
     350           0 :         ic->ic_media.ifm_change = athn_usb_media_change;
     351           0 :         timeout_set(&sc->scan_to, athn_usb_next_scan, usc);
     352             : 
     353           0 :         ops->rx_enable = athn_usb_rx_enable;
     354           0 :         splx(s);
     355             : 
     356             :         /* Reset HW key cache entries. */
     357           0 :         for (i = 0; i < sc->kc_entries; i++)
     358           0 :                 athn_reset_key(sc, i);
     359             : 
     360           0 :         ops->enable_antenna_diversity(sc);
     361             : 
     362             : #ifdef ATHN_BT_COEXISTENCE
     363             :         /* Configure bluetooth coexistence for combo chips. */
     364             :         if (sc->flags & ATHN_FLAG_BTCOEX)
     365             :                 athn_btcoex_init(sc);
     366             : #endif
     367             :         /* Configure LED. */
     368           0 :         athn_led_init(sc);
     369           0 : }
     370             : 
     371             : int
     372           0 : athn_usb_open_pipes(struct athn_usb_softc *usc)
     373             : {
     374             :         usb_endpoint_descriptor_t *ed;
     375             :         int isize, error;
     376             : 
     377           0 :         error = usbd_open_pipe(usc->sc_iface, AR_PIPE_TX_DATA, 0,
     378           0 :             &usc->tx_data_pipe);
     379           0 :         if (error != 0) {
     380           0 :                 printf("%s: could not open Tx bulk pipe\n",
     381           0 :                     usc->usb_dev.dv_xname);
     382           0 :                 goto fail;
     383             :         }
     384             : 
     385           0 :         error = usbd_open_pipe(usc->sc_iface, AR_PIPE_RX_DATA, 0,
     386           0 :             &usc->rx_data_pipe);
     387           0 :         if (error != 0) {
     388           0 :                 printf("%s: could not open Rx bulk pipe\n",
     389           0 :                     usc->usb_dev.dv_xname);
     390           0 :                 goto fail;
     391             :         }
     392             : 
     393           0 :         ed = usbd_get_endpoint_descriptor(usc->sc_iface, AR_PIPE_RX_INTR);
     394           0 :         if (ed == NULL) {
     395           0 :                 printf("%s: could not retrieve Rx intr pipe descriptor\n",
     396           0 :                     usc->usb_dev.dv_xname);
     397           0 :                 goto fail;
     398             :         }
     399           0 :         isize = UGETW(ed->wMaxPacketSize);
     400           0 :         if (isize == 0) {
     401           0 :                 printf("%s: invalid Rx intr pipe descriptor\n",
     402           0 :                     usc->usb_dev.dv_xname);
     403           0 :                 goto fail;
     404             :         }
     405           0 :         usc->ibuf = malloc(isize, M_USBDEV, M_NOWAIT);
     406           0 :         if (usc->ibuf == NULL) {
     407           0 :                 printf("%s: could not allocate Rx intr buffer\n",
     408           0 :                     usc->usb_dev.dv_xname);
     409           0 :                 goto fail;
     410             :         }
     411           0 :         usc->ibuflen = isize;
     412           0 :         error = usbd_open_pipe_intr(usc->sc_iface, AR_PIPE_RX_INTR,
     413           0 :             USBD_SHORT_XFER_OK, &usc->rx_intr_pipe, usc, usc->ibuf, isize,
     414             :             athn_usb_intr, USBD_DEFAULT_INTERVAL);
     415           0 :         if (error != 0) {
     416           0 :                 printf("%s: could not open Rx intr pipe\n",
     417           0 :                     usc->usb_dev.dv_xname);
     418           0 :                 goto fail;
     419             :         }
     420             : 
     421           0 :         error = usbd_open_pipe(usc->sc_iface, AR_PIPE_TX_INTR, 0,
     422           0 :             &usc->tx_intr_pipe);
     423           0 :         if (error != 0) {
     424           0 :                 printf("%s: could not open Tx intr pipe\n",
     425           0 :                     usc->usb_dev.dv_xname);
     426           0 :                 goto fail;
     427             :         }
     428             :  fail:
     429           0 :         if (error != 0)
     430           0 :                 athn_usb_close_pipes(usc);
     431           0 :         return (error);
     432             : }
     433             : 
     434             : void
     435           0 : athn_usb_close_pipes(struct athn_usb_softc *usc)
     436             : {
     437           0 :         if (usc->tx_data_pipe != NULL) {
     438           0 :                 usbd_close_pipe(usc->tx_data_pipe);
     439           0 :                 usc->tx_data_pipe = NULL;
     440           0 :         }
     441           0 :         if (usc->rx_data_pipe != NULL) {
     442           0 :                 usbd_close_pipe(usc->rx_data_pipe);
     443           0 :                 usc->rx_data_pipe = NULL;
     444           0 :         }
     445           0 :         if (usc->tx_intr_pipe != NULL) {
     446           0 :                 usbd_close_pipe(usc->tx_intr_pipe);
     447           0 :                 usc->tx_intr_pipe = NULL;
     448           0 :         }
     449           0 :         if (usc->rx_intr_pipe != NULL) {
     450           0 :                 usbd_close_pipe(usc->rx_intr_pipe);
     451           0 :                 usc->rx_intr_pipe = NULL;
     452           0 :         }
     453           0 :         if (usc->ibuf != NULL) {
     454           0 :                 free(usc->ibuf, M_USBDEV, usc->ibuflen);
     455           0 :                 usc->ibuf = NULL;
     456           0 :         }
     457           0 : }
     458             : 
     459             : int
     460           0 : athn_usb_alloc_rx_list(struct athn_usb_softc *usc)
     461             : {
     462             :         struct athn_usb_rx_data *data;
     463             :         int i, error = 0;
     464             : 
     465           0 :         for (i = 0; i < ATHN_USB_RX_LIST_COUNT; i++) {
     466           0 :                 data = &usc->rx_data[i];
     467             : 
     468           0 :                 data->sc = usc;      /* Backpointer for callbacks. */
     469             : 
     470           0 :                 data->xfer = usbd_alloc_xfer(usc->sc_udev);
     471           0 :                 if (data->xfer == NULL) {
     472           0 :                         printf("%s: could not allocate xfer\n",
     473           0 :                             usc->usb_dev.dv_xname);
     474             :                         error = ENOMEM;
     475           0 :                         break;
     476             :                 }
     477           0 :                 data->buf = usbd_alloc_buffer(data->xfer, ATHN_USB_RXBUFSZ);
     478           0 :                 if (data->buf == NULL) {
     479           0 :                         printf("%s: could not allocate xfer buffer\n",
     480           0 :                             usc->usb_dev.dv_xname);
     481             :                         error = ENOMEM;
     482           0 :                         break;
     483             :                 }
     484             :         }
     485           0 :         if (error != 0)
     486           0 :                 athn_usb_free_rx_list(usc);
     487           0 :         return (error);
     488             : }
     489             : 
     490             : void
     491           0 : athn_usb_free_rx_list(struct athn_usb_softc *usc)
     492             : {
     493             :         int i;
     494             : 
     495             :         /* NB: Caller must abort pipe first. */
     496           0 :         for (i = 0; i < ATHN_USB_RX_LIST_COUNT; i++) {
     497           0 :                 if (usc->rx_data[i].xfer != NULL)
     498           0 :                         usbd_free_xfer(usc->rx_data[i].xfer);
     499           0 :                 usc->rx_data[i].xfer = NULL;
     500             :         }
     501           0 : }
     502             : 
     503             : int
     504           0 : athn_usb_alloc_tx_list(struct athn_usb_softc *usc)
     505             : {
     506             :         struct athn_usb_tx_data *data;
     507             :         int i, error = 0;
     508             : 
     509           0 :         TAILQ_INIT(&usc->tx_free_list);
     510           0 :         for (i = 0; i < ATHN_USB_TX_LIST_COUNT; i++) {
     511           0 :                 data = &usc->tx_data[i];
     512             : 
     513           0 :                 data->sc = usc;      /* Backpointer for callbacks. */
     514             : 
     515           0 :                 data->xfer = usbd_alloc_xfer(usc->sc_udev);
     516           0 :                 if (data->xfer == NULL) {
     517           0 :                         printf("%s: could not allocate xfer\n",
     518           0 :                             usc->usb_dev.dv_xname);
     519             :                         error = ENOMEM;
     520           0 :                         break;
     521             :                 }
     522           0 :                 data->buf = usbd_alloc_buffer(data->xfer, ATHN_USB_TXBUFSZ);
     523           0 :                 if (data->buf == NULL) {
     524           0 :                         printf("%s: could not allocate xfer buffer\n",
     525           0 :                             usc->usb_dev.dv_xname);
     526             :                         error = ENOMEM;
     527           0 :                         break;
     528             :                 }
     529             :                 /* Append this Tx buffer to our free list. */
     530           0 :                 TAILQ_INSERT_TAIL(&usc->tx_free_list, data, next);
     531             :         }
     532           0 :         if (error != 0)
     533           0 :                 athn_usb_free_tx_list(usc);
     534           0 :         return (error);
     535             : }
     536             : 
     537             : void
     538           0 : athn_usb_free_tx_list(struct athn_usb_softc *usc)
     539             : {
     540             :         int i;
     541             : 
     542             :         /* NB: Caller must abort pipe first. */
     543           0 :         for (i = 0; i < ATHN_USB_TX_LIST_COUNT; i++) {
     544           0 :                 if (usc->tx_data[i].xfer != NULL)
     545           0 :                         usbd_free_xfer(usc->tx_data[i].xfer);
     546           0 :                 usc->tx_data[i].xfer = NULL;
     547             :         }
     548           0 : }
     549             : 
     550             : int
     551           0 : athn_usb_alloc_tx_cmd(struct athn_usb_softc *usc)
     552             : {
     553           0 :         struct athn_usb_tx_data *data = &usc->tx_cmd;
     554             : 
     555           0 :         data->sc = usc;      /* Backpointer for callbacks. */
     556             : 
     557           0 :         data->xfer = usbd_alloc_xfer(usc->sc_udev);
     558           0 :         if (data->xfer == NULL) {
     559           0 :                 printf("%s: could not allocate xfer\n",
     560           0 :                     usc->usb_dev.dv_xname);
     561           0 :                 return (ENOMEM);
     562             :         }
     563           0 :         data->buf = usbd_alloc_buffer(data->xfer, ATHN_USB_TXCMDSZ);
     564           0 :         if (data->buf == NULL) {
     565           0 :                 printf("%s: could not allocate xfer buffer\n",
     566           0 :                     usc->usb_dev.dv_xname);
     567           0 :                 return (ENOMEM);
     568             :         }
     569           0 :         return (0);
     570           0 : }
     571             : 
     572             : void
     573           0 : athn_usb_free_tx_cmd(struct athn_usb_softc *usc)
     574             : {
     575           0 :         if (usc->tx_cmd.xfer != NULL)
     576           0 :                 usbd_free_xfer(usc->tx_cmd.xfer);
     577           0 :         usc->tx_cmd.xfer = NULL;
     578           0 : }
     579             : 
     580             : void
     581           0 : athn_usb_task(void *arg)
     582             : {
     583           0 :         struct athn_usb_softc *usc = arg;
     584           0 :         struct athn_usb_host_cmd_ring *ring = &usc->cmdq;
     585             :         struct athn_usb_host_cmd *cmd;
     586             :         int s;
     587             : 
     588             :         /* Process host commands. */
     589           0 :         s = splusb();
     590           0 :         while (ring->next != ring->cur) {
     591           0 :                 cmd = &ring->cmd[ring->next];
     592           0 :                 splx(s);
     593             :                 /* Invoke callback. */
     594           0 :                 cmd->cb(usc, cmd->data);
     595           0 :                 s = splusb();
     596           0 :                 ring->queued--;
     597           0 :                 ring->next = (ring->next + 1) % ATHN_USB_HOST_CMD_RING_COUNT;
     598             :         }
     599           0 :         splx(s);
     600           0 : }
     601             : 
     602             : void
     603           0 : athn_usb_do_async(struct athn_usb_softc *usc,
     604             :     void (*cb)(struct athn_usb_softc *, void *), void *arg, int len)
     605             : {
     606           0 :         struct athn_usb_host_cmd_ring *ring = &usc->cmdq;
     607             :         struct athn_usb_host_cmd *cmd;
     608             :         int s;
     609             : 
     610           0 :         if (ring->queued == ATHN_USB_HOST_CMD_RING_COUNT) {
     611           0 :                 printf("%s: host cmd queue overrun\n", usc->usb_dev.dv_xname);
     612           0 :                 return; /* XXX */
     613             :         }
     614             :         
     615           0 :         s = splusb();
     616           0 :         cmd = &ring->cmd[ring->cur];
     617           0 :         cmd->cb = cb;
     618           0 :         KASSERT(len <= sizeof(cmd->data));
     619           0 :         memcpy(cmd->data, arg, len);
     620           0 :         ring->cur = (ring->cur + 1) % ATHN_USB_HOST_CMD_RING_COUNT;
     621             : 
     622             :         /* If there is no pending command already, schedule a task. */
     623           0 :         if (++ring->queued == 1)
     624           0 :                 usb_add_task(usc->sc_udev, &usc->sc_task);
     625           0 :         splx(s);
     626           0 : }
     627             : 
     628             : void
     629           0 : athn_usb_wait_async(struct athn_usb_softc *usc)
     630             : {
     631             :         /* Wait for all queued asynchronous commands to complete. */
     632           0 :         usb_wait_task(usc->sc_udev, &usc->sc_task);
     633           0 : }
     634             : 
     635             : int
     636           0 : athn_usb_load_firmware(struct athn_usb_softc *usc)
     637             : {
     638             :         usb_device_descriptor_t *dd;
     639           0 :         usb_device_request_t req;
     640             :         const char *name;
     641           0 :         u_char *fw, *ptr;
     642           0 :         size_t fwsize, size;
     643             :         uint32_t addr;
     644             :         int s, mlen, error;
     645             : 
     646             :         /* Determine which firmware image to load. */
     647           0 :         if (usc->flags & ATHN_USB_FLAG_AR7010) {
     648           0 :                 dd = usbd_get_device_descriptor(usc->sc_udev);
     649             :                 name = "athn-open-ar7010";
     650           0 :         } else
     651             :                 name = "athn-open-ar9271";
     652             :         /* Read firmware image from the filesystem. */
     653           0 :         if ((error = loadfirmware(name, &fw, &fwsize)) != 0) {
     654           0 :                 printf("%s: failed loadfirmware of file %s (error %d)\n",
     655           0 :                     usc->usb_dev.dv_xname, name, error);
     656           0 :                 return (error);
     657             :         }
     658             :         /* Load firmware image. */
     659           0 :         ptr = fw;
     660             :         addr = AR9271_FIRMWARE >> 8;
     661           0 :         req.bmRequestType = UT_WRITE_VENDOR_DEVICE;
     662           0 :         req.bRequest = AR_FW_DOWNLOAD;
     663           0 :         USETW(req.wIndex, 0);
     664           0 :         size = fwsize;
     665           0 :         while (size > 0) {
     666           0 :                 mlen = MIN(size, 4096);
     667             : 
     668           0 :                 USETW(req.wValue, addr);
     669           0 :                 USETW(req.wLength, mlen);
     670           0 :                 error = usbd_do_request(usc->sc_udev, &req, ptr);
     671           0 :                 if (error != 0) {
     672           0 :                         free(fw, M_DEVBUF, fwsize);
     673           0 :                         return (error);
     674             :                 }
     675           0 :                 addr += mlen >> 8;
     676           0 :                 ptr  += mlen;
     677           0 :                 size -= mlen;
     678             :         }
     679           0 :         free(fw, M_DEVBUF, fwsize);
     680             : 
     681             :         /* Start firmware. */
     682           0 :         if (usc->flags & ATHN_USB_FLAG_AR7010)
     683           0 :                 addr = AR7010_FIRMWARE_TEXT >> 8;
     684             :         else
     685             :                 addr = AR9271_FIRMWARE_TEXT >> 8;
     686           0 :         req.bmRequestType = UT_WRITE_VENDOR_DEVICE;
     687           0 :         req.bRequest = AR_FW_DOWNLOAD_COMP;
     688           0 :         USETW(req.wIndex, 0);
     689           0 :         USETW(req.wValue, addr);
     690           0 :         USETW(req.wLength, 0);
     691           0 :         s = splusb();
     692           0 :         usc->wait_msg_id = AR_HTC_MSG_READY;
     693           0 :         error = usbd_do_request(usc->sc_udev, &req, NULL);
     694             :         /* Wait at most 1 second for firmware to boot. */
     695           0 :         if (error == 0 && usc->wait_msg_id != 0)
     696           0 :                 error = tsleep(&usc->wait_msg_id, 0, "athnfw", hz);
     697           0 :         usc->wait_msg_id = 0;
     698           0 :         splx(s);
     699           0 :         return (error);
     700           0 : }
     701             : 
     702             : int
     703           0 : athn_usb_htc_msg(struct athn_usb_softc *usc, uint16_t msg_id, void *buf,
     704             :     int len)
     705             : {
     706           0 :         struct athn_usb_tx_data *data = &usc->tx_cmd;
     707             :         struct ar_htc_frame_hdr *htc;
     708             :         struct ar_htc_msg_hdr *msg;
     709             : 
     710           0 :         htc = (struct ar_htc_frame_hdr *)data->buf;
     711           0 :         memset(htc, 0, sizeof(*htc));
     712           0 :         htc->endpoint_id = 0;
     713           0 :         htc->payload_len = htobe16(sizeof(*msg) + len);
     714             : 
     715           0 :         msg = (struct ar_htc_msg_hdr *)&htc[1];
     716           0 :         msg->msg_id = htobe16(msg_id);
     717             : 
     718           0 :         memcpy(&msg[1], buf, len);
     719             : 
     720           0 :         usbd_setup_xfer(data->xfer, usc->tx_intr_pipe, NULL, data->buf,
     721           0 :             sizeof(*htc) + sizeof(*msg) + len,
     722             :             USBD_SHORT_XFER_OK | USBD_NO_COPY | USBD_SYNCHRONOUS,
     723             :             ATHN_USB_CMD_TIMEOUT, NULL);
     724           0 :         return (usbd_transfer(data->xfer));
     725             : }
     726             : 
     727             : int
     728           0 : athn_usb_htc_setup(struct athn_usb_softc *usc)
     729             : {
     730           0 :         struct ar_htc_msg_config_pipe cfg;
     731             :         int s, error;
     732             : 
     733             :         /*
     734             :          * Connect WMI services to USB pipes.
     735             :          */
     736           0 :         error = athn_usb_htc_connect_svc(usc, AR_SVC_WMI_CONTROL,
     737           0 :             AR_PIPE_TX_INTR, AR_PIPE_RX_INTR, &usc->ep_ctrl);
     738           0 :         if (error != 0)
     739           0 :                 return (error);
     740           0 :         error = athn_usb_htc_connect_svc(usc, AR_SVC_WMI_BEACON,
     741           0 :             AR_PIPE_TX_DATA, AR_PIPE_RX_DATA, &usc->ep_bcn);
     742           0 :         if (error != 0)
     743           0 :                 return (error);
     744           0 :         error = athn_usb_htc_connect_svc(usc, AR_SVC_WMI_CAB,
     745           0 :             AR_PIPE_TX_DATA, AR_PIPE_RX_DATA, &usc->ep_cab);
     746           0 :         if (error != 0)
     747           0 :                 return (error);
     748           0 :         error = athn_usb_htc_connect_svc(usc, AR_SVC_WMI_UAPSD,
     749           0 :             AR_PIPE_TX_DATA, AR_PIPE_RX_DATA, &usc->ep_uapsd);
     750           0 :         if (error != 0)
     751           0 :                 return (error);
     752           0 :         error = athn_usb_htc_connect_svc(usc, AR_SVC_WMI_MGMT,
     753           0 :             AR_PIPE_TX_DATA, AR_PIPE_RX_DATA, &usc->ep_mgmt);
     754           0 :         if (error != 0)
     755           0 :                 return (error);
     756           0 :         error = athn_usb_htc_connect_svc(usc, AR_SVC_WMI_DATA_BE,
     757           0 :             AR_PIPE_TX_DATA, AR_PIPE_RX_DATA, &usc->ep_data[EDCA_AC_BE]);
     758           0 :         if (error != 0)
     759           0 :                 return (error);
     760           0 :         error = athn_usb_htc_connect_svc(usc, AR_SVC_WMI_DATA_BK,
     761           0 :             AR_PIPE_TX_DATA, AR_PIPE_RX_DATA, &usc->ep_data[EDCA_AC_BK]);
     762           0 :         if (error != 0)
     763           0 :                 return (error);
     764           0 :         error = athn_usb_htc_connect_svc(usc, AR_SVC_WMI_DATA_VI,
     765           0 :             AR_PIPE_TX_DATA, AR_PIPE_RX_DATA, &usc->ep_data[EDCA_AC_VI]);
     766           0 :         if (error != 0)
     767           0 :                 return (error);
     768           0 :         error = athn_usb_htc_connect_svc(usc, AR_SVC_WMI_DATA_VO,
     769           0 :             AR_PIPE_TX_DATA, AR_PIPE_RX_DATA, &usc->ep_data[EDCA_AC_VO]);
     770           0 :         if (error != 0)
     771           0 :                 return (error);
     772             : 
     773             :         /* Set credits for WLAN Tx pipe. */
     774           0 :         memset(&cfg, 0, sizeof(cfg));
     775           0 :         cfg.pipe_id = UE_GET_ADDR(AR_PIPE_TX_DATA);
     776           0 :         cfg.credits = (usc->flags & ATHN_USB_FLAG_AR7010) ? 45 : 33;
     777           0 :         s = splusb();
     778           0 :         usc->wait_msg_id = AR_HTC_MSG_CONF_PIPE_RSP;
     779           0 :         error = athn_usb_htc_msg(usc, AR_HTC_MSG_CONF_PIPE, &cfg, sizeof(cfg));
     780           0 :         if (error == 0 && usc->wait_msg_id != 0)
     781           0 :                 error = tsleep(&usc->wait_msg_id, 0, "athnhtc", hz);
     782           0 :         usc->wait_msg_id = 0;
     783           0 :         splx(s);
     784           0 :         if (error != 0) {
     785           0 :                 printf("%s: could not configure pipe\n",
     786           0 :                     usc->usb_dev.dv_xname);
     787           0 :                 return (error);
     788             :         }
     789             : 
     790           0 :         error = athn_usb_htc_msg(usc, AR_HTC_MSG_SETUP_COMPLETE, NULL, 0);
     791           0 :         if (error != 0) {
     792           0 :                 printf("%s: could not complete setup\n",
     793           0 :                     usc->usb_dev.dv_xname);
     794           0 :                 return (error);
     795             :         }
     796           0 :         return (0);
     797           0 : }
     798             : 
     799             : int
     800           0 : athn_usb_htc_connect_svc(struct athn_usb_softc *usc, uint16_t svc_id,
     801             :     uint8_t ul_pipe, uint8_t dl_pipe, uint8_t *endpoint_id)
     802             : {
     803           0 :         struct ar_htc_msg_conn_svc msg;
     804           0 :         struct ar_htc_msg_conn_svc_rsp rsp;
     805             :         int s, error;
     806             : 
     807           0 :         memset(&msg, 0, sizeof(msg));
     808           0 :         msg.svc_id = htobe16(svc_id);
     809           0 :         msg.dl_pipeid = UE_GET_ADDR(dl_pipe);
     810           0 :         msg.ul_pipeid = UE_GET_ADDR(ul_pipe);
     811           0 :         s = splusb();
     812           0 :         usc->msg_conn_svc_rsp = &rsp;
     813           0 :         usc->wait_msg_id = AR_HTC_MSG_CONN_SVC_RSP;
     814           0 :         error = athn_usb_htc_msg(usc, AR_HTC_MSG_CONN_SVC, &msg, sizeof(msg));
     815             :         /* Wait at most 1 second for response. */
     816           0 :         if (error == 0 && usc->wait_msg_id != 0)
     817           0 :                 error = tsleep(&usc->wait_msg_id, 0, "athnhtc", hz);
     818           0 :         usc->wait_msg_id = 0;
     819           0 :         splx(s);
     820           0 :         if (error != 0) {
     821           0 :                 printf("%s: error waiting for service %d connection\n",
     822           0 :                     usc->usb_dev.dv_xname, svc_id);
     823           0 :                 return (error);
     824             :         }
     825           0 :         if (rsp.status != AR_HTC_SVC_SUCCESS) {
     826           0 :                 printf("%s: service %d connection failed, error %d\n",
     827           0 :                     usc->usb_dev.dv_xname, svc_id, rsp.status);
     828           0 :                 return (EIO);
     829             :         }
     830             :         DPRINTF(("service %d successfully connected to endpoint %d\n",
     831             :             svc_id, rsp.endpoint_id));
     832             : 
     833             :         /* Return endpoint id. */
     834           0 :         *endpoint_id = rsp.endpoint_id;
     835           0 :         return (0);
     836           0 : }
     837             : 
     838             : int
     839           0 : athn_usb_wmi_xcmd(struct athn_usb_softc *usc, uint16_t cmd_id, void *ibuf,
     840             :     int ilen, void *obuf)
     841             : {
     842           0 :         struct athn_usb_tx_data *data = &usc->tx_cmd;
     843             :         struct ar_htc_frame_hdr *htc;
     844             :         struct ar_wmi_cmd_hdr *wmi;
     845             :         int s, error;
     846             : 
     847           0 :         if (usbd_is_dying(usc->sc_udev))
     848           0 :                 return ENXIO;
     849             : 
     850           0 :         s = splusb();
     851           0 :         while (usc->wait_cmd_id) {
     852             :                 /* 
     853             :                  * The previous USB transfer is not done yet. We can't use
     854             :                  * data->xfer until it is done or we'll cause major confusion
     855             :                  * in the USB stack.
     856             :                  */
     857           0 :                 tsleep(&usc->wait_cmd_id, 0, "athnwmx", ATHN_USB_CMD_TIMEOUT);
     858           0 :                 if (usbd_is_dying(usc->sc_udev)) {
     859           0 :                         splx(s);
     860           0 :                         return ENXIO;
     861             :                 }
     862             :         }
     863           0 :         splx(s);
     864             : 
     865           0 :         htc = (struct ar_htc_frame_hdr *)data->buf;
     866           0 :         memset(htc, 0, sizeof(*htc));
     867           0 :         htc->endpoint_id = usc->ep_ctrl;
     868           0 :         htc->payload_len = htobe16(sizeof(*wmi) + ilen);
     869             : 
     870           0 :         wmi = (struct ar_wmi_cmd_hdr *)&htc[1];
     871           0 :         wmi->cmd_id = htobe16(cmd_id);
     872           0 :         usc->wmi_seq_no++;
     873           0 :         wmi->seq_no = htobe16(usc->wmi_seq_no);
     874             : 
     875           0 :         memcpy(&wmi[1], ibuf, ilen);
     876             : 
     877           0 :         usbd_setup_xfer(data->xfer, usc->tx_intr_pipe, NULL, data->buf,
     878           0 :             sizeof(*htc) + sizeof(*wmi) + ilen,
     879             :             USBD_SHORT_XFER_OK | USBD_NO_COPY, ATHN_USB_CMD_TIMEOUT,
     880             :             NULL);
     881           0 :         s = splusb();
     882           0 :         error = usbd_transfer(data->xfer);
     883           0 :         if (__predict_false(error != USBD_IN_PROGRESS && error != 0)) {
     884           0 :                 splx(s);
     885           0 :                 return (error);
     886             :         }
     887           0 :         usc->obuf = obuf;
     888           0 :         usc->wait_cmd_id = cmd_id;
     889             :         /* 
     890             :          * Wait for WMI command complete interrupt. In case it does not fire
     891             :          * wait until the USB transfer times out to avoid racing the transfer.
     892             :          */
     893           0 :         error = tsleep(&usc->wait_cmd_id, 0, "athnwmi", ATHN_USB_CMD_TIMEOUT);
     894           0 :         if (error) {
     895           0 :                 if (error == EWOULDBLOCK) {
     896           0 :                         printf("%s: firmware command 0x%x timed out\n",
     897           0 :                             usc->usb_dev.dv_xname, cmd_id);
     898             :                         error = ETIMEDOUT;
     899           0 :                 }
     900             :         }
     901             : 
     902             :         /* 
     903             :          * Both the WMI command and transfer are done or have timed out.
     904             :          * Allow other threads to enter this function and use data->xfer.
     905             :          */
     906           0 :         usc->wait_cmd_id = 0;
     907           0 :         wakeup(&usc->wait_cmd_id);
     908             : 
     909           0 :         splx(s);
     910           0 :         return (error);
     911           0 : }
     912             : 
     913             : int
     914           0 : athn_usb_read_rom(struct athn_softc *sc)
     915             : {
     916           0 :         struct athn_usb_softc *usc = (struct athn_usb_softc *)sc;
     917           0 :         uint32_t addrs[8], vals[8], addr;
     918             :         uint16_t *eep;
     919             :         int i, j, error;
     920             : 
     921             :         /* Read EEPROM by blocks of 16 bytes. */
     922           0 :         eep = sc->eep;
     923           0 :         addr = AR_EEPROM_OFFSET(sc->eep_base);
     924           0 :         for (i = 0; i < sc->eep_size / 16; i++) {
     925           0 :                 for (j = 0; j < 8; j++, addr += 4)
     926           0 :                         addrs[j] = htobe32(addr);
     927           0 :                 error = athn_usb_wmi_xcmd(usc, AR_WMI_CMD_REG_READ,
     928           0 :                     addrs, sizeof(addrs), vals);
     929           0 :                 if (error != 0)
     930             :                         break;
     931           0 :                 for (j = 0; j < 8; j++)
     932           0 :                         *eep++ = betoh32(vals[j]);
     933             :         }
     934           0 :         return (error);
     935           0 : }
     936             : 
     937             : uint32_t
     938           0 : athn_usb_read(struct athn_softc *sc, uint32_t addr)
     939             : {
     940           0 :         struct athn_usb_softc *usc = (struct athn_usb_softc *)sc;
     941           0 :         uint32_t val;
     942             :         int error;
     943             : 
     944             :         /* Flush pending writes for strict consistency. */
     945           0 :         athn_usb_write_barrier(sc);
     946             : 
     947           0 :         addr = htobe32(addr);
     948           0 :         error = athn_usb_wmi_xcmd(usc, AR_WMI_CMD_REG_READ,
     949           0 :             &addr, sizeof(addr), &val);
     950           0 :         if (error != 0)
     951           0 :                 return (0xdeadbeef);
     952           0 :         return (betoh32(val));
     953           0 : }
     954             : 
     955             : void
     956           0 : athn_usb_write(struct athn_softc *sc, uint32_t addr, uint32_t val)
     957             : {
     958           0 :         struct athn_usb_softc *usc = (struct athn_usb_softc *)sc;
     959             : 
     960           0 :         usc->wbuf[usc->wcount].addr = htobe32(addr);
     961           0 :         usc->wbuf[usc->wcount].val  = htobe32(val);
     962           0 :         if (++usc->wcount == AR_MAX_WRITE_COUNT)
     963           0 :                 athn_usb_write_barrier(sc);
     964           0 : }
     965             : 
     966             : void
     967           0 : athn_usb_write_barrier(struct athn_softc *sc)
     968             : {
     969           0 :         struct athn_usb_softc *usc = (struct athn_usb_softc *)sc;
     970             : 
     971           0 :         if (usc->wcount == 0)
     972           0 :                 return; /* Nothing to write. */
     973             : 
     974           0 :         (void)athn_usb_wmi_xcmd(usc, AR_WMI_CMD_REG_WRITE,
     975           0 :             usc->wbuf, usc->wcount * sizeof(usc->wbuf[0]), NULL);
     976           0 :         usc->wcount = 0;     /* Always flush buffer. */
     977           0 : }
     978             : 
     979             : int
     980           0 : athn_usb_media_change(struct ifnet *ifp)
     981             : {
     982           0 :         struct athn_usb_softc *usc = (struct athn_usb_softc *)ifp->if_softc;
     983             :         int error;
     984             : 
     985           0 :         if (usbd_is_dying(usc->sc_udev))
     986           0 :                 return ENXIO;
     987             : 
     988           0 :         error = ieee80211_media_change(ifp);
     989           0 :         if (error != ENETRESET)
     990           0 :                 return (error);
     991             : 
     992           0 :         if ((ifp->if_flags & (IFF_UP | IFF_RUNNING)) ==
     993             :             (IFF_UP | IFF_RUNNING)) {
     994           0 :                 athn_usb_stop(ifp);
     995           0 :                 error = athn_usb_init(ifp);
     996           0 :         }
     997           0 :         return (error);
     998           0 : }
     999             : 
    1000             : void
    1001           0 : athn_usb_next_scan(void *arg)
    1002             : {
    1003           0 :         struct athn_usb_softc *usc = arg;
    1004           0 :         struct athn_softc *sc = &usc->sc_sc;
    1005           0 :         struct ieee80211com *ic = &sc->sc_ic;
    1006             :         int s;
    1007             : 
    1008           0 :         if (usbd_is_dying(usc->sc_udev))
    1009           0 :                 return;
    1010             : 
    1011           0 :         usbd_ref_incr(usc->sc_udev);
    1012             : 
    1013           0 :         s = splnet();
    1014           0 :         if (ic->ic_state == IEEE80211_S_SCAN)
    1015           0 :                 ieee80211_next_scan(&ic->ic_if);
    1016           0 :         splx(s);
    1017             : 
    1018           0 :         usbd_ref_decr(usc->sc_udev);
    1019           0 : }
    1020             : 
    1021             : int
    1022           0 : athn_usb_newstate(struct ieee80211com *ic, enum ieee80211_state nstate,
    1023             :     int arg)
    1024             : {
    1025           0 :         struct athn_usb_softc *usc = ic->ic_softc;
    1026           0 :         struct athn_usb_cmd_newstate cmd;
    1027             : 
    1028             :         /* Do it in a process context. */
    1029           0 :         cmd.state = nstate;
    1030           0 :         cmd.arg = arg;
    1031           0 :         athn_usb_do_async(usc, athn_usb_newstate_cb, &cmd, sizeof(cmd));
    1032           0 :         return (0);
    1033           0 : }
    1034             : 
    1035             : void
    1036           0 : athn_usb_newstate_cb(struct athn_usb_softc *usc, void *arg)
    1037             : {
    1038           0 :         struct athn_usb_cmd_newstate *cmd = arg;
    1039           0 :         struct athn_softc *sc = &usc->sc_sc;
    1040           0 :         struct ieee80211com *ic = &sc->sc_ic;
    1041             :         enum ieee80211_state ostate;
    1042           0 :         uint32_t reg, imask;
    1043             :         int s, error;
    1044             : 
    1045           0 :         timeout_del(&sc->calib_to);
    1046             : 
    1047           0 :         s = splnet();
    1048           0 :         ostate = ic->ic_state;
    1049             : 
    1050           0 :         if (ostate == IEEE80211_S_RUN && ic->ic_opmode == IEEE80211_M_STA) {
    1051           0 :                 athn_usb_remove_node(usc, ic->ic_bss);
    1052           0 :                 reg = AR_READ(sc, AR_RX_FILTER);
    1053           0 :                 reg = (reg & ~AR_RX_FILTER_MYBEACON) |
    1054             :                     AR_RX_FILTER_BEACON;
    1055           0 :                 AR_WRITE(sc, AR_RX_FILTER, reg);
    1056           0 :                 AR_WRITE_BARRIER(sc);
    1057           0 :         }
    1058           0 :         switch (cmd->state) {
    1059             :         case IEEE80211_S_INIT:
    1060           0 :                 athn_set_led(sc, 0);
    1061           0 :                 break;
    1062             :         case IEEE80211_S_SCAN:
    1063             :                 /* Make the LED blink while scanning. */
    1064           0 :                 athn_set_led(sc, !sc->led_state);
    1065           0 :                 error = athn_usb_switch_chan(sc, ic->ic_bss->ni_chan, NULL);
    1066           0 :                 if (error)
    1067           0 :                         printf("%s: could not switch to channel %d\n",
    1068           0 :                             usc->usb_dev.dv_xname,
    1069           0 :                             ieee80211_chan2ieee(ic, ic->ic_bss->ni_chan));
    1070           0 :                 if (!usbd_is_dying(usc->sc_udev))
    1071           0 :                         timeout_add_msec(&sc->scan_to, 200);
    1072             :                 break;
    1073             :         case IEEE80211_S_AUTH:
    1074           0 :                 athn_set_led(sc, 0);
    1075           0 :                 error = athn_usb_switch_chan(sc, ic->ic_bss->ni_chan, NULL);
    1076           0 :                 if (error)
    1077           0 :                         printf("%s: could not switch to channel %d\n",
    1078           0 :                             usc->usb_dev.dv_xname,
    1079           0 :                             ieee80211_chan2ieee(ic, ic->ic_bss->ni_chan));
    1080             :                 break;
    1081             :         case IEEE80211_S_ASSOC:
    1082             :                 break;
    1083             :         case IEEE80211_S_RUN:
    1084           0 :                 athn_set_led(sc, 1);
    1085             : 
    1086           0 :                 if (ic->ic_opmode == IEEE80211_M_MONITOR)
    1087             :                         break;
    1088             : 
    1089           0 :                 if (ic->ic_opmode == IEEE80211_M_STA) {
    1090             :                         /* Create node entry for our BSS */
    1091           0 :                         error = athn_usb_create_node(usc, ic->ic_bss);
    1092           0 :                         if (error)
    1093           0 :                                 printf("%s: could not update firmware station "
    1094           0 :                                     "table\n", usc->usb_dev.dv_xname);
    1095             :                 }
    1096           0 :                 athn_set_bss(sc, ic->ic_bss);
    1097           0 :                 athn_usb_wmi_cmd(usc, AR_WMI_CMD_DISABLE_INTR);
    1098             : #ifndef IEEE80211_STA_ONLY
    1099           0 :                 if (ic->ic_opmode == IEEE80211_M_HOSTAP) {
    1100           0 :                         athn_usb_switch_chan(sc, ic->ic_bss->ni_chan, NULL);
    1101           0 :                         athn_set_hostap_timers(sc);
    1102             :                         /* Enable software beacon alert interrupts. */
    1103           0 :                         imask = htobe32(AR_IMR_SWBA);
    1104           0 :                 } else
    1105             : #endif
    1106             :                 {
    1107           0 :                         athn_set_sta_timers(sc);
    1108             :                         /* Enable beacon miss interrupts. */
    1109           0 :                         imask = htobe32(AR_IMR_BMISS);
    1110             : 
    1111             :                         /* Stop receiving beacons from other BSS. */
    1112           0 :                         reg = AR_READ(sc, AR_RX_FILTER);
    1113           0 :                         reg = (reg & ~AR_RX_FILTER_BEACON) |
    1114             :                             AR_RX_FILTER_MYBEACON;
    1115           0 :                         AR_WRITE(sc, AR_RX_FILTER, reg);
    1116           0 :                         AR_WRITE_BARRIER(sc);
    1117             :                 }
    1118           0 :                 athn_usb_wmi_xcmd(usc, AR_WMI_CMD_ENABLE_INTR,
    1119             :                     &imask, sizeof(imask), NULL);
    1120           0 :                 break;
    1121             :         }
    1122           0 :         (void)sc->sc_newstate(ic, cmd->state, cmd->arg);
    1123           0 :         splx(s);
    1124           0 : }
    1125             : 
    1126             : void
    1127           0 : athn_usb_newassoc(struct ieee80211com *ic, struct ieee80211_node *ni,
    1128             :     int isnew)
    1129             : {
    1130             : #ifndef IEEE80211_STA_ONLY
    1131           0 :         struct athn_usb_softc *usc = ic->ic_softc;
    1132             : 
    1133           0 :         if (ic->ic_opmode != IEEE80211_M_HOSTAP &&
    1134           0 :             ic->ic_state != IEEE80211_S_RUN)
    1135           0 :                 return;
    1136             : 
    1137             :         /* Update the node's supported rates in a process context. */
    1138           0 :         ieee80211_ref_node(ni);
    1139           0 :         athn_usb_do_async(usc, athn_usb_newassoc_cb, &ni, sizeof(ni));
    1140             : #endif
    1141           0 : }
    1142             : 
    1143             : #ifndef IEEE80211_STA_ONLY
    1144             : void
    1145           0 : athn_usb_newassoc_cb(struct athn_usb_softc *usc, void *arg)
    1146             : {
    1147           0 :         struct ieee80211com *ic = &usc->sc_sc.sc_ic;
    1148           0 :         struct ieee80211_node *ni = *(void **)arg;
    1149           0 :         struct athn_node *an = (struct athn_node *)ni;
    1150             :         int s;
    1151             : 
    1152           0 :         if (ic->ic_state != IEEE80211_S_RUN)
    1153           0 :                 return;
    1154             : 
    1155           0 :         s = splnet();
    1156             :         /* NB: Node may have left before we got scheduled. */
    1157           0 :         if (an->sta_index != 0)
    1158           0 :                 (void)athn_usb_node_set_rates(usc, ni);
    1159           0 :         ieee80211_release_node(ic, ni);
    1160           0 :         splx(s);
    1161           0 : }
    1162             : #endif
    1163             : 
    1164             : struct ieee80211_node *
    1165           0 : athn_usb_node_alloc(struct ieee80211com *ic)
    1166             : {
    1167             :         struct athn_node *an;
    1168             : 
    1169           0 :         an = malloc(sizeof(struct athn_node), M_DEVBUF, M_NOWAIT | M_ZERO);
    1170           0 :         return (struct ieee80211_node *)an;
    1171             : }
    1172             : 
    1173             : 
    1174             : #ifndef IEEE80211_STA_ONLY
    1175             : void
    1176           0 : athn_usb_count_active_sta(void *arg, struct ieee80211_node *ni)
    1177             : {
    1178           0 :         int *nsta = arg;
    1179           0 :         struct athn_node *an = (struct athn_node *)ni;
    1180             : 
    1181           0 :         if (an->sta_index == 0)
    1182           0 :                 return;
    1183             : 
    1184           0 :         if ((ni->ni_state == IEEE80211_STA_AUTH ||
    1185           0 :             ni->ni_state == IEEE80211_STA_ASSOC) &&
    1186           0 :             ni->ni_inact < IEEE80211_INACT_MAX)
    1187           0 :                 (*nsta)++;
    1188           0 : }
    1189             : 
    1190             : struct athn_usb_newauth_cb_arg {
    1191             :         struct ieee80211_node *ni;
    1192             :         uint16_t seq;
    1193             : };
    1194             : 
    1195             : void
    1196           0 : athn_usb_newauth_cb(struct athn_usb_softc *usc, void *arg)
    1197             : {
    1198           0 :         struct ieee80211com *ic = &usc->sc_sc.sc_ic;
    1199           0 :         struct athn_usb_newauth_cb_arg *a = arg;
    1200           0 :         struct ieee80211_node *ni = a->ni;
    1201           0 :         uint16_t seq = a->seq;
    1202           0 :         struct athn_node *an = (struct athn_node *)ni;
    1203             :         int s, error = 0;
    1204             : 
    1205           0 :         free(arg, M_DEVBUF, sizeof(*arg));
    1206             : 
    1207           0 :         if (ic->ic_state != IEEE80211_S_RUN)
    1208           0 :                 return;
    1209             : 
    1210           0 :         s = splnet();
    1211           0 :         if (an->sta_index == 0) {
    1212           0 :                 error = athn_usb_create_node(usc, ni);
    1213           0 :                 if (error)
    1214           0 :                         printf("%s: could not add station %s to firmware "
    1215           0 :                             "table\n", usc->usb_dev.dv_xname,
    1216           0 :                             ether_sprintf(ni->ni_macaddr));
    1217             :         }
    1218           0 :         if (error == 0)
    1219           0 :                 ieee80211_auth_open_confirm(ic, ni, seq);
    1220           0 :         ieee80211_unref_node(&ni);
    1221           0 :         splx(s);
    1222           0 : }
    1223             : #endif
    1224             : 
    1225             : int
    1226           0 : athn_usb_newauth(struct ieee80211com *ic, struct ieee80211_node *ni,
    1227             :     int isnew, uint16_t seq)
    1228             : {
    1229             : #ifndef IEEE80211_STA_ONLY
    1230           0 :         struct athn_usb_softc *usc = ic->ic_softc;
    1231             :         struct ifnet *ifp = &ic->ic_if;
    1232           0 :         struct athn_node *an = (struct athn_node *)ni;
    1233           0 :         int nsta;
    1234             :         struct athn_usb_newauth_cb_arg *arg;
    1235             : 
    1236           0 :         if (ic->ic_opmode != IEEE80211_M_HOSTAP)
    1237           0 :                 return 0;
    1238             : 
    1239           0 :         if (!isnew && an->sta_index != 0) /* already in firmware table */
    1240           0 :                 return 0;
    1241             : 
    1242             :         /* Check if we have room in the firmware table. */
    1243           0 :         nsta = 1; /* Account for default node. */
    1244           0 :         ieee80211_iterate_nodes(ic, athn_usb_count_active_sta, &nsta);
    1245           0 :         if (nsta >= AR_USB_MAX_STA) {
    1246           0 :                 if (ifp->if_flags & IFF_DEBUG)
    1247           0 :                         printf("%s: cannot authenticate station %s: firmware "
    1248           0 :                             "table is full\n", usc->usb_dev.dv_xname,
    1249           0 :                             ether_sprintf(ni->ni_macaddr));
    1250           0 :                 return ENOSPC;
    1251             :         }
    1252             : 
    1253             :         /* 
    1254             :          * In a process context, try to add this node to the
    1255             :          * firmware table and confirm the AUTH request.
    1256             :          */
    1257           0 :         arg = malloc(sizeof(*arg), M_DEVBUF, M_NOWAIT);
    1258           0 :         if (arg == NULL)
    1259           0 :                 return ENOMEM;
    1260           0 :         arg->ni = ieee80211_ref_node(ni);
    1261           0 :         arg->seq = seq;
    1262           0 :         athn_usb_do_async(usc, athn_usb_newauth_cb, arg, sizeof(*arg));
    1263           0 :         return EBUSY;
    1264             : #else
    1265             :         return 0;
    1266             : #endif /* IEEE80211_STA_ONLY */
    1267           0 : }
    1268             : 
    1269             : #ifndef IEEE80211_STA_ONLY
    1270             : void
    1271           0 : athn_usb_node_free(struct ieee80211com *ic, struct ieee80211_node *ni)
    1272             : {
    1273           0 :         struct athn_usb_softc *usc = ic->ic_softc;
    1274           0 :         struct athn_node *an = (struct athn_node *)ni;
    1275             : 
    1276             :         /* 
    1277             :          * Remove the node from the firmware table in a process context.
    1278             :          * Pass an index rather than the pointer which we will free.
    1279             :          */
    1280           0 :         if (an->sta_index != 0)
    1281           0 :                 athn_usb_do_async(usc, athn_usb_node_free_cb,
    1282             :                     &an->sta_index, sizeof(an->sta_index));
    1283           0 :         usc->sc_node_free(ic, ni);
    1284           0 : }
    1285             : 
    1286             : void
    1287           0 : athn_usb_node_free_cb(struct athn_usb_softc *usc, void *arg)
    1288             : {
    1289           0 :         struct ieee80211com *ic = &usc->sc_sc.sc_ic;
    1290           0 :         struct ifnet *ifp = &ic->ic_if;
    1291           0 :         uint8_t sta_index = *(uint8_t *)arg;
    1292             :         int error;
    1293             : 
    1294           0 :         error = athn_usb_wmi_xcmd(usc, AR_WMI_CMD_NODE_REMOVE,
    1295             :             &sta_index, sizeof(sta_index), NULL);
    1296           0 :         if (error) {
    1297           0 :                 printf("%s: could not remove station %u from firmware table\n",
    1298           0 :                     usc->usb_dev.dv_xname, sta_index);
    1299           0 :                 return;
    1300             :         }
    1301           0 :         usc->free_node_slots |= (1 << sta_index);
    1302           0 :         if (ifp->if_flags & IFF_DEBUG)
    1303           0 :                 printf("%s: station %u removed from firmware table\n",
    1304           0 :                     usc->usb_dev.dv_xname, sta_index);
    1305           0 : }
    1306             : #endif /* IEEE80211_STA_ONLY */
    1307             : 
    1308             : int
    1309           0 : athn_usb_ampdu_tx_start(struct ieee80211com *ic, struct ieee80211_node *ni,
    1310             :     uint8_t tid)
    1311             : {
    1312           0 :         struct athn_usb_softc *usc = ic->ic_softc;
    1313           0 :         struct athn_node *an = (struct athn_node *)ni;
    1314           0 :         struct athn_usb_aggr_cmd cmd;
    1315             : 
    1316             :         /* Do it in a process context. */
    1317           0 :         cmd.sta_index = an->sta_index;
    1318           0 :         cmd.tid = tid;
    1319           0 :         athn_usb_do_async(usc, athn_usb_ampdu_tx_start_cb, &cmd, sizeof(cmd));
    1320           0 :         return (0);
    1321           0 : }
    1322             : 
    1323             : void
    1324           0 : athn_usb_ampdu_tx_start_cb(struct athn_usb_softc *usc, void *arg)
    1325             : {
    1326           0 :         struct athn_usb_aggr_cmd *cmd = arg;
    1327           0 :         struct ar_htc_target_aggr aggr;
    1328             : 
    1329           0 :         memset(&aggr, 0, sizeof(aggr));
    1330           0 :         aggr.sta_index = cmd->sta_index;
    1331           0 :         aggr.tidno = cmd->tid;
    1332           0 :         aggr.aggr_enable = 1;
    1333           0 :         (void)athn_usb_wmi_xcmd(usc, AR_WMI_CMD_TX_AGGR_ENABLE,
    1334             :             &aggr, sizeof(aggr), NULL);
    1335           0 : }
    1336             : 
    1337             : void
    1338           0 : athn_usb_ampdu_tx_stop(struct ieee80211com *ic, struct ieee80211_node *ni,
    1339             :     uint8_t tid)
    1340             : {
    1341           0 :         struct athn_usb_softc *usc = ic->ic_softc;
    1342           0 :         struct athn_node *an = (struct athn_node *)ni;
    1343           0 :         struct athn_usb_aggr_cmd cmd;
    1344             : 
    1345             :         /* Do it in a process context. */
    1346           0 :         cmd.sta_index = an->sta_index;
    1347           0 :         cmd.tid = tid;
    1348           0 :         athn_usb_do_async(usc, athn_usb_ampdu_tx_stop_cb, &cmd, sizeof(cmd));
    1349           0 : }
    1350             : 
    1351             : void
    1352           0 : athn_usb_ampdu_tx_stop_cb(struct athn_usb_softc *usc, void *arg)
    1353             : {
    1354           0 :         struct athn_usb_aggr_cmd *cmd = arg;
    1355           0 :         struct ar_htc_target_aggr aggr;
    1356             : 
    1357           0 :         memset(&aggr, 0, sizeof(aggr));
    1358           0 :         aggr.sta_index = cmd->sta_index;
    1359           0 :         aggr.tidno = cmd->tid;
    1360           0 :         aggr.aggr_enable = 0;
    1361           0 :         (void)athn_usb_wmi_xcmd(usc, AR_WMI_CMD_TX_AGGR_ENABLE,
    1362             :             &aggr, sizeof(aggr), NULL);
    1363           0 : }
    1364             : 
    1365             : #ifndef IEEE80211_STA_ONLY
    1366             : /* Try to find a node we can evict to make room in the firmware table. */
    1367             : void
    1368           0 : athn_usb_clean_nodes(void *arg, struct ieee80211_node *ni)
    1369             : {
    1370           0 :         struct athn_usb_softc *usc = arg;
    1371           0 :         struct ieee80211com *ic = &usc->sc_sc.sc_ic;
    1372           0 :         struct athn_node *an = (struct athn_node *)ni;
    1373             : 
    1374             :         /* 
    1375             :          * Don't remove the default node (used for management frames).
    1376             :          * Nodes which are not in the firmware table also have index zero.
    1377             :          */
    1378           0 :         if (an->sta_index == 0)
    1379           0 :                 return;
    1380             : 
    1381             :         /* Remove non-associated nodes. */
    1382           0 :         if (ni->ni_state != IEEE80211_STA_AUTH &&
    1383           0 :             ni->ni_state != IEEE80211_STA_ASSOC) {
    1384           0 :                 athn_usb_remove_node(usc, ni);
    1385           0 :                 return;
    1386             :         }
    1387             : 
    1388             :         /* 
    1389             :          * Kick off inactive associated nodes. This won't help
    1390             :          * immediately but will help if the new STA retries later.
    1391             :          */
    1392           0 :         if (ni->ni_inact >= IEEE80211_INACT_MAX) {
    1393           0 :                 IEEE80211_SEND_MGMT(ic, ni, IEEE80211_FC0_SUBTYPE_DEAUTH,
    1394             :                     IEEE80211_REASON_AUTH_EXPIRE);
    1395           0 :                 ieee80211_node_leave(ic, ni);
    1396           0 :         }
    1397           0 : }
    1398             : #endif
    1399             : 
    1400             : int
    1401           0 : athn_usb_create_node(struct athn_usb_softc *usc, struct ieee80211_node *ni)
    1402             : {
    1403           0 :         struct athn_node *an = (struct athn_node *)ni;
    1404           0 :         struct ar_htc_target_sta sta;
    1405             :         int error, sta_index;
    1406             : #ifndef IEEE80211_STA_ONLY
    1407           0 :         struct ieee80211com *ic = &usc->sc_sc.sc_ic;
    1408           0 :         struct ifnet *ifp = &ic->ic_if;
    1409             : 
    1410             :         /* Firmware cannot handle more than 8 STAs. Try to make room first. */
    1411           0 :         if (ic->ic_opmode == IEEE80211_M_HOSTAP)
    1412           0 :                 ieee80211_iterate_nodes(ic, athn_usb_clean_nodes, usc);
    1413             : #endif
    1414           0 :         if (usc->free_node_slots == 0x00)
    1415           0 :                 return ENOBUFS;
    1416             : 
    1417           0 :         sta_index = ffs(usc->free_node_slots) - 1;
    1418           0 :         if (sta_index < 0 || sta_index >= AR_USB_MAX_STA)
    1419           0 :                 return ENOSPC;
    1420             : 
    1421             :         /* Create node entry on target. */
    1422           0 :         memset(&sta, 0, sizeof(sta));
    1423           0 :         IEEE80211_ADDR_COPY(sta.macaddr, ni->ni_macaddr);
    1424           0 :         IEEE80211_ADDR_COPY(sta.bssid, ni->ni_bssid);
    1425           0 :         sta.sta_index = sta_index;
    1426           0 :         sta.maxampdu = 0xffff;
    1427           0 :         if (ni->ni_flags & IEEE80211_NODE_HT)
    1428           0 :                 sta.flags |= htobe16(AR_HTC_STA_HT);
    1429           0 :         error = athn_usb_wmi_xcmd(usc, AR_WMI_CMD_NODE_CREATE,
    1430             :             &sta, sizeof(sta), NULL);
    1431           0 :         if (error != 0)
    1432           0 :                 return (error);
    1433           0 :         an->sta_index = sta_index;
    1434           0 :         usc->free_node_slots &= ~(1 << an->sta_index);
    1435             : 
    1436             : #ifndef IEEE80211_STA_ONLY
    1437           0 :         if (ifp->if_flags & IFF_DEBUG)
    1438           0 :                 printf("%s: station %u (%s) added to firmware table\n",
    1439           0 :                     usc->usb_dev.dv_xname, sta_index,
    1440           0 :                     ether_sprintf(ni->ni_macaddr));
    1441             : #endif
    1442           0 :         return athn_usb_node_set_rates(usc, ni);
    1443           0 : }
    1444             : 
    1445             : int
    1446           0 : athn_usb_node_set_rates(struct athn_usb_softc *usc, struct ieee80211_node *ni)
    1447             : {
    1448           0 :         struct athn_node *an = (struct athn_node *)ni;
    1449           0 :         struct ar_htc_target_rate rate;
    1450             :         int i, j;
    1451             : 
    1452             :         /* Setup supported rates. */
    1453           0 :         memset(&rate, 0, sizeof(rate));
    1454           0 :         rate.sta_index = an->sta_index;
    1455           0 :         rate.isnew = 1;
    1456           0 :         rate.lg_rates.rs_nrates = ni->ni_rates.rs_nrates;
    1457           0 :         memcpy(rate.lg_rates.rs_rates, ni->ni_rates.rs_rates,
    1458             :             ni->ni_rates.rs_nrates);
    1459           0 :         if (ni->ni_flags & IEEE80211_NODE_HT) {
    1460           0 :                 rate.capflags |= htobe32(AR_RC_HT_FLAG);
    1461             :                 /* Setup HT rates. */
    1462           0 :                 for (i = 0, j = 0; i < IEEE80211_HT_NUM_MCS; i++) {
    1463           0 :                         if (!isset(ni->ni_rxmcs, i))
    1464             :                                 continue;
    1465           0 :                         if (j >= AR_HTC_RATE_MAX)
    1466             :                                 break;
    1467           0 :                         rate.ht_rates.rs_rates[j++] = i;
    1468           0 :                 }
    1469           0 :                 rate.ht_rates.rs_nrates = j;
    1470             : 
    1471           0 :                 if (ni->ni_rxmcs[1]) /* dual-stream MIMO rates */
    1472           0 :                         rate.capflags |= htobe32(AR_RC_DS_FLAG);
    1473             : #ifdef notyet
    1474             :                 if (ni->ni_htcaps & IEEE80211_HTCAP_CBW20_40)
    1475             :                         rate.capflags |= htobe32(AR_RC_40_FLAG);
    1476             :                 if (ni->ni_htcaps & IEEE80211_HTCAP_SGI40)
    1477             :                         rate.capflags |= htobe32(AR_RC_SGI_FLAG);
    1478             :                 if (ni->ni_htcaps & IEEE80211_HTCAP_SGI20)
    1479             :                         rate.capflags |= htobe32(AR_RC_SGI_FLAG);
    1480             : #endif
    1481             :         }
    1482             : 
    1483           0 :         return athn_usb_wmi_xcmd(usc, AR_WMI_CMD_RC_RATE_UPDATE,
    1484             :             &rate, sizeof(rate), NULL);
    1485           0 : }
    1486             : 
    1487             : int
    1488           0 : athn_usb_remove_node(struct athn_usb_softc *usc, struct ieee80211_node *ni)
    1489             : {
    1490           0 :         struct athn_node *an = (struct athn_node *)ni;
    1491             :         int error;
    1492             : #ifndef IEEE80211_STA_ONLY
    1493           0 :         struct ieee80211com *ic = &usc->sc_sc.sc_ic;
    1494           0 :         struct ifnet *ifp = &ic->ic_if;
    1495             : #endif
    1496             : 
    1497           0 :         error = athn_usb_wmi_xcmd(usc, AR_WMI_CMD_NODE_REMOVE,
    1498           0 :             &an->sta_index, sizeof(an->sta_index), NULL);
    1499           0 :         if (error) {
    1500           0 :                 printf("%s: could not remove station %u (%s) from "
    1501           0 :                     "firmware table\n", usc->usb_dev.dv_xname, an->sta_index,
    1502           0 :                     ether_sprintf(ni->ni_macaddr));
    1503           0 :                 return error;
    1504             :         }
    1505             : 
    1506             : #ifndef IEEE80211_STA_ONLY
    1507           0 :         if (ifp->if_flags & IFF_DEBUG)
    1508           0 :                 printf("%s: station %u (%s) removed from firmware table\n",
    1509           0 :                     usc->usb_dev.dv_xname, an->sta_index,
    1510           0 :                     ether_sprintf(ni->ni_macaddr));
    1511             : #endif
    1512             : 
    1513           0 :         usc->free_node_slots |= (1 << an->sta_index);
    1514           0 :         an->sta_index = 0;
    1515           0 :         return 0;
    1516           0 : }
    1517             : 
    1518             : void
    1519           0 : athn_usb_rx_enable(struct athn_softc *sc)
    1520             : {
    1521           0 :         AR_WRITE(sc, AR_CR, AR_CR_RXE);
    1522           0 :         AR_WRITE_BARRIER(sc);
    1523           0 : }
    1524             : 
    1525             : int
    1526           0 : athn_usb_switch_chan(struct athn_softc *sc, struct ieee80211_channel *c,
    1527             :     struct ieee80211_channel *extc)
    1528             : {
    1529           0 :         struct athn_usb_softc *usc = (struct athn_usb_softc *)sc;
    1530           0 :         uint16_t mode;
    1531             :         int error;
    1532             : 
    1533             :         /* Disable interrupts. */
    1534           0 :         error = athn_usb_wmi_cmd(usc, AR_WMI_CMD_DISABLE_INTR);
    1535           0 :         if (error != 0)
    1536             :                 goto reset;
    1537             :         /* Stop all Tx queues. */
    1538           0 :         error = athn_usb_wmi_cmd(usc, AR_WMI_CMD_DRAIN_TXQ_ALL);
    1539           0 :         if (error != 0)
    1540             :                 goto reset;
    1541             :         /* Stop Rx. */
    1542           0 :         error = athn_usb_wmi_cmd(usc, AR_WMI_CMD_STOP_RECV);
    1543           0 :         if (error != 0)
    1544             :                 goto reset;
    1545             : 
    1546             :         /* If band or bandwidth changes, we need to do a full reset. */
    1547           0 :         if (c->ic_flags != sc->curchan->ic_flags ||
    1548           0 :             ((extc != NULL) ^ (sc->curchanext != NULL))) {
    1549             :                 DPRINTFN(2, ("channel band switch\n"));
    1550             :                 goto reset;
    1551             :         }
    1552             : 
    1553           0 :         error = athn_set_chan(sc, c, extc);
    1554           0 :         if (AR_SREV_9271(sc) && error == 0)
    1555           0 :                 ar9271_load_ani(sc);
    1556           0 :         if (error != 0) {
    1557             :  reset:         /* Error found, try a full reset. */
    1558             :                 DPRINTFN(3, ("needs a full reset\n"));
    1559           0 :                 error = athn_hw_reset(sc, c, extc, 0);
    1560           0 :                 if (error != 0) /* Hopeless case. */
    1561           0 :                         return (error);
    1562             : 
    1563           0 :                 error = athn_set_chan(sc, c, extc);
    1564           0 :                 if (AR_SREV_9271(sc) && error == 0)
    1565           0 :                         ar9271_load_ani(sc);
    1566           0 :                 if (error != 0)
    1567           0 :                         return (error);
    1568             :         }
    1569             : 
    1570           0 :         sc->ops.set_txpower(sc, c, extc);
    1571             : 
    1572           0 :         error = athn_usb_wmi_cmd(usc, AR_WMI_CMD_START_RECV);
    1573           0 :         if (error != 0)
    1574           0 :                 return (error);
    1575           0 :         athn_rx_start(sc);
    1576             : 
    1577           0 :         mode = htobe16(IEEE80211_IS_CHAN_2GHZ(c) ?
    1578             :             AR_HTC_MODE_11NG : AR_HTC_MODE_11NA);
    1579           0 :         error = athn_usb_wmi_xcmd(usc, AR_WMI_CMD_SET_MODE,
    1580             :             &mode, sizeof(mode), NULL);
    1581           0 :         if (error != 0)
    1582           0 :                 return (error);
    1583             : 
    1584             :         /* Re-enable interrupts. */
    1585           0 :         error = athn_usb_wmi_cmd(usc, AR_WMI_CMD_ENABLE_INTR);
    1586           0 :         return (error);
    1587           0 : }
    1588             : 
    1589             : void
    1590           0 : athn_usb_updateedca(struct ieee80211com *ic)
    1591             : {
    1592           0 :         struct athn_usb_softc *usc = ic->ic_softc;
    1593             : 
    1594             :         /* Do it in a process context. */
    1595           0 :         athn_usb_do_async(usc, athn_usb_updateedca_cb, NULL, 0);
    1596           0 : }
    1597             : 
    1598             : void
    1599           0 : athn_usb_updateedca_cb(struct athn_usb_softc *usc, void *arg)
    1600             : {
    1601             :         int s;
    1602             : 
    1603           0 :         s = splnet();
    1604           0 :         athn_updateedca(&usc->sc_sc.sc_ic);
    1605           0 :         splx(s);
    1606           0 : }
    1607             : 
    1608             : void
    1609           0 : athn_usb_updateslot(struct ieee80211com *ic)
    1610             : {
    1611           0 :         struct athn_usb_softc *usc = ic->ic_softc;
    1612             : 
    1613             :         return; /* XXX */
    1614             :         /* Do it in a process context. */
    1615             :         athn_usb_do_async(usc, athn_usb_updateslot_cb, NULL, 0);
    1616           0 : }
    1617             : 
    1618             : void
    1619           0 : athn_usb_updateslot_cb(struct athn_usb_softc *usc, void *arg)
    1620             : {
    1621             :         int s;
    1622             : 
    1623           0 :         s = splnet();
    1624           0 :         athn_updateslot(&usc->sc_sc.sc_ic);
    1625           0 :         splx(s);
    1626           0 : }
    1627             : 
    1628             : int
    1629           0 : athn_usb_set_key(struct ieee80211com *ic, struct ieee80211_node *ni,
    1630             :     struct ieee80211_key *k)
    1631             : {
    1632           0 :         struct athn_usb_softc *usc = ic->ic_softc;
    1633           0 :         struct athn_usb_cmd_key cmd;
    1634             : 
    1635             :         /* Defer setting of WEP keys until interface is brought up. */
    1636           0 :         if ((ic->ic_if.if_flags & (IFF_UP | IFF_RUNNING)) !=
    1637             :             (IFF_UP | IFF_RUNNING))
    1638           0 :                 return (0);
    1639             : 
    1640             :         /* Do it in a process context. */
    1641           0 :         cmd.ni = (ni != NULL) ? ieee80211_ref_node(ni) : NULL;
    1642           0 :         cmd.key = k;
    1643           0 :         athn_usb_do_async(usc, athn_usb_set_key_cb, &cmd, sizeof(cmd));
    1644           0 :         return (0);
    1645           0 : }
    1646             : 
    1647             : void
    1648           0 : athn_usb_set_key_cb(struct athn_usb_softc *usc, void *arg)
    1649             : {
    1650           0 :         struct ieee80211com *ic = &usc->sc_sc.sc_ic;
    1651           0 :         struct athn_usb_cmd_key *cmd = arg;
    1652             :         int s;
    1653             : 
    1654           0 :         s = splnet();
    1655           0 :         athn_set_key(ic, cmd->ni, cmd->key);
    1656           0 :         if (cmd->ni != NULL)
    1657           0 :                 ieee80211_release_node(ic, cmd->ni);
    1658           0 :         splx(s);
    1659           0 : }
    1660             : 
    1661             : void
    1662           0 : athn_usb_delete_key(struct ieee80211com *ic, struct ieee80211_node *ni,
    1663             :     struct ieee80211_key *k)
    1664             : {
    1665           0 :         struct athn_usb_softc *usc = ic->ic_softc;
    1666           0 :         struct athn_usb_cmd_key cmd;
    1667             : 
    1668           0 :         if (!(ic->ic_if.if_flags & IFF_RUNNING) ||
    1669           0 :             ic->ic_state != IEEE80211_S_RUN)
    1670           0 :                 return; /* Nothing to do. */
    1671             : 
    1672             :         /* Do it in a process context. */
    1673           0 :         cmd.ni = (ni != NULL) ? ieee80211_ref_node(ni) : NULL;
    1674           0 :         cmd.key = k;
    1675           0 :         athn_usb_do_async(usc, athn_usb_delete_key_cb, &cmd, sizeof(cmd));
    1676           0 : }
    1677             : 
    1678             : void
    1679           0 : athn_usb_delete_key_cb(struct athn_usb_softc *usc, void *arg)
    1680             : {
    1681           0 :         struct ieee80211com *ic = &usc->sc_sc.sc_ic;
    1682           0 :         struct athn_usb_cmd_key *cmd = arg;
    1683             :         int s;
    1684             : 
    1685           0 :         s = splnet();
    1686           0 :         athn_delete_key(ic, cmd->ni, cmd->key);
    1687           0 :         if (cmd->ni != NULL)
    1688           0 :                 ieee80211_release_node(ic, cmd->ni);
    1689           0 :         splx(s);
    1690           0 : }
    1691             : 
    1692             : #ifndef IEEE80211_STA_ONLY
    1693             : void
    1694           0 : athn_usb_bcneof(struct usbd_xfer *xfer, void *priv,
    1695             :     usbd_status status)
    1696             : {
    1697           0 :         struct athn_usb_tx_data *data = priv;
    1698           0 :         struct athn_usb_softc *usc = data->sc;
    1699             : 
    1700           0 :         if (__predict_false(status == USBD_STALLED))
    1701           0 :                 usbd_clear_endpoint_stall_async(usc->tx_data_pipe);
    1702           0 :         usc->tx_bcn = data;
    1703           0 : }
    1704             : 
    1705             : /*
    1706             :  * Process Software Beacon Alert interrupts.
    1707             :  */
    1708             : void
    1709           0 : athn_usb_swba(struct athn_usb_softc *usc)
    1710             : {
    1711           0 :         struct athn_softc *sc = &usc->sc_sc;
    1712           0 :         struct ieee80211com *ic = &sc->sc_ic;
    1713             :         struct athn_usb_tx_data *data;
    1714             :         struct ieee80211_frame *wh;
    1715             :         struct ar_stream_hdr *hdr;
    1716             :         struct ar_htc_frame_hdr *htc;
    1717             :         struct ar_tx_bcn *bcn;
    1718             :         struct mbuf *m;
    1719             :         int error;
    1720             : 
    1721           0 :         if (ic->ic_dtim_count == 0)
    1722           0 :                 ic->ic_dtim_count = ic->ic_dtim_period - 1;
    1723             :         else
    1724           0 :                 ic->ic_dtim_count--;
    1725             : 
    1726             :         /* Make sure previous beacon has been sent. */
    1727           0 :         if (usc->tx_bcn == NULL)
    1728           0 :                 return;
    1729             :         data = usc->tx_bcn;
    1730             : 
    1731             :         /* Get new beacon. */
    1732           0 :         m = ieee80211_beacon_alloc(ic, ic->ic_bss);
    1733           0 :         if (__predict_false(m == NULL))
    1734           0 :                 return;
    1735             :         /* Assign sequence number. */
    1736           0 :         wh = mtod(m, struct ieee80211_frame *);
    1737           0 :         *(uint16_t *)&wh->i_seq[0] =
    1738           0 :             htole16(ic->ic_bss->ni_txseq << IEEE80211_SEQ_SEQ_SHIFT);
    1739           0 :         ic->ic_bss->ni_txseq++;
    1740             : 
    1741           0 :         hdr = (struct ar_stream_hdr *)data->buf;
    1742           0 :         hdr->tag = htole16(AR_USB_TX_STREAM_TAG);
    1743           0 :         hdr->len = htole16(sizeof(*htc) + sizeof(*bcn) + m->m_pkthdr.len);
    1744             : 
    1745           0 :         htc = (struct ar_htc_frame_hdr *)&hdr[1];
    1746           0 :         memset(htc, 0, sizeof(*htc));
    1747           0 :         htc->endpoint_id = usc->ep_bcn;
    1748           0 :         htc->payload_len = htobe16(sizeof(*bcn) + m->m_pkthdr.len);
    1749             : 
    1750           0 :         bcn = (struct ar_tx_bcn *)&htc[1];
    1751           0 :         memset(bcn, 0, sizeof(*bcn));
    1752           0 :         bcn->vif_idx = 0;
    1753             : 
    1754           0 :         m_copydata(m, 0, m->m_pkthdr.len, (caddr_t)&bcn[1]);
    1755             : 
    1756           0 :         usbd_setup_xfer(data->xfer, usc->tx_data_pipe, data, data->buf,
    1757           0 :             sizeof(*hdr) + sizeof(*htc) + sizeof(*bcn) + m->m_pkthdr.len,
    1758             :             USBD_SHORT_XFER_OK | USBD_NO_COPY, ATHN_USB_TX_TIMEOUT,
    1759             :             athn_usb_bcneof);
    1760             : 
    1761           0 :         m_freem(m);
    1762           0 :         usc->tx_bcn = NULL;
    1763           0 :         error = usbd_transfer(data->xfer);
    1764           0 :         if (__predict_false(error != USBD_IN_PROGRESS && error != 0))
    1765           0 :                 usc->tx_bcn = data;
    1766           0 : }
    1767             : #endif
    1768             : 
    1769             : /* Update current transmit rate for a node based on firmware Tx status. */
    1770             : void
    1771           0 : athn_usb_tx_status(void *arg, struct ieee80211_node *ni)
    1772             : {
    1773           0 :         struct ar_wmi_evt_txstatus *ts = arg;
    1774           0 :         struct athn_node *an = (struct athn_node *)ni;
    1775           0 :         uint8_t rate_index = (ts->rate & AR_HTC_TXSTAT_RATE);
    1776             : 
    1777           0 :         if (an->sta_index != ts->cookie) /* Tx report for a different node */
    1778           0 :                 return;
    1779             : 
    1780           0 :         if (ts->flags & AR_HTC_TXSTAT_MCS) {
    1781           0 :                 if (isset(ni->ni_rxmcs, rate_index))
    1782           0 :                         ni->ni_txmcs = rate_index;
    1783           0 :         } else if (rate_index < ni->ni_rates.rs_nrates)
    1784           0 :                 ni->ni_txrate = rate_index;
    1785           0 : }
    1786             : 
    1787             : void
    1788           0 : athn_usb_rx_wmi_ctrl(struct athn_usb_softc *usc, uint8_t *buf, int len)
    1789             : {
    1790             :         struct ar_wmi_cmd_hdr *wmi;
    1791             :         uint16_t cmd_id;
    1792             : 
    1793           0 :         if (__predict_false(len < sizeof(*wmi)))
    1794           0 :                 return;
    1795           0 :         wmi = (struct ar_wmi_cmd_hdr *)buf;
    1796           0 :         cmd_id = betoh16(wmi->cmd_id);
    1797             : 
    1798           0 :         if (!(cmd_id & AR_WMI_EVT_FLAG)) {
    1799           0 :                 if (usc->wait_cmd_id != cmd_id)
    1800           0 :                         return; /* Unexpected reply. */
    1801           0 :                 if (usc->obuf != NULL) {
    1802             :                         /* Copy answer into caller supplied buffer. */
    1803           0 :                         memcpy(usc->obuf, &wmi[1], len - sizeof(*wmi));
    1804           0 :                 }
    1805             :                 /* Notify caller of completion. */
    1806           0 :                 wakeup(&usc->wait_cmd_id);
    1807           0 :                 return;
    1808             :         }
    1809           0 :         switch (cmd_id & 0xfff) {
    1810             : #ifndef IEEE80211_STA_ONLY
    1811             :         case AR_WMI_EVT_SWBA:
    1812           0 :                 athn_usb_swba(usc);
    1813           0 :                 break;
    1814             : #endif
    1815             :         case AR_WMI_EVT_TXSTATUS: {
    1816             :                 struct ar_wmi_evt_txstatus_list *tsl;
    1817             :                 int i;
    1818             : 
    1819           0 :                 tsl = (struct ar_wmi_evt_txstatus_list *)&wmi[1];
    1820           0 :                 for (i = 0; i < tsl->count && i < nitems(tsl->ts); i++) {
    1821           0 :                         struct ieee80211com *ic = &usc->sc_sc.sc_ic;
    1822           0 :                         struct athn_node *an = (struct athn_node *)ic->ic_bss;
    1823           0 :                         struct ar_wmi_evt_txstatus *ts = &tsl->ts[i];
    1824             :                         uint8_t qid;
    1825             : 
    1826             :                         /* Skip the node we use to send management frames. */
    1827           0 :                         if (ts->cookie == 0)
    1828           0 :                                 continue;
    1829             : 
    1830             :                         /* Skip Tx reports for non-data frame endpoints. */
    1831           0 :                         qid = (ts->rate & AR_HTC_TXSTAT_EPID) >>
    1832             :                                 AR_HTC_TXSTAT_EPID_SHIFT;
    1833           0 :                         if (qid != usc->ep_data[EDCA_AC_BE] &&
    1834           0 :                             qid != usc->ep_data[EDCA_AC_BK] &&
    1835           0 :                             qid != usc->ep_data[EDCA_AC_VI] &&
    1836           0 :                             qid != usc->ep_data[EDCA_AC_VO])
    1837           0 :                                 continue;
    1838             : 
    1839           0 :                         if (ts->cookie == an->sta_index)
    1840           0 :                                 athn_usb_tx_status(ts, ic->ic_bss);
    1841             :                         else
    1842           0 :                                 ieee80211_iterate_nodes(ic, athn_usb_tx_status,
    1843           0 :                                     ts);
    1844           0 :                 }
    1845             :                 break;
    1846             :         }
    1847             :         case AR_WMI_EVT_FATAL:
    1848           0 :                 printf("%s: fatal firmware error\n", usc->usb_dev.dv_xname);
    1849           0 :                 break;
    1850             :         default:
    1851             :                 DPRINTF(("WMI event %d ignored\n", cmd_id));
    1852             :                 break;
    1853             :         }
    1854           0 : }
    1855             : 
    1856             : void
    1857           0 : athn_usb_intr(struct usbd_xfer *xfer, void *priv,
    1858             :     usbd_status status)
    1859             : {
    1860           0 :         struct athn_usb_softc *usc = priv;
    1861             :         struct ar_htc_frame_hdr *htc;
    1862             :         struct ar_htc_msg_hdr *msg;
    1863           0 :         uint8_t *buf = usc->ibuf;
    1864             :         uint16_t msg_id;
    1865           0 :         int len;
    1866             : 
    1867           0 :         if (__predict_false(status != USBD_NORMAL_COMPLETION)) {
    1868             :                 DPRINTF(("intr status=%d\n", status));
    1869           0 :                 if (status == USBD_STALLED)
    1870           0 :                         usbd_clear_endpoint_stall_async(usc->rx_intr_pipe);
    1871           0 :                 else if (status == USBD_IOERROR) {
    1872             :                         /*
    1873             :                          * The device has gone away. If async commands are
    1874             :                          * pending or running ensure the device dies ASAP
    1875             :                          * and any blocked processes are woken up.
    1876             :                          */
    1877           0 :                         if (usc->cmdq.queued > 0)
    1878           0 :                                 usbd_deactivate(usc->sc_udev);
    1879             :                 }
    1880           0 :                 return;
    1881             :         }
    1882           0 :         usbd_get_xfer_status(xfer, NULL, NULL, &len, NULL);
    1883             : 
    1884             :         /* Skip watchdog pattern if present. */
    1885           0 :         if (len >= 4 && *(uint32_t *)buf == htobe32(0x00c60000)) {
    1886           0 :                 buf += 4;
    1887           0 :                 len -= 4;
    1888           0 :         }
    1889           0 :         if (__predict_false(len < sizeof(*htc)))
    1890           0 :                 return;
    1891           0 :         htc = (struct ar_htc_frame_hdr *)buf;
    1892             :         /* Skip HTC header. */
    1893           0 :         buf += sizeof(*htc);
    1894           0 :         len -= sizeof(*htc);
    1895             : 
    1896           0 :         if (htc->endpoint_id != 0) {
    1897           0 :                 if (__predict_false(htc->endpoint_id != usc->ep_ctrl))
    1898           0 :                         return;
    1899             :                 /* Remove trailer if present. */
    1900           0 :                 if (htc->flags & AR_HTC_FLAG_TRAILER) {
    1901           0 :                         if (__predict_false(len < htc->control[0]))
    1902           0 :                                 return;
    1903           0 :                         len -= htc->control[0];
    1904           0 :                 }
    1905           0 :                 athn_usb_rx_wmi_ctrl(usc, buf, len);
    1906           0 :                 return;
    1907             :         }
    1908             :         /* Endpoint 0 carries HTC messages. */
    1909           0 :         if (__predict_false(len < sizeof(*msg)))
    1910           0 :                 return;
    1911           0 :         msg = (struct ar_htc_msg_hdr *)buf;
    1912           0 :         msg_id = betoh16(msg->msg_id);
    1913             :         DPRINTF(("Rx HTC message %d\n", msg_id));
    1914           0 :         switch (msg_id) {
    1915             :         case AR_HTC_MSG_READY:
    1916           0 :                 if (usc->wait_msg_id != msg_id)
    1917             :                         break;
    1918           0 :                 usc->wait_msg_id = 0;
    1919           0 :                 wakeup(&usc->wait_msg_id);
    1920           0 :                 break;
    1921             :         case AR_HTC_MSG_CONN_SVC_RSP:
    1922           0 :                 if (usc->wait_msg_id != msg_id)
    1923             :                         break;
    1924           0 :                 if (usc->msg_conn_svc_rsp != NULL) {
    1925           0 :                         memcpy(usc->msg_conn_svc_rsp, &msg[1],
    1926             :                             sizeof(struct ar_htc_msg_conn_svc_rsp));
    1927           0 :                 }
    1928           0 :                 usc->wait_msg_id = 0;
    1929           0 :                 wakeup(&usc->wait_msg_id);
    1930           0 :                 break;
    1931             :         case AR_HTC_MSG_CONF_PIPE_RSP:
    1932           0 :                 if (usc->wait_msg_id != msg_id)
    1933             :                         break;
    1934           0 :                 usc->wait_msg_id = 0;
    1935           0 :                 wakeup(&usc->wait_msg_id);
    1936           0 :                 break;
    1937             :         default:
    1938             :                 DPRINTF(("HTC message %d ignored\n", msg_id));
    1939             :                 break;
    1940             :         }
    1941           0 : }
    1942             : 
    1943             : #if NBPFILTER > 0
    1944             : void
    1945           0 : athn_usb_rx_radiotap(struct athn_softc *sc, struct mbuf *m,
    1946             :     struct ar_rx_status *rs)
    1947             : {
    1948             : #define IEEE80211_RADIOTAP_F_SHORTGI    0x80    /* XXX from FBSD */
    1949             : 
    1950           0 :         struct athn_rx_radiotap_header *tap = &sc->sc_rxtap;
    1951           0 :         struct ieee80211com *ic = &sc->sc_ic;
    1952           0 :         struct mbuf mb;
    1953             :         uint8_t rate;
    1954             : 
    1955           0 :         tap->wr_flags = IEEE80211_RADIOTAP_F_FCS;
    1956           0 :         tap->wr_tsft = htole64(betoh64(rs->rs_tstamp));
    1957           0 :         tap->wr_chan_freq = htole16(ic->ic_bss->ni_chan->ic_freq);
    1958           0 :         tap->wr_chan_flags = htole16(ic->ic_bss->ni_chan->ic_flags);
    1959           0 :         tap->wr_dbm_antsignal = rs->rs_rssi;
    1960             :         /* XXX noise. */
    1961           0 :         tap->wr_antenna = rs->rs_antenna;
    1962           0 :         tap->wr_rate = 0;    /* In case it can't be found below. */
    1963           0 :         rate = rs->rs_rate;
    1964           0 :         if (rate & 0x80) {          /* HT. */
    1965             :                 /* Bit 7 set means HT MCS instead of rate. */
    1966           0 :                 tap->wr_rate = rate;
    1967           0 :                 if (!(rs->rs_flags & AR_RXS_FLAG_GI))
    1968           0 :                         tap->wr_flags |= IEEE80211_RADIOTAP_F_SHORTGI;
    1969             : 
    1970           0 :         } else if (rate & 0x10) {   /* CCK. */
    1971           0 :                 if (rate & 0x04)
    1972           0 :                         tap->wr_flags |= IEEE80211_RADIOTAP_F_SHORTPRE;
    1973           0 :                 switch (rate & ~0x14) {
    1974           0 :                 case 0xb: tap->wr_rate =   2; break;
    1975           0 :                 case 0xa: tap->wr_rate =   4; break;
    1976           0 :                 case 0x9: tap->wr_rate =  11; break;
    1977           0 :                 case 0x8: tap->wr_rate =  22; break;
    1978             :                 }
    1979             :         } else {                        /* OFDM. */
    1980           0 :                 switch (rate) {
    1981           0 :                 case 0xb: tap->wr_rate =  12; break;
    1982           0 :                 case 0xf: tap->wr_rate =  18; break;
    1983           0 :                 case 0xa: tap->wr_rate =  24; break;
    1984           0 :                 case 0xe: tap->wr_rate =  36; break;
    1985           0 :                 case 0x9: tap->wr_rate =  48; break;
    1986           0 :                 case 0xd: tap->wr_rate =  72; break;
    1987           0 :                 case 0x8: tap->wr_rate =  96; break;
    1988           0 :                 case 0xc: tap->wr_rate = 108; break;
    1989             :                 }
    1990             :         }
    1991           0 :         mb.m_data = (caddr_t)tap;
    1992           0 :         mb.m_len = sc->sc_rxtap_len;
    1993           0 :         mb.m_next = m;
    1994           0 :         mb.m_nextpkt = NULL;
    1995           0 :         mb.m_type = 0;
    1996           0 :         mb.m_flags = 0;
    1997           0 :         bpf_mtap(sc->sc_drvbpf, &mb, BPF_DIRECTION_IN);
    1998           0 : }
    1999             : #endif
    2000             : 
    2001             : void
    2002           0 : athn_usb_rx_frame(struct athn_usb_softc *usc, struct mbuf *m)
    2003             : {
    2004           0 :         struct athn_softc *sc = &usc->sc_sc;
    2005           0 :         struct ieee80211com *ic = &sc->sc_ic;
    2006           0 :         struct ifnet *ifp = &ic->ic_if;
    2007             :         struct ieee80211_frame *wh;
    2008             :         struct ieee80211_node *ni;
    2009           0 :         struct ieee80211_rxinfo rxi;
    2010             :         struct ar_htc_frame_hdr *htc;
    2011             :         struct ar_rx_status *rs;
    2012             :         uint16_t datalen;
    2013             :         int s;
    2014             : 
    2015           0 :         if (__predict_false(m->m_len < sizeof(*htc)))
    2016             :                 goto skip;
    2017           0 :         htc = mtod(m, struct ar_htc_frame_hdr *);
    2018           0 :         if (__predict_false(htc->endpoint_id == 0)) {
    2019             :                 DPRINTF(("bad endpoint %d\n", htc->endpoint_id));
    2020             :                 goto skip;
    2021             :         }
    2022           0 :         if (htc->flags & AR_HTC_FLAG_TRAILER) {
    2023           0 :                 if (m->m_len < htc->control[0])
    2024             :                         goto skip;
    2025           0 :                 m_adj(m, -(int)htc->control[0]);
    2026           0 :         }
    2027           0 :         m_adj(m, sizeof(*htc)); /* Strip HTC header. */
    2028             : 
    2029           0 :         if (__predict_false(m->m_len < sizeof(*rs)))
    2030             :                 goto skip;
    2031           0 :         rs = mtod(m, struct ar_rx_status *);
    2032             : 
    2033             :         /* Make sure that payload fits. */
    2034           0 :         datalen = betoh16(rs->rs_datalen);
    2035           0 :         if (__predict_false(m->m_len < sizeof(*rs) + datalen))
    2036             :                 goto skip;
    2037             : 
    2038           0 :         if (__predict_false(datalen < sizeof(*wh) + IEEE80211_CRC_LEN))
    2039             :                 goto skip;
    2040             : 
    2041           0 :         m_adj(m, sizeof(*rs));  /* Strip Rx status. */
    2042             : 
    2043           0 :         s = splnet();
    2044             : 
    2045             :         /* Grab a reference to the source node. */
    2046           0 :         wh = mtod(m, struct ieee80211_frame *);
    2047           0 :         ni = ieee80211_find_rxnode(ic, wh);
    2048             : 
    2049             :         /* Remove any HW padding after the 802.11 header. */
    2050           0 :         if (!(wh->i_fc[0] & IEEE80211_FC0_TYPE_CTL)) {
    2051           0 :                 u_int hdrlen = ieee80211_get_hdrlen(wh);
    2052           0 :                 if (hdrlen & 3) {
    2053           0 :                         memmove((caddr_t)wh + 2, wh, hdrlen);
    2054           0 :                         m_adj(m, 2);
    2055           0 :                 }
    2056           0 :         }
    2057             : #if NBPFILTER > 0
    2058           0 :         if (__predict_false(sc->sc_drvbpf != NULL))
    2059           0 :                 athn_usb_rx_radiotap(sc, m, rs);
    2060             : #endif
    2061             :         /* Trim 802.11 FCS after radiotap. */
    2062           0 :         m_adj(m, -IEEE80211_CRC_LEN);
    2063             : 
    2064             :         /* Send the frame to the 802.11 layer. */
    2065           0 :         rxi.rxi_flags = 0;
    2066           0 :         rxi.rxi_rssi = rs->rs_rssi + AR_USB_DEFAULT_NF;
    2067           0 :         rxi.rxi_tstamp = betoh64(rs->rs_tstamp);
    2068           0 :         ieee80211_input(ifp, m, ni, &rxi);
    2069             : 
    2070             :         /* Node is no longer needed. */
    2071           0 :         ieee80211_release_node(ic, ni);
    2072           0 :         splx(s);
    2073           0 :         return;
    2074             :  skip:
    2075           0 :         m_freem(m);
    2076           0 : }
    2077             : 
    2078             : void
    2079           0 : athn_usb_rxeof(struct usbd_xfer *xfer, void *priv,
    2080             :     usbd_status status)
    2081             : {
    2082           0 :         struct athn_usb_rx_data *data = priv;
    2083           0 :         struct athn_usb_softc *usc = data->sc;
    2084           0 :         struct athn_softc *sc = &usc->sc_sc;
    2085           0 :         struct ifnet *ifp = &sc->sc_ic.ic_if;
    2086           0 :         struct athn_usb_rx_stream *stream = &usc->rx_stream;
    2087           0 :         uint8_t *buf = data->buf;
    2088             :         struct ar_stream_hdr *hdr;
    2089             :         struct mbuf *m;
    2090             :         uint16_t pktlen;
    2091           0 :         int off, len;
    2092             : 
    2093           0 :         if (__predict_false(status != USBD_NORMAL_COMPLETION)) {
    2094             :                 DPRINTF(("RX status=%d\n", status));
    2095           0 :                 if (status == USBD_STALLED)
    2096           0 :                         usbd_clear_endpoint_stall_async(usc->rx_data_pipe);
    2097           0 :                 if (status != USBD_CANCELLED)
    2098             :                         goto resubmit;
    2099           0 :                 return;
    2100             :         }
    2101           0 :         usbd_get_xfer_status(xfer, NULL, NULL, &len, NULL);
    2102             : 
    2103           0 :         if (stream->left > 0) {
    2104           0 :                 if (len >= stream->left) {
    2105             :                         /* We have all our pktlen bytes now. */
    2106           0 :                         if (__predict_true(stream->m != NULL)) {
    2107           0 :                                 memcpy(mtod(stream->m, uint8_t *) +
    2108             :                                     stream->moff, buf, stream->left);
    2109           0 :                                 athn_usb_rx_frame(usc, stream->m);
    2110           0 :                                 stream->m = NULL;
    2111           0 :                         }
    2112             :                         /* Next header is 32-bit aligned. */
    2113           0 :                         off = (stream->left + 3) & ~3;
    2114           0 :                         buf += off;
    2115           0 :                         len -= off;
    2116           0 :                         stream->left = 0;
    2117             :                 } else {
    2118             :                         /* Still need more bytes, save what we have. */
    2119           0 :                         if (__predict_true(stream->m != NULL)) {
    2120           0 :                                 memcpy(mtod(stream->m, uint8_t *) +
    2121             :                                     stream->moff, buf, len);
    2122           0 :                                 stream->moff += len;
    2123           0 :                         }
    2124           0 :                         stream->left -= len;
    2125           0 :                         goto resubmit;
    2126             :                 }
    2127           0 :         }
    2128           0 :         KASSERT(stream->left == 0);
    2129           0 :         while (len >= sizeof(*hdr)) {
    2130           0 :                 hdr = (struct ar_stream_hdr *)buf;
    2131           0 :                 if (hdr->tag != htole16(AR_USB_RX_STREAM_TAG)) {
    2132             :                         DPRINTF(("invalid tag 0x%x\n", hdr->tag));
    2133             :                         break;
    2134             :                 }
    2135           0 :                 pktlen = letoh16(hdr->len);
    2136           0 :                 buf += sizeof(*hdr);
    2137           0 :                 len -= sizeof(*hdr);
    2138             : 
    2139           0 :                 if (__predict_true(pktlen <= MCLBYTES)) {
    2140             :                         /* Allocate an mbuf to store the next pktlen bytes. */
    2141           0 :                         MGETHDR(m, M_DONTWAIT, MT_DATA);
    2142           0 :                         if (__predict_true(m != NULL)) {
    2143           0 :                                 m->m_pkthdr.len = m->m_len = pktlen;
    2144           0 :                                 if (pktlen > MHLEN) {
    2145           0 :                                         MCLGET(m, M_DONTWAIT);
    2146           0 :                                         if (!(m->m_flags & M_EXT)) {
    2147           0 :                                                 m_free(m);
    2148             :                                                 m = NULL;
    2149           0 :                                         }
    2150             :                                 }
    2151             :                         }
    2152             :                 } else  /* Drop frames larger than MCLBYTES. */
    2153             :                         m = NULL;
    2154             : 
    2155           0 :                 if (m == NULL)
    2156           0 :                         ifp->if_ierrors++;
    2157             : 
    2158             :                 /*
    2159             :                  * NB: m can be NULL, in which case the next pktlen bytes
    2160             :                  * will be discarded from the Rx stream.
    2161             :                  */
    2162           0 :                 if (pktlen > len) {
    2163             :                         /* Need more bytes, save what we have. */
    2164           0 :                         stream->m = m;       /* NB: m can be NULL. */
    2165           0 :                         if (__predict_true(stream->m != NULL)) {
    2166           0 :                                 memcpy(mtod(stream->m, uint8_t *), buf, len);
    2167           0 :                                 stream->moff = len;
    2168           0 :                         }
    2169           0 :                         stream->left = pktlen - len;
    2170           0 :                         goto resubmit;
    2171             :                 }
    2172           0 :                 if (__predict_true(m != NULL)) {
    2173             :                         /* We have all the pktlen bytes in this xfer. */
    2174           0 :                         memcpy(mtod(m, uint8_t *), buf, pktlen);
    2175           0 :                         athn_usb_rx_frame(usc, m);
    2176           0 :                 }
    2177             : 
    2178             :                 /* Next header is 32-bit aligned. */
    2179           0 :                 off = (pktlen + 3) & ~3;
    2180           0 :                 buf += off;
    2181           0 :                 len -= off;
    2182             :         }
    2183             : 
    2184             :  resubmit:
    2185             :         /* Setup a new transfer. */
    2186           0 :         usbd_setup_xfer(xfer, usc->rx_data_pipe, data, data->buf,
    2187             :             ATHN_USB_RXBUFSZ, USBD_SHORT_XFER_OK | USBD_NO_COPY,
    2188             :             USBD_NO_TIMEOUT, athn_usb_rxeof);
    2189           0 :         (void)usbd_transfer(xfer);
    2190           0 : }
    2191             : 
    2192             : void
    2193           0 : athn_usb_txeof(struct usbd_xfer *xfer, void *priv,
    2194             :     usbd_status status)
    2195             : {
    2196           0 :         struct athn_usb_tx_data *data = priv;
    2197           0 :         struct athn_usb_softc *usc = data->sc;
    2198           0 :         struct athn_softc *sc = &usc->sc_sc;
    2199           0 :         struct ifnet *ifp = &sc->sc_ic.ic_if;
    2200             :         int s;
    2201             : 
    2202           0 :         s = splnet();
    2203             :         /* Put this Tx buffer back to our free list. */
    2204           0 :         TAILQ_INSERT_TAIL(&usc->tx_free_list, data, next);
    2205             : 
    2206           0 :         if (__predict_false(status != USBD_NORMAL_COMPLETION)) {
    2207             :                 DPRINTF(("TX status=%d\n", status));
    2208           0 :                 if (status == USBD_STALLED)
    2209           0 :                         usbd_clear_endpoint_stall_async(usc->tx_data_pipe);
    2210           0 :                 ifp->if_oerrors++;
    2211           0 :                 splx(s);
    2212             :                 /* XXX Why return? */
    2213           0 :                 return;
    2214             :         }
    2215           0 :         sc->sc_tx_timer = 0;
    2216             : 
    2217             :         /* We just released a Tx buffer, notify Tx. */
    2218           0 :         if (ifq_is_oactive(&ifp->if_snd)) {
    2219           0 :                 ifq_clr_oactive(&ifp->if_snd);
    2220           0 :                 ifp->if_start(ifp);
    2221           0 :         }
    2222           0 :         splx(s);
    2223           0 : }
    2224             : 
    2225             : int
    2226           0 : athn_usb_tx(struct athn_softc *sc, struct mbuf *m, struct ieee80211_node *ni)
    2227             : {
    2228           0 :         struct athn_usb_softc *usc = (struct athn_usb_softc *)sc;
    2229           0 :         struct athn_node *an = (struct athn_node *)ni;
    2230           0 :         struct ieee80211com *ic = &sc->sc_ic;
    2231             :         struct ieee80211_frame *wh;
    2232             :         struct ieee80211_key *k = NULL;
    2233             :         struct athn_usb_tx_data *data;
    2234             :         struct ar_stream_hdr *hdr;
    2235             :         struct ar_htc_frame_hdr *htc;
    2236             :         struct ar_tx_frame *txf;
    2237             :         struct ar_tx_mgmt *txm;
    2238             :         uint8_t *frm;
    2239             :         uint16_t qos;
    2240             :         uint8_t qid, tid = 0;
    2241             :         int hasqos, xferlen, error;
    2242             : 
    2243           0 :         wh = mtod(m, struct ieee80211_frame *);
    2244           0 :         if (wh->i_fc[1] & IEEE80211_FC1_PROTECTED) {
    2245           0 :                 k = ieee80211_get_txkey(ic, wh, ni);
    2246           0 :                 if ((m = ieee80211_encrypt(ic, m, k)) == NULL)
    2247           0 :                         return (ENOBUFS);
    2248           0 :                 wh = mtod(m, struct ieee80211_frame *);
    2249           0 :         }
    2250           0 :         if ((hasqos = ieee80211_has_qos(wh))) {
    2251           0 :                 qos = ieee80211_get_qos(wh);
    2252           0 :                 tid = qos & IEEE80211_QOS_TID;
    2253           0 :                 qid = ieee80211_up_to_ac(ic, tid);
    2254           0 :         } else
    2255             :                 qid = EDCA_AC_BE;
    2256             : 
    2257             :         /* Grab a Tx buffer from our free list. */
    2258           0 :         data = TAILQ_FIRST(&usc->tx_free_list);
    2259           0 :         TAILQ_REMOVE(&usc->tx_free_list, data, next);
    2260             : 
    2261             : #if NBPFILTER > 0
    2262             :         /* XXX Change radiotap Tx header for USB (no txrate). */
    2263           0 :         if (__predict_false(sc->sc_drvbpf != NULL)) {
    2264           0 :                 struct athn_tx_radiotap_header *tap = &sc->sc_txtap;
    2265           0 :                 struct mbuf mb;
    2266             : 
    2267           0 :                 tap->wt_flags = 0;
    2268           0 :                 tap->wt_chan_freq = htole16(ic->ic_bss->ni_chan->ic_freq);
    2269           0 :                 tap->wt_chan_flags = htole16(ic->ic_bss->ni_chan->ic_flags);
    2270           0 :                 mb.m_data = (caddr_t)tap;
    2271           0 :                 mb.m_len = sc->sc_txtap_len;
    2272           0 :                 mb.m_next = m;
    2273           0 :                 mb.m_nextpkt = NULL;
    2274           0 :                 mb.m_type = 0;
    2275           0 :                 mb.m_flags = 0;
    2276           0 :                 bpf_mtap(sc->sc_drvbpf, &mb, BPF_DIRECTION_OUT);
    2277           0 :         }
    2278             : #endif
    2279             : 
    2280             :         /* NB: We don't take advantage of USB Tx stream mode for now. */
    2281           0 :         hdr = (struct ar_stream_hdr *)data->buf;
    2282           0 :         hdr->tag = htole16(AR_USB_TX_STREAM_TAG);
    2283             : 
    2284           0 :         htc = (struct ar_htc_frame_hdr *)&hdr[1];
    2285           0 :         memset(htc, 0, sizeof(*htc));
    2286           0 :         if ((wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK) ==
    2287             :             IEEE80211_FC0_TYPE_DATA) {
    2288           0 :                 htc->endpoint_id = usc->ep_data[qid];
    2289             : 
    2290           0 :                 txf = (struct ar_tx_frame *)&htc[1];
    2291           0 :                 memset(txf, 0, sizeof(*txf));
    2292           0 :                 txf->data_type = AR_HTC_NORMAL;
    2293           0 :                 txf->node_idx = an->sta_index;
    2294           0 :                 txf->vif_idx = 0;
    2295           0 :                 txf->tid = tid;
    2296           0 :                 if (m->m_pkthdr.len + IEEE80211_CRC_LEN > ic->ic_rtsthreshold)
    2297           0 :                         txf->flags |= htobe32(AR_HTC_TX_RTSCTS);
    2298           0 :                 else if (ic->ic_flags & IEEE80211_F_USEPROT) {
    2299           0 :                         if (ic->ic_protmode == IEEE80211_PROT_CTSONLY)
    2300           0 :                                 txf->flags |= htobe32(AR_HTC_TX_CTSONLY);
    2301           0 :                         else if (ic->ic_protmode == IEEE80211_PROT_RTSCTS)
    2302           0 :                                 txf->flags |= htobe32(AR_HTC_TX_RTSCTS);
    2303             :                 }
    2304           0 :                 txf->key_idx = 0xff;
    2305           0 :                 txf->cookie = an->sta_index;
    2306           0 :                 frm = (uint8_t *)&txf[1];
    2307           0 :         } else {
    2308           0 :                 htc->endpoint_id = usc->ep_mgmt;
    2309             : 
    2310           0 :                 txm = (struct ar_tx_mgmt *)&htc[1];
    2311           0 :                 memset(txm, 0, sizeof(*txm));
    2312           0 :                 txm->node_idx = an->sta_index;
    2313           0 :                 txm->vif_idx = 0;
    2314           0 :                 txm->key_idx = 0xff;
    2315           0 :                 txm->cookie = an->sta_index;
    2316           0 :                 frm = (uint8_t *)&txm[1];
    2317             :         }
    2318             :         /* Copy payload. */
    2319           0 :         m_copydata(m, 0, m->m_pkthdr.len, (caddr_t)frm);
    2320           0 :         frm += m->m_pkthdr.len;
    2321           0 :         m_freem(m);
    2322             : 
    2323             :         /* Finalize headers. */
    2324           0 :         htc->payload_len = htobe16(frm - (uint8_t *)&htc[1]);
    2325           0 :         hdr->len = htole16(frm - (uint8_t *)&hdr[1]);
    2326           0 :         xferlen = frm - data->buf;
    2327             : 
    2328           0 :         usbd_setup_xfer(data->xfer, usc->tx_data_pipe, data, data->buf,
    2329             :             xferlen, USBD_FORCE_SHORT_XFER | USBD_NO_COPY, ATHN_USB_TX_TIMEOUT,
    2330             :             athn_usb_txeof);
    2331           0 :         error = usbd_transfer(data->xfer);
    2332           0 :         if (__predict_false(error != USBD_IN_PROGRESS && error != 0)) {
    2333             :                 /* Put this Tx buffer back to our free list. */
    2334           0 :                 TAILQ_INSERT_TAIL(&usc->tx_free_list, data, next);
    2335           0 :                 return (error);
    2336             :         }
    2337           0 :         ieee80211_release_node(ic, ni);
    2338           0 :         return (0);
    2339           0 : }
    2340             : 
    2341             : void
    2342           0 : athn_usb_start(struct ifnet *ifp)
    2343             : {
    2344           0 :         struct athn_softc *sc = ifp->if_softc;
    2345           0 :         struct athn_usb_softc *usc = (struct athn_usb_softc *)sc;
    2346           0 :         struct ieee80211com *ic = &sc->sc_ic;
    2347           0 :         struct ieee80211_node *ni;
    2348             :         struct mbuf *m;
    2349             : 
    2350           0 :         if (!(ifp->if_flags & IFF_RUNNING) || ifq_is_oactive(&ifp->if_snd))
    2351           0 :                 return;
    2352             : 
    2353           0 :         for (;;) {
    2354           0 :                 if (TAILQ_EMPTY(&usc->tx_free_list)) {
    2355           0 :                         ifq_set_oactive(&ifp->if_snd);
    2356           0 :                         break;
    2357             :                 }
    2358             :                 /* Send pending management frames first. */
    2359           0 :                 m = mq_dequeue(&ic->ic_mgtq);
    2360           0 :                 if (m != NULL) {
    2361           0 :                         ni = m->m_pkthdr.ph_cookie;
    2362           0 :                         goto sendit;
    2363             :                 }
    2364           0 :                 if (ic->ic_state != IEEE80211_S_RUN)
    2365             :                         break;
    2366             : 
    2367             :                 /* Encapsulate and send data frames. */
    2368           0 :                 IFQ_DEQUEUE(&ifp->if_snd, m);
    2369           0 :                 if (m == NULL)
    2370             :                         break;
    2371             : #if NBPFILTER > 0
    2372           0 :                 if (ifp->if_bpf != NULL)
    2373           0 :                         bpf_mtap(ifp->if_bpf, m, BPF_DIRECTION_OUT);
    2374             : #endif
    2375           0 :                 if ((m = ieee80211_encap(ifp, m, &ni)) == NULL)
    2376           0 :                         continue;
    2377             :  sendit:
    2378             : #if NBPFILTER > 0
    2379           0 :                 if (ic->ic_rawbpf != NULL)
    2380           0 :                         bpf_mtap(ic->ic_rawbpf, m, BPF_DIRECTION_OUT);
    2381             : #endif
    2382           0 :                 if (athn_usb_tx(sc, m, ni) != 0) {
    2383           0 :                         ieee80211_release_node(ic, ni);
    2384           0 :                         ifp->if_oerrors++;
    2385           0 :                         continue;
    2386             :                 }
    2387             : 
    2388           0 :                 sc->sc_tx_timer = 5;
    2389           0 :                 ifp->if_timer = 1;
    2390             :         }
    2391           0 : }
    2392             : 
    2393             : void
    2394           0 : athn_usb_watchdog(struct ifnet *ifp)
    2395             : {
    2396           0 :         struct athn_softc *sc = ifp->if_softc;
    2397             : 
    2398           0 :         ifp->if_timer = 0;
    2399             : 
    2400           0 :         if (sc->sc_tx_timer > 0) {
    2401           0 :                 if (--sc->sc_tx_timer == 0) {
    2402           0 :                         printf("%s: device timeout\n", sc->sc_dev.dv_xname);
    2403             :                         /* athn_usb_init(ifp); XXX needs a process context! */
    2404           0 :                         ifp->if_oerrors++;
    2405           0 :                         return;
    2406             :                 }
    2407           0 :                 ifp->if_timer = 1;
    2408           0 :         }
    2409           0 :         ieee80211_watchdog(ifp);
    2410           0 : }
    2411             : 
    2412             : int
    2413           0 : athn_usb_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
    2414             : {
    2415           0 :         struct athn_softc *sc = ifp->if_softc;
    2416           0 :         struct athn_usb_softc *usc = (struct athn_usb_softc *)sc;
    2417           0 :         struct ieee80211com *ic = &sc->sc_ic;
    2418             :         int s, error = 0;
    2419             : 
    2420           0 :         if (usbd_is_dying(usc->sc_udev))
    2421           0 :                 return ENXIO;
    2422             : 
    2423           0 :         usbd_ref_incr(usc->sc_udev);
    2424             : 
    2425           0 :         s = splnet();
    2426             : 
    2427           0 :         switch (cmd) {
    2428             :         case SIOCSIFADDR:
    2429           0 :                 ifp->if_flags |= IFF_UP;
    2430             :                 /* FALLTHROUGH */
    2431             :         case SIOCSIFFLAGS:
    2432           0 :                 if (ifp->if_flags & IFF_UP) {
    2433           0 :                         if (!(ifp->if_flags & IFF_RUNNING))
    2434           0 :                                 error = athn_usb_init(ifp);
    2435             :                 } else {
    2436           0 :                         if (ifp->if_flags & IFF_RUNNING)
    2437           0 :                                 athn_usb_stop(ifp);
    2438             :                 }
    2439             :                 break;
    2440             :         case SIOCS80211CHANNEL:
    2441           0 :                 error = ieee80211_ioctl(ifp, cmd, data);
    2442           0 :                 if (error == ENETRESET &&
    2443           0 :                     ic->ic_opmode == IEEE80211_M_MONITOR) {
    2444           0 :                         if ((ifp->if_flags & (IFF_UP | IFF_RUNNING)) ==
    2445             :                             (IFF_UP | IFF_RUNNING)) {
    2446           0 :                                 athn_usb_switch_chan(sc, ic->ic_ibss_chan,
    2447             :                                     NULL);
    2448           0 :                         }
    2449             :                         error = 0;
    2450           0 :                 }
    2451             :                 break;
    2452             :         default:
    2453           0 :                 error = ieee80211_ioctl(ifp, cmd, data);
    2454           0 :         }
    2455             : 
    2456           0 :         if (error == ENETRESET) {
    2457             :                 error = 0;
    2458           0 :                 if ((ifp->if_flags & (IFF_UP | IFF_RUNNING)) ==
    2459             :                     (IFF_UP | IFF_RUNNING)) {
    2460           0 :                         athn_usb_stop(ifp);
    2461           0 :                         error = athn_usb_init(ifp);
    2462           0 :                 }
    2463             :         }
    2464           0 :         splx(s);
    2465             : 
    2466           0 :         usbd_ref_decr(usc->sc_udev);
    2467             : 
    2468           0 :         return (error);
    2469           0 : }
    2470             : 
    2471             : int
    2472           0 : athn_usb_init(struct ifnet *ifp)
    2473             : {
    2474           0 :         struct athn_softc *sc = ifp->if_softc;
    2475           0 :         struct athn_usb_softc *usc = (struct athn_usb_softc *)sc;
    2476           0 :         struct athn_ops *ops = &sc->ops;
    2477           0 :         struct ieee80211com *ic = &sc->sc_ic;
    2478             :         struct ieee80211_channel *c, *extc;
    2479             :         struct athn_usb_rx_data *data;
    2480           0 :         struct ar_htc_target_vif hvif;
    2481           0 :         struct ar_htc_target_sta sta;
    2482           0 :         struct ar_htc_cap_target hic;
    2483           0 :         uint16_t mode;
    2484             :         int i, error;
    2485             : 
    2486             :         /* Init host async commands ring. */
    2487           0 :         usc->cmdq.cur = usc->cmdq.next = usc->cmdq.queued = 0;
    2488             : 
    2489             :         /* Allocate Tx/Rx buffers. */
    2490           0 :         error = athn_usb_alloc_rx_list(usc);
    2491           0 :         if (error != 0)
    2492             :                 goto fail;
    2493           0 :         error = athn_usb_alloc_tx_list(usc);
    2494           0 :         if (error != 0)
    2495             :                 goto fail;
    2496             :         /* Steal one buffer for beacons. */
    2497           0 :         usc->tx_bcn = TAILQ_FIRST(&usc->tx_free_list);
    2498           0 :         TAILQ_REMOVE(&usc->tx_free_list, usc->tx_bcn, next);
    2499             : 
    2500           0 :         c = ic->ic_bss->ni_chan = ic->ic_ibss_chan;
    2501             :         extc = NULL;
    2502             : 
    2503             :         /* In case a new MAC address has been configured. */
    2504           0 :         IEEE80211_ADDR_COPY(ic->ic_myaddr, LLADDR(ifp->if_sadl));
    2505             : 
    2506           0 :         error = athn_set_power_awake(sc);
    2507           0 :         if (error != 0)
    2508             :                 goto fail;
    2509             : 
    2510           0 :         error = athn_usb_wmi_cmd(usc, AR_WMI_CMD_FLUSH_RECV);
    2511           0 :         if (error != 0)
    2512             :                 goto fail;
    2513             : 
    2514           0 :         error = athn_hw_reset(sc, c, extc, 1);
    2515           0 :         if (error != 0)
    2516             :                 goto fail;
    2517             : 
    2518           0 :         ops->set_txpower(sc, c, extc);
    2519             : 
    2520           0 :         mode = htobe16(IEEE80211_IS_CHAN_2GHZ(c) ?
    2521             :             AR_HTC_MODE_11NG : AR_HTC_MODE_11NA);
    2522           0 :         error = athn_usb_wmi_xcmd(usc, AR_WMI_CMD_SET_MODE,
    2523             :             &mode, sizeof(mode), NULL);
    2524           0 :         if (error != 0)
    2525             :                 goto fail;
    2526             : 
    2527           0 :         error = athn_usb_wmi_cmd(usc, AR_WMI_CMD_ATH_INIT);
    2528           0 :         if (error != 0)
    2529             :                 goto fail;
    2530             : 
    2531           0 :         error = athn_usb_wmi_cmd(usc, AR_WMI_CMD_START_RECV);
    2532           0 :         if (error != 0)
    2533             :                 goto fail;
    2534             : 
    2535           0 :         athn_rx_start(sc);
    2536             : 
    2537             :         /* Create main interface on target. */
    2538           0 :         memset(&hvif, 0, sizeof(hvif));
    2539           0 :         hvif.index = 0;
    2540           0 :         IEEE80211_ADDR_COPY(hvif.myaddr, ic->ic_myaddr);
    2541           0 :         switch (ic->ic_opmode) {
    2542             :         case IEEE80211_M_STA:
    2543           0 :                 hvif.opmode = htobe32(AR_HTC_M_STA);
    2544           0 :                 break;
    2545             :         case IEEE80211_M_MONITOR:
    2546           0 :                 hvif.opmode = htobe32(AR_HTC_M_MONITOR);
    2547           0 :                 break;
    2548             : #ifndef IEEE80211_STA_ONLY
    2549             :         case IEEE80211_M_IBSS:
    2550           0 :                 hvif.opmode = htobe32(AR_HTC_M_IBSS);
    2551           0 :                 break;
    2552             :         case IEEE80211_M_AHDEMO:
    2553           0 :                 hvif.opmode = htobe32(AR_HTC_M_AHDEMO);
    2554           0 :                 break;
    2555             :         case IEEE80211_M_HOSTAP:
    2556           0 :                 hvif.opmode = htobe32(AR_HTC_M_HOSTAP);
    2557           0 :                 break;
    2558             : #endif
    2559             :         }
    2560           0 :         hvif.rtsthreshold = htobe16(ic->ic_rtsthreshold);
    2561             :         DPRINTF(("creating VAP\n"));
    2562           0 :         error = athn_usb_wmi_xcmd(usc, AR_WMI_CMD_VAP_CREATE,
    2563             :             &hvif, sizeof(hvif), NULL);
    2564           0 :         if (error != 0)
    2565             :                 goto fail;
    2566             : 
    2567             :         /* Create a fake node to send management frames before assoc. */
    2568           0 :         memset(&sta, 0, sizeof(sta));
    2569           0 :         IEEE80211_ADDR_COPY(sta.macaddr, ic->ic_myaddr);
    2570           0 :         sta.sta_index = 0;
    2571           0 :         sta.is_vif_sta = 1;
    2572           0 :         sta.vif_index = hvif.index;
    2573           0 :         sta.maxampdu = 0xffff;
    2574             :         DPRINTF(("creating default node\n"));
    2575           0 :         error = athn_usb_wmi_xcmd(usc, AR_WMI_CMD_NODE_CREATE,
    2576             :             &sta, sizeof(sta), NULL);
    2577           0 :         if (error != 0)
    2578             :                 goto fail;
    2579           0 :         usc->free_node_slots = ~(1 << sta.sta_index);
    2580             : 
    2581             :         /* Update target capabilities. */
    2582           0 :         memset(&hic, 0, sizeof(hic));
    2583           0 :         hic.ampdu_limit = htobe32(0x0000ffff);
    2584           0 :         hic.ampdu_subframes = 20;
    2585           0 :         hic.txchainmask = sc->txchainmask;
    2586             :         DPRINTF(("updating target configuration\n"));
    2587           0 :         error = athn_usb_wmi_xcmd(usc, AR_WMI_CMD_TARGET_IC_UPDATE,
    2588             :             &hic, sizeof(hic), NULL);
    2589           0 :         if (error != 0)
    2590             :                 goto fail;
    2591             : 
    2592             :         /* Queue Rx xfers. */
    2593           0 :         for (i = 0; i < ATHN_USB_RX_LIST_COUNT; i++) {
    2594           0 :                 data = &usc->rx_data[i];
    2595             : 
    2596           0 :                 usbd_setup_xfer(data->xfer, usc->rx_data_pipe, data, data->buf,
    2597             :                     ATHN_USB_RXBUFSZ, USBD_SHORT_XFER_OK | USBD_NO_COPY,
    2598             :                     USBD_NO_TIMEOUT, athn_usb_rxeof);
    2599           0 :                 error = usbd_transfer(data->xfer);
    2600           0 :                 if (error != 0 && error != USBD_IN_PROGRESS)
    2601             :                         goto fail;
    2602             :         }
    2603             :         /* We're ready to go. */
    2604           0 :         ifp->if_flags |= IFF_RUNNING;
    2605           0 :         ifq_clr_oactive(&ifp->if_snd);
    2606             : 
    2607             : #ifdef notyet
    2608             :         if (ic->ic_flags & IEEE80211_F_WEPON) {
    2609             :                 /* Install WEP keys. */
    2610             :                 for (i = 0; i < IEEE80211_WEP_NKID; i++)
    2611             :                         athn_usb_set_key(ic, NULL, &ic->ic_nw_keys[i]);
    2612             :         }
    2613             : #endif
    2614           0 :         if (ic->ic_opmode == IEEE80211_M_MONITOR)
    2615           0 :                 ieee80211_new_state(ic, IEEE80211_S_RUN, -1);
    2616             :         else
    2617           0 :                 ieee80211_new_state(ic, IEEE80211_S_SCAN, -1);
    2618           0 :         athn_usb_wait_async(usc);
    2619           0 :         return (0);
    2620             :  fail:
    2621           0 :         athn_usb_stop(ifp);
    2622           0 :         return (error);
    2623           0 : }
    2624             : 
    2625             : void
    2626           0 : athn_usb_stop(struct ifnet *ifp)
    2627             : {
    2628           0 :         struct athn_softc *sc = ifp->if_softc;
    2629           0 :         struct athn_usb_softc *usc = (struct athn_usb_softc *)sc;
    2630           0 :         struct ieee80211com *ic = &sc->sc_ic;
    2631           0 :         struct ar_htc_target_vif hvif;
    2632           0 :         uint8_t sta_index;
    2633             :         int s;
    2634             : 
    2635           0 :         sc->sc_tx_timer = 0;
    2636           0 :         ifp->if_timer = 0;
    2637           0 :         ifp->if_flags &= ~IFF_RUNNING;
    2638           0 :         ifq_clr_oactive(&ifp->if_snd);
    2639             : 
    2640           0 :         s = splusb();
    2641           0 :         ieee80211_new_state(ic, IEEE80211_S_INIT, -1);
    2642             : 
    2643             :         /* Wait for all async commands to complete. */
    2644           0 :         athn_usb_wait_async(usc);
    2645             : 
    2646           0 :         timeout_del(&sc->scan_to);
    2647           0 :         timeout_del(&sc->calib_to);
    2648             : 
    2649             :         /* Remove all non-default nodes. */
    2650           0 :         for (sta_index = 1; sta_index < AR_USB_MAX_STA; sta_index++) {
    2651           0 :                 if (usc->free_node_slots & (1 << sta_index))
    2652             :                         continue;
    2653           0 :                 (void)athn_usb_wmi_xcmd(usc, AR_WMI_CMD_NODE_REMOVE,
    2654             :                     &sta_index, sizeof(sta_index), NULL);
    2655           0 :         }
    2656             : 
    2657             :         /* Remove main interface. This also invalidates our default node. */
    2658           0 :         memset(&hvif, 0, sizeof(hvif));
    2659           0 :         hvif.index = 0;
    2660           0 :         IEEE80211_ADDR_COPY(hvif.myaddr, ic->ic_myaddr);
    2661           0 :         (void)athn_usb_wmi_xcmd(usc, AR_WMI_CMD_VAP_REMOVE,
    2662             :             &hvif, sizeof(hvif), NULL);
    2663             : 
    2664           0 :         usc->free_node_slots = 0xff;
    2665             : 
    2666           0 :         (void)athn_usb_wmi_cmd(usc, AR_WMI_CMD_DISABLE_INTR);
    2667           0 :         (void)athn_usb_wmi_cmd(usc, AR_WMI_CMD_DRAIN_TXQ_ALL);
    2668           0 :         (void)athn_usb_wmi_cmd(usc, AR_WMI_CMD_STOP_RECV);
    2669             : 
    2670           0 :         athn_reset(sc, 0);
    2671           0 :         athn_init_pll(sc, NULL);
    2672           0 :         athn_set_power_awake(sc);
    2673           0 :         athn_reset(sc, 1);
    2674           0 :         athn_init_pll(sc, NULL);
    2675           0 :         athn_set_power_sleep(sc);
    2676             : 
    2677             :         /* Abort Tx/Rx. */
    2678           0 :         usbd_abort_pipe(usc->tx_data_pipe);
    2679           0 :         usbd_abort_pipe(usc->rx_data_pipe);
    2680             : 
    2681             :         /* Free Tx/Rx buffers. */
    2682           0 :         athn_usb_free_tx_list(usc);
    2683           0 :         athn_usb_free_rx_list(usc);
    2684           0 :         splx(s);
    2685             : 
    2686             :         /* Flush Rx stream. */
    2687           0 :         m_freem(usc->rx_stream.m);
    2688           0 :         usc->rx_stream.m = NULL;
    2689           0 :         usc->rx_stream.left = 0;
    2690           0 : }

Generated by: LCOV version 1.13