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

Annotation of sys/dev/ic/atw.c, Revision 1.1

1.1     ! nbrk        1: /*     $OpenBSD: atw.c,v 1.54 2007/07/18 18:22:26 damien Exp $ */
        !             2: /*     $NetBSD: atw.c,v 1.69 2004/07/23 07:07:55 dyoung Exp $  */
        !             3:
        !             4: /*-
        !             5:  * Copyright (c) 1998, 1999, 2000, 2002, 2003, 2004 The NetBSD Foundation, Inc.
        !             6:  * All rights reserved.
        !             7:  *
        !             8:  * This code is derived from software contributed to The NetBSD Foundation
        !             9:  * by David Young, by Jason R. Thorpe, and by Charles M. Hannum.
        !            10:  *
        !            11:  * Redistribution and use in source and binary forms, with or without
        !            12:  * modification, are permitted provided that the following conditions
        !            13:  * are met:
        !            14:  * 1. Redistributions of source code must retain the above copyright
        !            15:  *    notice, this list of conditions and the following disclaimer.
        !            16:  * 2. Redistributions in binary form must reproduce the above copyright
        !            17:  *    notice, this list of conditions and the following disclaimer in the
        !            18:  *    documentation and/or other materials provided with the distribution.
        !            19:  * 3. All advertising materials mentioning features or use of this software
        !            20:  *    must display the following acknowledgement:
        !            21:  *     This product includes software developed by the NetBSD
        !            22:  *     Foundation, Inc. and its contributors.
        !            23:  * 4. Neither the name of The NetBSD Foundation nor the names of its
        !            24:  *    contributors may be used to endorse or promote products derived
        !            25:  *    from this software without specific prior written permission.
        !            26:  *
        !            27:  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
        !            28:  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
        !            29:  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
        !            30:  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
        !            31:  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
        !            32:  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
        !            33:  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
        !            34:  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
        !            35:  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
        !            36:  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
        !            37:  * POSSIBILITY OF SUCH DAMAGE.
        !            38:  */
        !            39:
        !            40: /*
        !            41:  * Device driver for the ADMtek ADM8211 802.11 MAC/BBP.
        !            42:  */
        !            43:
        !            44: #include <sys/cdefs.h>
        !            45: #if defined(__NetBSD__)
        !            46: __KERNEL_RCSID(0, "$NetBSD: atw.c,v 1.69 2004/07/23 07:07:55 dyoung Exp $");
        !            47: #endif
        !            48:
        !            49: #include "bpfilter.h"
        !            50:
        !            51: #include <sys/param.h>
        !            52: #include <sys/systm.h>
        !            53: #include <sys/mbuf.h>
        !            54: #include <sys/malloc.h>
        !            55: #include <sys/kernel.h>
        !            56: #include <sys/socket.h>
        !            57: #include <sys/ioctl.h>
        !            58: #include <sys/errno.h>
        !            59: #include <sys/device.h>
        !            60: #include <sys/time.h>
        !            61:
        !            62: #include <machine/endian.h>
        !            63:
        !            64: #include <uvm/uvm_extern.h>
        !            65:
        !            66: #include <net/if.h>
        !            67: #include <net/if_dl.h>
        !            68: #include <net/if_media.h>
        !            69:
        !            70: #if NBPFILTER > 0
        !            71: #include <net/bpf.h>
        !            72: #endif
        !            73:
        !            74: #ifdef INET
        !            75: #include <netinet/in.h>
        !            76: #include <netinet/if_ether.h>
        !            77: #endif
        !            78:
        !            79: #include <net80211/ieee80211_var.h>
        !            80: #include <net80211/ieee80211_radiotap.h>
        !            81:
        !            82: #include <machine/bus.h>
        !            83: #include <machine/intr.h>
        !            84:
        !            85: #include <dev/ic/atwreg.h>
        !            86: #include <dev/ic/rf3000reg.h>
        !            87: #include <dev/ic/si4136reg.h>
        !            88: #include <dev/ic/atwvar.h>
        !            89: #include <dev/ic/smc93cx6var.h>
        !            90:
        !            91: /* XXX TBD open questions
        !            92:  *
        !            93:  *
        !            94:  * When should I set DSSS PAD in reg 0x15 of RF3000? In 1-2Mbps
        !            95:  * modes only, or all modes (5.5-11 Mbps CCK modes, too?) Does the MAC
        !            96:  * handle this for me?
        !            97:  *
        !            98:  */
        !            99: /* device attachment
        !           100:  *
        !           101:  *    print TOFS[012]
        !           102:  *
        !           103:  * device initialization
        !           104:  *
        !           105:  *    clear ATW_FRCTL_MAXPSP to disable max power saving
        !           106:  *    set ATW_TXBR_ALCUPDATE to enable ALC
        !           107:  *    set TOFS[012]? (hope not)
        !           108:  *    disable rx/tx
        !           109:  *    set ATW_PAR_SWR (software reset)
        !           110:  *    wait for ATW_PAR_SWR clear
        !           111:  *    disable interrupts
        !           112:  *    ack status register
        !           113:  *    enable interrupts
        !           114:  *
        !           115:  * rx/tx initialization
        !           116:  *
        !           117:  *    disable rx/tx w/ ATW_NAR_SR, ATW_NAR_ST
        !           118:  *    allocate and init descriptor rings
        !           119:  *    write ATW_PAR_DSL (descriptor skip length)
        !           120:  *    write descriptor base addrs: ATW_TDBD, ATW_TDBP, write ATW_RDB
        !           121:  *    write ATW_NAR_SQ for one/both transmit descriptor rings
        !           122:  *    write ATW_NAR_SQ for one/both transmit descriptor rings
        !           123:  *    enable rx/tx w/ ATW_NAR_SR, ATW_NAR_ST
        !           124:  *
        !           125:  * rx/tx end
        !           126:  *
        !           127:  *    stop DMA
        !           128:  *    disable rx/tx w/ ATW_NAR_SR, ATW_NAR_ST
        !           129:  *    flush tx w/ ATW_NAR_HF
        !           130:  *
        !           131:  * scan
        !           132:  *
        !           133:  *    initialize rx/tx
        !           134:  *
        !           135:  * BSS join: (re)association response
        !           136:  *
        !           137:  *    set ATW_FRCTL_AID
        !           138:  *
        !           139:  * optimizations ???
        !           140:  *
        !           141:  */
        !           142:
        !           143: #define ATW_REFSLAVE   /* slavishly do what the reference driver does */
        !           144:
        !           145: int atw_bbp_io_enable_delay = 20 * 1000;
        !           146: int atw_bbp_io_disable_delay = 2 * 1000;
        !           147: int atw_writewep_delay = 1000;
        !           148: int atw_beacon_len_adjust = 4;
        !           149: int atw_dwelltime = 200;
        !           150: int atw_xindiv2 = 0;
        !           151:
        !           152: #ifdef ATW_DEBUG
        !           153: int atw_debug = 0;
        !           154:
        !           155: #define ATW_DPRINTF(x) if (atw_debug > 0) printf x
        !           156: #define ATW_DPRINTF2(x)        if (atw_debug > 1) printf x
        !           157: #define ATW_DPRINTF3(x)        if (atw_debug > 2) printf x
        !           158: #define        DPRINTF(sc, x)  if ((sc)->sc_ic.ic_if.if_flags & IFF_DEBUG) printf x
        !           159: #define        DPRINTF2(sc, x) if ((sc)->sc_ic.ic_if.if_flags & IFF_DEBUG) ATW_DPRINTF2(x)
        !           160: #define        DPRINTF3(sc, x) if ((sc)->sc_ic.ic_if.if_flags & IFF_DEBUG) ATW_DPRINTF3(x)
        !           161: void atw_print_regs(struct atw_softc *, const char *);
        !           162: void atw_dump_pkt(struct ifnet *, struct mbuf *);
        !           163:
        !           164: /* Note well: I never got atw_rf3000_read or atw_si4126_read to work. */
        !           165: #      ifdef ATW_BBPDEBUG
        !           166: int atw_rf3000_read(struct atw_softc *sc, u_int, u_int *);
        !           167: void atw_rf3000_print(struct atw_softc *);
        !           168: #      endif /* ATW_BBPDEBUG */
        !           169:
        !           170: #      ifdef ATW_SYNDEBUG
        !           171: int atw_si4126_read(struct atw_softc *, u_int, u_int *);
        !           172: void atw_si4126_print(struct atw_softc *);
        !           173: #      endif /* ATW_SYNDEBUG */
        !           174:
        !           175: #else
        !           176: #define ATW_DPRINTF(x)
        !           177: #define ATW_DPRINTF2(x)
        !           178: #define ATW_DPRINTF3(x)
        !           179: #define        DPRINTF(sc, x)  /* nothing */
        !           180: #define        DPRINTF2(sc, x) /* nothing */
        !           181: #define        DPRINTF3(sc, x) /* nothing */
        !           182: #endif
        !           183:
        !           184: #ifdef ATW_STATS
        !           185: void   atw_print_stats(struct atw_softc *);
        !           186: #endif
        !           187:
        !           188: const char *atw_printmac(u_int8_t);
        !           189:
        !           190: /* ifnet methods */
        !           191: void   atw_start(struct ifnet *);
        !           192: void   atw_watchdog(struct ifnet *);
        !           193: int    atw_ioctl(struct ifnet *, u_long, caddr_t);
        !           194: int    atw_init(struct ifnet *);
        !           195: void   atw_stop(struct ifnet *, int);
        !           196:
        !           197: /* Rx/Tx process */
        !           198: void   atw_rxdrain(struct atw_softc *);
        !           199: void   atw_txdrain(struct atw_softc *);
        !           200: int    atw_add_rxbuf(struct atw_softc *, int);
        !           201: void   atw_idle(struct atw_softc *, u_int32_t);
        !           202:
        !           203: /* Device (de)activation and power state */
        !           204: void   atw_disable(struct atw_softc *);
        !           205: void   atw_reset(struct atw_softc *);
        !           206:
        !           207: /* Interrupt handlers */
        !           208: void   atw_rxintr(struct atw_softc *);
        !           209: void   atw_txintr(struct atw_softc *);
        !           210: void   atw_linkintr(struct atw_softc *, u_int32_t);
        !           211:
        !           212: /* 802.11 state machine */
        !           213: int    atw_newstate(struct ieee80211com *, enum ieee80211_state, int);
        !           214: int    atw_tune(struct atw_softc *);
        !           215: void   atw_recv_mgmt(struct ieee80211com *, struct mbuf *,
        !           216:            struct ieee80211_node *, int, int, u_int32_t);
        !           217: void   atw_next_scan(void *);
        !           218:
        !           219: /* Device initialization */
        !           220: void   atw_wcsr_init(struct atw_softc *);
        !           221: void   atw_cmdr_init(struct atw_softc *);
        !           222: void   atw_tofs2_init(struct atw_softc *);
        !           223: void   atw_txlmt_init(struct atw_softc *);
        !           224: void   atw_test1_init(struct atw_softc *);
        !           225: void   atw_rf_reset(struct atw_softc *);
        !           226: void   atw_cfp_init(struct atw_softc *);
        !           227: void   atw_tofs0_init(struct atw_softc *);
        !           228: void   atw_ifs_init(struct atw_softc *);
        !           229: void   atw_response_times_init(struct atw_softc *);
        !           230: void   atw_bbp_io_init(struct atw_softc *);
        !           231: void   atw_nar_init(struct atw_softc *);
        !           232:
        !           233: /* RAM/ROM utilities */
        !           234: void   atw_clear_sram(struct atw_softc *);
        !           235: void   atw_write_sram(struct atw_softc *, u_int, u_int8_t *, u_int);
        !           236: int    atw_read_srom(struct atw_softc *);
        !           237:
        !           238: /* BSS setup */
        !           239: void   atw_predict_beacon(struct atw_softc *sc);
        !           240: void   atw_start_beacon(struct atw_softc *, int);
        !           241: void   atw_write_bssid(struct atw_softc *);
        !           242: void   atw_write_ssid(struct atw_softc *);
        !           243: void   atw_write_sup_rates(struct atw_softc *);
        !           244: void   atw_write_wep(struct atw_softc *);
        !           245:
        !           246: /* Media */
        !           247: int    atw_media_change(struct ifnet *);
        !           248: void   atw_media_status(struct ifnet *, struct ifmediareq *);
        !           249:
        !           250: void   atw_filter_setup(struct atw_softc *);
        !           251:
        !           252: /* 802.11 utilities */
        !           253: struct ieee80211_node *atw_node_alloc(struct ieee80211com *);
        !           254: void   atw_node_free(struct ieee80211com *, struct ieee80211_node *);
        !           255: static __inline uint32_t atw_last_even_tsft(uint32_t, uint32_t, uint32_t);
        !           256: uint64_t atw_get_tsft(struct atw_softc *sc);
        !           257: void   atw_change_ibss(struct atw_softc *);
        !           258: int    atw_compute_duration1(int, int, uint32_t, int, struct atw_duration *);
        !           259: int    atw_compute_duration(struct ieee80211_frame *, int, uint32_t, int,
        !           260:            int, struct atw_duration *, struct atw_duration *, int *, int);
        !           261:
        !           262: /*
        !           263:  * Tuner/transceiver/modem
        !           264:  */
        !           265: void   atw_bbp_io_enable(struct atw_softc *, int);
        !           266:
        !           267: /* RFMD RF3000 Baseband Processor */
        !           268: int    atw_rf3000_init(struct atw_softc *);
        !           269: int    atw_rf3000_tune(struct atw_softc *, u_int);
        !           270: int    atw_rf3000_write(struct atw_softc *, u_int, u_int);
        !           271:
        !           272: /* Silicon Laboratories Si4126 RF/IF Synthesizer */
        !           273: void   atw_si4126_tune(struct atw_softc *, u_int);
        !           274: void   atw_si4126_write(struct atw_softc *, u_int, u_int);
        !           275: void   atw_si4126_init(struct atw_softc *);
        !           276:
        !           277: const struct atw_txthresh_tab atw_txthresh_tab_lo[] = ATW_TXTHRESH_TAB_LO_RATE;
        !           278: const struct atw_txthresh_tab atw_txthresh_tab_hi[] = ATW_TXTHRESH_TAB_HI_RATE;
        !           279:
        !           280: struct cfdriver atw_cd = {
        !           281:     NULL, "atw", DV_IFNET
        !           282: };
        !           283:
        !           284: static const u_int atw_rfmd2958_ifn[] = {
        !           285:        0x22bd, 0x22d2, 0x22e8, 0x22fe, 0x2314, 0x232a, 0x2340,
        !           286:        0x2355, 0x236b, 0x2381, 0x2397, 0x23ad, 0x23c2, 0x23f7
        !           287: };
        !           288:
        !           289: static const u_int atw_rfmd2958_rf1r[] = {
        !           290:        0x05d17, 0x3a2e8, 0x2e8ba, 0x22e8b, 0x1745d, 0x0ba2e, 0x00000,
        !           291:        0x345d1, 0x28ba2, 0x1d174, 0x11745, 0x05d17, 0x3a2e8, 0x11745
        !           292: };
        !           293:
        !           294:
        !           295: #ifdef ATW_DEBUG
        !           296:
        !           297: const char *atw_tx_state[] = {
        !           298:        "STOPPED",
        !           299:        "RUNNING - read descriptor",
        !           300:        "RUNNING - transmitting",
        !           301:        "RUNNING - filling fifo",       /* XXX */
        !           302:        "SUSPENDED",
        !           303:        "RUNNING -- write descriptor",
        !           304:        "RUNNING -- write last descriptor",
        !           305:        "RUNNING - fifo full"
        !           306: };
        !           307:
        !           308: const char *atw_rx_state[] = {
        !           309:        "STOPPED",
        !           310:        "RUNNING - read descriptor",
        !           311:        "RUNNING - check this packet, pre-fetch next",
        !           312:        "RUNNING - wait for reception",
        !           313:        "SUSPENDED",
        !           314:        "RUNNING - write descriptor",
        !           315:        "RUNNING - flush fifo",
        !           316:        "RUNNING - fifo drain"
        !           317: };
        !           318:
        !           319: #endif
        !           320:
        !           321: #ifndef __OpenBSD__
        !           322: int
        !           323: atw_activate(struct device *self, enum devact act)
        !           324: {
        !           325:        struct atw_softc *sc = (struct atw_softc *)self;
        !           326:        int rv = 0, s;
        !           327:
        !           328:        s = splnet();
        !           329:        switch (act) {
        !           330:        case DVACT_ACTIVATE:
        !           331:                break;
        !           332:
        !           333:        case DVACT_DEACTIVATE:
        !           334:                if_deactivate(&sc->sc_ic.ic_if);
        !           335:                break;
        !           336:        }
        !           337:        splx(s);
        !           338:        return rv;
        !           339: }
        !           340: #endif
        !           341:
        !           342: /*
        !           343:  * atw_enable:
        !           344:  *
        !           345:  *     Enable the ADM8211 chip.
        !           346:  */
        !           347: int
        !           348: atw_enable(struct atw_softc *sc)
        !           349: {
        !           350:
        !           351:        if (ATW_IS_ENABLED(sc) == 0) {
        !           352:                if (sc->sc_enable != NULL && (*sc->sc_enable)(sc) != 0) {
        !           353:                        printf("%s: device enable failed\n",
        !           354:                            sc->sc_dev.dv_xname);
        !           355:                        return (EIO);
        !           356:                }
        !           357:                sc->sc_flags |= ATWF_ENABLED;
        !           358:        }
        !           359:        return (0);
        !           360: }
        !           361:
        !           362: /*
        !           363:  * atw_disable:
        !           364:  *
        !           365:  *     Disable the ADM8211 chip.
        !           366:  */
        !           367: void
        !           368: atw_disable(struct atw_softc *sc)
        !           369: {
        !           370:        if (!ATW_IS_ENABLED(sc))
        !           371:                return;
        !           372:        if (sc->sc_disable != NULL)
        !           373:                (*sc->sc_disable)(sc);
        !           374:        sc->sc_flags &= ~ATWF_ENABLED;
        !           375: }
        !           376:
        !           377: /* Returns -1 on failure. */
        !           378: int
        !           379: atw_read_srom(struct atw_softc *sc)
        !           380: {
        !           381:        struct seeprom_descriptor sd;
        !           382:        u_int32_t test0, fail_bits;
        !           383:
        !           384:        (void)memset(&sd, 0, sizeof(sd));
        !           385:
        !           386:        test0 = ATW_READ(sc, ATW_TEST0);
        !           387:
        !           388:        switch (sc->sc_rev) {
        !           389:        case ATW_REVISION_BA:
        !           390:        case ATW_REVISION_CA:
        !           391:                fail_bits = ATW_TEST0_EPNE;
        !           392:                break;
        !           393:        default:
        !           394:                fail_bits = ATW_TEST0_EPNE|ATW_TEST0_EPSNM;
        !           395:                break;
        !           396:        }
        !           397:        if ((test0 & fail_bits) != 0) {
        !           398:                printf("%s: bad or missing/bad SROM\n", sc->sc_dev.dv_xname);
        !           399:                return -1;
        !           400:        }
        !           401:
        !           402:        switch (test0 & ATW_TEST0_EPTYP_MASK) {
        !           403:        case ATW_TEST0_EPTYP_93c66:
        !           404:                ATW_DPRINTF(("%s: 93c66 SROM\n", sc->sc_dev.dv_xname));
        !           405:                sc->sc_sromsz = 512;
        !           406:                sd.sd_chip = C56_66;
        !           407:                break;
        !           408:        case ATW_TEST0_EPTYP_93c46:
        !           409:                ATW_DPRINTF(("%s: 93c46 SROM\n", sc->sc_dev.dv_xname));
        !           410:                sc->sc_sromsz = 128;
        !           411:                sd.sd_chip = C46;
        !           412:                break;
        !           413:        default:
        !           414:                printf("%s: unknown SROM type %d\n", sc->sc_dev.dv_xname,
        !           415:                    MASK_AND_RSHIFT(test0, ATW_TEST0_EPTYP_MASK));
        !           416:                return -1;
        !           417:        }
        !           418:
        !           419:        sc->sc_srom = malloc(sc->sc_sromsz, M_DEVBUF, M_NOWAIT);
        !           420:        if (sc->sc_srom == NULL) {
        !           421:                printf("%s: unable to allocate SROM buffer\n",
        !           422:                    sc->sc_dev.dv_xname);
        !           423:                return -1;
        !           424:        }
        !           425:
        !           426:        (void)memset(sc->sc_srom, 0, sc->sc_sromsz);
        !           427:        /* ADM8211 has a single 32-bit register for controlling the
        !           428:         * 93cx6 SROM.  Bit SRS enables the serial port. There is no
        !           429:         * "ready" bit. The ADM8211 input/output sense is the reverse
        !           430:         * of read_seeprom's.
        !           431:         */
        !           432:        sd.sd_tag = sc->sc_st;
        !           433:        sd.sd_bsh = sc->sc_sh;
        !           434:        sd.sd_regsize = 4;
        !           435:        sd.sd_control_offset = ATW_SPR;
        !           436:        sd.sd_status_offset = ATW_SPR;
        !           437:        sd.sd_dataout_offset = ATW_SPR;
        !           438:        sd.sd_CK = ATW_SPR_SCLK;
        !           439:        sd.sd_CS = ATW_SPR_SCS;
        !           440:        sd.sd_DI = ATW_SPR_SDO;
        !           441:        sd.sd_DO = ATW_SPR_SDI;
        !           442:        sd.sd_MS = ATW_SPR_SRS;
        !           443:        sd.sd_RDY = 0;
        !           444:
        !           445:        if (!read_seeprom(&sd, sc->sc_srom, 0, sc->sc_sromsz/2)) {
        !           446:                printf("%s: could not read SROM\n", sc->sc_dev.dv_xname);
        !           447:                free(sc->sc_srom, M_DEVBUF);
        !           448:                return -1;
        !           449:        }
        !           450: #ifdef ATW_DEBUG
        !           451:        {
        !           452:                int i;
        !           453:                ATW_DPRINTF(("\nSerial EEPROM:\n\t"));
        !           454:                for (i = 0; i < sc->sc_sromsz/2; i = i + 1) {
        !           455:                        if (((i % 8) == 0) && (i != 0)) {
        !           456:                                ATW_DPRINTF(("\n\t"));
        !           457:                        }
        !           458:                        ATW_DPRINTF((" 0x%x", sc->sc_srom[i]));
        !           459:                }
        !           460:                ATW_DPRINTF(("\n"));
        !           461:        }
        !           462: #endif /* ATW_DEBUG */
        !           463:        return 0;
        !           464: }
        !           465:
        !           466: #ifdef ATW_DEBUG
        !           467: void
        !           468: atw_print_regs(struct atw_softc *sc, const char *where)
        !           469: {
        !           470: #define PRINTREG(sc, reg) \
        !           471:        ATW_DPRINTF2(("%s: reg[ " #reg " / %03x ] = %08x\n", \
        !           472:            sc->sc_dev.dv_xname, reg, ATW_READ(sc, reg)))
        !           473:
        !           474:        ATW_DPRINTF2(("%s: %s\n", sc->sc_dev.dv_xname, where));
        !           475:
        !           476:        PRINTREG(sc, ATW_PAR);
        !           477:        PRINTREG(sc, ATW_FRCTL);
        !           478:        PRINTREG(sc, ATW_TDR);
        !           479:        PRINTREG(sc, ATW_WTDP);
        !           480:        PRINTREG(sc, ATW_RDR);
        !           481:        PRINTREG(sc, ATW_WRDP);
        !           482:        PRINTREG(sc, ATW_RDB);
        !           483:        PRINTREG(sc, ATW_CSR3A);
        !           484:        PRINTREG(sc, ATW_TDBD);
        !           485:        PRINTREG(sc, ATW_TDBP);
        !           486:        PRINTREG(sc, ATW_STSR);
        !           487:        PRINTREG(sc, ATW_CSR5A);
        !           488:        PRINTREG(sc, ATW_NAR);
        !           489:        PRINTREG(sc, ATW_CSR6A);
        !           490:        PRINTREG(sc, ATW_IER);
        !           491:        PRINTREG(sc, ATW_CSR7A);
        !           492:        PRINTREG(sc, ATW_LPC);
        !           493:        PRINTREG(sc, ATW_TEST1);
        !           494:        PRINTREG(sc, ATW_SPR);
        !           495:        PRINTREG(sc, ATW_TEST0);
        !           496:        PRINTREG(sc, ATW_WCSR);
        !           497:        PRINTREG(sc, ATW_WPDR);
        !           498:        PRINTREG(sc, ATW_GPTMR);
        !           499:        PRINTREG(sc, ATW_GPIO);
        !           500:        PRINTREG(sc, ATW_BBPCTL);
        !           501:        PRINTREG(sc, ATW_SYNCTL);
        !           502:        PRINTREG(sc, ATW_PLCPHD);
        !           503:        PRINTREG(sc, ATW_MMIWADDR);
        !           504:        PRINTREG(sc, ATW_MMIRADDR1);
        !           505:        PRINTREG(sc, ATW_MMIRADDR2);
        !           506:        PRINTREG(sc, ATW_TXBR);
        !           507:        PRINTREG(sc, ATW_CSR15A);
        !           508:        PRINTREG(sc, ATW_ALCSTAT);
        !           509:        PRINTREG(sc, ATW_TOFS2);
        !           510:        PRINTREG(sc, ATW_CMDR);
        !           511:        PRINTREG(sc, ATW_PCIC);
        !           512:        PRINTREG(sc, ATW_PMCSR);
        !           513:        PRINTREG(sc, ATW_PAR0);
        !           514:        PRINTREG(sc, ATW_PAR1);
        !           515:        PRINTREG(sc, ATW_MAR0);
        !           516:        PRINTREG(sc, ATW_MAR1);
        !           517:        PRINTREG(sc, ATW_ATIMDA0);
        !           518:        PRINTREG(sc, ATW_ABDA1);
        !           519:        PRINTREG(sc, ATW_BSSID0);
        !           520:        PRINTREG(sc, ATW_TXLMT);
        !           521:        PRINTREG(sc, ATW_MIBCNT);
        !           522:        PRINTREG(sc, ATW_BCNT);
        !           523:        PRINTREG(sc, ATW_TSFTH);
        !           524:        PRINTREG(sc, ATW_TSC);
        !           525:        PRINTREG(sc, ATW_SYNRF);
        !           526:        PRINTREG(sc, ATW_BPLI);
        !           527:        PRINTREG(sc, ATW_CAP0);
        !           528:        PRINTREG(sc, ATW_CAP1);
        !           529:        PRINTREG(sc, ATW_RMD);
        !           530:        PRINTREG(sc, ATW_CFPP);
        !           531:        PRINTREG(sc, ATW_TOFS0);
        !           532:        PRINTREG(sc, ATW_TOFS1);
        !           533:        PRINTREG(sc, ATW_IFST);
        !           534:        PRINTREG(sc, ATW_RSPT);
        !           535:        PRINTREG(sc, ATW_TSFTL);
        !           536:        PRINTREG(sc, ATW_WEPCTL);
        !           537:        PRINTREG(sc, ATW_WESK);
        !           538:        PRINTREG(sc, ATW_WEPCNT);
        !           539:        PRINTREG(sc, ATW_MACTEST);
        !           540:        PRINTREG(sc, ATW_FER);
        !           541:        PRINTREG(sc, ATW_FEMR);
        !           542:        PRINTREG(sc, ATW_FPSR);
        !           543:        PRINTREG(sc, ATW_FFER);
        !           544: #undef PRINTREG
        !           545: }
        !           546: #endif /* ATW_DEBUG */
        !           547:
        !           548: const char*
        !           549: atw_printmac(u_int8_t rev) {
        !           550:        switch (rev) {
        !           551:        case ATW_REVISION_AB:
        !           552:                return "ADM8211AB";
        !           553:        case ATW_REVISION_AF:
        !           554:                return "ADM8211AF";
        !           555:        case ATW_REVISION_BA:
        !           556:                return "ADM8211BA";
        !           557:        case ATW_REVISION_CA:
        !           558:                return "ADM8211CA";
        !           559:        default:
        !           560:                return "unknown";
        !           561:        }
        !           562: }
        !           563:
        !           564: /*
        !           565:  * Finish attaching an ADMtek ADM8211 MAC.  Called by bus-specific front-end.
        !           566:  */
        !           567: void
        !           568: atw_attach(struct atw_softc *sc)
        !           569: {
        !           570:        static const u_int8_t empty_macaddr[IEEE80211_ADDR_LEN] = {
        !           571:                0x00, 0x00, 0x00, 0x00, 0x00, 0x00
        !           572:        };
        !           573:        struct ieee80211com *ic = &sc->sc_ic;
        !           574:        struct ifnet *ifp = &ic->ic_if;
        !           575:        int country_code, error, i, srom_major;
        !           576:        u_int32_t reg;
        !           577:        static const char *type_strings[] = {"Intersil (not supported)",
        !           578:            "RFMD", "Marvel (not supported)"};
        !           579:
        !           580:        sc->sc_txth = atw_txthresh_tab_lo;
        !           581:
        !           582:        SIMPLEQ_INIT(&sc->sc_txfreeq);
        !           583:        SIMPLEQ_INIT(&sc->sc_txdirtyq);
        !           584:
        !           585: #ifdef ATW_DEBUG
        !           586:        atw_print_regs(sc, "atw_attach");
        !           587: #endif /* ATW_DEBUG */
        !           588:
        !           589:        /*
        !           590:         * Allocate the control data structures, and create and load the
        !           591:         * DMA map for it.
        !           592:         */
        !           593:        if ((error = bus_dmamem_alloc(sc->sc_dmat,
        !           594:            sizeof(struct atw_control_data), PAGE_SIZE, 0, &sc->sc_cdseg,
        !           595:            1, &sc->sc_cdnseg, 0)) != 0) {
        !           596:                printf("%s: unable to allocate control data, error = %d\n",
        !           597:                    sc->sc_dev.dv_xname, error);
        !           598:                goto fail_0;
        !           599:        }
        !           600:
        !           601:        if ((error = bus_dmamem_map(sc->sc_dmat, &sc->sc_cdseg, sc->sc_cdnseg,
        !           602:            sizeof(struct atw_control_data), (caddr_t *)&sc->sc_control_data,
        !           603:            BUS_DMA_COHERENT)) != 0) {
        !           604:                printf("%s: unable to map control data, error = %d\n",
        !           605:                    sc->sc_dev.dv_xname, error);
        !           606:                goto fail_1;
        !           607:        }
        !           608:
        !           609:        if ((error = bus_dmamap_create(sc->sc_dmat,
        !           610:            sizeof(struct atw_control_data), 1,
        !           611:            sizeof(struct atw_control_data), 0, 0, &sc->sc_cddmamap)) != 0) {
        !           612:                printf("%s: unable to create control data DMA map, "
        !           613:                    "error = %d\n", sc->sc_dev.dv_xname, error);
        !           614:                goto fail_2;
        !           615:        }
        !           616:
        !           617:        if ((error = bus_dmamap_load(sc->sc_dmat, sc->sc_cddmamap,
        !           618:            sc->sc_control_data, sizeof(struct atw_control_data), NULL,
        !           619:            0)) != 0) {
        !           620:                printf("%s: unable to load control data DMA map, error = %d\n",
        !           621:                    sc->sc_dev.dv_xname, error);
        !           622:                goto fail_3;
        !           623:        }
        !           624:
        !           625:        /*
        !           626:         * Create the transmit buffer DMA maps.
        !           627:         */
        !           628:        sc->sc_ntxsegs = ATW_NTXSEGS;
        !           629:        for (i = 0; i < ATW_TXQUEUELEN; i++) {
        !           630:                if ((error = bus_dmamap_create(sc->sc_dmat, MCLBYTES,
        !           631:                    sc->sc_ntxsegs, MCLBYTES, 0, 0,
        !           632:                    &sc->sc_txsoft[i].txs_dmamap)) != 0) {
        !           633:                        printf("%s: unable to create tx DMA map %d, "
        !           634:                            "error = %d\n", sc->sc_dev.dv_xname, i, error);
        !           635:                        goto fail_4;
        !           636:                }
        !           637:        }
        !           638:
        !           639:        /*
        !           640:         * Create the receive buffer DMA maps.
        !           641:         */
        !           642:        for (i = 0; i < ATW_NRXDESC; i++) {
        !           643:                if ((error = bus_dmamap_create(sc->sc_dmat, MCLBYTES, 1,
        !           644:                    MCLBYTES, 0, 0, &sc->sc_rxsoft[i].rxs_dmamap)) != 0) {
        !           645:                        printf("%s: unable to create rx DMA map %d, "
        !           646:                            "error = %d\n", sc->sc_dev.dv_xname, i, error);
        !           647:                        goto fail_5;
        !           648:                }
        !           649:        }
        !           650:        for (i = 0; i < ATW_NRXDESC; i++) {
        !           651:                sc->sc_rxsoft[i].rxs_mbuf = NULL;
        !           652:        }
        !           653:
        !           654:        switch (sc->sc_rev) {
        !           655:        case ATW_REVISION_AB:
        !           656:        case ATW_REVISION_AF:
        !           657:                sc->sc_sramlen = ATW_SRAM_A_SIZE;
        !           658:                break;
        !           659:        case ATW_REVISION_BA:
        !           660:        case ATW_REVISION_CA:
        !           661:                sc->sc_sramlen = ATW_SRAM_B_SIZE;
        !           662:                break;
        !           663:        }
        !           664:
        !           665:        /* Reset the chip to a known state. */
        !           666:        atw_reset(sc);
        !           667:
        !           668:        if (atw_read_srom(sc) == -1)
        !           669:                return;
        !           670:
        !           671:        sc->sc_rftype = MASK_AND_RSHIFT(sc->sc_srom[ATW_SR_CSR20],
        !           672:            ATW_SR_RFTYPE_MASK);
        !           673:
        !           674:        sc->sc_bbptype = MASK_AND_RSHIFT(sc->sc_srom[ATW_SR_CSR20],
        !           675:            ATW_SR_BBPTYPE_MASK);
        !           676:
        !           677:        if (sc->sc_rftype >= sizeof(type_strings)/sizeof(type_strings[0])) {
        !           678:                printf("%s: unknown RF\n", sc->sc_dev.dv_xname);
        !           679:                return;
        !           680:        }
        !           681:        if (sc->sc_bbptype >= sizeof(type_strings)/sizeof(type_strings[0])) {
        !           682:                printf("%s: unknown BBP\n", sc->sc_dev.dv_xname);
        !           683:                return;
        !           684:        }
        !           685:
        !           686:        printf("%s: MAC %s, BBP %s, RF %s", sc->sc_dev.dv_xname,
        !           687:            atw_printmac(sc->sc_rev), type_strings[sc->sc_bbptype],
        !           688:            type_strings[sc->sc_rftype]);
        !           689:
        !           690:        /* XXX There exists a Linux driver which seems to use RFType = 0 for
        !           691:         * MARVEL. My bug, or theirs?
        !           692:         */
        !           693:
        !           694:        reg = LSHIFT(sc->sc_rftype, ATW_SYNCTL_RFTYPE_MASK);
        !           695:
        !           696:        switch (sc->sc_rftype) {
        !           697:        case ATW_RFTYPE_INTERSIL:
        !           698:                reg |= ATW_SYNCTL_CS1;
        !           699:                break;
        !           700:        case ATW_RFTYPE_RFMD:
        !           701:                reg |= ATW_SYNCTL_CS0;
        !           702:                break;
        !           703:        case ATW_RFTYPE_MARVEL:
        !           704:                break;
        !           705:        }
        !           706:
        !           707:        sc->sc_synctl_rd = reg | ATW_SYNCTL_RD;
        !           708:        sc->sc_synctl_wr = reg | ATW_SYNCTL_WR;
        !           709:
        !           710:        reg = LSHIFT(sc->sc_bbptype, ATW_BBPCTL_TYPE_MASK);
        !           711:
        !           712:        switch (sc->sc_bbptype) {
        !           713:        case ATW_BBPTYPE_INTERSIL:
        !           714:                reg |= ATW_BBPCTL_TWI;
        !           715:                break;
        !           716:        case ATW_BBPTYPE_RFMD:
        !           717:                reg |= ATW_BBPCTL_RF3KADDR_ADDR | ATW_BBPCTL_NEGEDGE_DO |
        !           718:                    ATW_BBPCTL_CCA_ACTLO;
        !           719:                break;
        !           720:        case ATW_BBPTYPE_MARVEL:
        !           721:                break;
        !           722:        case ATW_C_BBPTYPE_RFMD:
        !           723:                printf("%s: ADM8211C MAC/RFMD BBP not supported yet.\n",
        !           724:                    sc->sc_dev.dv_xname);
        !           725:                break;
        !           726:        }
        !           727:
        !           728:        sc->sc_bbpctl_wr = reg | ATW_BBPCTL_WR;
        !           729:        sc->sc_bbpctl_rd = reg | ATW_BBPCTL_RD;
        !           730:
        !           731:        /*
        !           732:         * From this point forward, the attachment cannot fail.  A failure
        !           733:         * before this point releases all resources that may have been
        !           734:         * allocated.
        !           735:         */
        !           736:        sc->sc_flags |= ATWF_ATTACHED /* | ATWF_RTSCTS */;
        !           737:
        !           738:        ATW_DPRINTF((" SROM MAC %04x%04x%04x",
        !           739:            htole16(sc->sc_srom[ATW_SR_MAC00]),
        !           740:            htole16(sc->sc_srom[ATW_SR_MAC01]),
        !           741:            htole16(sc->sc_srom[ATW_SR_MAC10])));
        !           742:
        !           743:        srom_major = MASK_AND_RSHIFT(sc->sc_srom[ATW_SR_FORMAT_VERSION],
        !           744:            ATW_SR_MAJOR_MASK);
        !           745:
        !           746:        if (srom_major < 2)
        !           747:                sc->sc_rf3000_options1 = 0;
        !           748:        else if (sc->sc_rev == ATW_REVISION_BA) {
        !           749:                sc->sc_rf3000_options1 =
        !           750:                    MASK_AND_RSHIFT(sc->sc_srom[ATW_SR_CR28_CR03],
        !           751:                    ATW_SR_CR28_MASK);
        !           752:        } else
        !           753:                sc->sc_rf3000_options1 = 0;
        !           754:
        !           755:        sc->sc_rf3000_options2 = MASK_AND_RSHIFT(sc->sc_srom[ATW_SR_CTRY_CR29],
        !           756:            ATW_SR_CR29_MASK);
        !           757:
        !           758:        country_code = MASK_AND_RSHIFT(sc->sc_srom[ATW_SR_CTRY_CR29],
        !           759:            ATW_SR_CTRY_MASK);
        !           760:
        !           761: #define ADD_CHANNEL(_ic, _chan) do {                                   \
        !           762:        _ic->ic_channels[_chan].ic_flags = IEEE80211_CHAN_B;            \
        !           763:        _ic->ic_channels[_chan].ic_freq =                               \
        !           764:            ieee80211_ieee2mhz(_chan, _ic->ic_channels[_chan].ic_flags);\
        !           765: } while (0)
        !           766:
        !           767:        /* Find available channels */
        !           768:        switch (country_code) {
        !           769:        case COUNTRY_MMK2:      /* 1-14 */
        !           770:                ADD_CHANNEL(ic, 14);
        !           771:                /*FALLTHROUGH*/
        !           772:        case COUNTRY_ETSI:      /* 1-13 */
        !           773:                for (i = 1; i <= 13; i++)
        !           774:                        ADD_CHANNEL(ic, i);
        !           775:                break;
        !           776:        case COUNTRY_FCC:       /* 1-11 */
        !           777:        case COUNTRY_IC:        /* 1-11 */
        !           778:                for (i = 1; i <= 11; i++)
        !           779:                        ADD_CHANNEL(ic, i);
        !           780:                break;
        !           781:        case COUNTRY_MMK:       /* 14 */
        !           782:                ADD_CHANNEL(ic, 14);
        !           783:                break;
        !           784:        case COUNTRY_FRANCE:    /* 10-13 */
        !           785:                for (i = 10; i <= 13; i++)
        !           786:                        ADD_CHANNEL(ic, i);
        !           787:                break;
        !           788:        default:        /* assume channels 10-11 */
        !           789:        case COUNTRY_SPAIN:     /* 10-11 */
        !           790:                for (i = 10; i <= 11; i++)
        !           791:                        ADD_CHANNEL(ic, i);
        !           792:                break;
        !           793:        }
        !           794:
        !           795:        /* Read the MAC address. */
        !           796:        reg = ATW_READ(sc, ATW_PAR0);
        !           797:        ic->ic_myaddr[0] = MASK_AND_RSHIFT(reg, ATW_PAR0_PAB0_MASK);
        !           798:        ic->ic_myaddr[1] = MASK_AND_RSHIFT(reg, ATW_PAR0_PAB1_MASK);
        !           799:        ic->ic_myaddr[2] = MASK_AND_RSHIFT(reg, ATW_PAR0_PAB2_MASK);
        !           800:        ic->ic_myaddr[3] = MASK_AND_RSHIFT(reg, ATW_PAR0_PAB3_MASK);
        !           801:        reg = ATW_READ(sc, ATW_PAR1);
        !           802:        ic->ic_myaddr[4] = MASK_AND_RSHIFT(reg, ATW_PAR1_PAB4_MASK);
        !           803:        ic->ic_myaddr[5] = MASK_AND_RSHIFT(reg, ATW_PAR1_PAB5_MASK);
        !           804:
        !           805:        if (IEEE80211_ADDR_EQ(ic->ic_myaddr, empty_macaddr)) {
        !           806:                printf(" could not get mac address, attach failed\n");
        !           807:                return;
        !           808:        }
        !           809:
        !           810:        printf(", address %s\n", ether_sprintf(ic->ic_myaddr));
        !           811:
        !           812:        memcpy(ifp->if_xname, sc->sc_dev.dv_xname, IFNAMSIZ);
        !           813:        ifp->if_softc = sc;
        !           814:        ifp->if_flags = IFF_SIMPLEX | IFF_BROADCAST | IFF_MULTICAST |
        !           815:            IFF_NOTRAILERS;
        !           816:        ifp->if_ioctl = atw_ioctl;
        !           817:        ifp->if_start = atw_start;
        !           818:        ifp->if_watchdog = atw_watchdog;
        !           819: #if !defined(__OpenBSD__)
        !           820:        ifp->if_init = atw_init;
        !           821:        ifp->if_stop = atw_stop;
        !           822: #endif
        !           823:        IFQ_SET_READY(&ifp->if_snd);
        !           824:
        !           825:        ic->ic_phytype = IEEE80211_T_DS;
        !           826:        ic->ic_opmode = IEEE80211_M_STA;
        !           827:        ic->ic_caps = IEEE80211_C_PMGT | IEEE80211_C_IBSS |
        !           828:            IEEE80211_C_HOSTAP | IEEE80211_C_MONITOR | IEEE80211_C_WEP;
        !           829:
        !           830:        ic->ic_sup_rates[IEEE80211_MODE_11B] = ieee80211_std_rateset_11b;
        !           831:
        !           832:        /*
        !           833:         * Call MI attach routines.
        !           834:         */
        !           835:
        !           836:        if_attach(ifp);
        !           837:        ieee80211_ifattach(ifp);
        !           838:
        !           839:        sc->sc_newstate = ic->ic_newstate;
        !           840:        ic->ic_newstate = atw_newstate;
        !           841:
        !           842:        sc->sc_recv_mgmt = ic->ic_recv_mgmt;
        !           843:        ic->ic_recv_mgmt = atw_recv_mgmt;
        !           844:
        !           845:        sc->sc_node_free = ic->ic_node_free;
        !           846:        ic->ic_node_free = atw_node_free;
        !           847:
        !           848:        sc->sc_node_alloc = ic->ic_node_alloc;
        !           849:        ic->ic_node_alloc = atw_node_alloc;
        !           850:
        !           851:        /* possibly we should fill in our own sc_send_prresp, since
        !           852:         * the ADM8211 is probably sending probe responses in ad hoc
        !           853:         * mode.
        !           854:         */
        !           855:
        !           856:        /* complete initialization */
        !           857:        ieee80211_media_init(ifp, atw_media_change, atw_media_status);
        !           858:        timeout_set(&sc->sc_scan_to, atw_next_scan, sc);
        !           859:
        !           860: #if NBPFILTER > 0
        !           861:        bpfattach(&sc->sc_radiobpf, ifp, DLT_IEEE802_11_RADIO,
        !           862:            sizeof(struct ieee80211_frame) + 64);
        !           863: #endif
        !           864:
        !           865:        /*
        !           866:         * Make sure the interface is shutdown during reboot.
        !           867:         */
        !           868:        sc->sc_sdhook = shutdownhook_establish(atw_shutdown, sc);
        !           869:        if (sc->sc_sdhook == NULL)
        !           870:                printf("%s: WARNING: unable to establish shutdown hook\n",
        !           871:                    sc->sc_dev.dv_xname);
        !           872:
        !           873:        /*
        !           874:         * Add a suspend hook to make sure we come back up after a
        !           875:         * resume.
        !           876:         */
        !           877:        sc->sc_powerhook = powerhook_establish(atw_power, sc);
        !           878:        if (sc->sc_powerhook == NULL)
        !           879:                printf("%s: WARNING: unable to establish power hook\n",
        !           880:                    sc->sc_dev.dv_xname);
        !           881:
        !           882:        memset(&sc->sc_rxtapu, 0, sizeof(sc->sc_rxtapu));
        !           883:        sc->sc_rxtap.ar_ihdr.it_len = sizeof(sc->sc_rxtapu);
        !           884:        sc->sc_rxtap.ar_ihdr.it_present = ATW_RX_RADIOTAP_PRESENT;
        !           885:
        !           886:        memset(&sc->sc_txtapu, 0, sizeof(sc->sc_txtapu));
        !           887:        sc->sc_txtap.at_ihdr.it_len = sizeof(sc->sc_txtapu);
        !           888:        sc->sc_txtap.at_ihdr.it_present = ATW_TX_RADIOTAP_PRESENT;
        !           889:
        !           890:        return;
        !           891:
        !           892:        /*
        !           893:         * Free any resources we've allocated during the failed attach
        !           894:         * attempt.  Do this in reverse order and fall through.
        !           895:         */
        !           896:  fail_5:
        !           897:        for (i = 0; i < ATW_NRXDESC; i++) {
        !           898:                if (sc->sc_rxsoft[i].rxs_dmamap == NULL)
        !           899:                        continue;
        !           900:                bus_dmamap_destroy(sc->sc_dmat, sc->sc_rxsoft[i].rxs_dmamap);
        !           901:        }
        !           902:  fail_4:
        !           903:        for (i = 0; i < ATW_TXQUEUELEN; i++) {
        !           904:                if (sc->sc_txsoft[i].txs_dmamap == NULL)
        !           905:                        continue;
        !           906:                bus_dmamap_destroy(sc->sc_dmat, sc->sc_txsoft[i].txs_dmamap);
        !           907:        }
        !           908:        bus_dmamap_unload(sc->sc_dmat, sc->sc_cddmamap);
        !           909:  fail_3:
        !           910:        bus_dmamap_destroy(sc->sc_dmat, sc->sc_cddmamap);
        !           911:  fail_2:
        !           912:        bus_dmamem_unmap(sc->sc_dmat, (caddr_t)sc->sc_control_data,
        !           913:            sizeof(struct atw_control_data));
        !           914:  fail_1:
        !           915:        bus_dmamem_free(sc->sc_dmat, &sc->sc_cdseg, sc->sc_cdnseg);
        !           916:  fail_0:
        !           917:        return;
        !           918: }
        !           919:
        !           920: struct ieee80211_node *
        !           921: atw_node_alloc(struct ieee80211com *ic)
        !           922: {
        !           923:        struct atw_softc *sc = (struct atw_softc *)ic->ic_if.if_softc;
        !           924:        struct ieee80211_node *ni = (*sc->sc_node_alloc)(ic);
        !           925:
        !           926:        DPRINTF(sc, ("%s: alloc node %p\n", sc->sc_dev.dv_xname, ni));
        !           927:        return ni;
        !           928: }
        !           929:
        !           930: void
        !           931: atw_node_free(struct ieee80211com *ic, struct ieee80211_node *ni)
        !           932: {
        !           933:        struct atw_softc *sc = (struct atw_softc *)ic->ic_if.if_softc;
        !           934:
        !           935:        DPRINTF(sc, ("%s: freeing node %p %s\n", sc->sc_dev.dv_xname, ni,
        !           936:            ether_sprintf(ni->ni_bssid)));
        !           937:        (*sc->sc_node_free)(ic, ni);
        !           938: }
        !           939:
        !           940:
        !           941: static void
        !           942: atw_test1_reset(struct atw_softc *sc)
        !           943: {
        !           944:        switch (sc->sc_rev) {
        !           945:        case ATW_REVISION_BA:
        !           946:                if (1 /* XXX condition on transceiver type */) {
        !           947:                        ATW_SET(sc, ATW_TEST1, ATW_TEST1_TESTMODE_MONITOR);
        !           948:                }
        !           949:                break;
        !           950:        case ATW_REVISION_CA:
        !           951:                ATW_CLR(sc, ATW_TEST1, ATW_TEST1_TESTMODE_MASK);
        !           952:                break;
        !           953:        default:
        !           954:                break;
        !           955:        }
        !           956: }
        !           957:
        !           958: /*
        !           959:  * atw_reset:
        !           960:  *
        !           961:  *     Perform a soft reset on the ADM8211.
        !           962:  */
        !           963: void
        !           964: atw_reset(struct atw_softc *sc)
        !           965: {
        !           966:        int i;
        !           967:        uint32_t lpc;
        !           968:
        !           969:        ATW_WRITE(sc, ATW_NAR, 0x0);
        !           970:        DELAY(20 * 1000);
        !           971:
        !           972:        /* Reference driver has a cryptic remark indicating that this might
        !           973:         * power-on the chip.  I know that it turns off power-saving....
        !           974:         */
        !           975:        ATW_WRITE(sc, ATW_FRCTL, 0x0);
        !           976:
        !           977:        ATW_WRITE(sc, ATW_PAR, ATW_PAR_SWR);
        !           978:
        !           979:        for (i = 0; i < 50; i++) {
        !           980:                if (ATW_READ(sc, ATW_PAR) == 0)
        !           981:                        break;
        !           982:                DELAY(1000);
        !           983:        }
        !           984:
        !           985:        /* ... and then pause 100ms longer for good measure. */
        !           986:        DELAY(100 * 1000);
        !           987:
        !           988:        DPRINTF2(sc, ("%s: atw_reset %d iterations\n", sc->sc_dev.dv_xname, i));
        !           989:
        !           990:        if (ATW_ISSET(sc, ATW_PAR, ATW_PAR_SWR))
        !           991:                printf("%s: reset failed to complete\n", sc->sc_dev.dv_xname);
        !           992:
        !           993:        atw_test1_reset(sc);
        !           994:        /*
        !           995:         * Initialize the PCI Access Register.
        !           996:         */
        !           997:        sc->sc_busmode = ATW_PAR_PBL_8DW;
        !           998:
        !           999:        ATW_WRITE(sc, ATW_PAR, sc->sc_busmode);
        !          1000:        DPRINTF(sc, ("%s: ATW_PAR %08x busmode %08x\n", sc->sc_dev.dv_xname,
        !          1001:            ATW_READ(sc, ATW_PAR), sc->sc_busmode));
        !          1002:
        !          1003:        /* Turn off maximum power saving, etc.
        !          1004:         *
        !          1005:         * XXX Following example of reference driver, should I set
        !          1006:         * an AID of 1?  It didn't seem to help....
        !          1007:         */
        !          1008:        ATW_WRITE(sc, ATW_FRCTL, 0x0);
        !          1009:
        !          1010:        DELAY(100 * 1000);
        !          1011:
        !          1012:        /* Recall EEPROM. */
        !          1013:        ATW_SET(sc, ATW_TEST0, ATW_TEST0_EPRLD);
        !          1014:
        !          1015:        DELAY(10 * 1000);
        !          1016:
        !          1017:        lpc = ATW_READ(sc, ATW_LPC);
        !          1018:
        !          1019:        DPRINTF(sc, ("%s: ATW_LPC %#08x\n", __func__, lpc));
        !          1020:
        !          1021:        /* A reset seems to affect the SRAM contents, so put them into
        !          1022:         * a known state.
        !          1023:         */
        !          1024:        atw_clear_sram(sc);
        !          1025:
        !          1026:        memset(sc->sc_bssid, 0xff, sizeof(sc->sc_bssid));
        !          1027: }
        !          1028:
        !          1029: void
        !          1030: atw_clear_sram(struct atw_softc *sc)
        !          1031: {
        !          1032:        memset(sc->sc_sram, 0, sizeof(sc->sc_sram));
        !          1033:        /* XXX not for revision 0x20. */
        !          1034:        atw_write_sram(sc, 0, sc->sc_sram, sc->sc_sramlen);
        !          1035: }
        !          1036:
        !          1037: /* TBD atw_init
        !          1038:  *
        !          1039:  * set MAC based on ic->ic_bss->myaddr
        !          1040:  * write WEP keys
        !          1041:  * set TX rate
        !          1042:  */
        !          1043:
        !          1044: /* Tell the ADM8211 to raise ATW_INTR_LINKOFF if 7 beacon intervals pass
        !          1045:  * without receiving a beacon with the preferred BSSID & SSID.
        !          1046:  * atw_write_bssid & atw_write_ssid set the BSSID & SSID.
        !          1047:  */
        !          1048: void
        !          1049: atw_wcsr_init(struct atw_softc *sc)
        !          1050: {
        !          1051:        uint32_t wcsr;
        !          1052:
        !          1053:        wcsr = ATW_READ(sc, ATW_WCSR);
        !          1054:        wcsr &= ~(ATW_WCSR_BLN_MASK|ATW_WCSR_LSOE|ATW_WCSR_MPRE|ATW_WCSR_LSOE);
        !          1055:        wcsr |= LSHIFT(7, ATW_WCSR_BLN_MASK);
        !          1056:        ATW_WRITE(sc, ATW_WCSR, wcsr);  /* XXX resets wake-up status bits */
        !          1057:
        !          1058:        DPRINTF(sc, ("%s: %s reg[WCSR] = %08x\n",
        !          1059:            sc->sc_dev.dv_xname, __func__, ATW_READ(sc, ATW_WCSR)));
        !          1060: }
        !          1061:
        !          1062: /* Turn off power management.  Set Rx store-and-forward mode. */
        !          1063: void
        !          1064: atw_cmdr_init(struct atw_softc *sc)
        !          1065: {
        !          1066:        uint32_t cmdr;
        !          1067:        cmdr = ATW_READ(sc, ATW_CMDR);
        !          1068:        cmdr &= ~ATW_CMDR_APM;
        !          1069:        cmdr |= ATW_CMDR_RTE;
        !          1070:        cmdr &= ~ATW_CMDR_DRT_MASK;
        !          1071:        cmdr |= ATW_CMDR_DRT_SF;
        !          1072:
        !          1073:        ATW_WRITE(sc, ATW_CMDR, cmdr);
        !          1074: }
        !          1075:
        !          1076: void
        !          1077: atw_tofs2_init(struct atw_softc *sc)
        !          1078: {
        !          1079:        uint32_t tofs2;
        !          1080:        /* XXX this magic can probably be figured out from the RFMD docs */
        !          1081: #ifndef ATW_REFSLAVE
        !          1082:        tofs2 = LSHIFT(4, ATW_TOFS2_PWR1UP_MASK)    | /* 8 ms = 4 * 2 ms */
        !          1083:              LSHIFT(13, ATW_TOFS2_PWR0PAPE_MASK) | /* 13 us */
        !          1084:              LSHIFT(8, ATW_TOFS2_PWR1PAPE_MASK)  | /* 8 us */
        !          1085:              LSHIFT(5, ATW_TOFS2_PWR0TRSW_MASK)  | /* 5 us */
        !          1086:              LSHIFT(12, ATW_TOFS2_PWR1TRSW_MASK) | /* 12 us */
        !          1087:              LSHIFT(13, ATW_TOFS2_PWR0PE2_MASK)  | /* 13 us */
        !          1088:              LSHIFT(4, ATW_TOFS2_PWR1PE2_MASK)   | /* 4 us */
        !          1089:              LSHIFT(5, ATW_TOFS2_PWR0TXPE_MASK);  /* 5 us */
        !          1090: #else
        !          1091:        /* XXX new magic from reference driver source */
        !          1092:        tofs2 = LSHIFT(8, ATW_TOFS2_PWR1UP_MASK)    | /* 8 ms = 4 * 2 ms */
        !          1093:              LSHIFT(8, ATW_TOFS2_PWR0PAPE_MASK) | /* 13 us */
        !          1094:              LSHIFT(1, ATW_TOFS2_PWR1PAPE_MASK)  | /* 8 us */
        !          1095:              LSHIFT(5, ATW_TOFS2_PWR0TRSW_MASK)  | /* 5 us */
        !          1096:              LSHIFT(12, ATW_TOFS2_PWR1TRSW_MASK) | /* 12 us */
        !          1097:              LSHIFT(13, ATW_TOFS2_PWR0PE2_MASK)  | /* 13 us */
        !          1098:              LSHIFT(1, ATW_TOFS2_PWR1PE2_MASK)   | /* 4 us */
        !          1099:              LSHIFT(8, ATW_TOFS2_PWR0TXPE_MASK);  /* 5 us */
        !          1100: #endif
        !          1101:        ATW_WRITE(sc, ATW_TOFS2, tofs2);
        !          1102: }
        !          1103:
        !          1104: void
        !          1105: atw_nar_init(struct atw_softc *sc)
        !          1106: {
        !          1107:        ATW_WRITE(sc, ATW_NAR, ATW_NAR_SF|ATW_NAR_PB);
        !          1108: }
        !          1109:
        !          1110: void
        !          1111: atw_txlmt_init(struct atw_softc *sc)
        !          1112: {
        !          1113:        ATW_WRITE(sc, ATW_TXLMT, LSHIFT(512, ATW_TXLMT_MTMLT_MASK) |
        !          1114:                                 LSHIFT(1, ATW_TXLMT_SRTYLIM_MASK));
        !          1115: }
        !          1116:
        !          1117: void
        !          1118: atw_test1_init(struct atw_softc *sc)
        !          1119: {
        !          1120:        uint32_t test1;
        !          1121:
        !          1122:        test1 = ATW_READ(sc, ATW_TEST1);
        !          1123:        test1 &= ~(ATW_TEST1_DBGREAD_MASK|ATW_TEST1_CONTROL);
        !          1124:        /* XXX magic 0x1 */
        !          1125:        test1 |= LSHIFT(0x1, ATW_TEST1_DBGREAD_MASK) | ATW_TEST1_CONTROL;
        !          1126:        ATW_WRITE(sc, ATW_TEST1, test1);
        !          1127: }
        !          1128:
        !          1129: void
        !          1130: atw_rf_reset(struct atw_softc *sc)
        !          1131: {
        !          1132:        /* XXX this resets an Intersil RF front-end? */
        !          1133:        /* TBD condition on Intersil RFType? */
        !          1134:        ATW_WRITE(sc, ATW_SYNRF, ATW_SYNRF_INTERSIL_EN);
        !          1135:        DELAY(10 * 1000);
        !          1136:        ATW_WRITE(sc, ATW_SYNRF, 0);
        !          1137:        DELAY(5 * 1000);
        !          1138: }
        !          1139:
        !          1140: /* Set 16 TU max duration for the contention-free period (CFP). */
        !          1141: void
        !          1142: atw_cfp_init(struct atw_softc *sc)
        !          1143: {
        !          1144:        uint32_t cfpp;
        !          1145:
        !          1146:        cfpp = ATW_READ(sc, ATW_CFPP);
        !          1147:        cfpp &= ~ATW_CFPP_CFPMD;
        !          1148:        cfpp |= LSHIFT(16, ATW_CFPP_CFPMD);
        !          1149:        ATW_WRITE(sc, ATW_CFPP, cfpp);
        !          1150: }
        !          1151:
        !          1152: void
        !          1153: atw_tofs0_init(struct atw_softc *sc)
        !          1154: {
        !          1155:        /* XXX I guess that the Cardbus clock is 22MHz?
        !          1156:         * I am assuming that the role of ATW_TOFS0_USCNT is
        !          1157:         * to divide the bus clock to get a 1MHz clock---the datasheet is not
        !          1158:         * very clear on this point. It says in the datasheet that it is
        !          1159:         * possible for the ADM8211 to accomodate bus speeds between 22MHz
        !          1160:         * and 33MHz; maybe this is the way? I see a binary-only driver write
        !          1161:         * these values. These values are also the power-on default.
        !          1162:         */
        !          1163:        ATW_WRITE(sc, ATW_TOFS0,
        !          1164:            LSHIFT(22, ATW_TOFS0_USCNT_MASK) |
        !          1165:            ATW_TOFS0_TUCNT_MASK /* set all bits in TUCNT */);
        !          1166: }
        !          1167:
        !          1168: /* Initialize interframe spacing: 802.11b slot time, SIFS, DIFS, EIFS. */
        !          1169: void
        !          1170: atw_ifs_init(struct atw_softc *sc)
        !          1171: {
        !          1172:        uint32_t ifst;
        !          1173:        /* XXX EIFS=0x64, SIFS=110 are used by the reference driver.
        !          1174:         * Go figure.
        !          1175:         */
        !          1176:        ifst = LSHIFT(IEEE80211_DUR_DS_SLOT, ATW_IFST_SLOT_MASK) |
        !          1177:            LSHIFT(22 * 5 /* IEEE80211_DUR_DS_SIFS */ /* # of 22MHz cycles */,
        !          1178:                   ATW_IFST_SIFS_MASK) |
        !          1179:            LSHIFT(IEEE80211_DUR_DS_DIFS, ATW_IFST_DIFS_MASK) |
        !          1180:            LSHIFT(0x64 /* IEEE80211_DUR_DS_EIFS */, ATW_IFST_EIFS_MASK);
        !          1181:
        !          1182:        ATW_WRITE(sc, ATW_IFST, ifst);
        !          1183: }
        !          1184:
        !          1185: void
        !          1186: atw_response_times_init(struct atw_softc *sc)
        !          1187: {
        !          1188:        /* XXX More magic. Relates to ACK timing?  The datasheet seems to
        !          1189:         * indicate that the MAC expects at least SIFS + MIRT microseconds
        !          1190:         * to pass after it transmits a frame that requires a response;
        !          1191:         * it waits at most SIFS + MART microseconds for the response.
        !          1192:         * Surely this is not the ACK timeout?
        !          1193:         */
        !          1194:        ATW_WRITE(sc, ATW_RSPT, LSHIFT(0xffff, ATW_RSPT_MART_MASK) |
        !          1195:            LSHIFT(0xff, ATW_RSPT_MIRT_MASK));
        !          1196: }
        !          1197:
        !          1198: /* Set up the MMI read/write addresses for the baseband. The Tx/Rx
        !          1199:  * engines read and write baseband registers after Rx and before
        !          1200:  * Tx, respectively.
        !          1201:  */
        !          1202: void
        !          1203: atw_bbp_io_init(struct atw_softc *sc)
        !          1204: {
        !          1205:        uint32_t mmiraddr2;
        !          1206:
        !          1207:        /* XXX The reference driver does this, but is it *really*
        !          1208:         * necessary?
        !          1209:         */
        !          1210:        switch (sc->sc_rev) {
        !          1211:        case ATW_REVISION_AB:
        !          1212:        case ATW_REVISION_AF:
        !          1213:                mmiraddr2 = 0x0;
        !          1214:                break;
        !          1215:        default:
        !          1216:                mmiraddr2 = ATW_READ(sc, ATW_MMIRADDR2);
        !          1217:                mmiraddr2 &=
        !          1218:                    ~(ATW_MMIRADDR2_PROREXT|ATW_MMIRADDR2_PRORLEN_MASK);
        !          1219:                break;
        !          1220:        }
        !          1221:
        !          1222:        switch (sc->sc_bbptype) {
        !          1223:        case ATW_BBPTYPE_INTERSIL:
        !          1224:                ATW_WRITE(sc, ATW_MMIWADDR, ATW_MMIWADDR_INTERSIL);
        !          1225:                ATW_WRITE(sc, ATW_MMIRADDR1, ATW_MMIRADDR1_INTERSIL);
        !          1226:                mmiraddr2 |= ATW_MMIRADDR2_INTERSIL;
        !          1227:                break;
        !          1228:        case ATW_BBPTYPE_MARVEL:
        !          1229:                /* TBD find out the Marvel settings. */
        !          1230:                break;
        !          1231:        case ATW_BBPTYPE_RFMD:
        !          1232:        default:
        !          1233:                ATW_WRITE(sc, ATW_MMIWADDR, ATW_MMIWADDR_RFMD);
        !          1234:                ATW_WRITE(sc, ATW_MMIRADDR1, ATW_MMIRADDR1_RFMD);
        !          1235:                mmiraddr2 |= ATW_MMIRADDR2_RFMD;
        !          1236:                break;
        !          1237:        }
        !          1238:        ATW_WRITE(sc, ATW_MMIRADDR2, mmiraddr2);
        !          1239:
        !          1240:        atw_si4126_init(sc);
        !          1241:
        !          1242:        ATW_WRITE(sc, ATW_MACTEST, ATW_MACTEST_MMI_USETXCLK);
        !          1243: }
        !          1244:
        !          1245: void
        !          1246: atw_si4126_init(struct atw_softc *sc)
        !          1247: {
        !          1248:        switch (sc->sc_rftype) {
        !          1249:        case ATW_RFTYPE_RFMD:
        !          1250:                if (sc->sc_rev >= ATW_REVISION_BA) {
        !          1251:                        atw_si4126_write(sc, 0x1f, 0x00000);
        !          1252:                        atw_si4126_write(sc, 0x0c, 0x3001f);
        !          1253:                        atw_si4126_write(sc, SI4126_GAIN, 0x29c03);
        !          1254:                        atw_si4126_write(sc, SI4126_RF1N, 0x1ff6f);
        !          1255:                        atw_si4126_write(sc, SI4126_RF2N, 0x29403);
        !          1256:                        atw_si4126_write(sc, SI4126_RF2R, 0x1456f);
        !          1257:                        atw_si4126_write(sc, 0x09, 0x10050);
        !          1258:                        atw_si4126_write(sc, SI4126_IFR, 0x3fff8);
        !          1259:                }
        !          1260:                break;
        !          1261:        default:
        !          1262:                break;
        !          1263:        }
        !          1264: }
        !          1265:
        !          1266: /*
        !          1267:  * atw_init:           [ ifnet interface function ]
        !          1268:  *
        !          1269:  *     Initialize the interface.  Must be called at splnet().
        !          1270:  */
        !          1271: int
        !          1272: atw_init(struct ifnet *ifp)
        !          1273: {
        !          1274:        struct atw_softc *sc = ifp->if_softc;
        !          1275:        struct ieee80211com *ic = &sc->sc_ic;
        !          1276:        struct atw_txsoft *txs;
        !          1277:        struct atw_rxsoft *rxs;
        !          1278:        int i, error = 0;
        !          1279:
        !          1280:        if ((error = atw_enable(sc)) != 0)
        !          1281:                goto out;
        !          1282:
        !          1283:        /*
        !          1284:         * Cancel any pending I/O. This also resets.
        !          1285:         */
        !          1286:        atw_stop(ifp, 0);
        !          1287:
        !          1288:        ic->ic_bss->ni_chan = ic->ic_ibss_chan;
        !          1289:        DPRINTF(sc, ("%s: channel %d freq %d flags 0x%04x\n",
        !          1290:            __func__, ieee80211_chan2ieee(ic, ic->ic_bss->ni_chan),
        !          1291:            ic->ic_bss->ni_chan->ic_freq, ic->ic_bss->ni_chan->ic_flags));
        !          1292:
        !          1293:        atw_wcsr_init(sc);
        !          1294:
        !          1295:        atw_cmdr_init(sc);
        !          1296:
        !          1297:        /* Set data rate for PLCP Signal field, 1Mbps = 10 x 100Kb/s.
        !          1298:         *
        !          1299:         * XXX Set transmit power for ATIM, RTS, Beacon.
        !          1300:         */
        !          1301:        ATW_WRITE(sc, ATW_PLCPHD, LSHIFT(10, ATW_PLCPHD_SIGNAL_MASK) |
        !          1302:            LSHIFT(0xb0, ATW_PLCPHD_SERVICE_MASK));
        !          1303:
        !          1304:        atw_tofs2_init(sc);
        !          1305:
        !          1306:        atw_nar_init(sc);
        !          1307:
        !          1308:        atw_txlmt_init(sc);
        !          1309:
        !          1310:        atw_test1_init(sc);
        !          1311:
        !          1312:        atw_rf_reset(sc);
        !          1313:
        !          1314:        atw_cfp_init(sc);
        !          1315:
        !          1316:        atw_tofs0_init(sc);
        !          1317:
        !          1318:        atw_ifs_init(sc);
        !          1319:
        !          1320:        /* XXX Fall asleep after one second of inactivity.
        !          1321:         * XXX A frame may only dribble in for 65536us.
        !          1322:         */
        !          1323:        ATW_WRITE(sc, ATW_RMD,
        !          1324:            LSHIFT(1, ATW_RMD_PCNT) | LSHIFT(0xffff, ATW_RMD_RMRD_MASK));
        !          1325:
        !          1326:        atw_response_times_init(sc);
        !          1327:
        !          1328:        atw_bbp_io_init(sc);
        !          1329:
        !          1330:        ATW_WRITE(sc, ATW_STSR, 0xffffffff);
        !          1331:
        !          1332:        if ((error = atw_rf3000_init(sc)) != 0)
        !          1333:                goto out;
        !          1334:
        !          1335:        ATW_WRITE(sc, ATW_PAR, sc->sc_busmode);
        !          1336:        DPRINTF(sc, ("%s: ATW_PAR %08x busmode %08x\n", sc->sc_dev.dv_xname,
        !          1337:            ATW_READ(sc, ATW_PAR), sc->sc_busmode));
        !          1338:
        !          1339:        /*
        !          1340:         * Initialize the transmit descriptor ring.
        !          1341:         */
        !          1342:        memset(sc->sc_txdescs, 0, sizeof(sc->sc_txdescs));
        !          1343:        for (i = 0; i < ATW_NTXDESC; i++) {
        !          1344:                sc->sc_txdescs[i].at_ctl = 0;
        !          1345:                /* no transmit chaining */
        !          1346:                sc->sc_txdescs[i].at_flags = 0 /* ATW_TXFLAG_TCH */;
        !          1347:                sc->sc_txdescs[i].at_buf2 =
        !          1348:                    htole32(ATW_CDTXADDR(sc, ATW_NEXTTX(i)));
        !          1349:        }
        !          1350:        /* use ring mode */
        !          1351:        sc->sc_txdescs[ATW_NTXDESC - 1].at_flags |= htole32(ATW_TXFLAG_TER);
        !          1352:        ATW_CDTXSYNC(sc, 0, ATW_NTXDESC,
        !          1353:            BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE);
        !          1354:        sc->sc_txfree = ATW_NTXDESC;
        !          1355:        sc->sc_txnext = 0;
        !          1356:
        !          1357:        /*
        !          1358:         * Initialize the transmit job descriptors.
        !          1359:         */
        !          1360:        SIMPLEQ_INIT(&sc->sc_txfreeq);
        !          1361:        SIMPLEQ_INIT(&sc->sc_txdirtyq);
        !          1362:        for (i = 0; i < ATW_TXQUEUELEN; i++) {
        !          1363:                txs = &sc->sc_txsoft[i];
        !          1364:                txs->txs_mbuf = NULL;
        !          1365:                SIMPLEQ_INSERT_TAIL(&sc->sc_txfreeq, txs, txs_q);
        !          1366:        }
        !          1367:
        !          1368:        /*
        !          1369:         * Initialize the receive descriptor and receive job
        !          1370:         * descriptor rings.
        !          1371:         */
        !          1372:        for (i = 0; i < ATW_NRXDESC; i++) {
        !          1373:                rxs = &sc->sc_rxsoft[i];
        !          1374:                if (rxs->rxs_mbuf == NULL) {
        !          1375:                        if ((error = atw_add_rxbuf(sc, i)) != 0) {
        !          1376:                                printf("%s: unable to allocate or map rx "
        !          1377:                                    "buffer %d, error = %d\n",
        !          1378:                                    sc->sc_dev.dv_xname, i, error);
        !          1379:                                /*
        !          1380:                                 * XXX Should attempt to run with fewer receive
        !          1381:                                 * XXX buffers instead of just failing.
        !          1382:                                 */
        !          1383:                                atw_rxdrain(sc);
        !          1384:                                goto out;
        !          1385:                        }
        !          1386:                } else
        !          1387:                        ATW_INIT_RXDESC(sc, i);
        !          1388:        }
        !          1389:        sc->sc_rxptr = 0;
        !          1390:
        !          1391:        /*
        !          1392:         * Initialize the interrupt mask and enable interrupts.
        !          1393:         */
        !          1394:        /* normal interrupts */
        !          1395:        sc->sc_inten =  ATW_INTR_TCI | ATW_INTR_TDU | ATW_INTR_RCI |
        !          1396:            ATW_INTR_NISS | ATW_INTR_LINKON | ATW_INTR_BCNTC;
        !          1397:
        !          1398:        /* abnormal interrupts */
        !          1399:        sc->sc_inten |= ATW_INTR_TPS | ATW_INTR_TLT | ATW_INTR_TRT |
        !          1400:            ATW_INTR_TUF | ATW_INTR_RDU | ATW_INTR_RPS | ATW_INTR_AISS |
        !          1401:            ATW_INTR_FBE | ATW_INTR_LINKOFF | ATW_INTR_TSFTF | ATW_INTR_TSCZ;
        !          1402:
        !          1403:        sc->sc_linkint_mask = ATW_INTR_LINKON | ATW_INTR_LINKOFF |
        !          1404:            ATW_INTR_BCNTC | ATW_INTR_TSFTF | ATW_INTR_TSCZ;
        !          1405:        sc->sc_rxint_mask = ATW_INTR_RCI | ATW_INTR_RDU;
        !          1406:        sc->sc_txint_mask = ATW_INTR_TCI | ATW_INTR_TUF | ATW_INTR_TLT |
        !          1407:            ATW_INTR_TRT;
        !          1408:
        !          1409:        sc->sc_linkint_mask &= sc->sc_inten;
        !          1410:        sc->sc_rxint_mask &= sc->sc_inten;
        !          1411:        sc->sc_txint_mask &= sc->sc_inten;
        !          1412:
        !          1413:        ATW_WRITE(sc, ATW_IER, sc->sc_inten);
        !          1414:        ATW_WRITE(sc, ATW_STSR, 0xffffffff);
        !          1415:
        !          1416:        DPRINTF(sc, ("%s: ATW_IER %08x, inten %08x\n",
        !          1417:            sc->sc_dev.dv_xname, ATW_READ(sc, ATW_IER), sc->sc_inten));
        !          1418:
        !          1419:        /*
        !          1420:         * Give the transmit and receive rings to the ADM8211.
        !          1421:         */
        !          1422:        ATW_WRITE(sc, ATW_RDB, ATW_CDRXADDR(sc, sc->sc_rxptr));
        !          1423:        ATW_WRITE(sc, ATW_TDBD, ATW_CDTXADDR(sc, sc->sc_txnext));
        !          1424:
        !          1425:        sc->sc_txthresh = 0;
        !          1426:        sc->sc_opmode = ATW_NAR_SR | ATW_NAR_ST |
        !          1427:            sc->sc_txth[sc->sc_txthresh].txth_opmode;
        !          1428:
        !          1429:        /* common 802.11 configuration */
        !          1430:        ic->ic_flags &= ~IEEE80211_F_IBSSON;
        !          1431:        switch (ic->ic_opmode) {
        !          1432:        case IEEE80211_M_STA:
        !          1433:                break;
        !          1434:        case IEEE80211_M_AHDEMO: /* XXX */
        !          1435:        case IEEE80211_M_IBSS:
        !          1436:                ic->ic_flags |= IEEE80211_F_IBSSON;
        !          1437:                /*FALLTHROUGH*/
        !          1438:        case IEEE80211_M_HOSTAP: /* XXX */
        !          1439:                break;
        !          1440:        case IEEE80211_M_MONITOR: /* XXX */
        !          1441:                break;
        !          1442:        }
        !          1443:
        !          1444:        switch (ic->ic_opmode) {
        !          1445:        case IEEE80211_M_AHDEMO:
        !          1446:        case IEEE80211_M_HOSTAP:
        !          1447:                ic->ic_bss->ni_intval = ic->ic_lintval;
        !          1448:                ic->ic_bss->ni_rssi = 0;
        !          1449:                ic->ic_bss->ni_rstamp = 0;
        !          1450:                break;
        !          1451:        default:                                        /* XXX */
        !          1452:                break;
        !          1453:        }
        !          1454:
        !          1455:        sc->sc_wepctl = 0;
        !          1456:
        !          1457:        atw_write_ssid(sc);
        !          1458:        atw_write_sup_rates(sc);
        !          1459:        if (ic->ic_caps & IEEE80211_C_WEP)
        !          1460:                atw_write_wep(sc);
        !          1461:
        !          1462:        ic->ic_state = IEEE80211_S_INIT;
        !          1463:
        !          1464:        /*
        !          1465:         * Set the receive filter.  This will start the transmit and
        !          1466:         * receive processes.
        !          1467:         */
        !          1468:        atw_filter_setup(sc);
        !          1469:
        !          1470:        /*
        !          1471:         * Start the receive process.
        !          1472:         */
        !          1473:        ATW_WRITE(sc, ATW_RDR, 0x1);
        !          1474:
        !          1475:        /*
        !          1476:         * Note that the interface is now running.
        !          1477:         */
        !          1478:        ifp->if_flags |= IFF_RUNNING;
        !          1479:        ifp->if_flags &= ~IFF_OACTIVE;
        !          1480:
        !          1481:        /* send no beacons, yet. */
        !          1482:        atw_start_beacon(sc, 0);
        !          1483:
        !          1484:        if (ic->ic_opmode == IEEE80211_M_MONITOR)
        !          1485:                error = ieee80211_new_state(ic, IEEE80211_S_RUN, -1);
        !          1486:        else
        !          1487:                error = ieee80211_new_state(ic, IEEE80211_S_SCAN, -1);
        !          1488:  out:
        !          1489:        if (error) {
        !          1490:                ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE);
        !          1491:                ifp->if_timer = 0;
        !          1492:                printf("%s: interface not running\n", sc->sc_dev.dv_xname);
        !          1493:        }
        !          1494: #ifdef ATW_DEBUG
        !          1495:        atw_print_regs(sc, "end of init");
        !          1496: #endif /* ATW_DEBUG */
        !          1497:
        !          1498:        return (error);
        !          1499: }
        !          1500:
        !          1501: /* enable == 1: host control of RF3000/Si4126 through ATW_SYNCTL.
        !          1502:  *           0: MAC control of RF3000/Si4126.
        !          1503:  *
        !          1504:  * Applies power, or selects RF front-end? Sets reset condition.
        !          1505:  *
        !          1506:  * TBD support non-RFMD BBP, non-SiLabs synth.
        !          1507:  */
        !          1508: void
        !          1509: atw_bbp_io_enable(struct atw_softc *sc, int enable)
        !          1510: {
        !          1511:        if (enable) {
        !          1512:                ATW_WRITE(sc, ATW_SYNRF,
        !          1513:                    ATW_SYNRF_SELRF|ATW_SYNRF_PE1|ATW_SYNRF_PHYRST);
        !          1514:                DELAY(atw_bbp_io_enable_delay);
        !          1515:        } else {
        !          1516:                ATW_WRITE(sc, ATW_SYNRF, 0);
        !          1517:                DELAY(atw_bbp_io_disable_delay); /* shorter for some reason */
        !          1518:        }
        !          1519: }
        !          1520:
        !          1521: int
        !          1522: atw_tune(struct atw_softc *sc)
        !          1523: {
        !          1524:        int rc;
        !          1525:        u_int chan;
        !          1526:        struct ieee80211com *ic = &sc->sc_ic;
        !          1527:
        !          1528:        chan = ieee80211_chan2ieee(ic, ic->ic_bss->ni_chan);
        !          1529:        if (chan == 0 || chan == IEEE80211_CHAN_ANY)
        !          1530:                return 0;
        !          1531:
        !          1532:        if (chan == sc->sc_cur_chan)
        !          1533:                return 0;
        !          1534:
        !          1535:        DPRINTF(sc, ("%s: chan %d -> %d\n", sc->sc_dev.dv_xname,
        !          1536:            sc->sc_cur_chan, chan));
        !          1537:
        !          1538:        atw_idle(sc, ATW_NAR_SR|ATW_NAR_ST);
        !          1539:
        !          1540:        atw_si4126_tune(sc, chan);
        !          1541:        if ((rc = atw_rf3000_tune(sc, chan)) != 0)
        !          1542:                printf("%s: failed to tune channel %d\n", sc->sc_dev.dv_xname,
        !          1543:                    chan);
        !          1544:
        !          1545:        ATW_WRITE(sc, ATW_NAR, sc->sc_opmode);
        !          1546:        DELAY(20 * 1000);
        !          1547:        ATW_WRITE(sc, ATW_RDR, 0x1);
        !          1548:
        !          1549:        if (rc == 0)
        !          1550:                sc->sc_cur_chan = chan;
        !          1551:
        !          1552:        return rc;
        !          1553: }
        !          1554:
        !          1555: #ifdef ATW_SYNDEBUG
        !          1556: void
        !          1557: atw_si4126_print(struct atw_softc *sc)
        !          1558: {
        !          1559:        struct ifnet *ifp = &sc->sc_ic.ic_if;
        !          1560:        u_int addr, val;
        !          1561:
        !          1562:        if (atw_debug < 3 || (ifp->if_flags & IFF_DEBUG) == 0)
        !          1563:                return;
        !          1564:
        !          1565:        for (addr = 0; addr <= 8; addr++) {
        !          1566:                printf("%s: synth[%d] = ", sc->sc_dev.dv_xname, addr);
        !          1567:                if (atw_si4126_read(sc, addr, &val) == 0) {
        !          1568:                        printf("<unknown> (quitting print-out)\n");
        !          1569:                        break;
        !          1570:                }
        !          1571:                printf("%05x\n", val);
        !          1572:        }
        !          1573: }
        !          1574: #endif /* ATW_SYNDEBUG */
        !          1575:
        !          1576: /* Tune to channel chan by adjusting the Si4126 RF/IF synthesizer.
        !          1577:  *
        !          1578:  * The RF/IF synthesizer produces two reference frequencies for
        !          1579:  * the RF2948B transceiver.  The first frequency the RF2948B requires
        !          1580:  * is two times the so-called "intermediate frequency" (IF). Since
        !          1581:  * a SAW filter on the radio fixes the IF at 374MHz, I program the
        !          1582:  * Si4126 to generate IF LO = 374MHz x 2 = 748MHz.  The second
        !          1583:  * frequency required by the transceiver is the radio frequency
        !          1584:  * (RF). This is a superheterodyne transceiver; for f(chan) the
        !          1585:  * center frequency of the channel we are tuning, RF = f(chan) -
        !          1586:  * IF.
        !          1587:  *
        !          1588:  * XXX I am told by SiLabs that the Si4126 will accept a broader range
        !          1589:  * of XIN than the 2-25MHz mentioned by the datasheet, even *without*
        !          1590:  * XINDIV2 = 1.  I've tried this (it is necessary to double R) and it
        !          1591:  * works, but I have still programmed for XINDIV2 = 1 to be safe.
        !          1592:  */
        !          1593: void
        !          1594: atw_si4126_tune(struct atw_softc *sc, u_int chan)
        !          1595: {
        !          1596:        u_int mhz;
        !          1597:        u_int R;
        !          1598:        u_int32_t gpio;
        !          1599:        u_int16_t gain;
        !          1600:
        !          1601: #ifdef ATW_SYNDEBUG
        !          1602:        atw_si4126_print(sc);
        !          1603: #endif /* ATW_SYNDEBUG */
        !          1604:
        !          1605:        if (sc->sc_rev >= ATW_REVISION_BA) {
        !          1606:                atw_si4126_write(sc, SI4126_MAIN, 0x04007);
        !          1607:                atw_si4126_write(sc, SI4126_POWER, 0x00033);
        !          1608:                atw_si4126_write(sc, SI4126_IFN,
        !          1609:                    atw_rfmd2958_ifn[chan - 1]);
        !          1610:                atw_si4126_write(sc, SI4126_RF1R,
        !          1611:                    atw_rfmd2958_rf1r[chan - 1]);
        !          1612: #ifdef NOTYET
        !          1613:                /* set TX POWER? */
        !          1614:                atw_si4126_write(sc, 0x0a,
        !          1615:                    (sc->sc_srom[ATW_SR_CSR20] & mask) |
        !          1616:                    power << 9);
        !          1617: #endif
        !          1618:                /* set TX GAIN */
        !          1619:                atw_si4126_write(sc, 0x09, 0x00050 |
        !          1620:                    sc->sc_srom[ATW_SR_TXPOWER(chan - 1)]);
        !          1621:                /* wait 100us from power-up for RF, IF to settle */
        !          1622:                DELAY(100);
        !          1623:
        !          1624:                return;
        !          1625:        }
        !          1626:
        !          1627:        if (chan == 14)
        !          1628:                mhz = 2484;
        !          1629:        else
        !          1630:                mhz = 2412 + 5 * (chan - 1);
        !          1631:
        !          1632:        /* Tune IF to 748MHz to suit the IF LO input of the
        !          1633:         * RF2494B, which is 2 x IF. No need to set an IF divider
        !          1634:          * because an IF in 526MHz - 952MHz is allowed.
        !          1635:         *
        !          1636:         * XIN is 44.000MHz, so divide it by two to get allowable
        !          1637:         * range of 2-25MHz. SiLabs tells me that this is not
        !          1638:         * strictly necessary.
        !          1639:         */
        !          1640:
        !          1641:        if (atw_xindiv2)
        !          1642:                R = 44;
        !          1643:        else
        !          1644:                R = 88;
        !          1645:
        !          1646:        /* Power-up RF, IF synthesizers. */
        !          1647:        atw_si4126_write(sc, SI4126_POWER,
        !          1648:            SI4126_POWER_PDIB|SI4126_POWER_PDRB);
        !          1649:
        !          1650:        /* set LPWR, too? */
        !          1651:        atw_si4126_write(sc, SI4126_MAIN,
        !          1652:            (atw_xindiv2) ? SI4126_MAIN_XINDIV2 : 0);
        !          1653:
        !          1654:        /* Set the phase-locked loop gain.  If RF2 N > 2047, then
        !          1655:         * set KP2 to 1.
        !          1656:         *
        !          1657:         * REFDIF This is different from the reference driver, which
        !          1658:         * always sets SI4126_GAIN to 0.
        !          1659:         */
        !          1660:        gain = LSHIFT(((mhz - 374) > 2047) ? 1 : 0, SI4126_GAIN_KP2_MASK);
        !          1661:
        !          1662:        atw_si4126_write(sc, SI4126_GAIN, gain);
        !          1663:
        !          1664:        /* XIN = 44MHz.
        !          1665:         *
        !          1666:         * If XINDIV2 = 1, IF = N/(2 * R) * XIN.  I choose N = 1496,
        !          1667:         * R = 44 so that 1496/(2 * 44) * 44MHz = 748MHz.
        !          1668:         *
        !          1669:         * If XINDIV2 = 0, IF = N/R * XIN.  I choose N = 1496, R = 88
        !          1670:         * so that 1496/88 * 44MHz = 748MHz.
        !          1671:         */
        !          1672:        atw_si4126_write(sc, SI4126_IFN, 1496);
        !          1673:
        !          1674:        atw_si4126_write(sc, SI4126_IFR, R);
        !          1675:
        !          1676: #ifndef ATW_REFSLAVE
        !          1677:        /* Set RF1 arbitrarily. DO NOT configure RF1 after RF2, because
        !          1678:         * then RF1 becomes the active RF synthesizer, even on the Si4126,
        !          1679:         * which has no RF1!
        !          1680:         */
        !          1681:        atw_si4126_write(sc, SI4126_RF1R, R);
        !          1682:
        !          1683:        atw_si4126_write(sc, SI4126_RF1N, mhz - 374);
        !          1684: #endif
        !          1685:
        !          1686:        /* N/R * XIN = RF. XIN = 44MHz. We desire RF = mhz - IF,
        !          1687:         * where IF = 374MHz.  Let's divide XIN to 1MHz. So R = 44.
        !          1688:         * Now let's multiply it to mhz. So mhz - IF = N.
        !          1689:         */
        !          1690:        atw_si4126_write(sc, SI4126_RF2R, R);
        !          1691:
        !          1692:        atw_si4126_write(sc, SI4126_RF2N, mhz - 374);
        !          1693:
        !          1694:        /* wait 100us from power-up for RF, IF to settle */
        !          1695:        DELAY(100);
        !          1696:
        !          1697:        gpio = ATW_READ(sc, ATW_GPIO);
        !          1698:        gpio &= ~(ATW_GPIO_EN_MASK|ATW_GPIO_O_MASK|ATW_GPIO_I_MASK);
        !          1699:        gpio |= LSHIFT(1, ATW_GPIO_EN_MASK);
        !          1700:
        !          1701:        if ((sc->sc_if.if_flags & IFF_LINK1) != 0 && chan != 14) {
        !          1702:                /* Set a Prism RF front-end to a special mode for channel 14?
        !          1703:                 *
        !          1704:                 * Apparently the SMC2635W needs this, although I don't think
        !          1705:                 * it has a Prism RF.
        !          1706:                 */
        !          1707:                gpio |= LSHIFT(1, ATW_GPIO_O_MASK);
        !          1708:        }
        !          1709:        ATW_WRITE(sc, ATW_GPIO, gpio);
        !          1710:
        !          1711: #ifdef ATW_SYNDEBUG
        !          1712:        atw_si4126_print(sc);
        !          1713: #endif /* ATW_SYNDEBUG */
        !          1714: }
        !          1715:
        !          1716: /* Baseline initialization of RF3000 BBP: set CCA mode and enable antenna
        !          1717:  * diversity.
        !          1718:  *
        !          1719:  * !!!
        !          1720:  * !!! Call this w/ Tx/Rx suspended, atw_idle(, ATW_NAR_ST|ATW_NAR_SR).
        !          1721:  * !!!
        !          1722:  */
        !          1723: int
        !          1724: atw_rf3000_init(struct atw_softc *sc)
        !          1725: {
        !          1726:        int rc = 0;
        !          1727:
        !          1728:        atw_bbp_io_enable(sc, 1);
        !          1729:
        !          1730:        /* CCA is acquisition sensitive */
        !          1731:        rc = atw_rf3000_write(sc, RF3000_CCACTL,
        !          1732:            LSHIFT(RF3000_CCACTL_MODE_BOTH, RF3000_CCACTL_MODE_MASK));
        !          1733:
        !          1734:        if (rc != 0)
        !          1735:                goto out;
        !          1736:
        !          1737:        /* enable diversity */
        !          1738:        rc = atw_rf3000_write(sc, RF3000_DIVCTL, RF3000_DIVCTL_ENABLE);
        !          1739:
        !          1740:        if (rc != 0)
        !          1741:                goto out;
        !          1742:
        !          1743:        /* sensible setting from a binary-only driver */
        !          1744:        rc = atw_rf3000_write(sc, RF3000_GAINCTL,
        !          1745:            LSHIFT(0x1d, RF3000_GAINCTL_TXVGC_MASK));
        !          1746:
        !          1747:        if (rc != 0)
        !          1748:                goto out;
        !          1749:
        !          1750:        /* magic from a binary-only driver */
        !          1751:        rc = atw_rf3000_write(sc, RF3000_LOGAINCAL,
        !          1752:            LSHIFT(0x38, RF3000_LOGAINCAL_CAL_MASK));
        !          1753:
        !          1754:        if (rc != 0)
        !          1755:                goto out;
        !          1756:
        !          1757:        rc = atw_rf3000_write(sc, RF3000_HIGAINCAL, RF3000_HIGAINCAL_DSSSPAD);
        !          1758:
        !          1759:        if (rc != 0)
        !          1760:                goto out;
        !          1761:
        !          1762:        /*
        !          1763:         * XXX Reference driver remarks that Abocom sets this to 50.
        !          1764:         * Meaning 0x50, I think....  50 = 0x32, which would set a bit
        !          1765:         * in the "reserved" area of register RF3000_OPTIONS1.
        !          1766:         */
        !          1767:        rc = atw_rf3000_write(sc, RF3000_OPTIONS1, sc->sc_rf3000_options1);
        !          1768:
        !          1769:        if (rc != 0)
        !          1770:                goto out;
        !          1771:
        !          1772:        rc = atw_rf3000_write(sc, RF3000_OPTIONS2, sc->sc_rf3000_options2);
        !          1773:
        !          1774:        if (rc != 0)
        !          1775:                goto out;
        !          1776:
        !          1777: out:
        !          1778:        atw_bbp_io_enable(sc, 0);
        !          1779:        return rc;
        !          1780: }
        !          1781:
        !          1782: #ifdef ATW_BBPDEBUG
        !          1783: void
        !          1784: atw_rf3000_print(struct atw_softc *sc)
        !          1785: {
        !          1786:        struct ifnet *ifp = &sc->sc_ic.ic_if;
        !          1787:        u_int addr, val;
        !          1788:
        !          1789:        if (atw_debug < 3 || (ifp->if_flags & IFF_DEBUG) == 0)
        !          1790:                return;
        !          1791:
        !          1792:        for (addr = 0x01; addr <= 0x15; addr++) {
        !          1793:                printf("%s: bbp[%d] = \n", sc->sc_dev.dv_xname, addr);
        !          1794:                if (atw_rf3000_read(sc, addr, &val) != 0) {
        !          1795:                        printf("<unknown> (quitting print-out)\n");
        !          1796:                        break;
        !          1797:                }
        !          1798:                printf("%08x\n", val);
        !          1799:        }
        !          1800: }
        !          1801: #endif /* ATW_BBPDEBUG */
        !          1802:
        !          1803: /* Set the power settings on the BBP for channel `chan'. */
        !          1804: int
        !          1805: atw_rf3000_tune(struct atw_softc *sc, u_int chan)
        !          1806: {
        !          1807:        int rc = 0;
        !          1808:        u_int32_t reg;
        !          1809:        u_int16_t txpower, lpf_cutoff, lna_gs_thresh;
        !          1810:
        !          1811:        txpower = sc->sc_srom[ATW_SR_TXPOWER(chan)];
        !          1812:        lpf_cutoff = sc->sc_srom[ATW_SR_LPF_CUTOFF(chan)];
        !          1813:        lna_gs_thresh = sc->sc_srom[ATW_SR_LNA_GS_THRESH(chan)];
        !          1814:
        !          1815:        /* odd channels: LSB, even channels: MSB */
        !          1816:        if (chan % 2 == 1) {
        !          1817:                txpower &= 0xFF;
        !          1818:                lpf_cutoff &= 0xFF;
        !          1819:                lna_gs_thresh &= 0xFF;
        !          1820:        } else {
        !          1821:                txpower >>= 8;
        !          1822:                lpf_cutoff >>= 8;
        !          1823:                lna_gs_thresh >>= 8;
        !          1824:        }
        !          1825:
        !          1826: #ifdef ATW_BBPDEBUG
        !          1827:        atw_rf3000_print(sc);
        !          1828: #endif /* ATW_BBPDEBUG */
        !          1829:
        !          1830:        DPRINTF(sc, ("%s: chan %d txpower %02x, lpf_cutoff %02x, "
        !          1831:            "lna_gs_thresh %02x\n",
        !          1832:            sc->sc_dev.dv_xname, chan, txpower, lpf_cutoff, lna_gs_thresh));
        !          1833:
        !          1834:        atw_bbp_io_enable(sc, 1);
        !          1835:
        !          1836:        if ((rc = atw_rf3000_write(sc, RF3000_GAINCTL,
        !          1837:            LSHIFT(txpower, RF3000_GAINCTL_TXVGC_MASK))) != 0)
        !          1838:                goto out;
        !          1839:
        !          1840:        if ((rc = atw_rf3000_write(sc, RF3000_LOGAINCAL, lpf_cutoff)) != 0)
        !          1841:                goto out;
        !          1842:
        !          1843:        if ((rc = atw_rf3000_write(sc, RF3000_HIGAINCAL, lna_gs_thresh)) != 0)
        !          1844:                goto out;
        !          1845:
        !          1846:        if ((rc = atw_rf3000_write(sc, RF3000_OPTIONS1, 0x0)) != 0)
        !          1847:                goto out;
        !          1848:
        !          1849:        rc = atw_rf3000_write(sc, RF3000_OPTIONS2, RF3000_OPTIONS2_LNAGS_DELAY);
        !          1850:        if (rc != 0)
        !          1851:                goto out;
        !          1852:
        !          1853: #ifdef ATW_BBPDEBUG
        !          1854:        atw_rf3000_print(sc);
        !          1855: #endif /* ATW_BBPDEBUG */
        !          1856:
        !          1857: out:
        !          1858:        atw_bbp_io_enable(sc, 0);
        !          1859:
        !          1860:        /* set beacon, rts, atim transmit power */
        !          1861:        reg = ATW_READ(sc, ATW_PLCPHD);
        !          1862:        reg &= ~ATW_PLCPHD_SERVICE_MASK;
        !          1863:        reg |= LSHIFT(LSHIFT(txpower, RF3000_GAINCTL_TXVGC_MASK),
        !          1864:            ATW_PLCPHD_SERVICE_MASK);
        !          1865:        ATW_WRITE(sc, ATW_PLCPHD, reg);
        !          1866:        DELAY(2 * 1000);
        !          1867:
        !          1868:        return rc;
        !          1869: }
        !          1870:
        !          1871: /* Write a register on the RF3000 baseband processor using the
        !          1872:  * registers provided by the ADM8211 for this purpose.
        !          1873:  *
        !          1874:  * Return 0 on success.
        !          1875:  */
        !          1876: int
        !          1877: atw_rf3000_write(struct atw_softc *sc, u_int addr, u_int val)
        !          1878: {
        !          1879:        u_int32_t reg;
        !          1880:        int i;
        !          1881:
        !          1882:        reg = sc->sc_bbpctl_wr |
        !          1883:             LSHIFT(val & 0xff, ATW_BBPCTL_DATA_MASK) |
        !          1884:             LSHIFT(addr & 0x7f, ATW_BBPCTL_ADDR_MASK);
        !          1885:
        !          1886:        for (i = 10; --i >= 0; ) {
        !          1887:                ATW_WRITE(sc, ATW_BBPCTL, reg);
        !          1888:                DELAY(2000);
        !          1889:                if (ATW_ISSET(sc, ATW_BBPCTL, ATW_BBPCTL_WR) == 0)
        !          1890:                        break;
        !          1891:        }
        !          1892:
        !          1893:        if (i < 0) {
        !          1894:                printf("%s: BBPCTL still busy\n", sc->sc_dev.dv_xname);
        !          1895:                return ETIMEDOUT;
        !          1896:        }
        !          1897:        return 0;
        !          1898: }
        !          1899:
        !          1900: /* Read a register on the RF3000 baseband processor using the registers
        !          1901:  * the ADM8211 provides for this purpose.
        !          1902:  *
        !          1903:  * The 7-bit register address is addr.  Record the 8-bit data in the register
        !          1904:  * in *val.
        !          1905:  *
        !          1906:  * Return 0 on success.
        !          1907:  *
        !          1908:  * XXX This does not seem to work. The ADM8211 must require more or
        !          1909:  * different magic to read the chip than to write it. Possibly some
        !          1910:  * of the magic I have derived from a binary-only driver concerns
        !          1911:  * the "chip address" (see the RF3000 manual).
        !          1912:  */
        !          1913: #ifdef ATW_BBPDEBUG
        !          1914: int
        !          1915: atw_rf3000_read(struct atw_softc *sc, u_int addr, u_int *val)
        !          1916: {
        !          1917:        u_int32_t reg;
        !          1918:        int i;
        !          1919:
        !          1920:        for (i = 1000; --i >= 0; ) {
        !          1921:                if (ATW_ISSET(sc, ATW_BBPCTL, ATW_BBPCTL_RD|ATW_BBPCTL_WR) == 0)
        !          1922:                        break;
        !          1923:                DELAY(100);
        !          1924:        }
        !          1925:
        !          1926:        if (i < 0) {
        !          1927:                printf("%s: start atw_rf3000_read, BBPCTL busy\n",
        !          1928:                    sc->sc_dev.dv_xname);
        !          1929:                return ETIMEDOUT;
        !          1930:        }
        !          1931:
        !          1932:        reg = sc->sc_bbpctl_rd | LSHIFT(addr & 0x7f, ATW_BBPCTL_ADDR_MASK);
        !          1933:
        !          1934:        ATW_WRITE(sc, ATW_BBPCTL, reg);
        !          1935:
        !          1936:        for (i = 1000; --i >= 0; ) {
        !          1937:                DELAY(100);
        !          1938:                if (ATW_ISSET(sc, ATW_BBPCTL, ATW_BBPCTL_RD) == 0)
        !          1939:                        break;
        !          1940:        }
        !          1941:
        !          1942:        ATW_CLR(sc, ATW_BBPCTL, ATW_BBPCTL_RD);
        !          1943:
        !          1944:        if (i < 0) {
        !          1945:                printf("%s: atw_rf3000_read wrote %08x; BBPCTL still busy\n",
        !          1946:                    sc->sc_dev.dv_xname, reg);
        !          1947:                return ETIMEDOUT;
        !          1948:        }
        !          1949:        if (val != NULL)
        !          1950:                *val = MASK_AND_RSHIFT(reg, ATW_BBPCTL_DATA_MASK);
        !          1951:        return 0;
        !          1952: }
        !          1953: #endif /* ATW_BBPDEBUG */
        !          1954:
        !          1955: /* Write a register on the Si4126 RF/IF synthesizer using the registers
        !          1956:  * provided by the ADM8211 for that purpose.
        !          1957:  *
        !          1958:  * val is 18 bits of data, and val is the 4-bit address of the register.
        !          1959:  *
        !          1960:  * Return 0 on success.
        !          1961:  */
        !          1962: void
        !          1963: atw_si4126_write(struct atw_softc *sc, u_int addr, u_int val)
        !          1964: {
        !          1965:        uint32_t bits, mask, reg;
        !          1966:        int nbits;
        !          1967:
        !          1968:        if (sc->sc_rev >= ATW_REVISION_BA) {
        !          1969:                nbits = 24;
        !          1970:
        !          1971:                val &= 0x3ffff;
        !          1972:                addr &= 0x1f;
        !          1973:                bits = val | (addr << 18);
        !          1974:        } else {
        !          1975:                nbits = 22;
        !          1976:
        !          1977:                KASSERT((addr & ~PRESHIFT(SI4126_TWI_ADDR_MASK)) == 0);
        !          1978:                KASSERT((val & ~PRESHIFT(SI4126_TWI_DATA_MASK)) == 0);
        !          1979:
        !          1980:                bits = LSHIFT(val, SI4126_TWI_DATA_MASK) |
        !          1981:                    LSHIFT(addr, SI4126_TWI_ADDR_MASK);
        !          1982:        }
        !          1983:
        !          1984:        reg = ATW_SYNRF_SELSYN;
        !          1985:        /* reference driver: reset Si4126 serial bus to initial
        !          1986:         * conditions?
        !          1987:         */
        !          1988:        ATW_WRITE(sc, ATW_SYNRF, reg | ATW_SYNRF_LEIF);
        !          1989:        ATW_WRITE(sc, ATW_SYNRF, reg);
        !          1990:
        !          1991:        for (mask = BIT(nbits - 1); mask != 0; mask >>= 1) {
        !          1992:                if ((bits & mask) != 0)
        !          1993:                        reg |= ATW_SYNRF_SYNDATA;
        !          1994:                else
        !          1995:                        reg &= ~ATW_SYNRF_SYNDATA;
        !          1996:                ATW_WRITE(sc, ATW_SYNRF, reg);
        !          1997:                ATW_WRITE(sc, ATW_SYNRF, reg | ATW_SYNRF_SYNCLK);
        !          1998:                ATW_WRITE(sc, ATW_SYNRF, reg);
        !          1999:        }
        !          2000:        ATW_WRITE(sc, ATW_SYNRF, reg | ATW_SYNRF_LEIF);
        !          2001:        ATW_WRITE(sc, ATW_SYNRF, 0x0);
        !          2002: }
        !          2003:
        !          2004: /* Read 18-bit data from the 4-bit address addr in Si4126
        !          2005:  * RF synthesizer and write the data to *val. Return 0 on success.
        !          2006:  *
        !          2007:  * XXX This does not seem to work. The ADM8211 must require more or
        !          2008:  * different magic to read the chip than to write it.
        !          2009:  */
        !          2010: #ifdef ATW_SYNDEBUG
        !          2011: int
        !          2012: atw_si4126_read(struct atw_softc *sc, u_int addr, u_int *val)
        !          2013: {
        !          2014:        u_int32_t reg;
        !          2015:        int i;
        !          2016:
        !          2017:        KASSERT((addr & ~PRESHIFT(SI4126_TWI_ADDR_MASK)) == 0);
        !          2018:
        !          2019:        for (i = 1000; --i >= 0; ) {
        !          2020:                if (ATW_ISSET(sc, ATW_SYNCTL, ATW_SYNCTL_RD|ATW_SYNCTL_WR) == 0)
        !          2021:                        break;
        !          2022:                DELAY(100);
        !          2023:        }
        !          2024:
        !          2025:        if (i < 0) {
        !          2026:                printf("%s: start atw_si4126_read, SYNCTL busy\n",
        !          2027:                    sc->sc_dev.dv_xname);
        !          2028:                return ETIMEDOUT;
        !          2029:        }
        !          2030:
        !          2031:        reg = sc->sc_synctl_rd | LSHIFT(addr, ATW_SYNCTL_DATA_MASK);
        !          2032:
        !          2033:        ATW_WRITE(sc, ATW_SYNCTL, reg);
        !          2034:
        !          2035:        for (i = 1000; --i >= 0; ) {
        !          2036:                DELAY(100);
        !          2037:                if (ATW_ISSET(sc, ATW_SYNCTL, ATW_SYNCTL_RD) == 0)
        !          2038:                        break;
        !          2039:        }
        !          2040:
        !          2041:        ATW_CLR(sc, ATW_SYNCTL, ATW_SYNCTL_RD);
        !          2042:
        !          2043:        if (i < 0) {
        !          2044:                printf("%s: atw_si4126_read wrote %#08x, SYNCTL still busy\n",
        !          2045:                    sc->sc_dev.dv_xname, reg);
        !          2046:                return ETIMEDOUT;
        !          2047:        }
        !          2048:        if (val != NULL)
        !          2049:                *val = MASK_AND_RSHIFT(ATW_READ(sc, ATW_SYNCTL),
        !          2050:                                       ATW_SYNCTL_DATA_MASK);
        !          2051:        return 0;
        !          2052: }
        !          2053: #endif /* ATW_SYNDEBUG */
        !          2054:
        !          2055: /* XXX is the endianness correct? test. */
        !          2056: #define        atw_calchash(addr) \
        !          2057:        (ether_crc32_le((addr), IEEE80211_ADDR_LEN) & BITS(5, 0))
        !          2058:
        !          2059: /*
        !          2060:  * atw_filter_setup:
        !          2061:  *
        !          2062:  *     Set the ADM8211's receive filter.
        !          2063:  */
        !          2064: void
        !          2065: atw_filter_setup(struct atw_softc *sc)
        !          2066: {
        !          2067:        struct ieee80211com *ic = &sc->sc_ic;
        !          2068: #if defined(__OpenBSD__)
        !          2069:        struct arpcom *ec = &ic->ic_ac;
        !          2070: #else
        !          2071:        struct ethercom *ec = &ic->ic_ec;
        !          2072: #endif
        !          2073:        struct ifnet *ifp = &sc->sc_ic.ic_if;
        !          2074:        int hash;
        !          2075:        u_int32_t hashes[2];
        !          2076:        struct ether_multi *enm;
        !          2077:        struct ether_multistep step;
        !          2078:
        !          2079:        /* According to comments in tlp_al981_filter_setup
        !          2080:         * (dev/ic/tulip.c) the ADMtek AL981 does not like for its
        !          2081:         * multicast filter to be set while it is running.  Hopefully
        !          2082:         * the ADM8211 is not the same!
        !          2083:         */
        !          2084:        if ((ifp->if_flags & IFF_RUNNING) != 0)
        !          2085:                atw_idle(sc, ATW_NAR_SR);
        !          2086:
        !          2087:        sc->sc_opmode &= ~(ATW_NAR_PR|ATW_NAR_MM);
        !          2088:
        !          2089:        /* XXX in scan mode, do not filter packets.  Maybe this is
        !          2090:         * unnecessary.
        !          2091:         */
        !          2092:        if (ic->ic_state == IEEE80211_S_SCAN ||
        !          2093:            (ifp->if_flags & IFF_PROMISC) != 0) {
        !          2094:                sc->sc_opmode |= ATW_NAR_PR;
        !          2095:                goto allmulti;
        !          2096:        }
        !          2097:
        !          2098:        hashes[0] = hashes[1] = 0x0;
        !          2099:
        !          2100:        /*
        !          2101:         * Program the 64-bit multicast hash filter.
        !          2102:         */
        !          2103:        ETHER_FIRST_MULTI(step, ec, enm);
        !          2104:        while (enm != NULL) {
        !          2105:                if (memcmp(enm->enm_addrlo, enm->enm_addrhi,
        !          2106:                    ETHER_ADDR_LEN) != 0)
        !          2107:                        goto allmulti;
        !          2108:
        !          2109:                hash = atw_calchash(enm->enm_addrlo);
        !          2110:                hashes[hash >> 5] |= 1 << (hash & 0x1f);
        !          2111:                ETHER_NEXT_MULTI(step, enm);
        !          2112:                sc->sc_opmode |= ATW_NAR_MM;
        !          2113:        }
        !          2114:        ifp->if_flags &= ~IFF_ALLMULTI;
        !          2115:        goto setit;
        !          2116:
        !          2117: allmulti:
        !          2118:        sc->sc_opmode |= ATW_NAR_MM;
        !          2119:        ifp->if_flags |= IFF_ALLMULTI;
        !          2120:        hashes[0] = hashes[1] = 0xffffffff;
        !          2121:
        !          2122: setit:
        !          2123:        ATW_WRITE(sc, ATW_MAR0, hashes[0]);
        !          2124:        ATW_WRITE(sc, ATW_MAR1, hashes[1]);
        !          2125:        ATW_WRITE(sc, ATW_NAR, sc->sc_opmode);
        !          2126:        DELAY(20 * 1000);
        !          2127:        ATW_WRITE(sc, ATW_RDR, 0x1);
        !          2128:
        !          2129:        DPRINTF(sc, ("%s: ATW_NAR %08x opmode %08x\n", sc->sc_dev.dv_xname,
        !          2130:            ATW_READ(sc, ATW_NAR), sc->sc_opmode));
        !          2131: }
        !          2132:
        !          2133: /* Tell the ADM8211 our preferred BSSID. The ADM8211 must match
        !          2134:  * a beacon's BSSID and SSID against the preferred BSSID and SSID
        !          2135:  * before it will raise ATW_INTR_LINKON. When the ADM8211 receives
        !          2136:  * no beacon with the preferred BSSID and SSID in the number of
        !          2137:  * beacon intervals given in ATW_BPLI, then it raises ATW_INTR_LINKOFF.
        !          2138:  */
        !          2139: void
        !          2140: atw_write_bssid(struct atw_softc *sc)
        !          2141: {
        !          2142:        struct ieee80211com *ic = &sc->sc_ic;
        !          2143:        u_int8_t *bssid;
        !          2144:
        !          2145:        bssid = ic->ic_bss->ni_bssid;
        !          2146:
        !          2147:        ATW_WRITE(sc, ATW_BSSID0,
        !          2148:            LSHIFT(bssid[0], ATW_BSSID0_BSSIDB0_MASK) |
        !          2149:            LSHIFT(bssid[1], ATW_BSSID0_BSSIDB1_MASK) |
        !          2150:            LSHIFT(bssid[2], ATW_BSSID0_BSSIDB2_MASK) |
        !          2151:            LSHIFT(bssid[3], ATW_BSSID0_BSSIDB3_MASK));
        !          2152:
        !          2153:        ATW_WRITE(sc, ATW_ABDA1,
        !          2154:            (ATW_READ(sc, ATW_ABDA1) &
        !          2155:            ~(ATW_ABDA1_BSSIDB4_MASK|ATW_ABDA1_BSSIDB5_MASK)) |
        !          2156:            LSHIFT(bssid[4], ATW_ABDA1_BSSIDB4_MASK) |
        !          2157:            LSHIFT(bssid[5], ATW_ABDA1_BSSIDB5_MASK));
        !          2158:
        !          2159:        DPRINTF(sc, ("%s: BSSID %s -> ", sc->sc_dev.dv_xname,
        !          2160:            ether_sprintf(sc->sc_bssid)));
        !          2161:        DPRINTF(sc, ("%s\n", ether_sprintf(bssid)));
        !          2162:
        !          2163:        memcpy(sc->sc_bssid, bssid, sizeof(sc->sc_bssid));
        !          2164: }
        !          2165:
        !          2166: /* Write buflen bytes from buf to SRAM starting at the SRAM's ofs'th
        !          2167:  * 16-bit word.
        !          2168:  */
        !          2169: void
        !          2170: atw_write_sram(struct atw_softc *sc, u_int ofs, u_int8_t *buf, u_int buflen)
        !          2171: {
        !          2172:        u_int i;
        !          2173:        u_int8_t *ptr;
        !          2174:
        !          2175:        memcpy(&sc->sc_sram[ofs], buf, buflen);
        !          2176:
        !          2177:        KASSERT(ofs % 2 == 0 && buflen % 2 == 0);
        !          2178:
        !          2179:        KASSERT(buflen + ofs <= sc->sc_sramlen);
        !          2180:
        !          2181:        ptr = &sc->sc_sram[ofs];
        !          2182:
        !          2183:        for (i = 0; i < buflen; i += 2) {
        !          2184:                ATW_WRITE(sc, ATW_WEPCTL, ATW_WEPCTL_WR |
        !          2185:                    LSHIFT((ofs + i) / 2, ATW_WEPCTL_TBLADD_MASK));
        !          2186:                DELAY(atw_writewep_delay);
        !          2187:
        !          2188:                ATW_WRITE(sc, ATW_WESK,
        !          2189:                    LSHIFT((ptr[i + 1] << 8) | ptr[i], ATW_WESK_DATA_MASK));
        !          2190:                DELAY(atw_writewep_delay);
        !          2191:        }
        !          2192:        ATW_WRITE(sc, ATW_WEPCTL, sc->sc_wepctl); /* restore WEP condition */
        !          2193:
        !          2194:        if (sc->sc_if.if_flags & IFF_DEBUG) {
        !          2195:                int n_octets = 0;
        !          2196:                printf("%s: wrote %d bytes at 0x%x wepctl 0x%08x\n",
        !          2197:                    sc->sc_dev.dv_xname, buflen, ofs, sc->sc_wepctl);
        !          2198:                for (i = 0; i < buflen; i++) {
        !          2199:                        printf(" %02x", ptr[i]);
        !          2200:                        if (++n_octets % 24 == 0)
        !          2201:                                printf("\n");
        !          2202:                }
        !          2203:                if (n_octets % 24 != 0)
        !          2204:                        printf("\n");
        !          2205:        }
        !          2206: }
        !          2207:
        !          2208: /* Write WEP keys from the ieee80211com to the ADM8211's SRAM. */
        !          2209: void
        !          2210: atw_write_wep(struct atw_softc *sc)
        !          2211: {
        !          2212:        struct ieee80211com *ic = &sc->sc_ic;
        !          2213: #if 0
        !          2214:        u_int32_t reg;
        !          2215:        int i;
        !          2216: #endif
        !          2217:        /* SRAM shared-key record format: key0 flags key1 ... key12 */
        !          2218:        u_int8_t buf[IEEE80211_WEP_NKID]
        !          2219:                    [1 /* key[0] */ + 1 /* flags */ + 12 /* key[1 .. 12] */];
        !          2220:
        !          2221:        sc->sc_wepctl = 0;
        !          2222:        ATW_WRITE(sc, ATW_WEPCTL, sc->sc_wepctl);
        !          2223:
        !          2224:        if ((ic->ic_flags & IEEE80211_F_WEPON) == 0)
        !          2225:                return;
        !          2226:
        !          2227:        memset(&buf[0][0], 0, sizeof(buf));
        !          2228:
        !          2229: #if 0
        !          2230:        for (i = 0; i < IEEE80211_WEP_NKID; i++) {
        !          2231:                if (ic->ic_nw_keys[i].k_len > 5) {
        !          2232:                        buf[i][1] = ATW_WEP_ENABLED | ATW_WEP_104BIT;
        !          2233:                } else if (ic->ic_nw_keys[i].k_len != 0) {
        !          2234:                        buf[i][1] = ATW_WEP_ENABLED;
        !          2235:                } else {
        !          2236:                        buf[i][1] = 0;
        !          2237:                        continue;
        !          2238:                }
        !          2239:                buf[i][0] = ic->ic_nw_keys[i].k_key[0];
        !          2240:                memcpy(&buf[i][2], &ic->ic_nw_keys[i].k_key[1],
        !          2241:                    ic->ic_nw_keys[i].k_len - 1);
        !          2242:        }
        !          2243:
        !          2244:        reg = ATW_READ(sc, ATW_MACTEST);
        !          2245:        reg |= ATW_MACTEST_MMI_USETXCLK | ATW_MACTEST_FORCE_KEYID;
        !          2246:        reg &= ~ATW_MACTEST_KEYID_MASK;
        !          2247:        reg |= LSHIFT(ic->ic_wep_txkey, ATW_MACTEST_KEYID_MASK);
        !          2248:        ATW_WRITE(sc, ATW_MACTEST, reg);
        !          2249:
        !          2250:        sc->sc_wepctl = ATW_WEPCTL_WEPENABLE;
        !          2251:
        !          2252:        switch (sc->sc_rev) {
        !          2253:        case ATW_REVISION_AB:
        !          2254:        case ATW_REVISION_AF:
        !          2255:                /* Bypass WEP on Rx. */
        !          2256:                sc->sc_wepctl |= ATW_WEPCTL_WEPRXBYP;
        !          2257:                break;
        !          2258:        default:
        !          2259:                break;
        !          2260:        }
        !          2261: #endif
        !          2262:
        !          2263:        atw_write_sram(sc, ATW_SRAM_ADDR_SHARED_KEY, (u_int8_t*)&buf[0][0],
        !          2264:            sizeof(buf));
        !          2265: }
        !          2266:
        !          2267: void
        !          2268: atw_change_ibss(struct atw_softc *sc)
        !          2269: {
        !          2270:        atw_predict_beacon(sc);
        !          2271:        atw_write_bssid(sc);
        !          2272:        atw_start_beacon(sc, 1);
        !          2273: }
        !          2274:
        !          2275: void
        !          2276: atw_recv_mgmt(struct ieee80211com *ic, struct mbuf *m,
        !          2277:     struct ieee80211_node *ni, int subtype, int rssi, u_int32_t rstamp)
        !          2278: {
        !          2279:        struct atw_softc *sc = (struct atw_softc*)ic->ic_softc;
        !          2280:
        !          2281:        /* The ADM8211A answers probe requests. */
        !          2282:        if (subtype == IEEE80211_FC0_SUBTYPE_PROBE_REQ &&
        !          2283:            sc->sc_rev < ATW_REVISION_BA)
        !          2284:                return;
        !          2285:
        !          2286:        (*sc->sc_recv_mgmt)(ic, m, ni, subtype, rssi, rstamp);
        !          2287:
        !          2288:        switch (subtype) {
        !          2289:        case IEEE80211_FC0_SUBTYPE_PROBE_RESP:
        !          2290:        case IEEE80211_FC0_SUBTYPE_BEACON:
        !          2291:                if (ic->ic_opmode != IEEE80211_M_IBSS ||
        !          2292:                    ic->ic_state != IEEE80211_S_RUN)
        !          2293:                        break;
        !          2294:                if (ieee80211_ibss_merge(ic, ni, atw_get_tsft(sc)) == ENETRESET)
        !          2295:                        atw_change_ibss(sc);
        !          2296:                break;
        !          2297:        default:
        !          2298:                break;
        !          2299:        }
        !          2300:        return;
        !          2301: }
        !          2302:
        !          2303: /* Write the SSID in the ieee80211com to the SRAM on the ADM8211.
        !          2304:  * In ad hoc mode, the SSID is written to the beacons sent by the
        !          2305:  * ADM8211. In both ad hoc and infrastructure mode, beacons received
        !          2306:  * with matching SSID affect ATW_INTR_LINKON/ATW_INTR_LINKOFF
        !          2307:  * indications.
        !          2308:  */
        !          2309: void
        !          2310: atw_write_ssid(struct atw_softc *sc)
        !          2311: {
        !          2312:        struct ieee80211com *ic = &sc->sc_ic;
        !          2313:        /* 34 bytes are reserved in ADM8211 SRAM for the SSID, but
        !          2314:         * it only expects the element length, not its ID.
        !          2315:         */
        !          2316:        u_int8_t buf[roundup(1 /* length */ + IEEE80211_NWID_LEN, 2)];
        !          2317:
        !          2318:        memset(buf, 0, sizeof(buf));
        !          2319:        buf[0] = ic->ic_bss->ni_esslen;
        !          2320:        memcpy(&buf[1], ic->ic_bss->ni_essid, ic->ic_bss->ni_esslen);
        !          2321:
        !          2322:        atw_write_sram(sc, ATW_SRAM_ADDR_SSID, buf,
        !          2323:            roundup(1 + ic->ic_bss->ni_esslen, 2));
        !          2324: }
        !          2325:
        !          2326: /* Write the supported rates in the ieee80211com to the SRAM of the ADM8211.
        !          2327:  * In ad hoc mode, the supported rates are written to beacons sent by the
        !          2328:  * ADM8211.
        !          2329:  */
        !          2330: void
        !          2331: atw_write_sup_rates(struct atw_softc *sc)
        !          2332: {
        !          2333:        struct ieee80211com *ic = &sc->sc_ic;
        !          2334:        /* 14 bytes are probably (XXX) reserved in the ADM8211 SRAM for
        !          2335:         * supported rates
        !          2336:         */
        !          2337:        u_int8_t buf[roundup(1 /* length */ + IEEE80211_RATE_SIZE, 2)];
        !          2338:
        !          2339:        memset(buf, 0, sizeof(buf));
        !          2340:        buf[0] = ic->ic_bss->ni_rates.rs_nrates;
        !          2341:        memcpy(&buf[1], ic->ic_bss->ni_rates.rs_rates,
        !          2342:            ic->ic_bss->ni_rates.rs_nrates);
        !          2343:
        !          2344:        /* XXX deal with rev BA bug linux driver talks of? */
        !          2345:
        !          2346:        atw_write_sram(sc, ATW_SRAM_ADDR_SUPRATES, buf, sizeof(buf));
        !          2347: }
        !          2348:
        !          2349: /* Start/stop sending beacons. */
        !          2350: void
        !          2351: atw_start_beacon(struct atw_softc *sc, int start)
        !          2352: {
        !          2353:        struct ieee80211com *ic = &sc->sc_ic;
        !          2354:        uint16_t chan;
        !          2355:        uint32_t bcnt, bpli, cap0, cap1, capinfo;
        !          2356:        size_t len;
        !          2357:
        !          2358:        if (ATW_IS_ENABLED(sc) == 0)
        !          2359:                return;
        !          2360:
        !          2361:        /* start beacons */
        !          2362:        len = sizeof(struct ieee80211_frame) +
        !          2363:            8 /* timestamp */ + 2 /* beacon interval */ +
        !          2364:            2 /* capability info */ +
        !          2365:            2 + ic->ic_bss->ni_esslen /* SSID element */ +
        !          2366:            2 + ic->ic_bss->ni_rates.rs_nrates /* rates element */ +
        !          2367:            3 /* DS parameters */ +
        !          2368:            IEEE80211_CRC_LEN;
        !          2369:
        !          2370:        bcnt = ATW_READ(sc, ATW_BCNT) & ~ATW_BCNT_BCNT_MASK;
        !          2371:        cap0 = ATW_READ(sc, ATW_CAP0) & ~ATW_CAP0_CHN_MASK;
        !          2372:        cap1 = ATW_READ(sc, ATW_CAP1) & ~ATW_CAP1_CAPI_MASK;
        !          2373:
        !          2374:        ATW_WRITE(sc, ATW_BCNT, bcnt);
        !          2375:        ATW_WRITE(sc, ATW_CAP1, cap1);
        !          2376:
        !          2377:        if (!start)
        !          2378:                return;
        !          2379:
        !          2380:        /* TBD use ni_capinfo */
        !          2381:
        !          2382:        capinfo = 0;
        !          2383:        if (sc->sc_flags & ATWF_SHORT_PREAMBLE)
        !          2384:                capinfo |= IEEE80211_CAPINFO_SHORT_PREAMBLE;
        !          2385:        if (ic->ic_flags & IEEE80211_F_WEPON)
        !          2386:                capinfo |= IEEE80211_CAPINFO_PRIVACY;
        !          2387:
        !          2388:        switch (ic->ic_opmode) {
        !          2389:        case IEEE80211_M_IBSS:
        !          2390:                len += 4; /* IBSS parameters */
        !          2391:                capinfo |= IEEE80211_CAPINFO_IBSS;
        !          2392:                break;
        !          2393:        case IEEE80211_M_HOSTAP:
        !          2394:                /* XXX 6-byte minimum TIM */
        !          2395:                len += atw_beacon_len_adjust;
        !          2396:                capinfo |= IEEE80211_CAPINFO_ESS;
        !          2397:                break;
        !          2398:        default:
        !          2399:                return;
        !          2400:        }
        !          2401:
        !          2402:        /* set listen interval
        !          2403:         * XXX do software units agree w/ hardware?
        !          2404:         */
        !          2405:        bpli = LSHIFT(ic->ic_bss->ni_intval, ATW_BPLI_BP_MASK) |
        !          2406:            LSHIFT(ic->ic_lintval / ic->ic_bss->ni_intval, ATW_BPLI_LI_MASK);
        !          2407:
        !          2408:        chan = ieee80211_chan2ieee(ic, ic->ic_bss->ni_chan);
        !          2409:
        !          2410:        bcnt |= LSHIFT(len, ATW_BCNT_BCNT_MASK);
        !          2411:        cap0 |= LSHIFT(chan, ATW_CAP0_CHN_MASK);
        !          2412:        cap1 |= LSHIFT(capinfo, ATW_CAP1_CAPI_MASK);
        !          2413:
        !          2414:        ATW_WRITE(sc, ATW_BCNT, bcnt);
        !          2415:        ATW_WRITE(sc, ATW_BPLI, bpli);
        !          2416:        ATW_WRITE(sc, ATW_CAP0, cap0);
        !          2417:        ATW_WRITE(sc, ATW_CAP1, cap1);
        !          2418:
        !          2419:        DPRINTF(sc, ("%s: atw_start_beacon reg[ATW_BCNT] = %08x\n",
        !          2420:            sc->sc_dev.dv_xname, bcnt));
        !          2421:        DPRINTF(sc, ("%s: atw_start_beacon reg[ATW_CAP1] = %08x\n",
        !          2422:            sc->sc_dev.dv_xname, cap1));
        !          2423: }
        !          2424:
        !          2425: /* Return the 32 lsb of the last TSFT divisible by ival. */
        !          2426: static __inline uint32_t
        !          2427: atw_last_even_tsft(uint32_t tsfth, uint32_t tsftl, uint32_t ival)
        !          2428: {
        !          2429:        /* Following the reference driver's lead, I compute
        !          2430:         *
        !          2431:         *   (uint32_t)((((uint64_t)tsfth << 32) | tsftl) % ival)
        !          2432:         *
        !          2433:         * without using 64-bit arithmetic, using the following
        !          2434:         * relationship:
        !          2435:         *
        !          2436:         *     (0x100000000 * H + L) % m
        !          2437:         *   = ((0x100000000 % m) * H + L) % m
        !          2438:         *   = (((0xffffffff + 1) % m) * H + L) % m
        !          2439:         *   = ((0xffffffff % m + 1 % m) * H + L) % m
        !          2440:         *   = ((0xffffffff % m + 1) * H + L) % m
        !          2441:         */
        !          2442:        return ((0xFFFFFFFF % ival + 1) * tsfth + tsftl) % ival;
        !          2443: }
        !          2444:
        !          2445: uint64_t
        !          2446: atw_get_tsft(struct atw_softc *sc)
        !          2447: {
        !          2448:        int i;
        !          2449:        uint32_t tsfth, tsftl;
        !          2450:        for (i = 0; i < 2; i++) {
        !          2451:                tsfth = ATW_READ(sc, ATW_TSFTH);
        !          2452:                tsftl = ATW_READ(sc, ATW_TSFTL);
        !          2453:                if (ATW_READ(sc, ATW_TSFTH) == tsfth)
        !          2454:                        break;
        !          2455:        }
        !          2456:        return ((uint64_t)tsfth << 32) | tsftl;
        !          2457: }
        !          2458:
        !          2459: /* If we've created an IBSS, write the TSF time in the ADM8211 to
        !          2460:  * the ieee80211com.
        !          2461:  *
        !          2462:  * Predict the next target beacon transmission time (TBTT) and
        !          2463:  * write it to the ADM8211.
        !          2464:  */
        !          2465: void
        !          2466: atw_predict_beacon(struct atw_softc *sc)
        !          2467: {
        !          2468: #define TBTTOFS 20 /* TU */
        !          2469:
        !          2470:        struct ieee80211com *ic = &sc->sc_ic;
        !          2471:        uint64_t tsft;
        !          2472:        uint32_t ival, past_even, tbtt, tsfth, tsftl;
        !          2473:        union {
        !          2474:                uint64_t        word;
        !          2475:                uint8_t         tstamp[8];
        !          2476:        } u;
        !          2477:
        !          2478:        if ((ic->ic_opmode == IEEE80211_M_HOSTAP) ||
        !          2479:            ((ic->ic_opmode == IEEE80211_M_IBSS) &&
        !          2480:             (ic->ic_flags & IEEE80211_F_SIBSS))) {
        !          2481:                tsft = atw_get_tsft(sc);
        !          2482:                u.word = htole64(tsft);
        !          2483:                (void)memcpy(&ic->ic_bss->ni_tstamp[0], &u.tstamp[0],
        !          2484:                    sizeof(ic->ic_bss->ni_tstamp));
        !          2485:        } else {
        !          2486:                (void)memcpy(&u, &ic->ic_bss->ni_tstamp[0], sizeof(u));
        !          2487:                tsft = letoh64(u.word);
        !          2488:        }
        !          2489:
        !          2490:        ival = ic->ic_bss->ni_intval * IEEE80211_DUR_TU;
        !          2491:
        !          2492:        tsftl = tsft & 0xFFFFFFFF;
        !          2493:        tsfth = tsft >> 32;
        !          2494:
        !          2495:        /* We sent/received the last beacon `past' microseconds
        !          2496:         * after the interval divided the TSF timer.
        !          2497:         */
        !          2498:        past_even = tsftl - atw_last_even_tsft(tsfth, tsftl, ival);
        !          2499:
        !          2500:        /* Skip ten beacons so that the TBTT cannot pass before
        !          2501:         * we've programmed it.  Ten is an arbitrary number.
        !          2502:         */
        !          2503:        tbtt = past_even + ival * 10;
        !          2504:
        !          2505:        ATW_WRITE(sc, ATW_TOFS1,
        !          2506:            LSHIFT(1, ATW_TOFS1_TSFTOFSR_MASK) |
        !          2507:            LSHIFT(TBTTOFS, ATW_TOFS1_TBTTOFS_MASK) |
        !          2508:            LSHIFT(MASK_AND_RSHIFT(tbtt - TBTTOFS * IEEE80211_DUR_TU,
        !          2509:                ATW_TBTTPRE_MASK), ATW_TOFS1_TBTTPRE_MASK));
        !          2510: #undef TBTTOFS
        !          2511: }
        !          2512:
        !          2513: void
        !          2514: atw_next_scan(void *arg)
        !          2515: {
        !          2516:        struct atw_softc *sc = arg;
        !          2517:        struct ieee80211com *ic = &sc->sc_ic;
        !          2518:        struct ifnet *ifp = &ic->ic_if;
        !          2519:        int s;
        !          2520:
        !          2521:        /* don't call atw_start w/o network interrupts blocked */
        !          2522:        s = splnet();
        !          2523:        if (ic->ic_state == IEEE80211_S_SCAN)
        !          2524:                ieee80211_next_scan(ifp);
        !          2525:        splx(s);
        !          2526: }
        !          2527:
        !          2528: /* Synchronize the hardware state with the software state. */
        !          2529: int
        !          2530: atw_newstate(struct ieee80211com *ic, enum ieee80211_state nstate, int arg)
        !          2531: {
        !          2532:        struct ifnet *ifp = &ic->ic_if;
        !          2533:        struct atw_softc *sc = ifp->if_softc;
        !          2534:        enum ieee80211_state ostate = ic->ic_state;
        !          2535:        int error;
        !          2536:
        !          2537:        if (nstate == IEEE80211_S_INIT) {
        !          2538:                timeout_del(&sc->sc_scan_to);
        !          2539:                sc->sc_cur_chan = IEEE80211_CHAN_ANY;
        !          2540:                atw_start_beacon(sc, 0);
        !          2541:                return (*sc->sc_newstate)(ic, nstate, arg);
        !          2542:        }
        !          2543:
        !          2544:        if ((error = atw_tune(sc)) != 0)
        !          2545:                return error;
        !          2546:
        !          2547:        switch (nstate) {
        !          2548:        case IEEE80211_S_ASSOC:
        !          2549:                break;
        !          2550:        case IEEE80211_S_INIT:
        !          2551:                panic("%s: unexpected state IEEE80211_S_INIT", __func__);
        !          2552:                break;
        !          2553:        case IEEE80211_S_SCAN:
        !          2554:                timeout_add(&sc->sc_scan_to, atw_dwelltime * hz / 1000);
        !          2555:                break;
        !          2556:        case IEEE80211_S_RUN:
        !          2557:                if (ic->ic_opmode == IEEE80211_M_STA)
        !          2558:                        break;
        !          2559:                /*FALLTHROUGH*/
        !          2560:        case IEEE80211_S_AUTH:
        !          2561:                atw_write_bssid(sc);
        !          2562:                atw_write_ssid(sc);
        !          2563:                atw_write_sup_rates(sc);
        !          2564:
        !          2565:                if (ic->ic_opmode == IEEE80211_M_AHDEMO ||
        !          2566:                    ic->ic_opmode == IEEE80211_M_MONITOR)
        !          2567:                        break;
        !          2568:
        !          2569:                /* set listen interval
        !          2570:                 * XXX do software units agree w/ hardware?
        !          2571:                 */
        !          2572:                ATW_WRITE(sc, ATW_BPLI,
        !          2573:                    LSHIFT(ic->ic_bss->ni_intval, ATW_BPLI_BP_MASK) |
        !          2574:                    LSHIFT(ic->ic_lintval / ic->ic_bss->ni_intval,
        !          2575:                           ATW_BPLI_LI_MASK));
        !          2576:
        !          2577:                DPRINTF(sc, ("%s: reg[ATW_BPLI] = %08x\n",
        !          2578:                    sc->sc_dev.dv_xname, ATW_READ(sc, ATW_BPLI)));
        !          2579:
        !          2580:                atw_predict_beacon(sc);
        !          2581:                break;
        !          2582:        }
        !          2583:
        !          2584:        if (nstate != IEEE80211_S_SCAN)
        !          2585:                timeout_del(&sc->sc_scan_to);
        !          2586:
        !          2587:        if (nstate == IEEE80211_S_RUN &&
        !          2588:            (ic->ic_opmode == IEEE80211_M_HOSTAP ||
        !          2589:             ic->ic_opmode == IEEE80211_M_IBSS))
        !          2590:                atw_start_beacon(sc, 1);
        !          2591:        else
        !          2592:                atw_start_beacon(sc, 0);
        !          2593:
        !          2594:        error = (*sc->sc_newstate)(ic, nstate, arg);
        !          2595:
        !          2596:        if (ostate == IEEE80211_S_INIT && nstate == IEEE80211_S_SCAN)
        !          2597:                atw_write_bssid(sc);
        !          2598:
        !          2599:        return error;
        !          2600: }
        !          2601:
        !          2602: /*
        !          2603:  * atw_add_rxbuf:
        !          2604:  *
        !          2605:  *     Add a receive buffer to the indicated descriptor.
        !          2606:  */
        !          2607: int
        !          2608: atw_add_rxbuf(struct atw_softc *sc, int idx)
        !          2609: {
        !          2610:        struct atw_rxsoft *rxs = &sc->sc_rxsoft[idx];
        !          2611:        struct mbuf *m;
        !          2612:        int error;
        !          2613:
        !          2614:        MGETHDR(m, M_DONTWAIT, MT_DATA);
        !          2615:        if (m == NULL)
        !          2616:                return (ENOBUFS);
        !          2617:
        !          2618:        MCLGET(m, M_DONTWAIT);
        !          2619:        if ((m->m_flags & M_EXT) == 0) {
        !          2620:                m_freem(m);
        !          2621:                return (ENOBUFS);
        !          2622:        }
        !          2623:
        !          2624:        if (rxs->rxs_mbuf != NULL)
        !          2625:                bus_dmamap_unload(sc->sc_dmat, rxs->rxs_dmamap);
        !          2626:
        !          2627:        rxs->rxs_mbuf = m;
        !          2628:
        !          2629:        error = bus_dmamap_load(sc->sc_dmat, rxs->rxs_dmamap,
        !          2630:            m->m_ext.ext_buf, m->m_ext.ext_size, NULL,
        !          2631:            BUS_DMA_READ|BUS_DMA_NOWAIT);
        !          2632:        if (error) {
        !          2633:                printf("%s: can't load rx DMA map %d, error = %d\n",
        !          2634:                    sc->sc_dev.dv_xname, idx, error);
        !          2635:                panic("atw_add_rxbuf"); /* XXX */
        !          2636:        }
        !          2637:
        !          2638:        bus_dmamap_sync(sc->sc_dmat, rxs->rxs_dmamap, 0,
        !          2639:            rxs->rxs_dmamap->dm_mapsize, BUS_DMASYNC_PREREAD);
        !          2640:
        !          2641:        ATW_INIT_RXDESC(sc, idx);
        !          2642:
        !          2643:        return (0);
        !          2644: }
        !          2645:
        !          2646: /*
        !          2647:  * Release any queued transmit buffers.
        !          2648:  */
        !          2649: void
        !          2650: atw_txdrain(struct atw_softc *sc)
        !          2651: {
        !          2652:        struct atw_txsoft *txs;
        !          2653:
        !          2654:        while ((txs = SIMPLEQ_FIRST(&sc->sc_txdirtyq)) != NULL) {
        !          2655:                SIMPLEQ_REMOVE_HEAD(&sc->sc_txdirtyq, txs_q);
        !          2656:                if (txs->txs_mbuf != NULL) {
        !          2657:                        bus_dmamap_unload(sc->sc_dmat, txs->txs_dmamap);
        !          2658:                        m_freem(txs->txs_mbuf);
        !          2659:                        txs->txs_mbuf = NULL;
        !          2660:                }
        !          2661:                SIMPLEQ_INSERT_TAIL(&sc->sc_txfreeq, txs, txs_q);
        !          2662:        }
        !          2663:        sc->sc_tx_timer = 0;
        !          2664: }
        !          2665:
        !          2666: /*
        !          2667:  * atw_stop:           [ ifnet interface function ]
        !          2668:  *
        !          2669:  *     Stop transmission on the interface.
        !          2670:  */
        !          2671: void
        !          2672: atw_stop(struct ifnet *ifp, int disable)
        !          2673: {
        !          2674:        struct atw_softc *sc = ifp->if_softc;
        !          2675:        struct ieee80211com *ic = &sc->sc_ic;
        !          2676:
        !          2677:        ieee80211_new_state(ic, IEEE80211_S_INIT, -1);
        !          2678:
        !          2679:        /*
        !          2680:         * Mark the interface down and cancel the watchdog timer.
        !          2681:        */
        !          2682:        ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE);
        !          2683:        ifp->if_timer = 0;
        !          2684:
        !          2685:        /* Disable interrupts. */
        !          2686:        ATW_WRITE(sc, ATW_IER, 0);
        !          2687:
        !          2688:        /* Stop the transmit and receive processes. */
        !          2689:        sc->sc_opmode = 0;
        !          2690:        ATW_WRITE(sc, ATW_NAR, 0);
        !          2691:        DELAY(20 * 1000);
        !          2692:        ATW_WRITE(sc, ATW_TDBD, 0);
        !          2693:        ATW_WRITE(sc, ATW_TDBP, 0);
        !          2694:        ATW_WRITE(sc, ATW_RDB, 0);
        !          2695:
        !          2696:        atw_txdrain(sc);
        !          2697:
        !          2698:        if (disable) {
        !          2699:                atw_rxdrain(sc);
        !          2700:                atw_disable(sc);
        !          2701:        }
        !          2702:
        !          2703:        if (!disable)
        !          2704:                atw_reset(sc);
        !          2705: }
        !          2706:
        !          2707: /*
        !          2708:  * atw_rxdrain:
        !          2709:  *
        !          2710:  *     Drain the receive queue.
        !          2711:  */
        !          2712: void
        !          2713: atw_rxdrain(struct atw_softc *sc)
        !          2714: {
        !          2715:        struct atw_rxsoft *rxs;
        !          2716:        int i;
        !          2717:
        !          2718:        for (i = 0; i < ATW_NRXDESC; i++) {
        !          2719:                rxs = &sc->sc_rxsoft[i];
        !          2720:                if (rxs->rxs_mbuf == NULL)
        !          2721:                        continue;
        !          2722:                bus_dmamap_unload(sc->sc_dmat, rxs->rxs_dmamap);
        !          2723:                m_freem(rxs->rxs_mbuf);
        !          2724:                rxs->rxs_mbuf = NULL;
        !          2725:        }
        !          2726: }
        !          2727:
        !          2728: /*
        !          2729:  * atw_detach:
        !          2730:  *
        !          2731:  *     Detach an ADM8211 interface.
        !          2732:  */
        !          2733: int
        !          2734: atw_detach(struct atw_softc *sc)
        !          2735: {
        !          2736:        struct ifnet *ifp = &sc->sc_ic.ic_if;
        !          2737:        struct atw_rxsoft *rxs;
        !          2738:        struct atw_txsoft *txs;
        !          2739:        int i;
        !          2740:
        !          2741:        /*
        !          2742:         * Succeed now if there isn't any work to do.
        !          2743:         */
        !          2744:        if ((sc->sc_flags & ATWF_ATTACHED) == 0)
        !          2745:                return (0);
        !          2746:
        !          2747:        timeout_del(&sc->sc_scan_to);
        !          2748:
        !          2749:        ieee80211_ifdetach(ifp);
        !          2750:        if_detach(ifp);
        !          2751:
        !          2752:        for (i = 0; i < ATW_NRXDESC; i++) {
        !          2753:                rxs = &sc->sc_rxsoft[i];
        !          2754:                if (rxs->rxs_mbuf != NULL) {
        !          2755:                        bus_dmamap_unload(sc->sc_dmat, rxs->rxs_dmamap);
        !          2756:                        m_freem(rxs->rxs_mbuf);
        !          2757:                        rxs->rxs_mbuf = NULL;
        !          2758:                }
        !          2759:                bus_dmamap_destroy(sc->sc_dmat, rxs->rxs_dmamap);
        !          2760:        }
        !          2761:        for (i = 0; i < ATW_TXQUEUELEN; i++) {
        !          2762:                txs = &sc->sc_txsoft[i];
        !          2763:                if (txs->txs_mbuf != NULL) {
        !          2764:                        bus_dmamap_unload(sc->sc_dmat, txs->txs_dmamap);
        !          2765:                        m_freem(txs->txs_mbuf);
        !          2766:                        txs->txs_mbuf = NULL;
        !          2767:                }
        !          2768:                bus_dmamap_destroy(sc->sc_dmat, txs->txs_dmamap);
        !          2769:        }
        !          2770:        bus_dmamap_unload(sc->sc_dmat, sc->sc_cddmamap);
        !          2771:        bus_dmamap_destroy(sc->sc_dmat, sc->sc_cddmamap);
        !          2772:        bus_dmamem_unmap(sc->sc_dmat, (caddr_t)sc->sc_control_data,
        !          2773:            sizeof(struct atw_control_data));
        !          2774:        bus_dmamem_free(sc->sc_dmat, &sc->sc_cdseg, sc->sc_cdnseg);
        !          2775:
        !          2776:        if (sc->sc_sdhook != NULL)
        !          2777:                shutdownhook_disestablish(sc->sc_sdhook);
        !          2778:        if (sc->sc_powerhook != NULL)
        !          2779:                powerhook_disestablish(sc->sc_powerhook);
        !          2780:
        !          2781:        if (sc->sc_srom)
        !          2782:                free(sc->sc_srom, M_DEVBUF);
        !          2783:
        !          2784:        return (0);
        !          2785: }
        !          2786:
        !          2787: /* atw_shutdown: make sure the interface is stopped at reboot time. */
        !          2788: void
        !          2789: atw_shutdown(void *arg)
        !          2790: {
        !          2791:        struct atw_softc *sc = arg;
        !          2792:
        !          2793:        atw_stop(&sc->sc_ic.ic_if, 1);
        !          2794: }
        !          2795:
        !          2796: int
        !          2797: atw_intr(void *arg)
        !          2798: {
        !          2799:        struct atw_softc *sc = arg;
        !          2800:        struct ifnet *ifp = &sc->sc_ic.ic_if;
        !          2801:        u_int32_t status, rxstatus, txstatus, linkstatus;
        !          2802:        int handled = 0, txthresh;
        !          2803:
        !          2804: #ifdef DEBUG
        !          2805:        if (ATW_IS_ENABLED(sc) == 0)
        !          2806:                panic("%s: atw_intr: not enabled", sc->sc_dev.dv_xname);
        !          2807: #endif
        !          2808:
        !          2809:        /*
        !          2810:         * If the interface isn't running, the interrupt couldn't
        !          2811:         * possibly have come from us.
        !          2812:         */
        !          2813:        if ((ifp->if_flags & IFF_RUNNING) == 0 ||
        !          2814:            (sc->sc_dev.dv_flags & DVF_ACTIVE) == 0)
        !          2815:                return (0);
        !          2816:
        !          2817:        for (;;) {
        !          2818:                status = ATW_READ(sc, ATW_STSR);
        !          2819:
        !          2820:                if (status)
        !          2821:                        ATW_WRITE(sc, ATW_STSR, status);
        !          2822:
        !          2823: #ifdef ATW_DEBUG
        !          2824: #define PRINTINTR(flag) do { \
        !          2825:        if ((status & flag) != 0) { \
        !          2826:                printf("%s" #flag, delim); \
        !          2827:                delim = ","; \
        !          2828:        } \
        !          2829: } while (0)
        !          2830:
        !          2831:                if (atw_debug > 1 && status) {
        !          2832:                        const char *delim = "<";
        !          2833:
        !          2834:                        printf("%s: reg[STSR] = %x",
        !          2835:                            sc->sc_dev.dv_xname, status);
        !          2836:
        !          2837:                        PRINTINTR(ATW_INTR_FBE);
        !          2838:                        PRINTINTR(ATW_INTR_LINKOFF);
        !          2839:                        PRINTINTR(ATW_INTR_LINKON);
        !          2840:                        PRINTINTR(ATW_INTR_RCI);
        !          2841:                        PRINTINTR(ATW_INTR_RDU);
        !          2842:                        PRINTINTR(ATW_INTR_REIS);
        !          2843:                        PRINTINTR(ATW_INTR_RPS);
        !          2844:                        PRINTINTR(ATW_INTR_TCI);
        !          2845:                        PRINTINTR(ATW_INTR_TDU);
        !          2846:                        PRINTINTR(ATW_INTR_TLT);
        !          2847:                        PRINTINTR(ATW_INTR_TPS);
        !          2848:                        PRINTINTR(ATW_INTR_TRT);
        !          2849:                        PRINTINTR(ATW_INTR_TUF);
        !          2850:                        PRINTINTR(ATW_INTR_BCNTC);
        !          2851:                        PRINTINTR(ATW_INTR_ATIME);
        !          2852:                        PRINTINTR(ATW_INTR_TBTT);
        !          2853:                        PRINTINTR(ATW_INTR_TSCZ);
        !          2854:                        PRINTINTR(ATW_INTR_TSFTF);
        !          2855:                        printf(">\n");
        !          2856:                }
        !          2857: #undef PRINTINTR
        !          2858: #endif /* ATW_DEBUG */
        !          2859:
        !          2860:                if ((status & sc->sc_inten) == 0)
        !          2861:                        break;
        !          2862:
        !          2863:                handled = 1;
        !          2864:
        !          2865:                rxstatus = status & sc->sc_rxint_mask;
        !          2866:                txstatus = status & sc->sc_txint_mask;
        !          2867:                linkstatus = status & sc->sc_linkint_mask;
        !          2868:
        !          2869:                if (linkstatus) {
        !          2870:                        atw_linkintr(sc, linkstatus);
        !          2871:                }
        !          2872:
        !          2873:                if (rxstatus) {
        !          2874:                        /* Grab any new packets. */
        !          2875:                        atw_rxintr(sc);
        !          2876:
        !          2877:                        if (rxstatus & ATW_INTR_RDU) {
        !          2878:                                printf("%s: receive ring overrun\n",
        !          2879:                                    sc->sc_dev.dv_xname);
        !          2880:                                /* Get the receive process going again. */
        !          2881:                                ATW_WRITE(sc, ATW_RDR, 0x1);
        !          2882:                                break;
        !          2883:                        }
        !          2884:                }
        !          2885:
        !          2886:                if (txstatus) {
        !          2887:                        /* Sweep up transmit descriptors. */
        !          2888:                        atw_txintr(sc);
        !          2889:
        !          2890:                        if (txstatus & ATW_INTR_TLT)
        !          2891:                                DPRINTF(sc, ("%s: tx lifetime exceeded\n",
        !          2892:                                    sc->sc_dev.dv_xname));
        !          2893:
        !          2894:                        if (txstatus & ATW_INTR_TRT)
        !          2895:                                DPRINTF(sc, ("%s: tx retry limit exceeded\n",
        !          2896:                                    sc->sc_dev.dv_xname));
        !          2897:
        !          2898:                        /* If Tx under-run, increase our transmit threshold
        !          2899:                         * if another is available.
        !          2900:                         */
        !          2901:                        txthresh = sc->sc_txthresh + 1;
        !          2902:                        if ((txstatus & ATW_INTR_TUF) &&
        !          2903:                            sc->sc_txth[txthresh].txth_name != NULL) {
        !          2904:                                /* Idle the transmit process. */
        !          2905:                                atw_idle(sc, ATW_NAR_ST);
        !          2906:
        !          2907:                                sc->sc_txthresh = txthresh;
        !          2908:                                sc->sc_opmode &= ~(ATW_NAR_TR_MASK|ATW_NAR_SF);
        !          2909:                                sc->sc_opmode |=
        !          2910:                                    sc->sc_txth[txthresh].txth_opmode;
        !          2911:                                printf("%s: transmit underrun; new "
        !          2912:                                    "threshold: %s\n", sc->sc_dev.dv_xname,
        !          2913:                                    sc->sc_txth[txthresh].txth_name);
        !          2914:
        !          2915:                                /* Set the new threshold and restart
        !          2916:                                 * the transmit process.
        !          2917:                                 */
        !          2918:                                ATW_WRITE(sc, ATW_NAR, sc->sc_opmode);
        !          2919:                                DELAY(20 * 1000);
        !          2920:                                ATW_WRITE(sc, ATW_RDR, 0x1);
        !          2921:                                /* XXX Log every Nth underrun from
        !          2922:                                 * XXX now on?
        !          2923:                                 */
        !          2924:                        }
        !          2925:                }
        !          2926:
        !          2927:                if (status & (ATW_INTR_TPS|ATW_INTR_RPS)) {
        !          2928:                        if (status & ATW_INTR_TPS)
        !          2929:                                printf("%s: transmit process stopped\n",
        !          2930:                                    sc->sc_dev.dv_xname);
        !          2931:                        if (status & ATW_INTR_RPS)
        !          2932:                                printf("%s: receive process stopped\n",
        !          2933:                                    sc->sc_dev.dv_xname);
        !          2934:                        (void)atw_init(ifp);
        !          2935:                        break;
        !          2936:                }
        !          2937:
        !          2938:                if (status & ATW_INTR_FBE) {
        !          2939:                        printf("%s: fatal bus error\n", sc->sc_dev.dv_xname);
        !          2940:                        (void)atw_init(ifp);
        !          2941:                        break;
        !          2942:                }
        !          2943:
        !          2944:                /*
        !          2945:                 * Not handled:
        !          2946:                 *
        !          2947:                 *      Transmit buffer unavailable -- normal
        !          2948:                 *      condition, nothing to do, really.
        !          2949:                 *
        !          2950:                 *      Early receive interrupt -- not available on
        !          2951:                 *      all chips, we just use RI.  We also only
        !          2952:                 *      use single-segment receive DMA, so this
        !          2953:                 *      is mostly useless.
        !          2954:                 *
        !          2955:                 *      TBD others
        !          2956:                 */
        !          2957:        }
        !          2958:
        !          2959:        /* Try to get more packets going. */
        !          2960:        atw_start(ifp);
        !          2961:
        !          2962:        return (handled);
        !          2963: }
        !          2964:
        !          2965: /*
        !          2966:  * atw_idle:
        !          2967:  *
        !          2968:  *     Cause the transmit and/or receive processes to go idle.
        !          2969:  *
        !          2970:  *      XXX It seems that the ADM8211 will not signal the end of the Rx/Tx
        !          2971:  *     process in STSR if I clear SR or ST after the process has already
        !          2972:  *     ceased. Fair enough. But the Rx process status bits in ATW_TEST0
        !          2973:  *      do not seem to be too reliable. Perhaps I have the sense of the
        !          2974:  *     Rx bits switched with the Tx bits?
        !          2975:  */
        !          2976: void
        !          2977: atw_idle(struct atw_softc *sc, u_int32_t bits)
        !          2978: {
        !          2979:        u_int32_t ackmask = 0, opmode, stsr, test0;
        !          2980:        int i, s;
        !          2981:
        !          2982:        s = splnet();
        !          2983:
        !          2984:        opmode = sc->sc_opmode & ~bits;
        !          2985:
        !          2986:        if (bits & ATW_NAR_SR)
        !          2987:                ackmask |= ATW_INTR_RPS;
        !          2988:
        !          2989:        if (bits & ATW_NAR_ST) {
        !          2990:                ackmask |= ATW_INTR_TPS;
        !          2991:                /* set ATW_NAR_HF to flush TX FIFO. */
        !          2992:                opmode |= ATW_NAR_HF;
        !          2993:        }
        !          2994:
        !          2995:        ATW_WRITE(sc, ATW_NAR, opmode);
        !          2996:        DELAY(20 * 1000);
        !          2997:
        !          2998:        for (i = 0; i < 10; i++) {
        !          2999:                stsr = ATW_READ(sc, ATW_STSR);
        !          3000:                if ((stsr & ackmask) == ackmask)
        !          3001:                        break;
        !          3002:                DELAY(1000);
        !          3003:        }
        !          3004:
        !          3005:        ATW_WRITE(sc, ATW_STSR, stsr & ackmask);
        !          3006:
        !          3007:        if ((stsr & ackmask) == ackmask)
        !          3008:                goto out;
        !          3009:
        !          3010:        test0 = ATW_READ(sc, ATW_TEST0);
        !          3011:
        !          3012:        if ((bits & ATW_NAR_ST) != 0 && (stsr & ATW_INTR_TPS) == 0 &&
        !          3013:            (test0 & ATW_TEST0_TS_MASK) != ATW_TEST0_TS_STOPPED) {
        !          3014:                DPRINTF2(sc, ("%s: transmit process not idle [%s]\n",
        !          3015:                    sc->sc_dev.dv_xname,
        !          3016:                    atw_tx_state[MASK_AND_RSHIFT(test0, ATW_TEST0_TS_MASK)]));
        !          3017:                DPRINTF2(sc, ("%s: bits %08x test0 %08x stsr %08x\n",
        !          3018:                    sc->sc_dev.dv_xname, bits, test0, stsr));
        !          3019:        }
        !          3020:
        !          3021:        if ((bits & ATW_NAR_SR) != 0 && (stsr & ATW_INTR_RPS) == 0 &&
        !          3022:            (test0 & ATW_TEST0_RS_MASK) != ATW_TEST0_RS_STOPPED) {
        !          3023:                DPRINTF2(sc, ("%s: receive process not idle [%s]\n",
        !          3024:                    sc->sc_dev.dv_xname,
        !          3025:                    atw_rx_state[MASK_AND_RSHIFT(test0, ATW_TEST0_RS_MASK)]));
        !          3026:                DPRINTF2(sc, ("%s: bits %08x test0 %08x stsr %08x\n",
        !          3027:                    sc->sc_dev.dv_xname, bits, test0, stsr));
        !          3028:        }
        !          3029: out:
        !          3030:        if ((bits & ATW_NAR_ST) != 0)
        !          3031:                atw_txdrain(sc);
        !          3032:        splx(s);
        !          3033:        return;
        !          3034: }
        !          3035:
        !          3036: /*
        !          3037:  * atw_linkintr:
        !          3038:  *
        !          3039:  *     Helper; handle link-status interrupts.
        !          3040:  */
        !          3041: void
        !          3042: atw_linkintr(struct atw_softc *sc, u_int32_t linkstatus)
        !          3043: {
        !          3044:        struct ieee80211com *ic = &sc->sc_ic;
        !          3045:
        !          3046:        if (ic->ic_state != IEEE80211_S_RUN)
        !          3047:                return;
        !          3048:
        !          3049:        if (linkstatus & ATW_INTR_LINKON) {
        !          3050:                DPRINTF(sc, ("%s: link on\n", sc->sc_dev.dv_xname));
        !          3051:                sc->sc_rescan_timer = 0;
        !          3052:        } else if (linkstatus & ATW_INTR_LINKOFF) {
        !          3053:                DPRINTF(sc, ("%s: link off\n", sc->sc_dev.dv_xname));
        !          3054:                if (ic->ic_opmode != IEEE80211_M_STA)
        !          3055:                        return;
        !          3056:                sc->sc_rescan_timer = 3;
        !          3057:                ic->ic_if.if_timer = 1;
        !          3058:        }
        !          3059: }
        !          3060:
        !          3061: static __inline int
        !          3062: atw_hw_decrypted(struct atw_softc *sc, struct ieee80211_frame *wh)
        !          3063: {
        !          3064:        if ((sc->sc_ic.ic_flags & IEEE80211_F_WEPON) == 0)
        !          3065:                return 0;
        !          3066:        if ((wh->i_fc[1] & IEEE80211_FC1_WEP) == 0)
        !          3067:                return 0;
        !          3068:        return (sc->sc_wepctl & ATW_WEPCTL_WEPRXBYP) == 0;
        !          3069: }
        !          3070:
        !          3071: /*
        !          3072:  * atw_rxintr:
        !          3073:  *
        !          3074:  *     Helper; handle receive interrupts.
        !          3075:  */
        !          3076: void
        !          3077: atw_rxintr(struct atw_softc *sc)
        !          3078: {
        !          3079:        static int rate_tbl[] = {2, 4, 11, 22, 44};
        !          3080:        struct ieee80211com *ic = &sc->sc_ic;
        !          3081:        struct ieee80211_node *ni;
        !          3082:        struct ieee80211_frame *wh;
        !          3083:        struct ifnet *ifp = &ic->ic_if;
        !          3084:        struct atw_rxsoft *rxs;
        !          3085:        struct mbuf *m;
        !          3086:        u_int32_t rxstat;
        !          3087:        int i, len, rate, rate0;
        !          3088:        u_int32_t rssi, rssi0;
        !          3089:
        !          3090:        for (i = sc->sc_rxptr;; i = ATW_NEXTRX(i)) {
        !          3091:                rxs = &sc->sc_rxsoft[i];
        !          3092:
        !          3093:                ATW_CDRXSYNC(sc, i, BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE);
        !          3094:
        !          3095:                rxstat = letoh32(sc->sc_rxdescs[i].ar_stat);
        !          3096:                rssi0 = letoh32(sc->sc_rxdescs[i].ar_rssi);
        !          3097:                rate0 = MASK_AND_RSHIFT(rxstat, ATW_RXSTAT_RXDR_MASK);
        !          3098:
        !          3099:                if (rxstat & ATW_RXSTAT_OWN)
        !          3100:                        break; /* We have processed all receive buffers. */
        !          3101:
        !          3102:                DPRINTF3(sc,
        !          3103:                    ("%s: rx stat %08x rssi0 %08x buf1 %08x buf2 %08x\n",
        !          3104:                    sc->sc_dev.dv_xname,
        !          3105:                    rxstat, rssi0,
        !          3106:                    letoh32(sc->sc_rxdescs[i].ar_buf1),
        !          3107:                    letoh32(sc->sc_rxdescs[i].ar_buf2)));
        !          3108:
        !          3109:                /*
        !          3110:                 * Make sure the packet fits in one buffer.  This should
        !          3111:                 * always be the case.
        !          3112:                 */
        !          3113:                if ((rxstat & (ATW_RXSTAT_FS|ATW_RXSTAT_LS)) !=
        !          3114:                    (ATW_RXSTAT_FS|ATW_RXSTAT_LS)) {
        !          3115:                        printf("%s: incoming packet spilled, resetting\n",
        !          3116:                            sc->sc_dev.dv_xname);
        !          3117:                        (void)atw_init(ifp);
        !          3118:                        return;
        !          3119:                }
        !          3120:
        !          3121:                /*
        !          3122:                 * If an error occurred, update stats, clear the status
        !          3123:                 * word, and leave the packet buffer in place.  It will
        !          3124:                 * simply be reused the next time the ring comes around.
        !          3125:                 * If 802.1Q VLAN MTU is enabled, ignore the Frame Too Long
        !          3126:                 * error.
        !          3127:                 */
        !          3128:
        !          3129:                if ((rxstat & ATW_RXSTAT_ES) != 0 &&
        !          3130: #if defined(__OpenBSD__)
        !          3131:                    ((sc->sc_ic.ic_if.if_capabilities & IFCAP_VLAN_MTU) == 0 ||
        !          3132: #else
        !          3133:                    ((sc->sc_ic.ic_ec.ec_capenable & ETHERCAP_VLAN_MTU) == 0 ||
        !          3134: #endif
        !          3135:                     (rxstat & (ATW_RXSTAT_DE | ATW_RXSTAT_SFDE |
        !          3136:                                ATW_RXSTAT_SIGE | ATW_RXSTAT_CRC16E |
        !          3137:                                ATW_RXSTAT_RXTOE | ATW_RXSTAT_CRC32E |
        !          3138:                                ATW_RXSTAT_ICVE)) != 0)) {
        !          3139: #define        PRINTERR(bit, str)                                              \
        !          3140:                        if (rxstat & (bit))                             \
        !          3141:                                printf("%s: receive error: %s\n",       \
        !          3142:                                    sc->sc_dev.dv_xname, str)
        !          3143:                        ifp->if_ierrors++;
        !          3144:                        PRINTERR(ATW_RXSTAT_DE, "descriptor error");
        !          3145:                        PRINTERR(ATW_RXSTAT_SFDE, "PLCP SFD error");
        !          3146:                        PRINTERR(ATW_RXSTAT_SIGE, "PLCP signal error");
        !          3147:                        PRINTERR(ATW_RXSTAT_CRC16E, "PLCP CRC16 error");
        !          3148:                        PRINTERR(ATW_RXSTAT_RXTOE, "time-out");
        !          3149:                        PRINTERR(ATW_RXSTAT_CRC32E, "FCS error");
        !          3150:                        PRINTERR(ATW_RXSTAT_ICVE, "WEP ICV error");
        !          3151: #undef PRINTERR
        !          3152:                        ATW_INIT_RXDESC(sc, i);
        !          3153:                        continue;
        !          3154:                }
        !          3155:
        !          3156:                bus_dmamap_sync(sc->sc_dmat, rxs->rxs_dmamap, 0,
        !          3157:                    rxs->rxs_dmamap->dm_mapsize, BUS_DMASYNC_POSTREAD);
        !          3158:
        !          3159:                /*
        !          3160:                 * No errors; receive the packet.  Note the ADM8211
        !          3161:                 * includes the CRC in promiscuous mode.
        !          3162:                 */
        !          3163:                len = MASK_AND_RSHIFT(rxstat, ATW_RXSTAT_FL_MASK);
        !          3164:
        !          3165:                /*
        !          3166:                 * Allocate a new mbuf cluster.  If that fails, we are
        !          3167:                 * out of memory, and must drop the packet and recycle
        !          3168:                 * the buffer that's already attached to this descriptor.
        !          3169:                 */
        !          3170:                m = rxs->rxs_mbuf;
        !          3171:                if (atw_add_rxbuf(sc, i) != 0) {
        !          3172:                        ifp->if_ierrors++;
        !          3173:                        ATW_INIT_RXDESC(sc, i);
        !          3174:                        bus_dmamap_sync(sc->sc_dmat, rxs->rxs_dmamap, 0,
        !          3175:                            rxs->rxs_dmamap->dm_mapsize, BUS_DMASYNC_PREREAD);
        !          3176:                        continue;
        !          3177:                }
        !          3178:
        !          3179:                ifp->if_ipackets++;
        !          3180:                if (sc->sc_opmode & ATW_NAR_PR)
        !          3181:                        len -= IEEE80211_CRC_LEN;
        !          3182:                m->m_pkthdr.rcvif = ifp;
        !          3183:                m->m_pkthdr.len = m->m_len = MIN(m->m_ext.ext_size, len);
        !          3184:
        !          3185:                if (rate0 >= sizeof(rate_tbl) / sizeof(rate_tbl[0]))
        !          3186:                        rate = 0;
        !          3187:                else
        !          3188:                        rate = rate_tbl[rate0];
        !          3189:
        !          3190:                /* The RSSI comes straight from a register in the
        !          3191:                 * baseband processor.  I know that for the RF3000,
        !          3192:                 * the RSSI register also contains the antenna-selection
        !          3193:                 * bits.  Mask those off.
        !          3194:                 *
        !          3195:                 * TBD Treat other basebands.
        !          3196:                 */
        !          3197:                if (sc->sc_bbptype == ATW_BBPTYPE_RFMD)
        !          3198:                        rssi = rssi0 & RF3000_RSSI_MASK;
        !          3199:                else
        !          3200:                        rssi = rssi0;
        !          3201:
        !          3202: #if NBPFILTER > 0
        !          3203:                /* Pass this up to any BPF listeners. */
        !          3204:                if (sc->sc_radiobpf != NULL) {
        !          3205:                        struct mbuf mb;
        !          3206:
        !          3207:                        struct atw_rx_radiotap_header *tap = &sc->sc_rxtap;
        !          3208:
        !          3209:                        tap->ar_rate = rate;
        !          3210:                        tap->ar_chan_freq = ic->ic_bss->ni_chan->ic_freq;
        !          3211:                        tap->ar_chan_flags = ic->ic_bss->ni_chan->ic_flags;
        !          3212:
        !          3213:                        /* TBD verify units are dB */
        !          3214:                        tap->ar_antsignal = (int)rssi;
        !          3215:                        /* TBD tap->ar_flags */
        !          3216:
        !          3217:                        mb.m_data = (caddr_t)tap;
        !          3218:                        mb.m_len = tap->ar_ihdr.it_len;
        !          3219:                        mb.m_next = m;
        !          3220:                        mb.m_nextpkt = NULL;
        !          3221:                        mb.m_type = 0;
        !          3222:                        mb.m_flags = 0;
        !          3223:                        bpf_mtap(sc->sc_radiobpf, &mb, BPF_DIRECTION_IN);
        !          3224:                }
        !          3225: #endif /* NPBFILTER > 0 */
        !          3226:
        !          3227:                wh = mtod(m, struct ieee80211_frame *);
        !          3228:                ni = ieee80211_find_rxnode(ic, wh);
        !          3229: #if 0
        !          3230:                if (atw_hw_decrypted(sc, wh))
        !          3231:                        wh->i_fc[1] &= ~IEEE80211_FC1_WEP;
        !          3232: #endif
        !          3233:                ieee80211_input(ifp, m, ni, (int)rssi, 0);
        !          3234:                /*
        !          3235:                 * The frame may have caused the node to be marked for
        !          3236:                 * reclamation (e.g. in response to a DEAUTH message)
        !          3237:                 * so use release_node here instead of unref_node.
        !          3238:                 */
        !          3239:                ieee80211_release_node(ic, ni);
        !          3240:        }
        !          3241:
        !          3242:        /* Update the receive pointer. */
        !          3243:        sc->sc_rxptr = i;
        !          3244: }
        !          3245:
        !          3246: /*
        !          3247:  * atw_txintr:
        !          3248:  *
        !          3249:  *     Helper; handle transmit interrupts.
        !          3250:  */
        !          3251: void
        !          3252: atw_txintr(struct atw_softc *sc)
        !          3253: {
        !          3254: #define TXSTAT_ERRMASK (ATW_TXSTAT_TUF | ATW_TXSTAT_TLT | ATW_TXSTAT_TRT | \
        !          3255:     ATW_TXSTAT_TRO | ATW_TXSTAT_SOFBR)
        !          3256: #define TXSTAT_FMT "\20\31ATW_TXSTAT_SOFBR\32ATW_TXSTAT_TRO\33ATW_TXSTAT_TUF" \
        !          3257:     "\34ATW_TXSTAT_TRT\35ATW_TXSTAT_TLT"
        !          3258:        struct ifnet *ifp = &sc->sc_ic.ic_if;
        !          3259:        struct atw_txsoft *txs;
        !          3260:        u_int32_t txstat;
        !          3261:
        !          3262:        DPRINTF3(sc, ("%s: atw_txintr: sc_flags 0x%08x\n",
        !          3263:            sc->sc_dev.dv_xname, sc->sc_flags));
        !          3264:
        !          3265:        ifp->if_flags &= ~IFF_OACTIVE;
        !          3266:
        !          3267:        /*
        !          3268:         * Go through our Tx list and free mbufs for those
        !          3269:         * frames that have been transmitted.
        !          3270:         */
        !          3271:        while ((txs = SIMPLEQ_FIRST(&sc->sc_txdirtyq)) != NULL) {
        !          3272:                ATW_CDTXSYNC(sc, txs->txs_lastdesc, 1,
        !          3273:                    BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE);
        !          3274:
        !          3275: #ifdef ATW_DEBUG
        !          3276:                if ((ifp->if_flags & IFF_DEBUG) != 0 && atw_debug > 2) {
        !          3277:                        int i;
        !          3278:                        printf("    txsoft %p transmit chain:\n", txs);
        !          3279:                        ATW_CDTXSYNC(sc, txs->txs_firstdesc,
        !          3280:                            txs->txs_ndescs - 1,
        !          3281:                            BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE);
        !          3282:                        for (i = txs->txs_firstdesc;; i = ATW_NEXTTX(i)) {
        !          3283:                                printf("     descriptor %d:\n", i);
        !          3284:                                printf("       at_status:   0x%08x\n",
        !          3285:                                    letoh32(sc->sc_txdescs[i].at_stat));
        !          3286:                                printf("       at_flags:      0x%08x\n",
        !          3287:                                    letoh32(sc->sc_txdescs[i].at_flags));
        !          3288:                                printf("       at_buf1: 0x%08x\n",
        !          3289:                                    letoh32(sc->sc_txdescs[i].at_buf1));
        !          3290:                                printf("       at_buf2: 0x%08x\n",
        !          3291:                                    letoh32(sc->sc_txdescs[i].at_buf2));
        !          3292:                                if (i == txs->txs_lastdesc)
        !          3293:                                        break;
        !          3294:                        }
        !          3295:                }
        !          3296: #endif
        !          3297:
        !          3298:                txstat = letoh32(sc->sc_txdescs[txs->txs_lastdesc].at_stat);
        !          3299:                if (txstat & ATW_TXSTAT_OWN)
        !          3300:                        break;
        !          3301:
        !          3302:                SIMPLEQ_REMOVE_HEAD(&sc->sc_txdirtyq, txs_q);
        !          3303:
        !          3304:                sc->sc_txfree += txs->txs_ndescs;
        !          3305:
        !          3306:                bus_dmamap_sync(sc->sc_dmat, txs->txs_dmamap,
        !          3307:                    0, txs->txs_dmamap->dm_mapsize,
        !          3308:                    BUS_DMASYNC_POSTWRITE);
        !          3309:                bus_dmamap_unload(sc->sc_dmat, txs->txs_dmamap);
        !          3310:                m_freem(txs->txs_mbuf);
        !          3311:                txs->txs_mbuf = NULL;
        !          3312:
        !          3313:                SIMPLEQ_INSERT_TAIL(&sc->sc_txfreeq, txs, txs_q);
        !          3314:
        !          3315:                if ((ifp->if_flags & IFF_DEBUG) != 0 &&
        !          3316:                    (txstat & TXSTAT_ERRMASK) != 0) {
        !          3317: #if defined(__OpenBSD__)
        !          3318:                        printf("%s: txstat %b %d\n", sc->sc_dev.dv_xname,
        !          3319:                            txstat & TXSTAT_ERRMASK, TXSTAT_FMT,
        !          3320:                            MASK_AND_RSHIFT(txstat, ATW_TXSTAT_ARC_MASK));
        !          3321: #else
        !          3322:                        static char txstat_buf[sizeof("ffffffff<>" TXSTAT_FMT)];
        !          3323:                        bitmask_snprintf(txstat & TXSTAT_ERRMASK, TXSTAT_FMT,
        !          3324:                            txstat_buf, sizeof(txstat_buf));
        !          3325:                        printf("%s: txstat %s %d\n", sc->sc_dev.dv_xname,
        !          3326:                            txstat_buf,
        !          3327:                            MASK_AND_RSHIFT(txstat, ATW_TXSTAT_ARC_MASK));
        !          3328: #endif
        !          3329:                }
        !          3330:
        !          3331:                /*
        !          3332:                 * Check for errors and collisions.
        !          3333:                 */
        !          3334:                if (txstat & ATW_TXSTAT_TUF)
        !          3335:                        sc->sc_stats.ts_tx_tuf++;
        !          3336:                if (txstat & ATW_TXSTAT_TLT)
        !          3337:                        sc->sc_stats.ts_tx_tlt++;
        !          3338:                if (txstat & ATW_TXSTAT_TRT)
        !          3339:                        sc->sc_stats.ts_tx_trt++;
        !          3340:                if (txstat & ATW_TXSTAT_TRO)
        !          3341:                        sc->sc_stats.ts_tx_tro++;
        !          3342:                if (txstat & ATW_TXSTAT_SOFBR) {
        !          3343:                        sc->sc_stats.ts_tx_sofbr++;
        !          3344:                }
        !          3345:
        !          3346:                if ((txstat & ATW_TXSTAT_ES) == 0)
        !          3347:                        ifp->if_collisions +=
        !          3348:                            MASK_AND_RSHIFT(txstat, ATW_TXSTAT_ARC_MASK);
        !          3349:                else
        !          3350:                        ifp->if_oerrors++;
        !          3351:
        !          3352:                ifp->if_opackets++;
        !          3353:        }
        !          3354:
        !          3355:        /*
        !          3356:         * If there are no more pending transmissions, cancel the watchdog
        !          3357:         * timer.
        !          3358:         */
        !          3359:        if (txs == NULL)
        !          3360:                sc->sc_tx_timer = 0;
        !          3361: #undef TXSTAT_ERRMASK
        !          3362: #undef TXSTAT_FMT
        !          3363: }
        !          3364:
        !          3365: /*
        !          3366:  * atw_watchdog:       [ifnet interface function]
        !          3367:  *
        !          3368:  *     Watchdog timer handler.
        !          3369:  */
        !          3370: void
        !          3371: atw_watchdog(struct ifnet *ifp)
        !          3372: {
        !          3373:        struct atw_softc *sc = ifp->if_softc;
        !          3374:        struct ieee80211com *ic = &sc->sc_ic;
        !          3375:        uint32_t test1, rra, rwa;
        !          3376:
        !          3377:        ifp->if_timer = 0;
        !          3378:        if (ATW_IS_ENABLED(sc) == 0)
        !          3379:                return;
        !          3380:
        !          3381:        if (sc->sc_rescan_timer) {
        !          3382:                if (--sc->sc_rescan_timer == 0)
        !          3383:                        (void)ieee80211_new_state(ic, IEEE80211_S_SCAN, -1);
        !          3384:        }
        !          3385:        if (sc->sc_tx_timer) {
        !          3386:                if (--sc->sc_tx_timer == 0 &&
        !          3387:                    !SIMPLEQ_EMPTY(&sc->sc_txdirtyq)) {
        !          3388:                        printf("%s: transmit timeout\n", ifp->if_xname);
        !          3389:                        ifp->if_oerrors++;
        !          3390:                        (void)atw_init(ifp);
        !          3391:                        atw_start(ifp);
        !          3392:                }
        !          3393:        }
        !          3394:        if (sc->sc_tx_timer != 0 || sc->sc_rescan_timer != 0)
        !          3395:                ifp->if_timer = 1;
        !          3396:
        !          3397:        /*
        !          3398:         * ADM8211B seems to stall every so often, check for this.
        !          3399:         * These bits are what the Linux driver checks, they don't
        !          3400:         * seem to be documented by ADMTek/Infineon?
        !          3401:         */
        !          3402:        if (sc->sc_rev == ATW_REVISION_BA) {
        !          3403:                test1 = ATW_READ(sc, ATW_TEST1);
        !          3404:                rra = (test1 >> 12) & 0x1ff;
        !          3405:                rwa = (test1 >> 2) & 0x1ff;
        !          3406:
        !          3407:                if ((rra != rwa) && !(test1 & 0x2)) {
        !          3408:                        atw_init(ifp);
        !          3409:                        atw_start(ifp);
        !          3410:                }
        !          3411:        }
        !          3412:
        !          3413:        ieee80211_watchdog(ifp);
        !          3414: }
        !          3415:
        !          3416: /*
        !          3417:  * Arguments in:
        !          3418:  *
        !          3419:  * paylen:  payload length (no FCS, no WEP header)
        !          3420:  *
        !          3421:  * hdrlen:  header length
        !          3422:  *
        !          3423:  * rate:    MSDU speed, units 500kb/s
        !          3424:  *
        !          3425:  * flags:   IEEE80211_F_SHPREAMBLE (use short preamble),
        !          3426:  *          IEEE80211_F_SHSLOT (use short slot length)
        !          3427:  *
        !          3428:  * Arguments out:
        !          3429:  *
        !          3430:  * d:       802.11 Duration field for RTS,
        !          3431:  *          802.11 Duration field for data frame,
        !          3432:  *          PLCP Length for data frame,
        !          3433:  *          residual octets at end of data slot
        !          3434:  */
        !          3435: int
        !          3436: atw_compute_duration1(int len, int use_ack, uint32_t flags, int rate,
        !          3437:     struct atw_duration *d)
        !          3438: {
        !          3439:        int pre, ctsrate;
        !          3440:        int ack, bitlen, data_dur, remainder;
        !          3441:
        !          3442:        /* RTS reserves medium for SIFS | CTS | SIFS | (DATA) | SIFS | ACK
        !          3443:         * DATA reserves medium for SIFS | ACK
        !          3444:         *
        !          3445:         * XXXMYC: no ACK on multicast/broadcast or control packets
        !          3446:         */
        !          3447:
        !          3448:        bitlen = len * 8;
        !          3449:
        !          3450:        pre = IEEE80211_DUR_DS_SIFS;
        !          3451:        if ((flags & IEEE80211_F_SHPREAMBLE) != 0)
        !          3452:                pre += IEEE80211_DUR_DS_SHORT_PREAMBLE +
        !          3453:                    IEEE80211_DUR_DS_FAST_PLCPHDR;
        !          3454:        else
        !          3455:                pre += IEEE80211_DUR_DS_LONG_PREAMBLE +
        !          3456:                    IEEE80211_DUR_DS_SLOW_PLCPHDR;
        !          3457:
        !          3458:        d->d_residue = 0;
        !          3459:        data_dur = (bitlen * 2) / rate;
        !          3460:        remainder = (bitlen * 2) % rate;
        !          3461:        if (remainder != 0) {
        !          3462:                d->d_residue = (rate - remainder) / 16;
        !          3463:                data_dur++;
        !          3464:        }
        !          3465:
        !          3466:        switch (rate) {
        !          3467:        case 2:         /* 1 Mb/s */
        !          3468:        case 4:         /* 2 Mb/s */
        !          3469:                /* 1 - 2 Mb/s WLAN: send ACK/CTS at 1 Mb/s */
        !          3470:                ctsrate = 2;
        !          3471:                break;
        !          3472:        case 11:        /* 5.5 Mb/s */
        !          3473:        case 22:        /* 11  Mb/s */
        !          3474:        case 44:        /* 22  Mb/s */
        !          3475:                /* 5.5 - 11 Mb/s WLAN: send ACK/CTS at 2 Mb/s */
        !          3476:                ctsrate = 4;
        !          3477:                break;
        !          3478:        default:
        !          3479:                /* TBD */
        !          3480:                return -1;
        !          3481:        }
        !          3482:
        !          3483:        d->d_plcp_len = data_dur;
        !          3484:
        !          3485:        ack = (use_ack) ? pre + (IEEE80211_DUR_DS_SLOW_ACK * 2) / ctsrate : 0;
        !          3486:
        !          3487:        d->d_rts_dur =
        !          3488:            pre + (IEEE80211_DUR_DS_SLOW_CTS * 2) / ctsrate +
        !          3489:            pre + data_dur +
        !          3490:            ack;
        !          3491:
        !          3492:        d->d_data_dur = ack;
        !          3493:
        !          3494:        return 0;
        !          3495: }
        !          3496:
        !          3497: /*
        !          3498:  * Arguments in:
        !          3499:  *
        !          3500:  * wh:      802.11 header
        !          3501:  *
        !          3502:  * len: packet length
        !          3503:  *
        !          3504:  * rate:    MSDU speed, units 500kb/s
        !          3505:  *
        !          3506:  * fraglen: fragment length, set to maximum (or higher) for no
        !          3507:  *          fragmentation
        !          3508:  *
        !          3509:  * flags:   IEEE80211_F_WEPON (hardware adds WEP),
        !          3510:  *          IEEE80211_F_SHPREAMBLE (use short preamble),
        !          3511:  *          IEEE80211_F_SHSLOT (use short slot length)
        !          3512:  *
        !          3513:  * Arguments out:
        !          3514:  *
        !          3515:  * d0: 802.11 Duration fields (RTS/Data), PLCP Length, Service fields
        !          3516:  *     of first/only fragment
        !          3517:  *
        !          3518:  * dn: 802.11 Duration fields (RTS/Data), PLCP Length, Service fields
        !          3519:  *     of first/only fragment
        !          3520:  */
        !          3521: int
        !          3522: atw_compute_duration(struct ieee80211_frame *wh, int len, uint32_t flags,
        !          3523:     int fraglen, int rate, struct atw_duration *d0, struct atw_duration *dn,
        !          3524:     int *npktp, int debug)
        !          3525: {
        !          3526:        int ack, rc;
        !          3527:        int firstlen, hdrlen, lastlen, lastlen0, npkt, overlen, paylen;
        !          3528:
        !          3529:        if ((wh->i_fc[1] & IEEE80211_FC1_DIR_MASK) == IEEE80211_FC1_DIR_DSTODS)
        !          3530:                hdrlen = sizeof(struct ieee80211_frame_addr4);
        !          3531:        else
        !          3532:                hdrlen = sizeof(struct ieee80211_frame);
        !          3533:
        !          3534:        paylen = len - hdrlen;
        !          3535:
        !          3536:        if ((flags & IEEE80211_F_WEPON) != 0)
        !          3537:                overlen = IEEE80211_WEP_TOTLEN + IEEE80211_CRC_LEN;
        !          3538:        else
        !          3539:                overlen = IEEE80211_CRC_LEN;
        !          3540:
        !          3541:        npkt = paylen / fraglen;
        !          3542:        lastlen0 = paylen % fraglen;
        !          3543:
        !          3544:        if (npkt == 0)                  /* no fragments */
        !          3545:                lastlen = paylen + overlen;
        !          3546:        else if (lastlen0 != 0) {       /* a short "tail" fragment */
        !          3547:                lastlen = lastlen0 + overlen;
        !          3548:                npkt++;
        !          3549:        } else                          /* full-length "tail" fragment */
        !          3550:                lastlen = fraglen + overlen;
        !          3551:
        !          3552:        if (npktp != NULL)
        !          3553:                *npktp = npkt;
        !          3554:
        !          3555:        if (npkt > 1)
        !          3556:                firstlen = fraglen + overlen;
        !          3557:        else
        !          3558:                firstlen = paylen + overlen;
        !          3559:
        !          3560:        if (debug) {
        !          3561:                printf("%s: npkt %d firstlen %d lastlen0 %d lastlen %d "
        !          3562:                    "fraglen %d overlen %d len %d rate %d flags %08x\n",
        !          3563:                    __func__, npkt, firstlen, lastlen0, lastlen, fraglen,
        !          3564:                    overlen, len, rate, flags);
        !          3565:        }
        !          3566:
        !          3567:        ack = !IEEE80211_IS_MULTICAST(wh->i_addr1) &&
        !          3568:            (wh->i_fc[1] & IEEE80211_FC0_TYPE_MASK) != IEEE80211_FC0_TYPE_CTL;
        !          3569:
        !          3570:        rc = atw_compute_duration1(firstlen + hdrlen, ack, flags, rate, d0);
        !          3571:        if (rc == -1)
        !          3572:                return rc;
        !          3573:
        !          3574:        if (npkt <= 1) {
        !          3575:                *dn = *d0;
        !          3576:                return 0;
        !          3577:        }
        !          3578:        return atw_compute_duration1(lastlen + hdrlen, ack, flags, rate, dn);
        !          3579: }
        !          3580:
        !          3581: #ifdef ATW_DEBUG
        !          3582: void
        !          3583: atw_dump_pkt(struct ifnet *ifp, struct mbuf *m0)
        !          3584: {
        !          3585:        struct atw_softc *sc = ifp->if_softc;
        !          3586:        struct mbuf *m;
        !          3587:        int i, noctets = 0;
        !          3588:
        !          3589:        printf("%s: %d-byte packet\n", sc->sc_dev.dv_xname,
        !          3590:            m0->m_pkthdr.len);
        !          3591:
        !          3592:        for (m = m0; m; m = m->m_next) {
        !          3593:                if (m->m_len == 0)
        !          3594:                        continue;
        !          3595:                for (i = 0; i < m->m_len; i++) {
        !          3596:                        printf(" %02x", ((u_int8_t*)m->m_data)[i]);
        !          3597:                        if (++noctets % 24 == 0)
        !          3598:                                printf("\n");
        !          3599:                }
        !          3600:        }
        !          3601:        printf("%s%s: %d bytes emitted\n",
        !          3602:            (noctets % 24 != 0) ? "\n" : "", sc->sc_dev.dv_xname, noctets);
        !          3603: }
        !          3604: #endif /* ATW_DEBUG */
        !          3605:
        !          3606: /*
        !          3607:  * atw_start:          [ifnet interface function]
        !          3608:  *
        !          3609:  *     Start packet transmission on the interface.
        !          3610:  */
        !          3611: void
        !          3612: atw_start(struct ifnet *ifp)
        !          3613: {
        !          3614:        struct atw_softc *sc = ifp->if_softc;
        !          3615:        struct ieee80211com *ic = &sc->sc_ic;
        !          3616:        struct ieee80211_node *ni;
        !          3617:        struct ieee80211_frame *wh;
        !          3618:        struct atw_frame *hh;
        !          3619:        struct mbuf *m0, *m;
        !          3620:        struct atw_txsoft *txs, *last_txs;
        !          3621:        struct atw_txdesc *txd;
        !          3622:        int do_encrypt, npkt, rate;
        !          3623:        bus_dmamap_t dmamap;
        !          3624:        int ctl, error, firsttx, nexttx, lasttx = -1, first, ofree, seg;
        !          3625:
        !          3626:        DPRINTF2(sc, ("%s: atw_start: sc_flags 0x%08x, if_flags 0x%08x\n",
        !          3627:            sc->sc_dev.dv_xname, sc->sc_flags, ifp->if_flags));
        !          3628:
        !          3629:        if ((ifp->if_flags & (IFF_RUNNING|IFF_OACTIVE)) != IFF_RUNNING)
        !          3630:                return;
        !          3631:
        !          3632:        /*
        !          3633:         * Remember the previous number of free descriptors and
        !          3634:         * the first descriptor we'll use.
        !          3635:         */
        !          3636:        ofree = sc->sc_txfree;
        !          3637:        firsttx = sc->sc_txnext;
        !          3638:
        !          3639:        DPRINTF2(sc, ("%s: atw_start: txfree %d, txnext %d\n",
        !          3640:            sc->sc_dev.dv_xname, ofree, firsttx));
        !          3641:
        !          3642:        /*
        !          3643:         * Loop through the send queue, setting up transmit descriptors
        !          3644:         * until we drain the queue, or use up all available transmit
        !          3645:         * descriptors.
        !          3646:         */
        !          3647:        while ((txs = SIMPLEQ_FIRST(&sc->sc_txfreeq)) != NULL &&
        !          3648:               sc->sc_txfree != 0) {
        !          3649:
        !          3650:                /*
        !          3651:                 * Grab a packet off the management queue, if it
        !          3652:                 * is not empty. Otherwise, from the data queue.
        !          3653:                 */
        !          3654:                IF_DEQUEUE(&ic->ic_mgtq, m0);
        !          3655:                if (m0 != NULL) {
        !          3656:                        ni = (struct ieee80211_node *)m0->m_pkthdr.rcvif;
        !          3657:                        m0->m_pkthdr.rcvif = NULL;
        !          3658:                } else {
        !          3659:                        /* send no data packets until we are associated */
        !          3660:                        if (ic->ic_state != IEEE80211_S_RUN)
        !          3661:                                break;
        !          3662:                        IFQ_DEQUEUE(&ifp->if_snd, m0);
        !          3663:                        if (m0 == NULL)
        !          3664:                                break;
        !          3665: #if NBPFILTER > 0
        !          3666:                        if (ifp->if_bpf != NULL)
        !          3667:                                bpf_mtap(ifp->if_bpf, m0, BPF_DIRECTION_OUT);
        !          3668: #endif /* NBPFILTER > 0 */
        !          3669:                        if ((m0 = ieee80211_encap(ifp, m0, &ni)) == NULL) {
        !          3670:                                ifp->if_oerrors++;
        !          3671:                                break;
        !          3672:                        }
        !          3673:
        !          3674:                        if (sc->sc_ic.ic_flags & IEEE80211_F_WEPON) {
        !          3675:                                if ((m0 = ieee80211_wep_crypt(ifp, m0, 1)) == NULL) {
        !          3676:                                        ifp->if_oerrors++;
        !          3677:                                        break;
        !          3678:                                }
        !          3679:                        }
        !          3680:                }
        !          3681:
        !          3682:                wh = mtod(m0, struct ieee80211_frame *);
        !          3683:
        !          3684:                /* XXX do real rate control */
        !          3685:                if ((wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK) ==
        !          3686:                    IEEE80211_FC0_TYPE_MGT)
        !          3687:                        rate = 2;
        !          3688:                else
        !          3689:                        rate = MAX(2, ieee80211_get_rate(ic));
        !          3690:
        !          3691:                if (atw_compute_duration(wh, m0->m_pkthdr.len,
        !          3692:                    ic->ic_flags & ~IEEE80211_F_WEPON, ic->ic_fragthreshold,
        !          3693:                    rate, &txs->txs_d0, &txs->txs_dn, &npkt,
        !          3694:                    (sc->sc_if.if_flags & (IFF_DEBUG|IFF_LINK2)) ==
        !          3695:                    (IFF_DEBUG|IFF_LINK2)) == -1) {
        !          3696:                        DPRINTF2(sc, ("%s: fail compute duration\n", __func__));
        !          3697:                        m_freem(m0);
        !          3698:                        break;
        !          3699:                }
        !          3700:
        !          3701:                /*
        !          3702:                 * XXX Misleading if fragmentation is enabled.  Better
        !          3703:                 * to fragment in software?
        !          3704:                 */
        !          3705:                *(uint16_t *)wh->i_dur = htole16(txs->txs_d0.d_rts_dur);
        !          3706:
        !          3707: #if NBPFILTER > 0
        !          3708:                /*
        !          3709:                 * Pass the packet to any BPF listeners.
        !          3710:                 */
        !          3711:                if (ic->ic_rawbpf != NULL)
        !          3712:                        bpf_mtap(ic->ic_rawbpf, m0, BPF_DIRECTION_OUT);
        !          3713:
        !          3714:                if (sc->sc_radiobpf != NULL) {
        !          3715:                        struct mbuf mb;
        !          3716:                        struct atw_tx_radiotap_header *tap = &sc->sc_txtap;
        !          3717:
        !          3718:                        tap->at_rate = rate;
        !          3719:                        tap->at_chan_freq = ic->ic_bss->ni_chan->ic_freq;
        !          3720:                        tap->at_chan_flags = ic->ic_bss->ni_chan->ic_flags;
        !          3721:
        !          3722:                        /* TBD tap->at_flags */
        !          3723:
        !          3724:                        mb.m_data = (caddr_t)tap;
        !          3725:                        mb.m_len = tap->at_ihdr.it_len;
        !          3726:                        mb.m_next = m0;
        !          3727:                        mb.m_nextpkt = NULL;
        !          3728:                        mb.m_type = 0;
        !          3729:                        mb.m_flags = 0;
        !          3730:                        bpf_mtap(sc->sc_radiobpf, &mb, BPF_DIRECTION_OUT);
        !          3731:                }
        !          3732: #endif /* NBPFILTER > 0 */
        !          3733:
        !          3734:                M_PREPEND(m0, offsetof(struct atw_frame, atw_ihdr), M_DONTWAIT);
        !          3735:
        !          3736:                if (ni != NULL)
        !          3737:                        ieee80211_release_node(ic, ni);
        !          3738:
        !          3739:                if (m0 == NULL) {
        !          3740:                        ifp->if_oerrors++;
        !          3741:                        break;
        !          3742:                }
        !          3743:
        !          3744:                /* just to make sure. */
        !          3745:                m0 = m_pullup(m0, sizeof(struct atw_frame));
        !          3746:
        !          3747:                if (m0 == NULL) {
        !          3748:                        ifp->if_oerrors++;
        !          3749:                        break;
        !          3750:                }
        !          3751:
        !          3752:                hh = mtod(m0, struct atw_frame *);
        !          3753:                wh = &hh->atw_ihdr;
        !          3754:
        !          3755:                do_encrypt = ((wh->i_fc[1] & IEEE80211_FC1_WEP) != 0) ? 1 : 0;
        !          3756:
        !          3757:                /* Copy everything we need from the 802.11 header:
        !          3758:                 * Frame Control; address 1, address 3, or addresses
        !          3759:                 * 3 and 4. NIC fills in BSSID, SA.
        !          3760:                 */
        !          3761:                if (wh->i_fc[1] & IEEE80211_FC1_DIR_TODS) {
        !          3762:                        if (wh->i_fc[1] & IEEE80211_FC1_DIR_FROMDS)
        !          3763:                                panic("%s: illegal WDS frame",
        !          3764:                                    sc->sc_dev.dv_xname);
        !          3765:                        memcpy(hh->atw_dst, wh->i_addr3, IEEE80211_ADDR_LEN);
        !          3766:                } else
        !          3767:                        memcpy(hh->atw_dst, wh->i_addr1, IEEE80211_ADDR_LEN);
        !          3768:
        !          3769:                *(u_int16_t*)hh->atw_fc = *(u_int16_t*)wh->i_fc;
        !          3770:
        !          3771:                /* initialize remaining Tx parameters */
        !          3772:                memset(&hh->u, 0, sizeof(hh->u));
        !          3773:
        !          3774:                hh->atw_rate = rate * 5;
        !          3775:                /* XXX this could be incorrect if M_FCS. _encap should
        !          3776:                 * probably strip FCS just in case it sticks around in
        !          3777:                 * bridged packets.
        !          3778:                 */
        !          3779:                hh->atw_service = IEEE80211_PLCP_SERVICE; /* XXX guess */
        !          3780:                hh->atw_paylen = htole16(m0->m_pkthdr.len -
        !          3781:                    sizeof(struct atw_frame));
        !          3782:
        !          3783:                hh->atw_fragthr = htole16(ATW_FRAGTHR_FRAGTHR_MASK);
        !          3784:                hh->atw_rtylmt = 3;
        !          3785:                hh->atw_hdrctl = htole16(ATW_HDRCTL_UNKNOWN1);
        !          3786: #if 0
        !          3787:                if (do_encrypt) {
        !          3788:                        hh->atw_hdrctl |= htole16(ATW_HDRCTL_WEP);
        !          3789:                        hh->atw_keyid = ic->ic_wep_txkey;
        !          3790:                }
        !          3791: #endif
        !          3792:
        !          3793:                hh->atw_head_plcplen = htole16(txs->txs_d0.d_plcp_len);
        !          3794:                hh->atw_tail_plcplen = htole16(txs->txs_dn.d_plcp_len);
        !          3795:                if (txs->txs_d0.d_residue)
        !          3796:                        hh->atw_head_plcplen |= htole16(0x8000);
        !          3797:                if (txs->txs_dn.d_residue)
        !          3798:                        hh->atw_tail_plcplen |= htole16(0x8000);
        !          3799:                hh->atw_head_dur = htole16(txs->txs_d0.d_rts_dur);
        !          3800:                hh->atw_tail_dur = htole16(txs->txs_dn.d_rts_dur);
        !          3801:
        !          3802:                /* never fragment multicast frames */
        !          3803:                if (IEEE80211_IS_MULTICAST(hh->atw_dst)) {
        !          3804:                        hh->atw_fragthr = htole16(ATW_FRAGTHR_FRAGTHR_MASK);
        !          3805:                } else if (sc->sc_flags & ATWF_RTSCTS) {
        !          3806:                        hh->atw_hdrctl |= htole16(ATW_HDRCTL_RTSCTS);
        !          3807:                }
        !          3808:
        !          3809: #ifdef ATW_DEBUG
        !          3810:                hh->atw_fragnum = 0;
        !          3811:
        !          3812:                if ((ifp->if_flags & IFF_DEBUG) != 0 && atw_debug > 2) {
        !          3813:                        printf("%s: dst = %s, rate = 0x%02x, "
        !          3814:                            "service = 0x%02x, paylen = 0x%04x\n",
        !          3815:                            sc->sc_dev.dv_xname, ether_sprintf(hh->atw_dst),
        !          3816:                            hh->atw_rate, hh->atw_service, hh->atw_paylen);
        !          3817:
        !          3818:                        printf("%s: fc[0] = 0x%02x, fc[1] = 0x%02x, "
        !          3819:                            "dur1 = 0x%04x, dur2 = 0x%04x, "
        !          3820:                            "dur3 = 0x%04x, rts_dur = 0x%04x\n",
        !          3821:                            sc->sc_dev.dv_xname, hh->atw_fc[0], hh->atw_fc[1],
        !          3822:                            hh->atw_tail_plcplen, hh->atw_head_plcplen,
        !          3823:                            hh->atw_tail_dur, hh->atw_head_dur);
        !          3824:
        !          3825:                        printf("%s: hdrctl = 0x%04x, fragthr = 0x%04x, "
        !          3826:                            "fragnum = 0x%02x, rtylmt = 0x%04x\n",
        !          3827:                            sc->sc_dev.dv_xname, hh->atw_hdrctl,
        !          3828:                            hh->atw_fragthr, hh->atw_fragnum, hh->atw_rtylmt);
        !          3829:
        !          3830:                        printf("%s: keyid = %d\n",
        !          3831:                            sc->sc_dev.dv_xname, hh->atw_keyid);
        !          3832:
        !          3833:                        atw_dump_pkt(ifp, m0);
        !          3834:                }
        !          3835: #endif /* ATW_DEBUG */
        !          3836:
        !          3837:                dmamap = txs->txs_dmamap;
        !          3838:
        !          3839:                /*
        !          3840:                 * Load the DMA map.  Copy and try (once) again if the packet
        !          3841:                 * didn't fit in the alloted number of segments.
        !          3842:                 */
        !          3843:                for (first = 1;
        !          3844:                     (error = bus_dmamap_load_mbuf(sc->sc_dmat, dmamap, m0,
        !          3845:                                  BUS_DMA_WRITE|BUS_DMA_NOWAIT)) != 0 && first;
        !          3846:                     first = 0) {
        !          3847:                        MGETHDR(m, M_DONTWAIT, MT_DATA);
        !          3848:                        if (m == NULL) {
        !          3849:                                printf("%s: unable to allocate Tx mbuf\n",
        !          3850:                                    sc->sc_dev.dv_xname);
        !          3851:                                break;
        !          3852:                        }
        !          3853:                        if (m0->m_pkthdr.len > MHLEN) {
        !          3854:                                MCLGET(m, M_DONTWAIT);
        !          3855:                                if ((m->m_flags & M_EXT) == 0) {
        !          3856:                                        printf("%s: unable to allocate Tx "
        !          3857:                                            "cluster\n", sc->sc_dev.dv_xname);
        !          3858:                                        m_freem(m);
        !          3859:                                        break;
        !          3860:                                }
        !          3861:                        }
        !          3862:                        m_copydata(m0, 0, m0->m_pkthdr.len, mtod(m, caddr_t));
        !          3863:                        m->m_pkthdr.len = m->m_len = m0->m_pkthdr.len;
        !          3864:                        m_freem(m0);
        !          3865:                        m0 = m;
        !          3866:                        m = NULL;
        !          3867:                }
        !          3868:                if (error != 0) {
        !          3869:                        printf("%s: unable to load Tx buffer, "
        !          3870:                            "error = %d\n", sc->sc_dev.dv_xname, error);
        !          3871:                        m_freem(m0);
        !          3872:                        break;
        !          3873:                }
        !          3874:
        !          3875:                /*
        !          3876:                 * Ensure we have enough descriptors free to describe
        !          3877:                 * the packet.
        !          3878:                 */
        !          3879:                if (dmamap->dm_nsegs > sc->sc_txfree) {
        !          3880:                        /*
        !          3881:                         * Not enough free descriptors to transmit
        !          3882:                         * this packet.  Unload the DMA map and
        !          3883:                         * drop the packet.  Notify the upper layer
        !          3884:                         * that there are no more slots left.
        !          3885:                         *
        !          3886:                         * XXX We could allocate an mbuf and copy, but
        !          3887:                         * XXX it is worth it?
        !          3888:                         */
        !          3889:                        ifp->if_flags |= IFF_OACTIVE;
        !          3890:                        bus_dmamap_unload(sc->sc_dmat, dmamap);
        !          3891:                        m_freem(m0);
        !          3892:                        break;
        !          3893:                }
        !          3894:
        !          3895:                /*
        !          3896:                 * WE ARE NOW COMMITTED TO TRANSMITTING THE PACKET.
        !          3897:                 */
        !          3898:
        !          3899:                /* Sync the DMA map. */
        !          3900:                bus_dmamap_sync(sc->sc_dmat, dmamap, 0, dmamap->dm_mapsize,
        !          3901:                    BUS_DMASYNC_PREWRITE);
        !          3902:
        !          3903:                /* XXX arbitrary retry limit; 8 because I have seen it in
        !          3904:                 * use already and maybe 0 means "no tries" !
        !          3905:                 */
        !          3906:                ctl = htole32(LSHIFT(8, ATW_TXCTL_TL_MASK));
        !          3907:
        !          3908:                DPRINTF2(sc, ("%s: TXDR <- max(10, %d)\n",
        !          3909:                    sc->sc_dev.dv_xname, rate * 5));
        !          3910:                ctl |= htole32(LSHIFT(MAX(10, rate * 5), ATW_TXCTL_TXDR_MASK));
        !          3911:
        !          3912:                /*
        !          3913:                 * Initialize the transmit descriptors.
        !          3914:                 */
        !          3915:                for (nexttx = sc->sc_txnext, seg = 0;
        !          3916:                     seg < dmamap->dm_nsegs;
        !          3917:                     seg++, nexttx = ATW_NEXTTX(nexttx)) {
        !          3918:                        /*
        !          3919:                         * If this is the first descriptor we're
        !          3920:                         * enqueueing, don't set the OWN bit just
        !          3921:                         * yet.  That could cause a race condition.
        !          3922:                         * We'll do it below.
        !          3923:                         */
        !          3924:                        txd = &sc->sc_txdescs[nexttx];
        !          3925:                        txd->at_ctl = ctl |
        !          3926:                            ((nexttx == firsttx) ? 0 : htole32(ATW_TXCTL_OWN));
        !          3927:
        !          3928:                        txd->at_buf1 = htole32(dmamap->dm_segs[seg].ds_addr);
        !          3929:                        txd->at_flags =
        !          3930:                            htole32(LSHIFT(dmamap->dm_segs[seg].ds_len,
        !          3931:                                           ATW_TXFLAG_TBS1_MASK)) |
        !          3932:                            ((nexttx == (ATW_NTXDESC - 1))
        !          3933:                                ? htole32(ATW_TXFLAG_TER) : 0);
        !          3934:                        lasttx = nexttx;
        !          3935:                }
        !          3936:
        !          3937:                if (lasttx == -1)
        !          3938:                        panic("%s: bad lastx", ifp->if_xname);
        !          3939:                /* Set `first segment' and `last segment' appropriately. */
        !          3940:                sc->sc_txdescs[sc->sc_txnext].at_flags |=
        !          3941:                    htole32(ATW_TXFLAG_FS);
        !          3942:                sc->sc_txdescs[lasttx].at_flags |= htole32(ATW_TXFLAG_LS);
        !          3943:
        !          3944: #ifdef ATW_DEBUG
        !          3945:                if ((ifp->if_flags & IFF_DEBUG) != 0 && atw_debug > 2) {
        !          3946:                        printf("     txsoft %p transmit chain:\n", txs);
        !          3947:                        for (seg = sc->sc_txnext;; seg = ATW_NEXTTX(seg)) {
        !          3948:                                printf("     descriptor %d:\n", seg);
        !          3949:                                printf("       at_ctl:   0x%08x\n",
        !          3950:                                    letoh32(sc->sc_txdescs[seg].at_ctl));
        !          3951:                                printf("       at_flags:      0x%08x\n",
        !          3952:                                    letoh32(sc->sc_txdescs[seg].at_flags));
        !          3953:                                printf("       at_buf1: 0x%08x\n",
        !          3954:                                    letoh32(sc->sc_txdescs[seg].at_buf1));
        !          3955:                                printf("       at_buf2: 0x%08x\n",
        !          3956:                                    letoh32(sc->sc_txdescs[seg].at_buf2));
        !          3957:                                if (seg == lasttx)
        !          3958:                                        break;
        !          3959:                        }
        !          3960:                }
        !          3961: #endif
        !          3962:
        !          3963:                /* Sync the descriptors we're using. */
        !          3964:                ATW_CDTXSYNC(sc, sc->sc_txnext, dmamap->dm_nsegs,
        !          3965:                    BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE);
        !          3966:
        !          3967:                /*
        !          3968:                 * Store a pointer to the packet so we can free it later,
        !          3969:                 * and remember what txdirty will be once the packet is
        !          3970:                 * done.
        !          3971:                 */
        !          3972:                txs->txs_mbuf = m0;
        !          3973:                txs->txs_firstdesc = sc->sc_txnext;
        !          3974:                txs->txs_lastdesc = lasttx;
        !          3975:                txs->txs_ndescs = dmamap->dm_nsegs;
        !          3976:
        !          3977:                /* Advance the tx pointer. */
        !          3978:                sc->sc_txfree -= dmamap->dm_nsegs;
        !          3979:                sc->sc_txnext = nexttx;
        !          3980:
        !          3981:                SIMPLEQ_REMOVE_HEAD(&sc->sc_txfreeq, txs_q);
        !          3982:                SIMPLEQ_INSERT_TAIL(&sc->sc_txdirtyq, txs, txs_q);
        !          3983:
        !          3984:                last_txs = txs;
        !          3985:        }
        !          3986:
        !          3987:        if (txs == NULL || sc->sc_txfree == 0) {
        !          3988:                /* No more slots left; notify upper layer. */
        !          3989:                ifp->if_flags |= IFF_OACTIVE;
        !          3990:        }
        !          3991:
        !          3992:        if (sc->sc_txfree != ofree) {
        !          3993:                DPRINTF2(sc, ("%s: packets enqueued, IC on %d, OWN on %d\n",
        !          3994:                    sc->sc_dev.dv_xname, lasttx, firsttx));
        !          3995:                /*
        !          3996:                 * Cause a transmit interrupt to happen on the
        !          3997:                 * last packet we enqueued.
        !          3998:                 */
        !          3999:                sc->sc_txdescs[lasttx].at_flags |= htole32(ATW_TXFLAG_IC);
        !          4000:                ATW_CDTXSYNC(sc, lasttx, 1,
        !          4001:                    BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE);
        !          4002:
        !          4003:                /*
        !          4004:                 * The entire packet chain is set up.  Give the
        !          4005:                 * first descriptor to the chip now.
        !          4006:                 */
        !          4007:                sc->sc_txdescs[firsttx].at_ctl |= htole32(ATW_TXCTL_OWN);
        !          4008:                ATW_CDTXSYNC(sc, firsttx, 1,
        !          4009:                    BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE);
        !          4010:
        !          4011:                /* Wake up the transmitter. */
        !          4012:                ATW_WRITE(sc, ATW_TDR, 0x1);
        !          4013:
        !          4014:                /* Set a watchdog timer in case the chip flakes out. */
        !          4015:                sc->sc_tx_timer = 5;
        !          4016:                ifp->if_timer = 1;
        !          4017:        }
        !          4018: }
        !          4019:
        !          4020: /*
        !          4021:  * atw_power:
        !          4022:  *
        !          4023:  *     Power management (suspend/resume) hook.
        !          4024:  */
        !          4025: void
        !          4026: atw_power(int why, void *arg)
        !          4027: {
        !          4028:        struct atw_softc *sc = arg;
        !          4029:        struct ifnet *ifp = &sc->sc_ic.ic_if;
        !          4030:        int s;
        !          4031:
        !          4032:        DPRINTF(sc, ("%s: atw_power(%d,)\n", sc->sc_dev.dv_xname, why));
        !          4033:
        !          4034:        s = splnet();
        !          4035:        switch (why) {
        !          4036:        case PWR_STANDBY:
        !          4037:                /* XXX do nothing. */
        !          4038:                break;
        !          4039:        case PWR_SUSPEND:
        !          4040:                atw_stop(ifp, 1);
        !          4041:                if (sc->sc_power != NULL)
        !          4042:                        (*sc->sc_power)(sc, why);
        !          4043:                break;
        !          4044:        case PWR_RESUME:
        !          4045:                if (ifp->if_flags & IFF_UP) {
        !          4046:                        if (sc->sc_power != NULL)
        !          4047:                                (*sc->sc_power)(sc, why);
        !          4048:                        atw_init(ifp);
        !          4049:                }
        !          4050:                break;
        !          4051: #if !defined(__OpenBSD__)
        !          4052:        case PWR_SOFTSUSPEND:
        !          4053:        case PWR_SOFTSTANDBY:
        !          4054:        case PWR_SOFTRESUME:
        !          4055:                break;
        !          4056: #endif
        !          4057:        }
        !          4058:        splx(s);
        !          4059: }
        !          4060:
        !          4061: /*
        !          4062:  * atw_ioctl:          [ifnet interface function]
        !          4063:  *
        !          4064:  *     Handle control requests from the operator.
        !          4065:  */
        !          4066: int
        !          4067: atw_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
        !          4068: {
        !          4069:        struct atw_softc *sc = ifp->if_softc;
        !          4070:        struct ieee80211com *ic = &sc->sc_ic;
        !          4071:        struct ifreq *ifr = (struct ifreq *)data;
        !          4072:        struct ifaddr *ifa = (struct ifaddr *)data;
        !          4073:        int s, error = 0;
        !          4074:
        !          4075:        /* XXX monkey see, monkey do. comes from wi_ioctl. */
        !          4076:        if ((sc->sc_dev.dv_flags & DVF_ACTIVE) == 0)
        !          4077:                return ENXIO;
        !          4078:
        !          4079:        s = splnet();
        !          4080:
        !          4081:        switch (cmd) {
        !          4082:         case SIOCSIFMTU:
        !          4083:                 if (ifr->ifr_mtu > ETHERMTU || ifr->ifr_mtu < ETHERMIN) {
        !          4084:                         error = EINVAL;
        !          4085:                 } else if (ifp->if_mtu != ifr->ifr_mtu) {
        !          4086:                         ifp->if_mtu = ifr->ifr_mtu;
        !          4087:                 }
        !          4088:                 break;
        !          4089:         case SIOCSIFADDR:
        !          4090:                 ifp->if_flags |= IFF_UP;
        !          4091: #ifdef INET
        !          4092:                 if (ifa->ifa_addr->sa_family == AF_INET) {
        !          4093:                         arp_ifinit(&ic->ic_ac, ifa);
        !          4094:                 }
        !          4095: #endif  /* INET */
        !          4096:                /* FALLTHROUGH */
        !          4097:        case SIOCSIFFLAGS:
        !          4098:                if (ifp->if_flags & IFF_UP) {
        !          4099:                        if (ATW_IS_ENABLED(sc)) {
        !          4100:                                /*
        !          4101:                                 * To avoid rescanning another access point,
        !          4102:                                 * do not call atw_init() here.  Instead,
        !          4103:                                 * only reflect media settings.
        !          4104:                                 */
        !          4105:                                atw_filter_setup(sc);
        !          4106:                        } else
        !          4107:                                error = atw_init(ifp);
        !          4108:                } else if (ATW_IS_ENABLED(sc))
        !          4109:                        atw_stop(ifp, 1);
        !          4110:                break;
        !          4111:        case SIOCADDMULTI:
        !          4112:        case SIOCDELMULTI:
        !          4113:                error = (cmd == SIOCADDMULTI) ?
        !          4114: #if defined(__OpenBSD__)
        !          4115:                    ether_addmulti(ifr, &sc->sc_ic.ic_ac) :
        !          4116:                    ether_delmulti(ifr, &sc->sc_ic.ic_ac);
        !          4117: #else
        !          4118:                    ether_addmulti(ifr, &sc->sc_ic.ic_ec) :
        !          4119:                    ether_delmulti(ifr, &sc->sc_ic.ic_ec);
        !          4120: #endif
        !          4121:
        !          4122:                if (error == ENETRESET) {
        !          4123:                        if (ifp->if_flags & IFF_RUNNING)
        !          4124:                                atw_filter_setup(sc); /* do not rescan */
        !          4125:                        error = 0;
        !          4126:                }
        !          4127:                break;
        !          4128:        default:
        !          4129:                error = ieee80211_ioctl(ifp, cmd, data);
        !          4130:                if (error == ENETRESET) {
        !          4131:                        if (ATW_IS_ENABLED(sc))
        !          4132:                                error = atw_init(ifp);
        !          4133:                        else
        !          4134:                                error = 0;
        !          4135:                }
        !          4136:                break;
        !          4137:        }
        !          4138:
        !          4139:        /* Try to get more packets going. */
        !          4140:        if (ATW_IS_ENABLED(sc))
        !          4141:                atw_start(ifp);
        !          4142:
        !          4143:        splx(s);
        !          4144:        return (error);
        !          4145: }
        !          4146:
        !          4147: int
        !          4148: atw_media_change(struct ifnet *ifp)
        !          4149: {
        !          4150:        int error;
        !          4151:
        !          4152:        error = ieee80211_media_change(ifp);
        !          4153:        if (error == ENETRESET) {
        !          4154:                if ((ifp->if_flags & (IFF_RUNNING|IFF_UP)) ==
        !          4155:                    (IFF_RUNNING|IFF_UP))
        !          4156:                        atw_init(ifp);          /* XXX lose error */
        !          4157:                error = 0;
        !          4158:        }
        !          4159:        return error;
        !          4160: }
        !          4161:
        !          4162: void
        !          4163: atw_media_status(struct ifnet *ifp, struct ifmediareq *imr)
        !          4164: {
        !          4165:        struct atw_softc *sc = ifp->if_softc;
        !          4166:
        !          4167:        if (ATW_IS_ENABLED(sc) == 0) {
        !          4168:                imr->ifm_active = IFM_IEEE80211 | IFM_NONE;
        !          4169:                imr->ifm_status = 0;
        !          4170:                return;
        !          4171:        }
        !          4172:        ieee80211_media_status(ifp, imr);
        !          4173: }

CVSweb