コード例 #1
0
/*
 * Do periodic processing.  This routine is called from the
 * driver's rx interrupt handler after processing frames.
 */
void
ar5212AniPoll(struct ath_hal *ah, const struct ieee80211_channel *chan)
{
	struct ath_hal_5212 *ahp = AH5212(ah);
	struct ar5212AniState *aniState = ahp->ah_curani;
	const struct ar5212AniParams *params;
	int32_t listenTime;

	/* XXX can aniState be null? */
	if (aniState == AH_NULL)
		return;
	if (!ANI_ENA(ah))
		return;

	listenTime = ar5212AniGetListenTime(ah);
	if (listenTime < 0) {
		ahp->ah_stats.ast_ani_lneg++;
		/* restart ANI period if listenTime is invalid */
		ar5212AniRestart(ah, aniState);
	}
	/* XXX beware of overflow? */
	aniState->listenTime += listenTime;

	OS_MARK(ah, AH_MARK_ANI_POLL, aniState->listenTime);

	params = aniState->params;
	if (aniState->listenTime > 5*params->period) {
		/* 
		 * Check to see if need to lower immunity if
		 * 5 aniPeriods have passed
		 */
		if (ahp->ah_hasHwPhyCounters)
			updateMIBStats(ah, aniState);
		if (aniState->ofdmPhyErrCount <= aniState->listenTime *
		    params->ofdmTrigLow/1000 &&
		    aniState->cckPhyErrCount <= aniState->listenTime *
		    params->cckTrigLow/1000)
			ar5212AniLowerImmunity(ah);
		ar5212AniRestart(ah, aniState);
	} else if (aniState->listenTime > params->period) {
		if (ahp->ah_hasHwPhyCounters)
			updateMIBStats(ah, aniState);
		/* check to see if need to raise immunity */
		if (aniState->ofdmPhyErrCount > aniState->listenTime *
		    params->ofdmTrigHigh / 1000) {
			HALDEBUG(ah, HAL_DEBUG_ANI,
			    "%s: OFDM err %u listenTime %u\n", __func__,
			    aniState->ofdmPhyErrCount, aniState->listenTime);
			ar5212AniOfdmErrTrigger(ah);
			ar5212AniRestart(ah, aniState);
		} else if (aniState->cckPhyErrCount > aniState->listenTime *
			   params->cckTrigHigh / 1000) {
			HALDEBUG(ah, HAL_DEBUG_ANI,
			    "%s: CCK err %u listenTime %u\n", __func__,
			    aniState->cckPhyErrCount, aniState->listenTime);
			ar5212AniCckErrTrigger(ah);
			ar5212AniRestart(ah, aniState);
		}
	}
}
コード例 #2
0
ファイル: ar5212_ani.c プロジェクト: ele7enxxh/dtrace-pf
static void
ar5212AniCckErrTrigger(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 (aniState->noiseImmunityLevel+1 <= params->maxNoiseImmunityLevel) {
		HALDEBUG(ah, HAL_DEBUG_ANI, "%s: raise NI to %u\n", __func__,
		    aniState->noiseImmunityLevel + 1);
		ar5212AniControl(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) {
				HALDEBUG(ah, HAL_DEBUG_ANI,
				    "%s: rssi %d raise ST %u\n", __func__, rssi,
				    aniState->firstepLevel+1);
				ar5212AniControl(ah, HAL_ANI_FIRSTEP_LEVEL,
						 aniState->firstepLevel + 1);
			}
		} else {
			/*
			 * Beacon rssi is low, zero firstep level to maximize
			 * CCK sensitivity in 11b/g mode.
			 */
			/* XXX can optimize */
			if (IEEE80211_IS_CHAN_B(chan) ||
			    IEEE80211_IS_CHAN_G(chan)) {
				if (aniState->firstepLevel > 0) {
					HALDEBUG(ah, HAL_DEBUG_ANI,
					    "%s: rssi %d zero ST (was %u)\n",
					    __func__, rssi,
					    aniState->firstepLevel);
					ar5212AniControl(ah,
					    HAL_ANI_FIRSTEP_LEVEL, 0);
				}
			}
		}
	}
}
コード例 #3
0
ファイル: ar5416_ani.c プロジェクト: HWL-RobAt/madwifi
/*
 * Do periodic processing.  This routine is called from the
 * driver's rx interrupt handler after processing frames.
 */
