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

          Line data    Source code
       1             : /*      $OpenBSD: rtwn.c,v 1.37 2018/09/13 09:28:07 kevlo Exp $ */
       2             : 
       3             : /*-
       4             :  * Copyright (c) 2010 Damien Bergamini <damien.bergamini@free.fr>
       5             :  * Copyright (c) 2015 Stefan Sperling <stsp@openbsd.org>
       6             :  *
       7             :  * Permission to use, copy, modify, and distribute this software for any
       8             :  * purpose with or without fee is hereby granted, provided that the above
       9             :  * copyright notice and this permission notice appear in all copies.
      10             :  *
      11             :  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
      12             :  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
      13             :  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
      14             :  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
      15             :  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
      16             :  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
      17             :  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
      18             :  */
      19             : 
      20             : /*
      21             :  * Driver for Realtek 802.11b/g/n chipsets.
      22             :  */
      23             : 
      24             : #include "bpfilter.h"
      25             : 
      26             : #include <sys/param.h>
      27             : #include <sys/sockio.h>
      28             : #include <sys/mbuf.h>
      29             : #include <sys/kernel.h>
      30             : #include <sys/socket.h>
      31             : #include <sys/systm.h>
      32             : #include <sys/task.h>
      33             : #include <sys/timeout.h>
      34             : #include <sys/conf.h>
      35             : #include <sys/device.h>
      36             : #include <sys/endian.h>
      37             : 
      38             : #include <machine/bus.h>
      39             : #include <machine/intr.h>
      40             : 
      41             : #if NBPFILTER > 0
      42             : #include <net/bpf.h>
      43             : #endif
      44             : #include <net/if.h>
      45             : #include <net/if_dl.h>
      46             : #include <net/if_media.h>
      47             : 
      48             : #include <netinet/in.h>
      49             : #include <netinet/if_ether.h>
      50             : 
      51             : #include <net80211/ieee80211_var.h>
      52             : #include <net80211/ieee80211_radiotap.h>
      53             : 
      54             : #include <dev/ic/r92creg.h>
      55             : #include <dev/ic/rtwnvar.h>
      56             : 
      57             : #define RTWN_RIDX_CCK1          0
      58             : #define RTWN_RIDX_CCK2          1
      59             : #define RTWN_RIDX_CCK11         3
      60             : #define RTWN_RIDX_OFDM6         4
      61             : #define RTWN_RIDX_OFDM54        11
      62             : #define RTWN_RIDX_MCS0          12
      63             : #define RTWN_RIDX_MCS8          (RTWN_RIDX_MCS0 + 8)
      64             : #define RTWN_RIDX_MCS15         27
      65             : #define RTWN_RIDX_MAX           27
      66             : 
      67             : #define RTWN_POWER_CCK1         0
      68             : #define RTWN_POWER_CCK2         1
      69             : #define RTWN_POWER_CCK55        2
      70             : #define RTWN_POWER_CCK11        3
      71             : #define RTWN_POWER_OFDM6        4
      72             : #define RTWN_POWER_OFDM9        5
      73             : #define RTWN_POWER_OFDM12       6
      74             : #define RTWN_POWER_OFDM18       7
      75             : #define RTWN_POWER_OFDM24       8
      76             : #define RTWN_POWER_OFDM36       9
      77             : #define RTWN_POWER_OFDM48       10 
      78             : #define RTWN_POWER_OFDM54       11
      79             : #define RTWN_POWER_MCS(mcs)     (12 + (mcs))
      80             : #define RTWN_POWER_COUNT        28
      81             : 
      82             : 
      83             : #ifdef RTWN_DEBUG
      84             : #define DPRINTF(x)      do { if (rtwn_debug) printf x; } while (0)
      85             : #define DPRINTFN(n, x)  do { if (rtwn_debug >= (n)) printf x; } while (0)
      86             : int rtwn_debug = 0;
      87             : #else
      88             : #define DPRINTF(x)
      89             : #define DPRINTFN(n, x)
      90             : #endif
      91             : 
      92             : /* Registers to save and restore during IQ calibration. */
      93             : struct rtwn_iq_cal_regs {
      94             :         uint32_t        adda[16];
      95             :         uint8_t         txpause;
      96             :         uint8_t         bcn_ctrl;
      97             :         uint8_t         bcn_ctrl1;
      98             :         uint32_t        gpio_muxcfg;
      99             :         uint32_t        ofdm0_trxpathena;
     100             :         uint32_t        ofdm0_trmuxpar;
     101             :         uint32_t        fpga0_rfifacesw1;
     102             : };
     103             : 
     104             : void            rtwn_write_1(struct rtwn_softc *, uint16_t, uint8_t);
     105             : void            rtwn_write_2(struct rtwn_softc *, uint16_t, uint16_t);
     106             : void            rtwn_write_4(struct rtwn_softc *, uint16_t, uint32_t);
     107             : uint8_t         rtwn_read_1(struct rtwn_softc *, uint16_t);
     108             : uint16_t        rtwn_read_2(struct rtwn_softc *, uint16_t);
     109             : uint32_t        rtwn_read_4(struct rtwn_softc *, uint16_t);
     110             : int             rtwn_fw_cmd(struct rtwn_softc *, uint8_t, const void *, int);
     111             : void            rtwn_rf_write(struct rtwn_softc *, int, uint8_t, uint32_t);
     112             : uint32_t        rtwn_rf_read(struct rtwn_softc *, int, uint8_t);
     113             : void            rtwn_cam_write(struct rtwn_softc *, uint32_t, uint32_t);
     114             : uint8_t         rtwn_efuse_read_1(struct rtwn_softc *, uint16_t);
     115             : void            rtwn_efuse_read(struct rtwn_softc *, uint8_t *, size_t);
     116             : void            rtwn_efuse_switch_power(struct rtwn_softc *);
     117             : int             rtwn_read_chipid(struct rtwn_softc *);
     118             : void            rtwn_read_rom(struct rtwn_softc *);
     119             : void            rtwn_r92c_read_rom(struct rtwn_softc *);
     120             : void            rtwn_r88e_read_rom(struct rtwn_softc *);
     121             : int             rtwn_media_change(struct ifnet *);
     122             : int             rtwn_ra_init(struct rtwn_softc *);
     123             : int             rtwn_r92c_ra_init(struct rtwn_softc *, u_int8_t, u_int32_t,
     124             :                     int, uint32_t, int);
     125             : int             rtwn_r88e_ra_init(struct rtwn_softc *, u_int8_t, u_int32_t,
     126             :                     int, uint32_t, int);
     127             : void            rtwn_tsf_sync_enable(struct rtwn_softc *);
     128             : void            rtwn_set_led(struct rtwn_softc *, int, int);
     129             : void            rtwn_set_nettype(struct rtwn_softc *, enum ieee80211_opmode);
     130             : void            rtwn_update_short_preamble(struct ieee80211com *);
     131             : void            rtwn_r92c_update_short_preamble(struct rtwn_softc *);
     132             : void            rtwn_r88e_update_short_preamble(struct rtwn_softc *);
     133             : int8_t          rtwn_r88e_get_rssi(struct rtwn_softc *, int, void *);
     134             : void            rtwn_watchdog(struct ifnet *);
     135             : void            rtwn_fw_reset(struct rtwn_softc *);
     136             : void            rtwn_r92c_fw_reset(struct rtwn_softc *);
     137             : void            rtwn_r88e_fw_reset(struct rtwn_softc *);
     138             : int             rtwn_load_firmware(struct rtwn_softc *);
     139             : void            rtwn_rf_init(struct rtwn_softc *);
     140             : void            rtwn_cam_init(struct rtwn_softc *);
     141             : void            rtwn_pa_bias_init(struct rtwn_softc *);
     142             : void            rtwn_rxfilter_init(struct rtwn_softc *);
     143             : void            rtwn_edca_init(struct rtwn_softc *);
     144             : void            rtwn_rate_fallback_init(struct rtwn_softc *);
     145             : void            rtwn_usb_aggr_init(struct rtwn_softc *);
     146             : void            rtwn_write_txpower(struct rtwn_softc *, int, uint16_t[]);
     147             : void            rtwn_get_txpower(struct rtwn_softc *sc, int,
     148             :                     struct ieee80211_channel *, struct ieee80211_channel *,
     149             :                     uint16_t[]);
     150             : void            rtwn_r92c_get_txpower(struct rtwn_softc *, int,
     151             :                     struct ieee80211_channel *, struct ieee80211_channel *,
     152             :                     uint16_t[]);
     153             : void            rtwn_r88e_get_txpower(struct rtwn_softc *, int,
     154             :                     struct ieee80211_channel *,
     155             :                     struct ieee80211_channel *, uint16_t[]);
     156             : void            rtwn_set_txpower(struct rtwn_softc *,
     157             :                     struct ieee80211_channel *, struct ieee80211_channel *);
     158             : void            rtwn_set_chan(struct rtwn_softc *,
     159             :                     struct ieee80211_channel *, struct ieee80211_channel *);
     160             : int             rtwn_iq_calib_chain(struct rtwn_softc *, int, uint16_t[2],
     161             :                     uint16_t[2]);
     162             : void            rtwn_iq_calib_run(struct rtwn_softc *, int, uint16_t[2][2],
     163             :                     uint16_t rx[2][2], struct rtwn_iq_cal_regs *);
     164             : int             rtwn_iq_calib_compare_results(uint16_t[2][2], uint16_t[2][2],
     165             :                     uint16_t[2][2], uint16_t[2][2], int);
     166             : void            rtwn_iq_calib_write_results(struct rtwn_softc *, uint16_t[2],
     167             :                     uint16_t[2], int);
     168             : void            rtwn_iq_calib(struct rtwn_softc *);
     169             : void            rtwn_lc_calib(struct rtwn_softc *);
     170             : void            rtwn_temp_calib(struct rtwn_softc *);
     171             : void            rtwn_enable_intr(struct rtwn_softc *);
     172             : void            rtwn_disable_intr(struct rtwn_softc *);
     173             : int             rtwn_init(struct ifnet *);
     174             : void            rtwn_init_task(void *);
     175             : void            rtwn_stop(struct ifnet *);
     176             : 
     177             : /* Aliases. */
     178             : #define rtwn_bb_write   rtwn_write_4
     179             : #define rtwn_bb_read    rtwn_read_4
     180             : 
     181             : /* 
     182             :  * Macro to convert 4-bit signed integer to 8-bit signed integer.
     183             :  */
     184             : #define RTWN_SIGN4TO8(val)      (((val) & 0x08) ? (val) | 0xf0 : (val))
     185             : 
     186             : int
     187           0 : rtwn_attach(struct device *pdev, struct rtwn_softc *sc)
     188             : {
     189           0 :         struct ieee80211com *ic = &sc->sc_ic;
     190           0 :         struct ifnet *ifp = &ic->ic_if;
     191             :         int i, error;
     192             : 
     193           0 :         sc->sc_pdev = pdev;
     194             : 
     195           0 :         task_set(&sc->init_task, rtwn_init_task, sc);
     196             : 
     197           0 :         error = rtwn_read_chipid(sc);
     198           0 :         if (error != 0) {
     199           0 :                 printf("%s: unsupported chip\n", sc->sc_pdev->dv_xname);
     200           0 :                 return (ENXIO);
     201             :         }
     202             : 
     203             :         /* Determine number of Tx/Rx chains. */
     204           0 :         if (sc->chip & RTWN_CHIP_92C) {
     205           0 :                 sc->ntxchains = (sc->chip & RTWN_CHIP_92C_1T2R) ? 1 : 2;
     206           0 :                 sc->nrxchains = 2;
     207           0 :         } else {
     208           0 :                 sc->ntxchains = 1;
     209           0 :                 sc->nrxchains = 1;
     210             :         }
     211             : 
     212           0 :         rtwn_read_rom(sc);
     213             : 
     214           0 :         if (sc->chip & RTWN_CHIP_PCI) {
     215           0 :                 printf("%s: MAC/BB RTL%s, RF 6052 %dT%dR, address %s\n",
     216           0 :                     sc->sc_pdev->dv_xname,
     217           0 :                     (sc->chip & RTWN_CHIP_92C) ? "8192CE" :
     218           0 :                     (sc->chip & RTWN_CHIP_88E) ? "8188EE" : "8188CE",
     219           0 :                     sc->ntxchains, sc->nrxchains,
     220           0 :                     ether_sprintf(ic->ic_myaddr));
     221           0 :         } else if (sc->chip & RTWN_CHIP_USB) {
     222           0 :                 printf("%s: MAC/BB RTL%s, RF 6052 %dT%dR, address %s\n",
     223             :                     sc->sc_pdev->dv_xname,
     224           0 :                     (sc->chip & RTWN_CHIP_92C) ? "8192CU" :
     225           0 :                     (sc->chip & RTWN_CHIP_88E) ? "8188EU" :
     226           0 :                     (sc->board_type == R92C_BOARD_TYPE_HIGHPA) ? "8188RU" :
     227           0 :                     (sc->board_type == R92C_BOARD_TYPE_MINICARD) ?
     228             :                     "8188CE-VAU" : "8188CUS",
     229           0 :                     sc->ntxchains, sc->nrxchains,
     230           0 :                     ether_sprintf(ic->ic_myaddr));
     231             :         } else {
     232           0 :                 printf("%s: unsupported chip\n", sc->sc_pdev->dv_xname);
     233           0 :                 return (ENXIO);
     234             :         }
     235             : 
     236           0 :         ic->ic_phytype = IEEE80211_T_OFDM;   /* Not only, but not used. */
     237           0 :         ic->ic_opmode = IEEE80211_M_STA;     /* Default to BSS mode. */
     238           0 :         ic->ic_state = IEEE80211_S_INIT;
     239             : 
     240             :         /* Set device capabilities. */
     241           0 :         ic->ic_caps =
     242             :             IEEE80211_C_MONITOR |       /* Monitor mode supported. */
     243             :             IEEE80211_C_SHPREAMBLE |    /* Short preamble supported. */
     244             :             IEEE80211_C_SHSLOT |        /* Short slot time supported. */
     245             :             IEEE80211_C_WEP |           /* WEP. */
     246             :             IEEE80211_C_RSN;            /* WPA/RSN. */
     247             : 
     248             :         /* Set HT capabilities. */
     249           0 :         ic->ic_htcaps =
     250             :             IEEE80211_HTCAP_CBW20_40 |
     251             :             IEEE80211_HTCAP_DSSSCCK40;
     252             :         /* Set supported HT rates. */
     253           0 :         for (i = 0; i < sc->nrxchains; i++)
     254           0 :                 ic->ic_sup_mcs[i] = 0xff;
     255             : 
     256             :         /* Set supported .11b and .11g rates. */
     257           0 :         ic->ic_sup_rates[IEEE80211_MODE_11B] = ieee80211_std_rateset_11b;
     258           0 :         ic->ic_sup_rates[IEEE80211_MODE_11G] = ieee80211_std_rateset_11g;
     259             : 
     260             :         /* Set supported .11b and .11g channels (1 through 14). */
     261           0 :         for (i = 1; i <= 14; i++) {
     262           0 :                 ic->ic_channels[i].ic_freq =
     263           0 :                     ieee80211_ieee2mhz(i, IEEE80211_CHAN_2GHZ);
     264           0 :                 ic->ic_channels[i].ic_flags =
     265             :                     IEEE80211_CHAN_CCK | IEEE80211_CHAN_OFDM |
     266             :                     IEEE80211_CHAN_DYN | IEEE80211_CHAN_2GHZ;
     267             :         }
     268             : 
     269             : #ifdef notyet
     270             :         /*
     271             :          * The number of STAs that we can support is limited by the number
     272             :          * of CAM entries used for hardware crypto.
     273             :          */
     274             :         ic->ic_max_nnodes = R92C_CAM_ENTRY_COUNT - 4;
     275             :         if (ic->ic_max_nnodes > IEEE80211_CACHE_SIZE)
     276             :                 ic->ic_max_nnodes = IEEE80211_CACHE_SIZE;
     277             : #endif
     278             : 
     279           0 :         ifp->if_softc = sc;
     280           0 :         ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
     281           0 :         ifp->if_ioctl = rtwn_ioctl;
     282           0 :         ifp->if_start = rtwn_start;
     283           0 :         ifp->if_watchdog = rtwn_watchdog;
     284           0 :         memcpy(ifp->if_xname, sc->sc_pdev->dv_xname, IFNAMSIZ);
     285             : 
     286           0 :         if_attach(ifp);
     287           0 :         ieee80211_ifattach(ifp);
     288           0 :         ic->ic_updateslot = rtwn_updateslot;
     289           0 :         ic->ic_updateedca = rtwn_updateedca;
     290             : #ifdef notyet
     291             :         ic->ic_set_key = rtwn_set_key;
     292             :         ic->ic_delete_key = rtwn_delete_key;
     293             : #endif
     294             :         /* Override state transition machine. */
     295           0 :         sc->sc_newstate = ic->ic_newstate;
     296           0 :         ic->ic_newstate = rtwn_newstate;
     297           0 :         ieee80211_media_init(ifp, rtwn_media_change, ieee80211_media_status);
     298             : 
     299           0 :         return (0);
     300           0 : }
     301             : 
     302             : int
     303           0 : rtwn_detach(struct rtwn_softc *sc, int flags)
     304             : {
     305           0 :         struct ifnet *ifp = &sc->sc_ic.ic_if;
     306             :         int s;
     307             : 
     308           0 :         s = splnet();
     309             : 
     310           0 :         task_del(systq, &sc->init_task);
     311             : 
     312           0 :         if (ifp->if_softc != NULL) {
     313           0 :                 ieee80211_ifdetach(ifp);
     314           0 :                 if_detach(ifp);
     315           0 :         }
     316             : 
     317           0 :         splx(s);
     318             : 
     319           0 :         return (0);
     320             : }
     321             : 
     322             : int
     323           0 : rtwn_activate(struct rtwn_softc *sc, int act)
     324             : {
     325           0 :         struct ifnet *ifp = &sc->sc_ic.ic_if;
     326             : 
     327           0 :         switch (act) {
     328             :         case DVACT_QUIESCE: /* rtwn_stop() may sleep */
     329           0 :                 if (ifp->if_flags & IFF_RUNNING)
     330           0 :                         rtwn_stop(ifp);
     331             :                 break;
     332             :         case DVACT_WAKEUP:
     333           0 :                 rtwn_init_task(sc);
     334           0 :                 break;
     335             :         }
     336           0 :         return (0);
     337             : }
     338             : 
     339             : void
     340           0 : rtwn_write_1(struct rtwn_softc *sc, uint16_t addr, uint8_t val)
     341             : {
     342           0 :         sc->sc_ops.write_1(sc->sc_ops.cookie, addr, val);
     343           0 : }
     344             : 
     345             : void
     346           0 : rtwn_write_2(struct rtwn_softc *sc, uint16_t addr, uint16_t val)
     347             : {
     348           0 :         sc->sc_ops.write_2(sc->sc_ops.cookie, addr, val);
     349           0 : }
     350             : 
     351             : void
     352           0 : rtwn_write_4(struct rtwn_softc *sc, uint16_t addr, uint32_t val)
     353             : {
     354           0 :         sc->sc_ops.write_4(sc->sc_ops.cookie, addr, val);
     355           0 : }
     356             : 
     357             : uint8_t
     358           0 : rtwn_read_1(struct rtwn_softc *sc, uint16_t addr)
     359             : {
     360           0 :         return sc->sc_ops.read_1(sc->sc_ops.cookie, addr);
     361             : }
     362             : 
     363             : uint16_t
     364           0 : rtwn_read_2(struct rtwn_softc *sc, uint16_t addr)
     365             : {
     366           0 :         return sc->sc_ops.read_2(sc->sc_ops.cookie, addr);
     367             : }
     368             : 
     369             : uint32_t
     370           0 : rtwn_read_4(struct rtwn_softc *sc, uint16_t addr)
     371             : {
     372           0 :         return sc->sc_ops.read_4(sc->sc_ops.cookie, addr);
     373             : }
     374             : 
     375             : int
     376           0 : rtwn_fw_cmd(struct rtwn_softc *sc, uint8_t id, const void *buf, int len)
     377             : {
     378           0 :         struct r92c_fw_cmd cmd;
     379             :         int ntries;
     380             : 
     381             :         /* Wait for current FW box to be empty. */
     382           0 :         for (ntries = 0; ntries < 100; ntries++) {
     383           0 :                 if (!(rtwn_read_1(sc, R92C_HMETFR) & (1 << sc->fwcur)))
     384             :                         break;
     385           0 :                 DELAY(1);
     386             :         }
     387           0 :         if (ntries == 100) {
     388           0 :                 printf("%s: could not send firmware command %d\n",
     389           0 :                     sc->sc_pdev->dv_xname, id);
     390           0 :                 return (ETIMEDOUT);
     391             :         }
     392           0 :         memset(&cmd, 0, sizeof(cmd));
     393             :         cmd.id = id;
     394           0 :         if (len > 3)
     395           0 :                 cmd.id |= R92C_CMD_FLAG_EXT;
     396           0 :         KASSERT(len <= sizeof(cmd.msg));
     397           0 :         memcpy(cmd.msg, buf, len);
     398             : 
     399             :         /* Write the first word last since that will trigger the FW. */
     400           0 :         rtwn_write_2(sc, R92C_HMEBOX_EXT(sc->fwcur), *((uint8_t *)&cmd + 4));
     401           0 :         rtwn_write_4(sc, R92C_HMEBOX(sc->fwcur), *((uint8_t *)&cmd + 0));
     402             : 
     403           0 :         sc->fwcur = (sc->fwcur + 1) % R92C_H2C_NBOX;
     404             : 
     405           0 :         if (sc->chip & RTWN_CHIP_PCI) {
     406             :                 /* Give firmware some time for processing. */
     407           0 :                 DELAY(2000);
     408           0 :         }
     409             : 
     410           0 :         return (0);
     411           0 : }
     412             : 
     413             : void
     414           0 : rtwn_rf_write(struct rtwn_softc *sc, int chain, uint8_t addr, uint32_t val)
     415             : {
     416             :         uint32_t param_addr;
     417             : 
     418           0 :         if (sc->chip & RTWN_CHIP_88E)
     419           0 :                 param_addr = SM(R88E_LSSI_PARAM_ADDR, addr);
     420             :         else
     421           0 :                 param_addr = SM(R92C_LSSI_PARAM_ADDR, addr);
     422             : 
     423           0 :         rtwn_bb_write(sc, R92C_LSSI_PARAM(chain),
     424           0 :             param_addr | SM(R92C_LSSI_PARAM_DATA, val));
     425           0 : }
     426             : 
     427             : uint32_t
     428           0 : rtwn_rf_read(struct rtwn_softc *sc, int chain, uint8_t addr)
     429             : {
     430           0 :         uint32_t reg[R92C_MAX_CHAINS], val;
     431             : 
     432           0 :         reg[0] = rtwn_bb_read(sc, R92C_HSSI_PARAM2(0));
     433           0 :         if (chain != 0)
     434           0 :                 reg[chain] = rtwn_bb_read(sc, R92C_HSSI_PARAM2(chain));
     435             : 
     436           0 :         rtwn_bb_write(sc, R92C_HSSI_PARAM2(0),
     437           0 :             reg[0] & ~R92C_HSSI_PARAM2_READ_EDGE);
     438           0 :         DELAY(1000);
     439             : 
     440           0 :         rtwn_bb_write(sc, R92C_HSSI_PARAM2(chain),
     441           0 :             RW(reg[chain], R92C_HSSI_PARAM2_READ_ADDR, addr) |
     442             :             R92C_HSSI_PARAM2_READ_EDGE);
     443           0 :         DELAY(1000);
     444             : 
     445           0 :         if (!(sc->chip & RTWN_CHIP_88E)) {
     446           0 :                 rtwn_bb_write(sc, R92C_HSSI_PARAM2(0),
     447           0 :                     reg[0] | R92C_HSSI_PARAM2_READ_EDGE);
     448           0 :                 DELAY(1000);
     449           0 :         }
     450             : 
     451           0 :         if (rtwn_bb_read(sc, R92C_HSSI_PARAM1(chain)) & R92C_HSSI_PARAM1_PI)
     452           0 :                 val = rtwn_bb_read(sc, R92C_HSPI_READBACK(chain));
     453             :         else
     454           0 :                 val = rtwn_bb_read(sc, R92C_LSSI_READBACK(chain));
     455           0 :         return (MS(val, R92C_LSSI_READBACK_DATA));
     456           0 : }
     457             : 
     458             : void
     459           0 : rtwn_cam_write(struct rtwn_softc *sc, uint32_t addr, uint32_t data)
     460             : {
     461           0 :         rtwn_write_4(sc, R92C_CAMWRITE, data);
     462           0 :         rtwn_write_4(sc, R92C_CAMCMD,
     463           0 :             R92C_CAMCMD_POLLING | R92C_CAMCMD_WRITE |
     464           0 :             SM(R92C_CAMCMD_ADDR, addr));
     465           0 : }
     466             : 
     467             : uint8_t
     468           0 : rtwn_efuse_read_1(struct rtwn_softc *sc, uint16_t addr)
     469             : {
     470             :         uint32_t reg;
     471             :         int ntries;
     472             : 
     473           0 :         reg = rtwn_read_4(sc, R92C_EFUSE_CTRL);
     474           0 :         reg = RW(reg, R92C_EFUSE_CTRL_ADDR, addr);
     475           0 :         reg &= ~R92C_EFUSE_CTRL_VALID;
     476           0 :         rtwn_write_4(sc, R92C_EFUSE_CTRL, reg);
     477             :         /* Wait for read operation to complete. */
     478           0 :         for (ntries = 0; ntries < 100; ntries++) {
     479           0 :                 reg = rtwn_read_4(sc, R92C_EFUSE_CTRL);
     480           0 :                 if (reg & R92C_EFUSE_CTRL_VALID)
     481           0 :                         return (MS(reg, R92C_EFUSE_CTRL_DATA));
     482           0 :                 DELAY(5);
     483             :         }
     484           0 :         printf("%s: could not read efuse byte at address 0x%x\n",
     485           0 :             sc->sc_pdev->dv_xname, addr);
     486           0 :         return (0xff);
     487           0 : }
     488             : 
     489             : void
     490           0 : rtwn_efuse_read(struct rtwn_softc *sc, uint8_t *rom, size_t size)
     491             : {
     492             :         uint8_t off, msk, tmp;
     493             :         uint16_t addr = 0;
     494             :         uint32_t reg;
     495             :         int i, len;
     496             : 
     497           0 :         rtwn_write_1(sc, R92C_EFUSE_ACCESS, R92C_EFUSE_ACCESS_ON);
     498           0 :         rtwn_efuse_switch_power(sc);
     499             : 
     500           0 :         memset(rom, 0xff, size);
     501           0 :         len = (sc->chip & RTWN_CHIP_88E) ? 256 : 512;
     502           0 :         while (addr < len) {
     503           0 :                 reg = rtwn_efuse_read_1(sc, addr);
     504           0 :                 if (reg == 0xff)
     505             :                         break;
     506           0 :                 addr++;
     507             : 
     508             :                 /* Check for extended header. */
     509           0 :                 if ((sc->sc_flags & RTWN_FLAG_EXT_HDR) &&
     510           0 :                     (reg & 0x1f) == 0x0f) {
     511           0 :                         tmp = (reg & 0xe0) >> 5;
     512           0 :                         reg = rtwn_efuse_read_1(sc, addr);
     513           0 :                         addr++;
     514           0 :                         if ((reg & 0x0f) != 0x0f)
     515           0 :                                 off = ((reg & 0xf0) >> 1) | tmp;
     516             :                         else
     517           0 :                                 continue;
     518           0 :                 } else
     519           0 :                         off = reg >> 4;
     520           0 :                 msk = reg & 0xf;
     521           0 :                 for (i = 0; i < 4; i++) {
     522           0 :                         if (msk & (1 << i))
     523             :                                 continue;
     524           0 :                         rom[off * 8 + i * 2 + 0] = rtwn_efuse_read_1(sc, addr);
     525           0 :                         addr++;
     526           0 :                         rom[off * 8 + i * 2 + 1] = rtwn_efuse_read_1(sc, addr);
     527           0 :                         addr++;
     528           0 :                 }
     529             :         }
     530             : #ifdef RTWN_DEBUG
     531             :         if (rtwn_debug >= 2) {
     532             :                 /* Dump ROM content. */
     533             :                 printf("\n");
     534             :                 for (i = 0; i < size; i++)
     535             :                         printf("%02x:", rom[i]);
     536             :                 printf("\n");
     537             :         }
     538             : #endif
     539           0 :         rtwn_write_1(sc, R92C_EFUSE_ACCESS, R92C_EFUSE_ACCESS_OFF);
     540           0 : }
     541             : 
     542             : void
     543           0 : rtwn_efuse_switch_power(struct rtwn_softc *sc)
     544             : {
     545             :         uint16_t reg;
     546             : 
     547           0 :         reg = rtwn_read_2(sc, R92C_SYS_ISO_CTRL);
     548           0 :         if (!(reg & R92C_SYS_ISO_CTRL_PWC_EV12V)) {
     549           0 :                 rtwn_write_2(sc, R92C_SYS_ISO_CTRL,
     550           0 :                     reg | R92C_SYS_ISO_CTRL_PWC_EV12V);
     551           0 :         }
     552           0 :         reg = rtwn_read_2(sc, R92C_SYS_FUNC_EN);
     553           0 :         if (!(reg & R92C_SYS_FUNC_EN_ELDR)) {
     554           0 :                 rtwn_write_2(sc, R92C_SYS_FUNC_EN,
     555           0 :                     reg | R92C_SYS_FUNC_EN_ELDR);
     556           0 :         }
     557           0 :         reg = rtwn_read_2(sc, R92C_SYS_CLKR);
     558           0 :         if ((reg & (R92C_SYS_CLKR_LOADER_EN | R92C_SYS_CLKR_ANA8M)) !=
     559             :             (R92C_SYS_CLKR_LOADER_EN | R92C_SYS_CLKR_ANA8M)) {
     560           0 :                 rtwn_write_2(sc, R92C_SYS_CLKR,
     561           0 :                     reg | R92C_SYS_CLKR_LOADER_EN | R92C_SYS_CLKR_ANA8M);
     562           0 :         }
     563           0 : }
     564             : 
     565             : int
     566           0 : rtwn_read_chipid(struct rtwn_softc *sc)
     567             : {
     568             :         uint32_t reg;
     569             : 
     570           0 :         if (sc->chip & RTWN_CHIP_88E) {
     571           0 :                 sc->sc_flags |= RTWN_FLAG_EXT_HDR;
     572           0 :                 return (0);
     573             :         }
     574             : 
     575           0 :         reg = rtwn_read_4(sc, R92C_SYS_CFG);
     576           0 :         if (reg & R92C_SYS_CFG_TRP_VAUX_EN)
     577             :                 /* Unsupported test chip. */
     578           0 :                 return (EIO);
     579             : 
     580           0 :         if ((sc->chip & (RTWN_CHIP_92C | RTWN_CHIP_88C)) != 0) {
     581           0 :                 if (reg & R92C_SYS_CFG_TYPE_92C) {
     582           0 :                         sc->chip &= ~RTWN_CHIP_88C;
     583             :                         /* Check if it is a castrated 8192C. */
     584           0 :                         if (MS(rtwn_read_4(sc, R92C_HPON_FSM),
     585           0 :                             R92C_HPON_FSM_CHIP_BONDING_ID) ==
     586             :                             R92C_HPON_FSM_CHIP_BONDING_ID_92C_1T2R)
     587           0 :                                 sc->chip |= RTWN_CHIP_92C_1T2R;
     588             :                 } else
     589           0 :                         sc->chip &= ~RTWN_CHIP_92C;
     590             : 
     591           0 :                 if (reg & R92C_SYS_CFG_VENDOR_UMC) {
     592           0 :                         sc->chip |= RTWN_CHIP_UMC;
     593           0 :                         if (MS(reg, R92C_SYS_CFG_CHIP_VER_RTL) == 0)
     594           0 :                                 sc->chip |= RTWN_CHIP_UMC_A_CUT;
     595             :                 }
     596             : 
     597           0 :                 return (0);
     598             :         }
     599             : 
     600           0 :         return (ENXIO); /* unsupported chip */
     601           0 : }
     602             : 
     603             : void
     604           0 : rtwn_read_rom(struct rtwn_softc *sc)
     605             : {
     606           0 :         if (sc->chip & RTWN_CHIP_88E)
     607           0 :                 rtwn_r88e_read_rom(sc);
     608             :         else
     609           0 :                 rtwn_r92c_read_rom(sc);
     610           0 : }
     611             : 
     612             : void
     613           0 : rtwn_r92c_read_rom(struct rtwn_softc *sc)
     614             : {
     615           0 :         struct ieee80211com *ic = &sc->sc_ic;
     616           0 :         struct r92c_rom *rom = &sc->sc_r92c_rom;
     617             : 
     618             :         /* Read full ROM image. */
     619           0 :         rtwn_efuse_read(sc, (uint8_t *)&sc->sc_r92c_rom,
     620             :             sizeof(sc->sc_r92c_rom));
     621             : 
     622             :         /* XXX Weird but this is what the vendor driver does. */
     623           0 :         sc->pa_setting = rtwn_efuse_read_1(sc, 0x1fa);
     624             :         DPRINTF(("PA setting=0x%x\n", sc->pa_setting));
     625             : 
     626           0 :         sc->board_type = MS(rom->rf_opt1, R92C_ROM_RF1_BOARD_TYPE);
     627             :         DPRINTF(("board type=%d\n", sc->board_type));
     628             : 
     629           0 :         sc->regulatory = MS(rom->rf_opt1, R92C_ROM_RF1_REGULATORY);
     630             :         DPRINTF(("regulatory type=%d\n", sc->regulatory));
     631             : 
     632           0 :         IEEE80211_ADDR_COPY(ic->ic_myaddr, rom->macaddr);
     633           0 : }
     634             : 
     635             : void
     636           0 : rtwn_r88e_read_rom(struct rtwn_softc *sc)
     637             : {
     638           0 :         struct ieee80211com *ic = &sc->sc_ic;
     639           0 :         struct r88e_rom *rom = &sc->sc_r88e_rom;
     640             : 
     641             :         /* Read full ROM image. */
     642           0 :         rtwn_efuse_read(sc, (uint8_t *)&sc->sc_r88e_rom,
     643             :             sizeof(sc->sc_r88e_rom));
     644             : 
     645           0 :         sc->crystal_cap = rom->xtal;
     646             :         DPRINTF(("Crystal cap=0x%x\n", sc->crystal_cap));
     647             : 
     648           0 :         sc->regulatory = MS(rom->rf_board_opt, R92C_ROM_RF1_REGULATORY);
     649             :         DPRINTF(("regulatory type=%d\n", sc->regulatory));
     650             : 
     651           0 :         IEEE80211_ADDR_COPY(ic->ic_myaddr, rom->macaddr);
     652           0 : }
     653             : 
     654             : int
     655           0 : rtwn_media_change(struct ifnet *ifp)
     656             : {
     657             :         int error;
     658             : 
     659           0 :         error = ieee80211_media_change(ifp);
     660           0 :         if (error != ENETRESET)
     661           0 :                 return (error);
     662             : 
     663           0 :         if ((ifp->if_flags & (IFF_UP | IFF_RUNNING)) ==
     664             :             (IFF_UP | IFF_RUNNING)) {
     665           0 :                 rtwn_stop(ifp);
     666           0 :                 rtwn_init(ifp);
     667           0 :         }
     668           0 :         return (0);
     669           0 : }
     670             : 
     671             : /*
     672             :  * Initialize rate adaptation.
     673             :  */
     674             : int
     675           0 : rtwn_ra_init(struct rtwn_softc *sc)
     676             : {
     677             :         static const uint8_t map[] =
     678             :             { 2, 4, 11, 22, 12, 18, 24, 36, 48, 72, 96, 108 };
     679           0 :         struct ieee80211com *ic = &sc->sc_ic;
     680           0 :         struct ieee80211_node *ni = ic->ic_bss;
     681           0 :         struct ieee80211_rateset *rs = &ni->ni_rates;
     682             :         uint32_t rates, basicrates;
     683             :         uint8_t mode;
     684             :         int maxrate, maxbasicrate, i, j;
     685             :         int error = 0;
     686             : 
     687             :         /* Get normal and basic rates mask. */
     688             :         rates = basicrates = 0;
     689             :         maxrate = maxbasicrate = 0;
     690           0 :         for (i = 0; i < rs->rs_nrates; i++) {
     691             :                 /* Convert 802.11 rate to HW rate index. */
     692           0 :                 for (j = 0; j < nitems(map); j++)
     693           0 :                         if ((rs->rs_rates[i] & IEEE80211_RATE_VAL) == map[j])
     694             :                                 break;
     695           0 :                 if (j == nitems(map))   /* Unknown rate, skip. */
     696             :                         continue;
     697           0 :                 rates |= 1 << j;
     698           0 :                 if (j > maxrate)
     699           0 :                         maxrate = j;
     700           0 :                 if (rs->rs_rates[i] & IEEE80211_RATE_BASIC) {
     701           0 :                         basicrates |= 1 << j;
     702           0 :                         if (j > maxbasicrate)
     703           0 :                                 maxbasicrate = j;
     704             :                 }
     705             :         }
     706           0 :         if (ic->ic_curmode == IEEE80211_MODE_11B)
     707           0 :                 mode = R92C_RAID_11B;
     708             :         else
     709             :                 mode = R92C_RAID_11BG;
     710             :         DPRINTF(("mode=0x%x rates=0x%08x, basicrates=0x%08x\n",
     711             :             mode, rates, basicrates));
     712             : 
     713           0 :         if (sc->chip & RTWN_CHIP_PCI) {
     714             :                 /* Configure Automatic Rate Fallback Register. */
     715           0 :                 if (ic->ic_curmode == IEEE80211_MODE_11B) {
     716           0 :                         if (rates & 0x0c)
     717           0 :                                 rtwn_write_4(sc, R92C_ARFR(0), rates & 0x05);
     718             :                         else
     719           0 :                                 rtwn_write_4(sc, R92C_ARFR(0), rates & 0x07);
     720             :                 } else
     721           0 :                         rtwn_write_4(sc, R92C_ARFR(0), rates & 0x07f5);
     722             :         }
     723             : 
     724           0 :         if (sc->chip & RTWN_CHIP_88E) {
     725           0 :                 error = rtwn_r88e_ra_init(sc, mode, rates, maxrate,
     726             :                     basicrates, maxbasicrate);
     727             :                 /* We use AMRR with this chip. Start with the lowest rate. */
     728           0 :                 ni->ni_txrate = 0;
     729           0 :         } else {
     730           0 :                 if (sc->chip & RTWN_CHIP_PCI) {
     731           0 :                         ni->ni_txrate = 0; /* AMRR will raise. */
     732             :                         /* Set initial MRR rates. */
     733           0 :                         rtwn_write_1(sc,
     734           0 :                             R92C_INIDATA_RATE_SEL(R92C_MACID_BC), maxbasicrate);
     735           0 :                         rtwn_write_1(sc,
     736             :                             R92C_INIDATA_RATE_SEL(R92C_MACID_BSS), 0);
     737           0 :                 } else {
     738           0 :                         error = rtwn_r92c_ra_init(sc, mode, rates, maxrate,
     739             :                             basicrates, maxbasicrate);
     740             :                         /* No AMRR support. Indicate highest supported rate. */
     741           0 :                         ni->ni_txrate = rs->rs_nrates - 1;
     742             :                 }
     743             :         }
     744           0 :         return (error);
     745             : }
     746             : 
     747             : /*
     748             :  * Initialize rate adaptation in firmware.
     749             :  */
     750           0 : int rtwn_r92c_ra_init(struct rtwn_softc *sc, u_int8_t mode, u_int32_t rates,
     751             :     int maxrate, uint32_t basicrates, int maxbasicrate)
     752             : {
     753           0 :         struct r92c_fw_cmd_macid_cfg cmd;
     754             :         int error;
     755             : 
     756             :         /* Set rates mask for group addressed frames. */
     757           0 :         cmd.macid = R92C_MACID_BC | R92C_MACID_VALID;
     758           0 :         cmd.mask = htole32(mode << 28 | basicrates);
     759           0 :         error = rtwn_fw_cmd(sc, R92C_CMD_MACID_CONFIG, &cmd, sizeof(cmd));
     760           0 :         if (error != 0) {
     761           0 :                 printf("%s: could not add broadcast station\n",
     762           0 :                     sc->sc_pdev->dv_xname);
     763           0 :                 return (error);
     764             :         }
     765             :         /* Set initial MRR rate. */
     766             :         DPRINTF(("maxbasicrate=%d\n", maxbasicrate));
     767           0 :         rtwn_write_1(sc, R92C_INIDATA_RATE_SEL(R92C_MACID_BC),
     768           0 :             maxbasicrate);
     769             : 
     770             :         /* Set rates mask for unicast frames. */
     771           0 :         cmd.macid = R92C_MACID_BSS | R92C_MACID_VALID;
     772           0 :         cmd.mask = htole32(mode << 28 | rates);
     773           0 :         error = rtwn_fw_cmd(sc, R92C_CMD_MACID_CONFIG, &cmd, sizeof(cmd));
     774           0 :         if (error != 0) {
     775           0 :                 printf("%s: could not add BSS station\n",
     776           0 :                     sc->sc_pdev->dv_xname);
     777           0 :                 return (error);
     778             :         }
     779             :         /* Set initial MRR rate. */
     780             :         DPRINTF(("maxrate=%d\n", maxrate));
     781           0 :         rtwn_write_1(sc, R92C_INIDATA_RATE_SEL(R92C_MACID_BSS),
     782           0 :             maxrate);
     783             : 
     784           0 :         return (0);
     785           0 : }
     786             : 
     787             : int
     788           0 : rtwn_r88e_ra_init(struct rtwn_softc *sc, u_int8_t mode, u_int32_t rates,
     789             :     int maxrate, uint32_t basicrates, int maxbasicrate)
     790             : {
     791             :         u_int32_t reg;
     792             : 
     793           0 :         rtwn_write_1(sc, R92C_INIRTS_RATE_SEL, maxbasicrate);
     794             : 
     795           0 :         reg = rtwn_read_4(sc, R92C_RRSR);
     796           0 :         reg = RW(reg, R92C_RRSR_RATE_BITMAP, rates);
     797           0 :         rtwn_write_4(sc, R92C_RRSR, reg);
     798             : 
     799             :         /*
     800             :          * Workaround for performance problems with firmware rate adaptation:
     801             :          * If the AP only supports 11b rates, disable mixed B/G mode.
     802             :          */
     803           0 :         if (mode != R92C_RAID_11B && maxrate <= 3 /* 11M */)
     804           0 :                 sc->sc_flags |= RTWN_FLAG_FORCE_RAID_11B;
     805             : 
     806           0 :         return (0);
     807             : }
     808             : 
     809             : void
     810           0 : rtwn_tsf_sync_enable(struct rtwn_softc *sc)
     811             : {
     812           0 :         struct ieee80211_node *ni = sc->sc_ic.ic_bss;
     813             :         uint64_t tsf;
     814             : 
     815             :         /* Enable TSF synchronization. */
     816           0 :         rtwn_write_1(sc, R92C_BCN_CTRL,
     817           0 :             rtwn_read_1(sc, R92C_BCN_CTRL) & ~R92C_BCN_CTRL_DIS_TSF_UDT0);
     818             : 
     819           0 :         rtwn_write_1(sc, R92C_BCN_CTRL,
     820           0 :             rtwn_read_1(sc, R92C_BCN_CTRL) & ~R92C_BCN_CTRL_EN_BCN);
     821             : 
     822             :         /* Set initial TSF. */
     823           0 :         memcpy(&tsf, ni->ni_tstamp, sizeof(tsf));
     824             :         tsf = letoh64(tsf);
     825           0 :         tsf = tsf - (tsf % (ni->ni_intval * IEEE80211_DUR_TU));
     826           0 :         tsf -= IEEE80211_DUR_TU;
     827           0 :         rtwn_write_4(sc, R92C_TSFTR + 0, tsf);
     828           0 :         rtwn_write_4(sc, R92C_TSFTR + 4, tsf >> 32);
     829             : 
     830           0 :         rtwn_write_1(sc, R92C_BCN_CTRL,
     831           0 :             rtwn_read_1(sc, R92C_BCN_CTRL) | R92C_BCN_CTRL_EN_BCN);
     832           0 : }
     833             : 
     834             : void
     835           0 : rtwn_set_led(struct rtwn_softc *sc, int led, int on)
     836             : {
     837             :         uint8_t reg;
     838             : 
     839           0 :         if (led != RTWN_LED_LINK)
     840           0 :                 return; /* not supported */
     841             : 
     842           0 :         if (sc->chip & RTWN_CHIP_PCI) {
     843           0 :                 reg = rtwn_read_1(sc, R92C_LEDCFG2) & 0xf0;
     844           0 :                 if (!on)
     845           0 :                         reg |= R92C_LEDCFG2_DIS;
     846             :                 else
     847           0 :                         reg |= R92C_LEDCFG2_EN;
     848           0 :                 rtwn_write_1(sc, R92C_LEDCFG2, reg);
     849           0 :         } else if (sc->chip & RTWN_CHIP_USB) {
     850           0 :                 if (sc->chip & RTWN_CHIP_88E) {
     851           0 :                         reg = rtwn_read_1(sc, R92C_LEDCFG2) & 0xf0;
     852           0 :                         rtwn_write_1(sc, R92C_LEDCFG2, reg | R92C_LEDCFG2_EN);
     853           0 :                         if (!on) {
     854           0 :                                 reg = rtwn_read_1(sc, R92C_LEDCFG2) & 0x90;
     855           0 :                                 rtwn_write_1(sc, R92C_LEDCFG2,
     856           0 :                                     reg | R92C_LEDCFG0_DIS);
     857           0 :                                 rtwn_write_1(sc, R92C_MAC_PINMUX_CFG,
     858           0 :                                     rtwn_read_1(sc, R92C_MAC_PINMUX_CFG) &
     859             :                                     0xfe);
     860           0 :                         }
     861             :                 } else {
     862           0 :                         reg = rtwn_read_1(sc, R92C_LEDCFG0) & 0x70;
     863           0 :                         if (!on)
     864           0 :                                 reg |= R92C_LEDCFG0_DIS;
     865           0 :                         rtwn_write_1(sc, R92C_LEDCFG0, reg);
     866             :                 }
     867             :         }
     868           0 :         sc->ledlink = on;    /* Save LED state. */
     869           0 : }
     870             : 
     871             : void
     872           0 : rtwn_set_nettype(struct rtwn_softc *sc, enum ieee80211_opmode opmode)
     873             : {
     874             :         uint8_t msr;
     875             : 
     876           0 :         msr = rtwn_read_1(sc, R92C_MSR) & ~R92C_MSR_NETTYPE_MASK;
     877             : 
     878           0 :         switch (opmode) {
     879             :         case IEEE80211_M_MONITOR:
     880           0 :                 msr |= R92C_MSR_NETTYPE_NOLINK;
     881           0 :                 break;
     882             :         case IEEE80211_M_STA:
     883           0 :                 msr |= R92C_MSR_NETTYPE_INFRA;
     884           0 :                 break;
     885             :         default:
     886             :                 break;
     887             :         }
     888             : 
     889           0 :         rtwn_write_1(sc, R92C_MSR, msr);
     890           0 : }
     891             : 
     892             : void
     893           0 : rtwn_calib(struct rtwn_softc *sc)
     894             : {
     895           0 :         struct r92c_fw_cmd_rssi cmd;
     896             : 
     897           0 :         if (sc->avg_pwdb != -1) {
     898             :                 /* Indicate Rx signal strength to FW for rate adaptation. */
     899           0 :                 memset(&cmd, 0, sizeof(cmd));
     900           0 :                 cmd.macid = 0;  /* BSS. */
     901           0 :                 cmd.pwdb = sc->avg_pwdb;
     902             :                 DPRINTFN(3, ("sending RSSI command avg=%d\n", sc->avg_pwdb));
     903           0 :                 rtwn_fw_cmd(sc, R92C_CMD_RSSI_SETTING, &cmd, sizeof(cmd));
     904           0 :         }
     905             : 
     906             :         /* Do temperature compensation. */
     907           0 :         rtwn_temp_calib(sc);
     908             : 
     909           0 :         sc->sc_ops.next_calib(sc->sc_ops.cookie);
     910           0 : }
     911             : 
     912             : void
     913           0 : rtwn_next_scan(struct rtwn_softc *sc)
     914             : {
     915           0 :         struct ieee80211com *ic = &sc->sc_ic;
     916             :         int s;
     917             : 
     918           0 :         s = splnet();
     919           0 :         if (ic->ic_state == IEEE80211_S_SCAN)
     920           0 :                 ieee80211_next_scan(&ic->ic_if);
     921           0 :         splx(s);
     922           0 : }
     923             : 
     924             : int
     925           0 : rtwn_newstate(struct ieee80211com *ic, enum ieee80211_state nstate, int arg)
     926             : {
     927           0 :         struct rtwn_softc *sc = ic->ic_softc;
     928             :         struct ieee80211_node *ni;
     929             :         enum ieee80211_state ostate;
     930             :         uint32_t reg;
     931             :         int s, error;
     932             : 
     933           0 :         s = splnet();
     934           0 :         ostate = ic->ic_state;
     935             : 
     936             :         if (nstate != ostate)
     937             :                 DPRINTF(("newstate %s -> %s\n",
     938             :                     ieee80211_state_name[ostate],
     939             :                     ieee80211_state_name[nstate]));
     940             : 
     941           0 :         if (ostate == IEEE80211_S_RUN) {
     942             :                 /* Stop calibration. */
     943           0 :                 sc->sc_ops.cancel_calib(sc->sc_ops.cookie);
     944             : 
     945             :                 /* Turn link LED off. */
     946           0 :                 rtwn_set_led(sc, RTWN_LED_LINK, 0);
     947             : 
     948             :                 /* Set media status to 'No Link'. */
     949           0 :                 rtwn_set_nettype(sc, IEEE80211_M_MONITOR);
     950             : 
     951             :                 /* Stop Rx of data frames. */
     952           0 :                 rtwn_write_2(sc, R92C_RXFLTMAP2, 0);
     953             : 
     954             :                 /* Rest TSF. */
     955           0 :                 rtwn_write_1(sc, R92C_DUAL_TSF_RST, 0x03);
     956             : 
     957             :                 /* Disable TSF synchronization. */
     958           0 :                 rtwn_write_1(sc, R92C_BCN_CTRL,
     959           0 :                     rtwn_read_1(sc, R92C_BCN_CTRL) |
     960             :                     R92C_BCN_CTRL_DIS_TSF_UDT0);
     961             : 
     962             :                 /* Reset EDCA parameters. */
     963           0 :                 rtwn_edca_init(sc);
     964             : 
     965           0 :                 rtwn_updateslot(ic);
     966           0 :                 rtwn_update_short_preamble(ic);
     967             : 
     968             :                 /* Disable 11b-only AP workaround (see rtwn_r88e_ra_init). */
     969           0 :                 sc->sc_flags &= ~RTWN_FLAG_FORCE_RAID_11B;
     970           0 :         }
     971           0 :         switch (nstate) {
     972             :         case IEEE80211_S_INIT:
     973             :                 /* Turn link LED off. */
     974           0 :                 rtwn_set_led(sc, RTWN_LED_LINK, 0);
     975           0 :                 break;
     976             :         case IEEE80211_S_SCAN:
     977           0 :                 if (ostate != IEEE80211_S_SCAN) {
     978             :                         /* Allow Rx from any BSSID. */
     979           0 :                         rtwn_write_4(sc, R92C_RCR,
     980           0 :                             rtwn_read_4(sc, R92C_RCR) &
     981             :                             ~(R92C_RCR_CBSSID_DATA | R92C_RCR_CBSSID_BCN));
     982             : 
     983             :                         /* Set gain for scanning. */
     984           0 :                         reg = rtwn_bb_read(sc, R92C_OFDM0_AGCCORE1(0));
     985           0 :                         reg = RW(reg, R92C_OFDM0_AGCCORE1_GAIN, 0x20);
     986           0 :                         rtwn_bb_write(sc, R92C_OFDM0_AGCCORE1(0), reg);
     987             : 
     988           0 :                         if (!(sc->chip & RTWN_CHIP_88E)) {
     989           0 :                                 reg = rtwn_bb_read(sc, R92C_OFDM0_AGCCORE1(1));
     990           0 :                                 reg = RW(reg, R92C_OFDM0_AGCCORE1_GAIN, 0x20);
     991           0 :                                 rtwn_bb_write(sc, R92C_OFDM0_AGCCORE1(1), reg);
     992           0 :                         }
     993             :                 }
     994             : 
     995             :                 /* Make link LED blink during scan. */
     996           0 :                 rtwn_set_led(sc, RTWN_LED_LINK, !sc->ledlink);
     997             : 
     998             :                 /* Pause AC Tx queues. */
     999           0 :                 rtwn_write_1(sc, R92C_TXPAUSE,
    1000           0 :                     rtwn_read_1(sc, R92C_TXPAUSE) | R92C_TXPAUSE_AC_VO |
    1001           0 :                     R92C_TXPAUSE_AC_VI | R92C_TXPAUSE_AC_BE |
    1002             :                     R92C_TXPAUSE_AC_BK);
    1003             : 
    1004           0 :                 rtwn_set_chan(sc, ic->ic_bss->ni_chan, NULL);
    1005           0 :                 sc->sc_ops.next_scan(sc->sc_ops.cookie);
    1006           0 :                 break;
    1007             : 
    1008             :         case IEEE80211_S_AUTH:
    1009             :                 /* Set initial gain under link. */
    1010           0 :                 reg = rtwn_bb_read(sc, R92C_OFDM0_AGCCORE1(0));
    1011           0 :                 reg = RW(reg, R92C_OFDM0_AGCCORE1_GAIN, 0x32);
    1012           0 :                 rtwn_bb_write(sc, R92C_OFDM0_AGCCORE1(0), reg);
    1013             : 
    1014           0 :                 if (!(sc->chip & RTWN_CHIP_88E)) {
    1015           0 :                         reg = rtwn_bb_read(sc, R92C_OFDM0_AGCCORE1(1));
    1016           0 :                         reg = RW(reg, R92C_OFDM0_AGCCORE1_GAIN, 0x32);
    1017           0 :                         rtwn_bb_write(sc, R92C_OFDM0_AGCCORE1(1), reg);
    1018           0 :                 }
    1019             : 
    1020           0 :                 rtwn_set_chan(sc, ic->ic_bss->ni_chan, NULL);
    1021           0 :                 break;
    1022             :         case IEEE80211_S_ASSOC:
    1023             :                 break;
    1024             :         case IEEE80211_S_RUN:
    1025           0 :                 if (ic->ic_opmode == IEEE80211_M_MONITOR) {
    1026           0 :                         rtwn_set_chan(sc, ic->ic_ibss_chan, NULL);
    1027             : 
    1028             :                         /* Enable Rx of data frames. */
    1029           0 :                         rtwn_write_2(sc, R92C_RXFLTMAP2, 0xffff);
    1030             : 
    1031             :                         /* Turn link LED on. */
    1032           0 :                         rtwn_set_led(sc, RTWN_LED_LINK, 1);
    1033           0 :                         break;
    1034             :                 }
    1035           0 :                 ni = ic->ic_bss;
    1036             : 
    1037             :                 /* Set media status to 'Associated'. */
    1038           0 :                 rtwn_set_nettype(sc, IEEE80211_M_STA);
    1039             : 
    1040             :                 /* Set BSSID. */
    1041           0 :                 rtwn_write_4(sc, R92C_BSSID + 0, LE_READ_4(&ni->ni_bssid[0]));
    1042           0 :                 rtwn_write_4(sc, R92C_BSSID + 4, LE_READ_2(&ni->ni_bssid[4]));
    1043             : 
    1044           0 :                 if (ic->ic_curmode == IEEE80211_MODE_11B)
    1045           0 :                         rtwn_write_1(sc, R92C_INIRTS_RATE_SEL, 0);
    1046             :                 else    /* 802.11b/g */
    1047           0 :                         rtwn_write_1(sc, R92C_INIRTS_RATE_SEL, 3);
    1048             : 
    1049           0 :                 rtwn_updateslot(ic);
    1050           0 :                 rtwn_update_short_preamble(ic);
    1051             : 
    1052             :                 /* Enable Rx of data frames. */
    1053           0 :                 rtwn_write_2(sc, R92C_RXFLTMAP2, 0xffff);
    1054             : 
    1055             :                 /* Flush all AC queues. */
    1056           0 :                 rtwn_write_1(sc, R92C_TXPAUSE, 0x00);
    1057             : 
    1058             :                 /* Set beacon interval. */
    1059           0 :                 rtwn_write_2(sc, R92C_BCN_INTERVAL, ni->ni_intval);
    1060             : 
    1061             :                 /* Allow Rx from our BSSID only. */
    1062           0 :                 rtwn_write_4(sc, R92C_RCR,
    1063           0 :                     rtwn_read_4(sc, R92C_RCR) |
    1064           0 :                     R92C_RCR_CBSSID_DATA | R92C_RCR_CBSSID_BCN);
    1065             : 
    1066             :                 /* Enable TSF synchronization. */
    1067           0 :                 rtwn_tsf_sync_enable(sc);
    1068             : 
    1069             :                 /* Intialize rate adaptation. */
    1070           0 :                 rtwn_ra_init(sc);
    1071             : 
    1072             :                 /* Turn link LED on. */
    1073           0 :                 rtwn_set_led(sc, RTWN_LED_LINK, 1);
    1074             : 
    1075           0 :                 sc->avg_pwdb = -1;   /* Reset average RSSI. */
    1076             :                 /* Reset temperature calibration state machine. */
    1077           0 :                 sc->thcal_state = 0;
    1078           0 :                 sc->thcal_lctemp = 0;
    1079             :                 /* Start periodic calibration. */
    1080           0 :                 sc->sc_ops.next_calib(sc->sc_ops.cookie);
    1081           0 :                 break;
    1082             :         }
    1083             : 
    1084           0 :         error = sc->sc_newstate(ic, nstate, arg);
    1085           0 :         splx(s);
    1086             :  
    1087           0 :         return (error);
    1088             : }
    1089             : 
    1090             : void
    1091           0 : rtwn_update_short_preamble(struct ieee80211com *ic)
    1092             : {
    1093           0 :         struct rtwn_softc *sc = ic->ic_softc;
    1094             : 
    1095           0 :         if (sc->chip & RTWN_CHIP_88E)
    1096           0 :                 rtwn_r88e_update_short_preamble(sc);
    1097             :         else
    1098           0 :                 rtwn_r92c_update_short_preamble(sc);
    1099           0 : }
    1100             : 
    1101             : void
    1102           0 : rtwn_r92c_update_short_preamble(struct rtwn_softc *sc)
    1103             : {
    1104             :         uint32_t reg;
    1105             : 
    1106           0 :         reg = rtwn_read_4(sc, R92C_RRSR);
    1107           0 :         if (sc->sc_ic.ic_flags & IEEE80211_F_SHPREAMBLE)
    1108           0 :                 reg |= R92C_RRSR_SHORT;
    1109             :         else
    1110           0 :                 reg &= ~R92C_RRSR_SHORT;
    1111           0 :         rtwn_write_4(sc, R92C_RRSR, reg);
    1112           0 : }
    1113             : 
    1114             : void
    1115           0 : rtwn_r88e_update_short_preamble(struct rtwn_softc *sc)
    1116             : {
    1117             :         uint32_t reg;
    1118             : 
    1119           0 :         reg = rtwn_read_4(sc, R92C_WMAC_TRXPTCL_CTL);
    1120           0 :         if (sc->sc_ic.ic_flags & IEEE80211_F_SHPREAMBLE)
    1121           0 :                 reg |= R92C_WMAC_TRXPTCL_CTL_SHORT;
    1122             :         else
    1123           0 :                 reg &= ~R92C_WMAC_TRXPTCL_CTL_SHORT;
    1124           0 :         rtwn_write_4(sc, R92C_WMAC_TRXPTCL_CTL, reg);
    1125           0 : }
    1126             : 
    1127             : void
    1128           0 : rtwn_updateslot(struct ieee80211com *ic)
    1129             : {
    1130           0 :         struct rtwn_softc *sc = ic->ic_softc;
    1131             :         int s;
    1132             :         
    1133           0 :         s = splnet();
    1134           0 :         if (ic->ic_flags & IEEE80211_F_SHSLOT)
    1135           0 :                 rtwn_write_1(sc, R92C_SLOT, IEEE80211_DUR_DS_SHSLOT);
    1136             :         else
    1137           0 :                 rtwn_write_1(sc, R92C_SLOT, IEEE80211_DUR_DS_SLOT);
    1138           0 :         splx(s);
    1139           0 : }
    1140             : 
    1141             : void
    1142           0 : rtwn_updateedca(struct ieee80211com *ic)
    1143             : {
    1144           0 :         struct rtwn_softc *sc = ic->ic_softc;
    1145             :         const uint16_t aci2reg[EDCA_NUM_AC] = {
    1146             :                 R92C_EDCA_BE_PARAM,
    1147             :                 R92C_EDCA_BK_PARAM,
    1148             :                 R92C_EDCA_VI_PARAM,
    1149             :                 R92C_EDCA_VO_PARAM
    1150             :         };
    1151             :         struct ieee80211_edca_ac_params *ac;
    1152             :         int s, aci, aifs, slottime;
    1153             :         uint8_t acm = 0;
    1154             : 
    1155           0 :         if (ic->ic_flags & IEEE80211_F_SHSLOT)
    1156           0 :                 slottime = IEEE80211_DUR_DS_SHSLOT;
    1157             :         else
    1158             :                 slottime = IEEE80211_DUR_DS_SLOT;
    1159           0 :         s = splnet();
    1160           0 :         for (aci = 0; aci < EDCA_NUM_AC; aci++) {
    1161           0 :                 ac = &ic->ic_edca_ac[aci];
    1162             :                 /* AIFS[AC] = AIFSN[AC] * aSlotTime + aSIFSTime. */
    1163           0 :                 aifs = ac->ac_aifsn * slottime + IEEE80211_DUR_DS_SIFS;
    1164           0 :                 rtwn_write_4(sc, aci2reg[aci],
    1165           0 :                     SM(R92C_EDCA_PARAM_TXOP, ac->ac_txoplimit) |
    1166           0 :                     SM(R92C_EDCA_PARAM_ECWMIN, ac->ac_ecwmin) |
    1167           0 :                     SM(R92C_EDCA_PARAM_ECWMAX, ac->ac_ecwmax) |
    1168           0 :                     SM(R92C_EDCA_PARAM_AIFS, aifs));
    1169             : 
    1170             :                 /* Is admission control mandatory for this queue? */
    1171           0 :                 if (ac->ac_acm) {
    1172           0 :                         switch (aci) {
    1173             :                         case EDCA_AC_BE:
    1174           0 :                                 acm |= R92C_ACMHW_BEQEN;
    1175           0 :                                 break;
    1176             :                         case EDCA_AC_VI:
    1177           0 :                                 acm |= R92C_ACMHW_VIQEN;
    1178           0 :                                 break;
    1179             :                         case EDCA_AC_VO:
    1180           0 :                                 acm |= R92C_ACMHW_VOQEN;
    1181           0 :                                 break;
    1182             :                         default:
    1183             :                                 break;
    1184             :                         }
    1185             :                 }
    1186             :         }
    1187           0 :         splx(s);
    1188             : 
    1189             :         /* Enable hardware admission control. */
    1190           0 :         rtwn_write_1(sc, R92C_ACMHWCTRL, R92C_ACMHW_HWEN | acm);
    1191           0 : }
    1192             : 
    1193             : int
    1194           0 : rtwn_set_key(struct ieee80211com *ic, struct ieee80211_node *ni,
    1195             :     struct ieee80211_key *k)
    1196             : {
    1197           0 :         struct rtwn_softc *sc = ic->ic_softc;
    1198             :         static const uint8_t etherzeroaddr[6] = { 0 };
    1199             :         const uint8_t *macaddr;
    1200           0 :         uint8_t keybuf[16], algo;
    1201             :         int i, entry;
    1202             : 
    1203             :         /* Defer setting of WEP keys until interface is brought up. */
    1204           0 :         if ((ic->ic_if.if_flags & (IFF_UP | IFF_RUNNING)) !=
    1205             :             (IFF_UP | IFF_RUNNING))
    1206           0 :                 return (0);
    1207             : 
    1208             :         /* Map net80211 cipher to HW crypto algorithm. */
    1209           0 :         switch (k->k_cipher) {
    1210             :         case IEEE80211_CIPHER_WEP40:
    1211             :                 algo = R92C_CAM_ALGO_WEP40;
    1212           0 :                 break;
    1213             :         case IEEE80211_CIPHER_WEP104:
    1214             :                 algo = R92C_CAM_ALGO_WEP104;
    1215           0 :                 break;
    1216             :         case IEEE80211_CIPHER_TKIP:
    1217             :                 algo = R92C_CAM_ALGO_TKIP;
    1218           0 :                 break;
    1219             :         case IEEE80211_CIPHER_CCMP:
    1220             :                 algo = R92C_CAM_ALGO_AES;
    1221           0 :                 break;
    1222             :         default:
    1223             :                 /* Fallback to software crypto for other ciphers. */
    1224           0 :                 return (ieee80211_set_key(ic, ni, k));
    1225             :         }
    1226           0 :         if (k->k_flags & IEEE80211_KEY_GROUP) {
    1227             :                 macaddr = etherzeroaddr;
    1228           0 :                 entry = k->k_id;
    1229           0 :         } else {
    1230           0 :                 macaddr = ic->ic_bss->ni_macaddr;
    1231             :                 entry = 4;
    1232             :         }
    1233             :         /* Write key. */
    1234           0 :         memset(keybuf, 0, sizeof(keybuf));
    1235           0 :         memcpy(keybuf, k->k_key, MIN(k->k_len, sizeof(keybuf)));
    1236           0 :         for (i = 0; i < 4; i++) {
    1237           0 :                 rtwn_cam_write(sc, R92C_CAM_KEY(entry, i),
    1238           0 :                     LE_READ_4(&keybuf[i * 4]));
    1239             :         }
    1240             :         /* Write CTL0 last since that will validate the CAM entry. */
    1241           0 :         rtwn_cam_write(sc, R92C_CAM_CTL1(entry),
    1242           0 :             LE_READ_4(&macaddr[2]));
    1243           0 :         rtwn_cam_write(sc, R92C_CAM_CTL0(entry),
    1244           0 :             SM(R92C_CAM_ALGO, algo) |
    1245           0 :             SM(R92C_CAM_KEYID, k->k_id) |
    1246           0 :             SM(R92C_CAM_MACLO, LE_READ_2(&macaddr[0])) |
    1247             :             R92C_CAM_VALID);
    1248             : 
    1249           0 :         return (0);
    1250           0 : }
    1251             : 
    1252             : void
    1253           0 : rtwn_delete_key(struct ieee80211com *ic, struct ieee80211_node *ni,
    1254             :     struct ieee80211_key *k)
    1255             : {
    1256           0 :         struct rtwn_softc *sc = ic->ic_softc;
    1257             :         int i, entry;
    1258             : 
    1259           0 :         if (!(ic->ic_if.if_flags & IFF_RUNNING) ||
    1260           0 :             ic->ic_state != IEEE80211_S_RUN)
    1261           0 :                 return; /* Nothing to do. */
    1262             : 
    1263           0 :         if (k->k_flags & IEEE80211_KEY_GROUP)
    1264           0 :                 entry = k->k_id;
    1265             :         else
    1266             :                 entry = 4;
    1267           0 :         rtwn_cam_write(sc, R92C_CAM_CTL0(entry), 0);
    1268           0 :         rtwn_cam_write(sc, R92C_CAM_CTL1(entry), 0);
    1269             :         /* Clear key. */
    1270           0 :         for (i = 0; i < 4; i++)
    1271           0 :                 rtwn_cam_write(sc, R92C_CAM_KEY(entry, i), 0);
    1272           0 : }
    1273             : 
    1274             : void
    1275           0 : rtwn_update_avgrssi(struct rtwn_softc *sc, int rate, int8_t rssi)
    1276             : {
    1277             :         int pwdb;
    1278             : 
    1279             :         /* Convert antenna signal to percentage. */
    1280           0 :         if (rssi <= -100 || rssi >= 20)
    1281           0 :                 pwdb = 0;
    1282           0 :         else if (rssi >= 0)
    1283           0 :                 pwdb = 100;
    1284             :         else
    1285           0 :                 pwdb = 100 + rssi;
    1286           0 :         if (sc->chip & (RTWN_CHIP_92C | RTWN_CHIP_88C)) {
    1287           0 :                 if (rate <= 3) {
    1288             :                         /* CCK gain is smaller than OFDM/MCS gain. */
    1289           0 :                         pwdb += 6;
    1290           0 :                         if (pwdb > 100)
    1291             :                                 pwdb = 100;
    1292           0 :                         if (pwdb <= 14)
    1293           0 :                                 pwdb -= 4;
    1294           0 :                         else if (pwdb <= 26)
    1295           0 :                                 pwdb -= 8;
    1296           0 :                         else if (pwdb <= 34)
    1297           0 :                                 pwdb -= 6;
    1298           0 :                         else if (pwdb <= 42)
    1299           0 :                                 pwdb -= 2;
    1300             :                 }
    1301             :         }
    1302           0 :         if (sc->avg_pwdb == -1)      /* Init. */
    1303           0 :                 sc->avg_pwdb = pwdb;
    1304           0 :         else if (sc->avg_pwdb < pwdb)
    1305           0 :                 sc->avg_pwdb = ((sc->avg_pwdb * 19 + pwdb) / 20) + 1;
    1306             :         else
    1307           0 :                 sc->avg_pwdb = ((sc->avg_pwdb * 19 + pwdb) / 20);
    1308             :         DPRINTFN(4, ("PWDB=%d EMA=%d\n", pwdb, sc->avg_pwdb));
    1309           0 : }
    1310             : 
    1311             : int8_t
    1312           0 : rtwn_get_rssi(struct rtwn_softc *sc, int rate, void *physt)
    1313             : {
    1314             :         static const int8_t cckoff[] = { 16, -12, -26, -46 };
    1315             :         struct r92c_rx_phystat *phy;
    1316             :         struct r92c_rx_cck *cck;
    1317             :         uint8_t rpt;
    1318             :         int8_t rssi;
    1319             : 
    1320           0 :         if (sc->chip & RTWN_CHIP_88E)
    1321           0 :                 return rtwn_r88e_get_rssi(sc, rate, physt);
    1322             : 
    1323           0 :         if (rate <= 3) {
    1324           0 :                 cck = (struct r92c_rx_cck *)physt;
    1325           0 :                 if (sc->sc_flags & RTWN_FLAG_CCK_HIPWR) {
    1326           0 :                         rpt = (cck->agc_rpt >> 5) & 0x3;
    1327           0 :                         rssi = (cck->agc_rpt & 0x1f) << 1;
    1328           0 :                 } else {
    1329           0 :                         rpt = (cck->agc_rpt >> 6) & 0x3;
    1330           0 :                         rssi = cck->agc_rpt & 0x3e;
    1331             :                 }
    1332           0 :                 rssi = cckoff[rpt] - rssi;
    1333           0 :         } else {        /* OFDM/HT. */
    1334           0 :                 phy = (struct r92c_rx_phystat *)physt;
    1335           0 :                 rssi = ((letoh32(phy->phydw1) >> 1) & 0x7f) - 110;
    1336             :         }
    1337           0 :         return (rssi);
    1338           0 : }
    1339             : 
    1340             : int8_t
    1341           0 : rtwn_r88e_get_rssi(struct rtwn_softc *sc, int rate, void *physt)
    1342             : {
    1343             :         static const int8_t cckoff[] = { 20, 14, 10, -4, -16, -22, -38, -40 };
    1344             :         struct r88e_rx_phystat *phy;
    1345             :         uint8_t rpt;
    1346             :         int8_t rssi;
    1347             : 
    1348           0 :         phy = (struct r88e_rx_phystat *)physt;
    1349             : 
    1350           0 :         if (rate <= 3) {
    1351           0 :                 rpt = (phy->agc_rpt >> 5) & 0x7;
    1352           0 :                 rssi = (phy->agc_rpt & 0x1f) << 1;
    1353           0 :                 if (sc->sc_flags & RTWN_FLAG_CCK_HIPWR) {
    1354           0 :                         if (rpt == 2)
    1355           0 :                                 rssi -= 6;
    1356             :                 }
    1357           0 :                 rssi = (phy->agc_rpt & 0x1f) > 27 ? -94 : cckoff[rpt] - rssi;
    1358           0 :         } else {        /* OFDM/HT. */
    1359           0 :                 rssi = ((le32toh(phy->sq_rpt) >> 1) & 0x7f) - 110;
    1360             :         }
    1361           0 :         return (rssi);
    1362             : }
    1363             : 
    1364             : void
    1365           0 : rtwn_start(struct ifnet *ifp)
    1366             : {
    1367           0 :         struct rtwn_softc *sc = ifp->if_softc;
    1368           0 :         struct ieee80211com *ic = &sc->sc_ic;
    1369           0 :         struct ieee80211_node *ni;
    1370             :         struct mbuf *m;
    1371             : 
    1372           0 :         if (!(ifp->if_flags & IFF_RUNNING) || ifq_is_oactive(&ifp->if_snd))
    1373           0 :                 return;
    1374             : 
    1375           0 :         for (;;) {
    1376           0 :                 if (sc->sc_ops.is_oactive(sc->sc_ops.cookie)) {
    1377           0 :                         ifq_set_oactive(&ifp->if_snd);
    1378           0 :                         break;
    1379             :                 }
    1380             :                 /* Send pending management frames first. */
    1381           0 :                 m = mq_dequeue(&ic->ic_mgtq);
    1382           0 :                 if (m != NULL) {
    1383           0 :                         ni = m->m_pkthdr.ph_cookie;
    1384           0 :                         goto sendit;
    1385             :                 }
    1386           0 :                 if (ic->ic_state != IEEE80211_S_RUN)
    1387             :                         break;
    1388             : 
    1389             :                 /* Encapsulate and send data frames. */
    1390           0 :                 IFQ_DEQUEUE(&ifp->if_snd, m);
    1391           0 :                 if (m == NULL)
    1392             :                         break;
    1393             : #if NBPFILTER > 0
    1394           0 :                 if (ifp->if_bpf != NULL)
    1395           0 :                         bpf_mtap(ifp->if_bpf, m, BPF_DIRECTION_OUT);
    1396             : #endif
    1397           0 :                 if ((m = ieee80211_encap(ifp, m, &ni)) == NULL)
    1398           0 :                         continue;
    1399             : sendit:
    1400             : #if NBPFILTER > 0
    1401           0 :                 if (ic->ic_rawbpf != NULL)
    1402           0 :                         bpf_mtap(ic->ic_rawbpf, m, BPF_DIRECTION_OUT);
    1403             : #endif
    1404           0 :                 if (sc->sc_ops.tx(sc->sc_ops.cookie, m, ni) != 0) {
    1405           0 :                         ieee80211_release_node(ic, ni);
    1406           0 :                         ifp->if_oerrors++;
    1407           0 :                         continue;
    1408             :                 }
    1409             : 
    1410           0 :                 sc->sc_tx_timer = 5;
    1411           0 :                 ifp->if_timer = 1;
    1412             :         }
    1413           0 : }
    1414             : 
    1415             : void
    1416           0 : rtwn_watchdog(struct ifnet *ifp)
    1417             : {
    1418           0 :         struct rtwn_softc *sc = ifp->if_softc;
    1419             : 
    1420           0 :         ifp->if_timer = 0;
    1421             : 
    1422           0 :         if (sc->sc_tx_timer > 0) {
    1423           0 :                 if (--sc->sc_tx_timer == 0) {
    1424           0 :                         printf("%s: device timeout\n", sc->sc_pdev->dv_xname);
    1425           0 :                         task_add(systq, &sc->init_task);
    1426           0 :                         ifp->if_oerrors++;
    1427           0 :                         return;
    1428             :                 }
    1429           0 :                 ifp->if_timer = 1;
    1430           0 :         }
    1431           0 :         ieee80211_watchdog(ifp);
    1432           0 : }
    1433             : 
    1434             : int
    1435           0 : rtwn_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
    1436             : {
    1437           0 :         struct rtwn_softc *sc = ifp->if_softc;
    1438           0 :         struct ieee80211com *ic = &sc->sc_ic;
    1439             :         int s, error = 0;
    1440             : 
    1441           0 :         s = splnet();
    1442             :         /*
    1443             :          * Prevent processes from entering this function while another
    1444             :          * process is tsleep'ing in it.
    1445             :          */
    1446           0 :         while ((sc->sc_flags & RTWN_FLAG_BUSY) && error == 0)
    1447           0 :                 error = tsleep(&sc->sc_flags, PCATCH, "rtwnioc", 0);
    1448           0 :         if (error != 0) {
    1449           0 :                 splx(s);
    1450           0 :                 return error;
    1451             :         }
    1452           0 :         sc->sc_flags |= RTWN_FLAG_BUSY;
    1453             : 
    1454           0 :         switch (cmd) {
    1455             :         case SIOCSIFADDR:
    1456           0 :                 ifp->if_flags |= IFF_UP;
    1457             :                 /* FALLTHROUGH */
    1458             :         case SIOCSIFFLAGS:
    1459           0 :                 if (ifp->if_flags & IFF_UP) {
    1460           0 :                         if (!(ifp->if_flags & IFF_RUNNING))
    1461           0 :                                 rtwn_init(ifp);
    1462             :                 } else {
    1463           0 :                         if (ifp->if_flags & IFF_RUNNING)
    1464           0 :                                 rtwn_stop(ifp);
    1465             :                 }
    1466             :                 break;
    1467             :         case SIOCS80211CHANNEL:
    1468           0 :                 error = ieee80211_ioctl(ifp, cmd, data);
    1469           0 :                 if (error == ENETRESET &&
    1470           0 :                     ic->ic_opmode == IEEE80211_M_MONITOR) {
    1471           0 :                         if ((ifp->if_flags & (IFF_UP | IFF_RUNNING)) ==
    1472             :                             (IFF_UP | IFF_RUNNING))
    1473           0 :                                 rtwn_set_chan(sc, ic->ic_ibss_chan, NULL);
    1474             :                         error = 0;
    1475           0 :                 }
    1476             :                 break;
    1477             :         default:
    1478           0 :                 error = ieee80211_ioctl(ifp, cmd, data);
    1479           0 :         }
    1480             : 
    1481           0 :         if (error == ENETRESET) {
    1482           0 :                 if ((ifp->if_flags & (IFF_UP | IFF_RUNNING)) ==
    1483             :                     (IFF_UP | IFF_RUNNING)) {
    1484           0 :                         rtwn_stop(ifp);
    1485           0 :                         rtwn_init(ifp);
    1486           0 :                 }
    1487             :                 error = 0;
    1488           0 :         }
    1489           0 :         sc->sc_flags &= ~RTWN_FLAG_BUSY;
    1490           0 :         wakeup(&sc->sc_flags);
    1491           0 :         splx(s);
    1492             : 
    1493           0 :         return (error);
    1494           0 : }
    1495             : 
    1496             : void
    1497           0 : rtwn_fw_reset(struct rtwn_softc *sc)
    1498             : {
    1499           0 :         if (sc->chip & RTWN_CHIP_88E)
    1500           0 :                 rtwn_r88e_fw_reset(sc);
    1501             :         else
    1502           0 :                 rtwn_r92c_fw_reset(sc);
    1503           0 : }
    1504             : 
    1505             : void
    1506           0 : rtwn_r92c_fw_reset(struct rtwn_softc *sc)
    1507             : {
    1508           0 :         uint16_t reg;
    1509             :         int ntries;
    1510             : 
    1511             :         /* Tell 8051 to reset itself. */
    1512           0 :         rtwn_write_1(sc, R92C_HMETFR + 3, 0x20);
    1513             : 
    1514             :         /* Wait until 8051 resets by itself. */
    1515           0 :         for (ntries = 0; ntries < 100; ntries++) {
    1516           0 :                 reg = rtwn_read_2(sc, R92C_SYS_FUNC_EN);
    1517           0 :                 if (!(reg & R92C_SYS_FUNC_EN_CPUEN))
    1518             :                         goto sleep;
    1519           0 :                 DELAY(50);
    1520             :         }
    1521             :         /* Force 8051 reset. */
    1522           0 :         rtwn_write_2(sc, R92C_SYS_FUNC_EN, reg & ~R92C_SYS_FUNC_EN_CPUEN);
    1523             : sleep:
    1524           0 :         if (sc->chip & RTWN_CHIP_PCI) {
    1525             :                 /* 
    1526             :                  * We must sleep for one second to let the firmware settle.
    1527             :                  * Accessing registers too early will hang the whole system.
    1528             :                  */
    1529           0 :                 tsleep(&reg, 0, "rtwnrst", hz);
    1530           0 :         }
    1531           0 : }
    1532             : 
    1533             : void
    1534           0 : rtwn_r88e_fw_reset(struct rtwn_softc *sc)
    1535             : {
    1536             :         uint16_t reg;
    1537             : 
    1538             :         /* Reset MCU IO wrapper. */
    1539           0 :         rtwn_write_1(sc, R92C_RSV_CTRL + 1,
    1540           0 :             rtwn_read_1(sc, R92C_RSV_CTRL + 1) & ~R92C_RSV_CTRL_WLOCK_08);
    1541           0 :         reg = rtwn_read_2(sc, R92C_SYS_FUNC_EN);
    1542           0 :         rtwn_write_2(sc, R92C_SYS_FUNC_EN, reg & ~R92C_SYS_FUNC_EN_CPUEN);
    1543             :         /* Enable MCU IO wrapper. */
    1544           0 :         rtwn_write_1(sc, R92C_RSV_CTRL + 1,
    1545           0 :             rtwn_read_1(sc, R92C_RSV_CTRL) | R92C_RSV_CTRL_WLOCK_08);
    1546           0 :         rtwn_write_2(sc, R92C_SYS_FUNC_EN, reg | R92C_SYS_FUNC_EN_CPUEN);
    1547           0 : }
    1548             : 
    1549             : int
    1550           0 : rtwn_load_firmware(struct rtwn_softc *sc)
    1551             : {
    1552             :         const struct r92c_fw_hdr *hdr;
    1553           0 :         u_char *fw, *ptr;
    1554           0 :         size_t len0, len;
    1555             :         uint32_t reg;
    1556             :         int mlen, ntries, page, error;
    1557             : 
    1558             :         /* Read firmware image from the filesystem. */
    1559           0 :         error = sc->sc_ops.load_firmware(sc->sc_ops.cookie, &fw, &len0);
    1560           0 :         if (error)
    1561           0 :                 return (error);
    1562           0 :         len = len0;
    1563           0 :         if (len < sizeof(*hdr)) {
    1564           0 :                 printf("%s: firmware too short\n", sc->sc_pdev->dv_xname);
    1565             :                 error = EINVAL;
    1566           0 :                 goto fail;
    1567             :         }
    1568           0 :         ptr = fw;
    1569           0 :         hdr = (const struct r92c_fw_hdr *)ptr;
    1570             :         /* Check if there is a valid FW header and skip it. */
    1571           0 :         if ((letoh16(hdr->signature) >> 4) == 0x88c ||
    1572           0 :             (letoh16(hdr->signature) >> 4) == 0x88e ||
    1573           0 :             (letoh16(hdr->signature) >> 4) == 0x92c) {
    1574             :                 DPRINTF(("FW V%d.%d %02d-%02d %02d:%02d\n",
    1575             :                     letoh16(hdr->version), letoh16(hdr->subversion),
    1576             :                     hdr->month, hdr->date, hdr->hour, hdr->minute));
    1577           0 :                 ptr += sizeof(*hdr);
    1578           0 :                 len -= sizeof(*hdr);
    1579           0 :         }
    1580             : 
    1581           0 :         if (rtwn_read_1(sc, R92C_MCUFWDL) & R92C_MCUFWDL_RAM_DL_SEL) {
    1582           0 :                 rtwn_write_1(sc, R92C_MCUFWDL, 0);
    1583           0 :                 rtwn_fw_reset(sc);
    1584           0 :         }
    1585             : 
    1586           0 :         if (sc->chip & RTWN_CHIP_PCI) {
    1587           0 :                 rtwn_write_2(sc, R92C_SYS_FUNC_EN,
    1588           0 :                     rtwn_read_2(sc, R92C_SYS_FUNC_EN) | R92C_SYS_FUNC_EN_CPUEN);
    1589           0 :         }
    1590             : 
    1591             :         /* Enable FW download. */
    1592           0 :         rtwn_write_1(sc, R92C_MCUFWDL,
    1593           0 :             rtwn_read_1(sc, R92C_MCUFWDL) | R92C_MCUFWDL_EN);
    1594           0 :         rtwn_write_4(sc, R92C_MCUFWDL, 
    1595           0 :             rtwn_read_4(sc, R92C_MCUFWDL) & ~R92C_MCUFWDL_ROM_DLEN);
    1596             : 
    1597             :         /* Reset the FWDL checksum. */
    1598           0 :         rtwn_write_1(sc, R92C_MCUFWDL,
    1599           0 :             rtwn_read_1(sc, R92C_MCUFWDL) | R92C_MCUFWDL_CHKSUM_RPT);
    1600             : 
    1601           0 :         for (page = 0; len > 0; page++) {
    1602           0 :                 mlen = MIN(len, R92C_FW_PAGE_SIZE);
    1603           0 :                 error = sc->sc_ops.fw_loadpage(sc->sc_ops.cookie, page, ptr,
    1604             :                     mlen);
    1605           0 :                 if (error != 0) {
    1606           0 :                         printf("%s: could not load firmware page %d\n",
    1607           0 :                             sc->sc_pdev->dv_xname, page);
    1608           0 :                         goto fail;
    1609             :                 }
    1610           0 :                 ptr += mlen;
    1611           0 :                 len -= mlen;
    1612             :         }
    1613             : 
    1614             :         /* Wait for checksum report. */
    1615           0 :         for (ntries = 0; ntries < 1000; ntries++) {
    1616           0 :                 if (rtwn_read_4(sc, R92C_MCUFWDL) & R92C_MCUFWDL_CHKSUM_RPT)
    1617             :                         break;
    1618           0 :                 DELAY(5);
    1619             :         }
    1620           0 :         if (ntries == 1000) {
    1621           0 :                 printf("%s: timeout waiting for checksum report\n",
    1622           0 :                     sc->sc_pdev->dv_xname);
    1623             :                 error = ETIMEDOUT;
    1624           0 :                 goto fail;
    1625             :         }
    1626             : 
    1627             :         /* Disable FW download. */
    1628           0 :         rtwn_write_1(sc, R92C_MCUFWDL,
    1629           0 :             rtwn_read_1(sc, R92C_MCUFWDL) & ~R92C_MCUFWDL_EN);
    1630           0 :         rtwn_write_1(sc, R92C_MCUFWDL + 1, 0);
    1631             : 
    1632           0 :         reg = rtwn_read_4(sc, R92C_MCUFWDL);
    1633           0 :         reg = (reg & ~R92C_MCUFWDL_WINTINI_RDY) | R92C_MCUFWDL_RDY;
    1634           0 :         rtwn_write_4(sc, R92C_MCUFWDL, reg);
    1635           0 :         if (sc->chip & (RTWN_CHIP_92C | RTWN_CHIP_88C)) {
    1636           0 :                 reg = rtwn_read_2(sc, R92C_SYS_FUNC_EN);
    1637           0 :                 rtwn_write_2(sc, R92C_SYS_FUNC_EN,
    1638           0 :                     reg & ~R92C_SYS_FUNC_EN_CPUEN);
    1639           0 :                 rtwn_write_2(sc, R92C_SYS_FUNC_EN,
    1640           0 :                     reg | R92C_SYS_FUNC_EN_CPUEN);
    1641           0 :         } else
    1642           0 :                 rtwn_fw_reset(sc);
    1643             :         /* Wait for firmware readiness. */
    1644           0 :         for (ntries = 0; ntries < 1000; ntries++) {
    1645           0 :                 if (rtwn_read_4(sc, R92C_MCUFWDL) & R92C_MCUFWDL_WINTINI_RDY)
    1646             :                         break;
    1647           0 :                 DELAY(10);
    1648             :         }
    1649           0 :         if (ntries == 1000) {
    1650           0 :                 printf("%s: timeout waiting for firmware readiness\n",
    1651           0 :                     sc->sc_pdev->dv_xname);
    1652             :                 error = ETIMEDOUT;
    1653           0 :                 goto fail;
    1654             :         }
    1655             : fail:
    1656           0 :         free(fw, M_DEVBUF, len0);
    1657           0 :         return (error);
    1658           0 : }
    1659             : 
    1660             : void
    1661           0 : rtwn_rf_init(struct rtwn_softc *sc)
    1662             : {
    1663             :         const struct r92c_rf_prog *prog;
    1664             :         uint32_t reg, type;
    1665             :         int i, j, idx, off;
    1666             : 
    1667             :         /* Select RF programming based on board type. */
    1668           0 :         if (sc->chip & RTWN_CHIP_88E)
    1669           0 :                 prog = rtl8188eu_rf_prog;
    1670           0 :         else if (!(sc->chip & RTWN_CHIP_92C)) {
    1671           0 :                 if (sc->board_type == R92C_BOARD_TYPE_MINICARD)
    1672           0 :                         prog = rtl8188ce_rf_prog;
    1673           0 :                 else if (sc->board_type == R92C_BOARD_TYPE_HIGHPA)
    1674           0 :                         prog = rtl8188ru_rf_prog;
    1675             :                 else
    1676             :                         prog = rtl8188cu_rf_prog;
    1677             :         } else
    1678             :                 prog = rtl8192ce_rf_prog;
    1679             : 
    1680           0 :         for (i = 0; i < sc->nrxchains; i++) {
    1681             :                 /* Save RF_ENV control type. */
    1682           0 :                 idx = i / 2;
    1683           0 :                 off = (i % 2) * 16;
    1684           0 :                 reg = rtwn_bb_read(sc, R92C_FPGA0_RFIFACESW(idx));
    1685           0 :                 type = (reg >> off) & 0x10;
    1686             : 
    1687             :                 /* Set RF_ENV enable. */
    1688           0 :                 reg = rtwn_bb_read(sc, R92C_FPGA0_RFIFACEOE(i));
    1689           0 :                 reg |= 0x100000;
    1690           0 :                 rtwn_bb_write(sc, R92C_FPGA0_RFIFACEOE(i), reg);
    1691           0 :                 DELAY(1);
    1692             :                 /* Set RF_ENV output high. */
    1693           0 :                 reg = rtwn_bb_read(sc, R92C_FPGA0_RFIFACEOE(i));
    1694           0 :                 reg |= 0x10;
    1695           0 :                 rtwn_bb_write(sc, R92C_FPGA0_RFIFACEOE(i), reg);
    1696           0 :                 DELAY(1);
    1697             :                 /* Set address and data lengths of RF registers. */
    1698           0 :                 reg = rtwn_bb_read(sc, R92C_HSSI_PARAM2(i));
    1699           0 :                 reg &= ~R92C_HSSI_PARAM2_ADDR_LENGTH;
    1700           0 :                 rtwn_bb_write(sc, R92C_HSSI_PARAM2(i), reg);
    1701           0 :                 DELAY(1);
    1702           0 :                 reg = rtwn_bb_read(sc, R92C_HSSI_PARAM2(i));
    1703           0 :                 reg &= ~R92C_HSSI_PARAM2_DATA_LENGTH;
    1704           0 :                 rtwn_bb_write(sc, R92C_HSSI_PARAM2(i), reg);
    1705           0 :                 DELAY(1);
    1706             : 
    1707             :                 /* Write RF initialization values for this chain. */
    1708           0 :                 for (j = 0; j < prog[i].count; j++) {
    1709           0 :                         if (prog[i].regs[j] >= 0xf9 &&
    1710           0 :                             prog[i].regs[j] <= 0xfe) {
    1711             :                                 /*
    1712             :                                  * These are fake RF registers offsets that
    1713             :                                  * indicate a delay is required.
    1714             :                                  */
    1715           0 :                                 DELAY(50);
    1716           0 :                                 continue;
    1717             :                         }
    1718           0 :                         rtwn_rf_write(sc, i, prog[i].regs[j],
    1719           0 :                             prog[i].vals[j]);
    1720           0 :                         DELAY(1);
    1721           0 :                 }
    1722             : 
    1723             :                 /* Restore RF_ENV control type. */
    1724           0 :                 reg = rtwn_bb_read(sc, R92C_FPGA0_RFIFACESW(idx));
    1725           0 :                 reg &= ~(0x10 << off) | (type << off);
    1726           0 :                 rtwn_bb_write(sc, R92C_FPGA0_RFIFACESW(idx), reg);
    1727             : 
    1728             :                 /* Cache RF register CHNLBW. */
    1729           0 :                 sc->rf_chnlbw[i] = rtwn_rf_read(sc, i, R92C_RF_CHNLBW);
    1730             :         }
    1731             : 
    1732           0 :         if ((sc->chip & (RTWN_CHIP_UMC_A_CUT | RTWN_CHIP_92C)) ==
    1733             :             RTWN_CHIP_UMC_A_CUT) {
    1734           0 :                 rtwn_rf_write(sc, 0, R92C_RF_RX_G1, 0x30255);
    1735           0 :                 rtwn_rf_write(sc, 0, R92C_RF_RX_G2, 0x50a00);
    1736           0 :         }
    1737           0 : }
    1738             : 
    1739             : void
    1740           0 : rtwn_cam_init(struct rtwn_softc *sc)
    1741             : {
    1742             :         /* Invalidate all CAM entries. */
    1743           0 :         rtwn_write_4(sc, R92C_CAMCMD,
    1744             :             R92C_CAMCMD_POLLING | R92C_CAMCMD_CLR);
    1745           0 : }
    1746             : 
    1747             : void
    1748           0 : rtwn_pa_bias_init(struct rtwn_softc *sc)
    1749             : {
    1750             :         uint8_t reg;
    1751             :         int i;
    1752             : 
    1753           0 :         for (i = 0; i < sc->nrxchains; i++) {
    1754           0 :                 if (sc->pa_setting & (1 << i))
    1755             :                         continue;
    1756           0 :                 rtwn_rf_write(sc, i, R92C_RF_IPA, 0x0f406);
    1757           0 :                 rtwn_rf_write(sc, i, R92C_RF_IPA, 0x4f406);
    1758           0 :                 rtwn_rf_write(sc, i, R92C_RF_IPA, 0x8f406);
    1759           0 :                 rtwn_rf_write(sc, i, R92C_RF_IPA, 0xcf406);
    1760           0 :         }
    1761           0 :         if (!(sc->pa_setting & 0x10)) {
    1762           0 :                 reg = rtwn_read_1(sc, 0x16);
    1763           0 :                 reg = (reg & ~0xf0) | 0x90;
    1764           0 :                 rtwn_write_1(sc, 0x16, reg);
    1765           0 :         }
    1766           0 : }
    1767             : 
    1768             : void
    1769           0 : rtwn_rxfilter_init(struct rtwn_softc *sc)
    1770             : {
    1771             :         /* Initialize Rx filter. */
    1772             :         /* TODO: use better filter for monitor mode. */
    1773           0 :         rtwn_write_4(sc, R92C_RCR,
    1774             :             R92C_RCR_AAP | R92C_RCR_APM | R92C_RCR_AM | R92C_RCR_AB |
    1775             :             R92C_RCR_APP_ICV | R92C_RCR_AMF | R92C_RCR_HTC_LOC_CTRL |
    1776             :             R92C_RCR_APP_MIC | R92C_RCR_APP_PHYSTS);
    1777             :         /* Accept all multicast frames. */
    1778           0 :         rtwn_write_4(sc, R92C_MAR + 0, 0xffffffff);
    1779           0 :         rtwn_write_4(sc, R92C_MAR + 4, 0xffffffff);
    1780             :         /* Accept all management frames. */
    1781           0 :         rtwn_write_2(sc, R92C_RXFLTMAP0, 0xffff);
    1782             :         /* Reject all control frames. */
    1783           0 :         rtwn_write_2(sc, R92C_RXFLTMAP1, 0x0000);
    1784             :         /* Accept all data frames. */
    1785           0 :         rtwn_write_2(sc, R92C_RXFLTMAP2, 0xffff);
    1786           0 : }
    1787             : 
    1788             : void
    1789           0 : rtwn_edca_init(struct rtwn_softc *sc)
    1790             : {
    1791           0 :         struct ieee80211com *ic = &sc->sc_ic;
    1792             :         int mode, aci;
    1793             : 
    1794             :         /* Set SIFS; 0x10 = 16 usec (SIFS 11g), 0x0a = 10 usec (SIFS 11b) */
    1795           0 :         rtwn_write_2(sc, R92C_SPEC_SIFS, 0x100a);
    1796           0 :         rtwn_write_2(sc, R92C_MAC_SPEC_SIFS, 0x100a);
    1797           0 :         rtwn_write_2(sc, R92C_SIFS_CCK, 0x100a);
    1798           0 :         rtwn_write_2(sc, R92C_SIFS_OFDM, 0x100a);
    1799           0 :         rtwn_write_2(sc, R92C_RESP_SIFS_CCK, 0x100a);
    1800           0 :         rtwn_write_2(sc, R92C_RESP_SIFS_OFDM, 0x100a);
    1801             : 
    1802           0 :         if (ic->ic_curmode == IEEE80211_MODE_AUTO)
    1803           0 :                 mode = IEEE80211_MODE_11G; /* XXX */
    1804             :         else
    1805             :                 mode = ic->ic_curmode;
    1806           0 :         for (aci = 0; aci < EDCA_NUM_AC; aci++)
    1807           0 :                 memcpy(&ic->ic_edca_ac[aci], &ieee80211_edca_table[mode][aci],
    1808             :                     sizeof(struct ieee80211_edca_ac_params));
    1809           0 :         rtwn_updateedca(ic);
    1810             : 
    1811           0 :         if (sc->chip & RTWN_CHIP_PCI) {
    1812             :                 /* linux magic */
    1813           0 :                 rtwn_write_4(sc, R92C_FAST_EDCA_CTRL, 0x086666); 
    1814           0 :         }
    1815             : 
    1816           0 :         rtwn_write_4(sc, R92C_EDCA_RANDOM_GEN, arc4random());
    1817           0 : }
    1818             : 
    1819             : void
    1820           0 : rtwn_rate_fallback_init(struct rtwn_softc *sc)
    1821             : {
    1822           0 :         if (!(sc->chip & RTWN_CHIP_88E)) {
    1823           0 :                 if (sc->chip & RTWN_CHIP_PCI) {
    1824           0 :                         rtwn_write_4(sc, R92C_DARFRC + 0, 0x01000000);
    1825           0 :                         rtwn_write_4(sc, R92C_DARFRC + 4, 0x07060504);
    1826           0 :                         rtwn_write_4(sc, R92C_RARFRC + 0, 0x01000000);
    1827           0 :                         rtwn_write_4(sc, R92C_RARFRC + 4, 0x07060504);
    1828           0 :                 } else if (sc->chip & RTWN_CHIP_USB) {
    1829           0 :                         rtwn_write_4(sc, R92C_DARFRC + 0, 0x00000000);
    1830           0 :                         rtwn_write_4(sc, R92C_DARFRC + 4, 0x10080404);
    1831           0 :                         rtwn_write_4(sc, R92C_RARFRC + 0, 0x04030201);
    1832           0 :                         rtwn_write_4(sc, R92C_RARFRC + 4, 0x08070605);
    1833           0 :                 }
    1834             :         }
    1835           0 : }
    1836             : 
    1837             : void
    1838           0 : rtwn_usb_aggr_init(struct rtwn_softc *sc)
    1839             : {
    1840             :         uint32_t reg;
    1841             :         int dmasize, dmatiming, ndesc;
    1842             : 
    1843             :         dmasize = 48;
    1844             :         dmatiming = 4;
    1845           0 :         ndesc = (sc->chip & RTWN_CHIP_88E) ? 1 : 6;
    1846             : 
    1847             :         /* Tx aggregation setting. */
    1848           0 :         reg = rtwn_read_4(sc, R92C_TDECTRL);
    1849           0 :         reg = RW(reg, R92C_TDECTRL_BLK_DESC_NUM, ndesc);
    1850           0 :         rtwn_write_4(sc, R92C_TDECTRL, reg);
    1851             : 
    1852             :         /* Rx aggregation setting. */
    1853           0 :         rtwn_write_1(sc, R92C_TRXDMA_CTRL,
    1854           0 :             rtwn_read_1(sc, R92C_TRXDMA_CTRL) |
    1855             :             R92C_TRXDMA_CTRL_RXDMA_AGG_EN);
    1856           0 :         rtwn_write_1(sc, R92C_RXDMA_AGG_PG_TH, dmasize);
    1857           0 :         if (sc->chip & (RTWN_CHIP_92C | RTWN_CHIP_88C))
    1858           0 :                 rtwn_write_1(sc, R92C_USB_DMA_AGG_TO, dmatiming);
    1859             :         else
    1860           0 :                 rtwn_write_1(sc, R92C_RXDMA_AGG_PG_TH + 1, dmatiming);
    1861           0 : }
    1862             : 
    1863             : void
    1864           0 : rtwn_write_txpower(struct rtwn_softc *sc, int chain,
    1865             :     uint16_t power[RTWN_POWER_COUNT])
    1866             : {
    1867             :         uint32_t reg;
    1868             : 
    1869             :         /* Write per-CCK rate Tx power. */
    1870           0 :         if (chain == 0) {
    1871           0 :                 reg = rtwn_bb_read(sc, R92C_TXAGC_A_CCK1_MCS32);
    1872           0 :                 reg = RW(reg, R92C_TXAGC_A_CCK1,  power[RTWN_POWER_CCK1]);
    1873           0 :                 rtwn_bb_write(sc, R92C_TXAGC_A_CCK1_MCS32, reg);
    1874           0 :                 reg = rtwn_bb_read(sc, R92C_TXAGC_B_CCK11_A_CCK2_11);
    1875           0 :                 reg = RW(reg, R92C_TXAGC_A_CCK2,  power[RTWN_POWER_CCK2]);
    1876           0 :                 reg = RW(reg, R92C_TXAGC_A_CCK55, power[RTWN_POWER_CCK55]);
    1877           0 :                 reg = RW(reg, R92C_TXAGC_A_CCK11, power[RTWN_POWER_CCK11]);
    1878           0 :                 rtwn_bb_write(sc, R92C_TXAGC_B_CCK11_A_CCK2_11, reg);
    1879           0 :         } else {
    1880           0 :                 reg = rtwn_bb_read(sc, R92C_TXAGC_B_CCK1_55_MCS32);
    1881           0 :                 reg = RW(reg, R92C_TXAGC_B_CCK1,  power[RTWN_POWER_CCK1]);
    1882           0 :                 reg = RW(reg, R92C_TXAGC_B_CCK2,  power[RTWN_POWER_CCK2]);
    1883           0 :                 reg = RW(reg, R92C_TXAGC_B_CCK55, power[RTWN_POWER_CCK55]);
    1884           0 :                 rtwn_bb_write(sc, R92C_TXAGC_B_CCK1_55_MCS32, reg);
    1885           0 :                 reg = rtwn_bb_read(sc, R92C_TXAGC_B_CCK11_A_CCK2_11);
    1886           0 :                 reg = RW(reg, R92C_TXAGC_B_CCK11, power[RTWN_POWER_CCK11]);
    1887           0 :                 rtwn_bb_write(sc, R92C_TXAGC_B_CCK11_A_CCK2_11, reg);
    1888             :         }
    1889             :         /* Write per-OFDM rate Tx power. */
    1890           0 :         rtwn_bb_write(sc, R92C_TXAGC_RATE18_06(chain),
    1891           0 :             SM(R92C_TXAGC_RATE06, power[RTWN_POWER_OFDM6]) |
    1892           0 :             SM(R92C_TXAGC_RATE09, power[RTWN_POWER_OFDM9]) |
    1893           0 :             SM(R92C_TXAGC_RATE12, power[RTWN_POWER_OFDM12]) |
    1894           0 :             SM(R92C_TXAGC_RATE18, power[RTWN_POWER_OFDM18]));
    1895           0 :         rtwn_bb_write(sc, R92C_TXAGC_RATE54_24(chain),
    1896           0 :             SM(R92C_TXAGC_RATE24, power[RTWN_POWER_OFDM24]) |
    1897           0 :             SM(R92C_TXAGC_RATE36, power[RTWN_POWER_OFDM36]) |
    1898           0 :             SM(R92C_TXAGC_RATE48, power[RTWN_POWER_OFDM48]) |
    1899           0 :             SM(R92C_TXAGC_RATE54, power[RTWN_POWER_OFDM54]));
    1900             :         /* Write per-MCS Tx power. */
    1901           0 :         rtwn_bb_write(sc, R92C_TXAGC_MCS03_MCS00(chain),
    1902           0 :             SM(R92C_TXAGC_MCS00,  power[RTWN_POWER_MCS( 0)]) |
    1903           0 :             SM(R92C_TXAGC_MCS01,  power[RTWN_POWER_MCS( 1)]) |
    1904           0 :             SM(R92C_TXAGC_MCS02,  power[RTWN_POWER_MCS( 2)]) |
    1905           0 :             SM(R92C_TXAGC_MCS03,  power[RTWN_POWER_MCS( 3)]));
    1906           0 :         rtwn_bb_write(sc, R92C_TXAGC_MCS07_MCS04(chain),
    1907           0 :             SM(R92C_TXAGC_MCS04,  power[RTWN_POWER_MCS( 4)]) |
    1908           0 :             SM(R92C_TXAGC_MCS05,  power[RTWN_POWER_MCS( 5)]) |
    1909           0 :             SM(R92C_TXAGC_MCS06,  power[RTWN_POWER_MCS( 6)]) |
    1910           0 :             SM(R92C_TXAGC_MCS07,  power[RTWN_POWER_MCS( 7)]));
    1911           0 :         if (sc->ntxchains > 1) {
    1912           0 :                 rtwn_bb_write(sc, R92C_TXAGC_MCS11_MCS08(chain),
    1913           0 :                     SM(R92C_TXAGC_MCS08,  power[RTWN_POWER_MCS( 8)]) |
    1914           0 :                     SM(R92C_TXAGC_MCS09,  power[RTWN_POWER_MCS( 9)]) |
    1915           0 :                     SM(R92C_TXAGC_MCS10,  power[RTWN_POWER_MCS(10)]) |
    1916           0 :                     SM(R92C_TXAGC_MCS11,  power[RTWN_POWER_MCS(11)]));
    1917           0 :                 rtwn_bb_write(sc, R92C_TXAGC_MCS15_MCS12(chain),
    1918           0 :                     SM(R92C_TXAGC_MCS12,  power[RTWN_POWER_MCS(12)]) |
    1919           0 :                     SM(R92C_TXAGC_MCS13,  power[RTWN_POWER_MCS(13)]) |
    1920           0 :                     SM(R92C_TXAGC_MCS14,  power[RTWN_POWER_MCS(14)]) |
    1921           0 :                     SM(R92C_TXAGC_MCS15,  power[RTWN_POWER_MCS(15)]));
    1922           0 :         }
    1923           0 : }
    1924             : 
    1925             : void
    1926           0 : rtwn_get_txpower(struct rtwn_softc *sc, int chain, struct ieee80211_channel *c,
    1927             :     struct ieee80211_channel *extc, uint16_t power[RTWN_POWER_COUNT])
    1928             : {
    1929           0 :         if (sc->chip & RTWN_CHIP_88E)
    1930           0 :                 rtwn_r88e_get_txpower(sc, chain, c, extc, power);
    1931             :         else
    1932           0 :                 rtwn_r92c_get_txpower(sc, chain, c, extc, power);
    1933           0 : }
    1934             : 
    1935             : void
    1936           0 : rtwn_r92c_get_txpower(struct rtwn_softc *sc, int chain,
    1937             :     struct ieee80211_channel *c, struct ieee80211_channel *extc,
    1938             :     uint16_t power[RTWN_POWER_COUNT])
    1939             : {
    1940           0 :         struct ieee80211com *ic = &sc->sc_ic;
    1941           0 :         struct r92c_rom *rom = &sc->sc_r92c_rom;
    1942             :         uint16_t cckpow, ofdmpow, htpow, diff, max;
    1943             :         const struct r92c_txpwr *base;
    1944             :         int ridx, chan, group;
    1945             : 
    1946             :         /* Determine channel group. */
    1947           0 :         chan = ieee80211_chan2ieee(ic, c);      /* XXX center freq! */
    1948           0 :         if (chan <= 3)
    1949           0 :                 group = 0;
    1950           0 :         else if (chan <= 9)
    1951           0 :                 group = 1;
    1952             :         else
    1953             :                 group = 2;
    1954             : 
    1955             :         /* Get original Tx power based on board type and RF chain. */
    1956           0 :         if (!(sc->chip & RTWN_CHIP_92C)) {
    1957           0 :                 if (sc->board_type == R92C_BOARD_TYPE_HIGHPA)
    1958           0 :                         base = &rtl8188ru_txagc[chain];
    1959             :                 else
    1960           0 :                         base = &rtl8192cu_txagc[chain];
    1961             :         } else
    1962           0 :                 base = &rtl8192cu_txagc[chain];
    1963             : 
    1964           0 :         memset(power, 0, RTWN_POWER_COUNT * sizeof(power[0]));
    1965           0 :         if (sc->regulatory == 0) {
    1966           0 :                 for (ridx = RTWN_RIDX_CCK1; ridx <= RTWN_RIDX_CCK11; ridx++)
    1967           0 :                         power[ridx] = base->pwr[0][ridx];
    1968             :         }
    1969           0 :         for (ridx = RTWN_RIDX_OFDM6; ridx <= RTWN_RIDX_MAX; ridx++) {
    1970           0 :                 if (sc->regulatory == 3) {
    1971           0 :                         power[ridx] = base->pwr[0][ridx];
    1972             :                         /* Apply vendor limits. */
    1973           0 :                         if (extc != NULL)
    1974           0 :                                 max = rom->ht40_max_pwr[group];
    1975             :                         else
    1976           0 :                                 max = rom->ht20_max_pwr[group];
    1977           0 :                         max = (max >> (chain * 4)) & 0xf;
    1978           0 :                         if (power[ridx] > max)
    1979           0 :                                 power[ridx] = max;
    1980           0 :                 } else if (sc->regulatory == 1) {
    1981           0 :                         if (extc == NULL)
    1982           0 :                                 power[ridx] = base->pwr[group][ridx];
    1983           0 :                 } else if (sc->regulatory != 2)
    1984           0 :                         power[ridx] = base->pwr[0][ridx];
    1985             :         }
    1986             : 
    1987             :         /* Compute per-CCK rate Tx power. */
    1988           0 :         cckpow = rom->cck_tx_pwr[chain][group];
    1989           0 :         for (ridx = RTWN_RIDX_CCK1; ridx <= RTWN_RIDX_CCK11; ridx++) {
    1990           0 :                 power[ridx] += cckpow;
    1991           0 :                 if (power[ridx] > R92C_MAX_TX_PWR)
    1992           0 :                         power[ridx] = R92C_MAX_TX_PWR;
    1993             :         }
    1994             : 
    1995           0 :         htpow = rom->ht40_1s_tx_pwr[chain][group];
    1996           0 :         if (sc->ntxchains > 1) {
    1997             :                 /* Apply reduction for 2 spatial streams. */
    1998           0 :                 diff = rom->ht40_2s_tx_pwr_diff[group];
    1999           0 :                 diff = (diff >> (chain * 4)) & 0xf;
    2000           0 :                 htpow = (htpow > diff) ? htpow - diff : 0;
    2001           0 :         }
    2002             : 
    2003             :         /* Compute per-OFDM rate Tx power. */
    2004           0 :         diff = rom->ofdm_tx_pwr_diff[group];
    2005           0 :         diff = (diff >> (chain * 4)) & 0xf;
    2006           0 :         ofdmpow = htpow + diff; /* HT->OFDM correction. */
    2007           0 :         for (ridx = RTWN_RIDX_OFDM6; ridx <= RTWN_RIDX_OFDM54; ridx++) {
    2008           0 :                 power[ridx] += ofdmpow;
    2009           0 :                 if (power[ridx] > R92C_MAX_TX_PWR)
    2010           0 :                         power[ridx] = R92C_MAX_TX_PWR;
    2011             :         }
    2012             : 
    2013             :         /* Compute per-MCS Tx power. */
    2014           0 :         if (extc == NULL) {
    2015           0 :                 diff = rom->ht20_tx_pwr_diff[group];
    2016           0 :                 diff = (diff >> (chain * 4)) & 0xf;
    2017           0 :                 htpow += diff;  /* HT40->HT20 correction. */
    2018           0 :         }
    2019           0 :         for (ridx = RTWN_RIDX_MCS0; ridx <= RTWN_RIDX_MCS15; ridx++) {
    2020           0 :                 power[ridx] += htpow;
    2021           0 :                 if (power[ridx] > R92C_MAX_TX_PWR)
    2022           0 :                         power[ridx] = R92C_MAX_TX_PWR;
    2023             :         }
    2024             : #ifdef RTWN_DEBUG
    2025             :         if (rtwn_debug >= 4) {
    2026             :                 /* Dump per-rate Tx power values. */
    2027             :                 printf("Tx power for chain %d:\n", chain);
    2028             :                 for (ridx = RTWN_RIDX_CCK1; ridx <= RTWN_RIDX_MAX; ridx++)
    2029             :                         printf("Rate %d = %u\n", ridx, power[ridx]);
    2030             :         }
    2031             : #endif
    2032           0 : }
    2033             : 
    2034             : void
    2035           0 : rtwn_r88e_get_txpower(struct rtwn_softc *sc, int chain,
    2036             :     struct ieee80211_channel *c, struct ieee80211_channel *extc,
    2037             :     uint16_t power[RTWN_POWER_COUNT])
    2038             : {
    2039           0 :         struct ieee80211com *ic = &sc->sc_ic;
    2040           0 :         struct r88e_rom *rom = &sc->sc_r88e_rom;
    2041             :         uint8_t cckpow, htpow, ofdmpow;
    2042             :         int8_t diff;
    2043             :         int ridx, chan, group;
    2044             : 
    2045             :         /* Determine channel group. */
    2046           0 :         chan = ieee80211_chan2ieee(ic, c);      /* XXX center freq! */
    2047           0 :         if (chan <= 2)
    2048           0 :                 group = 0;
    2049           0 :         else if (chan <= 5)
    2050           0 :                 group = 1;
    2051           0 :         else if (chan <= 8)
    2052           0 :                 group = 2;
    2053           0 :         else if (chan <= 11)
    2054           0 :                 group = 3;
    2055           0 :         else if (chan <= 13)
    2056           0 :                 group = 4;
    2057             :         else
    2058             :                 group = 5;
    2059             : 
    2060           0 :         memset(power, 0, RTWN_POWER_COUNT * sizeof(power[0]));
    2061             : 
    2062             :         /* Compute per-CCK rate Tx power. */
    2063           0 :         cckpow = rom->txpwr.cck_tx_pwr[group];
    2064           0 :         for (ridx = RTWN_RIDX_CCK1; ridx <= RTWN_RIDX_CCK11; ridx++) {
    2065           0 :                 power[ridx] = (ridx == RTWN_RIDX_CCK2) ? cckpow - 9 : cckpow;
    2066           0 :                 if (power[ridx] > R92C_MAX_TX_PWR)
    2067           0 :                         power[ridx] = R92C_MAX_TX_PWR;
    2068             :         }
    2069             : 
    2070           0 :         htpow = (group == 5) ? rom->txpwr.ht40_tx_pwr[group - 1] :
    2071           0 :             rom->txpwr.ht40_tx_pwr[group];
    2072             : 
    2073             :         /* Compute per-OFDM rate Tx power. */
    2074           0 :         diff = RTWN_SIGN4TO8(MS(rom->txpwr.ht20_ofdm_tx_pwr_diff,
    2075             :             R88E_ROM_TXPWR_OFDM_DIFF));
    2076           0 :         ofdmpow = htpow + diff;
    2077           0 :         for (ridx = RTWN_RIDX_OFDM6; ridx <= RTWN_RIDX_OFDM54; ridx++) {
    2078           0 :                 power[ridx] = ofdmpow; 
    2079           0 :                 if (power[ridx] > R92C_MAX_TX_PWR)
    2080           0 :                         power[ridx] = R92C_MAX_TX_PWR;
    2081             :         }
    2082             : 
    2083             :         /* Compute per-MCS Tx power. */
    2084           0 :         if (extc == NULL) {
    2085           0 :                 diff = RTWN_SIGN4TO8(MS(rom->txpwr.ht20_ofdm_tx_pwr_diff,
    2086             :                     R88E_ROM_TXPWR_HT20_DIFF));
    2087           0 :                 htpow += diff;
    2088           0 :         }
    2089           0 :         for (ridx = RTWN_RIDX_MCS0; ridx < RTWN_RIDX_MCS8; ridx++) {
    2090           0 :                 power[ridx] = htpow;
    2091           0 :                 if (power[ridx] > R92C_MAX_TX_PWR)
    2092           0 :                         power[ridx] = R92C_MAX_TX_PWR;
    2093             :         }
    2094           0 : }
    2095             : 
    2096             : void
    2097           0 : rtwn_set_txpower(struct rtwn_softc *sc, struct ieee80211_channel *c,
    2098             :     struct ieee80211_channel *extc)
    2099             : {
    2100           0 :         uint16_t power[RTWN_POWER_COUNT];
    2101             :         int i;
    2102             : 
    2103           0 :         for (i = 0; i < sc->ntxchains; i++) {
    2104             :                 /* Compute per-rate Tx power values. */
    2105           0 :                 rtwn_get_txpower(sc, i, c, extc, power);
    2106             :                 /* Write per-rate Tx power values to hardware. */
    2107           0 :                 rtwn_write_txpower(sc, i, power);
    2108             :         }
    2109           0 : }
    2110             : 
    2111             : void
    2112           0 : rtwn_set_chan(struct rtwn_softc *sc, struct ieee80211_channel *c,
    2113             :     struct ieee80211_channel *extc)
    2114             : {
    2115           0 :         struct ieee80211com *ic = &sc->sc_ic;
    2116             :         u_int chan;
    2117             :         int i;
    2118             : 
    2119           0 :         chan = ieee80211_chan2ieee(ic, c);      /* XXX center freq! */
    2120             : 
    2121             :         /* Set Tx power for this new channel. */
    2122           0 :         rtwn_set_txpower(sc, c, extc);
    2123             : 
    2124           0 :         for (i = 0; i < sc->nrxchains; i++) {
    2125           0 :                 rtwn_rf_write(sc, i, R92C_RF_CHNLBW,
    2126           0 :                     RW(sc->rf_chnlbw[i], R92C_RF_CHNLBW_CHNL, chan));
    2127             :         }
    2128           0 :         if (extc != NULL) {
    2129             :                 uint32_t reg;
    2130             : 
    2131             :                 /* Is secondary channel below or above primary? */
    2132           0 :                 int prichlo = c->ic_freq < extc->ic_freq;
    2133             : 
    2134           0 :                 rtwn_write_1(sc, R92C_BWOPMODE,
    2135           0 :                     rtwn_read_1(sc, R92C_BWOPMODE) & ~R92C_BWOPMODE_20MHZ);
    2136             : 
    2137           0 :                 reg = rtwn_read_1(sc, R92C_RRSR + 2);
    2138           0 :                 reg = (reg & ~0x6f) | (prichlo ? 1 : 2) << 5;
    2139           0 :                 rtwn_write_1(sc, R92C_RRSR + 2, reg);
    2140             : 
    2141           0 :                 rtwn_bb_write(sc, R92C_FPGA0_RFMOD,
    2142           0 :                     rtwn_bb_read(sc, R92C_FPGA0_RFMOD) | R92C_RFMOD_40MHZ);
    2143           0 :                 rtwn_bb_write(sc, R92C_FPGA1_RFMOD,
    2144           0 :                     rtwn_bb_read(sc, R92C_FPGA1_RFMOD) | R92C_RFMOD_40MHZ);
    2145             : 
    2146             :                 /* Set CCK side band. */
    2147           0 :                 reg = rtwn_bb_read(sc, R92C_CCK0_SYSTEM);
    2148           0 :                 reg = (reg & ~0x00000010) | (prichlo ? 0 : 1) << 4;
    2149           0 :                 rtwn_bb_write(sc, R92C_CCK0_SYSTEM, reg);
    2150             : 
    2151           0 :                 reg = rtwn_bb_read(sc, R92C_OFDM1_LSTF);
    2152           0 :                 reg = (reg & ~0x00000c00) | (prichlo ? 1 : 2) << 10;
    2153           0 :                 rtwn_bb_write(sc, R92C_OFDM1_LSTF, reg);
    2154             : 
    2155           0 :                 if (!(sc->chip & RTWN_CHIP_88E)) {
    2156           0 :                         rtwn_bb_write(sc, R92C_FPGA0_ANAPARAM2,
    2157           0 :                             rtwn_bb_read(sc, R92C_FPGA0_ANAPARAM2) &
    2158             :                             ~R92C_FPGA0_ANAPARAM2_CBW20);
    2159           0 :                 }
    2160             : 
    2161           0 :                 reg = rtwn_bb_read(sc, 0x818);
    2162           0 :                 reg = (reg & ~0x0c000000) | (prichlo ? 2 : 1) << 26;
    2163           0 :                 rtwn_bb_write(sc, 0x818, reg);
    2164             : 
    2165             :                 /* Select 40MHz bandwidth. */
    2166           0 :                 rtwn_rf_write(sc, 0, R92C_RF_CHNLBW,
    2167           0 :                     (sc->rf_chnlbw[0] & ~0xfff) | chan);
    2168           0 :         } else {
    2169           0 :                 rtwn_write_1(sc, R92C_BWOPMODE,
    2170           0 :                     rtwn_read_1(sc, R92C_BWOPMODE) | R92C_BWOPMODE_20MHZ);
    2171             : 
    2172           0 :                 rtwn_bb_write(sc, R92C_FPGA0_RFMOD,
    2173           0 :                     rtwn_bb_read(sc, R92C_FPGA0_RFMOD) & ~R92C_RFMOD_40MHZ);
    2174           0 :                 rtwn_bb_write(sc, R92C_FPGA1_RFMOD,
    2175           0 :                     rtwn_bb_read(sc, R92C_FPGA1_RFMOD) & ~R92C_RFMOD_40MHZ);
    2176             : 
    2177           0 :                 if (!(sc->chip & RTWN_CHIP_88E)) {
    2178           0 :                         rtwn_bb_write(sc, R92C_FPGA0_ANAPARAM2,
    2179           0 :                             rtwn_bb_read(sc, R92C_FPGA0_ANAPARAM2) |
    2180             :                             R92C_FPGA0_ANAPARAM2_CBW20);
    2181           0 :                 }
    2182             : 
    2183             :                 /* Select 20MHz bandwidth. */
    2184           0 :                 rtwn_rf_write(sc, 0, R92C_RF_CHNLBW,
    2185           0 :                     (sc->rf_chnlbw[0] & ~0xfff) | chan | 
    2186           0 :                     ((sc->chip & RTWN_CHIP_88E) ? R88E_RF_CHNLBW_BW20 :
    2187             :                     R92C_RF_CHNLBW_BW20));
    2188             :         }
    2189           0 : }
    2190             : 
    2191             : int
    2192           0 : rtwn_iq_calib_chain(struct rtwn_softc *sc, int chain, uint16_t tx[2],
    2193             :     uint16_t rx[2])
    2194             : {
    2195             :         uint32_t status;
    2196           0 :         int offset = chain * 0x20;
    2197             : 
    2198           0 :         if (chain == 0) {       /* IQ calibration for chain 0. */
    2199             :                 /* IQ calibration settings for chain 0. */
    2200           0 :                 rtwn_bb_write(sc, 0xe30, 0x10008c1f);
    2201           0 :                 rtwn_bb_write(sc, 0xe34, 0x10008c1f);
    2202           0 :                 rtwn_bb_write(sc, 0xe38, 0x82140102);
    2203             : 
    2204           0 :                 if (sc->ntxchains > 1) {
    2205           0 :                         rtwn_bb_write(sc, 0xe3c, 0x28160202);   /* 2T */
    2206             :                         /* IQ calibration settings for chain 1. */
    2207           0 :                         rtwn_bb_write(sc, 0xe50, 0x10008c22);
    2208           0 :                         rtwn_bb_write(sc, 0xe54, 0x10008c22);
    2209           0 :                         rtwn_bb_write(sc, 0xe58, 0x82140102);
    2210           0 :                         rtwn_bb_write(sc, 0xe5c, 0x28160202);
    2211           0 :                 } else
    2212           0 :                         rtwn_bb_write(sc, 0xe3c, 0x28160502);   /* 1T */
    2213             : 
    2214             :                 /* LO calibration settings. */
    2215           0 :                 rtwn_bb_write(sc, 0xe4c, 0x001028d1);
    2216             :                 /* We're doing LO and IQ calibration in one shot. */
    2217           0 :                 rtwn_bb_write(sc, 0xe48, 0xf9000000);
    2218           0 :                 rtwn_bb_write(sc, 0xe48, 0xf8000000);
    2219             : 
    2220           0 :         } else {                /* IQ calibration for chain 1. */
    2221             :                 /* We're doing LO and IQ calibration in one shot. */
    2222           0 :                 rtwn_bb_write(sc, 0xe60, 0x00000002);
    2223           0 :                 rtwn_bb_write(sc, 0xe60, 0x00000000);
    2224             :         }
    2225             : 
    2226             :         /* Give LO and IQ calibrations the time to complete. */
    2227           0 :         DELAY(1000);
    2228             : 
    2229             :         /* Read IQ calibration status. */
    2230           0 :         status = rtwn_bb_read(sc, 0xeac);
    2231             : 
    2232           0 :         if (status & (1 << (28 + chain * 3)))
    2233           0 :                 return (0);     /* Tx failed. */
    2234             :         /* Read Tx IQ calibration results. */
    2235           0 :         tx[0] = (rtwn_bb_read(sc, 0xe94 + offset) >> 16) & 0x3ff;
    2236           0 :         tx[1] = (rtwn_bb_read(sc, 0xe9c + offset) >> 16) & 0x3ff;
    2237           0 :         if (tx[0] == 0x142 || tx[1] == 0x042)
    2238           0 :                 return (0);     /* Tx failed. */
    2239             : 
    2240           0 :         if (status & (1 << (27 + chain * 3)))
    2241           0 :                 return (1);     /* Rx failed. */
    2242             :         /* Read Rx IQ calibration results. */
    2243           0 :         rx[0] = (rtwn_bb_read(sc, 0xea4 + offset) >> 16) & 0x3ff;
    2244           0 :         rx[1] = (rtwn_bb_read(sc, 0xeac + offset) >> 16) & 0x3ff;
    2245           0 :         if (rx[0] == 0x132 || rx[1] == 0x036)
    2246           0 :                 return (1);     /* Rx failed. */
    2247             : 
    2248           0 :         return (3);     /* Both Tx and Rx succeeded. */
    2249           0 : }
    2250             : 
    2251             : void
    2252           0 : rtwn_iq_calib_run(struct rtwn_softc *sc, int n, uint16_t tx[2][2],
    2253             :     uint16_t rx[2][2], struct rtwn_iq_cal_regs *iq_cal_regs)
    2254             : {
    2255             :         static const uint16_t reg_adda[16] = {
    2256             :                 0x85c, 0xe6c, 0xe70, 0xe74,
    2257             :                 0xe78, 0xe7c, 0xe80, 0xe84,
    2258             :                 0xe88, 0xe8c, 0xed0, 0xed4,
    2259             :                 0xed8, 0xedc, 0xee0, 0xeec
    2260             :         };
    2261             :         int i, chain;
    2262             :         uint32_t hssi_param1;
    2263             : 
    2264           0 :         if (n == 0) {
    2265           0 :                 for (i = 0; i < nitems(reg_adda); i++)
    2266           0 :                         iq_cal_regs->adda[i] = rtwn_bb_read(sc, reg_adda[i]);
    2267             : 
    2268           0 :                 iq_cal_regs->txpause = rtwn_read_1(sc, R92C_TXPAUSE);
    2269           0 :                 iq_cal_regs->bcn_ctrl = rtwn_read_1(sc, R92C_BCN_CTRL);
    2270           0 :                 iq_cal_regs->bcn_ctrl1 = rtwn_read_1(sc, R92C_BCN_CTRL1);
    2271           0 :                 iq_cal_regs->gpio_muxcfg = rtwn_read_4(sc, R92C_GPIO_MUXCFG);
    2272           0 :         }
    2273             : 
    2274           0 :         if (sc->ntxchains == 1) {
    2275           0 :                 rtwn_bb_write(sc, reg_adda[0], 0x0b1b25a0);
    2276           0 :                 for (i = 1; i < nitems(reg_adda); i++)
    2277           0 :                         rtwn_bb_write(sc, reg_adda[i], 0x0bdb25a0);
    2278             :         } else {
    2279           0 :                 for (i = 0; i < nitems(reg_adda); i++)
    2280           0 :                         rtwn_bb_write(sc, reg_adda[i], 0x04db25a4);
    2281             :         }
    2282             : 
    2283           0 :         hssi_param1 = rtwn_bb_read(sc, R92C_HSSI_PARAM1(0));
    2284           0 :         if (!(hssi_param1 & R92C_HSSI_PARAM1_PI)) {
    2285           0 :                 rtwn_bb_write(sc, R92C_HSSI_PARAM1(0),
    2286           0 :                     hssi_param1 | R92C_HSSI_PARAM1_PI);
    2287           0 :                 rtwn_bb_write(sc, R92C_HSSI_PARAM1(1),
    2288             :                     hssi_param1 | R92C_HSSI_PARAM1_PI);
    2289           0 :         }
    2290             : 
    2291           0 :         if (n == 0) {
    2292           0 :                 iq_cal_regs->ofdm0_trxpathena =
    2293           0 :                     rtwn_bb_read(sc, R92C_OFDM0_TRXPATHENA);
    2294           0 :                 iq_cal_regs->ofdm0_trmuxpar =
    2295           0 :                     rtwn_bb_read(sc, R92C_OFDM0_TRMUXPAR);
    2296           0 :                 iq_cal_regs->fpga0_rfifacesw1 =
    2297           0 :                     rtwn_bb_read(sc, R92C_FPGA0_RFIFACESW(1));
    2298           0 :         }
    2299             : 
    2300           0 :         rtwn_bb_write(sc, R92C_OFDM0_TRXPATHENA, 0x03a05600);
    2301           0 :         rtwn_bb_write(sc, R92C_OFDM0_TRMUXPAR, 0x000800e4);
    2302           0 :         rtwn_bb_write(sc, R92C_FPGA0_RFIFACESW(1), 0x22204000);
    2303           0 :         if (sc->ntxchains > 1) {
    2304           0 :                 rtwn_bb_write(sc, R92C_LSSI_PARAM(0), 0x00010000);
    2305           0 :                 rtwn_bb_write(sc, R92C_LSSI_PARAM(1), 0x00010000);
    2306           0 :         }
    2307             : 
    2308           0 :         rtwn_write_1(sc, R92C_TXPAUSE, R92C_TXPAUSE_AC_VO |
    2309             :             R92C_TXPAUSE_AC_VI | R92C_TXPAUSE_AC_BE | R92C_TXPAUSE_AC_BK |
    2310             :             R92C_TXPAUSE_MGNT | R92C_TXPAUSE_HIGH);
    2311           0 :         rtwn_write_1(sc, R92C_BCN_CTRL,
    2312           0 :             iq_cal_regs->bcn_ctrl & ~(R92C_BCN_CTRL_EN_BCN));
    2313           0 :         rtwn_write_1(sc, R92C_BCN_CTRL1,
    2314           0 :             iq_cal_regs->bcn_ctrl1 & ~(R92C_BCN_CTRL_EN_BCN));
    2315           0 :         rtwn_write_1(sc, R92C_GPIO_MUXCFG,
    2316           0 :             iq_cal_regs->gpio_muxcfg & ~(R92C_GPIO_MUXCFG_ENBT));
    2317             : 
    2318           0 :         rtwn_bb_write(sc, 0x0b68, 0x00080000);
    2319           0 :         if (sc->ntxchains > 1)
    2320           0 :                 rtwn_bb_write(sc, 0x0b6c, 0x00080000);
    2321             : 
    2322           0 :         rtwn_bb_write(sc, 0x0e28, 0x80800000);
    2323           0 :         rtwn_bb_write(sc, 0x0e40, 0x01007c00);
    2324           0 :         rtwn_bb_write(sc, 0x0e44, 0x01004800);
    2325             : 
    2326           0 :         rtwn_bb_write(sc, 0x0b68, 0x00080000);
    2327             : 
    2328           0 :         for (chain = 0; chain < sc->ntxchains; chain++) {
    2329           0 :                 if (chain > 0) {
    2330             :                         /* Put chain 0 on standby. */
    2331           0 :                         rtwn_bb_write(sc, 0x0e28, 0x00);
    2332           0 :                         rtwn_bb_write(sc, R92C_LSSI_PARAM(0), 0x00010000);
    2333           0 :                         rtwn_bb_write(sc, 0x0e28, 0x80800000);
    2334             : 
    2335             :                         /* Enable chain 1. */
    2336           0 :                         for (i = 0; i < nitems(reg_adda); i++)
    2337           0 :                                 rtwn_bb_write(sc, reg_adda[i], 0x0b1b25a4);
    2338             :                 }
    2339             : 
    2340             :                 /* Run IQ calibration twice. */
    2341           0 :                 for (i = 0; i < 2; i++) {
    2342             :                         int ret;
    2343             : 
    2344           0 :                         ret = rtwn_iq_calib_chain(sc, chain,
    2345           0 :                             tx[chain], rx[chain]);
    2346           0 :                         if (ret == 0) {
    2347             :                                 DPRINTF(("%s: chain %d: Tx failed.\n",
    2348             :                                     __func__, chain));
    2349           0 :                                 tx[chain][0] = 0xff;
    2350           0 :                                 tx[chain][1] = 0xff;
    2351           0 :                                 rx[chain][0] = 0xff;
    2352           0 :                                 rx[chain][1] = 0xff;
    2353           0 :                         } else if (ret == 1) {
    2354             :                                 DPRINTF(("%s: chain %d: Rx failed.\n",
    2355             :                                     __func__, chain));
    2356           0 :                                 rx[chain][0] = 0xff;
    2357           0 :                                 rx[chain][1] = 0xff;
    2358           0 :                         } else if (ret == 3) {
    2359             :                                 DPRINTF(("%s: chain %d: Both Tx and Rx "
    2360             :                                     "succeeded.\n", __func__, chain));
    2361             :                         }
    2362             :                 }
    2363             : 
    2364             :                 DPRINTF(("%s: results for run %d chain %d: tx[0]=0x%x, "
    2365             :                     "tx[1]=0x%x rx[0]=0x%x rx[1]=0x%x\n", __func__, n, chain,
    2366             :                     tx[chain][0], tx[chain][1], rx[chain][0], rx[chain][1]));
    2367             :         }
    2368             : 
    2369           0 :         rtwn_bb_write(sc, R92C_OFDM0_TRXPATHENA,
    2370           0 :             iq_cal_regs->ofdm0_trxpathena); 
    2371           0 :         rtwn_bb_write(sc, R92C_FPGA0_RFIFACESW(1),
    2372           0 :             iq_cal_regs->fpga0_rfifacesw1);
    2373           0 :         rtwn_bb_write(sc, R92C_OFDM0_TRMUXPAR, iq_cal_regs->ofdm0_trmuxpar);
    2374             : 
    2375           0 :         rtwn_bb_write(sc, 0x0e28, 0x00);
    2376           0 :         rtwn_bb_write(sc, R92C_LSSI_PARAM(0), 0x00032ed3);
    2377           0 :         if (sc->ntxchains > 1)
    2378           0 :                 rtwn_bb_write(sc, R92C_LSSI_PARAM(1), 0x00032ed3);
    2379             : 
    2380           0 :         if (n != 0) {
    2381           0 :                 if (!(hssi_param1 & R92C_HSSI_PARAM1_PI)) {
    2382           0 :                         rtwn_bb_write(sc, R92C_HSSI_PARAM1(0), hssi_param1);
    2383           0 :                         rtwn_bb_write(sc, R92C_HSSI_PARAM1(1), hssi_param1);
    2384           0 :                 }
    2385             : 
    2386           0 :                 for (i = 0; i < nitems(reg_adda); i++)
    2387           0 :                         rtwn_bb_write(sc, reg_adda[i], iq_cal_regs->adda[i]);
    2388             : 
    2389           0 :                 rtwn_write_1(sc, R92C_TXPAUSE, iq_cal_regs->txpause);
    2390           0 :                 rtwn_write_1(sc, R92C_BCN_CTRL, iq_cal_regs->bcn_ctrl);
    2391           0 :                 rtwn_write_1(sc, R92C_BCN_CTRL1, iq_cal_regs->bcn_ctrl1);
    2392           0 :                 rtwn_write_4(sc, R92C_GPIO_MUXCFG, iq_cal_regs->gpio_muxcfg);
    2393           0 :         }
    2394           0 : }
    2395             : 
    2396             : #define RTWN_IQ_CAL_MAX_TOLERANCE 5
    2397             : int
    2398           0 : rtwn_iq_calib_compare_results(uint16_t tx1[2][2], uint16_t rx1[2][2],
    2399             :     uint16_t tx2[2][2], uint16_t rx2[2][2], int ntxchains)
    2400             : {
    2401           0 :         int chain, i, tx_ok[2], rx_ok[2];
    2402             : 
    2403           0 :         tx_ok[0] = tx_ok[1] = rx_ok[0] = rx_ok[1] = 0;
    2404           0 :         for (chain = 0; chain < ntxchains; chain++) {
    2405           0 :                 for (i = 0; i < 2; i++)      {
    2406           0 :                         if (tx1[chain][i] == 0xff || tx2[chain][i] == 0xff ||
    2407           0 :                             rx1[chain][i] == 0xff || rx2[chain][i] == 0xff)
    2408             :                                 continue;
    2409             : 
    2410           0 :                         tx_ok[chain] = (abs(tx1[chain][i] - tx2[chain][i]) <=
    2411             :                             RTWN_IQ_CAL_MAX_TOLERANCE);
    2412             : 
    2413           0 :                         rx_ok[chain] = (abs(rx1[chain][i] - rx2[chain][i]) <=
    2414             :                             RTWN_IQ_CAL_MAX_TOLERANCE);
    2415           0 :                 }
    2416             :         }
    2417             : 
    2418           0 :         if (ntxchains > 1)
    2419           0 :                 return (tx_ok[0] && tx_ok[1] && rx_ok[0] && rx_ok[1]);
    2420             :         else
    2421           0 :                 return (tx_ok[0] && rx_ok[0]);
    2422           0 : }
    2423             : #undef RTWN_IQ_CAL_MAX_TOLERANCE
    2424             : 
    2425             : void
    2426           0 : rtwn_iq_calib_write_results(struct rtwn_softc *sc, uint16_t tx[2],
    2427             :     uint16_t rx[2], int chain)
    2428             : {
    2429             :         uint32_t reg, val, x;
    2430             :         long y, tx_c;
    2431             : 
    2432           0 :         if (tx[0] == 0xff || tx[1] == 0xff)
    2433           0 :                 return;
    2434             : 
    2435           0 :         reg = rtwn_bb_read(sc, R92C_OFDM0_TXIQIMBALANCE(chain)); 
    2436           0 :         val = ((reg >> 22) & 0x3ff);
    2437           0 :         x = tx[0];
    2438           0 :         if (x & 0x00000200)
    2439           0 :                 x |= 0xfffffc00;
    2440           0 :         reg &= ~0x3ff;
    2441           0 :         reg |= (((x * val) >> 8) & 0x3ff);
    2442           0 :         rtwn_bb_write(sc, R92C_OFDM0_TXIQIMBALANCE(chain), reg);
    2443             : 
    2444           0 :         reg = rtwn_bb_read(sc, R92C_OFDM0_ECCATHRESHOLD);
    2445           0 :         if (((x * val) >> 7) & 0x01)
    2446           0 :                 reg |= 0x80000000;
    2447             :         else
    2448           0 :                 reg &= ~0x80000000;
    2449           0 :         rtwn_bb_write(sc, R92C_OFDM0_ECCATHRESHOLD, reg);
    2450             : 
    2451           0 :         y = tx[1];
    2452           0 :         if (y & 0x00000200)
    2453           0 :                 y |= 0xfffffc00;
    2454           0 :         tx_c = (y * val) >> 8;
    2455           0 :         reg = rtwn_bb_read(sc, R92C_OFDM0_TXAFE(chain));
    2456           0 :         reg &= ~0xf0000000;
    2457           0 :         reg |= ((tx_c & 0x3c0) << 22);
    2458           0 :         rtwn_bb_write(sc, R92C_OFDM0_TXAFE(chain), reg);
    2459             : 
    2460           0 :         reg = rtwn_bb_read(sc, R92C_OFDM0_TXIQIMBALANCE(chain)); 
    2461           0 :         reg &= ~0x003f0000;
    2462           0 :         reg |= ((tx_c & 0x3f) << 16);
    2463           0 :         rtwn_bb_write(sc, R92C_OFDM0_TXIQIMBALANCE(chain), reg);
    2464             : 
    2465           0 :         reg = rtwn_bb_read(sc, R92C_OFDM0_ECCATHRESHOLD);
    2466           0 :         if (((y * val) >> 7) & 0x01)
    2467           0 :                 reg |= 0x20000000;
    2468             :         else
    2469           0 :                 reg &= ~0x20000000;
    2470           0 :         rtwn_bb_write(sc, R92C_OFDM0_ECCATHRESHOLD, reg);
    2471             : 
    2472           0 :         if (rx[0] == 0xff || rx[1] == 0xff)
    2473           0 :                 return;
    2474             : 
    2475           0 :         reg = rtwn_bb_read(sc, R92C_OFDM0_RXIQIMBALANCE(chain));
    2476           0 :         reg &= ~0x3ff;
    2477           0 :         reg |= (rx[0] & 0x3ff);
    2478           0 :         rtwn_bb_write(sc, R92C_OFDM0_RXIQIMBALANCE(chain), reg);
    2479             : 
    2480           0 :         reg &= ~0xfc00;
    2481           0 :         reg |= ((rx[1] & 0x03f) << 10);
    2482           0 :         rtwn_bb_write(sc, R92C_OFDM0_RXIQIMBALANCE(chain), reg);
    2483             : 
    2484           0 :         if (chain == 0) {
    2485           0 :                 reg = rtwn_bb_read(sc, R92C_OFDM0_RXIQEXTANTA);
    2486           0 :                 reg &= ~0xf0000000;
    2487           0 :                 reg |= ((rx[1] & 0x3c0) << 22);
    2488           0 :                 rtwn_bb_write(sc, R92C_OFDM0_RXIQEXTANTA, reg);
    2489           0 :         } else {
    2490           0 :                 reg = rtwn_bb_read(sc, R92C_OFDM0_AGCRSSITABLE);
    2491           0 :                 reg &= ~0xf000;
    2492           0 :                 reg |= ((rx[1] & 0x3c0) << 6);
    2493           0 :                 rtwn_bb_write(sc, R92C_OFDM0_AGCRSSITABLE, reg);
    2494             :         }
    2495           0 : }
    2496             : 
    2497             : #define RTWN_IQ_CAL_NRUN        3
    2498             : void
    2499           0 : rtwn_iq_calib(struct rtwn_softc *sc)
    2500             : {
    2501           0 :         uint16_t tx[RTWN_IQ_CAL_NRUN][2][2], rx[RTWN_IQ_CAL_NRUN][2][2];
    2502             :         int n, valid;
    2503           0 :         struct rtwn_iq_cal_regs regs;
    2504             : 
    2505             :         valid = 0;
    2506           0 :         memset(&regs, 0, sizeof(regs));
    2507           0 :         for (n = 0; n < RTWN_IQ_CAL_NRUN; n++) {
    2508           0 :                 rtwn_iq_calib_run(sc, n, tx[n], rx[n], &regs);
    2509             : 
    2510           0 :                 if (n == 0)
    2511             :                         continue;
    2512             : 
    2513             :                 /* Valid results remain stable after consecutive runs. */
    2514           0 :                 valid = rtwn_iq_calib_compare_results(tx[n - 1], rx[n - 1],
    2515           0 :                     tx[n], rx[n], sc->ntxchains);
    2516           0 :                 if (valid)
    2517             :                         break;
    2518             :         }
    2519             : 
    2520           0 :         if (valid) {
    2521           0 :                 rtwn_iq_calib_write_results(sc, tx[n][0], rx[n][0], 0);
    2522           0 :                 if (sc->ntxchains > 1)
    2523           0 :                         rtwn_iq_calib_write_results(sc, tx[n][1], rx[n][1], 1);
    2524             :         }
    2525           0 : }
    2526             : #undef RTWN_IQ_CAL_NRUN
    2527             : 
    2528             : void
    2529           0 : rtwn_lc_calib(struct rtwn_softc *sc)
    2530             : {
    2531           0 :         uint32_t rf_ac[2];
    2532             :         uint8_t txmode;
    2533             :         int i;
    2534             : 
    2535           0 :         txmode = rtwn_read_1(sc, R92C_OFDM1_LSTF + 3);
    2536           0 :         if ((txmode & 0x70) != 0) {
    2537             :                 /* Disable all continuous Tx. */
    2538           0 :                 rtwn_write_1(sc, R92C_OFDM1_LSTF + 3, txmode & ~0x70);
    2539             : 
    2540             :                 /* Set RF mode to standby mode. */
    2541           0 :                 for (i = 0; i < sc->nrxchains; i++) {
    2542           0 :                         rf_ac[i] = rtwn_rf_read(sc, i, R92C_RF_AC);
    2543           0 :                         rtwn_rf_write(sc, i, R92C_RF_AC,
    2544           0 :                             RW(rf_ac[i], R92C_RF_AC_MODE,
    2545             :                                 R92C_RF_AC_MODE_STANDBY));
    2546             :                 }
    2547             :         } else {
    2548             :                 /* Block all Tx queues. */
    2549           0 :                 rtwn_write_1(sc, R92C_TXPAUSE, R92C_TXPAUSE_ALL);
    2550             :         }
    2551             :         /* Start calibration. */
    2552           0 :         rtwn_rf_write(sc, 0, R92C_RF_CHNLBW,
    2553           0 :             rtwn_rf_read(sc, 0, R92C_RF_CHNLBW) | R92C_RF_CHNLBW_LCSTART);
    2554             : 
    2555             :         /* Give calibration the time to complete. */
    2556           0 :         DELAY(100);
    2557             : 
    2558             :         /* Restore configuration. */
    2559           0 :         if ((txmode & 0x70) != 0) {
    2560             :                 /* Restore Tx mode. */
    2561           0 :                 rtwn_write_1(sc, R92C_OFDM1_LSTF + 3, txmode);
    2562             :                 /* Restore RF mode. */
    2563           0 :                 for (i = 0; i < sc->nrxchains; i++)
    2564           0 :                         rtwn_rf_write(sc, i, R92C_RF_AC, rf_ac[i]);
    2565             :         } else {
    2566             :                 /* Unblock all Tx queues. */
    2567           0 :                 rtwn_write_1(sc, R92C_TXPAUSE, 0x00);
    2568             :         }
    2569           0 : }
    2570             : 
    2571             : void
    2572           0 : rtwn_temp_calib(struct rtwn_softc *sc)
    2573             : {
    2574             :         int temp;
    2575             : 
    2576           0 :         if (sc->thcal_state == 0) {
    2577             :                 /* Start measuring temperature. */
    2578           0 :                 rtwn_rf_write(sc, 0, R92C_RF_T_METER, 0x60);
    2579           0 :                 sc->thcal_state = 1;
    2580           0 :                 return;
    2581             :         }
    2582           0 :         sc->thcal_state = 0;
    2583             : 
    2584             :         /* Read measured temperature. */
    2585           0 :         temp = rtwn_rf_read(sc, 0, R92C_RF_T_METER) & 0x1f;
    2586           0 :         if (temp == 0)  /* Read failed, skip. */
    2587           0 :                 return;
    2588             :         DPRINTFN(2, ("temperature=%d\n", temp));
    2589             : 
    2590             :         /*
    2591             :          * Redo IQ and LC calibration if temperature changed significantly
    2592             :          * since last calibration.
    2593             :          */
    2594           0 :         if (sc->thcal_lctemp == 0) {
    2595             :                 /* First calibration is performed in rtwn_init(). */
    2596           0 :                 sc->thcal_lctemp = temp;
    2597           0 :         } else if (abs(temp - sc->thcal_lctemp) > 1) {
    2598             :                 DPRINTF(("IQ/LC calib triggered by temp: %d -> %d\n",
    2599             :                     sc->thcal_lctemp, temp));
    2600           0 :                 rtwn_iq_calib(sc);
    2601           0 :                 rtwn_lc_calib(sc);
    2602             :                 /* Record temperature of last calibration. */
    2603           0 :                 sc->thcal_lctemp = temp;
    2604           0 :         }
    2605           0 : }
    2606             : 
    2607             : void
    2608           0 : rtwn_enable_intr(struct rtwn_softc *sc)
    2609             : {
    2610           0 :         if (sc->chip & RTWN_CHIP_88E) {
    2611           0 :                 rtwn_write_4(sc, R88E_HISR, 0xffffffff);
    2612           0 :                 rtwn_write_4(sc, R88E_HIMR, R88E_HIMR_CPWM |
    2613             :                 R88E_HIMR_CPWM2 | R88E_HIMR_TBDER |
    2614             :                 R88E_HIMR_PSTIMEOUT);
    2615           0 :                 rtwn_write_4(sc, R88E_HIMRE, R88E_HIMRE_RXFOVW |
    2616             :                     R88E_HIMRE_TXFOVW | R88E_HIMRE_RXERR |
    2617             :                     R88E_HIMRE_TXERR);
    2618           0 :                 if (sc->chip & RTWN_CHIP_USB) {
    2619           0 :                         rtwn_write_1(sc, R92C_USB_SPECIAL_OPTION,
    2620           0 :                             rtwn_read_1(sc, R92C_USB_SPECIAL_OPTION) |
    2621             :                             R92C_USB_SPECIAL_OPTION_INT_BULK_SEL);
    2622           0 :                 }
    2623             :         } else {
    2624             :                 uint32_t imask = 0;
    2625             : 
    2626           0 :                 if (sc->chip & RTWN_CHIP_USB)
    2627           0 :                         imask = 0xffffffff;
    2628           0 :                 else if (sc->chip & RTWN_CHIP_PCI)
    2629             :                         imask = RTWN_INT_ENABLE;
    2630             :                 else
    2631           0 :                         panic("unknown chip type 0x%x", sc->chip);
    2632             : 
    2633             :                 /* CLear pending interrupts. */
    2634           0 :                 rtwn_write_4(sc, R92C_HISR, 0xffffffff);
    2635             : 
    2636             :                 /* Enable interrupts. */
    2637           0 :                 rtwn_write_4(sc, R92C_HIMR, imask);
    2638             :         }
    2639           0 : }
    2640             : 
    2641             : void
    2642           0 : rtwn_disable_intr(struct rtwn_softc *sc)
    2643             : {
    2644           0 :         if (sc->chip & RTWN_CHIP_88E) {
    2645           0 :                 rtwn_write_4(sc, R88E_HISR, 0x00000000);
    2646           0 :                 rtwn_write_4(sc, R88E_HIMR, 0x00000000);
    2647           0 :                 rtwn_write_4(sc, R88E_HIMRE, 0x00000000);
    2648           0 :                 if (sc->chip & RTWN_CHIP_USB) {
    2649           0 :                         rtwn_write_1(sc, R92C_USB_SPECIAL_OPTION,
    2650           0 :                             rtwn_read_1(sc, R92C_USB_SPECIAL_OPTION) &
    2651             :                             ~R92C_USB_SPECIAL_OPTION_INT_BULK_SEL);
    2652           0 :                 }
    2653             :         } else {
    2654           0 :                 rtwn_write_4(sc, R92C_HISR, 0x00000000);
    2655           0 :                 rtwn_write_4(sc, R92C_HIMR, 0x00000000);
    2656             :         }
    2657           0 : }
    2658             : 
    2659             : int
    2660           0 : rtwn_init(struct ifnet *ifp)
    2661             : {
    2662           0 :         struct rtwn_softc *sc = ifp->if_softc;
    2663           0 :         struct ieee80211com *ic = &sc->sc_ic;
    2664             :         uint32_t reg;
    2665             :         int i, error;
    2666             : 
    2667             :         /* Init firmware commands ring. */
    2668           0 :         sc->fwcur = 0;
    2669             : 
    2670           0 :         error = sc->sc_ops.alloc_buffers(sc->sc_ops.cookie);
    2671           0 :         if (error)
    2672             :                 goto fail;
    2673             : 
    2674             :         /* Power on adapter. */
    2675           0 :         error = sc->sc_ops.power_on(sc->sc_ops.cookie);
    2676           0 :         if (error != 0) {
    2677           0 :                 printf("%s: could not power on adapter\n",
    2678           0 :                     sc->sc_pdev->dv_xname);
    2679           0 :                 goto fail;
    2680             :         }
    2681             : 
    2682             :         /* Initialize DMA. */
    2683           0 :         error = sc->sc_ops.dma_init(sc->sc_ops.cookie);
    2684           0 :         if (error != 0) {
    2685           0 :                 printf("%s: could not initialize DMA\n",
    2686           0 :                     sc->sc_pdev->dv_xname);
    2687           0 :                 goto fail;
    2688             :         }
    2689             : 
    2690             :         /* Set info size in Rx descriptors (in 64-bit words). */
    2691           0 :         rtwn_write_1(sc, R92C_RX_DRVINFO_SZ, 4);
    2692             : 
    2693           0 :         if (sc->chip & RTWN_CHIP_USB) {
    2694             :                 /* Init interrupts. */
    2695           0 :                 rtwn_enable_intr(sc);
    2696           0 :         } else if (sc->chip & RTWN_CHIP_PCI) {
    2697           0 :                 rtwn_disable_intr(sc);
    2698           0 :         }
    2699             : 
    2700             :         /* Set MAC address. */
    2701           0 :         IEEE80211_ADDR_COPY(ic->ic_myaddr, LLADDR(ifp->if_sadl));
    2702           0 :         for (i = 0; i < IEEE80211_ADDR_LEN; i++)
    2703           0 :                 rtwn_write_1(sc, R92C_MACID + i, ic->ic_myaddr[i]);
    2704             : 
    2705             :         /* Set initial network type. */
    2706           0 :         rtwn_set_nettype(sc, IEEE80211_M_MONITOR);
    2707             : 
    2708           0 :         rtwn_rxfilter_init(sc);
    2709             : 
    2710           0 :         reg = rtwn_read_4(sc, R92C_RRSR);
    2711           0 :         if (sc->chip & RTWN_CHIP_USB) {
    2712           0 :                 reg = RW(reg, R92C_RRSR_RATE_BITMAP,
    2713             :                     R92C_RRSR_RATE_CCK_ONLY_1M);
    2714           0 :         } else {
    2715           0 :                 reg = RW(reg, R92C_RRSR_RATE_BITMAP, R92C_RRSR_RATE_ALL);
    2716             :         }
    2717           0 :         rtwn_write_4(sc, R92C_RRSR, reg);
    2718             : 
    2719             :         /* Set short/long retry limits. */
    2720           0 :         if (sc->chip & RTWN_CHIP_USB) {
    2721           0 :                 rtwn_write_2(sc, R92C_RL,
    2722             :                     SM(R92C_RL_SRL, 0x30) | SM(R92C_RL_LRL, 0x30));
    2723           0 :         } else {
    2724           0 :                 rtwn_write_2(sc, R92C_RL,
    2725             :                     SM(R92C_RL_SRL, 0x07) | SM(R92C_RL_LRL, 0x07));
    2726             :         }
    2727             : 
    2728             :         /* Initialize EDCA parameters. */
    2729           0 :         rtwn_edca_init(sc);
    2730             : 
    2731             :         /* Set data and response automatic rate fallback retry counts. */
    2732           0 :         rtwn_rate_fallback_init(sc);
    2733             : 
    2734           0 :         if (sc->chip & RTWN_CHIP_USB) {
    2735           0 :                 rtwn_write_1(sc, R92C_FWHW_TXQ_CTRL,
    2736           0 :                     rtwn_read_1(sc, R92C_FWHW_TXQ_CTRL) |
    2737             :                     R92C_FWHW_TXQ_CTRL_AMPDU_RTY_NEW);
    2738           0 :         } else {
    2739           0 :                 rtwn_write_2(sc, R92C_FWHW_TXQ_CTRL, 0x1f80);
    2740             :         }
    2741             : 
    2742             :         /* Set ACK timeout. */
    2743           0 :         rtwn_write_1(sc, R92C_ACKTO, 0x40);
    2744             : 
    2745           0 :         if (sc->chip & RTWN_CHIP_USB) {
    2746             :                 /* Setup USB aggregation. */
    2747           0 :                 rtwn_usb_aggr_init(sc);
    2748           0 :         }
    2749             : 
    2750             :         /* Initialize beacon parameters. */
    2751           0 :         rtwn_write_2(sc, R92C_BCN_CTRL,
    2752             :             (R92C_BCN_CTRL_DIS_TSF_UDT0 << 8) | R92C_BCN_CTRL_DIS_TSF_UDT0);
    2753           0 :         rtwn_write_2(sc, R92C_TBTT_PROHIBIT, 0x6404);
    2754           0 :         rtwn_write_1(sc, R92C_DRVERLYINT, R92C_DRVERLYINT_INIT_TIME);
    2755           0 :         rtwn_write_1(sc, R92C_BCNDMATIM, R92C_BCNDMATIM_INIT_TIME);
    2756           0 :         rtwn_write_2(sc, R92C_BCNTCFG, 0x660f);
    2757             : 
    2758           0 :         if (!(sc->chip & RTWN_CHIP_88E)) {
    2759             :                 /* Setup AMPDU aggregation. */
    2760           0 :                 rtwn_write_4(sc, R92C_AGGLEN_LMT, 0x99997631);  /* MCS7~0 */
    2761           0 :                 rtwn_write_1(sc, R92C_AGGR_BREAK_TIME, 0x16);
    2762           0 :                 rtwn_write_2(sc, R92C_MAX_AGGR_NUM, 0x0708);
    2763             : 
    2764           0 :                 rtwn_write_1(sc, R92C_BCN_MAX_ERR, 0xff);
    2765           0 :         }
    2766             : 
    2767           0 :         if (sc->chip & RTWN_CHIP_PCI) {
    2768             :                 /* Reset H2C protection register. */
    2769           0 :                 rtwn_write_4(sc, R92C_MCUTST_1, 0x0);
    2770           0 :         }
    2771             : 
    2772             :         /* Load 8051 microcode. */
    2773           0 :         error = rtwn_load_firmware(sc);
    2774           0 :         if (error != 0)
    2775             :                 goto fail;
    2776             : 
    2777             :         /* Initialize MAC/BB/RF blocks. */
    2778           0 :         sc->sc_ops.mac_init(sc->sc_ops.cookie);
    2779           0 :         sc->sc_ops.bb_init(sc->sc_ops.cookie);
    2780           0 :         rtwn_rf_init(sc);
    2781             : 
    2782           0 :         if (sc->chip & RTWN_CHIP_88E) {
    2783           0 :                 rtwn_write_2(sc, R92C_CR,
    2784           0 :                     rtwn_read_2(sc, R92C_CR) | R92C_CR_MACTXEN |
    2785             :                     R92C_CR_MACRXEN);
    2786           0 :         }
    2787             : 
    2788             :         /* Turn CCK and OFDM blocks on. */
    2789           0 :         reg = rtwn_bb_read(sc, R92C_FPGA0_RFMOD);
    2790           0 :         reg |= R92C_RFMOD_CCK_EN;
    2791           0 :         rtwn_bb_write(sc, R92C_FPGA0_RFMOD, reg);
    2792           0 :         reg = rtwn_bb_read(sc, R92C_FPGA0_RFMOD);
    2793           0 :         reg |= R92C_RFMOD_OFDM_EN;
    2794           0 :         rtwn_bb_write(sc, R92C_FPGA0_RFMOD, reg);
    2795             : 
    2796             :         /* Clear per-station keys table. */
    2797           0 :         rtwn_cam_init(sc);
    2798             : 
    2799             :         /* Enable hardware sequence numbering. */
    2800           0 :         rtwn_write_1(sc, R92C_HWSEQ_CTRL, 0xff);
    2801             : 
    2802             :         /* Perform LO and IQ calibrations. */
    2803           0 :         rtwn_iq_calib(sc);
    2804             :         /* Perform LC calibration. */
    2805           0 :         rtwn_lc_calib(sc);
    2806             : 
    2807             :         /* Fix USB interference issue. */
    2808           0 :         if ((sc->chip & RTWN_CHIP_USB) && !(sc->chip & RTWN_CHIP_88E)) {
    2809           0 :                 rtwn_write_1(sc, 0xfe40, 0xe0);
    2810           0 :                 rtwn_write_1(sc, 0xfe41, 0x8d);
    2811           0 :                 rtwn_write_1(sc, 0xfe42, 0x80);
    2812             : 
    2813           0 :                 rtwn_pa_bias_init(sc);
    2814           0 :         }
    2815             : 
    2816             :         /* Initialize GPIO setting. */
    2817           0 :         rtwn_write_1(sc, R92C_GPIO_MUXCFG,
    2818           0 :             rtwn_read_1(sc, R92C_GPIO_MUXCFG) & ~R92C_GPIO_MUXCFG_ENBT);
    2819             : 
    2820             :         /* Fix for lower temperature. */
    2821           0 :         if (!(sc->chip & RTWN_CHIP_88E))
    2822           0 :                 rtwn_write_1(sc, 0x15, 0xe9);
    2823             : 
    2824             :         /* Set default channel. */
    2825           0 :         ic->ic_bss->ni_chan = ic->ic_ibss_chan;
    2826           0 :         rtwn_set_chan(sc, ic->ic_ibss_chan, NULL);
    2827             : 
    2828           0 :         if (sc->chip & RTWN_CHIP_PCI)
    2829           0 :                 rtwn_enable_intr(sc);
    2830             : 
    2831           0 :         error = sc->sc_ops.init(sc->sc_ops.cookie);
    2832           0 :         if (error)
    2833             :                 goto fail;
    2834             : 
    2835             :         /* We're ready to go. */
    2836           0 :         ifq_clr_oactive(&ifp->if_snd);
    2837           0 :         ifp->if_flags |= IFF_RUNNING;
    2838             : 
    2839             : #ifdef notyet
    2840             :         if (ic->ic_flags & IEEE80211_F_WEPON) {
    2841             :                 /* Install WEP keys. */
    2842             :                 for (i = 0; i < IEEE80211_WEP_NKID; i++)
    2843             :                         ic->ic_set_key(ic, NULL, &ic->ic_nw_keys[i]);
    2844             :                 sc->sc_ops.wait_async(sc->sc_ops.cookie);
    2845             :         }
    2846             : #endif
    2847           0 :         if (ic->ic_opmode == IEEE80211_M_MONITOR)
    2848           0 :                 ieee80211_new_state(ic, IEEE80211_S_RUN, -1);
    2849             :         else
    2850           0 :                 ieee80211_new_state(ic, IEEE80211_S_SCAN, -1);
    2851           0 :         return (0);
    2852             : fail:
    2853           0 :         rtwn_stop(ifp);
    2854           0 :         return (error);
    2855           0 : }
    2856             : 
    2857             : void
    2858           0 : rtwn_init_task(void *arg1)
    2859             : {
    2860           0 :         struct rtwn_softc *sc = arg1;
    2861           0 :         struct ifnet *ifp = &sc->sc_ic.ic_if;
    2862             :         int s;
    2863             : 
    2864           0 :         s = splnet();
    2865           0 :         while (sc->sc_flags & RTWN_FLAG_BUSY)
    2866           0 :                 tsleep(&sc->sc_flags, 0, "rtwnpwr", 0);
    2867           0 :         sc->sc_flags |= RTWN_FLAG_BUSY;
    2868             : 
    2869           0 :         rtwn_stop(ifp);
    2870             : 
    2871           0 :         if ((ifp->if_flags & (IFF_UP | IFF_RUNNING)) == IFF_UP)
    2872           0 :                 rtwn_init(ifp);
    2873             : 
    2874           0 :         sc->sc_flags &= ~RTWN_FLAG_BUSY;
    2875           0 :         wakeup(&sc->sc_flags);
    2876           0 :         splx(s);
    2877           0 : }
    2878             : 
    2879             : void
    2880           0 : rtwn_stop(struct ifnet *ifp)
    2881             : {
    2882           0 :         struct rtwn_softc *sc = ifp->if_softc;
    2883           0 :         struct ieee80211com *ic = &sc->sc_ic;
    2884             :         int s;
    2885             : 
    2886           0 :         sc->sc_tx_timer = 0;
    2887           0 :         ifp->if_timer = 0;
    2888           0 :         ifp->if_flags &= ~IFF_RUNNING;
    2889           0 :         ifq_clr_oactive(&ifp->if_snd);
    2890             : 
    2891           0 :         s = splnet();
    2892           0 :         ieee80211_new_state(ic, IEEE80211_S_INIT, -1);
    2893           0 :         splx(s);
    2894             : 
    2895           0 :         sc->sc_ops.wait_async(sc->sc_ops.cookie);
    2896             : 
    2897           0 :         s = splnet();
    2898             : 
    2899           0 :         sc->sc_ops.cancel_scan(sc->sc_ops.cookie);
    2900           0 :         sc->sc_ops.cancel_calib(sc->sc_ops.cookie);
    2901             : 
    2902           0 :         task_del(systq, &sc->init_task);
    2903             : 
    2904           0 :         splx(s);
    2905             : 
    2906           0 :         sc->sc_ops.stop(sc->sc_ops.cookie);
    2907           0 : }

Generated by: LCOV version 1.13