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

          Line data    Source code
       1             : /*      $OpenBSD: bwi.c,v 1.127 2017/10/26 15:00:28 mpi Exp $   */
       2             : 
       3             : /*
       4             :  * Copyright (c) 2007 The DragonFly Project.  All rights reserved.
       5             :  * 
       6             :  * This code is derived from software contributed to The DragonFly Project
       7             :  * by Sepherosa Ziehau <sepherosa@gmail.com>
       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             :  * 
      13             :  * 1. Redistributions of source code must retain the above copyright
      14             :  *    notice, this list of conditions and the following disclaimer.
      15             :  * 2. Redistributions in binary form must reproduce the above copyright
      16             :  *    notice, this list of conditions and the following disclaimer in
      17             :  *    the documentation and/or other materials provided with the
      18             :  *    distribution.
      19             :  * 3. Neither the name of The DragonFly Project nor the names of its
      20             :  *    contributors may be used to endorse or promote products derived
      21             :  *    from this software without specific, prior written permission.
      22             :  * 
      23             :  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
      24             :  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
      25             :  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
      26             :  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE
      27             :  * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
      28             :  * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
      29             :  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
      30             :  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
      31             :  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
      32             :  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
      33             :  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
      34             :  * SUCH DAMAGE.
      35             :  * 
      36             :  * $DragonFly: src/sys/dev/netif/bwi/bwimac.c,v 1.1 2007/09/08 06:15:54 sephe Exp $
      37             :  */
      38             : 
      39             : #include "bpfilter.h"
      40             : 
      41             : #include <sys/param.h>
      42             : 
      43             : #include <sys/device.h>
      44             : #include <sys/kernel.h>
      45             : #include <sys/malloc.h>
      46             : #include <sys/mbuf.h>
      47             : #include <sys/socket.h>
      48             : #include <sys/sockio.h>
      49             : #include <sys/systm.h>
      50             : #include <sys/endian.h>
      51             : 
      52             : #include <machine/bus.h>
      53             : #include <machine/intr.h>
      54             : 
      55             : #include <net/if.h>
      56             : #include <net/if_dl.h>
      57             : #include <net/if_media.h>
      58             : 
      59             : #if NBPFILTER > 0
      60             : #include <net/bpf.h>
      61             : #endif
      62             : 
      63             : #include <netinet/in.h>
      64             : #include <netinet/if_ether.h>
      65             : 
      66             : #include <net80211/ieee80211_var.h>
      67             : #include <net80211/ieee80211_amrr.h>
      68             : #include <net80211/ieee80211_radiotap.h>
      69             : 
      70             : #include <dev/ic/bwireg.h>
      71             : #include <dev/ic/bwivar.h>
      72             : 
      73             : #include <uvm/uvm_extern.h>
      74             : 
      75             : #ifdef BWI_DEBUG
      76             : int bwi_debug = 1;
      77             : #define DPRINTF(l, x...)        do { if ((l) <= bwi_debug) printf(x); } while (0)
      78             : #else
      79             : #define DPRINTF(l, x...)
      80             : #endif
      81             : 
      82             : /* XXX temporary porting goop */
      83             : #include <dev/pci/pcireg.h>
      84             : #include <dev/pci/pcidevs.h>
      85             : 
      86             : /* XXX does not belong here */
      87             : #define IEEE80211_OFDM_PLCP_RATE_MASK   0x0000000f
      88             : #define IEEE80211_OFDM_PLCP_LEN_MASK    0x0001ffe0
      89             : 
      90             : /*
      91             :  * Contention window (slots).
      92             :  */
      93             : #define IEEE80211_CW_MAX        1023    /* aCWmax */
      94             : #define IEEE80211_CW_MIN_0      31      /* DS/CCK aCWmin, ERP aCWmin(0) */
      95             : #define IEEE80211_CW_MIN_1      15      /* OFDM aCWmin, ERP aCWmin(1) */
      96             : 
      97             : #define __unused __attribute__((__unused__))
      98             : 
      99             : extern int ticks;
     100             : 
     101             : /* XXX end porting goop */
     102             : 
     103             : /* MAC */
     104             : struct bwi_retry_lim {
     105             :         uint16_t        shretry;
     106             :         uint16_t        shretry_fb;
     107             :         uint16_t        lgretry;
     108             :         uint16_t        lgretry_fb;
     109             : };
     110             : 
     111             : struct bwi_clock_freq {
     112             :         uint            clkfreq_min;
     113             :         uint            clkfreq_max;
     114             : };
     115             : 
     116             : /* XXX does not belong here */
     117             : struct ieee80211_ds_plcp_hdr {
     118             :         uint8_t         i_signal;
     119             :         uint8_t         i_service;
     120             :         uint16_t        i_length;
     121             :         uint16_t        i_crc;
     122             : } __packed;
     123             : 
     124             : enum bwi_modtype {
     125             :         IEEE80211_MODTYPE_DS    = 0,    /* DS/CCK modulation */
     126             :         IEEE80211_MODTYPE_PBCC  = 1,    /* PBCC modulation */
     127             :         IEEE80211_MODTYPE_OFDM  = 2     /* OFDM modulation */
     128             : };
     129             : #define IEEE80211_MODTYPE_CCK   IEEE80211_MODTYPE_DS
     130             : 
     131             : /* MAC */
     132             : void             bwi_tmplt_write_4(struct bwi_mac *, uint32_t, uint32_t);
     133             : void             bwi_hostflags_write(struct bwi_mac *, uint64_t);
     134             : uint64_t         bwi_hostflags_read(struct bwi_mac *);
     135             : uint16_t         bwi_memobj_read_2(struct bwi_mac *, uint16_t, uint16_t);
     136             : uint32_t         bwi_memobj_read_4(struct bwi_mac *, uint16_t, uint16_t);
     137             : void             bwi_memobj_write_2(struct bwi_mac *, uint16_t, uint16_t,
     138             :                      uint16_t);
     139             : void             bwi_memobj_write_4(struct bwi_mac *, uint16_t, uint16_t,
     140             :                      uint32_t);
     141             : int              bwi_mac_lateattach(struct bwi_mac *);
     142             : int              bwi_mac_init(struct bwi_mac *);
     143             : void             bwi_mac_reset(struct bwi_mac *, int);
     144             : void             bwi_mac_set_tpctl_11bg(struct bwi_mac *,
     145             :                      const struct bwi_tpctl *);
     146             : int              bwi_mac_test(struct bwi_mac *);
     147             : void             bwi_mac_setup_tpctl(struct bwi_mac *);
     148             : void             bwi_mac_dummy_xmit(struct bwi_mac *);
     149             : void             bwi_mac_init_tpctl_11bg(struct bwi_mac *);
     150             : void             bwi_mac_detach(struct bwi_mac *);
     151             : int              bwi_get_firmware(const char *, const uint8_t *, size_t,
     152             :                      size_t *, size_t *);
     153             : int              bwi_fwimage_is_valid(struct bwi_softc *, uint8_t *,
     154             :                      size_t, char *, uint8_t);
     155             : int              bwi_mac_fw_alloc(struct bwi_mac *);
     156             : void             bwi_mac_fw_free(struct bwi_mac *);
     157             : int              bwi_mac_fw_load(struct bwi_mac *);
     158             : int              bwi_mac_gpio_init(struct bwi_mac *);
     159             : int              bwi_mac_gpio_fini(struct bwi_mac *);
     160             : int              bwi_mac_fw_load_iv(struct bwi_mac *, uint8_t *, size_t);
     161             : int              bwi_mac_fw_init(struct bwi_mac *);
     162             : void             bwi_mac_opmode_init(struct bwi_mac *);
     163             : void             bwi_mac_hostflags_init(struct bwi_mac *);
     164             : void             bwi_mac_bss_param_init(struct bwi_mac *);
     165             : void             bwi_mac_set_retry_lim(struct bwi_mac *,
     166             :                      const struct bwi_retry_lim *);
     167             : void             bwi_mac_set_ackrates(struct bwi_mac *,
     168             :                      const struct ieee80211_rateset *);
     169             : int              bwi_mac_start(struct bwi_mac *);
     170             : int              bwi_mac_stop(struct bwi_mac *);
     171             : int              bwi_mac_config_ps(struct bwi_mac *);
     172             : void             bwi_mac_reset_hwkeys(struct bwi_mac *);
     173             : void             bwi_mac_shutdown(struct bwi_mac *);
     174             : int              bwi_mac_get_property(struct bwi_mac *);
     175             : void             bwi_mac_updateslot(struct bwi_mac *, int);
     176             : int              bwi_mac_attach(struct bwi_softc *, int, uint8_t);
     177             : void             bwi_mac_balance_atten(int *, int *);
     178             : void             bwi_mac_adjust_tpctl(struct bwi_mac *, int, int);
     179             : void             bwi_mac_calibrate_txpower(struct bwi_mac *,
     180             :                      enum bwi_txpwrcb_type);
     181             : void             bwi_mac_lock(struct bwi_mac *);
     182             : void             bwi_mac_unlock(struct bwi_mac *);
     183             : void             bwi_mac_set_promisc(struct bwi_mac *, int);
     184             : 
     185             : /* PHY */
     186             : void             bwi_phy_write(struct bwi_mac *, uint16_t, uint16_t);
     187             : uint16_t         bwi_phy_read(struct bwi_mac *, uint16_t);
     188             : int              bwi_phy_attach(struct bwi_mac *);
     189             : void             bwi_phy_set_bbp_atten(struct bwi_mac *, uint16_t);
     190             : int              bwi_phy_calibrate(struct bwi_mac *);
     191             : void             bwi_tbl_write_2(struct bwi_mac *mac, uint16_t, uint16_t);
     192             : void             bwi_tbl_write_4(struct bwi_mac *mac, uint16_t, uint32_t);
     193             : void             bwi_nrssi_write(struct bwi_mac *, uint16_t, int16_t);
     194             : int16_t          bwi_nrssi_read(struct bwi_mac *, uint16_t);
     195             : void             bwi_phy_init_11a(struct bwi_mac *);
     196             : void             bwi_phy_init_11g(struct bwi_mac *);
     197             : void             bwi_phy_init_11b_rev2(struct bwi_mac *);
     198             : void             bwi_phy_init_11b_rev4(struct bwi_mac *);
     199             : void             bwi_phy_init_11b_rev5(struct bwi_mac *);
     200             : void             bwi_phy_init_11b_rev6(struct bwi_mac *);
     201             : void             bwi_phy_config_11g(struct bwi_mac *);
     202             : void             bwi_phy_config_agc(struct bwi_mac *);
     203             : void             bwi_set_gains(struct bwi_mac *, const struct bwi_gains *);
     204             : void             bwi_phy_clear_state(struct bwi_phy *);
     205             : 
     206             : /* RF */
     207             : int16_t          bwi_nrssi_11g(struct bwi_mac *);
     208             : struct bwi_rf_lo
     209             :                 *bwi_get_rf_lo(struct bwi_mac *, uint16_t, uint16_t);
     210             : int              bwi_rf_lo_isused(struct bwi_mac *, const struct bwi_rf_lo *);
     211             : void             bwi_rf_write(struct bwi_mac *, uint16_t, uint16_t);
     212             : uint16_t         bwi_rf_read(struct bwi_mac *, uint16_t);
     213             : int              bwi_rf_attach(struct bwi_mac *);
     214             : void             bwi_rf_set_chan(struct bwi_mac *, uint, int);
     215             : void             bwi_rf_get_gains(struct bwi_mac *);
     216             : void             bwi_rf_init(struct bwi_mac *);
     217             : void             bwi_rf_off_11a(struct bwi_mac *);
     218             : void             bwi_rf_off_11bg(struct bwi_mac *);
     219             : void             bwi_rf_off_11g_rev5(struct bwi_mac *);
     220             : void             bwi_rf_workaround(struct bwi_mac *, uint);
     221             : struct bwi_rf_lo
     222             :                 *bwi_rf_lo_find(struct bwi_mac *, const struct bwi_tpctl *);
     223             : void             bwi_rf_lo_adjust(struct bwi_mac *, const struct bwi_tpctl *);
     224             : void             bwi_rf_lo_write(struct bwi_mac *, const struct bwi_rf_lo *);
     225             : int              bwi_rf_gain_max_reached(struct bwi_mac *, int);
     226             : uint16_t         bwi_bitswap4(uint16_t);
     227             : uint16_t         bwi_phy812_value(struct bwi_mac *, uint16_t);
     228             : void             bwi_rf_init_bcm2050(struct bwi_mac *);
     229             : uint16_t         bwi_rf_calibval(struct bwi_mac *);
     230             : int32_t          _bwi_adjust_devide(int32_t, int32_t);
     231             : int              bwi_rf_calc_txpower(int8_t *, uint8_t, const int16_t[]);
     232             : int              bwi_rf_map_txpower(struct bwi_mac *);
     233             : void             bwi_rf_lo_update_11g(struct bwi_mac *);
     234             : uint32_t         bwi_rf_lo_devi_measure(struct bwi_mac *, uint16_t);
     235             : uint16_t         bwi_rf_get_tp_ctrl2(struct bwi_mac *);
     236             : uint8_t          _bwi_rf_lo_update_11g(struct bwi_mac *, uint16_t);
     237             : void             bwi_rf_lo_measure_11g(struct bwi_mac *,
     238             :                      const struct bwi_rf_lo *, struct bwi_rf_lo *, uint8_t);
     239             : void             bwi_rf_calc_nrssi_slope_11b(struct bwi_mac *);
     240             : void             bwi_rf_set_nrssi_ofs_11g(struct bwi_mac *);
     241             : void             bwi_rf_calc_nrssi_slope_11g(struct bwi_mac *);
     242             : void             bwi_rf_init_sw_nrssi_table(struct bwi_mac *);
     243             : void             bwi_rf_init_hw_nrssi_table(struct bwi_mac *, uint16_t);
     244             : void             bwi_rf_set_nrssi_thr_11b(struct bwi_mac *);
     245             : int32_t          _nrssi_threshold(const struct bwi_rf *, int32_t);
     246             : void             bwi_rf_set_nrssi_thr_11g(struct bwi_mac *);
     247             : void             bwi_rf_clear_tssi(struct bwi_mac *);
     248             : void             bwi_rf_clear_state(struct bwi_rf *);
     249             : void             bwi_rf_on_11a(struct bwi_mac *);
     250             : void             bwi_rf_on_11bg(struct bwi_mac *);
     251             : void             bwi_rf_set_ant_mode(struct bwi_mac *, int);
     252             : int              bwi_rf_get_latest_tssi(struct bwi_mac *, int8_t[], uint16_t);
     253             : int              bwi_rf_tssi2dbm(struct bwi_mac *, int8_t, int8_t *);
     254             : int              bwi_rf_calc_rssi_bcm2050(struct bwi_mac *,
     255             :                      const struct bwi_rxbuf_hdr *);
     256             : int              bwi_rf_calc_rssi_bcm2053(struct bwi_mac *,
     257             :                      const struct bwi_rxbuf_hdr *);
     258             : int              bwi_rf_calc_rssi_bcm2060(struct bwi_mac *,
     259             :                      const struct bwi_rxbuf_hdr *);
     260             : uint16_t         bwi_rf_lo_measure_11b(struct bwi_mac *);
     261             : void             bwi_rf_lo_update_11b(struct bwi_mac *);
     262             : 
     263             : /* INTERFACE */
     264             : uint16_t         bwi_read_sprom(struct bwi_softc *, uint16_t);
     265             : void             bwi_setup_desc32(struct bwi_softc *, struct bwi_desc32 *, int,
     266             :                      int, bus_addr_t, int, int);
     267             : void             bwi_power_on(struct bwi_softc *, int);
     268             : int              bwi_power_off(struct bwi_softc *, int);
     269             : int              bwi_regwin_switch(struct bwi_softc *, struct bwi_regwin *,
     270             :                      struct bwi_regwin **);
     271             : int              bwi_regwin_select(struct bwi_softc *, int);
     272             : void             bwi_regwin_info(struct bwi_softc *, uint16_t *, uint8_t *);
     273             : void             bwi_led_attach(struct bwi_softc *);
     274             : void             bwi_led_newstate(struct bwi_softc *, enum ieee80211_state);
     275             : uint16_t         bwi_led_onoff(struct bwi_led *, uint16_t, int);
     276             : void             bwi_led_event(struct bwi_softc *, int);
     277             : void             bwi_led_blink_start(struct bwi_softc *, int, int);
     278             : void             bwi_led_blink_next(void *);
     279             : void             bwi_led_blink_end(void *);
     280             : int              bwi_bbp_attach(struct bwi_softc *);
     281             : int              bwi_bus_init(struct bwi_softc *, struct bwi_mac *);
     282             : void             bwi_get_card_flags(struct bwi_softc *);
     283             : void             bwi_get_eaddr(struct bwi_softc *, uint16_t, uint8_t *);
     284             : void             bwi_get_clock_freq(struct bwi_softc *,
     285             :                      struct bwi_clock_freq *);
     286             : int              bwi_set_clock_mode(struct bwi_softc *, enum bwi_clock_mode);
     287             : int              bwi_set_clock_delay(struct bwi_softc *);
     288             : int              bwi_ioctl(struct ifnet *, u_long, caddr_t);
     289             : void             bwi_start(struct ifnet *);
     290             : void             bwi_watchdog(struct ifnet *);
     291             : void             bwi_newstate_begin(struct bwi_softc *, enum ieee80211_state);
     292             : void             bwi_init_statechg(struct bwi_softc *, int);
     293             : int              bwi_newstate(struct ieee80211com *, enum ieee80211_state, int);
     294             : int              bwi_media_change(struct ifnet *);
     295             : void             bwi_iter_func(void *, struct ieee80211_node *);
     296             : void             bwi_amrr_timeout(void *);
     297             : void             bwi_newassoc(struct ieee80211com *, struct ieee80211_node *,
     298             :                      int);
     299             : struct ieee80211_node
     300             :                 *bwi_node_alloc(struct ieee80211com *ic);
     301             : int              bwi_dma_alloc(struct bwi_softc *);
     302             : void             bwi_dma_free(struct bwi_softc *);
     303             : int              bwi_dma_ring_alloc(struct bwi_softc *,
     304             :                      struct bwi_ring_data *, bus_size_t, uint32_t);
     305             : int              bwi_dma_txstats_alloc(struct bwi_softc *, uint32_t,
     306             :                      bus_size_t);
     307             : void             bwi_dma_txstats_free(struct bwi_softc *);
     308             : int              bwi_dma_mbuf_create30(struct bwi_softc *);
     309             : int              bwi_dma_mbuf_create(struct bwi_softc *);
     310             : void             bwi_dma_mbuf_destroy(struct bwi_softc *, int, int);
     311             : void             bwi_enable_intrs(struct bwi_softc *, uint32_t);
     312             : void             bwi_disable_intrs(struct bwi_softc *, uint32_t);
     313             : int              bwi_init_tx_ring32(struct bwi_softc *, int);
     314             : void             bwi_init_rxdesc_ring32(struct bwi_softc *, uint32_t,
     315             :                      bus_addr_t, int, int);
     316             : int              bwi_init_rx_ring32(struct bwi_softc *);
     317             : int              bwi_init_txstats32(struct bwi_softc *);
     318             : void             bwi_setup_rx_desc32(struct bwi_softc *, int, bus_addr_t, int);
     319             : void             bwi_setup_tx_desc32(struct bwi_softc *, struct bwi_ring_data *,
     320             :                      int, bus_addr_t, int);
     321             : int              bwi_newbuf30(struct bwi_softc *, int, int);
     322             : int              bwi_newbuf(struct bwi_softc *, int, int);
     323             : void             bwi_set_addr_filter(struct bwi_softc *, uint16_t,
     324             :                      const uint8_t *);
     325             : int              bwi_set_chan(struct bwi_softc *, uint8_t);
     326             : void             bwi_next_scan(void *);
     327             : int              bwi_rxeof(struct bwi_softc *, int);
     328             : int              bwi_rxeof32(struct bwi_softc *);
     329             : void             bwi_reset_rx_ring32(struct bwi_softc *, uint32_t);
     330             : void             bwi_free_txstats32(struct bwi_softc *);
     331             : void             bwi_free_rx_ring32(struct bwi_softc *);
     332             : void             bwi_free_tx_ring32(struct bwi_softc *, int);
     333             : uint8_t          bwi_plcp2rate(uint32_t, enum ieee80211_phymode);
     334             : void             bwi_ofdm_plcp_header(uint32_t *, int, uint8_t);
     335             : void             bwi_ds_plcp_header(struct ieee80211_ds_plcp_hdr *, int,
     336             :                      uint8_t);
     337             : void             bwi_plcp_header(void *, int, uint8_t);
     338             : int              bwi_encap(struct bwi_softc *, int, struct mbuf *,
     339             :                      struct ieee80211_node *);
     340             : void             bwi_start_tx32(struct bwi_softc *, uint32_t, int);
     341             : void             bwi_txeof_status32(struct bwi_softc *);
     342             : void             _bwi_txeof(struct bwi_softc *, uint16_t);
     343             : void             bwi_txeof_status(struct bwi_softc *, int);
     344             : void             bwi_txeof(struct bwi_softc *);
     345             : int              bwi_bbp_power_on(struct bwi_softc *, enum bwi_clock_mode);
     346             : void             bwi_bbp_power_off(struct bwi_softc *);
     347             : int              bwi_get_pwron_delay(struct bwi_softc *sc);
     348             : int              bwi_bus_attach(struct bwi_softc *);
     349             : const char      *bwi_regwin_name(const struct bwi_regwin *);
     350             : int              bwi_regwin_is_enabled(struct bwi_softc *, struct bwi_regwin *);
     351             : uint32_t         bwi_regwin_disable_bits(struct bwi_softc *);
     352             : void             bwi_regwin_enable(struct bwi_softc *, struct bwi_regwin *,
     353             :                      uint32_t);
     354             : void             bwi_regwin_disable(struct bwi_softc *, struct bwi_regwin *,
     355             :                      uint32_t);
     356             : void             bwi_set_bssid(struct bwi_softc *, const uint8_t *);
     357             : void             bwi_updateslot(struct ieee80211com *);
     358             : void             bwi_calibrate(void *);
     359             : int              bwi_calc_rssi(struct bwi_softc *,
     360             :                      const struct bwi_rxbuf_hdr *);
     361             : uint8_t          bwi_ack_rate(struct ieee80211_node *, uint8_t);
     362             : uint16_t         bwi_txtime(struct ieee80211com *, struct ieee80211_node *,
     363             :                      uint, uint8_t, uint32_t);
     364             : enum bwi_modtype
     365             :                  bwi_rate2modtype(uint8_t);
     366             : 
     367             : 
     368             : static const uint8_t bwi_sup_macrev[] = { 2, 4, 5, 6, 7, 9, 10 };
     369             : 
     370             : #define SUP_BPHY(num)   { .rev = num, .init = bwi_phy_init_11b_rev##num }
     371             : 
     372             : static const struct {
     373             :         uint8_t rev;
     374             :         void    (*init)(struct bwi_mac *);
     375             : } bwi_sup_bphy[] = {
     376             :         SUP_BPHY(2),
     377             :         SUP_BPHY(4),
     378             :         SUP_BPHY(5),
     379             :         SUP_BPHY(6)
     380             : };
     381             : 
     382             : #undef SUP_BPHY
     383             : 
     384             : #define BWI_PHYTBL_WRSSI        0x1000
     385             : #define BWI_PHYTBL_NOISE_SCALE  0x1400
     386             : #define BWI_PHYTBL_NOISE        0x1800
     387             : #define BWI_PHYTBL_ROTOR        0x2000
     388             : #define BWI_PHYTBL_DELAY        0x2400
     389             : #define BWI_PHYTBL_RSSI         0x4000
     390             : #define BWI_PHYTBL_SIGMA_SQ     0x5000
     391             : #define BWI_PHYTBL_WRSSI_REV1   0x5400
     392             : #define BWI_PHYTBL_FREQ         0x5800
     393             : 
     394             : static const uint16_t   bwi_phy_freq_11g_rev1[] =
     395             :         { BWI_PHY_FREQ_11G_REV1 };
     396             : static const uint16_t   bwi_phy_noise_11g_rev1[] =
     397             :         { BWI_PHY_NOISE_11G_REV1 };
     398             : static const uint16_t   bwi_phy_noise_11g[] =
     399             :         { BWI_PHY_NOISE_11G };
     400             : static const uint32_t   bwi_phy_rotor_11g_rev1[] =
     401             :         { BWI_PHY_ROTOR_11G_REV1 };
     402             : static const uint16_t   bwi_phy_noise_scale_11g_rev2[] =
     403             :         { BWI_PHY_NOISE_SCALE_11G_REV2 };
     404             : static const uint16_t   bwi_phy_noise_scale_11g_rev7[] =
     405             :         { BWI_PHY_NOISE_SCALE_11G_REV7 };
     406             : static const uint16_t   bwi_phy_noise_scale_11g[] =
     407             :         { BWI_PHY_NOISE_SCALE_11G };
     408             : static const uint16_t   bwi_phy_sigma_sq_11g_rev2[] =
     409             :         { BWI_PHY_SIGMA_SQ_11G_REV2 };
     410             : static const uint16_t   bwi_phy_sigma_sq_11g_rev7[] =
     411             :         { BWI_PHY_SIGMA_SQ_11G_REV7 };
     412             : static const uint32_t   bwi_phy_delay_11g_rev1[] =
     413             :         { BWI_PHY_DELAY_11G_REV1 };
     414             : 
     415             : /* RF */
     416             : #define RF_LO_WRITE(mac, lo)    bwi_rf_lo_write((mac), (lo))
     417             : 
     418             : #define BWI_RF_2GHZ_CHAN(chan) \
     419             :         (ieee80211_ieee2mhz((chan), IEEE80211_CHAN_2GHZ) - 2400)
     420             : 
     421             : #define BWI_DEFAULT_IDLE_TSSI   52
     422             : 
     423             : struct rf_saveregs {
     424             :         uint16_t        phy_01;
     425             :         uint16_t        phy_03;
     426             :         uint16_t        phy_0a;
     427             :         uint16_t        phy_15;
     428             :         uint16_t        phy_2a;
     429             :         uint16_t        phy_30;
     430             :         uint16_t        phy_35;
     431             :         uint16_t        phy_60;
     432             :         uint16_t        phy_429;
     433             :         uint16_t        phy_802;
     434             :         uint16_t        phy_811;
     435             :         uint16_t        phy_812;
     436             :         uint16_t        phy_814;
     437             :         uint16_t        phy_815;
     438             : 
     439             :         uint16_t        rf_43;
     440             :         uint16_t        rf_52;
     441             :         uint16_t        rf_7a;
     442             : };
     443             : 
     444             : #define SAVE_RF_REG(mac, regs, n)       (regs)->rf_##n = RF_READ((mac), 0x##n)
     445             : #define RESTORE_RF_REG(mac, regs, n)    RF_WRITE((mac), 0x##n, (regs)->rf_##n)
     446             : 
     447             : #define SAVE_PHY_REG(mac, regs, n)      (regs)->phy_##n = PHY_READ((mac), 0x##n)
     448             : #define RESTORE_PHY_REG(mac, regs, n)   PHY_WRITE((mac), 0x##n, (regs)->phy_##n)
     449             : 
     450             : static const int8_t     bwi_txpower_map_11b[BWI_TSSI_MAX] =
     451             :         { BWI_TXPOWER_MAP_11B };
     452             : static const int8_t     bwi_txpower_map_11g[BWI_TSSI_MAX] =
     453             :         { BWI_TXPOWER_MAP_11G };
     454             : 
     455             : /* IF_BWI */
     456             : 
     457             : struct bwi_myaddr_bssid {
     458             :         uint8_t         myaddr[IEEE80211_ADDR_LEN];
     459             :         uint8_t         bssid[IEEE80211_ADDR_LEN];
     460             : } __packed;
     461             : 
     462             : #define IEEE80211_DS_PLCP_SERVICE_LOCKED        0x04
     463             : #define IEEE80211_DS_PLCL_SERVICE_PBCC          0x08
     464             : #define IEEE80211_DS_PLCP_SERVICE_LENEXT5       0x20
     465             : #define IEEE80211_DS_PLCP_SERVICE_LENEXT6       0x40
     466             : #define IEEE80211_DS_PLCP_SERVICE_LENEXT7       0x80
     467             : 
     468             : struct cfdriver bwi_cd = {
     469             :         NULL, "bwi", DV_IFNET
     470             : };
     471             : 
     472             : static const struct {
     473             :         uint16_t        did_min;
     474             :         uint16_t        did_max;
     475             :         uint16_t        bbp_id;
     476             : } bwi_bbpid_map[] = {
     477             :         { 0x4301, 0x4301, 0x4301 },
     478             :         { 0x4305, 0x4307, 0x4307 },
     479             :         { 0x4402, 0x4403, 0x4402 },
     480             :         { 0x4610, 0x4615, 0x4610 },
     481             :         { 0x4710, 0x4715, 0x4710 },
     482             :         { 0x4720, 0x4725, 0x4309 }
     483             : };
     484             : 
     485             : static const struct {
     486             :         uint16_t        bbp_id;
     487             :         int             nregwin;
     488             : } bwi_regwin_count[] = {
     489             :         { 0x4301, 5 },
     490             :         { 0x4306, 6 },
     491             :         { 0x4307, 5 },
     492             :         { 0x4310, 8 },
     493             :         { 0x4401, 3 },
     494             :         { 0x4402, 3 },
     495             :         { 0x4610, 9 },
     496             :         { 0x4704, 9 },
     497             :         { 0x4710, 9 },
     498             :         { 0x5365, 7 }
     499             : };
     500             : 
     501             : #define CLKSRC(src)                             \
     502             : [BWI_CLKSRC_ ## src] = {                        \
     503             :         .freq_min = BWI_CLKSRC_ ##src## _FMIN,  \
     504             :         .freq_max = BWI_CLKSRC_ ##src## _FMAX   \
     505             : }
     506             : 
     507             : static const struct {
     508             :         uint    freq_min;
     509             :         uint    freq_max;
     510             : } bwi_clkfreq[BWI_CLKSRC_MAX] = {
     511             :         CLKSRC(LP_OSC),
     512             :         CLKSRC(CS_OSC),
     513             :         CLKSRC(PCI)
     514             : };
     515             : 
     516             : #undef CLKSRC
     517             : 
     518             : #define VENDOR_LED_ACT(vendor)                          \
     519             : {                                                       \
     520             :         .vid = PCI_VENDOR_##vendor,                     \
     521             :         .led_act = { BWI_VENDOR_LED_ACT_##vendor }      \
     522             : }
     523             : 
     524             : const struct {
     525             :         uint16_t        vid;
     526             :         uint8_t         led_act[BWI_LED_MAX];
     527             : } bwi_vendor_led_act[] = {
     528             :         VENDOR_LED_ACT(COMPAQ),
     529             :         VENDOR_LED_ACT(LINKSYS)
     530             : };
     531             : 
     532             : const uint8_t bwi_default_led_act[BWI_LED_MAX] =
     533             :         { BWI_VENDOR_LED_ACT_DEFAULT };
     534             : 
     535             : #undef VENDOR_LED_ACT
     536             : 
     537             : const struct {
     538             :         int     on_dur;
     539             :         int     off_dur;
     540             : } bwi_led_duration[109] = {
     541             :         { 400, 100 }, {   0,   0 }, { 150 ,  75 }, {   0,   0 }, {  90,  45 },
     542             :         {   0,   0 }, {   0,   0 }, {   0,    0 }, {   0,   0 }, {   0,   0 },
     543             :         {   0,   0 }, {  66,  34 }, {  53,   26 }, {   0,   0 }, {   0,   0 },
     544             :         {   0,   0 }, {   0,   0 }, {   0,    0 }, {  42,  21 }, {   0,   0 },
     545             :         {   0,   0 }, {   0,   0 }, {  35,   17 }, {   0,   0 }, {  32,  16 },
     546             :         {   0,   0 }, {   0,   0 }, {   0,    0 }, {   0,   0 }, {   0,   0 },
     547             :         {   0,   0 }, {   0,   0 }, {   0,    0 }, {   0,   0 }, {   0,   0 },
     548             :         {   0,   0 }, {  21,  10 }, {   0,    0 }, {   0,   0 }, {   0,   0 },
     549             :         {   0,   0 }, {   0,   0 }, {   0,    0 }, {   0,   0 }, {   0,   0 },
     550             :         {   0,   0 }, {   0,   0 }, {   0,    0 }, {  16,   8 }, {   0,   0 },
     551             :         {   0,   0 }, {   0,   0 }, {   0,    0 }, {   0,   0 }, {   0,   0 },
     552             :         {   0,   0 }, {   0,   0 }, {   0,    0 }, {   0,   0 }, {   0,   0 },
     553             :         {   0,   0 }, {   0,   0 }, {   0,    0 }, {   0,   0 }, {   0,   0 },
     554             :         {   0,   0 }, {   0,   0 }, {   0,    0 }, {   0,   0 }, {   0,   0 },
     555             :         {   0,   0 }, {   0,   0 }, {  11,    5 }, {   0,   0 }, {   0,   0 },
     556             :         {   0,   0 }, {   0,   0 }, {   0,    0 }, {   0,   0 }, {   0,   0 },
     557             :         {   0,   0 }, {   0,   0 }, {   0,    0 }, {   0,   0 }, {   0,   0 },
     558             :         {   0,   0 }, {   0,   0 }, {   0,    0 }, {   0,   0 }, {   0,   0 },
     559             :         {   0,   0 }, {   0,   0 }, {   0,    0 }, {   0,   0 }, {   0,   0 },
     560             :         {   0,   0 }, {   9,   4 }, {   0,    0 }, {   0,   0 }, {   0,   0 },
     561             :         {   0,   0 }, {   0,   0 }, {   0,    0 }, {   0,   0 }, {   0,   0 },
     562             :         {   0,   0 }, {   0,   0 }, {   0,    0 }, {   7,   3 }
     563             : };
     564             : 
     565             : static const uint8_t bwi_zero_addr[IEEE80211_ADDR_LEN];
     566             : 
     567             : 
     568             : /* CODE */
     569             : 
     570             : int
     571           0 : bwi_intr(void *xsc)
     572             : {
     573           0 :         struct bwi_softc *sc = xsc;
     574             :         struct bwi_mac *mac;
     575           0 :         struct ifnet *ifp = &sc->sc_ic.ic_if;
     576             :         uint32_t intr_status;
     577           0 :         uint32_t txrx_intr_status[BWI_TXRX_NRING];
     578             :         int i, txrx_error, tx = 0, rx_data = -1;
     579             : 
     580           0 :         if ((ifp->if_flags & IFF_RUNNING) == 0)
     581           0 :                 return (0);
     582             : 
     583             :         /*
     584             :          * Get interrupt status
     585             :          */
     586           0 :         intr_status = CSR_READ_4(sc, BWI_MAC_INTR_STATUS);
     587           0 :         if (intr_status == 0xffffffff)  /* Not for us */
     588           0 :                 return (0);
     589             : 
     590           0 :         intr_status &= CSR_READ_4(sc, BWI_MAC_INTR_MASK);
     591           0 :         if (intr_status == 0)           /* Nothing is interesting */
     592           0 :                 return (0);
     593             : 
     594             :         DPRINTF(2, "%s: intr status 0x%08x\n",
     595             :             sc->sc_dev.dv_xname, intr_status);
     596             : 
     597           0 :         KASSERT(sc->sc_cur_regwin->rw_type == BWI_REGWIN_T_MAC);
     598           0 :         mac = (struct bwi_mac *)sc->sc_cur_regwin;
     599             : 
     600             :         txrx_error = 0;
     601             : 
     602           0 :         for (i = 0; i < BWI_TXRX_NRING; ++i) {
     603             :                 uint32_t mask;
     604             : 
     605           0 :                 if (BWI_TXRX_IS_RX(i))
     606           0 :                         mask = BWI_TXRX_RX_INTRS;
     607             :                 else
     608             :                         mask = BWI_TXRX_TX_INTRS;
     609             : 
     610           0 :                 txrx_intr_status[i] =
     611           0 :                     CSR_READ_4(sc, BWI_TXRX_INTR_STATUS(i)) & mask;
     612             : 
     613           0 :                 if (txrx_intr_status[i] & BWI_TXRX_INTR_ERROR) {
     614           0 :                         printf("%s: intr fatal TX/RX (%d) error 0x%08x\n",
     615           0 :                             sc->sc_dev.dv_xname, i, txrx_intr_status[i]);
     616             :                         txrx_error = 1;
     617           0 :                 }
     618             :         }
     619             : 
     620             :         /*
     621             :          * Acknowledge interrupt
     622             :          */
     623           0 :         CSR_WRITE_4(sc, BWI_MAC_INTR_STATUS, intr_status);
     624             : 
     625           0 :         for (i = 0; i < BWI_TXRX_NRING; ++i)
     626           0 :                 CSR_WRITE_4(sc, BWI_TXRX_INTR_STATUS(i), txrx_intr_status[i]);
     627             : 
     628             :         /* Disable all interrupts */
     629           0 :         bwi_disable_intrs(sc, BWI_ALL_INTRS);
     630             : 
     631           0 :         if (intr_status & BWI_INTR_PHY_TXERR) {
     632           0 :                 if (mac->mac_flags & BWI_MAC_F_PHYE_RESET) {
     633           0 :                         printf("intr PHY TX error\n");
     634             :                         /* XXX to netisr0? */
     635           0 :                         bwi_init_statechg(sc, 0);
     636           0 :                         return (1);
     637             :                 }
     638             :         }
     639             : 
     640             :         if (txrx_error) {
     641             :                 /* TODO: reset device */
     642             :         }
     643             : 
     644           0 :         if (intr_status & BWI_INTR_TBTT)
     645           0 :                 bwi_mac_config_ps(mac);
     646             : 
     647           0 :         if (intr_status & BWI_INTR_EO_ATIM)
     648           0 :                 printf("%s: EO_ATIM\n", sc->sc_dev.dv_xname);
     649             : 
     650           0 :         if (intr_status & BWI_INTR_PMQ) {
     651           0 :                 for (;;) {
     652           0 :                         if ((CSR_READ_4(sc, BWI_MAC_PS_STATUS) & 0x8) == 0)
     653             :                                 break;
     654             :                 }
     655           0 :                 CSR_WRITE_2(sc, BWI_MAC_PS_STATUS, 0x2);
     656           0 :         }
     657             : 
     658           0 :         if (intr_status & BWI_INTR_NOISE)
     659           0 :                 printf("%s: intr noise\n", sc->sc_dev.dv_xname);
     660             : 
     661           0 :         if (txrx_intr_status[0] & BWI_TXRX_INTR_RX)
     662           0 :                 rx_data = sc->sc_rxeof(sc);
     663             : 
     664           0 :         if (txrx_intr_status[3] & BWI_TXRX_INTR_RX) {
     665           0 :                 sc->sc_txeof_status(sc);
     666             :                 tx = 1;
     667           0 :         }
     668             : 
     669           0 :         if (intr_status & BWI_INTR_TX_DONE) {
     670           0 :                 bwi_txeof(sc);
     671             :                 tx = 1;
     672           0 :         }
     673             : 
     674             :         /* Re-enable interrupts */
     675           0 :         bwi_enable_intrs(sc, BWI_INIT_INTRS);
     676             : 
     677           0 :         if (sc->sc_blink_led != NULL && sc->sc_led_blink) {
     678             :                 int evt = BWI_LED_EVENT_NONE;
     679             : 
     680           0 :                 if (tx && rx_data > 0) {
     681           0 :                         if (sc->sc_rx_rate > sc->sc_tx_rate)
     682           0 :                                 evt = BWI_LED_EVENT_RX;
     683             :                         else
     684             :                                 evt = BWI_LED_EVENT_TX;
     685           0 :                 } else if (tx) {
     686             :                         evt = BWI_LED_EVENT_TX;
     687           0 :                 } else if (rx_data > 0) {
     688             :                         evt = BWI_LED_EVENT_RX;
     689           0 :                 } else if (rx_data == 0) {
     690             :                         evt = BWI_LED_EVENT_POLL;
     691           0 :                 }
     692             : 
     693           0 :                 if (evt != BWI_LED_EVENT_NONE)
     694           0 :                         bwi_led_event(sc, evt);
     695           0 :         }
     696             : 
     697           0 :         return (1);
     698           0 : }
     699             : 
     700             : int
     701           0 : bwi_attach(struct bwi_softc *sc)
     702             : {
     703           0 :         struct ieee80211com *ic = &sc->sc_ic;
     704           0 :         struct ifnet *ifp = &ic->ic_if;
     705             :         struct bwi_mac *mac;
     706             :         struct bwi_phy *phy;
     707             :         int i, error;
     708             : 
     709             :         DPRINTF(1, "\n");
     710             : 
     711             :         /* Initialize LED vars */
     712           0 :         sc->sc_led_idle = (2350 * hz) / 1000;
     713           0 :         sc->sc_led_blink = 1;
     714             : 
     715             :         /* AMRR rate control */
     716           0 :         sc->sc_amrr.amrr_min_success_threshold = 1;
     717           0 :         sc->sc_amrr.amrr_max_success_threshold = 15;
     718           0 :         timeout_set(&sc->sc_amrr_ch, bwi_amrr_timeout, sc);
     719             : 
     720           0 :         timeout_set(&sc->sc_scan_ch, bwi_next_scan, sc);
     721           0 :         timeout_set(&sc->sc_calib_ch, bwi_calibrate, sc);
     722             : 
     723           0 :         bwi_power_on(sc, 1);
     724             : 
     725           0 :         error = bwi_bbp_attach(sc);
     726           0 :         if (error)
     727             :                 goto fail;
     728             : 
     729           0 :         error = bwi_bbp_power_on(sc, BWI_CLOCK_MODE_FAST);
     730           0 :         if (error)
     731             :                 goto fail;
     732             : 
     733           0 :         if (BWI_REGWIN_EXIST(&sc->sc_com_regwin)) {
     734           0 :                 error = bwi_set_clock_delay(sc);
     735           0 :                 if (error)
     736             :                         goto fail;
     737             : 
     738           0 :                 error = bwi_set_clock_mode(sc, BWI_CLOCK_MODE_FAST);
     739           0 :                 if (error)
     740             :                         goto fail;
     741             : 
     742           0 :                 error = bwi_get_pwron_delay(sc);
     743           0 :                 if (error)
     744             :                         goto fail;
     745             :         }
     746             : 
     747           0 :         error = bwi_bus_attach(sc);
     748           0 :         if (error)
     749             :                 goto fail;
     750             : 
     751           0 :         bwi_get_card_flags(sc);
     752             : 
     753           0 :         bwi_led_attach(sc);
     754             : 
     755           0 :         for (i = 0; i < sc->sc_nmac; ++i) {
     756           0 :                 struct bwi_regwin *old;
     757             : 
     758           0 :                 mac = &sc->sc_mac[i];
     759           0 :                 error = bwi_regwin_switch(sc, &mac->mac_regwin, &old);
     760           0 :                 if (error)
     761           0 :                         goto fail;
     762             : 
     763           0 :                 error = bwi_mac_lateattach(mac);
     764           0 :                 if (error)
     765           0 :                         goto fail;
     766             : 
     767           0 :                 error = bwi_regwin_switch(sc, old, NULL);
     768           0 :                 if (error)
     769           0 :                         goto fail;
     770           0 :         }
     771             : 
     772             :         /*
     773             :          * XXX First MAC is known to exist
     774             :          * TODO2
     775             :          */
     776           0 :         mac = &sc->sc_mac[0];
     777           0 :         phy = &mac->mac_phy;
     778             : 
     779           0 :         bwi_bbp_power_off(sc);
     780             : 
     781           0 :         error = bwi_dma_alloc(sc);
     782           0 :         if (error)
     783             :                 goto fail;
     784             : 
     785             :         /* setup interface */
     786           0 :         ifp->if_softc = sc;
     787           0 :         ifp->if_ioctl = bwi_ioctl;
     788           0 :         ifp->if_start = bwi_start;
     789           0 :         ifp->if_watchdog = bwi_watchdog;
     790           0 :         ifp->if_flags = IFF_SIMPLEX | IFF_BROADCAST | IFF_MULTICAST;
     791           0 :         strlcpy(ifp->if_xname, sc->sc_dev.dv_xname, IFNAMSIZ);
     792           0 :         IFQ_SET_MAXLEN(&ifp->if_snd, IFQ_MAXLEN);
     793             : 
     794             :         /* Get locale */
     795           0 :         sc->sc_locale = __SHIFTOUT(bwi_read_sprom(sc, BWI_SPROM_CARD_INFO),
     796             :             BWI_SPROM_CARD_INFO_LOCALE);
     797             :         DPRINTF(1, "%s: locale: %d\n", sc->sc_dev.dv_xname, sc->sc_locale);
     798             : 
     799             :         /*
     800             :          * Setup ratesets, phytype, channels and get MAC address
     801             :          */
     802           0 :         if (phy->phy_mode == IEEE80211_MODE_11B ||
     803           0 :             phy->phy_mode == IEEE80211_MODE_11G) {
     804             :                 uint16_t chan_flags;
     805             : 
     806           0 :                 ic->ic_sup_rates[IEEE80211_MODE_11B] =
     807           0 :                     ieee80211_std_rateset_11b;
     808             : 
     809           0 :                 if (phy->phy_mode == IEEE80211_MODE_11B) {
     810             :                         chan_flags = IEEE80211_CHAN_B;
     811           0 :                         ic->ic_phytype = IEEE80211_T_DS;
     812           0 :                 } else {
     813             :                         chan_flags = IEEE80211_CHAN_CCK |
     814             :                             IEEE80211_CHAN_OFDM |
     815             :                             IEEE80211_CHAN_DYN |
     816             :                             IEEE80211_CHAN_2GHZ;
     817           0 :                         ic->ic_phytype = IEEE80211_T_OFDM;
     818           0 :                         ic->ic_sup_rates[IEEE80211_MODE_11G] =
     819           0 :                             ieee80211_std_rateset_11g;
     820             :                 }
     821             : 
     822             :                 /* XXX depend on locale */
     823           0 :                 for (i = 1; i <= 14; ++i) {
     824           0 :                         ic->ic_channels[i].ic_freq =
     825           0 :                                 ieee80211_ieee2mhz(i, IEEE80211_CHAN_2GHZ);
     826           0 :                         ic->ic_channels[i].ic_flags = chan_flags;
     827             :                 }
     828             : 
     829           0 :                 bwi_get_eaddr(sc, BWI_SPROM_11BG_EADDR, ic->ic_myaddr);
     830           0 :                 if (IEEE80211_IS_MULTICAST(ic->ic_myaddr)) {
     831           0 :                         bwi_get_eaddr(sc, BWI_SPROM_11A_EADDR, ic->ic_myaddr);
     832           0 :                         if (IEEE80211_IS_MULTICAST(ic->ic_myaddr)) {
     833           0 :                                 printf("%s: invalid MAC address: %s\n",
     834             :                                     sc->sc_dev.dv_xname,
     835           0 :                                     ether_sprintf(ic->ic_myaddr));
     836           0 :                         }
     837             :                 }
     838           0 :         } else if (phy->phy_mode == IEEE80211_MODE_11A) {
     839             :                 /* TODO: 11A */
     840             :                 error = ENXIO;
     841           0 :                 goto fail;
     842             :         } else
     843           0 :                 panic("unknown phymode %d", phy->phy_mode);
     844             : 
     845           0 :         printf(", address %s\n", ether_sprintf(ic->ic_myaddr));
     846             : 
     847           0 :         sc->sc_fw_version = BWI_FW_VERSION3;
     848           0 :         sc->sc_dwell_time = 200;
     849             : 
     850           0 :         ic->ic_caps = IEEE80211_C_SHSLOT |
     851             :             IEEE80211_C_SHPREAMBLE |
     852             :             IEEE80211_C_WEP |
     853             :             IEEE80211_C_RSN |
     854             :             IEEE80211_C_MONITOR;
     855           0 :         ic->ic_state = IEEE80211_S_INIT;
     856           0 :         ic->ic_opmode = IEEE80211_M_STA;
     857             : 
     858           0 :         ic->ic_updateslot = bwi_updateslot;
     859             : 
     860           0 :         if_attach(ifp);
     861           0 :         ieee80211_ifattach(ifp);
     862             : 
     863           0 :         sc->sc_newstate = ic->ic_newstate;
     864           0 :         ic->ic_newstate = bwi_newstate;
     865           0 :         ic->ic_newassoc = bwi_newassoc;
     866           0 :         ic->ic_node_alloc = bwi_node_alloc;
     867             : 
     868           0 :         ieee80211_media_init(ifp, bwi_media_change, ieee80211_media_status);
     869             : 
     870           0 :         if (error) {
     871           0 :                 ieee80211_ifdetach(ifp);
     872           0 :                 goto fail;
     873             :         }
     874             : 
     875             : #if NBPFILTER > 0
     876           0 :         bpfattach(&sc->sc_drvbpf, ifp, DLT_IEEE802_11_RADIO,
     877             :             sizeof(struct ieee80211_frame) + 64);
     878             : 
     879           0 :         sc->sc_rxtap_len = sizeof(sc->sc_rxtapu);
     880           0 :         sc->sc_rxtap.wr_ihdr.it_len = htole16(sc->sc_rxtap_len);
     881           0 :         sc->sc_rxtap.wr_ihdr.it_present = htole32(BWI_RX_RADIOTAP_PRESENT);
     882             : 
     883           0 :         sc->sc_txtap_len = sizeof(sc->sc_txtapu);
     884           0 :         sc->sc_txtap.wt_ihdr.it_len = htole16(sc->sc_txtap_len);
     885           0 :         sc->sc_txtap.wt_ihdr.it_present = htole32(BWI_TX_RADIOTAP_PRESENT);
     886             : #endif
     887             : 
     888           0 :         return (0);
     889             : fail:
     890           0 :         return (error);
     891           0 : }
     892             : 
     893             : int
     894           0 : bwi_detach(void *arg)
     895             : {
     896           0 :         struct bwi_softc *sc = arg;
     897           0 :         struct ifnet *ifp = &sc->sc_ic.ic_if;
     898             :         int s, i;
     899             : 
     900           0 :         bwi_stop(sc, 1);
     901           0 :         ieee80211_ifdetach(ifp);
     902           0 :         if_detach(ifp);
     903             : 
     904           0 :         for (i = 0; i < sc->sc_nmac; ++i)
     905           0 :                 bwi_mac_detach(&sc->sc_mac[i]);
     906             : 
     907           0 :         s = splvm();
     908           0 :         bwi_dma_free(sc);
     909           0 :         splx(s);
     910           0 :         bwi_dma_mbuf_destroy(sc, BWI_TX_NRING, 1);
     911             : 
     912           0 :         return (0);
     913             : }
     914             : 
     915             : /* MAC */
     916             : 
     917             : void
     918           0 : bwi_tmplt_write_4(struct bwi_mac *mac, uint32_t ofs, uint32_t val)
     919             : {
     920           0 :         struct bwi_softc *sc = mac->mac_sc;
     921             : 
     922           0 :         if (mac->mac_flags & BWI_MAC_F_BSWAP)
     923           0 :                 val = swap32(val);
     924             : 
     925           0 :         CSR_WRITE_4(sc, BWI_MAC_TMPLT_CTRL, ofs);
     926           0 :         CSR_WRITE_4(sc, BWI_MAC_TMPLT_DATA, val);
     927           0 : }
     928             : 
     929             : void
     930           0 : bwi_hostflags_write(struct bwi_mac *mac, uint64_t flags)
     931             : {
     932             :         uint64_t val;
     933             : 
     934           0 :         val = flags & 0xffff;
     935           0 :         MOBJ_WRITE_2(mac, BWI_COMM_MOBJ, BWI_COMM_MOBJ_HFLAGS_LO, val);
     936             : 
     937           0 :         val = (flags >> 16) & 0xffff;
     938           0 :         MOBJ_WRITE_2(mac, BWI_COMM_MOBJ, BWI_COMM_MOBJ_HFLAGS_MI, val);
     939             : 
     940             :         /* HI has unclear meaning, so leave it as it is */
     941           0 : }
     942             : 
     943             : uint64_t
     944           0 : bwi_hostflags_read(struct bwi_mac *mac)
     945             : {
     946             :         uint64_t flags, val;
     947             : 
     948             :         /* HI has unclear meaning, so don't touch it */
     949             :         flags = 0;
     950             : 
     951           0 :         val = MOBJ_READ_2(mac, BWI_COMM_MOBJ, BWI_COMM_MOBJ_HFLAGS_MI);
     952           0 :         flags |= val << 16;
     953             : 
     954           0 :         val = MOBJ_READ_2(mac, BWI_COMM_MOBJ, BWI_COMM_MOBJ_HFLAGS_LO);
     955           0 :         flags |= val;
     956             : 
     957           0 :         return (flags);
     958             : }
     959             : 
     960             : uint16_t
     961           0 : bwi_memobj_read_2(struct bwi_mac *mac, uint16_t obj_id, uint16_t ofs0)
     962             : {
     963           0 :         struct bwi_softc *sc = mac->mac_sc;
     964             :         uint32_t data_reg;
     965             :         int ofs;
     966             : 
     967             :         data_reg = BWI_MOBJ_DATA;
     968           0 :         ofs = ofs0 / 4;
     969             : 
     970           0 :         if (ofs0 % 4 != 0)
     971           0 :                 data_reg = BWI_MOBJ_DATA_UNALIGN;
     972             : 
     973           0 :         CSR_WRITE_4(sc, BWI_MOBJ_CTRL, BWI_MOBJ_CTRL_VAL(obj_id, ofs));
     974           0 :         return (CSR_READ_2(sc, data_reg));
     975             : }
     976             : 
     977             : uint32_t
     978           0 : bwi_memobj_read_4(struct bwi_mac *mac, uint16_t obj_id, uint16_t ofs0)
     979             : {
     980           0 :         struct bwi_softc *sc = mac->mac_sc;
     981             :         int ofs;
     982             : 
     983           0 :         ofs = ofs0 / 4;
     984           0 :         if (ofs0 % 4 != 0) {
     985             :                 uint32_t ret;
     986             : 
     987           0 :                 CSR_WRITE_4(sc, BWI_MOBJ_CTRL, BWI_MOBJ_CTRL_VAL(obj_id, ofs));
     988           0 :                 ret = CSR_READ_2(sc, BWI_MOBJ_DATA_UNALIGN);
     989           0 :                 ret <<= 16;
     990             : 
     991           0 :                 CSR_WRITE_4(sc, BWI_MOBJ_CTRL,
     992             :                     BWI_MOBJ_CTRL_VAL(obj_id, ofs + 1));
     993           0 :                 ret |= CSR_READ_2(sc, BWI_MOBJ_DATA);
     994             : 
     995             :                 return (ret);
     996             :         } else {
     997           0 :                 CSR_WRITE_4(sc, BWI_MOBJ_CTRL, BWI_MOBJ_CTRL_VAL(obj_id, ofs));
     998           0 :                 return (CSR_READ_4(sc, BWI_MOBJ_DATA));
     999             :         }
    1000           0 : }
    1001             : 
    1002             : void
    1003           0 : bwi_memobj_write_2(struct bwi_mac *mac, uint16_t obj_id, uint16_t ofs0,
    1004             :     uint16_t v)
    1005             : {
    1006           0 :         struct bwi_softc *sc = mac->mac_sc;
    1007             :         uint32_t data_reg;
    1008             :         int ofs;
    1009             : 
    1010             :         data_reg = BWI_MOBJ_DATA;
    1011           0 :         ofs = ofs0 / 4;
    1012             : 
    1013           0 :         if (ofs0 % 4 != 0)
    1014           0 :                 data_reg = BWI_MOBJ_DATA_UNALIGN;
    1015             : 
    1016           0 :         CSR_WRITE_4(sc, BWI_MOBJ_CTRL, BWI_MOBJ_CTRL_VAL(obj_id, ofs));
    1017           0 :         CSR_WRITE_2(sc, data_reg, v);
    1018           0 : }
    1019             : 
    1020             : void
    1021           0 : bwi_memobj_write_4(struct bwi_mac *mac, uint16_t obj_id, uint16_t ofs0,
    1022             :     uint32_t v)
    1023             : {
    1024           0 :         struct bwi_softc *sc = mac->mac_sc;
    1025             :         int ofs;
    1026             : 
    1027           0 :         ofs = ofs0 / 4;
    1028           0 :         if (ofs0 % 4 != 0) {
    1029             :                 CSR_WRITE_4(sc, BWI_MOBJ_CTRL, BWI_MOBJ_CTRL_VAL(obj_id, ofs));
    1030           0 :                 CSR_WRITE_2(sc, BWI_MOBJ_DATA_UNALIGN, v >> 16);
    1031           0 :                 CSR_WRITE_4(sc, BWI_MOBJ_CTRL,
    1032             :                     BWI_MOBJ_CTRL_VAL(obj_id, ofs + 1));
    1033           0 :                 CSR_WRITE_2(sc, BWI_MOBJ_DATA, v & 0xffff);
    1034           0 :         } else {
    1035             :                 CSR_WRITE_4(sc, BWI_MOBJ_CTRL, BWI_MOBJ_CTRL_VAL(obj_id, ofs));
    1036           0 :                 CSR_WRITE_4(sc, BWI_MOBJ_DATA, v);
    1037             :         }
    1038           0 : }
    1039             : 
    1040             : int
    1041           0 : bwi_mac_lateattach(struct bwi_mac *mac)
    1042             : {
    1043             :         int error;
    1044             : 
    1045           0 :         if (mac->mac_rev >= 5)
    1046           0 :                 CSR_READ_4(mac->mac_sc, BWI_STATE_HI); /* dummy read */
    1047             : 
    1048           0 :         bwi_mac_reset(mac, 1);
    1049             : 
    1050           0 :         error = bwi_phy_attach(mac);
    1051           0 :         if (error)
    1052           0 :                 return (error);
    1053             : 
    1054           0 :         error = bwi_rf_attach(mac);
    1055           0 :         if (error)
    1056           0 :                 return (error);
    1057             : 
    1058             :         /* Link 11B/G PHY, unlink 11A PHY */
    1059           0 :         if (mac->mac_phy.phy_mode == IEEE80211_MODE_11A)
    1060           0 :                 bwi_mac_reset(mac, 0);
    1061             :         else
    1062           0 :                 bwi_mac_reset(mac, 1);
    1063             : 
    1064           0 :         error = bwi_mac_test(mac);
    1065           0 :         if (error)
    1066           0 :                 return (error);
    1067             : 
    1068           0 :         error = bwi_mac_get_property(mac);
    1069           0 :         if (error)
    1070           0 :                 return (error);
    1071             : 
    1072           0 :         error = bwi_rf_map_txpower(mac);
    1073           0 :         if (error)
    1074           0 :                 return (error);
    1075             : 
    1076           0 :         bwi_rf_off(mac);
    1077           0 :         CSR_WRITE_2(mac->mac_sc, BWI_BBP_ATTEN, BWI_BBP_ATTEN_MAGIC);
    1078           0 :         bwi_regwin_disable(mac->mac_sc, &mac->mac_regwin, 0);
    1079             : 
    1080           0 :         return (0);
    1081           0 : }
    1082             : 
    1083             : int
    1084           0 : bwi_mac_init(struct bwi_mac *mac)
    1085             : {
    1086           0 :         struct bwi_softc *sc = mac->mac_sc;
    1087             :         int error, i;
    1088             : 
    1089             :         /* Clear MAC/PHY/RF states */
    1090           0 :         bwi_mac_setup_tpctl(mac);
    1091           0 :         bwi_rf_clear_state(&mac->mac_rf);
    1092           0 :         bwi_phy_clear_state(&mac->mac_phy);
    1093             : 
    1094             :         /* Enable MAC and linked it to PHY */
    1095           0 :         if (!bwi_regwin_is_enabled(sc, &mac->mac_regwin))
    1096           0 :                 bwi_mac_reset(mac, 1);
    1097             : 
    1098             :         /* Initialize backplane */
    1099           0 :         error = bwi_bus_init(sc, mac);
    1100           0 :         if (error)
    1101           0 :                 return (error);
    1102             : 
    1103             :         /* XXX work around for hardware bugs? */
    1104           0 :         if (sc->sc_bus_regwin.rw_rev <= 5 &&
    1105           0 :             sc->sc_bus_regwin.rw_type != BWI_REGWIN_T_BUSPCIE) {
    1106           0 :                 CSR_SETBITS_4(sc, BWI_CONF_LO,
    1107             :                 __SHIFTIN(BWI_CONF_LO_SERVTO, BWI_CONF_LO_SERVTO_MASK) |
    1108             :                 __SHIFTIN(BWI_CONF_LO_REQTO, BWI_CONF_LO_REQTO_MASK));
    1109           0 :         }
    1110             : 
    1111             :         /* Calibrate PHY */
    1112           0 :         error = bwi_phy_calibrate(mac);
    1113           0 :         if (error) {
    1114           0 :                 printf("%s: PHY calibrate failed\n", sc->sc_dev.dv_xname);
    1115           0 :                 return (error);
    1116             :         }
    1117             : 
    1118             :         /* Prepare to initialize firmware */
    1119           0 :         CSR_WRITE_4(sc, BWI_MAC_STATUS,
    1120             :             BWI_MAC_STATUS_UCODE_JUMP0 |
    1121             :             BWI_MAC_STATUS_IHREN);
    1122             : 
    1123             :         /*
    1124             :          * Load and initialize firmwares
    1125             :          */
    1126           0 :         error = bwi_mac_fw_alloc(mac);
    1127           0 :         if (error)
    1128           0 :                 return (error);
    1129             : 
    1130           0 :         error = bwi_mac_fw_load(mac);
    1131           0 :         if (error)
    1132           0 :                 return (error);
    1133             : 
    1134           0 :         error = bwi_mac_gpio_init(mac);
    1135           0 :         if (error)
    1136           0 :                 return (error);
    1137             : 
    1138           0 :         error = bwi_mac_fw_init(mac);
    1139           0 :         if (error)
    1140           0 :                 return (error);
    1141             : 
    1142             :         /*
    1143             :          * Turn on RF
    1144             :          */
    1145           0 :         bwi_rf_on(mac);
    1146             : 
    1147             :         /* TODO: LED, hardware rf enabled is only related to LED setting */
    1148             : 
    1149             :         /*
    1150             :          * Initialize PHY
    1151             :          */
    1152           0 :         CSR_WRITE_2(sc, BWI_BBP_ATTEN, 0);
    1153           0 :         bwi_phy_init(mac);
    1154             : 
    1155             :         /* TODO: interference mitigation */
    1156             : 
    1157             :         /*
    1158             :          * Setup antenna mode
    1159             :          */
    1160           0 :         bwi_rf_set_ant_mode(mac, mac->mac_rf.rf_ant_mode);
    1161             : 
    1162             :         /*
    1163             :          * Initialize operation mode (RX configuration)
    1164             :          */
    1165           0 :         bwi_mac_opmode_init(mac);
    1166             : 
    1167             :         /* XXX what's these */
    1168           0 :         if (mac->mac_rev < 3) {
    1169           0 :                 CSR_WRITE_2(sc, 0x60e, 0);
    1170           0 :                 CSR_WRITE_2(sc, 0x610, 0x8000);
    1171           0 :                 CSR_WRITE_2(sc, 0x604, 0);
    1172           0 :                 CSR_WRITE_2(sc, 0x606, 0x200);
    1173           0 :         } else {
    1174           0 :                 CSR_WRITE_4(sc, 0x188, 0x80000000);
    1175           0 :                 CSR_WRITE_4(sc, 0x18c, 0x2000000);
    1176             :         }
    1177             : 
    1178             :         /*
    1179             :          * Initialize TX/RX interrupts' mask
    1180             :          */
    1181           0 :         CSR_WRITE_4(sc, BWI_MAC_INTR_STATUS, BWI_INTR_TIMER1);
    1182           0 :         for (i = 0; i < BWI_TXRX_NRING; ++i) {
    1183             :                 uint32_t intrs;
    1184             : 
    1185           0 :                 if (BWI_TXRX_IS_RX(i))
    1186           0 :                         intrs = BWI_TXRX_RX_INTRS;
    1187             :                 else
    1188             :                         intrs = BWI_TXRX_TX_INTRS;
    1189           0 :                 CSR_WRITE_4(sc, BWI_TXRX_INTR_MASK(i), intrs);
    1190             :         }
    1191             : 
    1192             :         /* XXX what's this */
    1193           0 :         CSR_SETBITS_4(sc, BWI_STATE_LO, 0x100000);
    1194             : 
    1195             :         /* Setup MAC power up delay */
    1196           0 :         CSR_WRITE_2(sc, BWI_MAC_POWERUP_DELAY, sc->sc_pwron_delay);
    1197             : 
    1198             :         /* Set MAC regwin revision */
    1199           0 :         MOBJ_WRITE_2(mac, BWI_COMM_MOBJ, BWI_COMM_MOBJ_MACREV, mac->mac_rev);
    1200             : 
    1201             :         /*
    1202             :          * Initialize host flags
    1203             :          */
    1204           0 :         bwi_mac_hostflags_init(mac);
    1205             : 
    1206             :         /*
    1207             :          * Initialize BSS parameters
    1208             :          */
    1209           0 :         bwi_mac_bss_param_init(mac);
    1210             : 
    1211             :         /*
    1212             :          * Initialize TX rings
    1213             :          */
    1214           0 :         for (i = 0; i < BWI_TX_NRING; ++i) {
    1215           0 :                 error = sc->sc_init_tx_ring(sc, i);
    1216           0 :                 if (error) {
    1217           0 :                         printf("%s: can't initialize %dth TX ring\n",
    1218           0 :                             sc->sc_dev.dv_xname, i);
    1219           0 :                         return (error);
    1220             :                 }
    1221             :         }
    1222             : 
    1223             :         /*
    1224             :          * Initialize RX ring
    1225             :          */
    1226           0 :         error = sc->sc_init_rx_ring(sc);
    1227           0 :         if (error) {
    1228           0 :                 printf("%s: can't initialize RX ring\n", sc->sc_dev.dv_xname);
    1229           0 :                 return (error);
    1230             :         }
    1231             : 
    1232             :         /*
    1233             :          * Initialize TX stats if the current MAC uses that
    1234             :          */
    1235           0 :         if (mac->mac_flags & BWI_MAC_F_HAS_TXSTATS) {
    1236           0 :                 error = sc->sc_init_txstats(sc);
    1237           0 :                 if (error) {
    1238           0 :                         printf("%s: can't initialize TX stats ring\n",
    1239           0 :                             sc->sc_dev.dv_xname);
    1240           0 :                         return (error);
    1241             :                 }
    1242             :         }
    1243             : 
    1244             :         /* XXX what's these */
    1245           0 :         CSR_WRITE_2(sc, 0x612, 0x50);   /* Force Pre-TBTT to 80? */
    1246           0 :         MOBJ_WRITE_2(mac, BWI_COMM_MOBJ, 0x416, 0x50);
    1247           0 :         MOBJ_WRITE_2(mac, BWI_COMM_MOBJ, 0x414, 0x1f4);
    1248             : 
    1249           0 :         mac->mac_flags |= BWI_MAC_F_INITED;
    1250             : 
    1251           0 :         return (0);
    1252           0 : }
    1253             : 
    1254             : void
    1255           0 : bwi_mac_reset(struct bwi_mac *mac, int link_phy)
    1256             : {
    1257           0 :         struct bwi_softc *sc = mac->mac_sc;
    1258             :         uint32_t flags, state_lo, status;
    1259             : 
    1260             :         flags = BWI_STATE_LO_FLAG_PHYRST | BWI_STATE_LO_FLAG_PHYCLKEN;
    1261           0 :         if (link_phy)
    1262           0 :                 flags |= BWI_STATE_LO_FLAG_PHYLNK;
    1263           0 :         bwi_regwin_enable(sc, &mac->mac_regwin, flags);
    1264           0 :         DELAY(2000);
    1265             : 
    1266           0 :         state_lo = CSR_READ_4(sc, BWI_STATE_LO);
    1267           0 :         state_lo |= BWI_STATE_LO_GATED_CLOCK;
    1268           0 :         state_lo &= ~__SHIFTIN(BWI_STATE_LO_FLAG_PHYRST,
    1269             :                                BWI_STATE_LO_FLAGS_MASK);
    1270           0 :         CSR_WRITE_4(sc, BWI_STATE_LO, state_lo);
    1271             :         /* Flush pending bus write */
    1272           0 :         CSR_READ_4(sc, BWI_STATE_LO);
    1273           0 :         DELAY(1000);
    1274             : 
    1275           0 :         state_lo &= ~BWI_STATE_LO_GATED_CLOCK;
    1276           0 :         CSR_WRITE_4(sc, BWI_STATE_LO, state_lo);
    1277             :         /* Flush pending bus write */
    1278           0 :         CSR_READ_4(sc, BWI_STATE_LO);
    1279           0 :         DELAY(1000);
    1280             : 
    1281           0 :         CSR_WRITE_2(sc, BWI_BBP_ATTEN, 0);
    1282             : 
    1283           0 :         status = CSR_READ_4(sc, BWI_MAC_STATUS);
    1284           0 :         status |= BWI_MAC_STATUS_IHREN;
    1285           0 :         if (link_phy)
    1286           0 :                 status |= BWI_MAC_STATUS_PHYLNK;
    1287             :         else
    1288           0 :                 status &= ~BWI_MAC_STATUS_PHYLNK;
    1289           0 :         CSR_WRITE_4(sc, BWI_MAC_STATUS, status);
    1290             : 
    1291           0 :         if (link_phy) {
    1292             :                 DPRINTF(1, "%s: PHY is linked\n", sc->sc_dev.dv_xname);
    1293           0 :                 mac->mac_phy.phy_flags |= BWI_PHY_F_LINKED;
    1294           0 :         } else {
    1295             :                 DPRINTF(1, "%s: PHY is unlinked\n", sc->sc_dev.dv_xname);
    1296           0 :                 mac->mac_phy.phy_flags &= ~BWI_PHY_F_LINKED;
    1297             :         }
    1298           0 : }
    1299             : 
    1300             : void
    1301           0 : bwi_mac_set_tpctl_11bg(struct bwi_mac *mac, const struct bwi_tpctl *new_tpctl)
    1302             : {
    1303           0 :         struct bwi_rf *rf = &mac->mac_rf;
    1304           0 :         struct bwi_tpctl *tpctl = &mac->mac_tpctl;
    1305             : 
    1306           0 :         if (new_tpctl != NULL) {
    1307           0 :                 KASSERT(new_tpctl->bbp_atten <= BWI_BBP_ATTEN_MAX);
    1308           0 :                 KASSERT(new_tpctl->rf_atten <=
    1309             :                     (rf->rf_rev < 6 ? BWI_RF_ATTEN_MAX0
    1310             :                     : BWI_RF_ATTEN_MAX1));
    1311           0 :                 KASSERT(new_tpctl->tp_ctrl1 <= BWI_TPCTL1_MAX);
    1312             : 
    1313           0 :                 tpctl->bbp_atten = new_tpctl->bbp_atten;
    1314           0 :                 tpctl->rf_atten = new_tpctl->rf_atten;
    1315           0 :                 tpctl->tp_ctrl1 = new_tpctl->tp_ctrl1;
    1316           0 :         }
    1317             : 
    1318             :         /* Set BBP attenuation */
    1319           0 :         bwi_phy_set_bbp_atten(mac, tpctl->bbp_atten);
    1320             : 
    1321             :         /* Set RF attenuation */
    1322           0 :         RF_WRITE(mac, BWI_RFR_ATTEN, tpctl->rf_atten);
    1323           0 :         MOBJ_WRITE_2(mac, BWI_COMM_MOBJ, BWI_COMM_MOBJ_RF_ATTEN,
    1324             :             tpctl->rf_atten);
    1325             : 
    1326             :         /* Set TX power */
    1327           0 :         if (rf->rf_type == BWI_RF_T_BCM2050) {
    1328           0 :                 RF_FILT_SETBITS(mac, BWI_RFR_TXPWR, ~BWI_RFR_TXPWR1_MASK,
    1329             :                     __SHIFTIN(tpctl->tp_ctrl1, BWI_RFR_TXPWR1_MASK));
    1330           0 :         }
    1331             : 
    1332             :         /* Adjust RF Local Oscillator */
    1333           0 :         if (mac->mac_phy.phy_mode == IEEE80211_MODE_11G)
    1334           0 :                 bwi_rf_lo_adjust(mac, tpctl);
    1335           0 : }
    1336             : 
    1337             : int
    1338           0 : bwi_mac_test(struct bwi_mac *mac)
    1339             : {
    1340           0 :         struct bwi_softc *sc = mac->mac_sc;
    1341             :         uint32_t orig_val, val;
    1342             : 
    1343             : #define TEST_VAL1       0xaa5555aa
    1344             : #define TEST_VAL2       0x55aaaa55
    1345             :         /* Save it for later restoring */
    1346           0 :         orig_val = MOBJ_READ_4(mac, BWI_COMM_MOBJ, 0);
    1347             : 
    1348             :         /* Test 1 */
    1349           0 :         MOBJ_WRITE_4(mac, BWI_COMM_MOBJ, 0, TEST_VAL1);
    1350           0 :         val = MOBJ_READ_4(mac, BWI_COMM_MOBJ, 0);
    1351           0 :         if (val != TEST_VAL1) {
    1352           0 :                 printf("%s: TEST1 failed\n", sc->sc_dev.dv_xname);
    1353           0 :                 return (ENXIO);
    1354             :         }
    1355             : 
    1356             :         /* Test 2 */
    1357           0 :         MOBJ_WRITE_4(mac, BWI_COMM_MOBJ, 0, TEST_VAL2);
    1358           0 :         val = MOBJ_READ_4(mac, BWI_COMM_MOBJ, 0);
    1359           0 :         if (val != TEST_VAL2) {
    1360           0 :                 printf("%s: TEST2 failed\n", sc->sc_dev.dv_xname);
    1361           0 :                 return (ENXIO);
    1362             :         }
    1363             : 
    1364             :         /* Restore to the original value */
    1365           0 :         MOBJ_WRITE_4(mac, BWI_COMM_MOBJ, 0, orig_val);
    1366             : 
    1367           0 :         val = CSR_READ_4(sc, BWI_MAC_STATUS);
    1368           0 :         if ((val & ~BWI_MAC_STATUS_PHYLNK) != BWI_MAC_STATUS_IHREN) {
    1369           0 :                 printf("%s: %s failed, MAC status 0x%08x\n",
    1370           0 :                     sc->sc_dev.dv_xname, __func__, val);
    1371           0 :                 return (ENXIO);
    1372             :         }
    1373             : 
    1374           0 :         val = CSR_READ_4(sc, BWI_MAC_INTR_STATUS);
    1375           0 :         if (val != 0) {
    1376           0 :                 printf("%s: %s failed, intr status %08x\n",
    1377           0 :                     sc->sc_dev.dv_xname, __func__, val);
    1378           0 :                 return (ENXIO);
    1379             :         }
    1380             : #undef TEST_VAL2
    1381             : #undef TEST_VAL1
    1382             : 
    1383           0 :         return (0);
    1384           0 : }
    1385             : 
    1386             : void
    1387           0 : bwi_mac_setup_tpctl(struct bwi_mac *mac)
    1388             : {
    1389           0 :         struct bwi_softc *sc = mac->mac_sc;
    1390           0 :         struct bwi_rf *rf = &mac->mac_rf;
    1391           0 :         struct bwi_phy *phy = &mac->mac_phy;
    1392           0 :         struct bwi_tpctl *tpctl = &mac->mac_tpctl;
    1393             : 
    1394             :         /* Calc BBP attenuation */
    1395           0 :         if (rf->rf_type == BWI_RF_T_BCM2050 && rf->rf_rev < 6)
    1396           0 :                 tpctl->bbp_atten = 0;
    1397             :         else
    1398           0 :                 tpctl->bbp_atten = 2;
    1399             : 
    1400             :         /* Calc TX power CTRL1?? */
    1401           0 :         tpctl->tp_ctrl1 = 0;
    1402           0 :         if (rf->rf_type == BWI_RF_T_BCM2050) {
    1403           0 :                 if (rf->rf_rev == 1)
    1404           0 :                         tpctl->tp_ctrl1 = 3;
    1405           0 :                 else if (rf->rf_rev < 6)
    1406           0 :                         tpctl->tp_ctrl1 = 2;
    1407           0 :                 else if (rf->rf_rev == 8)
    1408           0 :                         tpctl->tp_ctrl1 = 1;
    1409             :         }
    1410             : 
    1411             :         /* Empty TX power CTRL2?? */
    1412           0 :         tpctl->tp_ctrl2 = 0xffff;
    1413             : 
    1414             :         /*
    1415             :          * Calc RF attenuation
    1416             :          */
    1417           0 :         if (phy->phy_mode == IEEE80211_MODE_11A) {
    1418           0 :                 tpctl->rf_atten = 0x60;
    1419           0 :                 goto back;
    1420             :         }
    1421             : 
    1422           0 :         if (BWI_IS_BRCM_BCM4309G(sc) && sc->sc_pci_revid < 0x51) {
    1423           0 :                 tpctl->rf_atten = sc->sc_pci_revid < 0x43 ? 2 : 3;
    1424           0 :                 goto back;
    1425             :         }
    1426             : 
    1427           0 :         tpctl->rf_atten = 5;
    1428             : 
    1429           0 :         if (rf->rf_type != BWI_RF_T_BCM2050) {
    1430           0 :                 if (rf->rf_type == BWI_RF_T_BCM2053 && rf->rf_rev == 1)
    1431           0 :                         tpctl->rf_atten = 6;
    1432             :                 goto back;
    1433             :         }
    1434             : 
    1435             :         /*
    1436             :          * NB: If we reaches here and the card is BRCM_BCM4309G,
    1437             :          *     then the card's PCI revision must >= 0x51
    1438             :          */
    1439             : 
    1440             :         /* BCM2050 RF */
    1441           0 :         switch (rf->rf_rev) {
    1442             :         case 1:
    1443           0 :                 if (phy->phy_mode == IEEE80211_MODE_11G) {
    1444           0 :                         if (BWI_IS_BRCM_BCM4309G(sc) || BWI_IS_BRCM_BU4306(sc))
    1445           0 :                                 tpctl->rf_atten = 3;
    1446             :                         else
    1447           0 :                                 tpctl->rf_atten = 1;
    1448             :                 } else {
    1449           0 :                         if (BWI_IS_BRCM_BCM4309G(sc))
    1450           0 :                                 tpctl->rf_atten = 7;
    1451             :                         else
    1452           0 :                                 tpctl->rf_atten = 6;
    1453             :                 }
    1454             :                 break;
    1455             :         case 2:
    1456           0 :                 if (phy->phy_mode == IEEE80211_MODE_11G) {
    1457             :                         /*
    1458             :                          * NOTE: Order of following conditions is critical
    1459             :                          */
    1460           0 :                         if (BWI_IS_BRCM_BCM4309G(sc))
    1461           0 :                                 tpctl->rf_atten = 3;
    1462           0 :                         else if (BWI_IS_BRCM_BU4306(sc))
    1463           0 :                                 tpctl->rf_atten = 5;
    1464           0 :                         else if (sc->sc_bbp_id == BWI_BBPID_BCM4320)
    1465           0 :                                 tpctl->rf_atten = 4;
    1466             :                         else
    1467           0 :                                 tpctl->rf_atten = 3;
    1468             :                 } else {
    1469           0 :                         tpctl->rf_atten = 6;
    1470             :                 }
    1471             :                 break;
    1472             :         case 4:
    1473             :         case 5:
    1474           0 :                 tpctl->rf_atten = 1;
    1475           0 :                 break;
    1476             :         case 8:
    1477           0 :                 tpctl->rf_atten = 0x1a;
    1478           0 :                 break;
    1479             :         }
    1480             : back:
    1481             :         DPRINTF(1, "%s: bbp atten: %u, rf atten: %u, ctrl1: %u, ctrl2: %u\n",
    1482             :             sc->sc_dev.dv_xname, tpctl->bbp_atten, tpctl->rf_atten,
    1483             :             tpctl->tp_ctrl1, tpctl->tp_ctrl2);
    1484           0 : }
    1485             : 
    1486             : void
    1487           0 : bwi_mac_dummy_xmit(struct bwi_mac *mac)
    1488             : {
    1489             : #define PACKET_LEN      5
    1490           0 :         struct bwi_softc *sc = mac->mac_sc;
    1491           0 :         struct bwi_rf *rf = &mac->mac_rf;
    1492             :         const uint32_t *packet;
    1493             :         uint16_t val_50c;
    1494             :         int wait_max, i;
    1495             : 
    1496             :         static const uint32_t   packet_11a[PACKET_LEN] =
    1497             :             { 0x000201cc, 0x00d40000, 0x00000000, 0x01000000, 0x00000000 };
    1498             :         static const uint32_t   packet_11bg[PACKET_LEN] =
    1499             :             { 0x000b846e, 0x00d40000, 0x00000000, 0x01000000, 0x00000000 };
    1500             : 
    1501           0 :         if (mac->mac_phy.phy_mode == IEEE80211_MODE_11A) {
    1502             :                 wait_max = 30;
    1503             :                 packet = packet_11a;
    1504             :                 val_50c = 1;
    1505           0 :         } else {
    1506             :                 wait_max = 250;
    1507             :                 packet = packet_11bg;
    1508             :                 val_50c = 0;
    1509             :         }
    1510             : 
    1511           0 :         for (i = 0; i < PACKET_LEN; ++i)
    1512           0 :                 TMPLT_WRITE_4(mac, i * 4, packet[i]);
    1513             : 
    1514           0 :         CSR_READ_4(sc, BWI_MAC_STATUS); /* dummy read */
    1515             : 
    1516           0 :         CSR_WRITE_2(sc, 0x568, 0);
    1517           0 :         CSR_WRITE_2(sc, 0x7c0, 0);
    1518           0 :         CSR_WRITE_2(sc, 0x50c, val_50c);
    1519           0 :         CSR_WRITE_2(sc, 0x508, 0);
    1520           0 :         CSR_WRITE_2(sc, 0x50a, 0);
    1521           0 :         CSR_WRITE_2(sc, 0x54c, 0);
    1522           0 :         CSR_WRITE_2(sc, 0x56a, 0x14);
    1523           0 :         CSR_WRITE_2(sc, 0x568, 0x826);
    1524           0 :         CSR_WRITE_2(sc, 0x500, 0);
    1525           0 :         CSR_WRITE_2(sc, 0x502, 0x30);
    1526             : 
    1527           0 :         if (rf->rf_type == BWI_RF_T_BCM2050 && rf->rf_rev <= 5)
    1528           0 :                 RF_WRITE(mac, 0x51, 0x17);
    1529             : 
    1530           0 :         for (i = 0; i < wait_max; ++i) {
    1531           0 :                 if (CSR_READ_2(sc, 0x50e) & 0x80)
    1532             :                         break;
    1533           0 :                 DELAY(10);
    1534             :         }
    1535           0 :         for (i = 0; i < 10; ++i) {
    1536           0 :                 if (CSR_READ_2(sc, 0x50e) & 0x400)
    1537             :                         break;
    1538           0 :                 DELAY(10);
    1539             :         }
    1540           0 :         for (i = 0; i < 10; ++i) {
    1541           0 :                 if ((CSR_READ_2(sc, 0x690) & 0x100) == 0)
    1542             :                         break;
    1543           0 :                 DELAY(10);
    1544             :         }
    1545             : 
    1546           0 :         if (rf->rf_type == BWI_RF_T_BCM2050 && rf->rf_rev <= 5)
    1547           0 :                 RF_WRITE(mac, 0x51, 0x37);
    1548             : #undef PACKET_LEN
    1549           0 : }
    1550             : 
    1551             : void
    1552           0 : bwi_mac_init_tpctl_11bg(struct bwi_mac *mac)
    1553             : {
    1554           0 :         struct bwi_softc *sc = mac->mac_sc;
    1555           0 :         struct bwi_phy *phy = &mac->mac_phy;
    1556           0 :         struct bwi_rf *rf = &mac->mac_rf;
    1557           0 :         struct bwi_tpctl tpctl_orig;
    1558             :         int restore_tpctl = 0;
    1559             : 
    1560           0 :         KASSERT(phy->phy_mode != IEEE80211_MODE_11A);
    1561             : 
    1562           0 :         if (BWI_IS_BRCM_BU4306(sc))
    1563           0 :                 return;
    1564             : 
    1565           0 :         PHY_WRITE(mac, 0x28, 0x8018);
    1566           0 :         CSR_CLRBITS_2(sc, BWI_BBP_ATTEN, 0x20);
    1567             : 
    1568           0 :         if (phy->phy_mode == IEEE80211_MODE_11G) {
    1569           0 :                 if ((phy->phy_flags & BWI_PHY_F_LINKED) == 0)
    1570           0 :                         return;
    1571           0 :                 PHY_WRITE(mac, 0x47a, 0xc111);
    1572           0 :         }
    1573           0 :         if (mac->mac_flags & BWI_MAC_F_TPCTL_INITED)
    1574           0 :                 return;
    1575             : 
    1576           0 :         if (phy->phy_mode == IEEE80211_MODE_11B && phy->phy_rev >= 2 &&
    1577           0 :             rf->rf_type == BWI_RF_T_BCM2050) {
    1578           0 :                 RF_SETBITS(mac, 0x76, 0x84);
    1579           0 :         } else {
    1580           0 :                 struct bwi_tpctl tpctl;
    1581             : 
    1582             :                 /* Backup original TX power control variables */
    1583           0 :                 bcopy(&mac->mac_tpctl, &tpctl_orig, sizeof(tpctl_orig));
    1584             :                 restore_tpctl = 1;
    1585             : 
    1586           0 :                 bcopy(&mac->mac_tpctl, &tpctl, sizeof(tpctl));
    1587           0 :                 tpctl.bbp_atten = 11;
    1588           0 :                 tpctl.tp_ctrl1 = 0;
    1589             : #ifdef notyet
    1590             :                 if (rf->rf_rev >= 6 && rf->rf_rev <= 8)
    1591             :                         tpctl.rf_atten = 31;
    1592             :                 else
    1593             : #endif
    1594           0 :                         tpctl.rf_atten = 9;
    1595             : 
    1596           0 :                 bwi_mac_set_tpctl_11bg(mac, &tpctl);
    1597           0 :         }
    1598             : 
    1599           0 :         bwi_mac_dummy_xmit(mac);
    1600             : 
    1601           0 :         mac->mac_flags |= BWI_MAC_F_TPCTL_INITED;
    1602           0 :         rf->rf_base_tssi = PHY_READ(mac, 0x29);
    1603             :         DPRINTF(1, "%s: base tssi %d\n", sc->sc_dev.dv_xname, rf->rf_base_tssi);
    1604             : 
    1605           0 :         if (abs(rf->rf_base_tssi - rf->rf_idle_tssi) >= 20) {
    1606           0 :                 printf("%s: base tssi measure failed\n", sc->sc_dev.dv_xname);
    1607           0 :                 mac->mac_flags |= BWI_MAC_F_TPCTL_ERROR;
    1608           0 :         }
    1609             : 
    1610           0 :         if (restore_tpctl)
    1611           0 :                 bwi_mac_set_tpctl_11bg(mac, &tpctl_orig);
    1612             :         else
    1613           0 :                 RF_CLRBITS(mac, 0x76, 0x84);
    1614             : 
    1615           0 :         bwi_rf_clear_tssi(mac);
    1616           0 : }
    1617             : 
    1618             : void
    1619           0 : bwi_mac_detach(struct bwi_mac *mac)
    1620             : {
    1621           0 :         bwi_mac_fw_free(mac);
    1622           0 : }
    1623             : 
    1624             : int
    1625           0 : bwi_get_firmware(const char *name, const uint8_t *ucode, size_t size_ucode,
    1626             :     size_t *size, size_t *offset)
    1627             : {
    1628           0 :         int i, nfiles, off = 0, ret = 1;
    1629             :         struct fwheader *h;
    1630             : 
    1631           0 :         if ((h = malloc(sizeof(struct fwheader), M_DEVBUF, M_NOWAIT)) == NULL)
    1632           0 :                 return (ret);
    1633             : 
    1634             :         /* get number of firmware files */
    1635           0 :         bcopy(ucode, &nfiles, sizeof(nfiles));
    1636           0 :         nfiles = ntohl(nfiles);
    1637             :         off += sizeof(nfiles);
    1638             : 
    1639             :         /* parse header and search the firmware */
    1640           0 :         for (i = 0; i < nfiles && off < size_ucode; i++) {
    1641           0 :                 bzero(h, sizeof(struct fwheader));
    1642           0 :                 bcopy(ucode + off, h, sizeof(struct fwheader));
    1643           0 :                 off += sizeof(struct fwheader);
    1644             : 
    1645           0 :                 if (strcmp(name, h->filename) == 0) {
    1646             :                         ret = 0;
    1647           0 :                         *size = ntohl(h->filesize);
    1648           0 :                         *offset = ntohl(h->fileoffset);
    1649           0 :                         break;
    1650             :                 }
    1651             :         }
    1652             : 
    1653           0 :         free(h, M_DEVBUF, sizeof *h);
    1654             : 
    1655           0 :         return (ret);
    1656           0 : }
    1657             : 
    1658             : int
    1659           0 : bwi_fwimage_is_valid(struct bwi_softc *sc, uint8_t *fw, size_t fw_len,
    1660             :     char *fw_name, uint8_t fw_type)
    1661             : {
    1662             :         const struct bwi_fwhdr *hdr;
    1663             : 
    1664           0 :         if (fw_len < sizeof(*hdr)) {
    1665           0 :                 printf("%s: invalid firmware (%s): invalid size %zu\n",
    1666           0 :                     sc->sc_dev.dv_xname, fw_name, fw_len);
    1667           0 :                 return (1);
    1668             :         }
    1669             : 
    1670           0 :         hdr = (const struct bwi_fwhdr *)fw;
    1671             : 
    1672           0 :         if (fw_type != BWI_FW_T_IV) {
    1673             :                 /*
    1674             :                  * Don't verify IV's size, it has different meaning
    1675             :                  */
    1676           0 :                 if (betoh32(hdr->fw_size) != fw_len - sizeof(*hdr)) {
    1677           0 :                         printf("%s: invalid firmware (%s): size mismatch, "
    1678             :                             "fw %u, real %zu\n",
    1679           0 :                             sc->sc_dev.dv_xname,
    1680             :                             fw_name,
    1681             :                             betoh32(hdr->fw_size),
    1682             :                             fw_len - sizeof(*hdr));
    1683           0 :                         return (1);
    1684             :                 }
    1685             :         }
    1686             : 
    1687           0 :         if (hdr->fw_type != fw_type) {
    1688           0 :                 printf("%s: invalid firmware (%s): type mismatch, "
    1689             :                     "fw \'%c\', target \'%c\'\n",
    1690           0 :                     sc->sc_dev.dv_xname, fw_name, hdr->fw_type, fw_type);
    1691           0 :                 return (1);
    1692             :         }
    1693             : 
    1694           0 :         if (hdr->fw_gen != BWI_FW_GEN_1) {
    1695           0 :                 printf("%s: invalid firmware (%s): wrong generation, "
    1696             :                     "fw %d, target %d\n",
    1697           0 :                     sc->sc_dev.dv_xname, fw_name, hdr->fw_gen, BWI_FW_GEN_1);
    1698           0 :                 return (1);
    1699             :         }
    1700             : 
    1701           0 :         return (0);
    1702           0 : }
    1703             : 
    1704             : int
    1705           0 : bwi_mac_fw_alloc(struct bwi_mac *mac)
    1706             : {
    1707           0 :         struct bwi_softc *sc = mac->mac_sc;
    1708             :         char *name = "bwi-airforce";
    1709           0 :         size_t offset;
    1710           0 :         char fwname[64];
    1711             :         int idx, error;
    1712             : 
    1713           0 :         if (mac->mac_fw == NULL) {
    1714           0 :                 error = loadfirmware(name, &mac->mac_fw, &mac->mac_fw_size);
    1715           0 :                 if (error != 0) {
    1716           0 :                         printf("%s: error %d, could not read firmware %s\n",
    1717           0 :                             sc->sc_dev.dv_xname, error, name);
    1718           0 :                         mac->mac_fw = NULL;
    1719           0 :                         return (EIO);
    1720             :                 }
    1721             :         }
    1722             : 
    1723           0 :         if (mac->mac_ucode == NULL) {
    1724           0 :                 snprintf(fwname, sizeof(fwname), "ucode%d.fw",
    1725           0 :                     mac->mac_rev >= 5 ? 5 : mac->mac_rev);
    1726             : 
    1727           0 :                 error = bwi_get_firmware(fwname, mac->mac_fw, mac->mac_fw_size,
    1728           0 :                     &mac->mac_ucode_size, &offset);
    1729           0 :                 if (error != 0) {
    1730           0 :                         printf("%s: error %d, could not read firmware %s!\n",
    1731           0 :                             sc->sc_dev.dv_xname, error, fwname);
    1732           0 :                         return (ENOMEM);
    1733             :                 }
    1734           0 :                 mac->mac_ucode = (mac->mac_fw + offset);
    1735             :                 DPRINTF(1, "%s: loaded firmware file %s\n",
    1736             :                     sc->sc_dev.dv_xname, fwname);
    1737             : 
    1738           0 :                 if (bwi_fwimage_is_valid(sc, mac->mac_ucode,
    1739           0 :                     mac->mac_ucode_size, fwname, BWI_FW_T_UCODE))
    1740           0 :                         return (EINVAL);
    1741             :         }
    1742             : 
    1743           0 :         if (mac->mac_pcm == NULL) {
    1744           0 :                 snprintf(fwname, sizeof(fwname), "pcm%d.fw",
    1745           0 :                     mac->mac_rev < 5 ? 4 : 5);
    1746             : 
    1747           0 :                 error = bwi_get_firmware(fwname, mac->mac_fw, mac->mac_fw_size,
    1748           0 :                     &mac->mac_pcm_size, &offset);
    1749           0 :                 if (error != 0) {
    1750           0 :                         printf("%s: error %d, could not read firmware %s!\n",
    1751           0 :                             sc->sc_dev.dv_xname, error, fwname);
    1752           0 :                         return (ENOMEM);
    1753             :                 }
    1754           0 :                 mac->mac_pcm = (mac->mac_fw + offset);
    1755             :                 DPRINTF(1, "%s: loaded firmware file %s\n",
    1756             :                     sc->sc_dev.dv_xname, fwname);
    1757             : 
    1758           0 :                 if (bwi_fwimage_is_valid(sc, mac->mac_pcm,
    1759           0 :                     mac->mac_pcm_size, fwname, BWI_FW_T_PCM))
    1760           0 :                         return (EINVAL);
    1761             :         }
    1762             : 
    1763           0 :         if (mac->mac_iv == NULL) {
    1764             :                 /* TODO: 11A */
    1765           0 :                 if (mac->mac_rev == 2 || mac->mac_rev == 4) {
    1766             :                         idx = 2;
    1767           0 :                 } else if (mac->mac_rev >= 5 && mac->mac_rev <= 10) {
    1768             :                         idx = 5;
    1769             :                 } else {
    1770           0 :                         printf("%s: no suitable IV for MAC rev %d\n",
    1771           0 :                             sc->sc_dev.dv_xname, mac->mac_rev);
    1772           0 :                         return (ENODEV);
    1773             :                 }
    1774             : 
    1775           0 :                 snprintf(fwname, sizeof(fwname), "b0g0initvals%d.fw", idx);
    1776             : 
    1777           0 :                 error = bwi_get_firmware(fwname, mac->mac_fw, mac->mac_fw_size,
    1778           0 :                     &mac->mac_iv_size, &offset);
    1779           0 :                 if (error != 0) {
    1780           0 :                         printf("%s: error %d, could not read firmware %s!\n",
    1781           0 :                             sc->sc_dev.dv_xname, error, fwname);
    1782           0 :                         return (ENOMEM);
    1783             :                 }
    1784           0 :                 mac->mac_iv = (mac->mac_fw + offset);
    1785             :                 DPRINTF(1, "%s: loaded firmware file %s\n",
    1786             :                     sc->sc_dev.dv_xname, fwname);
    1787             : 
    1788           0 :                 if (bwi_fwimage_is_valid(sc, mac->mac_iv,
    1789           0 :                     mac->mac_iv_size, fwname, BWI_FW_T_IV))
    1790           0 :                         return (EINVAL);
    1791             :         }
    1792             : 
    1793           0 :         if (mac->mac_iv_ext == NULL) {
    1794             :                 /* TODO: 11A */
    1795           0 :                 if (mac->mac_rev == 2 || mac->mac_rev == 4 ||
    1796           0 :                     mac->mac_rev >= 11) {
    1797             :                         /* No extended IV */
    1798             :                         goto back;
    1799           0 :                 } else if (mac->mac_rev >= 5 && mac->mac_rev <= 10) {
    1800             :                         idx = 5;
    1801             :                 } else {
    1802           0 :                         printf("%s: no suitable ExtIV for MAC rev %d\n",
    1803           0 :                             sc->sc_dev.dv_xname, mac->mac_rev);
    1804           0 :                         return (ENODEV);
    1805             :                 }
    1806             : 
    1807           0 :                 snprintf(fwname, sizeof(fwname), "b0g0bsinitvals%d.fw", idx);
    1808             : 
    1809           0 :                 error = bwi_get_firmware(fwname, mac->mac_fw, mac->mac_fw_size,
    1810           0 :                     &mac->mac_iv_ext_size, &offset);
    1811           0 :                 if (error != 0) {
    1812           0 :                         printf("%s: error %d, could not read firmware %s!\n",
    1813           0 :                             sc->sc_dev.dv_xname, error, fwname);
    1814           0 :                         return (ENOMEM);
    1815             :                 }
    1816           0 :                 mac->mac_iv_ext = (mac->mac_fw + offset);
    1817             :                 DPRINTF(1, "%s: loaded firmware file %s\n",
    1818             :                     sc->sc_dev.dv_xname, fwname);
    1819             : 
    1820           0 :                 if (bwi_fwimage_is_valid(sc, mac->mac_iv_ext,
    1821           0 :                     mac->mac_iv_ext_size, fwname, BWI_FW_T_IV))
    1822           0 :                         return (EINVAL);
    1823             :         }
    1824             : 
    1825             : back:
    1826           0 :         return (0);
    1827           0 : }
    1828             : 
    1829             : void
    1830           0 : bwi_mac_fw_free(struct bwi_mac *mac)
    1831             : {
    1832           0 :         if (mac->mac_fw != NULL) {
    1833           0 :                 free(mac->mac_fw, M_DEVBUF, mac->mac_fw_size);
    1834           0 :                 mac->mac_fw = NULL;
    1835           0 :         }
    1836           0 : }
    1837             : 
    1838             : int
    1839           0 : bwi_mac_fw_load(struct bwi_mac *mac)
    1840             : {
    1841           0 :         struct bwi_softc *sc = mac->mac_sc;
    1842             :         uint16_t fw_rev;
    1843             :         const uint32_t *fw;
    1844             :         int fw_len, i, error = 0;
    1845             : 
    1846             :         /*
    1847             :          * Load FW image
    1848             :          */
    1849           0 :         fw = (const uint32_t *)(mac->mac_ucode + BWI_FWHDR_SZ);
    1850           0 :         fw_len = (mac->mac_ucode_size - BWI_FWHDR_SZ) / sizeof(uint32_t);
    1851             : 
    1852           0 :         CSR_WRITE_4(sc, BWI_MOBJ_CTRL,
    1853             :             BWI_MOBJ_CTRL_VAL(BWI_FW_UCODE_MOBJ | BWI_WR_MOBJ_AUTOINC, 0));
    1854           0 :         for (i = 0; i < fw_len; ++i) {
    1855           0 :                 CSR_WRITE_4(sc, BWI_MOBJ_DATA, betoh32(fw[i]));
    1856           0 :                 DELAY(10);
    1857             :         }
    1858             : 
    1859             :         /*
    1860             :          * Load PCM image
    1861             :          */
    1862           0 :         fw = (const uint32_t *)(mac->mac_pcm + BWI_FWHDR_SZ);
    1863           0 :         fw_len = (mac->mac_pcm_size - BWI_FWHDR_SZ) / sizeof(uint32_t);
    1864             : 
    1865           0 :         CSR_WRITE_4(sc, BWI_MOBJ_CTRL,
    1866             :             BWI_MOBJ_CTRL_VAL(BWI_FW_PCM_MOBJ, 0x01ea));
    1867           0 :         CSR_WRITE_4(sc, BWI_MOBJ_DATA, 0x4000);
    1868             : 
    1869           0 :         CSR_WRITE_4(sc, BWI_MOBJ_CTRL,
    1870             :             BWI_MOBJ_CTRL_VAL(BWI_FW_PCM_MOBJ, 0x01eb));
    1871           0 :         for (i = 0; i < fw_len; ++i) {
    1872           0 :                 CSR_WRITE_4(sc, BWI_MOBJ_DATA, betoh32(fw[i]));
    1873           0 :                 DELAY(10);
    1874             :         }
    1875             : 
    1876           0 :         CSR_WRITE_4(sc, BWI_MAC_INTR_STATUS, BWI_ALL_INTRS);
    1877           0 :         CSR_WRITE_4(sc, BWI_MAC_STATUS,
    1878             :             BWI_MAC_STATUS_UCODE_START |
    1879             :             BWI_MAC_STATUS_IHREN |
    1880             :             BWI_MAC_STATUS_INFRA);
    1881             : 
    1882             : #define NRETRY  200
    1883           0 :         for (i = 0; i < NRETRY; ++i) {
    1884             :                 uint32_t intr_status;
    1885             : 
    1886           0 :                 intr_status = CSR_READ_4(sc, BWI_MAC_INTR_STATUS);
    1887           0 :                 if (intr_status == BWI_INTR_READY)
    1888           0 :                         break;
    1889           0 :                 DELAY(10);
    1890           0 :         }
    1891           0 :         if (i == NRETRY) {
    1892           0 :                 printf("%s: firmware (fw & pcm) loading timed out\n",
    1893           0 :                     sc->sc_dev.dv_xname);
    1894             :                 error = ETIMEDOUT;
    1895           0 :                 goto out;
    1896             :         }
    1897             : #undef NRETRY
    1898             : 
    1899           0 :         CSR_READ_4(sc, BWI_MAC_INTR_STATUS);    /* dummy read */
    1900             : 
    1901           0 :         fw_rev = MOBJ_READ_2(mac, BWI_COMM_MOBJ, BWI_COMM_MOBJ_FWREV);
    1902           0 :         if (fw_rev > BWI_FW_VERSION3_REVMAX) {
    1903           0 :                 printf("%s: firmware version 4 is not supported yet\n",
    1904           0 :                     sc->sc_dev.dv_xname);
    1905             :                 error = ENODEV;
    1906           0 :                 goto out;
    1907             :         }
    1908             : 
    1909             :         DPRINTF(1, "%s: firmware rev 0x%04x, patch level 0x%04x\n",
    1910             :             sc->sc_dev.dv_xname, fw_rev,
    1911             :             MOBJ_READ_2(mac, BWI_COMM_MOBJ, BWI_COMM_MOBJ_FWPATCHLV));
    1912             : 
    1913             : out:
    1914           0 :         return (error);
    1915             : }
    1916             : 
    1917             : int
    1918           0 : bwi_mac_gpio_init(struct bwi_mac *mac)
    1919             : {
    1920           0 :         struct bwi_softc *sc = mac->mac_sc;
    1921           0 :         struct bwi_regwin *old, *gpio_rw;
    1922             :         uint32_t filt, bits;
    1923             :         int error;
    1924             : 
    1925           0 :         CSR_CLRBITS_4(sc, BWI_MAC_STATUS, BWI_MAC_STATUS_GPOSEL_MASK);
    1926             :         /* TODO: LED */
    1927             : 
    1928           0 :         CSR_SETBITS_2(sc, BWI_MAC_GPIO_MASK, 0xf);
    1929             : 
    1930             :         filt = 0x1f;
    1931             :         bits = 0xf;
    1932           0 :         if (sc->sc_bbp_id == BWI_BBPID_BCM4301) {
    1933             :                 filt |= 0x60;
    1934             :                 bits |= 0x60;
    1935           0 :         }
    1936           0 :         if (sc->sc_card_flags & BWI_CARD_F_PA_GPIO9) {
    1937           0 :                 CSR_SETBITS_2(sc, BWI_MAC_GPIO_MASK, 0x200);
    1938           0 :                 filt |= 0x200;
    1939           0 :                 bits |= 0x200;
    1940           0 :         }
    1941             : 
    1942           0 :         gpio_rw = BWI_GPIO_REGWIN(sc);
    1943           0 :         error = bwi_regwin_switch(sc, gpio_rw, &old);
    1944           0 :         if (error)
    1945           0 :                 return (error);
    1946             : 
    1947           0 :         CSR_FILT_SETBITS_4(sc, BWI_GPIO_CTRL, filt, bits);
    1948             : 
    1949           0 :         return (bwi_regwin_switch(sc, old, NULL));
    1950           0 : }
    1951             : 
    1952             : int
    1953           0 : bwi_mac_gpio_fini(struct bwi_mac *mac)
    1954             : {
    1955           0 :         struct bwi_softc *sc = mac->mac_sc;
    1956           0 :         struct bwi_regwin *old, *gpio_rw;
    1957             :         int error;
    1958             : 
    1959           0 :         gpio_rw = BWI_GPIO_REGWIN(sc);
    1960           0 :         error = bwi_regwin_switch(sc, gpio_rw, &old);
    1961           0 :         if (error)
    1962           0 :                 return (error);
    1963             : 
    1964           0 :         CSR_WRITE_4(sc, BWI_GPIO_CTRL, 0);
    1965             : 
    1966           0 :         return (bwi_regwin_switch(sc, old, NULL));
    1967           0 : }
    1968             : 
    1969             : int
    1970           0 : bwi_mac_fw_load_iv(struct bwi_mac *mac, uint8_t *fw, size_t fw_len)
    1971             : {
    1972           0 :         struct bwi_softc *sc = mac->mac_sc;
    1973             :         const struct bwi_fwhdr *hdr;
    1974             :         const struct bwi_fw_iv *iv;
    1975             :         int n, i, iv_img_size;
    1976             : 
    1977             :         /* Get the number of IVs in the IV image */
    1978           0 :         hdr = (const struct bwi_fwhdr *)fw;
    1979           0 :         n = betoh32(hdr->fw_iv_cnt);
    1980             :         DPRINTF(1, "%s: IV count %d\n", sc->sc_dev.dv_xname, n);
    1981             : 
    1982             :         /* Calculate the IV image size, for later sanity check */
    1983           0 :         iv_img_size = fw_len - sizeof(*hdr);
    1984             : 
    1985             :         /* Locate the first IV */
    1986           0 :         iv = (const struct bwi_fw_iv *)(fw + sizeof(*hdr));
    1987             : 
    1988           0 :         for (i = 0; i < n; ++i) {
    1989             :                 uint16_t iv_ofs, ofs;
    1990             :                 int sz = 0;
    1991             : 
    1992           0 :                 if (iv_img_size < sizeof(iv->iv_ofs)) {
    1993           0 :                         printf("%s: invalid IV image, ofs\n",
    1994           0 :                             sc->sc_dev.dv_xname);
    1995           0 :                         return (EINVAL);
    1996             :                 }
    1997           0 :                 iv_img_size -= sizeof(iv->iv_ofs);
    1998             :                 sz += sizeof(iv->iv_ofs);
    1999             : 
    2000           0 :                 iv_ofs = betoh16(iv->iv_ofs);
    2001             : 
    2002           0 :                 ofs = __SHIFTOUT(iv_ofs, BWI_FW_IV_OFS_MASK);
    2003           0 :                 if (ofs >= 0x1000) {
    2004           0 :                         printf("%s: invalid ofs (0x%04x) for %dth iv\n",
    2005           0 :                             sc->sc_dev.dv_xname, ofs, i);
    2006           0 :                         return (EINVAL);
    2007             :                 }
    2008             : 
    2009           0 :                 if (iv_ofs & BWI_FW_IV_IS_32BIT) {
    2010             :                         uint32_t val32;
    2011             : 
    2012           0 :                         if (iv_img_size < sizeof(iv->iv_val.val32)) {
    2013           0 :                                 printf("%s: invalid IV image, val32\n",
    2014           0 :                                     sc->sc_dev.dv_xname);
    2015           0 :                                 return (EINVAL);
    2016             :                         }
    2017           0 :                         iv_img_size -= sizeof(iv->iv_val.val32);
    2018             :                         sz += sizeof(iv->iv_val.val32);
    2019             : 
    2020           0 :                         val32 = betoh32(iv->iv_val.val32);
    2021           0 :                         CSR_WRITE_4(sc, ofs, val32);
    2022           0 :                 } else {
    2023             :                         uint16_t val16;
    2024             : 
    2025           0 :                         if (iv_img_size < sizeof(iv->iv_val.val16)) {
    2026           0 :                                 printf("%s: invalid IV image, val16\n",
    2027           0 :                                     sc->sc_dev.dv_xname);
    2028           0 :                                 return (EINVAL);
    2029             :                         }
    2030           0 :                         iv_img_size -= sizeof(iv->iv_val.val16);
    2031             :                         sz += sizeof(iv->iv_val.val16);
    2032             : 
    2033           0 :                         val16 = betoh16(iv->iv_val.val16);
    2034           0 :                         CSR_WRITE_2(sc, ofs, val16);
    2035           0 :                 }
    2036             : 
    2037           0 :                 iv = (const struct bwi_fw_iv *)((const uint8_t *)iv + sz);
    2038           0 :         }
    2039             : 
    2040           0 :         if (iv_img_size != 0) {
    2041           0 :                 printf("%s: invalid IV image, size left %d\n",
    2042           0 :                     sc->sc_dev.dv_xname, iv_img_size);
    2043           0 :                 return (EINVAL);
    2044             :         }
    2045             : 
    2046           0 :         return (0);
    2047           0 : }
    2048             : 
    2049             : int
    2050           0 : bwi_mac_fw_init(struct bwi_mac *mac)
    2051             : {
    2052           0 :         struct bwi_softc *sc = mac->mac_sc;
    2053             :         int error;
    2054             : 
    2055           0 :         error = bwi_mac_fw_load_iv(mac, mac->mac_iv, mac->mac_iv_size);
    2056           0 :         if (error) {
    2057           0 :                 printf("%s: load IV failed\n", sc->sc_dev.dv_xname);
    2058           0 :                 return (error);
    2059             :         }
    2060             : 
    2061           0 :         if (mac->mac_iv_ext != NULL) {
    2062           0 :                 error = bwi_mac_fw_load_iv(mac, mac->mac_iv_ext,
    2063           0 :                     mac->mac_iv_ext_size);
    2064           0 :                 if (error)
    2065           0 :                         printf("%s: load ExtIV failed\n", sc->sc_dev.dv_xname);
    2066             :         }
    2067             : 
    2068           0 :         return (error);
    2069           0 : }
    2070             : 
    2071             : void
    2072           0 : bwi_mac_opmode_init(struct bwi_mac *mac)
    2073             : {
    2074           0 :         struct bwi_softc *sc = mac->mac_sc;
    2075           0 :         struct ieee80211com *ic = &sc->sc_ic;
    2076             :         uint32_t mac_status;
    2077             :         uint16_t pre_tbtt;
    2078             : 
    2079           0 :         CSR_CLRBITS_4(sc, BWI_MAC_STATUS, BWI_MAC_STATUS_INFRA);
    2080           0 :         CSR_SETBITS_4(sc, BWI_MAC_STATUS, BWI_MAC_STATUS_INFRA);
    2081           0 :         CSR_SETBITS_4(sc, BWI_MAC_STATUS, BWI_MAC_STATUS_PASS_BCN);
    2082             : 
    2083             :         /* Set probe resp timeout to infinite */
    2084           0 :         MOBJ_WRITE_2(mac, BWI_COMM_MOBJ, BWI_COMM_MOBJ_PROBE_RESP_TO, 0);
    2085             : 
    2086             :         /*
    2087             :          * TODO: factor out following part
    2088             :          */
    2089             : 
    2090           0 :         mac_status = CSR_READ_4(sc, BWI_MAC_STATUS);
    2091           0 :         mac_status &= ~(BWI_MAC_STATUS_OPMODE_HOSTAP |
    2092             :             BWI_MAC_STATUS_PASS_CTL |
    2093             :             BWI_MAC_STATUS_PASS_BADPLCP |
    2094             :             BWI_MAC_STATUS_PASS_BADFCS |
    2095             :             BWI_MAC_STATUS_PROMISC);
    2096           0 :         mac_status |= BWI_MAC_STATUS_INFRA;
    2097             : 
    2098             :         /* Always turn on PROMISC on old hardware */
    2099           0 :         if (mac->mac_rev < 5)
    2100           0 :                 mac_status |= BWI_MAC_STATUS_PROMISC;
    2101             : 
    2102           0 :         switch (ic->ic_opmode) {
    2103             : #ifndef IEEE80211_STA_ONLY
    2104             :         case IEEE80211_M_IBSS:
    2105           0 :                 mac_status &= ~BWI_MAC_STATUS_INFRA;
    2106           0 :                 break;
    2107             :         case IEEE80211_M_HOSTAP:
    2108           0 :                 mac_status |= BWI_MAC_STATUS_OPMODE_HOSTAP;
    2109           0 :                 break;
    2110             : #endif
    2111             :         case IEEE80211_M_MONITOR:
    2112             : #if 0
    2113             :                 /* Do you want data from your microwave oven? */
    2114             :                 mac_status |= BWI_MAC_STATUS_PASS_CTL |
    2115             :                               BWI_MAC_STATUS_PASS_BADPLCP |
    2116             :                               BWI_MAC_STATUS_PASS_BADFCS;
    2117             : #else
    2118           0 :                 mac_status |= BWI_MAC_STATUS_PASS_CTL;
    2119             : #endif
    2120             :                 /* Promisc? */
    2121           0 :                 break;
    2122             :         default:
    2123             :                 break;
    2124             :         }
    2125             : 
    2126           0 :         if (ic->ic_if.if_flags & IFF_PROMISC)
    2127           0 :                 mac_status |= BWI_MAC_STATUS_PROMISC;
    2128             : 
    2129           0 :         CSR_WRITE_4(sc, BWI_MAC_STATUS, mac_status);
    2130             : 
    2131             : #ifndef IEEE80211_STA_ONLY
    2132           0 :         if (ic->ic_opmode != IEEE80211_M_IBSS &&
    2133           0 :             ic->ic_opmode != IEEE80211_M_HOSTAP) {
    2134             : #endif
    2135           0 :                 if (sc->sc_bbp_id == BWI_BBPID_BCM4306 && sc->sc_bbp_rev == 3)
    2136           0 :                         pre_tbtt = 100;
    2137             :                 else
    2138             :                         pre_tbtt = 50;
    2139             : #ifndef IEEE80211_STA_ONLY
    2140             :         } else
    2141             :                 pre_tbtt = 2;
    2142             : #endif
    2143           0 :         CSR_WRITE_2(sc, BWI_MAC_PRE_TBTT, pre_tbtt);
    2144           0 : }
    2145             : 
    2146             : void
    2147           0 : bwi_mac_hostflags_init(struct bwi_mac *mac)
    2148             : {
    2149           0 :         struct bwi_softc *sc = mac->mac_sc;
    2150           0 :         struct bwi_phy *phy = &mac->mac_phy;
    2151           0 :         struct bwi_rf *rf = &mac->mac_rf;
    2152             :         uint64_t host_flags;
    2153             : 
    2154           0 :         if (phy->phy_mode == IEEE80211_MODE_11A)
    2155           0 :                 return;
    2156             : 
    2157           0 :         host_flags = HFLAGS_READ(mac);
    2158           0 :         host_flags |= BWI_HFLAG_SYM_WA;
    2159             : 
    2160           0 :         if (phy->phy_mode == IEEE80211_MODE_11G) {
    2161           0 :                 if (phy->phy_rev == 1)
    2162           0 :                         host_flags |= BWI_HFLAG_GDC_WA;
    2163           0 :                 if (sc->sc_card_flags & BWI_CARD_F_PA_GPIO9)
    2164           0 :                         host_flags |= BWI_HFLAG_OFDM_PA;
    2165           0 :         } else if (phy->phy_mode == IEEE80211_MODE_11B) {
    2166           0 :                 if (phy->phy_rev >= 2 && rf->rf_type == BWI_RF_T_BCM2050)
    2167           0 :                         host_flags &= ~BWI_HFLAG_GDC_WA;
    2168             :         } else {
    2169           0 :                 panic("unknown PHY mode %u", phy->phy_mode);
    2170             :         }
    2171             : 
    2172           0 :         HFLAGS_WRITE(mac, host_flags);
    2173           0 : }
    2174             : 
    2175             : void
    2176           0 : bwi_mac_bss_param_init(struct bwi_mac *mac)
    2177             : {
    2178           0 :         struct bwi_softc *sc = mac->mac_sc;
    2179           0 :         struct bwi_phy *phy = &mac->mac_phy;
    2180           0 :         struct bwi_retry_lim lim;
    2181             :         uint16_t cw_min;
    2182             : 
    2183             :         /*
    2184             :          * Set short/long retry limits
    2185             :          */
    2186           0 :         bzero(&lim, sizeof(lim));
    2187           0 :         lim.shretry = BWI_SHRETRY;
    2188           0 :         lim.shretry_fb = BWI_SHRETRY_FB;
    2189           0 :         lim.lgretry = BWI_LGRETRY;
    2190           0 :         lim.lgretry_fb = BWI_LGRETRY_FB;
    2191           0 :         bwi_mac_set_retry_lim(mac, &lim);
    2192             : 
    2193             :         /*
    2194             :          * Implicitly prevent firmware from sending probe response
    2195             :          * by setting its "probe response timeout" to 1us.
    2196             :          */
    2197           0 :         MOBJ_WRITE_2(mac, BWI_COMM_MOBJ, BWI_COMM_MOBJ_PROBE_RESP_TO, 1);
    2198             : 
    2199             :         /*
    2200             :          * XXX MAC level acknowledge and CW min/max should depend
    2201             :          * on the char rateset of the IBSS/BSS to join.
    2202             :          */
    2203             : 
    2204             :         /*
    2205             :          * Set MAC level acknowledge rates
    2206             :          */
    2207           0 :         bwi_mac_set_ackrates(mac, &sc->sc_ic.ic_sup_rates[phy->phy_mode]);
    2208             : 
    2209             :         /*
    2210             :          * Set CW min
    2211             :          */
    2212           0 :         if (phy->phy_mode == IEEE80211_MODE_11B)
    2213           0 :                 cw_min = IEEE80211_CW_MIN_0;
    2214             :         else
    2215             :                 cw_min = IEEE80211_CW_MIN_1;
    2216           0 :         MOBJ_WRITE_2(mac, BWI_80211_MOBJ, BWI_80211_MOBJ_CWMIN, cw_min);
    2217             : 
    2218             :         /*
    2219             :          * Set CW max
    2220             :          */
    2221           0 :         MOBJ_WRITE_2(mac, BWI_80211_MOBJ, BWI_80211_MOBJ_CWMAX,
    2222             :             IEEE80211_CW_MAX);
    2223           0 : }
    2224             : 
    2225             : void
    2226           0 : bwi_mac_set_retry_lim(struct bwi_mac *mac, const struct bwi_retry_lim *lim)
    2227             : {
    2228             :         /* Short/Long retry limit */
    2229           0 :         MOBJ_WRITE_2(mac, BWI_80211_MOBJ, BWI_80211_MOBJ_SHRETRY,
    2230             :             lim->shretry);
    2231           0 :         MOBJ_WRITE_2(mac, BWI_80211_MOBJ, BWI_80211_MOBJ_LGRETRY,
    2232             :             lim->lgretry);
    2233             : 
    2234             :         /* Short/Long retry fallback limit */
    2235           0 :         MOBJ_WRITE_2(mac, BWI_COMM_MOBJ, BWI_COMM_MOBJ_SHRETRY_FB,
    2236             :             lim->shretry_fb);
    2237           0 :         MOBJ_WRITE_2(mac, BWI_COMM_MOBJ, BWI_COMM_MOBJ_LGRETEY_FB,
    2238             :             lim->lgretry_fb);
    2239           0 : }
    2240             : 
    2241             : void
    2242           0 : bwi_mac_set_ackrates(struct bwi_mac *mac, const struct ieee80211_rateset *rs)
    2243             : {
    2244             :         struct bwi_softc *sc;
    2245             :         int i;
    2246             : 
    2247           0 :         sc = mac->mac_sc;
    2248             : 
    2249             :         DPRINTF(1, "%s: %s\n", sc->sc_dev.dv_xname, __func__);
    2250             : 
    2251             :         /* XXX not standard conforming */
    2252           0 :         for (i = 0; i < rs->rs_nrates; ++i) {
    2253             :                 enum bwi_modtype modtype;
    2254             :                 uint16_t ofs;
    2255             : 
    2256           0 :                 modtype = bwi_rate2modtype(rs->rs_rates[i]);
    2257           0 :                 switch (modtype) {
    2258             :                 case IEEE80211_MODTYPE_DS:
    2259             :                         ofs = 0x4c0;
    2260           0 :                         ofs += (ieee80211_rate2plcp(rs->rs_rates[i],
    2261           0 :                             IEEE80211_MODE_11B) & 0xf) * 2;
    2262           0 :                         break;
    2263             :                 case IEEE80211_MODTYPE_OFDM:
    2264             :                         ofs = 0x480;
    2265           0 :                         ofs += (ieee80211_rate2plcp(rs->rs_rates[i],
    2266           0 :                             IEEE80211_MODE_11G) & 0xf) * 2;
    2267           0 :                         break;
    2268             :                 default:
    2269           0 :                         panic("unsupported modtype %u", modtype);
    2270             :                 }
    2271             : 
    2272           0 :                 MOBJ_WRITE_2(mac, BWI_COMM_MOBJ, ofs + 0x20,
    2273             :                     MOBJ_READ_2(mac, BWI_COMM_MOBJ, ofs));
    2274             :         }
    2275           0 : }
    2276             : 
    2277             : int
    2278           0 : bwi_mac_start(struct bwi_mac *mac)
    2279             : {
    2280           0 :         struct bwi_softc *sc = mac->mac_sc;
    2281             : 
    2282           0 :         CSR_SETBITS_4(sc, BWI_MAC_STATUS, BWI_MAC_STATUS_ENABLE);
    2283           0 :         CSR_WRITE_4(sc, BWI_MAC_INTR_STATUS, BWI_INTR_READY);
    2284             : 
    2285             :         /* Flush pending bus writes */
    2286           0 :         CSR_READ_4(sc, BWI_MAC_STATUS);
    2287           0 :         CSR_READ_4(sc, BWI_MAC_INTR_STATUS);
    2288             : 
    2289           0 :         return (bwi_mac_config_ps(mac));
    2290             : }
    2291             : 
    2292             : int
    2293           0 : bwi_mac_stop(struct bwi_mac *mac)
    2294             : {
    2295           0 :         struct bwi_softc *sc = mac->mac_sc;
    2296             :         int error, i;
    2297             : 
    2298           0 :         error = bwi_mac_config_ps(mac);
    2299           0 :         if (error)
    2300           0 :                 return (error);
    2301             : 
    2302           0 :         CSR_CLRBITS_4(sc, BWI_MAC_STATUS, BWI_MAC_STATUS_ENABLE);
    2303             : 
    2304             :         /* Flush pending bus write */
    2305           0 :         CSR_READ_4(sc, BWI_MAC_STATUS);
    2306             : 
    2307             : #define NRETRY  10000
    2308           0 :         for (i = 0; i < NRETRY; ++i) {
    2309           0 :                 if (CSR_READ_4(sc, BWI_MAC_INTR_STATUS) & BWI_INTR_READY)
    2310             :                         break;
    2311           0 :                 DELAY(1);
    2312             :         }
    2313           0 :         if (i == NRETRY) {
    2314           0 :                 printf("%s: can't stop MAC\n", sc->sc_dev.dv_xname);
    2315           0 :                 return (ETIMEDOUT);
    2316             :         }
    2317             : #undef NRETRY
    2318             : 
    2319           0 :         return (0);
    2320           0 : }
    2321             : 
    2322             : int
    2323           0 : bwi_mac_config_ps(struct bwi_mac *mac)
    2324             : {
    2325           0 :         struct bwi_softc *sc = mac->mac_sc;
    2326             :         uint32_t status;
    2327             : 
    2328           0 :         status = CSR_READ_4(sc, BWI_MAC_STATUS);
    2329             : 
    2330           0 :         status &= ~BWI_MAC_STATUS_HW_PS;
    2331           0 :         status |= BWI_MAC_STATUS_WAKEUP;
    2332           0 :         CSR_WRITE_4(sc, BWI_MAC_STATUS, status);
    2333             : 
    2334             :         /* Flush pending bus write */
    2335           0 :         CSR_READ_4(sc, BWI_MAC_STATUS);
    2336             : 
    2337           0 :         if (mac->mac_rev >= 5) {
    2338             :                 int i;
    2339             : 
    2340             : #define NRETRY  100
    2341           0 :                 for (i = 0; i < NRETRY; ++i) {
    2342           0 :                         if (MOBJ_READ_2(mac, BWI_COMM_MOBJ,
    2343           0 :                             BWI_COMM_MOBJ_UCODE_STATE) != BWI_UCODE_STATE_PS)
    2344             :                                 break;
    2345           0 :                         DELAY(10);
    2346             :                 }
    2347           0 :                 if (i == NRETRY) {
    2348           0 :                         printf("%s: config PS failed\n", sc->sc_dev.dv_xname);
    2349           0 :                         return (ETIMEDOUT);
    2350             :                 }
    2351             : #undef NRETRY
    2352           0 :         }
    2353           0 :         return (0);
    2354           0 : }
    2355             : 
    2356             : void
    2357           0 : bwi_mac_reset_hwkeys(struct bwi_mac *mac)
    2358             : {
    2359             :         /* TODO: firmware crypto */
    2360           0 :         MOBJ_READ_2(mac, BWI_COMM_MOBJ, BWI_COMM_MOBJ_KEYTABLE_OFS);
    2361           0 : }
    2362             : 
    2363             : void
    2364           0 : bwi_mac_shutdown(struct bwi_mac *mac)
    2365             : {
    2366           0 :         struct bwi_softc *sc = mac->mac_sc;
    2367             :         int i;
    2368             : 
    2369           0 :         if (mac->mac_flags & BWI_MAC_F_HAS_TXSTATS)
    2370           0 :                 sc->sc_free_txstats(sc);
    2371             : 
    2372           0 :         sc->sc_free_rx_ring(sc);
    2373             : 
    2374           0 :         for (i = 0; i < BWI_TX_NRING; ++i)
    2375           0 :                 sc->sc_free_tx_ring(sc, i);
    2376             : 
    2377           0 :         bwi_rf_off(mac);
    2378             : 
    2379             :         /* TODO: LED */
    2380             : 
    2381           0 :         bwi_mac_gpio_fini(mac);
    2382             : 
    2383           0 :         bwi_rf_off(mac); /* XXX again */
    2384           0 :         CSR_WRITE_2(sc, BWI_BBP_ATTEN, BWI_BBP_ATTEN_MAGIC);
    2385           0 :         bwi_regwin_disable(sc, &mac->mac_regwin, 0);
    2386             : 
    2387           0 :         mac->mac_flags &= ~BWI_MAC_F_INITED;
    2388           0 : }
    2389             : 
    2390             : int
    2391           0 : bwi_mac_get_property(struct bwi_mac *mac)
    2392             : {
    2393           0 :         struct bwi_softc *sc = mac->mac_sc;
    2394             :         enum bwi_bus_space old_bus_space;
    2395             :         uint32_t val;
    2396             : 
    2397             :         /*
    2398             :          * Byte swap
    2399             :          */
    2400           0 :         val = CSR_READ_4(sc, BWI_MAC_STATUS);
    2401           0 :         if (val & BWI_MAC_STATUS_BSWAP) {
    2402             :                 DPRINTF(1, "%s: need byte swap\n", sc->sc_dev.dv_xname);
    2403           0 :                 mac->mac_flags |= BWI_MAC_F_BSWAP;
    2404           0 :         }
    2405             : 
    2406             :         /*
    2407             :          * DMA address space
    2408             :          */
    2409           0 :         old_bus_space = sc->sc_bus_space;
    2410             : 
    2411           0 :         val = CSR_READ_4(sc, BWI_STATE_HI);
    2412           0 :         if (__SHIFTOUT(val, BWI_STATE_HI_FLAGS_MASK) &
    2413             :             BWI_STATE_HI_FLAG_64BIT) {
    2414             :                 /* 64bit address */
    2415           0 :                 sc->sc_bus_space = BWI_BUS_SPACE_64BIT;
    2416           0 :                 printf(": 64bit bus space not supported\n");
    2417           0 :                 return (ENODEV);
    2418             :         } else {
    2419             :                 uint32_t txrx_reg = BWI_TXRX_CTRL_BASE + BWI_TX32_CTRL;
    2420             : 
    2421           0 :                 CSR_WRITE_4(sc, txrx_reg, BWI_TXRX32_CTRL_ADDRHI_MASK);
    2422           0 :                 if (CSR_READ_4(sc, txrx_reg) & BWI_TXRX32_CTRL_ADDRHI_MASK) {
    2423             :                         /* 32bit address */
    2424           0 :                         sc->sc_bus_space = BWI_BUS_SPACE_32BIT;
    2425             :                         DPRINTF(1, "%s: 32bit bus space\n",
    2426             :                             sc->sc_dev.dv_xname);
    2427           0 :                 } else {
    2428             :                         /* 30bit address */
    2429           0 :                         sc->sc_bus_space = BWI_BUS_SPACE_30BIT;
    2430             :                         DPRINTF(1, "%s: 30bit bus space\n",
    2431             :                             sc->sc_dev.dv_xname);
    2432             :                 }
    2433             :         }
    2434             : 
    2435           0 :         if (old_bus_space != 0 && old_bus_space != sc->sc_bus_space) {
    2436           0 :                 printf("%s: MACs bus space mismatch!\n", sc->sc_dev.dv_xname);
    2437           0 :                 return (ENXIO);
    2438             :         }
    2439             : 
    2440           0 :         return (0);
    2441           0 : }
    2442             : 
    2443             : void
    2444           0 : bwi_mac_updateslot(struct bwi_mac *mac, int shslot)
    2445             : {
    2446             :         struct bwi_softc *sc;
    2447             :         uint16_t slot_time;
    2448             : 
    2449           0 :         sc = mac->mac_sc;
    2450             : 
    2451             :         DPRINTF(1, "%s: %s\n", sc->sc_dev.dv_xname, __func__);
    2452             : 
    2453           0 :         if (mac->mac_phy.phy_mode == IEEE80211_MODE_11B)
    2454           0 :                 return;
    2455             : 
    2456           0 :         if (shslot)
    2457           0 :                 slot_time = IEEE80211_DUR_DS_SHSLOT;
    2458             :         else
    2459             :                 slot_time = IEEE80211_DUR_DS_SLOT;
    2460             : 
    2461           0 :         CSR_WRITE_2(mac->mac_sc, BWI_MAC_SLOTTIME,
    2462             :             slot_time + BWI_MAC_SLOTTIME_ADJUST);
    2463           0 :         MOBJ_WRITE_2(mac, BWI_COMM_MOBJ, BWI_COMM_MOBJ_SLOTTIME, slot_time);
    2464           0 : }
    2465             : 
    2466             : int
    2467           0 : bwi_mac_attach(struct bwi_softc *sc, int id, uint8_t rev)
    2468             : {
    2469             :         struct bwi_mac *mac;
    2470             :         int i;
    2471             : 
    2472           0 :         KASSERT(sc->sc_nmac <= BWI_MAC_MAX && sc->sc_nmac >= 0);
    2473             : 
    2474           0 :         if (sc->sc_nmac == BWI_MAC_MAX) {
    2475           0 :                 printf("%s: too many MACs\n", sc->sc_dev.dv_xname);
    2476           0 :                 return (0);
    2477             :         }
    2478             : 
    2479             :         /*
    2480             :          * More than one MAC is only supported by BCM4309
    2481             :          */
    2482           0 :         if (sc->sc_nmac != 0 &&
    2483           0 :             sc->sc_pci_did != PCI_PRODUCT_BROADCOM_BCM4309) {
    2484             :                 DPRINTF(1, "%s: ignore second MAC\n", sc->sc_dev.dv_xname);
    2485           0 :                 return (0);
    2486             :         }
    2487             : 
    2488           0 :         mac = &sc->sc_mac[sc->sc_nmac];
    2489             : 
    2490             :         /* XXX will this happen? */
    2491           0 :         if (BWI_REGWIN_EXIST(&mac->mac_regwin)) {
    2492           0 :                 printf("%s: %dth MAC already attached\n",
    2493           0 :                     sc->sc_dev.dv_xname, sc->sc_nmac);
    2494           0 :                 return (0);
    2495             :         }
    2496             : 
    2497             :         /*
    2498             :          * Test whether the revision of this MAC is supported
    2499             :          */
    2500           0 :         for (i = 0; i < nitems(bwi_sup_macrev); ++i) {
    2501           0 :                 if (bwi_sup_macrev[i] == rev)
    2502             :                         break;
    2503             :         }
    2504           0 :         if (i == nitems(bwi_sup_macrev)) {
    2505           0 :                 printf("%s: MAC rev %u is not supported\n",
    2506           0 :                     sc->sc_dev.dv_xname, rev);
    2507           0 :                 return (ENXIO);
    2508             :         }
    2509             : 
    2510           0 :         BWI_CREATE_MAC(mac, sc, id, rev);
    2511           0 :         sc->sc_nmac++;
    2512             : 
    2513           0 :         if (mac->mac_rev < 5) {
    2514           0 :                 mac->mac_flags |= BWI_MAC_F_HAS_TXSTATS;
    2515             :                 DPRINTF(1, "%s: has TX stats\n", sc->sc_dev.dv_xname);
    2516           0 :         } else {
    2517           0 :                 mac->mac_flags |= BWI_MAC_F_PHYE_RESET;
    2518             :         }
    2519             : 
    2520           0 :         return (0);
    2521           0 : }
    2522             : 
    2523             : void
    2524           0 : bwi_mac_balance_atten(int *bbp_atten0, int *rf_atten0)
    2525             : {
    2526             :         int bbp_atten, rf_atten, rf_atten_lim = -1;
    2527             : 
    2528           0 :         bbp_atten = *bbp_atten0;
    2529           0 :         rf_atten = *rf_atten0;
    2530             : 
    2531             :         /*
    2532             :          * RF attenuation affects TX power BWI_RF_ATTEN_FACTOR times
    2533             :          * as much as BBP attenuation, so we try our best to keep RF
    2534             :          * attenuation within range.  BBP attenuation will be clamped
    2535             :          * later if it is out of range during balancing.
    2536             :          *
    2537             :          * BWI_RF_ATTEN_MAX0 is used as RF attenuation upper limit.
    2538             :          */
    2539             : 
    2540             :         /*
    2541             :          * Use BBP attenuation to balance RF attenuation
    2542             :          */
    2543           0 :         if (rf_atten < 0)
    2544           0 :                 rf_atten_lim = 0;
    2545           0 :         else if (rf_atten > BWI_RF_ATTEN_MAX0)
    2546           0 :                 rf_atten_lim = BWI_RF_ATTEN_MAX0;
    2547             : 
    2548           0 :         if (rf_atten_lim >= 0) {
    2549           0 :                 bbp_atten += (BWI_RF_ATTEN_FACTOR * (rf_atten - rf_atten_lim));
    2550             :                 rf_atten = rf_atten_lim;
    2551           0 :         }
    2552             : 
    2553             :         /*
    2554             :          * If possible, use RF attenuation to balance BBP attenuation
    2555             :          * NOTE: RF attenuation is still kept within range.
    2556             :          */
    2557           0 :         while (rf_atten < BWI_RF_ATTEN_MAX0 && bbp_atten > BWI_BBP_ATTEN_MAX) {
    2558           0 :                 bbp_atten -= BWI_RF_ATTEN_FACTOR;
    2559           0 :                 ++rf_atten;
    2560             :         }
    2561           0 :         while (rf_atten > 0 && bbp_atten < 0) {
    2562           0 :                 bbp_atten += BWI_RF_ATTEN_FACTOR;
    2563           0 :                 --rf_atten;
    2564             :         }
    2565             : 
    2566             :         /* RF attenuation MUST be within range */
    2567           0 :         KASSERT(rf_atten >= 0 && rf_atten <= BWI_RF_ATTEN_MAX0);
    2568             : 
    2569             :         /*
    2570             :          * Clamp BBP attenuation
    2571             :          */
    2572           0 :         if (bbp_atten < 0)
    2573           0 :                 bbp_atten = 0;
    2574           0 :         else if (bbp_atten > BWI_BBP_ATTEN_MAX)
    2575           0 :                 bbp_atten = BWI_BBP_ATTEN_MAX;
    2576             : 
    2577           0 :         *rf_atten0 = rf_atten;
    2578           0 :         *bbp_atten0 = bbp_atten;
    2579           0 : }
    2580             : 
    2581             : void
    2582           0 : bwi_mac_adjust_tpctl(struct bwi_mac *mac, int rf_atten_adj, int bbp_atten_adj)
    2583             : {
    2584           0 :         struct bwi_softc *sc = mac->mac_sc;
    2585           0 :         struct bwi_rf *rf = &mac->mac_rf;
    2586           0 :         struct bwi_tpctl tpctl;
    2587           0 :         int bbp_atten, rf_atten, tp_ctrl1;
    2588             : 
    2589           0 :         bcopy(&mac->mac_tpctl, &tpctl, sizeof(tpctl));
    2590             : 
    2591             :         /* NOTE: Use signed value to do calculation */
    2592           0 :         bbp_atten = tpctl.bbp_atten;
    2593           0 :         rf_atten = tpctl.rf_atten;
    2594           0 :         tp_ctrl1 = tpctl.tp_ctrl1;
    2595             : 
    2596           0 :         bbp_atten += bbp_atten_adj;
    2597           0 :         rf_atten += rf_atten_adj;
    2598             : 
    2599           0 :         bwi_mac_balance_atten(&bbp_atten, &rf_atten);
    2600             : 
    2601           0 :         if (rf->rf_type == BWI_RF_T_BCM2050 && rf->rf_rev == 2) {
    2602           0 :                 if (rf_atten <= 1) {
    2603           0 :                         if (tp_ctrl1 == 0) {
    2604             :                                 tp_ctrl1 = 3;
    2605           0 :                                 bbp_atten += 2;
    2606           0 :                                 rf_atten += 2;
    2607           0 :                         } else if (sc->sc_card_flags & BWI_CARD_F_PA_GPIO9) {
    2608           0 :                                 bbp_atten +=
    2609           0 :                                 (BWI_RF_ATTEN_FACTOR * (rf_atten - 2));
    2610           0 :                                 rf_atten = 2;
    2611           0 :                         }
    2612           0 :                 } else if (rf_atten > 4 && tp_ctrl1 != 0) {
    2613             :                         tp_ctrl1 = 0;
    2614           0 :                         if (bbp_atten < 3) {
    2615           0 :                                 bbp_atten += 2;
    2616           0 :                                 rf_atten -= 3;
    2617           0 :                         } else {
    2618           0 :                                 bbp_atten -= 2;
    2619           0 :                                 rf_atten -= 2;
    2620             :                         }
    2621             :                 }
    2622           0 :                 bwi_mac_balance_atten(&bbp_atten, &rf_atten);
    2623           0 :         }
    2624             : 
    2625           0 :         tpctl.bbp_atten = bbp_atten;
    2626           0 :         tpctl.rf_atten = rf_atten;
    2627           0 :         tpctl.tp_ctrl1 = tp_ctrl1;
    2628             : 
    2629           0 :         bwi_mac_lock(mac);
    2630           0 :         bwi_mac_set_tpctl_11bg(mac, &tpctl);
    2631           0 :         bwi_mac_unlock(mac);
    2632           0 : }
    2633             : 
    2634             : /*
    2635             :  * http://bcm-specs.sipsolutions.net/RecalculateTransmissionPower
    2636             :  */
    2637             : void
    2638           0 : bwi_mac_calibrate_txpower(struct bwi_mac *mac, enum bwi_txpwrcb_type type)
    2639             : {
    2640           0 :         struct bwi_softc *sc = mac->mac_sc;
    2641           0 :         struct bwi_rf *rf = &mac->mac_rf;
    2642           0 :         int8_t tssi[4], tssi_avg, cur_txpwr;
    2643             :         int error, i, ofdm_tssi;
    2644             :         int txpwr_diff, rf_atten_adj, bbp_atten_adj;
    2645             : 
    2646           0 :         if (mac->mac_flags & BWI_MAC_F_TPCTL_ERROR) {
    2647             :                 DPRINTF(1, "%s: tpctl error happened, can't set txpower\n",
    2648             :                     sc->sc_dev.dv_xname);
    2649           0 :                 return;
    2650             :         }
    2651             : 
    2652           0 :         if (BWI_IS_BRCM_BU4306(sc)) {
    2653             :                 DPRINTF(1, "%s: BU4306, can't set txpower\n",
    2654             :                     sc->sc_dev.dv_xname);
    2655           0 :                 return;
    2656             :         }
    2657             : 
    2658             :         /*
    2659             :          * Save latest TSSI and reset the related memory objects
    2660             :          */
    2661             :         ofdm_tssi = 0;
    2662           0 :         error = bwi_rf_get_latest_tssi(mac, tssi, BWI_COMM_MOBJ_TSSI_DS);
    2663           0 :         if (error) {
    2664             :                 DPRINTF(1, "%s: no DS tssi\n", sc->sc_dev.dv_xname);
    2665             : 
    2666           0 :                 if (mac->mac_phy.phy_mode == IEEE80211_MODE_11B) {
    2667           0 :                         if (type == BWI_TXPWR_FORCE) {
    2668             :                                 rf_atten_adj = 0;
    2669             :                                 bbp_atten_adj = 1;
    2670           0 :                                 goto calib;
    2671             :                         } else {
    2672           0 :                                 return;
    2673             :                         }
    2674             :                 }
    2675             : 
    2676           0 :                 error = bwi_rf_get_latest_tssi(mac, tssi,
    2677             :                     BWI_COMM_MOBJ_TSSI_OFDM);
    2678           0 :                 if (error) {
    2679             :                         DPRINTF(1, "%s: no OFDM tssi\n", sc->sc_dev.dv_xname);
    2680           0 :                         if (type == BWI_TXPWR_FORCE) {
    2681             :                                 rf_atten_adj = 0;
    2682             :                                 bbp_atten_adj = 1;
    2683           0 :                                 goto calib;
    2684             :                         } else {
    2685           0 :                                 return;
    2686             :                         }
    2687             :                 }
    2688             : 
    2689           0 :                 for (i = 0; i < 4; ++i) {
    2690           0 :                         tssi[i] += 0x20;
    2691           0 :                         tssi[i] &= 0x3f;
    2692             :                 }
    2693             :                 ofdm_tssi = 1;
    2694           0 :         }
    2695           0 :         bwi_rf_clear_tssi(mac);
    2696             : 
    2697             :         DPRINTF(1, "%s: tssi0 %d, tssi1 %d, tssi2 %d, tssi3 %d\n",
    2698             :             sc->sc_dev.dv_xname, tssi[0], tssi[1], tssi[2], tssi[3]);
    2699             : 
    2700             :         /*
    2701             :          * Calculate RF/BBP attenuation adjustment based on
    2702             :          * the difference between desired TX power and sampled
    2703             :          * TX power.
    2704             :          */
    2705             :         /* +8 == "each incremented by 1/2" */
    2706           0 :         tssi_avg = (tssi[0] + tssi[1] + tssi[2] + tssi[3] + 8) / 4;
    2707           0 :         if (ofdm_tssi && (HFLAGS_READ(mac) & BWI_HFLAG_PWR_BOOST_DS))
    2708           0 :                 tssi_avg -= 13;
    2709             : 
    2710             :         DPRINTF(1, "%s: tssi avg %d\n", sc->sc_dev.dv_xname, tssi_avg);
    2711             : 
    2712           0 :         error = bwi_rf_tssi2dbm(mac, tssi_avg, &cur_txpwr);
    2713           0 :         if (error)
    2714           0 :                 return;
    2715             :         DPRINTF(1, "%s: current txpower %d\n", sc->sc_dev.dv_xname, cur_txpwr);
    2716             : 
    2717           0 :         txpwr_diff = rf->rf_txpower_max - cur_txpwr; /* XXX ni_txpower */
    2718             : 
    2719           0 :         rf_atten_adj = -howmany(txpwr_diff, 8);
    2720             : 
    2721           0 :         if (type == BWI_TXPWR_INIT) {
    2722             :                 /*
    2723             :                  * Move toward EEPROM max TX power as fast as we can
    2724             :                  */
    2725           0 :                 bbp_atten_adj = -txpwr_diff;
    2726           0 :         } else {
    2727           0 :                 bbp_atten_adj = -(txpwr_diff / 2);
    2728             :         }
    2729           0 :         bbp_atten_adj -= (BWI_RF_ATTEN_FACTOR * rf_atten_adj);
    2730             : 
    2731           0 :         if (rf_atten_adj == 0 && bbp_atten_adj == 0) {
    2732             :                 DPRINTF(1, "%s: no need to adjust RF/BBP attenuation\n",
    2733             :                     sc->sc_dev.dv_xname);
    2734             :                 /* TODO: LO */
    2735           0 :                 return;
    2736             :         }
    2737             : 
    2738             : calib:
    2739             :         DPRINTF(1, "%s: rf atten adjust %d, bbp atten adjust %d\n",
    2740             :             sc->sc_dev.dv_xname, rf_atten_adj, bbp_atten_adj);
    2741           0 :         bwi_mac_adjust_tpctl(mac, rf_atten_adj, bbp_atten_adj);
    2742             :         /* TODO: LO */
    2743           0 : }
    2744             : 
    2745             : void
    2746           0 : bwi_mac_lock(struct bwi_mac *mac)
    2747             : {
    2748           0 :         struct bwi_softc *sc = mac->mac_sc;
    2749             : 
    2750           0 :         KASSERT((mac->mac_flags & BWI_MAC_F_LOCKED) == 0);
    2751             : 
    2752           0 :         if (mac->mac_rev < 3)
    2753           0 :                 bwi_mac_stop(mac);
    2754             :         else
    2755             : #ifndef IEEE80211_STA_ONLY
    2756           0 :         if (sc->sc_ic.ic_opmode != IEEE80211_M_HOSTAP)
    2757             : #endif
    2758           0 :                 bwi_mac_config_ps(mac);
    2759             : 
    2760           0 :         CSR_SETBITS_4(sc, BWI_MAC_STATUS, BWI_MAC_STATUS_RFLOCK);
    2761             : 
    2762             :         /* Flush pending bus write */
    2763           0 :         CSR_READ_4(sc, BWI_MAC_STATUS);
    2764           0 :         DELAY(10);
    2765             : 
    2766           0 :         mac->mac_flags |= BWI_MAC_F_LOCKED;
    2767           0 : }
    2768             : 
    2769             : void
    2770           0 : bwi_mac_unlock(struct bwi_mac *mac)
    2771             : {
    2772           0 :         struct bwi_softc *sc = mac->mac_sc;
    2773             : 
    2774           0 :         KASSERT(mac->mac_flags & BWI_MAC_F_LOCKED);
    2775             : 
    2776           0 :         CSR_READ_2(sc, BWI_PHYINFO); /* dummy read */
    2777             : 
    2778           0 :         CSR_CLRBITS_4(sc, BWI_MAC_STATUS, BWI_MAC_STATUS_RFLOCK);
    2779             : 
    2780           0 :         if (mac->mac_rev < 3)
    2781           0 :                 bwi_mac_start(mac);
    2782             :         else
    2783             : #ifndef IEEE80211_STA_ONLY
    2784           0 :         if (sc->sc_ic.ic_opmode != IEEE80211_M_HOSTAP)
    2785             : #endif
    2786           0 :                 bwi_mac_config_ps(mac);
    2787             : 
    2788           0 :         mac->mac_flags &= ~BWI_MAC_F_LOCKED;
    2789           0 : }
    2790             : 
    2791             : void
    2792           0 : bwi_mac_set_promisc(struct bwi_mac *mac, int promisc)
    2793             : {
    2794           0 :         struct bwi_softc *sc = mac->mac_sc;
    2795             : 
    2796           0 :         if (mac->mac_rev < 5) /* Promisc is always on */
    2797           0 :                 return;
    2798             : 
    2799           0 :         if (promisc)
    2800           0 :                 CSR_SETBITS_4(sc, BWI_MAC_STATUS, BWI_MAC_STATUS_PROMISC);
    2801             :         else
    2802           0 :                 CSR_CLRBITS_4(sc, BWI_MAC_STATUS, BWI_MAC_STATUS_PROMISC);
    2803           0 : }
    2804             : 
    2805             : /* PHY */
    2806             : 
    2807             : void
    2808           0 : bwi_phy_write(struct bwi_mac *mac, uint16_t ctrl, uint16_t data)
    2809             : {
    2810           0 :         struct bwi_softc *sc = mac->mac_sc;
    2811             : 
    2812             :         /* TODO: 11A */
    2813           0 :         CSR_WRITE_2(sc, BWI_PHY_CTRL, ctrl);
    2814           0 :         CSR_WRITE_2(sc, BWI_PHY_DATA, data);
    2815           0 : }
    2816             : 
    2817             : uint16_t
    2818           0 : bwi_phy_read(struct bwi_mac *mac, uint16_t ctrl)
    2819             : {
    2820           0 :         struct bwi_softc *sc = mac->mac_sc;
    2821             : 
    2822             :         /* TODO: 11A */
    2823           0 :         CSR_WRITE_2(sc, BWI_PHY_CTRL, ctrl);
    2824           0 :         return (CSR_READ_2(sc, BWI_PHY_DATA));
    2825             : }
    2826             : 
    2827             : int
    2828           0 : bwi_phy_attach(struct bwi_mac *mac)
    2829             : {
    2830           0 :         struct bwi_softc *sc = mac->mac_sc;
    2831           0 :         struct bwi_phy *phy = &mac->mac_phy;
    2832             :         uint8_t phyrev, phytype, phyver;
    2833             :         uint16_t val;
    2834             :         int i;
    2835             : 
    2836             :         /* Get PHY type/revision/version */
    2837           0 :         val = CSR_READ_2(sc, BWI_PHYINFO);
    2838           0 :         phyrev = __SHIFTOUT(val, BWI_PHYINFO_REV_MASK);
    2839           0 :         phytype = __SHIFTOUT(val, BWI_PHYINFO_TYPE_MASK);
    2840           0 :         phyver = __SHIFTOUT(val, BWI_PHYINFO_VER_MASK);
    2841             :         DPRINTF(1, "%s: PHY type %d, rev %d, ver %d\n",
    2842             :             sc->sc_dev.dv_xname, phytype, phyrev, phyver);
    2843             : 
    2844             :         /*
    2845             :          * Verify whether the revision of the PHY type is supported
    2846             :          * Convert PHY type to ieee80211_phymode
    2847             :          */
    2848           0 :         switch (phytype) {
    2849             :         case BWI_PHYINFO_TYPE_11A:
    2850           0 :                 if (phyrev >= 4) {
    2851           0 :                         printf("%s: unsupported 11A PHY, rev %u\n",
    2852           0 :                             sc->sc_dev.dv_xname, phyrev);
    2853           0 :                         return (ENXIO);
    2854             :                 }
    2855           0 :                 phy->phy_init = bwi_phy_init_11a;
    2856           0 :                 phy->phy_mode = IEEE80211_MODE_11A;
    2857           0 :                 phy->phy_tbl_ctrl = BWI_PHYR_TBL_CTRL_11A;
    2858           0 :                 phy->phy_tbl_data_lo = BWI_PHYR_TBL_DATA_LO_11A;
    2859           0 :                 phy->phy_tbl_data_hi = BWI_PHYR_TBL_DATA_HI_11A;
    2860           0 :                 break;
    2861             :         case BWI_PHYINFO_TYPE_11B:
    2862           0 :                 for (i = 0; i < nitems(bwi_sup_bphy); ++i) {
    2863           0 :                         if (phyrev == bwi_sup_bphy[i].rev) {
    2864           0 :                                 phy->phy_init = bwi_sup_bphy[i].init;
    2865           0 :                                 break;
    2866             :                         }
    2867             :                 }
    2868           0 :                 if (i == nitems(bwi_sup_bphy)) {
    2869           0 :                         printf("%s: unsupported 11B PHY, rev %u\n",
    2870           0 :                             sc->sc_dev.dv_xname, phyrev);
    2871           0 :                         return (ENXIO);
    2872             :                 }
    2873           0 :                 phy->phy_mode = IEEE80211_MODE_11B;
    2874           0 :                 break;
    2875             :         case BWI_PHYINFO_TYPE_11G:
    2876           0 :                 if (phyrev > 8) {
    2877           0 :                         printf("%s: unsupported 11G PHY, rev %u\n",
    2878           0 :                             sc->sc_dev.dv_xname, phyrev);
    2879           0 :                         return (ENXIO);
    2880             :                 }
    2881           0 :                 phy->phy_init = bwi_phy_init_11g;
    2882           0 :                 phy->phy_mode = IEEE80211_MODE_11G;
    2883           0 :                 phy->phy_tbl_ctrl = BWI_PHYR_TBL_CTRL_11G;
    2884           0 :                 phy->phy_tbl_data_lo = BWI_PHYR_TBL_DATA_LO_11G;
    2885           0 :                 phy->phy_tbl_data_hi = BWI_PHYR_TBL_DATA_HI_11G;
    2886           0 :                 break;
    2887             :         default:
    2888           0 :                 printf("%s: unsupported PHY type %d\n",
    2889           0 :                     sc->sc_dev.dv_xname, phytype);
    2890           0 :                 return (ENXIO);
    2891             :         }
    2892           0 :         phy->phy_rev = phyrev;
    2893           0 :         phy->phy_version = phyver;
    2894             : 
    2895           0 :         return (0);
    2896           0 : }
    2897             : 
    2898             : void
    2899           0 : bwi_phy_set_bbp_atten(struct bwi_mac *mac, uint16_t bbp_atten)
    2900             : {
    2901           0 :         struct bwi_phy *phy = &mac->mac_phy;
    2902             :         uint16_t mask = 0x000f;
    2903             : 
    2904           0 :         if (phy->phy_version == 0) {
    2905           0 :                 CSR_FILT_SETBITS_2(mac->mac_sc, BWI_BBP_ATTEN, ~mask,
    2906             :                     __SHIFTIN(bbp_atten, mask));
    2907           0 :         } else {
    2908           0 :                 if (phy->phy_version > 1)
    2909           0 :                         mask <<= 2;
    2910             :                 else
    2911             :                         mask <<= 3;
    2912           0 :                 PHY_FILT_SETBITS(mac, BWI_PHYR_BBP_ATTEN, ~mask,
    2913             :                     __SHIFTIN(bbp_atten, mask));
    2914             :         }
    2915           0 : }
    2916             : 
    2917             : int
    2918           0 : bwi_phy_calibrate(struct bwi_mac *mac)
    2919             : {
    2920           0 :         struct bwi_phy *phy = &mac->mac_phy;
    2921             : 
    2922             :         /* Dummy read */
    2923           0 :         CSR_READ_4(mac->mac_sc, BWI_MAC_STATUS);
    2924             : 
    2925             :         /* Don't re-init */
    2926           0 :         if (phy->phy_flags & BWI_PHY_F_CALIBRATED)
    2927           0 :                 return (0);
    2928             : 
    2929           0 :         if (phy->phy_mode == IEEE80211_MODE_11G && phy->phy_rev == 1) {
    2930           0 :                 bwi_mac_reset(mac, 0);
    2931           0 :                 bwi_phy_init_11g(mac);
    2932           0 :                 bwi_mac_reset(mac, 1);
    2933           0 :         }
    2934             : 
    2935           0 :         phy->phy_flags |= BWI_PHY_F_CALIBRATED;
    2936             : 
    2937           0 :         return (0);
    2938           0 : }
    2939             : 
    2940             : void
    2941           0 : bwi_tbl_write_2(struct bwi_mac *mac, uint16_t ofs, uint16_t data)
    2942             : {
    2943           0 :         struct bwi_phy *phy = &mac->mac_phy;
    2944             : 
    2945           0 :         KASSERT(phy->phy_tbl_ctrl != 0 && phy->phy_tbl_data_lo != 0);
    2946           0 :         PHY_WRITE(mac, phy->phy_tbl_ctrl, ofs);
    2947           0 :         PHY_WRITE(mac, phy->phy_tbl_data_lo, data);
    2948           0 : }
    2949             : 
    2950             : void
    2951           0 : bwi_tbl_write_4(struct bwi_mac *mac, uint16_t ofs, uint32_t data)
    2952             : {
    2953           0 :         struct bwi_phy *phy = &mac->mac_phy;
    2954             : 
    2955           0 :         KASSERT(phy->phy_tbl_data_lo != 0 && phy->phy_tbl_data_hi != 0 &&
    2956             :             phy->phy_tbl_ctrl != 0);
    2957             : 
    2958           0 :         PHY_WRITE(mac, phy->phy_tbl_ctrl, ofs);
    2959           0 :         PHY_WRITE(mac, phy->phy_tbl_data_hi, data >> 16);
    2960           0 :         PHY_WRITE(mac, phy->phy_tbl_data_lo, data & 0xffff);
    2961           0 : }
    2962             : 
    2963             : void
    2964           0 : bwi_nrssi_write(struct bwi_mac *mac, uint16_t ofs, int16_t data)
    2965             : {
    2966           0 :         PHY_WRITE(mac, BWI_PHYR_NRSSI_CTRL, ofs);
    2967           0 :         PHY_WRITE(mac, BWI_PHYR_NRSSI_DATA, (uint16_t)data);
    2968           0 : }
    2969             : 
    2970             : int16_t
    2971           0 : bwi_nrssi_read(struct bwi_mac *mac, uint16_t ofs)
    2972             : {
    2973           0 :         PHY_WRITE(mac, BWI_PHYR_NRSSI_CTRL, ofs);
    2974           0 :         return ((int16_t)PHY_READ(mac, BWI_PHYR_NRSSI_DATA));
    2975             : }
    2976             : 
    2977             : void
    2978           0 : bwi_phy_init_11a(struct bwi_mac *mac)
    2979             : {
    2980             :         /* TODO: 11A */
    2981           0 : }
    2982             : 
    2983             : void
    2984           0 : bwi_phy_init_11g(struct bwi_mac *mac)
    2985             : {
    2986           0 :         struct bwi_softc *sc = mac->mac_sc;
    2987           0 :         struct bwi_phy *phy = &mac->mac_phy;
    2988           0 :         struct bwi_rf *rf = &mac->mac_rf;
    2989           0 :         const struct bwi_tpctl *tpctl = &mac->mac_tpctl;
    2990             : 
    2991           0 :         if (phy->phy_rev == 1)
    2992           0 :                 bwi_phy_init_11b_rev5(mac);
    2993             :         else
    2994           0 :                 bwi_phy_init_11b_rev6(mac);
    2995             : 
    2996           0 :         if (phy->phy_rev >= 2 || (phy->phy_flags & BWI_PHY_F_LINKED))
    2997           0 :                 bwi_phy_config_11g(mac);
    2998             : 
    2999           0 :         if (phy->phy_rev >= 2) {
    3000           0 :                 PHY_WRITE(mac, 0x814, 0);
    3001           0 :                 PHY_WRITE(mac, 0x815, 0);
    3002             : 
    3003           0 :                 if (phy->phy_rev == 2) {
    3004           0 :                         PHY_WRITE(mac, 0x811, 0);
    3005           0 :                         PHY_WRITE(mac, 0x15, 0xc0);
    3006           0 :                 } else if (phy->phy_rev > 5) {
    3007           0 :                         PHY_WRITE(mac, 0x811, 0x400);
    3008           0 :                         PHY_WRITE(mac, 0x15, 0xc0);
    3009           0 :                 }
    3010             :         }
    3011             : 
    3012           0 :         if (phy->phy_rev >= 2 || (phy->phy_flags & BWI_PHY_F_LINKED)) {
    3013             :                 uint16_t val;
    3014             : 
    3015           0 :                 val = PHY_READ(mac, 0x400) & 0xff;
    3016           0 :                 if (val == 3 || val == 5) {
    3017           0 :                         PHY_WRITE(mac, 0x4c2, 0x1816);
    3018           0 :                         PHY_WRITE(mac, 0x4c3, 0x8006);
    3019           0 :                         if (val == 5) {
    3020           0 :                                 PHY_FILT_SETBITS(mac, 0x4cc,
    3021             :                                                  0xff, 0x1f00);
    3022           0 :                         }
    3023             :                 }
    3024           0 :         }
    3025             : 
    3026           0 :         if ((phy->phy_rev <= 2 && (phy->phy_flags & BWI_PHY_F_LINKED)) ||
    3027           0 :             phy->phy_rev >= 2)
    3028           0 :                 PHY_WRITE(mac, 0x47e, 0x78);
    3029             : 
    3030           0 :         if (rf->rf_rev == 8) {
    3031           0 :                 PHY_SETBITS(mac, 0x801, 0x80);
    3032           0 :                 PHY_SETBITS(mac, 0x43e, 0x4);
    3033           0 :         }
    3034             : 
    3035           0 :         if (phy->phy_rev >= 2 && (phy->phy_flags & BWI_PHY_F_LINKED))
    3036           0 :                 bwi_rf_get_gains(mac);
    3037             : 
    3038           0 :         if (rf->rf_rev != 8)
    3039           0 :                 bwi_rf_init(mac);
    3040             : 
    3041           0 :         if (tpctl->tp_ctrl2 == 0xffff) {
    3042           0 :                 bwi_rf_lo_update(mac);
    3043           0 :         } else {
    3044           0 :                 if (rf->rf_type == BWI_RF_T_BCM2050 && rf->rf_rev == 8) {
    3045           0 :                         RF_WRITE(mac, 0x52,
    3046             :                             (tpctl->tp_ctrl1 << 4) | tpctl->tp_ctrl2);
    3047           0 :                 } else {
    3048           0 :                         RF_FILT_SETBITS(mac, 0x52, 0xfff0, tpctl->tp_ctrl2);
    3049             :                 }
    3050             : 
    3051           0 :                 if (phy->phy_rev >= 6) {
    3052           0 :                         PHY_FILT_SETBITS(mac, 0x36, 0xfff,
    3053             :                             tpctl->tp_ctrl2 << 12);
    3054           0 :                 }
    3055             : 
    3056           0 :                 if (sc->sc_card_flags & BWI_CARD_F_PA_GPIO9)
    3057           0 :                         PHY_WRITE(mac, 0x2e, 0x8075);
    3058             :                 else
    3059           0 :                         PHY_WRITE(mac, 0x2e, 0x807f);
    3060             : 
    3061           0 :                 if (phy->phy_rev < 2)
    3062           0 :                         PHY_WRITE(mac, 0x2f, 0x101);
    3063             :                 else
    3064           0 :                         PHY_WRITE(mac, 0x2f, 0x202);
    3065             :         }
    3066             : 
    3067           0 :         if ((phy->phy_flags & BWI_PHY_F_LINKED) || phy->phy_rev >= 2) {
    3068           0 :                 bwi_rf_lo_adjust(mac, tpctl);
    3069           0 :                 PHY_WRITE(mac, 0x80f, 0x8078);
    3070           0 :         }
    3071             : 
    3072           0 :         if ((sc->sc_card_flags & BWI_CARD_F_SW_NRSSI) == 0) {
    3073           0 :                 bwi_rf_init_hw_nrssi_table(mac, 0xffff /* XXX */);
    3074           0 :                 bwi_rf_set_nrssi_thr(mac);
    3075           0 :         } else if ((phy->phy_flags & BWI_PHY_F_LINKED) || phy->phy_rev >= 2) {
    3076           0 :                 if (rf->rf_nrssi[0] == BWI_INVALID_NRSSI) {
    3077           0 :                         KASSERT(rf->rf_nrssi[1] == BWI_INVALID_NRSSI);
    3078           0 :                         bwi_rf_calc_nrssi_slope(mac);
    3079           0 :                 } else {
    3080           0 :                         KASSERT(rf->rf_nrssi[1] != BWI_INVALID_NRSSI);
    3081           0 :                         bwi_rf_set_nrssi_thr(mac);
    3082             :                 }
    3083             :         }
    3084             : 
    3085           0 :         if (rf->rf_rev == 8)
    3086           0 :                 PHY_WRITE(mac, 0x805, 0x3230);
    3087             : 
    3088           0 :         bwi_mac_init_tpctl_11bg(mac);
    3089             : 
    3090           0 :         if (sc->sc_bbp_id == BWI_BBPID_BCM4306 && sc->sc_bbp_pkg == 2) {
    3091           0 :                 PHY_CLRBITS(mac, 0x429, 0x4000);
    3092           0 :                 PHY_CLRBITS(mac, 0x4c3, 0x8000);
    3093           0 :         }
    3094           0 : }
    3095             : 
    3096             : void
    3097           0 : bwi_phy_init_11b_rev2(struct bwi_mac *mac)
    3098             : {
    3099             :         struct bwi_softc *sc;
    3100             : 
    3101           0 :         sc = mac->mac_sc;
    3102             : 
    3103             :         /* TODO: 11B */
    3104           0 :         printf("%s: %s is not implemented yet\n",
    3105           0 :             sc->sc_dev.dv_xname, __func__);
    3106           0 : }
    3107             : 
    3108             : void
    3109           0 : bwi_phy_init_11b_rev4(struct bwi_mac *mac)
    3110             : {
    3111           0 :         struct bwi_softc *sc = mac->mac_sc;
    3112           0 :         struct bwi_rf *rf = &mac->mac_rf;
    3113             :         uint16_t val, ofs;
    3114             :         u_int chan;
    3115             : 
    3116           0 :         CSR_WRITE_2(sc, BWI_BPHY_CTRL, BWI_BPHY_CTRL_INIT);
    3117             : 
    3118           0 :         PHY_WRITE(mac, 0x20, 0x301c);
    3119           0 :         PHY_WRITE(mac, 0x26, 0);
    3120           0 :         PHY_WRITE(mac, 0x30, 0xc6);
    3121           0 :         PHY_WRITE(mac, 0x88, 0x3e00);
    3122             : 
    3123           0 :         for (ofs = 0, val = 0x3c3d; ofs < 30; ++ofs, val -= 0x202)
    3124           0 :                 PHY_WRITE(mac, 0x89 + ofs, val);
    3125             : 
    3126           0 :         CSR_WRITE_2(sc, BWI_PHY_MAGIC_REG1, BWI_PHY_MAGIC_REG1_VAL1);
    3127             : 
    3128           0 :         chan = rf->rf_curchan;
    3129           0 :         if (chan == IEEE80211_CHAN_ANY)
    3130             :                 chan = 6;       /* Force to channel 6 */
    3131           0 :         bwi_rf_set_chan(mac, chan, 0);
    3132             : 
    3133           0 :         if (rf->rf_type != BWI_RF_T_BCM2050) {
    3134           0 :                 RF_WRITE(mac, 0x75, 0x80);
    3135           0 :                 RF_WRITE(mac, 0x79, 0x81);
    3136           0 :         }
    3137             : 
    3138           0 :         RF_WRITE(mac, 0x50, 0x20);
    3139           0 :         RF_WRITE(mac, 0x50, 0x23);
    3140             : 
    3141           0 :         if (rf->rf_type == BWI_RF_T_BCM2050) {
    3142           0 :                 RF_WRITE(mac, 0x50, 0x20);
    3143           0 :                 RF_WRITE(mac, 0x5a, 0x70);
    3144           0 :                 RF_WRITE(mac, 0x5b, 0x7b);
    3145           0 :                 RF_WRITE(mac, 0x5c, 0xb0);
    3146           0 :                 RF_WRITE(mac, 0x7a, 0xf);
    3147           0 :                 PHY_WRITE(mac, 0x38, 0x677);
    3148           0 :                 bwi_rf_init_bcm2050(mac);
    3149           0 :         }
    3150             : 
    3151           0 :         PHY_WRITE(mac, 0x14, 0x80);
    3152           0 :         PHY_WRITE(mac, 0x32, 0xca);
    3153           0 :         if (rf->rf_type == BWI_RF_T_BCM2050)
    3154           0 :                 PHY_WRITE(mac, 0x32, 0xe0);
    3155           0 :         PHY_WRITE(mac, 0x35, 0x7c2);
    3156             : 
    3157           0 :         bwi_rf_lo_update(mac);
    3158             : 
    3159           0 :         PHY_WRITE(mac, 0x26, 0xcc00);
    3160           0 :         if (rf->rf_type == BWI_RF_T_BCM2050)
    3161           0 :                 PHY_WRITE(mac, 0x26, 0xce00);
    3162             : 
    3163           0 :         CSR_WRITE_2(sc, BWI_RF_CHAN_EX, 0x1100);
    3164             : 
    3165           0 :         PHY_WRITE(mac, 0x2a, 0x88a3);
    3166           0 :         if (rf->rf_type == BWI_RF_T_BCM2050)
    3167           0 :                 PHY_WRITE(mac, 0x2a, 0x88c2);
    3168             : 
    3169           0 :         bwi_mac_set_tpctl_11bg(mac, NULL);
    3170           0 :         if (sc->sc_card_flags & BWI_CARD_F_SW_NRSSI) {
    3171           0 :                 bwi_rf_calc_nrssi_slope(mac);
    3172           0 :                 bwi_rf_set_nrssi_thr(mac);
    3173           0 :         }
    3174           0 :         bwi_mac_init_tpctl_11bg(mac);
    3175           0 : }
    3176             : 
    3177             : void
    3178           0 : bwi_phy_init_11b_rev5(struct bwi_mac *mac)
    3179             : {
    3180           0 :         struct bwi_softc *sc = mac->mac_sc;
    3181           0 :         struct bwi_rf *rf = &mac->mac_rf;
    3182           0 :         struct bwi_phy *phy = &mac->mac_phy;
    3183             :         uint orig_chan;
    3184             : 
    3185           0 :         if (phy->phy_version == 1)
    3186           0 :                 RF_SETBITS(mac, 0x7a, 0x50);
    3187             : 
    3188           0 :         if (sc->sc_pci_subvid != PCI_VENDOR_BROADCOM &&
    3189           0 :             sc->sc_pci_subdid != BWI_PCI_SUBDEVICE_BU4306) {
    3190             :                 uint16_t ofs, val;
    3191             : 
    3192             :                 val = 0x2120;
    3193           0 :                 for (ofs = 0xa8; ofs < 0xc7; ++ofs) {
    3194           0 :                         PHY_WRITE(mac, ofs, val);
    3195           0 :                         val += 0x202;
    3196             :                 }
    3197           0 :         }
    3198             : 
    3199           0 :         PHY_FILT_SETBITS(mac, 0x35, 0xf0ff, 0x700);
    3200             : 
    3201           0 :         if (rf->rf_type == BWI_RF_T_BCM2050)
    3202           0 :                 PHY_WRITE(mac, 0x38, 0x667);
    3203             : 
    3204           0 :         if ((phy->phy_flags & BWI_PHY_F_LINKED) || phy->phy_rev >= 2) {
    3205           0 :                 if (rf->rf_type == BWI_RF_T_BCM2050) {
    3206           0 :                         RF_SETBITS(mac, 0x7a, 0x20);
    3207           0 :                         RF_SETBITS(mac, 0x51, 0x4);
    3208           0 :                 }
    3209             : 
    3210           0 :                 CSR_WRITE_2(sc, BWI_RF_ANTDIV, 0);
    3211             : 
    3212           0 :                 PHY_SETBITS(mac, 0x802, 0x100);
    3213           0 :                 PHY_SETBITS(mac, 0x42b, 0x2000);
    3214           0 :                 PHY_WRITE(mac, 0x1c, 0x186a);
    3215             : 
    3216           0 :                 PHY_FILT_SETBITS(mac, 0x13, 0xff, 0x1900);
    3217           0 :                 PHY_FILT_SETBITS(mac, 0x35, 0xffc0, 0x64);
    3218           0 :                 PHY_FILT_SETBITS(mac, 0x5d, 0xff80, 0xa);
    3219           0 :         }
    3220             : 
    3221             :         /* TODO: bad_frame_preempt? */
    3222             : 
    3223           0 :         if (phy->phy_version == 1) {
    3224           0 :                 PHY_WRITE(mac, 0x26, 0xce00);
    3225           0 :                 PHY_WRITE(mac, 0x21, 0x3763);
    3226           0 :                 PHY_WRITE(mac, 0x22, 0x1bc3);
    3227           0 :                 PHY_WRITE(mac, 0x23, 0x6f9);
    3228           0 :                 PHY_WRITE(mac, 0x24, 0x37e);
    3229           0 :         } else
    3230           0 :                 PHY_WRITE(mac, 0x26, 0xcc00);
    3231           0 :         PHY_WRITE(mac, 0x30, 0xc6);
    3232             : 
    3233           0 :         CSR_WRITE_2(sc, BWI_BPHY_CTRL, BWI_BPHY_CTRL_INIT);
    3234             : 
    3235           0 :         if (phy->phy_version == 1)
    3236           0 :                 PHY_WRITE(mac, 0x20, 0x3e1c);
    3237             :         else
    3238           0 :                 PHY_WRITE(mac, 0x20, 0x301c);
    3239             : 
    3240           0 :         if (phy->phy_version == 0)
    3241           0 :                 CSR_WRITE_2(sc, BWI_PHY_MAGIC_REG1, BWI_PHY_MAGIC_REG1_VAL1);
    3242             : 
    3243             :         /* Force to channel 7 */
    3244           0 :         orig_chan = rf->rf_curchan;
    3245           0 :         bwi_rf_set_chan(mac, 7, 0);
    3246             : 
    3247           0 :         if (rf->rf_type != BWI_RF_T_BCM2050) {
    3248           0 :                 RF_WRITE(mac, 0x75, 0x80);
    3249           0 :                 RF_WRITE(mac, 0x79, 0x81);
    3250           0 :         }
    3251             : 
    3252           0 :         RF_WRITE(mac, 0x50, 0x20);
    3253           0 :         RF_WRITE(mac, 0x50, 0x23);
    3254             : 
    3255           0 :         if (rf->rf_type == BWI_RF_T_BCM2050) {
    3256           0 :                 RF_WRITE(mac, 0x50, 0x20);
    3257           0 :                 RF_WRITE(mac, 0x5a, 0x70);
    3258           0 :         }
    3259             : 
    3260           0 :         RF_WRITE(mac, 0x5b, 0x7b);
    3261           0 :         RF_WRITE(mac, 0x5c, 0xb0);
    3262           0 :         RF_SETBITS(mac, 0x7a, 0x7);
    3263             : 
    3264           0 :         bwi_rf_set_chan(mac, orig_chan, 0);
    3265             : 
    3266           0 :         PHY_WRITE(mac, 0x14, 0x80);
    3267           0 :         PHY_WRITE(mac, 0x32, 0xca);
    3268           0 :         PHY_WRITE(mac, 0x2a, 0x88a3);
    3269             : 
    3270           0 :         bwi_mac_set_tpctl_11bg(mac, NULL);
    3271             : 
    3272           0 :         if (rf->rf_type == BWI_RF_T_BCM2050)
    3273           0 :                 RF_WRITE(mac, 0x5d, 0xd);
    3274             : 
    3275           0 :         CSR_FILT_SETBITS_2(sc, BWI_PHY_MAGIC_REG1, 0xffc0, 0x4);
    3276           0 : }
    3277             : 
    3278             : void
    3279           0 : bwi_phy_init_11b_rev6(struct bwi_mac *mac)
    3280             : {
    3281           0 :         struct bwi_softc *sc = mac->mac_sc;
    3282           0 :         struct bwi_rf *rf = &mac->mac_rf;
    3283           0 :         struct bwi_phy *phy = &mac->mac_phy;
    3284             :         uint16_t val, ofs;
    3285             :         uint orig_chan;
    3286             : 
    3287           0 :         PHY_WRITE(mac, 0x3e, 0x817a);
    3288           0 :         RF_SETBITS(mac, 0x7a, 0x58);
    3289             : 
    3290           0 :         if (rf->rf_rev == 4 || rf->rf_rev == 5) {
    3291           0 :                 RF_WRITE(mac, 0x51, 0x37);
    3292           0 :                 RF_WRITE(mac, 0x52, 0x70);
    3293           0 :                 RF_WRITE(mac, 0x53, 0xb3);
    3294           0 :                 RF_WRITE(mac, 0x54, 0x9b);
    3295           0 :                 RF_WRITE(mac, 0x5a, 0x88);
    3296           0 :                 RF_WRITE(mac, 0x5b, 0x88);
    3297           0 :                 RF_WRITE(mac, 0x5d, 0x88);
    3298           0 :                 RF_WRITE(mac, 0x5e, 0x88);
    3299           0 :                 RF_WRITE(mac, 0x7d, 0x88);
    3300           0 :                 HFLAGS_SETBITS(mac, BWI_HFLAG_MAGIC1);
    3301           0 :         } else if (rf->rf_rev == 8) {
    3302           0 :                 RF_WRITE(mac, 0x51, 0);
    3303           0 :                 RF_WRITE(mac, 0x52, 0x40);
    3304           0 :                 RF_WRITE(mac, 0x53, 0xb7);
    3305           0 :                 RF_WRITE(mac, 0x54, 0x98);
    3306           0 :                 RF_WRITE(mac, 0x5a, 0x88);
    3307           0 :                 RF_WRITE(mac, 0x5b, 0x6b);
    3308           0 :                 RF_WRITE(mac, 0x5c, 0xf);
    3309           0 :                 if (sc->sc_card_flags & BWI_CARD_F_ALT_IQ) {
    3310           0 :                         RF_WRITE(mac, 0x5d, 0xfa);
    3311           0 :                         RF_WRITE(mac, 0x5e, 0xd8);
    3312           0 :                 } else {
    3313           0 :                         RF_WRITE(mac, 0x5d, 0xf5);
    3314           0 :                         RF_WRITE(mac, 0x5e, 0xb8);
    3315             :                 }
    3316           0 :                 RF_WRITE(mac, 0x73, 0x3);
    3317           0 :                 RF_WRITE(mac, 0x7d, 0xa8);
    3318           0 :                 RF_WRITE(mac, 0x7c, 0x1);
    3319           0 :                 RF_WRITE(mac, 0x7e, 0x8);
    3320           0 :         }
    3321             : 
    3322             :         val = 0x1e1f;
    3323           0 :         for (ofs = 0x88; ofs < 0x98; ++ofs) {
    3324           0 :                 PHY_WRITE(mac, ofs, val);
    3325           0 :                 val -= 0x202;
    3326             :         }
    3327             : 
    3328             :         val = 0x3e3f;
    3329           0 :         for (ofs = 0x98; ofs < 0xa8; ++ofs) {
    3330           0 :                 PHY_WRITE(mac, ofs, val);
    3331           0 :                 val -= 0x202;
    3332             :         }
    3333             : 
    3334             :         val = 0x2120;
    3335           0 :         for (ofs = 0xa8; ofs < 0xc8; ++ofs) {
    3336           0 :                 PHY_WRITE(mac, ofs, (val & 0x3f3f));
    3337           0 :                 val += 0x202;
    3338             : 
    3339             :                 /* XXX: delay 10 us to avoid PCI parity errors with BCM4318 */
    3340           0 :                 DELAY(10);
    3341             :         }
    3342             : 
    3343           0 :         if (phy->phy_mode == IEEE80211_MODE_11G) {
    3344           0 :                 RF_SETBITS(mac, 0x7a, 0x20);
    3345           0 :                 RF_SETBITS(mac, 0x51, 0x4);
    3346           0 :                 PHY_SETBITS(mac, 0x802, 0x100);
    3347           0 :                 PHY_SETBITS(mac, 0x42b, 0x2000);
    3348           0 :                 PHY_WRITE(mac, 0x5b, 0);
    3349           0 :                 PHY_WRITE(mac, 0x5c, 0);
    3350           0 :         }
    3351             : 
    3352             :         /* Force to channel 7 */
    3353           0 :         orig_chan = rf->rf_curchan;
    3354           0 :         if (orig_chan >= 8)
    3355           0 :                 bwi_rf_set_chan(mac, 1, 0);
    3356             :         else
    3357           0 :                 bwi_rf_set_chan(mac, 13, 0);
    3358             : 
    3359           0 :         RF_WRITE(mac, 0x50, 0x20);
    3360           0 :         RF_WRITE(mac, 0x50, 0x23);
    3361             : 
    3362           0 :         DELAY(40);
    3363             : 
    3364           0 :         if (rf->rf_rev < 6 || rf->rf_rev == 8) {
    3365           0 :                 RF_SETBITS(mac, 0x7c, 0x2);
    3366           0 :                 RF_WRITE(mac, 0x50, 0x20);
    3367           0 :         }
    3368           0 :         if (rf->rf_rev <= 2) {
    3369           0 :                 RF_WRITE(mac, 0x7c, 0x20);
    3370           0 :                 RF_WRITE(mac, 0x5a, 0x70);
    3371           0 :                 RF_WRITE(mac, 0x5b, 0x7b);
    3372           0 :                 RF_WRITE(mac, 0x5c, 0xb0);
    3373           0 :         }
    3374             : 
    3375           0 :         RF_FILT_SETBITS(mac, 0x7a, 0xf8, 0x7);
    3376             : 
    3377           0 :         bwi_rf_set_chan(mac, orig_chan, 0);
    3378             : 
    3379           0 :         PHY_WRITE(mac, 0x14, 0x200);
    3380           0 :         if (rf->rf_rev >= 6)
    3381           0 :                 PHY_WRITE(mac, 0x2a, 0x88c2);
    3382             :         else
    3383           0 :                 PHY_WRITE(mac, 0x2a, 0x8ac0);
    3384           0 :         PHY_WRITE(mac, 0x38, 0x668);
    3385             : 
    3386           0 :         bwi_mac_set_tpctl_11bg(mac, NULL);
    3387             : 
    3388           0 :         if (rf->rf_rev <= 5) {
    3389           0 :                 PHY_FILT_SETBITS(mac, 0x5d, 0xff80, 0x3);
    3390           0 :                 if (rf->rf_rev <= 2)
    3391           0 :                         RF_WRITE(mac, 0x5d, 0xd);
    3392             :         }
    3393             : 
    3394           0 :         if (phy->phy_version == 4) {
    3395           0 :                 CSR_WRITE_2(sc, BWI_PHY_MAGIC_REG1, BWI_PHY_MAGIC_REG1_VAL2);
    3396           0 :                 PHY_CLRBITS(mac, 0x61, 0xf000);
    3397           0 :         } else {
    3398           0 :                 PHY_FILT_SETBITS(mac, 0x2, 0xffc0, 0x4);
    3399             :         }
    3400             : 
    3401           0 :         if (phy->phy_mode == IEEE80211_MODE_11B) {
    3402           0 :                 CSR_WRITE_2(sc, BWI_BBP_ATTEN, BWI_BBP_ATTEN_MAGIC2);
    3403           0 :                 PHY_WRITE(mac, 0x16, 0x410);
    3404           0 :                 PHY_WRITE(mac, 0x17, 0x820);
    3405           0 :                 PHY_WRITE(mac, 0x62, 0x7);
    3406             : 
    3407           0 :                 bwi_rf_init_bcm2050(mac);
    3408           0 :                 bwi_rf_lo_update(mac);
    3409           0 :                 if (sc->sc_card_flags & BWI_CARD_F_SW_NRSSI) {
    3410           0 :                         bwi_rf_calc_nrssi_slope(mac);
    3411           0 :                         bwi_rf_set_nrssi_thr(mac);
    3412           0 :                 }
    3413           0 :                 bwi_mac_init_tpctl_11bg(mac);
    3414           0 :         } else
    3415           0 :                 CSR_WRITE_2(sc, BWI_BBP_ATTEN, 0);
    3416           0 : }
    3417             : 
    3418             : void
    3419           0 : bwi_phy_config_11g(struct bwi_mac *mac)
    3420             : {
    3421           0 :         struct bwi_softc *sc = mac->mac_sc;
    3422           0 :         struct bwi_phy *phy = &mac->mac_phy;
    3423             :         const uint16_t *tbl;
    3424             :         uint16_t wrd_ofs1, wrd_ofs2;
    3425             :         int i, n;
    3426             : 
    3427           0 :         if (phy->phy_rev == 1) {
    3428           0 :                 PHY_WRITE(mac, 0x406, 0x4f19);
    3429           0 :                 PHY_FILT_SETBITS(mac, 0x429, 0xfc3f, 0x340);
    3430           0 :                 PHY_WRITE(mac, 0x42c, 0x5a);
    3431           0 :                 PHY_WRITE(mac, 0x427, 0x1a);
    3432             : 
    3433             :                 /* Fill frequency table */
    3434           0 :                 for (i = 0; i < nitems(bwi_phy_freq_11g_rev1); ++i) {
    3435           0 :                         bwi_tbl_write_2(mac, BWI_PHYTBL_FREQ + i,
    3436           0 :                             bwi_phy_freq_11g_rev1[i]);
    3437             :                 }
    3438             : 
    3439             :                 /* Fill noise table */
    3440           0 :                 for (i = 0; i < nitems(bwi_phy_noise_11g_rev1); ++i) {
    3441           0 :                         bwi_tbl_write_2(mac, BWI_PHYTBL_NOISE + i,
    3442           0 :                             bwi_phy_noise_11g_rev1[i]);
    3443             :                 }
    3444             : 
    3445             :                 /* Fill rotor table */
    3446           0 :                 for (i = 0; i < nitems(bwi_phy_rotor_11g_rev1); ++i) {
    3447             :                         /* NB: data length is 4 bytes */
    3448           0 :                         bwi_tbl_write_4(mac, BWI_PHYTBL_ROTOR + i,
    3449           0 :                             bwi_phy_rotor_11g_rev1[i]);
    3450             :                 }
    3451             :         } else {
    3452           0 :                 bwi_nrssi_write(mac, 0xba98, (int16_t)0x7654); /* XXX */
    3453             : 
    3454           0 :                 if (phy->phy_rev == 2) {
    3455           0 :                         PHY_WRITE(mac, 0x4c0, 0x1861);
    3456           0 :                         PHY_WRITE(mac, 0x4c1, 0x271);
    3457           0 :                 } else if (phy->phy_rev > 2) {
    3458           0 :                         PHY_WRITE(mac, 0x4c0, 0x98);
    3459           0 :                         PHY_WRITE(mac, 0x4c1, 0x70);
    3460           0 :                         PHY_WRITE(mac, 0x4c9, 0x80);
    3461           0 :                 }
    3462           0 :                 PHY_SETBITS(mac, 0x42b, 0x800);
    3463             : 
    3464             :                 /* Fill RSSI table */
    3465           0 :                 for (i = 0; i < 64; ++i)
    3466           0 :                         bwi_tbl_write_2(mac, BWI_PHYTBL_RSSI + i, i);
    3467             : 
    3468             :                 /* Fill noise table */
    3469           0 :                 for (i = 0; i < nitems(bwi_phy_noise_11g); ++i) {
    3470           0 :                         bwi_tbl_write_2(mac, BWI_PHYTBL_NOISE + i,
    3471           0 :                             bwi_phy_noise_11g[i]);
    3472             :                 }
    3473             :         }
    3474             : 
    3475             :         /*
    3476             :          * Fill noise scale table
    3477             :          */
    3478           0 :         if (phy->phy_rev <= 2) {
    3479             :                 tbl = bwi_phy_noise_scale_11g_rev2;
    3480             :                 n = nitems(bwi_phy_noise_scale_11g_rev2);
    3481           0 :         } else if (phy->phy_rev >= 7 && (PHY_READ(mac, 0x449) & 0x200)) {
    3482             :                 tbl = bwi_phy_noise_scale_11g_rev7;
    3483             :                 n = nitems(bwi_phy_noise_scale_11g_rev7);
    3484           0 :         } else {
    3485             :                 tbl = bwi_phy_noise_scale_11g;
    3486             :                 n = nitems(bwi_phy_noise_scale_11g);
    3487             :         }
    3488           0 :         for (i = 0; i < n; ++i)
    3489           0 :                 bwi_tbl_write_2(mac, BWI_PHYTBL_NOISE_SCALE + i, tbl[i]);
    3490             : 
    3491             :         /*
    3492             :          * Fill sigma square table
    3493             :          */
    3494           0 :         if (phy->phy_rev == 2) {
    3495             :                 tbl = bwi_phy_sigma_sq_11g_rev2;
    3496             :                 n = nitems(bwi_phy_sigma_sq_11g_rev2);
    3497           0 :         } else if (phy->phy_rev > 2 && phy->phy_rev <= 8) {
    3498             :                 tbl = bwi_phy_sigma_sq_11g_rev7;
    3499             :                 n = nitems(bwi_phy_sigma_sq_11g_rev7);
    3500           0 :         } else {
    3501             :                 tbl = NULL;
    3502             :                 n = 0;
    3503             :         }
    3504           0 :         for (i = 0; i < n; ++i)
    3505           0 :                 bwi_tbl_write_2(mac, BWI_PHYTBL_SIGMA_SQ + i, tbl[i]);
    3506             : 
    3507           0 :         if (phy->phy_rev == 1) {
    3508             :                 /* Fill delay table */
    3509           0 :                 for (i = 0; i < nitems(bwi_phy_delay_11g_rev1); ++i) {
    3510           0 :                         bwi_tbl_write_4(mac, BWI_PHYTBL_DELAY + i,
    3511           0 :                             bwi_phy_delay_11g_rev1[i]);
    3512             :                 }
    3513             : 
    3514             :                 /* Fill WRSSI (Wide-Band RSSI) table */
    3515           0 :                 for (i = 4; i < 20; ++i)
    3516           0 :                         bwi_tbl_write_2(mac, BWI_PHYTBL_WRSSI_REV1 + i, 0x20);
    3517             : 
    3518           0 :                 bwi_phy_config_agc(mac);
    3519             : 
    3520             :                 wrd_ofs1 = 0x5001;
    3521             :                 wrd_ofs2 = 0x5002;
    3522           0 :         } else {
    3523             :                 /* Fill WRSSI (Wide-Band RSSI) table */
    3524           0 :                 for (i = 0; i < 0x20; ++i)
    3525           0 :                         bwi_tbl_write_2(mac, BWI_PHYTBL_WRSSI + i, 0x820);
    3526             : 
    3527           0 :                 bwi_phy_config_agc(mac);
    3528             : 
    3529           0 :                 PHY_READ(mac, 0x400);   /* Dummy read */
    3530           0 :                 PHY_WRITE(mac, 0x403, 0x1000);
    3531           0 :                 bwi_tbl_write_2(mac, 0x3c02, 0xf);
    3532           0 :                 bwi_tbl_write_2(mac, 0x3c03, 0x14);
    3533             : 
    3534             :                 wrd_ofs1 = 0x401;
    3535             :                 wrd_ofs2 = 0x402;
    3536             :         }
    3537             : 
    3538           0 :         if (!(BWI_IS_BRCM_BU4306(sc) && sc->sc_pci_revid == 0x17)) {
    3539           0 :                 bwi_tbl_write_2(mac, wrd_ofs1, 0x2);
    3540           0 :                 bwi_tbl_write_2(mac, wrd_ofs2, 0x1);
    3541           0 :         }
    3542             : 
    3543             :         /* phy->phy_flags & BWI_PHY_F_LINKED ? */
    3544           0 :         if (sc->sc_card_flags & BWI_CARD_F_PA_GPIO9)
    3545           0 :                 PHY_WRITE(mac, 0x46e, 0x3cf);
    3546           0 : }
    3547             : #undef N
    3548             : 
    3549             : /*
    3550             :  * Configure Automatic Gain Controller
    3551             :  */
    3552             : void
    3553           0 : bwi_phy_config_agc(struct bwi_mac *mac)
    3554             : {
    3555           0 :         struct bwi_phy *phy = &mac->mac_phy;
    3556             :         uint16_t ofs;
    3557             : 
    3558           0 :         ofs = phy->phy_rev == 1 ? 0x4c00 : 0;
    3559             : 
    3560           0 :         bwi_tbl_write_2(mac, ofs, 0xfe);
    3561           0 :         bwi_tbl_write_2(mac, ofs + 1, 0xd);
    3562           0 :         bwi_tbl_write_2(mac, ofs + 2, 0x13);
    3563           0 :         bwi_tbl_write_2(mac, ofs + 3, 0x19);
    3564             : 
    3565           0 :         if (phy->phy_rev == 1) {
    3566           0 :                 bwi_tbl_write_2(mac, 0x1800, 0x2710);
    3567           0 :                 bwi_tbl_write_2(mac, 0x1801, 0x9b83);
    3568           0 :                 bwi_tbl_write_2(mac, 0x1802, 0x9b83);
    3569           0 :                 bwi_tbl_write_2(mac, 0x1803, 0xf8d);
    3570           0 :                 PHY_WRITE(mac, 0x455, 0x4);
    3571           0 :         }
    3572             : 
    3573           0 :         PHY_FILT_SETBITS(mac, 0x4a5, 0xff, 0x5700);
    3574           0 :         PHY_FILT_SETBITS(mac, 0x41a, 0xff80, 0xf);
    3575           0 :         PHY_FILT_SETBITS(mac, 0x41a, 0xc07f, 0x2b80);
    3576           0 :         PHY_FILT_SETBITS(mac, 0x48c, 0xf0ff, 0x300);
    3577             : 
    3578           0 :         RF_SETBITS(mac, 0x7a, 0x8);
    3579             : 
    3580           0 :         PHY_FILT_SETBITS(mac, 0x4a0, 0xfff0, 0x8);
    3581           0 :         PHY_FILT_SETBITS(mac, 0x4a1, 0xf0ff, 0x600);
    3582           0 :         PHY_FILT_SETBITS(mac, 0x4a2, 0xf0ff, 0x700);
    3583           0 :         PHY_FILT_SETBITS(mac, 0x4a0, 0xf0ff, 0x100);
    3584             : 
    3585           0 :         if (phy->phy_rev == 1)
    3586           0 :                 PHY_FILT_SETBITS(mac, 0x4a2, 0xfff0, 0x7);
    3587             : 
    3588           0 :         PHY_FILT_SETBITS(mac, 0x488, 0xff00, 0x1c);
    3589           0 :         PHY_FILT_SETBITS(mac, 0x488, 0xc0ff, 0x200);
    3590           0 :         PHY_FILT_SETBITS(mac, 0x496, 0xff00, 0x1c);
    3591           0 :         PHY_FILT_SETBITS(mac, 0x489, 0xff00, 0x20);
    3592           0 :         PHY_FILT_SETBITS(mac, 0x489, 0xc0ff, 0x200);
    3593           0 :         PHY_FILT_SETBITS(mac, 0x482, 0xff00, 0x2e);
    3594           0 :         PHY_FILT_SETBITS(mac, 0x496, 0xff, 0x1a00);
    3595           0 :         PHY_FILT_SETBITS(mac, 0x481, 0xff00, 0x28);
    3596           0 :         PHY_FILT_SETBITS(mac, 0x481, 0xff, 0x2c00);
    3597             : 
    3598           0 :         if (phy->phy_rev == 1) {
    3599           0 :                 PHY_WRITE(mac, 0x430, 0x92b);
    3600           0 :                 PHY_FILT_SETBITS(mac, 0x41b, 0xffe1, 0x2);
    3601           0 :         } else {
    3602           0 :                 PHY_CLRBITS(mac, 0x41b, 0x1e);
    3603           0 :                 PHY_WRITE(mac, 0x41f, 0x287a);
    3604           0 :                 PHY_FILT_SETBITS(mac, 0x420, 0xfff0, 0x4);
    3605             : 
    3606           0 :                 if (phy->phy_rev >= 6) {
    3607           0 :                         PHY_WRITE(mac, 0x422, 0x287a);
    3608           0 :                         PHY_FILT_SETBITS(mac, 0x420, 0xfff, 0x3000);
    3609           0 :                 }
    3610             :         }
    3611             : 
    3612           0 :         PHY_FILT_SETBITS(mac, 0x4a8, 0x8080, 0x7874);
    3613           0 :         PHY_WRITE(mac, 0x48e, 0x1c00);
    3614             : 
    3615           0 :         if (phy->phy_rev == 1) {
    3616           0 :                 PHY_FILT_SETBITS(mac, 0x4ab, 0xf0ff, 0x600);
    3617           0 :                 PHY_WRITE(mac, 0x48b, 0x5e);
    3618           0 :                 PHY_FILT_SETBITS(mac, 0x48c, 0xff00, 0x1e);
    3619           0 :                 PHY_WRITE(mac, 0x48d, 0x2);
    3620           0 :         }
    3621             : 
    3622           0 :         bwi_tbl_write_2(mac, ofs + 0x800, 0);
    3623           0 :         bwi_tbl_write_2(mac, ofs + 0x801, 7);
    3624           0 :         bwi_tbl_write_2(mac, ofs + 0x802, 16);
    3625           0 :         bwi_tbl_write_2(mac, ofs + 0x803, 28);
    3626             : 
    3627           0 :         if (phy->phy_rev >= 6) {
    3628           0 :                 PHY_CLRBITS(mac, 0x426, 0x3);
    3629           0 :                 PHY_CLRBITS(mac, 0x426, 0x1000);
    3630           0 :         }
    3631           0 : }
    3632             : 
    3633             : void
    3634           0 : bwi_set_gains(struct bwi_mac *mac, const struct bwi_gains *gains)
    3635             : {
    3636           0 :         struct bwi_phy *phy = &mac->mac_phy;
    3637             :         uint16_t tbl_gain_ofs1, tbl_gain_ofs2, tbl_gain;
    3638             :         int i;
    3639             : 
    3640           0 :         if (phy->phy_rev <= 1) {
    3641             :                 tbl_gain_ofs1 = 0x5000;
    3642             :                 tbl_gain_ofs2 = tbl_gain_ofs1 + 16;
    3643           0 :         } else {
    3644             :                 tbl_gain_ofs1 = 0x400;
    3645             :                 tbl_gain_ofs2 = tbl_gain_ofs1 + 8;
    3646             :         }
    3647             : 
    3648           0 :         for (i = 0; i < 4; ++i) {
    3649           0 :                 if (gains != NULL) {
    3650           0 :                         tbl_gain = gains->tbl_gain1;
    3651           0 :                 } else {
    3652             :                         /* Bit swap */
    3653           0 :                         tbl_gain = (i & 0x1) << 1;
    3654           0 :                         tbl_gain |= (i & 0x2) >> 1;
    3655             :                 }
    3656           0 :                 bwi_tbl_write_2(mac, tbl_gain_ofs1 + i, tbl_gain);
    3657             :         }
    3658             : 
    3659           0 :         for (i = 0; i < 16; ++i) {
    3660           0 :                 if (gains != NULL)
    3661           0 :                         tbl_gain = gains->tbl_gain2;
    3662             :                 else
    3663           0 :                         tbl_gain = i;
    3664           0 :                 bwi_tbl_write_2(mac, tbl_gain_ofs2 + i, tbl_gain);
    3665             :         }
    3666             : 
    3667           0 :         if (gains == NULL || (gains != NULL && gains->phy_gain != -1)) {
    3668             :                 uint16_t phy_gain1, phy_gain2;
    3669             : 
    3670           0 :                 if (gains != NULL) {
    3671             :                         phy_gain1 =
    3672           0 :                         ((uint16_t)gains->phy_gain << 14) |
    3673           0 :                         ((uint16_t)gains->phy_gain << 6);
    3674             :                         phy_gain2 = phy_gain1;
    3675           0 :                 } else {
    3676             :                         phy_gain1 = 0x4040;
    3677             :                         phy_gain2 = 0x4000;
    3678             :                 }
    3679           0 :                 PHY_FILT_SETBITS(mac, 0x4a0, 0xbfbf, phy_gain1);
    3680           0 :                 PHY_FILT_SETBITS(mac, 0x4a1, 0xbfbf, phy_gain1);
    3681           0 :                 PHY_FILT_SETBITS(mac, 0x4a2, 0xbfbf, phy_gain2);
    3682           0 :         }
    3683           0 :         bwi_mac_dummy_xmit(mac);
    3684           0 : }
    3685             : 
    3686             : void
    3687           0 : bwi_phy_clear_state(struct bwi_phy *phy)
    3688             : {
    3689           0 :         phy->phy_flags &= ~BWI_CLEAR_PHY_FLAGS;
    3690           0 : }
    3691             : 
    3692             : /* RF */
    3693             : 
    3694             : int16_t
    3695           0 : bwi_nrssi_11g(struct bwi_mac *mac)
    3696             : {
    3697             :         int16_t val;
    3698             : 
    3699             : #define NRSSI_11G_MASK          0x3f00
    3700           0 :         val = (int16_t)__SHIFTOUT(PHY_READ(mac, 0x47f), NRSSI_11G_MASK);
    3701           0 :         if (val >= 32)
    3702           0 :                 val -= 64;
    3703             : 
    3704           0 :         return (val);
    3705             : #undef NRSSI_11G_MASK
    3706             : }
    3707             : 
    3708             : struct bwi_rf_lo *
    3709           0 : bwi_get_rf_lo(struct bwi_mac *mac, uint16_t rf_atten, uint16_t bbp_atten)
    3710             : {
    3711             :         int n;
    3712             : 
    3713           0 :         n = rf_atten + (14 * (bbp_atten / 2));
    3714           0 :         KASSERT(n < BWI_RFLO_MAX);
    3715             : 
    3716           0 :         return (&mac->mac_rf.rf_lo[n]);
    3717             : }
    3718             : 
    3719             : int
    3720           0 : bwi_rf_lo_isused(struct bwi_mac *mac, const struct bwi_rf_lo *lo)
    3721             : {
    3722           0 :         struct bwi_rf *rf = &mac->mac_rf;
    3723             :         int idx;
    3724             : 
    3725           0 :         idx = lo - rf->rf_lo;
    3726           0 :         KASSERT(idx >= 0 && idx < BWI_RFLO_MAX);
    3727             : 
    3728           0 :         return (isset(rf->rf_lo_used, idx));
    3729             : }
    3730             : 
    3731             : void
    3732           0 : bwi_rf_write(struct bwi_mac *mac, uint16_t ctrl, uint16_t data)
    3733             : {
    3734           0 :         struct bwi_softc *sc = mac->mac_sc;
    3735             : 
    3736           0 :         CSR_WRITE_2(sc, BWI_RF_CTRL, ctrl);
    3737           0 :         CSR_WRITE_2(sc, BWI_RF_DATA_LO, data);
    3738           0 : }
    3739             : 
    3740             : uint16_t
    3741           0 : bwi_rf_read(struct bwi_mac *mac, uint16_t ctrl)
    3742             : {
    3743           0 :         struct bwi_rf *rf = &mac->mac_rf;
    3744           0 :         struct bwi_softc *sc = mac->mac_sc;
    3745             : 
    3746           0 :         ctrl |= rf->rf_ctrl_rd;
    3747           0 :         if (rf->rf_ctrl_adj) {
    3748             :                 /* XXX */
    3749           0 :                 if (ctrl < 0x70)
    3750           0 :                         ctrl += 0x80;
    3751           0 :                 else if (ctrl < 0x80)
    3752           0 :                         ctrl += 0x70;
    3753             :         }
    3754             : 
    3755           0 :         CSR_WRITE_2(sc, BWI_RF_CTRL, ctrl);
    3756           0 :         return (CSR_READ_2(sc, BWI_RF_DATA_LO));
    3757             : }
    3758             : 
    3759             : int
    3760           0 : bwi_rf_attach(struct bwi_mac *mac)
    3761             : {
    3762           0 :         struct bwi_softc *sc = mac->mac_sc;
    3763           0 :         struct bwi_phy *phy = &mac->mac_phy;
    3764           0 :         struct bwi_rf *rf = &mac->mac_rf;
    3765             :         uint16_t type, manu;
    3766             :         uint8_t rev;
    3767             : 
    3768             :         /*
    3769             :          * Get RF manufacture/type/revision
    3770             :          */
    3771           0 :         if (sc->sc_bbp_id == BWI_BBPID_BCM4317) {
    3772             :                 /*
    3773             :                  * Fake a BCM2050 RF
    3774             :                  */
    3775             :                 manu = BWI_RF_MANUFACT_BCM;
    3776             :                 type = BWI_RF_T_BCM2050;
    3777           0 :                 if (sc->sc_bbp_rev == 0)
    3778           0 :                         rev = 3;
    3779           0 :                 else if (sc->sc_bbp_rev == 1)
    3780           0 :                         rev = 4;
    3781             :                 else
    3782             :                         rev = 5;
    3783             :         } else {
    3784             :                 uint32_t val;
    3785             : 
    3786           0 :                 CSR_WRITE_2(sc, BWI_RF_CTRL, BWI_RF_CTRL_RFINFO);
    3787           0 :                 val = CSR_READ_2(sc, BWI_RF_DATA_HI);
    3788           0 :                 val <<= 16;
    3789             : 
    3790           0 :                 CSR_WRITE_2(sc, BWI_RF_CTRL, BWI_RF_CTRL_RFINFO);
    3791           0 :                 val |= CSR_READ_2(sc, BWI_RF_DATA_LO);
    3792             : 
    3793           0 :                 manu = __SHIFTOUT(val, BWI_RFINFO_MANUFACT_MASK);
    3794           0 :                 type = __SHIFTOUT(val, BWI_RFINFO_TYPE_MASK);
    3795           0 :                 rev = __SHIFTOUT(val, BWI_RFINFO_REV_MASK);
    3796             :         }
    3797             :         DPRINTF(1, "%s: RF manu 0x%03x, type 0x%04x, rev %u\n",
    3798             :             sc->sc_dev.dv_xname, manu, type, rev);
    3799             : 
    3800             :         /*
    3801             :          * Verify whether the RF is supported
    3802             :          */
    3803           0 :         rf->rf_ctrl_rd = 0;
    3804           0 :         rf->rf_ctrl_adj = 0;
    3805           0 :         switch (phy->phy_mode) {
    3806             :         case IEEE80211_MODE_11A:
    3807           0 :                 if (manu != BWI_RF_MANUFACT_BCM ||
    3808           0 :                     type != BWI_RF_T_BCM2060 ||
    3809           0 :                     rev != 1) {
    3810           0 :                         printf("%s: only BCM2060 rev 1 RF is supported for "
    3811           0 :                             "11A PHY\n", sc->sc_dev.dv_xname);
    3812           0 :                         return (ENXIO);
    3813             :                 }
    3814           0 :                 rf->rf_ctrl_rd = BWI_RF_CTRL_RD_11A;
    3815           0 :                 rf->rf_on = bwi_rf_on_11a;
    3816           0 :                 rf->rf_off = bwi_rf_off_11a;
    3817           0 :                 rf->rf_calc_rssi = bwi_rf_calc_rssi_bcm2060;
    3818           0 :                 break;
    3819             :         case IEEE80211_MODE_11B:
    3820           0 :                 if (type == BWI_RF_T_BCM2050) {
    3821           0 :                         rf->rf_ctrl_rd = BWI_RF_CTRL_RD_11BG;
    3822           0 :                         rf->rf_calc_rssi = bwi_rf_calc_rssi_bcm2050;
    3823           0 :                 } else if (type == BWI_RF_T_BCM2053) {
    3824           0 :                         rf->rf_ctrl_adj = 1;
    3825           0 :                         rf->rf_calc_rssi = bwi_rf_calc_rssi_bcm2053;
    3826             :                 } else {
    3827           0 :                         printf("%s: only BCM2050/BCM2053 RF is supported "
    3828           0 :                             "for supported for 11B PHY\n", sc->sc_dev.dv_xname);
    3829           0 :                         return (ENXIO);
    3830             :                 }
    3831           0 :                 rf->rf_on = bwi_rf_on_11bg;
    3832           0 :                 rf->rf_off = bwi_rf_off_11bg;
    3833           0 :                 rf->rf_calc_nrssi_slope = bwi_rf_calc_nrssi_slope_11b;
    3834           0 :                 rf->rf_set_nrssi_thr = bwi_rf_set_nrssi_thr_11b;
    3835           0 :                 if (phy->phy_rev == 6)
    3836           0 :                         rf->rf_lo_update = bwi_rf_lo_update_11g;
    3837             :                 else
    3838           0 :                         rf->rf_lo_update = bwi_rf_lo_update_11b;
    3839             :                 break;
    3840             :         case IEEE80211_MODE_11G:
    3841           0 :                 if (type != BWI_RF_T_BCM2050) {
    3842           0 :                         printf("%s: only BCM2050 RF is supported for 11G "
    3843           0 :                             "PHY\n", sc->sc_dev.dv_xname);
    3844           0 :                         return (ENXIO);
    3845             :                 }
    3846           0 :                 rf->rf_ctrl_rd = BWI_RF_CTRL_RD_11BG;
    3847           0 :                 rf->rf_on = bwi_rf_on_11bg;
    3848           0 :                 if (mac->mac_rev >= 5)
    3849           0 :                         rf->rf_off = bwi_rf_off_11g_rev5;
    3850             :                 else
    3851           0 :                         rf->rf_off = bwi_rf_off_11bg;
    3852           0 :                 rf->rf_calc_nrssi_slope = bwi_rf_calc_nrssi_slope_11g;
    3853           0 :                 rf->rf_set_nrssi_thr = bwi_rf_set_nrssi_thr_11g;
    3854           0 :                 rf->rf_calc_rssi = bwi_rf_calc_rssi_bcm2050;
    3855           0 :                 rf->rf_lo_update = bwi_rf_lo_update_11g;
    3856           0 :                 break;
    3857             :         default:
    3858           0 :                 printf("%s: unsupported PHY mode\n", sc->sc_dev.dv_xname);
    3859           0 :                 return (ENXIO);
    3860             :         }
    3861             : 
    3862           0 :         rf->rf_type = type;
    3863           0 :         rf->rf_rev = rev;
    3864           0 :         rf->rf_manu = manu;
    3865           0 :         rf->rf_curchan = IEEE80211_CHAN_ANY;
    3866           0 :         rf->rf_ant_mode = BWI_ANT_MODE_AUTO;
    3867             : 
    3868           0 :         return (0);
    3869           0 : }
    3870             : 
    3871             : void
    3872           0 : bwi_rf_set_chan(struct bwi_mac *mac, uint chan, int work_around)
    3873             : {
    3874           0 :         struct bwi_softc *sc = mac->mac_sc;
    3875             : 
    3876           0 :         if (chan == IEEE80211_CHAN_ANY)
    3877           0 :                 return;
    3878             : 
    3879           0 :         MOBJ_WRITE_2(mac, BWI_COMM_MOBJ, BWI_COMM_MOBJ_CHAN, chan);
    3880             : 
    3881             :         /* TODO: 11A */
    3882             : 
    3883           0 :         if (work_around)
    3884           0 :                 bwi_rf_workaround(mac, chan);
    3885             : 
    3886           0 :         CSR_WRITE_2(sc, BWI_RF_CHAN, BWI_RF_2GHZ_CHAN(chan));
    3887             : 
    3888           0 :         if (chan == 14) {
    3889           0 :                 if (sc->sc_locale == BWI_SPROM_LOCALE_JAPAN)
    3890           0 :                         HFLAGS_CLRBITS(mac, BWI_HFLAG_NOT_JAPAN);
    3891             :                 else
    3892           0 :                         HFLAGS_SETBITS(mac, BWI_HFLAG_NOT_JAPAN);
    3893           0 :                 CSR_SETBITS_2(sc, BWI_RF_CHAN_EX, (1 << 11)); /* XXX */
    3894           0 :         } else {
    3895           0 :                 CSR_CLRBITS_2(sc, BWI_RF_CHAN_EX, 0x840); /* XXX */
    3896             :         }
    3897           0 :         DELAY(8000);    /* DELAY(2000); */
    3898             : 
    3899           0 :         mac->mac_rf.rf_curchan = chan;
    3900           0 : }
    3901             : 
    3902             : void
    3903           0 : bwi_rf_get_gains(struct bwi_mac *mac)
    3904             : {
    3905             : #define SAVE_PHY_MAX    15
    3906             : #define SAVE_RF_MAX     3
    3907             :         struct bwi_softc *sc;
    3908           0 :         struct bwi_phy *phy = &mac->mac_phy;
    3909           0 :         struct bwi_rf *rf = &mac->mac_rf;
    3910           0 :         uint16_t save_phy[SAVE_PHY_MAX];
    3911           0 :         uint16_t save_rf[SAVE_RF_MAX];
    3912             :         uint16_t trsw;
    3913             :         int i, j, loop1_max, loop1, loop2;
    3914             : 
    3915             :         static const uint16_t save_rf_regs[SAVE_RF_MAX] =
    3916             :             { 0x52, 0x43, 0x7a };
    3917             :         static const uint16_t save_phy_regs[SAVE_PHY_MAX] = {
    3918             :             0x0429, 0x0001, 0x0811, 0x0812,
    3919             :             0x0814, 0x0815, 0x005a, 0x0059,
    3920             :             0x0058, 0x000a, 0x0003, 0x080f,
    3921             :             0x0810, 0x002b, 0x0015
    3922             :         };
    3923             : 
    3924           0 :         sc = mac->mac_sc;
    3925             : 
    3926             :         /*
    3927             :          * Save PHY/RF registers for later restoration
    3928             :          */
    3929           0 :         for (i = 0; i < SAVE_PHY_MAX; ++i)
    3930           0 :                 save_phy[i] = PHY_READ(mac, save_phy_regs[i]);
    3931           0 :         PHY_READ(mac, 0x2d); /* dummy read */
    3932             : 
    3933           0 :         for (i = 0; i < SAVE_RF_MAX; ++i)
    3934           0 :                 save_rf[i] = RF_READ(mac, save_rf_regs[i]);
    3935             : 
    3936           0 :         PHY_CLRBITS(mac, 0x429, 0xc000);
    3937           0 :         PHY_SETBITS(mac, 0x1, 0x8000);
    3938             : 
    3939           0 :         PHY_SETBITS(mac, 0x811, 0x2);
    3940           0 :         PHY_CLRBITS(mac, 0x812, 0x2);
    3941           0 :         PHY_SETBITS(mac, 0x811, 0x1);
    3942           0 :         PHY_CLRBITS(mac, 0x812, 0x1);
    3943             : 
    3944           0 :         PHY_SETBITS(mac, 0x814, 0x1);
    3945           0 :         PHY_CLRBITS(mac, 0x815, 0x1);
    3946           0 :         PHY_SETBITS(mac, 0x814, 0x2);
    3947           0 :         PHY_CLRBITS(mac, 0x815, 0x2);
    3948             : 
    3949           0 :         PHY_SETBITS(mac, 0x811, 0xc);
    3950           0 :         PHY_SETBITS(mac, 0x812, 0xc);
    3951           0 :         PHY_SETBITS(mac, 0x811, 0x30);
    3952           0 :         PHY_FILT_SETBITS(mac, 0x812, 0xffcf, 0x10);
    3953             : 
    3954           0 :         PHY_WRITE(mac, 0x5a, 0x780);
    3955           0 :         PHY_WRITE(mac, 0x59, 0xc810);
    3956           0 :         PHY_WRITE(mac, 0x58, 0xd);
    3957           0 :         PHY_SETBITS(mac, 0xa, 0x2000);
    3958             : 
    3959           0 :         PHY_SETBITS(mac, 0x814, 0x4);
    3960           0 :         PHY_CLRBITS(mac, 0x815, 0x4);
    3961             : 
    3962           0 :         PHY_FILT_SETBITS(mac, 0x3, 0xff9f, 0x40);
    3963             : 
    3964           0 :         if (rf->rf_rev == 8) {
    3965             :                 loop1_max = 15;
    3966           0 :                 RF_WRITE(mac, 0x43, loop1_max);
    3967           0 :         } else {
    3968             :                 loop1_max = 9;
    3969           0 :                 RF_WRITE(mac, 0x52, 0x0);
    3970           0 :                 RF_FILT_SETBITS(mac, 0x43, 0xfff0, loop1_max);
    3971             :         }
    3972             : 
    3973           0 :         bwi_phy_set_bbp_atten(mac, 11);
    3974             : 
    3975           0 :         if (phy->phy_rev >= 3)
    3976           0 :                 PHY_WRITE(mac, 0x80f, 0xc020);
    3977             :         else
    3978           0 :                 PHY_WRITE(mac, 0x80f, 0x8020);
    3979           0 :         PHY_WRITE(mac, 0x810, 0);
    3980             : 
    3981           0 :         PHY_FILT_SETBITS(mac, 0x2b, 0xffc0, 0x1);
    3982           0 :         PHY_FILT_SETBITS(mac, 0x2b, 0xc0ff, 0x800);
    3983           0 :         PHY_SETBITS(mac, 0x811, 0x100);
    3984           0 :         PHY_CLRBITS(mac, 0x812, 0x3000);
    3985             : 
    3986           0 :         if ((mac->mac_sc->sc_card_flags & BWI_CARD_F_EXT_LNA) &&
    3987           0 :             phy->phy_rev >= 7) {
    3988           0 :                 PHY_SETBITS(mac, 0x811, 0x800);
    3989           0 :                 PHY_SETBITS(mac, 0x812, 0x8000);
    3990           0 :         }
    3991           0 :         RF_CLRBITS(mac, 0x7a, 0xff08);
    3992             : 
    3993             :         /*
    3994             :          * Find out 'loop1/loop2', which will be used to calculate
    3995             :          * max loopback gain later
    3996             :          */
    3997             :         j = 0;
    3998           0 :         for (i = 0; i < loop1_max; ++i) {
    3999           0 :                 for (j = 0; j < 16; ++j) {
    4000           0 :                         RF_WRITE(mac, 0x43, i);
    4001             : 
    4002           0 :                         if (bwi_rf_gain_max_reached(mac, j))
    4003             :                                 goto loop1_exit;
    4004             :                 }
    4005             :         }
    4006             : loop1_exit:
    4007             :         loop1 = i;
    4008             :         loop2 = j;
    4009             : 
    4010             :         /*
    4011             :          * Find out 'trsw', which will be used to calculate
    4012             :          * TRSW(TX/RX switch) RX gain later
    4013             :          */
    4014           0 :         if (loop2 >= 8) {
    4015           0 :                 PHY_SETBITS(mac, 0x812, 0x30);
    4016             :                 trsw = 0x1b;
    4017           0 :                 for (i = loop2 - 8; i < 16; ++i) {
    4018           0 :                         trsw -= 3;
    4019           0 :                         if (bwi_rf_gain_max_reached(mac, i))
    4020             :                                 break;
    4021             :                 }
    4022             :         } else {
    4023             :                 trsw = 0x18;
    4024             :         }
    4025             : 
    4026             :         /*
    4027             :          * Restore saved PHY/RF registers
    4028             :          */
    4029             :         /* First 4 saved PHY registers need special processing */
    4030           0 :         for (i = 4; i < SAVE_PHY_MAX; ++i)
    4031           0 :                 PHY_WRITE(mac, save_phy_regs[i], save_phy[i]);
    4032             : 
    4033           0 :         bwi_phy_set_bbp_atten(mac, mac->mac_tpctl.bbp_atten);
    4034             : 
    4035           0 :         for (i = 0; i < SAVE_RF_MAX; ++i)
    4036           0 :                 RF_WRITE(mac, save_rf_regs[i], save_rf[i]);
    4037             : 
    4038           0 :         PHY_WRITE(mac, save_phy_regs[2], save_phy[2] | 0x3);
    4039           0 :         DELAY(10);
    4040           0 :         PHY_WRITE(mac, save_phy_regs[2], save_phy[2]);
    4041           0 :         PHY_WRITE(mac, save_phy_regs[3], save_phy[3]);
    4042           0 :         PHY_WRITE(mac, save_phy_regs[0], save_phy[0]);
    4043           0 :         PHY_WRITE(mac, save_phy_regs[1], save_phy[1]);
    4044             : 
    4045             :         /*
    4046             :          * Calculate gains
    4047             :          */
    4048           0 :         rf->rf_lo_gain = (loop2 * 6) - (loop1 * 4) - 11;
    4049           0 :         rf->rf_rx_gain = trsw * 2;
    4050             :         DPRINTF(1, "%s: lo gain: %u, rx gain: %u\n",
    4051             :             sc->sc_dev.dv_xname, rf->rf_lo_gain, rf->rf_rx_gain);
    4052             : 
    4053             : #undef SAVE_RF_MAX
    4054             : #undef SAVE_PHY_MAX
    4055           0 : }
    4056             : 
    4057             : void
    4058           0 : bwi_rf_init(struct bwi_mac *mac)
    4059             : {
    4060           0 :         struct bwi_rf *rf = &mac->mac_rf;
    4061             : 
    4062           0 :         if (rf->rf_type == BWI_RF_T_BCM2060) {
    4063             :                 /* TODO: 11A */
    4064             :         } else {
    4065           0 :                 if (rf->rf_flags & BWI_RF_F_INITED)
    4066           0 :                         RF_WRITE(mac, 0x78, rf->rf_calib);
    4067             :                 else
    4068           0 :                         bwi_rf_init_bcm2050(mac);
    4069             :         }
    4070           0 : }
    4071             : 
    4072             : void
    4073           0 : bwi_rf_off_11a(struct bwi_mac *mac)
    4074             : {
    4075           0 :         RF_WRITE(mac, 0x4, 0xff);
    4076           0 :         RF_WRITE(mac, 0x5, 0xfb);
    4077             : 
    4078           0 :         PHY_SETBITS(mac, 0x10, 0x8);
    4079           0 :         PHY_SETBITS(mac, 0x11, 0x8);
    4080             : 
    4081           0 :         PHY_WRITE(mac, 0x15, 0xaa00);
    4082           0 : }
    4083             : 
    4084             : void
    4085           0 : bwi_rf_off_11bg(struct bwi_mac *mac)
    4086             : {
    4087           0 :         PHY_WRITE(mac, 0x15, 0xaa00);
    4088           0 : }
    4089             : 
    4090             : void
    4091           0 : bwi_rf_off_11g_rev5(struct bwi_mac *mac)
    4092             : {
    4093           0 :         PHY_SETBITS(mac, 0x811, 0x8c);
    4094           0 :         PHY_CLRBITS(mac, 0x812, 0x8c);
    4095           0 : }
    4096             : 
    4097             : void
    4098           0 : bwi_rf_workaround(struct bwi_mac *mac, uint chan)
    4099             : {
    4100           0 :         struct bwi_softc *sc = mac->mac_sc;
    4101           0 :         struct bwi_rf *rf = &mac->mac_rf;
    4102             : 
    4103           0 :         if (chan == IEEE80211_CHAN_ANY) {
    4104           0 :                 printf("%s: %s invalid channel!\n",
    4105           0 :                     sc->sc_dev.dv_xname, __func__);
    4106           0 :                 return;
    4107             :         }
    4108             : 
    4109           0 :         if (rf->rf_type != BWI_RF_T_BCM2050 || rf->rf_rev >= 6)
    4110           0 :                 return;
    4111             : 
    4112           0 :         if (chan <= 10)
    4113           0 :                 CSR_WRITE_2(sc, BWI_RF_CHAN, BWI_RF_2GHZ_CHAN(chan + 4));
    4114             :         else
    4115           0 :                 CSR_WRITE_2(sc, BWI_RF_CHAN, BWI_RF_2GHZ_CHAN(1));
    4116           0 :         DELAY(1000);
    4117           0 :         CSR_WRITE_2(sc, BWI_RF_CHAN, BWI_RF_2GHZ_CHAN(chan));
    4118           0 : }
    4119             : 
    4120             : struct bwi_rf_lo *
    4121           0 : bwi_rf_lo_find(struct bwi_mac *mac, const struct bwi_tpctl *tpctl)
    4122             : {
    4123             :         uint16_t rf_atten, bbp_atten;
    4124             :         int remap_rf_atten;
    4125             : 
    4126             :         remap_rf_atten = 1;
    4127           0 :         if (tpctl == NULL) {
    4128             :                 bbp_atten = 2;
    4129             :                 rf_atten = 3;
    4130           0 :         } else {
    4131           0 :                 if (tpctl->tp_ctrl1 == 3)
    4132           0 :                         remap_rf_atten = 0;
    4133             : 
    4134           0 :                 bbp_atten = tpctl->bbp_atten;
    4135           0 :                 rf_atten = tpctl->rf_atten;
    4136             : 
    4137           0 :                 if (bbp_atten > 6)
    4138           0 :                         bbp_atten = 6;
    4139             :         }
    4140             : 
    4141           0 :         if (remap_rf_atten) {
    4142             : #define MAP_MAX 10
    4143             :                 static const uint16_t map[MAP_MAX] =
    4144             :                 { 11, 10, 11, 12, 13, 12, 13, 12, 13, 12 };
    4145             : #if 0
    4146             :                 KASSERT(rf_atten < MAP_MAX);
    4147             :                 rf_atten = map[rf_atten];
    4148             : #else
    4149           0 :                 if (rf_atten >= MAP_MAX) {
    4150             :                         rf_atten = 0;   /* XXX */
    4151           0 :                 } else {
    4152           0 :                         rf_atten = map[rf_atten];
    4153             :                 }
    4154             : #endif
    4155             : #undef MAP_MAX
    4156             :         }
    4157             : 
    4158           0 :         return (bwi_get_rf_lo(mac, rf_atten, bbp_atten));
    4159             : }
    4160             : 
    4161             : void
    4162           0 : bwi_rf_lo_adjust(struct bwi_mac *mac, const struct bwi_tpctl *tpctl)
    4163             : {
    4164             :         const struct bwi_rf_lo *lo;
    4165             : 
    4166           0 :         lo = bwi_rf_lo_find(mac, tpctl);
    4167           0 :         RF_LO_WRITE(mac, lo);
    4168           0 : }
    4169             : 
    4170             : void
    4171           0 : bwi_rf_lo_write(struct bwi_mac *mac, const struct bwi_rf_lo *lo)
    4172             : {
    4173             :         uint16_t val;
    4174             : 
    4175           0 :         val = (uint8_t)lo->ctrl_lo;
    4176           0 :         val |= ((uint8_t)lo->ctrl_hi) << 8;
    4177             : 
    4178           0 :         PHY_WRITE(mac, BWI_PHYR_RF_LO, val);
    4179           0 : }
    4180             : 
    4181             : int
    4182           0 : bwi_rf_gain_max_reached(struct bwi_mac *mac, int idx)
    4183             : {
    4184           0 :         PHY_FILT_SETBITS(mac, 0x812, 0xf0ff, idx << 8);
    4185           0 :         PHY_FILT_SETBITS(mac, 0x15, 0xfff, 0xa000);
    4186           0 :         PHY_SETBITS(mac, 0x15, 0xf000);
    4187             : 
    4188           0 :         DELAY(20);
    4189             : 
    4190           0 :         return ((PHY_READ(mac, 0x2d) >= 0xdfc));
    4191             : }
    4192             : 
    4193             : /* XXX use bitmap array */
    4194             : uint16_t
    4195           0 : bwi_bitswap4(uint16_t val)
    4196             : {
    4197             :         uint16_t ret;
    4198             : 
    4199           0 :         ret = (val & 0x8) >> 3;
    4200           0 :         ret |= (val & 0x4) >> 1;
    4201           0 :         ret |= (val & 0x2) << 1;
    4202           0 :         ret |= (val & 0x1) << 3;
    4203             : 
    4204           0 :         return (ret);
    4205             : }
    4206             : 
    4207             : uint16_t
    4208           0 : bwi_phy812_value(struct bwi_mac *mac, uint16_t lpd)
    4209             : {
    4210           0 :         struct bwi_softc *sc = mac->mac_sc;
    4211           0 :         struct bwi_phy *phy = &mac->mac_phy;
    4212           0 :         struct bwi_rf *rf = &mac->mac_rf;
    4213             :         uint16_t lo_gain, ext_lna, loop;
    4214             : 
    4215           0 :         if ((phy->phy_flags & BWI_PHY_F_LINKED) == 0)
    4216           0 :                 return (0);
    4217             : 
    4218           0 :         lo_gain = rf->rf_lo_gain;
    4219           0 :         if (rf->rf_rev == 8)
    4220           0 :                 lo_gain += 0x3e;
    4221             :         else
    4222           0 :                 lo_gain += 0x26;
    4223             : 
    4224           0 :         if (lo_gain >= 0x46) {
    4225           0 :                 lo_gain -= 0x46;
    4226             :                 ext_lna = 0x3000;
    4227           0 :         } else if (lo_gain >= 0x3a) {
    4228           0 :                 lo_gain -= 0x3a;
    4229             :                 ext_lna = 0x1000;
    4230           0 :         } else if (lo_gain >= 0x2e) {
    4231           0 :                 lo_gain -= 0x2e;
    4232             :                 ext_lna = 0x2000;
    4233           0 :         } else {
    4234           0 :                 lo_gain -= 0x10;
    4235             :                 ext_lna = 0;
    4236             :         }
    4237             : 
    4238           0 :         for (loop = 0; loop < 16; ++loop) {
    4239           0 :                 lo_gain -= (6 * loop);
    4240           0 :                 if (lo_gain < 6)
    4241             :                         break;
    4242             :         }
    4243             : 
    4244           0 :         if (phy->phy_rev >= 7 && (sc->sc_card_flags & BWI_CARD_F_EXT_LNA)) {
    4245           0 :                 if (ext_lna)
    4246           0 :                         ext_lna |= 0x8000;
    4247           0 :                 ext_lna |= (loop << 8);
    4248           0 :                 switch (lpd) {
    4249             :                 case 0x011:
    4250           0 :                         return (0x8f92);
    4251             :                 case 0x001:
    4252           0 :                         return ((0x8092 | ext_lna));
    4253             :                 case 0x101:
    4254           0 :                         return ((0x2092 | ext_lna));
    4255             :                 case 0x100:
    4256           0 :                         return ((0x2093 | ext_lna));
    4257             :                 default:
    4258           0 :                         panic("unsupported lpd");
    4259             :                 }
    4260             :         } else {
    4261           0 :                 ext_lna |= (loop << 8);
    4262           0 :                 switch (lpd) {
    4263             :                 case 0x011:
    4264           0 :                         return (0xf92);
    4265             :                 case 0x001:
    4266             :                 case 0x101:
    4267           0 :                         return ((0x92 | ext_lna));
    4268             :                 case 0x100:
    4269           0 :                         return ((0x93 | ext_lna));
    4270             :                 default:
    4271           0 :                         panic("unsupported lpd");
    4272             :                 }
    4273             :         }
    4274             : 
    4275             :         panic("never reached");
    4276             : 
    4277             :         return (0);
    4278           0 : }
    4279             : 
    4280             : void
    4281           0 : bwi_rf_init_bcm2050(struct bwi_mac *mac)
    4282             : {
    4283             : #define SAVE_RF_MAX             3
    4284             : #define SAVE_PHY_COMM_MAX       4
    4285             : #define SAVE_PHY_11G_MAX        6
    4286           0 :         uint16_t save_rf[SAVE_RF_MAX];
    4287           0 :         uint16_t save_phy_comm[SAVE_PHY_COMM_MAX];
    4288           0 :         uint16_t save_phy_11g[SAVE_PHY_11G_MAX];
    4289             :         uint16_t phyr_35, phyr_30 = 0, rfr_78, phyr_80f = 0, phyr_810 = 0;
    4290             :         uint16_t bphy_ctrl = 0, bbp_atten, rf_chan_ex;
    4291             :         uint16_t phy812_val;
    4292             :         uint16_t calib;
    4293             :         uint32_t test_lim, test;
    4294           0 :         struct bwi_softc *sc = mac->mac_sc;
    4295           0 :         struct bwi_phy *phy = &mac->mac_phy;
    4296           0 :         struct bwi_rf *rf = &mac->mac_rf;
    4297             :         int i;
    4298             : 
    4299             :         static const uint16_t save_rf_regs[SAVE_RF_MAX] =
    4300             :             { 0x0043, 0x0051, 0x0052 };
    4301             :         static const uint16_t save_phy_regs_comm[SAVE_PHY_COMM_MAX] =
    4302             :             { 0x0015, 0x005a, 0x0059, 0x0058 };
    4303             :         static const uint16_t save_phy_regs_11g[SAVE_PHY_11G_MAX] =
    4304             :             { 0x0811, 0x0812, 0x0814, 0x0815, 0x0429, 0x0802 };
    4305             : 
    4306             :         /*
    4307             :          * Save registers for later restoring
    4308             :          */
    4309           0 :         for (i = 0; i < SAVE_RF_MAX; ++i)
    4310           0 :                 save_rf[i] = RF_READ(mac, save_rf_regs[i]);
    4311           0 :         for (i = 0; i < SAVE_PHY_COMM_MAX; ++i)
    4312           0 :                 save_phy_comm[i] = PHY_READ(mac, save_phy_regs_comm[i]);
    4313             : 
    4314           0 :         if (phy->phy_mode == IEEE80211_MODE_11B) {
    4315           0 :                 phyr_30 = PHY_READ(mac, 0x30);
    4316           0 :                 bphy_ctrl = CSR_READ_2(sc, BWI_BPHY_CTRL);
    4317             : 
    4318           0 :                 PHY_WRITE(mac, 0x30, 0xff);
    4319           0 :                 CSR_WRITE_2(sc, BWI_BPHY_CTRL, 0x3f3f);
    4320           0 :         } else if ((phy->phy_flags & BWI_PHY_F_LINKED) || phy->phy_rev >= 2) {
    4321           0 :                 for (i = 0; i < SAVE_PHY_11G_MAX; ++i) {
    4322           0 :                         save_phy_11g[i] =
    4323           0 :                             PHY_READ(mac, save_phy_regs_11g[i]);
    4324             :                 }
    4325             : 
    4326           0 :                 PHY_SETBITS(mac, 0x814, 0x3);
    4327           0 :                 PHY_CLRBITS(mac, 0x815, 0x3);
    4328           0 :                 PHY_CLRBITS(mac, 0x429, 0x8000);
    4329           0 :                 PHY_CLRBITS(mac, 0x802, 0x3);
    4330             : 
    4331           0 :                 phyr_80f = PHY_READ(mac, 0x80f);
    4332           0 :                 phyr_810 = PHY_READ(mac, 0x810);
    4333             : 
    4334           0 :                 if (phy->phy_rev >= 3)
    4335           0 :                         PHY_WRITE(mac, 0x80f, 0xc020);
    4336             :                 else
    4337           0 :                         PHY_WRITE(mac, 0x80f, 0x8020);
    4338           0 :                 PHY_WRITE(mac, 0x810, 0);
    4339             : 
    4340           0 :                 phy812_val = bwi_phy812_value(mac, 0x011);
    4341           0 :                 PHY_WRITE(mac, 0x812, phy812_val);
    4342           0 :                 if (phy->phy_rev < 7 ||
    4343           0 :                     (sc->sc_card_flags & BWI_CARD_F_EXT_LNA) == 0)
    4344           0 :                         PHY_WRITE(mac, 0x811, 0x1b3);
    4345             :                 else
    4346           0 :                         PHY_WRITE(mac, 0x811, 0x9b3);
    4347             :         }
    4348           0 :         CSR_SETBITS_2(sc, BWI_RF_ANTDIV, 0x8000);
    4349             : 
    4350           0 :         phyr_35 = PHY_READ(mac, 0x35);
    4351           0 :         PHY_CLRBITS(mac, 0x35, 0x80);
    4352             : 
    4353           0 :         bbp_atten = CSR_READ_2(sc, BWI_BBP_ATTEN);
    4354           0 :         rf_chan_ex = CSR_READ_2(sc, BWI_RF_CHAN_EX);
    4355             : 
    4356           0 :         if (phy->phy_version == 0) {
    4357           0 :                 CSR_WRITE_2(sc, BWI_BBP_ATTEN, 0x122);
    4358           0 :         } else {
    4359           0 :                 if (phy->phy_version >= 2)
    4360           0 :                         PHY_FILT_SETBITS(mac, 0x3, 0xffbf, 0x40);
    4361           0 :                 CSR_SETBITS_2(sc, BWI_RF_CHAN_EX, 0x2000);
    4362             :         }
    4363             : 
    4364           0 :         calib = bwi_rf_calibval(mac);
    4365             : 
    4366           0 :         if (phy->phy_mode == IEEE80211_MODE_11B)
    4367           0 :                 RF_WRITE(mac, 0x78, 0x26);
    4368             : 
    4369           0 :         if ((phy->phy_flags & BWI_PHY_F_LINKED) || phy->phy_rev >= 2) {
    4370           0 :                 phy812_val = bwi_phy812_value(mac, 0x011);
    4371           0 :                 PHY_WRITE(mac, 0x812, phy812_val);
    4372           0 :         }
    4373             : 
    4374           0 :         PHY_WRITE(mac, 0x15, 0xbfaf);
    4375           0 :         PHY_WRITE(mac, 0x2b, 0x1403);
    4376             : 
    4377           0 :         if ((phy->phy_flags & BWI_PHY_F_LINKED) || phy->phy_rev >= 2) {
    4378           0 :                 phy812_val = bwi_phy812_value(mac, 0x001);
    4379           0 :                 PHY_WRITE(mac, 0x812, phy812_val);
    4380           0 :         }
    4381             : 
    4382           0 :         PHY_WRITE(mac, 0x15, 0xbfa0);
    4383             : 
    4384           0 :         RF_SETBITS(mac, 0x51, 0x4);
    4385           0 :         if (rf->rf_rev == 8)
    4386           0 :                 RF_WRITE(mac, 0x43, 0x1f);
    4387             :         else {
    4388           0 :                 RF_WRITE(mac, 0x52, 0);
    4389           0 :                 RF_FILT_SETBITS(mac, 0x43, 0xfff0, 0x9);
    4390             :         }
    4391             : 
    4392             :         test_lim = 0;
    4393           0 :         PHY_WRITE(mac, 0x58, 0);
    4394           0 :         for (i = 0; i < 16; ++i) {
    4395           0 :                 PHY_WRITE(mac, 0x5a, 0x480);
    4396           0 :                 PHY_WRITE(mac, 0x59, 0xc810);
    4397             : 
    4398           0 :                 PHY_WRITE(mac, 0x58, 0xd);
    4399           0 :                 if ((phy->phy_flags & BWI_PHY_F_LINKED) || phy->phy_rev >= 2) {
    4400           0 :                         phy812_val = bwi_phy812_value(mac, 0x101);
    4401           0 :                         PHY_WRITE(mac, 0x812, phy812_val);
    4402           0 :                 }
    4403           0 :                 PHY_WRITE(mac, 0x15, 0xafb0);
    4404           0 :                 DELAY(10);
    4405             : 
    4406           0 :                 if ((phy->phy_flags & BWI_PHY_F_LINKED) || phy->phy_rev >= 2) {
    4407           0 :                         phy812_val = bwi_phy812_value(mac, 0x101);
    4408           0 :                         PHY_WRITE(mac, 0x812, phy812_val);
    4409           0 :                 }
    4410           0 :                 PHY_WRITE(mac, 0x15, 0xefb0);
    4411           0 :                 DELAY(10);
    4412             : 
    4413           0 :                 if ((phy->phy_flags & BWI_PHY_F_LINKED) || phy->phy_rev >= 2) {
    4414           0 :                         phy812_val = bwi_phy812_value(mac, 0x100);
    4415           0 :                         PHY_WRITE(mac, 0x812, phy812_val);
    4416           0 :                 }
    4417           0 :                 PHY_WRITE(mac, 0x15, 0xfff0);
    4418           0 :                 DELAY(20);
    4419             : 
    4420           0 :                 test_lim += PHY_READ(mac, 0x2d);
    4421             : 
    4422           0 :                 PHY_WRITE(mac, 0x58, 0);
    4423           0 :                 if ((phy->phy_flags & BWI_PHY_F_LINKED) || phy->phy_rev >= 2) {
    4424           0 :                         phy812_val = bwi_phy812_value(mac, 0x101);
    4425           0 :                         PHY_WRITE(mac, 0x812, phy812_val);
    4426           0 :                 }
    4427           0 :                 PHY_WRITE(mac, 0x15, 0xafb0);
    4428             :         }
    4429           0 :         ++test_lim;
    4430           0 :         test_lim >>= 9;
    4431             : 
    4432           0 :         DELAY(10);
    4433             : 
    4434             :         test = 0;
    4435           0 :         PHY_WRITE(mac, 0x58, 0);
    4436           0 :         for (i = 0; i < 16; ++i) {
    4437             :                 int j;
    4438             : 
    4439           0 :                 rfr_78 = (bwi_bitswap4(i) << 1) | 0x20;
    4440           0 :                 RF_WRITE(mac, 0x78, rfr_78);
    4441           0 :                 DELAY(10);
    4442             : 
    4443             :                 /* NB: This block is slight different than the above one */
    4444           0 :                 for (j = 0; j < 16; ++j) {
    4445           0 :                         PHY_WRITE(mac, 0x5a, 0xd80);
    4446           0 :                         PHY_WRITE(mac, 0x59, 0xc810);
    4447             : 
    4448           0 :                         PHY_WRITE(mac, 0x58, 0xd);
    4449           0 :                         if ((phy->phy_flags & BWI_PHY_F_LINKED) ||
    4450           0 :                             phy->phy_rev >= 2) {
    4451           0 :                                 phy812_val = bwi_phy812_value(mac, 0x101);
    4452           0 :                                 PHY_WRITE(mac, 0x812, phy812_val);
    4453           0 :                         }
    4454           0 :                         PHY_WRITE(mac, 0x15, 0xafb0);
    4455           0 :                         DELAY(10);
    4456             : 
    4457           0 :                         if ((phy->phy_flags & BWI_PHY_F_LINKED) ||
    4458           0 :                             phy->phy_rev >= 2) {
    4459           0 :                                 phy812_val = bwi_phy812_value(mac, 0x101);
    4460           0 :                                 PHY_WRITE(mac, 0x812, phy812_val);
    4461           0 :                         }
    4462           0 :                         PHY_WRITE(mac, 0x15, 0xefb0);
    4463           0 :                         DELAY(10);
    4464             : 
    4465           0 :                         if ((phy->phy_flags & BWI_PHY_F_LINKED) ||
    4466           0 :                             phy->phy_rev >= 2) {
    4467           0 :                                 phy812_val = bwi_phy812_value(mac, 0x100);
    4468           0 :                                 PHY_WRITE(mac, 0x812, phy812_val);
    4469           0 :                         }
    4470           0 :                         PHY_WRITE(mac, 0x15, 0xfff0);
    4471           0 :                         DELAY(10);
    4472             : 
    4473           0 :                         test += PHY_READ(mac, 0x2d);
    4474             : 
    4475           0 :                         PHY_WRITE(mac, 0x58, 0);
    4476           0 :                         if ((phy->phy_flags & BWI_PHY_F_LINKED) ||
    4477           0 :                             phy->phy_rev >= 2) {
    4478           0 :                                 phy812_val = bwi_phy812_value(mac, 0x101);
    4479           0 :                                 PHY_WRITE(mac, 0x812, phy812_val);
    4480           0 :                         }
    4481           0 :                         PHY_WRITE(mac, 0x15, 0xafb0);
    4482             :                 }
    4483             : 
    4484           0 :                 ++test;
    4485           0 :                 test >>= 8;
    4486             : 
    4487           0 :                 if (test > test_lim)
    4488           0 :                         break;
    4489           0 :         }
    4490           0 :         if (i > 15)
    4491           0 :                 rf->rf_calib = rfr_78;
    4492             :         else
    4493           0 :                 rf->rf_calib = calib;
    4494           0 :         if (rf->rf_calib != 0xffff) {
    4495             :                 DPRINTF(1, "%s: RF calibration value: 0x%04x\n",
    4496             :                     sc->sc_dev.dv_xname, rf->rf_calib);
    4497           0 :                 rf->rf_flags |= BWI_RF_F_INITED;
    4498           0 :         }
    4499             : 
    4500             :         /*
    4501             :          * Restore trashes registers
    4502             :          */
    4503           0 :         PHY_WRITE(mac, save_phy_regs_comm[0], save_phy_comm[0]);
    4504             : 
    4505           0 :         for (i = 0; i < SAVE_RF_MAX; ++i) {
    4506           0 :                 int pos = (i + 1) % SAVE_RF_MAX;
    4507             : 
    4508           0 :                 RF_WRITE(mac, save_rf_regs[pos], save_rf[pos]);
    4509             :         }
    4510           0 :         for (i = 1; i < SAVE_PHY_COMM_MAX; ++i)
    4511           0 :                 PHY_WRITE(mac, save_phy_regs_comm[i], save_phy_comm[i]);
    4512             : 
    4513           0 :         CSR_WRITE_2(sc, BWI_BBP_ATTEN, bbp_atten);
    4514           0 :         if (phy->phy_version != 0)
    4515           0 :                 CSR_WRITE_2(sc, BWI_RF_CHAN_EX, rf_chan_ex);
    4516             : 
    4517           0 :         PHY_WRITE(mac, 0x35, phyr_35);
    4518           0 :         bwi_rf_workaround(mac, rf->rf_curchan);
    4519             : 
    4520           0 :         if (phy->phy_mode == IEEE80211_MODE_11B) {
    4521           0 :                 PHY_WRITE(mac, 0x30, phyr_30);
    4522           0 :                 CSR_WRITE_2(sc, BWI_BPHY_CTRL, bphy_ctrl);
    4523           0 :         } else if ((phy->phy_flags & BWI_PHY_F_LINKED) || phy->phy_rev >= 2) {
    4524             :                 /* XXX Spec only says when PHY is linked (gmode) */
    4525           0 :                 CSR_CLRBITS_2(sc, BWI_RF_ANTDIV, 0x8000);
    4526             : 
    4527           0 :                 for (i = 0; i < SAVE_PHY_11G_MAX; ++i) {
    4528           0 :                         PHY_WRITE(mac, save_phy_regs_11g[i],
    4529             :                                   save_phy_11g[i]);
    4530             :                 }
    4531             : 
    4532           0 :                 PHY_WRITE(mac, 0x80f, phyr_80f);
    4533           0 :                 PHY_WRITE(mac, 0x810, phyr_810);
    4534           0 :         }
    4535             : 
    4536             : #undef SAVE_PHY_11G_MAX
    4537             : #undef SAVE_PHY_COMM_MAX
    4538             : #undef SAVE_RF_MAX
    4539           0 : }
    4540             : 
    4541             : uint16_t
    4542           0 : bwi_rf_calibval(struct bwi_mac *mac)
    4543             : {
    4544             :         uint16_t val, calib;
    4545             :         int idx;
    4546             : 
    4547             :         /* http://bcm-specs.sipsolutions.net/RCCTable */
    4548             :         static const uint16_t rf_calibvals[] = {
    4549             :                 0x2, 0x3, 0x1, 0xf, 0x6, 0x7, 0x5, 0xf,
    4550             :                 0xa, 0xb, 0x9, 0xf, 0xe, 0xf, 0xd, 0xf
    4551             :         };
    4552             : 
    4553           0 :         val = RF_READ(mac, BWI_RFR_BBP_ATTEN);
    4554           0 :         idx = __SHIFTOUT(val, BWI_RFR_BBP_ATTEN_CALIB_IDX);
    4555           0 :         KASSERT(idx < (int)(sizeof(rf_calibvals) / sizeof(rf_calibvals[0])));
    4556             : 
    4557           0 :         calib = rf_calibvals[idx] << 1;
    4558           0 :         if (val & BWI_RFR_BBP_ATTEN_CALIB_BIT)
    4559           0 :                 calib |= 0x1;
    4560           0 :         calib |= 0x20;
    4561             : 
    4562           0 :         return (calib);
    4563             : }
    4564             : 
    4565             : int32_t
    4566           0 : _bwi_adjust_devide(int32_t num, int32_t den)
    4567             : {
    4568           0 :         if (num < 0)
    4569           0 :                 return ((num / den));
    4570             :         else
    4571           0 :                 return ((num + den / 2) / den);
    4572           0 : }
    4573             : 
    4574             : /*
    4575             :  * http://bcm-specs.sipsolutions.net/TSSI_to_DBM_Table
    4576             :  * "calculating table entries"
    4577             :  */
    4578             : int
    4579           0 : bwi_rf_calc_txpower(int8_t *txpwr, uint8_t idx, const int16_t pa_params[])
    4580             : {
    4581             :         int32_t m1, m2, f, dbm;
    4582             :         int i;
    4583             : 
    4584           0 :         m1 = _bwi_adjust_devide(16 * pa_params[0] + idx * pa_params[1], 32);
    4585           0 :         m2 = imax(_bwi_adjust_devide(32768 + idx * pa_params[2], 256), 1);
    4586             : 
    4587             : #define ITER_MAX        16
    4588             :         f = 256;
    4589           0 :         for (i = 0; i < ITER_MAX; ++i) {
    4590             :                 int32_t q, d;
    4591             : 
    4592           0 :                 q = _bwi_adjust_devide(
    4593           0 :                     f * 4096 - _bwi_adjust_devide(m2 * f, 16) * f, 2048);
    4594           0 :                 d = abs(q - f);
    4595             :                 f = q;
    4596             : 
    4597           0 :                 if (d < 2)
    4598           0 :                         break;
    4599           0 :         }
    4600           0 :         if (i == ITER_MAX)
    4601           0 :                 return (EINVAL);
    4602             : #undef ITER_MAX
    4603             : 
    4604           0 :         dbm = _bwi_adjust_devide(m1 * f, 8192);
    4605           0 :         if (dbm < -127)
    4606           0 :                 dbm = -127;
    4607           0 :         else if (dbm > 128)
    4608           0 :                 dbm = 128;
    4609             : 
    4610           0 :         *txpwr = dbm;
    4611             : 
    4612           0 :         return (0);
    4613           0 : }
    4614             : 
    4615             : int
    4616           0 : bwi_rf_map_txpower(struct bwi_mac *mac)
    4617             : {
    4618           0 :         struct bwi_softc *sc = mac->mac_sc;
    4619           0 :         struct bwi_rf *rf = &mac->mac_rf;
    4620           0 :         struct bwi_phy *phy = &mac->mac_phy;
    4621             :         uint16_t sprom_ofs, val, mask;
    4622           0 :         int16_t pa_params[3];
    4623             :         int error = 0, i, ant_gain, reg_txpower_max;
    4624             : 
    4625             :         /*
    4626             :          * Find out max TX power
    4627             :          */
    4628           0 :         val = bwi_read_sprom(sc, BWI_SPROM_MAX_TXPWR);
    4629           0 :         if (phy->phy_mode == IEEE80211_MODE_11A) {
    4630           0 :                 rf->rf_txpower_max = __SHIFTOUT(val,
    4631             :                     BWI_SPROM_MAX_TXPWR_MASK_11A);
    4632           0 :         } else {
    4633           0 :                 rf->rf_txpower_max = __SHIFTOUT(val,
    4634             :                     BWI_SPROM_MAX_TXPWR_MASK_11BG);
    4635             : 
    4636           0 :                 if ((sc->sc_card_flags & BWI_CARD_F_PA_GPIO9) &&
    4637           0 :                     phy->phy_mode == IEEE80211_MODE_11G)
    4638           0 :                         rf->rf_txpower_max -= 3;
    4639             :         }
    4640           0 :         if (rf->rf_txpower_max <= 0) {
    4641           0 :                 printf("%s: invalid max txpower in sprom\n",
    4642           0 :                     sc->sc_dev.dv_xname);
    4643           0 :                 rf->rf_txpower_max = 74;
    4644           0 :         }
    4645             :         DPRINTF(1, "%s: max txpower from sprom: %d dBm\n",
    4646             :             sc->sc_dev.dv_xname, rf->rf_txpower_max);
    4647             : 
    4648             :         /*
    4649             :          * Find out region/domain max TX power, which is adjusted
    4650             :          * by antenna gain and 1.5 dBm fluctuation as mentioned
    4651             :          * in v3 spec.
    4652             :          */
    4653           0 :         val = bwi_read_sprom(sc, BWI_SPROM_ANT_GAIN);
    4654           0 :         if (phy->phy_mode == IEEE80211_MODE_11A)
    4655           0 :                 ant_gain = __SHIFTOUT(val, BWI_SPROM_ANT_GAIN_MASK_11A);
    4656             :         else
    4657           0 :                 ant_gain = __SHIFTOUT(val, BWI_SPROM_ANT_GAIN_MASK_11BG);
    4658           0 :         if (ant_gain == 0xff) {
    4659             :                 /* XXX why this always invalid? */
    4660             :                 DPRINTF(1, "%s: invalid antenna gain in sprom\n",
    4661             :                     sc->sc_dev.dv_xname);
    4662             :                 ant_gain = 2;
    4663           0 :         }
    4664           0 :         ant_gain *= 4;
    4665             :         DPRINTF(1, "%s: ant gain %d dBm\n", sc->sc_dev.dv_xname, ant_gain);
    4666             : 
    4667           0 :         reg_txpower_max = 90 - ant_gain - 6;    /* XXX magic number */
    4668             :         DPRINTF(1, "%s: region/domain max txpower %d dBm\n",
    4669             :             sc->sc_dev.dv_xname, reg_txpower_max);
    4670             : 
    4671             :         /*
    4672             :          * Force max TX power within region/domain TX power limit
    4673             :          */
    4674           0 :         if (rf->rf_txpower_max > reg_txpower_max)
    4675           0 :                 rf->rf_txpower_max = reg_txpower_max;
    4676             :         DPRINTF(1, "%s: max txpower %d dBm\n",
    4677             :             sc->sc_dev.dv_xname, rf->rf_txpower_max);
    4678             : 
    4679             :         /*
    4680             :          * Create TSSI to TX power mapping
    4681             :          */
    4682             : 
    4683           0 :         if (sc->sc_bbp_id == BWI_BBPID_BCM4301 &&
    4684           0 :             rf->rf_type != BWI_RF_T_BCM2050) {
    4685           0 :                 rf->rf_idle_tssi0 = BWI_DEFAULT_IDLE_TSSI;
    4686           0 :                 bcopy(bwi_txpower_map_11b, rf->rf_txpower_map0,
    4687             :                       sizeof(rf->rf_txpower_map0));
    4688           0 :                 goto back;
    4689             :         }
    4690             : 
    4691             : #define IS_VALID_PA_PARAM(p)    ((p) != 0 && (p) != -1)
    4692             :         /*
    4693             :          * Extract PA parameters
    4694             :          */
    4695           0 :         if (phy->phy_mode == IEEE80211_MODE_11A)
    4696           0 :                 sprom_ofs = BWI_SPROM_PA_PARAM_11A;
    4697             :         else
    4698             :                 sprom_ofs = BWI_SPROM_PA_PARAM_11BG;
    4699           0 :         for (i = 0; i < nitems(pa_params); ++i)
    4700           0 :                 pa_params[i] = (int16_t)bwi_read_sprom(sc, sprom_ofs + (i * 2));
    4701             : 
    4702           0 :         for (i = 0; i < nitems(pa_params); ++i) {
    4703             :                 /*
    4704             :                  * If one of the PA parameters from SPROM is not valid,
    4705             :                  * fall back to the default values, if there are any.
    4706             :                  */
    4707           0 :                 if (!IS_VALID_PA_PARAM(pa_params[i])) {
    4708             :                         const int8_t *txpower_map;
    4709             : 
    4710           0 :                         if (phy->phy_mode == IEEE80211_MODE_11A) {
    4711           0 :                                 printf("%s: no tssi2dbm table for 11a PHY\n",
    4712           0 :                                     sc->sc_dev.dv_xname);
    4713           0 :                                 return (ENXIO);
    4714             :                         }
    4715             : 
    4716           0 :                         if (phy->phy_mode == IEEE80211_MODE_11G) {
    4717             :                                 DPRINTF(1, "%s: use default 11g TSSI map\n",
    4718             :                                     sc->sc_dev.dv_xname);
    4719             :                                 txpower_map = bwi_txpower_map_11g;
    4720           0 :                         } else {
    4721             :                                 txpower_map = bwi_txpower_map_11b;
    4722             :                         }
    4723             : 
    4724           0 :                         rf->rf_idle_tssi0 = BWI_DEFAULT_IDLE_TSSI;
    4725           0 :                         bcopy(txpower_map, rf->rf_txpower_map0,
    4726             :                               sizeof(rf->rf_txpower_map0));
    4727           0 :                         goto back;
    4728             :                 }
    4729             :         }
    4730             : 
    4731             :         /*
    4732             :          * All of the PA parameters from SPROM are valid.
    4733             :          */
    4734             : 
    4735             :         /*
    4736             :          * Extract idle TSSI from SPROM.
    4737             :          */
    4738           0 :         val = bwi_read_sprom(sc, BWI_SPROM_IDLE_TSSI);
    4739             :         DPRINTF(1, "%s: sprom idle tssi: 0x%04x\n", sc->sc_dev.dv_xname, val);
    4740             : 
    4741           0 :         if (phy->phy_mode == IEEE80211_MODE_11A)
    4742           0 :                 mask = BWI_SPROM_IDLE_TSSI_MASK_11A;
    4743             :         else
    4744             :                 mask = BWI_SPROM_IDLE_TSSI_MASK_11BG;
    4745             : 
    4746           0 :         rf->rf_idle_tssi0 = (int)__SHIFTOUT(val, mask);
    4747           0 :         if (!IS_VALID_PA_PARAM(rf->rf_idle_tssi0))
    4748           0 :                 rf->rf_idle_tssi0 = 62;
    4749             : 
    4750             : #undef IS_VALID_PA_PARAM
    4751             : 
    4752             :         /*
    4753             :          * Calculate TX power map, which is indexed by TSSI
    4754             :          */
    4755             :         DPRINTF(1, "%s: TSSI-TX power map:\n", sc->sc_dev.dv_xname);
    4756           0 :         for (i = 0; i < BWI_TSSI_MAX; ++i) {
    4757           0 :                 error = bwi_rf_calc_txpower(&rf->rf_txpower_map0[i], i,
    4758           0 :                                             pa_params);
    4759           0 :                 if (error) {
    4760           0 :                         printf("%s: bwi_rf_calc_txpower failed\n",
    4761           0 :                             sc->sc_dev.dv_xname);
    4762           0 :                         break;
    4763             :                 }
    4764             :                 if (i != 0 && i % 8 == 0)
    4765             :                         DPRINTF(1, "\n");
    4766             :                 DPRINTF(1, "%d ", rf->rf_txpower_map0[i]);
    4767             :         }
    4768             :         DPRINTF(1, "\n");
    4769             : back:
    4770             :         DPRINTF(1, "%s: idle tssi0: %d\n",
    4771             :             sc->sc_dev.dv_xname, rf->rf_idle_tssi0);
    4772             : 
    4773           0 :         return (error);
    4774           0 : }
    4775             : 
    4776             : void
    4777           0 : bwi_rf_lo_update_11g(struct bwi_mac *mac)
    4778             : {
    4779           0 :         struct bwi_softc *sc = mac->mac_sc;
    4780           0 :         struct ifnet *ifp = &sc->sc_ic.ic_if;
    4781           0 :         struct bwi_rf *rf = &mac->mac_rf;
    4782           0 :         struct bwi_phy *phy = &mac->mac_phy;
    4783           0 :         struct bwi_tpctl *tpctl = &mac->mac_tpctl;
    4784           0 :         struct rf_saveregs regs;
    4785             :         uint16_t ant_div, chan_ex;
    4786             :         uint8_t devi_ctrl;
    4787             :         uint orig_chan;
    4788             : 
    4789             :         DPRINTF(1, "%s: %s\n", sc->sc_dev.dv_xname, __func__);
    4790             : 
    4791             :         /*
    4792             :          * Save RF/PHY registers for later restoration
    4793             :          */
    4794           0 :         orig_chan = rf->rf_curchan;
    4795           0 :         bzero(&regs, sizeof(regs));
    4796             : 
    4797           0 :         if (phy->phy_flags & BWI_PHY_F_LINKED) {
    4798           0 :                 SAVE_PHY_REG(mac, &regs, 429);
    4799           0 :                 SAVE_PHY_REG(mac, &regs, 802);
    4800             : 
    4801           0 :                 PHY_WRITE(mac, 0x429, regs.phy_429 & 0x7fff);
    4802           0 :                 PHY_WRITE(mac, 0x802, regs.phy_802 & 0xfffc);
    4803           0 :         }
    4804             : 
    4805           0 :         ant_div = CSR_READ_2(sc, BWI_RF_ANTDIV);
    4806           0 :         CSR_WRITE_2(sc, BWI_RF_ANTDIV, ant_div | 0x8000);
    4807           0 :         chan_ex = CSR_READ_2(sc, BWI_RF_CHAN_EX);
    4808             : 
    4809           0 :         SAVE_PHY_REG(mac, &regs, 15);
    4810           0 :         SAVE_PHY_REG(mac, &regs, 2a);
    4811           0 :         SAVE_PHY_REG(mac, &regs, 35);
    4812           0 :         SAVE_PHY_REG(mac, &regs, 60);
    4813           0 :         SAVE_RF_REG(mac, &regs, 43);
    4814           0 :         SAVE_RF_REG(mac, &regs, 7a);
    4815           0 :         SAVE_RF_REG(mac, &regs, 52);
    4816           0 :         if (phy->phy_flags & BWI_PHY_F_LINKED) {
    4817           0 :                 SAVE_PHY_REG(mac, &regs, 811);
    4818           0 :                 SAVE_PHY_REG(mac, &regs, 812);
    4819           0 :                 SAVE_PHY_REG(mac, &regs, 814);
    4820           0 :                 SAVE_PHY_REG(mac, &regs, 815);
    4821           0 :         }
    4822             : 
    4823             :         /* Force to channel 6 */
    4824           0 :         bwi_rf_set_chan(mac, 6, 0);
    4825             : 
    4826           0 :         if (phy->phy_flags & BWI_PHY_F_LINKED) {
    4827           0 :                 PHY_WRITE(mac, 0x429, regs.phy_429 & 0x7fff);
    4828           0 :                 PHY_WRITE(mac, 0x802, regs.phy_802 & 0xfffc);
    4829           0 :                 bwi_mac_dummy_xmit(mac);
    4830           0 :         }
    4831           0 :         RF_WRITE(mac, 0x43, 0x6);
    4832             : 
    4833           0 :         bwi_phy_set_bbp_atten(mac, 2);
    4834             : 
    4835           0 :         CSR_WRITE_2(sc, BWI_RF_CHAN_EX, 0);
    4836             : 
    4837           0 :         PHY_WRITE(mac, 0x2e, 0x7f);
    4838           0 :         PHY_WRITE(mac, 0x80f, 0x78);
    4839           0 :         PHY_WRITE(mac, 0x35, regs.phy_35 & 0xff7f);
    4840           0 :         RF_WRITE(mac, 0x7a, regs.rf_7a & 0xfff0);
    4841           0 :         PHY_WRITE(mac, 0x2b, 0x203);
    4842           0 :         PHY_WRITE(mac, 0x2a, 0x8a3);
    4843             : 
    4844           0 :         if (phy->phy_flags & BWI_PHY_F_LINKED) {
    4845           0 :                 PHY_WRITE(mac, 0x814, regs.phy_814 | 0x3);
    4846           0 :                 PHY_WRITE(mac, 0x815, regs.phy_815 & 0xfffc);
    4847           0 :                 PHY_WRITE(mac, 0x811, 0x1b3);
    4848           0 :                 PHY_WRITE(mac, 0x812, 0xb2);
    4849           0 :         }
    4850             : 
    4851           0 :         if ((ifp->if_flags & IFF_RUNNING) == 0)
    4852           0 :                 tpctl->tp_ctrl2 = bwi_rf_get_tp_ctrl2(mac);
    4853           0 :         PHY_WRITE(mac, 0x80f, 0x8078);
    4854             : 
    4855             :         /*
    4856             :          * Measure all RF LO
    4857             :          */
    4858           0 :         devi_ctrl = _bwi_rf_lo_update_11g(mac, regs.rf_7a);
    4859             : 
    4860             :         /*
    4861             :          * Restore saved RF/PHY registers
    4862             :          */
    4863           0 :         if (phy->phy_flags & BWI_PHY_F_LINKED) {
    4864           0 :                 PHY_WRITE(mac, 0x15, 0xe300);
    4865           0 :                 PHY_WRITE(mac, 0x812, (devi_ctrl << 8) | 0xa0);
    4866           0 :                 DELAY(5);
    4867           0 :                 PHY_WRITE(mac, 0x812, (devi_ctrl << 8) | 0xa2);
    4868           0 :                 DELAY(2);
    4869           0 :                 PHY_WRITE(mac, 0x812, (devi_ctrl << 8) | 0xa3);
    4870           0 :         } else
    4871           0 :                 PHY_WRITE(mac, 0x15, devi_ctrl | 0xefa0);
    4872             : 
    4873           0 :         if ((ifp->if_flags & IFF_RUNNING) == 0)
    4874           0 :                 tpctl = NULL;
    4875           0 :         bwi_rf_lo_adjust(mac, tpctl);
    4876             : 
    4877           0 :         PHY_WRITE(mac, 0x2e, 0x807f);
    4878           0 :         if (phy->phy_flags & BWI_PHY_F_LINKED)
    4879           0 :                 PHY_WRITE(mac, 0x2f, 0x202);
    4880             :         else
    4881           0 :                 PHY_WRITE(mac, 0x2f, 0x101);
    4882             : 
    4883           0 :         CSR_WRITE_2(sc, BWI_RF_CHAN_EX, chan_ex);
    4884             : 
    4885           0 :         RESTORE_PHY_REG(mac, &regs, 15);
    4886           0 :         RESTORE_PHY_REG(mac, &regs, 2a);
    4887           0 :         RESTORE_PHY_REG(mac, &regs, 35);
    4888           0 :         RESTORE_PHY_REG(mac, &regs, 60);
    4889             : 
    4890           0 :         RESTORE_RF_REG(mac, &regs, 43);
    4891           0 :         RESTORE_RF_REG(mac, &regs, 7a);
    4892             : 
    4893           0 :         regs.rf_52 &= 0xf0;
    4894           0 :         regs.rf_52 |= (RF_READ(mac, 0x52) & 0xf);
    4895           0 :         RF_WRITE(mac, 0x52, regs.rf_52);
    4896             : 
    4897           0 :         CSR_WRITE_2(sc, BWI_RF_ANTDIV, ant_div);
    4898             : 
    4899           0 :         if (phy->phy_flags & BWI_PHY_F_LINKED) {
    4900           0 :                 RESTORE_PHY_REG(mac, &regs, 811);
    4901           0 :                 RESTORE_PHY_REG(mac, &regs, 812);
    4902           0 :                 RESTORE_PHY_REG(mac, &regs, 814);
    4903           0 :                 RESTORE_PHY_REG(mac, &regs, 815);
    4904           0 :                 RESTORE_PHY_REG(mac, &regs, 429);
    4905           0 :                 RESTORE_PHY_REG(mac, &regs, 802);
    4906           0 :         }
    4907             : 
    4908           0 :         bwi_rf_set_chan(mac, orig_chan, 1);
    4909           0 : }
    4910             : 
    4911             : uint32_t
    4912           0 : bwi_rf_lo_devi_measure(struct bwi_mac *mac, uint16_t ctrl)
    4913             : {
    4914           0 :         struct bwi_phy *phy = &mac->mac_phy;
    4915             :         uint32_t devi = 0;
    4916             :         int i;
    4917             : 
    4918           0 :         if (phy->phy_flags & BWI_PHY_F_LINKED)
    4919           0 :                 ctrl <<= 8;
    4920             : 
    4921           0 :         for (i = 0; i < 8; ++i) {
    4922           0 :                 if (phy->phy_flags & BWI_PHY_F_LINKED) {
    4923           0 :                         PHY_WRITE(mac, 0x15, 0xe300);
    4924           0 :                         PHY_WRITE(mac, 0x812, ctrl | 0xb0);
    4925           0 :                         DELAY(5);
    4926           0 :                         PHY_WRITE(mac, 0x812, ctrl | 0xb2);
    4927           0 :                         DELAY(2);
    4928           0 :                         PHY_WRITE(mac, 0x812, ctrl | 0xb3);
    4929           0 :                         DELAY(4);
    4930           0 :                         PHY_WRITE(mac, 0x15, 0xf300);
    4931           0 :                 } else {
    4932           0 :                         PHY_WRITE(mac, 0x15, ctrl | 0xefa0);
    4933           0 :                         DELAY(2);
    4934           0 :                         PHY_WRITE(mac, 0x15, ctrl | 0xefe0);
    4935           0 :                         DELAY(4);
    4936           0 :                         PHY_WRITE(mac, 0x15, ctrl | 0xffe0);
    4937             :                 }
    4938           0 :                 DELAY(8);
    4939           0 :                 devi += PHY_READ(mac, 0x2d);
    4940             :         }
    4941             : 
    4942           0 :         return (devi);
    4943             : }
    4944             : 
    4945             : uint16_t
    4946           0 : bwi_rf_get_tp_ctrl2(struct bwi_mac *mac)
    4947             : {
    4948             :         uint32_t devi_min;
    4949             :         uint16_t tp_ctrl2 = 0;
    4950             :         int i;
    4951             : 
    4952           0 :         RF_WRITE(mac, 0x52, 0);
    4953           0 :         DELAY(10);
    4954           0 :         devi_min = bwi_rf_lo_devi_measure(mac, 0);
    4955             : 
    4956           0 :         for (i = 0; i < 16; ++i) {
    4957             :                 uint32_t devi;
    4958             : 
    4959           0 :                 RF_WRITE(mac, 0x52, i);
    4960           0 :                 DELAY(10);
    4961           0 :                 devi = bwi_rf_lo_devi_measure(mac, 0);
    4962             : 
    4963           0 :                 if (devi < devi_min) {
    4964             :                         devi_min = devi;
    4965             :                         tp_ctrl2 = i;
    4966           0 :                 }
    4967             :         }
    4968             : 
    4969           0 :         return (tp_ctrl2);
    4970             : }
    4971             : 
    4972             : uint8_t
    4973           0 : _bwi_rf_lo_update_11g(struct bwi_mac *mac, uint16_t orig_rf7a)
    4974             : {
    4975             : #define RF_ATTEN_LISTSZ 14
    4976             : #define BBP_ATTEN_MAX   4       /* half */
    4977           0 :         struct ifnet *ifp = &mac->mac_sc->sc_ic.ic_if;
    4978           0 :         struct bwi_rf_lo lo_save, *lo;
    4979             :         uint8_t devi_ctrl = 0;
    4980             :         int idx, adj_rf7a = 0;
    4981             : 
    4982             :         static const int rf_atten_list[RF_ATTEN_LISTSZ] =
    4983             :             { 3, 1, 5, 7, 9, 2, 0, 4, 6, 8, 1, 2, 3, 4 };
    4984             :         static const int rf_atten_init_list[RF_ATTEN_LISTSZ] =
    4985             :             { 0, 3, 1, 5, 7, 3, 2, 0, 4, 6, -1, -1, -1, -1 };
    4986             :         static const int rf_lo_measure_order[RF_ATTEN_LISTSZ] =
    4987             :             { 3, 1, 5, 7, 9, 2, 0, 4, 6, 8, 10, 11, 12, 13 };
    4988             : 
    4989           0 :         bzero(&lo_save, sizeof(lo_save));
    4990           0 :         for (idx = 0; idx < RF_ATTEN_LISTSZ; ++idx) {
    4991           0 :                 int init_rf_atten = rf_atten_init_list[idx];
    4992           0 :                 int rf_atten = rf_atten_list[idx];
    4993             :                 int bbp_atten;
    4994             : 
    4995           0 :                 for (bbp_atten = 0; bbp_atten < BBP_ATTEN_MAX; ++bbp_atten) {
    4996             :                         uint16_t tp_ctrl2, rf7a;
    4997             : 
    4998           0 :                         if ((ifp->if_flags & IFF_RUNNING) == 0) {
    4999           0 :                                 if (idx == 0) {
    5000           0 :                                         bzero(&lo_save, sizeof(lo_save));
    5001           0 :                                 } else if (init_rf_atten < 0) {
    5002           0 :                                         lo = bwi_get_rf_lo(mac,
    5003           0 :                                             rf_atten, 2 * bbp_atten);
    5004           0 :                                         bcopy(lo, &lo_save, sizeof(lo_save));
    5005           0 :                                 } else {
    5006           0 :                                         lo = bwi_get_rf_lo(mac,
    5007           0 :                                             init_rf_atten, 0);
    5008           0 :                                         bcopy(lo, &lo_save, sizeof(lo_save));
    5009             :                                 }
    5010             : 
    5011             :                                 devi_ctrl = 0;
    5012             :                                 adj_rf7a = 0;
    5013             : 
    5014             :                                 /*
    5015             :                                  * XXX
    5016             :                                  * Linux driver overflows 'val'
    5017             :                                  */
    5018           0 :                                 if (init_rf_atten >= 0) {
    5019             :                                         int val;
    5020             : 
    5021           0 :                                         val = rf_atten * 2 + bbp_atten;
    5022           0 :                                         if (val > 14) {
    5023             :                                                 adj_rf7a = 1;
    5024           0 :                                                 if (val > 17)
    5025           0 :                                                         devi_ctrl = 1;
    5026           0 :                                                 if (val > 19)
    5027           0 :                                                         devi_ctrl = 2;
    5028             :                                         }
    5029           0 :                                 }
    5030             :                         } else {
    5031           0 :                                 lo = bwi_get_rf_lo(mac,
    5032           0 :                                         rf_atten, 2 * bbp_atten);
    5033           0 :                                 if (!bwi_rf_lo_isused(mac, lo))
    5034           0 :                                         continue;
    5035           0 :                                 bcopy(lo, &lo_save, sizeof(lo_save));
    5036             : 
    5037             :                                 devi_ctrl = 3;
    5038             :                                 adj_rf7a = 0;
    5039             :                         }
    5040             : 
    5041           0 :                         RF_WRITE(mac, BWI_RFR_ATTEN, rf_atten);
    5042             : 
    5043           0 :                         tp_ctrl2 = mac->mac_tpctl.tp_ctrl2;
    5044           0 :                         if (init_rf_atten < 0)
    5045           0 :                                 tp_ctrl2 |= (3 << 4);
    5046           0 :                         RF_WRITE(mac, BWI_RFR_TXPWR, tp_ctrl2);
    5047             : 
    5048           0 :                         DELAY(10);
    5049             : 
    5050           0 :                         bwi_phy_set_bbp_atten(mac, bbp_atten * 2);
    5051             : 
    5052           0 :                         rf7a = orig_rf7a & 0xfff0;
    5053           0 :                         if (adj_rf7a)
    5054           0 :                                 rf7a |= 0x8;
    5055           0 :                         RF_WRITE(mac, 0x7a, rf7a);
    5056             : 
    5057           0 :                         lo = bwi_get_rf_lo(mac,
    5058           0 :                                 rf_lo_measure_order[idx], bbp_atten * 2);
    5059           0 :                         bwi_rf_lo_measure_11g(mac, &lo_save, lo, devi_ctrl);
    5060           0 :                 }
    5061             :         }
    5062             : 
    5063           0 :         return (devi_ctrl);
    5064             : 
    5065             : #undef RF_ATTEN_LISTSZ
    5066             : #undef BBP_ATTEN_MAX
    5067           0 : }
    5068             : 
    5069             : void
    5070           0 : bwi_rf_lo_measure_11g(struct bwi_mac *mac, const struct bwi_rf_lo *src_lo,
    5071             :     struct bwi_rf_lo *dst_lo, uint8_t devi_ctrl)
    5072             : {
    5073             : #define LO_ADJUST_MIN   1
    5074             : #define LO_ADJUST_MAX   8
    5075             : #define LO_ADJUST(hi, lo)       { .ctrl_hi = hi, .ctrl_lo = lo }
    5076             :         static const struct bwi_rf_lo rf_lo_adjust[LO_ADJUST_MAX] = {
    5077             :                 LO_ADJUST(1,    1),
    5078             :                 LO_ADJUST(1,    0),
    5079             :                 LO_ADJUST(1,    -1),
    5080             :                 LO_ADJUST(0,    -1),
    5081             :                 LO_ADJUST(-1,   -1),
    5082             :                 LO_ADJUST(-1,   0),
    5083             :                 LO_ADJUST(-1,   1),
    5084             :                 LO_ADJUST(0,    1)
    5085             :         };
    5086             : #undef LO_ADJUST
    5087             : 
    5088           0 :         struct bwi_rf_lo lo_min;
    5089             :         uint32_t devi_min;
    5090             :         int found, loop_count, adjust_state;
    5091             : 
    5092           0 :         bcopy(src_lo, &lo_min, sizeof(lo_min));
    5093           0 :         RF_LO_WRITE(mac, &lo_min);
    5094           0 :         devi_min = bwi_rf_lo_devi_measure(mac, devi_ctrl);
    5095             : 
    5096             :         loop_count = 12;        /* XXX */
    5097             :         adjust_state = 0;
    5098           0 :         do {
    5099           0 :                 struct bwi_rf_lo lo_base;
    5100             :                 int i, fin;
    5101             : 
    5102             :                 found = 0;
    5103           0 :                 if (adjust_state == 0) {
    5104             :                         i = LO_ADJUST_MIN;
    5105             :                         fin = LO_ADJUST_MAX;
    5106           0 :                 } else if (adjust_state % 2 == 0) {
    5107           0 :                         i = adjust_state - 1;
    5108           0 :                         fin = adjust_state + 1;
    5109           0 :                 } else {
    5110           0 :                         i = adjust_state - 2;
    5111           0 :                         fin = adjust_state + 2;
    5112             :                 }
    5113             : 
    5114           0 :                 if (i < LO_ADJUST_MIN)
    5115           0 :                         i += LO_ADJUST_MAX;
    5116           0 :                 KASSERT(i <= LO_ADJUST_MAX && i >= LO_ADJUST_MIN);
    5117             : 
    5118           0 :                 if (fin > LO_ADJUST_MAX)
    5119           0 :                         fin -= LO_ADJUST_MAX;
    5120           0 :                 KASSERT(fin <= LO_ADJUST_MAX && fin >= LO_ADJUST_MIN);
    5121             : 
    5122           0 :                 bcopy(&lo_min, &lo_base, sizeof(lo_base));
    5123           0 :                 for (;;) {
    5124           0 :                         struct bwi_rf_lo lo;
    5125             : 
    5126           0 :                         lo.ctrl_hi = lo_base.ctrl_hi +
    5127           0 :                                 rf_lo_adjust[i - 1].ctrl_hi;
    5128           0 :                         lo.ctrl_lo = lo_base.ctrl_lo +
    5129           0 :                                 rf_lo_adjust[i - 1].ctrl_lo;
    5130             : 
    5131           0 :                         if (abs(lo.ctrl_lo) < 9 && abs(lo.ctrl_hi) < 9) {
    5132             :                                 uint32_t devi;
    5133             : 
    5134           0 :                                 RF_LO_WRITE(mac, &lo);
    5135           0 :                                 devi = bwi_rf_lo_devi_measure(mac, devi_ctrl);
    5136           0 :                                 if (devi < devi_min) {
    5137             :                                         devi_min = devi;
    5138             :                                         adjust_state = i;
    5139             :                                         found = 1;
    5140           0 :                                         bcopy(&lo, &lo_min, sizeof(lo_min));
    5141           0 :                                 }
    5142           0 :                         }
    5143           0 :                         if (i == fin)
    5144           0 :                                 break;
    5145           0 :                         if (i == LO_ADJUST_MAX)
    5146           0 :                                 i = LO_ADJUST_MIN;
    5147             :                         else
    5148           0 :                                 ++i;
    5149           0 :                 }
    5150           0 :         } while (loop_count-- && found);
    5151             : 
    5152           0 :         bcopy(&lo_min, dst_lo, sizeof(*dst_lo));
    5153             : 
    5154             : #undef LO_ADJUST_MIN
    5155             : #undef LO_ADJUST_MAX
    5156           0 : }
    5157             : 
    5158             : void
    5159           0 : bwi_rf_calc_nrssi_slope_11b(struct bwi_mac *mac)
    5160             : {
    5161             : #define SAVE_RF_MAX     3
    5162             : #define SAVE_PHY_MAX    8
    5163           0 :         struct bwi_softc *sc = mac->mac_sc;
    5164           0 :         struct bwi_rf *rf = &mac->mac_rf;
    5165           0 :         struct bwi_phy *phy = &mac->mac_phy;
    5166           0 :         uint16_t save_rf[SAVE_RF_MAX];
    5167           0 :         uint16_t save_phy[SAVE_PHY_MAX];
    5168             :         uint16_t ant_div, bbp_atten, chan_ex;
    5169             :         int16_t nrssi[2];
    5170             :         int i;
    5171             : 
    5172             :         static const uint16_t save_rf_regs[SAVE_RF_MAX] =
    5173             :             { 0x7a, 0x52, 0x43 };
    5174             :         static const uint16_t save_phy_regs[SAVE_PHY_MAX] =
    5175             :             { 0x30, 0x26, 0x15, 0x2a, 0x20, 0x5a, 0x59, 0x58 };
    5176             : 
    5177             :         /*
    5178             :          * Save RF/PHY registers for later restoration
    5179             :          */
    5180           0 :         for (i = 0; i < SAVE_RF_MAX; ++i)
    5181           0 :                 save_rf[i] = RF_READ(mac, save_rf_regs[i]);
    5182           0 :         for (i = 0; i < SAVE_PHY_MAX; ++i)
    5183           0 :                 save_phy[i] = PHY_READ(mac, save_phy_regs[i]);
    5184             : 
    5185           0 :         ant_div = CSR_READ_2(sc, BWI_RF_ANTDIV);
    5186           0 :         bbp_atten = CSR_READ_2(sc, BWI_BBP_ATTEN);
    5187           0 :         chan_ex = CSR_READ_2(sc, BWI_RF_CHAN_EX);
    5188             : 
    5189             :         /*
    5190             :          * Calculate nrssi0
    5191             :          */
    5192           0 :         if (phy->phy_rev >= 5)
    5193           0 :                 RF_CLRBITS(mac, 0x7a, 0xff80);
    5194             :         else
    5195           0 :                 RF_CLRBITS(mac, 0x7a, 0xfff0);
    5196           0 :         PHY_WRITE(mac, 0x30, 0xff);
    5197             : 
    5198           0 :         CSR_WRITE_2(sc, BWI_BPHY_CTRL, 0x7f7f);
    5199             : 
    5200           0 :         PHY_WRITE(mac, 0x26, 0);
    5201           0 :         PHY_SETBITS(mac, 0x15, 0x20);
    5202           0 :         PHY_WRITE(mac, 0x2a, 0x8a3);
    5203           0 :         RF_SETBITS(mac, 0x7a, 0x80);
    5204             : 
    5205           0 :         nrssi[0] = (int16_t)PHY_READ(mac, 0x27);
    5206             : 
    5207             :         /*
    5208             :          * Calculate nrssi1
    5209             :          */
    5210           0 :         RF_CLRBITS(mac, 0x7a, 0xff80);
    5211           0 :         if (phy->phy_version >= 2)
    5212           0 :                 CSR_WRITE_2(sc, BWI_BBP_ATTEN, 0x40);
    5213           0 :         else if (phy->phy_version == 0)
    5214           0 :                 CSR_WRITE_2(sc, BWI_BBP_ATTEN, 0x122);
    5215             :         else
    5216           0 :                 CSR_CLRBITS_2(sc, BWI_RF_CHAN_EX, 0xdfff);
    5217             : 
    5218           0 :         PHY_WRITE(mac, 0x20, 0x3f3f);
    5219           0 :         PHY_WRITE(mac, 0x15, 0xf330);
    5220             : 
    5221           0 :         RF_WRITE(mac, 0x5a, 0x60);
    5222           0 :         RF_CLRBITS(mac, 0x43, 0xff0f);
    5223             : 
    5224           0 :         PHY_WRITE(mac, 0x5a, 0x480);
    5225           0 :         PHY_WRITE(mac, 0x59, 0x810);
    5226           0 :         PHY_WRITE(mac, 0x58, 0xd);
    5227             : 
    5228           0 :         DELAY(20);
    5229             : 
    5230           0 :         nrssi[1] = (int16_t)PHY_READ(mac, 0x27);
    5231             : 
    5232             :         /*
    5233             :          * Restore saved RF/PHY registers
    5234             :          */
    5235           0 :         PHY_WRITE(mac, save_phy_regs[0], save_phy[0]);
    5236           0 :         RF_WRITE(mac, save_rf_regs[0], save_rf[0]);
    5237             : 
    5238           0 :         CSR_WRITE_2(sc, BWI_RF_ANTDIV, ant_div);
    5239             : 
    5240           0 :         for (i = 1; i < 4; ++i)
    5241           0 :                 PHY_WRITE(mac, save_phy_regs[i], save_phy[i]);
    5242             : 
    5243           0 :         bwi_rf_workaround(mac, rf->rf_curchan);
    5244             : 
    5245           0 :         if (phy->phy_version != 0)
    5246           0 :                 CSR_WRITE_2(sc, BWI_RF_CHAN_EX, chan_ex);
    5247             : 
    5248           0 :         for (; i < SAVE_PHY_MAX; ++i)
    5249           0 :                 PHY_WRITE(mac, save_phy_regs[i], save_phy[i]);
    5250             : 
    5251           0 :         for (i = 1; i < SAVE_RF_MAX; ++i)
    5252           0 :                 RF_WRITE(mac, save_rf_regs[i], save_rf[i]);
    5253             : 
    5254             :         /*
    5255             :          * Install calculated narrow RSSI values
    5256             :          */
    5257           0 :         if (nrssi[0] == nrssi[1])
    5258           0 :                 rf->rf_nrssi_slope = 0x10000;
    5259             :         else
    5260           0 :                 rf->rf_nrssi_slope = 0x400000 / (nrssi[0] - nrssi[1]);
    5261           0 :         if (nrssi[0] <= -4) {
    5262           0 :                 rf->rf_nrssi[0] = nrssi[0];
    5263           0 :                 rf->rf_nrssi[1] = nrssi[1];
    5264           0 :         }
    5265             : 
    5266             : #undef SAVE_RF_MAX
    5267             : #undef SAVE_PHY_MAX
    5268           0 : }
    5269             : 
    5270             : void
    5271           0 : bwi_rf_set_nrssi_ofs_11g(struct bwi_mac *mac)
    5272             : {
    5273             : #define SAVE_RF_MAX             2
    5274             : #define SAVE_PHY_COMM_MAX       10
    5275             : #define SAVE_PHY6_MAX           8
    5276           0 :         struct bwi_phy *phy = &mac->mac_phy;
    5277           0 :         uint16_t save_rf[SAVE_RF_MAX];
    5278           0 :         uint16_t save_phy_comm[SAVE_PHY_COMM_MAX];
    5279           0 :         uint16_t save_phy6[SAVE_PHY6_MAX];
    5280             :         uint16_t rf7b = 0xffff;
    5281             :         int16_t nrssi;
    5282             :         int i, phy6_idx = 0;
    5283             : 
    5284             :         static const uint16_t save_rf_regs[SAVE_RF_MAX] = { 0x7a, 0x43 };
    5285             :         static const uint16_t save_phy_comm_regs[SAVE_PHY_COMM_MAX] = {
    5286             :                 0x0001, 0x0811, 0x0812, 0x0814,
    5287             :                 0x0815, 0x005a, 0x0059, 0x0058,
    5288             :                 0x000a, 0x0003
    5289             :         };
    5290             :         static const uint16_t save_phy6_regs[SAVE_PHY6_MAX] = {
    5291             :                 0x002e, 0x002f, 0x080f, 0x0810,
    5292             :                 0x0801, 0x0060, 0x0014, 0x0478
    5293             :         };
    5294             : 
    5295           0 :         for (i = 0; i < SAVE_PHY_COMM_MAX; ++i)
    5296           0 :                 save_phy_comm[i] = PHY_READ(mac, save_phy_comm_regs[i]);
    5297           0 :         for (i = 0; i < SAVE_RF_MAX; ++i)
    5298           0 :                 save_rf[i] = RF_READ(mac, save_rf_regs[i]);
    5299             : 
    5300           0 :         PHY_CLRBITS(mac, 0x429, 0x8000);
    5301           0 :         PHY_FILT_SETBITS(mac, 0x1, 0x3fff, 0x4000);
    5302           0 :         PHY_SETBITS(mac, 0x811, 0xc);
    5303           0 :         PHY_FILT_SETBITS(mac, 0x812, 0xfff3, 0x4);
    5304           0 :         PHY_CLRBITS(mac, 0x802, 0x3);
    5305             : 
    5306           0 :         if (phy->phy_rev >= 6) {
    5307           0 :                 for (i = 0; i < SAVE_PHY6_MAX; ++i)
    5308           0 :                         save_phy6[i] = PHY_READ(mac, save_phy6_regs[i]);
    5309             : 
    5310           0 :                 PHY_WRITE(mac, 0x2e, 0);
    5311           0 :                 PHY_WRITE(mac, 0x2f, 0);
    5312           0 :                 PHY_WRITE(mac, 0x80f, 0);
    5313           0 :                 PHY_WRITE(mac, 0x810, 0);
    5314           0 :                 PHY_SETBITS(mac, 0x478, 0x100);
    5315           0 :                 PHY_SETBITS(mac, 0x801, 0x40);
    5316           0 :                 PHY_SETBITS(mac, 0x60, 0x40);
    5317           0 :                 PHY_SETBITS(mac, 0x14, 0x200);
    5318           0 :         }
    5319             : 
    5320           0 :         RF_SETBITS(mac, 0x7a, 0x70);
    5321           0 :         RF_SETBITS(mac, 0x7a, 0x80);
    5322             : 
    5323           0 :         DELAY(30);
    5324             : 
    5325           0 :         nrssi = bwi_nrssi_11g(mac);
    5326           0 :         if (nrssi == 31) {
    5327           0 :                 for (i = 7; i >= 4; --i) {
    5328           0 :                         RF_WRITE(mac, 0x7b, i);
    5329           0 :                         DELAY(20);
    5330           0 :                         nrssi = bwi_nrssi_11g(mac);
    5331           0 :                         if (nrssi < 31 && rf7b == 0xffff)
    5332           0 :                                 rf7b = i;
    5333             :                 }
    5334           0 :                 if (rf7b == 0xffff)
    5335           0 :                         rf7b = 4;
    5336             :         } else {
    5337           0 :                 struct bwi_gains gains;
    5338             : 
    5339           0 :                 RF_CLRBITS(mac, 0x7a, 0xff80);
    5340             : 
    5341           0 :                 PHY_SETBITS(mac, 0x814, 0x1);
    5342           0 :                 PHY_CLRBITS(mac, 0x815, 0x1);
    5343           0 :                 PHY_SETBITS(mac, 0x811, 0xc);
    5344           0 :                 PHY_SETBITS(mac, 0x812, 0xc);
    5345           0 :                 PHY_SETBITS(mac, 0x811, 0x30);
    5346           0 :                 PHY_SETBITS(mac, 0x812, 0x30);
    5347           0 :                 PHY_WRITE(mac, 0x5a, 0x480);
    5348           0 :                 PHY_WRITE(mac, 0x59, 0x810);
    5349           0 :                 PHY_WRITE(mac, 0x58, 0xd);
    5350           0 :                 if (phy->phy_version == 0)
    5351           0 :                         PHY_WRITE(mac, 0x3, 0x122);
    5352             :                 else
    5353           0 :                         PHY_SETBITS(mac, 0xa, 0x2000);
    5354           0 :                 PHY_SETBITS(mac, 0x814, 0x4);
    5355           0 :                 PHY_CLRBITS(mac, 0x815, 0x4);
    5356           0 :                 PHY_FILT_SETBITS(mac, 0x3, 0xff9f, 0x40);
    5357           0 :                 RF_SETBITS(mac, 0x7a, 0xf);
    5358             : 
    5359           0 :                 bzero(&gains, sizeof(gains));
    5360           0 :                 gains.tbl_gain1 = 3;
    5361           0 :                 gains.tbl_gain2 = 0;
    5362           0 :                 gains.phy_gain = 1;
    5363           0 :                 bwi_set_gains(mac, &gains);
    5364             : 
    5365           0 :                 RF_FILT_SETBITS(mac, 0x43, 0xf0, 0xf);
    5366           0 :                 DELAY(30);
    5367             : 
    5368           0 :                 nrssi = bwi_nrssi_11g(mac);
    5369           0 :                 if (nrssi == -32) {
    5370           0 :                         for (i = 0; i < 4; ++i) {
    5371           0 :                                 RF_WRITE(mac, 0x7b, i);
    5372           0 :                                 DELAY(20);
    5373           0 :                                 nrssi = bwi_nrssi_11g(mac);
    5374           0 :                                 if (nrssi > -31 && rf7b == 0xffff)
    5375           0 :                                         rf7b = i;
    5376             :                         }
    5377           0 :                         if (rf7b == 0xffff)
    5378           0 :                                 rf7b = 3;
    5379             :                 } else {
    5380             :                         rf7b = 0;
    5381             :                 }
    5382           0 :         }
    5383           0 :         RF_WRITE(mac, 0x7b, rf7b);
    5384             : 
    5385             :         /*
    5386             :          * Restore saved RF/PHY registers
    5387             :          */
    5388           0 :         if (phy->phy_rev >= 6) {
    5389           0 :                 for (phy6_idx = 0; phy6_idx < 4; ++phy6_idx) {
    5390           0 :                         PHY_WRITE(mac, save_phy6_regs[phy6_idx],
    5391             :                             save_phy6[phy6_idx]);
    5392             :                 }
    5393             :         }
    5394             : 
    5395             :         /* Saved PHY registers 0, 1, 2 are handled later */
    5396           0 :         for (i = 3; i < SAVE_PHY_COMM_MAX; ++i)
    5397           0 :                 PHY_WRITE(mac, save_phy_comm_regs[i], save_phy_comm[i]);
    5398             : 
    5399           0 :         for (i = SAVE_RF_MAX - 1; i >= 0; --i)
    5400           0 :                 RF_WRITE(mac, save_rf_regs[i], save_rf[i]);
    5401             : 
    5402           0 :         PHY_SETBITS(mac, 0x802, 0x3);
    5403           0 :         PHY_SETBITS(mac, 0x429, 0x8000);
    5404             : 
    5405           0 :         bwi_set_gains(mac, NULL);
    5406             : 
    5407           0 :         if (phy->phy_rev >= 6) {
    5408           0 :                 for (; phy6_idx < SAVE_PHY6_MAX; ++phy6_idx) {
    5409           0 :                         PHY_WRITE(mac, save_phy6_regs[phy6_idx],
    5410             :                             save_phy6[phy6_idx]);
    5411             :                 }
    5412             :         }
    5413             : 
    5414           0 :         PHY_WRITE(mac, save_phy_comm_regs[0], save_phy_comm[0]);
    5415           0 :         PHY_WRITE(mac, save_phy_comm_regs[2], save_phy_comm[2]);
    5416           0 :         PHY_WRITE(mac, save_phy_comm_regs[1], save_phy_comm[1]);
    5417             : 
    5418             : #undef SAVE_RF_MAX
    5419             : #undef SAVE_PHY_COMM_MAX
    5420             : #undef SAVE_PHY6_MAX
    5421           0 : }
    5422             : 
    5423             : void
    5424           0 : bwi_rf_calc_nrssi_slope_11g(struct bwi_mac *mac)
    5425             : {
    5426             : #define SAVE_RF_MAX             3
    5427             : #define SAVE_PHY_COMM_MAX       4
    5428             : #define SAVE_PHY3_MAX           8
    5429           0 :         struct bwi_softc *sc = mac->mac_sc;
    5430           0 :         struct bwi_phy *phy = &mac->mac_phy;
    5431           0 :         struct bwi_rf *rf = &mac->mac_rf;
    5432           0 :         uint16_t save_rf[SAVE_RF_MAX];
    5433           0 :         uint16_t save_phy_comm[SAVE_PHY_COMM_MAX];
    5434           0 :         uint16_t save_phy3[SAVE_PHY3_MAX];
    5435             :         uint16_t ant_div, bbp_atten, chan_ex;
    5436           0 :         struct bwi_gains gains;
    5437             :         int16_t nrssi[2];
    5438             :         int i, phy3_idx = 0;
    5439             : 
    5440             :         static const uint16_t save_rf_regs[SAVE_RF_MAX] =
    5441             :             { 0x7a, 0x52, 0x43 };
    5442             :         static const uint16_t save_phy_comm_regs[SAVE_PHY_COMM_MAX] =
    5443             :             { 0x15, 0x5a, 0x59, 0x58 };
    5444             :         static const uint16_t save_phy3_regs[SAVE_PHY3_MAX] = {
    5445             :                 0x002e, 0x002f, 0x080f, 0x0810,
    5446             :                 0x0801, 0x0060, 0x0014, 0x0478
    5447             :         };
    5448             : 
    5449           0 :         if (rf->rf_rev >= 9)
    5450           0 :                 return;
    5451           0 :         else if (rf->rf_rev == 8)
    5452           0 :                 bwi_rf_set_nrssi_ofs_11g(mac);
    5453             : 
    5454           0 :         PHY_CLRBITS(mac, 0x429, 0x8000);
    5455           0 :         PHY_CLRBITS(mac, 0x802, 0x3);
    5456             : 
    5457             :         /*
    5458             :          * Save RF/PHY registers for later restoration
    5459             :          */
    5460           0 :         ant_div = CSR_READ_2(sc, BWI_RF_ANTDIV);
    5461           0 :         CSR_SETBITS_2(sc, BWI_RF_ANTDIV, 0x8000);
    5462             : 
    5463           0 :         for (i = 0; i < SAVE_RF_MAX; ++i)
    5464           0 :                 save_rf[i] = RF_READ(mac, save_rf_regs[i]);
    5465           0 :         for (i = 0; i < SAVE_PHY_COMM_MAX; ++i)
    5466           0 :                 save_phy_comm[i] = PHY_READ(mac, save_phy_comm_regs[i]);
    5467             : 
    5468           0 :         bbp_atten = CSR_READ_2(sc, BWI_BBP_ATTEN);
    5469           0 :         chan_ex = CSR_READ_2(sc, BWI_RF_CHAN_EX);
    5470             : 
    5471           0 :         if (phy->phy_rev >= 3) {
    5472           0 :                 for (i = 0; i < SAVE_PHY3_MAX; ++i)
    5473           0 :                         save_phy3[i] = PHY_READ(mac, save_phy3_regs[i]);
    5474             : 
    5475           0 :                 PHY_WRITE(mac, 0x2e, 0);
    5476           0 :                 PHY_WRITE(mac, 0x810, 0);
    5477             : 
    5478           0 :                 if (phy->phy_rev == 4 || phy->phy_rev == 6 ||
    5479           0 :                     phy->phy_rev == 7) {
    5480           0 :                         PHY_SETBITS(mac, 0x478, 0x100);
    5481           0 :                         PHY_SETBITS(mac, 0x810, 0x40);
    5482           0 :                 } else if (phy->phy_rev == 3 || phy->phy_rev == 5)
    5483           0 :                         PHY_CLRBITS(mac, 0x810, 0x40);
    5484             : 
    5485           0 :                 PHY_SETBITS(mac, 0x60, 0x40);
    5486           0 :                 PHY_SETBITS(mac, 0x14, 0x200);
    5487           0 :         }
    5488             : 
    5489             :         /*
    5490             :          * Calculate nrssi0
    5491             :          */
    5492           0 :         RF_SETBITS(mac, 0x7a, 0x70);
    5493             : 
    5494           0 :         bzero(&gains, sizeof(gains));
    5495           0 :         gains.tbl_gain1 = 0;
    5496           0 :         gains.tbl_gain2 = 8;
    5497           0 :         gains.phy_gain = 0;
    5498           0 :         bwi_set_gains(mac, &gains);
    5499             : 
    5500           0 :         RF_CLRBITS(mac, 0x7a, 0xff08);
    5501           0 :         if (phy->phy_rev >= 2) {
    5502           0 :                 PHY_FILT_SETBITS(mac, 0x811, 0xffcf, 0x30);
    5503           0 :                 PHY_FILT_SETBITS(mac, 0x812, 0xffcf, 0x10);
    5504           0 :         }
    5505             : 
    5506           0 :         RF_SETBITS(mac, 0x7a, 0x80);
    5507           0 :         DELAY(20);
    5508           0 :         nrssi[0] = bwi_nrssi_11g(mac);
    5509             : 
    5510             :         /*
    5511             :          * Calculate nrssi1
    5512             :          */
    5513           0 :         RF_CLRBITS(mac, 0x7a, 0xff80);
    5514           0 :         if (phy->phy_version >= 2)
    5515           0 :                 PHY_FILT_SETBITS(mac, 0x3, 0xff9f, 0x40);
    5516           0 :         CSR_SETBITS_2(sc, BWI_RF_CHAN_EX, 0x2000);
    5517             : 
    5518           0 :         RF_SETBITS(mac, 0x7a, 0xf);
    5519           0 :         PHY_WRITE(mac, 0x15, 0xf330);
    5520           0 :         if (phy->phy_rev >= 2) {
    5521           0 :                 PHY_FILT_SETBITS(mac, 0x812, 0xffcf, 0x20);
    5522           0 :                 PHY_FILT_SETBITS(mac, 0x811, 0xffcf, 0x20);
    5523           0 :         }
    5524             : 
    5525           0 :         bzero(&gains, sizeof(gains));
    5526           0 :         gains.tbl_gain1 = 3;
    5527           0 :         gains.tbl_gain2 = 0;
    5528           0 :         gains.phy_gain = 1;
    5529           0 :         bwi_set_gains(mac, &gains);
    5530             : 
    5531           0 :         if (rf->rf_rev == 8) {
    5532           0 :                 RF_WRITE(mac, 0x43, 0x1f);
    5533           0 :         } else {
    5534           0 :                 RF_FILT_SETBITS(mac, 0x52, 0xff0f, 0x60);
    5535           0 :                 RF_FILT_SETBITS(mac, 0x43, 0xfff0, 0x9);
    5536             :         }
    5537           0 :         PHY_WRITE(mac, 0x5a, 0x480);
    5538           0 :         PHY_WRITE(mac, 0x59, 0x810);
    5539           0 :         PHY_WRITE(mac, 0x58, 0xd);
    5540           0 :         DELAY(20);
    5541             : 
    5542           0 :         nrssi[1] = bwi_nrssi_11g(mac);
    5543             : 
    5544             :         /*
    5545             :          * Install calculated narrow RSSI values
    5546             :          */
    5547           0 :         if (nrssi[1] == nrssi[0])
    5548           0 :                 rf->rf_nrssi_slope = 0x10000;
    5549             :         else
    5550           0 :                 rf->rf_nrssi_slope = 0x400000 / (nrssi[0] - nrssi[1]);
    5551           0 :         if (nrssi[0] >= -4) {
    5552           0 :                 rf->rf_nrssi[0] = nrssi[1];
    5553           0 :                 rf->rf_nrssi[1] = nrssi[0];
    5554           0 :         }
    5555             : 
    5556             :         /*
    5557             :          * Restore saved RF/PHY registers
    5558             :          */
    5559           0 :         if (phy->phy_rev >= 3) {
    5560           0 :                 for (phy3_idx = 0; phy3_idx < 4; ++phy3_idx) {
    5561           0 :                         PHY_WRITE(mac, save_phy3_regs[phy3_idx],
    5562             :                                   save_phy3[phy3_idx]);
    5563             :                 }
    5564             :         }
    5565           0 :         if (phy->phy_rev >= 2) {
    5566           0 :                 PHY_CLRBITS(mac, 0x812, 0x30);
    5567           0 :                 PHY_CLRBITS(mac, 0x811, 0x30);
    5568           0 :         }
    5569             : 
    5570           0 :         for (i = 0; i < SAVE_RF_MAX; ++i)
    5571           0 :                 RF_WRITE(mac, save_rf_regs[i], save_rf[i]);
    5572             : 
    5573           0 :         CSR_WRITE_2(sc, BWI_RF_ANTDIV, ant_div);
    5574           0 :         CSR_WRITE_2(sc, BWI_BBP_ATTEN, bbp_atten);
    5575           0 :         CSR_WRITE_2(sc, BWI_RF_CHAN_EX, chan_ex);
    5576             : 
    5577           0 :         for (i = 0; i < SAVE_PHY_COMM_MAX; ++i)
    5578           0 :                 PHY_WRITE(mac, save_phy_comm_regs[i], save_phy_comm[i]);
    5579             : 
    5580           0 :         bwi_rf_workaround(mac, rf->rf_curchan);
    5581           0 :         PHY_SETBITS(mac, 0x802, 0x3);
    5582           0 :         bwi_set_gains(mac, NULL);
    5583           0 :         PHY_SETBITS(mac, 0x429, 0x8000);
    5584             : 
    5585           0 :         if (phy->phy_rev >= 3) {
    5586           0 :                 for (; phy3_idx < SAVE_PHY3_MAX; ++phy3_idx) {
    5587           0 :                         PHY_WRITE(mac, save_phy3_regs[phy3_idx],
    5588             :                             save_phy3[phy3_idx]);
    5589             :                 }
    5590             :         }
    5591             : 
    5592           0 :         bwi_rf_init_sw_nrssi_table(mac);
    5593           0 :         bwi_rf_set_nrssi_thr_11g(mac);
    5594             : 
    5595             : #undef SAVE_RF_MAX
    5596             : #undef SAVE_PHY_COMM_MAX
    5597             : #undef SAVE_PHY3_MAX
    5598           0 : }
    5599             : 
    5600             : void
    5601           0 : bwi_rf_init_sw_nrssi_table(struct bwi_mac *mac)
    5602             : {
    5603           0 :         struct bwi_rf *rf = &mac->mac_rf;
    5604             :         int d, i;
    5605             : 
    5606           0 :         d = 0x1f - rf->rf_nrssi[0];
    5607           0 :         for (i = 0; i < BWI_NRSSI_TBLSZ; ++i) {
    5608             :                 int val;
    5609             : 
    5610           0 :                 val = (((i - d) * rf->rf_nrssi_slope) / 0x10000) + 0x3a;
    5611           0 :                 if (val < 0)
    5612           0 :                         val = 0;
    5613           0 :                 else if (val > 0x3f)
    5614           0 :                         val = 0x3f;
    5615             : 
    5616           0 :                 rf->rf_nrssi_table[i] = val;
    5617             :         }
    5618           0 : }
    5619             : 
    5620             : void
    5621           0 : bwi_rf_init_hw_nrssi_table(struct bwi_mac *mac, uint16_t adjust)
    5622             : {
    5623             :         int i;
    5624             : 
    5625           0 :         for (i = 0; i < BWI_NRSSI_TBLSZ; ++i) {
    5626             :                 int16_t val;
    5627             : 
    5628           0 :                 val = bwi_nrssi_read(mac, i);
    5629             : 
    5630           0 :                 val -= adjust;
    5631           0 :                 if (val < -32)
    5632           0 :                         val = -32;
    5633           0 :                 else if (val > 31)
    5634           0 :                         val = 31;
    5635             : 
    5636           0 :                 bwi_nrssi_write(mac, i, val);
    5637             :         }
    5638           0 : }
    5639             : 
    5640             : void
    5641           0 : bwi_rf_set_nrssi_thr_11b(struct bwi_mac *mac)
    5642             : {
    5643           0 :         struct bwi_rf *rf = &mac->mac_rf;
    5644             :         int32_t thr;
    5645             : 
    5646           0 :         if (rf->rf_type != BWI_RF_T_BCM2050 ||
    5647           0 :             (mac->mac_sc->sc_card_flags & BWI_CARD_F_SW_NRSSI) == 0)
    5648           0 :                 return;
    5649             : 
    5650             :         /*
    5651             :          * Calculate nrssi threshold
    5652             :          */
    5653           0 :         if (rf->rf_rev >= 6) {
    5654           0 :                 thr = (rf->rf_nrssi[1] - rf->rf_nrssi[0]) * 32;
    5655           0 :                 thr += 20 * (rf->rf_nrssi[0] + 1);
    5656           0 :                 thr /= 40;
    5657           0 :         } else {
    5658           0 :                 thr = rf->rf_nrssi[1] - 5;
    5659             :         }
    5660           0 :         if (thr < 0)
    5661           0 :                 thr = 0;
    5662           0 :         else if (thr > 0x3e)
    5663           0 :                 thr = 0x3e;
    5664             : 
    5665           0 :         PHY_READ(mac, BWI_PHYR_NRSSI_THR_11B);  /* dummy read */
    5666           0 :         PHY_WRITE(mac, BWI_PHYR_NRSSI_THR_11B, (((uint16_t)thr) << 8) | 0x1c);
    5667             : 
    5668           0 :         if (rf->rf_rev >= 6) {
    5669           0 :                 PHY_WRITE(mac, 0x87, 0xe0d);
    5670           0 :                 PHY_WRITE(mac, 0x86, 0xc0b);
    5671           0 :                 PHY_WRITE(mac, 0x85, 0xa09);
    5672           0 :                 PHY_WRITE(mac, 0x84, 0x808);
    5673           0 :                 PHY_WRITE(mac, 0x83, 0x808);
    5674           0 :                 PHY_WRITE(mac, 0x82, 0x604);
    5675           0 :                 PHY_WRITE(mac, 0x81, 0x302);
    5676           0 :                 PHY_WRITE(mac, 0x80, 0x100);
    5677           0 :         }
    5678           0 : }
    5679             : 
    5680             : int32_t
    5681           0 : _nrssi_threshold(const struct bwi_rf *rf, int32_t val)
    5682             : {
    5683           0 :         val *= (rf->rf_nrssi[1] - rf->rf_nrssi[0]);
    5684           0 :         val += (rf->rf_nrssi[0] << 6);
    5685           0 :         if (val < 32)
    5686           0 :                 val += 31;
    5687             :         else
    5688           0 :                 val += 32;
    5689           0 :         val >>= 6;
    5690           0 :         if (val < -31)
    5691           0 :                 val = -31;
    5692           0 :         else if (val > 31)
    5693           0 :                 val = 31;
    5694             : 
    5695           0 :         return (val);
    5696             : }
    5697             : 
    5698             : void
    5699           0 : bwi_rf_set_nrssi_thr_11g(struct bwi_mac *mac)
    5700             : {
    5701             :         int32_t thr1, thr2;
    5702             :         uint16_t thr;
    5703             : 
    5704             :         /*
    5705             :          * Find the two nrssi thresholds
    5706             :          */
    5707           0 :         if ((mac->mac_phy.phy_flags & BWI_PHY_F_LINKED) == 0 ||
    5708           0 :             (mac->mac_sc->sc_card_flags & BWI_CARD_F_SW_NRSSI) == 0) {
    5709             :                 int16_t nrssi;
    5710             : 
    5711           0 :                 nrssi = bwi_nrssi_read(mac, 0x20);
    5712           0 :                 if (nrssi >= 32)
    5713           0 :                         nrssi -= 64;
    5714             : 
    5715           0 :                 if (nrssi < 3) {
    5716             :                         thr1 = 0x2b;
    5717             :                         thr2 = 0x27;
    5718           0 :                 } else {
    5719             :                         thr1 = 0x2d;
    5720             :                         thr2 = 0x2b;
    5721             :                 }
    5722           0 :         } else {
    5723             :                 /* TODO Interfere mode */
    5724           0 :                 thr1 = _nrssi_threshold(&mac->mac_rf, 0x11);
    5725           0 :                 thr2 = _nrssi_threshold(&mac->mac_rf, 0xe);
    5726             :         }
    5727             : 
    5728             : #define NRSSI_THR1_MASK         0x003f
    5729             : #define NRSSI_THR2_MASK         0x0fc0
    5730           0 :         thr = __SHIFTIN((uint32_t)thr1, NRSSI_THR1_MASK) |
    5731           0 :             __SHIFTIN((uint32_t)thr2, NRSSI_THR2_MASK);
    5732           0 :         PHY_FILT_SETBITS(mac, BWI_PHYR_NRSSI_THR_11G, 0xf000, thr);
    5733             : #undef NRSSI_THR1_MASK
    5734             : #undef NRSSI_THR2_MASK
    5735           0 : }
    5736             : 
    5737             : void
    5738           0 : bwi_rf_clear_tssi(struct bwi_mac *mac)
    5739             : {
    5740             :         /* XXX use function pointer */
    5741           0 :         if (mac->mac_phy.phy_mode == IEEE80211_MODE_11A) {
    5742             :                 /* TODO: 11A */
    5743             :         } else {
    5744             :                 uint16_t val;
    5745             :                 int i;
    5746             : 
    5747             :                 val = __SHIFTIN(BWI_INVALID_TSSI, BWI_LO_TSSI_MASK) |
    5748             :                     __SHIFTIN(BWI_INVALID_TSSI, BWI_HI_TSSI_MASK);
    5749             : 
    5750           0 :                 for (i = 0; i < 2; ++i) {
    5751           0 :                         MOBJ_WRITE_2(mac, BWI_COMM_MOBJ,
    5752             :                             BWI_COMM_MOBJ_TSSI_DS + (i * 2), val);
    5753             :                 }
    5754             : 
    5755           0 :                 for (i = 0; i < 2; ++i) {
    5756           0 :                         MOBJ_WRITE_2(mac, BWI_COMM_MOBJ,
    5757             :                             BWI_COMM_MOBJ_TSSI_OFDM + (i * 2), val);
    5758             :                 }
    5759             :         }
    5760           0 : }
    5761             : 
    5762             : void
    5763           0 : bwi_rf_clear_state(struct bwi_rf *rf)
    5764             : {
    5765             :         int i;
    5766             : 
    5767           0 :         rf->rf_flags &= ~BWI_RF_CLEAR_FLAGS;
    5768           0 :         bzero(rf->rf_lo, sizeof(rf->rf_lo));
    5769           0 :         bzero(rf->rf_lo_used, sizeof(rf->rf_lo_used));
    5770             : 
    5771           0 :         rf->rf_nrssi_slope = 0;
    5772           0 :         rf->rf_nrssi[0] = BWI_INVALID_NRSSI;
    5773           0 :         rf->rf_nrssi[1] = BWI_INVALID_NRSSI;
    5774             : 
    5775           0 :         for (i = 0; i < BWI_NRSSI_TBLSZ; ++i)
    5776           0 :                 rf->rf_nrssi_table[i] = i;
    5777             : 
    5778           0 :         rf->rf_lo_gain = 0;
    5779           0 :         rf->rf_rx_gain = 0;
    5780             : 
    5781           0 :         bcopy(rf->rf_txpower_map0, rf->rf_txpower_map,
    5782             :               sizeof(rf->rf_txpower_map));
    5783           0 :         rf->rf_idle_tssi = rf->rf_idle_tssi0;
    5784           0 : }
    5785             : 
    5786             : void
    5787           0 : bwi_rf_on_11a(struct bwi_mac *mac)
    5788             : {
    5789             :         /* TODO: 11A */
    5790           0 : }
    5791             : 
    5792             : void
    5793           0 : bwi_rf_on_11bg(struct bwi_mac *mac)
    5794             : {
    5795           0 :         struct bwi_phy *phy = &mac->mac_phy;
    5796             : 
    5797           0 :         PHY_WRITE(mac, 0x15, 0x8000);
    5798           0 :         PHY_WRITE(mac, 0x15, 0xcc00);
    5799           0 :         if (phy->phy_flags & BWI_PHY_F_LINKED)
    5800           0 :                 PHY_WRITE(mac, 0x15, 0xc0);
    5801             :         else
    5802           0 :                 PHY_WRITE(mac, 0x15, 0);
    5803             : 
    5804           0 :         bwi_rf_set_chan(mac, 6 /* XXX */, 1);
    5805           0 : }
    5806             : 
    5807             : void
    5808           0 : bwi_rf_set_ant_mode(struct bwi_mac *mac, int ant_mode)
    5809             : {
    5810           0 :         struct bwi_softc *sc = mac->mac_sc;
    5811           0 :         struct bwi_phy *phy = &mac->mac_phy;
    5812             :         uint16_t val;
    5813             : 
    5814           0 :         KASSERT(ant_mode == BWI_ANT_MODE_0 ||
    5815             :             ant_mode == BWI_ANT_MODE_1 ||
    5816             :             ant_mode == BWI_ANT_MODE_AUTO);
    5817             : 
    5818           0 :         HFLAGS_CLRBITS(mac, BWI_HFLAG_AUTO_ANTDIV);
    5819             : 
    5820           0 :         if (phy->phy_mode == IEEE80211_MODE_11B) {
    5821             :                 /* NOTE: v4/v3 conflicts, take v3 */
    5822           0 :                 if (mac->mac_rev == 2)
    5823           0 :                         val = BWI_ANT_MODE_AUTO;
    5824             :                 else
    5825           0 :                         val = ant_mode;
    5826           0 :                 val <<= 7;
    5827           0 :                 PHY_FILT_SETBITS(mac, 0x3e2, 0xfe7f, val);
    5828           0 :         } else {        /* 11a/g */
    5829             :                 /* XXX reg/value naming */
    5830           0 :                 val = ant_mode << 7;
    5831           0 :                 PHY_FILT_SETBITS(mac, 0x401, 0x7e7f, val);
    5832             : 
    5833           0 :                 if (ant_mode == BWI_ANT_MODE_AUTO)
    5834           0 :                         PHY_CLRBITS(mac, 0x42b, 0x100);
    5835             : 
    5836           0 :                 if (phy->phy_mode == IEEE80211_MODE_11A) {
    5837             :                         /* TODO: 11A */
    5838             :                 } else {        /* 11g */
    5839           0 :                         if (ant_mode == BWI_ANT_MODE_AUTO)
    5840           0 :                                 PHY_SETBITS(mac, 0x48c, 0x2000);
    5841             :                         else
    5842           0 :                                 PHY_CLRBITS(mac, 0x48c, 0x2000);
    5843             : 
    5844           0 :                         if (phy->phy_rev >= 2) {
    5845           0 :                                 PHY_SETBITS(mac, 0x461, 0x10);
    5846           0 :                                 PHY_FILT_SETBITS(mac, 0x4ad, 0xff00, 0x15);
    5847           0 :                                 if (phy->phy_rev == 2) {
    5848           0 :                                         PHY_WRITE(mac, 0x427, 0x8);
    5849           0 :                                 } else {
    5850           0 :                                         PHY_FILT_SETBITS(mac, 0x427,
    5851             :                                                          0xff00, 0x8);
    5852             :                                 }
    5853             : 
    5854           0 :                                 if (phy->phy_rev >= 6)
    5855           0 :                                         PHY_WRITE(mac, 0x49b, 0xdc);
    5856             :                         }
    5857             :                 }
    5858             :         }
    5859             : 
    5860             :         /* XXX v4 set AUTO_ANTDIV unconditionally */
    5861           0 :         if (ant_mode == BWI_ANT_MODE_AUTO)
    5862           0 :                 HFLAGS_SETBITS(mac, BWI_HFLAG_AUTO_ANTDIV);
    5863             : 
    5864           0 :         val = ant_mode << 8;
    5865           0 :         MOBJ_FILT_SETBITS_2(mac, BWI_COMM_MOBJ, BWI_COMM_MOBJ_TX_BEACON,
    5866             :             0xfc3f, val);
    5867           0 :         MOBJ_FILT_SETBITS_2(mac, BWI_COMM_MOBJ, BWI_COMM_MOBJ_TX_ACK,
    5868             :             0xfc3f, val);
    5869           0 :         MOBJ_FILT_SETBITS_2(mac, BWI_COMM_MOBJ, BWI_COMM_MOBJ_TX_PROBE_RESP,
    5870             :             0xfc3f, val);
    5871             : 
    5872             :         /* XXX what's these */
    5873           0 :         if (phy->phy_mode == IEEE80211_MODE_11B)
    5874           0 :                 CSR_SETBITS_2(sc, 0x5e, 0x4);
    5875             : 
    5876           0 :         CSR_WRITE_4(sc, 0x100, 0x1000000);
    5877           0 :         if (mac->mac_rev < 5)
    5878           0 :                 CSR_WRITE_4(sc, 0x10c, 0x1000000);
    5879             : 
    5880           0 :         mac->mac_rf.rf_ant_mode = ant_mode;
    5881           0 : }
    5882             : 
    5883             : int
    5884           0 : bwi_rf_get_latest_tssi(struct bwi_mac *mac, int8_t tssi[], uint16_t ofs)
    5885             : {
    5886             :         int i;
    5887             : 
    5888           0 :         for (i = 0; i < 4; ) {
    5889             :                 uint16_t val;
    5890             : 
    5891           0 :                 val = MOBJ_READ_2(mac, BWI_COMM_MOBJ, ofs + i);
    5892           0 :                 tssi[i++] = (int8_t)__SHIFTOUT(val, BWI_LO_TSSI_MASK);
    5893           0 :                 tssi[i++] = (int8_t)__SHIFTOUT(val, BWI_HI_TSSI_MASK);
    5894             :         }
    5895             : 
    5896           0 :         for (i = 0; i < 4; ++i) {
    5897           0 :                 if (tssi[i] == BWI_INVALID_TSSI)
    5898           0 :                         return (EINVAL);
    5899             :         }
    5900             : 
    5901           0 :         return (0);
    5902           0 : }
    5903             : 
    5904             : int
    5905           0 : bwi_rf_tssi2dbm(struct bwi_mac *mac, int8_t tssi, int8_t *txpwr)
    5906             : {
    5907           0 :         struct bwi_rf *rf = &mac->mac_rf;
    5908             :         int pwr_idx;
    5909             : 
    5910           0 :         pwr_idx = rf->rf_idle_tssi + (int)tssi - rf->rf_base_tssi;
    5911             : #if 0
    5912             :         if (pwr_idx < 0 || pwr_idx >= BWI_TSSI_MAX)
    5913             :                 return EINVAL;
    5914             : #else
    5915           0 :         if (pwr_idx < 0)
    5916           0 :                 pwr_idx = 0;
    5917           0 :         else if (pwr_idx >= BWI_TSSI_MAX)
    5918           0 :                 pwr_idx = BWI_TSSI_MAX - 1;
    5919             : #endif
    5920           0 :         *txpwr = rf->rf_txpower_map[pwr_idx];
    5921             : 
    5922           0 :         return (0);
    5923             : }
    5924             : 
    5925             : int
    5926           0 : bwi_rf_calc_rssi_bcm2050(struct bwi_mac *mac, const struct bwi_rxbuf_hdr *hdr)
    5927             : {
    5928             :         uint16_t flags1, flags3;
    5929             :         int rssi, lna_gain;
    5930             : 
    5931           0 :         rssi = hdr->rxh_rssi;
    5932           0 :         flags1 = letoh16(hdr->rxh_flags1);
    5933           0 :         flags3 = letoh16(hdr->rxh_flags3);
    5934             : 
    5935             : #define NEW_BCM2050_RSSI
    5936             : #ifdef NEW_BCM2050_RSSI
    5937           0 :         if (flags1 & BWI_RXH_F1_OFDM) {
    5938           0 :                 if (rssi > 127)
    5939           0 :                         rssi -= 256;
    5940           0 :                 if (flags3 & BWI_RXH_F3_BCM2050_RSSI)
    5941           0 :                         rssi += 17;
    5942             :                 else
    5943           0 :                         rssi -= 4;
    5944           0 :                 return (rssi);
    5945             :         }
    5946             : 
    5947           0 :         if (mac->mac_sc->sc_card_flags & BWI_CARD_F_SW_NRSSI) {
    5948           0 :                 struct bwi_rf *rf = &mac->mac_rf;
    5949             : 
    5950           0 :                 if (rssi >= BWI_NRSSI_TBLSZ)
    5951           0 :                         rssi = BWI_NRSSI_TBLSZ - 1;
    5952             : 
    5953           0 :                 rssi = ((31 - (int)rf->rf_nrssi_table[rssi]) * -131) / 128;
    5954           0 :                 rssi -= 67;
    5955           0 :         } else {
    5956           0 :                 rssi = ((31 - rssi) * -149) / 128;
    5957           0 :                 rssi -= 68;
    5958             :         }
    5959             : 
    5960           0 :         if (mac->mac_phy.phy_mode != IEEE80211_MODE_11G)
    5961           0 :                 return (rssi);
    5962             : 
    5963           0 :         if (flags3 & BWI_RXH_F3_BCM2050_RSSI)
    5964           0 :                 rssi += 20;
    5965             : 
    5966           0 :         lna_gain = __SHIFTOUT(letoh16(hdr->rxh_phyinfo),
    5967             :             BWI_RXH_PHYINFO_LNAGAIN);
    5968             :         DPRINTF(3, "lna_gain %d, phyinfo 0x%04x\n",
    5969             :             lna_gain, letoh16(hdr->rxh_phyinfo));
    5970           0 :         switch (lna_gain) {
    5971             :         case 0:
    5972           0 :                 rssi += 27;
    5973           0 :                 break;
    5974             :         case 1:
    5975           0 :                 rssi += 6;
    5976           0 :                 break;
    5977             :         case 2:
    5978           0 :                 rssi += 12;
    5979           0 :                 break;
    5980             :         case 3:
    5981             :                 /*
    5982             :                  * XXX
    5983             :                  * According to v3 spec, we should do _nothing_ here,
    5984             :                  * but it seems that the result RSSI will be too low
    5985             :                  * (relative to what ath(4) says).  Raise it a little
    5986             :                  * bit.
    5987             :                  */
    5988           0 :                 rssi += 5;
    5989           0 :                 break;
    5990             :         default:
    5991           0 :                 panic("impossible lna gain %d", lna_gain);
    5992             :         }
    5993             : #else   /* !NEW_BCM2050_RSSI */
    5994             :         lna_gain = 0; /* shut up gcc warning */
    5995             : 
    5996             :         if (flags1 & BWI_RXH_F1_OFDM) {
    5997             :                 if (rssi > 127)
    5998             :                         rssi -= 256;
    5999             :                 rssi = (rssi * 73) / 64;
    6000             : 
    6001             :                 if (flags3 & BWI_RXH_F3_BCM2050_RSSI)
    6002             :                         rssi += 25;
    6003             :                 else
    6004             :                         rssi -= 3;
    6005             :                 return (rssi);
    6006             :         }
    6007             : 
    6008             :         if (mac->mac_sc->sc_card_flags & BWI_CARD_F_SW_NRSSI) {
    6009             :                 struct bwi_rf *rf = &mac->mac_rf;
    6010             : 
    6011             :                 if (rssi >= BWI_NRSSI_TBLSZ)
    6012             :                         rssi = BWI_NRSSI_TBLSZ - 1;
    6013             : 
    6014             :                 rssi = ((31 - (int)rf->rf_nrssi_table[rssi]) * -131) / 128;
    6015             :                 rssi -= 57;
    6016             :         } else {
    6017             :                 rssi = ((31 - rssi) * -149) / 128;
    6018             :                 rssi -= 68;
    6019             :         }
    6020             : 
    6021             :         if (mac->mac_phy.phy_mode != IEEE80211_MODE_11G)
    6022             :                 return (rssi);
    6023             : 
    6024             :         if (flags3 & BWI_RXH_F3_BCM2050_RSSI)
    6025             :                 rssi += 25;
    6026             : #endif  /* NEW_BCM2050_RSSI */
    6027           0 :         return (rssi);
    6028           0 : }
    6029             : 
    6030             : int
    6031           0 : bwi_rf_calc_rssi_bcm2053(struct bwi_mac *mac, const struct bwi_rxbuf_hdr *hdr)
    6032             : {
    6033             :         uint16_t flags1;
    6034             :         int rssi;
    6035             : 
    6036           0 :         rssi = (((int)hdr->rxh_rssi - 11) * 103) / 64;
    6037             : 
    6038           0 :         flags1 = letoh16(hdr->rxh_flags1);
    6039           0 :         if (flags1 & BWI_RXH_F1_BCM2053_RSSI)
    6040           0 :                 rssi -= 109;
    6041             :         else
    6042           0 :                 rssi -= 83;
    6043             : 
    6044           0 :         return (rssi);
    6045             : }
    6046             : 
    6047             : int
    6048           0 : bwi_rf_calc_rssi_bcm2060(struct bwi_mac *mac, const struct bwi_rxbuf_hdr *hdr)
    6049             : {
    6050             :         int rssi;
    6051             : 
    6052           0 :         rssi = hdr->rxh_rssi;
    6053           0 :         if (rssi > 127)
    6054           0 :                 rssi -= 256;
    6055             : 
    6056           0 :         return (rssi);
    6057             : }
    6058             : 
    6059             : uint16_t
    6060           0 : bwi_rf_lo_measure_11b(struct bwi_mac *mac)
    6061             : {
    6062             :         uint16_t val;
    6063             :         int i;
    6064             : 
    6065             :         val = 0;
    6066           0 :         for (i = 0; i < 10; ++i) {
    6067           0 :                 PHY_WRITE(mac, 0x15, 0xafa0);
    6068           0 :                 DELAY(1);
    6069           0 :                 PHY_WRITE(mac, 0x15, 0xefa0);
    6070           0 :                 DELAY(10);
    6071           0 :                 PHY_WRITE(mac, 0x15, 0xffa0);
    6072           0 :                 DELAY(40);
    6073             : 
    6074           0 :                 val += PHY_READ(mac, 0x2c);
    6075             :         }
    6076             : 
    6077           0 :         return (val);
    6078             : }
    6079             : 
    6080             : void
    6081           0 : bwi_rf_lo_update_11b(struct bwi_mac *mac)
    6082             : {
    6083           0 :         struct bwi_softc *sc = mac->mac_sc;
    6084           0 :         struct bwi_rf *rf = &mac->mac_rf;
    6085           0 :         struct rf_saveregs regs;
    6086             :         uint16_t rf_val, phy_val, min_val, val;
    6087             :         uint16_t rf52, bphy_ctrl;
    6088             :         int i;
    6089             : 
    6090             :         DPRINTF(1, "%s: %s\n", sc->sc_dev.dv_xname, __func__);
    6091             : 
    6092           0 :         bzero(&regs, sizeof(regs));
    6093             :         bphy_ctrl = 0;
    6094             : 
    6095             :         /*
    6096             :          * Save RF/PHY registers for later restoration
    6097             :          */
    6098           0 :         SAVE_PHY_REG(mac, &regs, 15);
    6099           0 :         rf52 = RF_READ(mac, 0x52) & 0xfff0;
    6100           0 :         if (rf->rf_type == BWI_RF_T_BCM2050) {
    6101           0 :                 SAVE_PHY_REG(mac, &regs, 0a);
    6102           0 :                 SAVE_PHY_REG(mac, &regs, 2a);
    6103           0 :                 SAVE_PHY_REG(mac, &regs, 35);
    6104           0 :                 SAVE_PHY_REG(mac, &regs, 03);
    6105           0 :                 SAVE_PHY_REG(mac, &regs, 01);
    6106           0 :                 SAVE_PHY_REG(mac, &regs, 30);
    6107             : 
    6108           0 :                 SAVE_RF_REG(mac, &regs, 43);
    6109           0 :                 SAVE_RF_REG(mac, &regs, 7a);
    6110             : 
    6111           0 :                 bphy_ctrl = CSR_READ_2(sc, BWI_BPHY_CTRL);
    6112             : 
    6113           0 :                 SAVE_RF_REG(mac, &regs, 52);
    6114           0 :                 regs.rf_52 &= 0xf0;
    6115             : 
    6116           0 :                 PHY_WRITE(mac, 0x30, 0xff);
    6117           0 :                 CSR_WRITE_2(sc, BWI_PHY_CTRL, 0x3f3f);
    6118           0 :                 PHY_WRITE(mac, 0x35, regs.phy_35 & 0xff7f);
    6119           0 :                 RF_WRITE(mac, 0x7a, regs.rf_7a & 0xfff0);
    6120           0 :         }
    6121             : 
    6122           0 :         PHY_WRITE(mac, 0x15, 0xb000);
    6123             : 
    6124           0 :         if (rf->rf_type == BWI_RF_T_BCM2050) {
    6125           0 :                 PHY_WRITE(mac, 0x2b, 0x203);
    6126           0 :                 PHY_WRITE(mac, 0x2a, 0x8a3);
    6127           0 :         } else {
    6128           0 :                 PHY_WRITE(mac, 0x2b, 0x1402);
    6129             :         }
    6130             : 
    6131             :         /*
    6132             :          * Setup RF signal
    6133             :          */
    6134             :         rf_val = 0;
    6135             :         min_val = 65535;
    6136             : 
    6137           0 :         for (i = 0; i < 4; ++i) {
    6138           0 :                 RF_WRITE(mac, 0x52, rf52 | i);
    6139           0 :                 bwi_rf_lo_measure_11b(mac);     /* Ignore return value */
    6140             :         }
    6141           0 :         for (i = 0; i < 10; ++i) {
    6142           0 :                 RF_WRITE(mac, 0x52, rf52 | i);
    6143             : 
    6144           0 :                 val = bwi_rf_lo_measure_11b(mac) / 10;
    6145           0 :                 if (val < min_val) {
    6146             :                         min_val = val;
    6147           0 :                         rf_val = i;
    6148           0 :                 }
    6149             :         }
    6150           0 :         RF_WRITE(mac, 0x52, rf52 | rf_val);
    6151             : 
    6152             :         /*
    6153             :          * Setup PHY signal
    6154             :         */
    6155             :         phy_val = 0;
    6156             :         min_val = 65535;
    6157             : 
    6158           0 :         for (i = -4; i < 5; i += 2) {
    6159             :                 int j;
    6160             : 
    6161           0 :                 for (j = -4; j < 5; j += 2) {
    6162             :                         uint16_t phy2f;
    6163             : 
    6164           0 :                         phy2f = (0x100 * i) + j;
    6165           0 :                         if (j < 0)
    6166           0 :                                 phy2f += 0x100;
    6167           0 :                         PHY_WRITE(mac, 0x2f, phy2f);
    6168             : 
    6169           0 :                         val = bwi_rf_lo_measure_11b(mac) / 10;
    6170           0 :                         if (val < min_val) {
    6171             :                                 min_val = val;
    6172             :                                 phy_val = phy2f;
    6173           0 :                         }
    6174             :                 }
    6175             :         }
    6176           0 :         PHY_WRITE(mac, 0x2f, phy_val + 0x101);
    6177             : 
    6178             :         /*
    6179             :          * Restore saved RF/PHY registers
    6180             :          */
    6181           0 :         if (rf->rf_type == BWI_RF_T_BCM2050) {
    6182           0 :                 RESTORE_PHY_REG(mac, &regs, 0a);
    6183           0 :                 RESTORE_PHY_REG(mac, &regs, 2a);
    6184           0 :                 RESTORE_PHY_REG(mac, &regs, 35);
    6185           0 :                 RESTORE_PHY_REG(mac, &regs, 03);
    6186           0 :                 RESTORE_PHY_REG(mac, &regs, 01);
    6187           0 :                 RESTORE_PHY_REG(mac, &regs, 30);
    6188             : 
    6189           0 :                 RESTORE_RF_REG(mac, &regs, 43);
    6190           0 :                 RESTORE_RF_REG(mac, &regs, 7a);
    6191             : 
    6192           0 :                 RF_FILT_SETBITS(mac, 0x52, 0xf, regs.rf_52);
    6193             : 
    6194           0 :                 CSR_WRITE_2(sc, BWI_BPHY_CTRL, bphy_ctrl);
    6195           0 :         }
    6196           0 :         RESTORE_PHY_REG(mac, &regs, 15);
    6197             : 
    6198           0 :         bwi_rf_workaround(mac, rf->rf_curchan);
    6199           0 : }
    6200             : 
    6201             : /* INTERFACE */
    6202             : 
    6203             : uint16_t
    6204           0 : bwi_read_sprom(struct bwi_softc *sc, uint16_t ofs)
    6205             : {
    6206           0 :         return (CSR_READ_2(sc, ofs + BWI_SPROM_START));
    6207             : }
    6208             : 
    6209             : void
    6210           0 : bwi_setup_desc32(struct bwi_softc *sc, struct bwi_desc32 *desc_array,
    6211             :     int ndesc, int desc_idx, bus_addr_t paddr, int buf_len, int tx)
    6212             : {
    6213           0 :         struct bwi_desc32 *desc = &desc_array[desc_idx];
    6214             :         uint32_t ctrl, addr, addr_hi, addr_lo;
    6215             : 
    6216           0 :         if (sc->sc_bus_space == BWI_BUS_SPACE_30BIT && paddr >= 0x40000000)
    6217           0 :                 panic("bad paddr 0x%lx\n", (long)paddr);
    6218             : 
    6219           0 :         addr_lo = __SHIFTOUT(paddr, BWI_DESC32_A_ADDR_MASK);
    6220           0 :         addr_hi = __SHIFTOUT(paddr, BWI_DESC32_A_FUNC_MASK);
    6221             : 
    6222           0 :         addr = __SHIFTIN(addr_lo, BWI_DESC32_A_ADDR_MASK) |
    6223             :             __SHIFTIN(BWI_DESC32_A_FUNC_TXRX, BWI_DESC32_A_FUNC_MASK);
    6224             : 
    6225           0 :         ctrl = __SHIFTIN(buf_len, BWI_DESC32_C_BUFLEN_MASK) |
    6226           0 :              __SHIFTIN(addr_hi, BWI_DESC32_C_ADDRHI_MASK);
    6227           0 :         if (desc_idx == ndesc - 1)
    6228           0 :                 ctrl |= BWI_DESC32_C_EOR;
    6229           0 :         if (tx) {
    6230             :                 /* XXX */
    6231           0 :                 ctrl |= BWI_DESC32_C_FRAME_START |
    6232             :                     BWI_DESC32_C_FRAME_END |
    6233             :                     BWI_DESC32_C_INTR;
    6234           0 :         }
    6235             : 
    6236           0 :         desc->addr = htole32(addr);
    6237           0 :         desc->ctrl = htole32(ctrl);
    6238           0 : }
    6239             : 
    6240             : void
    6241           0 : bwi_power_on(struct bwi_softc *sc, int with_pll)
    6242             : {
    6243             :         uint32_t gpio_in, gpio_out, gpio_en, status;
    6244             : 
    6245             :         DPRINTF(1, "%s: %s\n", sc->sc_dev.dv_xname, __func__);
    6246             : 
    6247           0 :         gpio_in = (sc->sc_conf_read)(sc, BWI_PCIR_GPIO_IN);
    6248           0 :         if (gpio_in & BWI_PCIM_GPIO_PWR_ON)
    6249             :                 goto back;
    6250             : 
    6251           0 :         gpio_out = (sc->sc_conf_read)(sc, BWI_PCIR_GPIO_OUT);
    6252           0 :         gpio_en = (sc->sc_conf_read)(sc, BWI_PCIR_GPIO_ENABLE);
    6253             : 
    6254           0 :         gpio_out |= BWI_PCIM_GPIO_PWR_ON;
    6255           0 :         gpio_en |= BWI_PCIM_GPIO_PWR_ON;
    6256           0 :         if (with_pll) {
    6257             :                 /* Turn off PLL first */
    6258           0 :                 gpio_out |= BWI_PCIM_GPIO_PLL_PWR_OFF;
    6259           0 :                 gpio_en |= BWI_PCIM_GPIO_PLL_PWR_OFF;
    6260           0 :         }
    6261             : 
    6262           0 :         (sc->sc_conf_write)(sc, BWI_PCIR_GPIO_OUT, gpio_out);
    6263           0 :         (sc->sc_conf_write)(sc, BWI_PCIR_GPIO_ENABLE, gpio_en);
    6264           0 :         DELAY(1000);
    6265             : 
    6266           0 :         if (with_pll) {
    6267             :                 /* Turn on PLL */
    6268           0 :                 gpio_out &= ~BWI_PCIM_GPIO_PLL_PWR_OFF;
    6269           0 :                 (sc->sc_conf_write)(sc, BWI_PCIR_GPIO_OUT, gpio_out);
    6270           0 :                 DELAY(5000);
    6271           0 :         }
    6272             : 
    6273             : back:
    6274             :         /* Clear "Signaled Target Abort" */
    6275           0 :         status = (sc->sc_conf_read)(sc, PCI_COMMAND_STATUS_REG);
    6276           0 :         status &= ~PCI_STATUS_TARGET_TARGET_ABORT;
    6277           0 :         (sc->sc_conf_write)(sc, PCI_COMMAND_STATUS_REG, status);
    6278           0 : }
    6279             : 
    6280             : int
    6281           0 : bwi_power_off(struct bwi_softc *sc, int with_pll)
    6282             : {
    6283             :         uint32_t gpio_out, gpio_en;
    6284             : 
    6285             :         DPRINTF(1, "%s: %s\n", sc->sc_dev.dv_xname, __func__);
    6286             : 
    6287           0 :         (sc->sc_conf_read)(sc, BWI_PCIR_GPIO_IN); /* dummy read */
    6288           0 :         gpio_out = (sc->sc_conf_read)(sc, BWI_PCIR_GPIO_OUT);
    6289           0 :         gpio_en = (sc->sc_conf_read)(sc, BWI_PCIR_GPIO_ENABLE);
    6290             : 
    6291           0 :         gpio_out &= ~BWI_PCIM_GPIO_PWR_ON;
    6292           0 :         gpio_en |= BWI_PCIM_GPIO_PWR_ON;
    6293           0 :         if (with_pll) {
    6294           0 :                 gpio_out |= BWI_PCIM_GPIO_PLL_PWR_OFF;
    6295           0 :                 gpio_en |= BWI_PCIM_GPIO_PLL_PWR_OFF;
    6296           0 :         }
    6297             : 
    6298           0 :         (sc->sc_conf_write)(sc, BWI_PCIR_GPIO_OUT, gpio_out);
    6299           0 :         (sc->sc_conf_write)(sc, BWI_PCIR_GPIO_ENABLE, gpio_en);
    6300             : 
    6301           0 :         return (0);
    6302             : }
    6303             : 
    6304             : int
    6305           0 : bwi_regwin_switch(struct bwi_softc *sc, struct bwi_regwin *rw,
    6306             :     struct bwi_regwin **old_rw)
    6307             : {
    6308             :         int error;
    6309             : 
    6310           0 :         if (old_rw != NULL)
    6311           0 :                 *old_rw = NULL;
    6312             : 
    6313           0 :         if (!BWI_REGWIN_EXIST(rw))
    6314           0 :                 return (EINVAL);
    6315             : 
    6316           0 :         if (sc->sc_cur_regwin != rw) {
    6317           0 :                 error = bwi_regwin_select(sc, rw->rw_id);
    6318           0 :                 if (error) {
    6319           0 :                         printf("%s: can't select regwin %d\n",
    6320           0 :                             sc->sc_dev.dv_xname, rw->rw_id);
    6321           0 :                         return (error);
    6322             :                 }
    6323             :         }
    6324             : 
    6325           0 :         if (old_rw != NULL)
    6326           0 :                 *old_rw = sc->sc_cur_regwin;
    6327           0 :         sc->sc_cur_regwin = rw;
    6328             : 
    6329           0 :         return (0);
    6330           0 : }
    6331             : 
    6332             : int
    6333           0 : bwi_regwin_select(struct bwi_softc *sc, int id)
    6334             : {
    6335           0 :         uint32_t win = BWI_PCIM_REGWIN(id);
    6336             :         int i;
    6337             : 
    6338             : #define RETRY_MAX       50
    6339           0 :         for (i = 0; i < RETRY_MAX; ++i) {
    6340           0 :                 (sc->sc_conf_write)(sc, BWI_PCIR_SEL_REGWIN, win);
    6341           0 :                 if ((sc->sc_conf_read)(sc, BWI_PCIR_SEL_REGWIN) == win)
    6342           0 :                         return (0);
    6343           0 :                 DELAY(10);
    6344             :         }
    6345             : #undef RETRY_MAX
    6346             : 
    6347           0 :         return (ENXIO);
    6348           0 : }
    6349             : 
    6350             : void
    6351           0 : bwi_regwin_info(struct bwi_softc *sc, uint16_t *type, uint8_t *rev)
    6352             : {
    6353             :         uint32_t val;
    6354             : 
    6355           0 :         val = CSR_READ_4(sc, BWI_ID_HI);
    6356           0 :         *type = BWI_ID_HI_REGWIN_TYPE(val);
    6357           0 :         *rev = BWI_ID_HI_REGWIN_REV(val);
    6358             : 
    6359             :         DPRINTF(1, "%s: regwin: type 0x%03x, rev %d, vendor 0x%04x\n",
    6360             :             sc->sc_dev.dv_xname,
    6361             :             *type, *rev, __SHIFTOUT(val, BWI_ID_HI_REGWIN_VENDOR_MASK));
    6362           0 : }
    6363             : 
    6364             : void
    6365           0 : bwi_led_attach(struct bwi_softc *sc)
    6366             : {
    6367             :         const uint8_t *led_act = NULL;
    6368           0 :         uint16_t gpio, val[BWI_LED_MAX];
    6369             :         int i;
    6370             : 
    6371           0 :         for (i = 0; i < nitems(bwi_vendor_led_act); ++i) {
    6372           0 :                 if (sc->sc_pci_subvid == bwi_vendor_led_act[i].vid) {
    6373           0 :                         led_act = bwi_vendor_led_act[i].led_act;
    6374           0 :                                 break;
    6375             :                 }
    6376             :         }
    6377           0 :         if (led_act == NULL)
    6378           0 :                 led_act = bwi_default_led_act;
    6379             : 
    6380           0 :         gpio = bwi_read_sprom(sc, BWI_SPROM_GPIO01);
    6381           0 :         val[0] = __SHIFTOUT(gpio, BWI_SPROM_GPIO_0);
    6382           0 :         val[1] = __SHIFTOUT(gpio, BWI_SPROM_GPIO_1);
    6383             : 
    6384           0 :         gpio = bwi_read_sprom(sc, BWI_SPROM_GPIO23);
    6385           0 :         val[2] = __SHIFTOUT(gpio, BWI_SPROM_GPIO_2);
    6386           0 :         val[3] = __SHIFTOUT(gpio, BWI_SPROM_GPIO_3);
    6387             : 
    6388           0 :         for (i = 0; i < BWI_LED_MAX; ++i) {
    6389           0 :                 struct bwi_led *led = &sc->sc_leds[i];
    6390             : 
    6391           0 :                 if (val[i] == 0xff) {
    6392           0 :                         led->l_act = led_act[i];
    6393           0 :                 } else {
    6394           0 :                         if (val[i] & BWI_LED_ACT_LOW)
    6395           0 :                                 led->l_flags |= BWI_LED_F_ACTLOW;
    6396           0 :                         led->l_act = __SHIFTOUT(val[i], BWI_LED_ACT_MASK);
    6397             :                 }
    6398           0 :                 led->l_mask = (1 << i);
    6399             : 
    6400           0 :                 if (led->l_act == BWI_LED_ACT_BLINK_SLOW ||
    6401           0 :                     led->l_act == BWI_LED_ACT_BLINK_POLL ||
    6402           0 :                     led->l_act == BWI_LED_ACT_BLINK) {
    6403           0 :                     led->l_flags |= BWI_LED_F_BLINK;
    6404           0 :                         if (led->l_act == BWI_LED_ACT_BLINK_POLL)
    6405           0 :                                 led->l_flags |= BWI_LED_F_POLLABLE;
    6406           0 :                         else if (led->l_act == BWI_LED_ACT_BLINK_SLOW)
    6407           0 :                                 led->l_flags |= BWI_LED_F_SLOW;
    6408             : 
    6409           0 :                         if (sc->sc_blink_led == NULL) {
    6410           0 :                                 sc->sc_blink_led = led;
    6411           0 :                                 if (led->l_flags & BWI_LED_F_SLOW)
    6412           0 :                                         BWI_LED_SLOWDOWN(sc->sc_led_idle);
    6413             :                         }
    6414             :                 }
    6415             : 
    6416             :                 DPRINTF(1, "%s: %dth led, act %d, lowact %d\n",
    6417             :                     sc->sc_dev.dv_xname, i, led->l_act,
    6418             :                     led->l_flags & BWI_LED_F_ACTLOW);
    6419             :         }
    6420           0 :         timeout_set(&sc->sc_led_blink_next_ch, bwi_led_blink_next, sc);
    6421           0 :         timeout_set(&sc->sc_led_blink_end_ch, bwi_led_blink_end, sc);
    6422           0 : }
    6423             : 
    6424             : uint16_t
    6425           0 : bwi_led_onoff(struct bwi_led *led, uint16_t val, int on)
    6426             : {
    6427           0 :         if (led->l_flags & BWI_LED_F_ACTLOW)
    6428           0 :                 on = !on;
    6429           0 :         if (on)
    6430           0 :                 val |= led->l_mask;
    6431             :         else
    6432           0 :                 val &= ~led->l_mask;
    6433             : 
    6434           0 :         return (val);
    6435             : }
    6436             : 
    6437             : void
    6438           0 : bwi_led_newstate(struct bwi_softc *sc, enum ieee80211_state nstate)
    6439             : {
    6440           0 :         struct ieee80211com *ic = &sc->sc_ic;
    6441             :         uint16_t val;
    6442             :         int i;
    6443             : 
    6444           0 :         if (nstate == IEEE80211_S_INIT) {
    6445           0 :                 timeout_del(&sc->sc_led_blink_next_ch);
    6446           0 :                 timeout_del(&sc->sc_led_blink_end_ch);
    6447           0 :                 sc->sc_led_blinking = 0;
    6448           0 :         }
    6449             : 
    6450           0 :         if ((ic->ic_if.if_flags & IFF_RUNNING) == 0)
    6451           0 :                 return;
    6452             : 
    6453           0 :         val = CSR_READ_2(sc, BWI_MAC_GPIO_CTRL);
    6454           0 :         for (i = 0; i < BWI_LED_MAX; ++i) {
    6455           0 :                 struct bwi_led *led = &sc->sc_leds[i];
    6456             :                 int on;
    6457             : 
    6458           0 :                 if (led->l_act == BWI_LED_ACT_UNKN ||
    6459           0 :                     led->l_act == BWI_LED_ACT_NULL)
    6460           0 :                         continue;
    6461             : 
    6462           0 :                 if ((led->l_flags & BWI_LED_F_BLINK) &&
    6463           0 :                         nstate != IEEE80211_S_INIT)
    6464           0 :                         continue;
    6465             : 
    6466           0 :                 switch (led->l_act) {
    6467             :                 case BWI_LED_ACT_ON:    /* Always on */
    6468             :                         on = 1;
    6469           0 :                         break;
    6470             :                 case BWI_LED_ACT_OFF:   /* Always off */
    6471             :                 case BWI_LED_ACT_5GHZ:  /* TODO: 11A */
    6472             :                         on = 0;
    6473           0 :                         break;
    6474             :                 default:
    6475             :                         on = 1;
    6476           0 :                         switch (nstate) {
    6477             :                         case IEEE80211_S_INIT:
    6478             :                                 on = 0;
    6479           0 :                                 break;
    6480             :                         case IEEE80211_S_RUN:
    6481           0 :                                 if (led->l_act == BWI_LED_ACT_11G &&
    6482           0 :                                     ic->ic_curmode != IEEE80211_MODE_11G)
    6483           0 :                                         on = 0;
    6484             :                                 break;
    6485             :                         default:
    6486           0 :                                 if (led->l_act == BWI_LED_ACT_ASSOC)
    6487           0 :                                         on = 0;
    6488             :                                 break;
    6489             :                         }
    6490             :                         break;
    6491             :                 }
    6492             : 
    6493           0 :                 val = bwi_led_onoff(led, val, on);
    6494           0 :         }
    6495           0 :         CSR_WRITE_2(sc, BWI_MAC_GPIO_CTRL, val);
    6496           0 : }
    6497             : 
    6498             : void
    6499           0 : bwi_led_event(struct bwi_softc *sc, int event)
    6500             : {
    6501           0 :         struct bwi_led *led = sc->sc_blink_led;
    6502             :         int rate;
    6503             : 
    6504           0 :         if (event == BWI_LED_EVENT_POLL) {
    6505           0 :                 if ((led->l_flags & BWI_LED_F_POLLABLE) == 0)
    6506           0 :                         return;
    6507           0 :                 if (ticks - sc->sc_led_ticks < sc->sc_led_idle)
    6508           0 :                         return;
    6509             :         }
    6510             : 
    6511           0 :         sc->sc_led_ticks = ticks;
    6512           0 :         if (sc->sc_led_blinking)
    6513           0 :                 return;
    6514             : 
    6515           0 :         switch (event) {
    6516             :         case BWI_LED_EVENT_RX:
    6517           0 :                 rate = sc->sc_rx_rate;
    6518           0 :                 break;
    6519             :         case BWI_LED_EVENT_TX:
    6520           0 :                 rate = sc->sc_tx_rate;
    6521           0 :                 break;
    6522             :         case BWI_LED_EVENT_POLL:
    6523             :                 rate = 0;
    6524           0 :                 break;
    6525             :         default:
    6526           0 :                 panic("unknown LED event %d", event);
    6527             :                 break;
    6528             :         }
    6529           0 :         bwi_led_blink_start(sc, bwi_led_duration[rate].on_dur,
    6530           0 :             bwi_led_duration[rate].off_dur);
    6531           0 : }
    6532             : 
    6533             : void
    6534           0 : bwi_led_blink_start(struct bwi_softc *sc, int on_dur, int off_dur)
    6535             : {
    6536           0 :         struct bwi_led *led = sc->sc_blink_led;
    6537             :         uint16_t val;
    6538             : 
    6539           0 :         val = CSR_READ_2(sc, BWI_MAC_GPIO_CTRL);
    6540           0 :         val = bwi_led_onoff(led, val, 1);
    6541           0 :         CSR_WRITE_2(sc, BWI_MAC_GPIO_CTRL, val);
    6542             : 
    6543           0 :         if (led->l_flags & BWI_LED_F_SLOW) {
    6544           0 :                 BWI_LED_SLOWDOWN(on_dur);
    6545           0 :                 BWI_LED_SLOWDOWN(off_dur);
    6546           0 :         }
    6547             : 
    6548           0 :         sc->sc_led_blinking = 1;
    6549           0 :         sc->sc_led_blink_offdur = off_dur;
    6550             : 
    6551           0 :         timeout_add(&sc->sc_led_blink_next_ch, on_dur);
    6552           0 : }
    6553             : 
    6554             : void
    6555           0 : bwi_led_blink_next(void *xsc)
    6556             : {
    6557           0 :         struct bwi_softc *sc = xsc;
    6558             :         uint16_t val;
    6559             : 
    6560           0 :         val = CSR_READ_2(sc, BWI_MAC_GPIO_CTRL);
    6561           0 :         val = bwi_led_onoff(sc->sc_blink_led, val, 0);
    6562           0 :         CSR_WRITE_2(sc, BWI_MAC_GPIO_CTRL, val);
    6563             : 
    6564           0 :         timeout_add(&sc->sc_led_blink_end_ch, sc->sc_led_blink_offdur);
    6565           0 : }
    6566             : 
    6567             : void
    6568           0 : bwi_led_blink_end(void *xsc)
    6569             : {
    6570           0 :         struct bwi_softc *sc = xsc;
    6571             : 
    6572           0 :         sc->sc_led_blinking = 0;
    6573           0 : }
    6574             : 
    6575             : int
    6576           0 : bwi_bbp_attach(struct bwi_softc *sc)
    6577             : {
    6578           0 :         uint16_t bbp_id, rw_type;
    6579           0 :         uint8_t rw_rev;
    6580             :         uint32_t info;
    6581             :         int error, nregwin, i;
    6582             : 
    6583             :         /*
    6584             :          * Get 0th regwin information
    6585             :          * NOTE: 0th regwin should exist
    6586             :          */
    6587           0 :         error = bwi_regwin_select(sc, 0);
    6588           0 :         if (error) {
    6589           0 :                 printf("%s: can't select regwin 0\n", sc->sc_dev.dv_xname);
    6590           0 :                 return (error);
    6591             :         }
    6592           0 :         bwi_regwin_info(sc, &rw_type, &rw_rev);
    6593             : 
    6594             :         /*
    6595             :          * Find out BBP id
    6596             :          */
    6597             :         bbp_id = 0;
    6598             :         info = 0;
    6599           0 :         if (rw_type == BWI_REGWIN_T_COM) {
    6600           0 :                 info = CSR_READ_4(sc, BWI_INFO);
    6601           0 :                 bbp_id = __SHIFTOUT(info, BWI_INFO_BBPID_MASK);
    6602             : 
    6603           0 :                 BWI_CREATE_REGWIN(&sc->sc_com_regwin, 0, rw_type, rw_rev);
    6604             : 
    6605           0 :                 sc->sc_cap = CSR_READ_4(sc, BWI_CAPABILITY);
    6606           0 :         } else {
    6607           0 :                 uint16_t did = sc->sc_pci_did;
    6608           0 :                 uint8_t revid = sc->sc_pci_revid;
    6609             : 
    6610           0 :                 for (i = 0; i < nitems(bwi_bbpid_map); ++i) {
    6611           0 :                         if (did >= bwi_bbpid_map[i].did_min &&
    6612           0 :                             did <= bwi_bbpid_map[i].did_max) {
    6613           0 :                                 bbp_id = bwi_bbpid_map[i].bbp_id;
    6614           0 :                                 break;
    6615             :                         }
    6616             :                 }
    6617           0 :                 if (bbp_id == 0) {
    6618           0 :                         printf("%s: no BBP id for device id 0x%04x\n",
    6619           0 :                             sc->sc_dev.dv_xname, did);
    6620           0 :                         return (ENXIO);
    6621             :                 }
    6622             : 
    6623           0 :                 info = __SHIFTIN(revid, BWI_INFO_BBPREV_MASK) |
    6624             :                     __SHIFTIN(0, BWI_INFO_BBPPKG_MASK);
    6625           0 :         }
    6626             : 
    6627             :         /*
    6628             :          * Find out number of regwins
    6629             :          */
    6630             :         nregwin = 0;
    6631           0 :         if (rw_type == BWI_REGWIN_T_COM && rw_rev >= 4) {
    6632           0 :                 nregwin = __SHIFTOUT(info, BWI_INFO_NREGWIN_MASK);
    6633           0 :         } else {
    6634           0 :                 for (i = 0; i < nitems(bwi_regwin_count); ++i) {
    6635           0 :                         if (bwi_regwin_count[i].bbp_id == bbp_id) {
    6636           0 :                                 nregwin = bwi_regwin_count[i].nregwin;
    6637           0 :                                 break;
    6638             :                         }
    6639             :                 }
    6640           0 :                 if (nregwin == 0) {
    6641           0 :                         printf("%s: no number of win for BBP id 0x%04x\n",
    6642           0 :                             sc->sc_dev.dv_xname, bbp_id);
    6643           0 :                         return (ENXIO);
    6644             :                 }
    6645             :         }
    6646             : 
    6647             :         /* Record BBP id/rev for later using */
    6648           0 :         sc->sc_bbp_id = bbp_id;
    6649           0 :         sc->sc_bbp_rev = __SHIFTOUT(info, BWI_INFO_BBPREV_MASK);
    6650           0 :         sc->sc_bbp_pkg = __SHIFTOUT(info, BWI_INFO_BBPPKG_MASK);
    6651             :         DPRINTF(1, "%s: BBP id 0x%04x, BBP rev 0x%x, BBP pkg %d\n",
    6652             :             sc->sc_dev.dv_xname, sc->sc_bbp_id, sc->sc_bbp_rev, sc->sc_bbp_pkg);
    6653             :         DPRINTF(1, "%s: nregwin %d, cap 0x%08x\n",
    6654             :             sc->sc_dev.dv_xname, nregwin, sc->sc_cap);
    6655             : 
    6656             :         /*
    6657             :          * Create rest of the regwins
    6658             :          */
    6659             : 
    6660             :         /* Don't re-create common regwin, if it is already created */
    6661           0 :         i = BWI_REGWIN_EXIST(&sc->sc_com_regwin) ? 1 : 0;
    6662             : 
    6663           0 :         for (; i < nregwin; ++i) {
    6664             :                 /*
    6665             :                  * Get regwin information
    6666             :                  */
    6667           0 :                 error = bwi_regwin_select(sc, i);
    6668           0 :                 if (error) {
    6669           0 :                         printf("%s: can't select regwin %d\n",
    6670           0 :                             sc->sc_dev.dv_xname, i);
    6671           0 :                         return (error);
    6672             :                 }
    6673           0 :                 bwi_regwin_info(sc, &rw_type, &rw_rev);
    6674             : 
    6675             :                 /*
    6676             :                  * Try attach:
    6677             :                  * 1) Bus (PCI/PCIE) regwin
    6678             :                  * 2) MAC regwin
    6679             :                  * Ignore rest types of regwin
    6680             :                  */
    6681           0 :                 if (rw_type == BWI_REGWIN_T_BUSPCI ||
    6682           0 :                     rw_type == BWI_REGWIN_T_BUSPCIE) {
    6683           0 :                         if (BWI_REGWIN_EXIST(&sc->sc_bus_regwin)) {
    6684           0 :                                 printf("%s: bus regwin already exists\n",
    6685           0 :                                     sc->sc_dev.dv_xname);
    6686           0 :                         } else {
    6687           0 :                                 BWI_CREATE_REGWIN(&sc->sc_bus_regwin, i,
    6688             :                                     rw_type, rw_rev);
    6689             :                         }
    6690           0 :                 } else if (rw_type == BWI_REGWIN_T_MAC) {
    6691             :                         /* XXX ignore return value */
    6692           0 :                         bwi_mac_attach(sc, i, rw_rev);
    6693           0 :                 }
    6694             :         }
    6695             : 
    6696             :         /* At least one MAC shold exist */
    6697           0 :         if (!BWI_REGWIN_EXIST(&sc->sc_mac[0].mac_regwin)) {
    6698           0 :                 printf("%s: no MAC was found\n", sc->sc_dev.dv_xname);
    6699           0 :                 return (ENXIO);
    6700             :         }
    6701           0 :         KASSERT(sc->sc_nmac > 0);
    6702             : 
    6703             :         /* Bus regwin must exist */
    6704           0 :         if (!BWI_REGWIN_EXIST(&sc->sc_bus_regwin)) {
    6705           0 :                 printf("%s: no bus regwin was found\n", sc->sc_dev.dv_xname);
    6706           0 :                 return (ENXIO);
    6707             :         }
    6708             : 
    6709             :         /* Start with first MAC */
    6710           0 :         error = bwi_regwin_switch(sc, &sc->sc_mac[0].mac_regwin, NULL);
    6711           0 :         if (error)
    6712           0 :                 return (error);
    6713             : 
    6714           0 :         return (0);
    6715           0 : }
    6716             : 
    6717             : int
    6718           0 : bwi_bus_init(struct bwi_softc *sc, struct bwi_mac *mac)
    6719             : {
    6720           0 :         struct bwi_regwin *old, *bus;
    6721             :         uint32_t val;
    6722             :         int error;
    6723             : 
    6724           0 :         bus = &sc->sc_bus_regwin;
    6725           0 :         KASSERT(sc->sc_cur_regwin == &mac->mac_regwin);
    6726             : 
    6727             :         /*
    6728             :          * Tell bus to generate requested interrupts
    6729             :          */
    6730           0 :         if (bus->rw_rev < 6 && bus->rw_type == BWI_REGWIN_T_BUSPCI) {
    6731             :                 /*
    6732             :                  * NOTE: Read BWI_FLAGS from MAC regwin
    6733             :                  */
    6734           0 :                 val = CSR_READ_4(sc, BWI_FLAGS);
    6735             : 
    6736           0 :                 error = bwi_regwin_switch(sc, bus, &old);
    6737           0 :                 if (error)
    6738           0 :                         return (error);
    6739             : 
    6740           0 :                 CSR_SETBITS_4(sc, BWI_INTRVEC, (val & BWI_FLAGS_INTR_MASK));
    6741           0 :         } else {
    6742             :                 uint32_t mac_mask;
    6743             : 
    6744           0 :                 mac_mask = 1 << mac->mac_id;
    6745             : 
    6746           0 :                 error = bwi_regwin_switch(sc, bus, &old);
    6747           0 :                 if (error)
    6748           0 :                         return (error);
    6749             : 
    6750           0 :                 val = (sc->sc_conf_read)(sc, BWI_PCIR_INTCTL);
    6751           0 :                 val |= mac_mask << 8;
    6752           0 :                 (sc->sc_conf_write)(sc, BWI_PCIR_INTCTL, val);
    6753           0 :         }
    6754             : 
    6755           0 :         if (sc->sc_flags & BWI_F_BUS_INITED)
    6756             :                 goto back;
    6757             : 
    6758           0 :         if (bus->rw_type == BWI_REGWIN_T_BUSPCI) {
    6759             :                 /*
    6760             :                  * Enable prefetch and burst
    6761             :                  */
    6762           0 :                 CSR_SETBITS_4(sc, BWI_BUS_CONFIG,
    6763             :                     BWI_BUS_CONFIG_PREFETCH | BWI_BUS_CONFIG_BURST);
    6764             : 
    6765           0 :                 if (bus->rw_rev < 5) {
    6766           0 :                         struct bwi_regwin *com = &sc->sc_com_regwin;
    6767             : 
    6768             :                         /*
    6769             :                          * Configure timeouts for bus operation
    6770             :                          */
    6771             : 
    6772             :                         /*
    6773             :                          * Set service timeout and request timeout
    6774             :                          */
    6775           0 :                         CSR_SETBITS_4(sc, BWI_CONF_LO,
    6776             :                             __SHIFTIN(BWI_CONF_LO_SERVTO,
    6777             :                             BWI_CONF_LO_SERVTO_MASK) |
    6778             :                             __SHIFTIN(BWI_CONF_LO_REQTO,
    6779             :                             BWI_CONF_LO_REQTO_MASK));
    6780             : 
    6781             :                         /*
    6782             :                          * If there is common regwin, we switch to that regwin
    6783             :                          * and switch back to bus regwin once we have done.
    6784             :                          */
    6785           0 :                         if (BWI_REGWIN_EXIST(com)) {
    6786           0 :                                 error = bwi_regwin_switch(sc, com, NULL);
    6787           0 :                                 if (error)
    6788           0 :                                         return (error);
    6789             :                         }
    6790             : 
    6791             :                         /* Let bus know what we have changed */
    6792           0 :                         CSR_WRITE_4(sc, BWI_BUS_ADDR, BWI_BUS_ADDR_MAGIC);
    6793           0 :                         CSR_READ_4(sc, BWI_BUS_ADDR); /* Flush */
    6794           0 :                         CSR_WRITE_4(sc, BWI_BUS_DATA, 0);
    6795           0 :                         CSR_READ_4(sc, BWI_BUS_DATA); /* Flush */
    6796             : 
    6797           0 :                         if (BWI_REGWIN_EXIST(com)) {
    6798           0 :                                 error = bwi_regwin_switch(sc, bus, NULL);
    6799           0 :                                 if (error)
    6800           0 :                                         return (error);
    6801             :                         }
    6802           0 :                 } else if (bus->rw_rev >= 11) {
    6803             :                         /*
    6804             :                          * Enable memory read multiple
    6805             :                          */
    6806           0 :                         CSR_SETBITS_4(sc, BWI_BUS_CONFIG, BWI_BUS_CONFIG_MRM);
    6807           0 :                 }
    6808             :         } else {
    6809             :                 /* TODO: PCIE */
    6810             :         }
    6811             : 
    6812           0 :         sc->sc_flags |= BWI_F_BUS_INITED;
    6813             : back:
    6814           0 :         return (bwi_regwin_switch(sc, old, NULL));
    6815           0 : }
    6816             : 
    6817             : void
    6818           0 : bwi_get_card_flags(struct bwi_softc *sc)
    6819             : {
    6820           0 :         sc->sc_card_flags = bwi_read_sprom(sc, BWI_SPROM_CARD_FLAGS);
    6821           0 :         if (sc->sc_card_flags == 0xffff)
    6822           0 :                 sc->sc_card_flags = 0;
    6823             : 
    6824           0 :         if (sc->sc_pci_subvid == PCI_VENDOR_APPLE &&
    6825           0 :             sc->sc_pci_subdid == 0x4e && /* XXX */
    6826           0 :             sc->sc_pci_revid > 0x40)
    6827           0 :                 sc->sc_card_flags |= BWI_CARD_F_PA_GPIO9;
    6828             : 
    6829             :         DPRINTF(1, "%s: card flags 0x%04x\n",
    6830             :             sc->sc_dev.dv_xname, sc->sc_card_flags);
    6831           0 : }
    6832             : 
    6833             : void
    6834           0 : bwi_get_eaddr(struct bwi_softc *sc, uint16_t eaddr_ofs, uint8_t *eaddr)
    6835             : {
    6836             :         int i;
    6837             : 
    6838           0 :         for (i = 0; i < 3; ++i) {
    6839           0 :                 *((uint16_t *)eaddr + i) =
    6840           0 :                     htobe16(bwi_read_sprom(sc, eaddr_ofs + 2 * i));
    6841             :         }
    6842           0 : }
    6843             : 
    6844             : void
    6845           0 : bwi_get_clock_freq(struct bwi_softc *sc, struct bwi_clock_freq *freq)
    6846             : {
    6847             :         struct bwi_regwin *com;
    6848             :         uint32_t val;
    6849             :         uint div;
    6850             :         int src;
    6851             : 
    6852           0 :         bzero(freq, sizeof(*freq));
    6853           0 :         com = &sc->sc_com_regwin;
    6854             : 
    6855           0 :         KASSERT(BWI_REGWIN_EXIST(com));
    6856           0 :         KASSERT(sc->sc_cur_regwin == com);
    6857           0 :         KASSERT(sc->sc_cap & BWI_CAP_CLKMODE);
    6858             : 
    6859             :         /*
    6860             :          * Calculate clock frequency
    6861             :          */
    6862             :         src = -1;
    6863             :         div = 0;
    6864           0 :         if (com->rw_rev < 6) {
    6865           0 :                 val = (sc->sc_conf_read)(sc, BWI_PCIR_GPIO_OUT);
    6866           0 :                 if (val & BWI_PCIM_GPIO_OUT_CLKSRC) {
    6867             :                         src = BWI_CLKSRC_PCI;
    6868             :                         div = 64;
    6869           0 :                 } else {
    6870             :                         src = BWI_CLKSRC_CS_OSC;
    6871             :                         div = 32;
    6872             :                 }
    6873           0 :         } else if (com->rw_rev < 10) {
    6874           0 :                 val = CSR_READ_4(sc, BWI_CLOCK_CTRL);
    6875             : 
    6876           0 :                 src = __SHIFTOUT(val, BWI_CLOCK_CTRL_CLKSRC);
    6877           0 :                 if (src == BWI_CLKSRC_LP_OSC)
    6878           0 :                         div = 1;
    6879             :                 else {
    6880           0 :                         div = (__SHIFTOUT(val, BWI_CLOCK_CTRL_FDIV) + 1) << 2;
    6881             : 
    6882             :                         /* Unknown source */
    6883           0 :                         if (src >= BWI_CLKSRC_MAX)
    6884           0 :                                 src = BWI_CLKSRC_CS_OSC;
    6885             :                 }
    6886             :         } else {
    6887           0 :                 val = CSR_READ_4(sc, BWI_CLOCK_INFO);
    6888             : 
    6889             :                 src = BWI_CLKSRC_CS_OSC;
    6890           0 :                 div = (__SHIFTOUT(val, BWI_CLOCK_INFO_FDIV) + 1) << 2;
    6891             :         }
    6892             : 
    6893           0 :         KASSERT(src >= 0 && src < BWI_CLKSRC_MAX);
    6894           0 :         KASSERT(div != 0);
    6895             : 
    6896             :         DPRINTF(1, "%s: clksrc %s\n",
    6897             :             sc->sc_dev.dv_xname,
    6898             :             src == BWI_CLKSRC_PCI ? "PCI" :
    6899             :             (src == BWI_CLKSRC_LP_OSC ? "LP_OSC" : "CS_OSC"));
    6900             : 
    6901           0 :         freq->clkfreq_min = bwi_clkfreq[src].freq_min / div;
    6902           0 :         freq->clkfreq_max = bwi_clkfreq[src].freq_max / div;
    6903             : 
    6904             :         DPRINTF(1, "%s: clkfreq min %u, max %u\n",
    6905             :             sc->sc_dev.dv_xname, freq->clkfreq_min, freq->clkfreq_max);
    6906           0 : }
    6907             : 
    6908             : int
    6909           0 : bwi_set_clock_mode(struct bwi_softc *sc, enum bwi_clock_mode clk_mode)
    6910             : {
    6911           0 :         struct bwi_regwin *old, *com;
    6912             :         uint32_t clk_ctrl, clk_src;
    6913             :         int error, pwr_off = 0;
    6914             : 
    6915           0 :         com = &sc->sc_com_regwin;
    6916           0 :         if (!BWI_REGWIN_EXIST(com))
    6917           0 :                 return (0);
    6918             : 
    6919           0 :         if (com->rw_rev >= 10 || com->rw_rev < 6)
    6920           0 :                 return (0);
    6921             : 
    6922             :         /*
    6923             :          * For common regwin whose rev is [6, 10), the chip
    6924             :          * must be capable to change clock mode.
    6925             :          */
    6926           0 :         if ((sc->sc_cap & BWI_CAP_CLKMODE) == 0)
    6927           0 :                 return (0);
    6928             : 
    6929           0 :         error = bwi_regwin_switch(sc, com, &old);
    6930           0 :         if (error)
    6931           0 :                 return (error);
    6932             : 
    6933           0 :         if (clk_mode == BWI_CLOCK_MODE_FAST)
    6934           0 :                 bwi_power_on(sc, 0);    /* Don't turn on PLL */
    6935             : 
    6936           0 :         clk_ctrl = CSR_READ_4(sc, BWI_CLOCK_CTRL);
    6937           0 :         clk_src = __SHIFTOUT(clk_ctrl, BWI_CLOCK_CTRL_CLKSRC);
    6938             : 
    6939           0 :         switch (clk_mode) {
    6940             :         case BWI_CLOCK_MODE_FAST:
    6941           0 :                 clk_ctrl &= ~BWI_CLOCK_CTRL_SLOW;
    6942           0 :                 clk_ctrl |= BWI_CLOCK_CTRL_IGNPLL;
    6943           0 :                 break;
    6944             :         case BWI_CLOCK_MODE_SLOW:
    6945           0 :                 clk_ctrl |= BWI_CLOCK_CTRL_SLOW;
    6946           0 :                 break;
    6947             :         case BWI_CLOCK_MODE_DYN:
    6948           0 :                 clk_ctrl &= ~(BWI_CLOCK_CTRL_SLOW |
    6949             :                     BWI_CLOCK_CTRL_IGNPLL |
    6950             :                     BWI_CLOCK_CTRL_NODYN);
    6951           0 :                 if (clk_src != BWI_CLKSRC_CS_OSC) {
    6952           0 :                         clk_ctrl |= BWI_CLOCK_CTRL_NODYN;
    6953             :                         pwr_off = 1;
    6954           0 :                 }
    6955             :                 break;
    6956             :         }
    6957           0 :         CSR_WRITE_4(sc, BWI_CLOCK_CTRL, clk_ctrl);
    6958             : 
    6959           0 :         if (pwr_off)
    6960           0 :                 bwi_power_off(sc, 0);   /* Leave PLL as it is */
    6961             : 
    6962           0 :         return (bwi_regwin_switch(sc, old, NULL));
    6963           0 : }
    6964             : 
    6965             : int
    6966           0 : bwi_set_clock_delay(struct bwi_softc *sc)
    6967             : {
    6968           0 :         struct bwi_regwin *old, *com;
    6969             :         int error;
    6970             : 
    6971           0 :         com = &sc->sc_com_regwin;
    6972           0 :         if (!BWI_REGWIN_EXIST(com))
    6973           0 :                 return (0);
    6974             : 
    6975           0 :         error = bwi_regwin_switch(sc, com, &old);
    6976           0 :         if (error)
    6977           0 :                 return (error);
    6978             : 
    6979           0 :         if (sc->sc_bbp_id == BWI_BBPID_BCM4321) {
    6980           0 :                 if (sc->sc_bbp_rev == 0)
    6981           0 :                         CSR_WRITE_4(sc, BWI_CONTROL, BWI_CONTROL_MAGIC0);
    6982           0 :                 else if (sc->sc_bbp_rev == 1)
    6983           0 :                         CSR_WRITE_4(sc, BWI_CONTROL, BWI_CONTROL_MAGIC1);
    6984             :         }
    6985             : 
    6986           0 :         if (sc->sc_cap & BWI_CAP_CLKMODE) {
    6987           0 :                 if (com->rw_rev >= 10)
    6988           0 :                         CSR_FILT_SETBITS_4(sc, BWI_CLOCK_INFO, 0xffff, 0x40000);
    6989             :                 else {
    6990           0 :                         struct bwi_clock_freq freq;
    6991             : 
    6992           0 :                         bwi_get_clock_freq(sc, &freq);
    6993           0 :                         CSR_WRITE_4(sc, BWI_PLL_ON_DELAY,
    6994             :                             howmany(freq.clkfreq_max * 150, 1000000));
    6995           0 :                         CSR_WRITE_4(sc, BWI_FREQ_SEL_DELAY,
    6996             :                             howmany(freq.clkfreq_max * 15, 1000000));
    6997           0 :                 }
    6998             :         }
    6999             : 
    7000           0 :         return (bwi_regwin_switch(sc, old, NULL));
    7001           0 : }
    7002             : 
    7003             : int
    7004           0 : bwi_init(struct ifnet *ifp)
    7005             : {
    7006           0 :         struct bwi_softc *sc = ifp->if_softc;
    7007             : 
    7008           0 :         bwi_init_statechg(sc, 1);
    7009             : 
    7010           0 :         return (0);
    7011             : }
    7012             : 
    7013             : void
    7014           0 : bwi_init_statechg(struct bwi_softc *sc, int statechg)
    7015             : {
    7016           0 :         struct ieee80211com *ic = &sc->sc_ic;
    7017           0 :         struct ifnet *ifp = &ic->ic_if;
    7018             :         struct bwi_mac *mac;
    7019             :         int error;
    7020             : 
    7021             :         DPRINTF(1, "%s: %s\n", sc->sc_dev.dv_xname, __func__);
    7022             : 
    7023           0 :         error = bwi_stop(sc, statechg);
    7024           0 :         if (error) {
    7025             :                 DPRINTF(1, "%s: can't stop\n", sc->sc_dev.dv_xname);
    7026           0 :                 return;
    7027             :         }
    7028             : 
    7029             :         /* power on cardbus socket */
    7030           0 :         if (sc->sc_enable != NULL)
    7031           0 :                 (*sc->sc_enable)(sc);
    7032             : 
    7033           0 :         bwi_bbp_power_on(sc, BWI_CLOCK_MODE_FAST);
    7034             : 
    7035             :         /* TODO: 2 MAC */
    7036             : 
    7037           0 :         mac = &sc->sc_mac[0];
    7038           0 :         error = bwi_regwin_switch(sc, &mac->mac_regwin, NULL);
    7039           0 :         if (error)
    7040             :                 goto back;
    7041             : 
    7042           0 :         error = bwi_mac_init(mac);
    7043           0 :         if (error)
    7044             :                 goto back;
    7045             : 
    7046           0 :         bwi_bbp_power_on(sc, BWI_CLOCK_MODE_DYN);
    7047             :         
    7048           0 :         IEEE80211_ADDR_COPY(ic->ic_myaddr, LLADDR(ifp->if_sadl));
    7049             : 
    7050           0 :         bwi_set_bssid(sc, bwi_zero_addr);       /* Clear BSSID */
    7051           0 :         bwi_set_addr_filter(sc, BWI_ADDR_FILTER_MYADDR, ic->ic_myaddr);
    7052             : 
    7053           0 :         bwi_mac_reset_hwkeys(mac);
    7054             : 
    7055           0 :         if ((mac->mac_flags & BWI_MAC_F_HAS_TXSTATS) == 0) {
    7056             :                 int i;
    7057             : 
    7058             : #define NRETRY  1000
    7059             :                 /*
    7060             :                  * Drain any possible pending TX status
    7061             :                  */
    7062           0 :                 for (i = 0; i < NRETRY; ++i) {
    7063           0 :                         if ((CSR_READ_4(sc, BWI_TXSTATUS_0) &
    7064           0 :                              BWI_TXSTATUS_0_MORE) == 0)
    7065             :                                 break;
    7066           0 :                         CSR_READ_4(sc, BWI_TXSTATUS_1);
    7067             :                 }
    7068           0 :                 if (i == NRETRY)
    7069           0 :                         printf("%s: can't drain TX status\n",
    7070           0 :                             sc->sc_dev.dv_xname);
    7071             : #undef NRETRY
    7072           0 :         }
    7073             : 
    7074           0 :         if (mac->mac_phy.phy_mode == IEEE80211_MODE_11G)
    7075           0 :                 bwi_mac_updateslot(mac, 1);
    7076             : 
    7077             :         /* Start MAC */
    7078           0 :         error = bwi_mac_start(mac);
    7079           0 :         if (error)
    7080             :                 goto back;
    7081             : 
    7082             :         /* Enable intrs */
    7083           0 :         bwi_enable_intrs(sc, BWI_INIT_INTRS);
    7084             : 
    7085           0 :         ifp->if_flags |= IFF_RUNNING;
    7086           0 :         ifq_clr_oactive(&ifp->if_snd);
    7087             : 
    7088           0 :         if (statechg) {
    7089           0 :                 if (ic->ic_opmode != IEEE80211_M_MONITOR) {
    7090           0 :                         ieee80211_new_state(ic, IEEE80211_S_SCAN, -1);
    7091           0 :                 } else {
    7092           0 :                         ieee80211_new_state(ic, IEEE80211_S_RUN, -1);
    7093             :                 }
    7094             :         } else {
    7095           0 :                 ieee80211_new_state(ic, ic->ic_state, -1);
    7096             :         }
    7097             : 
    7098             : back:
    7099           0 :         if (error)
    7100           0 :                 bwi_stop(sc, 1);
    7101             :         else
    7102           0 :                 bwi_start(ifp);
    7103           0 : }
    7104             : 
    7105             : int
    7106           0 : bwi_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
    7107             : {
    7108           0 :         struct bwi_softc *sc = ifp->if_softc;
    7109           0 :         struct ieee80211com *ic = &sc->sc_ic;
    7110             :         int s, error = 0;
    7111             :         uint8_t chan;
    7112             : 
    7113           0 :         s = splnet();
    7114             : 
    7115           0 :         switch (cmd) {
    7116             :         case SIOCSIFADDR:
    7117           0 :                 ifp->if_flags |= IFF_UP;
    7118             :                 /* FALLTHROUGH */
    7119             :         case SIOCSIFFLAGS:
    7120           0 :                 if (ifp->if_flags & IFF_UP) {
    7121           0 :                         if ((ifp->if_flags & IFF_RUNNING) == 0)
    7122           0 :                                 bwi_init(ifp);
    7123             :                 } else {
    7124           0 :                         if (ifp->if_flags & IFF_RUNNING)
    7125           0 :                                 bwi_stop(sc, 1);
    7126             :                 }
    7127             :                 break;
    7128             :         case SIOCS80211CHANNEL:
    7129             :                 /* allow fast channel switching in monitor mode */
    7130           0 :                 error = ieee80211_ioctl(ifp, cmd, data);
    7131           0 :                 if (error == ENETRESET &&
    7132           0 :                     ic->ic_opmode == IEEE80211_M_MONITOR) {
    7133           0 :                         if ((ifp->if_flags & (IFF_UP | IFF_RUNNING)) ==
    7134             :                             (IFF_UP | IFF_RUNNING)) {
    7135           0 :                                 ic->ic_bss->ni_chan = ic->ic_ibss_chan;
    7136           0 :                                 chan = ieee80211_chan2ieee(ic,
    7137           0 :                                     ic->ic_bss->ni_chan);
    7138           0 :                                 bwi_set_chan(sc, chan);
    7139           0 :                         }
    7140             :                         error = 0;
    7141           0 :                 }
    7142             :                 break;
    7143             :         default:
    7144           0 :                 error = ieee80211_ioctl(ifp, cmd, data);
    7145           0 :                 break;
    7146             :         }
    7147             : 
    7148           0 :         if (error == ENETRESET) {
    7149           0 :                 if ((ifp->if_flags & (IFF_UP | IFF_RUNNING)) ==
    7150             :                     (IFF_UP | IFF_RUNNING))
    7151           0 :                         bwi_init(ifp);
    7152             :                 error = 0;
    7153           0 :         }
    7154             : 
    7155           0 :         splx(s);
    7156             : 
    7157           0 :         return (error);
    7158             : }
    7159             : 
    7160             : void
    7161           0 : bwi_start(struct ifnet *ifp)
    7162             : {
    7163           0 :         struct bwi_softc *sc = ifp->if_softc;
    7164           0 :         struct ieee80211com *ic = &sc->sc_ic;
    7165           0 :         struct bwi_txbuf_data *tbd = &sc->sc_tx_bdata[BWI_TX_DATA_RING];
    7166             :         int trans, idx;
    7167             : 
    7168           0 :         if (ifq_is_oactive(&ifp->if_snd) || (ifp->if_flags & IFF_RUNNING) == 0)
    7169           0 :                 return;
    7170             : 
    7171             :         trans = 0;
    7172           0 :         idx = tbd->tbd_idx;
    7173             : 
    7174           0 :         while (tbd->tbd_buf[idx].tb_mbuf == NULL) {
    7175             :                 struct ieee80211_frame *wh;
    7176           0 :                 struct ieee80211_node *ni;
    7177             :                 struct ieee80211_key *k;
    7178             :                 struct mbuf *m;
    7179             :                 int mgt_pkt = 0;
    7180             : 
    7181           0 :                 m = mq_dequeue(&ic->ic_mgtq);
    7182           0 :                 if (m != NULL) {
    7183           0 :                         ni = m->m_pkthdr.ph_cookie;
    7184             : 
    7185             :                         mgt_pkt = 1;
    7186           0 :                 } else {
    7187             :                         struct ether_header *eh;
    7188             : 
    7189           0 :                         if (ic->ic_state != IEEE80211_S_RUN)
    7190           0 :                                 break;
    7191             : 
    7192           0 :                         IFQ_DEQUEUE(&ifp->if_snd, m);
    7193           0 :                         if (m == NULL)
    7194           0 :                                 break;
    7195             : 
    7196           0 :                         if (m->m_len < sizeof(*eh)) {
    7197           0 :                                 m = m_pullup(m, sizeof(*eh));
    7198           0 :                                 if (m == NULL) {
    7199           0 :                                         ifp->if_oerrors++;
    7200           0 :                                         continue;
    7201             :                                 }
    7202             :                         }
    7203           0 :                         eh = mtod(m, struct ether_header *);
    7204             : 
    7205           0 :                         ni = ieee80211_find_txnode(ic, eh->ether_dhost);
    7206           0 :                         if (ni == NULL) {
    7207           0 :                                 m_freem(m);
    7208           0 :                                 ifp->if_oerrors++;
    7209           0 :                                 continue;
    7210             :                         }
    7211             : 
    7212             :                         /* TODO: PS */
    7213             : #if NBPFILTER > 0
    7214           0 :                         if (ifp->if_bpf != NULL)
    7215           0 :                                 bpf_mtap(ifp->if_bpf, m, BPF_DIRECTION_OUT);
    7216             : #endif
    7217           0 :                         m = ieee80211_encap(ifp, m, &ni);
    7218           0 :                         if (m == NULL)
    7219           0 :                                 continue;
    7220           0 :                 }
    7221             : #if NBPFILTER > 0
    7222           0 :                 if (ic->ic_rawbpf != NULL)
    7223           0 :                         bpf_mtap(ic->ic_rawbpf, m, BPF_DIRECTION_OUT);
    7224             : #endif
    7225           0 :                 wh = mtod(m, struct ieee80211_frame *);
    7226           0 :                 if (wh->i_fc[1] & IEEE80211_FC1_PROTECTED) {
    7227           0 :                         k = ieee80211_get_txkey(ic, wh, ni);
    7228           0 :                         if ((m = ieee80211_encrypt(ic, m, k)) == NULL)
    7229           0 :                                 return;
    7230             :                 }
    7231             :                 wh = NULL;      /* Catch any invalid use */
    7232             : 
    7233           0 :                 if (mgt_pkt) {
    7234           0 :                         ieee80211_release_node(ic, ni);
    7235           0 :                         ni = NULL;
    7236           0 :                 }
    7237             : 
    7238           0 :                 if (bwi_encap(sc, idx, m, ni) != 0) {
    7239             :                         /* 'm' is freed in bwi_encap() if we reach here */
    7240           0 :                         if (ni != NULL)
    7241           0 :                                 ieee80211_release_node(ic, ni);
    7242           0 :                         ifp->if_oerrors++;
    7243           0 :                         continue;
    7244             :                 }
    7245             : 
    7246             :                 trans = 1;
    7247           0 :                 tbd->tbd_used++;
    7248           0 :                 idx = (idx + 1) % BWI_TX_NDESC;
    7249             : 
    7250           0 :                 if (tbd->tbd_used + BWI_TX_NSPRDESC >= BWI_TX_NDESC) {
    7251           0 :                         ifq_set_oactive(&ifp->if_snd);
    7252           0 :                         break;
    7253             :                 }
    7254           0 :         }
    7255           0 :         tbd->tbd_idx = idx;
    7256             : 
    7257           0 :         if (trans)
    7258           0 :                 sc->sc_tx_timer = 5;
    7259           0 :         ifp->if_timer = 1;
    7260           0 : }
    7261             : 
    7262             : void
    7263           0 : bwi_watchdog(struct ifnet *ifp)
    7264             : {
    7265           0 :         struct bwi_softc *sc = ifp->if_softc;
    7266             : 
    7267           0 :         ifp->if_timer = 0;
    7268             : 
    7269           0 :         if ((ifp->if_flags & IFF_RUNNING) == 0)
    7270           0 :                 return;
    7271             : 
    7272           0 :         if (sc->sc_tx_timer) {
    7273           0 :                 if (--sc->sc_tx_timer == 0) {
    7274           0 :                         printf("%s: watchdog timeout\n",
    7275           0 :                             sc->sc_dev.dv_xname);
    7276           0 :                         ifp->if_oerrors++;
    7277             :                         /* TODO */
    7278           0 :                 } else
    7279           0 :                         ifp->if_timer = 1;
    7280             :         }
    7281             : 
    7282           0 :         ieee80211_watchdog(ifp);
    7283           0 : }
    7284             : 
    7285             : void
    7286           0 : bwi_newstate_begin(struct bwi_softc *sc, enum ieee80211_state nstate)
    7287             : {
    7288           0 :         timeout_del(&sc->sc_scan_ch);
    7289           0 :         timeout_del(&sc->sc_calib_ch);
    7290             : 
    7291           0 :         bwi_led_newstate(sc, nstate);
    7292             : 
    7293           0 :         if (nstate == IEEE80211_S_INIT)
    7294           0 :                 sc->sc_txpwrcb_type = BWI_TXPWR_INIT;
    7295           0 : }
    7296             : 
    7297             : int
    7298           0 : bwi_stop(struct bwi_softc *sc, int state_chg)
    7299             : {
    7300           0 :         struct ieee80211com *ic = &sc->sc_ic;
    7301           0 :         struct ifnet *ifp = &ic->ic_if;
    7302             :         struct bwi_mac *mac;
    7303             :         int i, error, pwr_off = 0;
    7304             : 
    7305             :         DPRINTF(1, "%s: %s\n", sc->sc_dev.dv_xname, __func__);
    7306             : 
    7307           0 :         if (state_chg)
    7308           0 :                 ieee80211_new_state(ic, IEEE80211_S_INIT, -1);
    7309             :         else
    7310           0 :                 bwi_newstate_begin(sc, IEEE80211_S_INIT);
    7311             : 
    7312           0 :         if (ifp->if_flags & IFF_RUNNING) {
    7313           0 :                 KASSERT(sc->sc_cur_regwin->rw_type == BWI_REGWIN_T_MAC);
    7314           0 :                 mac = (struct bwi_mac *)sc->sc_cur_regwin;
    7315             : 
    7316           0 :                 bwi_disable_intrs(sc, BWI_ALL_INTRS);
    7317           0 :                 CSR_READ_4(sc, BWI_MAC_INTR_MASK);
    7318           0 :                 bwi_mac_stop(mac);
    7319           0 :         }
    7320             : 
    7321           0 :         for (i = 0; i < sc->sc_nmac; ++i) {
    7322           0 :                 struct bwi_regwin *old_rw;
    7323             : 
    7324           0 :                 mac = &sc->sc_mac[i];
    7325           0 :                 if ((mac->mac_flags & BWI_MAC_F_INITED) == 0)
    7326           0 :                         continue;
    7327             : 
    7328           0 :                 error = bwi_regwin_switch(sc, &mac->mac_regwin, &old_rw);
    7329           0 :                 if (error)
    7330           0 :                         continue;
    7331             : 
    7332           0 :                 bwi_mac_shutdown(mac);
    7333             :                 pwr_off = 1;
    7334             : 
    7335           0 :                 bwi_regwin_switch(sc, old_rw, NULL);
    7336           0 :         }
    7337             : 
    7338           0 :         if (pwr_off)
    7339           0 :                 bwi_bbp_power_off(sc);
    7340             : 
    7341           0 :         sc->sc_tx_timer = 0;
    7342           0 :         ifp->if_timer = 0;
    7343           0 :         ifp->if_flags &= ~IFF_RUNNING;
    7344           0 :         ifq_clr_oactive(&ifp->if_snd);
    7345             : 
    7346             :         /* power off cardbus socket */
    7347           0 :         if (sc->sc_disable)
    7348           0 :                 sc->sc_disable(sc);
    7349             : 
    7350           0 :         return (0);
    7351             : }
    7352             : 
    7353             : int
    7354           0 : bwi_newstate(struct ieee80211com *ic, enum ieee80211_state nstate, int arg)
    7355             : {
    7356           0 :         struct bwi_softc *sc = ic->ic_if.if_softc;
    7357             :         struct ieee80211_node *ni;
    7358             :         int error;
    7359             :         uint8_t chan;
    7360             : 
    7361           0 :         timeout_del(&sc->sc_amrr_ch);
    7362             : 
    7363           0 :         bwi_newstate_begin(sc, nstate);
    7364             : 
    7365           0 :         if (nstate == IEEE80211_S_INIT)
    7366             :                 goto back;
    7367             : 
    7368           0 :         chan = ieee80211_chan2ieee(ic, ic->ic_bss->ni_chan);
    7369           0 :         error = bwi_set_chan(sc, chan);
    7370           0 :         if (error) {
    7371           0 :                 printf("%s: can't set channel to %u\n",
    7372           0 :                     sc->sc_dev.dv_xname,
    7373           0 :                     ieee80211_chan2ieee(ic, ic->ic_des_chan));
    7374           0 :                 return (error);
    7375             :         }
    7376             : 
    7377           0 :         if (ic->ic_opmode == IEEE80211_M_MONITOR) {
    7378             :                 /* Nothing to do */
    7379           0 :         } else if (nstate == IEEE80211_S_RUN) {
    7380             :                 struct bwi_mac *mac;
    7381             : 
    7382           0 :                 ni = ic->ic_bss;
    7383             : 
    7384           0 :                 bwi_set_bssid(sc, ic->ic_bss->ni_bssid);
    7385             : 
    7386           0 :                 KASSERT(sc->sc_cur_regwin->rw_type == BWI_REGWIN_T_MAC);
    7387           0 :                 mac = (struct bwi_mac *)sc->sc_cur_regwin;
    7388             : 
    7389             :                 /* Initial TX power calibration */
    7390           0 :                 bwi_mac_calibrate_txpower(mac, BWI_TXPWR_INIT);
    7391             : #ifdef notyet
    7392             :                 sc->sc_txpwrcb_type = BWI_TXPWR_FORCE;
    7393             : #else
    7394           0 :                 sc->sc_txpwrcb_type = BWI_TXPWR_CALIB;
    7395             : #endif
    7396           0 :                 if (ic->ic_opmode == IEEE80211_M_STA) {
    7397             :                         /* fake a join to init the tx rate */
    7398           0 :                         bwi_newassoc(ic, ni, 1);
    7399           0 :                 }
    7400             : 
    7401           0 :                 if (ic->ic_opmode != IEEE80211_M_MONITOR) {
    7402             :                         /* start automatic rate control timer */
    7403           0 :                         if (ic->ic_fixed_rate == -1)
    7404           0 :                                 timeout_add_msec(&sc->sc_amrr_ch, 500);
    7405             :                 }
    7406           0 :         } else
    7407           0 :                 bwi_set_bssid(sc, bwi_zero_addr);
    7408             : 
    7409             : back:
    7410           0 :         error = sc->sc_newstate(ic, nstate, arg);
    7411             : 
    7412           0 :         if (nstate == IEEE80211_S_SCAN) {
    7413           0 :                 timeout_add_msec(&sc->sc_scan_ch, sc->sc_dwell_time);
    7414           0 :         } else if (nstate == IEEE80211_S_RUN) {
    7415             :                 /* XXX 15 seconds */
    7416           0 :                 timeout_add_sec(&sc->sc_calib_ch, 1);
    7417           0 :         }
    7418             : 
    7419           0 :         return (error);
    7420           0 : }
    7421             : 
    7422             : int
    7423           0 : bwi_media_change(struct ifnet *ifp)
    7424             : {
    7425             :         int error;
    7426             : 
    7427           0 :         error = ieee80211_media_change(ifp);
    7428           0 :         if (error != ENETRESET)
    7429           0 :                 return (error);
    7430             : 
    7431           0 :         if ((ifp->if_flags & (IFF_UP | IFF_RUNNING)) == (IFF_UP | IFF_RUNNING))
    7432           0 :                 bwi_init(ifp);
    7433             : 
    7434           0 :         return (0);
    7435           0 : }
    7436             : 
    7437             : void
    7438           0 : bwi_iter_func(void *arg, struct ieee80211_node *ni)
    7439             : {
    7440           0 :         struct bwi_softc *sc = arg;
    7441           0 :         struct bwi_node *bn = (struct bwi_node *)ni;
    7442             : 
    7443           0 :         ieee80211_amrr_choose(&sc->sc_amrr, ni, &bn->amn);
    7444           0 : }
    7445             : 
    7446             : void
    7447           0 : bwi_amrr_timeout(void *arg)
    7448             : {
    7449           0 :         struct bwi_softc *sc = arg;
    7450           0 :         struct ieee80211com *ic = &sc->sc_ic;
    7451             : 
    7452           0 :         if (ic->ic_opmode == IEEE80211_M_STA)
    7453           0 :                 bwi_iter_func(sc, ic->ic_bss);
    7454             : #ifndef IEEE80211_STA_ONLY
    7455             :         else
    7456           0 :                 ieee80211_iterate_nodes(ic, bwi_iter_func, sc);
    7457             : #endif
    7458             : 
    7459           0 :         timeout_add_msec(&sc->sc_amrr_ch, 500);
    7460           0 : }
    7461             : 
    7462             : void
    7463           0 : bwi_newassoc(struct ieee80211com *ic, struct ieee80211_node *ni, int isnew)
    7464             : {
    7465           0 :         struct bwi_softc *sc = ic->ic_if.if_softc;
    7466             :         int i;
    7467             : 
    7468             :         DPRINTF(1, "%s: %s\n", sc->sc_dev.dv_xname, __func__);
    7469             : 
    7470           0 :         ieee80211_amrr_node_init(&sc->sc_amrr, &((struct bwi_node *)ni)->amn);
    7471             : 
    7472             :         /* set rate to some reasonable initial value */
    7473           0 :         for (i = ni->ni_rates.rs_nrates - 1;
    7474           0 :             i > 0 && (ni->ni_rates.rs_rates[i] & IEEE80211_RATE_VAL) > 72;
    7475           0 :             i--);
    7476             : 
    7477           0 :         ni->ni_txrate = i;
    7478           0 : }
    7479             : 
    7480             : struct ieee80211_node *
    7481           0 : bwi_node_alloc(struct ieee80211com *ic)
    7482             : {
    7483             :         struct bwi_node *bn;
    7484             : 
    7485           0 :         bn = malloc(sizeof(*bn), M_DEVBUF, M_NOWAIT | M_ZERO);
    7486           0 :         if (bn == NULL)
    7487           0 :                 return (NULL);
    7488             : 
    7489           0 :         return ((struct ieee80211_node *)bn);
    7490           0 : }
    7491             : 
    7492             : struct uvm_constraint_range bwi_constraint = { 0x0, (0x40000000 - 1) };
    7493             : struct kmem_pa_mode bwi_pa_mode = {
    7494             :         .kp_align = BWI_RING_ALIGN,
    7495             :         .kp_constraint = &bwi_constraint,
    7496             :         .kp_zero = 1
    7497             : };
    7498             : 
    7499             : int
    7500           0 : bwi_dma_alloc(struct bwi_softc *sc)
    7501             : {
    7502             :         int error, i, has_txstats;
    7503             :         bus_size_t tx_ring_sz, rx_ring_sz, desc_sz = 0;
    7504             :         uint32_t txrx_ctrl_step = 0;
    7505             :         int s;
    7506             : 
    7507             :         has_txstats = 0;
    7508           0 :         for (i = 0; i < sc->sc_nmac; ++i) {
    7509           0 :                 if (sc->sc_mac[i].mac_flags & BWI_MAC_F_HAS_TXSTATS) {
    7510             :                         has_txstats = 1;
    7511           0 :                         break;
    7512             :                 }
    7513             :         }
    7514             : 
    7515           0 :         switch (sc->sc_bus_space) {
    7516             :         case BWI_BUS_SPACE_30BIT:
    7517             :                 /* 
    7518             :                  * 30bit devices must use bounce buffers but
    7519             :                  * otherwise work like 32bit devices.
    7520             :                  */
    7521           0 :                 sc->sc_newbuf = bwi_newbuf30;
    7522             : 
    7523             :                 /* XXX implement txstats for 30bit? */
    7524           0 :                 has_txstats = 0;
    7525             : 
    7526             :                 /* FALLTHROUGH */
    7527             :         case BWI_BUS_SPACE_32BIT:
    7528             :                 desc_sz = sizeof(struct bwi_desc32);
    7529             :                 txrx_ctrl_step = 0x20;
    7530             : 
    7531           0 :                 sc->sc_init_tx_ring = bwi_init_tx_ring32;
    7532           0 :                 sc->sc_free_tx_ring = bwi_free_tx_ring32;
    7533           0 :                 sc->sc_init_rx_ring = bwi_init_rx_ring32;
    7534           0 :                 sc->sc_free_rx_ring = bwi_free_rx_ring32;
    7535           0 :                 if (sc->sc_newbuf == NULL)
    7536           0 :                         sc->sc_newbuf = bwi_newbuf;
    7537           0 :                 sc->sc_setup_rxdesc = bwi_setup_rx_desc32;
    7538           0 :                 sc->sc_setup_txdesc = bwi_setup_tx_desc32;
    7539           0 :                 sc->sc_rxeof = bwi_rxeof32;
    7540           0 :                 sc->sc_start_tx = bwi_start_tx32;
    7541           0 :                 if (has_txstats) {
    7542           0 :                         sc->sc_init_txstats = bwi_init_txstats32;
    7543           0 :                         sc->sc_free_txstats = bwi_free_txstats32;
    7544           0 :                         sc->sc_txeof_status = bwi_txeof_status32;
    7545           0 :                 }
    7546             :                 break;
    7547             : 
    7548             :         default:
    7549           0 :                 panic("unsupported bus space type %d", sc->sc_bus_space);
    7550             :         }
    7551             : 
    7552           0 :         KASSERT(desc_sz != 0);
    7553           0 :         KASSERT(txrx_ctrl_step != 0);
    7554             : 
    7555             :         tx_ring_sz = roundup(desc_sz * BWI_TX_NDESC, BWI_RING_ALIGN);
    7556             :         rx_ring_sz = roundup(desc_sz * BWI_RX_NDESC, BWI_RING_ALIGN);
    7557             : 
    7558           0 :         s = splvm();
    7559             : 
    7560             : #define TXRX_CTRL(idx)  (BWI_TXRX_CTRL_BASE + (idx) * txrx_ctrl_step)
    7561             :         /*
    7562             :          * Create TX ring DMA stuffs
    7563             :          */
    7564           0 :         for (i = 0; i < BWI_TX_NRING; ++i) {
    7565           0 :                 error = bwi_dma_ring_alloc(sc,
    7566           0 :                     &sc->sc_tx_rdata[i], tx_ring_sz, TXRX_CTRL(i));
    7567           0 :                 if (error) {
    7568           0 :                         printf("%s: %dth TX ring DMA alloc failed\n",
    7569           0 :                             sc->sc_dev.dv_xname, i);
    7570           0 :                         bwi_dma_free(sc);
    7571           0 :                         splx(s);
    7572           0 :                         return (error);
    7573             :                 }
    7574             :         }
    7575             : 
    7576             :         /*
    7577             :          * Create RX ring DMA stuffs
    7578             :          */
    7579           0 :         error = bwi_dma_ring_alloc(sc, &sc->sc_rx_rdata,
    7580             :             rx_ring_sz, TXRX_CTRL(0));
    7581           0 :         if (error) {
    7582           0 :                 printf("%s: RX ring DMA alloc failed\n", sc->sc_dev.dv_xname);
    7583           0 :                 bwi_dma_free(sc);
    7584           0 :                 splx(s);
    7585           0 :                 return (error);
    7586             :         }
    7587             : 
    7588           0 :         if (has_txstats) {
    7589           0 :                 error = bwi_dma_txstats_alloc(sc, TXRX_CTRL(3), desc_sz);
    7590           0 :                 if (error) {
    7591           0 :                         printf("%s: TX stats DMA alloc failed\n",
    7592           0 :                             sc->sc_dev.dv_xname);
    7593           0 :                         bwi_dma_free(sc);
    7594           0 :                         splx(s);
    7595           0 :                         return (error);
    7596             :                 }
    7597             :         }
    7598             : #undef TXRX_CTRL
    7599             : 
    7600           0 :         if (sc->sc_bus_space == BWI_BUS_SPACE_30BIT)
    7601           0 :                 error = bwi_dma_mbuf_create30(sc);
    7602             :         else
    7603           0 :                 error = bwi_dma_mbuf_create(sc);
    7604           0 :         if (error)
    7605           0 :                 bwi_dma_free(sc);
    7606             : 
    7607           0 :         splx(s);
    7608             : 
    7609           0 :         return (error);
    7610           0 : }
    7611             : 
    7612             : void
    7613           0 : bwi_dma_free(struct bwi_softc *sc)
    7614             : {
    7615             :         struct bwi_ring_data *rd;
    7616             :         int i;
    7617             : 
    7618           0 :         for (i = 0; i < BWI_TX_NRING; ++i) {
    7619           0 :                 rd = &sc->sc_tx_rdata[i];
    7620             : 
    7621           0 :                 if (rd->rdata_desc != NULL) {
    7622           0 :                         bus_dmamap_unload(sc->sc_dmat, rd->rdata_dmap);
    7623           0 :                         km_free(rd->rdata_desc, rd->rdata_ring_sz,
    7624             :                             &kv_intrsafe, &bwi_pa_mode);
    7625           0 :                         rd->rdata_desc = NULL;
    7626           0 :                 }
    7627             :         }
    7628             : 
    7629           0 :         rd = &sc->sc_rx_rdata;
    7630             : 
    7631           0 :         if (rd->rdata_desc != NULL) {
    7632           0 :                 bus_dmamap_unload(sc->sc_dmat, rd->rdata_dmap);
    7633           0 :                 km_free(rd->rdata_desc, rd->rdata_ring_sz,
    7634             :                     &kv_intrsafe, &bwi_pa_mode);
    7635           0 :                 rd->rdata_desc = NULL;
    7636           0 :         }
    7637             : 
    7638           0 :         bwi_dma_txstats_free(sc);
    7639             : 
    7640           0 :         if (sc->sc_bus_space == BWI_BUS_SPACE_30BIT) {
    7641           0 :                 for (i = 0; i < BWI_TX_NRING; ++i) {
    7642           0 :                         if (sc->sc_bounce_tx_data[i] != NULL) {
    7643           0 :                                 km_free(sc->sc_bounce_tx_data[i],
    7644             :                                     BWI_TX_NDESC * MCLBYTES,
    7645             :                                     &kv_intrsafe, &bwi_pa_mode);
    7646           0 :                                 sc->sc_bounce_tx_data[i] = NULL;
    7647           0 :                         }
    7648             :                 }
    7649             : 
    7650           0 :                 if (sc->sc_bounce_rx_data != NULL) {
    7651           0 :                         km_free(sc->sc_bounce_rx_data, BWI_RX_NDESC * MCLBYTES,
    7652             :                             &kv_intrsafe, &bwi_pa_mode);
    7653           0 :                         sc->sc_bounce_rx_data = NULL;
    7654           0 :                 }
    7655             :         }
    7656           0 : }
    7657             : 
    7658             : int
    7659           0 : bwi_dma_ring_alloc(struct bwi_softc *sc,
    7660             :     struct bwi_ring_data *rd, bus_size_t size, uint32_t txrx_ctrl)
    7661             : {
    7662             :         int error;
    7663             : 
    7664             :         /* Allocate rings below 1GB so 30bit devices can access them.*/
    7665           0 :         rd->rdata_desc = (caddr_t)km_alloc(size, &kv_intrsafe, &bwi_pa_mode,
    7666             :             &kd_nowait);
    7667           0 :         if (rd->rdata_desc == NULL) {
    7668           0 :                 printf(": could not allocate ring DMA memory\n");
    7669           0 :                 return (ENOMEM);
    7670             :         }
    7671             : 
    7672           0 :         error = bus_dmamap_create(sc->sc_dmat, size, 1, size, 0,
    7673             :             BUS_DMA_NOWAIT, &rd->rdata_dmap);
    7674           0 :         if (error) {
    7675           0 :                 printf(": cannot create ring DMA map (error %d)\n", error);
    7676           0 :                 km_free(rd->rdata_desc, size, &kv_intrsafe, &bwi_pa_mode);
    7677           0 :                 rd->rdata_desc = NULL;
    7678           0 :                 return (error);
    7679             :         }
    7680             : 
    7681           0 :         error = bus_dmamap_load(sc->sc_dmat, rd->rdata_dmap, rd->rdata_desc,
    7682             :             size, NULL, BUS_DMA_WAITOK);
    7683           0 :         if (error) {
    7684           0 :                 printf("%s: can't load DMA mem\n", sc->sc_dev.dv_xname);
    7685           0 :                 bus_dmamap_destroy(sc->sc_dmat, rd->rdata_dmap);
    7686           0 :                 km_free(rd->rdata_desc, size, &kv_intrsafe, &bwi_pa_mode);
    7687           0 :                 rd->rdata_desc = NULL;
    7688           0 :                 return (error);
    7689             :         }
    7690             : 
    7691           0 :         rd->rdata_ring_sz = size;
    7692           0 :         rd->rdata_paddr = rd->rdata_dmap->dm_segs[0].ds_addr;
    7693           0 :         rd->rdata_txrx_ctrl = txrx_ctrl;
    7694             : 
    7695           0 :         return (0);
    7696           0 : }
    7697             : 
    7698             : int
    7699           0 : bwi_dma_txstats_alloc(struct bwi_softc *sc, uint32_t ctrl_base,
    7700             :     bus_size_t desc_sz)
    7701             : {
    7702             :         struct bwi_txstats_data *st;
    7703             :         bus_size_t dma_size;
    7704           0 :         int error, nsegs;
    7705             : 
    7706           0 :         st = malloc(sizeof(*st), M_DEVBUF, M_WAITOK | M_ZERO);
    7707           0 :         sc->sc_txstats = st;
    7708             : 
    7709             :         /*
    7710             :          * Create TX stats descriptor DMA stuffs
    7711             :          */
    7712           0 :         dma_size = roundup(desc_sz * BWI_TXSTATS_NDESC, BWI_RING_ALIGN);
    7713             : 
    7714           0 :         error = bus_dmamap_create(sc->sc_dmat, dma_size, 1, dma_size, 0,
    7715             :             BUS_DMA_NOWAIT, &st->stats_ring_dmap);
    7716           0 :         if (error) {
    7717           0 :                 printf("%s: can't create txstats ring DMA mem\n",
    7718           0 :                     sc->sc_dev.dv_xname);
    7719           0 :                 return (error);
    7720             :         }
    7721             : 
    7722           0 :         error = bus_dmamem_alloc(sc->sc_dmat, dma_size, BWI_RING_ALIGN, 0,
    7723             :              &st->stats_ring_seg, 1, &nsegs, BUS_DMA_NOWAIT | BUS_DMA_ZERO);
    7724           0 :         if (error) {
    7725           0 :                 printf("%s: can't allocate txstats ring DMA mem\n",
    7726           0 :                     sc->sc_dev.dv_xname);
    7727           0 :                 return (error);
    7728             :         }
    7729             : 
    7730           0 :         error = bus_dmamem_map(sc->sc_dmat, &st->stats_ring_seg, nsegs,
    7731             :             dma_size, (caddr_t *)&st->stats_ring, BUS_DMA_NOWAIT);
    7732           0 :         if (error) {
    7733           0 :                 printf("%s: can't map txstats ring DMA mem\n",
    7734           0 :                     sc->sc_dev.dv_xname);
    7735           0 :                 return (error);
    7736             :         }
    7737             : 
    7738           0 :         error = bus_dmamap_load(sc->sc_dmat, st->stats_ring_dmap,
    7739             :             st->stats_ring, dma_size, NULL, BUS_DMA_WAITOK);
    7740           0 :         if (error) {
    7741           0 :                 printf("%s: can't load txstats ring DMA mem\n",
    7742           0 :                     sc->sc_dev.dv_xname);
    7743           0 :                 bus_dmamem_free(sc->sc_dmat, &st->stats_ring_seg, nsegs);
    7744           0 :                 return (error);
    7745             :         }
    7746             : 
    7747           0 :         st->stats_ring_paddr = st->stats_ring_dmap->dm_segs[0].ds_addr;
    7748             : 
    7749             :         /*
    7750             :          * Create TX stats DMA stuffs
    7751             :          */
    7752             :         dma_size = roundup(sizeof(struct bwi_txstats) * BWI_TXSTATS_NDESC,
    7753             :             BWI_ALIGN);
    7754             : 
    7755           0 :         error = bus_dmamap_create(sc->sc_dmat, dma_size, 1, dma_size, 0,
    7756             :             BUS_DMA_NOWAIT, &st->stats_dmap);
    7757           0 :         if (error) {
    7758           0 :                 printf("%s: can't create txstats ring DMA mem\n",
    7759           0 :                     sc->sc_dev.dv_xname);
    7760           0 :                 return (error);
    7761             :         }
    7762           0 :         error = bus_dmamem_alloc(sc->sc_dmat, dma_size, BWI_ALIGN, 0,
    7763             :             &st->stats_seg, 1, &nsegs, BUS_DMA_NOWAIT | BUS_DMA_ZERO);
    7764           0 :         if (error) {
    7765           0 :                 printf("%s: can't allocate txstats DMA mem\n",
    7766           0 :                     sc->sc_dev.dv_xname);
    7767           0 :                 return (error);
    7768             :         }
    7769             : 
    7770           0 :         error = bus_dmamem_map(sc->sc_dmat, &st->stats_seg, nsegs,
    7771             :             dma_size, (caddr_t *)&st->stats, BUS_DMA_NOWAIT);
    7772           0 :         if (error) {
    7773           0 :                 printf("%s: can't map txstats DMA mem\n", sc->sc_dev.dv_xname);
    7774           0 :                 return (error);
    7775             :         }
    7776             : 
    7777           0 :         error = bus_dmamap_load(sc->sc_dmat, st->stats_dmap, st->stats,
    7778             :             dma_size, NULL, BUS_DMA_WAITOK);
    7779           0 :         if (error) {
    7780           0 :                 printf("%s: can't load txstats DMA mem\n", sc->sc_dev.dv_xname);
    7781           0 :                 bus_dmamem_free(sc->sc_dmat, &st->stats_seg, nsegs);
    7782           0 :                 return (error);
    7783             :         }
    7784             : 
    7785           0 :         st->stats_paddr = st->stats_dmap->dm_segs[0].ds_addr;
    7786           0 :         st->stats_ctrl_base = ctrl_base;
    7787             : 
    7788           0 :         return (0);
    7789           0 : }
    7790             : 
    7791             : void
    7792           0 : bwi_dma_txstats_free(struct bwi_softc *sc)
    7793             : {
    7794             :         struct bwi_txstats_data *st;
    7795             : 
    7796           0 :         if (sc->sc_txstats == NULL)
    7797           0 :                 return;
    7798             :         st = sc->sc_txstats;
    7799             : 
    7800           0 :         bus_dmamap_unload(sc->sc_dmat, st->stats_ring_dmap);
    7801           0 :         bus_dmamem_free(sc->sc_dmat, &st->stats_ring_seg, 1);
    7802             : 
    7803           0 :         bus_dmamap_unload(sc->sc_dmat, st->stats_dmap);
    7804           0 :         bus_dmamem_free(sc->sc_dmat, &st->stats_seg, 1);
    7805             : 
    7806           0 :         free(st, M_DEVBUF, sizeof *st);
    7807           0 : }
    7808             : 
    7809             : int
    7810           0 : bwi_dma_mbuf_create30(struct bwi_softc *sc)
    7811             : {
    7812             :         int i, j, k, error;
    7813             : 
    7814           0 :         for (i = 0; i < BWI_TX_NRING; ++i) {
    7815           0 :                 struct bwi_txbuf_data *tbd = &sc->sc_tx_bdata[i];
    7816             : 
    7817           0 :                 sc->sc_bounce_tx_data[i] = (caddr_t)km_alloc(
    7818             :                     BWI_TX_NDESC * MCLBYTES, &kv_intrsafe,
    7819             :                     &bwi_pa_mode, &kd_waitok);
    7820           0 :                 if (sc->sc_bounce_tx_data[i] == NULL) {
    7821           0 :                         printf(": could not allocate TX mbuf bounce buffer\n");
    7822             :                         error = ENOMEM;
    7823           0 :                         break;
    7824             :                 }
    7825             : 
    7826           0 :                 for (j = 0; j < BWI_TX_NDESC; ++j) {
    7827           0 :                         error = bus_dmamap_create(sc->sc_dmat, MCLBYTES,
    7828             :                             1, MCLBYTES, 0, BUS_DMA_NOWAIT,
    7829             :                             &tbd->tbd_buf[j].tb_dmap);
    7830           0 :                         if (error) {
    7831           0 :                                 printf(": cannot create TX mbuf DMA map\n");
    7832           0 :                                 for (k = 0; k < j; ++k) {
    7833           0 :                                         bus_dmamap_destroy(sc->sc_dmat,
    7834             :                                             tbd->tbd_buf[k].tb_dmap);
    7835             :                                 }
    7836             :                                 break;
    7837             :                         }
    7838             :                 }
    7839           0 :         }
    7840           0 :         if (error) {
    7841           0 :                 bwi_dma_mbuf_destroy(sc, i, 0);
    7842           0 :                 for (j = 0; j < i; ++j)
    7843           0 :                         km_free(sc->sc_bounce_tx_data[j], BWI_TX_NDESC,
    7844             :                             &kv_intrsafe, &bwi_pa_mode);
    7845           0 :                 return (error);
    7846             :         }
    7847             : 
    7848           0 :         for (i = 0; i < BWI_TX_NRING; ++i) {
    7849           0 :                 struct bwi_txbuf_data *tbd = &sc->sc_tx_bdata[i];
    7850             : 
    7851           0 :                 for (j = 0; j < BWI_TX_NDESC; ++j) {
    7852           0 :                         struct bwi_txbuf *tb = &tbd->tbd_buf[j];
    7853             : 
    7854           0 :                         error = bus_dmamap_load(sc->sc_dmat, tb->tb_dmap,
    7855             :                             sc->sc_bounce_tx_data[i] + (MCLBYTES * j),
    7856             :                             MCLBYTES, NULL, BUS_DMA_NOWAIT);
    7857           0 :                         if (error) {
    7858           0 :                                 printf(": cannot create TX mbuf DMA map\n");
    7859           0 :                                 for (k = 0; k < j; ++k) {
    7860           0 :                                         bus_dmamap_destroy(sc->sc_dmat,
    7861             :                                             tbd->tbd_buf[k].tb_dmap);
    7862             :                                 }
    7863           0 :                                 break;
    7864             :                         }
    7865           0 :                 }
    7866             :         }
    7867           0 :         if (error) {
    7868           0 :                 bwi_dma_mbuf_destroy(sc, BWI_TX_NRING, 0);
    7869           0 :                 for (i = 0; i < BWI_TX_NRING; ++i)
    7870           0 :                         km_free(sc->sc_bounce_tx_data[i], BWI_TX_NDESC,
    7871             :                             &kv_intrsafe, &bwi_pa_mode);
    7872           0 :                 return (error);
    7873             :         }
    7874             : 
    7875           0 :         sc->sc_bounce_rx_data = (caddr_t)km_alloc(BWI_RX_NDESC * MCLBYTES,
    7876             :             &kv_intrsafe, &bwi_pa_mode, &kd_waitok);
    7877           0 :         if (sc->sc_bounce_rx_data == NULL) {
    7878           0 :                 printf(": could not allocate RX mbuf bounce buffer\n");
    7879           0 :                 bwi_dma_mbuf_destroy(sc, BWI_TX_NRING, 0);
    7880           0 :                 for (i = 0; i < BWI_TX_NRING; ++i)
    7881           0 :                         km_free(sc->sc_bounce_tx_data[i], BWI_TX_NDESC,
    7882             :                             &kv_intrsafe, &bwi_pa_mode);
    7883           0 :                 return (ENOMEM);
    7884             :         }
    7885             : 
    7886           0 :         for (i = 0; i < BWI_RX_NDESC; ++i) {
    7887           0 :                 error = bus_dmamap_create(sc->sc_dmat, MCLBYTES, 1,
    7888             :                     MCLBYTES, 0, BUS_DMA_NOWAIT,
    7889             :                     &sc->sc_rx_bdata.rbd_buf[i].rb_dmap);
    7890           0 :                 if (error) {
    7891           0 :                         printf(": cannot create RX mbuf DMA map\n");
    7892           0 :                         for (j = 0; j < i; ++j) {
    7893           0 :                                 bus_dmamap_destroy(sc->sc_dmat,
    7894             :                                     sc->sc_rx_bdata.rbd_buf[j].rb_dmap);
    7895             :                         }
    7896             :                         break;
    7897             :                 }
    7898             :         }
    7899           0 :         if (error) {
    7900           0 :                 bwi_dma_mbuf_destroy(sc, BWI_TX_NRING, 0);
    7901           0 :                 for (i = 0; i < BWI_TX_NRING; ++i)
    7902           0 :                         km_free(sc->sc_bounce_tx_data[i], BWI_TX_NDESC,
    7903             :                             &kv_intrsafe, &bwi_pa_mode);
    7904           0 :                 km_free(sc->sc_bounce_rx_data, BWI_RX_NDESC * MCLBYTES,
    7905             :                     &kv_intrsafe, &bwi_pa_mode);
    7906           0 :                 return (error);
    7907             :         }
    7908             : 
    7909           0 :         for (i = 0; i < BWI_RX_NDESC; ++i) {
    7910           0 :                 error = bwi_newbuf30(sc, i, 1);
    7911           0 :                 if (error) {
    7912           0 :                         printf(": cannot create RX mbuf DMA map\n");
    7913           0 :                         break;
    7914             :                 }
    7915             :         }
    7916           0 :         if (error) {
    7917           0 :                 bwi_dma_mbuf_destroy(sc, BWI_TX_NRING, 1);
    7918           0 :                 for (i = 0; i < BWI_TX_NRING; ++i)
    7919           0 :                         km_free(sc->sc_bounce_tx_data[i], BWI_TX_NDESC,
    7920             :                             &kv_intrsafe, &bwi_pa_mode);
    7921           0 :                 km_free(sc->sc_bounce_rx_data, BWI_RX_NDESC * MCLBYTES,
    7922             :                     &kv_intrsafe, &bwi_pa_mode);
    7923           0 :                 return (error);
    7924             :         }
    7925             : 
    7926           0 :         return (0);
    7927           0 : }
    7928             : 
    7929             : int
    7930           0 : bwi_dma_mbuf_create(struct bwi_softc *sc)
    7931             : {
    7932           0 :         struct bwi_rxbuf_data *rbd = &sc->sc_rx_bdata;
    7933             :         int i, j, k, ntx, error;
    7934             : 
    7935             :         ntx = 0;
    7936             : 
    7937             :         /*
    7938             :          * Create TX mbuf DMA map
    7939             :          */
    7940           0 :         for (i = 0; i < BWI_TX_NRING; ++i) {
    7941           0 :                 struct bwi_txbuf_data *tbd = &sc->sc_tx_bdata[i];
    7942             : 
    7943           0 :                 for (j = 0; j < BWI_TX_NDESC; ++j) {
    7944           0 :                         error = bus_dmamap_create(sc->sc_dmat, MCLBYTES, 1, MCLBYTES,
    7945             :                             0, BUS_DMA_NOWAIT, &tbd->tbd_buf[j].tb_dmap);
    7946           0 :                         if (error) {
    7947           0 :                                 printf(
    7948             :                                     "%s: can't create %dth tbd, %dth DMA map\n",
    7949           0 :                                     sc->sc_dev.dv_xname, i, j);
    7950             :                                 ntx = i;
    7951           0 :                                 for (k = 0; k < j; ++k) {
    7952           0 :                                         bus_dmamap_destroy(sc->sc_dmat,
    7953             :                                             tbd->tbd_buf[k].tb_dmap);
    7954             :                                 }
    7955           0 :                                 goto fail;
    7956             :                         }
    7957             :                 }
    7958           0 :         }
    7959             :         ntx = BWI_TX_NRING;
    7960             : 
    7961             :         /*
    7962             :          * Create RX mbuf DMA map and a spare DMA map
    7963             :          */
    7964           0 :         error = bus_dmamap_create(sc->sc_dmat, MCLBYTES, 1, MCLBYTES, 0,
    7965             :             BUS_DMA_NOWAIT, &rbd->rbd_tmp_dmap);
    7966           0 :         if (error) {
    7967           0 :                 printf("%s: can't create spare RX buf DMA map\n",
    7968           0 :                     sc->sc_dev.dv_xname);
    7969           0 :                 goto fail;
    7970             :         }
    7971             : 
    7972           0 :         for (j = 0; j < BWI_RX_NDESC; ++j) {
    7973           0 :                 error = bus_dmamap_create(sc->sc_dmat, MCLBYTES, 1, MCLBYTES, 0,
    7974             :                     BUS_DMA_NOWAIT, &rbd->rbd_buf[j].rb_dmap);
    7975           0 :                 if (error) {
    7976           0 :                         printf("%s: can't create %dth RX buf DMA map\n",
    7977           0 :                             sc->sc_dev.dv_xname, j);
    7978             : 
    7979           0 :                         for (k = 0; k < j; ++k) {
    7980           0 :                                 bus_dmamap_destroy(sc->sc_dmat,
    7981             :                                     rbd->rbd_buf[k].rb_dmap);
    7982             :                         }
    7983           0 :                         bus_dmamap_destroy(sc->sc_dmat,
    7984             :                             rbd->rbd_tmp_dmap);
    7985           0 :                         goto fail;
    7986             :                 }
    7987             :         }
    7988             : 
    7989           0 :         return 0;
    7990             : fail:
    7991           0 :         bwi_dma_mbuf_destroy(sc, ntx, 0);
    7992             : 
    7993           0 :         return (error);
    7994           0 : }
    7995             : 
    7996             : void
    7997           0 : bwi_dma_mbuf_destroy(struct bwi_softc *sc, int ntx, int nrx)
    7998             : {
    7999           0 :         struct ieee80211com *ic = &sc->sc_ic;
    8000             :         int i, j;
    8001             : 
    8002           0 :         for (i = 0; i < ntx; ++i) {
    8003           0 :                 struct bwi_txbuf_data *tbd = &sc->sc_tx_bdata[i];
    8004             : 
    8005           0 :                 for (j = 0; j < BWI_TX_NDESC; ++j) {
    8006           0 :                         struct bwi_txbuf *tb = &tbd->tbd_buf[j];
    8007             : 
    8008           0 :                         if (tb->tb_mbuf != NULL) {
    8009           0 :                                 bus_dmamap_unload(sc->sc_dmat,
    8010             :                                     tb->tb_dmap);
    8011           0 :                                 m_freem(tb->tb_mbuf);
    8012           0 :                         }
    8013           0 :                         if (tb->tb_ni != NULL)
    8014           0 :                                 ieee80211_release_node(ic, tb->tb_ni);
    8015           0 :                         bus_dmamap_destroy(sc->sc_dmat, tb->tb_dmap);
    8016             :                 }
    8017             :         }
    8018             : 
    8019           0 :         if (nrx) {
    8020           0 :                 struct bwi_rxbuf_data *rbd = &sc->sc_rx_bdata;
    8021             : 
    8022           0 :                 bus_dmamap_destroy(sc->sc_dmat, rbd->rbd_tmp_dmap);
    8023           0 :                 for (j = 0; j < BWI_RX_NDESC; ++j) {
    8024           0 :                         struct bwi_rxbuf *rb = &rbd->rbd_buf[j];
    8025             : 
    8026           0 :                         if (rb->rb_mbuf != NULL) {
    8027           0 :                                 bus_dmamap_unload(sc->sc_dmat,
    8028             :                                                   rb->rb_dmap);
    8029           0 :                                 m_freem(rb->rb_mbuf);
    8030           0 :                         }
    8031           0 :                         bus_dmamap_destroy(sc->sc_dmat, rb->rb_dmap);
    8032             :                 }
    8033           0 :         }
    8034           0 : }
    8035             : 
    8036             : void
    8037           0 : bwi_enable_intrs(struct bwi_softc *sc, uint32_t enable_intrs)
    8038             : {
    8039           0 :         CSR_SETBITS_4(sc, BWI_MAC_INTR_MASK, enable_intrs);
    8040           0 : }
    8041             : 
    8042             : void
    8043           0 : bwi_disable_intrs(struct bwi_softc *sc, uint32_t disable_intrs)
    8044             : {
    8045           0 :         CSR_CLRBITS_4(sc, BWI_MAC_INTR_MASK, disable_intrs);
    8046           0 : }
    8047             : 
    8048             : int
    8049           0 : bwi_init_tx_ring32(struct bwi_softc *sc, int ring_idx)
    8050             : {
    8051             :         struct bwi_ring_data *rd;
    8052             :         struct bwi_txbuf_data *tbd;
    8053             :         uint32_t val, addr_hi, addr_lo;
    8054             : 
    8055           0 :         KASSERT(ring_idx < BWI_TX_NRING);
    8056           0 :         rd = &sc->sc_tx_rdata[ring_idx];
    8057           0 :         tbd = &sc->sc_tx_bdata[ring_idx];
    8058             : 
    8059           0 :         tbd->tbd_idx = 0;
    8060           0 :         tbd->tbd_used = 0;
    8061             : 
    8062           0 :         bzero(rd->rdata_desc, sizeof(struct bwi_desc32) * BWI_TX_NDESC);
    8063           0 :         bus_dmamap_sync(sc->sc_dmat, rd->rdata_dmap, 0,
    8064             :             rd->rdata_dmap->dm_mapsize, BUS_DMASYNC_PREWRITE);
    8065             : 
    8066           0 :         addr_lo = __SHIFTOUT(rd->rdata_paddr, BWI_TXRX32_RINGINFO_ADDR_MASK);
    8067           0 :         addr_hi = __SHIFTOUT(rd->rdata_paddr, BWI_TXRX32_RINGINFO_FUNC_MASK);
    8068             : 
    8069           0 :         val = __SHIFTIN(addr_lo, BWI_TXRX32_RINGINFO_ADDR_MASK) |
    8070             :             __SHIFTIN(BWI_TXRX32_RINGINFO_FUNC_TXRX,
    8071             :             BWI_TXRX32_RINGINFO_FUNC_MASK);
    8072           0 :         CSR_WRITE_4(sc, rd->rdata_txrx_ctrl + BWI_TX32_RINGINFO, val);
    8073             : 
    8074           0 :         val = __SHIFTIN(addr_hi, BWI_TXRX32_CTRL_ADDRHI_MASK) |
    8075             :               BWI_TXRX32_CTRL_ENABLE;
    8076           0 :         CSR_WRITE_4(sc, rd->rdata_txrx_ctrl + BWI_TX32_CTRL, val);
    8077             : 
    8078           0 :         return (0);
    8079             : }
    8080             : 
    8081             : void
    8082           0 : bwi_init_rxdesc_ring32(struct bwi_softc *sc, uint32_t ctrl_base,
    8083             :     bus_addr_t paddr, int hdr_size, int ndesc)
    8084             : {
    8085             :         uint32_t val, addr_hi, addr_lo;
    8086             : 
    8087           0 :         addr_lo = __SHIFTOUT(paddr, BWI_TXRX32_RINGINFO_ADDR_MASK);
    8088           0 :         addr_hi = __SHIFTOUT(paddr, BWI_TXRX32_RINGINFO_FUNC_MASK);
    8089             : 
    8090           0 :         val = __SHIFTIN(addr_lo, BWI_TXRX32_RINGINFO_ADDR_MASK) |
    8091             :             __SHIFTIN(BWI_TXRX32_RINGINFO_FUNC_TXRX,
    8092             :                         BWI_TXRX32_RINGINFO_FUNC_MASK);
    8093           0 :         CSR_WRITE_4(sc, ctrl_base + BWI_RX32_RINGINFO, val);
    8094             : 
    8095           0 :         val = __SHIFTIN(hdr_size, BWI_RX32_CTRL_HDRSZ_MASK) |
    8096           0 :             __SHIFTIN(addr_hi, BWI_TXRX32_CTRL_ADDRHI_MASK) |
    8097             :             BWI_TXRX32_CTRL_ENABLE;
    8098           0 :         CSR_WRITE_4(sc, ctrl_base + BWI_RX32_CTRL, val);
    8099             : 
    8100           0 :         CSR_WRITE_4(sc, ctrl_base + BWI_RX32_INDEX,
    8101             :             (ndesc - 1) * sizeof(struct bwi_desc32));
    8102           0 : }
    8103             : 
    8104             : int
    8105           0 : bwi_init_rx_ring32(struct bwi_softc *sc)
    8106             : {
    8107           0 :         struct bwi_ring_data *rd = &sc->sc_rx_rdata;
    8108             :         int i, error;
    8109             : 
    8110           0 :         sc->sc_rx_bdata.rbd_idx = 0;
    8111           0 :         bzero(rd->rdata_desc, sizeof(struct bwi_desc32) * BWI_RX_NDESC);
    8112             : 
    8113           0 :         for (i = 0; i < BWI_RX_NDESC; ++i) {
    8114           0 :                 error = sc->sc_newbuf(sc, i, 1);
    8115           0 :                 if (error) {
    8116           0 :                         printf("%s: can't allocate %dth RX buffer\n",
    8117           0 :                             sc->sc_dev.dv_xname, i);
    8118           0 :                         return (error);
    8119             :                 }
    8120             :         }
    8121           0 :         bus_dmamap_sync(sc->sc_dmat, rd->rdata_dmap, 0,
    8122             :             rd->rdata_dmap->dm_mapsize, BUS_DMASYNC_PREWRITE);
    8123             : 
    8124           0 :         bwi_init_rxdesc_ring32(sc, rd->rdata_txrx_ctrl, rd->rdata_paddr,
    8125             :             sizeof(struct bwi_rxbuf_hdr), BWI_RX_NDESC);
    8126           0 :         return (0);
    8127           0 : }
    8128             : 
    8129             : int
    8130           0 : bwi_init_txstats32(struct bwi_softc *sc)
    8131             : {
    8132           0 :         struct bwi_txstats_data *st = sc->sc_txstats;
    8133             :         bus_addr_t stats_paddr;
    8134             :         int i;
    8135             : 
    8136           0 :         bzero(st->stats, BWI_TXSTATS_NDESC * sizeof(struct bwi_txstats));
    8137           0 :         bus_dmamap_sync(sc->sc_dmat, st->stats_dmap, 0,
    8138             :             st->stats_dmap->dm_mapsize, BUS_DMASYNC_PREWRITE);
    8139             : 
    8140           0 :         st->stats_idx = 0;
    8141             : 
    8142           0 :         stats_paddr = st->stats_paddr;
    8143           0 :         for (i = 0; i < BWI_TXSTATS_NDESC; ++i) {
    8144           0 :                 bwi_setup_desc32(sc, st->stats_ring, BWI_TXSTATS_NDESC, i,
    8145             :                                  stats_paddr, sizeof(struct bwi_txstats), 0);
    8146           0 :                 stats_paddr += sizeof(struct bwi_txstats);
    8147             :         }
    8148           0 :         bus_dmamap_sync(sc->sc_dmat, st->stats_ring_dmap, 0,
    8149             :             st->stats_ring_dmap->dm_mapsize, BUS_DMASYNC_PREWRITE);
    8150             : 
    8151           0 :         bwi_init_rxdesc_ring32(sc, st->stats_ctrl_base,
    8152           0 :             st->stats_ring_paddr, 0, BWI_TXSTATS_NDESC);
    8153             : 
    8154           0 :         return (0);
    8155             : }
    8156             : 
    8157             : void
    8158           0 : bwi_setup_rx_desc32(struct bwi_softc *sc, int buf_idx, bus_addr_t paddr,
    8159             :     int buf_len)
    8160             : {
    8161           0 :         struct bwi_ring_data *rd = &sc->sc_rx_rdata;
    8162             : 
    8163           0 :         KASSERT(buf_idx < BWI_RX_NDESC);
    8164           0 :         bwi_setup_desc32(sc, rd->rdata_desc, BWI_RX_NDESC, buf_idx,
    8165             :             paddr, buf_len, 0);
    8166           0 : }
    8167             : 
    8168             : void
    8169           0 : bwi_setup_tx_desc32(struct bwi_softc *sc, struct bwi_ring_data *rd,
    8170             :     int buf_idx, bus_addr_t paddr, int buf_len)
    8171             : {
    8172           0 :         KASSERT(buf_idx < BWI_TX_NDESC);
    8173           0 :         bwi_setup_desc32(sc, rd->rdata_desc, BWI_TX_NDESC, buf_idx,
    8174             :             paddr, buf_len, 1);
    8175           0 : }
    8176             : 
    8177             : int
    8178           0 : bwi_newbuf30(struct bwi_softc *sc, int buf_idx, int init)
    8179             : {
    8180           0 :         struct bwi_rxbuf_data *rbd = &sc->sc_rx_bdata;
    8181           0 :         struct bwi_rxbuf *rb = &rbd->rbd_buf[buf_idx];
    8182             :         struct mbuf *m;
    8183             :         struct bwi_rxbuf_hdr *hdr;
    8184             :         int error;
    8185             : 
    8186           0 :         KASSERT(buf_idx < BWI_RX_NDESC);
    8187             : 
    8188             :         /* Create host-side mbuf. */
    8189           0 :         MGETHDR(m, init ? M_WAITOK : M_NOWAIT, MT_DATA);
    8190           0 :         if (m == NULL)
    8191           0 :                 return (ENOBUFS);
    8192           0 :         MCLGET(m, init ? M_WAITOK : M_NOWAIT);
    8193           0 :         if (m == NULL)
    8194           0 :                 return (ENOBUFS);
    8195           0 :         m->m_len = m->m_pkthdr.len = MCLBYTES;
    8196             : 
    8197           0 :         if (init) {
    8198             :                 /* Load device-side RX DMA buffer. */
    8199           0 :                 error = bus_dmamap_load(sc->sc_dmat, rb->rb_dmap,
    8200             :                     sc->sc_bounce_rx_data + (MCLBYTES * buf_idx),
    8201             :                     MCLBYTES, NULL, BUS_DMA_WAITOK);
    8202           0 :                 if (error) {
    8203           0 :                         m_freem(m);
    8204           0 :                         return (error);
    8205             :                 }
    8206             :         }
    8207             : 
    8208           0 :         rb->rb_mbuf = m;
    8209           0 :         rb->rb_paddr = rb->rb_dmap->dm_segs[0].ds_addr;
    8210             : 
    8211             :         /*
    8212             :          * Clear RX buf header
    8213             :          */
    8214           0 :         hdr = (struct bwi_rxbuf_hdr *)(sc->sc_bounce_rx_data +
    8215           0 :             (MCLBYTES * buf_idx));
    8216           0 :         bzero(hdr, sizeof(*hdr));
    8217           0 :         bus_dmamap_sync(sc->sc_dmat, rb->rb_dmap, 0,
    8218             :             rb->rb_dmap->dm_mapsize, BUS_DMASYNC_PREWRITE);
    8219             : 
    8220             :         /*
    8221             :          * Setup RX buf descriptor
    8222             :          */
    8223           0 :         sc->sc_setup_rxdesc(sc, buf_idx, rb->rb_paddr,
    8224           0 :             m->m_len - sizeof(*hdr));
    8225             : 
    8226           0 :         return (0);
    8227           0 : }
    8228             : 
    8229             : int
    8230           0 : bwi_newbuf(struct bwi_softc *sc, int buf_idx, int init)
    8231             : {
    8232           0 :         struct bwi_rxbuf_data *rbd = &sc->sc_rx_bdata;
    8233           0 :         struct bwi_rxbuf *rxbuf = &rbd->rbd_buf[buf_idx];
    8234             :         struct bwi_rxbuf_hdr *hdr;
    8235             :         bus_dmamap_t map;
    8236             :         bus_addr_t paddr;
    8237             :         struct mbuf *m;
    8238             :         int error;
    8239             : 
    8240           0 :         KASSERT(buf_idx < BWI_RX_NDESC);
    8241             : 
    8242           0 :         MGETHDR(m, init ? M_WAITOK : M_DONTWAIT, MT_DATA);
    8243           0 :         if (m == NULL)
    8244           0 :                 return (ENOBUFS);
    8245           0 :         MCLGET(m, init ? M_WAITOK : M_DONTWAIT);
    8246           0 :         if (m == NULL) {
    8247             :                 error = ENOBUFS;
    8248             : 
    8249             :                 /*
    8250             :                  * If the NIC is up and running, we need to:
    8251             :                  * - Clear RX buffer's header.
    8252             :                  * - Restore RX descriptor settings.
    8253             :                  */
    8254           0 :                 if (init)
    8255           0 :                         return error;
    8256             :                 else
    8257             :                         goto back;
    8258             :         }
    8259           0 :         m->m_len = m->m_pkthdr.len = MCLBYTES;
    8260             : 
    8261             :         /*
    8262             :          * Try to load RX buf into temporary DMA map
    8263             :          */
    8264           0 :         error = bus_dmamap_load_mbuf(sc->sc_dmat, rbd->rbd_tmp_dmap, m,
    8265             :             init ? BUS_DMA_WAITOK : BUS_DMA_NOWAIT);
    8266           0 :         if (error) {
    8267           0 :                 m_freem(m);
    8268             : 
    8269             :                 /*
    8270             :                  * See the comment above
    8271             :                  */
    8272           0 :                 if (init)
    8273           0 :                         return error;
    8274             :                 else
    8275             :                         goto back;
    8276             :         }
    8277             : 
    8278           0 :         if (!init)
    8279           0 :                 bus_dmamap_unload(sc->sc_dmat, rxbuf->rb_dmap);
    8280           0 :         rxbuf->rb_mbuf = m;
    8281             : 
    8282             :         /*
    8283             :          * Swap RX buf's DMA map with the loaded temporary one
    8284             :          */
    8285           0 :         map = rxbuf->rb_dmap;
    8286           0 :         rxbuf->rb_dmap = rbd->rbd_tmp_dmap;
    8287           0 :         rbd->rbd_tmp_dmap = map;
    8288           0 :         paddr = rxbuf->rb_dmap->dm_segs[0].ds_addr;
    8289           0 :         rxbuf->rb_paddr = paddr;
    8290             : 
    8291             : back:
    8292             :         /*
    8293             :          * Clear RX buf header
    8294             :          */
    8295           0 :         hdr = mtod(rxbuf->rb_mbuf, struct bwi_rxbuf_hdr *);
    8296           0 :         bzero(hdr, sizeof(*hdr));
    8297           0 :         bus_dmamap_sync(sc->sc_dmat, rxbuf->rb_dmap, 0,
    8298             :             rxbuf->rb_dmap->dm_mapsize, BUS_DMASYNC_PREWRITE);
    8299             : 
    8300             :         /*
    8301             :          * Setup RX buf descriptor
    8302             :          */
    8303           0 :         sc->sc_setup_rxdesc(sc, buf_idx, rxbuf->rb_paddr,
    8304           0 :             rxbuf->rb_mbuf->m_len - sizeof(*hdr));
    8305           0 :         return error;
    8306           0 : }
    8307             : 
    8308             : void
    8309           0 : bwi_set_addr_filter(struct bwi_softc *sc, uint16_t addr_ofs,
    8310             :     const uint8_t *addr)
    8311             : {
    8312             :         int i;
    8313             : 
    8314           0 :         CSR_WRITE_2(sc, BWI_ADDR_FILTER_CTRL,
    8315             :             BWI_ADDR_FILTER_CTRL_SET | addr_ofs);
    8316             : 
    8317           0 :         for (i = 0; i < (IEEE80211_ADDR_LEN / 2); ++i) {
    8318             :                 uint16_t addr_val;
    8319             : 
    8320           0 :                 addr_val = (uint16_t)addr[i * 2] |
    8321           0 :                     (((uint16_t)addr[(i * 2) + 1]) << 8);
    8322           0 :                 CSR_WRITE_2(sc, BWI_ADDR_FILTER_DATA, addr_val);
    8323             :         }
    8324           0 : }
    8325             : 
    8326             : int
    8327           0 : bwi_set_chan(struct bwi_softc *sc, uint8_t chan)
    8328             : {
    8329             :         struct bwi_mac *mac;
    8330             : 
    8331           0 :         KASSERT(sc->sc_cur_regwin->rw_type == BWI_REGWIN_T_MAC);
    8332           0 :         mac = (struct bwi_mac *)sc->sc_cur_regwin;
    8333             : 
    8334           0 :         bwi_rf_set_chan(mac, chan, 0);
    8335             : 
    8336           0 :         return (0);
    8337             : }
    8338             : 
    8339             : void
    8340           0 : bwi_next_scan(void *xsc)
    8341             : {
    8342           0 :         struct bwi_softc *sc = xsc;
    8343           0 :         struct ieee80211com *ic = &sc->sc_ic;
    8344           0 :         struct ifnet *ifp = &ic->ic_if;
    8345             :         int s;
    8346             : 
    8347           0 :         s = splnet();
    8348             : 
    8349           0 :         if (ic->ic_state == IEEE80211_S_SCAN)
    8350           0 :                 ieee80211_next_scan(ifp);
    8351             : 
    8352           0 :         splx(s);
    8353           0 : }
    8354             : 
    8355             : int
    8356           0 : bwi_rxeof(struct bwi_softc *sc, int end_idx)
    8357             : {
    8358           0 :         struct bwi_ring_data *rd = &sc->sc_rx_rdata;
    8359           0 :         struct bwi_rxbuf_data *rbd = &sc->sc_rx_bdata;
    8360           0 :         struct ieee80211com *ic = &sc->sc_ic;
    8361           0 :         struct ifnet *ifp = &ic->ic_if;
    8362             :         int idx, rx_data = 0;
    8363             : 
    8364           0 :         idx = rbd->rbd_idx;
    8365           0 :         while (idx != end_idx) {
    8366           0 :                 struct bwi_rxbuf *rb = &rbd->rbd_buf[idx];
    8367             :                 struct bwi_rxbuf_hdr *hdr;
    8368             :                 struct ieee80211_frame *wh;
    8369           0 :                 struct ieee80211_rxinfo rxi;
    8370             :                 struct ieee80211_node *ni;
    8371             :                 struct mbuf *m;
    8372           0 :                 uint32_t plcp;
    8373             :                 uint16_t flags2;
    8374             :                 int buflen, wh_ofs, hdr_extra, rssi, type, rate;
    8375             : 
    8376           0 :                 bus_dmamap_sync(sc->sc_dmat, rb->rb_dmap, 0,
    8377             :                     rb->rb_dmap->dm_mapsize, BUS_DMASYNC_POSTREAD);
    8378             : 
    8379           0 :                 if (sc->sc_bus_space == BWI_BUS_SPACE_30BIT) {
    8380             :                         /* Bounce for 30bit devices. */
    8381           0 :                         if (m_copyback(rb->rb_mbuf, 0, MCLBYTES,
    8382           0 :                             sc->sc_bounce_rx_data + (MCLBYTES * idx),
    8383           0 :                             M_NOWAIT) == ENOBUFS) {
    8384           0 :                                 ifp->if_ierrors++;
    8385           0 :                                 goto next;
    8386             :                         }
    8387             :                 }
    8388             : 
    8389           0 :                 m = rb->rb_mbuf;
    8390             : 
    8391           0 :                 if (sc->sc_newbuf(sc, idx, 0)) {
    8392           0 :                         ifp->if_ierrors++;
    8393           0 :                         goto next;
    8394             :                 }
    8395             : 
    8396           0 :                 hdr = mtod(m, struct bwi_rxbuf_hdr *);
    8397           0 :                 flags2 = letoh16(hdr->rxh_flags2);
    8398             : 
    8399             :                 hdr_extra = 0;
    8400           0 :                 if (flags2 & BWI_RXH_F2_TYPE2FRAME)
    8401             :                         hdr_extra = 2;
    8402           0 :                 wh_ofs = hdr_extra + 6;
    8403             : 
    8404           0 :                 buflen = letoh16(hdr->rxh_buflen);
    8405           0 :                 if (buflen <= wh_ofs) {
    8406           0 :                         printf("%s: zero length data, hdr_extra %d\n",
    8407           0 :                             sc->sc_dev.dv_xname, hdr_extra);
    8408           0 :                         ifp->if_ierrors++;
    8409           0 :                         m_freem(m);
    8410           0 :                         goto next;
    8411             :                 }
    8412             : 
    8413           0 :                 bcopy((uint8_t *)(hdr + 1) + hdr_extra, &plcp, sizeof(plcp));
    8414           0 :                 rssi = bwi_calc_rssi(sc, hdr);
    8415             : 
    8416           0 :                 m->m_len = m->m_pkthdr.len = buflen + sizeof(*hdr);
    8417           0 :                 m_adj(m, sizeof(*hdr) + wh_ofs);
    8418             : 
    8419           0 :                 if (htole16(hdr->rxh_flags1) & BWI_RXH_F1_OFDM)
    8420           0 :                         rate = bwi_plcp2rate(plcp, IEEE80211_MODE_11G);
    8421             :                 else
    8422           0 :                         rate = bwi_plcp2rate(plcp, IEEE80211_MODE_11B);
    8423             : 
    8424             : #if NBPFILTER > 0
    8425             :                 /* RX radio tap */
    8426           0 :                 if (sc->sc_drvbpf != NULL) {
    8427           0 :                         struct mbuf mb;
    8428           0 :                         struct bwi_rx_radiotap_hdr *tap = &sc->sc_rxtap;
    8429             : 
    8430           0 :                         tap->wr_tsf = hdr->rxh_tsf;
    8431           0 :                         tap->wr_flags = IEEE80211_RADIOTAP_F_FCS;
    8432           0 :                         tap->wr_rate = rate;
    8433           0 :                         tap->wr_chan_freq =
    8434           0 :                             htole16(ic->ic_bss->ni_chan->ic_freq);
    8435           0 :                         tap->wr_chan_flags =
    8436           0 :                             htole16(ic->ic_bss->ni_chan->ic_flags);
    8437           0 :                         tap->wr_antsignal = rssi;
    8438           0 :                         tap->wr_antnoise = BWI_NOISE_FLOOR;
    8439             : 
    8440           0 :                         mb.m_data = (caddr_t)tap;
    8441           0 :                         mb.m_len = sc->sc_rxtap_len;
    8442           0 :                         mb.m_next = m;
    8443           0 :                         mb.m_nextpkt = NULL;
    8444           0 :                         mb.m_type = 0;
    8445           0 :                         mb.m_flags = 0;
    8446           0 :                         bpf_mtap(sc->sc_drvbpf, &mb, BPF_DIRECTION_IN);
    8447           0 :                 }
    8448             : #endif
    8449             : 
    8450           0 :                 m_adj(m, -IEEE80211_CRC_LEN);
    8451             : 
    8452           0 :                 wh = mtod(m, struct ieee80211_frame *);
    8453           0 :                 ni = ieee80211_find_rxnode(ic, wh);
    8454           0 :                 type = wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK;
    8455             : 
    8456           0 :                 rxi.rxi_rssi = hdr->rxh_rssi;
    8457           0 :                 rxi.rxi_tstamp = letoh16(hdr->rxh_tsf);
    8458           0 :                 ieee80211_input(ifp, m, ni, &rxi);
    8459             : 
    8460           0 :                 ieee80211_release_node(ic, ni);
    8461             : 
    8462           0 :                 if (type == IEEE80211_FC0_TYPE_DATA) {
    8463             :                         rx_data = 1;
    8464           0 :                         sc->sc_rx_rate = rate;
    8465           0 :                 }
    8466             : next:
    8467           0 :                 idx = (idx + 1) % BWI_RX_NDESC;
    8468           0 :         }
    8469             : 
    8470           0 :         rbd->rbd_idx = idx;
    8471           0 :         bus_dmamap_sync(sc->sc_dmat, rd->rdata_dmap, 0,
    8472             :             rd->rdata_dmap->dm_mapsize, BUS_DMASYNC_PREWRITE);
    8473             : 
    8474           0 :         return (rx_data);
    8475             : }
    8476             : 
    8477             : int
    8478           0 : bwi_rxeof32(struct bwi_softc *sc)
    8479             : {
    8480             :         uint32_t val, rx_ctrl;
    8481             :         int end_idx, rx_data;
    8482             : 
    8483           0 :         rx_ctrl = sc->sc_rx_rdata.rdata_txrx_ctrl;
    8484             : 
    8485           0 :         val = CSR_READ_4(sc, rx_ctrl + BWI_RX32_STATUS);
    8486           0 :         end_idx = __SHIFTOUT(val, BWI_RX32_STATUS_INDEX_MASK) /
    8487             :             sizeof(struct bwi_desc32);
    8488             : 
    8489           0 :         rx_data = bwi_rxeof(sc, end_idx);
    8490             : 
    8491           0 :         CSR_WRITE_4(sc, rx_ctrl + BWI_RX32_INDEX,
    8492             :             end_idx * sizeof(struct bwi_desc32));
    8493             : 
    8494           0 :         return (rx_data);
    8495             : }
    8496             : 
    8497             : void
    8498           0 : bwi_reset_rx_ring32(struct bwi_softc *sc, uint32_t rx_ctrl)
    8499             : {
    8500             :         int i;
    8501             : 
    8502           0 :         CSR_WRITE_4(sc, rx_ctrl + BWI_RX32_CTRL, 0);
    8503             : 
    8504             : #define NRETRY 10
    8505           0 :         for (i = 0; i < NRETRY; ++i) {
    8506             :                 uint32_t status;
    8507             : 
    8508           0 :                 status = CSR_READ_4(sc, rx_ctrl + BWI_RX32_STATUS);
    8509           0 :                 if (__SHIFTOUT(status, BWI_RX32_STATUS_STATE_MASK) ==
    8510             :                     BWI_RX32_STATUS_STATE_DISABLED)
    8511           0 :                         break;
    8512             : 
    8513           0 :                 DELAY(1000);
    8514           0 :         }
    8515           0 :         if (i == NRETRY)
    8516           0 :                 printf("%s: reset rx ring timedout\n", sc->sc_dev.dv_xname);
    8517             : #undef NRETRY
    8518             : 
    8519           0 :         CSR_WRITE_4(sc, rx_ctrl + BWI_RX32_RINGINFO, 0);
    8520           0 : }
    8521             : 
    8522             : void
    8523           0 : bwi_free_txstats32(struct bwi_softc *sc)
    8524             : {
    8525           0 :         bwi_reset_rx_ring32(sc, sc->sc_txstats->stats_ctrl_base);
    8526           0 : }
    8527             : 
    8528             : void
    8529           0 : bwi_free_rx_ring32(struct bwi_softc *sc)
    8530             : {
    8531           0 :         struct bwi_ring_data *rd = &sc->sc_rx_rdata;
    8532           0 :         struct bwi_rxbuf_data *rbd = &sc->sc_rx_bdata;
    8533             :         int i;
    8534             : 
    8535           0 :         bwi_reset_rx_ring32(sc, rd->rdata_txrx_ctrl);
    8536             : 
    8537           0 :         for (i = 0; i < BWI_RX_NDESC; ++i) {
    8538           0 :                 struct bwi_rxbuf *rb = &rbd->rbd_buf[i];
    8539             : 
    8540           0 :                 if (rb->rb_mbuf != NULL) {
    8541           0 :                         bus_dmamap_unload(sc->sc_dmat, rb->rb_dmap);
    8542           0 :                         m_freem(rb->rb_mbuf);
    8543           0 :                         rb->rb_mbuf = NULL;
    8544           0 :                 }
    8545             :         }
    8546           0 : }
    8547             : 
    8548             : void
    8549           0 : bwi_free_tx_ring32(struct bwi_softc *sc, int ring_idx)
    8550             : {
    8551           0 :         struct ieee80211com *ic = &sc->sc_ic;
    8552             :         struct bwi_ring_data *rd;
    8553             :         struct bwi_txbuf_data *tbd;
    8554             :         uint32_t state, val;
    8555             :         int i;
    8556             : 
    8557           0 :         KASSERT(ring_idx < BWI_TX_NRING);
    8558           0 :         rd = &sc->sc_tx_rdata[ring_idx];
    8559           0 :         tbd = &sc->sc_tx_bdata[ring_idx];
    8560             : 
    8561             : #define NRETRY 10
    8562           0 :         for (i = 0; i < NRETRY; ++i) {
    8563           0 :                 val = CSR_READ_4(sc, rd->rdata_txrx_ctrl + BWI_TX32_STATUS);
    8564           0 :                 state = __SHIFTOUT(val, BWI_TX32_STATUS_STATE_MASK);
    8565           0 :                 if (state == BWI_TX32_STATUS_STATE_DISABLED ||
    8566           0 :                     state == BWI_TX32_STATUS_STATE_IDLE ||
    8567           0 :                     state == BWI_TX32_STATUS_STATE_STOPPED)
    8568             :                         break;
    8569             : 
    8570           0 :                 DELAY(1000);
    8571             :         }
    8572           0 :         if (i == NRETRY) {
    8573           0 :                 printf("%s: wait for TX ring(%d) stable timed out\n",
    8574           0 :                     sc->sc_dev.dv_xname, ring_idx);
    8575           0 :         }
    8576             : 
    8577           0 :         CSR_WRITE_4(sc, rd->rdata_txrx_ctrl + BWI_TX32_CTRL, 0);
    8578           0 :         for (i = 0; i < NRETRY; ++i) {
    8579           0 :                 val = CSR_READ_4(sc, rd->rdata_txrx_ctrl + BWI_TX32_STATUS);
    8580           0 :                 state = __SHIFTOUT(val, BWI_TX32_STATUS_STATE_MASK);
    8581           0 :                 if (state == BWI_TX32_STATUS_STATE_DISABLED)
    8582             :                         break;
    8583             : 
    8584           0 :                 DELAY(1000);
    8585             :         }
    8586           0 :         if (i == NRETRY)
    8587           0 :                 printf("%s: reset TX ring (%d) timed out\n",
    8588           0 :                     sc->sc_dev.dv_xname, ring_idx);
    8589             : #undef NRETRY
    8590             : 
    8591           0 :         DELAY(1000);
    8592             : 
    8593           0 :         CSR_WRITE_4(sc, rd->rdata_txrx_ctrl + BWI_TX32_RINGINFO, 0);
    8594             : 
    8595           0 :         for (i = 0; i < BWI_TX_NDESC; ++i) {
    8596           0 :                 struct bwi_txbuf *tb = &tbd->tbd_buf[i];
    8597             : 
    8598           0 :                 if (tb->tb_mbuf != NULL) {
    8599           0 :                         bus_dmamap_unload(sc->sc_dmat, tb->tb_dmap);
    8600           0 :                         m_freem(tb->tb_mbuf);
    8601           0 :                         tb->tb_mbuf = NULL;
    8602           0 :                 }
    8603           0 :                 if (tb->tb_ni != NULL) {
    8604           0 :                         ieee80211_release_node(ic, tb->tb_ni);
    8605           0 :                         tb->tb_ni = NULL;
    8606           0 :                 }
    8607             :         }
    8608           0 : }
    8609             : 
    8610             : uint8_t
    8611           0 : bwi_plcp2rate(uint32_t plcp0, enum ieee80211_phymode phymode)
    8612             : {
    8613           0 :         uint32_t plcp = letoh32(plcp0) & IEEE80211_OFDM_PLCP_RATE_MASK;
    8614           0 :         return (ieee80211_plcp2rate(plcp, phymode));
    8615             : }
    8616             : 
    8617             : void
    8618           0 : bwi_ofdm_plcp_header(uint32_t *plcp0, int pkt_len, uint8_t rate)
    8619             : {
    8620             :         uint32_t plcp;
    8621             : 
    8622           0 :         plcp = __SHIFTIN(ieee80211_rate2plcp(rate, IEEE80211_MODE_11G),
    8623           0 :             IEEE80211_OFDM_PLCP_RATE_MASK) |
    8624           0 :             __SHIFTIN(pkt_len, IEEE80211_OFDM_PLCP_LEN_MASK);
    8625           0 :         *plcp0 = htole32(plcp);
    8626           0 : }
    8627             : 
    8628             : void
    8629           0 : bwi_ds_plcp_header(struct ieee80211_ds_plcp_hdr *plcp, int pkt_len,
    8630             :     uint8_t rate)
    8631             : {
    8632             :         int len, service, pkt_bitlen;
    8633             : 
    8634           0 :         pkt_bitlen = pkt_len * NBBY;
    8635           0 :         len = howmany(pkt_bitlen * 2, rate);
    8636             : 
    8637             :         service = IEEE80211_DS_PLCP_SERVICE_LOCKED;
    8638           0 :         if (rate == (11 * 2)) {
    8639             :                 int pkt_bitlen1;
    8640             : 
    8641             :                 /*
    8642             :                  * PLCP service field needs to be adjusted,
    8643             :                  * if TX rate is 11Mbytes/s
    8644             :                  */
    8645           0 :                 pkt_bitlen1 = len * 11;
    8646           0 :                 if (pkt_bitlen1 - pkt_bitlen >= NBBY)
    8647           0 :                         service |= IEEE80211_DS_PLCP_SERVICE_LENEXT7;
    8648           0 :         }
    8649             : 
    8650           0 :         plcp->i_signal = ieee80211_rate2plcp(rate, IEEE80211_MODE_11B);
    8651           0 :         plcp->i_service = service;
    8652           0 :         plcp->i_length = htole16(len);
    8653             :         /* NOTE: do NOT touch i_crc */
    8654           0 : }
    8655             : 
    8656             : void
    8657           0 : bwi_plcp_header(void *plcp, int pkt_len, uint8_t rate)
    8658             : {
    8659             :         enum bwi_modtype modtype;
    8660             : 
    8661             :         /*
    8662             :          * Assume caller has zeroed 'plcp'
    8663             :          */
    8664             : 
    8665           0 :         modtype = bwi_rate2modtype(rate);
    8666           0 :         if (modtype == IEEE80211_MODTYPE_OFDM)
    8667           0 :                 bwi_ofdm_plcp_header(plcp, pkt_len, rate);
    8668           0 :         else if (modtype == IEEE80211_MODTYPE_DS)
    8669           0 :                 bwi_ds_plcp_header(plcp, pkt_len, rate);
    8670             :         else
    8671           0 :                 panic("unsupport modulation type %u", modtype);
    8672           0 : }
    8673             : 
    8674             : enum bwi_modtype
    8675           0 : bwi_rate2modtype(uint8_t rate)
    8676             : {
    8677           0 :         rate &= IEEE80211_RATE_VAL;
    8678             : 
    8679           0 :         if (rate == 44)
    8680           0 :                 return IEEE80211_MODTYPE_PBCC;
    8681           0 :         else if (rate == 22 || rate < 12)
    8682           0 :                 return IEEE80211_MODTYPE_DS;
    8683             :         else
    8684           0 :                 return IEEE80211_MODTYPE_OFDM;
    8685           0 : }
    8686             : 
    8687             : uint8_t
    8688           0 : bwi_ack_rate(struct ieee80211_node *ni, uint8_t rate)
    8689             : {
    8690           0 :         const struct ieee80211_rateset *rs = &ni->ni_rates;
    8691             :         uint8_t ack_rate = 0;
    8692             :         enum bwi_modtype modtype;
    8693             :         int i;
    8694             : 
    8695           0 :         rate &= IEEE80211_RATE_VAL;
    8696             : 
    8697           0 :         modtype = bwi_rate2modtype(rate);
    8698             : 
    8699           0 :         for (i = 0; i < rs->rs_nrates; ++i) {
    8700           0 :                 uint8_t rate1 = rs->rs_rates[i] & IEEE80211_RATE_VAL;
    8701             :                 
    8702           0 :                 if (rate1 > rate) {
    8703           0 :                         if (ack_rate != 0)
    8704           0 :                                 return ack_rate;
    8705             :                         else
    8706           0 :                                 break;
    8707             :                 }
    8708             : 
    8709           0 :                 if ((rs->rs_rates[i] & IEEE80211_RATE_BASIC) &&
    8710           0 :                     bwi_rate2modtype(rate1) == modtype)
    8711           0 :                         ack_rate = rate1;
    8712           0 :         }
    8713             : 
    8714           0 :         switch (rate) {
    8715             :         /* CCK */
    8716             :         case 2:
    8717             :         case 4:
    8718             :         case 11:
    8719             :         case 22:
    8720             :                 ack_rate = rate;
    8721           0 :                 break;
    8722             :         /* PBCC */
    8723             :         case 44:
    8724             :                 ack_rate = 22;
    8725           0 :                 break;
    8726             : 
    8727             :         /* OFDM */
    8728             :         case 12:
    8729             :         case 18:
    8730             :                 ack_rate = 12;
    8731           0 :                 break;
    8732             :         case 24:
    8733             :         case 36:
    8734             :                 ack_rate = 24;
    8735           0 :                 break;
    8736             :         case 48:
    8737             :         case 72:
    8738             :         case 96:
    8739             :         case 108:
    8740             :                 ack_rate = 48;
    8741           0 :                 break;
    8742             :         default:
    8743           0 :                 panic("unsupported rate %d", rate);
    8744             :         }
    8745           0 :         return ack_rate;
    8746           0 : }
    8747             : 
    8748             : #define IEEE80211_OFDM_TXTIME(kbps, frmlen)     \
    8749             :         (IEEE80211_OFDM_PREAMBLE_TIME +         \
    8750             :          IEEE80211_OFDM_SIGNAL_TIME +           \
    8751             :         (IEEE80211_OFDM_NSYMS((kbps), (frmlen)) * IEEE80211_OFDM_SYM_TIME))
    8752             : 
    8753             : #define IEEE80211_OFDM_SYM_TIME                 4
    8754             : #define IEEE80211_OFDM_PREAMBLE_TIME            16
    8755             : #define IEEE80211_OFDM_SIGNAL_EXT_TIME          6
    8756             : #define IEEE80211_OFDM_SIGNAL_TIME              4
    8757             : 
    8758             : #define IEEE80211_OFDM_PLCP_SERVICE_NBITS       16
    8759             : #define IEEE80211_OFDM_TAIL_NBITS               6       
    8760             : 
    8761             : #define IEEE80211_OFDM_NBITS(frmlen)            \
    8762             :         (IEEE80211_OFDM_PLCP_SERVICE_NBITS +    \
    8763             :          ((frmlen) * NBBY) +                    \
    8764             :          IEEE80211_OFDM_TAIL_NBITS)
    8765             : 
    8766             : #define IEEE80211_OFDM_NBITS_PER_SYM(kbps)      \
    8767             :         (((kbps) * IEEE80211_OFDM_SYM_TIME) / 1000)
    8768             : 
    8769             : #define IEEE80211_OFDM_NSYMS(kbps, frmlen)      \
    8770             :         howmany(IEEE80211_OFDM_NBITS((frmlen)), \
    8771             :         IEEE80211_OFDM_NBITS_PER_SYM((kbps)))
    8772             : 
    8773             : #define IEEE80211_CCK_TXTIME(kbps, frmlen)      \
    8774             :         (((IEEE80211_CCK_NBITS((frmlen)) * 1000) + (kbps) - 1) / (kbps))
    8775             : 
    8776             : #define IEEE80211_CCK_PREAMBLE_LEN              144
    8777             : #define IEEE80211_CCK_PLCP_HDR_TIME             48
    8778             : #define IEEE80211_CCK_SHPREAMBLE_LEN            72
    8779             : #define IEEE80211_CCK_SHPLCP_HDR_TIME           24
    8780             : 
    8781             : #define IEEE80211_CCK_NBITS(frmlen)             ((frmlen) * NBBY)
    8782             : 
    8783             : uint16_t
    8784           0 : bwi_txtime(struct ieee80211com *ic, struct ieee80211_node *ni, uint len,
    8785             :     uint8_t rs_rate, uint32_t flags)
    8786             : {
    8787             :         enum bwi_modtype modtype;
    8788             :         uint16_t txtime;
    8789             :         int rate;
    8790             : 
    8791           0 :         rs_rate &= IEEE80211_RATE_VAL;
    8792             : 
    8793           0 :         rate = rs_rate * 500;   /* ieee80211 rate -> kbps */
    8794             : 
    8795           0 :         modtype = bwi_rate2modtype(rs_rate);
    8796           0 :         if (modtype == IEEE80211_MODTYPE_OFDM) {
    8797             :                 /*
    8798             :                  * IEEE Std 802.11a-1999, page 37, equation (29)
    8799             :                  * IEEE Std 802.11g-2003, page 44, equation (42)
    8800             :                  */
    8801           0 :                 txtime = IEEE80211_OFDM_TXTIME(rate, len);
    8802           0 :                 if (ic->ic_curmode == IEEE80211_MODE_11G)
    8803           0 :                         txtime += IEEE80211_OFDM_SIGNAL_EXT_TIME;
    8804             :         } else {
    8805             :                 /*
    8806             :                  * IEEE Std 802.11b-1999, page 28, subclause 18.3.4
    8807             :                  * IEEE Std 802.11g-2003, page 45, equation (43)
    8808             :                  */
    8809           0 :                 if (modtype == IEEE80211_MODTYPE_PBCC)
    8810           0 :                         ++len;
    8811           0 :                 txtime = IEEE80211_CCK_TXTIME(rate, len);
    8812             : 
    8813             :                 /*
    8814             :                  * Short preamble is not applicable for DS 1Mbits/s
    8815             :                  */
    8816           0 :                 if (rs_rate != 2 && (flags & IEEE80211_F_SHPREAMBLE)) {
    8817           0 :                         txtime += IEEE80211_CCK_SHPREAMBLE_LEN +
    8818             :                                   IEEE80211_CCK_SHPLCP_HDR_TIME;
    8819           0 :                 } else {
    8820           0 :                         txtime += IEEE80211_CCK_PREAMBLE_LEN +
    8821             :                                   IEEE80211_CCK_PLCP_HDR_TIME;
    8822             :                 }
    8823             :         }
    8824           0 :         return txtime;
    8825             : }
    8826             : 
    8827             : int
    8828           0 : bwi_encap(struct bwi_softc *sc, int idx, struct mbuf *m,
    8829             :     struct ieee80211_node *ni)
    8830             : {
    8831             :         DPRINTF(2, "%s: %s\n", sc->sc_dev.dv_xname, __func__);
    8832             : 
    8833           0 :         struct ieee80211com *ic = &sc->sc_ic;
    8834           0 :         struct bwi_ring_data *rd = &sc->sc_tx_rdata[BWI_TX_DATA_RING];
    8835           0 :         struct bwi_txbuf_data *tbd = &sc->sc_tx_bdata[BWI_TX_DATA_RING];
    8836           0 :         struct bwi_txbuf *tb = &tbd->tbd_buf[idx];
    8837             :         struct bwi_mac *mac;
    8838             :         struct bwi_txbuf_hdr *hdr;
    8839             :         struct ieee80211_frame *wh;
    8840             :         uint8_t rate;
    8841             :         uint32_t mac_ctrl;
    8842             :         uint16_t phy_ctrl;
    8843             :         bus_addr_t paddr;
    8844             :         int pkt_len, error = 0;
    8845             : #if 0
    8846             :         const uint8_t *p;
    8847             :         int i;
    8848             : #endif
    8849             : 
    8850           0 :         KASSERT(sc->sc_cur_regwin->rw_type == BWI_REGWIN_T_MAC);
    8851           0 :         mac = (struct bwi_mac *)sc->sc_cur_regwin;
    8852             : 
    8853           0 :         wh = mtod(m, struct ieee80211_frame *);
    8854             : 
    8855             :         /* Get 802.11 frame len before prepending TX header */
    8856           0 :         pkt_len = m->m_pkthdr.len + IEEE80211_CRC_LEN;
    8857             : 
    8858             :         /*
    8859             :          * Find TX rate
    8860             :          */
    8861           0 :         bzero(tb->tb_rate_idx, sizeof(tb->tb_rate_idx));
    8862           0 :         if (ni != NULL) {
    8863           0 :                 if (ic->ic_fixed_rate != -1) {
    8864           0 :                         rate = ic->ic_sup_rates[ic->ic_curmode].
    8865           0 :                             rs_rates[ic->ic_fixed_rate];
    8866           0 :                 } else {
    8867             :                         /* AMRR rate control */
    8868           0 :                         rate = ni->ni_rates.rs_rates[ni->ni_txrate];
    8869             :                 }
    8870             :         } else {
    8871             :                 /* Fixed at 1Mbytes/s for mgt frames */
    8872             :                 rate = (1 * 2);
    8873             :         }
    8874             : 
    8875           0 :         rate &= IEEE80211_RATE_VAL;
    8876             : 
    8877           0 :         if (IEEE80211_IS_MULTICAST(wh->i_addr1))
    8878             :                 rate = (1 * 2);
    8879             : 
    8880           0 :         if (rate == 0) {
    8881           0 :                 printf("%s: invalid rate %u or fallback rate",
    8882           0 :                     sc->sc_dev.dv_xname, rate);
    8883             :                 rate = (1 * 2); /* Force 1Mbytes/s */
    8884           0 :         }
    8885           0 :         sc->sc_tx_rate = rate;
    8886             : 
    8887             : #if NBPFILTER > 0
    8888             :         /* TX radio tap */
    8889           0 :         if (sc->sc_drvbpf != NULL) {
    8890           0 :                 struct mbuf mb;
    8891           0 :                 struct bwi_tx_radiotap_hdr *tap = &sc->sc_txtap;
    8892             : 
    8893           0 :                 tap->wt_flags = 0;
    8894           0 :                 tap->wt_rate = rate;
    8895           0 :                 tap->wt_chan_freq =
    8896           0 :                     htole16(ic->ic_bss->ni_chan->ic_freq);
    8897           0 :                 tap->wt_chan_flags =
    8898           0 :                     htole16(ic->ic_bss->ni_chan->ic_flags);
    8899             : 
    8900           0 :                 mb.m_data = (caddr_t)tap;
    8901           0 :                 mb.m_len = sc->sc_txtap_len;
    8902           0 :                 mb.m_next = m;
    8903           0 :                 mb.m_nextpkt = NULL;
    8904           0 :                 mb.m_type = 0;
    8905           0 :                 mb.m_flags = 0;
    8906           0 :                 bpf_mtap(sc->sc_drvbpf, &mb, BPF_DIRECTION_OUT);
    8907           0 :         }
    8908             : #endif
    8909             : 
    8910             :         /*
    8911             :          * Setup the embedded TX header
    8912             :          */
    8913           0 :         M_PREPEND(m, sizeof(*hdr), M_DONTWAIT);
    8914           0 :         if (m == NULL) {
    8915           0 :                 printf("%s: prepend TX header failed\n", sc->sc_dev.dv_xname);
    8916           0 :                 return (ENOBUFS);
    8917             :         }
    8918           0 :         hdr = mtod(m, struct bwi_txbuf_hdr *);
    8919             : 
    8920           0 :         bzero(hdr, sizeof(*hdr));
    8921             : 
    8922           0 :         bcopy(wh->i_fc, hdr->txh_fc, sizeof(hdr->txh_fc));
    8923           0 :         bcopy(wh->i_addr1, hdr->txh_addr1, sizeof(hdr->txh_addr1));
    8924             : 
    8925           0 :         if (ni != NULL && !IEEE80211_IS_MULTICAST(wh->i_addr1)) {
    8926             :                 uint16_t dur;
    8927             :                 uint8_t ack_rate;
    8928             : 
    8929           0 :                 ack_rate = bwi_ack_rate(ni, rate);
    8930           0 :                 dur = bwi_txtime(ic, ni,
    8931             :                     sizeof(struct ieee80211_frame_ack) + IEEE80211_CRC_LEN,
    8932           0 :                     ack_rate, ic->ic_flags & IEEE80211_F_SHPREAMBLE);
    8933             : 
    8934           0 :                 hdr->txh_fb_duration = htole16(dur);
    8935           0 :         }
    8936             : 
    8937           0 :         hdr->txh_id = __SHIFTIN(BWI_TX_DATA_RING, BWI_TXH_ID_RING_MASK) |
    8938             :             __SHIFTIN(idx, BWI_TXH_ID_IDX_MASK);
    8939             : 
    8940           0 :         bwi_plcp_header(hdr->txh_plcp, pkt_len, rate);
    8941           0 :         bwi_plcp_header(hdr->txh_fb_plcp, pkt_len, rate);
    8942             : 
    8943           0 :         phy_ctrl = __SHIFTIN(mac->mac_rf.rf_ant_mode,
    8944             :             BWI_TXH_PHY_C_ANTMODE_MASK);
    8945           0 :         if (bwi_rate2modtype(rate) == IEEE80211_MODTYPE_OFDM)
    8946           0 :                 phy_ctrl |= BWI_TXH_PHY_C_OFDM;
    8947           0 :         else if ((ic->ic_flags & IEEE80211_F_SHPREAMBLE) && rate != (2 * 1))
    8948           0 :                 phy_ctrl |= BWI_TXH_PHY_C_SHPREAMBLE;
    8949             : 
    8950             :         mac_ctrl = BWI_TXH_MAC_C_HWSEQ | BWI_TXH_MAC_C_FIRST_FRAG;
    8951           0 :         if (!IEEE80211_IS_MULTICAST(wh->i_addr1))
    8952           0 :                 mac_ctrl |= BWI_TXH_MAC_C_ACK;
    8953           0 :         if (bwi_rate2modtype(rate) == IEEE80211_MODTYPE_OFDM)
    8954           0 :                 mac_ctrl |= BWI_TXH_MAC_C_FB_OFDM;
    8955             : 
    8956           0 :         hdr->txh_mac_ctrl = htole32(mac_ctrl);
    8957           0 :         hdr->txh_phy_ctrl = htole16(phy_ctrl);
    8958             : 
    8959             :         /* Catch any further usage */
    8960             :         hdr = NULL;
    8961             :         wh = NULL;
    8962             : 
    8963           0 :         if (sc->sc_bus_space == BWI_BUS_SPACE_30BIT) {
    8964             :                 /* Bounce for 30bit devices. */
    8965           0 :                 m_copydata(m, 0, m->m_pkthdr.len,
    8966           0 :                     sc->sc_bounce_tx_data[BWI_TX_DATA_RING] +
    8967           0 :                     (MCLBYTES * idx));
    8968           0 :         } else {
    8969             :                 /* DMA load */
    8970           0 :                 error = bus_dmamap_load_mbuf(sc->sc_dmat, tb->tb_dmap, m,
    8971             :                     BUS_DMA_NOWAIT);
    8972           0 :                 if (error && error != EFBIG) {
    8973           0 :                         printf("%s: can't load TX buffer (1) %d\n",
    8974           0 :                             sc->sc_dev.dv_xname, error);
    8975           0 :                         goto back;
    8976             :                 }
    8977             : 
    8978           0 :                 if (error) {    /* error == EFBIG */
    8979           0 :                         if (m_defrag(m, M_DONTWAIT)) {
    8980           0 :                                 printf("%s: can't defrag TX buffer\n",
    8981           0 :                                     sc->sc_dev.dv_xname);
    8982           0 :                                 goto back;
    8983             :                         }
    8984           0 :                         error = bus_dmamap_load_mbuf(sc->sc_dmat, tb->tb_dmap,
    8985             :                             m, BUS_DMA_NOWAIT);
    8986           0 :                         if (error) {
    8987           0 :                                 printf("%s: can't load TX buffer (2) %d\n",
    8988           0 :                                     sc->sc_dev.dv_xname, error);
    8989           0 :                                 goto back;
    8990             :                         }
    8991             :                 }
    8992             :                 error = 0;
    8993             :         }
    8994             : 
    8995           0 :         bus_dmamap_sync(sc->sc_dmat, tb->tb_dmap, 0,
    8996             :             tb->tb_dmap->dm_mapsize, BUS_DMASYNC_PREWRITE);
    8997             : 
    8998           0 :         tb->tb_mbuf = m;
    8999           0 :         tb->tb_ni = ni;
    9000             : 
    9001             : #if 0
    9002             :         p = mtod(m, const uint8_t *);
    9003             :         for (i = 0; i < m->m_pkthdr.len; ++i) {
    9004             :                 if (i != 0 && i % 8 == 0)
    9005             :                         printf("\n");
    9006             :                 printf("%02x ", p[i]);
    9007             :         }
    9008             :         printf("\n");
    9009             : 
    9010             :         DPRINTF(1, "%s: idx %d, pkt_len %d, buflen %d\n",
    9011             :             sc->sc_dev.dv_xname, idx, pkt_len, m->m_pkthdr.len);
    9012             : #endif
    9013             : 
    9014             :         /* Setup TX descriptor */
    9015           0 :         paddr = tb->tb_dmap->dm_segs[0].ds_addr;
    9016           0 :         sc->sc_setup_txdesc(sc, rd, idx, paddr, m->m_pkthdr.len);
    9017           0 :         bus_dmamap_sync(sc->sc_dmat, rd->rdata_dmap, 0,
    9018             :             rd->rdata_dmap->dm_mapsize, BUS_DMASYNC_PREWRITE);
    9019             : 
    9020             :         /* Kick start */
    9021           0 :         sc->sc_start_tx(sc, rd->rdata_txrx_ctrl, idx);
    9022             : 
    9023             : back:
    9024           0 :         if (error)
    9025           0 :                 m_freem(m);
    9026           0 :         return (error);
    9027           0 : }
    9028             : 
    9029             : void
    9030           0 : bwi_start_tx32(struct bwi_softc *sc, uint32_t tx_ctrl, int idx)
    9031             : {
    9032           0 :         idx = (idx + 1) % BWI_TX_NDESC;
    9033           0 :         CSR_WRITE_4(sc, tx_ctrl + BWI_TX32_INDEX,
    9034             :             idx * sizeof(struct bwi_desc32));
    9035           0 : }
    9036             : 
    9037             : void
    9038           0 : bwi_txeof_status32(struct bwi_softc *sc)
    9039             : {
    9040           0 :         struct ifnet *ifp = &sc->sc_ic.ic_if;
    9041             :         uint32_t val, ctrl_base;
    9042             :         int end_idx;
    9043             : 
    9044           0 :         ctrl_base = sc->sc_txstats->stats_ctrl_base;
    9045             : 
    9046           0 :         val = CSR_READ_4(sc, ctrl_base + BWI_RX32_STATUS);
    9047           0 :         end_idx = __SHIFTOUT(val, BWI_RX32_STATUS_INDEX_MASK) /
    9048             :             sizeof(struct bwi_desc32);
    9049             : 
    9050           0 :         bwi_txeof_status(sc, end_idx);
    9051             : 
    9052           0 :         CSR_WRITE_4(sc, ctrl_base + BWI_RX32_INDEX,
    9053             :             end_idx * sizeof(struct bwi_desc32));
    9054             : 
    9055           0 :         if (ifq_is_oactive(&ifp->if_snd) == 0)
    9056           0 :                 ifp->if_start(ifp);
    9057           0 : }
    9058             : 
    9059             : void
    9060           0 : _bwi_txeof(struct bwi_softc *sc, uint16_t tx_id)
    9061             : {
    9062           0 :         struct ieee80211com *ic = &sc->sc_ic;
    9063           0 :         struct ifnet *ifp = &sc->sc_ic.ic_if;
    9064             :         struct bwi_txbuf_data *tbd;
    9065             :         struct bwi_txbuf *tb;
    9066             :         int ring_idx, buf_idx;
    9067             : 
    9068           0 :         if (tx_id == 0) {
    9069           0 :                 printf("%s: zero tx id\n", sc->sc_dev.dv_xname);
    9070           0 :                 return;
    9071             :         }
    9072             : 
    9073           0 :         ring_idx = __SHIFTOUT(tx_id, BWI_TXH_ID_RING_MASK);
    9074           0 :         buf_idx = __SHIFTOUT(tx_id, BWI_TXH_ID_IDX_MASK);
    9075             : 
    9076           0 :         KASSERT(ring_idx == BWI_TX_DATA_RING);
    9077           0 :         KASSERT(buf_idx < BWI_TX_NDESC);
    9078             : #if 0
    9079             :         DPRINTF(1, "%s: txeof idx %d\n", sc->sc_dev.dv_xname, buf_idx);
    9080             : #endif
    9081           0 :         tbd = &sc->sc_tx_bdata[ring_idx];
    9082           0 :         KASSERT(tbd->tbd_used > 0);
    9083           0 :         tbd->tbd_used--;
    9084             : 
    9085           0 :         tb = &tbd->tbd_buf[buf_idx];
    9086             : 
    9087           0 :         bus_dmamap_unload(sc->sc_dmat, tb->tb_dmap);
    9088           0 :         m_freem(tb->tb_mbuf);
    9089           0 :         tb->tb_mbuf = NULL;
    9090             : 
    9091           0 :         if (tb->tb_ni != NULL) {
    9092           0 :                 ieee80211_release_node(ic, tb->tb_ni);
    9093           0 :                 tb->tb_ni = NULL;
    9094           0 :         }
    9095             : 
    9096           0 :         if (tbd->tbd_used == 0)
    9097           0 :                 sc->sc_tx_timer = 0;
    9098             : 
    9099           0 :         ifq_clr_oactive(&ifp->if_snd);
    9100           0 : }
    9101             : 
    9102             : void
    9103           0 : bwi_txeof_status(struct bwi_softc *sc, int end_idx)
    9104             : {
    9105           0 :         struct bwi_txstats_data *st = sc->sc_txstats;
    9106             :         int idx;
    9107             : 
    9108           0 :         bus_dmamap_sync(sc->sc_dmat, st->stats_dmap, 0,
    9109             :             st->stats_dmap->dm_mapsize, BUS_DMASYNC_POSTREAD);
    9110             : 
    9111           0 :         idx = st->stats_idx;
    9112           0 :         while (idx != end_idx) {
    9113           0 :                 _bwi_txeof(sc, letoh16(st->stats[idx].txs_id));
    9114           0 :                 idx = (idx + 1) % BWI_TXSTATS_NDESC;
    9115             :         }
    9116           0 :         st->stats_idx = idx;
    9117           0 : }
    9118             : 
    9119             : void
    9120           0 : bwi_txeof(struct bwi_softc *sc)
    9121             : {
    9122           0 :         struct ifnet *ifp = &sc->sc_ic.ic_if;
    9123             : 
    9124           0 :         for (;;) {
    9125             :                 uint32_t tx_status0, tx_status1;
    9126             :                 uint16_t tx_id, tx_info;
    9127             : 
    9128           0 :                 tx_status0 = CSR_READ_4(sc, BWI_TXSTATUS_0);
    9129           0 :                 if (tx_status0 == 0)
    9130           0 :                         break;
    9131           0 :                 tx_status1 = CSR_READ_4(sc, BWI_TXSTATUS_1);
    9132             : 
    9133           0 :                 tx_id = __SHIFTOUT(tx_status0, BWI_TXSTATUS_0_TXID_MASK);
    9134           0 :                 tx_info = BWI_TXSTATUS_0_INFO(tx_status0);
    9135             : 
    9136           0 :                 if (tx_info & 0x30) /* XXX */
    9137           0 :                         continue;
    9138             : 
    9139           0 :                 _bwi_txeof(sc, letoh16(tx_id));
    9140           0 :         }
    9141             : 
    9142           0 :         if (ifq_is_oactive(&ifp->if_snd) == 0)
    9143           0 :                 ifp->if_start(ifp);
    9144           0 : }
    9145             : 
    9146             : int
    9147           0 : bwi_bbp_power_on(struct bwi_softc *sc, enum bwi_clock_mode clk_mode)
    9148             : {
    9149           0 :         bwi_power_on(sc, 1);
    9150             : 
    9151           0 :         return (bwi_set_clock_mode(sc, clk_mode));
    9152             : }
    9153             : 
    9154             : void
    9155           0 : bwi_bbp_power_off(struct bwi_softc *sc)
    9156             : {
    9157           0 :         bwi_set_clock_mode(sc, BWI_CLOCK_MODE_SLOW);
    9158           0 :         bwi_power_off(sc, 1);
    9159           0 : }
    9160             : 
    9161             : int
    9162           0 : bwi_get_pwron_delay(struct bwi_softc *sc)
    9163             : {
    9164           0 :         struct bwi_regwin *com, *old;
    9165           0 :         struct bwi_clock_freq freq;
    9166             :         uint32_t val;
    9167             :         int error;
    9168             : 
    9169           0 :         com = &sc->sc_com_regwin;
    9170           0 :         KASSERT(BWI_REGWIN_EXIST(com));
    9171             : 
    9172           0 :         if ((sc->sc_cap & BWI_CAP_CLKMODE) == 0)
    9173           0 :                 return (0);
    9174             : 
    9175           0 :         error = bwi_regwin_switch(sc, com, &old);
    9176           0 :         if (error)
    9177           0 :                 return (error);
    9178             : 
    9179           0 :         bwi_get_clock_freq(sc, &freq);
    9180             : 
    9181           0 :         val = CSR_READ_4(sc, BWI_PLL_ON_DELAY);
    9182           0 :         sc->sc_pwron_delay = howmany((val + 2) * 1000000, freq.clkfreq_min);
    9183             :         DPRINTF(1, "%s: power on delay %u\n",
    9184             :             sc->sc_dev.dv_xname, sc->sc_pwron_delay);
    9185             : 
    9186           0 :         return (bwi_regwin_switch(sc, old, NULL));
    9187           0 : }
    9188             : 
    9189             : int
    9190           0 : bwi_bus_attach(struct bwi_softc *sc)
    9191             : {
    9192           0 :         struct bwi_regwin *bus, *old;
    9193             :         int error;
    9194             : 
    9195           0 :         bus = &sc->sc_bus_regwin;
    9196             : 
    9197           0 :         error = bwi_regwin_switch(sc, bus, &old);
    9198           0 :         if (error)
    9199           0 :                 return (error);
    9200             : 
    9201           0 :         if (!bwi_regwin_is_enabled(sc, bus))
    9202           0 :                 bwi_regwin_enable(sc, bus, 0);
    9203             : 
    9204             :         /* Disable interripts */
    9205           0 :         CSR_WRITE_4(sc, BWI_INTRVEC, 0);
    9206             : 
    9207           0 :         return (bwi_regwin_switch(sc, old, NULL));
    9208           0 : }
    9209             : 
    9210             : const char *
    9211           0 : bwi_regwin_name(const struct bwi_regwin *rw)
    9212             : {
    9213           0 :         switch (rw->rw_type) {
    9214             :         case BWI_REGWIN_T_COM:
    9215           0 :                 return ("COM");
    9216             :         case BWI_REGWIN_T_BUSPCI:
    9217           0 :                 return ("PCI");
    9218             :         case BWI_REGWIN_T_MAC:
    9219           0 :                 return ("MAC");
    9220             :         case BWI_REGWIN_T_BUSPCIE:
    9221           0 :                 return ("PCIE");
    9222             :         }
    9223           0 :         panic("unknown regwin type 0x%04x", rw->rw_type);
    9224             : 
    9225             :         return (NULL);
    9226           0 : }
    9227             : 
    9228             : uint32_t
    9229           0 : bwi_regwin_disable_bits(struct bwi_softc *sc)
    9230             : {
    9231             :         uint32_t busrev;
    9232             : 
    9233             :         /* XXX cache this */
    9234           0 :         busrev = __SHIFTOUT(CSR_READ_4(sc, BWI_ID_LO), BWI_ID_LO_BUSREV_MASK);
    9235             :         DPRINTF(1, "%s: bus rev %u\n", sc->sc_dev.dv_xname, busrev);
    9236             : 
    9237           0 :         if (busrev == BWI_BUSREV_0)
    9238           0 :                 return (BWI_STATE_LO_DISABLE1);
    9239           0 :         else if (busrev == BWI_BUSREV_1)
    9240           0 :                 return (BWI_STATE_LO_DISABLE2);
    9241             :         else
    9242           0 :                 return ((BWI_STATE_LO_DISABLE1 | BWI_STATE_LO_DISABLE2));
    9243           0 : }
    9244             : 
    9245             : int
    9246           0 : bwi_regwin_is_enabled(struct bwi_softc *sc, struct bwi_regwin *rw)
    9247             : {
    9248             :         uint32_t val, disable_bits;
    9249             : 
    9250           0 :         disable_bits = bwi_regwin_disable_bits(sc);
    9251           0 :         val = CSR_READ_4(sc, BWI_STATE_LO);
    9252             : 
    9253           0 :         if ((val & (BWI_STATE_LO_CLOCK |
    9254           0 :             BWI_STATE_LO_RESET |
    9255           0 :             disable_bits)) == BWI_STATE_LO_CLOCK) {
    9256             :                 DPRINTF(1, "%s: %s is enabled\n",
    9257             :                     sc->sc_dev.dv_xname, bwi_regwin_name(rw));
    9258           0 :                 return (1);
    9259             :         } else {
    9260             :                 DPRINTF(1, "%s: %s is disabled\n",
    9261             :                     sc->sc_dev.dv_xname, bwi_regwin_name(rw));
    9262           0 :                 return (0);
    9263             :         }
    9264           0 : }
    9265             : 
    9266             : void
    9267           0 : bwi_regwin_disable(struct bwi_softc *sc, struct bwi_regwin *rw, uint32_t flags)
    9268             : {
    9269             :         uint32_t state_lo, disable_bits;
    9270             :         int i;
    9271             : 
    9272           0 :         state_lo = CSR_READ_4(sc, BWI_STATE_LO);
    9273             : 
    9274             :         /*
    9275             :          * If current regwin is in 'reset' state, it was already disabled.
    9276             :          */
    9277           0 :         if (state_lo & BWI_STATE_LO_RESET) {
    9278             :                 DPRINTF(1, "%s: %s was already disabled\n",
    9279             :                     sc->sc_dev.dv_xname, bwi_regwin_name(rw));
    9280           0 :                 return;
    9281             :         }
    9282             : 
    9283           0 :         disable_bits = bwi_regwin_disable_bits(sc);
    9284             : 
    9285             :         /*
    9286             :          * Disable normal clock
    9287             :          */
    9288           0 :         state_lo = BWI_STATE_LO_CLOCK | disable_bits;
    9289           0 :         CSR_WRITE_4(sc, BWI_STATE_LO, state_lo);
    9290             : 
    9291             :         /*
    9292             :          * Wait until normal clock is disabled
    9293             :          */
    9294             : #define NRETRY  1000
    9295           0 :         for (i = 0; i < NRETRY; ++i) {
    9296           0 :                 state_lo = CSR_READ_4(sc, BWI_STATE_LO);
    9297           0 :                 if (state_lo & disable_bits)
    9298             :                         break;
    9299           0 :                 DELAY(10);
    9300             :         }
    9301           0 :         if (i == NRETRY) {
    9302           0 :                 printf("%s: %s disable clock timeout\n",
    9303           0 :                     sc->sc_dev.dv_xname, bwi_regwin_name(rw));
    9304           0 :         }
    9305             : 
    9306           0 :         for (i = 0; i < NRETRY; ++i) {
    9307             :                 uint32_t state_hi;
    9308             : 
    9309           0 :                 state_hi = CSR_READ_4(sc, BWI_STATE_HI);
    9310           0 :                 if ((state_hi & BWI_STATE_HI_BUSY) == 0)
    9311           0 :                         break;
    9312           0 :                 DELAY(10);
    9313           0 :         }
    9314           0 :         if (i == NRETRY) {
    9315           0 :                 printf("%s: %s wait BUSY unset timeout\n",
    9316           0 :                     sc->sc_dev.dv_xname, bwi_regwin_name(rw));
    9317           0 :         }
    9318             : #undef NRETRY
    9319             : 
    9320             :         /*
    9321             :          * Reset and disable regwin with gated clock
    9322             :          */
    9323           0 :         state_lo = BWI_STATE_LO_RESET | disable_bits |
    9324           0 :             BWI_STATE_LO_CLOCK | BWI_STATE_LO_GATED_CLOCK |
    9325           0 :             __SHIFTIN(flags, BWI_STATE_LO_FLAGS_MASK);
    9326           0 :         CSR_WRITE_4(sc, BWI_STATE_LO, state_lo);
    9327             : 
    9328             :         /* Flush pending bus write */
    9329           0 :         CSR_READ_4(sc, BWI_STATE_LO);
    9330           0 :         DELAY(1);
    9331             : 
    9332             :         /* Reset and disable regwin */
    9333           0 :         state_lo = BWI_STATE_LO_RESET | disable_bits |
    9334             :                    __SHIFTIN(flags, BWI_STATE_LO_FLAGS_MASK);
    9335           0 :         CSR_WRITE_4(sc, BWI_STATE_LO, state_lo);
    9336             : 
    9337             :         /* Flush pending bus write */
    9338           0 :         CSR_READ_4(sc, BWI_STATE_LO);
    9339           0 :         DELAY(1);
    9340           0 : }
    9341             : 
    9342             : void
    9343           0 : bwi_regwin_enable(struct bwi_softc *sc, struct bwi_regwin *rw, uint32_t flags)
    9344             : {
    9345             :         uint32_t state_lo, state_hi, imstate;
    9346             : 
    9347           0 :         bwi_regwin_disable(sc, rw, flags);
    9348             : 
    9349             :         /* Reset regwin with gated clock */
    9350             :         state_lo = BWI_STATE_LO_RESET |
    9351             :             BWI_STATE_LO_CLOCK |
    9352           0 :             BWI_STATE_LO_GATED_CLOCK |
    9353           0 :             __SHIFTIN(flags, BWI_STATE_LO_FLAGS_MASK);
    9354           0 :         CSR_WRITE_4(sc, BWI_STATE_LO, state_lo);
    9355             : 
    9356             :         /* Flush pending bus write */
    9357           0 :         CSR_READ_4(sc, BWI_STATE_LO);
    9358           0 :         DELAY(1);
    9359             : 
    9360           0 :         state_hi = CSR_READ_4(sc, BWI_STATE_HI);
    9361           0 :         if (state_hi & BWI_STATE_HI_SERROR)
    9362           0 :                 CSR_WRITE_4(sc, BWI_STATE_HI, 0);
    9363             : 
    9364           0 :         imstate = CSR_READ_4(sc, BWI_IMSTATE);
    9365           0 :         if (imstate & (BWI_IMSTATE_INBAND_ERR | BWI_IMSTATE_TIMEOUT)) {
    9366           0 :                 imstate &= ~(BWI_IMSTATE_INBAND_ERR | BWI_IMSTATE_TIMEOUT);
    9367           0 :                 CSR_WRITE_4(sc, BWI_IMSTATE, imstate);
    9368           0 :         }
    9369             : 
    9370             :         /* Enable regwin with gated clock */
    9371             :         state_lo = BWI_STATE_LO_CLOCK |
    9372           0 :             BWI_STATE_LO_GATED_CLOCK |
    9373             :             __SHIFTIN(flags, BWI_STATE_LO_FLAGS_MASK);
    9374           0 :         CSR_WRITE_4(sc, BWI_STATE_LO, state_lo);
    9375             : 
    9376             :         /* Flush pending bus write */
    9377           0 :         CSR_READ_4(sc, BWI_STATE_LO);
    9378           0 :         DELAY(1);
    9379             : 
    9380             :         /* Enable regwin with normal clock */
    9381           0 :         state_lo = BWI_STATE_LO_CLOCK |
    9382             :             __SHIFTIN(flags, BWI_STATE_LO_FLAGS_MASK);
    9383           0 :         CSR_WRITE_4(sc, BWI_STATE_LO, state_lo);
    9384             : 
    9385             :         /* Flush pending bus write */
    9386           0 :         CSR_READ_4(sc, BWI_STATE_LO);
    9387           0 :         DELAY(1);
    9388           0 : }
    9389             : 
    9390             : void
    9391           0 : bwi_set_bssid(struct bwi_softc *sc, const uint8_t *bssid)
    9392             : {
    9393           0 :         struct ieee80211com *ic = &sc->sc_ic;
    9394             :         struct bwi_mac *mac;
    9395           0 :         struct bwi_myaddr_bssid buf;
    9396             :         const uint8_t *p;
    9397             :         uint32_t val;
    9398             :         int n, i;
    9399             : 
    9400           0 :         KASSERT(sc->sc_cur_regwin->rw_type == BWI_REGWIN_T_MAC);
    9401           0 :         mac = (struct bwi_mac *)sc->sc_cur_regwin;
    9402             : 
    9403           0 :         bwi_set_addr_filter(sc, BWI_ADDR_FILTER_BSSID, bssid);
    9404             : 
    9405           0 :         bcopy(ic->ic_myaddr, buf.myaddr, sizeof(buf.myaddr));
    9406           0 :         bcopy(bssid, buf.bssid, sizeof(buf.bssid));
    9407             : 
    9408             :         n = sizeof(buf) / sizeof(val);
    9409             :         p = (const uint8_t *)&buf;
    9410           0 :         for (i = 0; i < n; ++i) {
    9411             :                 int j;
    9412             : 
    9413             :                 val = 0;
    9414           0 :                 for (j = 0; j < sizeof(val); ++j)
    9415           0 :                         val |= ((uint32_t)(*p++)) << (j * 8);
    9416             : 
    9417           0 :                 TMPLT_WRITE_4(mac, 0x20 + (i * sizeof(val)), val);
    9418             :         }
    9419           0 : }
    9420             : 
    9421             : void
    9422           0 : bwi_updateslot(struct ieee80211com *ic)
    9423             : {
    9424           0 :         struct bwi_softc *sc = ic->ic_if.if_softc;
    9425             :         struct bwi_mac *mac;
    9426             :         struct ifnet *ifp = &ic->ic_if;
    9427             : 
    9428           0 :         if ((ifp->if_flags & IFF_RUNNING) == 0)
    9429           0 :                 return;
    9430             : 
    9431             :         DPRINTF(2, "%s: %s\n", sc->sc_dev.dv_xname, __func__);
    9432             : 
    9433           0 :         KASSERT(sc->sc_cur_regwin->rw_type == BWI_REGWIN_T_MAC);
    9434           0 :         mac = (struct bwi_mac *)sc->sc_cur_regwin;
    9435             : 
    9436           0 :         bwi_mac_updateslot(mac, (ic->ic_flags & IEEE80211_F_SHSLOT));
    9437           0 : }
    9438             : 
    9439             : void
    9440           0 : bwi_calibrate(void *xsc)
    9441             : {
    9442           0 :         struct bwi_softc *sc = xsc;
    9443           0 :         struct ieee80211com *ic = &sc->sc_ic;
    9444             :         int s;
    9445             : 
    9446           0 :         s = splnet();
    9447             : 
    9448           0 :         if (ic->ic_state == IEEE80211_S_RUN) {
    9449             :                 struct bwi_mac *mac;
    9450             : 
    9451           0 :                 KASSERT(sc->sc_cur_regwin->rw_type == BWI_REGWIN_T_MAC);
    9452           0 :                 mac = (struct bwi_mac *)sc->sc_cur_regwin;
    9453             : 
    9454           0 :                 if (ic->ic_opmode != IEEE80211_M_MONITOR) {
    9455           0 :                         bwi_mac_calibrate_txpower(mac, sc->sc_txpwrcb_type);
    9456           0 :                         sc->sc_txpwrcb_type = BWI_TXPWR_CALIB;
    9457           0 :                 }
    9458             : 
    9459             :                 /* XXX 15 seconds */
    9460           0 :                 timeout_add_sec(&sc->sc_calib_ch, 15);
    9461           0 :         }
    9462             : 
    9463           0 :         splx(s);
    9464           0 : }
    9465             : 
    9466             : int
    9467           0 : bwi_calc_rssi(struct bwi_softc *sc, const struct bwi_rxbuf_hdr *hdr)
    9468             : {
    9469             :         struct bwi_mac *mac;
    9470             : 
    9471           0 :         KASSERT(sc->sc_cur_regwin->rw_type == BWI_REGWIN_T_MAC);
    9472           0 :         mac = (struct bwi_mac *)sc->sc_cur_regwin;
    9473             : 
    9474           0 :         return (bwi_rf_calc_rssi(mac, hdr));
    9475             : }

Generated by: LCOV version 1.13