void
ar5416AniPoll(struct ath_hal *ah, const HAL_NODE_STATS *stats,
		HAL_CHANNEL *chan)
{
	struct ath_hal_5212 *ahp = AH5212(ah);
	struct ar5212AniState *aniState = ahp->ah_curani;
	const struct ar5212AniParams *params;
	int32_t listenTime;

	ahp->ah_stats.ast_nodestats.ns_avgbrssi = stats->ns_avgbrssi;

	/* XXX can aniState be null? */
	if (aniState == AH_NULL)
		return;
	if (!ANI_ENA(ah))
		return;

	listenTime = ar5416AniGetListenTime(ah);
	if (listenTime < 0) {
		ahp->ah_stats.ast_ani_lneg++;
		/* restart ANI period if listenTime is invalid */
		ar5416AniRestart(ah, aniState);
	}
	/* XXX beware of overflow? */
	aniState->listenTime += listenTime;

	OS_MARK(ah, AH_MARK_ANI_POLL, aniState->listenTime);

	params = aniState->params;
	if (aniState->listenTime > 5*params->period) {
		/* 
		 * Check to see if need to lower immunity if
		 * 5 aniPeriods have passed
		 */
		updateMIBStats(ah, aniState);
		if (aniState->ofdmPhyErrCount <= aniState->listenTime *
		    params->ofdmTrigLow/1000 &&
		    aniState->cckPhyErrCount <= aniState->listenTime *
		    params->cckTrigLow/1000)
			ar5416AniLowerImmunity(ah);
		ar5416AniRestart(ah, aniState);
	} else if (aniState->listenTime > params->period) {
		updateMIBStats(ah, aniState);
		/* check to see if need to raise immunity */
		if (aniState->ofdmPhyErrCount > aniState->listenTime *
		    params->ofdmTrigHigh / 1000) {
			ar5416AniOfdmErrTrigger(ah);
			ar5416AniRestart(ah, aniState);
		} else if (aniState->cckPhyErrCount > aniState->listenTime *
			   params->cckTrigHigh / 1000) {
			ar5416AniCckErrTrigger(ah);
			ar5416AniRestart(ah, aniState);
		}
	}
}
コード例 #4
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);
			}
		}
	}
}
コード例 #5
0
ファイル: ar5416_ani.c プロジェクト: juanfra684/DragonFlyBSD
static void
ar5416AniLowerImmunity(struct ath_hal *ah)
{
	struct ath_hal_5212 *ahp = AH5212(ah);
	struct ar5212AniState *aniState;
	const struct ar5212AniParams *params;
	
	HALASSERT(ANI_ENA(ah));

	aniState = ahp->ah_curani;
	params = aniState->params;
	if (ANI_ENA_RSSI(ah)) {
		int32_t rssi = BEACON_RSSI(ahp);
		if (rssi > params->rssiThrHigh) {
			/* 
			 * Beacon signal is high, leave ofdm weak signal
			 * detection off or it may oscillate.  Let it fall
			 * through.
			 */
		} else if (rssi > params->rssiThrLow) {
			/*
			 * Beacon rssi in mid range, turn on ofdm weak signal
			 * detection or lower firstep level.
			 */
			if (aniState->ofdmWeakSigDetectOff) {
				ar5416AniControl(ah,
				    HAL_ANI_OFDM_WEAK_SIGNAL_DETECTION,
				    AH_TRUE);
				return;
			}
			if (aniState->firstepLevel > 0) {
				ar5416AniControl(ah, HAL_ANI_FIRSTEP_LEVEL,
						 aniState->firstepLevel - 1);
				return;
			}
		} else {
			/*
			 * Beacon rssi is low, reduce firstep level.
			 */
			if (aniState->firstepLevel > 0) {
				ar5416AniControl(ah, HAL_ANI_FIRSTEP_LEVEL,
						 aniState->firstepLevel - 1);
				return;
			}
		}
	}
	/* then lower spur immunity level, down to zero */
	if (aniState->spurImmunityLevel > 0) {
		ar5416AniControl(ah, HAL_ANI_SPUR_IMMUNITY_LEVEL,
				 aniState->spurImmunityLevel - 1);
		return;
	}
	/* 
	 * if all else fails, lower noise immunity level down to a min value
	 * zero for now
	 */
	if (aniState->noiseImmunityLevel > 0) {
		ar5416AniControl(ah, HAL_ANI_NOISE_IMMUNITY_LEVEL,
				 aniState->noiseImmunityLevel - 1);
		return;
	}
}
コード例 #6
0
ファイル: ar5416_ani.c プロジェクト: juanfra684/DragonFlyBSD
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;
			}
		}
	}
}
コード例 #7
0
ファイル: ar5212_ani.c プロジェクト: ele7enxxh/dtrace-pf
/* 
 * Return an approximation of the time spent ``listening'' by
 * deducting the cycles spent tx'ing and rx'ing from the total
 * cycle count since our last call.  A return value <0 indicates
 * an invalid/inconsistent time.
 */
