[BACK]Return to if_zyd.c CVS log [TXT][DIR] Up to [local] / sys / dev / usb

Annotation of sys/dev/usb/if_zyd.c, Revision 1.1

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

CVSweb