The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/dev/rtwn/rtl8192c/r92c_chan.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*      $OpenBSD: if_urtwn.c,v 1.16 2011/02/10 17:26:40 jakemsr Exp $   */
    2 
    3 /*-
    4  * Copyright (c) 2010 Damien Bergamini <damien.bergamini@free.fr>
    5  * Copyright (c) 2014 Kevin Lo <kevlo@FreeBSD.org>
    6  * Copyright (c) 2016 Andriy Voskoboinyk <avos@FreeBSD.org>
    7  *
    8  * Permission to use, copy, modify, and distribute this software for any
    9  * purpose with or without fee is hereby granted, provided that the above
   10  * copyright notice and this permission notice appear in all copies.
   11  *
   12  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
   13  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
   14  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
   15  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
   16  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
   17  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
   18  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
   19  */
   20 
   21 #include <sys/cdefs.h>
   22 __FBSDID("$FreeBSD$");
   23 
   24 #include "opt_wlan.h"
   25 
   26 #include <sys/param.h>
   27 #include <sys/lock.h>
   28 #include <sys/mutex.h>
   29 #include <sys/mbuf.h>
   30 #include <sys/kernel.h>
   31 #include <sys/socket.h>
   32 #include <sys/systm.h>
   33 #include <sys/malloc.h>
   34 #include <sys/queue.h>
   35 #include <sys/taskqueue.h>
   36 #include <sys/bus.h>
   37 #include <sys/endian.h>
   38 #include <sys/linker.h>
   39 
   40 #include <net/if.h>
   41 #include <net/ethernet.h>
   42 #include <net/if_media.h>
   43 
   44 #include <net80211/ieee80211_var.h>
   45 #include <net80211/ieee80211_radiotap.h>
   46 
   47 #include <dev/rtwn/if_rtwnreg.h>
   48 #include <dev/rtwn/if_rtwnvar.h>
   49 
   50 #include <dev/rtwn/if_rtwn_debug.h>
   51 #include <dev/rtwn/if_rtwn_ridx.h>
   52 
   53 #include <dev/rtwn/rtl8192c/r92c.h>
   54 #include <dev/rtwn/rtl8192c/r92c_priv.h>
   55 #include <dev/rtwn/rtl8192c/r92c_reg.h>
   56 #include <dev/rtwn/rtl8192c/r92c_var.h>
   57 
   58 static int
   59 r92c_get_power_group(struct rtwn_softc *sc, struct ieee80211_channel *c)
   60 {
   61         uint8_t chan;
   62         int group;
   63 
   64         chan = rtwn_chan2centieee(c);
   65         if (IEEE80211_IS_CHAN_2GHZ(c)) {
   66                 if (chan <= 3)                  group = 0;
   67                 else if (chan <= 9)             group = 1;
   68                 else if (chan <= 14)            group = 2;
   69                 else {
   70                         KASSERT(0, ("wrong 2GHz channel %d!\n", chan));
   71                         return (-1);
   72                 }
   73         } else {
   74                 KASSERT(0, ("wrong channel band (flags %08X)\n", c->ic_flags));
   75                 return (-1);
   76         }
   77 
   78         return (group);
   79 }
   80 
   81 /* XXX recheck */
   82 void
   83 r92c_get_txpower(struct rtwn_softc *sc, int chain,
   84     struct ieee80211_channel *c, uint8_t power[RTWN_RIDX_COUNT])
   85 {
   86         struct r92c_softc *rs = sc->sc_priv;
   87         struct rtwn_r92c_txpwr *rt = rs->rs_txpwr;
   88         const struct rtwn_r92c_txagc *base = rs->rs_txagc;
   89         uint8_t ofdmpow, htpow, diff, max;
   90         int max_mcs, ridx, group;
   91 
   92         /* Determine channel group. */
   93         group = r92c_get_power_group(sc, c);
   94         if (group == -1) {      /* shouldn't happen */
   95                 device_printf(sc->sc_dev, "%s: incorrect channel\n", __func__);
   96                 return;
   97         }
   98 
   99         /* XXX net80211 regulatory */
  100 
  101         max_mcs = RTWN_RIDX_HT_MCS(sc->ntxchains * 8 - 1);
  102         KASSERT(max_mcs <= RTWN_RIDX_COUNT, ("increase ridx limit\n"));
  103 
  104         if (rs->regulatory == 0) {
  105                 for (ridx = RTWN_RIDX_CCK1; ridx <= RTWN_RIDX_CCK11; ridx++)
  106                         power[ridx] = base[chain].pwr[0][ridx];
  107         }
  108         for (ridx = RTWN_RIDX_OFDM6; ridx < RTWN_RIDX_COUNT; ridx++) {
  109                 if (rs->regulatory == 3) {
  110                         power[ridx] = base[chain].pwr[0][ridx];
  111                         /* Apply vendor limits. */
  112                         if (IEEE80211_IS_CHAN_HT40(c))
  113                                 max = rt->ht40_max_pwr[chain][group];
  114                         else
  115                                 max = rt->ht20_max_pwr[chain][group];
  116                         if (power[ridx] > max)
  117                                 power[ridx] = max;
  118                 } else if (rs->regulatory == 1) {
  119                         if (!IEEE80211_IS_CHAN_HT40(c))
  120                                 power[ridx] = base[chain].pwr[group][ridx];
  121                 } else if (rs->regulatory != 2)
  122                         power[ridx] = base[chain].pwr[0][ridx];
  123         }
  124 
  125         /* Compute per-CCK rate Tx power. */
  126         for (ridx = RTWN_RIDX_CCK1; ridx <= RTWN_RIDX_CCK11; ridx++)
  127                 power[ridx] += rt->cck_tx_pwr[chain][group];
  128 
  129         htpow = rt->ht40_1s_tx_pwr[chain][group];
  130         if (sc->ntxchains > 1) {
  131                 /* Apply reduction for 2 spatial streams. */
  132                 diff = rt->ht40_2s_tx_pwr_diff[chain][group];
  133                 htpow = (htpow > diff) ? htpow - diff : 0;
  134         }
  135 
  136         /* Compute per-OFDM rate Tx power. */
  137         diff = rt->ofdm_tx_pwr_diff[chain][group];
  138         ofdmpow = htpow + diff; /* HT->OFDM correction. */
  139         for (ridx = RTWN_RIDX_OFDM6; ridx <= RTWN_RIDX_OFDM54; ridx++)
  140                 power[ridx] += ofdmpow;
  141 
  142         /* Compute per-MCS Tx power. */
  143         if (!IEEE80211_IS_CHAN_HT40(c)) {
  144                 diff = rt->ht20_tx_pwr_diff[chain][group];
  145                 htpow += diff;  /* HT40->HT20 correction. */
  146         }
  147         for (ridx = RTWN_RIDX_HT_MCS(0); ridx <= max_mcs; ridx++)
  148                 power[ridx] += htpow;
  149 
  150         /* Apply max limit. */
  151         for (ridx = RTWN_RIDX_CCK1; ridx <= max_mcs; ridx++) {
  152                 if (power[ridx] > R92C_MAX_TX_PWR)
  153                         power[ridx] = R92C_MAX_TX_PWR;
  154         }
  155 }
  156 
  157 void
  158 r92c_write_txpower(struct rtwn_softc *sc, int chain,
  159     uint8_t power[RTWN_RIDX_COUNT])
  160 {
  161         uint32_t reg;
  162 
  163         /* Write per-CCK rate Tx power. */
  164         if (chain == 0) {
  165                 reg = rtwn_bb_read(sc, R92C_TXAGC_A_CCK1_MCS32);
  166                 reg = RW(reg, R92C_TXAGC_A_CCK1,  power[RTWN_RIDX_CCK1]);
  167                 rtwn_bb_write(sc, R92C_TXAGC_A_CCK1_MCS32, reg);
  168                 reg = rtwn_bb_read(sc, R92C_TXAGC_B_CCK11_A_CCK2_11);
  169                 reg = RW(reg, R92C_TXAGC_A_CCK2,  power[RTWN_RIDX_CCK2]);
  170                 reg = RW(reg, R92C_TXAGC_A_CCK55, power[RTWN_RIDX_CCK55]);
  171                 reg = RW(reg, R92C_TXAGC_A_CCK11, power[RTWN_RIDX_CCK11]);
  172                 rtwn_bb_write(sc, R92C_TXAGC_B_CCK11_A_CCK2_11, reg);
  173         } else {
  174                 reg = rtwn_bb_read(sc, R92C_TXAGC_B_CCK1_55_MCS32);
  175                 reg = RW(reg, R92C_TXAGC_B_CCK1,  power[RTWN_RIDX_CCK1]);
  176                 reg = RW(reg, R92C_TXAGC_B_CCK2,  power[RTWN_RIDX_CCK2]);
  177                 reg = RW(reg, R92C_TXAGC_B_CCK55, power[RTWN_RIDX_CCK55]);
  178                 rtwn_bb_write(sc, R92C_TXAGC_B_CCK1_55_MCS32, reg);
  179                 reg = rtwn_bb_read(sc, R92C_TXAGC_B_CCK11_A_CCK2_11);
  180                 reg = RW(reg, R92C_TXAGC_B_CCK11, power[RTWN_RIDX_CCK11]);
  181                 rtwn_bb_write(sc, R92C_TXAGC_B_CCK11_A_CCK2_11, reg);
  182         }
  183         /* Write per-OFDM rate Tx power. */
  184         rtwn_bb_write(sc, R92C_TXAGC_RATE18_06(chain),
  185             SM(R92C_TXAGC_RATE06, power[RTWN_RIDX_OFDM6]) |
  186             SM(R92C_TXAGC_RATE09, power[RTWN_RIDX_OFDM9]) |
  187             SM(R92C_TXAGC_RATE12, power[RTWN_RIDX_OFDM12]) |
  188             SM(R92C_TXAGC_RATE18, power[RTWN_RIDX_OFDM18]));
  189         rtwn_bb_write(sc, R92C_TXAGC_RATE54_24(chain),
  190             SM(R92C_TXAGC_RATE24, power[RTWN_RIDX_OFDM24]) |
  191             SM(R92C_TXAGC_RATE36, power[RTWN_RIDX_OFDM36]) |
  192             SM(R92C_TXAGC_RATE48, power[RTWN_RIDX_OFDM48]) |
  193             SM(R92C_TXAGC_RATE54, power[RTWN_RIDX_OFDM54]));
  194         /* Write per-MCS Tx power. */
  195         rtwn_bb_write(sc, R92C_TXAGC_MCS03_MCS00(chain),
  196             SM(R92C_TXAGC_MCS00,  power[RTWN_RIDX_HT_MCS(0)]) |
  197             SM(R92C_TXAGC_MCS01,  power[RTWN_RIDX_HT_MCS(1)]) |
  198             SM(R92C_TXAGC_MCS02,  power[RTWN_RIDX_HT_MCS(2)]) |
  199             SM(R92C_TXAGC_MCS03,  power[RTWN_RIDX_HT_MCS(3)]));
  200         rtwn_bb_write(sc, R92C_TXAGC_MCS07_MCS04(chain),
  201             SM(R92C_TXAGC_MCS04,  power[RTWN_RIDX_HT_MCS(4)]) |
  202             SM(R92C_TXAGC_MCS05,  power[RTWN_RIDX_HT_MCS(5)]) |
  203             SM(R92C_TXAGC_MCS06,  power[RTWN_RIDX_HT_MCS(6)]) |
  204             SM(R92C_TXAGC_MCS07,  power[RTWN_RIDX_HT_MCS(7)]));
  205         if (sc->ntxchains >= 2) {
  206                 rtwn_bb_write(sc, R92C_TXAGC_MCS11_MCS08(chain),
  207                     SM(R92C_TXAGC_MCS08,  power[RTWN_RIDX_HT_MCS(8)]) |
  208                     SM(R92C_TXAGC_MCS09,  power[RTWN_RIDX_HT_MCS(9)]) |
  209                     SM(R92C_TXAGC_MCS10,  power[RTWN_RIDX_HT_MCS(10)]) |
  210                     SM(R92C_TXAGC_MCS11,  power[RTWN_RIDX_HT_MCS(11)]));
  211                 rtwn_bb_write(sc, R92C_TXAGC_MCS15_MCS12(chain),
  212                     SM(R92C_TXAGC_MCS12,  power[RTWN_RIDX_HT_MCS(12)]) |
  213                     SM(R92C_TXAGC_MCS13,  power[RTWN_RIDX_HT_MCS(13)]) |
  214                     SM(R92C_TXAGC_MCS14,  power[RTWN_RIDX_HT_MCS(14)]) |
  215                     SM(R92C_TXAGC_MCS15,  power[RTWN_RIDX_HT_MCS(15)]));
  216         }
  217 }
  218 
  219 static void
  220 r92c_set_txpower(struct rtwn_softc *sc, struct ieee80211_channel *c)
  221 {
  222         uint8_t power[RTWN_RIDX_COUNT];
  223         int i;
  224 
  225         for (i = 0; i < sc->ntxchains; i++) {
  226                 memset(power, 0, sizeof(power));
  227                 /* Compute per-rate Tx power values. */
  228                 rtwn_r92c_get_txpower(sc, i, c, power);
  229 #ifdef RTWN_DEBUG
  230                 if (sc->sc_debug & RTWN_DEBUG_TXPWR) {
  231                         int max_mcs, ridx;
  232 
  233                         max_mcs = RTWN_RIDX_HT_MCS(sc->ntxchains * 8 - 1);
  234 
  235                         /* Dump per-rate Tx power values. */
  236                         printf("Tx power for chain %d:\n", i);
  237                         for (ridx = RTWN_RIDX_CCK1; ridx <= max_mcs; ridx++)
  238                                 printf("Rate %d = %u\n", ridx, power[ridx]);
  239                 }
  240 #endif
  241                 /* Write per-rate Tx power values to hardware. */
  242                 r92c_write_txpower(sc, i, power);
  243         }
  244 }
  245 
  246 static void
  247 r92c_set_bw40(struct rtwn_softc *sc, uint8_t chan, int prichlo)
  248 {
  249         struct r92c_softc *rs = sc->sc_priv;
  250 
  251         rtwn_setbits_1(sc, R92C_BWOPMODE, R92C_BWOPMODE_20MHZ, 0);
  252         rtwn_setbits_1(sc, R92C_RRSR + 2, 0x6f, (prichlo ? 1 : 2) << 5);
  253 
  254         rtwn_bb_setbits(sc, R92C_FPGA0_RFMOD, 0, R92C_RFMOD_40MHZ);
  255         rtwn_bb_setbits(sc, R92C_FPGA1_RFMOD, 0, R92C_RFMOD_40MHZ);
  256 
  257         /* Set CCK side band. */
  258         rtwn_bb_setbits(sc, R92C_CCK0_SYSTEM, 0x10,
  259             (prichlo ? 0 : 1) << 4);
  260 
  261         rtwn_bb_setbits(sc, R92C_OFDM1_LSTF, 0x0c00,
  262             (prichlo ? 1 : 2) << 10);
  263 
  264         rtwn_bb_setbits(sc, R92C_FPGA0_ANAPARAM2,
  265             R92C_FPGA0_ANAPARAM2_CBW20, 0);
  266 
  267         rtwn_bb_setbits(sc, 0x818, 0x0c000000, (prichlo ? 2 : 1) << 26);
  268 
  269         /* Select 40MHz bandwidth. */
  270         rtwn_rf_write(sc, 0, R92C_RF_CHNLBW,
  271             (rs->rf_chnlbw[0] & ~0xfff) | chan);
  272 }
  273 
  274 void
  275 r92c_set_bw20(struct rtwn_softc *sc, uint8_t chan)
  276 {
  277         struct r92c_softc *rs = sc->sc_priv;
  278 
  279         rtwn_setbits_1(sc, R92C_BWOPMODE, 0, R92C_BWOPMODE_20MHZ);
  280 
  281         rtwn_bb_setbits(sc, R92C_FPGA0_RFMOD, R92C_RFMOD_40MHZ, 0);
  282         rtwn_bb_setbits(sc, R92C_FPGA1_RFMOD, R92C_RFMOD_40MHZ, 0);
  283 
  284         rtwn_bb_setbits(sc, R92C_FPGA0_ANAPARAM2, 0,
  285             R92C_FPGA0_ANAPARAM2_CBW20);
  286 
  287         /* Select 20MHz bandwidth. */
  288         rtwn_rf_write(sc, 0, R92C_RF_CHNLBW,
  289             (rs->rf_chnlbw[0] & ~0xfff) | chan | R92C_RF_CHNLBW_BW20);
  290 }
  291 
  292 void
  293 r92c_set_chan(struct rtwn_softc *sc, struct ieee80211_channel *c)
  294 {
  295         struct r92c_softc *rs = sc->sc_priv;
  296         u_int chan;
  297         int i;
  298 
  299         chan = rtwn_chan2centieee(c);
  300 
  301         /* Set Tx power for this new channel. */
  302         r92c_set_txpower(sc, c);
  303 
  304         for (i = 0; i < sc->nrxchains; i++) {
  305                 rtwn_rf_write(sc, i, R92C_RF_CHNLBW,
  306                     RW(rs->rf_chnlbw[i], R92C_RF_CHNLBW_CHNL, chan));
  307         }
  308         if (IEEE80211_IS_CHAN_HT40(c))
  309                 r92c_set_bw40(sc, chan, IEEE80211_IS_CHAN_HT40U(c));
  310         else
  311                 rtwn_r92c_set_bw20(sc, chan);
  312 }
  313 
  314 void
  315 r92c_set_gain(struct rtwn_softc *sc, uint8_t gain)
  316 {
  317 
  318         rtwn_bb_setbits(sc, R92C_OFDM0_AGCCORE1(0),
  319             R92C_OFDM0_AGCCORE1_GAIN_M, gain);
  320         rtwn_bb_setbits(sc, R92C_OFDM0_AGCCORE1(1),
  321             R92C_OFDM0_AGCCORE1_GAIN_M, gain);
  322 }
  323 
  324 void
  325 r92c_scan_start(struct ieee80211com *ic)
  326 {
  327         struct rtwn_softc *sc = ic->ic_softc;
  328         struct r92c_softc *rs = sc->sc_priv;
  329 
  330         RTWN_LOCK(sc);
  331         /* Set gain for scanning. */
  332         rtwn_r92c_set_gain(sc, 0x20);
  333         RTWN_UNLOCK(sc);
  334 
  335         rs->rs_scan_start(ic);
  336 }
  337 
  338 void
  339 r92c_scan_end(struct ieee80211com *ic)
  340 {
  341         struct rtwn_softc *sc = ic->ic_softc;
  342         struct r92c_softc *rs = sc->sc_priv;
  343 
  344         RTWN_LOCK(sc);
  345         /* Set gain under link. */
  346         rtwn_r92c_set_gain(sc, 0x32);
  347         RTWN_UNLOCK(sc);
  348 
  349         rs->rs_scan_end(ic);
  350 }

Cache object: da272b617c86d221126651093db24251


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.