static int32_t
ar5212AniGetListenTime(struct ath_hal *ah)
{
	struct ath_hal_5212 *ahp = AH5212(ah);
	struct ar5212AniState *aniState = NULL;
	int32_t listenTime = 0;
	int good;
	HAL_SURVEY_SAMPLE hs;
	HAL_CHANNEL_SURVEY *cs = AH_NULL;

	/*
	 * We shouldn't see ah_curchan be NULL, but just in case..
	 */
	if (AH_PRIVATE(ah)->ah_curchan == AH_NULL) {
		ath_hal_printf(ah, "%s: ah_curchan = NULL?\n", __func__);
		return (0);
	}

	cs = &ahp->ah_chansurvey;

	/*
	 * Fetch the current statistics, squirrel away the current
	 * sample, bump the sequence/sample counter.
	 */
	OS_MEMZERO(&hs, sizeof(hs));
	good = ar5212GetMibCycleCounts(ah, &hs);
	if (cs != AH_NULL) {
		OS_MEMCPY(&cs->samples[cs->cur_sample], &hs, sizeof(hs));
		cs->samples[cs->cur_sample].seq_num = cs->cur_seq;
		cs->cur_sample =
		    (cs->cur_sample + 1) % CHANNEL_SURVEY_SAMPLE_COUNT;
		cs->cur_seq++;
	}

	if (ANI_ENA(ah))
		aniState = ahp->ah_curani;

	if (good == AH_FALSE) {
		/*
		 * Cycle counter wrap (or initial call); it's not possible
		 * to accurately calculate a value because the registers
		 * right shift rather than wrap--so punt and return 0.
		 */
		listenTime = 0;
		ahp->ah_stats.ast_ani_lzero++;
	} else if (ANI_ENA(ah)) {
		/*
		 * Only calculate and update the cycle count if we have
		 * an ANI state.
		 */
		int32_t ccdelta =
		    AH5212(ah)->ah_cycleCount - aniState->cycleCount;
		int32_t rfdelta =
		    AH5212(ah)->ah_rxBusy - aniState->rxFrameCount;
		int32_t tfdelta =
		    AH5212(ah)->ah_txBusy - aniState->txFrameCount;
		listenTime = (ccdelta - rfdelta - tfdelta) / CLOCK_RATE;
	}

	/*
	 * Again, only update ANI state if we have it.
	 */
	if (ANI_ENA(ah)) {
		aniState->cycleCount = AH5212(ah)->ah_cycleCount;
		aniState->rxFrameCount = AH5212(ah)->ah_rxBusy;
		aniState->txFrameCount = AH5212(ah)->ah_txBusy;
	}

	return listenTime;
}
コード例 #8
0
ファイル: ar5212_ani.c プロジェクト: ele7enxxh/dtrace-pf
/*
 * Restore/reset the ANI parameters and reset the statistics.
 * This routine must be called for every channel change.
 */
