Exemplo n.º 1
0
static void
ar5416AniCckErrTrigger(struct ath_hal *ah)
{
	struct ath_hal_5212 *ahp = AH5212(ah);
	const struct ieee80211_channel *chan = AH_PRIVATE(ah)->ah_curchan;
	struct ar5212AniState *aniState;
	const struct ar5212AniParams *params;

	HALASSERT(chan != AH_NULL);

	if (!ANI_ENA(ah))
		return;

	/* first, raise noise immunity level, up to max */
	aniState = ahp->ah_curani;
	params = aniState->params;
	if ((AH5416(ah)->ah_ani_function & (1 << HAL_ANI_NOISE_IMMUNITY_LEVEL) &&
	    aniState->noiseImmunityLevel+1 < params->maxNoiseImmunityLevel)) {
		ar5416AniControl(ah, HAL_ANI_NOISE_IMMUNITY_LEVEL,
				 aniState->noiseImmunityLevel + 1);
		return;
	}

	if (ANI_ENA_RSSI(ah)) {
		int32_t rssi = BEACON_RSSI(ahp);
		if (rssi >  params->rssiThrLow) {
			/*
			 * Beacon signal in mid and high range,
			 * raise firstep level.
			 */
			if (aniState->firstepLevel+1 < params->maxFirstepLevel)
				ar5416AniControl(ah, HAL_ANI_FIRSTEP_LEVEL,
						 aniState->firstepLevel + 1);
		} else {
			/*
			 * Beacon rssi is low, zero firstep level to maximize
			 * CCK sensitivity in 11b/g mode.
			 */
			if (IEEE80211_IS_CHAN_CCK(chan)) {
				if (aniState->firstepLevel > 0)
					ar5416AniControl(ah,
					    HAL_ANI_FIRSTEP_LEVEL, 0);
			}
		}
	}
}
Exemplo n.º 2
0
/*
 * Sets the transmit power in the baseband for the given
 * operating channel and mode.
 */
