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

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

1.1     ! nbrk        1: /*     $OpenBSD: rtw.c,v 1.61 2007/06/07 20:20:15 damien Exp $ */
        !             2: /*     $NetBSD: rtw.c,v 1.29 2004/12/27 19:49:16 dyoung Exp $ */
        !             3:
        !             4: /*-
        !             5:  * Copyright (c) 2004, 2005 David Young.  All rights reserved.
        !             6:  *
        !             7:  * Programmed for NetBSD by David Young.
        !             8:  *
        !             9:  * Redistribution and use in source and binary forms, with or without
        !            10:  * modification, are permitted provided that the following conditions
        !            11:  * are met:
        !            12:  * 1. Redistributions of source code must retain the above copyright
        !            13:  *    notice, this list of conditions and the following disclaimer.
        !            14:  * 2. Redistributions in binary form must reproduce the above copyright
        !            15:  *    notice, this list of conditions and the following disclaimer in the
        !            16:  *    documentation and/or other materials provided with the distribution.
        !            17:  * 3. The name of David Young may not be used to endorse or promote
        !            18:  *    products derived from this software without specific prior
        !            19:  *    written permission.
        !            20:  *
        !            21:  * THIS SOFTWARE IS PROVIDED BY David Young ``AS IS'' AND ANY
        !            22:  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
        !            23:  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
        !            24:  * PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL David
        !            25:  * Young BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
        !            26:  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
        !            27:  * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
        !            28:  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
        !            29:  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
        !            30:  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
        !            31:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
        !            32:  * OF SUCH DAMAGE.
        !            33:  */
        !            34: /*
        !            35:  * Device driver for the Realtek RTL8180 802.11 MAC/BBP.
        !            36:  */
        !            37:
        !            38: #include <sys/cdefs.h>
        !            39: #include "bpfilter.h"
        !            40:
        !            41: #include <sys/param.h>
        !            42: #include <sys/systm.h>
        !            43: #include <sys/mbuf.h>
        !            44: #include <sys/malloc.h>
        !            45: #include <sys/kernel.h>
        !            46: #include <sys/ioctl.h>
        !            47: #include <sys/socket.h>
        !            48: #include <sys/time.h>
        !            49: #include <sys/types.h>
        !            50:
        !            51: #include <machine/endian.h>
        !            52: #include <machine/bus.h>
        !            53: #include <machine/intr.h>      /* splnet */
        !            54:
        !            55: #include <uvm/uvm_extern.h>
        !            56:
        !            57: #include <net/if.h>
        !            58: #include <net/if_media.h>
        !            59:
        !            60: #if NBPFILTER > 0
        !            61: #include <net/bpf.h>
        !            62: #endif
        !            63:
        !            64: #ifdef INET
        !            65: #include <netinet/in.h>
        !            66: #include <netinet/if_ether.h>
        !            67: #endif
        !            68:
        !            69: #include <net80211/ieee80211_var.h>
        !            70: #include <net80211/ieee80211_radiotap.h>
        !            71:
        !            72: #include <dev/ic/rtwreg.h>
        !            73: #include <dev/ic/rtwvar.h>
        !            74: #include <dev/ic/max2820reg.h>
        !            75: #include <dev/ic/sa2400reg.h>
        !            76: #include <dev/ic/si4136reg.h>
        !            77: #include <dev/ic/rtl8225reg.h>
        !            78: #include <dev/ic/smc93cx6var.h>
        !            79:
        !            80: int rtw_rfprog_fallback = 0;
        !            81: int rtw_do_chip_reset = 0;
        !            82: int rtw_dwelltime = 200;       /* milliseconds per channel */
        !            83: int rtw_macbangbits_timeout = 100;
        !            84:
        !            85: #ifdef RTW_DEBUG
        !            86: int rtw_debug = 0;
        !            87: int rtw_rxbufs_limit = RTW_RXQLEN;
        !            88: #endif /* RTW_DEBUG */
        !            89:
        !            90: void    rtw_start(struct ifnet *);
        !            91: void    rtw_txdesc_blk_init_all(struct rtw_txdesc_blk *);
        !            92: void    rtw_txsoft_blk_init_all(struct rtw_txsoft_blk *);
        !            93: void    rtw_txdesc_blk_init(struct rtw_txdesc_blk *);
        !            94: void    rtw_txdescs_sync(struct rtw_txdesc_blk *, u_int, u_int, int);
        !            95: u_int   rtw_txring_next(struct rtw_regs *, struct rtw_txdesc_blk *);
        !            96: void    rtw_txring_fixup(struct rtw_softc *);
        !            97: void    rtw_rxbufs_release(bus_dma_tag_t, struct rtw_rxsoft *);
        !            98: void    rtw_rxdesc_init(struct rtw_rxdesc_blk *, struct rtw_rxsoft *, int, int);
        !            99: void    rtw_rxring_fixup(struct rtw_softc *);
        !           100: void    rtw_io_enable(struct rtw_regs *, u_int8_t, int);
        !           101: void    rtw_intr_rx(struct rtw_softc *, u_int16_t);
        !           102: void    rtw_intr_beacon(struct rtw_softc *, u_int16_t);
        !           103: void    rtw_intr_atim(struct rtw_softc *);
        !           104: void    rtw_transmit_config(struct rtw_softc *);
        !           105: void    rtw_pktfilt_load(struct rtw_softc *);
        !           106: void    rtw_start(struct ifnet *);
        !           107: void    rtw_watchdog(struct ifnet *);
        !           108: void    rtw_next_scan(void *);
        !           109: void    rtw_recv_mgmt(struct ieee80211com *, struct mbuf *,
        !           110:            struct ieee80211_node *, int, int, u_int32_t);
        !           111: struct ieee80211_node *rtw_node_alloc(struct ieee80211com *);
        !           112: void    rtw_node_free(struct ieee80211com *, struct ieee80211_node *);
        !           113: void    rtw_media_status(struct ifnet *, struct ifmediareq *);
        !           114: void    rtw_txsoft_blk_cleanup_all(struct rtw_softc *);
        !           115: void    rtw_txdesc_blk_setup(struct rtw_txdesc_blk *, struct rtw_txdesc *,
        !           116:            u_int, bus_addr_t, bus_addr_t);
        !           117: void    rtw_txdesc_blk_setup_all(struct rtw_softc *);
        !           118: void    rtw_intr_tx(struct rtw_softc *, u_int16_t);
        !           119: void    rtw_intr_ioerror(struct rtw_softc *, u_int16_t);
        !           120: void    rtw_intr_timeout(struct rtw_softc *);
        !           121: void    rtw_stop(struct ifnet *, int);
        !           122: void    rtw_maxim_pwrstate(struct rtw_regs *, enum rtw_pwrstate, int, int);
        !           123: void    rtw_philips_pwrstate(struct rtw_regs *, enum rtw_pwrstate, int, int);
        !           124: void    rtw_rtl_pwrstate(struct rtw_regs *, enum rtw_pwrstate, int, int);
        !           125: void    rtw_pwrstate0(struct rtw_softc *, enum rtw_pwrstate, int, int);
        !           126: void    rtw_join_bss(struct rtw_softc *, u_int8_t *, u_int16_t);
        !           127: void    rtw_set_access1(struct rtw_regs *, enum rtw_access);
        !           128: int     rtw_srom_parse(struct rtw_softc *);
        !           129: int     rtw_srom_read(struct rtw_regs *, u_int32_t, struct rtw_srom *,
        !           130:            const char *);
        !           131: void    rtw_set_rfprog(struct rtw_regs *, int, const char *);
        !           132: u_int8_t rtw_chan2txpower(struct rtw_srom *, struct ieee80211com *,
        !           133:            struct ieee80211_channel *);
        !           134: int     rtw_txsoft_blk_init(struct rtw_txsoft_blk *);
        !           135: int     rtw_rxsoft_init_all(bus_dma_tag_t, struct rtw_rxsoft *,
        !           136:            int *, const char *);
        !           137: void    rtw_txsoft_release(bus_dma_tag_t, struct ieee80211com *,
        !           138:            struct rtw_txsoft *);
        !           139: void    rtw_txsofts_release(bus_dma_tag_t, struct ieee80211com *,
        !           140:            struct rtw_txsoft_blk *);
        !           141: void    rtw_hwring_setup(struct rtw_softc *);
        !           142: int     rtw_swring_setup(struct rtw_softc *);
        !           143: void    rtw_txdescs_reset(struct rtw_softc *);
        !           144: void    rtw_rfmd_pwrstate(struct rtw_regs *, enum rtw_pwrstate, int, int);
        !           145: int     rtw_pwrstate(struct rtw_softc *, enum rtw_pwrstate);
        !           146: int     rtw_tune(struct rtw_softc *);
        !           147: void    rtw_set_nettype(struct rtw_softc *, enum ieee80211_opmode);
        !           148: int     rtw_compute_duration1(int, int, uint32_t, int, struct rtw_duration *);
        !           149: int     rtw_compute_duration(struct ieee80211_frame *, int, uint32_t, int,
        !           150:            int, struct rtw_duration *, struct rtw_duration *, int *, int);
        !           151: int     rtw_init(struct ifnet *);
        !           152: int     rtw_ioctl(struct ifnet *, u_long, caddr_t);
        !           153: int     rtw_seg_too_short(bus_dmamap_t);
        !           154: struct mbuf *rtw_dmamap_load_txbuf(bus_dma_tag_t, bus_dmamap_t, struct mbuf *,
        !           155:            u_int, short *, const char *);
        !           156: int     rtw_newstate(struct ieee80211com *, enum ieee80211_state, int);
        !           157: int     rtw_media_change(struct ifnet *);
        !           158: int     rtw_txsoft_blk_setup_all(struct rtw_softc *);
        !           159: int     rtw_rf_attach(struct rtw_softc *, int);
        !           160: u_int8_t rtw_check_phydelay(struct rtw_regs *, u_int32_t);
        !           161: int     rtw_chip_reset1(struct rtw_regs *, const char *);
        !           162: int     rtw_chip_reset(struct rtw_regs *, const char *);
        !           163: int     rtw_recall_eeprom(struct rtw_regs *, const char *);
        !           164: int     rtw_reset(struct rtw_softc *);
        !           165: void    rtw_reset_oactive(struct rtw_softc *);
        !           166: int     rtw_txdesc_dmamaps_create(bus_dma_tag_t, struct rtw_txsoft *, u_int);
        !           167: int     rtw_rxdesc_dmamaps_create(bus_dma_tag_t, struct rtw_rxsoft *, u_int);
        !           168: void    rtw_rxdesc_dmamaps_destroy(bus_dma_tag_t, struct rtw_rxsoft *, u_int);
        !           169: void    rtw_txdesc_dmamaps_destroy(bus_dma_tag_t, struct rtw_txsoft *, u_int);
        !           170: void    rtw_init_channels(enum rtw_locale, struct ieee80211_channel (*)[],
        !           171:            const char*);
        !           172: void    rtw_identify_country(struct rtw_regs *, enum rtw_locale *);
        !           173: int     rtw_identify_sta(struct rtw_regs *, u_int8_t (*)[], const char *);
        !           174: void    rtw_rxdescs_sync(struct rtw_rxdesc_blk *, int, int, int);
        !           175: int     rtw_rxsoft_alloc(bus_dma_tag_t, struct rtw_rxsoft *);
        !           176: void    rtw_collect_txpkt(struct rtw_softc *, struct rtw_txdesc_blk *,
        !           177:            struct rtw_txsoft *, int);
        !           178: void    rtw_collect_txring(struct rtw_softc *, struct rtw_txsoft_blk *,
        !           179:            struct rtw_txdesc_blk *, int);
        !           180: void    rtw_suspend_ticks(struct rtw_softc *);
        !           181: void    rtw_resume_ticks(struct rtw_softc *);
        !           182: void    rtw_enable_interrupts(struct rtw_softc *);
        !           183: int     rtw_dequeue(struct ifnet *, struct rtw_txsoft_blk **,
        !           184:            struct rtw_txdesc_blk **, struct mbuf **,
        !           185:            struct ieee80211_node **);
        !           186: void    rtw_establish_hooks(struct rtw_hooks *, const char *, void *);
        !           187: void    rtw_disestablish_hooks(struct rtw_hooks *, const char *, void *);
        !           188: int     rtw_txsoft_blk_setup(struct rtw_txsoft_blk *, u_int);
        !           189: void    rtw_rxdesc_init_all(struct rtw_rxdesc_blk *, struct rtw_rxsoft *,
        !           190:            int);
        !           191: int     rtw_txring_choose(struct rtw_softc *, struct rtw_txsoft_blk **,
        !           192:            struct rtw_txdesc_blk **, int);
        !           193: u_int   rtw_txring_next(struct rtw_regs *, struct rtw_txdesc_blk *);
        !           194: struct mbuf *rtw_80211_dequeue(struct rtw_softc *, struct ifqueue *, int,
        !           195:            struct rtw_txsoft_blk **, struct rtw_txdesc_blk **,
        !           196:            struct ieee80211_node **, short *);
        !           197: uint64_t rtw_tsf_extend(struct rtw_regs *, u_int32_t);
        !           198: void    rtw_ibss_merge(struct rtw_softc *, struct ieee80211_node *,
        !           199:            u_int32_t);
        !           200: void    rtw_idle(struct rtw_regs *);
        !           201: void    rtw_led_attach(struct rtw_led_state *, void *);
        !           202: void    rtw_led_init(struct rtw_regs *);
        !           203: void    rtw_led_slowblink(void *);
        !           204: void    rtw_led_fastblink(void *);
        !           205: void    rtw_led_set(struct rtw_led_state *, struct rtw_regs *, u_int);
        !           206: void    rtw_led_newstate(struct rtw_softc *, enum ieee80211_state);
        !           207:
        !           208: int     rtw_phy_init(struct rtw_softc *);
        !           209: int     rtw_bbp_preinit(struct rtw_regs *, u_int, int, u_int);
        !           210: int     rtw_bbp_init(struct rtw_regs *, struct rtw_bbpset *, int,
        !           211:            int, u_int8_t, u_int);
        !           212: void    rtw_verify_syna(u_int, u_int32_t);
        !           213: int     rtw_sa2400_pwrstate(struct rtw_softc *, enum rtw_pwrstate);
        !           214: int     rtw_sa2400_txpower(struct rtw_softc *, u_int8_t);
        !           215: int     rtw_sa2400_tune(struct rtw_softc *, u_int);
        !           216: int     rtw_sa2400_vcocal_start(struct rtw_softc *, int);
        !           217: int     rtw_sa2400_vco_calibration(struct rtw_softc *);
        !           218: int     rtw_sa2400_filter_calibration(struct rtw_softc *);
        !           219: int     rtw_sa2400_dc_calibration(struct rtw_softc *);
        !           220: int     rtw_sa2400_calibrate(struct rtw_softc *, u_int);
        !           221: int     rtw_sa2400_init(struct rtw_softc *, u_int, u_int8_t,
        !           222:            enum rtw_pwrstate);
        !           223: int     rtw_max2820_pwrstate(struct rtw_softc *, enum rtw_pwrstate);
        !           224: int     rtw_max2820_init(struct rtw_softc *, u_int, u_int8_t,
        !           225:            enum rtw_pwrstate);
        !           226: int     rtw_max2820_txpower(struct rtw_softc *, u_int8_t);
        !           227: int     rtw_max2820_tune(struct rtw_softc *, u_int);
        !           228: int     rtw_rtl8225_pwrstate(struct rtw_softc *, enum rtw_pwrstate);
        !           229: int     rtw_rtl8225_init(struct rtw_softc *, u_int, u_int8_t,
        !           230:            enum rtw_pwrstate);
        !           231: int     rtw_rtl8225_txpower(struct rtw_softc *, u_int8_t);
        !           232: int     rtw_rtl8225_tune(struct rtw_softc *, u_int);
        !           233: int     rtw_rtl8255_pwrstate(struct rtw_softc *, enum rtw_pwrstate);
        !           234: int     rtw_rtl8255_init(struct rtw_softc *, u_int, u_int8_t,
        !           235:            enum rtw_pwrstate);
        !           236: int     rtw_rtl8255_txpower(struct rtw_softc *, u_int8_t);
        !           237: int     rtw_rtl8255_tune(struct rtw_softc *, u_int);
        !           238: int     rtw_grf5101_pwrstate(struct rtw_softc *, enum rtw_pwrstate);
        !           239: int     rtw_grf5101_init(struct rtw_softc *, u_int, u_int8_t,
        !           240:            enum rtw_pwrstate);
        !           241: int     rtw_grf5101_txpower(struct rtw_softc *, u_int8_t);
        !           242: int     rtw_grf5101_tune(struct rtw_softc *, u_int);
        !           243: int     rtw_rf_hostwrite(struct rtw_softc *, u_int, u_int32_t);
        !           244: int     rtw_rf_macwrite(struct rtw_softc *, u_int, u_int32_t);
        !           245: int     rtw_bbp_write(struct rtw_regs *, u_int, u_int);
        !           246: u_int32_t rtw_grf5101_host_crypt(u_int, u_int32_t);
        !           247: u_int32_t rtw_maxim_swizzle(u_int, uint32_t);
        !           248: u_int32_t rtw_grf5101_mac_crypt(u_int, u_int32_t);
        !           249: void    rtw_rf_hostbangbits(struct rtw_regs *, u_int32_t, int, u_int);
        !           250: void    rtw_rf_rtl8225_hostbangbits(struct rtw_regs *, u_int32_t, int, u_int);
        !           251: int     rtw_rf_macbangbits(struct rtw_regs *, u_int32_t);
        !           252:
        !           253: u_int8_t rtw_read8(void *, u_int32_t);
        !           254: u_int16_t rtw_read16(void *, u_int32_t);
        !           255: u_int32_t rtw_read32(void *, u_int32_t);
        !           256: void    rtw_write8(void *, u_int32_t, u_int8_t);
        !           257: void    rtw_write16(void *, u_int32_t, u_int16_t);
        !           258: void    rtw_write32(void *, u_int32_t, u_int32_t);
        !           259: void    rtw_barrier(void *, u_int32_t, u_int32_t, int);
        !           260:
        !           261: #ifdef RTW_DEBUG
        !           262: void    rtw_print_txdesc(struct rtw_softc *, const char *,
        !           263:            struct rtw_txsoft *, struct rtw_txdesc_blk *, int);
        !           264: const char *rtw_access_string(enum rtw_access);
        !           265: void    rtw_dump_rings(struct rtw_softc *);
        !           266: void    rtw_print_txdesc(struct rtw_softc *, const char *,
        !           267:            struct rtw_txsoft *, struct rtw_txdesc_blk *, int);
        !           268: #endif
        !           269:
        !           270: struct cfdriver rtw_cd = {
        !           271:        NULL, "rtw", DV_IFNET
        !           272: };
        !           273:
        !           274: void
        !           275: rtw_continuous_tx_enable(struct rtw_softc *sc, int enable)
        !           276: {
        !           277:        struct rtw_regs *regs = &sc->sc_regs;
        !           278:
        !           279:        u_int32_t tcr;
        !           280:        tcr = RTW_READ(regs, RTW_TCR);
        !           281:        tcr &= ~RTW_TCR_LBK_MASK;
        !           282:        if (enable)
        !           283:                tcr |= RTW_TCR_LBK_CONT;
        !           284:        else
        !           285:                tcr |= RTW_TCR_LBK_NORMAL;
        !           286:        RTW_WRITE(regs, RTW_TCR, tcr);
        !           287:        RTW_SYNC(regs, RTW_TCR, RTW_TCR);
        !           288:        rtw_set_access(regs, RTW_ACCESS_ANAPARM);
        !           289:        rtw_txdac_enable(sc, !enable);
        !           290:        rtw_set_access(regs, RTW_ACCESS_ANAPARM);/* XXX Voodoo from Linux. */
        !           291:        rtw_set_access(regs, RTW_ACCESS_NONE);
        !           292: }
        !           293:
        !           294: #ifdef RTW_DEBUG
        !           295: const char *
        !           296: rtw_access_string(enum rtw_access access)
        !           297: {
        !           298:        switch (access) {
        !           299:        case RTW_ACCESS_NONE:
        !           300:                return "none";
        !           301:        case RTW_ACCESS_CONFIG:
        !           302:                return "config";
        !           303:        case RTW_ACCESS_ANAPARM:
        !           304:                return "anaparm";
        !           305:        default:
        !           306:                return "unknown";
        !           307:        }
        !           308: }
        !           309: #endif
        !           310:
        !           311: void
        !           312: rtw_set_access1(struct rtw_regs *regs, enum rtw_access naccess)
        !           313: {
        !           314:        KASSERT(naccess >= RTW_ACCESS_NONE && naccess <= RTW_ACCESS_ANAPARM);
        !           315:        KASSERT(regs->r_access >= RTW_ACCESS_NONE &&
        !           316:            regs->r_access <= RTW_ACCESS_ANAPARM);
        !           317:
        !           318:        if (naccess == regs->r_access)
        !           319:                return;
        !           320:
        !           321:        switch (naccess) {
        !           322:        case RTW_ACCESS_NONE:
        !           323:                switch (regs->r_access) {
        !           324:                case RTW_ACCESS_ANAPARM:
        !           325:                        rtw_anaparm_enable(regs, 0);
        !           326:                        /*FALLTHROUGH*/
        !           327:                case RTW_ACCESS_CONFIG:
        !           328:                        rtw_config0123_enable(regs, 0);
        !           329:                        /*FALLTHROUGH*/
        !           330:                case RTW_ACCESS_NONE:
        !           331:                        break;
        !           332:                }
        !           333:                break;
        !           334:        case RTW_ACCESS_CONFIG:
        !           335:                switch (regs->r_access) {
        !           336:                case RTW_ACCESS_NONE:
        !           337:                        rtw_config0123_enable(regs, 1);
        !           338:                        /*FALLTHROUGH*/
        !           339:                case RTW_ACCESS_CONFIG:
        !           340:                        break;
        !           341:                case RTW_ACCESS_ANAPARM:
        !           342:                        rtw_anaparm_enable(regs, 0);
        !           343:                        break;
        !           344:                }
        !           345:                break;
        !           346:        case RTW_ACCESS_ANAPARM:
        !           347:                switch (regs->r_access) {
        !           348:                case RTW_ACCESS_NONE:
        !           349:                        rtw_config0123_enable(regs, 1);
        !           350:                        /*FALLTHROUGH*/
        !           351:                case RTW_ACCESS_CONFIG:
        !           352:                        rtw_anaparm_enable(regs, 1);
        !           353:                        /*FALLTHROUGH*/
        !           354:                case RTW_ACCESS_ANAPARM:
        !           355:                        break;
        !           356:                }
        !           357:                break;
        !           358:        }
        !           359: }
        !           360:
        !           361: void
        !           362: rtw_set_access(struct rtw_regs *regs, enum rtw_access access)
        !           363: {
        !           364:        rtw_set_access1(regs, access);
        !           365:        RTW_DPRINTF(RTW_DEBUG_ACCESS,
        !           366:            ("%s: access %s -> %s\n",__func__,
        !           367:            rtw_access_string(regs->r_access),
        !           368:            rtw_access_string(access)));
        !           369:        regs->r_access = access;
        !           370: }
        !           371:
        !           372: /*
        !           373:  * Enable registers, switch register banks.
        !           374:  */
        !           375: void
        !           376: rtw_config0123_enable(struct rtw_regs *regs, int enable)
        !           377: {
        !           378:        u_int8_t ecr;
        !           379:        ecr = RTW_READ8(regs, RTW_9346CR);
        !           380:        ecr &= ~(RTW_9346CR_EEM_MASK | RTW_9346CR_EECS | RTW_9346CR_EESK);
        !           381:        if (enable)
        !           382:                ecr |= RTW_9346CR_EEM_CONFIG;
        !           383:        else {
        !           384:                RTW_WBW(regs, RTW_9346CR, MAX(RTW_CONFIG0, RTW_CONFIG3));
        !           385:                ecr |= RTW_9346CR_EEM_NORMAL;
        !           386:        }
        !           387:        RTW_WRITE8(regs, RTW_9346CR, ecr);
        !           388:        RTW_SYNC(regs, RTW_9346CR, RTW_9346CR);
        !           389: }
        !           390:
        !           391: /* requires rtw_config0123_enable(, 1) */
        !           392: void
        !           393: rtw_anaparm_enable(struct rtw_regs *regs, int enable)
        !           394: {
        !           395:        u_int8_t cfg3;
        !           396:
        !           397:        cfg3 = RTW_READ8(regs, RTW_CONFIG3);
        !           398:        cfg3 |= RTW_CONFIG3_CLKRUNEN;
        !           399:        if (enable)
        !           400:                cfg3 |= RTW_CONFIG3_PARMEN;
        !           401:        else
        !           402:                cfg3 &= ~RTW_CONFIG3_PARMEN;
        !           403:        RTW_WRITE8(regs, RTW_CONFIG3, cfg3);
        !           404:        RTW_SYNC(regs, RTW_CONFIG3, RTW_CONFIG3);
        !           405: }
        !           406:
        !           407: /* requires rtw_anaparm_enable(, 1) */
        !           408: void
        !           409: rtw_txdac_enable(struct rtw_softc *sc, int enable)
        !           410: {
        !           411:        u_int32_t anaparm;
        !           412:        struct rtw_regs *regs = &sc->sc_regs;
        !           413:
        !           414:        anaparm = RTW_READ(regs, RTW_ANAPARM_0);
        !           415:        if (enable)
        !           416:                anaparm &= ~RTW_ANAPARM_TXDACOFF;
        !           417:        else
        !           418:                anaparm |= RTW_ANAPARM_TXDACOFF;
        !           419:        RTW_WRITE(regs, RTW_ANAPARM_0, anaparm);
        !           420:        RTW_SYNC(regs, RTW_ANAPARM_0, RTW_ANAPARM_0);
        !           421: }
        !           422:
        !           423: int
        !           424: rtw_chip_reset1(struct rtw_regs *regs, const char *dvname)
        !           425: {
        !           426:        u_int8_t cr;
        !           427:        int i;
        !           428:
        !           429:        RTW_WRITE8(regs, RTW_CR, RTW_CR_RST);
        !           430:
        !           431:        RTW_WBR(regs, RTW_CR, RTW_CR);
        !           432:
        !           433:        for (i = 0; i < 1000; i++) {
        !           434:                if ((cr = RTW_READ8(regs, RTW_CR) & RTW_CR_RST) == 0) {
        !           435:                        RTW_DPRINTF(RTW_DEBUG_RESET,
        !           436:                            ("%s: reset in %dus\n", dvname, i));
        !           437:                        return 0;
        !           438:                }
        !           439:                RTW_RBR(regs, RTW_CR, RTW_CR);
        !           440:                DELAY(10); /* 10us */
        !           441:        }
        !           442:
        !           443:        printf("\n%s: reset failed\n", dvname);
        !           444:        return ETIMEDOUT;
        !           445: }
        !           446:
        !           447: int
        !           448: rtw_chip_reset(struct rtw_regs *regs, const char *dvname)
        !           449: {
        !           450:        uint32_t tcr;
        !           451:
        !           452:        /* from Linux driver */
        !           453:        tcr = RTW_TCR_CWMIN | RTW_TCR_MXDMA_2048 |
        !           454:            LSHIFT(7, RTW_TCR_SRL_MASK) | LSHIFT(7, RTW_TCR_LRL_MASK);
        !           455:
        !           456:        RTW_WRITE(regs, RTW_TCR, tcr);
        !           457:
        !           458:        RTW_WBW(regs, RTW_CR, RTW_TCR);
        !           459:
        !           460:        return rtw_chip_reset1(regs, dvname);
        !           461: }
        !           462:
        !           463: int
        !           464: rtw_recall_eeprom(struct rtw_regs *regs, const char *dvname)
        !           465: {
        !           466:        int i;
        !           467:        u_int8_t ecr;
        !           468:
        !           469:        ecr = RTW_READ8(regs, RTW_9346CR);
        !           470:        ecr = (ecr & ~RTW_9346CR_EEM_MASK) | RTW_9346CR_EEM_AUTOLOAD;
        !           471:        RTW_WRITE8(regs, RTW_9346CR, ecr);
        !           472:
        !           473:        RTW_WBR(regs, RTW_9346CR, RTW_9346CR);
        !           474:
        !           475:        /* wait 10ms for completion */
        !           476:        for (i = 0; i < 50; i++) {
        !           477:                ecr = RTW_READ8(regs, RTW_9346CR);
        !           478:                if ((ecr & RTW_9346CR_EEM_MASK) == RTW_9346CR_EEM_NORMAL) {
        !           479:                        RTW_DPRINTF(RTW_DEBUG_RESET,
        !           480:                            ("%s: recall EEPROM in %dus\n", dvname, i * 200));
        !           481:                        return (0);
        !           482:                }
        !           483:                RTW_RBR(regs, RTW_9346CR, RTW_9346CR);
        !           484:                DELAY(200);
        !           485:        }
        !           486:
        !           487:        printf("\n%s: could not recall EEPROM in %dus\n", dvname, i * 200);
        !           488:
        !           489:        return (ETIMEDOUT);
        !           490: }
        !           491:
        !           492: int
        !           493: rtw_reset(struct rtw_softc *sc)
        !           494: {
        !           495:        int rc;
        !           496:        uint8_t config1;
        !           497:
        !           498:        if ((rc = rtw_chip_reset(&sc->sc_regs, sc->sc_dev.dv_xname)) != 0)
        !           499:                return rc;
        !           500:
        !           501:        if ((rc = rtw_recall_eeprom(&sc->sc_regs, sc->sc_dev.dv_xname)) != 0)
        !           502:                ;
        !           503:
        !           504:        config1 = RTW_READ8(&sc->sc_regs, RTW_CONFIG1);
        !           505:        RTW_WRITE8(&sc->sc_regs, RTW_CONFIG1, config1 & ~RTW_CONFIG1_PMEN);
        !           506:        /* TBD turn off maximum power saving? */
        !           507:
        !           508:        return 0;
        !           509: }
        !           510:
        !           511: int
        !           512: rtw_txdesc_dmamaps_create(bus_dma_tag_t dmat, struct rtw_txsoft *descs,
        !           513:     u_int ndescs)
        !           514: {
        !           515:        int i, rc = 0;
        !           516:        for (i = 0; i < ndescs; i++) {
        !           517:                rc = bus_dmamap_create(dmat, MCLBYTES, RTW_MAXPKTSEGS, MCLBYTES,
        !           518:                    0, 0, &descs[i].ts_dmamap);
        !           519:                if (rc != 0)
        !           520:                        break;
        !           521:        }
        !           522:        return rc;
        !           523: }
        !           524:
        !           525: int
        !           526: rtw_rxdesc_dmamaps_create(bus_dma_tag_t dmat, struct rtw_rxsoft *descs,
        !           527:     u_int ndescs)
        !           528: {
        !           529:        int i, rc = 0;
        !           530:        for (i = 0; i < ndescs; i++) {
        !           531:                rc = bus_dmamap_create(dmat, MCLBYTES, 1, MCLBYTES, 0, 0,
        !           532:                    &descs[i].rs_dmamap);
        !           533:                if (rc != 0)
        !           534:                        break;
        !           535:        }
        !           536:        return rc;
        !           537: }
        !           538:
        !           539: void
        !           540: rtw_rxdesc_dmamaps_destroy(bus_dma_tag_t dmat, struct rtw_rxsoft *descs,
        !           541:     u_int ndescs)
        !           542: {
        !           543:        int i;
        !           544:        for (i = 0; i < ndescs; i++) {
        !           545:                if (descs[i].rs_dmamap != NULL)
        !           546:                        bus_dmamap_destroy(dmat, descs[i].rs_dmamap);
        !           547:        }
        !           548: }
        !           549:
        !           550: void
        !           551: rtw_txdesc_dmamaps_destroy(bus_dma_tag_t dmat, struct rtw_txsoft *descs,
        !           552:     u_int ndescs)
        !           553: {
        !           554:        int i;
        !           555:        for (i = 0; i < ndescs; i++) {
        !           556:                if (descs[i].ts_dmamap != NULL)
        !           557:                        bus_dmamap_destroy(dmat, descs[i].ts_dmamap);
        !           558:        }
        !           559: }
        !           560:
        !           561: int
        !           562: rtw_srom_parse(struct rtw_softc *sc)
        !           563: {
        !           564:        int i;
        !           565:        struct rtw_srom *sr = &sc->sc_srom;
        !           566:        u_int32_t *flags = &sc->sc_flags;
        !           567:        u_int8_t *cs_threshold = &sc->sc_csthr;
        !           568:        int *rfchipid = &sc->sc_rfchipid;
        !           569:        u_int32_t *rcr = &sc->sc_rcr;
        !           570:        enum rtw_locale *locale = &sc->sc_locale;
        !           571:        u_int16_t version;
        !           572:        u_int8_t mac[IEEE80211_ADDR_LEN];
        !           573:
        !           574:        *flags &= ~(RTW_F_DIGPHY|RTW_F_DFLANTB|RTW_F_ANTDIV);
        !           575:        *rcr &= ~(RTW_RCR_ENCS1 | RTW_RCR_ENCS2);
        !           576:
        !           577:        version = RTW_SR_GET16(sr, RTW_SR_VERSION);
        !           578:        RTW_DPRINTF(RTW_DEBUG_ATTACH,
        !           579:            ("%s: SROM %d.%d\n", sc->sc_dev.dv_xname, version >> 8,
        !           580:            version & 0xff));
        !           581:
        !           582:        if (version <= 0x0101) {
        !           583:                printf(" is not understood, limping along with defaults ");
        !           584:                *flags |= (RTW_F_DIGPHY|RTW_F_ANTDIV);
        !           585:                *cs_threshold = RTW_SR_ENERGYDETTHR_DEFAULT;
        !           586:                *rcr |= RTW_RCR_ENCS1;
        !           587:                *rfchipid = RTW_RFCHIPID_PHILIPS;
        !           588:                return 0;
        !           589:        }
        !           590:
        !           591:        for (i = 0; i < IEEE80211_ADDR_LEN; i++)
        !           592:                mac[i] = RTW_SR_GET(sr, RTW_SR_MAC + i);
        !           593:
        !           594:        RTW_DPRINTF(RTW_DEBUG_ATTACH,
        !           595:            ("%s: EEPROM MAC %s\n", sc->sc_dev.dv_xname, ether_sprintf(mac)));
        !           596:
        !           597:        *cs_threshold = RTW_SR_GET(sr, RTW_SR_ENERGYDETTHR);
        !           598:
        !           599:        if ((RTW_SR_GET(sr, RTW_SR_CONFIG2) & RTW8180_CONFIG2_ANT) != 0)
        !           600:                *flags |= RTW_F_ANTDIV;
        !           601:
        !           602:        /* Note well: the sense of the RTW_SR_RFPARM_DIGPHY bit seems
        !           603:         * to be reversed.
        !           604:         */
        !           605:        if ((RTW_SR_GET(sr, RTW_SR_RFPARM) & RTW_SR_RFPARM_DIGPHY) == 0)
        !           606:                *flags |= RTW_F_DIGPHY;
        !           607:        if ((RTW_SR_GET(sr, RTW_SR_RFPARM) & RTW_SR_RFPARM_DFLANTB) != 0)
        !           608:                *flags |= RTW_F_DFLANTB;
        !           609:
        !           610:        *rcr |= LSHIFT(MASK_AND_RSHIFT(RTW_SR_GET(sr, RTW_SR_RFPARM),
        !           611:            RTW_SR_RFPARM_CS_MASK), RTW_RCR_ENCS1);
        !           612:
        !           613:        *rfchipid = RTW_SR_GET(sr, RTW_SR_RFCHIPID);
        !           614:
        !           615:        if (sc->sc_flags & RTW_F_RTL8185) {
        !           616:                *locale = RTW_LOCALE_UNKNOWN;
        !           617:                return (0);
        !           618:        }
        !           619:
        !           620:        switch (RTW_SR_GET(sr, RTW_SR_CONFIG0) & RTW8180_CONFIG0_GL_MASK) {
        !           621:        case RTW8180_CONFIG0_GL_USA:
        !           622:                *locale = RTW_LOCALE_USA;
        !           623:                break;
        !           624:        case RTW8180_CONFIG0_GL_EUROPE:
        !           625:                *locale = RTW_LOCALE_EUROPE;
        !           626:                break;
        !           627:        case RTW8180_CONFIG0_GL_JAPAN:
        !           628:        case RTW8180_CONFIG0_GL_JAPAN2:
        !           629:                *locale = RTW_LOCALE_JAPAN;
        !           630:                break;
        !           631:        default:
        !           632:                *locale = RTW_LOCALE_UNKNOWN;
        !           633:                break;
        !           634:        }
        !           635:        return 0;
        !           636: }
        !           637:
        !           638: /* Returns -1 on failure. */
        !           639: int
        !           640: rtw_srom_read(struct rtw_regs *regs, u_int32_t flags, struct rtw_srom *sr,
        !           641:     const char *dvname)
        !           642: {
        !           643:        int rc;
        !           644:        struct seeprom_descriptor sd;
        !           645:        u_int8_t ecr;
        !           646:
        !           647:        bzero(&sd, sizeof(sd));
        !           648:
        !           649:        ecr = RTW_READ8(regs, RTW_9346CR);
        !           650:
        !           651:        if ((flags & RTW_F_9356SROM) != 0) {
        !           652:                RTW_DPRINTF(RTW_DEBUG_ATTACH, ("%s: 93c56 SROM\n", dvname));
        !           653:                sr->sr_size = 256;
        !           654:                sd.sd_chip = C56_66;
        !           655:        } else {
        !           656:                RTW_DPRINTF(RTW_DEBUG_ATTACH, ("%s: 93c46 SROM\n", dvname));
        !           657:                sr->sr_size = 128;
        !           658:                sd.sd_chip = C46;
        !           659:        }
        !           660:
        !           661:        ecr &= ~(RTW_9346CR_EEDI | RTW_9346CR_EEDO | RTW_9346CR_EESK |
        !           662:            RTW_9346CR_EEM_MASK | RTW_9346CR_EECS);
        !           663:        ecr |= RTW_9346CR_EEM_PROGRAM;
        !           664:
        !           665:        RTW_WRITE8(regs, RTW_9346CR, ecr);
        !           666:
        !           667:        sr->sr_content = malloc(sr->sr_size, M_DEVBUF, M_NOWAIT);
        !           668:
        !           669:        if (sr->sr_content == NULL) {
        !           670:                printf("%s: unable to allocate SROM buffer\n", dvname);
        !           671:                return ENOMEM;
        !           672:        }
        !           673:
        !           674:        bzero(sr->sr_content, sr->sr_size);
        !           675:
        !           676:        /* RTL8180 has a single 8-bit register for controlling the
        !           677:         * 93cx6 SROM.  There is no "ready" bit. The RTL8180
        !           678:         * input/output sense is the reverse of read_seeprom's.
        !           679:         */
        !           680:        sd.sd_tag = regs->r_bt;
        !           681:        sd.sd_bsh = regs->r_bh;
        !           682:        sd.sd_regsize = 1;
        !           683:        sd.sd_control_offset = RTW_9346CR;
        !           684:        sd.sd_status_offset = RTW_9346CR;
        !           685:        sd.sd_dataout_offset = RTW_9346CR;
        !           686:        sd.sd_CK = RTW_9346CR_EESK;
        !           687:        sd.sd_CS = RTW_9346CR_EECS;
        !           688:        sd.sd_DI = RTW_9346CR_EEDO;
        !           689:        sd.sd_DO = RTW_9346CR_EEDI;
        !           690:        /* make read_seeprom enter EEPROM read/write mode */
        !           691:        sd.sd_MS = ecr;
        !           692:        sd.sd_RDY = 0;
        !           693:
        !           694:        /* TBD bus barriers */
        !           695:        if (!read_seeprom(&sd, sr->sr_content, 0, sr->sr_size/2)) {
        !           696:                printf("\n%s: could not read SROM\n", dvname);
        !           697:                free(sr->sr_content, M_DEVBUF);
        !           698:                sr->sr_content = NULL;
        !           699:                return -1;      /* XXX */
        !           700:        }
        !           701:
        !           702:        /* end EEPROM read/write mode */
        !           703:        RTW_WRITE8(regs, RTW_9346CR,
        !           704:            (ecr & ~RTW_9346CR_EEM_MASK) | RTW_9346CR_EEM_NORMAL);
        !           705:        RTW_WBRW(regs, RTW_9346CR, RTW_9346CR);
        !           706:
        !           707:        if ((rc = rtw_recall_eeprom(regs, dvname)) != 0)
        !           708:                return rc;
        !           709:
        !           710: #ifdef RTW_DEBUG
        !           711:        {
        !           712:                int i;
        !           713:                RTW_DPRINTF(RTW_DEBUG_ATTACH,
        !           714:                    ("\n%s: serial ROM:\n\t", dvname));
        !           715:                for (i = 0; i < sr->sr_size/2; i++) {
        !           716:                        if (((i % 8) == 0) && (i != 0))
        !           717:                                RTW_DPRINTF(RTW_DEBUG_ATTACH, ("\n\t"));
        !           718:                        RTW_DPRINTF(RTW_DEBUG_ATTACH,
        !           719:                            (" %04x", sr->sr_content[i]));
        !           720:                }
        !           721:                RTW_DPRINTF(RTW_DEBUG_ATTACH, ("\n"));
        !           722:        }
        !           723: #endif /* RTW_DEBUG */
        !           724:        return 0;
        !           725: }
        !           726:
        !           727: void
        !           728: rtw_set_rfprog(struct rtw_regs *regs, int rfchipid,
        !           729:     const char *dvname)
        !           730: {
        !           731:        u_int8_t cfg4;
        !           732:        const char *method;
        !           733:
        !           734:        cfg4 = RTW_READ8(regs, RTW_CONFIG4) & ~RTW_CONFIG4_RFTYPE_MASK;
        !           735:
        !           736:        switch (rfchipid) {
        !           737:        default:
        !           738:                cfg4 |= LSHIFT(rtw_rfprog_fallback, RTW_CONFIG4_RFTYPE_MASK);
        !           739:                method = "fallback";
        !           740:                break;
        !           741:        case RTW_RFCHIPID_INTERSIL:
        !           742:                cfg4 |= RTW_CONFIG4_RFTYPE_INTERSIL;
        !           743:                method = "Intersil";
        !           744:                break;
        !           745:        case RTW_RFCHIPID_PHILIPS:
        !           746:                cfg4 |= RTW_CONFIG4_RFTYPE_PHILIPS;
        !           747:                method = "Philips";
        !           748:                break;
        !           749:        case RTW_RFCHIPID_RFMD2948:
        !           750:                cfg4 |= RTW_CONFIG4_RFTYPE_RFMD;
        !           751:                method = "RFMD";
        !           752:                break;
        !           753:        }
        !           754:
        !           755:        RTW_WRITE8(regs, RTW_CONFIG4, cfg4);
        !           756:
        !           757:        RTW_WBR(regs, RTW_CONFIG4, RTW_CONFIG4);
        !           758:
        !           759:        RTW_DPRINTF(RTW_DEBUG_INIT,
        !           760:            ("%s: %s RF programming method, %#02x\n", dvname, method,
        !           761:            RTW_READ8(regs, RTW_CONFIG4)));
        !           762: }
        !           763:
        !           764: void
        !           765: rtw_init_channels(enum rtw_locale locale,
        !           766:     struct ieee80211_channel (*chans)[IEEE80211_CHAN_MAX+1],
        !           767:     const char *dvname)
        !           768: {
        !           769:        int i;
        !           770:        const char *name = NULL;
        !           771: #define ADD_CHANNEL(_chans, _chan) do {                        \
        !           772:        (*_chans)[_chan].ic_flags = IEEE80211_CHAN_B;           \
        !           773:        (*_chans)[_chan].ic_freq =                              \
        !           774:            ieee80211_ieee2mhz(_chan, (*_chans)[_chan].ic_flags);\
        !           775: } while (0)
        !           776:
        !           777:        switch (locale) {
        !           778:        case RTW_LOCALE_USA:    /* 1-11 */
        !           779:                name = "USA";
        !           780:                for (i = 1; i <= 11; i++)
        !           781:                        ADD_CHANNEL(chans, i);
        !           782:                break;
        !           783:        case RTW_LOCALE_JAPAN:  /* 1-14 */
        !           784:                name = "Japan";
        !           785:                ADD_CHANNEL(chans, 14);
        !           786:                for (i = 1; i <= 14; i++)
        !           787:                        ADD_CHANNEL(chans, i);
        !           788:                break;
        !           789:        case RTW_LOCALE_EUROPE: /* 1-13 */
        !           790:                name = "Europe";
        !           791:                for (i = 1; i <= 13; i++)
        !           792:                        ADD_CHANNEL(chans, i);
        !           793:                break;
        !           794:        default:                        /* 10-11 allowed by most countries */
        !           795:                name = "<unknown>";
        !           796:                for (i = 10; i <= 11; i++)
        !           797:                        ADD_CHANNEL(chans, i);
        !           798:                break;
        !           799:        }
        !           800:        RTW_DPRINTF(RTW_DEBUG_ATTACH, ("%s: Geographic Location %s\n",
        !           801:            dvname, name));
        !           802: #undef ADD_CHANNEL
        !           803: }
        !           804:
        !           805: void
        !           806: rtw_identify_country(struct rtw_regs *regs, enum rtw_locale *locale)
        !           807: {
        !           808:        u_int8_t cfg0 = RTW_READ8(regs, RTW_CONFIG0);
        !           809:
        !           810:        switch (cfg0 & RTW8180_CONFIG0_GL_MASK) {
        !           811:        case RTW8180_CONFIG0_GL_USA:
        !           812:                *locale = RTW_LOCALE_USA;
        !           813:                break;
        !           814:        case RTW8180_CONFIG0_GL_JAPAN:
        !           815:        case RTW8180_CONFIG0_GL_JAPAN2:
        !           816:                *locale = RTW_LOCALE_JAPAN;
        !           817:                break;
        !           818:        case RTW8180_CONFIG0_GL_EUROPE:
        !           819:                *locale = RTW_LOCALE_EUROPE;
        !           820:                break;
        !           821:        default:
        !           822:                *locale = RTW_LOCALE_UNKNOWN;
        !           823:                break;
        !           824:        }
        !           825: }
        !           826:
        !           827: int
        !           828: rtw_identify_sta(struct rtw_regs *regs, u_int8_t (*addr)[IEEE80211_ADDR_LEN],
        !           829:     const char *dvname)
        !           830: {
        !           831:        static const u_int8_t empty_macaddr[IEEE80211_ADDR_LEN] = {
        !           832:                0x00, 0x00, 0x00, 0x00, 0x00, 0x00
        !           833:        };
        !           834:        u_int32_t idr0 = RTW_READ(regs, RTW_IDR0),
        !           835:            idr1 = RTW_READ(regs, RTW_IDR1);
        !           836:
        !           837:        (*addr)[0] = MASK_AND_RSHIFT(idr0, BITS(0,  7));
        !           838:        (*addr)[1] = MASK_AND_RSHIFT(idr0, BITS(8,  15));
        !           839:        (*addr)[2] = MASK_AND_RSHIFT(idr0, BITS(16, 23));
        !           840:        (*addr)[3] = MASK_AND_RSHIFT(idr0, BITS(24 ,31));
        !           841:
        !           842:        (*addr)[4] = MASK_AND_RSHIFT(idr1, BITS(0,  7));
        !           843:        (*addr)[5] = MASK_AND_RSHIFT(idr1, BITS(8, 15));
        !           844:
        !           845:        if (IEEE80211_ADDR_EQ(addr, empty_macaddr)) {
        !           846:                printf("\n%s: could not get mac address, attach failed\n",
        !           847:                    dvname);
        !           848:                return ENXIO;
        !           849:        }
        !           850:
        !           851:        printf("address %s\n", ether_sprintf(*addr));
        !           852:
        !           853:        return 0;
        !           854: }
        !           855:
        !           856: u_int8_t
        !           857: rtw_chan2txpower(struct rtw_srom *sr, struct ieee80211com *ic,
        !           858:     struct ieee80211_channel *chan)
        !           859: {
        !           860:        u_int idx = RTW_SR_TXPOWER1 + ieee80211_chan2ieee(ic, chan) - 1;
        !           861:        KASSERT2(idx >= RTW_SR_TXPOWER1 && idx <= RTW_SR_TXPOWER14,
        !           862:            ("%s: channel %d out of range", __func__,
        !           863:             idx - RTW_SR_TXPOWER1 + 1));
        !           864:        return RTW_SR_GET(sr, idx);
        !           865: }
        !           866:
        !           867: void
        !           868: rtw_txdesc_blk_init_all(struct rtw_txdesc_blk *tdb)
        !           869: {
        !           870:        int pri;
        !           871:        /* nfree: the number of free descriptors in each ring.
        !           872:         * The beacon ring is a special case: I do not let the
        !           873:         * driver use all of the descriptors on the beacon ring.
        !           874:         * The reasons are two-fold:
        !           875:         *
        !           876:         * (1) A BEACON descriptor's OWN bit is (apparently) not
        !           877:         * updated, so the driver cannot easily know if the descriptor
        !           878:         * belongs to it, or if it is racing the NIC.  If the NIC
        !           879:         * does not OWN every descriptor, then the driver can safely
        !           880:         * update the descriptors when RTW_TBDA points at tdb_next.
        !           881:         *
        !           882:         * (2) I hope that the NIC will process more than one BEACON
        !           883:         * descriptor in a single beacon interval, since that will
        !           884:         * enable multiple-BSS support.  Since the NIC does not
        !           885:         * clear the OWN bit, there is no natural place for it to
        !           886:         * stop processing BEACON desciptors.  Maybe it will *not*
        !           887:         * stop processing them!  I do not want to chance the NIC
        !           888:         * looping around and around a saturated beacon ring, so
        !           889:         * I will leave one descriptor unOWNed at all times.
        !           890:         */
        !           891:        u_int nfree[RTW_NTXPRI] =
        !           892:            {RTW_NTXDESCLO, RTW_NTXDESCMD, RTW_NTXDESCHI,
        !           893:             RTW_NTXDESCBCN - 1};
        !           894:
        !           895:        for (pri = 0; pri < RTW_NTXPRI; pri++) {
        !           896:                tdb[pri].tdb_nfree = nfree[pri];
        !           897:                tdb[pri].tdb_next = 0;
        !           898:        }
        !           899: }
        !           900:
        !           901: int
        !           902: rtw_txsoft_blk_init(struct rtw_txsoft_blk *tsb)
        !           903: {
        !           904:        int i;
        !           905:        struct rtw_txsoft *ts;
        !           906:
        !           907:        SIMPLEQ_INIT(&tsb->tsb_dirtyq);
        !           908:        SIMPLEQ_INIT(&tsb->tsb_freeq);
        !           909:        for (i = 0; i < tsb->tsb_ndesc; i++) {
        !           910:                ts = &tsb->tsb_desc[i];
        !           911:                ts->ts_mbuf = NULL;
        !           912:                SIMPLEQ_INSERT_TAIL(&tsb->tsb_freeq, ts, ts_q);
        !           913:        }
        !           914:        tsb->tsb_tx_timer = 0;
        !           915:        return 0;
        !           916: }
        !           917:
        !           918: void
        !           919: rtw_txsoft_blk_init_all(struct rtw_txsoft_blk *tsb)
        !           920: {
        !           921:        int pri;
        !           922:        for (pri = 0; pri < RTW_NTXPRI; pri++)
        !           923:                rtw_txsoft_blk_init(&tsb[pri]);
        !           924: }
        !           925:
        !           926: void
        !           927: rtw_rxdescs_sync(struct rtw_rxdesc_blk *rdb, int desc0, int nsync, int ops)
        !           928: {
        !           929:        KASSERT(nsync <= rdb->rdb_ndesc);
        !           930:        /* sync to end of ring */
        !           931:        if (desc0 + nsync > rdb->rdb_ndesc) {
        !           932:                bus_dmamap_sync(rdb->rdb_dmat, rdb->rdb_dmamap,
        !           933:                    offsetof(struct rtw_descs, hd_rx[desc0]),
        !           934:                    sizeof(struct rtw_rxdesc) * (rdb->rdb_ndesc - desc0), ops);
        !           935:                nsync -= (rdb->rdb_ndesc - desc0);
        !           936:                desc0 = 0;
        !           937:        }
        !           938:
        !           939:        KASSERT(desc0 < rdb->rdb_ndesc);
        !           940:        KASSERT(nsync <= rdb->rdb_ndesc);
        !           941:        KASSERT(desc0 + nsync <= rdb->rdb_ndesc);
        !           942:
        !           943:        /* sync what remains */
        !           944:        bus_dmamap_sync(rdb->rdb_dmat, rdb->rdb_dmamap,
        !           945:            offsetof(struct rtw_descs, hd_rx[desc0]),
        !           946:            sizeof(struct rtw_rxdesc) * nsync, ops);
        !           947: }
        !           948:
        !           949: void
        !           950: rtw_txdescs_sync(struct rtw_txdesc_blk *tdb, u_int desc0, u_int nsync, int ops)
        !           951: {
        !           952:        /* sync to end of ring */
        !           953:        if (desc0 + nsync > tdb->tdb_ndesc) {
        !           954:                bus_dmamap_sync(tdb->tdb_dmat, tdb->tdb_dmamap,
        !           955:                    tdb->tdb_ofs + sizeof(struct rtw_txdesc) * desc0,
        !           956:                    sizeof(struct rtw_txdesc) * (tdb->tdb_ndesc - desc0),
        !           957:                    ops);
        !           958:                nsync -= (tdb->tdb_ndesc - desc0);
        !           959:                desc0 = 0;
        !           960:        }
        !           961:
        !           962:        /* sync what remains */
        !           963:        bus_dmamap_sync(tdb->tdb_dmat, tdb->tdb_dmamap,
        !           964:            tdb->tdb_ofs + sizeof(struct rtw_txdesc) * desc0,
        !           965:            sizeof(struct rtw_txdesc) * nsync, ops);
        !           966: }
        !           967:
        !           968: void
        !           969: rtw_rxbufs_release(bus_dma_tag_t dmat, struct rtw_rxsoft *desc)
        !           970: {
        !           971:        int i;
        !           972:        struct rtw_rxsoft *rs;
        !           973:
        !           974:        for (i = 0; i < RTW_RXQLEN; i++) {
        !           975:                rs = &desc[i];
        !           976:                if (rs->rs_mbuf == NULL)
        !           977:                        continue;
        !           978:                bus_dmamap_sync(dmat, rs->rs_dmamap, 0,
        !           979:                    rs->rs_dmamap->dm_mapsize, BUS_DMASYNC_POSTREAD);
        !           980:                bus_dmamap_unload(dmat, rs->rs_dmamap);
        !           981:                m_freem(rs->rs_mbuf);
        !           982:                rs->rs_mbuf = NULL;
        !           983:        }
        !           984: }
        !           985:
        !           986: int
        !           987: rtw_rxsoft_alloc(bus_dma_tag_t dmat, struct rtw_rxsoft *rs)
        !           988: {
        !           989:        int rc;
        !           990:        struct mbuf *m;
        !           991:
        !           992:        MGETHDR(m, M_DONTWAIT, MT_DATA);
        !           993:        if (m == NULL)
        !           994:                return ENOBUFS;
        !           995:
        !           996:        MCLGET(m, M_DONTWAIT);
        !           997:        if ((m->m_flags & M_EXT) == 0) {
        !           998:                m_freem(m);
        !           999:                return ENOBUFS;
        !          1000:        }
        !          1001:
        !          1002:        m->m_pkthdr.len = m->m_len = m->m_ext.ext_size;
        !          1003:
        !          1004:        if (rs->rs_mbuf != NULL)
        !          1005:                bus_dmamap_unload(dmat, rs->rs_dmamap);
        !          1006:
        !          1007:        rs->rs_mbuf = NULL;
        !          1008:
        !          1009:        rc = bus_dmamap_load_mbuf(dmat, rs->rs_dmamap, m, BUS_DMA_NOWAIT);
        !          1010:        if (rc != 0) {
        !          1011:                m_freem(m);
        !          1012:                return -1;
        !          1013:        }
        !          1014:
        !          1015:        rs->rs_mbuf = m;
        !          1016:
        !          1017:        return 0;
        !          1018: }
        !          1019:
        !          1020: int
        !          1021: rtw_rxsoft_init_all(bus_dma_tag_t dmat, struct rtw_rxsoft *desc,
        !          1022:     int *ndesc, const char *dvname)
        !          1023: {
        !          1024:        int i, rc = 0;
        !          1025:        struct rtw_rxsoft *rs;
        !          1026:
        !          1027:        for (i = 0; i < RTW_RXQLEN; i++) {
        !          1028:                rs = &desc[i];
        !          1029:                /* we're in rtw_init, so there should be no mbufs allocated */
        !          1030:                KASSERT(rs->rs_mbuf == NULL);
        !          1031: #ifdef RTW_DEBUG
        !          1032:                if (i == rtw_rxbufs_limit) {
        !          1033:                        printf("%s: TEST hit %d-buffer limit\n", dvname, i);
        !          1034:                        rc = ENOBUFS;
        !          1035:                        break;
        !          1036:                }
        !          1037: #endif /* RTW_DEBUG */
        !          1038:                if ((rc = rtw_rxsoft_alloc(dmat, rs)) != 0) {
        !          1039:                        printf("%s: rtw_rxsoft_alloc failed, %d buffers, "
        !          1040:                            "rc %d\n", dvname, i, rc);
        !          1041:                        break;
        !          1042:                }
        !          1043:        }
        !          1044:        *ndesc = i;
        !          1045:        return rc;
        !          1046: }
        !          1047:
        !          1048: void
        !          1049: rtw_rxdesc_init(struct rtw_rxdesc_blk *rdb, struct rtw_rxsoft *rs,
        !          1050:     int idx, int kick)
        !          1051: {
        !          1052:        int is_last = (idx == rdb->rdb_ndesc - 1);
        !          1053:        uint32_t ctl, octl, obuf;
        !          1054:        struct rtw_rxdesc *rd = &rdb->rdb_desc[idx];
        !          1055:
        !          1056:        obuf = rd->rd_buf;
        !          1057:        rd->rd_buf = htole32(rs->rs_dmamap->dm_segs[0].ds_addr);
        !          1058:
        !          1059:        ctl = LSHIFT(rs->rs_mbuf->m_len, RTW_RXCTL_LENGTH_MASK) |
        !          1060:            RTW_RXCTL_OWN | RTW_RXCTL_FS | RTW_RXCTL_LS;
        !          1061:
        !          1062:        if (is_last)
        !          1063:                ctl |= RTW_RXCTL_EOR;
        !          1064:
        !          1065:        octl = rd->rd_ctl;
        !          1066:        rd->rd_ctl = htole32(ctl);
        !          1067:
        !          1068:        RTW_DPRINTF(kick ? (RTW_DEBUG_RECV_DESC | RTW_DEBUG_IO_KICK)
        !          1069:            : RTW_DEBUG_RECV_DESC,
        !          1070:            ("%s: rd %p buf %08x -> %08x ctl %08x -> %08x\n", __func__, rd,
        !          1071:            letoh32(obuf), letoh32(rd->rd_buf), letoh32(octl),
        !          1072:            letoh32(rd->rd_ctl)));
        !          1073:
        !          1074:        /* sync the mbuf */
        !          1075:        bus_dmamap_sync(rdb->rdb_dmat, rs->rs_dmamap, 0,
        !          1076:            rs->rs_dmamap->dm_mapsize, BUS_DMASYNC_PREREAD);
        !          1077:
        !          1078:        /* sync the descriptor */
        !          1079:        bus_dmamap_sync(rdb->rdb_dmat, rdb->rdb_dmamap,
        !          1080:            RTW_DESC_OFFSET(hd_rx, idx), sizeof(struct rtw_rxdesc),
        !          1081:            BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE);
        !          1082: }
        !          1083:
        !          1084: void
        !          1085: rtw_rxdesc_init_all(struct rtw_rxdesc_blk *rdb, struct rtw_rxsoft *ctl,
        !          1086:     int kick)
        !          1087: {
        !          1088:        int i;
        !          1089:        struct rtw_rxdesc *rd;
        !          1090:        struct rtw_rxsoft *rs;
        !          1091:
        !          1092:        for (i = 0; i < rdb->rdb_ndesc; i++) {
        !          1093:                rd = &rdb->rdb_desc[i];
        !          1094:                rs = &ctl[i];
        !          1095:                rtw_rxdesc_init(rdb, rs, i, kick);
        !          1096:        }
        !          1097: }
        !          1098:
        !          1099: void
        !          1100: rtw_io_enable(struct rtw_regs *regs, u_int8_t flags, int enable)
        !          1101: {
        !          1102:        u_int8_t cr;
        !          1103:
        !          1104:        RTW_DPRINTF(RTW_DEBUG_IOSTATE, ("%s: %s 0x%02x\n", __func__,
        !          1105:            enable ? "enable" : "disable", flags));
        !          1106:
        !          1107:        cr = RTW_READ8(regs, RTW_CR);
        !          1108:
        !          1109:        /* XXX reference source does not enable MULRW */
        !          1110: #if 0
        !          1111:        /* enable PCI Read/Write Multiple */
        !          1112:        cr |= RTW_CR_MULRW;
        !          1113: #endif
        !          1114:
        !          1115:        RTW_RBW(regs, RTW_CR, RTW_CR);  /* XXX paranoia? */
        !          1116:        if (enable)
        !          1117:                cr |= flags;
        !          1118:        else
        !          1119:                cr &= ~flags;
        !          1120:        RTW_WRITE8(regs, RTW_CR, cr);
        !          1121:        RTW_SYNC(regs, RTW_CR, RTW_CR);
        !          1122: }
        !          1123:
        !          1124: void
        !          1125: rtw_intr_rx(struct rtw_softc *sc, u_int16_t isr)
        !          1126: {
        !          1127: #define        IS_BEACON(__fc0)                                                \
        !          1128:     ((__fc0 & (IEEE80211_FC0_TYPE_MASK | IEEE80211_FC0_SUBTYPE_MASK)) ==\
        !          1129:      (IEEE80211_FC0_TYPE_MGT | IEEE80211_FC0_SUBTYPE_BEACON))
        !          1130:
        !          1131:        static const int ratetbl[4] = {2, 4, 11, 22};   /* convert rates:
        !          1132:                                                         * hardware -> net80211
        !          1133:                                                         */
        !          1134:        u_int next, nproc = 0;
        !          1135:        int hwrate, len, rate, rssi, sq;
        !          1136:        u_int32_t hrssi, hstat, htsfth, htsftl;
        !          1137:        struct rtw_rxdesc *rd;
        !          1138:        struct rtw_rxsoft *rs;
        !          1139:        struct rtw_rxdesc_blk *rdb;
        !          1140:        struct mbuf *m;
        !          1141:
        !          1142:        struct ieee80211_node *ni;
        !          1143:        struct ieee80211_frame *wh;
        !          1144:
        !          1145:        rdb = &sc->sc_rxdesc_blk;
        !          1146:
        !          1147:        KASSERT(rdb->rdb_next < rdb->rdb_ndesc);
        !          1148:
        !          1149:        for (next = rdb->rdb_next; ; next = (next + 1) % rdb->rdb_ndesc) {
        !          1150:                rtw_rxdescs_sync(rdb, next, 1,
        !          1151:                    BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE);
        !          1152:                rd = &rdb->rdb_desc[next];
        !          1153:                rs = &sc->sc_rxsoft[next];
        !          1154:
        !          1155:                hstat = letoh32(rd->rd_stat);
        !          1156:                hrssi = letoh32(rd->rd_rssi);
        !          1157:                htsfth = letoh32(rd->rd_tsfth);
        !          1158:                htsftl = letoh32(rd->rd_tsftl);
        !          1159:
        !          1160:                RTW_DPRINTF(RTW_DEBUG_RECV_DESC,
        !          1161:                    ("%s: rxdesc[%d] hstat %08x hrssi %08x htsft %08x%08x\n",
        !          1162:                    __func__, next, hstat, hrssi, htsfth, htsftl));
        !          1163:
        !          1164:                ++nproc;
        !          1165:
        !          1166:                /* still belongs to NIC */
        !          1167:                if ((hstat & RTW_RXSTAT_OWN) != 0) {
        !          1168:                        if (nproc > 1)
        !          1169:                                break;
        !          1170:
        !          1171:                        /* sometimes the NIC skips to the 0th descriptor */
        !          1172:                        rtw_rxdescs_sync(rdb, 0, 1,
        !          1173:                            BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE);
        !          1174:                        rd = &rdb->rdb_desc[0];
        !          1175:                        if ((rd->rd_stat & htole32(RTW_RXSTAT_OWN)) != 0)
        !          1176:                                break;
        !          1177:                        RTW_DPRINTF(RTW_DEBUG_BUGS,
        !          1178:                            ("%s: NIC skipped from rxdesc[%u] to rxdesc[0]\n",
        !          1179:                             sc->sc_dev.dv_xname, next));
        !          1180:                        next = rdb->rdb_ndesc - 1;
        !          1181:                        continue;
        !          1182:                }
        !          1183:
        !          1184: #ifdef RTW_DEBUG
        !          1185: #define PRINTSTAT(flag) do { \
        !          1186:        if ((hstat & flag) != 0) { \
        !          1187:                printf("%s" #flag, delim); \
        !          1188:                delim = ","; \
        !          1189:        } \
        !          1190: } while (0)
        !          1191:                if ((rtw_debug & RTW_DEBUG_RECV_DESC) != 0) {
        !          1192:                        const char *delim = "<";
        !          1193:                        printf("%s: ", sc->sc_dev.dv_xname);
        !          1194:                        if ((hstat & RTW_RXSTAT_DEBUG) != 0) {
        !          1195:                                printf("status %08x", hstat);
        !          1196:                                PRINTSTAT(RTW_RXSTAT_SPLCP);
        !          1197:                                PRINTSTAT(RTW_RXSTAT_MAR);
        !          1198:                                PRINTSTAT(RTW_RXSTAT_PAR);
        !          1199:                                PRINTSTAT(RTW_RXSTAT_BAR);
        !          1200:                                PRINTSTAT(RTW_RXSTAT_PWRMGT);
        !          1201:                                PRINTSTAT(RTW_RXSTAT_CRC32);
        !          1202:                                PRINTSTAT(RTW_RXSTAT_ICV);
        !          1203:                                printf(">, ");
        !          1204:                        }
        !          1205:                }
        !          1206: #undef PRINTSTAT
        !          1207: #endif /* RTW_DEBUG */
        !          1208:
        !          1209:                if ((hstat & RTW_RXSTAT_IOERROR) != 0) {
        !          1210:                        printf("%s: DMA error/FIFO overflow %08x, "
        !          1211:                            "rx descriptor %d\n", sc->sc_dev.dv_xname,
        !          1212:                            hstat & RTW_RXSTAT_IOERROR, next);
        !          1213:                        sc->sc_if.if_ierrors++;
        !          1214:                        goto next;
        !          1215:                }
        !          1216:
        !          1217:                len = MASK_AND_RSHIFT(hstat, RTW_RXSTAT_LENGTH_MASK);
        !          1218:                if (len < IEEE80211_MIN_LEN) {
        !          1219:                        sc->sc_ic.ic_stats.is_rx_tooshort++;
        !          1220:                        goto next;
        !          1221:                }
        !          1222:
        !          1223:                /* CRC is included with the packet; trim it off. */
        !          1224:                len -= IEEE80211_CRC_LEN;
        !          1225:
        !          1226:                hwrate = MASK_AND_RSHIFT(hstat, RTW_RXSTAT_RATE_MASK);
        !          1227:                if (hwrate >= sizeof(ratetbl) / sizeof(ratetbl[0])) {
        !          1228:                        printf("%s: unknown rate #%d\n", sc->sc_dev.dv_xname,
        !          1229:                            MASK_AND_RSHIFT(hstat, RTW_RXSTAT_RATE_MASK));
        !          1230:                        sc->sc_if.if_ierrors++;
        !          1231:                        goto next;
        !          1232:                }
        !          1233:                rate = ratetbl[hwrate];
        !          1234:
        !          1235: #ifdef RTW_DEBUG
        !          1236:                RTW_DPRINTF(RTW_DEBUG_RECV_DESC,
        !          1237:                    ("rate %d.%d Mb/s, time %08x%08x\n", (rate * 5) / 10,
        !          1238:                     (rate * 5) % 10, htsfth, htsftl));
        !          1239: #endif /* RTW_DEBUG */
        !          1240:
        !          1241:                if ((hstat & RTW_RXSTAT_RES) != 0 &&
        !          1242:                    sc->sc_ic.ic_opmode != IEEE80211_M_MONITOR)
        !          1243:                        goto next;
        !          1244:
        !          1245:                /* if bad flags, skip descriptor */
        !          1246:                if ((hstat & RTW_RXSTAT_ONESEG) != RTW_RXSTAT_ONESEG) {
        !          1247:                        printf("%s: too many rx segments\n",
        !          1248:                            sc->sc_dev.dv_xname);
        !          1249:                        goto next;
        !          1250:                }
        !          1251:
        !          1252:                bus_dmamap_sync(sc->sc_dmat, rs->rs_dmamap, 0,
        !          1253:                    rs->rs_dmamap->dm_mapsize, BUS_DMASYNC_POSTREAD);
        !          1254:
        !          1255:                m = rs->rs_mbuf;
        !          1256:
        !          1257:                /* if temporarily out of memory, re-use mbuf */
        !          1258:                switch (rtw_rxsoft_alloc(sc->sc_dmat, rs)) {
        !          1259:                case 0:
        !          1260:                        break;
        !          1261:                case ENOBUFS:
        !          1262:                        printf("%s: rtw_rxsoft_alloc(, %d) failed, "
        !          1263:                            "dropping this packet\n", sc->sc_dev.dv_xname,
        !          1264:                            next);
        !          1265:                        goto next;
        !          1266:                default:
        !          1267:                        /* XXX shorten rx ring, instead? */
        !          1268:                        panic("%s: could not load DMA map",
        !          1269:                            sc->sc_dev.dv_xname);
        !          1270:                }
        !          1271:
        !          1272:                if (sc->sc_rfchipid == RTW_RFCHIPID_PHILIPS)
        !          1273:                        rssi = MASK_AND_RSHIFT(hrssi, RTW_RXRSSI_RSSI);
        !          1274:                else {
        !          1275:                        rssi = MASK_AND_RSHIFT(hrssi, RTW_RXRSSI_IMR_RSSI);
        !          1276:                        /* TBD find out each front-end's LNA gain in the
        !          1277:                         * front-end's units
        !          1278:                         */
        !          1279:                        if ((hrssi & RTW_RXRSSI_IMR_LNA) == 0)
        !          1280:                                rssi |= 0x80;
        !          1281:                }
        !          1282:
        !          1283:                sq = MASK_AND_RSHIFT(hrssi, RTW_RXRSSI_SQ);
        !          1284:
        !          1285:                /*
        !          1286:                 * Note well: now we cannot recycle the rs_mbuf unless
        !          1287:                 * we restore its original length.
        !          1288:                 */
        !          1289:                m->m_pkthdr.rcvif = &sc->sc_if;
        !          1290:                m->m_pkthdr.len = m->m_len = len;
        !          1291:
        !          1292:                wh = mtod(m, struct ieee80211_frame *);
        !          1293:
        !          1294:                if (!IS_BEACON(wh->i_fc[0]))
        !          1295:                        sc->sc_led_state.ls_event |= RTW_LED_S_RX;
        !          1296:                /* TBD use _MAR, _BAR, _PAR flags as hints to _find_rxnode? */
        !          1297:                ni = ieee80211_find_rxnode(&sc->sc_ic, wh);
        !          1298:
        !          1299:                sc->sc_tsfth = htsfth;
        !          1300:
        !          1301: #ifdef RTW_DEBUG
        !          1302:                if ((sc->sc_if.if_flags & (IFF_DEBUG|IFF_LINK2)) ==
        !          1303:                    (IFF_DEBUG|IFF_LINK2)) {
        !          1304:                        ieee80211_dump_pkt(mtod(m, uint8_t *), m->m_pkthdr.len,
        !          1305:                            rate, rssi);
        !          1306:                }
        !          1307: #endif /* RTW_DEBUG */
        !          1308:
        !          1309: #if NBPFILTER > 0
        !          1310:                if (sc->sc_radiobpf != NULL) {
        !          1311:                        struct mbuf mb;
        !          1312:                        struct ieee80211com *ic = &sc->sc_ic;
        !          1313:                        struct rtw_rx_radiotap_header *rr = &sc->sc_rxtap;
        !          1314:
        !          1315:                        rr->rr_tsft =
        !          1316:                            htole64(((uint64_t)htsfth << 32) | htsftl);
        !          1317:
        !          1318:                        if ((hstat & RTW_RXSTAT_SPLCP) != 0)
        !          1319:                                rr->rr_flags = IEEE80211_RADIOTAP_F_SHORTPRE;
        !          1320:
        !          1321:                        rr->rr_flags = 0;
        !          1322:                        rr->rr_rate = rate;
        !          1323:                        rr->rr_chan_freq =
        !          1324:                            htole16(ic->ic_bss->ni_chan->ic_freq);
        !          1325:                        rr->rr_chan_flags =
        !          1326:                            htole16(ic->ic_bss->ni_chan->ic_flags);
        !          1327:                        rr->rr_antsignal = rssi;
        !          1328:                        rr->rr_barker_lock = htole16(sq);
        !          1329:
        !          1330:                        mb.m_data = (caddr_t)rr;
        !          1331:                        mb.m_len = sizeof(sc->sc_rxtapu);
        !          1332:                        mb.m_next = m;
        !          1333:                        mb.m_nextpkt = NULL;
        !          1334:                        mb.m_type = 0;
        !          1335:                        mb.m_flags = 0;
        !          1336:                        bpf_mtap(sc->sc_radiobpf, &mb, BPF_DIRECTION_IN);
        !          1337:                }
        !          1338: #endif /* NPBFILTER > 0 */
        !          1339:
        !          1340:                ieee80211_input(&sc->sc_if, m, ni, rssi, htsftl);
        !          1341:                ieee80211_release_node(&sc->sc_ic, ni);
        !          1342: next:
        !          1343:                rtw_rxdesc_init(rdb, rs, next, 0);
        !          1344:        }
        !          1345:        rdb->rdb_next = next;
        !          1346:
        !          1347:        KASSERT(rdb->rdb_next < rdb->rdb_ndesc);
        !          1348:
        !          1349:        /*
        !          1350:         * In HostAP mode, ieee80211_input() will enqueue packets in if_snd
        !          1351:         * without calling if_start().
        !          1352:         */
        !          1353:        if (!IFQ_IS_EMPTY(&sc->sc_if.if_snd) &&
        !          1354:            !(sc->sc_if.if_flags & IFF_OACTIVE))
        !          1355:                (*sc->sc_if.if_start)(&sc->sc_if);
        !          1356:
        !          1357:        return;
        !          1358: #undef IS_BEACON
        !          1359: }
        !          1360:
        !          1361: void
        !          1362: rtw_txsoft_release(bus_dma_tag_t dmat, struct ieee80211com *ic,
        !          1363:     struct rtw_txsoft *ts)
        !          1364: {
        !          1365:        struct mbuf *m;
        !          1366:        struct ieee80211_node *ni;
        !          1367:
        !          1368:        m = ts->ts_mbuf;
        !          1369:        ni = ts->ts_ni;
        !          1370:        KASSERT(m != NULL);
        !          1371:        KASSERT(ni != NULL);
        !          1372:        ts->ts_mbuf = NULL;
        !          1373:        ts->ts_ni = NULL;
        !          1374:
        !          1375:        bus_dmamap_sync(dmat, ts->ts_dmamap, 0, ts->ts_dmamap->dm_mapsize,
        !          1376:            BUS_DMASYNC_POSTWRITE);
        !          1377:        bus_dmamap_unload(dmat, ts->ts_dmamap);
        !          1378:        m_freem(m);
        !          1379:        ieee80211_release_node(ic, ni);
        !          1380: }
        !          1381:
        !          1382: void
        !          1383: rtw_txsofts_release(bus_dma_tag_t dmat, struct ieee80211com *ic,
        !          1384:     struct rtw_txsoft_blk *tsb)
        !          1385: {
        !          1386:        struct rtw_txsoft *ts;
        !          1387:
        !          1388:        while ((ts = SIMPLEQ_FIRST(&tsb->tsb_dirtyq)) != NULL) {
        !          1389:                rtw_txsoft_release(dmat, ic, ts);
        !          1390:                SIMPLEQ_REMOVE_HEAD(&tsb->tsb_dirtyq, ts_q);
        !          1391:                SIMPLEQ_INSERT_TAIL(&tsb->tsb_freeq, ts, ts_q);
        !          1392:        }
        !          1393:        tsb->tsb_tx_timer = 0;
        !          1394: }
        !          1395:
        !          1396: void
        !          1397: rtw_collect_txpkt(struct rtw_softc *sc, struct rtw_txdesc_blk *tdb,
        !          1398:     struct rtw_txsoft *ts, int ndesc)
        !          1399: {
        !          1400:        uint32_t hstat;
        !          1401:        int data_retry, rts_retry;
        !          1402:        struct rtw_txdesc *tdn;
        !          1403:        const char *condstring;
        !          1404:
        !          1405:        rtw_txsoft_release(sc->sc_dmat, &sc->sc_ic, ts);
        !          1406:
        !          1407:        tdb->tdb_nfree += ndesc;
        !          1408:
        !          1409:        tdn = &tdb->tdb_desc[ts->ts_last];
        !          1410:
        !          1411:        hstat = letoh32(tdn->td_stat);
        !          1412:        rts_retry = MASK_AND_RSHIFT(hstat, RTW_TXSTAT_RTSRETRY_MASK);
        !          1413:        data_retry = MASK_AND_RSHIFT(hstat, RTW_TXSTAT_DRC_MASK);
        !          1414:
        !          1415:        sc->sc_if.if_collisions += rts_retry + data_retry;
        !          1416:
        !          1417:        if ((hstat & RTW_TXSTAT_TOK) != 0)
        !          1418:                condstring = "ok";
        !          1419:        else {
        !          1420:                sc->sc_if.if_oerrors++;
        !          1421:                condstring = "error";
        !          1422:        }
        !          1423:
        !          1424:        DPRINTF(sc, RTW_DEBUG_XMIT_DESC,
        !          1425:            ("%s: ts %p txdesc[%d, %d] %s tries rts %u data %u\n",
        !          1426:            sc->sc_dev.dv_xname, ts, ts->ts_first, ts->ts_last,
        !          1427:            condstring, rts_retry, data_retry));
        !          1428: }
        !          1429:
        !          1430: void
        !          1431: rtw_reset_oactive(struct rtw_softc *sc)
        !          1432: {
        !          1433:        short oflags;
        !          1434:        int pri;
        !          1435:        struct rtw_txsoft_blk *tsb;
        !          1436:        struct rtw_txdesc_blk *tdb;
        !          1437:        oflags = sc->sc_if.if_flags;
        !          1438:        for (pri = 0; pri < RTW_NTXPRI; pri++) {
        !          1439:                tsb = &sc->sc_txsoft_blk[pri];
        !          1440:                tdb = &sc->sc_txdesc_blk[pri];
        !          1441:                if (!SIMPLEQ_EMPTY(&tsb->tsb_freeq) && tdb->tdb_nfree > 0)
        !          1442:                        sc->sc_if.if_flags &= ~IFF_OACTIVE;
        !          1443:        }
        !          1444:        if (oflags != sc->sc_if.if_flags) {
        !          1445:                DPRINTF(sc, RTW_DEBUG_OACTIVE,
        !          1446:                    ("%s: reset OACTIVE\n", __func__));
        !          1447:        }
        !          1448: }
        !          1449:
        !          1450: /* Collect transmitted packets. */
        !          1451: void
        !          1452: rtw_collect_txring(struct rtw_softc *sc, struct rtw_txsoft_blk *tsb,
        !          1453:     struct rtw_txdesc_blk *tdb, int force)
        !          1454: {
        !          1455:        int ndesc;
        !          1456:        struct rtw_txsoft *ts;
        !          1457:
        !          1458:        while ((ts = SIMPLEQ_FIRST(&tsb->tsb_dirtyq)) != NULL) {
        !          1459:                ndesc = 1 + ts->ts_last - ts->ts_first;
        !          1460:                if (ts->ts_last < ts->ts_first)
        !          1461:                        ndesc += tdb->tdb_ndesc;
        !          1462:
        !          1463:                KASSERT(ndesc > 0);
        !          1464:
        !          1465:                rtw_txdescs_sync(tdb, ts->ts_first, ndesc,
        !          1466:                    BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE);
        !          1467:
        !          1468:                if (force) {
        !          1469:                        int i;
        !          1470:                        for (i = ts->ts_first; ; i = RTW_NEXT_IDX(tdb, i)) {
        !          1471:                                tdb->tdb_desc[i].td_stat &=
        !          1472:                                    ~htole32(RTW_TXSTAT_OWN);
        !          1473:                                if (i == ts->ts_last)
        !          1474:                                        break;
        !          1475:                        }
        !          1476:                        rtw_txdescs_sync(tdb, ts->ts_first, ndesc,
        !          1477:                            BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE);
        !          1478:                } else if ((tdb->tdb_desc[ts->ts_last].td_stat &
        !          1479:                    htole32(RTW_TXSTAT_OWN)) != 0)
        !          1480:                        break;
        !          1481:
        !          1482:                rtw_collect_txpkt(sc, tdb, ts, ndesc);
        !          1483:                SIMPLEQ_REMOVE_HEAD(&tsb->tsb_dirtyq, ts_q);
        !          1484:                SIMPLEQ_INSERT_TAIL(&tsb->tsb_freeq, ts, ts_q);
        !          1485:        }
        !          1486:        /* no more pending transmissions, cancel watchdog */
        !          1487:        if (ts == NULL)
        !          1488:                tsb->tsb_tx_timer = 0;
        !          1489:        rtw_reset_oactive(sc);
        !          1490: }
        !          1491:
        !          1492: void
        !          1493: rtw_intr_tx(struct rtw_softc *sc, u_int16_t isr)
        !          1494: {
        !          1495:        int pri;
        !          1496:        struct rtw_txsoft_blk   *tsb;
        !          1497:        struct rtw_txdesc_blk   *tdb;
        !          1498:
        !          1499:        for (pri = 0; pri < RTW_NTXPRI; pri++) {
        !          1500:                tsb = &sc->sc_txsoft_blk[pri];
        !          1501:                tdb = &sc->sc_txdesc_blk[pri];
        !          1502:
        !          1503:                rtw_collect_txring(sc, tsb, tdb, 0);
        !          1504:
        !          1505:        }
        !          1506:
        !          1507:        if ((isr & RTW_INTR_TX) != 0)
        !          1508:                rtw_start(&sc->sc_if);
        !          1509: }
        !          1510:
        !          1511: void
        !          1512: rtw_intr_beacon(struct rtw_softc *sc, u_int16_t isr)
        !          1513: {
        !          1514:        u_int next;
        !          1515:        uint32_t tsfth, tsftl;
        !          1516:        struct ieee80211com *ic;
        !          1517:        struct rtw_txdesc_blk *tdb = &sc->sc_txdesc_blk[RTW_TXPRIBCN];
        !          1518:        struct rtw_txsoft_blk *tsb = &sc->sc_txsoft_blk[RTW_TXPRIBCN];
        !          1519:        struct mbuf *m;
        !          1520:
        !          1521:        tsfth = RTW_READ(&sc->sc_regs, RTW_TSFTRH);
        !          1522:        tsftl = RTW_READ(&sc->sc_regs, RTW_TSFTRL);
        !          1523:
        !          1524:        if ((isr & (RTW_INTR_TBDOK|RTW_INTR_TBDER)) != 0) {
        !          1525:                next = rtw_txring_next(&sc->sc_regs, tdb);
        !          1526:                RTW_DPRINTF(RTW_DEBUG_BEACON,
        !          1527:                    ("%s: beacon ring %sprocessed, isr = %#04hx"
        !          1528:                     ", next %u expected %u, %llu\n", __func__,
        !          1529:                     (next == tdb->tdb_next) ? "" : "un", isr, next,
        !          1530:                     tdb->tdb_next, (uint64_t)tsfth << 32 | tsftl));
        !          1531:                if ((RTW_READ8(&sc->sc_regs, RTW_TPPOLL) & RTW_TPPOLL_BQ) == 0){
        !          1532:                        rtw_collect_txring(sc, tsb, tdb, 1);
        !          1533:                        tdb->tdb_next = 0;
        !          1534:                }
        !          1535:        }
        !          1536:        /* Start beacon transmission. */
        !          1537:
        !          1538:        if ((isr & RTW_INTR_BCNINT) != 0 &&
        !          1539:            sc->sc_ic.ic_state == IEEE80211_S_RUN &&
        !          1540:            SIMPLEQ_EMPTY(&tsb->tsb_dirtyq)) {
        !          1541:                RTW_DPRINTF(RTW_DEBUG_BEACON,
        !          1542:                    ("%s: beacon prep. time, isr = %#04hx"
        !          1543:                     ", %16llu\n", __func__, isr,
        !          1544:                     (uint64_t)tsfth << 32 | tsftl));
        !          1545:                ic = &sc->sc_ic;
        !          1546:                if ((m = ieee80211_beacon_alloc(ic, ic->ic_bss)) != NULL) {
        !          1547:                        RTW_DPRINTF(RTW_DEBUG_BEACON,
        !          1548:                            ("%s: m %p len %u\n", __func__, m, m->m_len));
        !          1549:                }
        !          1550:
        !          1551:                if (m == NULL) {
        !          1552:                        printf("%s: could not allocate beacon\n",
        !          1553:                            sc->sc_dev.dv_xname);
        !          1554:                        return;
        !          1555:                }
        !          1556:                m->m_pkthdr.rcvif = (void *)ieee80211_ref_node(ic->ic_bss);
        !          1557:                IF_ENQUEUE(&sc->sc_beaconq, m);
        !          1558:                rtw_start(&sc->sc_if);
        !          1559:        }
        !          1560: }
        !          1561:
        !          1562: void
        !          1563: rtw_intr_atim(struct rtw_softc *sc)
        !          1564: {
        !          1565:        /* TBD */
        !          1566:        return;
        !          1567: }
        !          1568:
        !          1569: #ifdef RTW_DEBUG
        !          1570: void
        !          1571: rtw_dump_rings(struct rtw_softc *sc)
        !          1572: {
        !          1573:        struct rtw_txdesc_blk *tdb;
        !          1574:        struct rtw_rxdesc *rd;
        !          1575:        struct rtw_rxdesc_blk *rdb;
        !          1576:        int desc, pri;
        !          1577:
        !          1578:        if ((rtw_debug & RTW_DEBUG_IO_KICK) == 0)
        !          1579:                return;
        !          1580:
        !          1581:        for (pri = 0; pri < RTW_NTXPRI; pri++) {
        !          1582:                tdb = &sc->sc_txdesc_blk[pri];
        !          1583:                printf("%s: txpri %d ndesc %d nfree %d\n", __func__, pri,
        !          1584:                    tdb->tdb_ndesc, tdb->tdb_nfree);
        !          1585:                for (desc = 0; desc < tdb->tdb_ndesc; desc++)
        !          1586:                        rtw_print_txdesc(sc, ".", NULL, tdb, desc);
        !          1587:        }
        !          1588:
        !          1589:        rdb = &sc->sc_rxdesc_blk;
        !          1590:
        !          1591:        for (desc = 0; desc < RTW_RXQLEN; desc++) {
        !          1592:                rd = &rdb->rdb_desc[desc];
        !          1593:                printf("%s: %sctl %08x rsvd0/rssi %08x buf/tsftl %08x "
        !          1594:                    "rsvd1/tsfth %08x\n", __func__,
        !          1595:                    (desc >= rdb->rdb_ndesc) ? "UNUSED " : "",
        !          1596:                    letoh32(rd->rd_ctl), letoh32(rd->rd_rssi),
        !          1597:                    letoh32(rd->rd_buf), letoh32(rd->rd_tsfth));
        !          1598:        }
        !          1599: }
        !          1600: #endif /* RTW_DEBUG */
        !          1601:
        !          1602: void
        !          1603: rtw_hwring_setup(struct rtw_softc *sc)
        !          1604: {
        !          1605:        int pri;
        !          1606:        struct rtw_regs *regs = &sc->sc_regs;
        !          1607:        struct rtw_txdesc_blk *tdb;
        !          1608:
        !          1609:        sc->sc_txdesc_blk[RTW_TXPRILO].tdb_basereg = RTW_TLPDA;
        !          1610:        sc->sc_txdesc_blk[RTW_TXPRILO].tdb_base = RTW_RING_BASE(sc, hd_txlo);
        !          1611:        sc->sc_txdesc_blk[RTW_TXPRIMD].tdb_basereg = RTW_TNPDA;
        !          1612:        sc->sc_txdesc_blk[RTW_TXPRIMD].tdb_base = RTW_RING_BASE(sc, hd_txmd);
        !          1613:        sc->sc_txdesc_blk[RTW_TXPRIHI].tdb_basereg = RTW_THPDA;
        !          1614:        sc->sc_txdesc_blk[RTW_TXPRIHI].tdb_base = RTW_RING_BASE(sc, hd_txhi);
        !          1615:        sc->sc_txdesc_blk[RTW_TXPRIBCN].tdb_basereg = RTW_TBDA;
        !          1616:        sc->sc_txdesc_blk[RTW_TXPRIBCN].tdb_base = RTW_RING_BASE(sc, hd_bcn);
        !          1617:
        !          1618:        for (pri = 0; pri < RTW_NTXPRI; pri++) {
        !          1619:                tdb = &sc->sc_txdesc_blk[pri];
        !          1620:                RTW_WRITE(regs, tdb->tdb_basereg, tdb->tdb_base);
        !          1621:                RTW_DPRINTF(RTW_DEBUG_XMIT_DESC,
        !          1622:                    ("%s: reg[tdb->tdb_basereg] <- %lx\n", __func__,
        !          1623:                     (u_int *)tdb->tdb_base));
        !          1624:        }
        !          1625:
        !          1626:        RTW_WRITE(regs, RTW_RDSAR, RTW_RING_BASE(sc, hd_rx));
        !          1627:
        !          1628:        RTW_DPRINTF(RTW_DEBUG_RECV_DESC,
        !          1629:            ("%s: reg[RDSAR] <- %lx\n", __func__,
        !          1630:             (u_int *)RTW_RING_BASE(sc, hd_rx)));
        !          1631:
        !          1632:        RTW_SYNC(regs, RTW_TLPDA, RTW_RDSAR);
        !          1633: }
        !          1634:
        !          1635: int
        !          1636: rtw_swring_setup(struct rtw_softc *sc)
        !          1637: {
        !          1638:        int rc, pri;
        !          1639:        struct rtw_rxdesc_blk *rdb;
        !          1640:        struct rtw_txdesc_blk *tdb;
        !          1641:
        !          1642:        rtw_txdesc_blk_init_all(&sc->sc_txdesc_blk[0]);
        !          1643:
        !          1644:        rtw_txsoft_blk_init_all(&sc->sc_txsoft_blk[0]);
        !          1645:
        !          1646:        rdb = &sc->sc_rxdesc_blk;
        !          1647:        if ((rc = rtw_rxsoft_init_all(sc->sc_dmat, sc->sc_rxsoft,
        !          1648:            &rdb->rdb_ndesc, sc->sc_dev.dv_xname)) != 0 &&
        !          1649:            rdb->rdb_ndesc == 0) {
        !          1650:                printf("%s: could not allocate rx buffers\n",
        !          1651:                    sc->sc_dev.dv_xname);
        !          1652:                return rc;
        !          1653:        }
        !          1654:
        !          1655:        rdb = &sc->sc_rxdesc_blk;
        !          1656:        rtw_rxdescs_sync(rdb, 0, rdb->rdb_ndesc,
        !          1657:            BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE);
        !          1658:        rtw_rxdesc_init_all(rdb, sc->sc_rxsoft, 1);
        !          1659:        rdb->rdb_next = 0;
        !          1660:
        !          1661:        tdb = &sc->sc_txdesc_blk[0];
        !          1662:        for (pri = 0; pri < RTW_NTXPRI; pri++) {
        !          1663:                rtw_txdescs_sync(&tdb[pri], 0, tdb[pri].tdb_ndesc,
        !          1664:                    BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE);
        !          1665:        }
        !          1666:        return 0;
        !          1667: }
        !          1668:
        !          1669: void
        !          1670: rtw_txdesc_blk_init(struct rtw_txdesc_blk *tdb)
        !          1671: {
        !          1672:        int i;
        !          1673:
        !          1674:        bzero(tdb->tdb_desc, sizeof(tdb->tdb_desc[0]) * tdb->tdb_ndesc);
        !          1675:        for (i = 0; i < tdb->tdb_ndesc; i++)
        !          1676:                tdb->tdb_desc[i].td_next = htole32(RTW_NEXT_DESC(tdb, i));
        !          1677: }
        !          1678:
        !          1679: u_int
        !          1680: rtw_txring_next(struct rtw_regs *regs, struct rtw_txdesc_blk *tdb)
        !          1681: {
        !          1682:        return (letoh32(RTW_READ(regs, tdb->tdb_basereg)) - tdb->tdb_base) /
        !          1683:            sizeof(struct rtw_txdesc);
        !          1684: }
        !          1685:
        !          1686: void
        !          1687: rtw_txring_fixup(struct rtw_softc *sc)
        !          1688: {
        !          1689:        int pri;
        !          1690:        u_int next;
        !          1691:        struct rtw_txdesc_blk *tdb;
        !          1692:        struct rtw_regs *regs = &sc->sc_regs;
        !          1693:
        !          1694:        for (pri = 0; pri < RTW_NTXPRI; pri++) {
        !          1695:                tdb = &sc->sc_txdesc_blk[pri];
        !          1696:                next = rtw_txring_next(regs, tdb);
        !          1697:                if (tdb->tdb_next == next)
        !          1698:                        continue;
        !          1699:                RTW_DPRINTF(RTW_DEBUG_BUGS,
        !          1700:                    ("%s: tx-ring %d expected next %u, read %u\n", __func__,
        !          1701:                    pri, tdb->tdb_next, next));
        !          1702:                tdb->tdb_next = MIN(next, tdb->tdb_ndesc - 1);
        !          1703:        }
        !          1704: }
        !          1705:
        !          1706: void
        !          1707: rtw_rxring_fixup(struct rtw_softc *sc)
        !          1708: {
        !          1709:        u_int next;
        !          1710:        uint32_t rdsar;
        !          1711:        struct rtw_rxdesc_blk *rdb;
        !          1712:
        !          1713:        rdsar = letoh32(RTW_READ(&sc->sc_regs, RTW_RDSAR));
        !          1714:        next = (rdsar - RTW_RING_BASE(sc, hd_rx)) / sizeof(struct rtw_rxdesc);
        !          1715:
        !          1716:        rdb = &sc->sc_rxdesc_blk;
        !          1717:        if (rdb->rdb_next != next) {
        !          1718:                RTW_DPRINTF(RTW_DEBUG_BUGS,
        !          1719:                    ("%s: rx-ring expected next %u, read %u\n", __func__,
        !          1720:                    rdb->rdb_next, next));
        !          1721:                rdb->rdb_next = MIN(next, rdb->rdb_ndesc - 1);
        !          1722:        }
        !          1723: }
        !          1724:
        !          1725: void
        !          1726: rtw_txdescs_reset(struct rtw_softc *sc)
        !          1727: {
        !          1728:        int pri;
        !          1729:
        !          1730:        for (pri = 0; pri < RTW_NTXPRI; pri++) {
        !          1731:                rtw_collect_txring(sc, &sc->sc_txsoft_blk[pri],
        !          1732:                    &sc->sc_txdesc_blk[pri], 1);
        !          1733:        }
        !          1734: }
        !          1735:
        !          1736: void
        !          1737: rtw_intr_ioerror(struct rtw_softc *sc, u_int16_t isr)
        !          1738: {
        !          1739:        uint8_t cr = 0;
        !          1740:        int xmtr = 0, rcvr = 0;
        !          1741:        struct rtw_regs *regs = &sc->sc_regs;
        !          1742:
        !          1743:        if ((isr & RTW_INTR_TXFOVW) != 0) {
        !          1744:                RTW_DPRINTF(RTW_DEBUG_BUGS,
        !          1745:                    ("%s: tx fifo underflow\n", sc->sc_dev.dv_xname));
        !          1746:                rcvr = xmtr = 1;
        !          1747:                cr |= RTW_CR_TE | RTW_CR_RE;
        !          1748:        }
        !          1749:
        !          1750:        if ((isr & (RTW_INTR_RDU|RTW_INTR_RXFOVW)) != 0) {
        !          1751:                cr |= RTW_CR_RE;
        !          1752:                rcvr = 1;
        !          1753:        }
        !          1754:
        !          1755:        RTW_DPRINTF(RTW_DEBUG_BUGS, ("%s: restarting xmit/recv, isr %hx"
        !          1756:            "\n", sc->sc_dev.dv_xname, isr));
        !          1757:
        !          1758: #ifdef RTW_DEBUG
        !          1759:        rtw_dump_rings(sc);
        !          1760: #endif /* RTW_DEBUG */
        !          1761:
        !          1762:        rtw_io_enable(regs, cr, 0);
        !          1763:
        !          1764:        /* Collect rx'd packets.  Refresh rx buffers. */
        !          1765:        if (rcvr)
        !          1766:                rtw_intr_rx(sc, 0);
        !          1767:        /* Collect tx'd packets.  XXX let's hope this stops the transmit
        !          1768:         * timeouts.
        !          1769:         */
        !          1770:        if (xmtr)
        !          1771:                rtw_txdescs_reset(sc);
        !          1772:
        !          1773:        RTW_WRITE16(regs, RTW_IMR, 0);
        !          1774:        RTW_SYNC(regs, RTW_IMR, RTW_IMR);
        !          1775:
        !          1776:        if (rtw_do_chip_reset) {
        !          1777:                rtw_chip_reset1(regs, sc->sc_dev.dv_xname);
        !          1778:        }
        !          1779:
        !          1780:        rtw_rxdesc_init_all(&sc->sc_rxdesc_blk, &sc->sc_rxsoft[0], 1);
        !          1781:
        !          1782: #ifdef RTW_DEBUG
        !          1783:        rtw_dump_rings(sc);
        !          1784: #endif /* RTW_DEBUG */
        !          1785:
        !          1786:        RTW_WRITE16(regs, RTW_IMR, sc->sc_inten);
        !          1787:        RTW_SYNC(regs, RTW_IMR, RTW_IMR);
        !          1788:        if (rcvr)
        !          1789:                rtw_rxring_fixup(sc);
        !          1790:        rtw_io_enable(regs, cr, 1);
        !          1791:        if (xmtr)
        !          1792:                rtw_txring_fixup(sc);
        !          1793: }
        !          1794:
        !          1795: void
        !          1796: rtw_suspend_ticks(struct rtw_softc *sc)
        !          1797: {
        !          1798:        RTW_DPRINTF(RTW_DEBUG_TIMEOUT,
        !          1799:            ("%s: suspending ticks\n", sc->sc_dev.dv_xname));
        !          1800:        sc->sc_do_tick = 0;
        !          1801: }
        !          1802:
        !          1803: void
        !          1804: rtw_resume_ticks(struct rtw_softc *sc)
        !          1805: {
        !          1806:        u_int32_t tsftrl0, tsftrl1, next_tick;
        !          1807:
        !          1808:        tsftrl0 = RTW_READ(&sc->sc_regs, RTW_TSFTRL);
        !          1809:
        !          1810:        tsftrl1 = RTW_READ(&sc->sc_regs, RTW_TSFTRL);
        !          1811:        next_tick = tsftrl1 + 1000000;
        !          1812:        RTW_WRITE(&sc->sc_regs, RTW_TINT, next_tick);
        !          1813:
        !          1814:        sc->sc_do_tick = 1;
        !          1815:
        !          1816:        RTW_DPRINTF(RTW_DEBUG_TIMEOUT,
        !          1817:            ("%s: resume ticks delta %#08x now %#08x next %#08x\n",
        !          1818:            sc->sc_dev.dv_xname, tsftrl1 - tsftrl0, tsftrl1, next_tick));
        !          1819: }
        !          1820:
        !          1821: void
        !          1822: rtw_intr_timeout(struct rtw_softc *sc)
        !          1823: {
        !          1824:        RTW_DPRINTF(RTW_DEBUG_TIMEOUT, ("%s: timeout\n", sc->sc_dev.dv_xname));
        !          1825:        if (sc->sc_do_tick)
        !          1826:                rtw_resume_ticks(sc);
        !          1827:        return;
        !          1828: }
        !          1829:
        !          1830: int
        !          1831: rtw_intr(void *arg)
        !          1832: {
        !          1833:        int i;
        !          1834:        struct rtw_softc *sc = arg;
        !          1835:        struct rtw_regs *regs = &sc->sc_regs;
        !          1836:        u_int16_t isr;
        !          1837:
        !          1838:        /*
        !          1839:         * If the interface isn't running, the interrupt couldn't
        !          1840:         * possibly have come from us.
        !          1841:         */
        !          1842:        if ((sc->sc_flags & RTW_F_ENABLED) == 0 ||
        !          1843:            (sc->sc_if.if_flags & IFF_RUNNING) == 0 ||
        !          1844:            (sc->sc_dev.dv_flags & DVF_ACTIVE) == 0) {
        !          1845:                RTW_DPRINTF(RTW_DEBUG_INTR, ("%s: stray interrupt\n",
        !          1846:                     sc->sc_dev.dv_xname));
        !          1847:                return (0);
        !          1848:        }
        !          1849:
        !          1850:        for (i = 0; i < 10; i++) {
        !          1851:                isr = RTW_READ16(regs, RTW_ISR);
        !          1852:
        !          1853:                RTW_WRITE16(regs, RTW_ISR, isr);
        !          1854:                RTW_WBR(regs, RTW_ISR, RTW_ISR);
        !          1855:
        !          1856:                if (sc->sc_intr_ack != NULL)
        !          1857:                        (*sc->sc_intr_ack)(regs);
        !          1858:
        !          1859:                if (isr == 0)
        !          1860:                        break;
        !          1861:
        !          1862: #ifdef RTW_DEBUG
        !          1863: #define PRINTINTR(flag) do { \
        !          1864:        if ((isr & flag) != 0) { \
        !          1865:                printf("%s" #flag, delim); \
        !          1866:                delim = ","; \
        !          1867:        } \
        !          1868: } while (0)
        !          1869:
        !          1870:                if ((rtw_debug & RTW_DEBUG_INTR) != 0 && isr != 0) {
        !          1871:                        const char *delim = "<";
        !          1872:
        !          1873:                        printf("%s: reg[ISR] = %x", sc->sc_dev.dv_xname, isr);
        !          1874:
        !          1875:                        PRINTINTR(RTW_INTR_TXFOVW);
        !          1876:                        PRINTINTR(RTW_INTR_TIMEOUT);
        !          1877:                        PRINTINTR(RTW_INTR_BCNINT);
        !          1878:                        PRINTINTR(RTW_INTR_ATIMINT);
        !          1879:                        PRINTINTR(RTW_INTR_TBDER);
        !          1880:                        PRINTINTR(RTW_INTR_TBDOK);
        !          1881:                        PRINTINTR(RTW_INTR_THPDER);
        !          1882:                        PRINTINTR(RTW_INTR_THPDOK);
        !          1883:                        PRINTINTR(RTW_INTR_TNPDER);
        !          1884:                        PRINTINTR(RTW_INTR_TNPDOK);
        !          1885:                        PRINTINTR(RTW_INTR_RXFOVW);
        !          1886:                        PRINTINTR(RTW_INTR_RDU);
        !          1887:                        PRINTINTR(RTW_INTR_TLPDER);
        !          1888:                        PRINTINTR(RTW_INTR_TLPDOK);
        !          1889:                        PRINTINTR(RTW_INTR_RER);
        !          1890:                        PRINTINTR(RTW_INTR_ROK);
        !          1891:
        !          1892:                        printf(">\n");
        !          1893:                }
        !          1894: #undef PRINTINTR
        !          1895: #endif /* RTW_DEBUG */
        !          1896:
        !          1897:                if ((isr & RTW_INTR_RX) != 0)
        !          1898:                        rtw_intr_rx(sc, isr & RTW_INTR_RX);
        !          1899:                if ((isr & RTW_INTR_TX) != 0)
        !          1900:                        rtw_intr_tx(sc, isr & RTW_INTR_TX);
        !          1901:                if ((isr & RTW_INTR_BEACON) != 0)
        !          1902:                        rtw_intr_beacon(sc, isr & RTW_INTR_BEACON);
        !          1903:                if ((isr & RTW_INTR_ATIMINT) != 0)
        !          1904:                        rtw_intr_atim(sc);
        !          1905:                if ((isr & RTW_INTR_IOERROR) != 0)
        !          1906:                        rtw_intr_ioerror(sc, isr & RTW_INTR_IOERROR);
        !          1907:                if ((isr & RTW_INTR_TIMEOUT) != 0)
        !          1908:                        rtw_intr_timeout(sc);
        !          1909:        }
        !          1910:
        !          1911:        return 1;
        !          1912: }
        !          1913:
        !          1914: /* Must be called at splnet. */
        !          1915: void
        !          1916: rtw_stop(struct ifnet *ifp, int disable)
        !          1917: {
        !          1918:        int pri;
        !          1919:        struct rtw_softc *sc = (struct rtw_softc *)ifp->if_softc;
        !          1920:        struct ieee80211com *ic = &sc->sc_ic;
        !          1921:        struct rtw_regs *regs = &sc->sc_regs;
        !          1922:
        !          1923:        if ((sc->sc_flags & RTW_F_ENABLED) == 0)
        !          1924:                return;
        !          1925:
        !          1926:        rtw_suspend_ticks(sc);
        !          1927:
        !          1928:        ieee80211_new_state(ic, IEEE80211_S_INIT, -1);
        !          1929:
        !          1930:        if ((sc->sc_flags & RTW_F_INVALID) == 0) {
        !          1931:                /* Disable interrupts. */
        !          1932:                RTW_WRITE16(regs, RTW_IMR, 0);
        !          1933:
        !          1934:                RTW_WBW(regs, RTW_TPPOLL, RTW_IMR);
        !          1935:
        !          1936:                /* Stop the transmit and receive processes. First stop DMA,
        !          1937:                 * then disable receiver and transmitter.
        !          1938:                 */
        !          1939:                RTW_WRITE8(regs, RTW_TPPOLL, RTW_TPPOLL_SALL);
        !          1940:
        !          1941:                RTW_SYNC(regs, RTW_TPPOLL, RTW_IMR);
        !          1942:
        !          1943:                rtw_io_enable(&sc->sc_regs, RTW_CR_RE|RTW_CR_TE, 0);
        !          1944:        }
        !          1945:
        !          1946:        for (pri = 0; pri < RTW_NTXPRI; pri++) {
        !          1947:                rtw_txsofts_release(sc->sc_dmat, &sc->sc_ic,
        !          1948:                    &sc->sc_txsoft_blk[pri]);
        !          1949:        }
        !          1950:
        !          1951:        rtw_rxbufs_release(sc->sc_dmat, &sc->sc_rxsoft[0]);
        !          1952:
        !          1953:        if (disable)
        !          1954:                rtw_disable(sc);
        !          1955:
        !          1956:        /* Mark the interface as not running.  Cancel the watchdog timer. */
        !          1957:        ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE);
        !          1958:        ifp->if_timer = 0;
        !          1959:
        !          1960:        return;
        !          1961: }
        !          1962:
        !          1963: #ifdef RTW_DEBUG
        !          1964: const char *
        !          1965: rtw_pwrstate_string(enum rtw_pwrstate power)
        !          1966: {
        !          1967:        switch (power) {
        !          1968:        case RTW_ON:
        !          1969:                return "on";
        !          1970:        case RTW_SLEEP:
        !          1971:                return "sleep";
        !          1972:        case RTW_OFF:
        !          1973:                return "off";
        !          1974:        default:
        !          1975:                return "unknown";
        !          1976:        }
        !          1977: }
        !          1978: #endif
        !          1979:
        !          1980: /* XXX For Maxim, I am using the RFMD settings gleaned from the
        !          1981:  * reference driver, plus a magic Maxim "ON" value that comes from
        !          1982:  * the Realtek document "Windows PG for Rtl8180."
        !          1983:  */
        !          1984: void
        !          1985: rtw_maxim_pwrstate(struct rtw_regs *regs, enum rtw_pwrstate power,
        !          1986:     int before_rf, int digphy)
        !          1987: {
        !          1988:        u_int32_t anaparm;
        !          1989:
        !          1990:        anaparm = RTW_READ(regs, RTW_ANAPARM_0);
        !          1991:        anaparm &= ~(RTW_ANAPARM_RFPOW_MASK | RTW_ANAPARM_TXDACOFF);
        !          1992:
        !          1993:        switch (power) {
        !          1994:        case RTW_OFF:
        !          1995:                if (before_rf)
        !          1996:                        return;
        !          1997:                anaparm |= RTW_ANAPARM_RFPOW_MAXIM_OFF;
        !          1998:                anaparm |= RTW_ANAPARM_TXDACOFF;
        !          1999:                break;
        !          2000:        case RTW_SLEEP:
        !          2001:                if (!before_rf)
        !          2002:                        return;
        !          2003:                anaparm |= RTW_ANAPARM_RFPOW_MAXIM_SLEEP;
        !          2004:                anaparm |= RTW_ANAPARM_TXDACOFF;
        !          2005:                break;
        !          2006:        case RTW_ON:
        !          2007:                if (!before_rf)
        !          2008:                        return;
        !          2009:                anaparm |= RTW_ANAPARM_RFPOW_MAXIM_ON;
        !          2010:                break;
        !          2011:        }
        !          2012:        RTW_DPRINTF(RTW_DEBUG_PWR,
        !          2013:            ("%s: power state %s, %s RF, reg[ANAPARM] <- %08x\n",
        !          2014:            __func__, rtw_pwrstate_string(power),
        !          2015:            (before_rf) ? "before" : "after", anaparm));
        !          2016:
        !          2017:        RTW_WRITE(regs, RTW_ANAPARM_0, anaparm);
        !          2018:        RTW_SYNC(regs, RTW_ANAPARM_0, RTW_ANAPARM_0);
        !          2019: }
        !          2020:
        !          2021: /* XXX I am using the RFMD settings gleaned from the reference
        !          2022:  * driver.  They agree
        !          2023:  */
        !          2024: void
        !          2025: rtw_rfmd_pwrstate(struct rtw_regs *regs, enum rtw_pwrstate power,
        !          2026:     int before_rf, int digphy)
        !          2027: {
        !          2028:        u_int32_t anaparm;
        !          2029:
        !          2030:        anaparm = RTW_READ(regs, RTW_ANAPARM_0);
        !          2031:        anaparm &= ~(RTW_ANAPARM_RFPOW_MASK | RTW_ANAPARM_TXDACOFF);
        !          2032:
        !          2033:        switch (power) {
        !          2034:        case RTW_OFF:
        !          2035:                if (before_rf)
        !          2036:                        return;
        !          2037:                anaparm |= RTW_ANAPARM_RFPOW_RFMD_OFF;
        !          2038:                anaparm |= RTW_ANAPARM_TXDACOFF;
        !          2039:                break;
        !          2040:        case RTW_SLEEP:
        !          2041:                if (!before_rf)
        !          2042:                        return;
        !          2043:                anaparm |= RTW_ANAPARM_RFPOW_RFMD_SLEEP;
        !          2044:                anaparm |= RTW_ANAPARM_TXDACOFF;
        !          2045:                break;
        !          2046:        case RTW_ON:
        !          2047:                if (!before_rf)
        !          2048:                        return;
        !          2049:                anaparm |= RTW_ANAPARM_RFPOW_RFMD_ON;
        !          2050:                break;
        !          2051:        }
        !          2052:        RTW_DPRINTF(RTW_DEBUG_PWR,
        !          2053:            ("%s: power state %s, %s RF, reg[ANAPARM] <- %08x\n",
        !          2054:            __func__, rtw_pwrstate_string(power),
        !          2055:            (before_rf) ? "before" : "after", anaparm));
        !          2056:
        !          2057:        RTW_WRITE(regs, RTW_ANAPARM_0, anaparm);
        !          2058:        RTW_SYNC(regs, RTW_ANAPARM_0, RTW_ANAPARM_0);
        !          2059: }
        !          2060:
        !          2061: void
        !          2062: rtw_philips_pwrstate(struct rtw_regs *regs, enum rtw_pwrstate power,
        !          2063:     int before_rf, int digphy)
        !          2064: {
        !          2065:        u_int32_t anaparm;
        !          2066:
        !          2067:        anaparm = RTW_READ(regs, RTW_ANAPARM_0);
        !          2068:        anaparm &= ~(RTW_ANAPARM_RFPOW_MASK | RTW_ANAPARM_TXDACOFF);
        !          2069:
        !          2070:        switch (power) {
        !          2071:        case RTW_OFF:
        !          2072:                if (before_rf)
        !          2073:                        return;
        !          2074:                anaparm |= RTW_ANAPARM_RFPOW_PHILIPS_OFF;
        !          2075:                anaparm |= RTW_ANAPARM_TXDACOFF;
        !          2076:                break;
        !          2077:        case RTW_SLEEP:
        !          2078:                if (!before_rf)
        !          2079:                        return;
        !          2080:                anaparm |= RTW_ANAPARM_RFPOW_PHILIPS_SLEEP;
        !          2081:                anaparm |= RTW_ANAPARM_TXDACOFF;
        !          2082:                break;
        !          2083:        case RTW_ON:
        !          2084:                if (!before_rf)
        !          2085:                        return;
        !          2086:                if (digphy) {
        !          2087:                        anaparm |= RTW_ANAPARM_RFPOW_DIG_PHILIPS_ON;
        !          2088:                        /* XXX guess */
        !          2089:                        anaparm |= RTW_ANAPARM_TXDACOFF;
        !          2090:                } else
        !          2091:                        anaparm |= RTW_ANAPARM_RFPOW_ANA_PHILIPS_ON;
        !          2092:                break;
        !          2093:        }
        !          2094:        RTW_DPRINTF(RTW_DEBUG_PWR,
        !          2095:            ("%s: power state %s, %s RF, reg[ANAPARM] <- %08x\n",
        !          2096:            __func__, rtw_pwrstate_string(power),
        !          2097:            (before_rf) ? "before" : "after", anaparm));
        !          2098:
        !          2099:        RTW_WRITE(regs, RTW_ANAPARM_0, anaparm);
        !          2100:        RTW_SYNC(regs, RTW_ANAPARM_0, RTW_ANAPARM_0);
        !          2101: }
        !          2102:
        !          2103: void
        !          2104: rtw_rtl_pwrstate(struct rtw_regs *regs, enum rtw_pwrstate power,
        !          2105:     int before_rf, int digphy)
        !          2106: {
        !          2107:        /* empty */
        !          2108: }
        !          2109:
        !          2110: void
        !          2111: rtw_pwrstate0(struct rtw_softc *sc, enum rtw_pwrstate power, int before_rf,
        !          2112:     int digphy)
        !          2113: {
        !          2114:        struct rtw_regs *regs = &sc->sc_regs;
        !          2115:
        !          2116:        rtw_set_access(regs, RTW_ACCESS_ANAPARM);
        !          2117:
        !          2118:        (*sc->sc_pwrstate_cb)(regs, power, before_rf, digphy);
        !          2119:
        !          2120:        rtw_set_access(regs, RTW_ACCESS_NONE);
        !          2121:
        !          2122:        return;
        !          2123: }
        !          2124:
        !          2125: int
        !          2126: rtw_pwrstate(struct rtw_softc *sc, enum rtw_pwrstate power)
        !          2127: {
        !          2128:        int rc;
        !          2129:
        !          2130:        RTW_DPRINTF(RTW_DEBUG_PWR,
        !          2131:            ("%s: %s->%s\n", __func__,
        !          2132:            rtw_pwrstate_string(sc->sc_pwrstate), rtw_pwrstate_string(power)));
        !          2133:
        !          2134:        if (sc->sc_pwrstate == power)
        !          2135:                return 0;
        !          2136:
        !          2137:        rtw_pwrstate0(sc, power, 1, sc->sc_flags & RTW_F_DIGPHY);
        !          2138:        rc = (*sc->sc_rf_pwrstate)(sc, power);
        !          2139:        rtw_pwrstate0(sc, power, 0, sc->sc_flags & RTW_F_DIGPHY);
        !          2140:
        !          2141:        switch (power) {
        !          2142:        case RTW_ON:
        !          2143:                /* TBD set LEDs */
        !          2144:                break;
        !          2145:        case RTW_SLEEP:
        !          2146:                /* TBD */
        !          2147:                break;
        !          2148:        case RTW_OFF:
        !          2149:                /* TBD */
        !          2150:                break;
        !          2151:        }
        !          2152:        if (rc == 0)
        !          2153:                sc->sc_pwrstate = power;
        !          2154:        else
        !          2155:                sc->sc_pwrstate = RTW_OFF;
        !          2156:        return rc;
        !          2157: }
        !          2158:
        !          2159: int
        !          2160: rtw_tune(struct rtw_softc *sc)
        !          2161: {
        !          2162:        struct ieee80211com *ic = &sc->sc_ic;
        !          2163:        u_int chan, idx;
        !          2164:        u_int8_t txpower;
        !          2165:        int rc;
        !          2166:
        !          2167:        KASSERT(ic->ic_bss->ni_chan != NULL);
        !          2168:
        !          2169:        chan = ieee80211_chan2ieee(ic, ic->ic_bss->ni_chan);
        !          2170:        if (chan == 0 || chan == IEEE80211_CHAN_ANY)
        !          2171:                return 0;
        !          2172:
        !          2173:        if (chan == sc->sc_cur_chan) {
        !          2174:                RTW_DPRINTF(RTW_DEBUG_TUNE,
        !          2175:                    ("%s: already tuned chan #%d\n", __func__, chan));
        !          2176:                return 0;
        !          2177:        }
        !          2178:
        !          2179:        rtw_suspend_ticks(sc);
        !          2180:
        !          2181:        rtw_io_enable(&sc->sc_regs, RTW_CR_RE | RTW_CR_TE, 0);
        !          2182:
        !          2183:        /* TBD wait for Tx to complete */
        !          2184:
        !          2185:        KASSERT((sc->sc_flags & RTW_F_ENABLED) != 0);
        !          2186:
        !          2187:        idx = RTW_SR_TXPOWER1 +
        !          2188:            ieee80211_chan2ieee(ic, ic->ic_bss->ni_chan) - 1;
        !          2189:        KASSERT2(idx >= RTW_SR_TXPOWER1 && idx <= RTW_SR_TXPOWER14,
        !          2190:            ("%s: channel %d out of range", __func__,
        !          2191:             idx - RTW_SR_TXPOWER1 + 1));
        !          2192:        txpower =  RTW_SR_GET(&sc->sc_srom, idx);
        !          2193:
        !          2194:        if ((rc = rtw_phy_init(sc)) != 0) {
        !          2195:                /* XXX condition on powersaving */
        !          2196:                printf("%s: phy init failed\n", sc->sc_dev.dv_xname);
        !          2197:        }
        !          2198:
        !          2199:        sc->sc_cur_chan = chan;
        !          2200:
        !          2201:        rtw_io_enable(&sc->sc_regs, RTW_CR_RE | RTW_CR_TE, 1);
        !          2202:
        !          2203:        rtw_resume_ticks(sc);
        !          2204:
        !          2205:        return rc;
        !          2206: }
        !          2207:
        !          2208: void
        !          2209: rtw_disable(struct rtw_softc *sc)
        !          2210: {
        !          2211:        int rc;
        !          2212:
        !          2213:        if ((sc->sc_flags & RTW_F_ENABLED) == 0)
        !          2214:                return;
        !          2215:
        !          2216:        /* turn off PHY */
        !          2217:        if ((sc->sc_flags & RTW_F_INVALID) == 0 &&
        !          2218:            (rc = rtw_pwrstate(sc, RTW_OFF)) != 0) {
        !          2219:                printf("%s: failed to turn off PHY (%d)\n",
        !          2220:                    sc->sc_dev.dv_xname, rc);
        !          2221:        }
        !          2222:
        !          2223:        if (sc->sc_disable != NULL)
        !          2224:                (*sc->sc_disable)(sc);
        !          2225:
        !          2226:        sc->sc_flags &= ~RTW_F_ENABLED;
        !          2227: }
        !          2228:
        !          2229: int
        !          2230: rtw_enable(struct rtw_softc *sc)
        !          2231: {
        !          2232:        if ((sc->sc_flags & RTW_F_ENABLED) == 0) {
        !          2233:                if (sc->sc_enable != NULL && (*sc->sc_enable)(sc) != 0) {
        !          2234:                        printf("%s: device enable failed\n",
        !          2235:                            sc->sc_dev.dv_xname);
        !          2236:                        return (EIO);
        !          2237:                }
        !          2238:                sc->sc_flags |= RTW_F_ENABLED;
        !          2239:        }
        !          2240:        return (0);
        !          2241: }
        !          2242:
        !          2243: void
        !          2244: rtw_transmit_config(struct rtw_softc *sc)
        !          2245: {
        !          2246:        struct rtw_regs *regs = &sc->sc_regs;
        !          2247:        u_int32_t tcr;
        !          2248:
        !          2249:        tcr = RTW_READ(regs, RTW_TCR);
        !          2250:
        !          2251:        tcr |= RTW_TCR_CWMIN;
        !          2252:        tcr &= ~RTW_TCR_MXDMA_MASK;
        !          2253:        tcr |= RTW_TCR_MXDMA_256;
        !          2254:        if ((sc->sc_flags & RTW_F_RTL8185) == 0)
        !          2255:                tcr |= RTW8180_TCR_SAT;         /* send ACK as fast as possible */
        !          2256:        tcr &= ~RTW_TCR_LBK_MASK;
        !          2257:        tcr |= RTW_TCR_LBK_NORMAL;      /* normal operating mode */
        !          2258:
        !          2259:        /* set short/long retry limits */
        !          2260:        tcr &= ~(RTW_TCR_SRL_MASK|RTW_TCR_LRL_MASK);
        !          2261:        tcr |= LSHIFT(4, RTW_TCR_SRL_MASK) | LSHIFT(4, RTW_TCR_LRL_MASK);
        !          2262:
        !          2263:        tcr &= ~RTW_TCR_CRC;    /* NIC appends CRC32 */
        !          2264:
        !          2265:        RTW_WRITE(regs, RTW_TCR, tcr);
        !          2266:        RTW_SYNC(regs, RTW_TCR, RTW_TCR);
        !          2267: }
        !          2268:
        !          2269: void
        !          2270: rtw_enable_interrupts(struct rtw_softc *sc)
        !          2271: {
        !          2272:        struct rtw_regs *regs = &sc->sc_regs;
        !          2273:
        !          2274:        sc->sc_inten = RTW_INTR_RX|RTW_INTR_TX|RTW_INTR_BEACON|RTW_INTR_ATIMINT;
        !          2275:        sc->sc_inten |= RTW_INTR_IOERROR|RTW_INTR_TIMEOUT;
        !          2276:
        !          2277:        RTW_WRITE16(regs, RTW_IMR, sc->sc_inten);
        !          2278:        RTW_WBW(regs, RTW_IMR, RTW_ISR);
        !          2279:        RTW_WRITE16(regs, RTW_ISR, 0xffff);
        !          2280:        RTW_SYNC(regs, RTW_IMR, RTW_ISR);
        !          2281:
        !          2282:        /* XXX necessary? */
        !          2283:        if (sc->sc_intr_ack != NULL)
        !          2284:                (*sc->sc_intr_ack)(regs);
        !          2285: }
        !          2286:
        !          2287: void
        !          2288: rtw_set_nettype(struct rtw_softc *sc, enum ieee80211_opmode opmode)
        !          2289: {
        !          2290:        uint8_t msr;
        !          2291:
        !          2292:        /* I'm guessing that MSR is protected as CONFIG[0123] are. */
        !          2293:        rtw_set_access(&sc->sc_regs, RTW_ACCESS_CONFIG);
        !          2294:
        !          2295:        msr = RTW_READ8(&sc->sc_regs, RTW_MSR) & ~RTW_MSR_NETYPE_MASK;
        !          2296:
        !          2297:        switch (opmode) {
        !          2298:        case IEEE80211_M_AHDEMO:
        !          2299:        case IEEE80211_M_IBSS:
        !          2300:                msr |= RTW_MSR_NETYPE_ADHOC_OK;
        !          2301:                break;
        !          2302:        case IEEE80211_M_HOSTAP:
        !          2303:                msr |= RTW_MSR_NETYPE_AP_OK;
        !          2304:                break;
        !          2305:        case IEEE80211_M_MONITOR:
        !          2306:                /* XXX */
        !          2307:                msr |= RTW_MSR_NETYPE_NOLINK;
        !          2308:                break;
        !          2309:        case IEEE80211_M_STA:
        !          2310:                msr |= RTW_MSR_NETYPE_INFRA_OK;
        !          2311:                break;
        !          2312:        }
        !          2313:        RTW_WRITE8(&sc->sc_regs, RTW_MSR, msr);
        !          2314:
        !          2315:        rtw_set_access(&sc->sc_regs, RTW_ACCESS_NONE);
        !          2316: }
        !          2317:
        !          2318: void
        !          2319: rtw_pktfilt_load(struct rtw_softc *sc)
        !          2320: {
        !          2321:        struct rtw_regs *regs = &sc->sc_regs;
        !          2322:        struct ieee80211com *ic = &sc->sc_ic;
        !          2323:        struct arpcom *ec = &ic->ic_ac;
        !          2324:        struct ifnet *ifp = &sc->sc_ic.ic_if;
        !          2325:        int hash;
        !          2326:        u_int32_t hashes[2] = { 0, 0 };
        !          2327:        struct ether_multi *enm;
        !          2328:        struct ether_multistep step;
        !          2329:
        !          2330:        /* XXX might be necessary to stop Rx/Tx engines while setting filters */
        !          2331:
        !          2332:        sc->sc_rcr &= ~RTW_RCR_PKTFILTER_MASK;
        !          2333:        sc->sc_rcr &= ~(RTW_RCR_MXDMA_MASK | RTW8180_RCR_RXFTH_MASK);
        !          2334:
        !          2335:        sc->sc_rcr |= RTW_RCR_PKTFILTER_DEFAULT;
        !          2336:        /* MAC auto-reset PHY (huh?) */
        !          2337:        sc->sc_rcr |= RTW_RCR_ENMARP;
        !          2338:        /* DMA whole Rx packets, only.  Set Tx DMA burst size to 1024 bytes. */
        !          2339:        sc->sc_rcr |= RTW_RCR_MXDMA_1024 | RTW8180_RCR_RXFTH_WHOLE;
        !          2340:
        !          2341:        switch (ic->ic_opmode) {
        !          2342:        case IEEE80211_M_MONITOR:
        !          2343:                sc->sc_rcr |= RTW_RCR_MONITOR;
        !          2344:                break;
        !          2345:        case IEEE80211_M_AHDEMO:
        !          2346:        case IEEE80211_M_IBSS:
        !          2347:                /* receive broadcasts in our BSS */
        !          2348:                sc->sc_rcr |= RTW_RCR_ADD3;
        !          2349:                break;
        !          2350:        default:
        !          2351:                break;
        !          2352:        }
        !          2353:
        !          2354:        ifp->if_flags &= ~IFF_ALLMULTI;
        !          2355:
        !          2356:        /* XXX accept all broadcast if scanning */
        !          2357:        if ((ifp->if_flags & IFF_BROADCAST) != 0)
        !          2358:                sc->sc_rcr |= RTW_RCR_AB;       /* accept all broadcast */
        !          2359:
        !          2360:        if (ifp->if_flags & IFF_PROMISC) {
        !          2361:                sc->sc_rcr |= RTW_RCR_AB;       /* accept all broadcast */
        !          2362: allmulti:
        !          2363:                ifp->if_flags |= IFF_ALLMULTI;
        !          2364:                goto setit;
        !          2365:        }
        !          2366:
        !          2367:        /*
        !          2368:         * Program the 64-bit multicast hash filter.
        !          2369:         */
        !          2370:        ETHER_FIRST_MULTI(step, ec, enm);
        !          2371:        while (enm != NULL) {
        !          2372:                /* XXX */
        !          2373:                if (bcmp(enm->enm_addrlo, enm->enm_addrhi,
        !          2374:                    ETHER_ADDR_LEN) != 0)
        !          2375:                        goto allmulti;
        !          2376:
        !          2377:                hash = ether_crc32_be((enm->enm_addrlo),
        !          2378:                    IEEE80211_ADDR_LEN) >> 26;
        !          2379:                hashes[hash >> 5] |= (1 << (hash & 0x1f));
        !          2380:                sc->sc_rcr |= RTW_RCR_AM;
        !          2381:                ETHER_NEXT_MULTI(step, enm);
        !          2382:        }
        !          2383:
        !          2384:        /* all bits set => hash is useless */
        !          2385:        if (~(hashes[0] & hashes[1]) == 0)
        !          2386:                goto allmulti;
        !          2387:
        !          2388:  setit:
        !          2389:        if (ifp->if_flags & IFF_ALLMULTI) {
        !          2390:                sc->sc_rcr |= RTW_RCR_AM;       /* accept all multicast */
        !          2391:                hashes[0] = hashes[1] = 0xffffffff;
        !          2392:        }
        !          2393:
        !          2394:        RTW_WRITE(regs, RTW_MAR0, hashes[0]);
        !          2395:        RTW_WRITE(regs, RTW_MAR1, hashes[1]);
        !          2396:        RTW_WRITE(regs, RTW_RCR, sc->sc_rcr);
        !          2397:        RTW_SYNC(regs, RTW_MAR0, RTW_RCR); /* RTW_MAR0 < RTW_MAR1 < RTW_RCR */
        !          2398:
        !          2399:        DPRINTF(sc, RTW_DEBUG_PKTFILT,
        !          2400:            ("%s: RTW_MAR0 %08x RTW_MAR1 %08x RTW_RCR %08x\n",
        !          2401:            sc->sc_dev.dv_xname, RTW_READ(regs, RTW_MAR0),
        !          2402:            RTW_READ(regs, RTW_MAR1), RTW_READ(regs, RTW_RCR)));
        !          2403:
        !          2404:        return;
        !          2405: }
        !          2406:
        !          2407: /* Must be called at splnet. */
        !          2408: int
        !          2409: rtw_init(struct ifnet *ifp)
        !          2410: {
        !          2411:        struct rtw_softc *sc = (struct rtw_softc *)ifp->if_softc;
        !          2412:        struct ieee80211com *ic = &sc->sc_ic;
        !          2413:        struct rtw_regs *regs = &sc->sc_regs;
        !          2414:        int rc = 0;
        !          2415:
        !          2416:        if ((rc = rtw_enable(sc)) != 0)
        !          2417:                goto out;
        !          2418:
        !          2419:        /* Cancel pending I/O and reset. */
        !          2420:        rtw_stop(ifp, 0);
        !          2421:
        !          2422:        ic->ic_bss->ni_chan = ic->ic_ibss_chan;
        !          2423:        DPRINTF(sc, RTW_DEBUG_TUNE, ("%s: channel %d freq %d flags 0x%04x\n",
        !          2424:            __func__, ieee80211_chan2ieee(ic, ic->ic_bss->ni_chan),
        !          2425:            ic->ic_bss->ni_chan->ic_freq, ic->ic_bss->ni_chan->ic_flags));
        !          2426:
        !          2427:        if ((rc = rtw_pwrstate(sc, RTW_OFF)) != 0)
        !          2428:                goto out;
        !          2429:
        !          2430:        if ((rc = rtw_swring_setup(sc)) != 0)
        !          2431:                goto out;
        !          2432:
        !          2433:        rtw_transmit_config(sc);
        !          2434:
        !          2435:        rtw_set_access(regs, RTW_ACCESS_CONFIG);
        !          2436:
        !          2437:        RTW_WRITE8(regs, RTW_MSR, 0x0); /* no link */
        !          2438:        RTW_WBW(regs, RTW_MSR, RTW_BRSR);
        !          2439:
        !          2440:        /* long PLCP header, 1Mb/2Mb basic rate */
        !          2441:        if (sc->sc_flags & RTW_F_RTL8185)
        !          2442:                RTW_WRITE16(regs, RTW_BRSR, RTW8185_BRSR_MBR_2MBPS);
        !          2443:        else
        !          2444:                RTW_WRITE16(regs, RTW_BRSR, RTW8180_BRSR_MBR_2MBPS);
        !          2445:        RTW_SYNC(regs, RTW_BRSR, RTW_BRSR);
        !          2446:
        !          2447:        rtw_set_access(regs, RTW_ACCESS_ANAPARM);
        !          2448:        rtw_set_access(regs, RTW_ACCESS_NONE);
        !          2449:
        !          2450:        /* XXX from reference sources */
        !          2451:        RTW_WRITE(regs, RTW_FEMR, 0xffff);
        !          2452:        RTW_SYNC(regs, RTW_FEMR, RTW_FEMR);
        !          2453:
        !          2454:        rtw_set_rfprog(regs, sc->sc_rfchipid, sc->sc_dev.dv_xname);
        !          2455:
        !          2456:        RTW_WRITE8(regs, RTW_PHYDELAY, sc->sc_phydelay);
        !          2457:        /* from Linux driver */
        !          2458:        RTW_WRITE8(regs, RTW_CRCOUNT, RTW_CRCOUNT_MAGIC);
        !          2459:
        !          2460:        RTW_SYNC(regs, RTW_PHYDELAY, RTW_CRCOUNT);
        !          2461:
        !          2462:        rtw_enable_interrupts(sc);
        !          2463:
        !          2464:        rtw_pktfilt_load(sc);
        !          2465:
        !          2466:        rtw_hwring_setup(sc);
        !          2467:
        !          2468:        rtw_io_enable(regs, RTW_CR_RE|RTW_CR_TE, 1);
        !          2469:
        !          2470:        ifp->if_flags |= IFF_RUNNING;
        !          2471:        ic->ic_state = IEEE80211_S_INIT;
        !          2472:
        !          2473:        RTW_WRITE16(regs, RTW_BSSID16, 0x0);
        !          2474:        RTW_WRITE(regs, RTW_BSSID32, 0x0);
        !          2475:
        !          2476:        rtw_resume_ticks(sc);
        !          2477:
        !          2478:        rtw_set_nettype(sc, IEEE80211_M_MONITOR);
        !          2479:
        !          2480:        if (ic->ic_opmode == IEEE80211_M_MONITOR)
        !          2481:                return ieee80211_new_state(ic, IEEE80211_S_RUN, -1);
        !          2482:        else
        !          2483:                return ieee80211_new_state(ic, IEEE80211_S_SCAN, -1);
        !          2484:
        !          2485: out:
        !          2486:        printf("%s: interface not running\n", sc->sc_dev.dv_xname);
        !          2487:        return rc;
        !          2488: }
        !          2489:
        !          2490: void
        !          2491: rtw_led_init(struct rtw_regs *regs)
        !          2492: {
        !          2493:        u_int8_t cfg0, cfg1;
        !          2494:
        !          2495:        rtw_set_access(regs, RTW_ACCESS_CONFIG);
        !          2496:
        !          2497:        cfg0 = RTW_READ8(regs, RTW_CONFIG0);
        !          2498:        cfg0 |= RTW8180_CONFIG0_LEDGPOEN;
        !          2499:        RTW_WRITE8(regs, RTW_CONFIG0, cfg0);
        !          2500:
        !          2501:        cfg1 = RTW_READ8(regs, RTW_CONFIG1);
        !          2502:        RTW_DPRINTF(RTW_DEBUG_LED,
        !          2503:            ("%s: read % from reg[CONFIG1]\n", __func__, cfg1));
        !          2504:
        !          2505:        cfg1 &= ~RTW_CONFIG1_LEDS_MASK;
        !          2506:        cfg1 |= RTW_CONFIG1_LEDS_TX_RX;
        !          2507:        RTW_WRITE8(regs, RTW_CONFIG1, cfg1);
        !          2508:
        !          2509:        rtw_set_access(regs, RTW_ACCESS_NONE);
        !          2510: }
        !          2511:
        !          2512: /*
        !          2513:  * IEEE80211_S_INIT:           LED1 off
        !          2514:  *
        !          2515:  * IEEE80211_S_AUTH,
        !          2516:  * IEEE80211_S_ASSOC,
        !          2517:  * IEEE80211_S_SCAN:           LED1 blinks @ 1 Hz, blinks at 5Hz for tx/rx
        !          2518:  *
        !          2519:  * IEEE80211_S_RUN:            LED1 on, blinks @ 5Hz for tx/rx
        !          2520:  */
        !          2521: void
        !          2522: rtw_led_newstate(struct rtw_softc *sc, enum ieee80211_state nstate)
        !          2523: {
        !          2524:        struct rtw_led_state *ls;
        !          2525:
        !          2526:        ls = &sc->sc_led_state;
        !          2527:
        !          2528:        switch (nstate) {
        !          2529:        case IEEE80211_S_INIT:
        !          2530:                rtw_led_init(&sc->sc_regs);
        !          2531:                timeout_del(&ls->ls_slow_ch);
        !          2532:                timeout_del(&ls->ls_fast_ch);
        !          2533:                ls->ls_slowblink = 0;
        !          2534:                ls->ls_actblink = 0;
        !          2535:                ls->ls_default = 0;
        !          2536:                break;
        !          2537:        case IEEE80211_S_SCAN:
        !          2538:                timeout_add(&ls->ls_slow_ch, RTW_LED_SLOW_TICKS);
        !          2539:                timeout_add(&ls->ls_fast_ch, RTW_LED_FAST_TICKS);
        !          2540:                /*FALLTHROUGH*/
        !          2541:        case IEEE80211_S_AUTH:
        !          2542:        case IEEE80211_S_ASSOC:
        !          2543:                ls->ls_default = RTW_LED1;
        !          2544:                ls->ls_actblink = RTW_LED1;
        !          2545:                ls->ls_slowblink = RTW_LED1;
        !          2546:                break;
        !          2547:        case IEEE80211_S_RUN:
        !          2548:                ls->ls_slowblink = 0;
        !          2549:                break;
        !          2550:        }
        !          2551:        rtw_led_set(ls, &sc->sc_regs, sc->sc_hwverid);
        !          2552: }
        !          2553:
        !          2554: void
        !          2555: rtw_led_set(struct rtw_led_state *ls, struct rtw_regs *regs, u_int hwverid)
        !          2556: {
        !          2557:        u_int8_t led_condition;
        !          2558:        bus_size_t ofs;
        !          2559:        u_int8_t mask, newval, val;
        !          2560:
        !          2561:        led_condition = ls->ls_default;
        !          2562:
        !          2563:        if (ls->ls_state & RTW_LED_S_SLOW)
        !          2564:                led_condition ^= ls->ls_slowblink;
        !          2565:        if (ls->ls_state & (RTW_LED_S_RX|RTW_LED_S_TX))
        !          2566:                led_condition ^= ls->ls_actblink;
        !          2567:
        !          2568:        RTW_DPRINTF(RTW_DEBUG_LED,
        !          2569:            ("%s: LED condition %\n", __func__, led_condition));
        !          2570:
        !          2571:        switch (hwverid) {
        !          2572:        default:
        !          2573:        case RTW_TCR_HWVERID_RTL8180F:
        !          2574:                ofs = RTW_PSR;
        !          2575:                newval = mask = RTW_PSR_LEDGPO0 | RTW_PSR_LEDGPO1;
        !          2576:                if (led_condition & RTW_LED0)
        !          2577:                        newval &= ~RTW_PSR_LEDGPO0;
        !          2578:                if (led_condition & RTW_LED1)
        !          2579:                        newval &= ~RTW_PSR_LEDGPO1;
        !          2580:                break;
        !          2581:        case RTW_TCR_HWVERID_RTL8180D:
        !          2582:                ofs = RTW_9346CR;
        !          2583:                mask = RTW_9346CR_EEM_MASK | RTW_9346CR_EEDI | RTW_9346CR_EECS;
        !          2584:                newval = RTW_9346CR_EEM_PROGRAM;
        !          2585:                if (led_condition & RTW_LED0)
        !          2586:                        newval |= RTW_9346CR_EEDI;
        !          2587:                if (led_condition & RTW_LED1)
        !          2588:                        newval |= RTW_9346CR_EECS;
        !          2589:                break;
        !          2590:        }
        !          2591:        val = RTW_READ8(regs, ofs);
        !          2592:        RTW_DPRINTF(RTW_DEBUG_LED,
        !          2593:            ("%s: read % from reg[%#02]\n", __func__, val,
        !          2594:             (u_int *)ofs));
        !          2595:        val &= ~mask;
        !          2596:        val |= newval;
        !          2597:        RTW_WRITE8(regs, ofs, val);
        !          2598:        RTW_DPRINTF(RTW_DEBUG_LED,
        !          2599:            ("%s: wrote % to reg[%#02]\n", __func__, val,
        !          2600:             (u_int *)ofs));
        !          2601:        RTW_SYNC(regs, ofs, ofs);
        !          2602: }
        !          2603:
        !          2604: void
        !          2605: rtw_led_fastblink(void *arg)
        !          2606: {
        !          2607:        int ostate, s;
        !          2608:        struct rtw_softc *sc = (struct rtw_softc *)arg;
        !          2609:        struct rtw_led_state *ls = &sc->sc_led_state;
        !          2610:
        !          2611:        s = splnet();
        !          2612:        ostate = ls->ls_state;
        !          2613:        ls->ls_state ^= ls->ls_event;
        !          2614:
        !          2615:        if ((ls->ls_event & RTW_LED_S_TX) == 0)
        !          2616:                ls->ls_state &= ~RTW_LED_S_TX;
        !          2617:
        !          2618:        if ((ls->ls_event & RTW_LED_S_RX) == 0)
        !          2619:                ls->ls_state &= ~RTW_LED_S_RX;
        !          2620:
        !          2621:        ls->ls_event = 0;
        !          2622:
        !          2623:        if (ostate != ls->ls_state)
        !          2624:                rtw_led_set(ls, &sc->sc_regs, sc->sc_hwverid);
        !          2625:        splx(s);
        !          2626:
        !          2627:        timeout_add(&ls->ls_fast_ch, RTW_LED_FAST_TICKS);
        !          2628: }
        !          2629:
        !          2630: void
        !          2631: rtw_led_slowblink(void *arg)
        !          2632: {
        !          2633:        int s;
        !          2634:        struct rtw_softc *sc = (struct rtw_softc *)arg;
        !          2635:        struct rtw_led_state *ls = &sc->sc_led_state;
        !          2636:
        !          2637:        s = splnet();
        !          2638:        ls->ls_state ^= RTW_LED_S_SLOW;
        !          2639:        rtw_led_set(ls, &sc->sc_regs, sc->sc_hwverid);
        !          2640:        splx(s);
        !          2641:        timeout_add(&ls->ls_slow_ch, RTW_LED_SLOW_TICKS);
        !          2642: }
        !          2643:
        !          2644: void
        !          2645: rtw_led_attach(struct rtw_led_state *ls, void *arg)
        !          2646: {
        !          2647:        timeout_set(&ls->ls_fast_ch, rtw_led_fastblink, arg);
        !          2648:        timeout_set(&ls->ls_slow_ch, rtw_led_slowblink, arg);
        !          2649: }
        !          2650:
        !          2651: int
        !          2652: rtw_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
        !          2653: {
        !          2654:        int rc = 0, s;
        !          2655:        struct rtw_softc *sc = ifp->if_softc;
        !          2656:        struct ieee80211com *ic = &sc->sc_ic;
        !          2657:        struct ifreq *ifr = (struct ifreq *)data;
        !          2658:        struct ifaddr *ifa = (struct ifaddr *)data;
        !          2659:
        !          2660:        s = splnet();
        !          2661:        switch (cmd) {
        !          2662:        case SIOCSIFMTU:
        !          2663:                if (ifr->ifr_mtu > ETHERMTU || ifr->ifr_mtu < ETHERMIN) {
        !          2664:                        rc = EINVAL;
        !          2665:                } else if (ifp->if_mtu != ifr->ifr_mtu) {
        !          2666:                        ifp->if_mtu = ifr->ifr_mtu;
        !          2667:                }
        !          2668:                break;
        !          2669:        case SIOCSIFADDR:
        !          2670:                ifp->if_flags |= IFF_UP;
        !          2671: #ifdef INET
        !          2672:                if (ifa->ifa_addr->sa_family == AF_INET) {
        !          2673:                        arp_ifinit(&ic->ic_ac, ifa);
        !          2674:                }
        !          2675: #endif  /* INET */
        !          2676:                /* FALLTHROUGH */
        !          2677:
        !          2678:        case SIOCSIFFLAGS:
        !          2679:                if ((ifp->if_flags & IFF_UP) != 0) {
        !          2680:                        if ((sc->sc_flags & RTW_F_ENABLED) != 0) {
        !          2681:                                rtw_pktfilt_load(sc);
        !          2682:                        } else
        !          2683:                                rc = rtw_init(ifp);
        !          2684:                } else if ((sc->sc_flags & RTW_F_ENABLED) != 0)
        !          2685:                        rtw_stop(ifp, 1);
        !          2686:                break;
        !          2687:        case SIOCADDMULTI:
        !          2688:        case SIOCDELMULTI:
        !          2689:                if (cmd == SIOCADDMULTI)
        !          2690:                        rc = ether_addmulti(ifr, &sc->sc_ic.ic_ac);
        !          2691:                else
        !          2692:                        rc = ether_delmulti(ifr, &sc->sc_ic.ic_ac);
        !          2693:                if (rc != ENETRESET)
        !          2694:                        break;
        !          2695:                if (ifp->if_flags & IFF_RUNNING)
        !          2696:                        rtw_pktfilt_load(sc);
        !          2697:                rc = 0;
        !          2698:                break;
        !          2699:        default:
        !          2700:                if ((rc = ieee80211_ioctl(ifp, cmd, data)) == ENETRESET) {
        !          2701:                        if ((sc->sc_flags & RTW_F_ENABLED) != 0)
        !          2702:                                rc = rtw_init(ifp);
        !          2703:                        else
        !          2704:                                rc = 0;
        !          2705:                }
        !          2706:                break;
        !          2707:        }
        !          2708:        splx(s);
        !          2709:        return rc;
        !          2710: }
        !          2711:
        !          2712: /* Select a transmit ring with at least one h/w and s/w descriptor free.
        !          2713:  * Return 0 on success, -1 on failure.
        !          2714:  */
        !          2715: int
        !          2716: rtw_txring_choose(struct rtw_softc *sc, struct rtw_txsoft_blk **tsbp,
        !          2717:     struct rtw_txdesc_blk **tdbp, int pri)
        !          2718: {
        !          2719:        struct rtw_txsoft_blk *tsb;
        !          2720:        struct rtw_txdesc_blk *tdb;
        !          2721:
        !          2722:        KASSERT(pri >= 0 && pri < RTW_NTXPRI);
        !          2723:
        !          2724:        tsb = &sc->sc_txsoft_blk[pri];
        !          2725:        tdb = &sc->sc_txdesc_blk[pri];
        !          2726:
        !          2727:        if (SIMPLEQ_EMPTY(&tsb->tsb_freeq) || tdb->tdb_nfree == 0) {
        !          2728:                if (tsb->tsb_tx_timer == 0)
        !          2729:                        tsb->tsb_tx_timer = 5;
        !          2730:                *tsbp = NULL;
        !          2731:                *tdbp = NULL;
        !          2732:                return -1;
        !          2733:        }
        !          2734:        *tsbp = tsb;
        !          2735:        *tdbp = tdb;
        !          2736:        return 0;
        !          2737: }
        !          2738:
        !          2739: struct mbuf *
        !          2740: rtw_80211_dequeue(struct rtw_softc *sc, struct ifqueue *ifq, int pri,
        !          2741:     struct rtw_txsoft_blk **tsbp, struct rtw_txdesc_blk **tdbp,
        !          2742:     struct ieee80211_node **nip, short *if_flagsp)
        !          2743: {
        !          2744:        struct mbuf *m;
        !          2745:
        !          2746:        if (IF_IS_EMPTY(ifq))
        !          2747:                return NULL;
        !          2748:        if (rtw_txring_choose(sc, tsbp, tdbp, pri) == -1) {
        !          2749:                DPRINTF(sc, RTW_DEBUG_XMIT_RSRC, ("%s: no ring %d descriptor\n",
        !          2750:                    __func__, pri));
        !          2751:                *if_flagsp |= IFF_OACTIVE;
        !          2752:                sc->sc_if.if_timer = 1;
        !          2753:                return NULL;
        !          2754:        }
        !          2755:        IF_DEQUEUE(ifq, m);
        !          2756:        *nip = (struct ieee80211_node *)m->m_pkthdr.rcvif;
        !          2757:        m->m_pkthdr.rcvif = NULL;
        !          2758:        return m;
        !          2759: }
        !          2760:
        !          2761: /* Point *mp at the next 802.11 frame to transmit.  Point *tsbp
        !          2762:  * at the driver's selection of transmit control block for the packet.
        !          2763:  */
        !          2764: int
        !          2765: rtw_dequeue(struct ifnet *ifp, struct rtw_txsoft_blk **tsbp,
        !          2766:     struct rtw_txdesc_blk **tdbp, struct mbuf **mp,
        !          2767:     struct ieee80211_node **nip)
        !          2768: {
        !          2769:        struct mbuf *m0;
        !          2770:        struct rtw_softc *sc;
        !          2771:        short *if_flagsp;
        !          2772:
        !          2773:        sc = (struct rtw_softc *)ifp->if_softc;
        !          2774:
        !          2775:        DPRINTF(sc, RTW_DEBUG_XMIT,
        !          2776:            ("%s: enter %s\n", sc->sc_dev.dv_xname, __func__));
        !          2777:
        !          2778:        if_flagsp = &ifp->if_flags;
        !          2779:
        !          2780:        if (sc->sc_ic.ic_state == IEEE80211_S_RUN &&
        !          2781:            (*mp = rtw_80211_dequeue(sc, &sc->sc_beaconq, RTW_TXPRIBCN, tsbp,
        !          2782:            tdbp, nip, if_flagsp)) != NULL) {
        !          2783:                DPRINTF(sc, RTW_DEBUG_XMIT, ("%s: dequeue beacon frame\n",
        !          2784:                    __func__));
        !          2785:                return 0;
        !          2786:        }
        !          2787:
        !          2788:        if ((*mp = rtw_80211_dequeue(sc, &sc->sc_ic.ic_mgtq, RTW_TXPRIMD, tsbp,
        !          2789:            tdbp, nip, if_flagsp)) != NULL) {
        !          2790:                DPRINTF(sc, RTW_DEBUG_XMIT, ("%s: dequeue mgt frame\n",
        !          2791:                    __func__));
        !          2792:                return 0;
        !          2793:        }
        !          2794:
        !          2795:        if (sc->sc_ic.ic_state != IEEE80211_S_RUN) {
        !          2796:                DPRINTF(sc, RTW_DEBUG_XMIT, ("%s: not running\n", __func__));
        !          2797:                return 0;
        !          2798:        }
        !          2799:
        !          2800:        if ((*mp = rtw_80211_dequeue(sc, &sc->sc_ic.ic_pwrsaveq, RTW_TXPRIHI,
        !          2801:            tsbp, tdbp, nip, if_flagsp)) != NULL) {
        !          2802:                DPRINTF(sc, RTW_DEBUG_XMIT, ("%s: dequeue pwrsave frame\n",
        !          2803:                    __func__));
        !          2804:                return 0;
        !          2805:        }
        !          2806:
        !          2807:        if (sc->sc_ic.ic_state != IEEE80211_S_RUN) {
        !          2808:                DPRINTF(sc, RTW_DEBUG_XMIT, ("%s: not running\n", __func__));
        !          2809:                return 0;
        !          2810:        }
        !          2811:
        !          2812:        *mp = NULL;
        !          2813:
        !          2814:        IFQ_POLL(&ifp->if_snd, m0);
        !          2815:        if (m0 == NULL) {
        !          2816:                DPRINTF(sc, RTW_DEBUG_XMIT, ("%s: no frame ready\n",
        !          2817:                    __func__));
        !          2818:                return 0;
        !          2819:        }
        !          2820:
        !          2821:        if (rtw_txring_choose(sc, tsbp, tdbp, RTW_TXPRIMD) == -1) {
        !          2822:                DPRINTF(sc, RTW_DEBUG_XMIT, ("%s: no descriptor\n", __func__));
        !          2823:                *if_flagsp |= IFF_OACTIVE;
        !          2824:                sc->sc_if.if_timer = 1;
        !          2825:                return 0;
        !          2826:        }
        !          2827:
        !          2828:        IFQ_DEQUEUE(&ifp->if_snd, m0);
        !          2829:        if (m0 == NULL) {
        !          2830:                DPRINTF(sc, RTW_DEBUG_XMIT, ("%s: no frame/ring ready\n",
        !          2831:                    __func__));
        !          2832:                return 0;
        !          2833:        }
        !          2834:        DPRINTF(sc, RTW_DEBUG_XMIT, ("%s: dequeue data frame\n", __func__));
        !          2835:        ifp->if_opackets++;
        !          2836: #if NBPFILTER > 0
        !          2837:        if (ifp->if_bpf)
        !          2838:                bpf_mtap(ifp->if_bpf, m0, BPF_DIRECTION_OUT);
        !          2839: #endif
        !          2840:        if ((m0 = ieee80211_encap(ifp, m0, nip)) == NULL) {
        !          2841:                DPRINTF(sc, RTW_DEBUG_XMIT,
        !          2842:                    ("%s: encap error\n", __func__));
        !          2843:                ifp->if_oerrors++;
        !          2844:                return -1;
        !          2845:        }
        !          2846:
        !          2847:        /* XXX should do WEP in hardware */
        !          2848:        if (sc->sc_ic.ic_flags & IEEE80211_F_WEPON) {
        !          2849:                if ((m0 = ieee80211_wep_crypt(ifp, m0, 1)) == NULL)
        !          2850:                        return -1;
        !          2851:        }
        !          2852:
        !          2853:        DPRINTF(sc, RTW_DEBUG_XMIT, ("%s: leave\n", __func__));
        !          2854:        *mp = m0;
        !          2855:        return 0;
        !          2856: }
        !          2857:
        !          2858: int
        !          2859: rtw_seg_too_short(bus_dmamap_t dmamap)
        !          2860: {
        !          2861:        int i;
        !          2862:        for (i = 0; i < dmamap->dm_nsegs; i++) {
        !          2863:                if (dmamap->dm_segs[i].ds_len < 4) {
        !          2864:                        printf("%s: segment too short\n", __func__);
        !          2865:                        return 1;
        !          2866:                }
        !          2867:        }
        !          2868:        return 0;
        !          2869: }
        !          2870:
        !          2871: /* TBD factor with atw_start */
        !          2872: struct mbuf *
        !          2873: rtw_dmamap_load_txbuf(bus_dma_tag_t dmat, bus_dmamap_t dmam, struct mbuf *chain,
        !          2874:     u_int ndescfree, short *ifflagsp, const char *dvname)
        !          2875: {
        !          2876:        int first, rc;
        !          2877:        struct mbuf *m, *m0;
        !          2878:
        !          2879:        m0 = chain;
        !          2880:
        !          2881:        /*
        !          2882:         * Load the DMA map.  Copy and try (once) again if the packet
        !          2883:         * didn't fit in the alloted number of segments.
        !          2884:         */
        !          2885:        for (first = 1;
        !          2886:             ((rc = bus_dmamap_load_mbuf(dmat, dmam, m0,
        !          2887:             BUS_DMA_WRITE|BUS_DMA_NOWAIT)) != 0 ||
        !          2888:             dmam->dm_nsegs > ndescfree || rtw_seg_too_short(dmam)) && first;
        !          2889:             first = 0) {
        !          2890:                if (rc == 0)
        !          2891:                        bus_dmamap_unload(dmat, dmam);
        !          2892:                MGETHDR(m, M_DONTWAIT, MT_DATA);
        !          2893:                if (m == NULL) {
        !          2894:                        printf("%s: unable to allocate Tx mbuf\n",
        !          2895:                            dvname);
        !          2896:                        break;
        !          2897:                }
        !          2898:                if (m0->m_pkthdr.len > MHLEN) {
        !          2899:                        MCLGET(m, M_DONTWAIT);
        !          2900:                        if ((m->m_flags & M_EXT) == 0) {
        !          2901:                                printf("%s: cannot allocate Tx cluster\n",
        !          2902:                                    dvname);
        !          2903:                                m_freem(m);
        !          2904:                                break;
        !          2905:                        }
        !          2906:                }
        !          2907:                m_copydata(m0, 0, m0->m_pkthdr.len, mtod(m, caddr_t));
        !          2908:                m->m_pkthdr.len = m->m_len = m0->m_pkthdr.len;
        !          2909:                m_freem(m0);
        !          2910:                m0 = m;
        !          2911:                m = NULL;
        !          2912:        }
        !          2913:        if (rc != 0) {
        !          2914:                printf("%s: cannot load Tx buffer, rc = %d\n", dvname, rc);
        !          2915:                m_freem(m0);
        !          2916:                return NULL;
        !          2917:        } else if (rtw_seg_too_short(dmam)) {
        !          2918:                printf("%s: cannot load Tx buffer, segment too short\n",
        !          2919:                    dvname);
        !          2920:                bus_dmamap_unload(dmat, dmam);
        !          2921:                m_freem(m0);
        !          2922:                return NULL;
        !          2923:        } else if (dmam->dm_nsegs > ndescfree) {
        !          2924:                printf("%s: too many tx segments\n", dvname);
        !          2925:                bus_dmamap_unload(dmat, dmam);
        !          2926:                m_freem(m0);
        !          2927:                return NULL;
        !          2928:        }
        !          2929:        return m0;
        !          2930: }
        !          2931:
        !          2932:
        !          2933: /*
        !          2934:  * Arguments in:
        !          2935:  *
        !          2936:  * paylen:  payload length (no FCS, no WEP header)
        !          2937:  *
        !          2938:  * hdrlen:  header length
        !          2939:  *
        !          2940:  * rate:    MSDU speed, units 500kb/s
        !          2941:  *
        !          2942:  * flags:   IEEE80211_F_SHPREAMBLE (use short preamble),
        !          2943:  *          IEEE80211_F_SHSLOT (use short slot length)
        !          2944:  *
        !          2945:  * Arguments out:
        !          2946:  *
        !          2947:  * d:       802.11 Duration field for RTS,
        !          2948:  *          802.11 Duration field for data frame,
        !          2949:  *          PLCP Length for data frame,
        !          2950:  *          residual octets at end of data slot
        !          2951:  */
        !          2952: int
        !          2953: rtw_compute_duration1(int len, int use_ack, uint32_t flags, int rate,
        !          2954:     struct rtw_duration *d)
        !          2955: {
        !          2956:        int pre, ctsrate;
        !          2957:        int ack, bitlen, data_dur, remainder;
        !          2958:
        !          2959:        /* RTS reserves medium for SIFS | CTS | SIFS | (DATA) | SIFS | ACK
        !          2960:         * DATA reserves medium for SIFS | ACK
        !          2961:         *
        !          2962:         * XXXMYC: no ACK on multicast/broadcast or control packets
        !          2963:         */
        !          2964:
        !          2965:        bitlen = len * 8;
        !          2966:
        !          2967:        pre = IEEE80211_DUR_DS_SIFS;
        !          2968:        if ((flags & IEEE80211_F_SHPREAMBLE) != 0)
        !          2969:                pre += IEEE80211_DUR_DS_SHORT_PREAMBLE +
        !          2970:                    IEEE80211_DUR_DS_FAST_PLCPHDR;
        !          2971:        else
        !          2972:                pre += IEEE80211_DUR_DS_LONG_PREAMBLE +
        !          2973:                    IEEE80211_DUR_DS_SLOW_PLCPHDR;
        !          2974:
        !          2975:        d->d_residue = 0;
        !          2976:        data_dur = (bitlen * 2) / rate;
        !          2977:        remainder = (bitlen * 2) % rate;
        !          2978:        if (remainder != 0) {
        !          2979:                d->d_residue = (rate - remainder) / 16;
        !          2980:                data_dur++;
        !          2981:        }
        !          2982:
        !          2983:        switch (rate) {
        !          2984:        case 2:         /* 1 Mb/s */
        !          2985:        case 4:         /* 2 Mb/s */
        !          2986:                /* 1 - 2 Mb/s WLAN: send ACK/CTS at 1 Mb/s */
        !          2987:                ctsrate = 2;
        !          2988:                break;
        !          2989:        case 11:        /* 5.5 Mb/s */
        !          2990:        case 22:        /* 11  Mb/s */
        !          2991:        case 44:        /* 22  Mb/s */
        !          2992:                /* 5.5 - 11 Mb/s WLAN: send ACK/CTS at 2 Mb/s */
        !          2993:                ctsrate = 4;
        !          2994:                break;
        !          2995:        default:
        !          2996:                /* TBD */
        !          2997:                return -1;
        !          2998:        }
        !          2999:
        !          3000:        d->d_plcp_len = data_dur;
        !          3001:
        !          3002:        ack = (use_ack) ? pre + (IEEE80211_DUR_DS_SLOW_ACK * 2) / ctsrate : 0;
        !          3003:
        !          3004:        d->d_rts_dur =
        !          3005:            pre + (IEEE80211_DUR_DS_SLOW_CTS * 2) / ctsrate +
        !          3006:            pre + data_dur +
        !          3007:            ack;
        !          3008:
        !          3009:        d->d_data_dur = ack;
        !          3010:
        !          3011:        return 0;
        !          3012: }
        !          3013:
        !          3014: /*
        !          3015:  * Arguments in:
        !          3016:  *
        !          3017:  * wh:      802.11 header
        !          3018:  *
        !          3019:  * len: packet length
        !          3020:  *
        !          3021:  * rate:    MSDU speed, units 500kb/s
        !          3022:  *
        !          3023:  * fraglen: fragment length, set to maximum (or higher) for no
        !          3024:  *          fragmentation
        !          3025:  *
        !          3026:  * flags:   IEEE80211_F_WEPON (hardware adds WEP),
        !          3027:  *          IEEE80211_F_SHPREAMBLE (use short preamble),
        !          3028:  *          IEEE80211_F_SHSLOT (use short slot length)
        !          3029:  *
        !          3030:  * Arguments out:
        !          3031:  *
        !          3032:  * d0: 802.11 Duration fields (RTS/Data), PLCP Length, Service fields
        !          3033:  *     of first/only fragment
        !          3034:  *
        !          3035:  * dn: 802.11 Duration fields (RTS/Data), PLCP Length, Service fields
        !          3036:  *     of first/only fragment
        !          3037:  */
        !          3038: int
        !          3039: rtw_compute_duration(struct ieee80211_frame *wh, int len, uint32_t flags,
        !          3040:     int fraglen, int rate, struct rtw_duration *d0, struct rtw_duration *dn,
        !          3041:     int *npktp, int debug)
        !          3042: {
        !          3043:        int ack, rc;
        !          3044:        int firstlen, hdrlen, lastlen, lastlen0, npkt, overlen, paylen;
        !          3045:
        !          3046:        if ((wh->i_fc[1] & IEEE80211_FC1_DIR_MASK) == IEEE80211_FC1_DIR_DSTODS)
        !          3047:                hdrlen = sizeof(struct ieee80211_frame_addr4);
        !          3048:        else
        !          3049:                hdrlen = sizeof(struct ieee80211_frame);
        !          3050:
        !          3051:        paylen = len - hdrlen;
        !          3052:
        !          3053:        if ((flags & IEEE80211_F_WEPON) != 0)
        !          3054:                overlen = IEEE80211_WEP_TOTLEN + IEEE80211_CRC_LEN;
        !          3055:        else
        !          3056:                overlen = IEEE80211_CRC_LEN;
        !          3057:
        !          3058:        npkt = paylen / fraglen;
        !          3059:        lastlen0 = paylen % fraglen;
        !          3060:
        !          3061:        if (npkt == 0)                  /* no fragments */
        !          3062:                lastlen = paylen + overlen;
        !          3063:        else if (lastlen0 != 0) {       /* a short "tail" fragment */
        !          3064:                lastlen = lastlen0 + overlen;
        !          3065:                npkt++;
        !          3066:        } else                          /* full-length "tail" fragment */
        !          3067:                lastlen = fraglen + overlen;
        !          3068:
        !          3069:        if (npktp != NULL)
        !          3070:                *npktp = npkt;
        !          3071:
        !          3072:        if (npkt > 1)
        !          3073:                firstlen = fraglen + overlen;
        !          3074:        else
        !          3075:                firstlen = paylen + overlen;
        !          3076:
        !          3077:        if (debug) {
        !          3078:                printf("%s: npkt %d firstlen %d lastlen0 %d lastlen %d "
        !          3079:                    "fraglen %d overlen %d len %d rate %d flags %08x\n",
        !          3080:                    __func__, npkt, firstlen, lastlen0, lastlen, fraglen,
        !          3081:                    overlen, len, rate, flags);
        !          3082:        }
        !          3083:
        !          3084:        ack = !IEEE80211_IS_MULTICAST(wh->i_addr1) &&
        !          3085:            (wh->i_fc[1] & IEEE80211_FC0_TYPE_MASK) != IEEE80211_FC0_TYPE_CTL;
        !          3086:
        !          3087:        rc = rtw_compute_duration1(firstlen + hdrlen, ack, flags, rate, d0);
        !          3088:        if (rc == -1)
        !          3089:                return rc;
        !          3090:
        !          3091:        if (npkt <= 1) {
        !          3092:                *dn = *d0;
        !          3093:                return 0;
        !          3094:        }
        !          3095:        return rtw_compute_duration1(lastlen + hdrlen, ack, flags, rate, dn);
        !          3096: }
        !          3097:
        !          3098: #ifdef RTW_DEBUG
        !          3099: void
        !          3100: rtw_print_txdesc(struct rtw_softc *sc, const char *action,
        !          3101:     struct rtw_txsoft *ts, struct rtw_txdesc_blk *tdb, int desc)
        !          3102: {
        !          3103:        struct rtw_txdesc *td = &tdb->tdb_desc[desc];
        !          3104:        DPRINTF(sc, RTW_DEBUG_XMIT_DESC, ("%s: %p %s txdesc[%d] next %#08x "
        !          3105:            "buf %#08x ctl0 %#08x ctl1 %#08x len %#08x\n",
        !          3106:            sc->sc_dev.dv_xname, ts, action, desc,
        !          3107:            letoh32(td->td_buf), letoh32(td->td_next),
        !          3108:            letoh32(td->td_ctl0), letoh32(td->td_ctl1),
        !          3109:            letoh32(td->td_len)));
        !          3110: }
        !          3111: #endif /* RTW_DEBUG */
        !          3112:
        !          3113: void
        !          3114: rtw_start(struct ifnet *ifp)
        !          3115: {
        !          3116:        uint8_t tppoll;
        !          3117:        int desc, i, lastdesc, npkt, rate;
        !          3118:        uint32_t proto_ctl0, ctl0, ctl1;
        !          3119:        bus_dmamap_t            dmamap;
        !          3120:        struct ieee80211com     *ic;
        !          3121:        struct ieee80211_frame  *wh;
        !          3122:        struct ieee80211_node   *ni;
        !          3123:        struct mbuf             *m0;
        !          3124:        struct rtw_softc        *sc;
        !          3125:        struct rtw_duration     *d0;
        !          3126:        struct rtw_txsoft_blk   *tsb;
        !          3127:        struct rtw_txdesc_blk   *tdb;
        !          3128:        struct rtw_txsoft       *ts;
        !          3129:        struct rtw_txdesc       *td;
        !          3130:
        !          3131:        sc = (struct rtw_softc *)ifp->if_softc;
        !          3132:        ic = &sc->sc_ic;
        !          3133:
        !          3134:        DPRINTF(sc, RTW_DEBUG_XMIT,
        !          3135:            ("%s: enter %s\n", sc->sc_dev.dv_xname, __func__));
        !          3136:
        !          3137:        if ((ifp->if_flags & (IFF_RUNNING|IFF_OACTIVE)) != IFF_RUNNING)
        !          3138:                goto out;
        !          3139:
        !          3140:        /* XXX do real rate control */
        !          3141:        proto_ctl0 = RTW_TXCTL0_RTSRATE_1MBPS;
        !          3142:
        !          3143:        if ((ic->ic_flags & IEEE80211_F_SHPREAMBLE) != 0)
        !          3144:                proto_ctl0 |= RTW_TXCTL0_SPLCP;
        !          3145:
        !          3146:        for (;;) {
        !          3147:                if (rtw_dequeue(ifp, &tsb, &tdb, &m0, &ni) == -1)
        !          3148:                        continue;
        !          3149:                if (m0 == NULL)
        !          3150:                        break;
        !          3151:                ts = SIMPLEQ_FIRST(&tsb->tsb_freeq);
        !          3152:
        !          3153:                dmamap = ts->ts_dmamap;
        !          3154:
        !          3155:                m0 = rtw_dmamap_load_txbuf(sc->sc_dmat, dmamap, m0,
        !          3156:                    tdb->tdb_nfree, &ifp->if_flags, sc->sc_dev.dv_xname);
        !          3157:
        !          3158:                if (m0 == NULL || dmamap->dm_nsegs == 0) {
        !          3159:                        DPRINTF(sc, RTW_DEBUG_XMIT,
        !          3160:                            ("%s: fail dmamap load\n", __func__));
        !          3161:                        goto post_dequeue_err;
        !          3162:                }
        !          3163:
        !          3164:                wh = mtod(m0, struct ieee80211_frame *);
        !          3165:
        !          3166:                /* XXX do real rate control */
        !          3167:                if ((wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK) ==
        !          3168:                    IEEE80211_FC0_TYPE_MGT)
        !          3169:                        rate = 2;
        !          3170:                else
        !          3171:                        rate = MAX(2, ieee80211_get_rate(ic));
        !          3172:
        !          3173: #ifdef RTW_DEBUG
        !          3174:                if ((sc->sc_if.if_flags & (IFF_DEBUG|IFF_LINK2)) ==
        !          3175:                    (IFF_DEBUG|IFF_LINK2)) {
        !          3176:                        ieee80211_dump_pkt(mtod(m0, uint8_t *),
        !          3177:                            (dmamap->dm_nsegs == 1) ? m0->m_pkthdr.len
        !          3178:                            : sizeof(wh), rate, 0);
        !          3179:                }
        !          3180: #endif /* RTW_DEBUG */
        !          3181:                ctl0 = proto_ctl0 |
        !          3182:                    LSHIFT(m0->m_pkthdr.len, RTW_TXCTL0_TPKTSIZE_MASK);
        !          3183:
        !          3184:                switch (rate) {
        !          3185:                default:
        !          3186:                case 2:
        !          3187:                        ctl0 |= RTW_TXCTL0_RATE_1MBPS;
        !          3188:                        break;
        !          3189:                case 4:
        !          3190:                        ctl0 |= RTW_TXCTL0_RATE_2MBPS;
        !          3191:                        break;
        !          3192:                case 11:
        !          3193:                        ctl0 |= RTW_TXCTL0_RATE_5MBPS;
        !          3194:                        break;
        !          3195:                case 22:
        !          3196:                        ctl0 |= RTW_TXCTL0_RATE_11MBPS;
        !          3197:                        break;
        !          3198:                }
        !          3199:
        !          3200:                /* XXX >= ? Compare after fragmentation? */
        !          3201:                if (m0->m_pkthdr.len > ic->ic_rtsthreshold)
        !          3202:                        ctl0 |= RTW_TXCTL0_RTSEN;
        !          3203:
        !          3204:                if ((wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK) ==
        !          3205:                    IEEE80211_FC0_TYPE_MGT) {
        !          3206:                        ctl0 &= ~(RTW_TXCTL0_SPLCP | RTW_TXCTL0_RTSEN);
        !          3207:                        if ((wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK) ==
        !          3208:                            IEEE80211_FC0_SUBTYPE_BEACON)
        !          3209:                                ctl0 |= RTW_TXCTL0_BEACON;
        !          3210:                }
        !          3211:
        !          3212:                if (rtw_compute_duration(wh, m0->m_pkthdr.len,
        !          3213:                    ic->ic_flags & ~IEEE80211_F_WEPON, ic->ic_fragthreshold,
        !          3214:                    rate, &ts->ts_d0, &ts->ts_dn, &npkt,
        !          3215:                    (sc->sc_if.if_flags & (IFF_DEBUG|IFF_LINK2)) ==
        !          3216:                    (IFF_DEBUG|IFF_LINK2)) == -1) {
        !          3217:                        DPRINTF(sc, RTW_DEBUG_XMIT,
        !          3218:                            ("%s: fail compute duration\n", __func__));
        !          3219:                        goto post_load_err;
        !          3220:                }
        !          3221:
        !          3222:                d0 = &ts->ts_d0;
        !          3223:
        !          3224:                *(uint16_t*)wh->i_dur = htole16(d0->d_data_dur);
        !          3225:
        !          3226:                ctl1 = LSHIFT(d0->d_plcp_len, RTW_TXCTL1_LENGTH_MASK) |
        !          3227:                    LSHIFT(d0->d_rts_dur, RTW_TXCTL1_RTSDUR_MASK);
        !          3228:
        !          3229:                if (d0->d_residue)
        !          3230:                        ctl1 |= RTW_TXCTL1_LENGEXT;
        !          3231:
        !          3232:                /* TBD fragmentation */
        !          3233:
        !          3234:                ts->ts_first = tdb->tdb_next;
        !          3235:
        !          3236:                rtw_txdescs_sync(tdb, ts->ts_first, dmamap->dm_nsegs,
        !          3237:                    BUS_DMASYNC_PREWRITE);
        !          3238:
        !          3239:                KASSERT(ts->ts_first < tdb->tdb_ndesc);
        !          3240:
        !          3241: #if NBPFILTER > 0
        !          3242:                if (ic->ic_rawbpf != NULL)
        !          3243:                        bpf_mtap((caddr_t)ic->ic_rawbpf, m0,
        !          3244:                            BPF_DIRECTION_OUT);
        !          3245:
        !          3246:                if (sc->sc_radiobpf != NULL) {
        !          3247:                        struct mbuf mb;
        !          3248:                        struct rtw_tx_radiotap_header *rt = &sc->sc_txtap;
        !          3249:
        !          3250:                        rt->rt_flags = 0;
        !          3251:                        rt->rt_rate = rate;
        !          3252:                        rt->rt_chan_freq =
        !          3253:                            htole16(ic->ic_bss->ni_chan->ic_freq);
        !          3254:                        rt->rt_chan_flags =
        !          3255:                            htole16(ic->ic_bss->ni_chan->ic_flags);
        !          3256:
        !          3257:                        mb.m_data = (caddr_t)rt;
        !          3258:                        mb.m_len = sizeof(sc->sc_txtapu);
        !          3259:                        mb.m_next = m0;
        !          3260:                        mb.m_nextpkt = NULL;
        !          3261:                        mb.m_type = 0;
        !          3262:                        mb.m_flags = 0;
        !          3263:                        bpf_mtap(sc->sc_radiobpf, &mb, BPF_DIRECTION_OUT);
        !          3264:
        !          3265:                }
        !          3266: #endif /* NPBFILTER > 0 */
        !          3267:
        !          3268:                for (i = 0, lastdesc = desc = ts->ts_first;
        !          3269:                     i < dmamap->dm_nsegs;
        !          3270:                     i++, desc = RTW_NEXT_IDX(tdb, desc)) {
        !          3271:                        if (dmamap->dm_segs[i].ds_len > RTW_TXLEN_LENGTH_MASK) {
        !          3272:                                DPRINTF(sc, RTW_DEBUG_XMIT_DESC,
        !          3273:                                    ("%s: seg too long\n", __func__));
        !          3274:                                goto post_load_err;
        !          3275:                        }
        !          3276:                        td = &tdb->tdb_desc[desc];
        !          3277:                        td->td_ctl0 = htole32(ctl0);
        !          3278:                        if (i != 0)
        !          3279:                                td->td_ctl0 |= htole32(RTW_TXCTL0_OWN);
        !          3280:                        td->td_ctl1 = htole32(ctl1);
        !          3281:                        td->td_buf = htole32(dmamap->dm_segs[i].ds_addr);
        !          3282:                        td->td_len = htole32(dmamap->dm_segs[i].ds_len);
        !          3283:                        lastdesc = desc;
        !          3284: #ifdef RTW_DEBUG
        !          3285:                        rtw_print_txdesc(sc, "load", ts, tdb, desc);
        !          3286: #endif /* RTW_DEBUG */
        !          3287:                }
        !          3288:
        !          3289:                KASSERT(desc < tdb->tdb_ndesc);
        !          3290:
        !          3291:                ts->ts_ni = ni;
        !          3292:                ts->ts_mbuf = m0;
        !          3293:                ts->ts_last = lastdesc;
        !          3294:                tdb->tdb_desc[ts->ts_last].td_ctl0 |= htole32(RTW_TXCTL0_LS);
        !          3295:                tdb->tdb_desc[ts->ts_first].td_ctl0 |=
        !          3296:                    htole32(RTW_TXCTL0_FS);
        !          3297:
        !          3298: #ifdef RTW_DEBUG
        !          3299:                rtw_print_txdesc(sc, "FS on", ts, tdb, ts->ts_first);
        !          3300:                rtw_print_txdesc(sc, "LS on", ts, tdb, ts->ts_last);
        !          3301: #endif /* RTW_DEBUG */
        !          3302:
        !          3303:                tdb->tdb_nfree -= dmamap->dm_nsegs;
        !          3304:                tdb->tdb_next = desc;
        !          3305:
        !          3306:                rtw_txdescs_sync(tdb, ts->ts_first, dmamap->dm_nsegs,
        !          3307:                    BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE);
        !          3308:
        !          3309:                tdb->tdb_desc[ts->ts_first].td_ctl0 |=
        !          3310:                    htole32(RTW_TXCTL0_OWN);
        !          3311:
        !          3312: #ifdef RTW_DEBUG
        !          3313:                rtw_print_txdesc(sc, "OWN on", ts, tdb, ts->ts_first);
        !          3314: #endif /* RTW_DEBUG */
        !          3315:
        !          3316:                rtw_txdescs_sync(tdb, ts->ts_first, 1,
        !          3317:                    BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE);
        !          3318:
        !          3319:                SIMPLEQ_REMOVE_HEAD(&tsb->tsb_freeq, ts_q);
        !          3320:                SIMPLEQ_INSERT_TAIL(&tsb->tsb_dirtyq, ts, ts_q);
        !          3321:
        !          3322:                if (tsb != &sc->sc_txsoft_blk[RTW_TXPRIBCN])
        !          3323:                        sc->sc_led_state.ls_event |= RTW_LED_S_TX;
        !          3324:                tsb->tsb_tx_timer = 5;
        !          3325:                ifp->if_timer = 1;
        !          3326:                tppoll = RTW_READ8(&sc->sc_regs, RTW_TPPOLL);
        !          3327:                tppoll &= ~RTW_TPPOLL_SALL;
        !          3328:                tppoll |= tsb->tsb_poll & RTW_TPPOLL_ALL;
        !          3329:                RTW_WRITE8(&sc->sc_regs, RTW_TPPOLL, tppoll);
        !          3330:                RTW_SYNC(&sc->sc_regs, RTW_TPPOLL, RTW_TPPOLL);
        !          3331:        }
        !          3332: out:
        !          3333:        DPRINTF(sc, RTW_DEBUG_XMIT, ("%s: leave\n", __func__));
        !          3334:        return;
        !          3335: post_load_err:
        !          3336:        bus_dmamap_unload(sc->sc_dmat, dmamap);
        !          3337:        m_freem(m0);
        !          3338: post_dequeue_err:
        !          3339:        ieee80211_release_node(&sc->sc_ic, ni);
        !          3340:        return;
        !          3341: }
        !          3342:
        !          3343: void
        !          3344: rtw_idle(struct rtw_regs *regs)
        !          3345: {
        !          3346:        int active;
        !          3347:
        !          3348:        /* request stop DMA; wait for packets to stop transmitting. */
        !          3349:
        !          3350:        RTW_WRITE8(regs, RTW_TPPOLL, RTW_TPPOLL_SALL);
        !          3351:        RTW_WBR(regs, RTW_TPPOLL, RTW_TPPOLL);
        !          3352:
        !          3353:        for (active = 0; active < 300 &&
        !          3354:             (RTW_READ8(regs, RTW_TPPOLL) & RTW_TPPOLL_ACTIVE) != 0; active++)
        !          3355:                DELAY(10);
        !          3356:        RTW_DPRINTF(RTW_DEBUG_BUGS,
        !          3357:            ("%s: transmit DMA idle in %dus\n", __func__, active * 10));
        !          3358: }
        !          3359:
        !          3360: void
        !          3361: rtw_watchdog(struct ifnet *ifp)
        !          3362: {
        !          3363:        int pri, tx_timeouts = 0;
        !          3364:        struct rtw_softc *sc;
        !          3365:        struct rtw_txsoft_blk *tsb;
        !          3366:
        !          3367:        sc = ifp->if_softc;
        !          3368:
        !          3369:        ifp->if_timer = 0;
        !          3370:
        !          3371:        if ((sc->sc_flags & RTW_F_ENABLED) == 0)
        !          3372:                return;
        !          3373:
        !          3374:        for (pri = 0; pri < RTW_NTXPRI; pri++) {
        !          3375:                tsb = &sc->sc_txsoft_blk[pri];
        !          3376:
        !          3377:                if (tsb->tsb_tx_timer == 0)
        !          3378:                        continue;
        !          3379:                else if (--tsb->tsb_tx_timer == 0) {
        !          3380:                        if (SIMPLEQ_EMPTY(&tsb->tsb_dirtyq))
        !          3381:                                continue;
        !          3382:                        RTW_DPRINTF(RTW_DEBUG_BUGS,
        !          3383:                            ("%s: transmit timeout, priority %d\n",
        !          3384:                            ifp->if_xname, pri));
        !          3385:                        ifp->if_oerrors++;
        !          3386:                        tx_timeouts++;
        !          3387:                } else
        !          3388:                        ifp->if_timer = 1;
        !          3389:        }
        !          3390:
        !          3391:        if (tx_timeouts > 0) {
        !          3392:                /* Stop Tx DMA, disable xmtr, flush Tx rings, enable xmtr,
        !          3393:                 * reset s/w tx-ring pointers, and start transmission.
        !          3394:                 *
        !          3395:                 * TBD Stop/restart just the broken rings?
        !          3396:                 */
        !          3397:                rtw_idle(&sc->sc_regs);
        !          3398:                rtw_io_enable(&sc->sc_regs, RTW_CR_TE, 0);
        !          3399:                rtw_txdescs_reset(sc);
        !          3400:                rtw_io_enable(&sc->sc_regs, RTW_CR_TE, 1);
        !          3401:                rtw_txring_fixup(sc);
        !          3402:                rtw_start(ifp);
        !          3403:        }
        !          3404:        ieee80211_watchdog(ifp);
        !          3405: }
        !          3406:
        !          3407: void
        !          3408: rtw_next_scan(void *arg)
        !          3409: {
        !          3410:        struct rtw_softc *sc = arg;
        !          3411:        struct ieee80211com *ic = &sc->sc_ic;
        !          3412:        struct ifnet *ifp = &ic->ic_if;
        !          3413:        int s;
        !          3414:
        !          3415:        /* don't call rtw_start w/o network interrupts blocked */
        !          3416:        s = splnet();
        !          3417:        if (ic->ic_state == IEEE80211_S_SCAN)
        !          3418:                ieee80211_next_scan(ifp);
        !          3419:        splx(s);
        !          3420: }
        !          3421:
        !          3422: void
        !          3423: rtw_join_bss(struct rtw_softc *sc, u_int8_t *bssid, u_int16_t intval0)
        !          3424: {
        !          3425:        uint16_t bcnitv, bintritv, intval;
        !          3426:        int i;
        !          3427:        struct rtw_regs *regs = &sc->sc_regs;
        !          3428:
        !          3429:        for (i = 0; i < IEEE80211_ADDR_LEN; i++)
        !          3430:                RTW_WRITE8(regs, RTW_BSSID + i, bssid[i]);
        !          3431:
        !          3432:        RTW_SYNC(regs, RTW_BSSID16, RTW_BSSID32);
        !          3433:
        !          3434:        rtw_set_access(regs, RTW_ACCESS_CONFIG);
        !          3435:
        !          3436:        intval = MIN(intval0, PRESHIFT(RTW_BCNITV_BCNITV_MASK));
        !          3437:
        !          3438:        bcnitv = RTW_READ16(regs, RTW_BCNITV) & ~RTW_BCNITV_BCNITV_MASK;
        !          3439:        bcnitv |= LSHIFT(intval, RTW_BCNITV_BCNITV_MASK);
        !          3440:        RTW_WRITE16(regs, RTW_BCNITV, bcnitv);
        !          3441:        /* interrupt host 1ms before the TBTT */
        !          3442:        bintritv = RTW_READ16(regs, RTW_BINTRITV) & ~RTW_BINTRITV_BINTRITV;
        !          3443:        bintritv |= LSHIFT(1000, RTW_BINTRITV_BINTRITV);
        !          3444:        RTW_WRITE16(regs, RTW_BINTRITV, bintritv);
        !          3445:        /* magic from Linux */
        !          3446:        RTW_WRITE16(regs, RTW_ATIMWND, LSHIFT(1, RTW_ATIMWND_ATIMWND));
        !          3447:        RTW_WRITE16(regs, RTW_ATIMTRITV, LSHIFT(2, RTW_ATIMTRITV_ATIMTRITV));
        !          3448:        rtw_set_access(regs, RTW_ACCESS_NONE);
        !          3449:
        !          3450:        /* TBD WEP */
        !          3451:        RTW_WRITE8(regs, RTW8180_SCR, 0);
        !          3452:
        !          3453:        rtw_io_enable(regs, RTW_CR_RE | RTW_CR_TE, 1);
        !          3454: }
        !          3455:
        !          3456: /* Synchronize the hardware state with the software state. */
        !          3457: int
        !          3458: rtw_newstate(struct ieee80211com *ic, enum ieee80211_state nstate, int arg)
        !          3459: {
        !          3460:        struct ifnet *ifp = &ic->ic_if;
        !          3461:        struct rtw_softc *sc = ifp->if_softc;
        !          3462:        enum ieee80211_state ostate;
        !          3463:        int error;
        !          3464:
        !          3465:        ostate = ic->ic_state;
        !          3466:
        !          3467:        rtw_led_newstate(sc, nstate);
        !          3468:
        !          3469:        if (nstate == IEEE80211_S_INIT) {
        !          3470:                timeout_del(&sc->sc_scan_to);
        !          3471:                sc->sc_cur_chan = IEEE80211_CHAN_ANY;
        !          3472:                return (*sc->sc_mtbl.mt_newstate)(ic, nstate, arg);
        !          3473:        }
        !          3474:
        !          3475:        if (ostate == IEEE80211_S_INIT && nstate != IEEE80211_S_INIT)
        !          3476:                rtw_pwrstate(sc, RTW_ON);
        !          3477:
        !          3478:        if ((error = rtw_tune(sc)) != 0)
        !          3479:                return error;
        !          3480:
        !          3481:        switch (nstate) {
        !          3482:        case IEEE80211_S_INIT:
        !          3483:                panic("%s: unexpected state IEEE80211_S_INIT", __func__);
        !          3484:                break;
        !          3485:        case IEEE80211_S_SCAN:
        !          3486:                if (ostate != IEEE80211_S_SCAN) {
        !          3487:                        bzero(ic->ic_bss->ni_bssid, IEEE80211_ADDR_LEN);
        !          3488:                        rtw_set_nettype(sc, IEEE80211_M_MONITOR);
        !          3489:                }
        !          3490:
        !          3491:                timeout_add(&sc->sc_scan_to, rtw_dwelltime * hz / 1000);
        !          3492:
        !          3493:                break;
        !          3494:        case IEEE80211_S_RUN:
        !          3495:                switch (ic->ic_opmode) {
        !          3496:                case IEEE80211_M_HOSTAP:
        !          3497:                case IEEE80211_M_IBSS:
        !          3498:                        rtw_set_nettype(sc, IEEE80211_M_MONITOR);
        !          3499:                        /*FALLTHROUGH*/
        !          3500:                case IEEE80211_M_AHDEMO:
        !          3501:                case IEEE80211_M_STA:
        !          3502:                        rtw_join_bss(sc, ic->ic_bss->ni_bssid,
        !          3503:                            ic->ic_bss->ni_intval);
        !          3504:                        break;
        !          3505:                case IEEE80211_M_MONITOR:
        !          3506:                        break;
        !          3507:                }
        !          3508:                rtw_set_nettype(sc, ic->ic_opmode);
        !          3509:                break;
        !          3510:        case IEEE80211_S_ASSOC:
        !          3511:        case IEEE80211_S_AUTH:
        !          3512:                break;
        !          3513:        }
        !          3514:
        !          3515:        if (nstate != IEEE80211_S_SCAN)
        !          3516:                timeout_del(&sc->sc_scan_to);
        !          3517:
        !          3518:        return (*sc->sc_mtbl.mt_newstate)(ic, nstate, arg);
        !          3519: }
        !          3520:
        !          3521: /* Extend a 32-bit TSF timestamp to a 64-bit timestamp. */
        !          3522: uint64_t
        !          3523: rtw_tsf_extend(struct rtw_regs *regs, u_int32_t rstamp)
        !          3524: {
        !          3525:        u_int32_t tsftl, tsfth;
        !          3526:
        !          3527:        tsfth = RTW_READ(regs, RTW_TSFTRH);
        !          3528:        tsftl = RTW_READ(regs, RTW_TSFTRL);
        !          3529:        if (tsftl < rstamp)     /* Compensate for rollover. */
        !          3530:                tsfth--;
        !          3531:        return ((u_int64_t)tsfth << 32) | rstamp;
        !          3532: }
        !          3533:
        !          3534: void
        !          3535: rtw_ibss_merge(struct rtw_softc *sc, struct ieee80211_node *ni,
        !          3536:     u_int32_t rstamp)
        !          3537: {
        !          3538:        u_int8_t tppoll;
        !          3539:        struct ieee80211com *ic = &sc->sc_ic;
        !          3540:
        !          3541:        if (ieee80211_ibss_merge(ic, ni,
        !          3542:            rtw_tsf_extend(&sc->sc_regs, rstamp)) == ENETRESET) {
        !          3543:                /* Stop beacon queue.  Kick state machine to synchronize
        !          3544:                 * with the new IBSS.
        !          3545:                 */
        !          3546:                tppoll = RTW_READ8(&sc->sc_regs, RTW_TPPOLL);
        !          3547:                tppoll |= RTW_TPPOLL_SBQ;
        !          3548:                RTW_WRITE8(&sc->sc_regs, RTW_TPPOLL, tppoll);
        !          3549:                (void)ieee80211_new_state(&sc->sc_ic, IEEE80211_S_RUN, -1);
        !          3550:        }
        !          3551:        return;
        !          3552: }
        !          3553:
        !          3554: void
        !          3555: rtw_recv_mgmt(struct ieee80211com *ic, struct mbuf *m,
        !          3556:     struct ieee80211_node *ni, int subtype, int rssi, u_int32_t rstamp)
        !          3557: {
        !          3558:        struct rtw_softc *sc = (struct rtw_softc*)ic->ic_softc;
        !          3559:
        !          3560:        (*sc->sc_mtbl.mt_recv_mgmt)(ic, m, ni, subtype, rssi, rstamp);
        !          3561:
        !          3562:        switch (subtype) {
        !          3563:        case IEEE80211_FC0_SUBTYPE_PROBE_RESP:
        !          3564:        case IEEE80211_FC0_SUBTYPE_BEACON:
        !          3565:                if (ic->ic_opmode != IEEE80211_M_IBSS ||
        !          3566:                    ic->ic_state != IEEE80211_S_RUN)
        !          3567:                        return;
        !          3568:                rtw_ibss_merge(sc, ni, rstamp);
        !          3569:                break;
        !          3570:        default:
        !          3571:                break;
        !          3572:        }
        !          3573:        return;
        !          3574: }
        !          3575:
        !          3576: struct ieee80211_node *
        !          3577: rtw_node_alloc(struct ieee80211com *ic)
        !          3578: {
        !          3579:        struct rtw_softc *sc = (struct rtw_softc *)ic->ic_if.if_softc;
        !          3580:        struct ieee80211_node *ni = (*sc->sc_mtbl.mt_node_alloc)(ic);
        !          3581:
        !          3582:        DPRINTF(sc, RTW_DEBUG_NODE,
        !          3583:            ("%s: alloc node %p\n", sc->sc_dev.dv_xname, ni));
        !          3584:        return ni;
        !          3585: }
        !          3586:
        !          3587: void
        !          3588: rtw_node_free(struct ieee80211com *ic, struct ieee80211_node *ni)
        !          3589: {
        !          3590:        struct rtw_softc *sc = (struct rtw_softc *)ic->ic_if.if_softc;
        !          3591:
        !          3592:        DPRINTF(sc, RTW_DEBUG_NODE,
        !          3593:            ("%s: freeing node %p %s\n", sc->sc_dev.dv_xname, ni,
        !          3594:            ether_sprintf(ni->ni_bssid)));
        !          3595:        (*sc->sc_mtbl.mt_node_free)(ic, ni);
        !          3596: }
        !          3597:
        !          3598: int
        !          3599: rtw_media_change(struct ifnet *ifp)
        !          3600: {
        !          3601:        int error;
        !          3602:
        !          3603:        error = ieee80211_media_change(ifp);
        !          3604:        if (error == ENETRESET) {
        !          3605:                if ((ifp->if_flags & (IFF_RUNNING|IFF_UP)) ==
        !          3606:                    (IFF_RUNNING|IFF_UP))
        !          3607:                        rtw_init(ifp);          /* XXX lose error */
        !          3608:                error = 0;
        !          3609:        }
        !          3610:        return error;
        !          3611: }
        !          3612:
        !          3613: void
        !          3614: rtw_media_status(struct ifnet *ifp, struct ifmediareq *imr)
        !          3615: {
        !          3616:        struct rtw_softc *sc = ifp->if_softc;
        !          3617:
        !          3618:        if ((sc->sc_flags & RTW_F_ENABLED) == 0) {
        !          3619:                imr->ifm_active = IFM_IEEE80211 | IFM_NONE;
        !          3620:                imr->ifm_status = 0;
        !          3621:                return;
        !          3622:        }
        !          3623:        ieee80211_media_status(ifp, imr);
        !          3624: }
        !          3625:
        !          3626: void
        !          3627: rtw_power(int why, void *arg)
        !          3628: {
        !          3629:        struct rtw_softc *sc = arg;
        !          3630:        struct ifnet *ifp = &sc->sc_ic.ic_if;
        !          3631:        int s;
        !          3632:
        !          3633:        DPRINTF(sc, RTW_DEBUG_PWR,
        !          3634:            ("%s: rtw_power(%d,)\n", sc->sc_dev.dv_xname, why));
        !          3635:
        !          3636:        s = splnet();
        !          3637:        switch (why) {
        !          3638:        case PWR_STANDBY:
        !          3639:                /* XXX do nothing. */
        !          3640:                break;
        !          3641:        case PWR_SUSPEND:
        !          3642:                rtw_stop(ifp, 1);
        !          3643:                if (sc->sc_power != NULL)
        !          3644:                        (*sc->sc_power)(sc, why);
        !          3645:                break;
        !          3646:        case PWR_RESUME:
        !          3647:                if (ifp->if_flags & IFF_UP) {
        !          3648:                        if (sc->sc_power != NULL)
        !          3649:                                (*sc->sc_power)(sc, why);
        !          3650:                        rtw_init(ifp);
        !          3651:                }
        !          3652:                break;
        !          3653:        }
        !          3654:        splx(s);
        !          3655: }
        !          3656:
        !          3657: /* rtw_shutdown: make sure the interface is stopped at reboot time. */
        !          3658: void
        !          3659: rtw_shutdown(void *arg)
        !          3660: {
        !          3661:        struct rtw_softc *sc = arg;
        !          3662:
        !          3663:        rtw_stop(&sc->sc_ic.ic_if, 1);
        !          3664: }
        !          3665:
        !          3666: void
        !          3667: rtw_establish_hooks(struct rtw_hooks *hooks, const char *dvname,
        !          3668:     void *arg)
        !          3669: {
        !          3670:        /*
        !          3671:         * Make sure the interface is shutdown during reboot.
        !          3672:         */
        !          3673:        hooks->rh_shutdown = shutdownhook_establish(rtw_shutdown, arg);
        !          3674:        if (hooks->rh_shutdown == NULL)
        !          3675:                printf("%s: WARNING: unable to establish shutdown hook\n",
        !          3676:                    dvname);
        !          3677:
        !          3678:        /*
        !          3679:         * Add a suspend hook to make sure we come back up after a
        !          3680:         * resume.
        !          3681:         */
        !          3682:        hooks->rh_power = powerhook_establish(rtw_power, arg);
        !          3683:        if (hooks->rh_power == NULL)
        !          3684:                printf("%s: WARNING: unable to establish power hook\n",
        !          3685:                    dvname);
        !          3686: }
        !          3687:
        !          3688: void
        !          3689: rtw_disestablish_hooks(struct rtw_hooks *hooks, const char *dvname,
        !          3690:     void *arg)
        !          3691: {
        !          3692:        if (hooks->rh_shutdown != NULL)
        !          3693:                shutdownhook_disestablish(hooks->rh_shutdown);
        !          3694:
        !          3695:        if (hooks->rh_power != NULL)
        !          3696:                powerhook_disestablish(hooks->rh_power);
        !          3697: }
        !          3698:
        !          3699: int
        !          3700: rtw_txsoft_blk_setup(struct rtw_txsoft_blk *tsb, u_int qlen)
        !          3701: {
        !          3702:        SIMPLEQ_INIT(&tsb->tsb_dirtyq);
        !          3703:        SIMPLEQ_INIT(&tsb->tsb_freeq);
        !          3704:        tsb->tsb_ndesc = qlen;
        !          3705:        tsb->tsb_desc = malloc(qlen * sizeof(*tsb->tsb_desc), M_DEVBUF,
        !          3706:            M_NOWAIT);
        !          3707:        if (tsb->tsb_desc == NULL)
        !          3708:                return ENOMEM;
        !          3709:        return 0;
        !          3710: }
        !          3711:
        !          3712: void
        !          3713: rtw_txsoft_blk_cleanup_all(struct rtw_softc *sc)
        !          3714: {
        !          3715:        int pri;
        !          3716:        struct rtw_txsoft_blk *tsb;
        !          3717:
        !          3718:        for (pri = 0; pri < RTW_NTXPRI; pri++) {
        !          3719:                tsb = &sc->sc_txsoft_blk[pri];
        !          3720:                free(tsb->tsb_desc, M_DEVBUF);
        !          3721:                tsb->tsb_desc = NULL;
        !          3722:        }
        !          3723: }
        !          3724:
        !          3725: int
        !          3726: rtw_txsoft_blk_setup_all(struct rtw_softc *sc)
        !          3727: {
        !          3728:        int pri, rc = 0;
        !          3729:        int qlen[RTW_NTXPRI] =
        !          3730:             {RTW_TXQLENLO, RTW_TXQLENMD, RTW_TXQLENHI, RTW_TXQLENBCN};
        !          3731:        struct rtw_txsoft_blk *tsbs;
        !          3732:
        !          3733:        tsbs = sc->sc_txsoft_blk;
        !          3734:
        !          3735:        for (pri = 0; pri < RTW_NTXPRI; pri++) {
        !          3736:                rc = rtw_txsoft_blk_setup(&tsbs[pri], qlen[pri]);
        !          3737:                if (rc != 0)
        !          3738:                        break;
        !          3739:        }
        !          3740:        tsbs[RTW_TXPRILO].tsb_poll = RTW_TPPOLL_LPQ | RTW_TPPOLL_SLPQ;
        !          3741:        tsbs[RTW_TXPRIMD].tsb_poll = RTW_TPPOLL_NPQ | RTW_TPPOLL_SNPQ;
        !          3742:        tsbs[RTW_TXPRIHI].tsb_poll = RTW_TPPOLL_HPQ | RTW_TPPOLL_SHPQ;
        !          3743:        tsbs[RTW_TXPRIBCN].tsb_poll = RTW_TPPOLL_BQ | RTW_TPPOLL_SBQ;
        !          3744:        return rc;
        !          3745: }
        !          3746:
        !          3747: void
        !          3748: rtw_txdesc_blk_setup(struct rtw_txdesc_blk *tdb, struct rtw_txdesc *desc,
        !          3749:     u_int ndesc, bus_addr_t ofs, bus_addr_t physbase)
        !          3750: {
        !          3751:        tdb->tdb_ndesc = ndesc;
        !          3752:        tdb->tdb_desc = desc;
        !          3753:        tdb->tdb_physbase = physbase;
        !          3754:        tdb->tdb_ofs = ofs;
        !          3755:
        !          3756:        bzero(tdb->tdb_desc, sizeof(tdb->tdb_desc[0]) * tdb->tdb_ndesc);
        !          3757:
        !          3758:        rtw_txdesc_blk_init(tdb);
        !          3759:        tdb->tdb_next = 0;
        !          3760: }
        !          3761:
        !          3762: void
        !          3763: rtw_txdesc_blk_setup_all(struct rtw_softc *sc)
        !          3764: {
        !          3765:        rtw_txdesc_blk_setup(&sc->sc_txdesc_blk[RTW_TXPRILO],
        !          3766:            &sc->sc_descs->hd_txlo[0], RTW_NTXDESCLO,
        !          3767:            RTW_RING_OFFSET(hd_txlo), RTW_RING_BASE(sc, hd_txlo));
        !          3768:
        !          3769:        rtw_txdesc_blk_setup(&sc->sc_txdesc_blk[RTW_TXPRIMD],
        !          3770:            &sc->sc_descs->hd_txmd[0], RTW_NTXDESCMD,
        !          3771:            RTW_RING_OFFSET(hd_txmd), RTW_RING_BASE(sc, hd_txmd));
        !          3772:
        !          3773:        rtw_txdesc_blk_setup(&sc->sc_txdesc_blk[RTW_TXPRIHI],
        !          3774:            &sc->sc_descs->hd_txhi[0], RTW_NTXDESCHI,
        !          3775:            RTW_RING_OFFSET(hd_txhi), RTW_RING_BASE(sc, hd_txhi));
        !          3776:
        !          3777:        rtw_txdesc_blk_setup(&sc->sc_txdesc_blk[RTW_TXPRIBCN],
        !          3778:            &sc->sc_descs->hd_bcn[0], RTW_NTXDESCBCN,
        !          3779:            RTW_RING_OFFSET(hd_bcn), RTW_RING_BASE(sc, hd_bcn));
        !          3780: }
        !          3781:
        !          3782: int
        !          3783: rtw_rf_attach(struct rtw_softc *sc, int rfchipid)
        !          3784: {
        !          3785:        struct rtw_bbpset *bb = &sc->sc_bbpset;
        !          3786:        int notsup = 0;
        !          3787:        const char *rfname, *paname = NULL;
        !          3788:        char scratch[sizeof("unknown 0xXX")];
        !          3789:
        !          3790:        switch (rfchipid) {
        !          3791:        case RTW_RFCHIPID_RTL8225:
        !          3792:                rfname = "RTL8225";
        !          3793:                sc->sc_pwrstate_cb = rtw_rtl_pwrstate;
        !          3794:                sc->sc_rf_init = rtw_rtl8255_init;
        !          3795:                sc->sc_rf_pwrstate = rtw_rtl8225_pwrstate;
        !          3796:                sc->sc_rf_tune = rtw_rtl8225_tune;
        !          3797:                sc->sc_rf_txpower = rtw_rtl8225_txpower;
        !          3798:                break;
        !          3799:        case RTW_RFCHIPID_RTL8255:
        !          3800:                rfname = "RTL8255";
        !          3801:                sc->sc_pwrstate_cb = rtw_rtl_pwrstate;
        !          3802:                sc->sc_rf_init = rtw_rtl8255_init;
        !          3803:                sc->sc_rf_pwrstate = rtw_rtl8255_pwrstate;
        !          3804:                sc->sc_rf_tune = rtw_rtl8255_tune;
        !          3805:                sc->sc_rf_txpower = rtw_rtl8255_txpower;
        !          3806:                break;
        !          3807:        case RTW_RFCHIPID_MAXIM2820:
        !          3808:                rfname = "MAX2820";     /* guess */
        !          3809:                paname = "MAX2422";     /* guess */
        !          3810:                /* XXX magic */
        !          3811:                bb->bb_antatten = RTW_BBP_ANTATTEN_MAXIM_MAGIC;
        !          3812:                bb->bb_chestlim =       0x00;
        !          3813:                bb->bb_chsqlim =        0x9f;
        !          3814:                bb->bb_ifagcdet =       0x64;
        !          3815:                bb->bb_ifagcini =       0x90;
        !          3816:                bb->bb_ifagclimit =     0x1a;
        !          3817:                bb->bb_lnadet =         0xf8;
        !          3818:                bb->bb_sys1 =           0x88;
        !          3819:                bb->bb_sys2 =           0x47;
        !          3820:                bb->bb_sys3 =           0x9b;
        !          3821:                bb->bb_trl =            0x88;
        !          3822:                bb->bb_txagc =          0x08;
        !          3823:                sc->sc_pwrstate_cb = rtw_maxim_pwrstate;
        !          3824:                sc->sc_rf_init = rtw_max2820_init;
        !          3825:                sc->sc_rf_pwrstate = rtw_max2820_pwrstate;
        !          3826:                sc->sc_rf_tune = rtw_max2820_tune;
        !          3827:                sc->sc_rf_txpower = rtw_max2820_txpower;
        !          3828:                break;
        !          3829:        case RTW_RFCHIPID_PHILIPS:
        !          3830:                rfname = "SA2400A";
        !          3831:                paname = "SA2411";
        !          3832:                /* XXX magic */
        !          3833:                bb->bb_antatten = RTW_BBP_ANTATTEN_PHILIPS_MAGIC;
        !          3834:                bb->bb_chestlim =       0x00;
        !          3835:                bb->bb_chsqlim =        0xa0;
        !          3836:                bb->bb_ifagcdet =       0x64;
        !          3837:                bb->bb_ifagcini =       0x90;
        !          3838:                bb->bb_ifagclimit =     0x1a;
        !          3839:                bb->bb_lnadet =         0xe0;
        !          3840:                bb->bb_sys1 =           0x98;
        !          3841:                bb->bb_sys2 =           0x47;
        !          3842:                bb->bb_sys3 =           0x90;
        !          3843:                bb->bb_trl =            0x88;
        !          3844:                bb->bb_txagc =          0x38;
        !          3845:                sc->sc_pwrstate_cb = rtw_philips_pwrstate;
        !          3846:                sc->sc_rf_init = rtw_sa2400_init;
        !          3847:                sc->sc_rf_pwrstate = rtw_sa2400_pwrstate;
        !          3848:                sc->sc_rf_tune = rtw_sa2400_tune;
        !          3849:                sc->sc_rf_txpower = rtw_sa2400_txpower;
        !          3850:                break;
        !          3851:        case RTW_RFCHIPID_RFMD2948:
        !          3852:                /* this is the same front-end as an atw(4)! */
        !          3853:                rfname = "RFMD RF2948B, "       /* mentioned in Realtek docs */
        !          3854:                         "LNA: RFMD RF2494, "   /* mentioned in Realtek docs */
        !          3855:                         "SYN: Silicon Labs Si4126";     /* inferred from
        !          3856:                                                          * reference driver
        !          3857:                                                          */
        !          3858:                paname = "RF2189";              /* mentioned in Realtek docs */
        !          3859:                /* XXX RFMD has no RF constructor */
        !          3860:                sc->sc_pwrstate_cb = rtw_rfmd_pwrstate;
        !          3861:                notsup =  1;
        !          3862:                break;
        !          3863:        case RTW_RFCHIPID_GCT:          /* this combo seen in the wild */
        !          3864:                rfname = "GRF5101";
        !          3865:                paname = "WS9901";
        !          3866:                /* XXX magic */
        !          3867:                bb->bb_antatten = RTW_BBP_ANTATTEN_GCT_MAGIC;
        !          3868:                bb->bb_chestlim =       0x00;
        !          3869:                bb->bb_chsqlim =        0xa0;
        !          3870:                bb->bb_ifagcdet =       0x64;
        !          3871:                bb->bb_ifagcini =       0x90;
        !          3872:                bb->bb_ifagclimit =     0x1e;
        !          3873:                bb->bb_lnadet =         0xc0;
        !          3874:                bb->bb_sys1 =           0xa8;
        !          3875:                bb->bb_sys2 =           0x47;
        !          3876:                bb->bb_sys3 =           0x9b;
        !          3877:                bb->bb_trl =            0x88;
        !          3878:                bb->bb_txagc =          0x08;
        !          3879:                sc->sc_pwrstate_cb = rtw_maxim_pwrstate;
        !          3880:                sc->sc_rf_init = rtw_grf5101_init;
        !          3881:                sc->sc_rf_pwrstate = rtw_grf5101_pwrstate;
        !          3882:                sc->sc_rf_tune = rtw_grf5101_tune;
        !          3883:                sc->sc_rf_txpower = rtw_grf5101_txpower;
        !          3884:                break;
        !          3885:        case RTW_RFCHIPID_INTERSIL:
        !          3886:                rfname = "HFA3873";     /* guess */
        !          3887:                paname = "Intersil <unknown>";
        !          3888:                notsup = 1;
        !          3889:                break;
        !          3890:        default:
        !          3891:                snprintf(scratch, sizeof(scratch), "unknown 0x%02x", rfchipid);
        !          3892:                rfname = scratch;
        !          3893:                notsup = 1;
        !          3894:        }
        !          3895:
        !          3896:        printf("radio %s, ", rfname);
        !          3897:        if (paname != NULL)
        !          3898:                printf("amp %s, ", paname);
        !          3899:
        !          3900:        return (notsup);
        !          3901: }
        !          3902:
        !          3903: /* Revision C and later use a different PHY delay setting than
        !          3904:  * revisions A and B.
        !          3905:  */
        !          3906: u_int8_t
        !          3907: rtw_check_phydelay(struct rtw_regs *regs, u_int32_t rcr0)
        !          3908: {
        !          3909: #define REVAB (RTW_RCR_MXDMA_UNLIMITED | RTW_RCR_AICV)
        !          3910: #define REVC (REVAB | RTW8180_RCR_RXFTH_WHOLE)
        !          3911:
        !          3912:        u_int8_t phydelay = LSHIFT(0x6, RTW_PHYDELAY_PHYDELAY);
        !          3913:
        !          3914:        RTW_WRITE(regs, RTW_RCR, REVAB);
        !          3915:        RTW_WBW(regs, RTW_RCR, RTW_RCR);
        !          3916:        RTW_WRITE(regs, RTW_RCR, REVC);
        !          3917:
        !          3918:        RTW_WBR(regs, RTW_RCR, RTW_RCR);
        !          3919:        if ((RTW_READ(regs, RTW_RCR) & REVC) == REVC)
        !          3920:                phydelay |= RTW_PHYDELAY_REVC_MAGIC;
        !          3921:
        !          3922:        RTW_WRITE(regs, RTW_RCR, rcr0); /* restore RCR */
        !          3923:        RTW_SYNC(regs, RTW_RCR, RTW_RCR);
        !          3924:
        !          3925:        return phydelay;
        !          3926: #undef REVC
        !          3927: }
        !          3928:
        !          3929: void
        !          3930: rtw_attach(struct rtw_softc *sc)
        !          3931: {
        !          3932:        struct ieee80211com *ic = &sc->sc_ic;
        !          3933:        struct rtw_txsoft_blk *tsb;
        !          3934:        struct rtw_mtbl *mtbl;
        !          3935:        struct rtw_srom *sr;
        !          3936:        const char *vername;
        !          3937:        struct ifnet *ifp;
        !          3938:        char scratch[sizeof("unknown 0xXXXXXXXX")];
        !          3939:        int pri, rc;
        !          3940:
        !          3941:
        !          3942:        /* Use default DMA memory access */
        !          3943:        if (sc->sc_regs.r_read8 == NULL) {
        !          3944:                sc->sc_regs.r_read8 = rtw_read8;
        !          3945:                sc->sc_regs.r_read16 = rtw_read16;
        !          3946:                sc->sc_regs.r_read32 = rtw_read32;
        !          3947:                sc->sc_regs.r_write8 = rtw_write8;
        !          3948:                sc->sc_regs.r_write16 = rtw_write16;
        !          3949:                sc->sc_regs.r_write32 = rtw_write32;
        !          3950:                sc->sc_regs.r_barrier = rtw_barrier;
        !          3951:        }
        !          3952:
        !          3953:        sc->sc_hwverid = RTW_READ(&sc->sc_regs, RTW_TCR) & RTW_TCR_HWVERID_MASK;
        !          3954:        switch (sc->sc_hwverid) {
        !          3955:        case RTW_TCR_HWVERID_RTL8185:
        !          3956:                vername = "RTL8185";
        !          3957:                sc->sc_flags |= RTW_F_RTL8185;
        !          3958:                break;
        !          3959:        case RTW_TCR_HWVERID_RTL8180F:
        !          3960:                vername = "RTL8180F";
        !          3961:                break;
        !          3962:        case RTW_TCR_HWVERID_RTL8180D:
        !          3963:                vername = "RTL8180D";
        !          3964:                break;
        !          3965:        default:
        !          3966:                snprintf(scratch, sizeof(scratch), "unknown 0x%08x",
        !          3967:                    sc->sc_hwverid);
        !          3968:                vername = scratch;
        !          3969:                break;
        !          3970:        }
        !          3971:
        !          3972:        printf("%s: ver %s, ", sc->sc_dev.dv_xname, vername);
        !          3973:
        !          3974:        rc = bus_dmamem_alloc(sc->sc_dmat, sizeof(struct rtw_descs),
        !          3975:            RTW_DESC_ALIGNMENT, 0, &sc->sc_desc_segs, 1, &sc->sc_desc_nsegs,
        !          3976:            0);
        !          3977:
        !          3978:        if (rc != 0) {
        !          3979:                printf("\n%s: could not allocate hw descriptors, error %d\n",
        !          3980:                     sc->sc_dev.dv_xname, rc);
        !          3981:                goto fail0;
        !          3982:        }
        !          3983:
        !          3984:        rc = bus_dmamem_map(sc->sc_dmat, &sc->sc_desc_segs,
        !          3985:            sc->sc_desc_nsegs, sizeof(struct rtw_descs),
        !          3986:            (caddr_t*)&sc->sc_descs, BUS_DMA_COHERENT);
        !          3987:
        !          3988:        if (rc != 0) {
        !          3989:                printf("\n%s: could not map hw descriptors, error %d\n",
        !          3990:                    sc->sc_dev.dv_xname, rc);
        !          3991:                goto fail1;
        !          3992:        }
        !          3993:
        !          3994:        rc = bus_dmamap_create(sc->sc_dmat, sizeof(struct rtw_descs), 1,
        !          3995:            sizeof(struct rtw_descs), 0, 0, &sc->sc_desc_dmamap);
        !          3996:
        !          3997:        if (rc != 0) {
        !          3998:                printf("\n%s: could not create DMA map for hw descriptors, "
        !          3999:                    "error %d\n", sc->sc_dev.dv_xname, rc);
        !          4000:                goto fail2;
        !          4001:        }
        !          4002:
        !          4003:        sc->sc_rxdesc_blk.rdb_dmat = sc->sc_dmat;
        !          4004:        sc->sc_rxdesc_blk.rdb_dmamap = sc->sc_desc_dmamap;
        !          4005:
        !          4006:        for (pri = 0; pri < RTW_NTXPRI; pri++) {
        !          4007:                sc->sc_txdesc_blk[pri].tdb_dmat = sc->sc_dmat;
        !          4008:                sc->sc_txdesc_blk[pri].tdb_dmamap = sc->sc_desc_dmamap;
        !          4009:        }
        !          4010:
        !          4011:        rc = bus_dmamap_load(sc->sc_dmat, sc->sc_desc_dmamap, sc->sc_descs,
        !          4012:            sizeof(struct rtw_descs), NULL, 0);
        !          4013:
        !          4014:        if (rc != 0) {
        !          4015:                printf("\n%s: could not load DMA map for hw descriptors, "
        !          4016:                    "error %d\n", sc->sc_dev.dv_xname, rc);
        !          4017:                goto fail3;
        !          4018:        }
        !          4019:
        !          4020:        if (rtw_txsoft_blk_setup_all(sc) != 0)
        !          4021:                goto fail4;
        !          4022:
        !          4023:        rtw_txdesc_blk_setup_all(sc);
        !          4024:
        !          4025:        sc->sc_rxdesc_blk.rdb_desc = &sc->sc_descs->hd_rx[0];
        !          4026:
        !          4027:        for (pri = 0; pri < RTW_NTXPRI; pri++) {
        !          4028:                tsb = &sc->sc_txsoft_blk[pri];
        !          4029:
        !          4030:                if ((rc = rtw_txdesc_dmamaps_create(sc->sc_dmat,
        !          4031:                    &tsb->tsb_desc[0], tsb->tsb_ndesc)) != 0) {
        !          4032:                        printf("\n%s: could not load DMA map for "
        !          4033:                            "hw tx descriptors, error %d\n",
        !          4034:                            sc->sc_dev.dv_xname, rc);
        !          4035:                        goto fail5;
        !          4036:                }
        !          4037:        }
        !          4038:
        !          4039:        if ((rc = rtw_rxdesc_dmamaps_create(sc->sc_dmat, &sc->sc_rxsoft[0],
        !          4040:            RTW_RXQLEN)) != 0) {
        !          4041:                printf("\n%s: could not load DMA map for hw rx descriptors, "
        !          4042:                    "error %d\n", sc->sc_dev.dv_xname, rc);
        !          4043:                goto fail6;
        !          4044:        }
        !          4045:
        !          4046:        /* Reset the chip to a known state. */
        !          4047:        if (rtw_reset(sc) != 0)
        !          4048:                goto fail7;
        !          4049:
        !          4050:        sc->sc_rcr = RTW_READ(&sc->sc_regs, RTW_RCR);
        !          4051:
        !          4052:        if ((sc->sc_rcr & RTW_RCR_9356SEL) != 0)
        !          4053:                sc->sc_flags |= RTW_F_9356SROM;
        !          4054:
        !          4055:        if (rtw_srom_read(&sc->sc_regs, sc->sc_flags, &sc->sc_srom,
        !          4056:            sc->sc_dev.dv_xname) != 0)
        !          4057:                goto fail7;
        !          4058:
        !          4059:        if (rtw_srom_parse(sc) != 0) {
        !          4060:                printf("\n%s: attach failed, malformed serial ROM\n",
        !          4061:                    sc->sc_dev.dv_xname);
        !          4062:                goto fail8;
        !          4063:        }
        !          4064:
        !          4065:        RTW_DPRINTF(RTW_DEBUG_ATTACH, ("%s: %s PHY\n", sc->sc_dev.dv_xname,
        !          4066:            ((sc->sc_flags & RTW_F_DIGPHY) != 0) ? "digital" : "analog"));
        !          4067:
        !          4068:        RTW_DPRINTF(RTW_DEBUG_ATTACH, ("%s: CS threshold %u\n",
        !          4069:            sc->sc_dev.dv_xname, sc->sc_csthr));
        !          4070:
        !          4071:        if ((rtw_rf_attach(sc, sc->sc_rfchipid)) != 0) {
        !          4072:                printf("\n%s: attach failed, could not attach RF\n",
        !          4073:                    sc->sc_dev.dv_xname);
        !          4074:                goto fail8;
        !          4075:        }
        !          4076:
        !          4077:        sc->sc_phydelay = rtw_check_phydelay(&sc->sc_regs, sc->sc_rcr);
        !          4078:
        !          4079:        RTW_DPRINTF(RTW_DEBUG_ATTACH,
        !          4080:            ("%s: PHY delay %d\n", sc->sc_dev.dv_xname, sc->sc_phydelay));
        !          4081:
        !          4082:        if (sc->sc_locale == RTW_LOCALE_UNKNOWN)
        !          4083:                rtw_identify_country(&sc->sc_regs, &sc->sc_locale);
        !          4084:
        !          4085:        rtw_init_channels(sc->sc_locale, &sc->sc_ic.ic_channels,
        !          4086:            sc->sc_dev.dv_xname);
        !          4087:
        !          4088:        if (rtw_identify_sta(&sc->sc_regs, &sc->sc_ic.ic_myaddr,
        !          4089:            sc->sc_dev.dv_xname) != 0)
        !          4090:                goto fail8;
        !          4091:
        !          4092:        ifp = &sc->sc_if;
        !          4093:        (void)memcpy(ifp->if_xname, sc->sc_dev.dv_xname, IFNAMSIZ);
        !          4094:        ifp->if_softc = sc;
        !          4095:        ifp->if_flags = IFF_SIMPLEX | IFF_BROADCAST | IFF_MULTICAST |
        !          4096:            IFF_NOTRAILERS;
        !          4097:        ifp->if_ioctl = rtw_ioctl;
        !          4098:        ifp->if_start = rtw_start;
        !          4099:        ifp->if_watchdog = rtw_watchdog;
        !          4100:
        !          4101:        IFQ_SET_READY(&sc->sc_if.if_snd);
        !          4102:
        !          4103:        ic->ic_phytype = IEEE80211_T_DS;
        !          4104:        ic->ic_opmode = IEEE80211_M_STA;
        !          4105:        ic->ic_caps = IEEE80211_C_PMGT | IEEE80211_C_IBSS |
        !          4106:            IEEE80211_C_HOSTAP | IEEE80211_C_MONITOR | IEEE80211_C_WEP;
        !          4107:
        !          4108:        ic->ic_sup_rates[IEEE80211_MODE_11B] = ieee80211_std_rateset_11b;
        !          4109:
        !          4110:        rtw_led_attach(&sc->sc_led_state, (void *)sc);
        !          4111:
        !          4112:        /*
        !          4113:         * Call MI attach routines.
        !          4114:         */
        !          4115:        if_attach(&sc->sc_if);
        !          4116:        ieee80211_ifattach(&sc->sc_if);
        !          4117:
        !          4118:        mtbl = &sc->sc_mtbl;
        !          4119:        mtbl->mt_newstate = ic->ic_newstate;
        !          4120:        ic->ic_newstate = rtw_newstate;
        !          4121:
        !          4122:        mtbl->mt_recv_mgmt = ic->ic_recv_mgmt;
        !          4123:        ic->ic_recv_mgmt = rtw_recv_mgmt;
        !          4124:
        !          4125:        mtbl->mt_node_free = ic->ic_node_free;
        !          4126:        ic->ic_node_free = rtw_node_free;
        !          4127:
        !          4128:        mtbl->mt_node_alloc = ic->ic_node_alloc;
        !          4129:        ic->ic_node_alloc = rtw_node_alloc;
        !          4130:
        !          4131:        /* possibly we should fill in our own sc_send_prresp, since
        !          4132:         * the RTL8180 is probably sending probe responses in ad hoc
        !          4133:         * mode.
        !          4134:         */
        !          4135:
        !          4136:        /* complete initialization */
        !          4137:        ieee80211_media_init(&sc->sc_if, rtw_media_change, rtw_media_status);
        !          4138:        timeout_set(&sc->sc_scan_to, rtw_next_scan, sc);
        !          4139:
        !          4140: #if NBPFILTER > 0
        !          4141:        bzero(&sc->sc_rxtapu, sizeof(sc->sc_rxtapu));
        !          4142:        sc->sc_rxtap.rr_ihdr.it_len = sizeof(sc->sc_rxtapu);
        !          4143:        sc->sc_rxtap.rr_ihdr.it_present = RTW_RX_RADIOTAP_PRESENT;
        !          4144:
        !          4145:        bzero(&sc->sc_txtapu, sizeof(sc->sc_txtapu));
        !          4146:        sc->sc_txtap.rt_ihdr.it_len = sizeof(sc->sc_txtapu);
        !          4147:        sc->sc_txtap.rt_ihdr.it_present = RTW_TX_RADIOTAP_PRESENT;
        !          4148:
        !          4149:        bpfattach(&sc->sc_radiobpf, &sc->sc_ic.ic_if, DLT_IEEE802_11_RADIO,
        !          4150:            sizeof(struct ieee80211_frame) + 64);
        !          4151: #endif
        !          4152:
        !          4153:        rtw_establish_hooks(&sc->sc_hooks, sc->sc_dev.dv_xname, (void*)sc);
        !          4154:
        !          4155:        return;
        !          4156:
        !          4157: fail8:
        !          4158:        sr = &sc->sc_srom;
        !          4159:        sr->sr_size = 0;
        !          4160:        if (sr->sr_content != NULL) {
        !          4161:                free(sr->sr_content, M_DEVBUF);
        !          4162:                sr->sr_content = NULL;
        !          4163:        }
        !          4164:
        !          4165: fail7:
        !          4166:        rtw_rxdesc_dmamaps_destroy(sc->sc_dmat, &sc->sc_rxsoft[0],
        !          4167:            RTW_RXQLEN);
        !          4168:
        !          4169: fail6:
        !          4170:        for (pri = 0; pri < RTW_NTXPRI; pri++) {
        !          4171:                rtw_txdesc_dmamaps_destroy(sc->sc_dmat,
        !          4172:                    sc->sc_txsoft_blk[pri].tsb_desc,
        !          4173:                    sc->sc_txsoft_blk[pri].tsb_ndesc);
        !          4174:        }
        !          4175:
        !          4176: fail5:
        !          4177:        rtw_txsoft_blk_cleanup_all(sc);
        !          4178:
        !          4179: fail4:
        !          4180:        bus_dmamap_unload(sc->sc_dmat, sc->sc_desc_dmamap);
        !          4181: fail3:
        !          4182:        bus_dmamap_destroy(sc->sc_dmat, sc->sc_desc_dmamap);
        !          4183: fail2:
        !          4184:        bus_dmamem_unmap(sc->sc_dmat, (caddr_t)sc->sc_descs,
        !          4185:            sizeof(struct rtw_descs));
        !          4186: fail1:
        !          4187:        bus_dmamem_free(sc->sc_dmat, &sc->sc_desc_segs,
        !          4188:            sc->sc_desc_nsegs);
        !          4189: fail0:
        !          4190:        return;
        !          4191: }
        !          4192:
        !          4193: int
        !          4194: rtw_detach(struct rtw_softc *sc)
        !          4195: {
        !          4196:        sc->sc_flags |= RTW_F_INVALID;
        !          4197:
        !          4198:        rtw_stop(&sc->sc_if, 1);
        !          4199:
        !          4200:        rtw_disestablish_hooks(&sc->sc_hooks, sc->sc_dev.dv_xname,
        !          4201:            (void*)sc);
        !          4202:        timeout_del(&sc->sc_scan_to);
        !          4203:        ieee80211_ifdetach(&sc->sc_if);
        !          4204:        if_detach(&sc->sc_if);
        !          4205:
        !          4206:        return 0;
        !          4207: }
        !          4208:
        !          4209: /*
        !          4210:  * PHY specific functions
        !          4211:  */
        !          4212:
        !          4213: int
        !          4214: rtw_bbp_preinit(struct rtw_regs *regs, u_int antatten0, int dflantb,
        !          4215:     u_int freq)
        !          4216: {
        !          4217:        u_int antatten = antatten0;
        !          4218:        if (dflantb)
        !          4219:                antatten |= RTW_BBP_ANTATTEN_DFLANTB;
        !          4220:        if (freq == 2484) /* channel 14 */
        !          4221:                antatten |= RTW_BBP_ANTATTEN_CHAN14;
        !          4222:        return rtw_bbp_write(regs, RTW_BBP_ANTATTEN, antatten);
        !          4223: }
        !          4224:
        !          4225: int
        !          4226: rtw_bbp_init(struct rtw_regs *regs, struct rtw_bbpset *bb, int antdiv,
        !          4227:     int dflantb, u_int8_t cs_threshold, u_int freq)
        !          4228: {
        !          4229:        int rc;
        !          4230:        u_int32_t sys2, sys3;
        !          4231:
        !          4232:        sys2 = bb->bb_sys2;
        !          4233:        if (antdiv)
        !          4234:                sys2 |= RTW_BBP_SYS2_ANTDIV;
        !          4235:        sys3 = bb->bb_sys3 |
        !          4236:            LSHIFT(cs_threshold, RTW_BBP_SYS3_CSTHRESH_MASK);
        !          4237:
        !          4238: #define        RTW_BBP_WRITE_OR_RETURN(reg, val) \
        !          4239:        if ((rc = rtw_bbp_write(regs, reg, val)) != 0) \
        !          4240:                return rc;
        !          4241:
        !          4242:        RTW_BBP_WRITE_OR_RETURN(RTW_BBP_SYS1,           bb->bb_sys1);
        !          4243:        RTW_BBP_WRITE_OR_RETURN(RTW_BBP_TXAGC,          bb->bb_txagc);
        !          4244:        RTW_BBP_WRITE_OR_RETURN(RTW_BBP_LNADET,         bb->bb_lnadet);
        !          4245:        RTW_BBP_WRITE_OR_RETURN(RTW_BBP_IFAGCINI,       bb->bb_ifagcini);
        !          4246:        RTW_BBP_WRITE_OR_RETURN(RTW_BBP_IFAGCLIMIT,     bb->bb_ifagclimit);
        !          4247:        RTW_BBP_WRITE_OR_RETURN(RTW_BBP_IFAGCDET,       bb->bb_ifagcdet);
        !          4248:
        !          4249:        if ((rc = rtw_bbp_preinit(regs, bb->bb_antatten, dflantb, freq)) != 0)
        !          4250:                return rc;
        !          4251:
        !          4252:        RTW_BBP_WRITE_OR_RETURN(RTW_BBP_TRL,            bb->bb_trl);
        !          4253:        RTW_BBP_WRITE_OR_RETURN(RTW_BBP_SYS2,           sys2);
        !          4254:        RTW_BBP_WRITE_OR_RETURN(RTW_BBP_SYS3,           sys3);
        !          4255:        RTW_BBP_WRITE_OR_RETURN(RTW_BBP_CHESTLIM,       bb->bb_chestlim);
        !          4256:        RTW_BBP_WRITE_OR_RETURN(RTW_BBP_CHSQLIM,        bb->bb_chsqlim);
        !          4257:        return 0;
        !          4258: }
        !          4259:
        !          4260: int
        !          4261: rtw_sa2400_txpower(struct rtw_softc *sc, u_int8_t opaque_txpower)
        !          4262: {
        !          4263:        return rtw_rf_macwrite(sc, SA2400_TX, opaque_txpower);
        !          4264: }
        !          4265:
        !          4266: /* make sure we're using the same settings as the reference driver */
        !          4267: void
        !          4268: rtw_verify_syna(u_int freq, u_int32_t val)
        !          4269: {
        !          4270:        u_int32_t expected_val = ~val;
        !          4271:
        !          4272:        switch (freq) {
        !          4273:        case 2412:
        !          4274:                expected_val = 0x0000096c; /* ch 1 */
        !          4275:                break;
        !          4276:        case 2417:
        !          4277:                expected_val = 0x00080970; /* ch 2 */
        !          4278:                break;
        !          4279:        case 2422:
        !          4280:                expected_val = 0x00100974; /* ch 3 */
        !          4281:                break;
        !          4282:        case 2427:
        !          4283:                expected_val = 0x00180978; /* ch 4 */
        !          4284:                break;
        !          4285:        case 2432:
        !          4286:                expected_val = 0x00000980; /* ch 5 */
        !          4287:                break;
        !          4288:        case 2437:
        !          4289:                expected_val = 0x00080984; /* ch 6 */
        !          4290:                break;
        !          4291:        case 2442:
        !          4292:                expected_val = 0x00100988; /* ch 7 */
        !          4293:                break;
        !          4294:        case 2447:
        !          4295:                expected_val = 0x0018098c; /* ch 8 */
        !          4296:                break;
        !          4297:        case 2452:
        !          4298:                expected_val = 0x00000994; /* ch 9 */
        !          4299:                break;
        !          4300:        case 2457:
        !          4301:                expected_val = 0x00080998; /* ch 10 */
        !          4302:                break;
        !          4303:        case 2462:
        !          4304:                expected_val = 0x0010099c; /* ch 11 */
        !          4305:                break;
        !          4306:        case 2467:
        !          4307:                expected_val = 0x001809a0; /* ch 12 */
        !          4308:                break;
        !          4309:        case 2472:
        !          4310:                expected_val = 0x000009a8; /* ch 13 */
        !          4311:                break;
        !          4312:        case 2484:
        !          4313:                expected_val = 0x000009b4; /* ch 14 */
        !          4314:                break;
        !          4315:        }
        !          4316:        KASSERT(val == expected_val);
        !          4317: }
        !          4318:
        !          4319: /* freq is in MHz */
        !          4320: int
        !          4321: rtw_sa2400_tune(struct rtw_softc *sc, u_int freq)
        !          4322: {
        !          4323:        int rc;
        !          4324:        u_int32_t syna, synb, sync;
        !          4325:
        !          4326:        /* XO = 44MHz, R = 11, hence N is in units of XO / R = 4MHz.
        !          4327:         *
        !          4328:         * The channel spacing (5MHz) is not divisible by 4MHz, so
        !          4329:         * we set the fractional part of N to compensate.
        !          4330:         */
        !          4331:        int n = freq / 4, nf = (freq % 4) * 2;
        !          4332:
        !          4333:        syna = LSHIFT(nf, SA2400_SYNA_NF_MASK) | LSHIFT(n, SA2400_SYNA_N_MASK);
        !          4334:        rtw_verify_syna(freq, syna);
        !          4335:
        !          4336:        /* Divide the 44MHz crystal down to 4MHz. Set the fractional
        !          4337:         * compensation charge pump value to agree with the fractional
        !          4338:         * modulus.
        !          4339:         */
        !          4340:        synb = LSHIFT(11, SA2400_SYNB_R_MASK) | SA2400_SYNB_L_NORMAL |
        !          4341:            SA2400_SYNB_ON | SA2400_SYNB_ONE |
        !          4342:            LSHIFT(80, SA2400_SYNB_FC_MASK); /* agrees w/ SA2400_SYNA_FM = 0 */
        !          4343:
        !          4344:        sync = SA2400_SYNC_CP_NORMAL;
        !          4345:
        !          4346:        if ((rc = rtw_rf_macwrite(sc, SA2400_SYNA, syna)) != 0)
        !          4347:                return rc;
        !          4348:        if ((rc = rtw_rf_macwrite(sc, SA2400_SYNB, synb)) != 0)
        !          4349:                return rc;
        !          4350:        if ((rc = rtw_rf_macwrite(sc, SA2400_SYNC, sync)) != 0)
        !          4351:                return rc;
        !          4352:        return rtw_rf_macwrite(sc, SA2400_SYND, 0x0);
        !          4353: }
        !          4354:
        !          4355: int
        !          4356: rtw_sa2400_pwrstate(struct rtw_softc *sc, enum rtw_pwrstate power)
        !          4357: {
        !          4358:        u_int32_t opmode;
        !          4359:        opmode = SA2400_OPMODE_DEFAULTS;
        !          4360:        switch (power) {
        !          4361:        case RTW_ON:
        !          4362:                opmode |= SA2400_OPMODE_MODE_TXRX;
        !          4363:                break;
        !          4364:        case RTW_SLEEP:
        !          4365:                opmode |= SA2400_OPMODE_MODE_WAIT;
        !          4366:                break;
        !          4367:        case RTW_OFF:
        !          4368:                opmode |= SA2400_OPMODE_MODE_SLEEP;
        !          4369:                break;
        !          4370:        }
        !          4371:
        !          4372:        if (sc->sc_flags & RTW_F_DIGPHY)
        !          4373:                opmode |= SA2400_OPMODE_DIGIN;
        !          4374:
        !          4375:        return rtw_rf_macwrite(sc, SA2400_OPMODE, opmode);
        !          4376: }
        !          4377:
        !          4378: int
        !          4379: rtw_sa2400_vcocal_start(struct rtw_softc *sc, int start)
        !          4380: {
        !          4381:        u_int32_t opmode;
        !          4382:
        !          4383:        opmode = SA2400_OPMODE_DEFAULTS;
        !          4384:        if (start)
        !          4385:                opmode |= SA2400_OPMODE_MODE_VCOCALIB;
        !          4386:        else
        !          4387:                opmode |= SA2400_OPMODE_MODE_SLEEP;
        !          4388:
        !          4389:        if (sc->sc_flags & RTW_F_DIGPHY)
        !          4390:                opmode |= SA2400_OPMODE_DIGIN;
        !          4391:
        !          4392:        return rtw_rf_macwrite(sc, SA2400_OPMODE, opmode);
        !          4393: }
        !          4394:
        !          4395: int
        !          4396: rtw_sa2400_vco_calibration(struct rtw_softc *sc)
        !          4397: {
        !          4398:        int rc;
        !          4399:        /* calibrate VCO */
        !          4400:        if ((rc = rtw_sa2400_vcocal_start(sc, 1)) != 0)
        !          4401:                return rc;
        !          4402:        DELAY(2200);    /* 2.2 milliseconds */
        !          4403:        /* XXX superfluous: SA2400 automatically entered SLEEP mode. */
        !          4404:        return rtw_sa2400_vcocal_start(sc, 0);
        !          4405: }
        !          4406:
        !          4407: int
        !          4408: rtw_sa2400_filter_calibration(struct rtw_softc *sc)
        !          4409: {
        !          4410:        u_int32_t opmode;
        !          4411:
        !          4412:        opmode = SA2400_OPMODE_DEFAULTS | SA2400_OPMODE_MODE_FCALIB;
        !          4413:        if (sc->sc_flags & RTW_F_DIGPHY)
        !          4414:                opmode |= SA2400_OPMODE_DIGIN;
        !          4415:
        !          4416:        return rtw_rf_macwrite(sc, SA2400_OPMODE, opmode);
        !          4417: }
        !          4418:
        !          4419: int
        !          4420: rtw_sa2400_dc_calibration(struct rtw_softc *sc)
        !          4421: {
        !          4422:        int rc;
        !          4423:        u_int32_t dccal;
        !          4424:
        !          4425:        rtw_continuous_tx_enable(sc, 1);
        !          4426:
        !          4427:        dccal = SA2400_OPMODE_DEFAULTS | SA2400_OPMODE_MODE_TXRX;
        !          4428:
        !          4429:        rc = rtw_rf_macwrite(sc, SA2400_OPMODE, dccal);
        !          4430:
        !          4431:        if (rc != 0)
        !          4432:                return rc;
        !          4433:
        !          4434:        DELAY(5);       /* DCALIB after being in Tx mode for 5
        !          4435:                         * microseconds
        !          4436:                         */
        !          4437:
        !          4438:        dccal &= ~SA2400_OPMODE_MODE_MASK;
        !          4439:        dccal |= SA2400_OPMODE_MODE_DCALIB;
        !          4440:
        !          4441:        rc = rtw_rf_macwrite(sc, SA2400_OPMODE, dccal);
        !          4442:        if (rc != 0)
        !          4443:                return rc;
        !          4444:
        !          4445:        DELAY(20);      /* calibration takes at most 20 microseconds */
        !          4446:
        !          4447:        rtw_continuous_tx_enable(sc, 0);
        !          4448:
        !          4449:        return 0;
        !          4450: }
        !          4451:
        !          4452: int
        !          4453: rtw_sa2400_calibrate(struct rtw_softc *sc, u_int freq)
        !          4454: {
        !          4455:        int i, rc;
        !          4456:
        !          4457:        /* XXX reference driver calibrates VCO twice. Is it a bug? */
        !          4458:        for (i = 0; i < 2; i++) {
        !          4459:                if ((rc = rtw_sa2400_vco_calibration(sc)) != 0)
        !          4460:                        return rc;
        !          4461:        }
        !          4462:        /* VCO calibration erases synthesizer registers, so re-tune */
        !          4463:        if ((rc = rtw_sa2400_tune(sc, freq)) != 0)
        !          4464:                return rc;
        !          4465:        if ((rc = rtw_sa2400_filter_calibration(sc)) != 0)
        !          4466:                return rc;
        !          4467:        /* analog PHY needs DC calibration */
        !          4468:        if (!(sc->sc_flags & RTW_F_DIGPHY))
        !          4469:                return rtw_sa2400_dc_calibration(sc);
        !          4470:        return 0;
        !          4471: }
        !          4472:
        !          4473: int
        !          4474: rtw_sa2400_init(struct rtw_softc *sc, u_int freq, u_int8_t opaque_txpower,
        !          4475:     enum rtw_pwrstate power)
        !          4476: {
        !          4477:        int rc;
        !          4478:        u_int32_t agc, manrx;
        !          4479:
        !          4480:        if ((rc = rtw_sa2400_txpower(sc, opaque_txpower)) != 0)
        !          4481:                return rc;
        !          4482:
        !          4483:        /* skip configuration if it's time to sleep or to power-down. */
        !          4484:        if (power == RTW_SLEEP || power == RTW_OFF)
        !          4485:                return rtw_sa2400_pwrstate(sc, power);
        !          4486:
        !          4487:        /* go to sleep for configuration */
        !          4488:        if ((rc = rtw_sa2400_pwrstate(sc, RTW_SLEEP)) != 0)
        !          4489:                return rc;
        !          4490:
        !          4491:        if ((rc = rtw_sa2400_tune(sc, freq)) != 0)
        !          4492:                return rc;
        !          4493:
        !          4494:        agc = LSHIFT(25, SA2400_AGC_MAXGAIN_MASK);
        !          4495:        agc |= LSHIFT(7, SA2400_AGC_BBPDELAY_MASK);
        !          4496:        agc |= LSHIFT(15, SA2400_AGC_LNADELAY_MASK);
        !          4497:        agc |= LSHIFT(27, SA2400_AGC_RXONDELAY_MASK);
        !          4498:
        !          4499:        if ((rc = rtw_rf_macwrite(sc, SA2400_AGC, agc)) != 0)
        !          4500:                return rc;
        !          4501:
        !          4502:        /* XXX we are not supposed to be in RXMGC mode when we do this? */
        !          4503:        manrx = SA2400_MANRX_AHSN;
        !          4504:        manrx |= SA2400_MANRX_TEN;
        !          4505:        manrx |= LSHIFT(1023, SA2400_MANRX_RXGAIN_MASK);
        !          4506:
        !          4507:        if ((rc = rtw_rf_macwrite(sc, SA2400_MANRX, manrx)) != 0)
        !          4508:                return rc;
        !          4509:
        !          4510:        if ((rc = rtw_sa2400_calibrate(sc, freq)) != 0)
        !          4511:                return rc;
        !          4512:
        !          4513:        /* enter Tx/Rx mode */
        !          4514:        return rtw_sa2400_pwrstate(sc, power);
        !          4515: }
        !          4516:
        !          4517: /* freq is in MHz */
        !          4518: int
        !          4519: rtw_max2820_tune(struct rtw_softc *sc, u_int freq)
        !          4520: {
        !          4521:        if (freq < 2400 || freq > 2499)
        !          4522:                return -1;
        !          4523:
        !          4524:        return rtw_rf_hostwrite(sc, MAX2820_CHANNEL,
        !          4525:            LSHIFT(freq - 2400, MAX2820_CHANNEL_CF_MASK));
        !          4526: }
        !          4527:
        !          4528: int
        !          4529: rtw_max2820_init(struct rtw_softc *sc, u_int freq, u_int8_t opaque_txpower,
        !          4530:     enum rtw_pwrstate power)
        !          4531: {
        !          4532:        int rc;
        !          4533:
        !          4534:        if ((rc = rtw_rf_hostwrite(sc, MAX2820_TEST,
        !          4535:            MAX2820_TEST_DEFAULT)) != 0)
        !          4536:                return rc;
        !          4537:
        !          4538:        if ((rc = rtw_rf_hostwrite(sc, MAX2820_ENABLE,
        !          4539:            MAX2820_ENABLE_DEFAULT)) != 0)
        !          4540:                return rc;
        !          4541:
        !          4542:        /* skip configuration if it's time to sleep or to power-down. */
        !          4543:        if ((rc = rtw_max2820_pwrstate(sc, power)) != 0)
        !          4544:                return rc;
        !          4545:        else if (power == RTW_OFF || power == RTW_SLEEP)
        !          4546:                return 0;
        !          4547:
        !          4548:        if ((rc = rtw_rf_hostwrite(sc, MAX2820_SYNTH,
        !          4549:            MAX2820_SYNTH_R_44MHZ)) != 0)
        !          4550:                return rc;
        !          4551:
        !          4552:        if ((rc = rtw_max2820_tune(sc, freq)) != 0)
        !          4553:                return rc;
        !          4554:
        !          4555:        /* XXX The MAX2820 datasheet indicates that 1C and 2C should not
        !          4556:         * be changed from 7, however, the reference driver sets them
        !          4557:         * to 4 and 1, respectively.
        !          4558:         */
        !          4559:        if ((rc = rtw_rf_hostwrite(sc, MAX2820_RECEIVE,
        !          4560:            MAX2820_RECEIVE_DL_DEFAULT |
        !          4561:            LSHIFT(4, MAX2820A_RECEIVE_1C_MASK) |
        !          4562:            LSHIFT(1, MAX2820A_RECEIVE_2C_MASK))) != 0)
        !          4563:                return rc;
        !          4564:
        !          4565:        return rtw_rf_hostwrite(sc, MAX2820_TRANSMIT,
        !          4566:            MAX2820_TRANSMIT_PA_DEFAULT);
        !          4567: }
        !          4568:
        !          4569: int
        !          4570: rtw_max2820_txpower(struct rtw_softc *sc, u_int8_t opaque_txpower)
        !          4571: {
        !          4572:        /* TBD */
        !          4573:        return 0;
        !          4574: }
        !          4575:
        !          4576: int
        !          4577: rtw_max2820_pwrstate(struct rtw_softc *sc, enum rtw_pwrstate power)
        !          4578: {
        !          4579:        uint32_t enable;
        !          4580:
        !          4581:        switch (power) {
        !          4582:        case RTW_OFF:
        !          4583:        case RTW_SLEEP:
        !          4584:        default:
        !          4585:                enable = 0x0;
        !          4586:                break;
        !          4587:        case RTW_ON:
        !          4588:                enable = MAX2820_ENABLE_DEFAULT;
        !          4589:                break;
        !          4590:        }
        !          4591:        return rtw_rf_hostwrite(sc, MAX2820_ENABLE, enable);
        !          4592: }
        !          4593:
        !          4594: int
        !          4595: rtw_grf5101_init(struct rtw_softc *sc, u_int freq, u_int8_t opaque_txpower,
        !          4596:     enum rtw_pwrstate power)
        !          4597: {
        !          4598:        int rc;
        !          4599:
        !          4600:        /*
        !          4601:         * These values have been derived from the rtl8180-sa2400 Linux driver.
        !          4602:         * It is unknown what they all do, GCT refuse to release any documentation
        !          4603:         * so these are more than likely sub optimal settings
        !          4604:         */
        !          4605:
        !          4606:        rtw_rf_macwrite(sc, 0x01, 0x1a23);
        !          4607:        rtw_rf_macwrite(sc, 0x02, 0x4971);
        !          4608:        rtw_rf_macwrite(sc, 0x03, 0x41de);
        !          4609:        rtw_rf_macwrite(sc, 0x04, 0x2d80);
        !          4610:
        !          4611:        rtw_rf_macwrite(sc, 0x05, 0x61ff);
        !          4612:
        !          4613:        rtw_rf_macwrite(sc, 0x06, 0x0);
        !          4614:
        !          4615:        rtw_rf_macwrite(sc, 0x08, 0x7533);
        !          4616:        rtw_rf_macwrite(sc, 0x09, 0xc401);
        !          4617:        rtw_rf_macwrite(sc, 0x0a, 0x0);
        !          4618:        rtw_rf_macwrite(sc, 0x0c, 0x1c7);
        !          4619:        rtw_rf_macwrite(sc, 0x0d, 0x29d3);
        !          4620:        rtw_rf_macwrite(sc, 0x0e, 0x2e8);
        !          4621:        rtw_rf_macwrite(sc, 0x10, 0x192);
        !          4622:        rtw_rf_macwrite(sc, 0x11, 0x248);
        !          4623:        rtw_rf_macwrite(sc, 0x12, 0x0);
        !          4624:        rtw_rf_macwrite(sc, 0x13, 0x20c4);
        !          4625:        rtw_rf_macwrite(sc, 0x14, 0xf4fc);
        !          4626:        rtw_rf_macwrite(sc, 0x15, 0x0);
        !          4627:        rtw_rf_macwrite(sc, 0x16, 0x1500);
        !          4628:
        !          4629:        if ((rc = rtw_grf5101_txpower(sc, opaque_txpower)) != 0)
        !          4630:                return rc;
        !          4631:
        !          4632:        if ((rc = rtw_grf5101_tune(sc, freq)) != 0)
        !          4633:                return rc;
        !          4634:
        !          4635:        return (0);
        !          4636: }
        !          4637:
        !          4638: int
        !          4639: rtw_grf5101_tune(struct rtw_softc *sc, u_int freq)
        !          4640: {
        !          4641:        struct ieee80211com *ic = &sc->sc_ic;
        !          4642:        u_int channel = ieee80211_chan2ieee(ic, ic->ic_bss->ni_chan);
        !          4643:
        !          4644:        /* set channel */
        !          4645:        rtw_rf_macwrite(sc, 0x07, 0);
        !          4646:        rtw_rf_macwrite(sc, 0x0b, channel - 1);
        !          4647:        rtw_rf_macwrite(sc, 0x07, 0x1000);
        !          4648:
        !          4649:        return (0);
        !          4650: }
        !          4651:
        !          4652: int
        !          4653: rtw_grf5101_txpower(struct rtw_softc *sc, u_int8_t opaque_txpower)
        !          4654: {
        !          4655:        rtw_rf_macwrite(sc, 0x15, 0);
        !          4656:        rtw_rf_macwrite(sc, 0x06, opaque_txpower);
        !          4657:        rtw_rf_macwrite(sc, 0x15, 0x10);
        !          4658:        rtw_rf_macwrite(sc, 0x15, 0x00);
        !          4659:
        !          4660:        return (0);
        !          4661: }
        !          4662:
        !          4663: int
        !          4664: rtw_grf5101_pwrstate(struct rtw_softc *sc, enum rtw_pwrstate power)
        !          4665: {
        !          4666:        switch (power) {
        !          4667:        case RTW_OFF:
        !          4668:        case RTW_SLEEP:
        !          4669:                rtw_rf_macwrite(sc, 0x07, 0x0000);
        !          4670:                rtw_rf_macwrite(sc, 0x1f, 0x0045);
        !          4671:                rtw_rf_macwrite(sc, 0x1f, 0x0005);
        !          4672:                rtw_rf_macwrite(sc, 0x00, 0x08e4);
        !          4673:        default:
        !          4674:                break;
        !          4675:        case RTW_ON:
        !          4676:                rtw_rf_macwrite(sc, 0x1f, 0x0001);
        !          4677:                DELAY(10);
        !          4678:                rtw_rf_macwrite(sc, 0x1f, 0x0001);
        !          4679:                DELAY(10);
        !          4680:                rtw_rf_macwrite(sc, 0x1f, 0x0041);
        !          4681:                DELAY(10);
        !          4682:                rtw_rf_macwrite(sc, 0x1f, 0x0061);
        !          4683:                DELAY(10);
        !          4684:                rtw_rf_macwrite(sc, 0x00, 0x0ae4);
        !          4685:                DELAY(10);
        !          4686:                rtw_rf_macwrite(sc, 0x07, 0x1000);
        !          4687:                DELAY(100);
        !          4688:                break;
        !          4689:        }
        !          4690:
        !          4691:        return 0;
        !          4692: }
        !          4693:
        !          4694: int
        !          4695: rtw_rtl8225_pwrstate(struct rtw_softc *sc, enum rtw_pwrstate power)
        !          4696: {
        !          4697:        return (0);
        !          4698: }
        !          4699:
        !          4700: int
        !          4701: rtw_rtl8225_init(struct rtw_softc *sc, u_int freq, u_int8_t opaque_txpower,
        !          4702:     enum rtw_pwrstate power)
        !          4703: {
        !          4704:        return (0);
        !          4705: }
        !          4706:
        !          4707: int
        !          4708: rtw_rtl8225_txpower(struct rtw_softc *sc, u_int8_t opaque_txpower)
        !          4709: {
        !          4710:        return (0);
        !          4711: }
        !          4712:
        !          4713: int
        !          4714: rtw_rtl8225_tune(struct rtw_softc *sc, u_int freq)
        !          4715: {
        !          4716:        return (0);
        !          4717: }
        !          4718:
        !          4719: int
        !          4720: rtw_rtl8255_pwrstate(struct rtw_softc *sc, enum rtw_pwrstate power)
        !          4721: {
        !          4722:        return (0);
        !          4723: }
        !          4724:
        !          4725: int
        !          4726: rtw_rtl8255_init(struct rtw_softc *sc, u_int freq, u_int8_t opaque_txpower,
        !          4727:     enum rtw_pwrstate power)
        !          4728: {
        !          4729:        return (0);
        !          4730: }
        !          4731:
        !          4732: int
        !          4733: rtw_rtl8255_txpower(struct rtw_softc *sc, u_int8_t opaque_txpower)
        !          4734: {
        !          4735:        return (0);
        !          4736: }
        !          4737:
        !          4738: int
        !          4739: rtw_rtl8255_tune(struct rtw_softc *sc, u_int freq)
        !          4740: {
        !          4741:        return (0);
        !          4742: }
        !          4743:
        !          4744: int
        !          4745: rtw_phy_init(struct rtw_softc *sc)
        !          4746: {
        !          4747:        int rc;
        !          4748:        struct ieee80211com *ic = &sc->sc_ic;
        !          4749:        struct rtw_regs *regs = &sc->sc_regs;
        !          4750:        int antdiv = sc->sc_flags & RTW_F_ANTDIV;
        !          4751:        int dflantb = sc->sc_flags & RTW_F_DFLANTB;
        !          4752:        u_int freq = ic->ic_bss->ni_chan->ic_freq;      /* freq is in MHz */
        !          4753:        u_int8_t opaque_txpower = rtw_chan2txpower(&sc->sc_srom, ic,
        !          4754:            ic->ic_bss->ni_chan);
        !          4755:        u_int8_t cs_threshold = sc->sc_csthr;
        !          4756:        enum rtw_pwrstate power = RTW_ON;
        !          4757:
        !          4758:        RTW_DPRINTF(RTW_DEBUG_PHY,
        !          4759:            ("%s: txpower %u csthresh %u freq %u antdiv %u dflantb %u "
        !          4760:             "pwrstate %s\n", __func__, opaque_txpower, cs_threshold, freq,
        !          4761:             antdiv, dflantb, rtw_pwrstate_string(power)));
        !          4762:
        !          4763:        /* XXX is this really necessary? */
        !          4764:        if ((rc = (*sc->sc_rf_txpower)(sc, opaque_txpower)) != 0)
        !          4765:                return rc;
        !          4766:        if ((rc = rtw_bbp_preinit(regs, sc->sc_bbpset.bb_antatten, dflantb,
        !          4767:            freq)) != 0)
        !          4768:                return rc;
        !          4769:        if ((rc = (*sc->sc_rf_tune)(sc, freq)) != 0)
        !          4770:                return rc;
        !          4771:        /* initialize RF  */
        !          4772:        if ((rc = (*sc->sc_rf_init)(sc, freq, opaque_txpower, power)) != 0)
        !          4773:                return rc;
        !          4774: #if 0  /* what is this redundant tx power setting here for? */
        !          4775:        if ((rc = (*sc->sc_rf_txpower)(sc, opaque_txpower)) != 0)
        !          4776:                return rc;
        !          4777: #endif
        !          4778:        return rtw_bbp_init(regs, &sc->sc_bbpset, antdiv, dflantb,
        !          4779:            cs_threshold, freq);
        !          4780: }
        !          4781:
        !          4782: /*
        !          4783:  * Generic PHY I/O functions
        !          4784:  */
        !          4785:
        !          4786: int
        !          4787: rtw_bbp_write(struct rtw_regs *regs, u_int addr, u_int val)
        !          4788: {
        !          4789: #define        BBP_WRITE_ITERS 50
        !          4790: #define        BBP_WRITE_DELAY 1
        !          4791:        int i;
        !          4792:        u_int32_t wrbbp, rdbbp;
        !          4793:
        !          4794:        RTW_DPRINTF(RTW_DEBUG_PHYIO,
        !          4795:            ("%s: bbp[%u] <- %u\n", __func__, addr, val));
        !          4796:
        !          4797:        KASSERT((addr & ~PRESHIFT(RTW_BB_ADDR_MASK)) == 0);
        !          4798:        KASSERT((val & ~PRESHIFT(RTW_BB_WR_MASK)) == 0);
        !          4799:
        !          4800:        wrbbp = LSHIFT(addr, RTW_BB_ADDR_MASK) | RTW_BB_WREN |
        !          4801:            LSHIFT(val, RTW_BB_WR_MASK) | RTW_BB_RD_MASK,
        !          4802:
        !          4803:        rdbbp = LSHIFT(addr, RTW_BB_ADDR_MASK) |
        !          4804:            RTW_BB_WR_MASK | RTW_BB_RD_MASK;
        !          4805:
        !          4806:        RTW_DPRINTF(RTW_DEBUG_PHYIO,
        !          4807:            ("%s: rdbbp = %#08x, wrbbp = %#08x\n", __func__, rdbbp, wrbbp));
        !          4808:
        !          4809:        for (i = BBP_WRITE_ITERS; --i >= 0; ) {
        !          4810:                RTW_RBW(regs, RTW_BB, RTW_BB);
        !          4811:                RTW_WRITE(regs, RTW_BB, wrbbp);
        !          4812:                RTW_SYNC(regs, RTW_BB, RTW_BB);
        !          4813:                RTW_WRITE(regs, RTW_BB, rdbbp);
        !          4814:                RTW_SYNC(regs, RTW_BB, RTW_BB);
        !          4815:                delay(BBP_WRITE_DELAY); /* 1 microsecond */
        !          4816:                if (MASK_AND_RSHIFT(RTW_READ(regs, RTW_BB),
        !          4817:                    RTW_BB_RD_MASK) == val) {
        !          4818:                        RTW_DPRINTF(RTW_DEBUG_PHYIO,
        !          4819:                            ("%s: finished in %dus\n", __func__,
        !          4820:                            BBP_WRITE_DELAY * (BBP_WRITE_ITERS - i)));
        !          4821:                        return 0;
        !          4822:                }
        !          4823:                delay(BBP_WRITE_DELAY); /* again */
        !          4824:        }
        !          4825:        printf("%s: timeout\n", __func__);
        !          4826:        return -1;
        !          4827: }
        !          4828:
        !          4829: /* Help rtw_rf_hostwrite bang bits to RF over 3-wire interface. */
        !          4830: void
        !          4831: rtw_rf_hostbangbits(struct rtw_regs *regs, u_int32_t bits, int lo_to_hi,
        !          4832:     u_int nbits)
        !          4833: {
        !          4834:        int i;
        !          4835:        u_int32_t mask, reg;
        !          4836:
        !          4837:        KASSERT(nbits <= 32);
        !          4838:
        !          4839:        RTW_DPRINTF(RTW_DEBUG_PHYIO,
        !          4840:            ("%s: %u bits, %#08x, %s\n", __func__, nbits, bits,
        !          4841:            (lo_to_hi) ? "lo to hi" : "hi to lo"));
        !          4842:
        !          4843:        reg = RTW8180_PHYCFG_HST;
        !          4844:        RTW_WRITE(regs, RTW8180_PHYCFG, reg);
        !          4845:        RTW_SYNC(regs, RTW8180_PHYCFG, RTW8180_PHYCFG);
        !          4846:
        !          4847:        if (lo_to_hi)
        !          4848:                mask = 0x1;
        !          4849:        else
        !          4850:                mask = 1 << (nbits - 1);
        !          4851:
        !          4852:        for (i = 0; i < nbits; i++) {
        !          4853:                RTW_DPRINTF(RTW_DEBUG_PHYBITIO,
        !          4854:                    ("%s: bits %#08x mask %#08x -> bit %#08x\n",
        !          4855:                    __func__, bits, mask, bits & mask));
        !          4856:
        !          4857:                if ((bits & mask) != 0)
        !          4858:                        reg |= RTW8180_PHYCFG_HST_DATA;
        !          4859:                else
        !          4860:                        reg &= ~RTW8180_PHYCFG_HST_DATA;
        !          4861:
        !          4862:                reg |= RTW8180_PHYCFG_HST_CLK;
        !          4863:                RTW_WRITE(regs, RTW8180_PHYCFG, reg);
        !          4864:                RTW_SYNC(regs, RTW8180_PHYCFG, RTW8180_PHYCFG);
        !          4865:
        !          4866:                DELAY(2);       /* arbitrary delay */
        !          4867:
        !          4868:                reg &= ~RTW8180_PHYCFG_HST_CLK;
        !          4869:                RTW_WRITE(regs, RTW8180_PHYCFG, reg);
        !          4870:                RTW_SYNC(regs, RTW8180_PHYCFG, RTW8180_PHYCFG);
        !          4871:
        !          4872:                if (lo_to_hi)
        !          4873:                        mask <<= 1;
        !          4874:                else
        !          4875:                        mask >>= 1;
        !          4876:        }
        !          4877:
        !          4878:        reg |= RTW8180_PHYCFG_HST_EN;
        !          4879:        KASSERT((reg & RTW8180_PHYCFG_HST_CLK) == 0);
        !          4880:        RTW_WRITE(regs, RTW8180_PHYCFG, reg);
        !          4881:        RTW_SYNC(regs, RTW8180_PHYCFG, RTW8180_PHYCFG);
        !          4882: }
        !          4883:
        !          4884: #if 0
        !          4885: void
        !          4886: rtw_rf_rtl8225_hostbangbits(struct rtw_regs *regs, u_int32_t bits, int lo_to_hi,
        !          4887:     u_int nbits)
        !          4888: {
        !          4889:        int i;
        !          4890:        u_int8_t page;
        !          4891:        u_int16_t reg0, reg1, reg2;
        !          4892:        u_int32_t mask;
        !          4893:
        !          4894:        /* enable page 0 */
        !          4895:        page = RTW_READ8(regs, RTW_PSR);
        !          4896:        RTW_WRITE8(regs, RTW_PSR, page & ~RTW_PSR_PSEN);
        !          4897:
        !          4898:        /* enable RF access */
        !          4899:        reg0 = RTW_READ16(regs, RTW8185_RFPINSOUTPUT) &
        !          4900:            RTW8185_RFPINSOUTPUT_MASK;
        !          4901:        reg1 = RTW_READ16(regs, RTW8185_RFPINSENABLE);
        !          4902:        RTW_WRITE16(regs, RTW8185_RFPINSENABLE,
        !          4903:            RTW8185_RFPINSENABLE_ENABLE | reg0);
        !          4904:        reg2 = RTW_READ16(regs, RTW8185_RFPINSSELECT);
        !          4905:        RTW_WRITE16(regs, RTW8185_RFPINSSELECT,
        !          4906:            RTW8185_RFPINSSELECT_ENABLE | reg1 /* XXX | SW_GPIO_CTL */);
        !          4907:        DELAY(10);
        !          4908:
        !          4909:        RTW_WRITE16(regs, RTW8185_RFPINSOUTPUT, reg0);
        !          4910:        DELAY(10);
        !          4911:
        !          4912:        if (lo_to_hi)
        !          4913:                mask = 0x1;
        !          4914:        else
        !          4915:                mask = 1 << (nbits - 1);
        !          4916:
        !          4917:        for (i = 0; i < nbits; i++) {
        !          4918:                RTW_DPRINTF(RTW_DEBUG_PHYBITIO,
        !          4919:                    ("%s: bits %#08x mask %#08x -> bit %#08x\n",
        !          4920:                    __func__, bits, mask, bits & mask));
        !          4921:
        !          4922:                if ((bits & mask) != 0)
        !          4923:                        reg |= RTW8180_PHYCFG_HST_DATA;
        !          4924:                else
        !          4925:                        reg &= ~RTW8180_PHYCFG_HST_DATA;
        !          4926:
        !          4927:                reg |= RTW8180_PHYCFG_HST_CLK;
        !          4928:                RTW_WRITE(regs, RTW8180_PHYCFG, reg);
        !          4929:                RTW_SYNC(regs, RTW8180_PHYCFG, RTW8180_PHYCFG);
        !          4930:
        !          4931:                DELAY(2);       /* arbitrary delay */
        !          4932:
        !          4933:                reg &= ~RTW8180_PHYCFG_HST_CLK;
        !          4934:                RTW_WRITE(regs, RTW8180_PHYCFG, reg);
        !          4935:                RTW_SYNC(regs, RTW8180_PHYCFG, RTW8180_PHYCFG);
        !          4936:
        !          4937:                if (lo_to_hi)
        !          4938:                        mask <<= 1;
        !          4939:                else
        !          4940:                        mask >>= 1;
        !          4941:        }
        !          4942:
        !          4943:        /* reset the page */
        !          4944:        RTW_WRITE8(regs, RTW_PSR, page);
        !          4945: }
        !          4946: #endif
        !          4947:
        !          4948: /* Help rtw_rf_macwrite: tell MAC to bang bits to RF over the 3-wire
        !          4949:  * interface.
        !          4950:  */
        !          4951: int
        !          4952: rtw_rf_macbangbits(struct rtw_regs *regs, u_int32_t reg)
        !          4953: {
        !          4954:        int i;
        !          4955:
        !          4956:        RTW_DPRINTF(RTW_DEBUG_PHY, ("%s: %#08x\n", __func__, reg));
        !          4957:
        !          4958:        RTW_WRITE(regs, RTW8180_PHYCFG, RTW8180_PHYCFG_MAC_POLL | reg);
        !          4959:
        !          4960:        RTW_WBR(regs, RTW8180_PHYCFG, RTW8180_PHYCFG);
        !          4961:
        !          4962:        for (i = rtw_macbangbits_timeout; --i >= 0; delay(1)) {
        !          4963:                if ((RTW_READ(regs, RTW8180_PHYCFG) &
        !          4964:                    RTW8180_PHYCFG_MAC_POLL) == 0) {
        !          4965:                        RTW_DPRINTF(RTW_DEBUG_PHY,
        !          4966:                            ("%s: finished in %dus\n", __func__,
        !          4967:                            rtw_macbangbits_timeout - i));
        !          4968:                        return 0;
        !          4969:                }
        !          4970:                RTW_RBR(regs, RTW8180_PHYCFG, RTW8180_PHYCFG);
        !          4971:        }
        !          4972:
        !          4973:        printf("%s: RTW8180_PHYCFG_MAC_POLL still set.\n", __func__);
        !          4974:        return -1;
        !          4975: }
        !          4976:
        !          4977: u_int32_t
        !          4978: rtw_grf5101_host_crypt(u_int addr, u_int32_t val)
        !          4979: {
        !          4980:        /* TBD */
        !          4981:        return 0;
        !          4982: }
        !          4983:
        !          4984: u_int32_t
        !          4985: rtw_grf5101_mac_crypt(u_int addr, u_int32_t val)
        !          4986: {
        !          4987:        u_int32_t data_and_addr;
        !          4988: #define EXTRACT_NIBBLE(d, which) (((d) >> (4 * (which))) & 0xf)
        !          4989:        static u_int8_t caesar[16] = {
        !          4990:                0x0, 0x8, 0x4, 0xc,
        !          4991:                0x2, 0xa, 0x6, 0xe,
        !          4992:                0x1, 0x9, 0x5, 0xd,
        !          4993:                0x3, 0xb, 0x7, 0xf
        !          4994:        };
        !          4995:        data_and_addr =
        !          4996:            caesar[EXTRACT_NIBBLE(val, 2)] |
        !          4997:            (caesar[EXTRACT_NIBBLE(val, 1)] <<  4) |
        !          4998:            (caesar[EXTRACT_NIBBLE(val, 0)] <<  8) |
        !          4999:            (caesar[(addr >> 1) & 0xf]      << 12) |
        !          5000:            ((addr & 0x1)                   << 16) |
        !          5001:            (caesar[EXTRACT_NIBBLE(val, 3)] << 24);
        !          5002:        return LSHIFT(data_and_addr, RTW8180_PHYCFG_MAC_PHILIPS_ADDR_MASK |
        !          5003:            RTW8180_PHYCFG_MAC_PHILIPS_DATA_MASK);
        !          5004: #undef EXTRACT_NIBBLE
        !          5005: }
        !          5006:
        !          5007: /* Bang bits over the 3-wire interface. */
        !          5008: int
        !          5009: rtw_rf_hostwrite(struct rtw_softc *sc, u_int addr, u_int32_t val)
        !          5010: {
        !          5011:        u_int nbits;
        !          5012:        int lo_to_hi;
        !          5013:        u_int32_t bits;
        !          5014:        void(*rf_bangbits)(struct rtw_regs *, u_int32_t, int, u_int) =
        !          5015:            rtw_rf_hostbangbits;
        !          5016:
        !          5017:        RTW_DPRINTF(RTW_DEBUG_PHYIO, ("%s: [%u] <- %#08x\n", __func__,
        !          5018:            addr, val));
        !          5019:
        !          5020:        switch (sc->sc_rfchipid) {
        !          5021:        case RTW_RFCHIPID_MAXIM2820:
        !          5022:                nbits = 16;
        !          5023:                lo_to_hi = 0;
        !          5024:                bits = LSHIFT(val, MAX2820_TWI_DATA_MASK) |
        !          5025:                    LSHIFT(addr, MAX2820_TWI_ADDR_MASK);
        !          5026:                break;
        !          5027:        case RTW_RFCHIPID_PHILIPS:
        !          5028:                KASSERT((addr & ~PRESHIFT(SA2400_TWI_ADDR_MASK)) == 0);
        !          5029:                KASSERT((val & ~PRESHIFT(SA2400_TWI_DATA_MASK)) == 0);
        !          5030:                bits = LSHIFT(val, SA2400_TWI_DATA_MASK) |
        !          5031:                    LSHIFT(addr, SA2400_TWI_ADDR_MASK) | SA2400_TWI_WREN;
        !          5032:                nbits = 32;
        !          5033:                lo_to_hi = 1;
        !          5034:                break;
        !          5035:        case RTW_RFCHIPID_GCT:
        !          5036:                KASSERT((addr & ~PRESHIFT(SI4126_TWI_ADDR_MASK)) == 0);
        !          5037:                KASSERT((val & ~PRESHIFT(SI4126_TWI_DATA_MASK)) == 0);
        !          5038:                bits = rtw_grf5101_host_crypt(addr, val);
        !          5039:                nbits = 21;
        !          5040:                lo_to_hi = 1;
        !          5041:                break;
        !          5042:        case RTW_RFCHIPID_RFMD2948:
        !          5043:                KASSERT((addr & ~PRESHIFT(SI4126_TWI_ADDR_MASK)) == 0);
        !          5044:                KASSERT((val & ~PRESHIFT(SI4126_TWI_DATA_MASK)) == 0);
        !          5045:                bits = LSHIFT(val, SI4126_TWI_DATA_MASK) |
        !          5046:                    LSHIFT(addr, SI4126_TWI_ADDR_MASK);
        !          5047:                nbits = 22;
        !          5048:                lo_to_hi = 0;
        !          5049:                break;
        !          5050:        case RTW_RFCHIPID_RTL8225:
        !          5051:        case RTW_RFCHIPID_RTL8255:
        !          5052:                nbits = 16;
        !          5053:                lo_to_hi = 0;
        !          5054:                bits = LSHIFT(val, RTL8225_TWI_DATA_MASK) |
        !          5055:                    LSHIFT(addr, RTL8225_TWI_ADDR_MASK);
        !          5056:
        !          5057:                /* the RTL8225 uses a slightly modified RF interface */
        !          5058:                rf_bangbits = rtw_rf_hostbangbits;
        !          5059:                break;
        !          5060:        case RTW_RFCHIPID_INTERSIL:
        !          5061:        default:
        !          5062:                printf("%s: unknown rfchipid %d\n", __func__, sc->sc_rfchipid);
        !          5063:                return -1;
        !          5064:        }
        !          5065:
        !          5066:        (*rf_bangbits)(&sc->sc_regs, bits, lo_to_hi, nbits);
        !          5067:
        !          5068:        return 0;
        !          5069: }
        !          5070:
        !          5071: u_int32_t
        !          5072: rtw_maxim_swizzle(u_int addr, u_int32_t val)
        !          5073: {
        !          5074:        u_int32_t hidata, lodata;
        !          5075:
        !          5076:        KASSERT((val & ~(RTW_MAXIM_LODATA_MASK|RTW_MAXIM_HIDATA_MASK)) == 0);
        !          5077:        lodata = MASK_AND_RSHIFT(val, RTW_MAXIM_LODATA_MASK);
        !          5078:        hidata = MASK_AND_RSHIFT(val, RTW_MAXIM_HIDATA_MASK);
        !          5079:        return LSHIFT(lodata, RTW8180_PHYCFG_MAC_MAXIM_LODATA_MASK) |
        !          5080:            LSHIFT(hidata, RTW8180_PHYCFG_MAC_MAXIM_HIDATA_MASK) |
        !          5081:            LSHIFT(addr, RTW8180_PHYCFG_MAC_MAXIM_ADDR_MASK);
        !          5082: }
        !          5083:
        !          5084: /* Tell the MAC what to bang over the 3-wire interface. */
        !          5085: int
        !          5086: rtw_rf_macwrite(struct rtw_softc *sc, u_int addr, u_int32_t val)
        !          5087: {
        !          5088:        u_int32_t reg;
        !          5089:
        !          5090:        RTW_DPRINTF(RTW_DEBUG_PHYIO, ("%s: %s[%u] <- %#08x\n", __func__,
        !          5091:            addr, val));
        !          5092:
        !          5093:        switch (sc->sc_rfchipid) {
        !          5094:        case RTW_RFCHIPID_GCT:
        !          5095:                reg = rtw_grf5101_mac_crypt(addr, val);
        !          5096:                break;
        !          5097:        case RTW_RFCHIPID_MAXIM2820:
        !          5098:                reg = rtw_maxim_swizzle(addr, val);
        !          5099:                break;
        !          5100:        default:                /* XXX */
        !          5101:        case RTW_RFCHIPID_PHILIPS:
        !          5102:                KASSERT((addr &
        !          5103:                    ~PRESHIFT(RTW8180_PHYCFG_MAC_PHILIPS_ADDR_MASK)) == 0);
        !          5104:                KASSERT((val &
        !          5105:                    ~PRESHIFT(RTW8180_PHYCFG_MAC_PHILIPS_DATA_MASK)) == 0);
        !          5106:
        !          5107:                reg = LSHIFT(addr, RTW8180_PHYCFG_MAC_PHILIPS_ADDR_MASK) |
        !          5108:                    LSHIFT(val, RTW8180_PHYCFG_MAC_PHILIPS_DATA_MASK);
        !          5109:        }
        !          5110:
        !          5111:        switch (sc->sc_rfchipid) {
        !          5112:        case RTW_RFCHIPID_GCT:
        !          5113:        case RTW_RFCHIPID_MAXIM2820:
        !          5114:        case RTW_RFCHIPID_RFMD2948:
        !          5115:                reg |= RTW8180_PHYCFG_MAC_RFTYPE_RFMD;
        !          5116:                break;
        !          5117:        case RTW_RFCHIPID_INTERSIL:
        !          5118:                reg |= RTW8180_PHYCFG_MAC_RFTYPE_INTERSIL;
        !          5119:                break;
        !          5120:        case RTW_RFCHIPID_PHILIPS:
        !          5121:                reg |= RTW8180_PHYCFG_MAC_RFTYPE_PHILIPS;
        !          5122:                break;
        !          5123:        default:
        !          5124:                printf("%s: unknown rfchipid %d\n", __func__, sc->sc_rfchipid);
        !          5125:                return -1;
        !          5126:        }
        !          5127:
        !          5128:        return rtw_rf_macbangbits(&sc->sc_regs, reg);
        !          5129: }
        !          5130:
        !          5131:
        !          5132: u_int8_t
        !          5133: rtw_read8(void *arg, u_int32_t off)
        !          5134: {
        !          5135:        struct rtw_regs *regs = (struct rtw_regs *)arg;
        !          5136:        return (bus_space_read_1(regs->r_bt, regs->r_bh, off));
        !          5137: }
        !          5138:
        !          5139: u_int16_t
        !          5140: rtw_read16(void *arg, u_int32_t off)
        !          5141: {
        !          5142:        struct rtw_regs *regs = (struct rtw_regs *)arg;
        !          5143:        return (bus_space_read_2(regs->r_bt, regs->r_bh, off));
        !          5144: }
        !          5145:
        !          5146: u_int32_t
        !          5147: rtw_read32(void *arg, u_int32_t off)
        !          5148: {
        !          5149:        struct rtw_regs *regs = (struct rtw_regs *)arg;
        !          5150:        return (bus_space_read_4(regs->r_bt, regs->r_bh, off));
        !          5151: }
        !          5152:
        !          5153: void
        !          5154: rtw_write8(void *arg, u_int32_t off, u_int8_t val)
        !          5155: {
        !          5156:        struct rtw_regs *regs = (struct rtw_regs *)arg;
        !          5157:        bus_space_write_1(regs->r_bt, regs->r_bh, off, val);
        !          5158: }
        !          5159:
        !          5160: void
        !          5161: rtw_write16(void *arg, u_int32_t off, u_int16_t val)
        !          5162: {
        !          5163:        struct rtw_regs *regs = (struct rtw_regs *)arg;
        !          5164:        bus_space_write_2(regs->r_bt, regs->r_bh, off, val);
        !          5165: }
        !          5166:
        !          5167: void
        !          5168: rtw_write32(void *arg, u_int32_t off, u_int32_t val)
        !          5169: {
        !          5170:        struct rtw_regs *regs = (struct rtw_regs *)arg;
        !          5171:        bus_space_write_4(regs->r_bt, regs->r_bh, off, val);
        !          5172: }
        !          5173:
        !          5174: void
        !          5175: rtw_barrier(void *arg, u_int32_t reg0, u_int32_t reg1, int flags)
        !          5176: {
        !          5177:        struct rtw_regs *regs = (struct rtw_regs *)arg;
        !          5178:        bus_space_barrier(regs->r_bt, regs->r_bh, MIN(reg0, reg1),
        !          5179:            MAX(reg0, reg1) - MIN(reg0, reg1) + 4, flags);
        !          5180: }

CVSweb