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

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

1.1     ! nbrk        1: /*     $OpenBSD: rt2661.c,v 1.36 2007/03/08 18:50:57 deraadt Exp $     */
        !             2:
        !             3: /*-
        !             4:  * Copyright (c) 2006
        !             5:  *     Damien Bergamini <damien.bergamini@free.fr>
        !             6:  *
        !             7:  * Permission to use, copy, modify, and distribute this software for any
        !             8:  * purpose with or without fee is hereby granted, provided that the above
        !             9:  * copyright notice and this permission notice appear in all copies.
        !            10:  *
        !            11:  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
        !            12:  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
        !            13:  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
        !            14:  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
        !            15:  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
        !            16:  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
        !            17:  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
        !            18:  */
        !            19:
        !            20: /*-
        !            21:  * Ralink Technology RT2561, RT2561S and RT2661 chipset driver
        !            22:  * http://www.ralinktech.com/
        !            23:  */
        !            24:
        !            25: #include "bpfilter.h"
        !            26:
        !            27: #include <sys/param.h>
        !            28: #include <sys/sockio.h>
        !            29: #include <sys/sysctl.h>
        !            30: #include <sys/mbuf.h>
        !            31: #include <sys/kernel.h>
        !            32: #include <sys/socket.h>
        !            33: #include <sys/systm.h>
        !            34: #include <sys/malloc.h>
        !            35: #include <sys/timeout.h>
        !            36: #include <sys/conf.h>
        !            37: #include <sys/device.h>
        !            38:
        !            39: #include <machine/bus.h>
        !            40: #include <machine/endian.h>
        !            41: #include <machine/intr.h>
        !            42:
        !            43: #if NBPFILTER > 0
        !            44: #include <net/bpf.h>
        !            45: #endif
        !            46: #include <net/if.h>
        !            47: #include <net/if_arp.h>
        !            48: #include <net/if_dl.h>
        !            49: #include <net/if_media.h>
        !            50: #include <net/if_types.h>
        !            51:
        !            52: #include <netinet/in.h>
        !            53: #include <netinet/in_systm.h>
        !            54: #include <netinet/in_var.h>
        !            55: #include <netinet/if_ether.h>
        !            56: #include <netinet/ip.h>
        !            57:
        !            58: #include <net80211/ieee80211_var.h>
        !            59: #include <net80211/ieee80211_amrr.h>
        !            60: #include <net80211/ieee80211_radiotap.h>
        !            61:
        !            62: #include <dev/ic/rt2661reg.h>
        !            63: #include <dev/ic/rt2661var.h>
        !            64:
        !            65: #include <dev/pci/pcireg.h>
        !            66: #include <dev/pci/pcivar.h>
        !            67: #include <dev/pci/pcidevs.h>
        !            68:
        !            69: #ifdef RAL_DEBUG
        !            70: #define DPRINTF(x)     do { if (rt2661_debug > 0) printf x; } while (0)
        !            71: #define DPRINTFN(n, x) do { if (rt2661_debug >= (n)) printf x; } while (0)
        !            72: int rt2661_debug = 1;
        !            73: #else
        !            74: #define DPRINTF(x)
        !            75: #define DPRINTFN(n, x)
        !            76: #endif
        !            77:
        !            78: int            rt2661_alloc_tx_ring(struct rt2661_softc *,
        !            79:                    struct rt2661_tx_ring *, int);
        !            80: void           rt2661_reset_tx_ring(struct rt2661_softc *,
        !            81:                    struct rt2661_tx_ring *);
        !            82: void           rt2661_free_tx_ring(struct rt2661_softc *,
        !            83:                    struct rt2661_tx_ring *);
        !            84: int            rt2661_alloc_rx_ring(struct rt2661_softc *,
        !            85:                    struct rt2661_rx_ring *, int);
        !            86: void           rt2661_reset_rx_ring(struct rt2661_softc *,
        !            87:                    struct rt2661_rx_ring *);
        !            88: void           rt2661_free_rx_ring(struct rt2661_softc *,
        !            89:                    struct rt2661_rx_ring *);
        !            90: struct         ieee80211_node *rt2661_node_alloc(struct ieee80211com *);
        !            91: int            rt2661_media_change(struct ifnet *);
        !            92: void           rt2661_next_scan(void *);
        !            93: void           rt2661_iter_func(void *, struct ieee80211_node *);
        !            94: void           rt2661_updatestats(void *);
        !            95: void           rt2661_newassoc(struct ieee80211com *, struct ieee80211_node *,
        !            96:                    int);
        !            97: int            rt2661_newstate(struct ieee80211com *, enum ieee80211_state,
        !            98:                    int);
        !            99: uint16_t       rt2661_eeprom_read(struct rt2661_softc *, uint8_t);
        !           100: void           rt2661_tx_intr(struct rt2661_softc *);
        !           101: void           rt2661_tx_dma_intr(struct rt2661_softc *,
        !           102:                    struct rt2661_tx_ring *);
        !           103: void           rt2661_rx_intr(struct rt2661_softc *);
        !           104: void           rt2661_mcu_beacon_expire(struct rt2661_softc *);
        !           105: void           rt2661_mcu_wakeup(struct rt2661_softc *);
        !           106: void           rt2661_mcu_cmd_intr(struct rt2661_softc *);
        !           107: int            rt2661_intr(void *);
        !           108: #if NBPFILTER > 0
        !           109: uint8_t                rt2661_rxrate(const struct rt2661_rx_desc *);
        !           110: #endif
        !           111: int            rt2661_ack_rate(struct ieee80211com *, int);
        !           112: uint16_t       rt2661_txtime(int, int, uint32_t);
        !           113: uint8_t                rt2661_plcp_signal(int);
        !           114: void           rt2661_setup_tx_desc(struct rt2661_softc *,
        !           115:                    struct rt2661_tx_desc *, uint32_t, uint16_t, int, int,
        !           116:                    const bus_dma_segment_t *, int, int);
        !           117: int            rt2661_tx_mgt(struct rt2661_softc *, struct mbuf *,
        !           118:                    struct ieee80211_node *);
        !           119: int            rt2661_tx_data(struct rt2661_softc *, struct mbuf *,
        !           120:                    struct ieee80211_node *, int);
        !           121: void           rt2661_start(struct ifnet *);
        !           122: void           rt2661_watchdog(struct ifnet *);
        !           123: int            rt2661_ioctl(struct ifnet *, u_long, caddr_t);
        !           124: void           rt2661_bbp_write(struct rt2661_softc *, uint8_t, uint8_t);
        !           125: uint8_t                rt2661_bbp_read(struct rt2661_softc *, uint8_t);
        !           126: void           rt2661_rf_write(struct rt2661_softc *, uint8_t, uint32_t);
        !           127: int            rt2661_tx_cmd(struct rt2661_softc *, uint8_t, uint16_t);
        !           128: void           rt2661_select_antenna(struct rt2661_softc *);
        !           129: void           rt2661_enable_mrr(struct rt2661_softc *);
        !           130: void           rt2661_set_txpreamble(struct rt2661_softc *);
        !           131: void           rt2661_set_basicrates(struct rt2661_softc *);
        !           132: void           rt2661_select_band(struct rt2661_softc *,
        !           133:                    struct ieee80211_channel *);
        !           134: void           rt2661_set_chan(struct rt2661_softc *,
        !           135:                    struct ieee80211_channel *);
        !           136: void           rt2661_set_bssid(struct rt2661_softc *, const uint8_t *);
        !           137: void           rt2661_set_macaddr(struct rt2661_softc *, const uint8_t *);
        !           138: void           rt2661_update_promisc(struct rt2661_softc *);
        !           139: void           rt2661_updateslot(struct ieee80211com *);
        !           140: void           rt2661_set_slottime(struct rt2661_softc *);
        !           141: const char     *rt2661_get_rf(int);
        !           142: void           rt2661_read_eeprom(struct rt2661_softc *);
        !           143: int            rt2661_bbp_init(struct rt2661_softc *);
        !           144: int            rt2661_init(struct ifnet *);
        !           145: void           rt2661_stop(struct ifnet *, int);
        !           146: int            rt2661_load_microcode(struct rt2661_softc *, const uint8_t *,
        !           147:                    int);
        !           148: void           rt2661_rx_tune(struct rt2661_softc *);
        !           149: #ifdef notyet
        !           150: void           rt2661_radar_start(struct rt2661_softc *);
        !           151: int            rt2661_radar_stop(struct rt2661_softc *);
        !           152: #endif
        !           153: int            rt2661_prepare_beacon(struct rt2661_softc *);
        !           154: void           rt2661_enable_tsf_sync(struct rt2661_softc *);
        !           155: int            rt2661_get_rssi(struct rt2661_softc *, uint8_t);
        !           156: void           rt2661_power(int, void *);
        !           157: void           rt2661_shutdown(void *);
        !           158:
        !           159: static const struct {
        !           160:        uint32_t        reg;
        !           161:        uint32_t        val;
        !           162: } rt2661_def_mac[] = {
        !           163:        RT2661_DEF_MAC
        !           164: };
        !           165:
        !           166: static const struct {
        !           167:        uint8_t reg;
        !           168:        uint8_t val;
        !           169: } rt2661_def_bbp[] = {
        !           170:        RT2661_DEF_BBP
        !           171: };
        !           172:
        !           173: static const struct rfprog {
        !           174:        uint8_t         chan;
        !           175:        uint32_t        r1, r2, r3, r4;
        !           176: }  rt2661_rf5225_1[] = {
        !           177:        RT2661_RF5225_1
        !           178: }, rt2661_rf5225_2[] = {
        !           179:        RT2661_RF5225_2
        !           180: };
        !           181:
        !           182: int
        !           183: rt2661_attach(void *xsc, int id)
        !           184: {
        !           185:        struct rt2661_softc *sc = xsc;
        !           186:        struct ieee80211com *ic = &sc->sc_ic;
        !           187:        struct ifnet *ifp = &ic->ic_if;
        !           188:        uint32_t val;
        !           189:        int error, ac, i, ntries;
        !           190:
        !           191:        sc->sc_id = id;
        !           192:
        !           193:        sc->amrr.amrr_min_success_threshold =  1;
        !           194:        sc->amrr.amrr_max_success_threshold = 15;
        !           195:        timeout_set(&sc->amrr_to, rt2661_updatestats, sc);
        !           196:        timeout_set(&sc->scan_to, rt2661_next_scan, sc);
        !           197:
        !           198:        /* wait for NIC to initialize */
        !           199:        for (ntries = 0; ntries < 1000; ntries++) {
        !           200:                if ((val = RAL_READ(sc, RT2661_MAC_CSR0)) != 0)
        !           201:                        break;
        !           202:                DELAY(1000);
        !           203:        }
        !           204:        if (ntries == 1000) {
        !           205:                printf("%s: timeout waiting for NIC to initialize\n",
        !           206:                    sc->sc_dev.dv_xname);
        !           207:                return EIO;
        !           208:        }
        !           209:
        !           210:        /* retrieve RF rev. no and various other things from EEPROM */
        !           211:        rt2661_read_eeprom(sc);
        !           212:        printf(", address %s\n", ether_sprintf(ic->ic_myaddr));
        !           213:
        !           214:        printf("%s: MAC/BBP RT%X, RF %s\n", sc->sc_dev.dv_xname, val,
        !           215:            rt2661_get_rf(sc->rf_rev));
        !           216:
        !           217:        /*
        !           218:         * Allocate Tx and Rx rings.
        !           219:         */
        !           220:        for (ac = 0; ac < 4; ac++) {
        !           221:                error = rt2661_alloc_tx_ring(sc, &sc->txq[ac],
        !           222:                    RT2661_TX_RING_COUNT);
        !           223:                if (error != 0) {
        !           224:                        printf("%s: could not allocate Tx ring %d\n",
        !           225:                            sc->sc_dev.dv_xname, ac);
        !           226:                        goto fail1;
        !           227:                }
        !           228:        }
        !           229:
        !           230:        error = rt2661_alloc_tx_ring(sc, &sc->mgtq, RT2661_MGT_RING_COUNT);
        !           231:        if (error != 0) {
        !           232:                printf("%s: could not allocate Mgt ring\n",
        !           233:                    sc->sc_dev.dv_xname);
        !           234:                goto fail1;
        !           235:        }
        !           236:
        !           237:        error = rt2661_alloc_rx_ring(sc, &sc->rxq, RT2661_RX_RING_COUNT);
        !           238:        if (error != 0) {
        !           239:                printf("%s: could not allocate Rx ring\n",
        !           240:                    sc->sc_dev.dv_xname);
        !           241:                goto fail2;
        !           242:        }
        !           243:
        !           244:        ic->ic_phytype = IEEE80211_T_OFDM; /* not only, but not used */
        !           245:        ic->ic_opmode = IEEE80211_M_STA; /* default to BSS mode */
        !           246:        ic->ic_state = IEEE80211_S_INIT;
        !           247:
        !           248:        /* set device capabilities */
        !           249:        ic->ic_caps =
        !           250:            IEEE80211_C_IBSS |          /* IBSS mode supported */
        !           251:            IEEE80211_C_MONITOR |       /* monitor mode supported */
        !           252:            IEEE80211_C_HOSTAP |        /* HostAP mode supported */
        !           253:            IEEE80211_C_TXPMGT |        /* tx power management */
        !           254:            IEEE80211_C_SHPREAMBLE |    /* short preamble supported */
        !           255:            IEEE80211_C_SHSLOT |        /* short slot time supported */
        !           256:            IEEE80211_C_WEP;            /* s/w WEP */
        !           257:
        !           258:        if (sc->rf_rev == RT2661_RF_5225 || sc->rf_rev == RT2661_RF_5325) {
        !           259:                /* set supported .11a rates */
        !           260:                ic->ic_sup_rates[IEEE80211_MODE_11A] =
        !           261:                    ieee80211_std_rateset_11a;
        !           262:
        !           263:                /* set supported .11a channels */
        !           264:                for (i = 36; i <= 64; i += 4) {
        !           265:                        ic->ic_channels[i].ic_freq =
        !           266:                            ieee80211_ieee2mhz(i, IEEE80211_CHAN_5GHZ);
        !           267:                        ic->ic_channels[i].ic_flags = IEEE80211_CHAN_A;
        !           268:                }
        !           269:                for (i = 100; i <= 140; i += 4) {
        !           270:                        ic->ic_channels[i].ic_freq =
        !           271:                            ieee80211_ieee2mhz(i, IEEE80211_CHAN_5GHZ);
        !           272:                        ic->ic_channels[i].ic_flags = IEEE80211_CHAN_A;
        !           273:                }
        !           274:                for (i = 149; i <= 165; i += 4) {
        !           275:                        ic->ic_channels[i].ic_freq =
        !           276:                            ieee80211_ieee2mhz(i, IEEE80211_CHAN_5GHZ);
        !           277:                        ic->ic_channels[i].ic_flags = IEEE80211_CHAN_A;
        !           278:                }
        !           279:        }
        !           280:
        !           281:        /* set supported .11b and .11g rates */
        !           282:        ic->ic_sup_rates[IEEE80211_MODE_11B] = ieee80211_std_rateset_11b;
        !           283:        ic->ic_sup_rates[IEEE80211_MODE_11G] = ieee80211_std_rateset_11g;
        !           284:
        !           285:        /* set supported .11b and .11g channels (1 through 14) */
        !           286:        for (i = 1; i <= 14; i++) {
        !           287:                ic->ic_channels[i].ic_freq =
        !           288:                    ieee80211_ieee2mhz(i, IEEE80211_CHAN_2GHZ);
        !           289:                ic->ic_channels[i].ic_flags =
        !           290:                    IEEE80211_CHAN_CCK | IEEE80211_CHAN_OFDM |
        !           291:                    IEEE80211_CHAN_DYN | IEEE80211_CHAN_2GHZ;
        !           292:        }
        !           293:
        !           294:        ifp->if_softc = sc;
        !           295:        ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
        !           296:        ifp->if_init = rt2661_init;
        !           297:        ifp->if_ioctl = rt2661_ioctl;
        !           298:        ifp->if_start = rt2661_start;
        !           299:        ifp->if_watchdog = rt2661_watchdog;
        !           300:        IFQ_SET_READY(&ifp->if_snd);
        !           301:        memcpy(ifp->if_xname, sc->sc_dev.dv_xname, IFNAMSIZ);
        !           302:
        !           303:        if_attach(ifp);
        !           304:        ieee80211_ifattach(ifp);
        !           305:        ic->ic_node_alloc = rt2661_node_alloc;
        !           306:        ic->ic_newassoc = rt2661_newassoc;
        !           307:        ic->ic_updateslot = rt2661_updateslot;
        !           308:
        !           309:        /* override state transition machine */
        !           310:        sc->sc_newstate = ic->ic_newstate;
        !           311:        ic->ic_newstate = rt2661_newstate;
        !           312:        ieee80211_media_init(ifp, rt2661_media_change, ieee80211_media_status);
        !           313:
        !           314: #if NBPFILTER > 0
        !           315:        bpfattach(&sc->sc_drvbpf, ifp, DLT_IEEE802_11_RADIO,
        !           316:            sizeof (struct ieee80211_frame) + 64);
        !           317:
        !           318:        sc->sc_rxtap_len = sizeof sc->sc_rxtapu;
        !           319:        sc->sc_rxtap.wr_ihdr.it_len = htole16(sc->sc_rxtap_len);
        !           320:        sc->sc_rxtap.wr_ihdr.it_present = htole32(RT2661_RX_RADIOTAP_PRESENT);
        !           321:
        !           322:        sc->sc_txtap_len = sizeof sc->sc_txtapu;
        !           323:        sc->sc_txtap.wt_ihdr.it_len = htole16(sc->sc_txtap_len);
        !           324:        sc->sc_txtap.wt_ihdr.it_present = htole32(RT2661_TX_RADIOTAP_PRESENT);
        !           325: #endif
        !           326:
        !           327:        /*
        !           328:         * Make sure the interface is shutdown during reboot.
        !           329:         */
        !           330:        sc->sc_sdhook = shutdownhook_establish(rt2661_shutdown, sc);
        !           331:        if (sc->sc_sdhook == NULL) {
        !           332:                printf("%s: WARNING: unable to establish shutdown hook\n",
        !           333:                    sc->sc_dev.dv_xname);
        !           334:        }
        !           335:        sc->sc_powerhook = powerhook_establish(rt2661_power, sc);
        !           336:        if (sc->sc_powerhook == NULL) {
        !           337:                printf("%s: WARNING: unable to establish power hook\n",
        !           338:                    sc->sc_dev.dv_xname);
        !           339:        }
        !           340:
        !           341:        return 0;
        !           342:
        !           343: fail2: rt2661_free_tx_ring(sc, &sc->mgtq);
        !           344: fail1: while (--ac >= 0)
        !           345:                rt2661_free_tx_ring(sc, &sc->txq[ac]);
        !           346:        return ENXIO;
        !           347: }
        !           348:
        !           349: int
        !           350: rt2661_detach(void *xsc)
        !           351: {
        !           352:        struct rt2661_softc *sc = xsc;
        !           353:        struct ifnet *ifp = &sc->sc_ic.ic_if;
        !           354:        int ac;
        !           355:
        !           356:        timeout_del(&sc->scan_to);
        !           357:        timeout_del(&sc->amrr_to);
        !           358:
        !           359:        ieee80211_ifdetach(ifp);        /* free all nodes */
        !           360:        if_detach(ifp);
        !           361:
        !           362:        if (sc->sc_powerhook != NULL)
        !           363:                powerhook_disestablish(sc->sc_powerhook);
        !           364:        if (sc->sc_sdhook != NULL)
        !           365:                shutdownhook_disestablish(sc->sc_sdhook);
        !           366:
        !           367:        for (ac = 0; ac < 4; ac++)
        !           368:                rt2661_free_tx_ring(sc, &sc->txq[ac]);
        !           369:        rt2661_free_tx_ring(sc, &sc->mgtq);
        !           370:        rt2661_free_rx_ring(sc, &sc->rxq);
        !           371:
        !           372:        return 0;
        !           373: }
        !           374:
        !           375: int
        !           376: rt2661_alloc_tx_ring(struct rt2661_softc *sc, struct rt2661_tx_ring *ring,
        !           377:     int count)
        !           378: {
        !           379:        int i, nsegs, error;
        !           380:
        !           381:        ring->count = count;
        !           382:        ring->queued = 0;
        !           383:        ring->cur = ring->next = ring->stat = 0;
        !           384:
        !           385:        error = bus_dmamap_create(sc->sc_dmat, count * RT2661_TX_DESC_SIZE, 1,
        !           386:            count * RT2661_TX_DESC_SIZE, 0, BUS_DMA_NOWAIT, &ring->map);
        !           387:        if (error != 0) {
        !           388:                printf("%s: could not create desc DMA map\n",
        !           389:                    sc->sc_dev.dv_xname);
        !           390:                goto fail;
        !           391:        }
        !           392:
        !           393:        error = bus_dmamem_alloc(sc->sc_dmat, count * RT2661_TX_DESC_SIZE,
        !           394:            PAGE_SIZE, 0, &ring->seg, 1, &nsegs, BUS_DMA_NOWAIT);
        !           395:        if (error != 0) {
        !           396:                printf("%s: could not allocate DMA memory\n",
        !           397:                    sc->sc_dev.dv_xname);
        !           398:                goto fail;
        !           399:        }
        !           400:
        !           401:        error = bus_dmamem_map(sc->sc_dmat, &ring->seg, nsegs,
        !           402:            count * RT2661_TX_DESC_SIZE, (caddr_t *)&ring->desc,
        !           403:            BUS_DMA_NOWAIT);
        !           404:        if (error != 0) {
        !           405:                printf("%s: could not map desc DMA memory\n",
        !           406:                    sc->sc_dev.dv_xname);
        !           407:                goto fail;
        !           408:        }
        !           409:
        !           410:        error = bus_dmamap_load(sc->sc_dmat, ring->map, ring->desc,
        !           411:            count * RT2661_TX_DESC_SIZE, NULL, BUS_DMA_NOWAIT);
        !           412:        if (error != 0) {
        !           413:                printf("%s: could not load desc DMA map\n",
        !           414:                    sc->sc_dev.dv_xname);
        !           415:                goto fail;
        !           416:        }
        !           417:
        !           418:        memset(ring->desc, 0, count * RT2661_TX_DESC_SIZE);
        !           419:        ring->physaddr = ring->map->dm_segs->ds_addr;
        !           420:
        !           421:        ring->data = malloc(count * sizeof (struct rt2661_tx_data), M_DEVBUF,
        !           422:            M_NOWAIT);
        !           423:        if (ring->data == NULL) {
        !           424:                printf("%s: could not allocate soft data\n",
        !           425:                    sc->sc_dev.dv_xname);
        !           426:                error = ENOMEM;
        !           427:                goto fail;
        !           428:        }
        !           429:
        !           430:        memset(ring->data, 0, count * sizeof (struct rt2661_tx_data));
        !           431:        for (i = 0; i < count; i++) {
        !           432:                error = bus_dmamap_create(sc->sc_dmat, MCLBYTES,
        !           433:                    RT2661_MAX_SCATTER, MCLBYTES, 0, BUS_DMA_NOWAIT,
        !           434:                    &ring->data[i].map);
        !           435:                if (error != 0) {
        !           436:                        printf("%s: could not create DMA map\n",
        !           437:                            sc->sc_dev.dv_xname);
        !           438:                        goto fail;
        !           439:                }
        !           440:        }
        !           441:
        !           442:        return 0;
        !           443:
        !           444: fail:  rt2661_free_tx_ring(sc, ring);
        !           445:        return error;
        !           446: }
        !           447:
        !           448: void
        !           449: rt2661_reset_tx_ring(struct rt2661_softc *sc, struct rt2661_tx_ring *ring)
        !           450: {
        !           451:        int i;
        !           452:
        !           453:        for (i = 0; i < ring->count; i++) {
        !           454:                struct rt2661_tx_desc *desc = &ring->desc[i];
        !           455:                struct rt2661_tx_data *data = &ring->data[i];
        !           456:
        !           457:                if (data->m != NULL) {
        !           458:                        bus_dmamap_sync(sc->sc_dmat, data->map, 0,
        !           459:                            data->map->dm_mapsize, BUS_DMASYNC_POSTWRITE);
        !           460:                        bus_dmamap_unload(sc->sc_dmat, data->map);
        !           461:                        m_freem(data->m);
        !           462:                        data->m = NULL;
        !           463:                }
        !           464:
        !           465:                /*
        !           466:                 * The node has already been freed at that point so don't call
        !           467:                 * ieee80211_release_node() here.
        !           468:                 */
        !           469:                data->ni = NULL;
        !           470:
        !           471:                desc->flags = 0;
        !           472:        }
        !           473:
        !           474:        bus_dmamap_sync(sc->sc_dmat, ring->map, 0, ring->map->dm_mapsize,
        !           475:            BUS_DMASYNC_PREWRITE);
        !           476:
        !           477:        ring->queued = 0;
        !           478:        ring->cur = ring->next = ring->stat = 0;
        !           479: }
        !           480:
        !           481: void
        !           482: rt2661_free_tx_ring(struct rt2661_softc *sc, struct rt2661_tx_ring *ring)
        !           483: {
        !           484:        int i;
        !           485:
        !           486:        if (ring->desc != NULL) {
        !           487:                bus_dmamap_sync(sc->sc_dmat, ring->map, 0,
        !           488:                    ring->map->dm_mapsize, BUS_DMASYNC_POSTWRITE);
        !           489:                bus_dmamap_unload(sc->sc_dmat, ring->map);
        !           490:                bus_dmamem_unmap(sc->sc_dmat, (caddr_t)ring->desc,
        !           491:                    ring->count * RT2661_TX_DESC_SIZE);
        !           492:                bus_dmamem_free(sc->sc_dmat, &ring->seg, 1);
        !           493:        }
        !           494:
        !           495:        if (ring->data != NULL) {
        !           496:                for (i = 0; i < ring->count; i++) {
        !           497:                        struct rt2661_tx_data *data = &ring->data[i];
        !           498:
        !           499:                        if (data->m != NULL) {
        !           500:                                bus_dmamap_sync(sc->sc_dmat, data->map, 0,
        !           501:                                    data->map->dm_mapsize,
        !           502:                                    BUS_DMASYNC_POSTWRITE);
        !           503:                                bus_dmamap_unload(sc->sc_dmat, data->map);
        !           504:                                m_freem(data->m);
        !           505:                        }
        !           506:                        /*
        !           507:                         * The node has already been freed at that point so
        !           508:                         * don't call ieee80211_release_node() here.
        !           509:                         */
        !           510:                        data->ni = NULL;
        !           511:
        !           512:                        if (data->map != NULL)
        !           513:                                bus_dmamap_destroy(sc->sc_dmat, data->map);
        !           514:                }
        !           515:                free(ring->data, M_DEVBUF);
        !           516:        }
        !           517: }
        !           518:
        !           519: int
        !           520: rt2661_alloc_rx_ring(struct rt2661_softc *sc, struct rt2661_rx_ring *ring,
        !           521:     int count)
        !           522: {
        !           523:        int i, nsegs, error;
        !           524:
        !           525:        ring->count = count;
        !           526:        ring->cur = ring->next = 0;
        !           527:
        !           528:        error = bus_dmamap_create(sc->sc_dmat, count * RT2661_RX_DESC_SIZE, 1,
        !           529:            count * RT2661_RX_DESC_SIZE, 0, BUS_DMA_NOWAIT, &ring->map);
        !           530:        if (error != 0) {
        !           531:                printf("%s: could not create desc DMA map\n",
        !           532:                    sc->sc_dev.dv_xname);
        !           533:                goto fail;
        !           534:        }
        !           535:
        !           536:        error = bus_dmamem_alloc(sc->sc_dmat, count * RT2661_RX_DESC_SIZE,
        !           537:            PAGE_SIZE, 0, &ring->seg, 1, &nsegs, BUS_DMA_NOWAIT);
        !           538:        if (error != 0) {
        !           539:                printf("%s: could not allocate DMA memory\n",
        !           540:                    sc->sc_dev.dv_xname);
        !           541:                goto fail;
        !           542:        }
        !           543:
        !           544:        error = bus_dmamem_map(sc->sc_dmat, &ring->seg, nsegs,
        !           545:            count * RT2661_RX_DESC_SIZE, (caddr_t *)&ring->desc,
        !           546:            BUS_DMA_NOWAIT);
        !           547:        if (error != 0) {
        !           548:                printf("%s: could not map desc DMA memory\n",
        !           549:                    sc->sc_dev.dv_xname);
        !           550:                goto fail;
        !           551:        }
        !           552:
        !           553:        error = bus_dmamap_load(sc->sc_dmat, ring->map, ring->desc,
        !           554:            count * RT2661_RX_DESC_SIZE, NULL, BUS_DMA_NOWAIT);
        !           555:        if (error != 0) {
        !           556:                printf("%s: could not load desc DMA map\n",
        !           557:                    sc->sc_dev.dv_xname);
        !           558:                goto fail;
        !           559:        }
        !           560:
        !           561:        memset(ring->desc, 0, count * RT2661_RX_DESC_SIZE);
        !           562:        ring->physaddr = ring->map->dm_segs->ds_addr;
        !           563:
        !           564:        ring->data = malloc(count * sizeof (struct rt2661_rx_data), M_DEVBUF,
        !           565:            M_NOWAIT);
        !           566:        if (ring->data == NULL) {
        !           567:                printf("%s: could not allocate soft data\n",
        !           568:                    sc->sc_dev.dv_xname);
        !           569:                error = ENOMEM;
        !           570:                goto fail;
        !           571:        }
        !           572:
        !           573:        /*
        !           574:         * Pre-allocate Rx buffers and populate Rx ring.
        !           575:         */
        !           576:        memset(ring->data, 0, count * sizeof (struct rt2661_rx_data));
        !           577:        for (i = 0; i < count; i++) {
        !           578:                struct rt2661_rx_desc *desc = &sc->rxq.desc[i];
        !           579:                struct rt2661_rx_data *data = &sc->rxq.data[i];
        !           580:
        !           581:                error = bus_dmamap_create(sc->sc_dmat, MCLBYTES, 1, MCLBYTES,
        !           582:                    0, BUS_DMA_NOWAIT, &data->map);
        !           583:                if (error != 0) {
        !           584:                        printf("%s: could not create DMA map\n",
        !           585:                            sc->sc_dev.dv_xname);
        !           586:                        goto fail;
        !           587:                }
        !           588:
        !           589:                MGETHDR(data->m, M_DONTWAIT, MT_DATA);
        !           590:                if (data->m == NULL) {
        !           591:                        printf("%s: could not allocate rx mbuf\n",
        !           592:                            sc->sc_dev.dv_xname);
        !           593:                        error = ENOMEM;
        !           594:                        goto fail;
        !           595:                }
        !           596:                MCLGET(data->m, M_DONTWAIT);
        !           597:                if (!(data->m->m_flags & M_EXT)) {
        !           598:                        printf("%s: could not allocate rx mbuf cluster\n",
        !           599:                            sc->sc_dev.dv_xname);
        !           600:                        error = ENOMEM;
        !           601:                        goto fail;
        !           602:                }
        !           603:
        !           604:                error = bus_dmamap_load(sc->sc_dmat, data->map,
        !           605:                    mtod(data->m, void *), MCLBYTES, NULL, BUS_DMA_NOWAIT);
        !           606:                if (error != 0) {
        !           607:                        printf("%s: could not load rx buf DMA map",
        !           608:                            sc->sc_dev.dv_xname);
        !           609:                        goto fail;
        !           610:                }
        !           611:
        !           612:                desc->flags = htole32(RT2661_RX_BUSY);
        !           613:                desc->physaddr = htole32(data->map->dm_segs->ds_addr);
        !           614:        }
        !           615:
        !           616:        bus_dmamap_sync(sc->sc_dmat, ring->map, 0, ring->map->dm_mapsize,
        !           617:            BUS_DMASYNC_PREWRITE);
        !           618:
        !           619:        return 0;
        !           620:
        !           621: fail:  rt2661_free_rx_ring(sc, ring);
        !           622:        return error;
        !           623: }
        !           624:
        !           625: void
        !           626: rt2661_reset_rx_ring(struct rt2661_softc *sc, struct rt2661_rx_ring *ring)
        !           627: {
        !           628:        int i;
        !           629:
        !           630:        for (i = 0; i < ring->count; i++)
        !           631:                ring->desc[i].flags = htole32(RT2661_RX_BUSY);
        !           632:
        !           633:        bus_dmamap_sync(sc->sc_dmat, ring->map, 0, ring->map->dm_mapsize,
        !           634:            BUS_DMASYNC_PREWRITE);
        !           635:
        !           636:        ring->cur = ring->next = 0;
        !           637: }
        !           638:
        !           639: void
        !           640: rt2661_free_rx_ring(struct rt2661_softc *sc, struct rt2661_rx_ring *ring)
        !           641: {
        !           642:        int i;
        !           643:
        !           644:        if (ring->desc != NULL) {
        !           645:                bus_dmamap_sync(sc->sc_dmat, ring->map, 0,
        !           646:                    ring->map->dm_mapsize, BUS_DMASYNC_POSTWRITE);
        !           647:                bus_dmamap_unload(sc->sc_dmat, ring->map);
        !           648:                bus_dmamem_unmap(sc->sc_dmat, (caddr_t)ring->desc,
        !           649:                    ring->count * RT2661_RX_DESC_SIZE);
        !           650:                bus_dmamem_free(sc->sc_dmat, &ring->seg, 1);
        !           651:        }
        !           652:
        !           653:        if (ring->data != NULL) {
        !           654:                for (i = 0; i < ring->count; i++) {
        !           655:                        struct rt2661_rx_data *data = &ring->data[i];
        !           656:
        !           657:                        if (data->m != NULL) {
        !           658:                                bus_dmamap_sync(sc->sc_dmat, data->map, 0,
        !           659:                                    data->map->dm_mapsize,
        !           660:                                    BUS_DMASYNC_POSTREAD);
        !           661:                                bus_dmamap_unload(sc->sc_dmat, data->map);
        !           662:                                m_freem(data->m);
        !           663:                        }
        !           664:
        !           665:                        if (data->map != NULL)
        !           666:                                bus_dmamap_destroy(sc->sc_dmat, data->map);
        !           667:                }
        !           668:                free(ring->data, M_DEVBUF);
        !           669:        }
        !           670: }
        !           671:
        !           672: struct ieee80211_node *
        !           673: rt2661_node_alloc(struct ieee80211com *ic)
        !           674: {
        !           675:        struct rt2661_node *rn;
        !           676:
        !           677:        rn = malloc(sizeof (struct rt2661_node), M_DEVBUF, M_NOWAIT);
        !           678:        if (rn != NULL)
        !           679:                bzero(rn, sizeof (struct rt2661_node));
        !           680:        return (struct ieee80211_node *)rn;
        !           681: }
        !           682:
        !           683: int
        !           684: rt2661_media_change(struct ifnet *ifp)
        !           685: {
        !           686:        int error;
        !           687:
        !           688:        error = ieee80211_media_change(ifp);
        !           689:        if (error != ENETRESET)
        !           690:                return error;
        !           691:
        !           692:        if ((ifp->if_flags & (IFF_UP | IFF_RUNNING)) == (IFF_UP | IFF_RUNNING))
        !           693:                rt2661_init(ifp);
        !           694:
        !           695:        return 0;
        !           696: }
        !           697:
        !           698: /*
        !           699:  * This function is called periodically (every 200ms) during scanning to
        !           700:  * switch from one channel to another.
        !           701:  */
        !           702: void
        !           703: rt2661_next_scan(void *arg)
        !           704: {
        !           705:        struct rt2661_softc *sc = arg;
        !           706:        struct ieee80211com *ic = &sc->sc_ic;
        !           707:        struct ifnet *ifp = &ic->ic_if;
        !           708:        int s;
        !           709:
        !           710:        s = splnet();
        !           711:        if (ic->ic_state == IEEE80211_S_SCAN)
        !           712:                ieee80211_next_scan(ifp);
        !           713:        splx(s);
        !           714: }
        !           715:
        !           716: /*
        !           717:  * This function is called for each neighbor node.
        !           718:  */
        !           719: void
        !           720: rt2661_iter_func(void *arg, struct ieee80211_node *ni)
        !           721: {
        !           722:        struct rt2661_softc *sc = arg;
        !           723:        struct rt2661_node *rn = (struct rt2661_node *)ni;
        !           724:
        !           725:        ieee80211_amrr_choose(&sc->amrr, ni, &rn->amn);
        !           726: }
        !           727:
        !           728: /*
        !           729:  * This function is called periodically (every 500ms) in RUN state to update
        !           730:  * various settings like rate control statistics or Rx sensitivity.
        !           731:  */
        !           732: void
        !           733: rt2661_updatestats(void *arg)
        !           734: {
        !           735:        struct rt2661_softc *sc = arg;
        !           736:        struct ieee80211com *ic = &sc->sc_ic;
        !           737:        int s;
        !           738:
        !           739:        s = splnet();
        !           740:        if (ic->ic_opmode == IEEE80211_M_STA)
        !           741:                rt2661_iter_func(sc, ic->ic_bss);
        !           742:        else
        !           743:                ieee80211_iterate_nodes(ic, rt2661_iter_func, arg);
        !           744:
        !           745:        /* update rx sensitivity every 1 sec */
        !           746:        if (++sc->ncalls & 1)
        !           747:                rt2661_rx_tune(sc);
        !           748:        splx(s);
        !           749:
        !           750:        timeout_add(&sc->amrr_to, hz / 2);
        !           751: }
        !           752:
        !           753: void
        !           754: rt2661_newassoc(struct ieee80211com *ic, struct ieee80211_node *ni, int isnew)
        !           755: {
        !           756:        struct rt2661_softc *sc = ic->ic_softc;
        !           757:        int i;
        !           758:
        !           759:        ieee80211_amrr_node_init(&sc->amrr, &((struct rt2661_node *)ni)->amn);
        !           760:
        !           761:        /* set rate to some reasonable initial value */
        !           762:        for (i = ni->ni_rates.rs_nrates - 1;
        !           763:             i > 0 && (ni->ni_rates.rs_rates[i] & IEEE80211_RATE_VAL) > 72;
        !           764:             i--);
        !           765:        ni->ni_txrate = i;
        !           766: }
        !           767:
        !           768: int
        !           769: rt2661_newstate(struct ieee80211com *ic, enum ieee80211_state nstate, int arg)
        !           770: {
        !           771:        struct rt2661_softc *sc = ic->ic_if.if_softc;
        !           772:        enum ieee80211_state ostate;
        !           773:        struct ieee80211_node *ni;
        !           774:        uint32_t tmp;
        !           775:        int error = 0;
        !           776:
        !           777:        ostate = ic->ic_state;
        !           778:        timeout_del(&sc->scan_to);
        !           779:        timeout_del(&sc->amrr_to);
        !           780:
        !           781:        switch (nstate) {
        !           782:        case IEEE80211_S_INIT:
        !           783:                if (ostate == IEEE80211_S_RUN) {
        !           784:                        /* abort TSF synchronization */
        !           785:                        tmp = RAL_READ(sc, RT2661_TXRX_CSR9);
        !           786:                        RAL_WRITE(sc, RT2661_TXRX_CSR9, tmp & ~0x00ffffff);
        !           787:                }
        !           788:                break;
        !           789:
        !           790:        case IEEE80211_S_SCAN:
        !           791:                rt2661_set_chan(sc, ic->ic_bss->ni_chan);
        !           792:                timeout_add(&sc->scan_to, hz / 5);
        !           793:                break;
        !           794:
        !           795:        case IEEE80211_S_AUTH:
        !           796:        case IEEE80211_S_ASSOC:
        !           797:                rt2661_set_chan(sc, ic->ic_bss->ni_chan);
        !           798:                break;
        !           799:
        !           800:        case IEEE80211_S_RUN:
        !           801:                rt2661_set_chan(sc, ic->ic_bss->ni_chan);
        !           802:
        !           803:                ni = ic->ic_bss;
        !           804:
        !           805:                if (ic->ic_opmode != IEEE80211_M_MONITOR) {
        !           806:                        rt2661_set_slottime(sc);
        !           807:                        rt2661_enable_mrr(sc);
        !           808:                        rt2661_set_txpreamble(sc);
        !           809:                        rt2661_set_basicrates(sc);
        !           810:                        rt2661_set_bssid(sc, ni->ni_bssid);
        !           811:                }
        !           812:
        !           813:                if (ic->ic_opmode == IEEE80211_M_HOSTAP ||
        !           814:                    ic->ic_opmode == IEEE80211_M_IBSS)
        !           815:                        rt2661_prepare_beacon(sc);
        !           816:
        !           817:                if (ic->ic_opmode == IEEE80211_M_STA) {
        !           818:                        /* fake a join to init the tx rate */
        !           819:                        rt2661_newassoc(ic, ni, 1);
        !           820:                }
        !           821:
        !           822:                if (ic->ic_opmode != IEEE80211_M_MONITOR) {
        !           823:                        sc->ncalls = 0;
        !           824:                        sc->avg_rssi = -95;     /* reset EMA */
        !           825:                        timeout_add(&sc->amrr_to, hz / 2);
        !           826:                        rt2661_enable_tsf_sync(sc);
        !           827:                }
        !           828:                break;
        !           829:        }
        !           830:
        !           831:        return (error != 0) ? error : sc->sc_newstate(ic, nstate, arg);
        !           832: }
        !           833:
        !           834: /*
        !           835:  * Read 16 bits at address 'addr' from the serial EEPROM (either 93C46 or
        !           836:  * 93C66).
        !           837:  */
        !           838: uint16_t
        !           839: rt2661_eeprom_read(struct rt2661_softc *sc, uint8_t addr)
        !           840: {
        !           841:        uint32_t tmp;
        !           842:        uint16_t val;
        !           843:        int n;
        !           844:
        !           845:        /* clock C once before the first command */
        !           846:        RT2661_EEPROM_CTL(sc, 0);
        !           847:
        !           848:        RT2661_EEPROM_CTL(sc, RT2661_S);
        !           849:        RT2661_EEPROM_CTL(sc, RT2661_S | RT2661_C);
        !           850:        RT2661_EEPROM_CTL(sc, RT2661_S);
        !           851:
        !           852:        /* write start bit (1) */
        !           853:        RT2661_EEPROM_CTL(sc, RT2661_S | RT2661_D);
        !           854:        RT2661_EEPROM_CTL(sc, RT2661_S | RT2661_D | RT2661_C);
        !           855:
        !           856:        /* write READ opcode (10) */
        !           857:        RT2661_EEPROM_CTL(sc, RT2661_S | RT2661_D);
        !           858:        RT2661_EEPROM_CTL(sc, RT2661_S | RT2661_D | RT2661_C);
        !           859:        RT2661_EEPROM_CTL(sc, RT2661_S);
        !           860:        RT2661_EEPROM_CTL(sc, RT2661_S | RT2661_C);
        !           861:
        !           862:        /* write address (A5-A0 or A7-A0) */
        !           863:        n = (RAL_READ(sc, RT2661_E2PROM_CSR) & RT2661_93C46) ? 5 : 7;
        !           864:        for (; n >= 0; n--) {
        !           865:                RT2661_EEPROM_CTL(sc, RT2661_S |
        !           866:                    (((addr >> n) & 1) << RT2661_SHIFT_D));
        !           867:                RT2661_EEPROM_CTL(sc, RT2661_S |
        !           868:                    (((addr >> n) & 1) << RT2661_SHIFT_D) | RT2661_C);
        !           869:        }
        !           870:
        !           871:        RT2661_EEPROM_CTL(sc, RT2661_S);
        !           872:
        !           873:        /* read data Q15-Q0 */
        !           874:        val = 0;
        !           875:        for (n = 15; n >= 0; n--) {
        !           876:                RT2661_EEPROM_CTL(sc, RT2661_S | RT2661_C);
        !           877:                tmp = RAL_READ(sc, RT2661_E2PROM_CSR);
        !           878:                val |= ((tmp & RT2661_Q) >> RT2661_SHIFT_Q) << n;
        !           879:                RT2661_EEPROM_CTL(sc, RT2661_S);
        !           880:        }
        !           881:
        !           882:        RT2661_EEPROM_CTL(sc, 0);
        !           883:
        !           884:        /* clear Chip Select and clock C */
        !           885:        RT2661_EEPROM_CTL(sc, RT2661_S);
        !           886:        RT2661_EEPROM_CTL(sc, 0);
        !           887:        RT2661_EEPROM_CTL(sc, RT2661_C);
        !           888:
        !           889:        return val;
        !           890: }
        !           891:
        !           892: void
        !           893: rt2661_tx_intr(struct rt2661_softc *sc)
        !           894: {
        !           895:        struct ieee80211com *ic = &sc->sc_ic;
        !           896:        struct ifnet *ifp = &ic->ic_if;
        !           897:        struct rt2661_tx_ring *txq;
        !           898:        struct rt2661_tx_data *data;
        !           899:        struct rt2661_node *rn;
        !           900:        int qid, retrycnt;
        !           901:
        !           902:        for (;;) {
        !           903:                const uint32_t val = RAL_READ(sc, RT2661_STA_CSR4);
        !           904:                if (!(val & RT2661_TX_STAT_VALID))
        !           905:                        break;
        !           906:
        !           907:                /* retrieve the queue in which this frame was sent */
        !           908:                qid = RT2661_TX_QID(val);
        !           909:                txq = (qid <= 3) ? &sc->txq[qid] : &sc->mgtq;
        !           910:
        !           911:                /* retrieve rate control algorithm context */
        !           912:                data = &txq->data[txq->stat];
        !           913:                rn = (struct rt2661_node *)data->ni;
        !           914:
        !           915:                /* if no frame has been sent, ignore */
        !           916:                if (rn == NULL)
        !           917:                        continue;
        !           918:
        !           919:                switch (RT2661_TX_RESULT(val)) {
        !           920:                case RT2661_TX_SUCCESS:
        !           921:                        retrycnt = RT2661_TX_RETRYCNT(val);
        !           922:
        !           923:                        DPRINTFN(10, ("data frame sent successfully after "
        !           924:                            "%d retries\n", retrycnt));
        !           925:                        rn->amn.amn_txcnt++;
        !           926:                        if (retrycnt > 0)
        !           927:                                rn->amn.amn_retrycnt++;
        !           928:                        ifp->if_opackets++;
        !           929:                        break;
        !           930:
        !           931:                case RT2661_TX_RETRY_FAIL:
        !           932:                        DPRINTFN(9, ("sending data frame failed (too much "
        !           933:                            "retries)\n"));
        !           934:                        rn->amn.amn_txcnt++;
        !           935:                        rn->amn.amn_retrycnt++;
        !           936:                        ifp->if_oerrors++;
        !           937:                        break;
        !           938:
        !           939:                default:
        !           940:                        /* other failure */
        !           941:                        printf("%s: sending data frame failed 0x%08x\n",
        !           942:                            sc->sc_dev.dv_xname, val);
        !           943:                        ifp->if_oerrors++;
        !           944:                }
        !           945:
        !           946:                ieee80211_release_node(ic, data->ni);
        !           947:                data->ni = NULL;
        !           948:
        !           949:                DPRINTFN(15, ("tx done q=%d idx=%u\n", qid, txq->stat));
        !           950:
        !           951:                txq->queued--;
        !           952:                if (++txq->stat >= txq->count)  /* faster than % count */
        !           953:                        txq->stat = 0;
        !           954:        }
        !           955:
        !           956:        sc->sc_tx_timer = 0;
        !           957:        ifp->if_flags &= ~IFF_OACTIVE;
        !           958:        rt2661_start(ifp);
        !           959: }
        !           960:
        !           961: void
        !           962: rt2661_tx_dma_intr(struct rt2661_softc *sc, struct rt2661_tx_ring *txq)
        !           963: {
        !           964:        for (;;) {
        !           965:                struct rt2661_tx_desc *desc = &txq->desc[txq->next];
        !           966:                struct rt2661_tx_data *data = &txq->data[txq->next];
        !           967:
        !           968:                bus_dmamap_sync(sc->sc_dmat, txq->map,
        !           969:                    txq->next * RT2661_TX_DESC_SIZE, RT2661_TX_DESC_SIZE,
        !           970:                    BUS_DMASYNC_POSTREAD);
        !           971:
        !           972:                if ((letoh32(desc->flags) & RT2661_TX_BUSY) ||
        !           973:                    !(letoh32(desc->flags) & RT2661_TX_VALID))
        !           974:                        break;
        !           975:
        !           976:                bus_dmamap_sync(sc->sc_dmat, data->map, 0,
        !           977:                    data->map->dm_mapsize, BUS_DMASYNC_POSTWRITE);
        !           978:                bus_dmamap_unload(sc->sc_dmat, data->map);
        !           979:                m_freem(data->m);
        !           980:                data->m = NULL;
        !           981:                /* node reference is released in rt2661_tx_intr() */
        !           982:
        !           983:                /* descriptor is no longer valid */
        !           984:                desc->flags &= ~htole32(RT2661_TX_VALID);
        !           985:
        !           986:                bus_dmamap_sync(sc->sc_dmat, txq->map,
        !           987:                    txq->next * RT2661_TX_DESC_SIZE, RT2661_TX_DESC_SIZE,
        !           988:                    BUS_DMASYNC_PREWRITE);
        !           989:
        !           990:                DPRINTFN(15, ("tx dma done q=%p idx=%u\n", txq, txq->next));
        !           991:
        !           992:                if (++txq->next >= txq->count)  /* faster than % count */
        !           993:                        txq->next = 0;
        !           994:        }
        !           995: }
        !           996:
        !           997: void
        !           998: rt2661_rx_intr(struct rt2661_softc *sc)
        !           999: {
        !          1000:        struct ieee80211com *ic = &sc->sc_ic;
        !          1001:        struct ifnet *ifp = &ic->ic_if;
        !          1002:        struct ieee80211_frame *wh;
        !          1003:        struct ieee80211_node *ni;
        !          1004:        struct mbuf *mnew, *m;
        !          1005:        int error, rssi;
        !          1006:
        !          1007:        for (;;) {
        !          1008:                struct rt2661_rx_desc *desc = &sc->rxq.desc[sc->rxq.cur];
        !          1009:                struct rt2661_rx_data *data = &sc->rxq.data[sc->rxq.cur];
        !          1010:
        !          1011:                bus_dmamap_sync(sc->sc_dmat, sc->rxq.map,
        !          1012:                    sc->rxq.cur * RT2661_RX_DESC_SIZE, RT2661_RX_DESC_SIZE,
        !          1013:                    BUS_DMASYNC_POSTREAD);
        !          1014:
        !          1015:                if (letoh32(desc->flags) & RT2661_RX_BUSY)
        !          1016:                        break;
        !          1017:
        !          1018:                if ((letoh32(desc->flags) & RT2661_RX_PHY_ERROR) ||
        !          1019:                    (letoh32(desc->flags) & RT2661_RX_CRC_ERROR)) {
        !          1020:                        /*
        !          1021:                         * This should not happen since we did not request
        !          1022:                         * to receive those frames when we filled TXRX_CSR0.
        !          1023:                         */
        !          1024:                        DPRINTFN(5, ("PHY or CRC error flags 0x%08x\n",
        !          1025:                            letoh32(desc->flags)));
        !          1026:                        ifp->if_ierrors++;
        !          1027:                        goto skip;
        !          1028:                }
        !          1029:
        !          1030:                if ((letoh32(desc->flags) & RT2661_RX_CIPHER_MASK) != 0) {
        !          1031:                        ifp->if_ierrors++;
        !          1032:                        goto skip;
        !          1033:                }
        !          1034:
        !          1035:                /*
        !          1036:                 * Try to allocate a new mbuf for this ring element and load it
        !          1037:                 * before processing the current mbuf. If the ring element
        !          1038:                 * cannot be loaded, drop the received packet and reuse the old
        !          1039:                 * mbuf. In the unlikely case that the old mbuf can't be
        !          1040:                 * reloaded either, explicitly panic.
        !          1041:                 */
        !          1042:                MGETHDR(mnew, M_DONTWAIT, MT_DATA);
        !          1043:                if (mnew == NULL) {
        !          1044:                        ifp->if_ierrors++;
        !          1045:                        goto skip;
        !          1046:                }
        !          1047:                MCLGET(mnew, M_DONTWAIT);
        !          1048:                if (!(mnew->m_flags & M_EXT)) {
        !          1049:                        m_freem(mnew);
        !          1050:                        ifp->if_ierrors++;
        !          1051:                        goto skip;
        !          1052:                }
        !          1053:
        !          1054:                bus_dmamap_sync(sc->sc_dmat, data->map, 0,
        !          1055:                    data->map->dm_mapsize, BUS_DMASYNC_POSTREAD);
        !          1056:                bus_dmamap_unload(sc->sc_dmat, data->map);
        !          1057:
        !          1058:                error = bus_dmamap_load(sc->sc_dmat, data->map,
        !          1059:                    mtod(mnew, void *), MCLBYTES, NULL, BUS_DMA_NOWAIT);
        !          1060:                if (error != 0) {
        !          1061:                        m_freem(mnew);
        !          1062:
        !          1063:                        /* try to reload the old mbuf */
        !          1064:                        error = bus_dmamap_load(sc->sc_dmat, data->map,
        !          1065:                            mtod(data->m, void *), MCLBYTES, NULL,
        !          1066:                            BUS_DMA_NOWAIT);
        !          1067:                        if (error != 0) {
        !          1068:                                /* very unlikely that it will fail... */
        !          1069:                                panic("%s: could not load old rx mbuf",
        !          1070:                                    sc->sc_dev.dv_xname);
        !          1071:                        }
        !          1072:                        ifp->if_ierrors++;
        !          1073:                        goto skip;
        !          1074:                }
        !          1075:
        !          1076:                /*
        !          1077:                 * New mbuf successfully loaded, update Rx ring and continue
        !          1078:                 * processing.
        !          1079:                 */
        !          1080:                m = data->m;
        !          1081:                data->m = mnew;
        !          1082:                desc->physaddr = htole32(data->map->dm_segs->ds_addr);
        !          1083:
        !          1084:                /* finalize mbuf */
        !          1085:                m->m_pkthdr.rcvif = ifp;
        !          1086:                m->m_pkthdr.len = m->m_len =
        !          1087:                    (letoh32(desc->flags) >> 16) & 0xfff;
        !          1088:
        !          1089: #if NBPFILTER > 0
        !          1090:                if (sc->sc_drvbpf != NULL) {
        !          1091:                        struct mbuf mb;
        !          1092:                        struct rt2661_rx_radiotap_header *tap = &sc->sc_rxtap;
        !          1093:                        uint32_t tsf_lo, tsf_hi;
        !          1094:
        !          1095:                        /* get timestamp (low and high 32 bits) */
        !          1096:                        tsf_hi = RAL_READ(sc, RT2661_TXRX_CSR13);
        !          1097:                        tsf_lo = RAL_READ(sc, RT2661_TXRX_CSR12);
        !          1098:
        !          1099:                        tap->wr_tsf =
        !          1100:                            htole64(((uint64_t)tsf_hi << 32) | tsf_lo);
        !          1101:                        tap->wr_flags = 0;
        !          1102:                        tap->wr_rate = rt2661_rxrate(desc);
        !          1103:                        tap->wr_chan_freq = htole16(sc->sc_curchan->ic_freq);
        !          1104:                        tap->wr_chan_flags = htole16(sc->sc_curchan->ic_flags);
        !          1105:                        tap->wr_antsignal = desc->rssi;
        !          1106:
        !          1107:                        mb.m_data = (caddr_t)tap;
        !          1108:                        mb.m_len = sc->sc_rxtap_len;
        !          1109:                        mb.m_next = m;
        !          1110:                        mb.m_nextpkt = NULL;
        !          1111:                        mb.m_type = 0;
        !          1112:                        mb.m_flags = 0;
        !          1113:                        bpf_mtap(sc->sc_drvbpf, &mb, BPF_DIRECTION_IN);
        !          1114:                }
        !          1115: #endif
        !          1116:
        !          1117:                wh = mtod(m, struct ieee80211_frame *);
        !          1118:                ni = ieee80211_find_rxnode(ic, wh);
        !          1119:
        !          1120:                /* send the frame to the 802.11 layer */
        !          1121:                ieee80211_input(ifp, m, ni, desc->rssi, 0);
        !          1122:
        !          1123:                /*-
        !          1124:                 * Keep track of the average RSSI using an Exponential Moving
        !          1125:                 * Average (EMA) of 8 Wilder's days:
        !          1126:                 *     avg = (1 / N) x rssi + ((N - 1) / N) x avg
        !          1127:                 */
        !          1128:                rssi = rt2661_get_rssi(sc, desc->rssi);
        !          1129:                sc->avg_rssi = (rssi + 7 * sc->avg_rssi) / 8;
        !          1130:
        !          1131:                /* node is no longer needed */
        !          1132:                ieee80211_release_node(ic, ni);
        !          1133:
        !          1134: skip:          desc->flags |= htole32(RT2661_RX_BUSY);
        !          1135:
        !          1136:                bus_dmamap_sync(sc->sc_dmat, sc->rxq.map,
        !          1137:                    sc->rxq.cur * RT2661_RX_DESC_SIZE, RT2661_RX_DESC_SIZE,
        !          1138:                    BUS_DMASYNC_PREWRITE);
        !          1139:
        !          1140:                DPRINTFN(15, ("rx intr idx=%u\n", sc->rxq.cur));
        !          1141:
        !          1142:                sc->rxq.cur = (sc->rxq.cur + 1) % RT2661_RX_RING_COUNT;
        !          1143:        }
        !          1144:
        !          1145:        /*
        !          1146:         * In HostAP mode, ieee80211_input() will enqueue packets in if_snd
        !          1147:         * without calling if_start().
        !          1148:         */
        !          1149:        if (!IFQ_IS_EMPTY(&ifp->if_snd) && !(ifp->if_flags & IFF_OACTIVE))
        !          1150:                rt2661_start(ifp);
        !          1151: }
        !          1152:
        !          1153: /*
        !          1154:  * This function is called in HostAP or IBSS modes when it's time to send a
        !          1155:  * new beacon (every ni_intval milliseconds).
        !          1156:  */
        !          1157: void
        !          1158: rt2661_mcu_beacon_expire(struct rt2661_softc *sc)
        !          1159: {
        !          1160:        struct ieee80211com *ic = &sc->sc_ic;
        !          1161:
        !          1162:        if (sc->sc_flags & RT2661_UPDATE_SLOT) {
        !          1163:                sc->sc_flags &= ~RT2661_UPDATE_SLOT;
        !          1164:                sc->sc_flags |= RT2661_SET_SLOTTIME;
        !          1165:        } else if (sc->sc_flags & RT2661_SET_SLOTTIME) {
        !          1166:                sc->sc_flags &= ~RT2661_SET_SLOTTIME;
        !          1167:                rt2661_set_slottime(sc);
        !          1168:        }
        !          1169:
        !          1170:        if (ic->ic_curmode == IEEE80211_MODE_11G) {
        !          1171:                /* update ERP Information Element */
        !          1172:                RAL_WRITE_1(sc, sc->erp_csr, ic->ic_bss->ni_erp);
        !          1173:                RAL_RW_BARRIER_1(sc, sc->erp_csr);
        !          1174:        }
        !          1175:
        !          1176:        DPRINTFN(15, ("beacon expired\n"));
        !          1177: }
        !          1178:
        !          1179: void
        !          1180: rt2661_mcu_wakeup(struct rt2661_softc *sc)
        !          1181: {
        !          1182:        RAL_WRITE(sc, RT2661_MAC_CSR11, 5 << 16);
        !          1183:
        !          1184:        RAL_WRITE(sc, RT2661_SOFT_RESET_CSR, 0x7);
        !          1185:        RAL_WRITE(sc, RT2661_IO_CNTL_CSR, 0x18);
        !          1186:        RAL_WRITE(sc, RT2661_PCI_USEC_CSR, 0x20);
        !          1187:
        !          1188:        /* send wakeup command to MCU */
        !          1189:        rt2661_tx_cmd(sc, RT2661_MCU_CMD_WAKEUP, 0);
        !          1190: }
        !          1191:
        !          1192: void
        !          1193: rt2661_mcu_cmd_intr(struct rt2661_softc *sc)
        !          1194: {
        !          1195:        RAL_READ(sc, RT2661_M2H_CMD_DONE_CSR);
        !          1196:        RAL_WRITE(sc, RT2661_M2H_CMD_DONE_CSR, 0xffffffff);
        !          1197: }
        !          1198:
        !          1199: int
        !          1200: rt2661_intr(void *arg)
        !          1201: {
        !          1202:        struct rt2661_softc *sc = arg;
        !          1203:        struct ifnet *ifp = &sc->sc_ic.ic_if;
        !          1204:        uint32_t r1, r2;
        !          1205:
        !          1206:        r1 = RAL_READ(sc, RT2661_INT_SOURCE_CSR);
        !          1207:        r2 = RAL_READ(sc, RT2661_MCU_INT_SOURCE_CSR);
        !          1208:        if (r1 == 0 && r2 == 0)
        !          1209:                return 0;       /* not for us */
        !          1210:
        !          1211:        /* disable MAC and MCU interrupts */
        !          1212:        RAL_WRITE(sc, RT2661_INT_MASK_CSR, 0xffffff7f);
        !          1213:        RAL_WRITE(sc, RT2661_MCU_INT_MASK_CSR, 0xffffffff);
        !          1214:
        !          1215:        /* acknowledge interrupts */
        !          1216:        RAL_WRITE(sc, RT2661_INT_SOURCE_CSR, r1);
        !          1217:        RAL_WRITE(sc, RT2661_MCU_INT_SOURCE_CSR, r2);
        !          1218:
        !          1219:        /* don't re-enable interrupts if we're shutting down */
        !          1220:        if (!(ifp->if_flags & IFF_RUNNING))
        !          1221:                return 0;
        !          1222:
        !          1223:        if (r1 & RT2661_MGT_DONE)
        !          1224:                rt2661_tx_dma_intr(sc, &sc->mgtq);
        !          1225:
        !          1226:        if (r1 & RT2661_RX_DONE)
        !          1227:                rt2661_rx_intr(sc);
        !          1228:
        !          1229:        if (r1 & RT2661_TX0_DMA_DONE)
        !          1230:                rt2661_tx_dma_intr(sc, &sc->txq[0]);
        !          1231:
        !          1232:        if (r1 & RT2661_TX1_DMA_DONE)
        !          1233:                rt2661_tx_dma_intr(sc, &sc->txq[1]);
        !          1234:
        !          1235:        if (r1 & RT2661_TX2_DMA_DONE)
        !          1236:                rt2661_tx_dma_intr(sc, &sc->txq[2]);
        !          1237:
        !          1238:        if (r1 & RT2661_TX3_DMA_DONE)
        !          1239:                rt2661_tx_dma_intr(sc, &sc->txq[3]);
        !          1240:
        !          1241:        if (r1 & RT2661_TX_DONE)
        !          1242:                rt2661_tx_intr(sc);
        !          1243:
        !          1244:        if (r2 & RT2661_MCU_CMD_DONE)
        !          1245:                rt2661_mcu_cmd_intr(sc);
        !          1246:
        !          1247:        if (r2 & RT2661_MCU_BEACON_EXPIRE)
        !          1248:                rt2661_mcu_beacon_expire(sc);
        !          1249:
        !          1250:        if (r2 & RT2661_MCU_WAKEUP)
        !          1251:                rt2661_mcu_wakeup(sc);
        !          1252:
        !          1253:        /* re-enable MAC and MCU interrupts */
        !          1254:        RAL_WRITE(sc, RT2661_INT_MASK_CSR, 0x0000ff10);
        !          1255:        RAL_WRITE(sc, RT2661_MCU_INT_MASK_CSR, 0);
        !          1256:
        !          1257:        return 1;
        !          1258: }
        !          1259:
        !          1260: /* quickly determine if a given rate is CCK or OFDM */
        !          1261: #define RAL_RATE_IS_OFDM(rate) ((rate) >= 12 && (rate) != 22)
        !          1262:
        !          1263: #define RAL_ACK_SIZE   14      /* 10 + 4(FCS) */
        !          1264: #define RAL_CTS_SIZE   14      /* 10 + 4(FCS) */
        !          1265:
        !          1266: /*
        !          1267:  * This function is only used by the Rx radiotap code. It returns the rate at
        !          1268:  * which a given frame was received.
        !          1269:  */
        !          1270: #if NBPFILTER > 0
        !          1271: uint8_t
        !          1272: rt2661_rxrate(const struct rt2661_rx_desc *desc)
        !          1273: {
        !          1274:        if (letoh32(desc->flags) & RT2661_RX_OFDM) {
        !          1275:                /* reverse function of rt2661_plcp_signal */
        !          1276:                switch (desc->rate & 0xf) {
        !          1277:                case 0xb:       return 12;
        !          1278:                case 0xf:       return 18;
        !          1279:                case 0xa:       return 24;
        !          1280:                case 0xe:       return 36;
        !          1281:                case 0x9:       return 48;
        !          1282:                case 0xd:       return 72;
        !          1283:                case 0x8:       return 96;
        !          1284:                case 0xc:       return 108;
        !          1285:                }
        !          1286:        } else {
        !          1287:                if (desc->rate == 10)
        !          1288:                        return 2;
        !          1289:                if (desc->rate == 20)
        !          1290:                        return 4;
        !          1291:                if (desc->rate == 55)
        !          1292:                        return 11;
        !          1293:                if (desc->rate == 110)
        !          1294:                        return 22;
        !          1295:        }
        !          1296:        return 2;       /* should not get there */
        !          1297: }
        !          1298: #endif
        !          1299:
        !          1300: /*
        !          1301:  * Return the expected ack rate for a frame transmitted at rate `rate'.
        !          1302:  */
        !          1303: int
        !          1304: rt2661_ack_rate(struct ieee80211com *ic, int rate)
        !          1305: {
        !          1306:        switch (rate) {
        !          1307:        /* CCK rates */
        !          1308:        case 2:
        !          1309:                return 2;
        !          1310:        case 4:
        !          1311:        case 11:
        !          1312:        case 22:
        !          1313:                return (ic->ic_curmode == IEEE80211_MODE_11B) ? 4 : rate;
        !          1314:
        !          1315:        /* OFDM rates */
        !          1316:        case 12:
        !          1317:        case 18:
        !          1318:                return 12;
        !          1319:        case 24:
        !          1320:        case 36:
        !          1321:                return 24;
        !          1322:        case 48:
        !          1323:        case 72:
        !          1324:        case 96:
        !          1325:        case 108:
        !          1326:                return 48;
        !          1327:        }
        !          1328:
        !          1329:        /* default to 1Mbps */
        !          1330:        return 2;
        !          1331: }
        !          1332:
        !          1333: /*
        !          1334:  * Compute the duration (in us) needed to transmit `len' bytes at rate `rate'.
        !          1335:  * The function automatically determines the operating mode depending on the
        !          1336:  * given rate. `flags' indicates whether short preamble is in use or not.
        !          1337:  */
        !          1338: uint16_t
        !          1339: rt2661_txtime(int len, int rate, uint32_t flags)
        !          1340: {
        !          1341:        uint16_t txtime;
        !          1342:
        !          1343:        if (RAL_RATE_IS_OFDM(rate)) {
        !          1344:                /* IEEE Std 802.11g-2003, pp. 44 */
        !          1345:                txtime = (8 + 4 * len + 3 + rate - 1) / rate;
        !          1346:                txtime = 16 + 4 + 4 * txtime + 6;
        !          1347:        } else {
        !          1348:                /* IEEE Std 802.11b-1999, pp. 28 */
        !          1349:                txtime = (16 * len + rate - 1) / rate;
        !          1350:                if (rate != 2 && (flags & IEEE80211_F_SHPREAMBLE))
        !          1351:                        txtime +=  72 + 24;
        !          1352:                else
        !          1353:                        txtime += 144 + 48;
        !          1354:        }
        !          1355:        return txtime;
        !          1356: }
        !          1357:
        !          1358: uint8_t
        !          1359: rt2661_plcp_signal(int rate)
        !          1360: {
        !          1361:        switch (rate) {
        !          1362:        /* CCK rates (returned values are device-dependent) */
        !          1363:        case 2:         return 0x0;
        !          1364:        case 4:         return 0x1;
        !          1365:        case 11:        return 0x2;
        !          1366:        case 22:        return 0x3;
        !          1367:
        !          1368:        /* OFDM rates (cf IEEE Std 802.11a-1999, pp. 14 Table 80) */
        !          1369:        case 12:        return 0xb;
        !          1370:        case 18:        return 0xf;
        !          1371:        case 24:        return 0xa;
        !          1372:        case 36:        return 0xe;
        !          1373:        case 48:        return 0x9;
        !          1374:        case 72:        return 0xd;
        !          1375:        case 96:        return 0x8;
        !          1376:        case 108:       return 0xc;
        !          1377:
        !          1378:        /* unsupported rates (should not get there) */
        !          1379:        default:        return 0xff;
        !          1380:        }
        !          1381: }
        !          1382:
        !          1383: void
        !          1384: rt2661_setup_tx_desc(struct rt2661_softc *sc, struct rt2661_tx_desc *desc,
        !          1385:     uint32_t flags, uint16_t xflags, int len, int rate,
        !          1386:     const bus_dma_segment_t *segs, int nsegs, int ac)
        !          1387: {
        !          1388:        struct ieee80211com *ic = &sc->sc_ic;
        !          1389:        uint16_t plcp_length;
        !          1390:        int i, remainder;
        !          1391:
        !          1392:        desc->flags = htole32(flags);
        !          1393:        desc->flags |= htole32(len << 16);
        !          1394:        desc->flags |= htole32(RT2661_TX_BUSY | RT2661_TX_VALID);
        !          1395:
        !          1396:        desc->xflags = htole16(xflags);
        !          1397:        desc->xflags |= htole16(nsegs << 13);
        !          1398:
        !          1399:        desc->wme = htole16(
        !          1400:            RT2661_QID(ac) |
        !          1401:            RT2661_AIFSN(2) |
        !          1402:            RT2661_LOGCWMIN(4) |
        !          1403:            RT2661_LOGCWMAX(10));
        !          1404:
        !          1405:        /*
        !          1406:         * Remember in which queue this frame was sent. This field is driver
        !          1407:         * private data only. It will be made available by the NIC in STA_CSR4
        !          1408:         * on Tx interrupts.
        !          1409:         */
        !          1410:        desc->qid = ac;
        !          1411:
        !          1412:        /* setup PLCP fields */
        !          1413:        desc->plcp_signal  = rt2661_plcp_signal(rate);
        !          1414:        desc->plcp_service = 4;
        !          1415:
        !          1416:        len += IEEE80211_CRC_LEN;
        !          1417:        if (RAL_RATE_IS_OFDM(rate)) {
        !          1418:                desc->flags |= htole32(RT2661_TX_OFDM);
        !          1419:
        !          1420:                plcp_length = len & 0xfff;
        !          1421:                desc->plcp_length_hi = plcp_length >> 6;
        !          1422:                desc->plcp_length_lo = plcp_length & 0x3f;
        !          1423:        } else {
        !          1424:                plcp_length = (16 * len + rate - 1) / rate;
        !          1425:                if (rate == 22) {
        !          1426:                        remainder = (16 * len) % 22;
        !          1427:                        if (remainder != 0 && remainder < 7)
        !          1428:                                desc->plcp_service |= RT2661_PLCP_LENGEXT;
        !          1429:                }
        !          1430:                desc->plcp_length_hi = plcp_length >> 8;
        !          1431:                desc->plcp_length_lo = plcp_length & 0xff;
        !          1432:
        !          1433:                if (rate != 2 && (ic->ic_flags & IEEE80211_F_SHPREAMBLE))
        !          1434:                        desc->plcp_signal |= 0x08;
        !          1435:        }
        !          1436:
        !          1437:        /* RT2x61 supports scatter with up to 5 segments */
        !          1438:        for (i = 0; i < nsegs; i++) {
        !          1439:                desc->addr[i] = htole32(segs[i].ds_addr);
        !          1440:                desc->len [i] = htole16(segs[i].ds_len);
        !          1441:        }
        !          1442: }
        !          1443:
        !          1444: int
        !          1445: rt2661_tx_mgt(struct rt2661_softc *sc, struct mbuf *m0,
        !          1446:     struct ieee80211_node *ni)
        !          1447: {
        !          1448:        struct ieee80211com *ic = &sc->sc_ic;
        !          1449:        struct ifnet *ifp = &ic->ic_if;
        !          1450:        struct rt2661_tx_desc *desc;
        !          1451:        struct rt2661_tx_data *data;
        !          1452:        struct ieee80211_frame *wh;
        !          1453:        uint16_t dur;
        !          1454:        uint32_t flags = 0;
        !          1455:        int rate, error;
        !          1456:
        !          1457:        desc = &sc->mgtq.desc[sc->mgtq.cur];
        !          1458:        data = &sc->mgtq.data[sc->mgtq.cur];
        !          1459:
        !          1460:        /* send mgt frames at the lowest available rate */
        !          1461:        rate = IEEE80211_IS_CHAN_5GHZ(ni->ni_chan) ? 12 : 2;
        !          1462:
        !          1463:        wh = mtod(m0, struct ieee80211_frame *);
        !          1464:
        !          1465:        if (wh->i_fc[1] & IEEE80211_FC1_WEP) {
        !          1466:                m0 = ieee80211_wep_crypt(ifp, m0, 1);
        !          1467:                if (m0 == NULL)
        !          1468:                        return ENOBUFS;
        !          1469:
        !          1470:                /* packet header may have moved, reset our local pointer */
        !          1471:                wh = mtod(m0, struct ieee80211_frame *);
        !          1472:        }
        !          1473:
        !          1474:        error = bus_dmamap_load_mbuf(sc->sc_dmat, data->map, m0,
        !          1475:            BUS_DMA_NOWAIT);
        !          1476:        if (error != 0) {
        !          1477:                printf("%s: could not map mbuf (error %d)\n",
        !          1478:                    sc->sc_dev.dv_xname, error);
        !          1479:                m_freem(m0);
        !          1480:                return error;
        !          1481:        }
        !          1482:
        !          1483: #if NBPFILTER > 0
        !          1484:        if (sc->sc_drvbpf != NULL) {
        !          1485:                struct mbuf mb;
        !          1486:                struct rt2661_tx_radiotap_header *tap = &sc->sc_txtap;
        !          1487:
        !          1488:                tap->wt_flags = 0;
        !          1489:                tap->wt_rate = rate;
        !          1490:                tap->wt_chan_freq = htole16(sc->sc_curchan->ic_freq);
        !          1491:                tap->wt_chan_flags = htole16(sc->sc_curchan->ic_flags);
        !          1492:
        !          1493:                mb.m_data = (caddr_t)tap;
        !          1494:                mb.m_len = sc->sc_txtap_len;
        !          1495:                mb.m_next = m0;
        !          1496:                mb.m_nextpkt = NULL;
        !          1497:                mb.m_type = 0;
        !          1498:                mb.m_flags = 0;
        !          1499:                bpf_mtap(sc->sc_drvbpf, &mb, BPF_DIRECTION_OUT);
        !          1500:        }
        !          1501: #endif
        !          1502:
        !          1503:        data->m = m0;
        !          1504:        data->ni = ni;
        !          1505:
        !          1506:        if (!IEEE80211_IS_MULTICAST(wh->i_addr1)) {
        !          1507:                flags |= RT2661_TX_NEED_ACK;
        !          1508:
        !          1509:                dur = rt2661_txtime(RAL_ACK_SIZE, rate, ic->ic_flags) +
        !          1510:                    sc->sifs;
        !          1511:                *(uint16_t *)wh->i_dur = htole16(dur);
        !          1512:
        !          1513:                /* tell hardware to set timestamp in probe responses */
        !          1514:                if ((wh->i_fc[0] &
        !          1515:                    (IEEE80211_FC0_TYPE_MASK | IEEE80211_FC0_SUBTYPE_MASK)) ==
        !          1516:                    (IEEE80211_FC0_TYPE_MGT | IEEE80211_FC0_SUBTYPE_PROBE_RESP))
        !          1517:                        flags |= RT2661_TX_TIMESTAMP;
        !          1518:        }
        !          1519:
        !          1520:        rt2661_setup_tx_desc(sc, desc, flags, 0 /* XXX HWSEQ */,
        !          1521:            m0->m_pkthdr.len, rate, data->map->dm_segs, data->map->dm_nsegs,
        !          1522:            RT2661_QID_MGT);
        !          1523:
        !          1524:        bus_dmamap_sync(sc->sc_dmat, data->map, 0, data->map->dm_mapsize,
        !          1525:            BUS_DMASYNC_PREWRITE);
        !          1526:        bus_dmamap_sync(sc->sc_dmat, sc->mgtq.map,
        !          1527:            sc->mgtq.cur * RT2661_TX_DESC_SIZE, RT2661_TX_DESC_SIZE,
        !          1528:            BUS_DMASYNC_PREWRITE);
        !          1529:
        !          1530:        DPRINTFN(10, ("sending mgt frame len=%u idx=%u rate=%u\n",
        !          1531:            m0->m_pkthdr.len, sc->mgtq.cur, rate));
        !          1532:
        !          1533:        /* kick mgt */
        !          1534:        sc->mgtq.queued++;
        !          1535:        sc->mgtq.cur = (sc->mgtq.cur + 1) % RT2661_MGT_RING_COUNT;
        !          1536:        RAL_WRITE(sc, RT2661_TX_CNTL_CSR, RT2661_KICK_MGT);
        !          1537:
        !          1538:        return 0;
        !          1539: }
        !          1540:
        !          1541: int
        !          1542: rt2661_tx_data(struct rt2661_softc *sc, struct mbuf *m0,
        !          1543:     struct ieee80211_node *ni, int ac)
        !          1544: {
        !          1545:        struct ieee80211com *ic = &sc->sc_ic;
        !          1546:        struct ifnet *ifp = &ic->ic_if;
        !          1547:        struct rt2661_tx_ring *txq = &sc->txq[ac];
        !          1548:        struct rt2661_tx_desc *desc;
        !          1549:        struct rt2661_tx_data *data;
        !          1550:        struct ieee80211_frame *wh;
        !          1551:        struct mbuf *mnew;
        !          1552:        uint16_t dur;
        !          1553:        uint32_t flags = 0;
        !          1554:        int pktlen, rate, needcts = 0, needrts = 0, error;
        !          1555:
        !          1556:        wh = mtod(m0, struct ieee80211_frame *);
        !          1557:
        !          1558:        if (wh->i_fc[1] & IEEE80211_FC1_WEP) {
        !          1559:                m0 = ieee80211_wep_crypt(ifp, m0, 1);
        !          1560:                if (m0 == NULL)
        !          1561:                        return ENOBUFS;
        !          1562:
        !          1563:                /* packet header may have moved, reset our local pointer */
        !          1564:                wh = mtod(m0, struct ieee80211_frame *);
        !          1565:        }
        !          1566:
        !          1567:        /* compute actual packet length (including CRC and crypto overhead) */
        !          1568:        pktlen = m0->m_pkthdr.len + IEEE80211_CRC_LEN;
        !          1569:
        !          1570:        /* pickup a rate */
        !          1571:        if (IEEE80211_IS_MULTICAST(wh->i_addr1)) {
        !          1572:                /* multicast frames are sent at the lowest avail. rate */
        !          1573:                rate = ni->ni_rates.rs_rates[0];
        !          1574:        } else if (ic->ic_fixed_rate != -1) {
        !          1575:                rate = ic->ic_sup_rates[ic->ic_curmode].
        !          1576:                    rs_rates[ic->ic_fixed_rate];
        !          1577:        } else
        !          1578:                rate = ni->ni_rates.rs_rates[ni->ni_txrate];
        !          1579:        if (rate == 0)
        !          1580:                rate = 2;       /* XXX should not happen */
        !          1581:        rate &= IEEE80211_RATE_VAL;
        !          1582:
        !          1583:        /*
        !          1584:         * Packet Bursting: backoff after ppb=8 frames to give other STAs a
        !          1585:         * chance to contend for the wireless medium.
        !          1586:         */
        !          1587:        if (ic->ic_opmode == IEEE80211_M_STA && (ni->ni_txseq & 7))
        !          1588:                flags |= RT2661_TX_IFS_SIFS;
        !          1589:
        !          1590:        /* check if RTS/CTS or CTS-to-self protection must be used */
        !          1591:        if (!IEEE80211_IS_MULTICAST(wh->i_addr1)) {
        !          1592:                /* multicast frames are not sent at OFDM rates in 802.11b/g */
        !          1593:                if (pktlen > ic->ic_rtsthreshold) {
        !          1594:                        needrts = 1;    /* RTS/CTS based on frame length */
        !          1595:                } else if ((ic->ic_flags & IEEE80211_F_USEPROT) &&
        !          1596:                    RAL_RATE_IS_OFDM(rate)) {
        !          1597:                        if (ic->ic_protmode == IEEE80211_PROT_CTSONLY)
        !          1598:                                needcts = 1;    /* CTS-to-self */
        !          1599:                        else if (ic->ic_protmode == IEEE80211_PROT_RTSCTS)
        !          1600:                                needrts = 1;    /* RTS/CTS */
        !          1601:                }
        !          1602:        }
        !          1603:        if (needrts || needcts) {
        !          1604:                struct mbuf *mprot;
        !          1605:                int protrate, ackrate;
        !          1606:                uint16_t dur;
        !          1607:
        !          1608:                protrate = IEEE80211_IS_CHAN_5GHZ(ni->ni_chan) ? 12 : 2;
        !          1609:                ackrate  = rt2661_ack_rate(ic, rate);
        !          1610:
        !          1611:                dur = rt2661_txtime(pktlen, rate, ic->ic_flags) +
        !          1612:                      rt2661_txtime(RAL_ACK_SIZE, ackrate, ic->ic_flags) +
        !          1613:                      2 * sc->sifs;
        !          1614:                if (needrts) {
        !          1615:                        dur += rt2661_txtime(RAL_CTS_SIZE, rt2661_ack_rate(ic,
        !          1616:                            protrate), ic->ic_flags) + sc->sifs;
        !          1617:                        mprot = ieee80211_get_rts(ic, wh, dur);
        !          1618:                } else {
        !          1619:                        mprot = ieee80211_get_cts_to_self(ic, dur);
        !          1620:                }
        !          1621:                if (mprot == NULL) {
        !          1622:                        printf("%s: could not allocate protection frame\n",
        !          1623:                            sc->sc_dev.dv_xname);
        !          1624:                        m_freem(m0);
        !          1625:                        return ENOBUFS;
        !          1626:                }
        !          1627:
        !          1628:                desc = &txq->desc[txq->cur];
        !          1629:                data = &txq->data[txq->cur];
        !          1630:
        !          1631:                error = bus_dmamap_load_mbuf(sc->sc_dmat, data->map, mprot,
        !          1632:                    BUS_DMA_NOWAIT);
        !          1633:                if (error != 0) {
        !          1634:                        printf("%s: could not map mbuf (error %d)\n",
        !          1635:                            sc->sc_dev.dv_xname, error);
        !          1636:                        m_freem(mprot);
        !          1637:                        m_freem(m0);
        !          1638:                        return error;
        !          1639:                }
        !          1640:
        !          1641:                data->m = mprot;
        !          1642:                /* avoid multiple free() of the same node for each fragment */
        !          1643:                data->ni = ieee80211_ref_node(ni);
        !          1644:
        !          1645:                /* XXX may want to pass the protection frame to BPF */
        !          1646:
        !          1647:                rt2661_setup_tx_desc(sc, desc,
        !          1648:                    (needrts ? RT2661_TX_NEED_ACK : 0) | RT2661_TX_MORE_FRAG,
        !          1649:                    0, mprot->m_pkthdr.len, protrate, data->map->dm_segs,
        !          1650:                    data->map->dm_nsegs, ac);
        !          1651:
        !          1652:                bus_dmamap_sync(sc->sc_dmat, data->map, 0,
        !          1653:                    data->map->dm_mapsize, BUS_DMASYNC_PREWRITE);
        !          1654:                bus_dmamap_sync(sc->sc_dmat, txq->map,
        !          1655:                    txq->cur * RT2661_TX_DESC_SIZE, RT2661_TX_DESC_SIZE,
        !          1656:                    BUS_DMASYNC_PREWRITE);
        !          1657:
        !          1658:                txq->queued++;
        !          1659:                txq->cur = (txq->cur + 1) % RT2661_TX_RING_COUNT;
        !          1660:
        !          1661:                flags |= RT2661_TX_LONG_RETRY | RT2661_TX_IFS_SIFS;
        !          1662:        }
        !          1663:
        !          1664:        data = &txq->data[txq->cur];
        !          1665:        desc = &txq->desc[txq->cur];
        !          1666:
        !          1667:        error = bus_dmamap_load_mbuf(sc->sc_dmat, data->map, m0,
        !          1668:            BUS_DMA_NOWAIT);
        !          1669:        if (error != 0 && error != EFBIG) {
        !          1670:                printf("%s: could not map mbuf (error %d)\n",
        !          1671:                    sc->sc_dev.dv_xname, error);
        !          1672:                m_freem(m0);
        !          1673:                return error;
        !          1674:        }
        !          1675:        if (error != 0) {
        !          1676:                /* too many fragments, linearize */
        !          1677:
        !          1678:                MGETHDR(mnew, M_DONTWAIT, MT_DATA);
        !          1679:                if (mnew == NULL) {
        !          1680:                        m_freem(m0);
        !          1681:                        return ENOMEM;
        !          1682:                }
        !          1683:                M_DUP_PKTHDR(mnew, m0);
        !          1684:                if (m0->m_pkthdr.len > MHLEN) {
        !          1685:                        MCLGET(mnew, M_DONTWAIT);
        !          1686:                        if (!(mnew->m_flags & M_EXT)) {
        !          1687:                                m_freem(m0);
        !          1688:                                m_freem(mnew);
        !          1689:                                return ENOMEM;
        !          1690:                        }
        !          1691:                }
        !          1692:
        !          1693:                m_copydata(m0, 0, m0->m_pkthdr.len, mtod(mnew, caddr_t));
        !          1694:                m_freem(m0);
        !          1695:                mnew->m_len = mnew->m_pkthdr.len;
        !          1696:                m0 = mnew;
        !          1697:
        !          1698:                error = bus_dmamap_load_mbuf(sc->sc_dmat, data->map, m0,
        !          1699:                    BUS_DMA_NOWAIT);
        !          1700:                if (error != 0) {
        !          1701:                        printf("%s: could not map mbuf (error %d)\n",
        !          1702:                            sc->sc_dev.dv_xname, error);
        !          1703:                        m_freem(m0);
        !          1704:                        return error;
        !          1705:                }
        !          1706:
        !          1707:                /* packet header have moved, reset our local pointer */
        !          1708:                wh = mtod(m0, struct ieee80211_frame *);
        !          1709:        }
        !          1710:
        !          1711: #if NBPFILTER > 0
        !          1712:        if (sc->sc_drvbpf != NULL) {
        !          1713:                struct mbuf mb;
        !          1714:                struct rt2661_tx_radiotap_header *tap = &sc->sc_txtap;
        !          1715:
        !          1716:                tap->wt_flags = 0;
        !          1717:                tap->wt_rate = rate;
        !          1718:                tap->wt_chan_freq = htole16(sc->sc_curchan->ic_freq);
        !          1719:                tap->wt_chan_flags = htole16(sc->sc_curchan->ic_flags);
        !          1720:
        !          1721:                mb.m_data = (caddr_t)tap;
        !          1722:                mb.m_len = sc->sc_txtap_len;
        !          1723:                mb.m_next = m0;
        !          1724:                mb.m_nextpkt = NULL;
        !          1725:                mb.m_type = 0;
        !          1726:                mb.m_flags = 0;
        !          1727:                bpf_mtap(sc->sc_drvbpf, &mb, BPF_DIRECTION_OUT);
        !          1728:        }
        !          1729: #endif
        !          1730:
        !          1731:        data->m = m0;
        !          1732:        data->ni = ni;
        !          1733:
        !          1734:        if (!IEEE80211_IS_MULTICAST(wh->i_addr1)) {
        !          1735:                flags |= RT2661_TX_NEED_ACK;
        !          1736:
        !          1737:                dur = rt2661_txtime(RAL_ACK_SIZE, rt2661_ack_rate(ic, rate),
        !          1738:                    ic->ic_flags) + sc->sifs;
        !          1739:                *(uint16_t *)wh->i_dur = htole16(dur);
        !          1740:        }
        !          1741:
        !          1742:        rt2661_setup_tx_desc(sc, desc, flags, 0, m0->m_pkthdr.len, rate,
        !          1743:            data->map->dm_segs, data->map->dm_nsegs, ac);
        !          1744:
        !          1745:        bus_dmamap_sync(sc->sc_dmat, data->map, 0, data->map->dm_mapsize,
        !          1746:            BUS_DMASYNC_PREWRITE);
        !          1747:        bus_dmamap_sync(sc->sc_dmat, txq->map, txq->cur * RT2661_TX_DESC_SIZE,
        !          1748:            RT2661_TX_DESC_SIZE, BUS_DMASYNC_PREWRITE);
        !          1749:
        !          1750:        DPRINTFN(10, ("sending data frame len=%u idx=%u rate=%u\n",
        !          1751:            m0->m_pkthdr.len, txq->cur, rate));
        !          1752:
        !          1753:        /* kick Tx */
        !          1754:        txq->queued++;
        !          1755:        txq->cur = (txq->cur + 1) % RT2661_TX_RING_COUNT;
        !          1756:        RAL_WRITE(sc, RT2661_TX_CNTL_CSR, 1);
        !          1757:
        !          1758:        return 0;
        !          1759: }
        !          1760:
        !          1761: void
        !          1762: rt2661_start(struct ifnet *ifp)
        !          1763: {
        !          1764:        struct rt2661_softc *sc = ifp->if_softc;
        !          1765:        struct ieee80211com *ic = &sc->sc_ic;
        !          1766:        struct mbuf *m0;
        !          1767:        struct ieee80211_node *ni;
        !          1768:
        !          1769:        /*
        !          1770:         * net80211 may still try to send management frames even if the
        !          1771:         * IFF_RUNNING flag is not set...
        !          1772:         */
        !          1773:        if ((ifp->if_flags & (IFF_RUNNING | IFF_OACTIVE)) != IFF_RUNNING)
        !          1774:                return;
        !          1775:
        !          1776:        for (;;) {
        !          1777:                IF_POLL(&ic->ic_mgtq, m0);
        !          1778:                if (m0 != NULL) {
        !          1779:                        if (sc->mgtq.queued >= RT2661_MGT_RING_COUNT) {
        !          1780:                                ifp->if_flags |= IFF_OACTIVE;
        !          1781:                                break;
        !          1782:                        }
        !          1783:                        IF_DEQUEUE(&ic->ic_mgtq, m0);
        !          1784:
        !          1785:                        ni = (struct ieee80211_node *)m0->m_pkthdr.rcvif;
        !          1786:                        m0->m_pkthdr.rcvif = NULL;
        !          1787: #if NBPFILTER > 0
        !          1788:                        if (ic->ic_rawbpf != NULL)
        !          1789:                                bpf_mtap(ic->ic_rawbpf, m0, BPF_DIRECTION_OUT);
        !          1790: #endif
        !          1791:                        if (rt2661_tx_mgt(sc, m0, ni) != 0)
        !          1792:                                break;
        !          1793:
        !          1794:                } else {
        !          1795:                        if (ic->ic_state != IEEE80211_S_RUN)
        !          1796:                                break;
        !          1797:                        IFQ_POLL(&ifp->if_snd, m0);
        !          1798:                        if (m0 == NULL)
        !          1799:                                break;
        !          1800:                        if (sc->txq[0].queued >= RT2661_TX_RING_COUNT - 1) {
        !          1801:                                /* there is no place left in this ring */
        !          1802:                                ifp->if_flags |= IFF_OACTIVE;
        !          1803:                                break;
        !          1804:                        }
        !          1805:                        IFQ_DEQUEUE(&ifp->if_snd, m0);
        !          1806: #if NBPFILTER > 0
        !          1807:                        if (ifp->if_bpf != NULL)
        !          1808:                                bpf_mtap(ifp->if_bpf, m0, BPF_DIRECTION_OUT);
        !          1809: #endif
        !          1810:                        m0 = ieee80211_encap(ifp, m0, &ni);
        !          1811:                        if (m0 == NULL)
        !          1812:                                continue;
        !          1813: #if NBPFILTER > 0
        !          1814:                        if (ic->ic_rawbpf != NULL)
        !          1815:                                bpf_mtap(ic->ic_rawbpf, m0,
        !          1816:                                    BPF_DIRECTION_OUT);
        !          1817: #endif
        !          1818:                        if (rt2661_tx_data(sc, m0, ni, 0) != 0) {
        !          1819:                                if (ni != NULL)
        !          1820:                                        ieee80211_release_node(ic, ni);
        !          1821:                                ifp->if_oerrors++;
        !          1822:                                break;
        !          1823:                        }
        !          1824:                }
        !          1825:
        !          1826:                sc->sc_tx_timer = 5;
        !          1827:                ifp->if_timer = 1;
        !          1828:        }
        !          1829: }
        !          1830:
        !          1831: void
        !          1832: rt2661_watchdog(struct ifnet *ifp)
        !          1833: {
        !          1834:        struct rt2661_softc *sc = ifp->if_softc;
        !          1835:
        !          1836:        ifp->if_timer = 0;
        !          1837:
        !          1838:        if (sc->sc_tx_timer > 0) {
        !          1839:                if (--sc->sc_tx_timer == 0) {
        !          1840:                        printf("%s: device timeout\n", sc->sc_dev.dv_xname);
        !          1841:                        rt2661_init(ifp);
        !          1842:                        ifp->if_oerrors++;
        !          1843:                        return;
        !          1844:                }
        !          1845:                ifp->if_timer = 1;
        !          1846:        }
        !          1847:
        !          1848:        ieee80211_watchdog(ifp);
        !          1849: }
        !          1850:
        !          1851: int
        !          1852: rt2661_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
        !          1853: {
        !          1854:        struct rt2661_softc *sc = ifp->if_softc;
        !          1855:        struct ieee80211com *ic = &sc->sc_ic;
        !          1856:        struct ifaddr *ifa;
        !          1857:        struct ifreq *ifr;
        !          1858:        int s, error = 0;
        !          1859:
        !          1860:        s = splnet();
        !          1861:
        !          1862:        switch (cmd) {
        !          1863:        case SIOCSIFADDR:
        !          1864:                ifa = (struct ifaddr *)data;
        !          1865:                ifp->if_flags |= IFF_UP;
        !          1866: #ifdef INET
        !          1867:                if (ifa->ifa_addr->sa_family == AF_INET)
        !          1868:                        arp_ifinit(&ic->ic_ac, ifa);
        !          1869: #endif
        !          1870:                /* FALLTHROUGH */
        !          1871:        case SIOCSIFFLAGS:
        !          1872:                if (ifp->if_flags & IFF_UP) {
        !          1873:                        if (ifp->if_flags & IFF_RUNNING)
        !          1874:                                rt2661_update_promisc(sc);
        !          1875:                        else
        !          1876:                                rt2661_init(ifp);
        !          1877:                } else {
        !          1878:                        if (ifp->if_flags & IFF_RUNNING)
        !          1879:                                rt2661_stop(ifp, 1);
        !          1880:                }
        !          1881:                break;
        !          1882:
        !          1883:        case SIOCADDMULTI:
        !          1884:        case SIOCDELMULTI:
        !          1885:                ifr = (struct ifreq *)data;
        !          1886:                error = (cmd == SIOCADDMULTI) ?
        !          1887:                    ether_addmulti(ifr, &ic->ic_ac) :
        !          1888:                    ether_delmulti(ifr, &ic->ic_ac);
        !          1889:
        !          1890:                if (error == ENETRESET)
        !          1891:                        error = 0;
        !          1892:                break;
        !          1893:
        !          1894:        case SIOCS80211CHANNEL:
        !          1895:                /*
        !          1896:                 * This allows for fast channel switching in monitor mode
        !          1897:                 * (used by kismet). In IBSS mode, we must explicitly reset
        !          1898:                 * the interface to generate a new beacon frame.
        !          1899:                 */
        !          1900:                error = ieee80211_ioctl(ifp, cmd, data);
        !          1901:                if (error == ENETRESET &&
        !          1902:                    ic->ic_opmode == IEEE80211_M_MONITOR) {
        !          1903:                        if ((ifp->if_flags & (IFF_UP | IFF_RUNNING)) ==
        !          1904:                            (IFF_UP | IFF_RUNNING))
        !          1905:                                rt2661_set_chan(sc, ic->ic_ibss_chan);
        !          1906:                        error = 0;
        !          1907:                }
        !          1908:                break;
        !          1909:
        !          1910:        default:
        !          1911:                error = ieee80211_ioctl(ifp, cmd, data);
        !          1912:        }
        !          1913:
        !          1914:        if (error == ENETRESET) {
        !          1915:                if ((ifp->if_flags & (IFF_UP | IFF_RUNNING)) ==
        !          1916:                    (IFF_UP | IFF_RUNNING))
        !          1917:                        rt2661_init(ifp);
        !          1918:                error = 0;
        !          1919:        }
        !          1920:
        !          1921:        splx(s);
        !          1922:
        !          1923:        return error;
        !          1924: }
        !          1925:
        !          1926: void
        !          1927: rt2661_bbp_write(struct rt2661_softc *sc, uint8_t reg, uint8_t val)
        !          1928: {
        !          1929:        uint32_t tmp;
        !          1930:        int ntries;
        !          1931:
        !          1932:        for (ntries = 0; ntries < 100; ntries++) {
        !          1933:                if (!(RAL_READ(sc, RT2661_PHY_CSR3) & RT2661_BBP_BUSY))
        !          1934:                        break;
        !          1935:                DELAY(1);
        !          1936:        }
        !          1937:        if (ntries == 100) {
        !          1938:                printf("%s: could not write to BBP\n", sc->sc_dev.dv_xname);
        !          1939:                return;
        !          1940:        }
        !          1941:
        !          1942:        tmp = RT2661_BBP_BUSY | (reg & 0x7f) << 8 | val;
        !          1943:        RAL_WRITE(sc, RT2661_PHY_CSR3, tmp);
        !          1944:
        !          1945:        DPRINTFN(15, ("BBP R%u <- 0x%02x\n", reg, val));
        !          1946: }
        !          1947:
        !          1948: uint8_t
        !          1949: rt2661_bbp_read(struct rt2661_softc *sc, uint8_t reg)
        !          1950: {
        !          1951:        uint32_t val;
        !          1952:        int ntries;
        !          1953:
        !          1954:        for (ntries = 0; ntries < 100; ntries++) {
        !          1955:                if (!(RAL_READ(sc, RT2661_PHY_CSR3) & RT2661_BBP_BUSY))
        !          1956:                        break;
        !          1957:                DELAY(1);
        !          1958:        }
        !          1959:        if (ntries == 100) {
        !          1960:                printf("%s: could not read from BBP\n", sc->sc_dev.dv_xname);
        !          1961:                return 0;
        !          1962:        }
        !          1963:
        !          1964:        val = RT2661_BBP_BUSY | RT2661_BBP_READ | reg << 8;
        !          1965:        RAL_WRITE(sc, RT2661_PHY_CSR3, val);
        !          1966:
        !          1967:        for (ntries = 0; ntries < 100; ntries++) {
        !          1968:                val = RAL_READ(sc, RT2661_PHY_CSR3);
        !          1969:                if (!(val & RT2661_BBP_BUSY))
        !          1970:                        return val & 0xff;
        !          1971:                DELAY(1);
        !          1972:        }
        !          1973:
        !          1974:        printf("%s: could not read from BBP\n", sc->sc_dev.dv_xname);
        !          1975:        return 0;
        !          1976: }
        !          1977:
        !          1978: void
        !          1979: rt2661_rf_write(struct rt2661_softc *sc, uint8_t reg, uint32_t val)
        !          1980: {
        !          1981:        uint32_t tmp;
        !          1982:        int ntries;
        !          1983:
        !          1984:        for (ntries = 0; ntries < 100; ntries++) {
        !          1985:                if (!(RAL_READ(sc, RT2661_PHY_CSR4) & RT2661_RF_BUSY))
        !          1986:                        break;
        !          1987:                DELAY(1);
        !          1988:        }
        !          1989:        if (ntries == 100) {
        !          1990:                printf("%s: could not write to RF\n", sc->sc_dev.dv_xname);
        !          1991:                return;
        !          1992:        }
        !          1993:
        !          1994:        tmp = RT2661_RF_BUSY | RT2661_RF_21BIT | (val & 0x1fffff) << 2 |
        !          1995:            (reg & 3);
        !          1996:        RAL_WRITE(sc, RT2661_PHY_CSR4, tmp);
        !          1997:
        !          1998:        /* remember last written value in sc */
        !          1999:        sc->rf_regs[reg] = val;
        !          2000:
        !          2001:        DPRINTFN(15, ("RF R[%u] <- 0x%05x\n", reg & 3, val & 0x1fffff));
        !          2002: }
        !          2003:
        !          2004: int
        !          2005: rt2661_tx_cmd(struct rt2661_softc *sc, uint8_t cmd, uint16_t arg)
        !          2006: {
        !          2007:        if (RAL_READ(sc, RT2661_H2M_MAILBOX_CSR) & RT2661_H2M_BUSY)
        !          2008:                return EIO;     /* there is already a command pending */
        !          2009:
        !          2010:        RAL_WRITE(sc, RT2661_H2M_MAILBOX_CSR,
        !          2011:            RT2661_H2M_BUSY | RT2661_TOKEN_NO_INTR << 16 | arg);
        !          2012:
        !          2013:        RAL_WRITE(sc, RT2661_HOST_CMD_CSR, RT2661_KICK_CMD | cmd);
        !          2014:
        !          2015:        return 0;
        !          2016: }
        !          2017:
        !          2018: void
        !          2019: rt2661_select_antenna(struct rt2661_softc *sc)
        !          2020: {
        !          2021:        uint8_t bbp4, bbp77;
        !          2022:        uint32_t tmp;
        !          2023:
        !          2024:        bbp4  = rt2661_bbp_read(sc,  4);
        !          2025:        bbp77 = rt2661_bbp_read(sc, 77);
        !          2026:
        !          2027:        /* TBD */
        !          2028:
        !          2029:        /* make sure Rx is disabled before switching antenna */
        !          2030:        tmp = RAL_READ(sc, RT2661_TXRX_CSR0);
        !          2031:        RAL_WRITE(sc, RT2661_TXRX_CSR0, tmp | RT2661_DISABLE_RX);
        !          2032:
        !          2033:        rt2661_bbp_write(sc,  4, bbp4);
        !          2034:        rt2661_bbp_write(sc, 77, bbp77);
        !          2035:
        !          2036:        /* restore Rx filter */
        !          2037:        RAL_WRITE(sc, RT2661_TXRX_CSR0, tmp);
        !          2038: }
        !          2039:
        !          2040: /*
        !          2041:  * Enable multi-rate retries for frames sent at OFDM rates.
        !          2042:  * In 802.11b/g mode, allow fallback to CCK rates.
        !          2043:  */
        !          2044: void
        !          2045: rt2661_enable_mrr(struct rt2661_softc *sc)
        !          2046: {
        !          2047:        struct ieee80211com *ic = &sc->sc_ic;
        !          2048:        uint32_t tmp;
        !          2049:
        !          2050:        tmp = RAL_READ(sc, RT2661_TXRX_CSR4);
        !          2051:
        !          2052:        tmp &= ~RT2661_MRR_CCK_FALLBACK;
        !          2053:        if (!IEEE80211_IS_CHAN_5GHZ(ic->ic_bss->ni_chan))
        !          2054:                tmp |= RT2661_MRR_CCK_FALLBACK;
        !          2055:        tmp |= RT2661_MRR_ENABLED;
        !          2056:
        !          2057:        RAL_WRITE(sc, RT2661_TXRX_CSR4, tmp);
        !          2058: }
        !          2059:
        !          2060: void
        !          2061: rt2661_set_txpreamble(struct rt2661_softc *sc)
        !          2062: {
        !          2063:        uint32_t tmp;
        !          2064:
        !          2065:        tmp = RAL_READ(sc, RT2661_TXRX_CSR4);
        !          2066:
        !          2067:        tmp &= ~RT2661_SHORT_PREAMBLE;
        !          2068:        if (sc->sc_ic.ic_flags & IEEE80211_F_SHPREAMBLE)
        !          2069:                tmp |= RT2661_SHORT_PREAMBLE;
        !          2070:
        !          2071:        RAL_WRITE(sc, RT2661_TXRX_CSR4, tmp);
        !          2072: }
        !          2073:
        !          2074: void
        !          2075: rt2661_set_basicrates(struct rt2661_softc *sc)
        !          2076: {
        !          2077:        struct ieee80211com *ic = &sc->sc_ic;
        !          2078:
        !          2079:        /* update basic rate set */
        !          2080:        if (ic->ic_curmode == IEEE80211_MODE_11B) {
        !          2081:                /* 11b basic rates: 1, 2Mbps */
        !          2082:                RAL_WRITE(sc, RT2661_TXRX_CSR5, 0x3);
        !          2083:        } else if (ic->ic_curmode == IEEE80211_MODE_11A) {
        !          2084:                /* 11a basic rates: 6, 12, 24Mbps */
        !          2085:                RAL_WRITE(sc, RT2661_TXRX_CSR5, 0x150);
        !          2086:        } else {
        !          2087:                /* 11b/g basic rates: 1, 2, 5.5, 11Mbps */
        !          2088:                RAL_WRITE(sc, RT2661_TXRX_CSR5, 0xf);
        !          2089:        }
        !          2090: }
        !          2091:
        !          2092: /*
        !          2093:  * Reprogram MAC/BBP to switch to a new band.  Values taken from the reference
        !          2094:  * driver.
        !          2095:  */
        !          2096: void
        !          2097: rt2661_select_band(struct rt2661_softc *sc, struct ieee80211_channel *c)
        !          2098: {
        !          2099:        uint8_t bbp17, bbp35, bbp96, bbp97, bbp98, bbp104;
        !          2100:        uint32_t tmp;
        !          2101:
        !          2102:        /* update all BBP registers that depend on the band */
        !          2103:        bbp17 = 0x20; bbp96 = 0x48; bbp104 = 0x2c;
        !          2104:        bbp35 = 0x50; bbp97 = 0x48; bbp98  = 0x48;
        !          2105:        if (IEEE80211_IS_CHAN_5GHZ(c)) {
        !          2106:                bbp17 += 0x08; bbp96 += 0x10; bbp104 += 0x0c;
        !          2107:                bbp35 += 0x10; bbp97 += 0x10; bbp98  += 0x10;
        !          2108:        }
        !          2109:        if ((IEEE80211_IS_CHAN_2GHZ(c) && sc->ext_2ghz_lna) ||
        !          2110:            (IEEE80211_IS_CHAN_5GHZ(c) && sc->ext_5ghz_lna)) {
        !          2111:                bbp17 += 0x10; bbp96 += 0x10; bbp104 += 0x10;
        !          2112:        }
        !          2113:
        !          2114:        sc->bbp17 = bbp17;
        !          2115:        rt2661_bbp_write(sc,  17, bbp17);
        !          2116:        rt2661_bbp_write(sc,  96, bbp96);
        !          2117:        rt2661_bbp_write(sc, 104, bbp104);
        !          2118:
        !          2119:        if ((IEEE80211_IS_CHAN_2GHZ(c) && sc->ext_2ghz_lna) ||
        !          2120:            (IEEE80211_IS_CHAN_5GHZ(c) && sc->ext_5ghz_lna)) {
        !          2121:                rt2661_bbp_write(sc, 75, 0x80);
        !          2122:                rt2661_bbp_write(sc, 86, 0x80);
        !          2123:                rt2661_bbp_write(sc, 88, 0x80);
        !          2124:        }
        !          2125:
        !          2126:        rt2661_bbp_write(sc, 35, bbp35);
        !          2127:        rt2661_bbp_write(sc, 97, bbp97);
        !          2128:        rt2661_bbp_write(sc, 98, bbp98);
        !          2129:
        !          2130:        tmp = RAL_READ(sc, RT2661_PHY_CSR0);
        !          2131:        tmp &= ~(RT2661_PA_PE_2GHZ | RT2661_PA_PE_5GHZ);
        !          2132:        if (IEEE80211_IS_CHAN_2GHZ(c))
        !          2133:                tmp |= RT2661_PA_PE_2GHZ;
        !          2134:        else
        !          2135:                tmp |= RT2661_PA_PE_5GHZ;
        !          2136:        RAL_WRITE(sc, RT2661_PHY_CSR0, tmp);
        !          2137:
        !          2138:        /* 802.11a uses a 16 microseconds short interframe space */
        !          2139:        sc->sifs = IEEE80211_IS_CHAN_5GHZ(c) ? 16 : 10;
        !          2140: }
        !          2141:
        !          2142: void
        !          2143: rt2661_set_chan(struct rt2661_softc *sc, struct ieee80211_channel *c)
        !          2144: {
        !          2145:        struct ieee80211com *ic = &sc->sc_ic;
        !          2146:        const struct rfprog *rfprog;
        !          2147:        uint8_t bbp3, bbp94 = RT2661_BBPR94_DEFAULT;
        !          2148:        int8_t power;
        !          2149:        u_int i, chan;
        !          2150:
        !          2151:        chan = ieee80211_chan2ieee(ic, c);
        !          2152:        if (chan == 0 || chan == IEEE80211_CHAN_ANY)
        !          2153:                return;
        !          2154:
        !          2155:        /* select the appropriate RF settings based on what EEPROM says */
        !          2156:        rfprog = (sc->rfprog == 0) ? rt2661_rf5225_1 : rt2661_rf5225_2;
        !          2157:
        !          2158:        /* find the settings for this channel (we know it exists) */
        !          2159:        for (i = 0; rfprog[i].chan != chan; i++);
        !          2160:
        !          2161:        power = sc->txpow[i];
        !          2162:        if (power < 0) {
        !          2163:                bbp94 += power;
        !          2164:                power = 0;
        !          2165:        } else if (power > 31) {
        !          2166:                bbp94 += power - 31;
        !          2167:                power = 31;
        !          2168:        }
        !          2169:
        !          2170:        /*
        !          2171:         * If we are switching from the 2GHz band to the 5GHz band or
        !          2172:         * vice-versa, BBP registers need to be reprogrammed.
        !          2173:         */
        !          2174:        if (c->ic_flags != sc->sc_curchan->ic_flags) {
        !          2175:                rt2661_select_band(sc, c);
        !          2176:                rt2661_select_antenna(sc);
        !          2177:        }
        !          2178:        sc->sc_curchan = c;
        !          2179:
        !          2180:        rt2661_rf_write(sc, RAL_RF1, rfprog[i].r1);
        !          2181:        rt2661_rf_write(sc, RAL_RF2, rfprog[i].r2);
        !          2182:        rt2661_rf_write(sc, RAL_RF3, rfprog[i].r3 | power << 7);
        !          2183:        rt2661_rf_write(sc, RAL_RF4, rfprog[i].r4 | sc->rffreq << 10);
        !          2184:
        !          2185:        DELAY(200);
        !          2186:
        !          2187:        rt2661_rf_write(sc, RAL_RF1, rfprog[i].r1);
        !          2188:        rt2661_rf_write(sc, RAL_RF2, rfprog[i].r2);
        !          2189:        rt2661_rf_write(sc, RAL_RF3, rfprog[i].r3 | power << 7 | 1);
        !          2190:        rt2661_rf_write(sc, RAL_RF4, rfprog[i].r4 | sc->rffreq << 10);
        !          2191:
        !          2192:        DELAY(200);
        !          2193:
        !          2194:        rt2661_rf_write(sc, RAL_RF1, rfprog[i].r1);
        !          2195:        rt2661_rf_write(sc, RAL_RF2, rfprog[i].r2);
        !          2196:        rt2661_rf_write(sc, RAL_RF3, rfprog[i].r3 | power << 7);
        !          2197:        rt2661_rf_write(sc, RAL_RF4, rfprog[i].r4 | sc->rffreq << 10);
        !          2198:
        !          2199:        /* enable smart mode for MIMO-capable RFs */
        !          2200:        bbp3 = rt2661_bbp_read(sc, 3);
        !          2201:
        !          2202:        bbp3 &= ~RT2661_SMART_MODE;
        !          2203:        if (sc->rf_rev == RT2661_RF_5325 || sc->rf_rev == RT2661_RF_2529)
        !          2204:                bbp3 |= RT2661_SMART_MODE;
        !          2205:
        !          2206:        rt2661_bbp_write(sc, 3, bbp3);
        !          2207:
        !          2208:        if (bbp94 != RT2661_BBPR94_DEFAULT)
        !          2209:                rt2661_bbp_write(sc, 94, bbp94);
        !          2210:
        !          2211:        /* 5GHz radio needs a 1ms delay here */
        !          2212:        if (IEEE80211_IS_CHAN_5GHZ(c))
        !          2213:                DELAY(1000);
        !          2214: }
        !          2215:
        !          2216: void
        !          2217: rt2661_set_bssid(struct rt2661_softc *sc, const uint8_t *bssid)
        !          2218: {
        !          2219:        uint32_t tmp;
        !          2220:
        !          2221:        tmp = bssid[0] | bssid[1] << 8 | bssid[2] << 16 | bssid[3] << 24;
        !          2222:        RAL_WRITE(sc, RT2661_MAC_CSR4, tmp);
        !          2223:
        !          2224:        tmp = bssid[4] | bssid[5] << 8 | RT2661_ONE_BSSID << 16;
        !          2225:        RAL_WRITE(sc, RT2661_MAC_CSR5, tmp);
        !          2226: }
        !          2227:
        !          2228: void
        !          2229: rt2661_set_macaddr(struct rt2661_softc *sc, const uint8_t *addr)
        !          2230: {
        !          2231:        uint32_t tmp;
        !          2232:
        !          2233:        tmp = addr[0] | addr[1] << 8 | addr[2] << 16 | addr[3] << 24;
        !          2234:        RAL_WRITE(sc, RT2661_MAC_CSR2, tmp);
        !          2235:
        !          2236:        tmp = addr[4] | addr[5] << 8 | 0xff << 16;
        !          2237:        RAL_WRITE(sc, RT2661_MAC_CSR3, tmp);
        !          2238: }
        !          2239:
        !          2240: void
        !          2241: rt2661_update_promisc(struct rt2661_softc *sc)
        !          2242: {
        !          2243:        struct ifnet *ifp = &sc->sc_ic.ic_if;
        !          2244:        uint32_t tmp;
        !          2245:
        !          2246:        tmp = RAL_READ(sc, RT2661_TXRX_CSR0);
        !          2247:
        !          2248:        tmp &= ~RT2661_DROP_NOT_TO_ME;
        !          2249:        if (!(ifp->if_flags & IFF_PROMISC))
        !          2250:                tmp |= RT2661_DROP_NOT_TO_ME;
        !          2251:
        !          2252:        RAL_WRITE(sc, RT2661_TXRX_CSR0, tmp);
        !          2253:
        !          2254:        DPRINTF(("%s promiscuous mode\n", (ifp->if_flags & IFF_PROMISC) ?
        !          2255:            "entering" : "leaving"));
        !          2256: }
        !          2257:
        !          2258: void
        !          2259: rt2661_updateslot(struct ieee80211com *ic)
        !          2260: {
        !          2261:        struct rt2661_softc *sc = ic->ic_if.if_softc;
        !          2262:
        !          2263:        if (ic->ic_opmode == IEEE80211_M_HOSTAP) {
        !          2264:                /*
        !          2265:                 * In HostAP mode, we defer setting of new slot time until
        !          2266:                 * updated ERP Information Element has propagated to all
        !          2267:                 * associated STAs.
        !          2268:                 */
        !          2269:                sc->sc_flags |= RT2661_UPDATE_SLOT;
        !          2270:        } else
        !          2271:                rt2661_set_slottime(sc);
        !          2272: }
        !          2273:
        !          2274: void
        !          2275: rt2661_set_slottime(struct rt2661_softc *sc)
        !          2276: {
        !          2277:        struct ieee80211com *ic = &sc->sc_ic;
        !          2278:        uint8_t slottime;
        !          2279:        uint32_t tmp;
        !          2280:
        !          2281:        slottime = (ic->ic_flags & IEEE80211_F_SHSLOT) ? 9 : 20;
        !          2282:
        !          2283:        tmp = RAL_READ(sc, RT2661_MAC_CSR9);
        !          2284:        tmp = (tmp & ~0xff) | slottime;
        !          2285:        RAL_WRITE(sc, RT2661_MAC_CSR9, tmp);
        !          2286:
        !          2287:        DPRINTF(("setting slot time to %uus\n", slottime));
        !          2288: }
        !          2289:
        !          2290: const char *
        !          2291: rt2661_get_rf(int rev)
        !          2292: {
        !          2293:        switch (rev) {
        !          2294:        case RT2661_RF_5225:    return "RT5225";
        !          2295:        case RT2661_RF_5325:    return "RT5325 (MIMO XR)";
        !          2296:        case RT2661_RF_2527:    return "RT2527";
        !          2297:        case RT2661_RF_2529:    return "RT2529 (MIMO XR)";
        !          2298:        default:                return "unknown";
        !          2299:        }
        !          2300: }
        !          2301:
        !          2302: void
        !          2303: rt2661_read_eeprom(struct rt2661_softc *sc)
        !          2304: {
        !          2305:        struct ieee80211com *ic = &sc->sc_ic;
        !          2306:        uint16_t val;
        !          2307:        int i;
        !          2308:
        !          2309:        /* read MAC address */
        !          2310:        val = rt2661_eeprom_read(sc, RT2661_EEPROM_MAC01);
        !          2311:        ic->ic_myaddr[0] = val & 0xff;
        !          2312:        ic->ic_myaddr[1] = val >> 8;
        !          2313:
        !          2314:        val = rt2661_eeprom_read(sc, RT2661_EEPROM_MAC23);
        !          2315:        ic->ic_myaddr[2] = val & 0xff;
        !          2316:        ic->ic_myaddr[3] = val >> 8;
        !          2317:
        !          2318:        val = rt2661_eeprom_read(sc, RT2661_EEPROM_MAC45);
        !          2319:        ic->ic_myaddr[4] = val & 0xff;
        !          2320:        ic->ic_myaddr[5] = val >> 8;
        !          2321:
        !          2322:        val = rt2661_eeprom_read(sc, RT2661_EEPROM_ANTENNA);
        !          2323:        /* XXX: test if different from 0xffff? */
        !          2324:        sc->rf_rev   = (val >> 11) & 0x1f;
        !          2325:        sc->hw_radio = (val >> 10) & 0x1;
        !          2326:        sc->rx_ant   = (val >> 4)  & 0x3;
        !          2327:        sc->tx_ant   = (val >> 2)  & 0x3;
        !          2328:        sc->nb_ant   = val & 0x3;
        !          2329:
        !          2330:        DPRINTF(("RF revision=%d\n", sc->rf_rev));
        !          2331:
        !          2332:        val = rt2661_eeprom_read(sc, RT2661_EEPROM_CONFIG2);
        !          2333:        sc->ext_5ghz_lna = (val >> 6) & 0x1;
        !          2334:        sc->ext_2ghz_lna = (val >> 4) & 0x1;
        !          2335:
        !          2336:        DPRINTF(("External 2GHz LNA=%d\nExternal 5GHz LNA=%d\n",
        !          2337:            sc->ext_2ghz_lna, sc->ext_5ghz_lna));
        !          2338:
        !          2339:        val = rt2661_eeprom_read(sc, RT2661_EEPROM_RSSI_2GHZ_OFFSET);
        !          2340:        if ((val & 0xff) != 0xff)
        !          2341:                sc->rssi_2ghz_corr = (int8_t)(val & 0xff);      /* signed */
        !          2342:
        !          2343:        val = rt2661_eeprom_read(sc, RT2661_EEPROM_RSSI_5GHZ_OFFSET);
        !          2344:        if ((val & 0xff) != 0xff)
        !          2345:                sc->rssi_5ghz_corr = (int8_t)(val & 0xff);      /* signed */
        !          2346:
        !          2347:        /* adjust RSSI correction for external low-noise amplifier */
        !          2348:        if (sc->ext_2ghz_lna)
        !          2349:                sc->rssi_2ghz_corr -= 14;
        !          2350:        if (sc->ext_5ghz_lna)
        !          2351:                sc->rssi_5ghz_corr -= 14;
        !          2352:
        !          2353:        DPRINTF(("RSSI 2GHz corr=%d\nRSSI 5GHz corr=%d\n",
        !          2354:            sc->rssi_2ghz_corr, sc->rssi_5ghz_corr));
        !          2355:
        !          2356:        val = rt2661_eeprom_read(sc, RT2661_EEPROM_FREQ_OFFSET);
        !          2357:        if ((val >> 8) != 0xff)
        !          2358:                sc->rfprog = (val >> 8) & 0x3;
        !          2359:        if ((val & 0xff) != 0xff)
        !          2360:                sc->rffreq = val & 0xff;
        !          2361:
        !          2362:        DPRINTF(("RF prog=%d\nRF freq=%d\n", sc->rfprog, sc->rffreq));
        !          2363:
        !          2364:        /* read Tx power for all a/b/g channels */
        !          2365:        for (i = 0; i < 19; i++) {
        !          2366:                val = rt2661_eeprom_read(sc, RT2661_EEPROM_TXPOWER + i);
        !          2367:                sc->txpow[i * 2] = (int8_t)(val >> 8);          /* signed */
        !          2368:                DPRINTF(("Channel=%d Tx power=%d\n",
        !          2369:                    rt2661_rf5225_1[i * 2].chan, sc->txpow[i * 2]));
        !          2370:                sc->txpow[i * 2 + 1] = (int8_t)(val & 0xff);    /* signed */
        !          2371:                DPRINTF(("Channel=%d Tx power=%d\n",
        !          2372:                    rt2661_rf5225_1[i * 2 + 1].chan, sc->txpow[i * 2 + 1]));
        !          2373:        }
        !          2374:
        !          2375:        /* read vendor-specific BBP values */
        !          2376:        for (i = 0; i < 16; i++) {
        !          2377:                val = rt2661_eeprom_read(sc, RT2661_EEPROM_BBP_BASE + i);
        !          2378:                if (val == 0 || val == 0xffff)
        !          2379:                        continue;       /* skip invalid entries */
        !          2380:                sc->bbp_prom[i].reg = val >> 8;
        !          2381:                sc->bbp_prom[i].val = val & 0xff;
        !          2382:                DPRINTF(("BBP R%d=%02x\n", sc->bbp_prom[i].reg,
        !          2383:                    sc->bbp_prom[i].val));
        !          2384:        }
        !          2385: }
        !          2386:
        !          2387: int
        !          2388: rt2661_bbp_init(struct rt2661_softc *sc)
        !          2389: {
        !          2390: #define N(a)   (sizeof (a) / sizeof ((a)[0]))
        !          2391:        int i, ntries;
        !          2392:
        !          2393:        /* wait for BBP to be ready */
        !          2394:        for (ntries = 0; ntries < 100; ntries++) {
        !          2395:                const uint8_t val = rt2661_bbp_read(sc, 0);
        !          2396:                if (val != 0 && val != 0xff)
        !          2397:                        break;
        !          2398:                DELAY(100);
        !          2399:        }
        !          2400:        if (ntries == 100) {
        !          2401:                printf("%s: timeout waiting for BBP\n", sc->sc_dev.dv_xname);
        !          2402:                return EIO;
        !          2403:        }
        !          2404:
        !          2405:        /* initialize BBP registers to default values */
        !          2406:        for (i = 0; i < N(rt2661_def_bbp); i++) {
        !          2407:                rt2661_bbp_write(sc, rt2661_def_bbp[i].reg,
        !          2408:                    rt2661_def_bbp[i].val);
        !          2409:        }
        !          2410:
        !          2411:        /* write vendor-specific BBP values (from EEPROM) */
        !          2412:        for (i = 0; i < 16; i++) {
        !          2413:                if (sc->bbp_prom[i].reg == 0)
        !          2414:                        continue;
        !          2415:                rt2661_bbp_write(sc, sc->bbp_prom[i].reg, sc->bbp_prom[i].val);
        !          2416:        }
        !          2417:
        !          2418:        return 0;
        !          2419: #undef N
        !          2420: }
        !          2421:
        !          2422: int
        !          2423: rt2661_init(struct ifnet *ifp)
        !          2424: {
        !          2425: #define N(a)   (sizeof (a) / sizeof ((a)[0]))
        !          2426:        struct rt2661_softc *sc = ifp->if_softc;
        !          2427:        struct ieee80211com *ic = &sc->sc_ic;
        !          2428:        const char *name = NULL;        /* make lint happy */
        !          2429:        uint8_t *ucode;
        !          2430:        size_t size;
        !          2431:        uint32_t tmp, sta[3];
        !          2432:        int i, ntries;
        !          2433:
        !          2434:        /* for CardBus, power on the socket */
        !          2435:        if (!(sc->sc_flags & RT2661_ENABLED)) {
        !          2436:                if (sc->sc_enable != NULL && (*sc->sc_enable)(sc) != 0) {
        !          2437:                        printf("%s: could not enable device\n",
        !          2438:                            sc->sc_dev.dv_xname);
        !          2439:                        return EIO;
        !          2440:                }
        !          2441:                sc->sc_flags |= RT2661_ENABLED;
        !          2442:        }
        !          2443:
        !          2444:        rt2661_stop(ifp, 0);
        !          2445:
        !          2446:        if (!(sc->sc_flags & RT2661_FWLOADED)) {
        !          2447:                switch (sc->sc_id) {
        !          2448:                case PCI_PRODUCT_RALINK_RT2561:
        !          2449:                        name = "ral-rt2561";
        !          2450:                        break;
        !          2451:                case PCI_PRODUCT_RALINK_RT2561S:
        !          2452:                        name = "ral-rt2561s";
        !          2453:                        break;
        !          2454:                case PCI_PRODUCT_RALINK_RT2661:
        !          2455:                        name = "ral-rt2661";
        !          2456:                        break;
        !          2457:                }
        !          2458:
        !          2459:                if (loadfirmware(name, &ucode, &size) != 0) {
        !          2460:                        printf("%s: could not read microcode %s\n",
        !          2461:                            sc->sc_dev.dv_xname, name);
        !          2462:                        rt2661_stop(ifp, 1);
        !          2463:                        return EIO;
        !          2464:                }
        !          2465:
        !          2466:                if (rt2661_load_microcode(sc, ucode, size) != 0) {
        !          2467:                        printf("%s: could not load 8051 microcode\n",
        !          2468:                            sc->sc_dev.dv_xname);
        !          2469:                        free(ucode, M_DEVBUF);
        !          2470:                        rt2661_stop(ifp, 1);
        !          2471:                        return EIO;
        !          2472:                }
        !          2473:
        !          2474:                free(ucode, M_DEVBUF);
        !          2475:                sc->sc_flags |= RT2661_FWLOADED;
        !          2476:        }
        !          2477:
        !          2478:        /* initialize Tx rings */
        !          2479:        RAL_WRITE(sc, RT2661_AC1_BASE_CSR, sc->txq[1].physaddr);
        !          2480:        RAL_WRITE(sc, RT2661_AC0_BASE_CSR, sc->txq[0].physaddr);
        !          2481:        RAL_WRITE(sc, RT2661_AC2_BASE_CSR, sc->txq[2].physaddr);
        !          2482:        RAL_WRITE(sc, RT2661_AC3_BASE_CSR, sc->txq[3].physaddr);
        !          2483:
        !          2484:        /* initialize Mgt ring */
        !          2485:        RAL_WRITE(sc, RT2661_MGT_BASE_CSR, sc->mgtq.physaddr);
        !          2486:
        !          2487:        /* initialize Rx ring */
        !          2488:        RAL_WRITE(sc, RT2661_RX_BASE_CSR, sc->rxq.physaddr);
        !          2489:
        !          2490:        /* initialize Tx rings sizes */
        !          2491:        RAL_WRITE(sc, RT2661_TX_RING_CSR0,
        !          2492:            RT2661_TX_RING_COUNT << 24 |
        !          2493:            RT2661_TX_RING_COUNT << 16 |
        !          2494:            RT2661_TX_RING_COUNT <<  8 |
        !          2495:            RT2661_TX_RING_COUNT);
        !          2496:
        !          2497:        RAL_WRITE(sc, RT2661_TX_RING_CSR1,
        !          2498:            RT2661_TX_DESC_WSIZE << 16 |
        !          2499:            RT2661_TX_RING_COUNT <<  8 |        /* XXX: HCCA ring unused */
        !          2500:            RT2661_MGT_RING_COUNT);
        !          2501:
        !          2502:        /* initialize Rx rings */
        !          2503:        RAL_WRITE(sc, RT2661_RX_RING_CSR,
        !          2504:            RT2661_RX_DESC_BACK  << 16 |
        !          2505:            RT2661_RX_DESC_WSIZE <<  8 |
        !          2506:            RT2661_RX_RING_COUNT);
        !          2507:
        !          2508:        /* XXX: some magic here */
        !          2509:        RAL_WRITE(sc, RT2661_TX_DMA_DST_CSR, 0xaa);
        !          2510:
        !          2511:        /* load base addresses of all 5 Tx rings (4 data + 1 mgt) */
        !          2512:        RAL_WRITE(sc, RT2661_LOAD_TX_RING_CSR, 0x1f);
        !          2513:
        !          2514:        /* load base address of Rx ring */
        !          2515:        RAL_WRITE(sc, RT2661_RX_CNTL_CSR, 2);
        !          2516:
        !          2517:        /* initialize MAC registers to default values */
        !          2518:        for (i = 0; i < N(rt2661_def_mac); i++)
        !          2519:                RAL_WRITE(sc, rt2661_def_mac[i].reg, rt2661_def_mac[i].val);
        !          2520:
        !          2521:        IEEE80211_ADDR_COPY(ic->ic_myaddr, LLADDR(ifp->if_sadl));
        !          2522:        rt2661_set_macaddr(sc, ic->ic_myaddr);
        !          2523:
        !          2524:        /* set host ready */
        !          2525:        RAL_WRITE(sc, RT2661_MAC_CSR1, 3);
        !          2526:        RAL_WRITE(sc, RT2661_MAC_CSR1, 0);
        !          2527:
        !          2528:        /* wait for BBP/RF to wakeup */
        !          2529:        for (ntries = 0; ntries < 1000; ntries++) {
        !          2530:                if (RAL_READ(sc, RT2661_MAC_CSR12) & 8)
        !          2531:                        break;
        !          2532:                DELAY(1000);
        !          2533:        }
        !          2534:        if (ntries == 1000) {
        !          2535:                printf("timeout waiting for BBP/RF to wakeup\n");
        !          2536:                rt2661_stop(ifp, 1);
        !          2537:                return EIO;
        !          2538:        }
        !          2539:
        !          2540:        if (rt2661_bbp_init(sc) != 0) {
        !          2541:                rt2661_stop(ifp, 1);
        !          2542:                return EIO;
        !          2543:        }
        !          2544:
        !          2545:        /* select default channel */
        !          2546:        sc->sc_curchan = ic->ic_bss->ni_chan = ic->ic_ibss_chan;
        !          2547:        rt2661_select_band(sc, sc->sc_curchan);
        !          2548:        rt2661_select_antenna(sc);
        !          2549:        rt2661_set_chan(sc, sc->sc_curchan);
        !          2550:
        !          2551:        /* update Rx filter */
        !          2552:        tmp = RAL_READ(sc, RT2661_TXRX_CSR0) & 0xffff;
        !          2553:
        !          2554:        tmp |= RT2661_DROP_PHY_ERROR | RT2661_DROP_CRC_ERROR;
        !          2555:        if (ic->ic_opmode != IEEE80211_M_MONITOR) {
        !          2556:                tmp |= RT2661_DROP_CTL | RT2661_DROP_VER_ERROR |
        !          2557:                       RT2661_DROP_ACKCTS;
        !          2558:                if (ic->ic_opmode != IEEE80211_M_HOSTAP)
        !          2559:                        tmp |= RT2661_DROP_TODS;
        !          2560:                if (!(ifp->if_flags & IFF_PROMISC))
        !          2561:                        tmp |= RT2661_DROP_NOT_TO_ME;
        !          2562:        }
        !          2563:
        !          2564:        RAL_WRITE(sc, RT2661_TXRX_CSR0, tmp);
        !          2565:
        !          2566:        /* clear STA registers */
        !          2567:        RAL_READ_REGION_4(sc, RT2661_STA_CSR0, sta, N(sta));
        !          2568:
        !          2569:        /* initialize ASIC */
        !          2570:        RAL_WRITE(sc, RT2661_MAC_CSR1, 4);
        !          2571:
        !          2572:        /* clear any pending interrupt */
        !          2573:        RAL_WRITE(sc, RT2661_INT_SOURCE_CSR, 0xffffffff);
        !          2574:
        !          2575:        /* enable interrupts */
        !          2576:        RAL_WRITE(sc, RT2661_INT_MASK_CSR, 0x0000ff10);
        !          2577:        RAL_WRITE(sc, RT2661_MCU_INT_MASK_CSR, 0);
        !          2578:
        !          2579:        /* kick Rx */
        !          2580:        RAL_WRITE(sc, RT2661_RX_CNTL_CSR, 1);
        !          2581:
        !          2582:        ifp->if_flags &= ~IFF_OACTIVE;
        !          2583:        ifp->if_flags |= IFF_RUNNING;
        !          2584:
        !          2585:        if (ic->ic_opmode != IEEE80211_M_MONITOR)
        !          2586:                ieee80211_new_state(ic, IEEE80211_S_SCAN, -1);
        !          2587:        else
        !          2588:                ieee80211_new_state(ic, IEEE80211_S_RUN, -1);
        !          2589:
        !          2590:        return 0;
        !          2591: #undef N
        !          2592: }
        !          2593:
        !          2594: void
        !          2595: rt2661_stop(struct ifnet *ifp, int disable)
        !          2596: {
        !          2597:        struct rt2661_softc *sc = ifp->if_softc;
        !          2598:        struct ieee80211com *ic = &sc->sc_ic;
        !          2599:        uint32_t tmp;
        !          2600:        int ac;
        !          2601:
        !          2602:        sc->sc_tx_timer = 0;
        !          2603:        ifp->if_timer = 0;
        !          2604:        ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE);
        !          2605:
        !          2606:        ieee80211_new_state(ic, IEEE80211_S_INIT, -1);  /* free all nodes */
        !          2607:
        !          2608:        /* abort Tx (for all 5 Tx rings) */
        !          2609:        RAL_WRITE(sc, RT2661_TX_CNTL_CSR, 0x1f << 16);
        !          2610:
        !          2611:        /* disable Rx (value remains after reset!) */
        !          2612:        tmp = RAL_READ(sc, RT2661_TXRX_CSR0);
        !          2613:        RAL_WRITE(sc, RT2661_TXRX_CSR0, tmp | RT2661_DISABLE_RX);
        !          2614:
        !          2615:        /* reset ASIC */
        !          2616:        RAL_WRITE(sc, RT2661_MAC_CSR1, 3);
        !          2617:        RAL_WRITE(sc, RT2661_MAC_CSR1, 0);
        !          2618:
        !          2619:        /* disable interrupts */
        !          2620:        RAL_WRITE(sc, RT2661_INT_MASK_CSR, 0xffffff7f);
        !          2621:        RAL_WRITE(sc, RT2661_MCU_INT_MASK_CSR, 0xffffffff);
        !          2622:
        !          2623:        /* clear any pending interrupt */
        !          2624:        RAL_WRITE(sc, RT2661_INT_SOURCE_CSR, 0xffffffff);
        !          2625:        RAL_WRITE(sc, RT2661_MCU_INT_SOURCE_CSR, 0xffffffff);
        !          2626:
        !          2627:        /* reset Tx and Rx rings */
        !          2628:        for (ac = 0; ac < 4; ac++)
        !          2629:                rt2661_reset_tx_ring(sc, &sc->txq[ac]);
        !          2630:        rt2661_reset_tx_ring(sc, &sc->mgtq);
        !          2631:        rt2661_reset_rx_ring(sc, &sc->rxq);
        !          2632:
        !          2633:        /* for CardBus, power down the socket */
        !          2634:        if (disable && sc->sc_disable != NULL) {
        !          2635:                if (sc->sc_flags & RT2661_ENABLED) {
        !          2636:                        (*sc->sc_disable)(sc);
        !          2637:                        sc->sc_flags &= ~(RT2661_ENABLED | RT2661_FWLOADED);
        !          2638:                }
        !          2639:        }
        !          2640: }
        !          2641:
        !          2642: int
        !          2643: rt2661_load_microcode(struct rt2661_softc *sc, const uint8_t *ucode, int size)
        !          2644: {
        !          2645:        int ntries;
        !          2646:
        !          2647:        /* reset 8051 */
        !          2648:        RAL_WRITE(sc, RT2661_MCU_CNTL_CSR, RT2661_MCU_RESET);
        !          2649:
        !          2650:        /* cancel any pending Host to MCU command */
        !          2651:        RAL_WRITE(sc, RT2661_H2M_MAILBOX_CSR, 0);
        !          2652:        RAL_WRITE(sc, RT2661_M2H_CMD_DONE_CSR, 0xffffffff);
        !          2653:        RAL_WRITE(sc, RT2661_HOST_CMD_CSR, 0);
        !          2654:
        !          2655:        /* write 8051's microcode */
        !          2656:        RAL_WRITE(sc, RT2661_MCU_CNTL_CSR, RT2661_MCU_RESET | RT2661_MCU_SEL);
        !          2657:        RAL_WRITE_REGION_1(sc, RT2661_MCU_CODE_BASE, ucode, size);
        !          2658:        RAL_WRITE(sc, RT2661_MCU_CNTL_CSR, RT2661_MCU_RESET);
        !          2659:
        !          2660:        /* kick 8051's ass */
        !          2661:        RAL_WRITE(sc, RT2661_MCU_CNTL_CSR, 0);
        !          2662:
        !          2663:        /* wait for 8051 to initialize */
        !          2664:        for (ntries = 0; ntries < 500; ntries++) {
        !          2665:                if (RAL_READ(sc, RT2661_MCU_CNTL_CSR) & RT2661_MCU_READY)
        !          2666:                        break;
        !          2667:                DELAY(100);
        !          2668:        }
        !          2669:        if (ntries == 500) {
        !          2670:                printf("timeout waiting for MCU to initialize\n");
        !          2671:                return EIO;
        !          2672:        }
        !          2673:        return 0;
        !          2674: }
        !          2675:
        !          2676: /*
        !          2677:  * Dynamically tune Rx sensitivity (BBP register 17) based on average RSSI and
        !          2678:  * false CCA count.  This function is called periodically (every seconds) when
        !          2679:  * in the RUN state.  Values taken from the reference driver.
        !          2680:  */
        !          2681: void
        !          2682: rt2661_rx_tune(struct rt2661_softc *sc)
        !          2683: {
        !          2684:        uint8_t bbp17;
        !          2685:        uint16_t cca;
        !          2686:        int lo, hi, dbm;
        !          2687:
        !          2688:        /*
        !          2689:         * Tuning range depends on operating band and on the presence of an
        !          2690:         * external low-noise amplifier.
        !          2691:         */
        !          2692:        lo = 0x20;
        !          2693:        if (IEEE80211_IS_CHAN_5GHZ(sc->sc_curchan))
        !          2694:                lo += 0x08;
        !          2695:        if ((IEEE80211_IS_CHAN_2GHZ(sc->sc_curchan) && sc->ext_2ghz_lna) ||
        !          2696:            (IEEE80211_IS_CHAN_5GHZ(sc->sc_curchan) && sc->ext_5ghz_lna))
        !          2697:                lo += 0x10;
        !          2698:        hi = lo + 0x20;
        !          2699:
        !          2700:        dbm = sc->avg_rssi;
        !          2701:        /* retrieve false CCA count since last call (clear on read) */
        !          2702:        cca = RAL_READ(sc, RT2661_STA_CSR1) & 0xffff;
        !          2703:
        !          2704:        DPRINTFN(2, ("RSSI=%ddBm false CCA=%d\n", dbm, cca));
        !          2705:
        !          2706:        if (dbm < -74) {
        !          2707:                /* very bad RSSI, tune using false CCA count */
        !          2708:                bbp17 = sc->bbp17; /* current value */
        !          2709:
        !          2710:                hi -= 2 * (-74 - dbm);
        !          2711:                if (hi < lo)
        !          2712:                        hi = lo;
        !          2713:
        !          2714:                if (bbp17 > hi)
        !          2715:                        bbp17 = hi;
        !          2716:                else if (cca > 512)
        !          2717:                        bbp17 = min(bbp17 + 1, hi);
        !          2718:                else if (cca < 100)
        !          2719:                        bbp17 = max(bbp17 - 1, lo);
        !          2720:
        !          2721:        } else if (dbm < -66) {
        !          2722:                bbp17 = lo + 0x08;
        !          2723:        } else if (dbm < -58) {
        !          2724:                bbp17 = lo + 0x10;
        !          2725:        } else if (dbm < -35) {
        !          2726:                bbp17 = hi;
        !          2727:        } else {        /* very good RSSI >= -35dBm */
        !          2728:                bbp17 = 0x60;   /* very low sensitivity */
        !          2729:        }
        !          2730:
        !          2731:        if (bbp17 != sc->bbp17) {
        !          2732:                DPRINTF(("BBP17 %x->%x\n", sc->bbp17, bbp17));
        !          2733:                rt2661_bbp_write(sc, 17, bbp17);
        !          2734:                sc->bbp17 = bbp17;
        !          2735:        }
        !          2736: }
        !          2737:
        !          2738: #ifdef notyet
        !          2739: /*
        !          2740:  * Enter/Leave radar detection mode.
        !          2741:  * This is for 802.11h additional regulatory domains.
        !          2742:  */
        !          2743: void
        !          2744: rt2661_radar_start(struct rt2661_softc *sc)
        !          2745: {
        !          2746:        uint32_t tmp;
        !          2747:
        !          2748:        /* disable Rx */
        !          2749:        tmp = RAL_READ(sc, RT2661_TXRX_CSR0);
        !          2750:        RAL_WRITE(sc, RT2661_TXRX_CSR0, tmp | RT2661_DISABLE_RX);
        !          2751:
        !          2752:        rt2661_bbp_write(sc, 82, 0x20);
        !          2753:        rt2661_bbp_write(sc, 83, 0x00);
        !          2754:        rt2661_bbp_write(sc, 84, 0x40);
        !          2755:
        !          2756:        /* save current BBP registers values */
        !          2757:        sc->bbp18 = rt2661_bbp_read(sc, 18);
        !          2758:        sc->bbp21 = rt2661_bbp_read(sc, 21);
        !          2759:        sc->bbp22 = rt2661_bbp_read(sc, 22);
        !          2760:        sc->bbp16 = rt2661_bbp_read(sc, 16);
        !          2761:        sc->bbp17 = rt2661_bbp_read(sc, 17);
        !          2762:        sc->bbp64 = rt2661_bbp_read(sc, 64);
        !          2763:
        !          2764:        rt2661_bbp_write(sc, 18, 0xff);
        !          2765:        rt2661_bbp_write(sc, 21, 0x3f);
        !          2766:        rt2661_bbp_write(sc, 22, 0x3f);
        !          2767:        rt2661_bbp_write(sc, 16, 0xbd);
        !          2768:        rt2661_bbp_write(sc, 17, sc->ext_5ghz_lna ? 0x44 : 0x34);
        !          2769:        rt2661_bbp_write(sc, 64, 0x21);
        !          2770:
        !          2771:        /* restore Rx filter */
        !          2772:        RAL_WRITE(sc, RT2661_TXRX_CSR0, tmp);
        !          2773: }
        !          2774:
        !          2775: int
        !          2776: rt2661_radar_stop(struct rt2661_softc *sc)
        !          2777: {
        !          2778:        uint8_t bbp66;
        !          2779:
        !          2780:        /* read radar detection result */
        !          2781:        bbp66 = rt2661_bbp_read(sc, 66);
        !          2782:
        !          2783:        /* restore BBP registers values */
        !          2784:        rt2661_bbp_write(sc, 16, sc->bbp16);
        !          2785:        rt2661_bbp_write(sc, 17, sc->bbp17);
        !          2786:        rt2661_bbp_write(sc, 18, sc->bbp18);
        !          2787:        rt2661_bbp_write(sc, 21, sc->bbp21);
        !          2788:        rt2661_bbp_write(sc, 22, sc->bbp22);
        !          2789:        rt2661_bbp_write(sc, 64, sc->bbp64);
        !          2790:
        !          2791:        return bbp66 == 1;
        !          2792: }
        !          2793: #endif
        !          2794:
        !          2795: int
        !          2796: rt2661_prepare_beacon(struct rt2661_softc *sc)
        !          2797: {
        !          2798:        struct ieee80211com *ic = &sc->sc_ic;
        !          2799:        struct ieee80211_node *ni = ic->ic_bss;
        !          2800:        struct rt2661_tx_desc desc;
        !          2801:        struct mbuf *m0;
        !          2802:        int rate;
        !          2803:
        !          2804:        m0 = ieee80211_beacon_alloc(ic, ni);
        !          2805:        if (m0 == NULL) {
        !          2806:                printf("%s: could not allocate beacon frame\n",
        !          2807:                    sc->sc_dev.dv_xname);
        !          2808:                return ENOBUFS;
        !          2809:        }
        !          2810:
        !          2811:        /* send beacons at the lowest available rate */
        !          2812:        rate = IEEE80211_IS_CHAN_5GHZ(ni->ni_chan) ? 12 : 2;
        !          2813:
        !          2814:        rt2661_setup_tx_desc(sc, &desc, RT2661_TX_TIMESTAMP, RT2661_TX_HWSEQ,
        !          2815:            m0->m_pkthdr.len, rate, NULL, 0, RT2661_QID_MGT);
        !          2816:
        !          2817:        /* copy the first 24 bytes of Tx descriptor into NIC memory */
        !          2818:        RAL_WRITE_REGION_1(sc, RT2661_HW_BEACON_BASE0, (uint8_t *)&desc, 24);
        !          2819:
        !          2820:        /* copy beacon header and payload into NIC memory */
        !          2821:        RAL_WRITE_REGION_1(sc, RT2661_HW_BEACON_BASE0 + 24,
        !          2822:            mtod(m0, uint8_t *), m0->m_pkthdr.len);
        !          2823:
        !          2824:        m_freem(m0);
        !          2825:
        !          2826:        /*
        !          2827:         * Store offset of ERP Information Element so that we can update it
        !          2828:         * dynamically when the slot time changes.
        !          2829:         * XXX: this is ugly since it depends on how net80211 builds beacon
        !          2830:         * frames but ieee80211_beacon_alloc() doesn't store offsets for us.
        !          2831:         */
        !          2832:        if (ic->ic_curmode == IEEE80211_MODE_11G) {
        !          2833:                sc->erp_csr =
        !          2834:                    RT2661_HW_BEACON_BASE0 + 24 +
        !          2835:                    sizeof (struct ieee80211_frame) +
        !          2836:                    8 + 2 + 2 +
        !          2837:                    ((ic->ic_flags & IEEE80211_F_HIDENWID) ?
        !          2838:                        1 : 2 + ni->ni_esslen) +
        !          2839:                    2 + min(ni->ni_rates.rs_nrates, IEEE80211_RATE_SIZE) +
        !          2840:                    2 + 1 +
        !          2841:                    ((ic->ic_opmode == IEEE80211_M_IBSS) ? 4 : 6) +
        !          2842:                    2;
        !          2843:        }
        !          2844:
        !          2845:        return 0;
        !          2846: }
        !          2847:
        !          2848: /*
        !          2849:  * Enable TSF synchronization and tell h/w to start sending beacons for IBSS
        !          2850:  * and HostAP operating modes.
        !          2851:  */
        !          2852: void
        !          2853: rt2661_enable_tsf_sync(struct rt2661_softc *sc)
        !          2854: {
        !          2855:        struct ieee80211com *ic = &sc->sc_ic;
        !          2856:        uint32_t tmp;
        !          2857:
        !          2858:        if (ic->ic_opmode != IEEE80211_M_STA) {
        !          2859:                /*
        !          2860:                 * Change default 16ms TBTT adjustment to 8ms.
        !          2861:                 * Must be done before enabling beacon generation.
        !          2862:                 */
        !          2863:                RAL_WRITE(sc, RT2661_TXRX_CSR10, 1 << 12 | 8);
        !          2864:        }
        !          2865:
        !          2866:        tmp = RAL_READ(sc, RT2661_TXRX_CSR9) & 0xff000000;
        !          2867:
        !          2868:        /* set beacon interval (in 1/16ms unit) */
        !          2869:        tmp |= ic->ic_bss->ni_intval * 16;
        !          2870:
        !          2871:        tmp |= RT2661_TSF_TICKING | RT2661_ENABLE_TBTT;
        !          2872:        if (ic->ic_opmode == IEEE80211_M_STA)
        !          2873:                tmp |= RT2661_TSF_MODE(1);
        !          2874:        else
        !          2875:                tmp |= RT2661_TSF_MODE(2) | RT2661_GENERATE_BEACON;
        !          2876:
        !          2877:        RAL_WRITE(sc, RT2661_TXRX_CSR9, tmp);
        !          2878: }
        !          2879:
        !          2880: /*
        !          2881:  * Retrieve the "Received Signal Strength Indicator" from the raw values
        !          2882:  * contained in Rx descriptors.  The computation depends on which band the
        !          2883:  * frame was received.  Correction values taken from the reference driver.
        !          2884:  */
        !          2885: int
        !          2886: rt2661_get_rssi(struct rt2661_softc *sc, uint8_t raw)
        !          2887: {
        !          2888:        int lna, agc, rssi;
        !          2889:
        !          2890:        lna = (raw >> 5) & 0x3;
        !          2891:        agc = raw & 0x1f;
        !          2892:
        !          2893:        rssi = 2 * agc;
        !          2894:
        !          2895:        if (IEEE80211_IS_CHAN_2GHZ(sc->sc_curchan)) {
        !          2896:                rssi += sc->rssi_2ghz_corr;
        !          2897:
        !          2898:                if (lna == 1)
        !          2899:                        rssi -= 64;
        !          2900:                else if (lna == 2)
        !          2901:                        rssi -= 74;
        !          2902:                else if (lna == 3)
        !          2903:                        rssi -= 90;
        !          2904:        } else {
        !          2905:                rssi += sc->rssi_5ghz_corr;
        !          2906:
        !          2907:                if (lna == 1)
        !          2908:                        rssi -= 64;
        !          2909:                else if (lna == 2)
        !          2910:                        rssi -= 86;
        !          2911:                else if (lna == 3)
        !          2912:                        rssi -= 100;
        !          2913:        }
        !          2914:        return rssi;
        !          2915: }
        !          2916:
        !          2917: void
        !          2918: rt2661_power(int why, void *arg)
        !          2919: {
        !          2920:        struct rt2661_softc *sc = arg;
        !          2921:        struct ifnet *ifp = &sc->sc_ic.ic_if;
        !          2922:        int s;
        !          2923:
        !          2924:        DPRINTF(("%s: rt2661_power(%d)\n", sc->sc_dev.dv_xname, why));
        !          2925:
        !          2926:        s = splnet();
        !          2927:        switch (why) {
        !          2928:        case PWR_SUSPEND:
        !          2929:        case PWR_STANDBY:
        !          2930:                rt2661_stop(ifp, 1);
        !          2931:                sc->sc_flags &= ~RT2661_FWLOADED;
        !          2932:                if (sc->sc_power != NULL)
        !          2933:                        (*sc->sc_power)(sc, why);
        !          2934:                break;
        !          2935:        case PWR_RESUME:
        !          2936:                if (ifp->if_flags & IFF_UP) {
        !          2937:                        rt2661_init(ifp);
        !          2938:                        if (sc->sc_power != NULL)
        !          2939:                                (*sc->sc_power)(sc, why);
        !          2940:                        if (ifp->if_flags & IFF_RUNNING)
        !          2941:                                rt2661_start(ifp);
        !          2942:                }
        !          2943:                break;
        !          2944:        }
        !          2945:        splx(s);
        !          2946: }
        !          2947:
        !          2948: void
        !          2949: rt2661_shutdown(void *arg)
        !          2950: {
        !          2951:        struct rt2661_softc *sc = arg;
        !          2952:        struct ifnet *ifp = &sc->sc_ic.ic_if;
        !          2953:
        !          2954:        rt2661_stop(ifp, 1);
        !          2955: }

CVSweb