static HAL_BOOL
setRateTable(struct ath_hal *ah, const struct ieee80211_channel *chan, 
		   int16_t tpcScaleReduction, int16_t powerLimit,
                   int16_t *pMinPower, int16_t *pMaxPower)
{
	u_int16_t ratesArray[16];
	u_int16_t *rpow = ratesArray;
	u_int16_t twiceMaxRDPower, twiceMaxEdgePower, twiceMaxEdgePowerCck;
	int8_t twiceAntennaGain, twiceAntennaReduction;
	TRGT_POWER_INFO targetPowerOfdm, targetPowerCck;
	RD_EDGES_POWER *rep;
	int16_t scaledPower;
	u_int8_t cfgCtl;

	twiceMaxRDPower = chan->ic_maxregpower * 2;
	*pMaxPower = -MAX_RATE_POWER;
	*pMinPower = MAX_RATE_POWER;

	/* Get conformance test limit maximum for this channel */
	cfgCtl = ath_hal_getctl(ah, chan);
	rep = findEdgePower(ah, cfgCtl);
	if (rep != AH_NULL)
		twiceMaxEdgePower = ar5212GetMaxEdgePower(chan->ic_freq, rep);
	else
		twiceMaxEdgePower = MAX_RATE_POWER;

	if (IEEE80211_IS_CHAN_G(chan)) {
		/* Check for a CCK CTL for 11G CCK powers */
		cfgCtl = (cfgCtl & 0xFC) | 0x01;
		rep = findEdgePower(ah, cfgCtl);
		if (rep != AH_NULL)
			twiceMaxEdgePowerCck = ar5212GetMaxEdgePower(chan->ic_freq, rep);
		else
			twiceMaxEdgePowerCck = MAX_RATE_POWER;
	} else {
		/* Set the 11B cck edge power to the one found before */
		twiceMaxEdgePowerCck = twiceMaxEdgePower;
	}

	/* Get Antenna Gain reduction */
	if (IEEE80211_IS_CHAN_5GHZ(chan)) {
		twiceAntennaGain = antennaGainMax[0];
	} else {
		twiceAntennaGain = antennaGainMax[1];
	}
	twiceAntennaReduction =
		ath_hal_getantennareduction(ah, chan, twiceAntennaGain);

	if (IEEE80211_IS_CHAN_OFDM(chan)) {
		/* Get final OFDM target powers */
		if (IEEE80211_IS_CHAN_G(chan)) { 
			/* TODO - add Turbo 2.4 to this mode check */
			ar5212GetTargetPowers(ah, chan, trgtPwr_11g,
				numTargetPwr_11g, &targetPowerOfdm);
		} else {
			ar5212GetTargetPowers(ah, chan, trgtPwr_11a,
				numTargetPwr_11a, &targetPowerOfdm);
		}

		/* Get Maximum OFDM power */
		/* Minimum of target and edge powers */
		scaledPower = AH_MIN(twiceMaxEdgePower,
				twiceMaxRDPower - twiceAntennaReduction);

		/*
		 * If turbo is set, reduce power to keep power
		 * consumption under 2 Watts.  Note that we always do
		 * this unless specially configured.  Then we limit
		 * power only for non-AP operation.
		 */
		if (IEEE80211_IS_CHAN_TURBO(chan)
#ifdef AH_ENABLE_AP_SUPPORT
		    && AH_PRIVATE(ah)->ah_opmode != HAL_M_HOSTAP
#endif
		) {
			/*
			 * If turbo is set, reduce power to keep power
			 * consumption under 2 Watts
			 */
			if (eeversion >= AR_EEPROM_VER3_1)
				scaledPower = AH_MIN(scaledPower,
					turbo2WMaxPower5);
			/*
			 * EEPROM version 4.0 added an additional
			 * constraint on 2.4GHz channels.
			 */
			if (eeversion >= AR_EEPROM_VER4_0 &&
			    IEEE80211_IS_CHAN_2GHZ(chan))
				scaledPower = AH_MIN(scaledPower,
					turbo2WMaxPower2);
		}
		/* Reduce power by max regulatory domain allowed restrictions */
		scaledPower -= (tpcScaleReduction * 2);
		scaledPower = (scaledPower < 0) ? 0 : scaledPower;
		scaledPower = AH_MIN(scaledPower, powerLimit);

		scaledPower = AH_MIN(scaledPower, targetPowerOfdm.twicePwr6_24);

		/* Set OFDM rates 9, 12, 18, 24, 36, 48, 54, XR */
		rpow[0] = rpow[1] = rpow[2] = rpow[3] = rpow[4] = scaledPower;
		rpow[5] = AH_MIN(rpow[0], targetPowerOfdm.twicePwr36);
		rpow[6] = AH_MIN(rpow[0], targetPowerOfdm.twicePwr48);
		rpow[7] = AH_MIN(rpow[0], targetPowerOfdm.twicePwr54);

#ifdef notyet
		if (eeversion >= AR_EEPROM_VER4_0) {
			/* Setup XR target power from EEPROM */
			rpow[15] = AH_MIN(scaledPower, IS_CHAN_2GHZ(chan) ?
				xrTargetPower2 : xrTargetPower5);
		} else {
			/* XR uses 6mb power */
			rpow[15] = rpow[0];
		}
#else
		rpow[15] = rpow[0];
#endif

		*pMinPower = rpow[7];
		*pMaxPower = rpow[0];

#if 0
		ahp->ah_ofdmTxPower = rpow[0];
#endif

		HALDEBUG(ah, HAL_DEBUG_ANY,
		    "%s: MaxRD: %d TurboMax: %d MaxCTL: %d "
		    "TPC_Reduction %d\n", __func__,
		    twiceMaxRDPower, turbo2WMaxPower5,
		    twiceMaxEdgePower, tpcScaleReduction * 2);
	}

	if (IEEE80211_IS_CHAN_CCK(chan)) {
		/* Get final CCK target powers */
		ar5212GetTargetPowers(ah, chan, trgtPwr_11b,
			numTargetPwr_11b, &targetPowerCck);

		/* Reduce power by max regulatory domain allowed restrictions */
		scaledPower = AH_MIN(twiceMaxEdgePowerCck,
			twiceMaxRDPower - twiceAntennaReduction);

		scaledPower -= (tpcScaleReduction * 2);
		scaledPower = (scaledPower < 0) ? 0 : scaledPower;
		scaledPower = AH_MIN(scaledPower, powerLimit);

		rpow[8] = (scaledPower < 1) ? 1 : scaledPower;

		/* Set CCK rates 2L, 2S, 5.5L, 5.5S, 11L, 11S */
		rpow[8]  = AH_MIN(scaledPower, targetPowerCck.twicePwr6_24);
		rpow[9]  = AH_MIN(scaledPower, targetPowerCck.twicePwr36);
		rpow[10] = rpow[9];
		rpow[11] = AH_MIN(scaledPower, targetPowerCck.twicePwr48);
		rpow[12] = rpow[11];
		rpow[13] = AH_MIN(scaledPower, targetPowerCck.twicePwr54);
		rpow[14] = rpow[13];

		/* Set min/max power based off OFDM values or initialization */
		if (rpow[13] < *pMinPower)
		    *pMinPower = rpow[13];
		if (rpow[9] > *pMaxPower)
		    *pMaxPower = rpow[9];

	}
#if 0
	ahp->ah_tx6PowerInHalfDbm = *pMaxPower;
#endif
	return AH_TRUE;
}
Exemplo n.º 3
0
static void
ar5416AniOfdmErrTrigger(struct ath_hal *ah)
{
	struct ath_hal_5212 *ahp = AH5212(ah);
	const struct ieee80211_channel *chan = AH_PRIVATE(ah)->ah_curchan;
	struct ar5212AniState *aniState;
	const struct ar5212AniParams *params;

	HALASSERT(chan != AH_NULL);

	if (!ANI_ENA(ah))
		return;

	aniState = ahp->ah_curani;
	params = aniState->params;
	/* First, raise noise immunity level, up to max */
	if (aniState->noiseImmunityLevel+1 < params->maxNoiseImmunityLevel) {
		ar5416AniControl(ah, HAL_ANI_NOISE_IMMUNITY_LEVEL, 
				 aniState->noiseImmunityLevel + 1);
		return;
	}
	/* then, raise spur immunity level, up to max */
	if (aniState->spurImmunityLevel+1 < params->maxSpurImmunityLevel) {
		ar5416AniControl(ah, HAL_ANI_SPUR_IMMUNITY_LEVEL,
				 aniState->spurImmunityLevel + 1);
		return;
	}

	if (ANI_ENA_RSSI(ah)) {
		int32_t rssi = BEACON_RSSI(ahp);
		if (rssi > params->rssiThrHigh) {
			/*
			 * Beacon rssi is high, can turn off ofdm
			 * weak sig detect.
			 */
			if (!aniState->ofdmWeakSigDetectOff) {
				ar5416AniControl(ah,
				    HAL_ANI_OFDM_WEAK_SIGNAL_DETECTION,
				    AH_FALSE);
				ar5416AniControl(ah,
				    HAL_ANI_SPUR_IMMUNITY_LEVEL, 0);
				return;
			}
			/* 
			 * If weak sig detect is already off, as last resort,
			 * raise firstep level 
			 */
			if (aniState->firstepLevel+1 < params->maxFirstepLevel) {
				ar5416AniControl(ah, HAL_ANI_FIRSTEP_LEVEL,
						 aniState->firstepLevel + 1);
				return;
			}
		} else if (rssi > params->rssiThrLow) {
			/* 
			 * Beacon rssi in mid range, need ofdm weak signal
			 * detect, but we can raise firststepLevel.
			 */
			if (aniState->ofdmWeakSigDetectOff)
				ar5416AniControl(ah,
				    HAL_ANI_OFDM_WEAK_SIGNAL_DETECTION,
				    AH_TRUE);
			if (aniState->firstepLevel+1 < params->maxFirstepLevel)
				ar5416AniControl(ah, HAL_ANI_FIRSTEP_LEVEL,
				     aniState->firstepLevel + 1);
			return;
		} else {
			/* 
			 * Beacon rssi is low, if in 11b/g mode, turn off ofdm
			 * weak signal detection and zero firstepLevel to
			 * maximize CCK sensitivity 
			 */
			if (IEEE80211_IS_CHAN_CCK(chan)) {
				if (!aniState->ofdmWeakSigDetectOff)
					ar5416AniControl(ah,
					    HAL_ANI_OFDM_WEAK_SIGNAL_DETECTION,
					    AH_FALSE);
				if (aniState->firstepLevel > 0)
					ar5416AniControl(ah,
					     HAL_ANI_FIRSTEP_LEVEL, 0);
				return;
			}
		}
	}
}
Exemplo n.º 4
0
/*
 * Places the hardware into reset and then pulls it out of reset
 *
 * TODO: Only write the PLL if we're changing to or from CCK mode
 * 
 * WARNING: The order of the PLL and mode registers must be correct.
 */
