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

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

Generated by: LCOV version 1.13