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

          Line data    Source code
       1             : /*      $OpenBSD: if_zyd.c,v 1.118 2017/04/08 02:57:25 deraadt Exp $    */
       2             : 
       3             : /*-
       4             :  * Copyright (c) 2006 by Damien Bergamini <damien.bergamini@free.fr>
       5             :  * Copyright (c) 2006 by Florian Stoehr <ich@florian-stoehr.de>
       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             :  * ZyDAS ZD1211/ZD1211B USB WLAN driver.
      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/malloc.h>
      33             : #include <sys/timeout.h>
      34             : #include <sys/conf.h>
      35             : #include <sys/device.h>
      36             : #include <sys/endian.h>
      37             : 
      38             : #if NBPFILTER > 0
      39             : #include <net/bpf.h>
      40             : #endif
      41             : #include <net/if.h>
      42             : #include <net/if_dl.h>
      43             : #include <net/if_media.h>
      44             : 
      45             : #include <netinet/in.h>
      46             : #include <netinet/if_ether.h>
      47             : 
      48             : #include <net80211/ieee80211_var.h>
      49             : #include <net80211/ieee80211_amrr.h>
      50             : #include <net80211/ieee80211_radiotap.h>
      51             : 
      52             : #include <dev/usb/usb.h>
      53             : #include <dev/usb/usbdi.h>
      54             : #include <dev/usb/usbdi_util.h>
      55             : #include <dev/usb/usbdevs.h>
      56             : 
      57             : #include <dev/usb/if_zydreg.h>
      58             : 
      59             : #ifdef ZYD_DEBUG
      60             : #define DPRINTF(x)      do { if (zyddebug > 0) printf x; } while (0)
      61             : #define DPRINTFN(n, x)  do { if (zyddebug > (n)) printf x; } while (0)
      62             : int zyddebug = 0;
      63             : #else
      64             : #define DPRINTF(x)
      65             : #define DPRINTFN(n, x)
      66             : #endif
      67             : 
      68             : static const struct zyd_phy_pair zyd_def_phy[] = ZYD_DEF_PHY;
      69             : static const struct zyd_phy_pair zyd_def_phyB[] = ZYD_DEF_PHYB;
      70             : 
      71             : /* various supported device vendors/products */
      72             : #define ZYD_ZD1211_DEV(v, p)    \
      73             :         { { USB_VENDOR_##v, USB_PRODUCT_##v##_##p }, ZYD_ZD1211 }
      74             : #define ZYD_ZD1211B_DEV(v, p)   \
      75             :         { { USB_VENDOR_##v, USB_PRODUCT_##v##_##p }, ZYD_ZD1211B }
      76             : static const struct zyd_type {
      77             :         struct usb_devno        dev;
      78             :         uint8_t                 rev;
      79             : #define ZYD_ZD1211      0
      80             : #define ZYD_ZD1211B     1
      81             : } zyd_devs[] = {
      82             :         ZYD_ZD1211_DEV(3COM2,           3CRUSB10075),
      83             :         ZYD_ZD1211_DEV(ABOCOM,          WL54),
      84             :         ZYD_ZD1211_DEV(ASUS,            WL159G),
      85             :         ZYD_ZD1211_DEV(CYBERTAN,        TG54USB),
      86             :         ZYD_ZD1211_DEV(DRAYTEK,         VIGOR550),
      87             :         ZYD_ZD1211_DEV(PLANEX2,         GWUS54GD),
      88             :         ZYD_ZD1211_DEV(PLANEX2,         GWUS54GZL),
      89             :         ZYD_ZD1211_DEV(PLANEX3,         GWUS54GZ),
      90             :         ZYD_ZD1211_DEV(PLANEX3,         GWUS54MINI),
      91             :         ZYD_ZD1211_DEV(SAGEM,           XG760A),
      92             :         ZYD_ZD1211_DEV(SENAO,           NUB8301),
      93             :         ZYD_ZD1211_DEV(SITECOMEU,       WL113),
      94             :         ZYD_ZD1211_DEV(SWEEX,           ZD1211),
      95             :         ZYD_ZD1211_DEV(TEKRAM,          QUICKWLAN),
      96             :         ZYD_ZD1211_DEV(TEKRAM,          ZD1211_1),
      97             :         ZYD_ZD1211_DEV(TEKRAM,          ZD1211_2),
      98             :         ZYD_ZD1211_DEV(TWINMOS,         G240),
      99             :         ZYD_ZD1211_DEV(UMEDIA,          ALL0298V2),
     100             :         ZYD_ZD1211_DEV(UMEDIA,          TEW429UB_A),
     101             :         ZYD_ZD1211_DEV(UMEDIA,          TEW429UB),
     102             :         ZYD_ZD1211_DEV(UNKNOWN2,        NW3100),
     103             :         ZYD_ZD1211_DEV(WISTRONNEWEB,    UR055G),
     104             :         ZYD_ZD1211_DEV(ZCOM,            ZD1211),
     105             :         ZYD_ZD1211_DEV(ZYDAS,           ALL0298),
     106             :         ZYD_ZD1211_DEV(ZYDAS,           ZD1211),
     107             :         ZYD_ZD1211_DEV(ZYXEL,           AG225H),
     108             :         ZYD_ZD1211_DEV(ZYXEL,           G200V2),
     109             :         ZYD_ZD1211_DEV(ZYXEL,           G202),
     110             :         ZYD_ZD1211_DEV(ZYXEL,           G220),
     111             :         ZYD_ZD1211_DEV(ZYXEL,           G220F),
     112             : 
     113             :         ZYD_ZD1211B_DEV(ACCTON,         SMCWUSBG),
     114             :         ZYD_ZD1211B_DEV(ACCTON,         WN4501H_LF_IR),
     115             :         ZYD_ZD1211B_DEV(ACCTON,         WUS201),
     116             :         ZYD_ZD1211B_DEV(ACCTON,         ZD1211B),
     117             :         ZYD_ZD1211B_DEV(ASUS,           A9T_WIFI),
     118             :         ZYD_ZD1211B_DEV(BELKIN,         F5D7050C),
     119             :         ZYD_ZD1211B_DEV(BELKIN,         ZD1211B),
     120             :         ZYD_ZD1211B_DEV(BEWAN,          BWIFI_USB54AR),
     121             :         ZYD_ZD1211B_DEV(CISCOLINKSYS,   WUSBF54G),
     122             :         ZYD_ZD1211B_DEV(CYBERTAN,       ZD1211B),
     123             :         ZYD_ZD1211B_DEV(FIBERLINE,      WL430U),
     124             :         ZYD_ZD1211B_DEV(MELCO,          KG54L),
     125             :         ZYD_ZD1211B_DEV(PHILIPS,        SNU5600),
     126             :         ZYD_ZD1211B_DEV(PHILIPS,        SNU5630NS05),
     127             :         ZYD_ZD1211B_DEV(PLANEX2,        GW_US54GXS),
     128             :         ZYD_ZD1211B_DEV(PLANEX4,        GWUS54ZGL),
     129             :         ZYD_ZD1211B_DEV(PLANEX4,        ZD1211B),
     130             :         ZYD_ZD1211B_DEV(SAGEM,          XG76NA),
     131             :         ZYD_ZD1211B_DEV(SITECOMEU,      WL603),
     132             :         ZYD_ZD1211B_DEV(SITECOMEU,      ZD1211B),
     133             :         ZYD_ZD1211B_DEV(UMEDIA,         TEW429UBC1),
     134             :         ZYD_ZD1211B_DEV(UNKNOWN2,       ZD1211B),
     135             :         ZYD_ZD1211B_DEV(UNKNOWN3,       ZD1211B),
     136             :         ZYD_ZD1211B_DEV(SONY,           IFU_WLM2),
     137             :         ZYD_ZD1211B_DEV(USR,            USR5423),
     138             :         ZYD_ZD1211B_DEV(VTECH,          ZD1211B),
     139             :         ZYD_ZD1211B_DEV(ZCOM,           ZD1211B),
     140             :         ZYD_ZD1211B_DEV(ZYDAS,          ZD1211B),
     141             :         ZYD_ZD1211B_DEV(ZYDAS,          ZD1211B_2),
     142             :         ZYD_ZD1211B_DEV(ZYXEL,          AG220),
     143             :         ZYD_ZD1211B_DEV(ZYXEL,          AG225HV2),
     144             :         ZYD_ZD1211B_DEV(ZYXEL,          G220V2),
     145             :         ZYD_ZD1211B_DEV(ZYXEL,          M202)
     146             : };
     147             : #define zyd_lookup(v, p)        \
     148             :         ((const struct zyd_type *)usb_lookup(zyd_devs, v, p))
     149             : 
     150             : int zyd_match(struct device *, void *, void *);
     151             : void zyd_attach(struct device *, struct device *, void *);
     152             : int zyd_detach(struct device *, int);
     153             : 
     154             : struct cfdriver zyd_cd = {
     155             :         NULL, "zyd", DV_IFNET
     156             : };
     157             : 
     158             : const struct cfattach zyd_ca = {
     159             :         sizeof(struct zyd_softc), zyd_match, zyd_attach, zyd_detach
     160             : };
     161             : 
     162             : void            zyd_attachhook(struct device *);
     163             : int             zyd_complete_attach(struct zyd_softc *);
     164             : int             zyd_open_pipes(struct zyd_softc *);
     165             : void            zyd_close_pipes(struct zyd_softc *);
     166             : int             zyd_alloc_tx_list(struct zyd_softc *);
     167             : void            zyd_free_tx_list(struct zyd_softc *);
     168             : int             zyd_alloc_rx_list(struct zyd_softc *);
     169             : void            zyd_free_rx_list(struct zyd_softc *);
     170             : struct          ieee80211_node *zyd_node_alloc(struct ieee80211com *);
     171             : int             zyd_media_change(struct ifnet *);
     172             : void            zyd_next_scan(void *);
     173             : void            zyd_task(void *);
     174             : int             zyd_newstate(struct ieee80211com *, enum ieee80211_state, int);
     175             : int             zyd_cmd_read(struct zyd_softc *, const void *, size_t, int);
     176             : int             zyd_read16(struct zyd_softc *, uint16_t, uint16_t *);
     177             : int             zyd_read32(struct zyd_softc *, uint16_t, uint32_t *);
     178             : int             zyd_cmd_write(struct zyd_softc *, u_int16_t, const void *, int);
     179             : int             zyd_write16(struct zyd_softc *, uint16_t, uint16_t);
     180             : int             zyd_write32(struct zyd_softc *, uint16_t, uint32_t);
     181             : int             zyd_rfwrite(struct zyd_softc *, uint32_t);
     182             : void            zyd_lock_phy(struct zyd_softc *);
     183             : void            zyd_unlock_phy(struct zyd_softc *);
     184             : int             zyd_rfmd_init(struct zyd_rf *);
     185             : int             zyd_rfmd_switch_radio(struct zyd_rf *, int);
     186             : int             zyd_rfmd_set_channel(struct zyd_rf *, uint8_t);
     187             : int             zyd_al2230_init(struct zyd_rf *);
     188             : int             zyd_al2230_switch_radio(struct zyd_rf *, int);
     189             : int             zyd_al2230_set_channel(struct zyd_rf *, uint8_t);
     190             : int             zyd_al2230_init_b(struct zyd_rf *);
     191             : int             zyd_al7230B_init(struct zyd_rf *);
     192             : int             zyd_al7230B_switch_radio(struct zyd_rf *, int);
     193             : int             zyd_al7230B_set_channel(struct zyd_rf *, uint8_t);
     194             : int             zyd_al2210_init(struct zyd_rf *);
     195             : int             zyd_al2210_switch_radio(struct zyd_rf *, int);
     196             : int             zyd_al2210_set_channel(struct zyd_rf *, uint8_t);
     197             : int             zyd_gct_init(struct zyd_rf *);
     198             : int             zyd_gct_switch_radio(struct zyd_rf *, int);
     199             : int             zyd_gct_set_channel(struct zyd_rf *, uint8_t);
     200             : int             zyd_maxim_init(struct zyd_rf *);
     201             : int             zyd_maxim_switch_radio(struct zyd_rf *, int);
     202             : int             zyd_maxim_set_channel(struct zyd_rf *, uint8_t);
     203             : int             zyd_maxim2_init(struct zyd_rf *);
     204             : int             zyd_maxim2_switch_radio(struct zyd_rf *, int);
     205             : int             zyd_maxim2_set_channel(struct zyd_rf *, uint8_t);
     206             : int             zyd_rf_attach(struct zyd_softc *, uint8_t);
     207             : const char      *zyd_rf_name(uint8_t);
     208             : int             zyd_hw_init(struct zyd_softc *);
     209             : int             zyd_read_eeprom(struct zyd_softc *);
     210             : void            zyd_set_multi(struct zyd_softc *);
     211             : void            zyd_set_macaddr(struct zyd_softc *, const uint8_t *);
     212             : void            zyd_set_bssid(struct zyd_softc *, const uint8_t *);
     213             : int             zyd_switch_radio(struct zyd_softc *, int);
     214             : void            zyd_set_led(struct zyd_softc *, int, int);
     215             : int             zyd_set_rxfilter(struct zyd_softc *);
     216             : void            zyd_set_chan(struct zyd_softc *, struct ieee80211_channel *);
     217             : int             zyd_set_beacon_interval(struct zyd_softc *, int);
     218             : uint8_t         zyd_plcp_signal(int);
     219             : void            zyd_intr(struct usbd_xfer *, void *, usbd_status);
     220             : void            zyd_rx_data(struct zyd_softc *, const uint8_t *, uint16_t);
     221             : void            zyd_rxeof(struct usbd_xfer *, void *, usbd_status);
     222             : void            zyd_txeof(struct usbd_xfer *, void *, usbd_status);
     223             : int             zyd_tx(struct zyd_softc *, struct mbuf *,
     224             :                     struct ieee80211_node *);
     225             : void            zyd_start(struct ifnet *);
     226             : void            zyd_watchdog(struct ifnet *);
     227             : int             zyd_ioctl(struct ifnet *, u_long, caddr_t);
     228             : int             zyd_init(struct ifnet *);
     229             : void            zyd_stop(struct ifnet *, int);
     230             : int             zyd_loadfirmware(struct zyd_softc *, u_char *, size_t);
     231             : void            zyd_iter_func(void *, struct ieee80211_node *);
     232             : void            zyd_amrr_timeout(void *);
     233             : void            zyd_newassoc(struct ieee80211com *, struct ieee80211_node *,
     234             :                     int);
     235             : 
     236             : int
     237           0 : zyd_match(struct device *parent, void *match, void *aux)
     238             : {
     239           0 :         struct usb_attach_arg *uaa = aux;
     240             : 
     241           0 :         if (!uaa->iface)
     242           0 :                 return UMATCH_NONE;
     243             : 
     244           0 :         return (zyd_lookup(uaa->vendor, uaa->product) != NULL) ?
     245             :             UMATCH_VENDOR_PRODUCT : UMATCH_NONE;
     246           0 : }
     247             : 
     248             : void
     249           0 : zyd_attachhook(struct device *self)
     250             : {
     251           0 :         struct zyd_softc *sc = (struct zyd_softc *)self;
     252             :         const char *fwname;
     253           0 :         u_char *fw;
     254           0 :         size_t fwsize;
     255             :         int error;
     256             : 
     257           0 :         fwname = (sc->mac_rev == ZYD_ZD1211) ? "zd1211" : "zd1211b";
     258           0 :         if ((error = loadfirmware(fwname, &fw, &fwsize)) != 0) {
     259           0 :                 printf("%s: error %d, could not read firmware file %s\n",
     260           0 :                     sc->sc_dev.dv_xname, error, fwname);
     261           0 :                 return;
     262             :         }
     263             : 
     264           0 :         error = zyd_loadfirmware(sc, fw, fwsize);
     265           0 :         free(fw, M_DEVBUF, fwsize);
     266           0 :         if (error != 0) {
     267           0 :                 printf("%s: could not load firmware (error=%d)\n",
     268           0 :                     sc->sc_dev.dv_xname, error);
     269           0 :                 return;
     270             :         }
     271             : 
     272             :         /* complete the attach process */
     273           0 :         if (zyd_complete_attach(sc) == 0)
     274           0 :                 sc->attached = 1;
     275           0 : }
     276             : 
     277             : void
     278           0 : zyd_attach(struct device *parent, struct device *self, void *aux)
     279             : {
     280           0 :         struct zyd_softc *sc = (struct zyd_softc *)self;
     281           0 :         struct usb_attach_arg *uaa = aux;
     282             :         usb_device_descriptor_t* ddesc;
     283             : 
     284           0 :         sc->sc_udev = uaa->device;
     285             : 
     286           0 :         sc->mac_rev = zyd_lookup(uaa->vendor, uaa->product)->rev;
     287             : 
     288           0 :         ddesc = usbd_get_device_descriptor(sc->sc_udev);
     289           0 :         if (UGETW(ddesc->bcdDevice) < 0x4330) {
     290           0 :                 printf("%s: device version mismatch: 0x%x "
     291           0 :                     "(only >= 43.30 supported)\n", sc->sc_dev.dv_xname,
     292             :                     UGETW(ddesc->bcdDevice));
     293           0 :                 return;
     294             :         }
     295             : 
     296           0 :         config_mountroot(self, zyd_attachhook);
     297           0 : }
     298             : 
     299             : int
     300           0 : zyd_complete_attach(struct zyd_softc *sc)
     301             : {
     302           0 :         struct ieee80211com *ic = &sc->sc_ic;
     303           0 :         struct ifnet *ifp = &ic->ic_if;
     304             :         usbd_status error;
     305             :         int i;
     306             : 
     307           0 :         usb_init_task(&sc->sc_task, zyd_task, sc, USB_TASK_TYPE_GENERIC);
     308           0 :         timeout_set(&sc->scan_to, zyd_next_scan, sc);
     309             : 
     310           0 :         sc->amrr.amrr_min_success_threshold =  1;
     311           0 :         sc->amrr.amrr_max_success_threshold = 10;
     312           0 :         timeout_set(&sc->amrr_to, zyd_amrr_timeout, sc);
     313             : 
     314           0 :         error = usbd_set_config_no(sc->sc_udev, ZYD_CONFIG_NO, 1);
     315           0 :         if (error != 0) {
     316           0 :                 printf("%s: setting config no failed\n",
     317           0 :                     sc->sc_dev.dv_xname);
     318           0 :                 goto fail;
     319             :         }
     320             : 
     321           0 :         error = usbd_device2interface_handle(sc->sc_udev, ZYD_IFACE_INDEX,
     322           0 :             &sc->sc_iface);
     323           0 :         if (error != 0) {
     324           0 :                 printf("%s: getting interface handle failed\n",
     325           0 :                     sc->sc_dev.dv_xname);
     326           0 :                 goto fail;
     327             :         }
     328             : 
     329           0 :         if ((error = zyd_open_pipes(sc)) != 0) {
     330           0 :                 printf("%s: could not open pipes\n", sc->sc_dev.dv_xname);
     331           0 :                 goto fail;
     332             :         }
     333             : 
     334           0 :         if ((error = zyd_read_eeprom(sc)) != 0) {
     335           0 :                 printf("%s: could not read EEPROM\n", sc->sc_dev.dv_xname);
     336           0 :                 goto fail;
     337             :         }
     338             : 
     339           0 :         if ((error = zyd_rf_attach(sc, sc->rf_rev)) != 0) {
     340           0 :                 printf("%s: could not attach RF\n", sc->sc_dev.dv_xname);
     341           0 :                 goto fail;
     342             :         }
     343             : 
     344           0 :         if ((error = zyd_hw_init(sc)) != 0) {
     345           0 :                 printf("%s: hardware initialization failed\n",
     346             :                     sc->sc_dev.dv_xname);
     347           0 :                 goto fail;
     348             :         }
     349             : 
     350           0 :         printf("%s: HMAC ZD1211%s, FW %02x.%02x, RF %s, PA %x, address %s\n",
     351           0 :             sc->sc_dev.dv_xname, (sc->mac_rev == ZYD_ZD1211) ? "": "B",
     352           0 :             sc->fw_rev >> 8, sc->fw_rev & 0xff, zyd_rf_name(sc->rf_rev),
     353           0 :             sc->pa_rev, ether_sprintf(ic->ic_myaddr));
     354             : 
     355           0 :         ic->ic_phytype = IEEE80211_T_OFDM;   /* not only, but not used */
     356           0 :         ic->ic_opmode = IEEE80211_M_STA;     /* default to BSS mode */
     357           0 :         ic->ic_state = IEEE80211_S_INIT;
     358             : 
     359             :         /* set device capabilities */
     360           0 :         ic->ic_caps =
     361             :             IEEE80211_C_MONITOR |       /* monitor mode supported */
     362             :             IEEE80211_C_TXPMGT |        /* tx power management */
     363             :             IEEE80211_C_SHPREAMBLE |    /* short preamble supported */
     364             :             IEEE80211_C_WEP |           /* s/w WEP */
     365             :             IEEE80211_C_RSN;            /* WPA/RSN */
     366             : 
     367             :         /* set supported .11b and .11g rates */
     368           0 :         ic->ic_sup_rates[IEEE80211_MODE_11B] = ieee80211_std_rateset_11b;
     369           0 :         ic->ic_sup_rates[IEEE80211_MODE_11G] = ieee80211_std_rateset_11g;
     370             : 
     371             :         /* set supported .11b and .11g channels (1 through 14) */
     372           0 :         for (i = 1; i <= 14; i++) {
     373           0 :                 ic->ic_channels[i].ic_freq =
     374           0 :                     ieee80211_ieee2mhz(i, IEEE80211_CHAN_2GHZ);
     375           0 :                 ic->ic_channels[i].ic_flags =
     376             :                     IEEE80211_CHAN_CCK | IEEE80211_CHAN_OFDM |
     377             :                     IEEE80211_CHAN_DYN | IEEE80211_CHAN_2GHZ;
     378             :         }
     379             : 
     380           0 :         ifp->if_softc = sc;
     381           0 :         ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
     382           0 :         ifp->if_ioctl = zyd_ioctl;
     383           0 :         ifp->if_start = zyd_start;
     384           0 :         ifp->if_watchdog = zyd_watchdog;
     385           0 :         memcpy(ifp->if_xname, sc->sc_dev.dv_xname, IFNAMSIZ);
     386             : 
     387           0 :         if_attach(ifp);
     388           0 :         ieee80211_ifattach(ifp);
     389           0 :         ic->ic_node_alloc = zyd_node_alloc;
     390           0 :         ic->ic_newassoc = zyd_newassoc;
     391             : 
     392             :         /* override state transition machine */
     393           0 :         sc->sc_newstate = ic->ic_newstate;
     394           0 :         ic->ic_newstate = zyd_newstate;
     395           0 :         ieee80211_media_init(ifp, zyd_media_change, ieee80211_media_status);
     396             : 
     397             : #if NBPFILTER > 0
     398           0 :         bpfattach(&sc->sc_drvbpf, ifp, DLT_IEEE802_11_RADIO,
     399             :             sizeof (struct ieee80211_frame) + IEEE80211_RADIOTAP_HDRLEN);
     400             : 
     401           0 :         sc->sc_rxtap_len = sizeof sc->sc_rxtapu;
     402           0 :         sc->sc_rxtap.wr_ihdr.it_len = htole16(sc->sc_rxtap_len);
     403           0 :         sc->sc_rxtap.wr_ihdr.it_present = htole32(ZYD_RX_RADIOTAP_PRESENT);
     404             : 
     405           0 :         sc->sc_txtap_len = sizeof sc->sc_txtapu;
     406           0 :         sc->sc_txtap.wt_ihdr.it_len = htole16(sc->sc_txtap_len);
     407           0 :         sc->sc_txtap.wt_ihdr.it_present = htole32(ZYD_TX_RADIOTAP_PRESENT);
     408             : #endif
     409             : 
     410           0 : fail:   return error;
     411             : }
     412             : 
     413             : int
     414           0 : zyd_detach(struct device *self, int flags)
     415             : {
     416           0 :         struct zyd_softc *sc = (struct zyd_softc *)self;
     417           0 :         struct ifnet *ifp = &sc->sc_ic.ic_if;
     418             :         int s;
     419             : 
     420           0 :         s = splusb();
     421             : 
     422           0 :         usb_rem_task(sc->sc_udev, &sc->sc_task);
     423           0 :         if (timeout_initialized(&sc->scan_to))
     424           0 :                 timeout_del(&sc->scan_to);
     425           0 :         if (timeout_initialized(&sc->amrr_to))
     426           0 :                 timeout_del(&sc->amrr_to);
     427             : 
     428           0 :         zyd_close_pipes(sc);
     429             : 
     430           0 :         if (!sc->attached) {
     431           0 :                 splx(s);
     432           0 :                 return 0;
     433             :         }
     434             : 
     435           0 :         if (ifp->if_softc != NULL) {
     436           0 :                 ieee80211_ifdetach(ifp);
     437           0 :                 if_detach(ifp);
     438           0 :         }
     439             : 
     440           0 :         zyd_free_rx_list(sc);
     441           0 :         zyd_free_tx_list(sc);
     442             : 
     443           0 :         sc->attached = 0;
     444             : 
     445           0 :         splx(s);
     446             : 
     447           0 :         return 0;
     448           0 : }
     449             : 
     450             : int
     451           0 : zyd_open_pipes(struct zyd_softc *sc)
     452             : {
     453             :         usb_endpoint_descriptor_t *edesc;
     454             :         int isize;
     455             :         usbd_status error;
     456             : 
     457             :         /* interrupt in */
     458           0 :         edesc = usbd_get_endpoint_descriptor(sc->sc_iface, 0x83);
     459           0 :         if (edesc == NULL)
     460           0 :                 return EINVAL;
     461             : 
     462           0 :         isize = UGETW(edesc->wMaxPacketSize);
     463           0 :         if (isize == 0) /* should not happen */
     464           0 :                 return EINVAL;
     465             : 
     466           0 :         sc->ibuf = malloc(isize, M_USBDEV, M_NOWAIT);
     467           0 :         if (sc->ibuf == NULL)
     468           0 :                 return ENOMEM;
     469           0 :         sc->ibuflen = isize;
     470           0 :         error = usbd_open_pipe_intr(sc->sc_iface, 0x83, USBD_SHORT_XFER_OK,
     471           0 :             &sc->zyd_ep[ZYD_ENDPT_IIN], sc, sc->ibuf, isize, zyd_intr,
     472             :             USBD_DEFAULT_INTERVAL);
     473           0 :         if (error != 0) {
     474           0 :                 printf("%s: open rx intr pipe failed: %s\n",
     475           0 :                     sc->sc_dev.dv_xname, usbd_errstr(error));
     476           0 :                 goto fail;
     477             :         }
     478             : 
     479             :         /* interrupt out (not necessarily an interrupt pipe) */
     480           0 :         error = usbd_open_pipe(sc->sc_iface, 0x04, USBD_EXCLUSIVE_USE,
     481           0 :             &sc->zyd_ep[ZYD_ENDPT_IOUT]);
     482           0 :         if (error != 0) {
     483           0 :                 printf("%s: open tx intr pipe failed: %s\n",
     484           0 :                     sc->sc_dev.dv_xname, usbd_errstr(error));
     485           0 :                 goto fail;
     486             :         }
     487             : 
     488             :         /* bulk in */
     489           0 :         error = usbd_open_pipe(sc->sc_iface, 0x82, USBD_EXCLUSIVE_USE,
     490           0 :             &sc->zyd_ep[ZYD_ENDPT_BIN]);
     491           0 :         if (error != 0) {
     492           0 :                 printf("%s: open rx pipe failed: %s\n",
     493           0 :                     sc->sc_dev.dv_xname, usbd_errstr(error));
     494           0 :                 goto fail;
     495             :         }
     496             : 
     497             :         /* bulk out */
     498           0 :         error = usbd_open_pipe(sc->sc_iface, 0x01, USBD_EXCLUSIVE_USE,
     499           0 :             &sc->zyd_ep[ZYD_ENDPT_BOUT]);
     500           0 :         if (error != 0) {
     501           0 :                 printf("%s: open tx pipe failed: %s\n",
     502           0 :                     sc->sc_dev.dv_xname, usbd_errstr(error));
     503           0 :                 goto fail;
     504             :         }
     505             : 
     506           0 :         return 0;
     507             : 
     508           0 : fail:   zyd_close_pipes(sc);
     509           0 :         return error;
     510           0 : }
     511             : 
     512             : void
     513           0 : zyd_close_pipes(struct zyd_softc *sc)
     514             : {
     515             :         int i;
     516             : 
     517           0 :         for (i = 0; i < ZYD_ENDPT_CNT; i++) {
     518           0 :                 if (sc->zyd_ep[i] != NULL) {
     519           0 :                         usbd_abort_pipe(sc->zyd_ep[i]);
     520           0 :                         usbd_close_pipe(sc->zyd_ep[i]);
     521           0 :                         sc->zyd_ep[i] = NULL;
     522           0 :                 }
     523             :         }
     524           0 :         if (sc->ibuf != NULL) {
     525           0 :                 free(sc->ibuf, M_USBDEV, sc->ibuflen);
     526           0 :                 sc->ibuf = NULL;
     527           0 :         }
     528           0 : }
     529             : 
     530             : int
     531           0 : zyd_alloc_tx_list(struct zyd_softc *sc)
     532             : {
     533             :         int i, error;
     534             : 
     535           0 :         sc->tx_queued = 0;
     536             : 
     537           0 :         for (i = 0; i < ZYD_TX_LIST_CNT; i++) {
     538           0 :                 struct zyd_tx_data *data = &sc->tx_data[i];
     539             : 
     540           0 :                 data->sc = sc;       /* backpointer for callbacks */
     541             : 
     542           0 :                 data->xfer = usbd_alloc_xfer(sc->sc_udev);
     543           0 :                 if (data->xfer == NULL) {
     544           0 :                         printf("%s: could not allocate tx xfer\n",
     545           0 :                             sc->sc_dev.dv_xname);
     546             :                         error = ENOMEM;
     547           0 :                         goto fail;
     548             :                 }
     549           0 :                 data->buf = usbd_alloc_buffer(data->xfer, ZYD_MAX_TXBUFSZ);
     550           0 :                 if (data->buf == NULL) {
     551           0 :                         printf("%s: could not allocate tx buffer\n",
     552           0 :                             sc->sc_dev.dv_xname);
     553             :                         error = ENOMEM;
     554           0 :                         goto fail;
     555             :                 }
     556             : 
     557             :                 /* clear Tx descriptor */
     558           0 :                 bzero(data->buf, sizeof (struct zyd_tx_desc));
     559           0 :         }
     560           0 :         return 0;
     561             : 
     562           0 : fail:   zyd_free_tx_list(sc);
     563           0 :         return error;
     564           0 : }
     565             : 
     566             : void
     567           0 : zyd_free_tx_list(struct zyd_softc *sc)
     568             : {
     569           0 :         struct ieee80211com *ic = &sc->sc_ic;
     570             :         int i;
     571             : 
     572           0 :         for (i = 0; i < ZYD_TX_LIST_CNT; i++) {
     573           0 :                 struct zyd_tx_data *data = &sc->tx_data[i];
     574             : 
     575           0 :                 if (data->xfer != NULL) {
     576           0 :                         usbd_free_xfer(data->xfer);
     577           0 :                         data->xfer = NULL;
     578           0 :                 }
     579           0 :                 if (data->ni != NULL) {
     580           0 :                         ieee80211_release_node(ic, data->ni);
     581           0 :                         data->ni = NULL;
     582           0 :                 }
     583             :         }
     584           0 : }
     585             : 
     586             : int
     587           0 : zyd_alloc_rx_list(struct zyd_softc *sc)
     588             : {
     589             :         int i, error;
     590             : 
     591           0 :         for (i = 0; i < ZYD_RX_LIST_CNT; i++) {
     592           0 :                 struct zyd_rx_data *data = &sc->rx_data[i];
     593             : 
     594           0 :                 data->sc = sc;       /* backpointer for callbacks */
     595             : 
     596           0 :                 data->xfer = usbd_alloc_xfer(sc->sc_udev);
     597           0 :                 if (data->xfer == NULL) {
     598           0 :                         printf("%s: could not allocate rx xfer\n",
     599           0 :                             sc->sc_dev.dv_xname);
     600             :                         error = ENOMEM;
     601           0 :                         goto fail;
     602             :                 }
     603           0 :                 data->buf = usbd_alloc_buffer(data->xfer, ZYX_MAX_RXBUFSZ);
     604           0 :                 if (data->buf == NULL) {
     605           0 :                         printf("%s: could not allocate rx buffer\n",
     606           0 :                             sc->sc_dev.dv_xname);
     607             :                         error = ENOMEM;
     608           0 :                         goto fail;
     609             :                 }
     610           0 :         }
     611           0 :         return 0;
     612             : 
     613           0 : fail:   zyd_free_rx_list(sc);
     614           0 :         return error;
     615           0 : }
     616             : 
     617             : void
     618           0 : zyd_free_rx_list(struct zyd_softc *sc)
     619             : {
     620             :         int i;
     621             : 
     622           0 :         for (i = 0; i < ZYD_RX_LIST_CNT; i++) {
     623           0 :                 struct zyd_rx_data *data = &sc->rx_data[i];
     624             : 
     625           0 :                 if (data->xfer != NULL) {
     626           0 :                         usbd_free_xfer(data->xfer);
     627           0 :                         data->xfer = NULL;
     628           0 :                 }
     629             :         }
     630           0 : }
     631             : 
     632             : struct ieee80211_node *
     633           0 : zyd_node_alloc(struct ieee80211com *ic)
     634             : {
     635           0 :         return malloc(sizeof (struct zyd_node), M_DEVBUF, M_NOWAIT | M_ZERO);
     636             : }
     637             : 
     638             : int
     639           0 : zyd_media_change(struct ifnet *ifp)
     640             : {
     641             :         int error;
     642             : 
     643           0 :         error = ieee80211_media_change(ifp);
     644           0 :         if (error != ENETRESET)
     645           0 :                 return error;
     646             : 
     647           0 :         if ((ifp->if_flags & (IFF_UP | IFF_RUNNING)) == (IFF_UP | IFF_RUNNING))
     648           0 :                 zyd_init(ifp);
     649             : 
     650           0 :         return 0;
     651           0 : }
     652             : 
     653             : /*
     654             :  * This function is called periodically (every 200ms) during scanning to
     655             :  * switch from one channel to another.
     656             :  */
     657             : void
     658           0 : zyd_next_scan(void *arg)
     659             : {
     660           0 :         struct zyd_softc *sc = arg;
     661           0 :         struct ieee80211com *ic = &sc->sc_ic;
     662           0 :         struct ifnet *ifp = &ic->ic_if;
     663             : 
     664           0 :         if (ic->ic_state == IEEE80211_S_SCAN)
     665           0 :                 ieee80211_next_scan(ifp);
     666           0 : }
     667             : 
     668             : void
     669           0 : zyd_task(void *arg)
     670             : {
     671           0 :         struct zyd_softc *sc = arg;
     672           0 :         struct ieee80211com *ic = &sc->sc_ic;
     673             :         enum ieee80211_state ostate;
     674             : 
     675           0 :         ostate = ic->ic_state;
     676             : 
     677           0 :         switch (sc->sc_state) {
     678             :         case IEEE80211_S_INIT:
     679           0 :                 if (ostate == IEEE80211_S_RUN) {
     680             :                         /* turn link LED off */
     681           0 :                         zyd_set_led(sc, ZYD_LED1, 0);
     682             : 
     683             :                         /* stop data LED from blinking */
     684           0 :                         zyd_write32(sc, sc->fwbase + ZYD_FW_LINK_STATUS, 0);
     685           0 :                 }
     686             :                 break;
     687             : 
     688             :         case IEEE80211_S_SCAN:
     689           0 :                 zyd_set_chan(sc, ic->ic_bss->ni_chan);
     690           0 :                 timeout_add_msec(&sc->scan_to, 200);
     691           0 :                 break;
     692             : 
     693             :         case IEEE80211_S_AUTH:
     694             :         case IEEE80211_S_ASSOC:
     695           0 :                 zyd_set_chan(sc, ic->ic_bss->ni_chan);
     696           0 :                 break;
     697             : 
     698             :         case IEEE80211_S_RUN:
     699             :         {
     700           0 :                 struct ieee80211_node *ni = ic->ic_bss;
     701             : 
     702           0 :                 zyd_set_chan(sc, ni->ni_chan);
     703             : 
     704           0 :                 if (ic->ic_opmode != IEEE80211_M_MONITOR) {
     705             :                         /* turn link LED on */
     706           0 :                         zyd_set_led(sc, ZYD_LED1, 1);
     707             : 
     708             :                         /* make data LED blink upon Tx */
     709           0 :                         zyd_write32(sc, sc->fwbase + ZYD_FW_LINK_STATUS, 1);
     710             : 
     711           0 :                         zyd_set_bssid(sc, ni->ni_bssid);
     712           0 :                 }
     713             : 
     714           0 :                 if (ic->ic_opmode == IEEE80211_M_STA) {
     715             :                         /* fake a join to init the tx rate */
     716           0 :                         zyd_newassoc(ic, ni, 1);
     717           0 :                 }
     718             : 
     719             :                 /* start automatic rate control timer */
     720           0 :                 if (ic->ic_fixed_rate == -1)
     721           0 :                         timeout_add_sec(&sc->amrr_to, 1);
     722             : 
     723             :                 break;
     724             :         }
     725             :         }
     726             : 
     727           0 :         sc->sc_newstate(ic, sc->sc_state, sc->sc_arg);
     728           0 : }
     729             : 
     730             : int
     731           0 : zyd_newstate(struct ieee80211com *ic, enum ieee80211_state nstate, int arg)
     732             : {
     733           0 :         struct zyd_softc *sc = ic->ic_softc;
     734             : 
     735           0 :         usb_rem_task(sc->sc_udev, &sc->sc_task);
     736           0 :         timeout_del(&sc->scan_to);
     737           0 :         timeout_del(&sc->amrr_to);
     738             : 
     739             :         /* do it in a process context */
     740           0 :         sc->sc_state = nstate;
     741           0 :         sc->sc_arg = arg;
     742           0 :         usb_add_task(sc->sc_udev, &sc->sc_task);
     743             : 
     744           0 :         return 0;
     745             : }
     746             : 
     747             : /*
     748             :  * Issue a read command for the specificed register (of size regsize)
     749             :  * and await a reply of olen bytes in sc->odata.
     750             :  */
     751             : int
     752           0 : zyd_cmd_read(struct zyd_softc *sc, const void *reg, size_t regsize, int olen)
     753             : {
     754             :         struct usbd_xfer *xfer;
     755           0 :         struct zyd_cmd cmd;
     756             :         usbd_status error;
     757             :         int s;
     758             : 
     759           0 :         if ((xfer = usbd_alloc_xfer(sc->sc_udev)) == NULL)
     760           0 :                 return ENOMEM;
     761             : 
     762           0 :         bzero(&cmd, sizeof(cmd));
     763           0 :         cmd.code = htole16(ZYD_CMD_IORD);
     764           0 :         bcopy(reg, cmd.data, regsize);
     765             : 
     766           0 :         bzero(sc->odata, sizeof(sc->odata));
     767           0 :         sc->olen = olen;
     768             : 
     769           0 :         usbd_setup_xfer(xfer, sc->zyd_ep[ZYD_ENDPT_IOUT], 0,
     770           0 :             &cmd, sizeof(cmd.code) + regsize,
     771             :             USBD_FORCE_SHORT_XFER | USBD_SYNCHRONOUS,
     772             :             ZYD_INTR_TIMEOUT, NULL);
     773           0 :         s = splusb();
     774           0 :         sc->odone = 0;
     775           0 :         error = usbd_transfer(xfer);
     776           0 :         splx(s);
     777           0 :         if (error) {
     778           0 :                 printf("%s: could not send command: %s\n",
     779           0 :                     sc->sc_dev.dv_xname, usbd_errstr(error));
     780           0 :                 usbd_free_xfer(xfer);
     781           0 :                 return EIO;
     782             :         }
     783             : 
     784           0 :         if (!sc->odone) {
     785             :                 /* wait for ZYD_NOTIF_IORD interrupt */
     786           0 :                 if (tsleep(sc, PWAIT, "zydcmd", ZYD_INTR_TIMEOUT) != 0)
     787           0 :                         printf("%s: read command failed\n",
     788           0 :                             sc->sc_dev.dv_xname);
     789             :         }
     790           0 :         usbd_free_xfer(xfer);
     791             : 
     792           0 :         return error;
     793           0 : }
     794             : 
     795             : int
     796           0 : zyd_read16(struct zyd_softc *sc, uint16_t reg, uint16_t *val)
     797             : {
     798             :         struct zyd_io *odata;
     799             :         int error;
     800             : 
     801           0 :         reg = htole16(reg);
     802           0 :         error = zyd_cmd_read(sc, &reg, sizeof(reg), sizeof(*odata));
     803           0 :         if (error == 0) {
     804           0 :                 odata = (struct zyd_io *)sc->odata;
     805           0 :                 *val = letoh16(odata[0].val);
     806           0 :         }
     807           0 :         return error;
     808             : }
     809             : 
     810             : int
     811           0 : zyd_read32(struct zyd_softc *sc, uint16_t reg, uint32_t *val)
     812             : {
     813             :         struct zyd_io *odata;
     814           0 :         uint16_t regs[2];
     815             :         int error;
     816             : 
     817           0 :         regs[0] = htole16(ZYD_REG32_HI(reg));
     818           0 :         regs[1] = htole16(ZYD_REG32_LO(reg));
     819           0 :         error = zyd_cmd_read(sc, regs, sizeof(regs), sizeof(*odata) * 2);
     820           0 :         if (error == 0) {
     821           0 :                 odata = (struct zyd_io *)sc->odata;
     822           0 :                 *val = letoh16(odata[0].val) << 16 | letoh16(odata[1].val);
     823           0 :         }
     824           0 :         return error;
     825           0 : }
     826             : 
     827             : int
     828           0 : zyd_cmd_write(struct zyd_softc *sc, u_int16_t code, const void *data, int len)
     829             : {
     830             :         struct usbd_xfer *xfer;
     831           0 :         struct zyd_cmd cmd;
     832             :         usbd_status error;
     833             : 
     834           0 :         if ((xfer = usbd_alloc_xfer(sc->sc_udev)) == NULL)
     835           0 :                 return ENOMEM;
     836             : 
     837           0 :         bzero(&cmd, sizeof(cmd));
     838           0 :         cmd.code = htole16(code);
     839           0 :         bcopy(data, cmd.data, len);
     840             : 
     841           0 :         usbd_setup_xfer(xfer, sc->zyd_ep[ZYD_ENDPT_IOUT], 0,
     842           0 :             &cmd, sizeof(cmd.code) + len,
     843             :             USBD_FORCE_SHORT_XFER | USBD_SYNCHRONOUS,
     844             :             ZYD_INTR_TIMEOUT, NULL);
     845           0 :         error = usbd_transfer(xfer);
     846           0 :         if (error)
     847           0 :                 printf("%s: could not send command: %s\n",
     848           0 :                     sc->sc_dev.dv_xname, usbd_errstr(error));
     849             : 
     850           0 :         usbd_free_xfer(xfer);
     851           0 :         return error;
     852           0 : }
     853             : 
     854             : int
     855           0 : zyd_write16(struct zyd_softc *sc, uint16_t reg, uint16_t val)
     856             : { 
     857           0 :         struct zyd_io io;
     858             : 
     859           0 :         io.reg = htole16(reg);
     860           0 :         io.val = htole16(val);
     861           0 :         return zyd_cmd_write(sc, ZYD_CMD_IOWR, &io, sizeof(io));
     862           0 : }
     863             : 
     864             : int
     865           0 : zyd_write32(struct zyd_softc *sc, uint16_t reg, uint32_t val)
     866             : {
     867           0 :         struct zyd_io io[2];
     868             : 
     869           0 :         io[0].reg = htole16(ZYD_REG32_HI(reg));
     870           0 :         io[0].val = htole16(val >> 16);
     871           0 :         io[1].reg = htole16(ZYD_REG32_LO(reg));
     872           0 :         io[1].val = htole16(val & 0xffff);
     873             : 
     874           0 :         return zyd_cmd_write(sc, ZYD_CMD_IOWR, io, sizeof(io));
     875           0 : }
     876             : 
     877             : int
     878           0 : zyd_rfwrite(struct zyd_softc *sc, uint32_t val)
     879             : {
     880           0 :         struct zyd_rf *rf = &sc->sc_rf;
     881           0 :         struct zyd_rfwrite req;
     882           0 :         uint16_t cr203;
     883             :         int i;
     884             : 
     885           0 :         (void)zyd_read16(sc, ZYD_CR203, &cr203);
     886           0 :         cr203 &= ~(ZYD_RF_IF_LE | ZYD_RF_CLK | ZYD_RF_DATA);
     887             : 
     888           0 :         req.code  = htole16(2);
     889           0 :         req.width = htole16(rf->width);
     890           0 :         for (i = 0; i < rf->width; i++) {
     891           0 :                 req.bit[i] = htole16(cr203);
     892           0 :                 if (val & (1 << (rf->width - 1 - i)))
     893           0 :                         req.bit[i] |= htole16(ZYD_RF_DATA);
     894             :         }
     895           0 :         return zyd_cmd_write(sc, ZYD_CMD_RFCFG, &req, 4 + 2 * rf->width);
     896           0 : }
     897             : 
     898             : void
     899           0 : zyd_lock_phy(struct zyd_softc *sc)
     900             : {
     901           0 :         uint32_t tmp;
     902             : 
     903           0 :         (void)zyd_read32(sc, ZYD_MAC_MISC, &tmp);
     904           0 :         tmp &= ~ZYD_UNLOCK_PHY_REGS;
     905           0 :         (void)zyd_write32(sc, ZYD_MAC_MISC, tmp);
     906           0 : }
     907             : 
     908             : void
     909           0 : zyd_unlock_phy(struct zyd_softc *sc)
     910             : {
     911           0 :         uint32_t tmp;
     912             : 
     913           0 :         (void)zyd_read32(sc, ZYD_MAC_MISC, &tmp);
     914           0 :         tmp |= ZYD_UNLOCK_PHY_REGS;
     915           0 :         (void)zyd_write32(sc, ZYD_MAC_MISC, tmp);
     916           0 : }
     917             : 
     918             : /*
     919             :  * RFMD RF methods.
     920             :  */
     921             : int
     922           0 : zyd_rfmd_init(struct zyd_rf *rf)
     923             : {
     924           0 :         struct zyd_softc *sc = rf->rf_sc;
     925             :         static const struct zyd_phy_pair phyini[] = ZYD_RFMD_PHY;
     926             :         static const uint32_t rfini[] = ZYD_RFMD_RF;
     927             :         int i, error;
     928             : 
     929             :         /* init RF-dependent PHY registers */
     930           0 :         for (i = 0; i < nitems(phyini); i++) {
     931           0 :                 error = zyd_write16(sc, phyini[i].reg, phyini[i].val);
     932           0 :                 if (error != 0)
     933           0 :                         return error;
     934             :         }
     935             : 
     936             :         /* init RFMD radio */
     937           0 :         for (i = 0; i < nitems(rfini); i++) {
     938           0 :                 if ((error = zyd_rfwrite(sc, rfini[i])) != 0)
     939           0 :                         return error;
     940             :         }
     941           0 :         return 0;
     942           0 : }
     943             : 
     944             : int
     945           0 : zyd_rfmd_switch_radio(struct zyd_rf *rf, int on)
     946             : {
     947           0 :         struct zyd_softc *sc = rf->rf_sc;
     948             : 
     949           0 :         (void)zyd_write16(sc, ZYD_CR10, on ? 0x89 : 0x15);
     950           0 :         (void)zyd_write16(sc, ZYD_CR11, on ? 0x00 : 0x81);
     951             : 
     952           0 :         return 0;
     953             : }
     954             : 
     955             : int
     956           0 : zyd_rfmd_set_channel(struct zyd_rf *rf, uint8_t chan)
     957             : {
     958           0 :         struct zyd_softc *sc = rf->rf_sc;
     959             :         static const struct {
     960             :                 uint32_t        r1, r2;
     961             :         } rfprog[] = ZYD_RFMD_CHANTABLE;
     962             : 
     963           0 :         (void)zyd_rfwrite(sc, rfprog[chan - 1].r1);
     964           0 :         (void)zyd_rfwrite(sc, rfprog[chan - 1].r2);
     965             : 
     966           0 :         return 0;
     967             : }
     968             : 
     969             : /*
     970             :  * AL2230 RF methods.
     971             :  */
     972             : int
     973           0 : zyd_al2230_init(struct zyd_rf *rf)
     974             : {
     975           0 :         struct zyd_softc *sc = rf->rf_sc;
     976             :         static const struct zyd_phy_pair phyini[] = ZYD_AL2230_PHY;
     977             :         static const struct zyd_phy_pair phy2230s[] = ZYD_AL2230S_PHY_INIT;
     978             :         static const uint32_t rfini[] = ZYD_AL2230_RF;
     979             :         int i, error;
     980             : 
     981             :         /* init RF-dependent PHY registers */
     982           0 :         for (i = 0; i < nitems(phyini); i++) {
     983           0 :                 error = zyd_write16(sc, phyini[i].reg, phyini[i].val);
     984           0 :                 if (error != 0)
     985           0 :                         return error;
     986             :         }
     987           0 :         if (sc->rf_rev == ZYD_RF_AL2230S) {
     988           0 :                 for (i = 0; i < nitems(phy2230s); i++) {
     989           0 :                         error = zyd_write16(sc, phy2230s[i].reg,
     990           0 :                             phy2230s[i].val);
     991           0 :                         if (error != 0)
     992           0 :                                 return error;
     993             :                 }
     994             :         }
     995             :         /* init AL2230 radio */
     996           0 :         for (i = 0; i < nitems(rfini); i++) {
     997           0 :                 if ((error = zyd_rfwrite(sc, rfini[i])) != 0)
     998           0 :                         return error;
     999             :         }
    1000           0 :         return 0;
    1001           0 : }
    1002             : 
    1003             : int
    1004           0 : zyd_al2230_init_b(struct zyd_rf *rf)
    1005             : {
    1006           0 :         struct zyd_softc *sc = rf->rf_sc;
    1007             :         static const struct zyd_phy_pair phyini[] = ZYD_AL2230_PHY_B;
    1008             :         static const uint32_t rfini[] = ZYD_AL2230_RF_B;
    1009             :         int i, error;
    1010             : 
    1011             :         /* init RF-dependent PHY registers */
    1012           0 :         for (i = 0; i < nitems(phyini); i++) {
    1013           0 :                 error = zyd_write16(sc, phyini[i].reg, phyini[i].val);
    1014           0 :                 if (error != 0)
    1015           0 :                         return error;
    1016             :         }
    1017             : 
    1018             :         /* init AL2230 radio */
    1019           0 :         for (i = 0; i < nitems(rfini); i++) {
    1020           0 :                 if ((error = zyd_rfwrite(sc, rfini[i])) != 0)
    1021           0 :                         return error;
    1022             :         }
    1023           0 :         return 0;
    1024           0 : }
    1025             : 
    1026             : int
    1027           0 : zyd_al2230_switch_radio(struct zyd_rf *rf, int on)
    1028             : {
    1029           0 :         struct zyd_softc *sc = rf->rf_sc;
    1030           0 :         int on251 = (sc->mac_rev == ZYD_ZD1211) ? 0x3f : 0x7f;
    1031             : 
    1032           0 :         (void)zyd_write16(sc, ZYD_CR11,  on ? 0x00 : 0x04);
    1033           0 :         (void)zyd_write16(sc, ZYD_CR251, on ? on251 : 0x2f);
    1034             : 
    1035           0 :         return 0;
    1036             : }
    1037             : 
    1038             : int
    1039           0 : zyd_al2230_set_channel(struct zyd_rf *rf, uint8_t chan)
    1040             : {
    1041           0 :         struct zyd_softc *sc = rf->rf_sc;
    1042             :         static const struct {
    1043             :                 uint32_t        r1, r2, r3;
    1044             :         } rfprog[] = ZYD_AL2230_CHANTABLE;
    1045             : 
    1046           0 :         (void)zyd_rfwrite(sc, rfprog[chan - 1].r1);
    1047           0 :         (void)zyd_rfwrite(sc, rfprog[chan - 1].r2);
    1048           0 :         (void)zyd_rfwrite(sc, rfprog[chan - 1].r3);
    1049             : 
    1050           0 :         (void)zyd_write16(sc, ZYD_CR138, 0x28);
    1051           0 :         (void)zyd_write16(sc, ZYD_CR203, 0x06);
    1052             : 
    1053           0 :         return 0;
    1054             : }
    1055             : 
    1056             : /*
    1057             :  * AL7230B RF methods.
    1058             :  */
    1059             : int
    1060           0 : zyd_al7230B_init(struct zyd_rf *rf)
    1061             : {
    1062           0 :         struct zyd_softc *sc = rf->rf_sc;
    1063             :         static const struct zyd_phy_pair phyini_1[] = ZYD_AL7230B_PHY_1;
    1064             :         static const struct zyd_phy_pair phyini_2[] = ZYD_AL7230B_PHY_2;
    1065             :         static const struct zyd_phy_pair phyini_3[] = ZYD_AL7230B_PHY_3;
    1066             :         static const uint32_t rfini_1[] = ZYD_AL7230B_RF_1;
    1067             :         static const uint32_t rfini_2[] = ZYD_AL7230B_RF_2;
    1068             :         int i, error;
    1069             : 
    1070             :         /* for AL7230B, PHY and RF need to be initialized in "phases" */
    1071             : 
    1072             :         /* init RF-dependent PHY registers, part one */
    1073           0 :         for (i = 0; i < nitems(phyini_1); i++) {
    1074           0 :                 error = zyd_write16(sc, phyini_1[i].reg, phyini_1[i].val);
    1075           0 :                 if (error != 0)
    1076           0 :                         return error;
    1077             :         }
    1078             :         /* init AL7230B radio, part one */
    1079           0 :         for (i = 0; i < nitems(rfini_1); i++) {
    1080           0 :                 if ((error = zyd_rfwrite(sc, rfini_1[i])) != 0)
    1081           0 :                         return error;
    1082             :         }
    1083             :         /* init RF-dependent PHY registers, part two */
    1084           0 :         for (i = 0; i < nitems(phyini_2); i++) {
    1085           0 :                 error = zyd_write16(sc, phyini_2[i].reg, phyini_2[i].val);
    1086           0 :                 if (error != 0)
    1087           0 :                         return error;
    1088             :         }
    1089             :         /* init AL7230B radio, part two */
    1090           0 :         for (i = 0; i < nitems(rfini_2); i++) {
    1091           0 :                 if ((error = zyd_rfwrite(sc, rfini_2[i])) != 0)
    1092           0 :                         return error;
    1093             :         }
    1094             :         /* init RF-dependent PHY registers, part three */
    1095           0 :         for (i = 0; i < nitems(phyini_3); i++) {
    1096           0 :                 error = zyd_write16(sc, phyini_3[i].reg, phyini_3[i].val);
    1097           0 :                 if (error != 0)
    1098           0 :                         return error;
    1099             :         }
    1100             : 
    1101           0 :         return 0;
    1102           0 : }
    1103             : 
    1104             : int
    1105           0 : zyd_al7230B_switch_radio(struct zyd_rf *rf, int on)
    1106             : {
    1107           0 :         struct zyd_softc *sc = rf->rf_sc;
    1108             : 
    1109           0 :         (void)zyd_write16(sc, ZYD_CR11,  on ? 0x00 : 0x04);
    1110           0 :         (void)zyd_write16(sc, ZYD_CR251, on ? 0x3f : 0x2f);
    1111             : 
    1112           0 :         return 0;
    1113             : }
    1114             : 
    1115             : int
    1116           0 : zyd_al7230B_set_channel(struct zyd_rf *rf, uint8_t chan)
    1117             : {
    1118           0 :         struct zyd_softc *sc = rf->rf_sc;
    1119             :         static const struct {
    1120             :                 uint32_t        r1, r2;
    1121             :         } rfprog[] = ZYD_AL7230B_CHANTABLE;
    1122             :         static const uint32_t rfsc[] = ZYD_AL7230B_RF_SETCHANNEL;
    1123             :         int i, error;
    1124             : 
    1125           0 :         (void)zyd_write16(sc, ZYD_CR240, 0x57);
    1126           0 :         (void)zyd_write16(sc, ZYD_CR251, 0x2f);
    1127             : 
    1128           0 :         for (i = 0; i < nitems(rfsc); i++) {
    1129           0 :                 if ((error = zyd_rfwrite(sc, rfsc[i])) != 0)
    1130           0 :                         return error;
    1131             :         }
    1132             : 
    1133           0 :         (void)zyd_write16(sc, ZYD_CR128, 0x14);
    1134           0 :         (void)zyd_write16(sc, ZYD_CR129, 0x12);
    1135           0 :         (void)zyd_write16(sc, ZYD_CR130, 0x10);
    1136           0 :         (void)zyd_write16(sc, ZYD_CR38,  0x38);
    1137           0 :         (void)zyd_write16(sc, ZYD_CR136, 0xdf);
    1138             : 
    1139           0 :         (void)zyd_rfwrite(sc, rfprog[chan - 1].r1);
    1140           0 :         (void)zyd_rfwrite(sc, rfprog[chan - 1].r2);
    1141           0 :         (void)zyd_rfwrite(sc, 0x3c9000);
    1142             : 
    1143           0 :         (void)zyd_write16(sc, ZYD_CR251, 0x3f);
    1144           0 :         (void)zyd_write16(sc, ZYD_CR203, 0x06);
    1145           0 :         (void)zyd_write16(sc, ZYD_CR240, 0x08);
    1146             : 
    1147           0 :         return 0;
    1148           0 : }
    1149             : 
    1150             : /*
    1151             :  * AL2210 RF methods.
    1152             :  */
    1153             : int
    1154           0 : zyd_al2210_init(struct zyd_rf *rf)
    1155             : {
    1156           0 :         struct zyd_softc *sc = rf->rf_sc;
    1157             :         static const struct zyd_phy_pair phyini[] = ZYD_AL2210_PHY;
    1158             :         static const uint32_t rfini[] = ZYD_AL2210_RF;
    1159           0 :         uint32_t tmp;
    1160             :         int i, error;
    1161             : 
    1162           0 :         (void)zyd_write32(sc, ZYD_CR18, 2);
    1163             : 
    1164             :         /* init RF-dependent PHY registers */
    1165           0 :         for (i = 0; i < nitems(phyini); i++) {
    1166           0 :                 error = zyd_write16(sc, phyini[i].reg, phyini[i].val);
    1167           0 :                 if (error != 0)
    1168           0 :                         return error;
    1169             :         }
    1170             :         /* init AL2210 radio */
    1171           0 :         for (i = 0; i < nitems(rfini); i++) {
    1172           0 :                 if ((error = zyd_rfwrite(sc, rfini[i])) != 0)
    1173           0 :                         return error;
    1174             :         }
    1175           0 :         (void)zyd_write16(sc, ZYD_CR47, 0x1e);
    1176           0 :         (void)zyd_read32(sc, ZYD_CR_RADIO_PD, &tmp);
    1177           0 :         (void)zyd_write32(sc, ZYD_CR_RADIO_PD, tmp & ~1);
    1178           0 :         (void)zyd_write32(sc, ZYD_CR_RADIO_PD, tmp | 1);
    1179           0 :         (void)zyd_write32(sc, ZYD_CR_RFCFG, 0x05);
    1180           0 :         (void)zyd_write32(sc, ZYD_CR_RFCFG, 0x00);
    1181           0 :         (void)zyd_write16(sc, ZYD_CR47, 0x1e);
    1182           0 :         (void)zyd_write32(sc, ZYD_CR18, 3);
    1183             : 
    1184           0 :         return 0;
    1185           0 : }
    1186             : 
    1187             : int
    1188           0 : zyd_al2210_switch_radio(struct zyd_rf *rf, int on)
    1189             : {
    1190             :         /* vendor driver does nothing for this RF chip */
    1191             : 
    1192           0 :         return 0;
    1193             : }
    1194             : 
    1195             : int
    1196           0 : zyd_al2210_set_channel(struct zyd_rf *rf, uint8_t chan)
    1197             : {
    1198           0 :         struct zyd_softc *sc = rf->rf_sc;
    1199             :         static const uint32_t rfprog[] = ZYD_AL2210_CHANTABLE;
    1200           0 :         uint32_t tmp;
    1201             : 
    1202           0 :         (void)zyd_write32(sc, ZYD_CR18, 2);
    1203           0 :         (void)zyd_write16(sc, ZYD_CR47, 0x1e);
    1204           0 :         (void)zyd_read32(sc, ZYD_CR_RADIO_PD, &tmp);
    1205           0 :         (void)zyd_write32(sc, ZYD_CR_RADIO_PD, tmp & ~1);
    1206           0 :         (void)zyd_write32(sc, ZYD_CR_RADIO_PD, tmp | 1);
    1207           0 :         (void)zyd_write32(sc, ZYD_CR_RFCFG, 0x05);
    1208             : 
    1209           0 :         (void)zyd_write32(sc, ZYD_CR_RFCFG, 0x00);
    1210           0 :         (void)zyd_write16(sc, ZYD_CR47, 0x1e);
    1211             : 
    1212             :         /* actually set the channel */
    1213           0 :         (void)zyd_rfwrite(sc, rfprog[chan - 1]);
    1214             : 
    1215           0 :         (void)zyd_write32(sc, ZYD_CR18, 3);
    1216             : 
    1217           0 :         return 0;
    1218           0 : }
    1219             : 
    1220             : /*
    1221             :  * GCT RF methods.
    1222             :  */
    1223             : int
    1224           0 : zyd_gct_init(struct zyd_rf *rf)
    1225             : {
    1226           0 :         struct zyd_softc *sc = rf->rf_sc;
    1227             :         static const struct zyd_phy_pair phyini[] = ZYD_GCT_PHY;
    1228             :         static const uint32_t rfini[] = ZYD_GCT_RF;
    1229             :         int i, error;
    1230             : 
    1231             :         /* init RF-dependent PHY registers */
    1232           0 :         for (i = 0; i < nitems(phyini); i++) {
    1233           0 :                 error = zyd_write16(sc, phyini[i].reg, phyini[i].val);
    1234           0 :                 if (error != 0)
    1235           0 :                         return error;
    1236             :         }
    1237             :         /* init cgt radio */
    1238           0 :         for (i = 0; i < nitems(rfini); i++) {
    1239           0 :                 if ((error = zyd_rfwrite(sc, rfini[i])) != 0)
    1240           0 :                         return error;
    1241             :         }
    1242           0 :         return 0;
    1243           0 : }
    1244             : 
    1245             : int
    1246           0 : zyd_gct_switch_radio(struct zyd_rf *rf, int on)
    1247             : {
    1248             :         /* vendor driver does nothing for this RF chip */
    1249             : 
    1250           0 :         return 0;
    1251             : }
    1252             : 
    1253             : int
    1254           0 : zyd_gct_set_channel(struct zyd_rf *rf, uint8_t chan)
    1255             : {
    1256           0 :         struct zyd_softc *sc = rf->rf_sc;
    1257             :         static const uint32_t rfprog[] = ZYD_GCT_CHANTABLE;
    1258             : 
    1259           0 :         (void)zyd_rfwrite(sc, 0x1c0000);
    1260           0 :         (void)zyd_rfwrite(sc, rfprog[chan - 1]);
    1261           0 :         (void)zyd_rfwrite(sc, 0x1c0008);
    1262             : 
    1263           0 :         return 0;
    1264             : }
    1265             : 
    1266             : /*
    1267             :  * Maxim RF methods.
    1268             :  */
    1269             : int
    1270           0 : zyd_maxim_init(struct zyd_rf *rf)
    1271             : {
    1272           0 :         struct zyd_softc *sc = rf->rf_sc;
    1273             :         static const struct zyd_phy_pair phyini[] = ZYD_MAXIM_PHY;
    1274             :         static const uint32_t rfini[] = ZYD_MAXIM_RF;
    1275           0 :         uint16_t tmp;
    1276             :         int i, error;
    1277             : 
    1278             :         /* init RF-dependent PHY registers */
    1279           0 :         for (i = 0; i < nitems(phyini); i++) {
    1280           0 :                 error = zyd_write16(sc, phyini[i].reg, phyini[i].val);
    1281           0 :                 if (error != 0)
    1282           0 :                         return error;
    1283             :         }
    1284           0 :         (void)zyd_read16(sc, ZYD_CR203, &tmp);
    1285           0 :         (void)zyd_write16(sc, ZYD_CR203, tmp & ~(1 << 4));
    1286             : 
    1287             :         /* init maxim radio */
    1288           0 :         for (i = 0; i < nitems(rfini); i++) {
    1289           0 :                 if ((error = zyd_rfwrite(sc, rfini[i])) != 0)
    1290           0 :                         return error;
    1291             :         }
    1292           0 :         (void)zyd_read16(sc, ZYD_CR203, &tmp);
    1293           0 :         (void)zyd_write16(sc, ZYD_CR203, tmp | (1 << 4));
    1294             : 
    1295           0 :         return 0;
    1296           0 : }
    1297             : 
    1298             : int
    1299           0 : zyd_maxim_switch_radio(struct zyd_rf *rf, int on)
    1300             : {
    1301             :         /* vendor driver does nothing for this RF chip */
    1302             : 
    1303           0 :         return 0;
    1304             : }
    1305             : 
    1306             : int
    1307           0 : zyd_maxim_set_channel(struct zyd_rf *rf, uint8_t chan)
    1308             : {
    1309           0 :         struct zyd_softc *sc = rf->rf_sc;
    1310             :         static const struct zyd_phy_pair phyini[] = ZYD_MAXIM_PHY;
    1311             :         static const uint32_t rfini[] = ZYD_MAXIM_RF;
    1312             :         static const struct {
    1313             :                 uint32_t        r1, r2;
    1314             :         } rfprog[] = ZYD_MAXIM_CHANTABLE;
    1315           0 :         uint16_t tmp;
    1316             :         int i, error;
    1317             : 
    1318             :         /*
    1319             :          * Do the same as we do when initializing it, except for the channel
    1320             :          * values coming from the two channel tables.
    1321             :          */
    1322             : 
    1323             :         /* init RF-dependent PHY registers */
    1324           0 :         for (i = 0; i < nitems(phyini); i++) {
    1325           0 :                 error = zyd_write16(sc, phyini[i].reg, phyini[i].val);
    1326           0 :                 if (error != 0)
    1327           0 :                         return error;
    1328             :         }
    1329           0 :         (void)zyd_read16(sc, ZYD_CR203, &tmp);
    1330           0 :         (void)zyd_write16(sc, ZYD_CR203, tmp & ~(1 << 4));
    1331             : 
    1332             :         /* first two values taken from the chantables */
    1333           0 :         (void)zyd_rfwrite(sc, rfprog[chan - 1].r1);
    1334           0 :         (void)zyd_rfwrite(sc, rfprog[chan - 1].r2);
    1335             : 
    1336             :         /* init maxim radio - skipping the two first values */
    1337           0 :         for (i = 2; i < nitems(rfini); i++) {
    1338           0 :                 if ((error = zyd_rfwrite(sc, rfini[i])) != 0)
    1339           0 :                         return error;
    1340             :         }
    1341           0 :         (void)zyd_read16(sc, ZYD_CR203, &tmp);
    1342           0 :         (void)zyd_write16(sc, ZYD_CR203, tmp | (1 << 4));
    1343             : 
    1344           0 :         return 0;
    1345           0 : }
    1346             : 
    1347             : /*
    1348             :  * Maxim2 RF methods.
    1349             :  */
    1350             : int
    1351           0 : zyd_maxim2_init(struct zyd_rf *rf)
    1352             : {
    1353           0 :         struct zyd_softc *sc = rf->rf_sc;
    1354             :         static const struct zyd_phy_pair phyini[] = ZYD_MAXIM2_PHY;
    1355             :         static const uint32_t rfini[] = ZYD_MAXIM2_RF;
    1356           0 :         uint16_t tmp;
    1357             :         int i, error;
    1358             : 
    1359             :         /* init RF-dependent PHY registers */
    1360           0 :         for (i = 0; i < nitems(phyini); i++) {
    1361           0 :                 error = zyd_write16(sc, phyini[i].reg, phyini[i].val);
    1362           0 :                 if (error != 0)
    1363           0 :                         return error;
    1364             :         }
    1365           0 :         (void)zyd_read16(sc, ZYD_CR203, &tmp);
    1366           0 :         (void)zyd_write16(sc, ZYD_CR203, tmp & ~(1 << 4));
    1367             : 
    1368             :         /* init maxim2 radio */
    1369           0 :         for (i = 0; i < nitems(rfini); i++) {
    1370           0 :                 if ((error = zyd_rfwrite(sc, rfini[i])) != 0)
    1371           0 :                         return error;
    1372             :         }
    1373           0 :         (void)zyd_read16(sc, ZYD_CR203, &tmp);
    1374           0 :         (void)zyd_write16(sc, ZYD_CR203, tmp | (1 << 4));
    1375             : 
    1376           0 :         return 0;
    1377           0 : }
    1378             : 
    1379             : int
    1380           0 : zyd_maxim2_switch_radio(struct zyd_rf *rf, int on)
    1381             : {
    1382             :         /* vendor driver does nothing for this RF chip */
    1383             : 
    1384           0 :         return 0;
    1385             : }
    1386             : 
    1387             : int
    1388           0 : zyd_maxim2_set_channel(struct zyd_rf *rf, uint8_t chan)
    1389             : {
    1390           0 :         struct zyd_softc *sc = rf->rf_sc;
    1391             :         static const struct zyd_phy_pair phyini[] = ZYD_MAXIM2_PHY;
    1392             :         static const uint32_t rfini[] = ZYD_MAXIM2_RF;
    1393             :         static const struct {
    1394             :                 uint32_t        r1, r2;
    1395             :         } rfprog[] = ZYD_MAXIM2_CHANTABLE;
    1396           0 :         uint16_t tmp;
    1397             :         int i, error;
    1398             : 
    1399             :         /*
    1400             :          * Do the same as we do when initializing it, except for the channel
    1401             :          * values coming from the two channel tables.
    1402             :          */
    1403             : 
    1404             :         /* init RF-dependent PHY registers */
    1405           0 :         for (i = 0; i < nitems(phyini); i++) {
    1406           0 :                 error = zyd_write16(sc, phyini[i].reg, phyini[i].val);
    1407           0 :                 if (error != 0)
    1408           0 :                         return error;
    1409             :         }
    1410           0 :         (void)zyd_read16(sc, ZYD_CR203, &tmp);
    1411           0 :         (void)zyd_write16(sc, ZYD_CR203, tmp & ~(1 << 4));
    1412             : 
    1413             :         /* first two values taken from the chantables */
    1414           0 :         (void)zyd_rfwrite(sc, rfprog[chan - 1].r1);
    1415           0 :         (void)zyd_rfwrite(sc, rfprog[chan - 1].r2);
    1416             : 
    1417             :         /* init maxim2 radio - skipping the two first values */
    1418           0 :         for (i = 2; i < nitems(rfini); i++) {
    1419           0 :                 if ((error = zyd_rfwrite(sc, rfini[i])) != 0)
    1420           0 :                         return error;
    1421             :         }
    1422           0 :         (void)zyd_read16(sc, ZYD_CR203, &tmp);
    1423           0 :         (void)zyd_write16(sc, ZYD_CR203, tmp | (1 << 4));
    1424             : 
    1425           0 :         return 0;
    1426           0 : }
    1427             : 
    1428             : int
    1429           0 : zyd_rf_attach(struct zyd_softc *sc, uint8_t type)
    1430             : {
    1431           0 :         struct zyd_rf *rf = &sc->sc_rf;
    1432             : 
    1433           0 :         rf->rf_sc = sc;
    1434             : 
    1435           0 :         switch (type) {
    1436             :         case ZYD_RF_RFMD:
    1437           0 :                 rf->init         = zyd_rfmd_init;
    1438           0 :                 rf->switch_radio = zyd_rfmd_switch_radio;
    1439           0 :                 rf->set_channel  = zyd_rfmd_set_channel;
    1440           0 :                 rf->width        = 24;       /* 24-bit RF values */
    1441           0 :                 break;
    1442             :         case ZYD_RF_AL2230:
    1443             :         case ZYD_RF_AL2230S:
    1444           0 :                 if (sc->mac_rev == ZYD_ZD1211B)
    1445           0 :                         rf->init = zyd_al2230_init_b;
    1446             :                 else
    1447           0 :                         rf->init = zyd_al2230_init;
    1448           0 :                 rf->switch_radio = zyd_al2230_switch_radio;
    1449           0 :                 rf->set_channel  = zyd_al2230_set_channel;
    1450           0 :                 rf->width        = 24;       /* 24-bit RF values */
    1451           0 :                 break;
    1452             :         case ZYD_RF_AL7230B:
    1453           0 :                 rf->init         = zyd_al7230B_init;
    1454           0 :                 rf->switch_radio = zyd_al7230B_switch_radio;
    1455           0 :                 rf->set_channel  = zyd_al7230B_set_channel;
    1456           0 :                 rf->width        = 24;       /* 24-bit RF values */
    1457           0 :                 break;
    1458             :         case ZYD_RF_AL2210:
    1459           0 :                 rf->init         = zyd_al2210_init;
    1460           0 :                 rf->switch_radio = zyd_al2210_switch_radio;
    1461           0 :                 rf->set_channel  = zyd_al2210_set_channel;
    1462           0 :                 rf->width        = 24;       /* 24-bit RF values */
    1463           0 :                 break;
    1464             :         case ZYD_RF_GCT:
    1465           0 :                 rf->init         = zyd_gct_init;
    1466           0 :                 rf->switch_radio = zyd_gct_switch_radio;
    1467           0 :                 rf->set_channel  = zyd_gct_set_channel;
    1468           0 :                 rf->width        = 21;       /* 21-bit RF values */
    1469           0 :                 break;
    1470             :         case ZYD_RF_MAXIM_NEW:
    1471           0 :                 rf->init         = zyd_maxim_init;
    1472           0 :                 rf->switch_radio = zyd_maxim_switch_radio;
    1473           0 :                 rf->set_channel  = zyd_maxim_set_channel;
    1474           0 :                 rf->width        = 18;       /* 18-bit RF values */
    1475           0 :                 break;
    1476             :         case ZYD_RF_MAXIM_NEW2:
    1477           0 :                 rf->init         = zyd_maxim2_init;
    1478           0 :                 rf->switch_radio = zyd_maxim2_switch_radio;
    1479           0 :                 rf->set_channel  = zyd_maxim2_set_channel;
    1480           0 :                 rf->width        = 18;       /* 18-bit RF values */
    1481           0 :                 break;
    1482             :         default:
    1483           0 :                 printf("%s: sorry, radio \"%s\" is not supported yet\n",
    1484           0 :                     sc->sc_dev.dv_xname, zyd_rf_name(type));
    1485           0 :                 return EINVAL;
    1486             :         }
    1487           0 :         return 0;
    1488           0 : }
    1489             : 
    1490             : const char *
    1491           0 : zyd_rf_name(uint8_t type)
    1492             : {
    1493             :         static const char * const zyd_rfs[] = {
    1494             :                 "unknown", "unknown", "UW2451",   "UCHIP",     "AL2230",
    1495             :                 "AL7230B", "THETA",   "AL2210",   "MAXIM_NEW", "GCT",
    1496             :                 "AL2230S", "RALINK",  "INTERSIL", "RFMD",      "MAXIM_NEW2",
    1497             :                 "PHILIPS"
    1498             :         };
    1499           0 :         return zyd_rfs[(type > 15) ? 0 : type];
    1500             : }
    1501             : 
    1502             : int
    1503           0 : zyd_hw_init(struct zyd_softc *sc)
    1504             : {
    1505           0 :         struct zyd_rf *rf = &sc->sc_rf;
    1506             :         const struct zyd_phy_pair *phyp;
    1507           0 :         uint32_t tmp;
    1508             :         int error;
    1509             : 
    1510             :         /* specify that the plug and play is finished */
    1511           0 :         (void)zyd_write32(sc, ZYD_MAC_AFTER_PNP, 1);
    1512             : 
    1513           0 :         (void)zyd_read16(sc, ZYD_FIRMWARE_BASE_ADDR, &sc->fwbase);
    1514             :         DPRINTF(("firmware base address=0x%04x\n", sc->fwbase));
    1515             : 
    1516             :         /* retrieve firmware revision number */
    1517           0 :         (void)zyd_read16(sc, sc->fwbase + ZYD_FW_FIRMWARE_REV, &sc->fw_rev);
    1518             : 
    1519           0 :         (void)zyd_write32(sc, ZYD_CR_GPI_EN, 0);
    1520           0 :         (void)zyd_write32(sc, ZYD_MAC_CONT_WIN_LIMIT, 0x7f043f);
    1521             : 
    1522             :         /* disable interrupts */
    1523           0 :         (void)zyd_write32(sc, ZYD_CR_INTERRUPT, 0);
    1524             : 
    1525             :         /* PHY init */
    1526           0 :         zyd_lock_phy(sc);
    1527           0 :         phyp = (sc->mac_rev == ZYD_ZD1211B) ? zyd_def_phyB : zyd_def_phy;
    1528           0 :         for (; phyp->reg != 0; phyp++) {
    1529           0 :                 if ((error = zyd_write16(sc, phyp->reg, phyp->val)) != 0)
    1530             :                         goto fail;
    1531             :         }
    1532           0 :         if (sc->fix_cr157) {
    1533           0 :                 if (zyd_read32(sc, ZYD_EEPROM_PHY_REG, &tmp) == 0)
    1534           0 :                         (void)zyd_write32(sc, ZYD_CR157, tmp >> 8);
    1535             :         }
    1536           0 :         zyd_unlock_phy(sc);
    1537             : 
    1538             :         /* HMAC init */
    1539           0 :         zyd_write32(sc, ZYD_MAC_ACK_EXT, 0x00000020);
    1540           0 :         zyd_write32(sc, ZYD_CR_ADDA_MBIAS_WT, 0x30000808);
    1541             : 
    1542           0 :         if (sc->mac_rev == ZYD_ZD1211) {
    1543           0 :                 zyd_write32(sc, ZYD_MAC_RETRY, 0x00000002);
    1544           0 :         } else {
    1545           0 :                 zyd_write32(sc, ZYD_MACB_MAX_RETRY, 0x02020202);
    1546           0 :                 zyd_write32(sc, ZYD_MACB_TXPWR_CTL4, 0x007f003f);
    1547           0 :                 zyd_write32(sc, ZYD_MACB_TXPWR_CTL3, 0x007f003f);
    1548           0 :                 zyd_write32(sc, ZYD_MACB_TXPWR_CTL2, 0x003f001f);
    1549           0 :                 zyd_write32(sc, ZYD_MACB_TXPWR_CTL1, 0x001f000f);
    1550           0 :                 zyd_write32(sc, ZYD_MACB_AIFS_CTL1, 0x00280028);
    1551           0 :                 zyd_write32(sc, ZYD_MACB_AIFS_CTL2, 0x008C003c);
    1552           0 :                 zyd_write32(sc, ZYD_MACB_TXOP, 0x01800824);
    1553             :         }
    1554             : 
    1555           0 :         zyd_write32(sc, ZYD_MAC_SNIFFER, 0x00000000);
    1556           0 :         zyd_write32(sc, ZYD_MAC_RXFILTER, 0x00000000);
    1557           0 :         zyd_write32(sc, ZYD_MAC_GHTBL, 0x00000000);
    1558           0 :         zyd_write32(sc, ZYD_MAC_GHTBH, 0x80000000);
    1559           0 :         zyd_write32(sc, ZYD_MAC_MISC, 0x000000a4);
    1560           0 :         zyd_write32(sc, ZYD_CR_ADDA_PWR_DWN, 0x0000007f);
    1561           0 :         zyd_write32(sc, ZYD_MAC_BCNCFG, 0x00f00401);
    1562           0 :         zyd_write32(sc, ZYD_MAC_PHY_DELAY2, 0x00000000);
    1563           0 :         zyd_write32(sc, ZYD_MAC_ACK_EXT, 0x00000080);
    1564           0 :         zyd_write32(sc, ZYD_CR_ADDA_PWR_DWN, 0x00000000);
    1565           0 :         zyd_write32(sc, ZYD_MAC_SIFS_ACK_TIME, 0x00000100);
    1566           0 :         zyd_write32(sc, ZYD_MAC_DIFS_EIFS_SIFS, 0x0547c032);
    1567           0 :         zyd_write32(sc, ZYD_CR_RX_PE_DELAY, 0x00000070);
    1568           0 :         zyd_write32(sc, ZYD_CR_PS_CTRL, 0x10000000);
    1569           0 :         zyd_write32(sc, ZYD_MAC_RTSCTSRATE, 0x02030203);
    1570           0 :         zyd_write32(sc, ZYD_MAC_RX_THRESHOLD, 0x000c0640);
    1571           0 :         zyd_write32(sc, ZYD_MAC_BACKOFF_PROTECT, 0x00000114);
    1572             : 
    1573             :         /* RF chip init */
    1574           0 :         zyd_lock_phy(sc);
    1575           0 :         error = (*rf->init)(rf);
    1576           0 :         zyd_unlock_phy(sc);
    1577           0 :         if (error != 0) {
    1578           0 :                 printf("%s: radio initialization failed\n",
    1579           0 :                     sc->sc_dev.dv_xname);
    1580           0 :                 goto fail;
    1581             :         }
    1582             : 
    1583             :         /* init beacon interval to 100ms */
    1584           0 :         if ((error = zyd_set_beacon_interval(sc, 100)) != 0)
    1585           0 :                 goto fail;
    1586             : 
    1587           0 : fail:   return error;
    1588           0 : }
    1589             : 
    1590             : int
    1591           0 : zyd_read_eeprom(struct zyd_softc *sc)
    1592             : {
    1593           0 :         struct ieee80211com *ic = &sc->sc_ic;
    1594           0 :         uint32_t tmp;
    1595           0 :         uint16_t val;
    1596             :         int i;
    1597             : 
    1598             :         /* read MAC address */
    1599           0 :         (void)zyd_read32(sc, ZYD_EEPROM_MAC_ADDR_P1, &tmp);
    1600           0 :         ic->ic_myaddr[0] = tmp & 0xff;
    1601           0 :         ic->ic_myaddr[1] = tmp >>  8;
    1602           0 :         ic->ic_myaddr[2] = tmp >> 16;
    1603           0 :         ic->ic_myaddr[3] = tmp >> 24;
    1604           0 :         (void)zyd_read32(sc, ZYD_EEPROM_MAC_ADDR_P2, &tmp);
    1605           0 :         ic->ic_myaddr[4] = tmp & 0xff;
    1606           0 :         ic->ic_myaddr[5] = tmp >>  8;
    1607             : 
    1608           0 :         (void)zyd_read32(sc, ZYD_EEPROM_POD, &tmp);
    1609           0 :         sc->rf_rev    = tmp & 0x0f;
    1610           0 :         sc->fix_cr47  = (tmp >> 8 ) & 0x01;
    1611           0 :         sc->fix_cr157 = (tmp >> 13) & 0x01;
    1612           0 :         sc->pa_rev    = (tmp >> 16) & 0x0f;
    1613             : 
    1614             :         /* read regulatory domain (currently unused) */
    1615           0 :         (void)zyd_read32(sc, ZYD_EEPROM_SUBID, &tmp);
    1616           0 :         sc->regdomain = tmp >> 16;
    1617             :         DPRINTF(("regulatory domain %x\n", sc->regdomain));
    1618             : 
    1619             :         /* read Tx power calibration tables */
    1620           0 :         for (i = 0; i < 7; i++) {
    1621           0 :                 (void)zyd_read16(sc, ZYD_EEPROM_PWR_CAL + i, &val);
    1622           0 :                 sc->pwr_cal[i * 2] = val >> 8;
    1623           0 :                 sc->pwr_cal[i * 2 + 1] = val & 0xff;
    1624             : 
    1625           0 :                 (void)zyd_read16(sc, ZYD_EEPROM_PWR_INT + i, &val);
    1626           0 :                 sc->pwr_int[i * 2] = val >> 8;
    1627           0 :                 sc->pwr_int[i * 2 + 1] = val & 0xff;
    1628             : 
    1629           0 :                 (void)zyd_read16(sc, ZYD_EEPROM_36M_CAL + i, &val);
    1630           0 :                 sc->ofdm36_cal[i * 2] = val >> 8;
    1631           0 :                 sc->ofdm36_cal[i * 2 + 1] = val & 0xff;
    1632             : 
    1633           0 :                 (void)zyd_read16(sc, ZYD_EEPROM_48M_CAL + i, &val);
    1634           0 :                 sc->ofdm48_cal[i * 2] = val >> 8;
    1635           0 :                 sc->ofdm48_cal[i * 2 + 1] = val & 0xff;
    1636             : 
    1637           0 :                 (void)zyd_read16(sc, ZYD_EEPROM_54M_CAL + i, &val);
    1638           0 :                 sc->ofdm54_cal[i * 2] = val >> 8;
    1639           0 :                 sc->ofdm54_cal[i * 2 + 1] = val & 0xff;
    1640             :         }
    1641           0 :         return 0;
    1642           0 : }
    1643             : 
    1644             : void
    1645           0 : zyd_set_multi(struct zyd_softc *sc)
    1646             : {
    1647           0 :         struct arpcom *ac = &sc->sc_ic.ic_ac;
    1648           0 :         struct ifnet *ifp = &ac->ac_if;
    1649             :         struct ether_multi *enm;
    1650             :         struct ether_multistep step;
    1651             :         uint32_t lo, hi;
    1652             :         uint8_t bit;
    1653             : 
    1654           0 :         if (ac->ac_multirangecnt > 0)
    1655           0 :                 ifp->if_flags |= IFF_ALLMULTI;
    1656             : 
    1657           0 :         if ((ifp->if_flags & (IFF_ALLMULTI | IFF_PROMISC)) != 0) {
    1658             :                 lo = hi = 0xffffffff;
    1659           0 :                 goto done;
    1660             :         }
    1661             :         lo = hi = 0;
    1662           0 :         ETHER_FIRST_MULTI(step, ac, enm);
    1663           0 :         while (enm != NULL) {
    1664           0 :                 bit = enm->enm_addrlo[5] >> 2;
    1665           0 :                 if (bit < 32)
    1666           0 :                         lo |= 1 << bit;
    1667             :                 else
    1668           0 :                         hi |= 1 << (bit - 32);
    1669           0 :                 ETHER_NEXT_MULTI(step, enm);
    1670             :         }
    1671             : 
    1672             : done:
    1673           0 :         hi |= 1U << 31;   /* make sure the broadcast bit is set */
    1674           0 :         zyd_write32(sc, ZYD_MAC_GHTBL, lo);
    1675           0 :         zyd_write32(sc, ZYD_MAC_GHTBH, hi);
    1676           0 : }
    1677             : 
    1678             : void
    1679           0 : zyd_set_macaddr(struct zyd_softc *sc, const uint8_t *addr)
    1680             : {
    1681             :         uint32_t tmp;
    1682             : 
    1683           0 :         tmp = addr[3] << 24 | addr[2] << 16 | addr[1] << 8 | addr[0];
    1684           0 :         (void)zyd_write32(sc, ZYD_MAC_MACADRL, tmp);
    1685             : 
    1686           0 :         tmp = addr[5] << 8 | addr[4];
    1687           0 :         (void)zyd_write32(sc, ZYD_MAC_MACADRH, tmp);
    1688           0 : }
    1689             : 
    1690             : void
    1691           0 : zyd_set_bssid(struct zyd_softc *sc, const uint8_t *addr)
    1692             : {
    1693             :         uint32_t tmp;
    1694             : 
    1695           0 :         tmp = addr[3] << 24 | addr[2] << 16 | addr[1] << 8 | addr[0];
    1696           0 :         (void)zyd_write32(sc, ZYD_MAC_BSSADRL, tmp);
    1697             : 
    1698           0 :         tmp = addr[5] << 8 | addr[4];
    1699           0 :         (void)zyd_write32(sc, ZYD_MAC_BSSADRH, tmp);
    1700           0 : }
    1701             : 
    1702             : int
    1703           0 : zyd_switch_radio(struct zyd_softc *sc, int on)
    1704             : {
    1705           0 :         struct zyd_rf *rf = &sc->sc_rf;
    1706             :         int error;
    1707             : 
    1708           0 :         zyd_lock_phy(sc);
    1709           0 :         error = (*rf->switch_radio)(rf, on);
    1710           0 :         zyd_unlock_phy(sc);
    1711             : 
    1712           0 :         return error;
    1713             : }
    1714             : 
    1715             : void
    1716           0 : zyd_set_led(struct zyd_softc *sc, int which, int on)
    1717             : {
    1718           0 :         uint32_t tmp;
    1719             : 
    1720           0 :         (void)zyd_read32(sc, ZYD_MAC_TX_PE_CONTROL, &tmp);
    1721           0 :         tmp &= ~which;
    1722           0 :         if (on)
    1723           0 :                 tmp |= which;
    1724           0 :         (void)zyd_write32(sc, ZYD_MAC_TX_PE_CONTROL, tmp);
    1725           0 : }
    1726             : 
    1727             : int
    1728           0 : zyd_set_rxfilter(struct zyd_softc *sc)
    1729             : {
    1730             :         uint32_t rxfilter;
    1731             : 
    1732           0 :         switch (sc->sc_ic.ic_opmode) {
    1733             :         case IEEE80211_M_STA:
    1734             :                 rxfilter = ZYD_FILTER_BSS;
    1735           0 :                 break;
    1736             : #ifndef IEEE80211_STA_ONLY
    1737             :         case IEEE80211_M_IBSS:
    1738             :         case IEEE80211_M_HOSTAP:
    1739             :                 rxfilter = ZYD_FILTER_HOSTAP;
    1740           0 :                 break;
    1741             : #endif
    1742             :         case IEEE80211_M_MONITOR:
    1743             :                 rxfilter = ZYD_FILTER_MONITOR;
    1744           0 :                 break;
    1745             :         default:
    1746             :                 /* should not get there */
    1747           0 :                 return EINVAL;
    1748             :         }
    1749           0 :         return zyd_write32(sc, ZYD_MAC_RXFILTER, rxfilter);
    1750           0 : }
    1751             : 
    1752             : void
    1753           0 : zyd_set_chan(struct zyd_softc *sc, struct ieee80211_channel *c)
    1754             : {
    1755           0 :         struct ieee80211com *ic = &sc->sc_ic;
    1756           0 :         struct zyd_rf *rf = &sc->sc_rf;
    1757           0 :         uint32_t tmp;
    1758             :         u_int chan;
    1759             : 
    1760           0 :         chan = ieee80211_chan2ieee(ic, c);
    1761           0 :         if (chan == 0 || chan == IEEE80211_CHAN_ANY)
    1762           0 :                 return;
    1763             : 
    1764           0 :         zyd_lock_phy(sc);
    1765             : 
    1766           0 :         (*rf->set_channel)(rf, chan);
    1767             : 
    1768             :         /* update Tx power */
    1769           0 :         (void)zyd_write16(sc, ZYD_CR31, sc->pwr_int[chan - 1]);
    1770             : 
    1771           0 :         if (sc->mac_rev == ZYD_ZD1211B) {
    1772           0 :                 (void)zyd_write16(sc, ZYD_CR67, sc->ofdm36_cal[chan - 1]);
    1773           0 :                 (void)zyd_write16(sc, ZYD_CR66, sc->ofdm48_cal[chan - 1]);
    1774           0 :                 (void)zyd_write16(sc, ZYD_CR65, sc->ofdm54_cal[chan - 1]);
    1775             : 
    1776           0 :                 (void)zyd_write16(sc, ZYD_CR68, sc->pwr_cal[chan - 1]);
    1777             : 
    1778           0 :                 (void)zyd_write16(sc, ZYD_CR69, 0x28);
    1779           0 :                 (void)zyd_write16(sc, ZYD_CR69, 0x2a);
    1780           0 :         }
    1781             : 
    1782           0 :         if (sc->fix_cr47) {
    1783             :                 /* set CCK baseband gain from EEPROM */
    1784           0 :                 if (zyd_read32(sc, ZYD_EEPROM_PHY_REG, &tmp) == 0)
    1785           0 :                         (void)zyd_write16(sc, ZYD_CR47, tmp & 0xff);
    1786             :         }
    1787             : 
    1788           0 :         (void)zyd_write32(sc, ZYD_CR_CONFIG_PHILIPS, 0);
    1789             : 
    1790           0 :         zyd_unlock_phy(sc);
    1791           0 : }
    1792             : 
    1793             : int
    1794           0 : zyd_set_beacon_interval(struct zyd_softc *sc, int bintval)
    1795             : {
    1796             :         /* XXX this is probably broken.. */
    1797           0 :         (void)zyd_write32(sc, ZYD_CR_ATIM_WND_PERIOD, bintval - 2);
    1798           0 :         (void)zyd_write32(sc, ZYD_CR_PRE_TBTT,        bintval - 1);
    1799           0 :         (void)zyd_write32(sc, ZYD_CR_BCN_INTERVAL,    bintval);
    1800             : 
    1801           0 :         return 0;
    1802             : }
    1803             : 
    1804             : uint8_t
    1805           0 : zyd_plcp_signal(int rate)
    1806             : {
    1807           0 :         switch (rate) {
    1808             :         /* CCK rates (returned values are device-dependent) */
    1809           0 :         case 2:         return 0x0;
    1810           0 :         case 4:         return 0x1;
    1811           0 :         case 11:        return 0x2;
    1812           0 :         case 22:        return 0x3;
    1813             : 
    1814             :         /* OFDM rates (cf IEEE Std 802.11a-1999, pp. 14 Table 80) */
    1815           0 :         case 12:        return 0xb;
    1816           0 :         case 18:        return 0xf;
    1817           0 :         case 24:        return 0xa;
    1818           0 :         case 36:        return 0xe;
    1819           0 :         case 48:        return 0x9;
    1820           0 :         case 72:        return 0xd;
    1821           0 :         case 96:        return 0x8;
    1822           0 :         case 108:       return 0xc;
    1823             : 
    1824             :         /* unsupported rates (should not get there) */
    1825           0 :         default:        return 0xff;
    1826             :         }
    1827           0 : }
    1828             : 
    1829             : void
    1830           0 : zyd_intr(struct usbd_xfer *xfer, void *priv, usbd_status status)
    1831             : {
    1832           0 :         struct zyd_softc *sc = (struct zyd_softc *)priv;
    1833             :         const struct zyd_cmd *cmd;
    1834           0 :         uint32_t len;
    1835             : 
    1836           0 :         if (status != USBD_NORMAL_COMPLETION) {
    1837           0 :                 if (status == USBD_NOT_STARTED || status == USBD_CANCELLED)
    1838           0 :                         return;
    1839             : 
    1840           0 :                 if (status == USBD_STALLED) {
    1841           0 :                         usbd_clear_endpoint_stall_async(
    1842           0 :                             sc->zyd_ep[ZYD_ENDPT_IIN]);
    1843           0 :                 }
    1844           0 :                 return;
    1845             :         }
    1846             : 
    1847           0 :         cmd = (const struct zyd_cmd *)sc->ibuf;
    1848             : 
    1849           0 :         if (letoh16(cmd->code) == ZYD_NOTIF_RETRYSTATUS) {
    1850             :                 struct zyd_notif_retry *retry =
    1851           0 :                     (struct zyd_notif_retry *)cmd->data;
    1852           0 :                 struct ieee80211com *ic = &sc->sc_ic;
    1853           0 :                 struct ifnet *ifp = &ic->ic_if;
    1854             :                 struct ieee80211_node *ni;
    1855             : 
    1856             :                 DPRINTF(("retry intr: rate=0x%x addr=%s count=%d (0x%x)\n",
    1857             :                     letoh16(retry->rate), ether_sprintf(retry->macaddr),
    1858             :                     letoh16(retry->count) & 0xff, letoh16(retry->count)));
    1859             : 
    1860             :                 /*
    1861             :                  * Find the node to which the packet was sent and update its
    1862             :                  * retry statistics.  In BSS mode, this node is the AP we're
    1863             :                  * associated to so no lookup is actually needed.
    1864             :                  */
    1865           0 :                 if (ic->ic_opmode != IEEE80211_M_STA) {
    1866           0 :                         ni = ieee80211_find_node(ic, retry->macaddr);
    1867           0 :                         if (ni == NULL)
    1868           0 :                                 return; /* just ignore */
    1869             :                 } else
    1870           0 :                         ni = ic->ic_bss;
    1871             : 
    1872           0 :                 ((struct zyd_node *)ni)->amn.amn_retrycnt++;
    1873             : 
    1874           0 :                 if (letoh16(retry->count) & 0x100)
    1875           0 :                         ifp->if_oerrors++;   /* too many retries */
    1876             : 
    1877           0 :         } else if (letoh16(cmd->code) == ZYD_NOTIF_IORD) {
    1878           0 :                 if (letoh16(*(uint16_t *)cmd->data) == ZYD_CR_INTERRUPT)
    1879           0 :                         return; /* HMAC interrupt */
    1880             : 
    1881           0 :                 if (!sc->odone) {
    1882             :                         /* copy answer into sc->odata buffer */
    1883           0 :                         usbd_get_xfer_status(xfer, NULL, NULL, &len, NULL);
    1884           0 :                         bcopy(cmd->data, sc->odata, sc->olen);
    1885           0 :                         sc->odone = 1;
    1886           0 :                         wakeup(sc); /* wakeup zyd_cmd_read() */
    1887           0 :                 }
    1888             : 
    1889             :         } else {
    1890           0 :                 printf("%s: unknown notification %x\n", sc->sc_dev.dv_xname,
    1891             :                     letoh16(cmd->code));
    1892             :         }
    1893           0 : }
    1894             : 
    1895             : void
    1896           0 : zyd_rx_data(struct zyd_softc *sc, const uint8_t *buf, uint16_t len)
    1897             : {
    1898           0 :         struct ieee80211com *ic = &sc->sc_ic;
    1899           0 :         struct ifnet *ifp = &ic->ic_if;
    1900             :         struct ieee80211_node *ni;
    1901             :         struct ieee80211_frame *wh;
    1902           0 :         struct ieee80211_rxinfo rxi;
    1903             :         const struct zyd_plcphdr *plcp;
    1904             :         const struct zyd_rx_stat *stat;
    1905             :         struct mbuf *m;
    1906             :         int s;
    1907             : 
    1908           0 :         if (len < ZYD_MIN_FRAGSZ) {
    1909             :                 DPRINTFN(2, ("frame too short (length=%d)\n", len));
    1910           0 :                 ifp->if_ierrors++;
    1911           0 :                 return;
    1912             :         }
    1913             : 
    1914           0 :         plcp = (const struct zyd_plcphdr *)buf;
    1915           0 :         stat = (const struct zyd_rx_stat *)(buf + len - sizeof (*stat));
    1916             : 
    1917           0 :         if (stat->flags & ZYD_RX_ERROR) {
    1918             :                 DPRINTF(("%s: RX status indicated error (%x)\n",
    1919             :                     sc->sc_dev.dv_xname, stat->flags));
    1920           0 :                 ifp->if_ierrors++;
    1921           0 :                 return;
    1922             :         }
    1923             : 
    1924             :         /* compute actual frame length */
    1925           0 :         len -= (sizeof (*plcp) + sizeof (*stat) + IEEE80211_CRC_LEN);
    1926             : 
    1927           0 :         if (len > MCLBYTES) {
    1928             :                 DPRINTFN(2, ("frame too large (length=%d)\n", len));
    1929           0 :                 ifp->if_ierrors++;
    1930           0 :                 return;
    1931             :         }
    1932             : 
    1933             :         /* allocate a mbuf to store the frame */
    1934           0 :         MGETHDR(m, M_DONTWAIT, MT_DATA);
    1935           0 :         if (m == NULL) {
    1936           0 :                 ifp->if_ierrors++;
    1937           0 :                 return;
    1938             :         }
    1939           0 :         if (len > MHLEN) {
    1940           0 :                 MCLGET(m, M_DONTWAIT);
    1941           0 :                 if (!(m->m_flags & M_EXT)) {
    1942           0 :                         ifp->if_ierrors++;
    1943           0 :                         m_freem(m);
    1944           0 :                         return;
    1945             :                 }
    1946             :         }
    1947           0 :         bcopy(plcp + 1, mtod(m, caddr_t), len);
    1948           0 :         m->m_pkthdr.len = m->m_len = len;
    1949             : 
    1950             : #if NBPFILTER > 0
    1951           0 :         if (sc->sc_drvbpf != NULL) {
    1952           0 :                 struct mbuf mb;
    1953           0 :                 struct zyd_rx_radiotap_header *tap = &sc->sc_rxtap;
    1954             :                 static const uint8_t rates[] = {
    1955             :                         /* reverse function of zyd_plcp_signal() */
    1956             :                         2, 4, 11, 22, 0, 0, 0, 0,
    1957             :                         96, 48, 24, 12, 108, 72, 36, 18
    1958             :                 };
    1959             : 
    1960           0 :                 tap->wr_flags = 0;
    1961           0 :                 tap->wr_chan_freq = htole16(ic->ic_bss->ni_chan->ic_freq);
    1962           0 :                 tap->wr_chan_flags = htole16(ic->ic_bss->ni_chan->ic_flags);
    1963           0 :                 tap->wr_rssi = stat->rssi;
    1964           0 :                 tap->wr_rate = rates[plcp->signal & 0xf];
    1965             : 
    1966           0 :                 mb.m_data = (caddr_t)tap;
    1967           0 :                 mb.m_len = sc->sc_rxtap_len;
    1968           0 :                 mb.m_next = m;
    1969           0 :                 mb.m_nextpkt = NULL;
    1970           0 :                 mb.m_type = 0;
    1971           0 :                 mb.m_flags = 0;
    1972           0 :                 bpf_mtap(sc->sc_drvbpf, &mb, BPF_DIRECTION_IN);
    1973           0 :         }
    1974             : #endif
    1975             : 
    1976           0 :         s = splnet();
    1977           0 :         wh = mtod(m, struct ieee80211_frame *);
    1978           0 :         ni = ieee80211_find_rxnode(ic, wh);
    1979           0 :         rxi.rxi_flags = 0;
    1980           0 :         rxi.rxi_rssi = stat->rssi;
    1981           0 :         rxi.rxi_tstamp = 0;     /* unused */
    1982           0 :         ieee80211_input(ifp, m, ni, &rxi);
    1983             : 
    1984             :         /* node is no longer needed */
    1985           0 :         ieee80211_release_node(ic, ni);
    1986             : 
    1987           0 :         splx(s);
    1988           0 : }
    1989             : 
    1990             : void
    1991           0 : zyd_rxeof(struct usbd_xfer *xfer, void *priv, usbd_status status)
    1992             : {
    1993           0 :         struct zyd_rx_data *data = priv;
    1994           0 :         struct zyd_softc *sc = data->sc;
    1995           0 :         struct ieee80211com *ic = &sc->sc_ic;
    1996           0 :         struct ifnet *ifp = &ic->ic_if;
    1997             :         const struct zyd_rx_desc *desc;
    1998           0 :         int len;
    1999             : 
    2000           0 :         if (status != USBD_NORMAL_COMPLETION) {
    2001           0 :                 if (status == USBD_NOT_STARTED || status == USBD_CANCELLED)
    2002           0 :                         return;
    2003             : 
    2004           0 :                 if (status == USBD_STALLED)
    2005           0 :                         usbd_clear_endpoint_stall(sc->zyd_ep[ZYD_ENDPT_BIN]);
    2006             : 
    2007             :                 goto skip;
    2008             :         }
    2009           0 :         usbd_get_xfer_status(xfer, NULL, NULL, &len, NULL);
    2010             : 
    2011           0 :         if (len < ZYD_MIN_RXBUFSZ) {
    2012             :                 DPRINTFN(2, ("xfer too short (length=%d)\n", len));
    2013           0 :                 ifp->if_ierrors++;
    2014           0 :                 goto skip;
    2015             :         }
    2016             : 
    2017           0 :         desc = (const struct zyd_rx_desc *)
    2018           0 :             (data->buf + len - sizeof (struct zyd_rx_desc));
    2019             : 
    2020           0 :         if (UGETW(desc->tag) == ZYD_TAG_MULTIFRAME) {
    2021             :                 const uint8_t *p = data->buf, *end = p + len;
    2022             :                 int i;
    2023             : 
    2024             :                 DPRINTFN(3, ("received multi-frame transfer\n"));
    2025             : 
    2026           0 :                 for (i = 0; i < ZYD_MAX_RXFRAMECNT; i++) {
    2027           0 :                         const uint16_t len = UGETW(desc->len[i]);
    2028             : 
    2029           0 :                         if (len == 0 || p + len >= end)
    2030           0 :                                 break;
    2031             : 
    2032           0 :                         zyd_rx_data(sc, p, len);
    2033             :                         /* next frame is aligned on a 32-bit boundary */
    2034           0 :                         p += (len + 3) & ~3;
    2035           0 :                 }
    2036           0 :         } else {
    2037             :                 DPRINTFN(3, ("received single-frame transfer\n"));
    2038             : 
    2039           0 :                 zyd_rx_data(sc, data->buf, len);
    2040             :         }
    2041             : 
    2042             : skip:   /* setup a new transfer */
    2043           0 :         usbd_setup_xfer(xfer, sc->zyd_ep[ZYD_ENDPT_BIN], data, NULL,
    2044             :             ZYX_MAX_RXBUFSZ, USBD_NO_COPY | USBD_SHORT_XFER_OK,
    2045             :             USBD_NO_TIMEOUT, zyd_rxeof);
    2046           0 :         (void)usbd_transfer(xfer);
    2047           0 : }
    2048             : 
    2049             : void
    2050           0 : zyd_txeof(struct usbd_xfer *xfer, void *priv, usbd_status status)
    2051             : {
    2052           0 :         struct zyd_tx_data *data = priv;
    2053           0 :         struct zyd_softc *sc = data->sc;
    2054           0 :         struct ieee80211com *ic = &sc->sc_ic;
    2055           0 :         struct ifnet *ifp = &ic->ic_if;
    2056             :         int s;
    2057             : 
    2058           0 :         if (status != USBD_NORMAL_COMPLETION) {
    2059           0 :                 if (status == USBD_NOT_STARTED || status == USBD_CANCELLED)
    2060           0 :                         return;
    2061             : 
    2062           0 :                 printf("%s: could not transmit buffer: %s\n",
    2063           0 :                     sc->sc_dev.dv_xname, usbd_errstr(status));
    2064             : 
    2065           0 :                 if (status == USBD_STALLED) {
    2066           0 :                         usbd_clear_endpoint_stall_async(
    2067           0 :                             sc->zyd_ep[ZYD_ENDPT_BOUT]);
    2068           0 :                 }
    2069           0 :                 ifp->if_oerrors++;
    2070           0 :                 return;
    2071             :         }
    2072             : 
    2073           0 :         s = splnet();
    2074             : 
    2075             :         /* update rate control statistics */
    2076           0 :         ((struct zyd_node *)data->ni)->amn.amn_txcnt++;
    2077             : 
    2078           0 :         ieee80211_release_node(ic, data->ni);
    2079           0 :         data->ni = NULL;
    2080             : 
    2081           0 :         sc->tx_queued--;
    2082             : 
    2083           0 :         sc->tx_timer = 0;
    2084           0 :         ifq_clr_oactive(&ifp->if_snd);
    2085           0 :         zyd_start(ifp);
    2086             : 
    2087           0 :         splx(s);
    2088           0 : }
    2089             : 
    2090             : int
    2091           0 : zyd_tx(struct zyd_softc *sc, struct mbuf *m, struct ieee80211_node *ni)
    2092             : {
    2093           0 :         struct ieee80211com *ic = &sc->sc_ic;
    2094           0 :         struct ifnet *ifp = &ic->ic_if;
    2095             :         struct zyd_tx_desc *desc;
    2096             :         struct zyd_tx_data *data;
    2097             :         struct ieee80211_frame *wh;
    2098             :         struct ieee80211_key *k;
    2099             :         int xferlen, totlen, rate;
    2100             :         uint16_t pktlen;
    2101             :         usbd_status error;
    2102             : 
    2103           0 :         wh = mtod(m, struct ieee80211_frame *);
    2104             : 
    2105           0 :         if (wh->i_fc[1] & IEEE80211_FC1_PROTECTED) {
    2106           0 :                 k = ieee80211_get_txkey(ic, wh, ni);
    2107           0 :                 if ((m = ieee80211_encrypt(ic, m, k)) == NULL)
    2108           0 :                         return ENOBUFS;
    2109           0 :                 wh = mtod(m, struct ieee80211_frame *);
    2110           0 :         }
    2111             : 
    2112             :         /* pickup a rate */
    2113           0 :         if (IEEE80211_IS_MULTICAST(wh->i_addr1) ||
    2114           0 :             ((wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK) ==
    2115             :              IEEE80211_FC0_TYPE_MGT)) {
    2116             :                 /* mgmt/multicast frames are sent at the lowest avail. rate */
    2117           0 :                 rate = ni->ni_rates.rs_rates[0];
    2118           0 :         } else if (ic->ic_fixed_rate != -1) {
    2119           0 :                 rate = ic->ic_sup_rates[ic->ic_curmode].
    2120           0 :                     rs_rates[ic->ic_fixed_rate];
    2121           0 :         } else
    2122           0 :                 rate = ni->ni_rates.rs_rates[ni->ni_txrate];
    2123           0 :         rate &= IEEE80211_RATE_VAL;
    2124           0 :         if (rate == 0)  /* XXX should not happen */
    2125             :                 rate = 2;
    2126             : 
    2127           0 :         data = &sc->tx_data[0];
    2128           0 :         desc = (struct zyd_tx_desc *)data->buf;
    2129             : 
    2130           0 :         data->ni = ni;
    2131             : 
    2132           0 :         xferlen = sizeof (struct zyd_tx_desc) + m->m_pkthdr.len;
    2133           0 :         totlen = m->m_pkthdr.len + IEEE80211_CRC_LEN;
    2134             : 
    2135             :         /* fill Tx descriptor */
    2136           0 :         desc->len = htole16(totlen);
    2137             : 
    2138           0 :         desc->flags = ZYD_TX_FLAG_BACKOFF;
    2139           0 :         if (!IEEE80211_IS_MULTICAST(wh->i_addr1)) {
    2140             :                 /* multicast frames are not sent at OFDM rates in 802.11b/g */
    2141           0 :                 if (totlen > ic->ic_rtsthreshold) {
    2142           0 :                         desc->flags |= ZYD_TX_FLAG_RTS;
    2143           0 :                 } else if (ZYD_RATE_IS_OFDM(rate) &&
    2144           0 :                     (ic->ic_flags & IEEE80211_F_USEPROT)) {
    2145           0 :                         if (ic->ic_protmode == IEEE80211_PROT_CTSONLY)
    2146           0 :                                 desc->flags |= ZYD_TX_FLAG_CTS_TO_SELF;
    2147           0 :                         else if (ic->ic_protmode == IEEE80211_PROT_RTSCTS)
    2148           0 :                                 desc->flags |= ZYD_TX_FLAG_RTS;
    2149             :                 }
    2150             :         } else
    2151           0 :                 desc->flags |= ZYD_TX_FLAG_MULTICAST;
    2152             : 
    2153           0 :         if ((wh->i_fc[0] &
    2154           0 :             (IEEE80211_FC0_TYPE_MASK | IEEE80211_FC0_SUBTYPE_MASK)) ==
    2155             :             (IEEE80211_FC0_TYPE_CTL | IEEE80211_FC0_SUBTYPE_PS_POLL))
    2156           0 :                 desc->flags |= ZYD_TX_FLAG_TYPE(ZYD_TX_TYPE_PS_POLL);
    2157             : 
    2158           0 :         desc->phy = zyd_plcp_signal(rate);
    2159           0 :         if (ZYD_RATE_IS_OFDM(rate)) {
    2160           0 :                 desc->phy |= ZYD_TX_PHY_OFDM;
    2161           0 :                 if (ic->ic_curmode == IEEE80211_MODE_11A)
    2162           0 :                         desc->phy |= ZYD_TX_PHY_5GHZ;
    2163           0 :         } else if (rate != 2 && (ic->ic_flags & IEEE80211_F_SHPREAMBLE))
    2164           0 :                 desc->phy |= ZYD_TX_PHY_SHPREAMBLE;
    2165             : 
    2166             :         /* actual transmit length (XXX why +10?) */
    2167             :         pktlen = sizeof (struct zyd_tx_desc) + 10;
    2168           0 :         if (sc->mac_rev == ZYD_ZD1211)
    2169           0 :                 pktlen += totlen;
    2170           0 :         desc->pktlen = htole16(pktlen);
    2171             : 
    2172           0 :         desc->plcp_length = htole16((16 * totlen + rate - 1) / rate);
    2173           0 :         desc->plcp_service = 0;
    2174           0 :         if (rate == 22) {
    2175           0 :                 const int remainder = (16 * totlen) % 22;
    2176           0 :                 if (remainder != 0 && remainder < 7)
    2177           0 :                         desc->plcp_service |= ZYD_PLCP_LENGEXT;
    2178           0 :         }
    2179             : 
    2180             : #if NBPFILTER > 0
    2181           0 :         if (sc->sc_drvbpf != NULL) {
    2182           0 :                 struct mbuf mb;
    2183           0 :                 struct zyd_tx_radiotap_header *tap = &sc->sc_txtap;
    2184             : 
    2185           0 :                 tap->wt_flags = 0;
    2186           0 :                 tap->wt_rate = rate;
    2187           0 :                 tap->wt_chan_freq = htole16(ic->ic_bss->ni_chan->ic_freq);
    2188           0 :                 tap->wt_chan_flags = htole16(ic->ic_bss->ni_chan->ic_flags);
    2189             : 
    2190           0 :                 mb.m_data = (caddr_t)tap;
    2191           0 :                 mb.m_len = sc->sc_txtap_len;
    2192           0 :                 mb.m_next = m;
    2193           0 :                 mb.m_nextpkt = NULL;
    2194           0 :                 mb.m_type = 0;
    2195           0 :                 mb.m_flags = 0;
    2196           0 :                 bpf_mtap(sc->sc_drvbpf, &mb, BPF_DIRECTION_OUT);
    2197           0 :         }
    2198             : #endif
    2199             : 
    2200           0 :         m_copydata(m, 0, m->m_pkthdr.len,
    2201           0 :             data->buf + sizeof (struct zyd_tx_desc));
    2202             : 
    2203             :         DPRINTFN(10, ("%s: sending data frame len=%u rate=%u xferlen=%u\n",
    2204             :             sc->sc_dev.dv_xname, m->m_pkthdr.len, rate, xferlen));
    2205             : 
    2206           0 :         m_freem(m);     /* mbuf no longer needed */
    2207             : 
    2208           0 :         usbd_setup_xfer(data->xfer, sc->zyd_ep[ZYD_ENDPT_BOUT], data,
    2209           0 :             data->buf, xferlen, USBD_FORCE_SHORT_XFER | USBD_NO_COPY,
    2210             :             ZYD_TX_TIMEOUT, zyd_txeof);
    2211           0 :         error = usbd_transfer(data->xfer);
    2212           0 :         if (error != USBD_IN_PROGRESS && error != 0) {
    2213           0 :                 ifp->if_oerrors++;
    2214           0 :                 return EIO;
    2215             :         }
    2216           0 :         sc->tx_queued++;
    2217             : 
    2218           0 :         return 0;
    2219           0 : }
    2220             : 
    2221             : void
    2222           0 : zyd_start(struct ifnet *ifp)
    2223             : {
    2224           0 :         struct zyd_softc *sc = ifp->if_softc;
    2225           0 :         struct ieee80211com *ic = &sc->sc_ic;
    2226           0 :         struct ieee80211_node *ni;
    2227             :         struct mbuf *m;
    2228             : 
    2229           0 :         if (!(ifp->if_flags & IFF_RUNNING) || ifq_is_oactive(&ifp->if_snd))
    2230           0 :                 return;
    2231             : 
    2232           0 :         for (;;) {
    2233           0 :                 if (sc->tx_queued >= ZYD_TX_LIST_CNT) {
    2234           0 :                         ifq_set_oactive(&ifp->if_snd);
    2235           0 :                         break;
    2236             :                 }
    2237             :                 /* send pending management frames first */
    2238           0 :                 m = mq_dequeue(&ic->ic_mgtq);
    2239           0 :                 if (m != NULL) {
    2240           0 :                         ni = m->m_pkthdr.ph_cookie;
    2241           0 :                         goto sendit;
    2242             :                 }
    2243           0 :                 if (ic->ic_state != IEEE80211_S_RUN)
    2244             :                         break;
    2245             : 
    2246             :                 /* encapsulate and send data frames */
    2247           0 :                 IFQ_DEQUEUE(&ifp->if_snd, m);
    2248           0 :                 if (m == NULL)
    2249             :                         break;
    2250             : #if NBPFILTER > 0
    2251           0 :                 if (ifp->if_bpf != NULL)
    2252           0 :                         bpf_mtap(ifp->if_bpf, m, BPF_DIRECTION_OUT);
    2253             : #endif
    2254           0 :                 if ((m = ieee80211_encap(ifp, m, &ni)) == NULL)
    2255           0 :                         continue;
    2256             : sendit:
    2257             : #if NBPFILTER > 0
    2258           0 :                 if (ic->ic_rawbpf != NULL)
    2259           0 :                         bpf_mtap(ic->ic_rawbpf, m, BPF_DIRECTION_OUT);
    2260             : #endif
    2261           0 :                 if (zyd_tx(sc, m, ni) != 0) {
    2262           0 :                         ieee80211_release_node(ic, ni);
    2263           0 :                         ifp->if_oerrors++;
    2264           0 :                         continue;
    2265             :                 }
    2266             : 
    2267           0 :                 sc->tx_timer = 5;
    2268           0 :                 ifp->if_timer = 1;
    2269             :         }
    2270           0 : }
    2271             : 
    2272             : void
    2273           0 : zyd_watchdog(struct ifnet *ifp)
    2274             : {
    2275           0 :         struct zyd_softc *sc = ifp->if_softc;
    2276             : 
    2277           0 :         ifp->if_timer = 0;
    2278             : 
    2279           0 :         if (sc->tx_timer > 0) {
    2280           0 :                 if (--sc->tx_timer == 0) {
    2281           0 :                         printf("%s: device timeout\n", sc->sc_dev.dv_xname);
    2282             :                         /* zyd_init(ifp); XXX needs a process context ? */
    2283           0 :                         ifp->if_oerrors++;
    2284           0 :                         return;
    2285             :                 }
    2286           0 :                 ifp->if_timer = 1;
    2287           0 :         }
    2288             : 
    2289           0 :         ieee80211_watchdog(ifp);
    2290           0 : }
    2291             : 
    2292             : int
    2293           0 : zyd_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
    2294             : {
    2295           0 :         struct zyd_softc *sc = ifp->if_softc;
    2296           0 :         struct ieee80211com *ic = &sc->sc_ic;
    2297             :         struct ifreq *ifr;
    2298             :         int s, error = 0;
    2299             : 
    2300           0 :         s = splnet();
    2301             : 
    2302           0 :         switch (cmd) {
    2303             :         case SIOCSIFADDR:
    2304           0 :                 ifp->if_flags |= IFF_UP;
    2305             :                 /* FALLTHROUGH */
    2306             :         case SIOCSIFFLAGS:
    2307           0 :                 if (ifp->if_flags & IFF_UP) {
    2308             :                         /*
    2309             :                          * If only the PROMISC or ALLMULTI flag changes, then
    2310             :                          * don't do a full re-init of the chip, just update
    2311             :                          * the Rx filter.
    2312             :                          */
    2313           0 :                         if ((ifp->if_flags & IFF_RUNNING) &&
    2314           0 :                             ((ifp->if_flags ^ sc->sc_if_flags) &
    2315           0 :                              (IFF_ALLMULTI | IFF_PROMISC)) != 0) {
    2316           0 :                                 zyd_set_multi(sc);
    2317           0 :                         } else {
    2318           0 :                                 if (!(ifp->if_flags & IFF_RUNNING))
    2319           0 :                                         zyd_init(ifp);
    2320             :                         }
    2321             :                 } else {
    2322           0 :                         if (ifp->if_flags & IFF_RUNNING)
    2323           0 :                                 zyd_stop(ifp, 1);
    2324             :                 }
    2325           0 :                 sc->sc_if_flags = ifp->if_flags;
    2326           0 :                 break;
    2327             : 
    2328             :         case SIOCADDMULTI:
    2329             :         case SIOCDELMULTI:
    2330           0 :                 ifr = (struct ifreq *)data;
    2331           0 :                 error = (cmd == SIOCADDMULTI) ?
    2332           0 :                     ether_addmulti(ifr, &ic->ic_ac) :
    2333           0 :                     ether_delmulti(ifr, &ic->ic_ac);
    2334           0 :                 if (error == ENETRESET) {
    2335           0 :                         if (ifp->if_flags & IFF_RUNNING)
    2336           0 :                                 zyd_set_multi(sc);
    2337             :                         error = 0;
    2338           0 :                 }
    2339             :                 break;
    2340             : 
    2341             :         case SIOCS80211CHANNEL:
    2342             :                 /*
    2343             :                  * This allows for fast channel switching in monitor mode
    2344             :                  * (used by kismet). In IBSS mode, we must explicitly reset
    2345             :                  * the interface to generate a new beacon frame.
    2346             :                  */
    2347           0 :                 error = ieee80211_ioctl(ifp, cmd, data);
    2348           0 :                 if (error == ENETRESET &&
    2349           0 :                     ic->ic_opmode == IEEE80211_M_MONITOR) {
    2350           0 :                         zyd_set_chan(sc, ic->ic_ibss_chan);
    2351             :                         error = 0;
    2352           0 :                 }
    2353             :                 break;
    2354             : 
    2355             :         default:
    2356           0 :                 error = ieee80211_ioctl(ifp, cmd, data);
    2357           0 :         }
    2358             : 
    2359           0 :         if (error == ENETRESET) {
    2360           0 :                 if ((ifp->if_flags & (IFF_RUNNING | IFF_UP)) ==
    2361             :                     (IFF_RUNNING | IFF_UP))
    2362           0 :                         zyd_init(ifp);
    2363             :                 error = 0;
    2364           0 :         }
    2365             : 
    2366           0 :         splx(s);
    2367             : 
    2368           0 :         return error;
    2369             : }
    2370             : 
    2371             : int
    2372           0 : zyd_init(struct ifnet *ifp)
    2373             : {
    2374           0 :         struct zyd_softc *sc = ifp->if_softc;
    2375           0 :         struct ieee80211com *ic = &sc->sc_ic;
    2376             :         int i, error;
    2377             : 
    2378           0 :         zyd_stop(ifp, 0);
    2379             : 
    2380           0 :         IEEE80211_ADDR_COPY(ic->ic_myaddr, LLADDR(ifp->if_sadl));
    2381             :         DPRINTF(("setting MAC address to %s\n", ether_sprintf(ic->ic_myaddr)));
    2382           0 :         zyd_set_macaddr(sc, ic->ic_myaddr);
    2383             : 
    2384             :         /* we'll do software WEP decryption for now */
    2385             :         DPRINTF(("setting encryption type\n"));
    2386           0 :         error = zyd_write32(sc, ZYD_MAC_ENCRYPTION_TYPE, ZYD_ENC_SNIFFER);
    2387           0 :         if (error != 0)
    2388           0 :                 return error;
    2389             : 
    2390             :         /* promiscuous mode */
    2391           0 :         (void)zyd_write32(sc, ZYD_MAC_SNIFFER,
    2392           0 :             (ic->ic_opmode == IEEE80211_M_MONITOR) ? 1 : 0);
    2393             : 
    2394           0 :         (void)zyd_set_rxfilter(sc);
    2395             : 
    2396             :         /* switch radio transmitter ON */
    2397           0 :         (void)zyd_switch_radio(sc, 1);
    2398             : 
    2399             :         /* set basic rates */
    2400           0 :         if (ic->ic_curmode == IEEE80211_MODE_11B)
    2401           0 :                 (void)zyd_write32(sc, ZYD_MAC_BAS_RATE, 0x0003);
    2402           0 :         else if (ic->ic_curmode == IEEE80211_MODE_11A)
    2403           0 :                 (void)zyd_write32(sc, ZYD_MAC_BAS_RATE, 0x1500);
    2404             :         else    /* assumes 802.11b/g */
    2405           0 :                 (void)zyd_write32(sc, ZYD_MAC_BAS_RATE, 0x000f);
    2406             : 
    2407             :         /* set mandatory rates */
    2408           0 :         if (ic->ic_curmode == IEEE80211_MODE_11B)
    2409           0 :                 (void)zyd_write32(sc, ZYD_MAC_MAN_RATE, 0x000f);
    2410           0 :         else if (ic->ic_curmode == IEEE80211_MODE_11A)
    2411           0 :                 (void)zyd_write32(sc, ZYD_MAC_MAN_RATE, 0x1500);
    2412             :         else    /* assumes 802.11b/g */
    2413           0 :                 (void)zyd_write32(sc, ZYD_MAC_MAN_RATE, 0x150f);
    2414             : 
    2415             :         /* set default BSS channel */
    2416           0 :         ic->ic_bss->ni_chan = ic->ic_ibss_chan;
    2417           0 :         zyd_set_chan(sc, ic->ic_bss->ni_chan);
    2418             : 
    2419             :         /* enable interrupts */
    2420           0 :         (void)zyd_write32(sc, ZYD_CR_INTERRUPT, ZYD_HWINT_MASK);
    2421             : 
    2422             :         /*
    2423             :          * Allocate Tx and Rx xfer queues.
    2424             :          */
    2425           0 :         if ((error = zyd_alloc_tx_list(sc)) != 0) {
    2426           0 :                 printf("%s: could not allocate Tx list\n",
    2427           0 :                     sc->sc_dev.dv_xname);
    2428           0 :                 goto fail;
    2429             :         }
    2430           0 :         if ((error = zyd_alloc_rx_list(sc)) != 0) {
    2431           0 :                 printf("%s: could not allocate Rx list\n",
    2432           0 :                     sc->sc_dev.dv_xname);
    2433           0 :                 goto fail;
    2434             :         }
    2435             : 
    2436             :         /*
    2437             :          * Start up the receive pipe.
    2438             :          */
    2439           0 :         for (i = 0; i < ZYD_RX_LIST_CNT; i++) {
    2440           0 :                 struct zyd_rx_data *data = &sc->rx_data[i];
    2441             : 
    2442           0 :                 usbd_setup_xfer(data->xfer, sc->zyd_ep[ZYD_ENDPT_BIN], data,
    2443             :                     NULL, ZYX_MAX_RXBUFSZ, USBD_NO_COPY | USBD_SHORT_XFER_OK,
    2444             :                     USBD_NO_TIMEOUT, zyd_rxeof);
    2445           0 :                 error = usbd_transfer(data->xfer);
    2446           0 :                 if (error != USBD_IN_PROGRESS && error != 0) {
    2447           0 :                         printf("%s: could not queue Rx transfer\n",
    2448           0 :                             sc->sc_dev.dv_xname);
    2449           0 :                         goto fail;
    2450             :                 }
    2451           0 :         }
    2452             : 
    2453           0 :         ifq_clr_oactive(&ifp->if_snd);
    2454           0 :         ifp->if_flags |= IFF_RUNNING;
    2455             : 
    2456           0 :         if (ic->ic_opmode == IEEE80211_M_MONITOR)
    2457           0 :                 ieee80211_new_state(ic, IEEE80211_S_RUN, -1);
    2458             :         else
    2459           0 :                 ieee80211_new_state(ic, IEEE80211_S_SCAN, -1);
    2460             : 
    2461           0 :         return 0;
    2462             : 
    2463           0 : fail:   zyd_stop(ifp, 1);
    2464           0 :         return error;
    2465           0 : }
    2466             : 
    2467             : void
    2468           0 : zyd_stop(struct ifnet *ifp, int disable)
    2469             : {
    2470           0 :         struct zyd_softc *sc = ifp->if_softc;
    2471           0 :         struct ieee80211com *ic = &sc->sc_ic;
    2472             : 
    2473           0 :         sc->tx_timer = 0;
    2474           0 :         ifp->if_timer = 0;
    2475           0 :         ifp->if_flags &= ~IFF_RUNNING;
    2476           0 :         ifq_clr_oactive(&ifp->if_snd);
    2477             : 
    2478           0 :         ieee80211_new_state(ic, IEEE80211_S_INIT, -1);  /* free all nodes */
    2479             : 
    2480             :         /* switch radio transmitter OFF */
    2481           0 :         (void)zyd_switch_radio(sc, 0);
    2482             : 
    2483             :         /* disable Rx */
    2484           0 :         (void)zyd_write32(sc, ZYD_MAC_RXFILTER, 0);
    2485             : 
    2486             :         /* disable interrupts */
    2487           0 :         (void)zyd_write32(sc, ZYD_CR_INTERRUPT, 0);
    2488             : 
    2489           0 :         usbd_abort_pipe(sc->zyd_ep[ZYD_ENDPT_BIN]);
    2490           0 :         usbd_abort_pipe(sc->zyd_ep[ZYD_ENDPT_BOUT]);
    2491             : 
    2492           0 :         zyd_free_rx_list(sc);
    2493           0 :         zyd_free_tx_list(sc);
    2494           0 : }
    2495             : 
    2496             : int
    2497           0 : zyd_loadfirmware(struct zyd_softc *sc, u_char *fw, size_t size)
    2498             : {
    2499           0 :         usb_device_request_t req;
    2500             :         uint16_t addr;
    2501           0 :         uint8_t stat;
    2502             : 
    2503             :         DPRINTF(("firmware size=%zd\n", size));
    2504             : 
    2505           0 :         req.bmRequestType = UT_WRITE_VENDOR_DEVICE;
    2506           0 :         req.bRequest = ZYD_DOWNLOADREQ;
    2507           0 :         USETW(req.wIndex, 0);
    2508             : 
    2509             :         addr = ZYD_FIRMWARE_START_ADDR;
    2510           0 :         while (size > 0) {
    2511           0 :                 const int mlen = min(size, 4096);
    2512             : 
    2513             :                 DPRINTF(("loading firmware block: len=%d, addr=0x%x\n", mlen,
    2514             :                     addr));
    2515             : 
    2516           0 :                 USETW(req.wValue, addr);
    2517           0 :                 USETW(req.wLength, mlen);
    2518           0 :                 if (usbd_do_request(sc->sc_udev, &req, fw) != 0)
    2519           0 :                         return EIO;
    2520             : 
    2521           0 :                 addr += mlen / 2;
    2522           0 :                 fw   += mlen;
    2523           0 :                 size -= mlen;
    2524           0 :         }
    2525             : 
    2526             :         /* check whether the upload succeeded */
    2527           0 :         req.bmRequestType = UT_READ_VENDOR_DEVICE;
    2528           0 :         req.bRequest = ZYD_DOWNLOADSTS;
    2529           0 :         USETW(req.wValue, 0);
    2530           0 :         USETW(req.wIndex, 0);
    2531           0 :         USETW(req.wLength, sizeof stat);
    2532           0 :         if (usbd_do_request(sc->sc_udev, &req, &stat) != 0)
    2533           0 :                 return EIO;
    2534             : 
    2535           0 :         return (stat & 0x80) ? EIO : 0;
    2536           0 : }
    2537             : 
    2538             : void
    2539           0 : zyd_iter_func(void *arg, struct ieee80211_node *ni)
    2540             : {
    2541           0 :         struct zyd_softc *sc = arg;
    2542           0 :         struct zyd_node *zn = (struct zyd_node *)ni;
    2543             : 
    2544           0 :         ieee80211_amrr_choose(&sc->amrr, ni, &zn->amn);
    2545           0 : }
    2546             : 
    2547             : void
    2548           0 : zyd_amrr_timeout(void *arg)
    2549             : {
    2550           0 :         struct zyd_softc *sc = arg;
    2551           0 :         struct ieee80211com *ic = &sc->sc_ic;
    2552             :         int s;
    2553             : 
    2554           0 :         s = splnet();
    2555           0 :         if (ic->ic_opmode == IEEE80211_M_STA)
    2556           0 :                 zyd_iter_func(sc, ic->ic_bss);
    2557             :         else
    2558           0 :                 ieee80211_iterate_nodes(ic, zyd_iter_func, sc);
    2559           0 :         splx(s);
    2560             : 
    2561           0 :         timeout_add_sec(&sc->amrr_to, 1);
    2562           0 : }
    2563             : 
    2564             : void
    2565           0 : zyd_newassoc(struct ieee80211com *ic, struct ieee80211_node *ni, int isnew)
    2566             : {
    2567           0 :         struct zyd_softc *sc = ic->ic_softc;
    2568             :         int i;
    2569             : 
    2570           0 :         ieee80211_amrr_node_init(&sc->amrr, &((struct zyd_node *)ni)->amn);
    2571             : 
    2572             :         /* set rate to some reasonable initial value */
    2573           0 :         for (i = ni->ni_rates.rs_nrates - 1;
    2574           0 :              i > 0 && (ni->ni_rates.rs_rates[i] & IEEE80211_RATE_VAL) > 72;
    2575           0 :              i--);
    2576           0 :         ni->ni_txrate = i;
    2577           0 : }

Generated by: LCOV version 1.13