void
ar5212AniReset(struct ath_hal *ah, const struct ieee80211_channel *chan,
	HAL_OPMODE opmode, int restore)
{
	struct ath_hal_5212 *ahp = AH5212(ah);
	HAL_CHANNEL_INTERNAL *ichan = ath_hal_checkchannel(ah, chan);
	/* XXX bounds check ic_devdata */
	struct ar5212AniState *aniState = &ahp->ah_ani[chan->ic_devdata];
	uint32_t rxfilter;

	if ((ichan->privFlags & CHANNEL_ANI_INIT) == 0) {
		OS_MEMZERO(aniState, sizeof(*aniState));
		if (IEEE80211_IS_CHAN_2GHZ(chan))
			aniState->params = &ahp->ah_aniParams24;
		else
			aniState->params = &ahp->ah_aniParams5;
		ichan->privFlags |= CHANNEL_ANI_INIT;
		HALASSERT((ichan->privFlags & CHANNEL_ANI_SETUP) == 0);
	}
	ahp->ah_curani = aniState;
#if 0
	ath_hal_printf(ah,"%s: chan %u/0x%x restore %d opmode %u%s\n",
	    __func__, chan->ic_freq, chan->ic_flags, restore, opmode,
	    ichan->privFlags & CHANNEL_ANI_SETUP ? " setup" : "");
#else
	HALDEBUG(ah, HAL_DEBUG_ANI, "%s: chan %u/0x%x restore %d opmode %u%s\n",
	    __func__, chan->ic_freq, chan->ic_flags, restore, opmode,
	    ichan->privFlags & CHANNEL_ANI_SETUP ? " setup" : "");
#endif
	OS_MARK(ah, AH_MARK_ANI_RESET, opmode);

	/*
	 * Turn off PHY error frame delivery while we futz with settings.
	 */
	rxfilter = ah->ah_getRxFilter(ah);
	ah->ah_setRxFilter(ah, rxfilter &~ HAL_RX_FILTER_PHYERR);

	/*
	 * If ANI is disabled at this point, don't set the default
	 * ANI parameter settings - leave the HAL settings there.
	 * This is (currently) needed for reliable radar detection.
	 */
	if (! ANI_ENA(ah)) {
		HALDEBUG(ah, HAL_DEBUG_ANI, "%s: ANI disabled\n",
		    __func__);
		goto finish;
	}

	/*
	 * Automatic processing is done only in station mode right now.
	 */
	if (opmode == HAL_M_STA)
		ahp->ah_procPhyErr |= HAL_RSSI_ANI_ENA;
	else
		ahp->ah_procPhyErr &= ~HAL_RSSI_ANI_ENA;
	/*
	 * Set all ani parameters.  We either set them to initial
	 * values or restore the previous ones for the channel.
	 * XXX if ANI follows hardware, we don't care what mode we're
	 * XXX in, we should keep the ani parameters
	 */
	if (restore && (ichan->privFlags & CHANNEL_ANI_SETUP)) {
		ar5212AniControl(ah, HAL_ANI_NOISE_IMMUNITY_LEVEL,
				 aniState->noiseImmunityLevel);
		ar5212AniControl(ah, HAL_ANI_SPUR_IMMUNITY_LEVEL,
				 aniState->spurImmunityLevel);
		ar5212AniControl(ah, HAL_ANI_OFDM_WEAK_SIGNAL_DETECTION,
				 !aniState->ofdmWeakSigDetectOff);
		ar5212AniControl(ah, HAL_ANI_CCK_WEAK_SIGNAL_THR,
				 aniState->cckWeakSigThreshold);
		ar5212AniControl(ah, HAL_ANI_FIRSTEP_LEVEL,
				 aniState->firstepLevel);
	} else {
		ar5212AniControl(ah, HAL_ANI_NOISE_IMMUNITY_LEVEL, 0);
		ar5212AniControl(ah, HAL_ANI_SPUR_IMMUNITY_LEVEL, 0);
		ar5212AniControl(ah, HAL_ANI_OFDM_WEAK_SIGNAL_DETECTION,
			AH_TRUE);
		ar5212AniControl(ah, HAL_ANI_CCK_WEAK_SIGNAL_THR, AH_FALSE);
		ar5212AniControl(ah, HAL_ANI_FIRSTEP_LEVEL, 0);
		ichan->privFlags |= CHANNEL_ANI_SETUP;
	}
	/*
	 * In case the counters haven't yet been setup; set them up.
	 */
	enableAniMIBCounters(ah, ahp->ah_curani->params);
	ar5212AniRestart(ah, aniState);

finish:
	/* restore RX filter mask */
	ah->ah_setRxFilter(ah, rxfilter);
}
コード例 #9
0
static void
ar5212AniOfdmErrTrigger(struct ath_hal *ah)
{
	struct ath_hal_5212 *ahp = AH5212(ah);
	HAL_CHANNEL_INTERNAL *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) {
		HALDEBUG(ah, HAL_DEBUG_ANI, "%s: raise NI to %u\n", __func__,
		    aniState->noiseImmunityLevel + 1);
		ar5212AniControl(ah, HAL_ANI_NOISE_IMMUNITY_LEVEL, 
				 aniState->noiseImmunityLevel + 1);
		return;
	}
	/* then, raise spur immunity level, up to max */
	if (aniState->spurImmunityLevel+1 <= params->maxSpurImmunityLevel) {
		HALDEBUG(ah, HAL_DEBUG_ANI, "%s: raise SI to %u\n", __func__,
		    aniState->spurImmunityLevel + 1);
		ar5212AniControl(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) {
				HALDEBUG(ah, HAL_DEBUG_ANI,
				    "%s: rssi %d OWSD off\n", __func__, rssi);
				ar5212AniControl(ah,
				    HAL_ANI_OFDM_WEAK_SIGNAL_DETECTION,
				    AH_FALSE);
				ar5212AniControl(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) {
				HALDEBUG(ah, HAL_DEBUG_ANI,
				    "%s: rssi %d raise ST %u\n", __func__, rssi,
				    aniState->firstepLevel+1);
				ar5212AniControl(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) {
				HALDEBUG(ah, HAL_DEBUG_ANI,
				    "%s: rssi %d OWSD on\n", __func__, rssi);
				ar5212AniControl(ah,
				    HAL_ANI_OFDM_WEAK_SIGNAL_DETECTION,
				    AH_TRUE);
			}
			if (aniState->firstepLevel+1 <= params->maxFirstepLevel) {
				HALDEBUG(ah, HAL_DEBUG_ANI,
				    "%s: rssi %d raise ST %u\n", __func__, rssi,
				    aniState->firstepLevel+1);
				ar5212AniControl(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 
			 */
			/* XXX can optimize */
			if (IS_CHAN_B(chan) || IS_CHAN_G(chan)) {
				if (!aniState->ofdmWeakSigDetectOff) {
					HALDEBUG(ah, HAL_DEBUG_ANI,
					    "%s: rssi %d OWSD off\n",
					    __func__, rssi);
					ar5212AniControl(ah,
					    HAL_ANI_OFDM_WEAK_SIGNAL_DETECTION,
					    AH_FALSE);
				}
				if (aniState->firstepLevel > 0) {
					HALDEBUG(ah, HAL_DEBUG_ANI,
					    "%s: rssi %d zero ST (was %u)\n",
					    __func__, rssi,
					    aniState->firstepLevel);
					ar5212AniControl(ah,
					     HAL_ANI_FIRSTEP_LEVEL, 0);
				}
				return;
			}
		}
	}
}