HAL_BOOL
ar5312ChipReset(struct ath_hal *ah, const struct ieee80211_channel *chan)
{

	OS_MARK(ah, AH_MARK_CHIPRESET, chan ? chan->ic_freq : 0);

	/*
	 * Reset the HW 
	 */
	if (!ar5312SetResetReg(ah, AR_RC_MAC | AR_RC_BB)) {
		HALDEBUG(ah, HAL_DEBUG_ANY, "%s: ar5312SetResetReg failed\n",
		    __func__);
		return AH_FALSE;
	}

	/* Bring out of sleep mode (AGAIN) */
	if (!ar5312SetPowerMode(ah, HAL_PM_AWAKE, AH_TRUE)) {
		HALDEBUG(ah, HAL_DEBUG_ANY, "%s: ar5312SetPowerMode failed\n",
		    __func__);
		return AH_FALSE;
	}

	/* Clear warm reset register */
	if (!ar5312SetResetReg(ah, 0)) {
		HALDEBUG(ah, HAL_DEBUG_ANY, "%s: ar5312SetResetReg failed\n",
		    __func__);
		return AH_FALSE;
	}

	/*
	 * Perform warm reset before the mode/PLL/turbo registers
	 * are changed in order to deactivate the radio.  Mode changes
	 * with an active radio can result in corrupted shifts to the
	 * radio device.
	 */

	/*
	 * Set CCK and Turbo modes correctly.
	 */
	if (chan != AH_NULL) {		/* NB: can be null during attach */
		uint32_t rfMode, phyPLL = 0, curPhyPLL, turbo;

		if (IS_RAD5112_ANY(ah)) {
			rfMode = AR_PHY_MODE_AR5112;
			if (!IS_5315(ah)) {
				if (IEEE80211_IS_CHAN_CCK(chan)) {
					phyPLL = AR_PHY_PLL_CTL_44_5312;
				} else {
					if (IEEE80211_IS_CHAN_HALF(chan)) {
						phyPLL = AR_PHY_PLL_CTL_40_5312_HALF;
					} else if (IEEE80211_IS_CHAN_QUARTER(chan)) {
						phyPLL = AR_PHY_PLL_CTL_40_5312_QUARTER;
					} else {
						phyPLL = AR_PHY_PLL_CTL_40_5312;
					}
				}
			} else {
				if (IEEE80211_IS_CHAN_CCK(chan))
					phyPLL = AR_PHY_PLL_CTL_44_5112;
				else
					phyPLL = AR_PHY_PLL_CTL_40_5112;
				if (IEEE80211_IS_CHAN_HALF(chan))
					phyPLL |= AR_PHY_PLL_CTL_HALF;
				else if (IEEE80211_IS_CHAN_QUARTER(chan))
					phyPLL |= AR_PHY_PLL_CTL_QUARTER;
			}
		} else {
			rfMode = AR_PHY_MODE_AR5111;
			if (IEEE80211_IS_CHAN_CCK(chan))
				phyPLL = AR_PHY_PLL_CTL_44;
			else
				phyPLL = AR_PHY_PLL_CTL_40;
			if (IEEE80211_IS_CHAN_HALF(chan))
				phyPLL = AR_PHY_PLL_CTL_HALF;
			else if (IEEE80211_IS_CHAN_QUARTER(chan))
				phyPLL = AR_PHY_PLL_CTL_QUARTER;
		}
		if (IEEE80211_IS_CHAN_G(chan))
			rfMode |= AR_PHY_MODE_DYNAMIC;
		else if (IEEE80211_IS_CHAN_OFDM(chan))
			rfMode |= AR_PHY_MODE_OFDM;
		else
			rfMode |= AR_PHY_MODE_CCK;
		if (IEEE80211_IS_CHAN_5GHZ(chan))
			rfMode |= AR_PHY_MODE_RF5GHZ;
		else
			rfMode |= AR_PHY_MODE_RF2GHZ;
		turbo = IEEE80211_IS_CHAN_TURBO(chan) ?
			(AR_PHY_FC_TURBO_MODE | AR_PHY_FC_TURBO_SHORT) : 0;
		curPhyPLL = OS_REG_READ(ah, AR_PHY_PLL_CTL);
		/*
		 * PLL, Mode, and Turbo values must be written in the correct
		 * order to ensure:
		 * - The PLL cannot be set to 44 unless the CCK or DYNAMIC
		 *   mode bit is set
		 * - Turbo cannot be set at the same time as CCK or DYNAMIC
		 */
		if (IEEE80211_IS_CHAN_CCK(chan)) {
			OS_REG_WRITE(ah, AR_PHY_TURBO, turbo);
			OS_REG_WRITE(ah, AR_PHY_MODE, rfMode);
			if (curPhyPLL != phyPLL) {
				OS_REG_WRITE(ah,  AR_PHY_PLL_CTL,  phyPLL);
				/* Wait for the PLL to settle */
				OS_DELAY(PLL_SETTLE_DELAY);
			}
		} else {
			if (curPhyPLL != phyPLL) {
				OS_REG_WRITE(ah,  AR_PHY_PLL_CTL,  phyPLL);
				/* Wait for the PLL to settle */
				OS_DELAY(PLL_SETTLE_DELAY);
			}
			OS_REG_WRITE(ah, AR_PHY_TURBO, turbo);
			OS_REG_WRITE(ah, AR_PHY_MODE, rfMode);
		}
	}
	return AH_TRUE;
}