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/ath/ath_hal/ar5212/ar5212_reset.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 /*-
    2  * SPDX-License-Identifier: ISC
    3  *
    4  * Copyright (c) 2002-2009 Sam Leffler, Errno Consulting
    5  * Copyright (c) 2002-2008 Atheros Communications, Inc.
    6  *
    7  * Permission to use, copy, modify, and/or 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  * $FreeBSD$
   20  */
   21 #include "opt_ah.h"
   22 
   23 #include "ah.h"
   24 #include "ah_internal.h"
   25 #include "ah_devid.h"
   26 
   27 #include "ar5212/ar5212.h"
   28 #include "ar5212/ar5212reg.h"
   29 #include "ar5212/ar5212phy.h"
   30 
   31 #include "ah_eeprom_v3.h"
   32 
   33 /* Additional Time delay to wait after activiting the Base band */
   34 #define BASE_ACTIVATE_DELAY     100     /* 100 usec */
   35 #define PLL_SETTLE_DELAY        300     /* 300 usec */
   36 
   37 static HAL_BOOL ar5212SetResetReg(struct ath_hal *, uint32_t resetMask);
   38 /* NB: public for 5312 use */
   39 HAL_BOOL        ar5212IsSpurChannel(struct ath_hal *,
   40                     const struct ieee80211_channel *);
   41 HAL_BOOL        ar5212ChannelChange(struct ath_hal *,
   42                     const struct ieee80211_channel *);
   43 int16_t         ar5212GetNf(struct ath_hal *, struct ieee80211_channel *);
   44 HAL_BOOL        ar5212SetBoardValues(struct ath_hal *,
   45                     const struct ieee80211_channel *);
   46 void            ar5212SetDeltaSlope(struct ath_hal *,
   47                     const struct ieee80211_channel *);
   48 HAL_BOOL        ar5212SetTransmitPower(struct ath_hal *ah,
   49                    const struct ieee80211_channel *chan, uint16_t *rfXpdGain);
   50 static HAL_BOOL ar5212SetRateTable(struct ath_hal *, 
   51                    const struct ieee80211_channel *, int16_t tpcScaleReduction,
   52                    int16_t powerLimit,
   53                    HAL_BOOL commit, int16_t *minPower, int16_t *maxPower);
   54 static void ar5212CorrectGainDelta(struct ath_hal *, int twiceOfdmCckDelta);
   55 static void ar5212GetTargetPowers(struct ath_hal *,
   56                    const struct ieee80211_channel *,
   57                    const TRGT_POWER_INFO *pPowerInfo, uint16_t numChannels,
   58                    TRGT_POWER_INFO *pNewPower);
   59 static uint16_t ar5212GetMaxEdgePower(uint16_t channel,
   60                    const RD_EDGES_POWER  *pRdEdgesPower);
   61 void            ar5212SetRateDurationTable(struct ath_hal *,
   62                     const struct ieee80211_channel *);
   63 void            ar5212SetIFSTiming(struct ath_hal *,
   64                     const struct ieee80211_channel *);
   65 
   66 /* NB: public for RF backend use */
   67 void            ar5212GetLowerUpperValues(uint16_t value,
   68                    uint16_t *pList, uint16_t listSize,
   69                    uint16_t *pLowerValue, uint16_t *pUpperValue);
   70 void            ar5212ModifyRfBuffer(uint32_t *rfBuf, uint32_t reg32,
   71                    uint32_t numBits, uint32_t firstBit, uint32_t column);
   72 
   73 static int
   74 write_common(struct ath_hal *ah, const HAL_INI_ARRAY *ia,
   75         HAL_BOOL bChannelChange, int writes)
   76 {
   77 #define IS_NO_RESET_TIMER_ADDR(x)                      \
   78     ( (((x) >= AR_BEACON) && ((x) <= AR_CFP_DUR)) || \
   79       (((x) >= AR_SLEEP1) && ((x) <= AR_SLEEP3)))
   80 #define V(r, c) (ia)->data[((r)*(ia)->cols) + (c)]
   81         int r;
   82 
   83         /* Write Common Array Parameters */
   84         for (r = 0; r < ia->rows; r++) {
   85                 uint32_t reg = V(r, 0);
   86                 /* XXX timer/beacon setup registers? */
   87                 /* On channel change, don't reset the PCU registers */
   88                 if (!(bChannelChange && IS_NO_RESET_TIMER_ADDR(reg))) {
   89                         OS_REG_WRITE(ah, reg, V(r, 1));
   90                         DMA_YIELD(writes);
   91                 }
   92         }
   93         return writes;
   94 #undef IS_NO_RESET_TIMER_ADDR
   95 #undef V
   96 }
   97 
   98 #define IS_DISABLE_FAST_ADC_CHAN(x) (((x) == 2462) || ((x) == 2467))
   99 
  100 /*
  101  * XXX NDIS 5.x code had MAX_RESET_WAIT set to 2000 for AP code
  102  * and 10 for Client code
  103  */
  104 #define MAX_RESET_WAIT                  10
  105 
  106 #define TX_QUEUEPEND_CHECK              1
  107 #define TX_ENABLE_CHECK                 2
  108 #define RX_ENABLE_CHECK                 4
  109 
  110 /*
  111  * Places the device in and out of reset and then places sane
  112  * values in the registers based on EEPROM config, initialization
  113  * vectors (as determined by the mode), and station configuration
  114  *
  115  * bChannelChange is used to preserve DMA/PCU registers across
  116  * a HW Reset during channel change.
  117  */
  118 HAL_BOOL
  119 ar5212Reset(struct ath_hal *ah, HAL_OPMODE opmode,
  120         struct ieee80211_channel *chan,
  121         HAL_BOOL bChannelChange,
  122         HAL_RESET_TYPE resetType,
  123         HAL_STATUS *status)
  124 {
  125 #define N(a)    (sizeof (a) / sizeof (a[0]))
  126 #define FAIL(_code)     do { ecode = _code; goto bad; } while (0)
  127         struct ath_hal_5212 *ahp = AH5212(ah);
  128         HAL_CHANNEL_INTERNAL *ichan = AH_NULL;
  129         const HAL_EEPROM *ee;
  130         uint32_t softLedCfg, softLedState;
  131         uint32_t saveFrameSeqCount, saveDefAntenna, saveLedState;
  132         uint32_t macStaId1, synthDelay, txFrm2TxDStart;
  133         uint16_t rfXpdGain[MAX_NUM_PDGAINS_PER_CHANNEL];
  134         int16_t cckOfdmPwrDelta = 0;
  135         u_int modesIndex, freqIndex;
  136         HAL_STATUS ecode;
  137         int i, regWrites;
  138         uint32_t testReg, powerVal;
  139         int8_t twiceAntennaGain, twiceAntennaReduction;
  140         uint32_t ackTpcPow, ctsTpcPow, chirpTpcPow;
  141         HAL_BOOL isBmode = AH_FALSE;
  142 
  143         HALASSERT(ah->ah_magic == AR5212_MAGIC);
  144         ee = AH_PRIVATE(ah)->ah_eeprom;
  145 
  146         OS_MARK(ah, AH_MARK_RESET, bChannelChange);
  147 
  148         /* Bring out of sleep mode */
  149         if (!ar5212SetPowerMode(ah, HAL_PM_AWAKE, AH_TRUE)) {
  150                 HALDEBUG(ah, HAL_DEBUG_ANY, "%s: chip did not wakeup\n",
  151                     __func__);
  152                 FAIL(HAL_EIO);
  153         }
  154 
  155         /*
  156          * Map public channel to private.
  157          */
  158         ichan = ath_hal_checkchannel(ah, chan);
  159         if (ichan == AH_NULL)
  160                 FAIL(HAL_EINVAL);
  161         switch (opmode) {
  162         case HAL_M_STA:
  163         case HAL_M_IBSS:
  164         case HAL_M_HOSTAP:
  165         case HAL_M_MONITOR:
  166                 break;
  167         default:
  168                 HALDEBUG(ah, HAL_DEBUG_ANY, "%s: invalid operating mode %u\n",
  169                     __func__, opmode);
  170                 FAIL(HAL_EINVAL);
  171                 break;
  172         }
  173         HALASSERT(AH_PRIVATE(ah)->ah_eeversion >= AR_EEPROM_VER3);
  174 
  175         SAVE_CCK(ah, chan, isBmode);
  176 
  177         /* Preserve certain DMA hardware registers on a channel change */
  178         if (bChannelChange) {
  179                 /*
  180                  * On Venice, the TSF is almost preserved across a reset;
  181                  * it requires doubling writes to the RESET_TSF
  182                  * bit in the AR_BEACON register; it also has the quirk
  183                  * of the TSF going back in time on the station (station
  184                  * latches onto the last beacon's tsf during a reset 50%
  185                  * of the times); the latter is not a problem for adhoc
  186                  * stations since as long as the TSF is behind, it will
  187                  * get resynchronized on receiving the next beacon; the
  188                  * TSF going backwards in time could be a problem for the
  189                  * sleep operation (supported on infrastructure stations
  190                  * only) - the best and most general fix for this situation
  191                  * is to resynchronize the various sleep/beacon timers on
  192                  * the receipt of the next beacon i.e. when the TSF itself
  193                  * gets resynchronized to the AP's TSF - power save is
  194                  * needed to be temporarily disabled until that time
  195                  *
  196                  * Need to save the sequence number to restore it after
  197                  * the reset!
  198                  */
  199                 saveFrameSeqCount = OS_REG_READ(ah, AR_D_SEQNUM);
  200         } else
  201                 saveFrameSeqCount = 0;          /* NB: silence compiler */
  202 
  203         /* Blank the channel survey statistics */
  204         ath_hal_survey_clear(ah);
  205 
  206 #if 0
  207         /*
  208          * XXX disable for now; this appears to sometimes cause OFDM
  209          * XXX timing error floods when ani is enabled and bg scanning
  210          * XXX kicks in
  211          */
  212         /* If the channel change is across the same mode - perform a fast channel change */
  213         if (IS_2413(ah) || IS_5413(ah)) {
  214                 /*
  215                  * Fast channel change can only be used when:
  216                  *  -channel change requested - so it's not the initial reset.
  217                  *  -it's not a change to the current channel -
  218                  *      often called when switching modes on a channel
  219                  *  -the modes of the previous and requested channel are the
  220                  *      same
  221                  * XXX opmode shouldn't change either?
  222                  */
  223                 if (bChannelChange &&
  224                     (AH_PRIVATE(ah)->ah_curchan != AH_NULL) &&
  225                     (chan->ic_freq != AH_PRIVATE(ah)->ah_curchan->ic_freq) &&
  226                     ((chan->ic_flags & IEEE80211_CHAN_ALLTURBO) ==
  227                      (AH_PRIVATE(ah)->ah_curchan->ic_flags & IEEE80211_CHAN_ALLTURBO))) {
  228                         if (ar5212ChannelChange(ah, chan)) {
  229                                 /* If ChannelChange completed - skip the rest of reset */
  230                                 /* XXX ani? */
  231                                 goto done;
  232                         }
  233                 }
  234         }
  235 #endif
  236         /*
  237          * Preserve the antenna on a channel change
  238          */
  239         saveDefAntenna = OS_REG_READ(ah, AR_DEF_ANTENNA);
  240         if (saveDefAntenna == 0)                /* XXX magic constants */
  241                 saveDefAntenna = 1;
  242 
  243         /* Save hardware flag before chip reset clears the register */
  244         macStaId1 = OS_REG_READ(ah, AR_STA_ID1) & 
  245                 (AR_STA_ID1_BASE_RATE_11B | AR_STA_ID1_USE_DEFANT);
  246 
  247         /* Save led state from pci config register */
  248         saveLedState = OS_REG_READ(ah, AR_PCICFG) &
  249                 (AR_PCICFG_LEDCTL | AR_PCICFG_LEDMODE | AR_PCICFG_LEDBLINK |
  250                  AR_PCICFG_LEDSLOW);
  251         softLedCfg = OS_REG_READ(ah, AR_GPIOCR);
  252         softLedState = OS_REG_READ(ah, AR_GPIODO);
  253 
  254         ar5212RestoreClock(ah, opmode);         /* move to refclk operation */
  255 
  256         /*
  257          * Adjust gain parameters before reset if
  258          * there's an outstanding gain updated.
  259          */
  260         (void) ar5212GetRfgain(ah);
  261 
  262         if (!ar5212ChipReset(ah, chan)) {
  263                 HALDEBUG(ah, HAL_DEBUG_ANY, "%s: chip reset failed\n", __func__);
  264                 FAIL(HAL_EIO);
  265         }
  266 
  267         /* Setup the indices for the next set of register array writes */
  268         if (IEEE80211_IS_CHAN_2GHZ(chan)) {
  269                 freqIndex  = 2;
  270                 if (IEEE80211_IS_CHAN_108G(chan))
  271                         modesIndex = 5;
  272                 else if (IEEE80211_IS_CHAN_G(chan))
  273                         modesIndex = 4;
  274                 else if (IEEE80211_IS_CHAN_B(chan))
  275                         modesIndex = 3;
  276                 else {
  277                         HALDEBUG(ah, HAL_DEBUG_ANY,
  278                             "%s: invalid channel %u/0x%x\n",
  279                             __func__, chan->ic_freq, chan->ic_flags);
  280                         FAIL(HAL_EINVAL);
  281                 }
  282         } else {
  283                 freqIndex  = 1;
  284                 if (IEEE80211_IS_CHAN_TURBO(chan))
  285                         modesIndex = 2;
  286                 else if (IEEE80211_IS_CHAN_A(chan))
  287                         modesIndex = 1;
  288                 else {
  289                         HALDEBUG(ah, HAL_DEBUG_ANY,
  290                             "%s: invalid channel %u/0x%x\n",
  291                             __func__, chan->ic_freq, chan->ic_flags);
  292                         FAIL(HAL_EINVAL);
  293                 }
  294         }
  295 
  296         OS_MARK(ah, AH_MARK_RESET_LINE, __LINE__);
  297 
  298         /* Set correct Baseband to analog shift setting to access analog chips. */
  299         OS_REG_WRITE(ah, AR_PHY(0), 0x00000007);
  300 
  301         regWrites = ath_hal_ini_write(ah, &ahp->ah_ini_modes, modesIndex, 0);
  302         regWrites = write_common(ah, &ahp->ah_ini_common, bChannelChange,
  303                 regWrites);
  304 #ifdef AH_RXCFG_SDMAMW_4BYTES
  305         /*
  306          * Nala doesn't work with 128 byte bursts on pb42(hydra) (ar71xx),
  307          * use 4 instead.  Enabling it on all platforms would hurt performance,
  308          * so we only enable it on the ones that are affected by it.
  309          */
  310         OS_REG_WRITE(ah, AR_RXCFG, 0);
  311 #endif
  312         ahp->ah_rfHal->writeRegs(ah, modesIndex, freqIndex, regWrites);
  313 
  314         OS_MARK(ah, AH_MARK_RESET_LINE, __LINE__);
  315 
  316         if (IEEE80211_IS_CHAN_HALF(chan) || IEEE80211_IS_CHAN_QUARTER(chan)) {
  317                 ar5212SetIFSTiming(ah, chan);
  318                 if (IS_5413(ah)) {
  319                         /*
  320                          * Force window_length for 1/2 and 1/4 rate channels,
  321                          * the ini file sets this to zero otherwise.
  322                          */
  323                         OS_REG_RMW_FIELD(ah, AR_PHY_FRAME_CTL,
  324                                 AR_PHY_FRAME_CTL_WINLEN, 3);
  325                 }
  326         }
  327 
  328         /* Overwrite INI values for revised chipsets */
  329         if (AH_PRIVATE(ah)->ah_phyRev >= AR_PHY_CHIP_ID_REV_2) {
  330                 /* ADC_CTL */
  331                 OS_REG_WRITE(ah, AR_PHY_ADC_CTL,
  332                         SM(2, AR_PHY_ADC_CTL_OFF_INBUFGAIN) |
  333                         SM(2, AR_PHY_ADC_CTL_ON_INBUFGAIN) |
  334                         AR_PHY_ADC_CTL_OFF_PWDDAC |
  335                         AR_PHY_ADC_CTL_OFF_PWDADC);
  336 
  337                 /* TX_PWR_ADJ */
  338                 if (ichan->channel == 2484) {
  339                         cckOfdmPwrDelta = SCALE_OC_DELTA(
  340                             ee->ee_cckOfdmPwrDelta -
  341                             ee->ee_scaledCh14FilterCckDelta);
  342                 } else {
  343                         cckOfdmPwrDelta = SCALE_OC_DELTA(
  344                             ee->ee_cckOfdmPwrDelta);
  345                 }
  346 
  347                 if (IEEE80211_IS_CHAN_G(chan)) {
  348                     OS_REG_WRITE(ah, AR_PHY_TXPWRADJ,
  349                         SM((ee->ee_cckOfdmPwrDelta*-1),
  350                             AR_PHY_TXPWRADJ_CCK_GAIN_DELTA) |
  351                         SM((cckOfdmPwrDelta*-1),
  352                             AR_PHY_TXPWRADJ_CCK_PCDAC_INDEX));
  353                 } else {
  354                         OS_REG_WRITE(ah, AR_PHY_TXPWRADJ, 0);
  355                 }
  356 
  357                 /* Add barker RSSI thresh enable as disabled */
  358                 OS_REG_CLR_BIT(ah, AR_PHY_DAG_CTRLCCK,
  359                         AR_PHY_DAG_CTRLCCK_EN_RSSI_THR);
  360                 OS_REG_RMW_FIELD(ah, AR_PHY_DAG_CTRLCCK,
  361                         AR_PHY_DAG_CTRLCCK_RSSI_THR, 2);
  362 
  363                 /* Set the mute mask to the correct default */
  364                 OS_REG_WRITE(ah, AR_SEQ_MASK, 0x0000000F);
  365         }
  366 
  367         if (AH_PRIVATE(ah)->ah_phyRev >= AR_PHY_CHIP_ID_REV_3) {
  368                 /* Clear reg to alllow RX_CLEAR line debug */
  369                 OS_REG_WRITE(ah, AR_PHY_BLUETOOTH,  0);
  370         }
  371         if (AH_PRIVATE(ah)->ah_phyRev >= AR_PHY_CHIP_ID_REV_4) {
  372 #ifdef notyet
  373                 /* Enable burst prefetch for the data queues */
  374                 OS_REG_RMW_FIELD(ah, AR_D_FPCTL, ... );
  375                 /* Enable double-buffering */
  376                 OS_REG_CLR_BIT(ah, AR_TXCFG, AR_TXCFG_DBL_BUF_DIS);
  377 #endif
  378         }
  379 
  380         /* Set ADC/DAC select values */
  381         OS_REG_WRITE(ah, AR_PHY_SLEEP_SCAL, 0x0e);
  382 
  383         if (IS_5413(ah) || IS_2417(ah)) {
  384                 uint32_t newReg = 1;
  385                 if (IS_DISABLE_FAST_ADC_CHAN(ichan->channel))
  386                         newReg = 0;
  387                 /* As it's a clock changing register, only write when the value needs to be changed */
  388                 if (OS_REG_READ(ah, AR_PHY_FAST_ADC) != newReg)
  389                         OS_REG_WRITE(ah, AR_PHY_FAST_ADC, newReg);
  390         }
  391 
  392         /* Setup the transmit power values. */
  393         if (!ar5212SetTransmitPower(ah, chan, rfXpdGain)) {
  394                 HALDEBUG(ah, HAL_DEBUG_ANY,
  395                     "%s: error init'ing transmit power\n", __func__);
  396                 FAIL(HAL_EIO);
  397         }
  398 
  399         /* Write the analog registers */
  400         if (!ahp->ah_rfHal->setRfRegs(ah, chan, modesIndex, rfXpdGain)) {
  401                 HALDEBUG(ah, HAL_DEBUG_ANY, "%s: ar5212SetRfRegs failed\n",
  402                     __func__);
  403                 FAIL(HAL_EIO);
  404         }
  405 
  406         /* Write delta slope for OFDM enabled modes (A, G, Turbo) */
  407         if (IEEE80211_IS_CHAN_OFDM(chan)) {
  408                 if (IS_5413(ah) ||
  409                     AH_PRIVATE(ah)->ah_eeversion >= AR_EEPROM_VER5_3)
  410                         ar5212SetSpurMitigation(ah, chan);
  411                 ar5212SetDeltaSlope(ah, chan);
  412         }
  413 
  414         /* Setup board specific options for EEPROM version 3 */
  415         if (!ar5212SetBoardValues(ah, chan)) {
  416                 HALDEBUG(ah, HAL_DEBUG_ANY,
  417                     "%s: error setting board options\n", __func__);
  418                 FAIL(HAL_EIO);
  419         }
  420 
  421         /* Restore certain DMA hardware registers on a channel change */
  422         if (bChannelChange)
  423                 OS_REG_WRITE(ah, AR_D_SEQNUM, saveFrameSeqCount);
  424 
  425         OS_MARK(ah, AH_MARK_RESET_LINE, __LINE__);
  426 
  427         OS_REG_WRITE(ah, AR_STA_ID0, LE_READ_4(ahp->ah_macaddr));
  428         OS_REG_WRITE(ah, AR_STA_ID1, LE_READ_2(ahp->ah_macaddr + 4)
  429                 | macStaId1
  430                 | AR_STA_ID1_RTS_USE_DEF
  431                 | ahp->ah_staId1Defaults
  432         );
  433         ar5212SetOperatingMode(ah, opmode);
  434 
  435         /* Set Venice BSSID mask according to current state */
  436         OS_REG_WRITE(ah, AR_BSSMSKL, LE_READ_4(ahp->ah_bssidmask));
  437         OS_REG_WRITE(ah, AR_BSSMSKU, LE_READ_2(ahp->ah_bssidmask + 4));
  438 
  439         /* Restore previous led state */
  440         OS_REG_WRITE(ah, AR_PCICFG, OS_REG_READ(ah, AR_PCICFG) | saveLedState);
  441 
  442         /* Restore soft Led state to GPIO */
  443         OS_REG_WRITE(ah, AR_GPIOCR, softLedCfg);
  444         OS_REG_WRITE(ah, AR_GPIODO, softLedState);
  445 
  446         /* Restore previous antenna */
  447         OS_REG_WRITE(ah, AR_DEF_ANTENNA, saveDefAntenna);
  448 
  449         /* then our BSSID and associate id */
  450         OS_REG_WRITE(ah, AR_BSS_ID0, LE_READ_4(ahp->ah_bssid));
  451         OS_REG_WRITE(ah, AR_BSS_ID1, LE_READ_2(ahp->ah_bssid + 4) |
  452             (ahp->ah_assocId & 0x3fff) << AR_BSS_ID1_AID_S);
  453 
  454         /* Restore bmiss rssi & count thresholds */
  455         OS_REG_WRITE(ah, AR_RSSI_THR, ahp->ah_rssiThr);
  456 
  457         OS_REG_WRITE(ah, AR_ISR, ~0);           /* cleared on write */
  458 
  459         if (!ar5212SetChannel(ah, chan))
  460                 FAIL(HAL_EIO);
  461 
  462         OS_MARK(ah, AH_MARK_RESET_LINE, __LINE__);
  463 
  464         ar5212SetCoverageClass(ah, AH_PRIVATE(ah)->ah_coverageClass, 1);
  465 
  466         ar5212SetRateDurationTable(ah, chan);
  467 
  468         /* Set Tx frame start to tx data start delay */
  469         if (IS_RAD5112_ANY(ah) &&
  470             (IEEE80211_IS_CHAN_HALF(chan) || IEEE80211_IS_CHAN_QUARTER(chan))) {
  471                 txFrm2TxDStart = 
  472                         IEEE80211_IS_CHAN_HALF(chan) ?
  473                                         TX_FRAME_D_START_HALF_RATE:
  474                                         TX_FRAME_D_START_QUARTER_RATE;
  475                 OS_REG_RMW_FIELD(ah, AR_PHY_TX_CTL, 
  476                         AR_PHY_TX_FRAME_TO_TX_DATA_START, txFrm2TxDStart);
  477         }
  478 
  479         /*
  480          * Setup fast diversity.
  481          * Fast diversity can be enabled or disabled via regadd.txt.
  482          * Default is enabled.
  483          * For reference,
  484          *    Disable: reg        val
  485          *             0x00009860 0x00009d18 (if 11a / 11g, else no change)
  486          *             0x00009970 0x192bb514
  487          *             0x0000a208 0xd03e4648
  488          *
  489          *    Enable:  0x00009860 0x00009d10 (if 11a / 11g, else no change)
  490          *             0x00009970 0x192fb514
  491          *             0x0000a208 0xd03e6788
  492          */
  493 
  494         /* XXX Setup pre PHY ENABLE EAR additions */
  495         /*
  496          * Wait for the frequency synth to settle (synth goes on
  497          * via AR_PHY_ACTIVE_EN).  Read the phy active delay register.
  498          * Value is in 100ns increments.
  499          */
  500         synthDelay = OS_REG_READ(ah, AR_PHY_RX_DELAY) & AR_PHY_RX_DELAY_DELAY;
  501         if (IEEE80211_IS_CHAN_B(chan)) {
  502                 synthDelay = (4 * synthDelay) / 22;
  503         } else {
  504                 synthDelay /= 10;
  505         }
  506 
  507         /* Activate the PHY (includes baseband activate and synthesizer on) */
  508         OS_REG_WRITE(ah, AR_PHY_ACTIVE, AR_PHY_ACTIVE_EN);
  509 
  510         /* 
  511          * There is an issue if the AP starts the calibration before
  512          * the base band timeout completes.  This could result in the
  513          * rx_clear false triggering.  As a workaround we add delay an
  514          * extra BASE_ACTIVATE_DELAY usecs to ensure this condition
  515          * does not happen.
  516          */
  517         if (IEEE80211_IS_CHAN_HALF(chan)) {
  518                 OS_DELAY((synthDelay << 1) + BASE_ACTIVATE_DELAY);
  519         } else if (IEEE80211_IS_CHAN_QUARTER(chan)) {
  520                 OS_DELAY((synthDelay << 2) + BASE_ACTIVATE_DELAY);
  521         } else {
  522                 OS_DELAY(synthDelay + BASE_ACTIVATE_DELAY);
  523         }
  524 
  525         /*
  526          * The udelay method is not reliable with notebooks.
  527          * Need to check to see if the baseband is ready
  528          */
  529         testReg = OS_REG_READ(ah, AR_PHY_TESTCTRL);
  530         /* Selects the Tx hold */
  531         OS_REG_WRITE(ah, AR_PHY_TESTCTRL, AR_PHY_TESTCTRL_TXHOLD);
  532         i = 0;
  533         while ((i++ < 20) &&
  534                (OS_REG_READ(ah, 0x9c24) & 0x10)) /* test if baseband not ready */               OS_DELAY(200);
  535         OS_REG_WRITE(ah, AR_PHY_TESTCTRL, testReg);
  536 
  537         /* Calibrate the AGC and start a NF calculation */
  538         OS_REG_WRITE(ah, AR_PHY_AGC_CONTROL,
  539                   OS_REG_READ(ah, AR_PHY_AGC_CONTROL)
  540                 | AR_PHY_AGC_CONTROL_CAL
  541                 | AR_PHY_AGC_CONTROL_NF);
  542 
  543         if (!IEEE80211_IS_CHAN_B(chan) && ahp->ah_bIQCalibration != IQ_CAL_DONE) {
  544                 /* Start IQ calibration w/ 2^(INIT_IQCAL_LOG_COUNT_MAX+1) samples */
  545                 OS_REG_RMW_FIELD(ah, AR_PHY_TIMING_CTRL4, 
  546                         AR_PHY_TIMING_CTRL4_IQCAL_LOG_COUNT_MAX,
  547                         INIT_IQCAL_LOG_COUNT_MAX);
  548                 OS_REG_SET_BIT(ah, AR_PHY_TIMING_CTRL4,
  549                         AR_PHY_TIMING_CTRL4_DO_IQCAL);
  550                 ahp->ah_bIQCalibration = IQ_CAL_RUNNING;
  551         } else
  552                 ahp->ah_bIQCalibration = IQ_CAL_INACTIVE;
  553 
  554         /* Setup compression registers */
  555         ar5212SetCompRegs(ah);
  556 
  557         /* Set 1:1 QCU to DCU mapping for all queues */
  558         for (i = 0; i < AR_NUM_DCU; i++)
  559                 OS_REG_WRITE(ah, AR_DQCUMASK(i), 1 << i);
  560 
  561         ahp->ah_intrTxqs = 0;
  562         for (i = 0; i < AH_PRIVATE(ah)->ah_caps.halTotalQueues; i++)
  563                 ar5212ResetTxQueue(ah, i);
  564 
  565         /*
  566          * Setup interrupt handling.  Note that ar5212ResetTxQueue
  567          * manipulates the secondary IMR's as queues are enabled
  568          * and disabled.  This is done with RMW ops to insure the
  569          * settings we make here are preserved.
  570          */
  571         ahp->ah_maskReg = AR_IMR_TXOK | AR_IMR_TXERR | AR_IMR_TXURN
  572                         | AR_IMR_RXOK | AR_IMR_RXERR | AR_IMR_RXORN
  573                         | AR_IMR_HIUERR
  574                         ;
  575         if (opmode == HAL_M_HOSTAP)
  576                 ahp->ah_maskReg |= AR_IMR_MIB;
  577         OS_REG_WRITE(ah, AR_IMR, ahp->ah_maskReg);
  578         /* Enable bus errors that are OR'd to set the HIUERR bit */
  579         OS_REG_WRITE(ah, AR_IMR_S2,
  580                 OS_REG_READ(ah, AR_IMR_S2)
  581                 | AR_IMR_S2_MCABT | AR_IMR_S2_SSERR | AR_IMR_S2_DPERR);
  582 
  583         if (AH_PRIVATE(ah)->ah_rfkillEnabled)
  584                 ar5212EnableRfKill(ah);
  585 
  586         if (!ath_hal_wait(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_CAL, 0)) {
  587                 HALDEBUG(ah, HAL_DEBUG_ANY,
  588                     "%s: offset calibration failed to complete in 1ms;"
  589                     " noisy environment?\n", __func__);
  590         }
  591 
  592         /*
  593          * Set clocks back to 32kHz if they had been using refClk, then
  594          * use an external 32kHz crystal when sleeping, if one exists.
  595          */
  596         ar5212SetupClock(ah, opmode);
  597 
  598         /*
  599          * Writing to AR_BEACON will start timers. Hence it should
  600          * be the last register to be written. Do not reset tsf, do
  601          * not enable beacons at this point, but preserve other values
  602          * like beaconInterval.
  603          */
  604         OS_REG_WRITE(ah, AR_BEACON,
  605                 (OS_REG_READ(ah, AR_BEACON) &~ (AR_BEACON_EN | AR_BEACON_RESET_TSF)));
  606 
  607         /* XXX Setup post reset EAR additions */
  608 
  609         /* QoS support */
  610         if (AH_PRIVATE(ah)->ah_macVersion > AR_SREV_VERSION_VENICE ||
  611             (AH_PRIVATE(ah)->ah_macVersion == AR_SREV_VERSION_VENICE &&
  612              AH_PRIVATE(ah)->ah_macRev >= AR_SREV_GRIFFIN_LITE)) {
  613                 OS_REG_WRITE(ah, AR_QOS_CONTROL, 0x100aa);      /* XXX magic */
  614                 OS_REG_WRITE(ah, AR_QOS_SELECT, 0x3210);        /* XXX magic */
  615         }
  616 
  617         /* Turn on NOACK Support for QoS packets */
  618         OS_REG_WRITE(ah, AR_NOACK,
  619                 SM(2, AR_NOACK_2BIT_VALUE) |
  620                 SM(5, AR_NOACK_BIT_OFFSET) |
  621                 SM(0, AR_NOACK_BYTE_OFFSET));
  622 
  623         /* Get Antenna Gain reduction */
  624         if (IEEE80211_IS_CHAN_5GHZ(chan)) {
  625                 ath_hal_eepromGet(ah, AR_EEP_ANTGAINMAX_5, &twiceAntennaGain);
  626         } else {
  627                 ath_hal_eepromGet(ah, AR_EEP_ANTGAINMAX_2, &twiceAntennaGain);
  628         }
  629         twiceAntennaReduction =
  630                 ath_hal_getantennareduction(ah, chan, twiceAntennaGain);
  631 
  632         /* TPC for self-generated frames */
  633 
  634         ackTpcPow = MS(ahp->ah_macTPC, AR_TPC_ACK);
  635         if ((ackTpcPow-ahp->ah_txPowerIndexOffset) > chan->ic_maxpower)
  636                 ackTpcPow = chan->ic_maxpower+ahp->ah_txPowerIndexOffset;
  637 
  638         if (ackTpcPow > (2*chan->ic_maxregpower - twiceAntennaReduction))
  639                 ackTpcPow = (2*chan->ic_maxregpower - twiceAntennaReduction)
  640                         + ahp->ah_txPowerIndexOffset;
  641 
  642         ctsTpcPow = MS(ahp->ah_macTPC, AR_TPC_CTS);
  643         if ((ctsTpcPow-ahp->ah_txPowerIndexOffset) > chan->ic_maxpower)
  644                 ctsTpcPow = chan->ic_maxpower+ahp->ah_txPowerIndexOffset;
  645 
  646         if (ctsTpcPow > (2*chan->ic_maxregpower - twiceAntennaReduction))
  647                 ctsTpcPow = (2*chan->ic_maxregpower - twiceAntennaReduction)
  648                         + ahp->ah_txPowerIndexOffset;
  649 
  650         chirpTpcPow = MS(ahp->ah_macTPC, AR_TPC_CHIRP);
  651         if ((chirpTpcPow-ahp->ah_txPowerIndexOffset) > chan->ic_maxpower)
  652                 chirpTpcPow = chan->ic_maxpower+ahp->ah_txPowerIndexOffset;
  653 
  654         if (chirpTpcPow > (2*chan->ic_maxregpower - twiceAntennaReduction))
  655                 chirpTpcPow = (2*chan->ic_maxregpower - twiceAntennaReduction)
  656                         + ahp->ah_txPowerIndexOffset;
  657 
  658         if (ackTpcPow > 63)
  659                 ackTpcPow = 63;
  660         if (ctsTpcPow > 63)
  661                 ctsTpcPow = 63;
  662         if (chirpTpcPow > 63)
  663                 chirpTpcPow = 63;
  664 
  665         powerVal = SM(ackTpcPow, AR_TPC_ACK) |
  666                 SM(ctsTpcPow, AR_TPC_CTS) |
  667                 SM(chirpTpcPow, AR_TPC_CHIRP);
  668 
  669         OS_REG_WRITE(ah, AR_TPC, powerVal);
  670 
  671         /* Restore user-specified settings */
  672         if (ahp->ah_miscMode != 0)
  673                 OS_REG_WRITE(ah, AR_MISC_MODE, ahp->ah_miscMode);
  674         if (ahp->ah_sifstime != (u_int) -1)
  675                 ar5212SetSifsTime(ah, ahp->ah_sifstime);
  676         if (ahp->ah_slottime != (u_int) -1)
  677                 ar5212SetSlotTime(ah, ahp->ah_slottime);
  678         if (ahp->ah_acktimeout != (u_int) -1)
  679                 ar5212SetAckTimeout(ah, ahp->ah_acktimeout);
  680         if (ahp->ah_ctstimeout != (u_int) -1)
  681                 ar5212SetCTSTimeout(ah, ahp->ah_ctstimeout);
  682         if (AH_PRIVATE(ah)->ah_diagreg != 0)
  683                 OS_REG_WRITE(ah, AR_DIAG_SW, AH_PRIVATE(ah)->ah_diagreg);
  684 
  685         AH_PRIVATE(ah)->ah_opmode = opmode;     /* record operating mode */
  686 #if 0
  687 done:
  688 #endif
  689         if (bChannelChange && !IEEE80211_IS_CHAN_DFS(chan)) 
  690                 chan->ic_state &= ~IEEE80211_CHANSTATE_CWINT;
  691 
  692         HALDEBUG(ah, HAL_DEBUG_RESET, "%s: done\n", __func__);
  693 
  694         RESTORE_CCK(ah, chan, isBmode);
  695 
  696         OS_MARK(ah, AH_MARK_RESET_DONE, 0);
  697 
  698         return AH_TRUE;
  699 bad:
  700         RESTORE_CCK(ah, chan, isBmode);
  701 
  702         OS_MARK(ah, AH_MARK_RESET_DONE, ecode);
  703         if (status != AH_NULL)
  704                 *status = ecode;
  705         return AH_FALSE;
  706 #undef FAIL
  707 #undef N
  708 }
  709 
  710 /*
  711  * Call the rf backend to change the channel.
  712  */
  713 HAL_BOOL
  714 ar5212SetChannel(struct ath_hal *ah, const struct ieee80211_channel *chan)
  715 {
  716         struct ath_hal_5212 *ahp = AH5212(ah);
  717 
  718         /* Change the synth */
  719         if (!ahp->ah_rfHal->setChannel(ah, chan))
  720                 return AH_FALSE;
  721         return AH_TRUE;
  722 }
  723 
  724 /*
  725  * This channel change evaluates whether the selected hardware can
  726  * perform a synthesizer-only channel change (no reset).  If the
  727  * TX is not stopped, or the RFBus cannot be granted in the given
  728  * time, the function returns false as a reset is necessary
  729  */
  730 HAL_BOOL
  731 ar5212ChannelChange(struct ath_hal *ah, const struct ieee80211_channel *chan)
  732 {
  733         uint32_t       ulCount;
  734         uint32_t   data, synthDelay, qnum;
  735         uint16_t   rfXpdGain[MAX_NUM_PDGAINS_PER_CHANNEL];
  736         HAL_BOOL    txStopped = AH_TRUE;
  737         HAL_CHANNEL_INTERNAL *ichan;
  738 
  739         /*
  740          * Map public channel to private.
  741          */
  742         ichan = ath_hal_checkchannel(ah, chan);
  743 
  744         /* TX must be stopped or RF Bus grant will not work */
  745         for (qnum = 0; qnum < AH_PRIVATE(ah)->ah_caps.halTotalQueues; qnum++) {
  746                 if (ar5212NumTxPending(ah, qnum)) {
  747                         txStopped = AH_FALSE;
  748                         break;
  749                 }
  750         }
  751         if (!txStopped)
  752                 return AH_FALSE;
  753 
  754         /* Kill last Baseband Rx Frame */
  755         OS_REG_WRITE(ah, AR_PHY_RFBUS_REQ, AR_PHY_RFBUS_REQ_REQUEST); /* Request analog bus grant */
  756         for (ulCount = 0; ulCount < 100; ulCount++) {
  757                 if (OS_REG_READ(ah, AR_PHY_RFBUS_GNT))
  758                         break;
  759                 OS_DELAY(5);
  760         }
  761         if (ulCount >= 100)
  762                 return AH_FALSE;
  763 
  764         /* Change the synth */
  765         if (!ar5212SetChannel(ah, chan))
  766                 return AH_FALSE;
  767 
  768         /*
  769          * Wait for the frequency synth to settle (synth goes on via PHY_ACTIVE_EN).
  770          * Read the phy active delay register. Value is in 100ns increments.
  771          */
  772         data = OS_REG_READ(ah, AR_PHY_RX_DELAY) & AR_PHY_RX_DELAY_DELAY;
  773         if (IEEE80211_IS_CHAN_B(chan)) {
  774                 synthDelay = (4 * data) / 22;
  775         } else {
  776                 synthDelay = data / 10;
  777         }
  778         OS_DELAY(synthDelay + BASE_ACTIVATE_DELAY);
  779 
  780         /* Setup the transmit power values. */
  781         if (!ar5212SetTransmitPower(ah, chan, rfXpdGain)) {
  782                 HALDEBUG(ah, HAL_DEBUG_ANY,
  783                     "%s: error init'ing transmit power\n", __func__);
  784                 return AH_FALSE;
  785         }
  786 
  787         /* Write delta slope for OFDM enabled modes (A, G, Turbo) */
  788         if (IEEE80211_IS_CHAN_OFDM(chan)) {
  789                 if (IS_5413(ah) ||
  790                     AH_PRIVATE(ah)->ah_eeversion >= AR_EEPROM_VER5_3)
  791                         ar5212SetSpurMitigation(ah, chan);
  792                 ar5212SetDeltaSlope(ah, chan);
  793         }
  794 
  795         /* Release the RFBus Grant */
  796         OS_REG_WRITE(ah, AR_PHY_RFBUS_REQ, 0);
  797 
  798         /* Start Noise Floor Cal */
  799         OS_REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_NF);
  800         return AH_TRUE;
  801 }
  802 
  803 void
  804 ar5212SetOperatingMode(struct ath_hal *ah, int opmode)
  805 {
  806         uint32_t val;
  807 
  808         val = OS_REG_READ(ah, AR_STA_ID1);
  809         val &= ~(AR_STA_ID1_STA_AP | AR_STA_ID1_ADHOC);
  810         switch (opmode) {
  811         case HAL_M_HOSTAP:
  812                 OS_REG_WRITE(ah, AR_STA_ID1, val | AR_STA_ID1_STA_AP
  813                                         | AR_STA_ID1_KSRCH_MODE);
  814                 OS_REG_CLR_BIT(ah, AR_CFG, AR_CFG_AP_ADHOC_INDICATION);
  815                 break;
  816         case HAL_M_IBSS:
  817                 OS_REG_WRITE(ah, AR_STA_ID1, val | AR_STA_ID1_ADHOC
  818                                         | AR_STA_ID1_KSRCH_MODE);
  819                 OS_REG_SET_BIT(ah, AR_CFG, AR_CFG_AP_ADHOC_INDICATION);
  820                 break;
  821         case HAL_M_STA:
  822         case HAL_M_MONITOR:
  823                 OS_REG_WRITE(ah, AR_STA_ID1, val | AR_STA_ID1_KSRCH_MODE);
  824                 break;
  825         }
  826 }
  827 
  828 /*
  829  * Places the PHY and Radio chips into reset.  A full reset
  830  * must be called to leave this state.  The PCI/MAC/PCU are
  831  * not placed into reset as we must receive interrupt to
  832  * re-enable the hardware.
  833  */
  834 HAL_BOOL
  835 ar5212PhyDisable(struct ath_hal *ah)
  836 {
  837         return ar5212SetResetReg(ah, AR_RC_BB);
  838 }
  839 
  840 /*
  841  * Places all of hardware into reset
  842  */
  843 HAL_BOOL
  844 ar5212Disable(struct ath_hal *ah)
  845 {
  846         if (!ar5212SetPowerMode(ah, HAL_PM_AWAKE, AH_TRUE))
  847                 return AH_FALSE;
  848         /*
  849          * Reset the HW - PCI must be reset after the rest of the
  850          * device has been reset.
  851          */
  852         return ar5212SetResetReg(ah, AR_RC_MAC | AR_RC_BB | AR_RC_PCI);
  853 }
  854 
  855 /*
  856  * Places the hardware into reset and then pulls it out of reset
  857  *
  858  * TODO: Only write the PLL if we're changing to or from CCK mode
  859  * 
  860  * WARNING: The order of the PLL and mode registers must be correct.
  861  */
  862 HAL_BOOL
  863 ar5212ChipReset(struct ath_hal *ah, const struct ieee80211_channel *chan)
  864 {
  865 
  866         OS_MARK(ah, AH_MARK_CHIPRESET, chan ? chan->ic_freq : 0);
  867 
  868         /*
  869          * Reset the HW - PCI must be reset after the rest of the
  870          * device has been reset
  871          */
  872         if (!ar5212SetResetReg(ah, AR_RC_MAC | AR_RC_BB | AR_RC_PCI))
  873                 return AH_FALSE;
  874 
  875         /* Bring out of sleep mode (AGAIN) */
  876         if (!ar5212SetPowerMode(ah, HAL_PM_AWAKE, AH_TRUE))
  877                 return AH_FALSE;
  878 
  879         /* Clear warm reset register */
  880         if (!ar5212SetResetReg(ah, 0))
  881                 return AH_FALSE;
  882 
  883         /*
  884          * Perform warm reset before the mode/PLL/turbo registers
  885          * are changed in order to deactivate the radio.  Mode changes
  886          * with an active radio can result in corrupted shifts to the
  887          * radio device.
  888          */
  889 
  890         /*
  891          * Set CCK and Turbo modes correctly.
  892          */
  893         if (chan != AH_NULL) {          /* NB: can be null during attach */
  894                 uint32_t rfMode, phyPLL = 0, curPhyPLL, turbo;
  895 
  896                 if (IS_5413(ah)) {      /* NB: =>'s 5424 also */
  897                         rfMode = AR_PHY_MODE_AR5112;
  898                         if (IEEE80211_IS_CHAN_HALF(chan))
  899                                 rfMode |= AR_PHY_MODE_HALF;
  900                         else if (IEEE80211_IS_CHAN_QUARTER(chan))
  901                                 rfMode |= AR_PHY_MODE_QUARTER;
  902 
  903                         if (IEEE80211_IS_CHAN_CCK(chan))
  904                                 phyPLL = AR_PHY_PLL_CTL_44_5112;
  905                         else
  906                                 phyPLL = AR_PHY_PLL_CTL_40_5413;
  907                 } else if (IS_RAD5111(ah)) {
  908                         rfMode = AR_PHY_MODE_AR5111;
  909                         if (IEEE80211_IS_CHAN_CCK(chan))
  910                                 phyPLL = AR_PHY_PLL_CTL_44;
  911                         else
  912                                 phyPLL = AR_PHY_PLL_CTL_40;
  913                         if (IEEE80211_IS_CHAN_HALF(chan))
  914                                 phyPLL = AR_PHY_PLL_CTL_HALF;
  915                         else if (IEEE80211_IS_CHAN_QUARTER(chan))
  916                                 phyPLL = AR_PHY_PLL_CTL_QUARTER;
  917                 } else {                /* 5112, 2413, 2316, 2317 */
  918                         rfMode = AR_PHY_MODE_AR5112;
  919                         if (IEEE80211_IS_CHAN_CCK(chan))
  920                                 phyPLL = AR_PHY_PLL_CTL_44_5112;
  921                         else
  922                                 phyPLL = AR_PHY_PLL_CTL_40_5112;
  923                         if (IEEE80211_IS_CHAN_HALF(chan))
  924                                 phyPLL |= AR_PHY_PLL_CTL_HALF;
  925                         else if (IEEE80211_IS_CHAN_QUARTER(chan))
  926                                 phyPLL |= AR_PHY_PLL_CTL_QUARTER;
  927                 }
  928                 if (IEEE80211_IS_CHAN_G(chan))
  929                         rfMode |= AR_PHY_MODE_DYNAMIC;
  930                 else if (IEEE80211_IS_CHAN_OFDM(chan))
  931                         rfMode |= AR_PHY_MODE_OFDM;
  932                 else
  933                         rfMode |= AR_PHY_MODE_CCK;
  934                 if (IEEE80211_IS_CHAN_5GHZ(chan))
  935                         rfMode |= AR_PHY_MODE_RF5GHZ;
  936                 else
  937                         rfMode |= AR_PHY_MODE_RF2GHZ;
  938                 turbo = IEEE80211_IS_CHAN_TURBO(chan) ?
  939                         (AR_PHY_FC_TURBO_MODE | AR_PHY_FC_TURBO_SHORT) : 0;
  940                 curPhyPLL = OS_REG_READ(ah, AR_PHY_PLL_CTL);
  941                 /*
  942                  * PLL, Mode, and Turbo values must be written in the correct
  943                  * order to ensure:
  944                  * - The PLL cannot be set to 44 unless the CCK or DYNAMIC
  945                  *   mode bit is set
  946                  * - Turbo cannot be set at the same time as CCK or DYNAMIC
  947                  */
  948                 if (IEEE80211_IS_CHAN_CCK(chan)) {
  949                         OS_REG_WRITE(ah, AR_PHY_TURBO, turbo);
  950                         OS_REG_WRITE(ah, AR_PHY_MODE, rfMode);
  951                         if (curPhyPLL != phyPLL) {
  952                                 OS_REG_WRITE(ah,  AR_PHY_PLL_CTL,  phyPLL);
  953                                 /* Wait for the PLL to settle */
  954                                 OS_DELAY(PLL_SETTLE_DELAY);
  955                         }
  956                 } else {
  957                         if (curPhyPLL != phyPLL) {
  958                                 OS_REG_WRITE(ah,  AR_PHY_PLL_CTL,  phyPLL);
  959                                 /* Wait for the PLL to settle */
  960                                 OS_DELAY(PLL_SETTLE_DELAY);
  961                         }
  962                         OS_REG_WRITE(ah, AR_PHY_TURBO, turbo);
  963                         OS_REG_WRITE(ah, AR_PHY_MODE, rfMode);
  964                 }
  965         }
  966         return AH_TRUE;
  967 }
  968 
  969 /*
  970  * Recalibrate the lower PHY chips to account for temperature/environment
  971  * changes.
  972  */
  973 HAL_BOOL
  974 ar5212PerCalibrationN(struct ath_hal *ah,
  975         struct ieee80211_channel *chan,
  976         u_int chainMask, HAL_BOOL longCal, HAL_BOOL *isCalDone)
  977 {
  978 #define IQ_CAL_TRIES    10
  979         struct ath_hal_5212 *ahp = AH5212(ah);
  980         HAL_CHANNEL_INTERNAL *ichan;
  981         int32_t qCoff, qCoffDenom;
  982         int32_t iqCorrMeas, iCoff, iCoffDenom;
  983         uint32_t powerMeasQ, powerMeasI;
  984         HAL_BOOL isBmode = AH_FALSE;
  985 
  986         OS_MARK(ah, AH_MARK_PERCAL, chan->ic_freq);
  987         *isCalDone = AH_FALSE;
  988         ichan = ath_hal_checkchannel(ah, chan);
  989         if (ichan == AH_NULL) {
  990                 HALDEBUG(ah, HAL_DEBUG_ANY,
  991                     "%s: invalid channel %u/0x%x; no mapping\n",
  992                     __func__, chan->ic_freq, chan->ic_flags);
  993                 return AH_FALSE;
  994         }
  995         SAVE_CCK(ah, chan, isBmode);
  996 
  997         if (ahp->ah_bIQCalibration == IQ_CAL_DONE ||
  998             ahp->ah_bIQCalibration == IQ_CAL_INACTIVE)
  999                 *isCalDone = AH_TRUE;
 1000 
 1001         /* IQ calibration in progress. Check to see if it has finished. */
 1002         if (ahp->ah_bIQCalibration == IQ_CAL_RUNNING &&
 1003             !(OS_REG_READ(ah, AR_PHY_TIMING_CTRL4) & AR_PHY_TIMING_CTRL4_DO_IQCAL)) {
 1004                 int i;
 1005 
 1006                 /* IQ Calibration has finished. */
 1007                 ahp->ah_bIQCalibration = IQ_CAL_INACTIVE;
 1008                 *isCalDone = AH_TRUE;
 1009 
 1010                 /* workaround for misgated IQ Cal results */
 1011                 i = 0;
 1012                 do {
 1013                         /* Read calibration results. */
 1014                         powerMeasI = OS_REG_READ(ah, AR_PHY_IQCAL_RES_PWR_MEAS_I);
 1015                         powerMeasQ = OS_REG_READ(ah, AR_PHY_IQCAL_RES_PWR_MEAS_Q);
 1016                         iqCorrMeas = OS_REG_READ(ah, AR_PHY_IQCAL_RES_IQ_CORR_MEAS);
 1017                         if (powerMeasI && powerMeasQ)
 1018                                 break;
 1019                         /* Do we really need this??? */
 1020                         OS_REG_SET_BIT(ah, AR_PHY_TIMING_CTRL4,
 1021                             AR_PHY_TIMING_CTRL4_DO_IQCAL);
 1022                 } while (++i < IQ_CAL_TRIES);
 1023 
 1024                 HALDEBUG(ah, HAL_DEBUG_PERCAL,
 1025                     "%s: IQ cal finished: %d tries\n", __func__, i);
 1026                 HALDEBUG(ah, HAL_DEBUG_PERCAL,
 1027                     "%s: powerMeasI %u powerMeasQ %u iqCorrMeas %d\n",
 1028                     __func__, powerMeasI, powerMeasQ, iqCorrMeas);
 1029 
 1030                 /*
 1031                  * Prescale these values to remove 64-bit operation
 1032                  * requirement at the loss of a little precision.
 1033                  */
 1034                 iCoffDenom = (powerMeasI / 2 + powerMeasQ / 2) / 128;
 1035                 qCoffDenom = powerMeasQ / 128;
 1036 
 1037                 /* Protect against divide-by-0 and loss of sign bits. */
 1038                 if (iCoffDenom != 0 && qCoffDenom >= 2) {
 1039                         iCoff = (int8_t)(-iqCorrMeas) / iCoffDenom;
 1040                         /* IQCORR_Q_I_COFF is a signed 6 bit number */
 1041                         if (iCoff < -32) {
 1042                                 iCoff = -32;
 1043                         } else if (iCoff > 31) {
 1044                                 iCoff = 31;
 1045                         }
 1046 
 1047                         /* IQCORR_Q_Q_COFF is a signed 5 bit number */
 1048                         qCoff = (powerMeasI / qCoffDenom) - 128;
 1049                         if (qCoff < -16) {
 1050                                 qCoff = -16;
 1051                         } else if (qCoff > 15) {
 1052                                 qCoff = 15;
 1053                         }
 1054 
 1055                         HALDEBUG(ah, HAL_DEBUG_PERCAL,
 1056                             "%s: iCoff %d qCoff %d\n", __func__, iCoff, qCoff);
 1057 
 1058                         /* Write values and enable correction */
 1059                         OS_REG_RMW_FIELD(ah, AR_PHY_TIMING_CTRL4,
 1060                                 AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF, iCoff);
 1061                         OS_REG_RMW_FIELD(ah, AR_PHY_TIMING_CTRL4,
 1062                                 AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF, qCoff);
 1063                         OS_REG_SET_BIT(ah, AR_PHY_TIMING_CTRL4, 
 1064                                 AR_PHY_TIMING_CTRL4_IQCORR_ENABLE);
 1065 
 1066                         ahp->ah_bIQCalibration = IQ_CAL_DONE;
 1067                         ichan->privFlags |= CHANNEL_IQVALID;
 1068                         ichan->iCoff = iCoff;
 1069                         ichan->qCoff = qCoff;
 1070                 }
 1071         } else if (!IEEE80211_IS_CHAN_B(chan) &&
 1072             ahp->ah_bIQCalibration == IQ_CAL_DONE &&
 1073             (ichan->privFlags & CHANNEL_IQVALID) == 0) {
 1074                 /*
 1075                  * Start IQ calibration if configured channel has changed.
 1076                  * Use a magic number of 15 based on default value.
 1077                  */
 1078                 OS_REG_RMW_FIELD(ah, AR_PHY_TIMING_CTRL4,
 1079                         AR_PHY_TIMING_CTRL4_IQCAL_LOG_COUNT_MAX,
 1080                         INIT_IQCAL_LOG_COUNT_MAX);
 1081                 OS_REG_SET_BIT(ah, AR_PHY_TIMING_CTRL4,
 1082                         AR_PHY_TIMING_CTRL4_DO_IQCAL);
 1083                 ahp->ah_bIQCalibration = IQ_CAL_RUNNING;
 1084         }
 1085         /* XXX EAR */
 1086 
 1087         if (longCal) {
 1088                 /* Check noise floor results */
 1089                 ar5212GetNf(ah, chan);
 1090                 if (!IEEE80211_IS_CHAN_CWINT(chan)) {
 1091                         /* Perform cal for 5Ghz channels and any OFDM on 5112 */
 1092                         if (IEEE80211_IS_CHAN_5GHZ(chan) ||
 1093                             (IS_RAD5112(ah) && IEEE80211_IS_CHAN_OFDM(chan)))
 1094                                 ar5212RequestRfgain(ah);
 1095                 }
 1096         }
 1097         RESTORE_CCK(ah, chan, isBmode);
 1098 
 1099         return AH_TRUE;
 1100 #undef IQ_CAL_TRIES
 1101 }
 1102 
 1103 HAL_BOOL
 1104 ar5212PerCalibration(struct ath_hal *ah,  struct ieee80211_channel *chan,
 1105         HAL_BOOL *isIQdone)
 1106 {
 1107         return ar5212PerCalibrationN(ah, chan, 0x1, AH_TRUE, isIQdone);
 1108 }
 1109 
 1110 HAL_BOOL
 1111 ar5212ResetCalValid(struct ath_hal *ah, const struct ieee80211_channel *chan)
 1112 {
 1113         HAL_CHANNEL_INTERNAL *ichan;
 1114 
 1115         ichan = ath_hal_checkchannel(ah, chan);
 1116         if (ichan == AH_NULL) {
 1117                 HALDEBUG(ah, HAL_DEBUG_ANY,
 1118                     "%s: invalid channel %u/0x%x; no mapping\n",
 1119                     __func__, chan->ic_freq, chan->ic_flags);
 1120                 return AH_FALSE;
 1121         }
 1122         ichan->privFlags &= ~CHANNEL_IQVALID;
 1123         return AH_TRUE;
 1124 }
 1125 
 1126 /**************************************************************
 1127  * ar5212MacStop
 1128  *
 1129  * Disables all active QCUs and ensure that the mac is in a
 1130  * quiessence state.
 1131  */
 1132 static HAL_BOOL
 1133 ar5212MacStop(struct ath_hal *ah)
 1134 {
 1135         HAL_BOOL     status;
 1136         uint32_t    count;
 1137         uint32_t    pendFrameCount;
 1138         uint32_t    macStateFlag;
 1139         uint32_t    queue;
 1140 
 1141         status = AH_FALSE;
 1142 
 1143         /* Disable Rx Operation ***********************************/
 1144         OS_REG_SET_BIT(ah, AR_CR, AR_CR_RXD);
 1145 
 1146         /* Disable TX Operation ***********************************/
 1147 #ifdef NOT_YET
 1148         ar5212SetTxdpInvalid(ah);
 1149 #endif
 1150         OS_REG_SET_BIT(ah, AR_Q_TXD, AR_Q_TXD_M);
 1151 
 1152         /* Polling operation for completion of disable ************/
 1153         macStateFlag = TX_ENABLE_CHECK | RX_ENABLE_CHECK;
 1154 
 1155         for (count = 0; count < MAX_RESET_WAIT; count++) {
 1156                 if (macStateFlag & RX_ENABLE_CHECK) {
 1157                         if (!OS_REG_IS_BIT_SET(ah, AR_CR, AR_CR_RXE)) {
 1158                                 macStateFlag &= ~RX_ENABLE_CHECK;
 1159                         }
 1160                 }
 1161 
 1162                 if (macStateFlag & TX_ENABLE_CHECK) {
 1163                         if (!OS_REG_IS_BIT_SET(ah, AR_Q_TXE, AR_Q_TXE_M)) {
 1164                                 macStateFlag &= ~TX_ENABLE_CHECK;
 1165                                 macStateFlag |= TX_QUEUEPEND_CHECK;
 1166                         }
 1167                 }
 1168                 if (macStateFlag & TX_QUEUEPEND_CHECK) {
 1169                         pendFrameCount = 0;
 1170                         for (queue = 0; queue < AR_NUM_DCU; queue++) {
 1171                                 pendFrameCount += OS_REG_READ(ah,
 1172                                     AR_Q0_STS + (queue * 4)) &
 1173                                     AR_Q_STS_PEND_FR_CNT;
 1174                         }
 1175                         if (pendFrameCount == 0) {
 1176                                 macStateFlag &= ~TX_QUEUEPEND_CHECK;
 1177                         }
 1178                 }
 1179                 if (macStateFlag == 0) {
 1180                         status = AH_TRUE;
 1181                         break;
 1182                 }
 1183                 OS_DELAY(50);
 1184         }
 1185 
 1186         if (status != AH_TRUE) {
 1187                 HALDEBUG(ah, HAL_DEBUG_RESET,
 1188                     "%s:Failed to stop the MAC state 0x%x\n",
 1189                     __func__, macStateFlag);
 1190         }
 1191 
 1192         return status;
 1193 }
 1194 
 1195 /*
 1196  * Write the given reset bit mask into the reset register
 1197  */
 1198 static HAL_BOOL
 1199 ar5212SetResetReg(struct ath_hal *ah, uint32_t resetMask)
 1200 {
 1201         uint32_t mask = resetMask ? resetMask : ~0;
 1202         HAL_BOOL rt;
 1203 
 1204         /* Never reset the PCIE core */
 1205         if (AH_PRIVATE(ah)->ah_ispcie) {
 1206                 resetMask &= ~AR_RC_PCI;
 1207         }
 1208 
 1209         if (resetMask & (AR_RC_MAC | AR_RC_PCI)) {
 1210                 /*
 1211                  * To ensure that the driver can reset the
 1212                  * MAC, wake up the chip
 1213                  */
 1214                 rt = ar5212SetPowerMode(ah, HAL_PM_AWAKE, AH_TRUE);
 1215 
 1216                 if (rt != AH_TRUE) {
 1217                         return rt;
 1218                 }
 1219 
 1220                 /*
 1221                  * Disable interrupts
 1222                  */
 1223                 OS_REG_WRITE(ah, AR_IER, AR_IER_DISABLE);
 1224                 OS_REG_READ(ah, AR_IER);
 1225 
 1226                 if (ar5212MacStop(ah) != AH_TRUE) {
 1227                         /*
 1228                          * Failed to stop the MAC gracefully; let's be more forceful then
 1229                          */
 1230 
 1231                         /* need some delay before flush any pending MMR writes */
 1232                         OS_DELAY(15);
 1233                         OS_REG_READ(ah, AR_RXDP);
 1234 
 1235                         resetMask |= AR_RC_MAC | AR_RC_BB;
 1236                         /* _Never_ reset PCI Express core */
 1237                         if (! AH_PRIVATE(ah)->ah_ispcie) {
 1238                                 resetMask |= AR_RC_PCI;
 1239                         }
 1240 #if 0
 1241                         /*
 1242                          * Flush the park address of the PCI controller
 1243                         */
 1244                         /* Read PCI slot information less than Hainan revision */
 1245                         if (AH_PRIVATE(ah)->ah_bustype == HAL_BUS_TYPE_PCI) {
 1246                                 if (!IS_5112_REV5_UP(ah)) {
 1247 #define PCI_COMMON_CONFIG_STATUS    0x06
 1248                                         u_int32_t    i;
 1249                                         u_int16_t    reg16;
 1250 
 1251                                         for (i = 0; i < 32; i++) {
 1252                                                 ath_hal_read_pci_config_space(ah,
 1253                                                     PCI_COMMON_CONFIG_STATUS,
 1254                                                     &reg16, sizeof(reg16));
 1255                                         }
 1256                                 }
 1257 #undef PCI_COMMON_CONFIG_STATUS
 1258                         }
 1259 #endif
 1260                 } else {
 1261                         /*
 1262                          * MAC stopped gracefully; no need to warm-reset the PCI bus
 1263                          */
 1264 
 1265                         resetMask &= ~AR_RC_PCI;
 1266 
 1267                         /* need some delay before flush any pending MMR writes */
 1268                         OS_DELAY(15);
 1269                         OS_REG_READ(ah, AR_RXDP);
 1270                 }
 1271         }
 1272 
 1273         (void) OS_REG_READ(ah, AR_RXDP);/* flush any pending MMR writes */
 1274         OS_REG_WRITE(ah, AR_RC, resetMask);
 1275         OS_DELAY(15);                   /* need to wait at least 128 clocks
 1276                                            when reseting PCI before read */
 1277         mask &= (AR_RC_MAC | AR_RC_BB);
 1278         resetMask &= (AR_RC_MAC | AR_RC_BB);
 1279         rt = ath_hal_wait(ah, AR_RC, mask, resetMask);
 1280         if ((resetMask & AR_RC_MAC) == 0) {
 1281                 if (isBigEndian()) {
 1282                         /*
 1283                          * Set CFG, little-endian for descriptor accesses.
 1284                          */
 1285                         mask = INIT_CONFIG_STATUS | AR_CFG_SWRD;
 1286 #ifndef AH_NEED_DESC_SWAP
 1287                         mask |= AR_CFG_SWTD;
 1288 #endif
 1289                         OS_REG_WRITE(ah, AR_CFG, mask);
 1290                 } else
 1291                         OS_REG_WRITE(ah, AR_CFG, INIT_CONFIG_STATUS);
 1292                 if (ar5212SetPowerMode(ah, HAL_PM_AWAKE, AH_TRUE))
 1293                         (void) OS_REG_READ(ah, AR_ISR_RAC);
 1294         }
 1295 
 1296         /* track PHY power state so we don't try to r/w BB registers */
 1297         AH5212(ah)->ah_phyPowerOn = ((resetMask & AR_RC_BB) == 0);
 1298         return rt;
 1299 }
 1300 
 1301 int16_t
 1302 ar5212GetNoiseFloor(struct ath_hal *ah)
 1303 {
 1304         int16_t nf = (OS_REG_READ(ah, AR_PHY(25)) >> 19) & 0x1ff;
 1305         if (nf & 0x100)
 1306                 nf = 0 - ((nf ^ 0x1ff) + 1);
 1307         return nf;
 1308 }
 1309 
 1310 static HAL_BOOL
 1311 getNoiseFloorThresh(struct ath_hal *ah, const struct ieee80211_channel *chan,
 1312         int16_t *nft)
 1313 {
 1314         const HAL_EEPROM *ee = AH_PRIVATE(ah)->ah_eeprom;
 1315 
 1316         HALASSERT(ah->ah_magic == AR5212_MAGIC);
 1317 
 1318         switch (chan->ic_flags & IEEE80211_CHAN_ALLFULL) {
 1319         case IEEE80211_CHAN_A:
 1320                 *nft = ee->ee_noiseFloorThresh[headerInfo11A];
 1321                 break;
 1322         case IEEE80211_CHAN_B:
 1323                 *nft = ee->ee_noiseFloorThresh[headerInfo11B];
 1324                 break;
 1325         case IEEE80211_CHAN_G:
 1326         case IEEE80211_CHAN_PUREG:      /* NB: really 108G */
 1327                 *nft = ee->ee_noiseFloorThresh[headerInfo11G];
 1328                 break;
 1329         default:
 1330                 HALDEBUG(ah, HAL_DEBUG_ANY,
 1331                     "%s: invalid channel flags %u/0x%x\n",
 1332                     __func__, chan->ic_freq, chan->ic_flags);
 1333                 return AH_FALSE;
 1334         }
 1335         return AH_TRUE;
 1336 }
 1337 
 1338 /*
 1339  * Setup the noise floor cal history buffer.
 1340  */
 1341 void 
 1342 ar5212InitNfCalHistBuffer(struct ath_hal *ah)
 1343 {
 1344         struct ath_hal_5212 *ahp = AH5212(ah);
 1345         int i;
 1346 
 1347         ahp->ah_nfCalHist.first_run = 1;        
 1348         ahp->ah_nfCalHist.currIndex = 0;
 1349         ahp->ah_nfCalHist.privNF = AR5212_CCA_MAX_GOOD_VALUE;
 1350         ahp->ah_nfCalHist.invalidNFcount = AR512_NF_CAL_HIST_MAX;
 1351         for (i = 0; i < AR512_NF_CAL_HIST_MAX; i ++)
 1352                 ahp->ah_nfCalHist.nfCalBuffer[i] = AR5212_CCA_MAX_GOOD_VALUE;
 1353 }
 1354 
 1355 /*
 1356  * Add a noise floor value to the ring buffer.
 1357  */
 1358 static __inline void
 1359 updateNFHistBuff(struct ar5212NfCalHist *h, int16_t nf)
 1360 {
 1361         h->nfCalBuffer[h->currIndex] = nf;
 1362         if (++h->currIndex >= AR512_NF_CAL_HIST_MAX)
 1363                 h->currIndex = 0;
 1364 }       
 1365 
 1366 /*
 1367  * Return the median noise floor value in the ring buffer.
 1368  */
 1369 int16_t 
 1370 ar5212GetNfHistMid(const int16_t calData[AR512_NF_CAL_HIST_MAX])
 1371 {
 1372         int16_t sort[AR512_NF_CAL_HIST_MAX];
 1373         int i, j;
 1374 
 1375         OS_MEMCPY(sort, calData, AR512_NF_CAL_HIST_MAX*sizeof(int16_t));
 1376         for (i = 0; i < AR512_NF_CAL_HIST_MAX-1; i ++) {
 1377                 for (j = 1; j < AR512_NF_CAL_HIST_MAX-i; j ++) {
 1378                         if (sort[j] > sort[j-1]) {
 1379                                 int16_t nf = sort[j];
 1380                                 sort[j] = sort[j-1];
 1381                                 sort[j-1] = nf;
 1382                         }
 1383                 }
 1384         }
 1385         return sort[(AR512_NF_CAL_HIST_MAX-1)>>1];
 1386 }
 1387 
 1388 /*
 1389  * Read the NF and check it against the noise floor threshold
 1390  */
 1391 int16_t
 1392 ar5212GetNf(struct ath_hal *ah, struct ieee80211_channel *chan)
 1393 {
 1394         struct ath_hal_5212 *ahp = AH5212(ah);
 1395         struct ar5212NfCalHist *h = &ahp->ah_nfCalHist;
 1396         HAL_CHANNEL_INTERNAL *ichan = ath_hal_checkchannel(ah, chan);
 1397         int16_t nf, nfThresh;
 1398         int32_t val;
 1399 
 1400         if (OS_REG_READ(ah, AR_PHY_AGC_CONTROL) & AR_PHY_AGC_CONTROL_NF) {
 1401                 HALDEBUG(ah, HAL_DEBUG_ANY,
 1402                     "%s: NF did not complete in calibration window\n", __func__);
 1403                 ichan->rawNoiseFloor = h->privNF;       /* most recent value */
 1404                 return ichan->rawNoiseFloor;
 1405         }
 1406 
 1407         /*
 1408          * Finished NF cal, check against threshold.
 1409          */
 1410         nf = ar5212GetNoiseFloor(ah);
 1411         if (getNoiseFloorThresh(ah, chan, &nfThresh)) {
 1412                 if (nf > nfThresh) {
 1413                         HALDEBUG(ah, HAL_DEBUG_ANY,
 1414                             "%s: noise floor failed detected; detected %u, "
 1415                             "threshold %u\n", __func__, nf, nfThresh);
 1416                         /*
 1417                          * NB: Don't discriminate 2.4 vs 5Ghz, if this
 1418                          *     happens it indicates a problem regardless
 1419                          *     of the band.
 1420                          */
 1421                         chan->ic_state |= IEEE80211_CHANSTATE_CWINT;
 1422                         nf = 0;
 1423                 }
 1424         } else
 1425                 nf = 0;
 1426 
 1427         /*
 1428          * Pass through histogram and write median value as
 1429          * calculated from the accrued window.  We require a
 1430          * full window of in-range values to be seen before we
 1431          * start using the history.
 1432          */
 1433         updateNFHistBuff(h, nf);
 1434         if (h->first_run) {
 1435                 if (nf < AR5212_CCA_MIN_BAD_VALUE ||
 1436                     nf > AR5212_CCA_MAX_HIGH_VALUE) {
 1437                         nf = AR5212_CCA_MAX_GOOD_VALUE;
 1438                         h->invalidNFcount = AR512_NF_CAL_HIST_MAX;
 1439                 } else if (--(h->invalidNFcount) == 0) {
 1440                         h->first_run = 0;
 1441                         h->privNF = nf = ar5212GetNfHistMid(h->nfCalBuffer);
 1442                 } else {
 1443                         nf = AR5212_CCA_MAX_GOOD_VALUE;
 1444                 }
 1445         } else {
 1446                 h->privNF = nf = ar5212GetNfHistMid(h->nfCalBuffer);
 1447         }
 1448 
 1449         val = OS_REG_READ(ah, AR_PHY(25));
 1450         val &= 0xFFFFFE00;
 1451         val |= (((uint32_t)nf << 1) & 0x1FF);
 1452         OS_REG_WRITE(ah, AR_PHY(25), val);
 1453         OS_REG_CLR_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_ENABLE_NF);
 1454         OS_REG_CLR_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_NO_UPDATE_NF);
 1455         OS_REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_NF);
 1456 
 1457         if (!ath_hal_wait(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_NF, 0)) {
 1458 #ifdef AH_DEBUG
 1459                 ath_hal_printf(ah, "%s: AGC not ready AGC_CONTROL 0x%x\n",
 1460                     __func__, OS_REG_READ(ah, AR_PHY_AGC_CONTROL));
 1461 #endif
 1462         }
 1463 
 1464         /*
 1465          * Now load a high maxCCAPower value again so that we're
 1466          * not capped by the median we just loaded
 1467          */
 1468         val &= 0xFFFFFE00;
 1469         val |= (((uint32_t)(-50) << 1) & 0x1FF);
 1470         OS_REG_WRITE(ah, AR_PHY(25), val);
 1471         OS_REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_ENABLE_NF);
 1472         OS_REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_NO_UPDATE_NF);
 1473         OS_REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_NF);
 1474 
 1475         return (ichan->rawNoiseFloor = nf);
 1476 }
 1477 
 1478 /*
 1479  * Set up compression configuration registers
 1480  */
 1481 void
 1482 ar5212SetCompRegs(struct ath_hal *ah)
 1483 {
 1484         struct ath_hal_5212 *ahp = AH5212(ah);
 1485         int i;
 1486 
 1487         /* Check if h/w supports compression */
 1488         if (!AH_PRIVATE(ah)->ah_caps.halCompressSupport)
 1489                 return;
 1490 
 1491         OS_REG_WRITE(ah, AR_DCCFG, 1);
 1492 
 1493         OS_REG_WRITE(ah, AR_CCFG,
 1494                 (AR_COMPRESSION_WINDOW_SIZE >> 8) & AR_CCFG_WIN_M);
 1495 
 1496         OS_REG_WRITE(ah, AR_CCFG,
 1497                 OS_REG_READ(ah, AR_CCFG) | AR_CCFG_MIB_INT_EN);
 1498         OS_REG_WRITE(ah, AR_CCUCFG,
 1499                 AR_CCUCFG_RESET_VAL | AR_CCUCFG_CATCHUP_EN);
 1500 
 1501         OS_REG_WRITE(ah, AR_CPCOVF, 0);
 1502 
 1503         /* reset decompression mask */
 1504         for (i = 0; i < HAL_DECOMP_MASK_SIZE; i++) {
 1505                 OS_REG_WRITE(ah, AR_DCM_A, i);
 1506                 OS_REG_WRITE(ah, AR_DCM_D, ahp->ah_decompMask[i]);
 1507         }
 1508 }
 1509 
 1510 HAL_BOOL
 1511 ar5212SetAntennaSwitchInternal(struct ath_hal *ah, HAL_ANT_SETTING settings,
 1512         const struct ieee80211_channel *chan)
 1513 {
 1514 #define ANT_SWITCH_TABLE1       AR_PHY(88)
 1515 #define ANT_SWITCH_TABLE2       AR_PHY(89)
 1516         struct ath_hal_5212 *ahp = AH5212(ah);
 1517         const HAL_EEPROM *ee = AH_PRIVATE(ah)->ah_eeprom;
 1518         uint32_t antSwitchA, antSwitchB;
 1519         int ix;
 1520 
 1521         HALASSERT(ah->ah_magic == AR5212_MAGIC);
 1522         HALASSERT(ahp->ah_phyPowerOn);
 1523 
 1524         switch (chan->ic_flags & IEEE80211_CHAN_ALLFULL) {
 1525         case IEEE80211_CHAN_A:
 1526                 ix = 0;
 1527                 break;
 1528         case IEEE80211_CHAN_G:
 1529         case IEEE80211_CHAN_PUREG:              /* NB: 108G */
 1530                 ix = 2;
 1531                 break;
 1532         case IEEE80211_CHAN_B:
 1533                 if (IS_2425(ah) || IS_2417(ah)) {
 1534                         /* NB: Nala/Swan: 11b is handled using 11g */
 1535                         ix = 2;
 1536                 } else
 1537                         ix = 1;
 1538                 break;
 1539         default:
 1540                 HALDEBUG(ah, HAL_DEBUG_ANY, "%s: invalid channel flags 0x%x\n",
 1541                     __func__, chan->ic_flags);
 1542                 return AH_FALSE;
 1543         }
 1544 
 1545         antSwitchA =  ee->ee_antennaControl[1][ix]
 1546                    | (ee->ee_antennaControl[2][ix] << 6)
 1547                    | (ee->ee_antennaControl[3][ix] << 12) 
 1548                    | (ee->ee_antennaControl[4][ix] << 18)
 1549                    | (ee->ee_antennaControl[5][ix] << 24)
 1550                    ;
 1551         antSwitchB =  ee->ee_antennaControl[6][ix]
 1552                    | (ee->ee_antennaControl[7][ix] << 6)
 1553                    | (ee->ee_antennaControl[8][ix] << 12)
 1554                    | (ee->ee_antennaControl[9][ix] << 18)
 1555                    | (ee->ee_antennaControl[10][ix] << 24)
 1556                    ;
 1557         /*
 1558          * For fixed antenna, give the same setting for both switch banks
 1559          */
 1560         switch (settings) {
 1561         case HAL_ANT_FIXED_A:
 1562                 antSwitchB = antSwitchA;
 1563                 break;
 1564         case HAL_ANT_FIXED_B:
 1565                 antSwitchA = antSwitchB;
 1566                 break;
 1567         case HAL_ANT_VARIABLE:
 1568                 break;
 1569         default:
 1570                 HALDEBUG(ah, HAL_DEBUG_ANY, "%s: bad antenna setting %u\n",
 1571                     __func__, settings);
 1572                 return AH_FALSE;
 1573         }
 1574         if (antSwitchB == antSwitchA) {
 1575                 HALDEBUG(ah, HAL_DEBUG_RFPARAM,
 1576                     "%s: Setting fast diversity off.\n", __func__);
 1577                 OS_REG_CLR_BIT(ah,AR_PHY_CCK_DETECT, 
 1578                                AR_PHY_CCK_DETECT_BB_ENABLE_ANT_FAST_DIV);
 1579                 ahp->ah_diversity = AH_FALSE;
 1580         } else {
 1581                 HALDEBUG(ah, HAL_DEBUG_RFPARAM,
 1582                     "%s: Setting fast diversity on.\n", __func__);
 1583                 OS_REG_SET_BIT(ah,AR_PHY_CCK_DETECT, 
 1584                                AR_PHY_CCK_DETECT_BB_ENABLE_ANT_FAST_DIV);
 1585                 ahp->ah_diversity = AH_TRUE;
 1586         }
 1587         ahp->ah_antControl = settings;
 1588 
 1589         OS_REG_WRITE(ah, ANT_SWITCH_TABLE1, antSwitchA);
 1590         OS_REG_WRITE(ah, ANT_SWITCH_TABLE2, antSwitchB);
 1591 
 1592         return AH_TRUE;
 1593 #undef ANT_SWITCH_TABLE2
 1594 #undef ANT_SWITCH_TABLE1
 1595 }
 1596 
 1597 HAL_BOOL
 1598 ar5212IsSpurChannel(struct ath_hal *ah, const struct ieee80211_channel *chan)
 1599 {
 1600         uint16_t freq = ath_hal_gethwchannel(ah, chan);
 1601         uint32_t clockFreq =
 1602             ((IS_5413(ah) || IS_RAD5112_ANY(ah) || IS_2417(ah)) ? 40 : 32);
 1603         return ( ((freq % clockFreq) != 0)
 1604               && (((freq % clockFreq) < 10)
 1605              || (((freq) % clockFreq) > 22)) );
 1606 }
 1607 
 1608 /*
 1609  * Read EEPROM header info and program the device for correct operation
 1610  * given the channel value.
 1611  */
 1612 HAL_BOOL
 1613 ar5212SetBoardValues(struct ath_hal *ah, const struct ieee80211_channel *chan)
 1614 {
 1615 #define NO_FALSE_DETECT_BACKOFF   2
 1616 #define CB22_FALSE_DETECT_BACKOFF 6
 1617 #define AR_PHY_BIS(_ah, _reg, _mask, _val) \
 1618         OS_REG_WRITE(_ah, AR_PHY(_reg), \
 1619                 (OS_REG_READ(_ah, AR_PHY(_reg)) & _mask) | (_val));
 1620         struct ath_hal_5212 *ahp = AH5212(ah);
 1621         const HAL_EEPROM *ee = AH_PRIVATE(ah)->ah_eeprom;
 1622         int arrayMode, falseDectectBackoff;
 1623         int is2GHz = IEEE80211_IS_CHAN_2GHZ(chan);
 1624         HAL_CHANNEL_INTERNAL *ichan = ath_hal_checkchannel(ah, chan);
 1625         int8_t adcDesiredSize, pgaDesiredSize;
 1626         uint16_t switchSettling, txrxAtten, rxtxMargin;
 1627         int iCoff, qCoff;
 1628 
 1629         HALASSERT(ah->ah_magic == AR5212_MAGIC);
 1630 
 1631         switch (chan->ic_flags & IEEE80211_CHAN_ALLTURBOFULL) {
 1632         case IEEE80211_CHAN_A:
 1633         case IEEE80211_CHAN_ST:
 1634                 arrayMode = headerInfo11A;
 1635                 if (!IS_RAD5112_ANY(ah) && !IS_2413(ah) && !IS_5413(ah))
 1636                         OS_REG_RMW_FIELD(ah, AR_PHY_FRAME_CTL,
 1637                                 AR_PHY_FRAME_CTL_TX_CLIP,
 1638                                 ahp->ah_gainValues.currStep->paramVal[GP_TXCLIP]);
 1639                 break;
 1640         case IEEE80211_CHAN_B:
 1641                 arrayMode = headerInfo11B;
 1642                 break;
 1643         case IEEE80211_CHAN_G:
 1644         case IEEE80211_CHAN_108G:
 1645                 arrayMode = headerInfo11G;
 1646                 break;
 1647         default:
 1648                 HALDEBUG(ah, HAL_DEBUG_ANY, "%s: invalid channel flags 0x%x\n",
 1649                     __func__, chan->ic_flags);
 1650                 return AH_FALSE;
 1651         }
 1652 
 1653         /* Set the antenna register(s) correctly for the chip revision */
 1654         AR_PHY_BIS(ah, 68, 0xFFFFFC06,
 1655                 (ee->ee_antennaControl[0][arrayMode] << 4) | 0x1);
 1656 
 1657         ar5212SetAntennaSwitchInternal(ah, ahp->ah_antControl, chan);
 1658 
 1659         /* Set the Noise Floor Thresh on ar5211 devices */
 1660         OS_REG_WRITE(ah, AR_PHY(90),
 1661                 (ee->ee_noiseFloorThresh[arrayMode] & 0x1FF)
 1662                 | (1 << 9));
 1663 
 1664         if (ee->ee_version >= AR_EEPROM_VER5_0 && IEEE80211_IS_CHAN_TURBO(chan)) {
 1665                 switchSettling = ee->ee_switchSettlingTurbo[is2GHz];
 1666                 adcDesiredSize = ee->ee_adcDesiredSizeTurbo[is2GHz];
 1667                 pgaDesiredSize = ee->ee_pgaDesiredSizeTurbo[is2GHz];
 1668                 txrxAtten = ee->ee_txrxAttenTurbo[is2GHz];
 1669                 rxtxMargin = ee->ee_rxtxMarginTurbo[is2GHz];
 1670         } else {
 1671                 switchSettling = ee->ee_switchSettling[arrayMode];
 1672                 adcDesiredSize = ee->ee_adcDesiredSize[arrayMode];
 1673                 pgaDesiredSize = ee->ee_pgaDesiredSize[is2GHz];
 1674                 txrxAtten = ee->ee_txrxAtten[is2GHz];
 1675                 rxtxMargin = ee->ee_rxtxMargin[is2GHz];
 1676         }
 1677 
 1678         OS_REG_RMW_FIELD(ah, AR_PHY_SETTLING, 
 1679                          AR_PHY_SETTLING_SWITCH, switchSettling);
 1680         OS_REG_RMW_FIELD(ah, AR_PHY_DESIRED_SZ,
 1681                          AR_PHY_DESIRED_SZ_ADC, adcDesiredSize);
 1682         OS_REG_RMW_FIELD(ah, AR_PHY_DESIRED_SZ,
 1683                          AR_PHY_DESIRED_SZ_PGA, pgaDesiredSize);
 1684         OS_REG_RMW_FIELD(ah, AR_PHY_RXGAIN,
 1685                          AR_PHY_RXGAIN_TXRX_ATTEN, txrxAtten);
 1686         OS_REG_WRITE(ah, AR_PHY(13),
 1687                 (ee->ee_txEndToXPAOff[arrayMode] << 24)
 1688                 | (ee->ee_txEndToXPAOff[arrayMode] << 16)
 1689                 | (ee->ee_txFrameToXPAOn[arrayMode] << 8)
 1690                 | ee->ee_txFrameToXPAOn[arrayMode]);
 1691         AR_PHY_BIS(ah, 10, 0xFFFF00FF,
 1692                 ee->ee_txEndToXLNAOn[arrayMode] << 8);
 1693         AR_PHY_BIS(ah, 25, 0xFFF80FFF,
 1694                 (ee->ee_thresh62[arrayMode] << 12) & 0x7F000);
 1695 
 1696         /*
 1697          * False detect backoff - suspected 32 MHz spur causes false
 1698          * detects in OFDM, causing Tx Hangs.  Decrease weak signal
 1699          * sensitivity for this card.
 1700          */
 1701         falseDectectBackoff = NO_FALSE_DETECT_BACKOFF;
 1702         if (ee->ee_version < AR_EEPROM_VER3_3) {
 1703                 /* XXX magic number */
 1704                 if (AH_PRIVATE(ah)->ah_subvendorid == 0x1022 &&
 1705                     IEEE80211_IS_CHAN_OFDM(chan))
 1706                         falseDectectBackoff += CB22_FALSE_DETECT_BACKOFF;
 1707         } else {
 1708                 if (ar5212IsSpurChannel(ah, chan))
 1709                         falseDectectBackoff += ee->ee_falseDetectBackoff[arrayMode];
 1710         }
 1711         AR_PHY_BIS(ah, 73, 0xFFFFFF01, (falseDectectBackoff << 1) & 0xFE);
 1712 
 1713         if (ichan->privFlags & CHANNEL_IQVALID) {
 1714                 iCoff = ichan->iCoff;
 1715                 qCoff = ichan->qCoff;
 1716         } else {
 1717                 iCoff = ee->ee_iqCalI[is2GHz];
 1718                 qCoff = ee->ee_iqCalQ[is2GHz];
 1719         }
 1720 
 1721         /* write previous IQ results */
 1722         OS_REG_RMW_FIELD(ah, AR_PHY_TIMING_CTRL4,
 1723                 AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF, iCoff);
 1724         OS_REG_RMW_FIELD(ah, AR_PHY_TIMING_CTRL4,
 1725                 AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF, qCoff);
 1726         OS_REG_SET_BIT(ah, AR_PHY_TIMING_CTRL4,
 1727                 AR_PHY_TIMING_CTRL4_IQCORR_ENABLE);
 1728 
 1729         if (ee->ee_version >= AR_EEPROM_VER4_1) {
 1730                 if (!IEEE80211_IS_CHAN_108G(chan) || ee->ee_version >= AR_EEPROM_VER5_0)
 1731                         OS_REG_RMW_FIELD(ah, AR_PHY_GAIN_2GHZ,
 1732                                 AR_PHY_GAIN_2GHZ_RXTX_MARGIN, rxtxMargin);
 1733         }
 1734         if (ee->ee_version >= AR_EEPROM_VER5_1) {
 1735                 /* for now always disabled */
 1736                 OS_REG_WRITE(ah,  AR_PHY_HEAVY_CLIP_ENABLE,  0);
 1737         }
 1738 
 1739         return AH_TRUE;
 1740 #undef AR_PHY_BIS
 1741 #undef NO_FALSE_DETECT_BACKOFF
 1742 #undef CB22_FALSE_DETECT_BACKOFF
 1743 }
 1744 
 1745 /*
 1746  * Apply Spur Immunity to Boards that require it.
 1747  * Applies only to OFDM RX operation.
 1748  */
 1749 
 1750 void
 1751 ar5212SetSpurMitigation(struct ath_hal *ah,
 1752         const struct ieee80211_channel *chan)
 1753 {
 1754         uint32_t pilotMask[2] = {0, 0}, binMagMask[4] = {0, 0, 0 , 0};
 1755         uint16_t i, finalSpur, curChanAsSpur, binWidth = 0, spurDetectWidth, spurChan;
 1756         int32_t spurDeltaPhase = 0, spurFreqSd = 0, spurOffset, binOffsetNumT16, curBinOffset;
 1757         int16_t numBinOffsets;
 1758         static const uint16_t magMapFor4[4] = {1, 2, 2, 1};
 1759         static const uint16_t magMapFor3[3] = {1, 2, 1};
 1760         const uint16_t *pMagMap;
 1761         HAL_BOOL is2GHz = IEEE80211_IS_CHAN_2GHZ(chan);
 1762         HAL_CHANNEL_INTERNAL *ichan = ath_hal_checkchannel(ah, chan);
 1763         uint32_t val;
 1764 
 1765 #define CHAN_TO_SPUR(_f, _freq)   ( ((_freq) - ((_f) ? 2300 : 4900)) * 10 )
 1766         if (IS_2417(ah)) {
 1767                 HALDEBUG(ah, HAL_DEBUG_RFPARAM, "%s: no spur mitigation\n",
 1768                     __func__);
 1769                 return;
 1770         }
 1771 
 1772         curChanAsSpur = CHAN_TO_SPUR(is2GHz, ichan->channel);
 1773 
 1774         if (ichan->mainSpur) {
 1775                 /* Pull out the saved spur value */
 1776                 finalSpur = ichan->mainSpur;
 1777         } else {
 1778                 /*
 1779                  * Check if spur immunity should be performed for this channel
 1780                  * Should only be performed once per channel and then saved
 1781                  */
 1782                 finalSpur = AR_NO_SPUR;
 1783                 spurDetectWidth = HAL_SPUR_CHAN_WIDTH;
 1784                 if (IEEE80211_IS_CHAN_TURBO(chan))
 1785                         spurDetectWidth *= 2;
 1786 
 1787                 /* Decide if any spur affects the current channel */
 1788                 for (i = 0; i < AR_EEPROM_MODAL_SPURS; i++) {
 1789                         spurChan = ath_hal_getSpurChan(ah, i, is2GHz);
 1790                         if (spurChan == AR_NO_SPUR) {
 1791                                 break;
 1792                         }
 1793                         if ((curChanAsSpur - spurDetectWidth <= (spurChan & HAL_SPUR_VAL_MASK)) &&
 1794                             (curChanAsSpur + spurDetectWidth >= (spurChan & HAL_SPUR_VAL_MASK))) {
 1795                                 finalSpur = spurChan & HAL_SPUR_VAL_MASK;
 1796                                 break;
 1797                         }
 1798                 }
 1799                 /* Save detected spur (or no spur) for this channel */
 1800                 ichan->mainSpur = finalSpur;
 1801         }
 1802 
 1803         /* Write spur immunity data */
 1804         if (finalSpur == AR_NO_SPUR) {
 1805                 /* Disable Spur Immunity Regs if they appear set */
 1806                 if (OS_REG_READ(ah, AR_PHY_TIMING_CTRL4) & AR_PHY_TIMING_CTRL4_ENABLE_SPUR_FILTER) {
 1807                         /* Clear Spur Delta Phase, Spur Freq, and enable bits */
 1808                         OS_REG_RMW_FIELD(ah, AR_PHY_MASK_CTL, AR_PHY_MASK_CTL_RATE, 0);
 1809                         val = OS_REG_READ(ah, AR_PHY_TIMING_CTRL4);
 1810                         val &= ~(AR_PHY_TIMING_CTRL4_ENABLE_SPUR_FILTER |
 1811                                  AR_PHY_TIMING_CTRL4_ENABLE_CHAN_MASK |
 1812                                  AR_PHY_TIMING_CTRL4_ENABLE_PILOT_MASK);
 1813                         OS_REG_WRITE(ah, AR_PHY_MASK_CTL, val);
 1814                         OS_REG_WRITE(ah, AR_PHY_TIMING11, 0);
 1815 
 1816                         /* Clear pilot masks */
 1817                         OS_REG_WRITE(ah, AR_PHY_TIMING7, 0);
 1818                         OS_REG_RMW_FIELD(ah, AR_PHY_TIMING8, AR_PHY_TIMING8_PILOT_MASK_2, 0);
 1819                         OS_REG_WRITE(ah, AR_PHY_TIMING9, 0);
 1820                         OS_REG_RMW_FIELD(ah, AR_PHY_TIMING10, AR_PHY_TIMING10_PILOT_MASK_2, 0);
 1821 
 1822                         /* Clear magnitude masks */
 1823                         OS_REG_WRITE(ah, AR_PHY_BIN_MASK_1, 0);
 1824                         OS_REG_WRITE(ah, AR_PHY_BIN_MASK_2, 0);
 1825                         OS_REG_WRITE(ah, AR_PHY_BIN_MASK_3, 0);
 1826                         OS_REG_RMW_FIELD(ah, AR_PHY_MASK_CTL, AR_PHY_MASK_CTL_MASK_4, 0);
 1827                         OS_REG_WRITE(ah, AR_PHY_BIN_MASK2_1, 0);
 1828                         OS_REG_WRITE(ah, AR_PHY_BIN_MASK2_2, 0);
 1829                         OS_REG_WRITE(ah, AR_PHY_BIN_MASK2_3, 0);
 1830                         OS_REG_RMW_FIELD(ah, AR_PHY_BIN_MASK2_4, AR_PHY_BIN_MASK2_4_MASK_4, 0);
 1831                 }
 1832         } else {
 1833                 spurOffset = finalSpur - curChanAsSpur;
 1834                 /*
 1835                  * Spur calculations:
 1836                  * spurDeltaPhase is (spurOffsetIn100KHz / chipFrequencyIn100KHz) << 21
 1837                  * spurFreqSd is (spurOffsetIn100KHz / sampleFrequencyIn100KHz) << 11
 1838                  */
 1839                 if (IEEE80211_IS_CHAN_TURBO(chan)) {
 1840                         /* Chip Frequency & sampleFrequency are 80 MHz */
 1841                         spurDeltaPhase = (spurOffset << 16) / 25;
 1842                         spurFreqSd = spurDeltaPhase >> 10;
 1843                         binWidth = HAL_BIN_WIDTH_TURBO_100HZ;
 1844                 } else if (IEEE80211_IS_CHAN_G(chan)) {
 1845                         /* Chip Frequency is 44MHz, sampleFrequency is 40 MHz */
 1846                         spurFreqSd = (spurOffset << 8) / 55;
 1847                         spurDeltaPhase = (spurOffset << 17) / 25;
 1848                         binWidth = HAL_BIN_WIDTH_BASE_100HZ;
 1849                 } else {
 1850                         HALASSERT(!IEEE80211_IS_CHAN_B(chan));
 1851                         /* Chip Frequency & sampleFrequency are 40 MHz */
 1852                         spurDeltaPhase = (spurOffset << 17) / 25;
 1853                         spurFreqSd = spurDeltaPhase >> 10;
 1854                         binWidth = HAL_BIN_WIDTH_BASE_100HZ;
 1855                 }
 1856 
 1857                 /* Compute Pilot Mask */
 1858                 binOffsetNumT16 = ((spurOffset * 1000) << 4) / binWidth;
 1859                 /* The spur is on a bin if it's remainder at times 16 is 0 */
 1860                 if (binOffsetNumT16 & 0xF) {
 1861                         numBinOffsets = 4;
 1862                         pMagMap = magMapFor4;
 1863                 } else {
 1864                         numBinOffsets = 3;
 1865                         pMagMap = magMapFor3;
 1866                 }
 1867                 for (i = 0; i < numBinOffsets; i++) {
 1868                         if ((binOffsetNumT16 >> 4) > HAL_MAX_BINS_ALLOWED) {
 1869                                 HALDEBUG(ah, HAL_DEBUG_ANY,
 1870                                     "Too man bins in spur mitigation\n");
 1871                                 return;
 1872                         }
 1873 
 1874                         /* Get Pilot Mask values */
 1875                         curBinOffset = (binOffsetNumT16 >> 4) + i + 25;
 1876                         if ((curBinOffset >= 0) && (curBinOffset <= 32)) {
 1877                                 if (curBinOffset <= 25)
 1878                                         pilotMask[0] |= 1 << curBinOffset;
 1879                                 else if (curBinOffset >= 27)
 1880                                         pilotMask[0] |= 1 << (curBinOffset - 1);
 1881                         } else if ((curBinOffset >= 33) && (curBinOffset <= 52))
 1882                                 pilotMask[1] |= 1 << (curBinOffset - 33);
 1883 
 1884                         /* Get viterbi values */
 1885                         if ((curBinOffset >= -1) && (curBinOffset <= 14))
 1886                                 binMagMask[0] |= pMagMap[i] << (curBinOffset + 1) * 2;
 1887                         else if ((curBinOffset >= 15) && (curBinOffset <= 30))
 1888                                 binMagMask[1] |= pMagMap[i] << (curBinOffset - 15) * 2;
 1889                         else if ((curBinOffset >= 31) && (curBinOffset <= 46))
 1890                                 binMagMask[2] |= pMagMap[i] << (curBinOffset -31) * 2;
 1891                         else if((curBinOffset >= 47) && (curBinOffset <= 53))
 1892                                 binMagMask[3] |= pMagMap[i] << (curBinOffset -47) * 2;
 1893                 }
 1894 
 1895                 /* Write Spur Delta Phase, Spur Freq, and enable bits */
 1896                 OS_REG_RMW_FIELD(ah, AR_PHY_MASK_CTL, AR_PHY_MASK_CTL_RATE, 0xFF);
 1897                 val = OS_REG_READ(ah, AR_PHY_TIMING_CTRL4);
 1898                 val |= (AR_PHY_TIMING_CTRL4_ENABLE_SPUR_FILTER |
 1899                         AR_PHY_TIMING_CTRL4_ENABLE_CHAN_MASK | 
 1900                         AR_PHY_TIMING_CTRL4_ENABLE_PILOT_MASK);
 1901                 OS_REG_WRITE(ah, AR_PHY_TIMING_CTRL4, val);
 1902                 OS_REG_WRITE(ah, AR_PHY_TIMING11, AR_PHY_TIMING11_USE_SPUR_IN_AGC |             
 1903                              SM(spurFreqSd, AR_PHY_TIMING11_SPUR_FREQ_SD) |
 1904                              SM(spurDeltaPhase, AR_PHY_TIMING11_SPUR_DELTA_PHASE));
 1905 
 1906                 /* Write pilot masks */
 1907                 OS_REG_WRITE(ah, AR_PHY_TIMING7, pilotMask[0]);
 1908                 OS_REG_RMW_FIELD(ah, AR_PHY_TIMING8, AR_PHY_TIMING8_PILOT_MASK_2, pilotMask[1]);
 1909                 OS_REG_WRITE(ah, AR_PHY_TIMING9, pilotMask[0]);
 1910                 OS_REG_RMW_FIELD(ah, AR_PHY_TIMING10, AR_PHY_TIMING10_PILOT_MASK_2, pilotMask[1]);
 1911 
 1912                 /* Write magnitude masks */
 1913                 OS_REG_WRITE(ah, AR_PHY_BIN_MASK_1, binMagMask[0]);
 1914                 OS_REG_WRITE(ah, AR_PHY_BIN_MASK_2, binMagMask[1]);
 1915                 OS_REG_WRITE(ah, AR_PHY_BIN_MASK_3, binMagMask[2]);
 1916                 OS_REG_RMW_FIELD(ah, AR_PHY_MASK_CTL, AR_PHY_MASK_CTL_MASK_4, binMagMask[3]);
 1917                 OS_REG_WRITE(ah, AR_PHY_BIN_MASK2_1, binMagMask[0]);
 1918                 OS_REG_WRITE(ah, AR_PHY_BIN_MASK2_2, binMagMask[1]);
 1919                 OS_REG_WRITE(ah, AR_PHY_BIN_MASK2_3, binMagMask[2]);
 1920                 OS_REG_RMW_FIELD(ah, AR_PHY_BIN_MASK2_4, AR_PHY_BIN_MASK2_4_MASK_4, binMagMask[3]);
 1921         }
 1922 #undef CHAN_TO_SPUR
 1923 }
 1924 
 1925 /*
 1926  * Delta slope coefficient computation.
 1927  * Required for OFDM operation.
 1928  */
 1929 void
 1930 ar5212SetDeltaSlope(struct ath_hal *ah, const struct ieee80211_channel *chan)
 1931 {
 1932 #define COEF_SCALE_S 24
 1933 #define INIT_CLOCKMHZSCALED     0x64000000
 1934         uint16_t freq = ath_hal_gethwchannel(ah, chan);
 1935         unsigned long coef_scaled, coef_exp, coef_man, ds_coef_exp, ds_coef_man;
 1936         unsigned long clockMhzScaled = INIT_CLOCKMHZSCALED;
 1937 
 1938         if (IEEE80211_IS_CHAN_TURBO(chan))
 1939                 clockMhzScaled *= 2;
 1940         /* half and quarter rate can divide the scaled clock by 2 or 4 respectively */
 1941         /* scale for selected channel bandwidth */ 
 1942         if (IEEE80211_IS_CHAN_HALF(chan)) {
 1943                 clockMhzScaled = clockMhzScaled >> 1;
 1944         } else if (IEEE80211_IS_CHAN_QUARTER(chan)) {
 1945                 clockMhzScaled = clockMhzScaled >> 2;
 1946         } 
 1947 
 1948         /*
 1949          * ALGO -> coef = 1e8/fcarrier*fclock/40;
 1950          * scaled coef to provide precision for this floating calculation 
 1951          */
 1952         coef_scaled = clockMhzScaled / freq;
 1953 
 1954         /*
 1955          * ALGO -> coef_exp = 14-floor(log2(coef)); 
 1956          * floor(log2(x)) is the highest set bit position
 1957          */
 1958         for (coef_exp = 31; coef_exp > 0; coef_exp--)
 1959                 if ((coef_scaled >> coef_exp) & 0x1)
 1960                         break;
 1961         /* A coef_exp of 0 is a legal bit position but an unexpected coef_exp */
 1962         HALASSERT(coef_exp);
 1963         coef_exp = 14 - (coef_exp - COEF_SCALE_S);
 1964 
 1965         /*
 1966          * ALGO -> coef_man = floor(coef* 2^coef_exp+0.5);
 1967          * The coefficient is already shifted up for scaling
 1968          */
 1969         coef_man = coef_scaled + (1 << (COEF_SCALE_S - coef_exp - 1));
 1970         ds_coef_man = coef_man >> (COEF_SCALE_S - coef_exp);
 1971         ds_coef_exp = coef_exp - 16;
 1972 
 1973         OS_REG_RMW_FIELD(ah, AR_PHY_TIMING3,
 1974                 AR_PHY_TIMING3_DSC_MAN, ds_coef_man);
 1975         OS_REG_RMW_FIELD(ah, AR_PHY_TIMING3,
 1976                 AR_PHY_TIMING3_DSC_EXP, ds_coef_exp);
 1977 #undef INIT_CLOCKMHZSCALED
 1978 #undef COEF_SCALE_S
 1979 }
 1980 
 1981 /*
 1982  * Set a limit on the overall output power.  Used for dynamic
 1983  * transmit power control and the like.
 1984  *
 1985  * NB: limit is in units of 0.5 dbM.
 1986  */
 1987 HAL_BOOL
 1988 ar5212SetTxPowerLimit(struct ath_hal *ah, uint32_t limit)
 1989 {
 1990         /* XXX blech, construct local writable copy */
 1991         struct ieee80211_channel dummy = *AH_PRIVATE(ah)->ah_curchan;
 1992         uint16_t dummyXpdGains[2];
 1993         HAL_BOOL isBmode;
 1994 
 1995         SAVE_CCK(ah, &dummy, isBmode);
 1996         AH_PRIVATE(ah)->ah_powerLimit = AH_MIN(limit, MAX_RATE_POWER);
 1997         return ar5212SetTransmitPower(ah, &dummy, dummyXpdGains);
 1998 }
 1999 
 2000 /*
 2001  * Set the transmit power in the baseband for the given
 2002  * operating channel and mode.
 2003  */
 2004 HAL_BOOL
 2005 ar5212SetTransmitPower(struct ath_hal *ah,
 2006         const struct ieee80211_channel *chan, uint16_t *rfXpdGain)
 2007 {
 2008 #define POW_OFDM(_r, _s)        (((0 & 1)<< ((_s)+6)) | (((_r) & 0x3f) << (_s)))
 2009 #define POW_CCK(_r, _s)         (((_r) & 0x3f) << (_s))
 2010 #define N(a)                    (sizeof (a) / sizeof (a[0]))
 2011         static const uint16_t tpcScaleReductionTable[5] =
 2012                 { 0, 3, 6, 9, MAX_RATE_POWER };
 2013         struct ath_hal_5212 *ahp = AH5212(ah);
 2014         uint16_t freq = ath_hal_gethwchannel(ah, chan);
 2015         const HAL_EEPROM *ee = AH_PRIVATE(ah)->ah_eeprom;
 2016         int16_t minPower, maxPower, tpcInDb, powerLimit;
 2017         int i;
 2018 
 2019         HALASSERT(ah->ah_magic == AR5212_MAGIC);
 2020 
 2021         OS_MEMZERO(ahp->ah_pcdacTable, ahp->ah_pcdacTableSize);
 2022         OS_MEMZERO(ahp->ah_ratesArray, sizeof(ahp->ah_ratesArray));
 2023 
 2024         powerLimit = AH_MIN(MAX_RATE_POWER, AH_PRIVATE(ah)->ah_powerLimit);
 2025         if (powerLimit >= MAX_RATE_POWER || powerLimit == 0)
 2026                 tpcInDb = tpcScaleReductionTable[AH_PRIVATE(ah)->ah_tpScale];
 2027         else
 2028                 tpcInDb = 0;
 2029         if (!ar5212SetRateTable(ah, chan, tpcInDb, powerLimit,
 2030                                 AH_TRUE, &minPower, &maxPower)) {
 2031                 HALDEBUG(ah, HAL_DEBUG_ANY, "%s: unable to set rate table\n",
 2032                     __func__);
 2033                 return AH_FALSE;
 2034         }
 2035         if (!ahp->ah_rfHal->setPowerTable(ah,
 2036                 &minPower, &maxPower, chan, rfXpdGain)) {
 2037                 HALDEBUG(ah, HAL_DEBUG_ANY, "%s: unable to set power table\n",
 2038                     __func__);
 2039                 return AH_FALSE;
 2040         }
 2041 
 2042         /* 
 2043          * Adjust XR power/rate up by 2 dB to account for greater peak
 2044          * to avg ratio - except in newer avg power designs
 2045          */
 2046         if (!IS_2413(ah) && !IS_5413(ah))
 2047                 ahp->ah_ratesArray[15] += 4;
 2048         /* 
 2049          * txPowerIndexOffset is set by the SetPowerTable() call -
 2050          *  adjust the rate table 
 2051          */
 2052         for (i = 0; i < N(ahp->ah_ratesArray); i++) {
 2053                 ahp->ah_ratesArray[i] += ahp->ah_txPowerIndexOffset;
 2054                 if (ahp->ah_ratesArray[i] > 63) 
 2055                         ahp->ah_ratesArray[i] = 63;
 2056         }
 2057 
 2058         if (ee->ee_eepMap < 2) {
 2059                 /* 
 2060                  * Correct gain deltas for 5212 G operation -
 2061                  * Removed with revised chipset
 2062                  */
 2063                 if (AH_PRIVATE(ah)->ah_phyRev < AR_PHY_CHIP_ID_REV_2 &&
 2064                     IEEE80211_IS_CHAN_G(chan)) {
 2065                         uint16_t cckOfdmPwrDelta;
 2066 
 2067                         if (freq == 2484) 
 2068                                 cckOfdmPwrDelta = SCALE_OC_DELTA(
 2069                                         ee->ee_cckOfdmPwrDelta - 
 2070                                         ee->ee_scaledCh14FilterCckDelta);
 2071                         else 
 2072                                 cckOfdmPwrDelta = SCALE_OC_DELTA(
 2073                                         ee->ee_cckOfdmPwrDelta);
 2074                         ar5212CorrectGainDelta(ah, cckOfdmPwrDelta);
 2075                 }
 2076                 /* 
 2077                  * Finally, write the power values into the
 2078                  * baseband power table
 2079                  */
 2080                 for (i = 0; i < (PWR_TABLE_SIZE/2); i++) {
 2081                         OS_REG_WRITE(ah, AR_PHY_PCDAC_TX_POWER(i),
 2082                                  ((((ahp->ah_pcdacTable[2*i + 1] << 8) | 0xff) & 0xffff) << 16)
 2083                                 | (((ahp->ah_pcdacTable[2*i]     << 8) | 0xff) & 0xffff)
 2084                         );
 2085                 }
 2086         }
 2087 
 2088         /* Write the OFDM power per rate set */
 2089         OS_REG_WRITE(ah, AR_PHY_POWER_TX_RATE1, 
 2090                 POW_OFDM(ahp->ah_ratesArray[3], 24)
 2091               | POW_OFDM(ahp->ah_ratesArray[2], 16)
 2092               | POW_OFDM(ahp->ah_ratesArray[1],  8)
 2093               | POW_OFDM(ahp->ah_ratesArray[0],  0)
 2094         );
 2095         OS_REG_WRITE(ah, AR_PHY_POWER_TX_RATE2, 
 2096                 POW_OFDM(ahp->ah_ratesArray[7], 24)
 2097               | POW_OFDM(ahp->ah_ratesArray[6], 16)
 2098               | POW_OFDM(ahp->ah_ratesArray[5],  8)
 2099               | POW_OFDM(ahp->ah_ratesArray[4],  0)
 2100         );
 2101 
 2102         /* Write the CCK power per rate set */
 2103         OS_REG_WRITE(ah, AR_PHY_POWER_TX_RATE3,
 2104                 POW_CCK(ahp->ah_ratesArray[10], 24)
 2105               | POW_CCK(ahp->ah_ratesArray[9],  16)
 2106               | POW_CCK(ahp->ah_ratesArray[15],  8)     /* XR target power */
 2107               | POW_CCK(ahp->ah_ratesArray[8],   0)
 2108         );
 2109         OS_REG_WRITE(ah, AR_PHY_POWER_TX_RATE4,
 2110                 POW_CCK(ahp->ah_ratesArray[14], 24)
 2111               | POW_CCK(ahp->ah_ratesArray[13], 16)
 2112               | POW_CCK(ahp->ah_ratesArray[12],  8)
 2113               | POW_CCK(ahp->ah_ratesArray[11],  0)
 2114         );
 2115 
 2116         /*
 2117          * Set max power to 30 dBm and, optionally,
 2118          * enable TPC in tx descriptors.
 2119          */
 2120         OS_REG_WRITE(ah, AR_PHY_POWER_TX_RATE_MAX, MAX_RATE_POWER |
 2121                 (ahp->ah_tpcEnabled ? AR_PHY_POWER_TX_RATE_MAX_TPC_ENABLE : 0));
 2122 
 2123         return AH_TRUE;
 2124 #undef N
 2125 #undef POW_CCK
 2126 #undef POW_OFDM
 2127 }
 2128 
 2129 /*
 2130  * Sets the transmit power in the baseband for the given
 2131  * operating channel and mode.
 2132  */
 2133 static HAL_BOOL
 2134 ar5212SetRateTable(struct ath_hal *ah, const struct ieee80211_channel *chan,
 2135         int16_t tpcScaleReduction, int16_t powerLimit, HAL_BOOL commit,
 2136         int16_t *pMinPower, int16_t *pMaxPower)
 2137 {
 2138         struct ath_hal_5212 *ahp = AH5212(ah);
 2139         uint16_t freq = ath_hal_gethwchannel(ah, chan);
 2140         const HAL_EEPROM *ee = AH_PRIVATE(ah)->ah_eeprom;
 2141         uint16_t *rpow = ahp->ah_ratesArray;
 2142         uint16_t twiceMaxEdgePower = MAX_RATE_POWER;
 2143         uint16_t twiceMaxEdgePowerCck = MAX_RATE_POWER;
 2144         uint16_t twiceMaxRDPower = MAX_RATE_POWER;
 2145         int i;
 2146         uint8_t cfgCtl;
 2147         int8_t twiceAntennaGain, twiceAntennaReduction;
 2148         const RD_EDGES_POWER *rep;
 2149         TRGT_POWER_INFO targetPowerOfdm, targetPowerCck;
 2150         int16_t scaledPower, maxAvailPower = 0;
 2151         int16_t r13, r9, r7, r0;
 2152 
 2153         HALASSERT(ah->ah_magic == AR5212_MAGIC);
 2154 
 2155         twiceMaxRDPower = chan->ic_maxregpower * 2;
 2156         *pMaxPower = -MAX_RATE_POWER;
 2157         *pMinPower = MAX_RATE_POWER;
 2158 
 2159         /* Get conformance test limit maximum for this channel */
 2160         cfgCtl = ath_hal_getctl(ah, chan);
 2161         for (i = 0; i < ee->ee_numCtls; i++) {
 2162                 uint16_t twiceMinEdgePower;
 2163 
 2164                 if (ee->ee_ctl[i] == 0)
 2165                         continue;
 2166                 if (ee->ee_ctl[i] == cfgCtl ||
 2167                     cfgCtl == ((ee->ee_ctl[i] & CTL_MODE_M) | SD_NO_CTL)) {
 2168                         rep = &ee->ee_rdEdgesPower[i * NUM_EDGES];
 2169                         twiceMinEdgePower = ar5212GetMaxEdgePower(freq, rep);
 2170                         if ((cfgCtl & ~CTL_MODE_M) == SD_NO_CTL) {
 2171                                 /* Find the minimum of all CTL edge powers that apply to this channel */
 2172                                 twiceMaxEdgePower = AH_MIN(twiceMaxEdgePower, twiceMinEdgePower);
 2173                         } else {
 2174                                 twiceMaxEdgePower = twiceMinEdgePower;
 2175                                 break;
 2176                         }
 2177                 }
 2178         }
 2179 
 2180         if (IEEE80211_IS_CHAN_G(chan)) {
 2181                 /* Check for a CCK CTL for 11G CCK powers */
 2182                 cfgCtl = (cfgCtl & ~CTL_MODE_M) | CTL_11B;
 2183                 for (i = 0; i < ee->ee_numCtls; i++) {
 2184                         uint16_t twiceMinEdgePowerCck;
 2185 
 2186                         if (ee->ee_ctl[i] == 0)
 2187                                 continue;
 2188                         if (ee->ee_ctl[i] == cfgCtl ||
 2189                             cfgCtl == ((ee->ee_ctl[i] & CTL_MODE_M) | SD_NO_CTL)) {
 2190                                 rep = &ee->ee_rdEdgesPower[i * NUM_EDGES];
 2191                                 twiceMinEdgePowerCck = ar5212GetMaxEdgePower(freq, rep);
 2192                                 if ((cfgCtl & ~CTL_MODE_M) == SD_NO_CTL) {
 2193                                         /* Find the minimum of all CTL edge powers that apply to this channel */
 2194                                         twiceMaxEdgePowerCck = AH_MIN(twiceMaxEdgePowerCck, twiceMinEdgePowerCck);
 2195                                 } else {
 2196                                         twiceMaxEdgePowerCck = twiceMinEdgePowerCck;
 2197                                         break;
 2198                                 }
 2199                         }
 2200                 }
 2201         } else {
 2202                 /* Set the 11B cck edge power to the one found before */
 2203                 twiceMaxEdgePowerCck = twiceMaxEdgePower;
 2204         }
 2205 
 2206         /* Get Antenna Gain reduction */
 2207         if (IEEE80211_IS_CHAN_5GHZ(chan)) {
 2208                 ath_hal_eepromGet(ah, AR_EEP_ANTGAINMAX_5, &twiceAntennaGain);
 2209         } else {
 2210                 ath_hal_eepromGet(ah, AR_EEP_ANTGAINMAX_2, &twiceAntennaGain);
 2211         }
 2212         twiceAntennaReduction =
 2213                 ath_hal_getantennareduction(ah, chan, twiceAntennaGain);
 2214 
 2215         if (IEEE80211_IS_CHAN_OFDM(chan)) {
 2216                 /* Get final OFDM target powers */
 2217                 if (IEEE80211_IS_CHAN_2GHZ(chan)) { 
 2218                         ar5212GetTargetPowers(ah, chan, ee->ee_trgtPwr_11g,
 2219                                 ee->ee_numTargetPwr_11g, &targetPowerOfdm);
 2220                 } else {
 2221                         ar5212GetTargetPowers(ah, chan, ee->ee_trgtPwr_11a,
 2222                                 ee->ee_numTargetPwr_11a, &targetPowerOfdm);
 2223                 }
 2224 
 2225                 /* Get Maximum OFDM power */
 2226                 /* Minimum of target and edge powers */
 2227                 scaledPower = AH_MIN(twiceMaxEdgePower,
 2228                                 twiceMaxRDPower - twiceAntennaReduction);
 2229 
 2230                 /*
 2231                  * If turbo is set, reduce power to keep power
 2232                  * consumption under 2 Watts.  Note that we always do
 2233                  * this unless specially configured.  Then we limit
 2234                  * power only for non-AP operation.
 2235                  */
 2236                 if (IEEE80211_IS_CHAN_TURBO(chan)
 2237 #ifdef AH_ENABLE_AP_SUPPORT
 2238                     && AH_PRIVATE(ah)->ah_opmode != HAL_M_HOSTAP
 2239 #endif
 2240                 ) {
 2241                         /*
 2242                          * If turbo is set, reduce power to keep power
 2243                          * consumption under 2 Watts
 2244                          */
 2245                         if (ee->ee_version >= AR_EEPROM_VER3_1)
 2246                                 scaledPower = AH_MIN(scaledPower,
 2247                                         ee->ee_turbo2WMaxPower5);
 2248                         /*
 2249                          * EEPROM version 4.0 added an additional
 2250                          * constraint on 2.4GHz channels.
 2251                          */
 2252                         if (ee->ee_version >= AR_EEPROM_VER4_0 &&
 2253                             IEEE80211_IS_CHAN_2GHZ(chan))
 2254                                 scaledPower = AH_MIN(scaledPower,
 2255                                         ee->ee_turbo2WMaxPower2);
 2256                 }
 2257 
 2258                 maxAvailPower = AH_MIN(scaledPower,
 2259                                         targetPowerOfdm.twicePwr6_24);
 2260 
 2261                 /* Reduce power by max regulatory domain allowed restrictions */
 2262                 scaledPower = maxAvailPower - (tpcScaleReduction * 2);
 2263                 scaledPower = (scaledPower < 0) ? 0 : scaledPower;
 2264                 scaledPower = AH_MIN(scaledPower, powerLimit);
 2265 
 2266                 if (commit) {
 2267                         /* Set OFDM rates 9, 12, 18, 24 */
 2268                         r0 = rpow[0] = rpow[1] = rpow[2] = rpow[3] = rpow[4] = scaledPower;
 2269 
 2270                         /* Set OFDM rates 36, 48, 54, XR */
 2271                         rpow[5] = AH_MIN(rpow[0], targetPowerOfdm.twicePwr36);
 2272                         rpow[6] = AH_MIN(rpow[0], targetPowerOfdm.twicePwr48);
 2273                         r7 = rpow[7] = AH_MIN(rpow[0], targetPowerOfdm.twicePwr54);
 2274 
 2275                         if (ee->ee_version >= AR_EEPROM_VER4_0) {
 2276                                 /* Setup XR target power from EEPROM */
 2277                                 rpow[15] = AH_MIN(scaledPower, IEEE80211_IS_CHAN_2GHZ(chan) ?
 2278                                                   ee->ee_xrTargetPower2 : ee->ee_xrTargetPower5);
 2279                         } else {
 2280                                 /* XR uses 6mb power */
 2281                                 rpow[15] = rpow[0];
 2282                         }
 2283                         ahp->ah_ofdmTxPower = *pMaxPower;
 2284 
 2285                 } else {
 2286                         r0 = scaledPower;
 2287                         r7 = AH_MIN(r0, targetPowerOfdm.twicePwr54);
 2288                 }
 2289                 *pMinPower = r7;
 2290                 *pMaxPower = r0;
 2291 
 2292                 HALDEBUG(ah, HAL_DEBUG_RFPARAM,
 2293                     "%s: MaxRD: %d TurboMax: %d MaxCTL: %d "
 2294                     "TPC_Reduction %d chan=%d (0x%x) maxAvailPower=%d pwr6_24=%d, maxPower=%d\n",
 2295                     __func__, twiceMaxRDPower, ee->ee_turbo2WMaxPower5,
 2296                     twiceMaxEdgePower, tpcScaleReduction * 2,
 2297                     chan->ic_freq, chan->ic_flags,
 2298                     maxAvailPower, targetPowerOfdm.twicePwr6_24, *pMaxPower);
 2299         }
 2300 
 2301         if (IEEE80211_IS_CHAN_CCK(chan)) {
 2302                 /* Get final CCK target powers */
 2303                 ar5212GetTargetPowers(ah, chan, ee->ee_trgtPwr_11b,
 2304                         ee->ee_numTargetPwr_11b, &targetPowerCck);
 2305 
 2306                 /* Reduce power by max regulatory domain allowed restrictions */
 2307                 scaledPower = AH_MIN(twiceMaxEdgePowerCck,
 2308                         twiceMaxRDPower - twiceAntennaReduction);
 2309                 if (maxAvailPower < AH_MIN(scaledPower, targetPowerCck.twicePwr6_24))
 2310                         maxAvailPower = AH_MIN(scaledPower, targetPowerCck.twicePwr6_24);
 2311 
 2312                 /* Reduce power by user selection */
 2313                 scaledPower = AH_MIN(scaledPower, targetPowerCck.twicePwr6_24) - (tpcScaleReduction * 2);
 2314                 scaledPower = (scaledPower < 0) ? 0 : scaledPower;
 2315                 scaledPower = AH_MIN(scaledPower, powerLimit);
 2316 
 2317                 if (commit) {
 2318                         /* Set CCK rates 2L, 2S, 5.5L, 5.5S, 11L, 11S */
 2319                         rpow[8]  = AH_MIN(scaledPower, targetPowerCck.twicePwr6_24);
 2320                         r9 = rpow[9]  = AH_MIN(scaledPower, targetPowerCck.twicePwr36);
 2321                         rpow[10] = rpow[9];
 2322                         rpow[11] = AH_MIN(scaledPower, targetPowerCck.twicePwr48);
 2323                         rpow[12] = rpow[11];
 2324                         r13 = rpow[13] = AH_MIN(scaledPower, targetPowerCck.twicePwr54);
 2325                         rpow[14] = rpow[13];
 2326                 } else {
 2327                         r9 = AH_MIN(scaledPower, targetPowerCck.twicePwr36);
 2328                         r13 = AH_MIN(scaledPower, targetPowerCck.twicePwr54);
 2329                 }
 2330 
 2331                 /* Set min/max power based off OFDM values or initialization */
 2332                 if (r13 < *pMinPower)
 2333                         *pMinPower = r13;
 2334                 if (r9 > *pMaxPower)
 2335                         *pMaxPower = r9;
 2336 
 2337                 HALDEBUG(ah, HAL_DEBUG_RFPARAM,
 2338                     "%s: cck: MaxRD: %d MaxCTL: %d "
 2339                     "TPC_Reduction %d chan=%d (0x%x) maxAvailPower=%d pwr6_24=%d, maxPower=%d\n",
 2340                     __func__, twiceMaxRDPower, twiceMaxEdgePowerCck,
 2341                     tpcScaleReduction * 2, chan->ic_freq, chan->ic_flags,
 2342                     maxAvailPower, targetPowerCck.twicePwr6_24, *pMaxPower);
 2343         }
 2344         if (commit) {
 2345                 ahp->ah_tx6PowerInHalfDbm = *pMaxPower;
 2346                 AH_PRIVATE(ah)->ah_maxPowerLevel = ahp->ah_tx6PowerInHalfDbm;
 2347         }
 2348         return AH_TRUE;
 2349 }
 2350 
 2351 HAL_BOOL
 2352 ar5212GetChipPowerLimits(struct ath_hal *ah, struct ieee80211_channel *chan)
 2353 {
 2354         struct ath_hal_5212 *ahp = AH5212(ah);
 2355 #if 0
 2356         static const uint16_t tpcScaleReductionTable[5] =
 2357                 { 0, 3, 6, 9, MAX_RATE_POWER };
 2358         int16_t tpcInDb, powerLimit;
 2359 #endif
 2360         int16_t minPower, maxPower;
 2361 
 2362         /*
 2363          * Get Pier table max and min powers.
 2364          */
 2365         if (ahp->ah_rfHal->getChannelMaxMinPower(ah, chan, &maxPower, &minPower)) {
 2366                 /* NB: rf code returns 1/4 dBm units, convert */
 2367                 chan->ic_maxpower = maxPower / 2;
 2368                 chan->ic_minpower = minPower / 2;
 2369         } else {
 2370                 HALDEBUG(ah, HAL_DEBUG_ANY,
 2371                     "%s: no min/max power for %u/0x%x\n",
 2372                     __func__, chan->ic_freq, chan->ic_flags);
 2373                 chan->ic_maxpower = MAX_RATE_POWER;
 2374                 chan->ic_minpower = 0;
 2375         }
 2376 #if 0
 2377         /*
 2378          * Now adjust to reflect any global scale and/or CTL's.
 2379          * (XXX is that correct?)
 2380          */
 2381         powerLimit = AH_MIN(MAX_RATE_POWER, AH_PRIVATE(ah)->ah_powerLimit);
 2382         if (powerLimit >= MAX_RATE_POWER || powerLimit == 0)
 2383                 tpcInDb = tpcScaleReductionTable[AH_PRIVATE(ah)->ah_tpScale];
 2384         else
 2385                 tpcInDb = 0;
 2386         if (!ar5212SetRateTable(ah, chan, tpcInDb, powerLimit,
 2387                                 AH_FALSE, &minPower, &maxPower)) {
 2388                 HALDEBUG(ah, HAL_DEBUG_ANY,
 2389                     "%s: unable to find max/min power\n",__func__);
 2390                 return AH_FALSE;
 2391         }
 2392         if (maxPower < chan->ic_maxpower)
 2393                 chan->ic_maxpower = maxPower;
 2394         if (minPower < chan->ic_minpower)
 2395                 chan->ic_minpower = minPower;
 2396         HALDEBUG(ah, HAL_DEBUG_RESET,
 2397             "Chan %d: MaxPow = %d MinPow = %d\n",
 2398             chan->ic_freq, chan->ic_maxpower, chans->ic_minpower);
 2399 #endif
 2400         return AH_TRUE;
 2401 }
 2402 
 2403 /*
 2404  * Correct for the gain-delta between ofdm and cck mode target
 2405  * powers. Write the results to the rate table and the power table.
 2406  *
 2407  *   Conventions :
 2408  *   1. rpow[ii] is the integer value of 2*(desired power
 2409  *    for the rate ii in dBm) to provide 0.5dB resolution. rate
 2410  *    mapping is as following :
 2411  *     [0..7]  --> ofdm 6, 9, .. 48, 54
 2412  *     [8..14] --> cck 1L, 2L, 2S, .. 11L, 11S
 2413  *     [15]    --> XR (all rates get the same power)
 2414  *   2. powv[ii]  is the pcdac corresponding to ii/2 dBm.
 2415  */
 2416 static void
 2417 ar5212CorrectGainDelta(struct ath_hal *ah, int twiceOfdmCckDelta)
 2418 {
 2419 #define N(_a)   (sizeof(_a) / sizeof(_a[0]))
 2420         struct ath_hal_5212 *ahp = AH5212(ah);
 2421         const HAL_EEPROM *ee = AH_PRIVATE(ah)->ah_eeprom;
 2422         int16_t ratesIndex[N(ahp->ah_ratesArray)];
 2423         uint16_t ii, jj, iter;
 2424         int32_t cckIndex;
 2425         int16_t gainDeltaAdjust;
 2426 
 2427         HALASSERT(ah->ah_magic == AR5212_MAGIC);
 2428 
 2429         gainDeltaAdjust = ee->ee_cckOfdmGainDelta;
 2430 
 2431         /* make a local copy of desired powers as initial indices */
 2432         OS_MEMCPY(ratesIndex, ahp->ah_ratesArray, sizeof(ratesIndex));
 2433 
 2434         /* fix only the CCK indices */
 2435         for (ii = 8; ii < 15; ii++) {
 2436                 /* apply a gain_delta correction of -15 for CCK */
 2437                 ratesIndex[ii] -= gainDeltaAdjust;
 2438 
 2439                 /* Now check for contention with all ofdm target powers */
 2440                 jj = 0;
 2441                 iter = 0;
 2442                 /* indicates not all ofdm rates checked forcontention yet */
 2443                 while (jj < 16) {
 2444                         if (ratesIndex[ii] < 0)
 2445                                 ratesIndex[ii] = 0;
 2446                         if (jj == 8) {          /* skip CCK rates */
 2447                                 jj = 15;
 2448                                 continue;
 2449                         }
 2450                         if (ratesIndex[ii] == ahp->ah_ratesArray[jj]) {
 2451                                 if (ahp->ah_ratesArray[jj] == 0)
 2452                                         ratesIndex[ii]++;
 2453                                 else if (iter > 50) {
 2454                                         /*
 2455                                          * To avoid pathological case of of
 2456                                          * dm target powers 0 and 0.5dBm
 2457                                          */
 2458                                         ratesIndex[ii]++;
 2459                                 } else
 2460                                         ratesIndex[ii]--;
 2461                                 /* check with all rates again */
 2462                                 jj = 0;
 2463                                 iter++;
 2464                         } else
 2465                                 jj++;
 2466                 }
 2467                 if (ratesIndex[ii] >= PWR_TABLE_SIZE)
 2468                         ratesIndex[ii] = PWR_TABLE_SIZE -1;
 2469                 cckIndex = ahp->ah_ratesArray[ii] - twiceOfdmCckDelta;
 2470                 if (cckIndex < 0)
 2471                         cckIndex = 0;
 2472 
 2473                 /* 
 2474                  * Validate that the indexes for the powv are not
 2475                  * out of bounds.
 2476                  */
 2477                 HALASSERT(cckIndex < PWR_TABLE_SIZE);
 2478                 HALASSERT(ratesIndex[ii] < PWR_TABLE_SIZE);
 2479                 ahp->ah_pcdacTable[ratesIndex[ii]] =
 2480                         ahp->ah_pcdacTable[cckIndex];
 2481         }
 2482         /* Override rate per power table with new values */
 2483         for (ii = 8; ii < 15; ii++)
 2484                 ahp->ah_ratesArray[ii] = ratesIndex[ii];
 2485 #undef N
 2486 }
 2487 
 2488 /*
 2489  * Find the maximum conformance test limit for the given channel and CTL info
 2490  */
 2491 static uint16_t
 2492 ar5212GetMaxEdgePower(uint16_t channel, const RD_EDGES_POWER *pRdEdgesPower)
 2493 {
 2494         /* temp array for holding edge channels */
 2495         uint16_t tempChannelList[NUM_EDGES];
 2496         uint16_t clo, chi, twiceMaxEdgePower;
 2497         int i, numEdges;
 2498 
 2499         /* Get the edge power */
 2500         for (i = 0; i < NUM_EDGES; i++) {
 2501                 if (pRdEdgesPower[i].rdEdge == 0)
 2502                         break;
 2503                 tempChannelList[i] = pRdEdgesPower[i].rdEdge;
 2504         }
 2505         numEdges = i;
 2506 
 2507         ar5212GetLowerUpperValues(channel, tempChannelList,
 2508                 numEdges, &clo, &chi);
 2509         /* Get the index for the lower channel */
 2510         for (i = 0; i < numEdges && clo != tempChannelList[i]; i++)
 2511                 ;
 2512         /* Is lower channel ever outside the rdEdge? */
 2513         HALASSERT(i != numEdges);
 2514 
 2515         if ((clo == chi && clo == channel) || (pRdEdgesPower[i].flag)) {
 2516                 /* 
 2517                  * If there's an exact channel match or an inband flag set
 2518                  * on the lower channel use the given rdEdgePower 
 2519                  */
 2520                 twiceMaxEdgePower = pRdEdgesPower[i].twice_rdEdgePower;
 2521                 HALASSERT(twiceMaxEdgePower > 0);
 2522         } else
 2523                 twiceMaxEdgePower = MAX_RATE_POWER;
 2524         return twiceMaxEdgePower;
 2525 }
 2526 
 2527 /*
 2528  * Returns interpolated or the scaled up interpolated value
 2529  */
 2530 static uint16_t
 2531 interpolate(uint16_t target, uint16_t srcLeft, uint16_t srcRight,
 2532         uint16_t targetLeft, uint16_t targetRight)
 2533 {
 2534         uint16_t rv;
 2535         int16_t lRatio;
 2536 
 2537         /* to get an accurate ratio, always scale, if want to scale, then don't scale back down */
 2538         if ((targetLeft * targetRight) == 0)
 2539                 return 0;
 2540 
 2541         if (srcRight != srcLeft) {
 2542                 /*
 2543                  * Note the ratio always need to be scaled,
 2544                  * since it will be a fraction.
 2545                  */
 2546                 lRatio = (target - srcLeft) * EEP_SCALE / (srcRight - srcLeft);
 2547                 if (lRatio < 0) {
 2548                     /* Return as Left target if value would be negative */
 2549                     rv = targetLeft;
 2550                 } else if (lRatio > EEP_SCALE) {
 2551                     /* Return as Right target if Ratio is greater than 100% (SCALE) */
 2552                     rv = targetRight;
 2553                 } else {
 2554                         rv = (lRatio * targetRight + (EEP_SCALE - lRatio) *
 2555                                         targetLeft) / EEP_SCALE;
 2556                 }
 2557         } else {
 2558                 rv = targetLeft;
 2559         }
 2560         return rv;
 2561 }
 2562 
 2563 /*
 2564  * Return the four rates of target power for the given target power table 
 2565  * channel, and number of channels
 2566  */
 2567 static void
 2568 ar5212GetTargetPowers(struct ath_hal *ah, const struct ieee80211_channel *chan,
 2569         const TRGT_POWER_INFO *powInfo,
 2570         uint16_t numChannels, TRGT_POWER_INFO *pNewPower)
 2571 {
 2572         uint16_t freq = ath_hal_gethwchannel(ah, chan);
 2573         /* temp array for holding target power channels */
 2574         uint16_t tempChannelList[NUM_TEST_FREQUENCIES];
 2575         uint16_t clo, chi, ixlo, ixhi;
 2576         int i;
 2577 
 2578         /* Copy the target powers into the temp channel list */
 2579         for (i = 0; i < numChannels; i++)
 2580                 tempChannelList[i] = powInfo[i].testChannel;
 2581 
 2582         ar5212GetLowerUpperValues(freq, tempChannelList,
 2583                 numChannels, &clo, &chi);
 2584 
 2585         /* Get the indices for the channel */
 2586         ixlo = ixhi = 0;
 2587         for (i = 0; i < numChannels; i++) {
 2588                 if (clo == tempChannelList[i]) {
 2589                         ixlo = i;
 2590                 }
 2591                 if (chi == tempChannelList[i]) {
 2592                         ixhi = i;
 2593                         break;
 2594                 }
 2595         }
 2596 
 2597         /*
 2598          * Get the lower and upper channels, target powers,
 2599          * and interpolate between them.
 2600          */
 2601         pNewPower->twicePwr6_24 = interpolate(freq, clo, chi,
 2602                 powInfo[ixlo].twicePwr6_24, powInfo[ixhi].twicePwr6_24);
 2603         pNewPower->twicePwr36 = interpolate(freq, clo, chi,
 2604                 powInfo[ixlo].twicePwr36, powInfo[ixhi].twicePwr36);
 2605         pNewPower->twicePwr48 = interpolate(freq, clo, chi,
 2606                 powInfo[ixlo].twicePwr48, powInfo[ixhi].twicePwr48);
 2607         pNewPower->twicePwr54 = interpolate(freq, clo, chi,
 2608                 powInfo[ixlo].twicePwr54, powInfo[ixhi].twicePwr54);
 2609 }
 2610 
 2611 static uint32_t
 2612 udiff(uint32_t u, uint32_t v)
 2613 {
 2614         return (u >= v ? u - v : v - u);
 2615 }
 2616 
 2617 /*
 2618  * Search a list for a specified value v that is within
 2619  * EEP_DELTA of the search values.  Return the closest
 2620  * values in the list above and below the desired value.
 2621  * EEP_DELTA is a factional value; everything is scaled
 2622  * so only integer arithmetic is used.
 2623  *
 2624  * NB: the input list is assumed to be sorted in ascending order
 2625  */
 2626 void
 2627 ar5212GetLowerUpperValues(uint16_t v, uint16_t *lp, uint16_t listSize,
 2628                           uint16_t *vlo, uint16_t *vhi)
 2629 {
 2630         uint32_t target = v * EEP_SCALE;
 2631         uint16_t *ep = lp+listSize;
 2632 
 2633         /*
 2634          * Check first and last elements for out-of-bounds conditions.
 2635          */
 2636         if (target < (uint32_t)(lp[0] * EEP_SCALE - EEP_DELTA)) {
 2637                 *vlo = *vhi = lp[0];
 2638                 return;
 2639         }
 2640         if (target > (uint32_t)(ep[-1] * EEP_SCALE + EEP_DELTA)) {
 2641                 *vlo = *vhi = ep[-1];
 2642                 return;
 2643         }
 2644 
 2645         /* look for value being near or between 2 values in list */
 2646         for (; lp < ep; lp++) {
 2647                 /*
 2648                  * If value is close to the current value of the list
 2649                  * then target is not between values, it is one of the values
 2650                  */
 2651                 if (udiff(lp[0] * EEP_SCALE, target) < EEP_DELTA) {
 2652                         *vlo = *vhi = lp[0];
 2653                         return;
 2654                 }
 2655                 /*
 2656                  * Look for value being between current value and next value
 2657                  * if so return these 2 values
 2658                  */
 2659                 if (target < (uint32_t)(lp[1] * EEP_SCALE - EEP_DELTA)) {
 2660                         *vlo = lp[0];
 2661                         *vhi = lp[1];
 2662                         return;
 2663                 }
 2664         }
 2665         HALASSERT(AH_FALSE);            /* should not reach here */
 2666 }
 2667 
 2668 /*
 2669  * Perform analog "swizzling" of parameters into their location
 2670  *
 2671  * NB: used by RF backends
 2672  */
 2673 void
 2674 ar5212ModifyRfBuffer(uint32_t *rfBuf, uint32_t reg32, uint32_t numBits,
 2675                      uint32_t firstBit, uint32_t column)
 2676 {
 2677 #define MAX_ANALOG_START        319             /* XXX */
 2678         uint32_t tmp32, mask, arrayEntry, lastBit;
 2679         int32_t bitPosition, bitsLeft;
 2680 
 2681         HALASSERT(column <= 3);
 2682         HALASSERT(numBits <= 32);
 2683         HALASSERT(firstBit + numBits <= MAX_ANALOG_START);
 2684 
 2685         tmp32 = ath_hal_reverseBits(reg32, numBits);
 2686         arrayEntry = (firstBit - 1) / 8;
 2687         bitPosition = (firstBit - 1) % 8;
 2688         bitsLeft = numBits;
 2689         while (bitsLeft > 0) {
 2690                 lastBit = (bitPosition + bitsLeft > 8) ?
 2691                         8 : bitPosition + bitsLeft;
 2692                 mask = (((1 << lastBit) - 1) ^ ((1 << bitPosition) - 1)) <<
 2693                         (column * 8);
 2694                 rfBuf[arrayEntry] &= ~mask;
 2695                 rfBuf[arrayEntry] |= ((tmp32 << bitPosition) <<
 2696                         (column * 8)) & mask;
 2697                 bitsLeft -= 8 - bitPosition;
 2698                 tmp32 = tmp32 >> (8 - bitPosition);
 2699                 bitPosition = 0;
 2700                 arrayEntry++;
 2701         }
 2702 #undef MAX_ANALOG_START
 2703 }
 2704 
 2705 /*
 2706  * Sets the rate to duration values in MAC - used for multi-
 2707  * rate retry.
 2708  * The rate duration table needs to cover all valid rate codes;
 2709  * the 11g table covers all ofdm rates, while the 11b table
 2710  * covers all cck rates => all valid rates get covered between
 2711  * these two mode's ratetables!
 2712  * But if we're turbo, the ofdm phy is replaced by the turbo phy
 2713  * and cck is not valid with turbo => all rates get covered
 2714  * by the turbo ratetable only
 2715  */
 2716 void
 2717 ar5212SetRateDurationTable(struct ath_hal *ah,
 2718         const struct ieee80211_channel *chan)
 2719 {
 2720         const HAL_RATE_TABLE *rt;
 2721         int i;
 2722 
 2723         /* NB: band doesn't matter for 1/2 and 1/4 rate */
 2724         if (IEEE80211_IS_CHAN_HALF(chan)) {
 2725                 rt = ar5212GetRateTable(ah, HAL_MODE_11A_HALF_RATE);
 2726         } else if (IEEE80211_IS_CHAN_QUARTER(chan)) {
 2727                 rt = ar5212GetRateTable(ah, HAL_MODE_11A_QUARTER_RATE);
 2728         } else {
 2729                 rt = ar5212GetRateTable(ah,
 2730                         IEEE80211_IS_CHAN_TURBO(chan) ? HAL_MODE_TURBO : HAL_MODE_11G);
 2731         }
 2732 
 2733         for (i = 0; i < rt->rateCount; ++i)
 2734                 OS_REG_WRITE(ah,
 2735                         AR_RATE_DURATION(rt->info[i].rateCode),
 2736                         ath_hal_computetxtime(ah, rt,
 2737                                 WLAN_CTRL_FRAME_SIZE,
 2738                                 rt->info[i].controlRate, AH_FALSE, AH_TRUE));
 2739         if (!IEEE80211_IS_CHAN_TURBO(chan)) {
 2740                 /* 11g Table is used to cover the CCK rates. */
 2741                 rt = ar5212GetRateTable(ah, HAL_MODE_11G);
 2742                 for (i = 0; i < rt->rateCount; ++i) {
 2743                         uint32_t reg = AR_RATE_DURATION(rt->info[i].rateCode);
 2744 
 2745                         if (rt->info[i].phy != IEEE80211_T_CCK)
 2746                                 continue;
 2747 
 2748                         OS_REG_WRITE(ah, reg,
 2749                                 ath_hal_computetxtime(ah, rt,
 2750                                         WLAN_CTRL_FRAME_SIZE,
 2751                                         rt->info[i].controlRate, AH_FALSE,
 2752                                         AH_TRUE));
 2753                         /* cck rates have short preamble option also */
 2754                         if (rt->info[i].shortPreamble) {
 2755                                 reg += rt->info[i].shortPreamble << 2;
 2756                                 OS_REG_WRITE(ah, reg,
 2757                                         ath_hal_computetxtime(ah, rt,
 2758                                                 WLAN_CTRL_FRAME_SIZE,
 2759                                                 rt->info[i].controlRate,
 2760                                                 AH_TRUE, AH_TRUE));
 2761                         }
 2762                 }
 2763         }
 2764 }
 2765 
 2766 /* Adjust various register settings based on half/quarter rate clock setting.
 2767  * This includes: +USEC, TX/RX latency, 
 2768  *                + IFS params: slot, eifs, misc etc.
 2769  */
 2770 void 
 2771 ar5212SetIFSTiming(struct ath_hal *ah, const struct ieee80211_channel *chan)
 2772 {
 2773         uint32_t txLat, rxLat, usec, slot, refClock, eifs, init_usec;
 2774 
 2775         HALASSERT(IEEE80211_IS_CHAN_HALF(chan) ||
 2776                   IEEE80211_IS_CHAN_QUARTER(chan));
 2777 
 2778         refClock = OS_REG_READ(ah, AR_USEC) & AR_USEC_USEC32;
 2779         if (IEEE80211_IS_CHAN_HALF(chan)) {
 2780                 slot = IFS_SLOT_HALF_RATE;
 2781                 rxLat = RX_NON_FULL_RATE_LATENCY << AR5212_USEC_RX_LAT_S;
 2782                 txLat = TX_HALF_RATE_LATENCY << AR5212_USEC_TX_LAT_S;
 2783                 usec = HALF_RATE_USEC;
 2784                 eifs = IFS_EIFS_HALF_RATE;
 2785                 init_usec = INIT_USEC >> 1;
 2786         } else { /* quarter rate */
 2787                 slot = IFS_SLOT_QUARTER_RATE;
 2788                 rxLat = RX_NON_FULL_RATE_LATENCY << AR5212_USEC_RX_LAT_S;
 2789                 txLat = TX_QUARTER_RATE_LATENCY << AR5212_USEC_TX_LAT_S;
 2790                 usec = QUARTER_RATE_USEC;
 2791                 eifs = IFS_EIFS_QUARTER_RATE;
 2792                 init_usec = INIT_USEC >> 2;
 2793         }
 2794 
 2795         OS_REG_WRITE(ah, AR_USEC, (usec | refClock | txLat | rxLat));
 2796         OS_REG_WRITE(ah, AR_D_GBL_IFS_SLOT, slot);
 2797         OS_REG_WRITE(ah, AR_D_GBL_IFS_EIFS, eifs);
 2798         OS_REG_RMW_FIELD(ah, AR_D_GBL_IFS_MISC,
 2799                                 AR_D_GBL_IFS_MISC_USEC_DURATION, init_usec);
 2800 }

Cache object: 1dc48d81aeb206838f9d85d82e210c31


[ 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.