Exemplo n.º 1
0
/*
 * Control Adaptive Noise Immunity Parameters
 */
HAL_BOOL
ar5416AniControl(struct ath_hal *ah, HAL_ANI_CMD cmd, int param)
{
	typedef int TABLE[];
	struct ath_hal_5212 *ahp = AH5212(ah);
	struct ar5212AniState *aniState = ahp->ah_curani;
	const struct ar5212AniParams *params = aniState->params;

	OS_MARK(ah, AH_MARK_ANI_CONTROL, cmd);

	switch (cmd) {
	case HAL_ANI_NOISE_IMMUNITY_LEVEL: {
		u_int level = param;

		if (level >= params->maxNoiseImmunityLevel) {
			HALDEBUG(ah, HAL_DEBUG_ANY,
			    "%s: immunity level out of range (%u > %u)\n",
			    __func__, level, params->maxNoiseImmunityLevel);
			return AH_FALSE;
		}

		OS_REG_RMW_FIELD(ah, AR_PHY_DESIRED_SZ,
		    AR_PHY_DESIRED_SZ_TOT_DES, params->totalSizeDesired[level]);
		OS_REG_RMW_FIELD(ah, AR_PHY_AGC_CTL1,
		    AR_PHY_AGC_CTL1_COARSE_LOW, params->coarseLow[level]);
		OS_REG_RMW_FIELD(ah, AR_PHY_AGC_CTL1,
		    AR_PHY_AGC_CTL1_COARSE_HIGH, params->coarseHigh[level]);
		OS_REG_RMW_FIELD(ah, AR_PHY_FIND_SIG,
		    AR_PHY_FIND_SIG_FIRPWR, params->firpwr[level]);

		if (level > aniState->noiseImmunityLevel)
			ahp->ah_stats.ast_ani_niup++;
		else if (level < aniState->noiseImmunityLevel)
			ahp->ah_stats.ast_ani_nidown++;
		aniState->noiseImmunityLevel = level;
		break;
	}
	case HAL_ANI_OFDM_WEAK_SIGNAL_DETECTION: {
		static const TABLE m1ThreshLow   = { 127,   50 };
		static const TABLE m2ThreshLow   = { 127,   40 };
		static const TABLE m1Thresh      = { 127, 0x4d };
		static const TABLE m2Thresh      = { 127, 0x40 };
		static const TABLE m2CountThr    = {  31,   16 };
		static const TABLE m2CountThrLow = {  63,   48 };
		u_int on = param ? 1 : 0;

		OS_REG_RMW_FIELD(ah, AR_PHY_SFCORR_LOW,
			AR_PHY_SFCORR_LOW_M1_THRESH_LOW, m1ThreshLow[on]);
		OS_REG_RMW_FIELD(ah, AR_PHY_SFCORR_LOW,
			AR_PHY_SFCORR_LOW_M2_THRESH_LOW, m2ThreshLow[on]);
		OS_REG_RMW_FIELD(ah, AR_PHY_SFCORR,
			AR_PHY_SFCORR_M1_THRESH, m1Thresh[on]);
		OS_REG_RMW_FIELD(ah, AR_PHY_SFCORR,
			AR_PHY_SFCORR_M2_THRESH, m2Thresh[on]);
		OS_REG_RMW_FIELD(ah, AR_PHY_SFCORR,
			AR_PHY_SFCORR_M2COUNT_THR, m2CountThr[on]);
		OS_REG_RMW_FIELD(ah, AR_PHY_SFCORR_LOW,
			AR_PHY_SFCORR_LOW_M2COUNT_THR_LOW, m2CountThrLow[on]);

		OS_REG_RMW_FIELD(ah, AR_PHY_SFCORR_EXT,
			AR_PHY_SFCORR_EXT_M1_THRESH_LOW, m1ThreshLow[on]);
		OS_REG_RMW_FIELD(ah, AR_PHY_SFCORR_EXT,
			AR_PHY_SFCORR_EXT_M2_THRESH_LOW, m2ThreshLow[on]);
		OS_REG_RMW_FIELD(ah, AR_PHY_SFCORR_EXT,
			AR_PHY_SFCORR_EXT_M1_THRESH, m1Thresh[on]);
		OS_REG_RMW_FIELD(ah, AR_PHY_SFCORR_EXT,
			AR_PHY_SFCORR_EXT_M2_THRESH, m2Thresh[on]);

		if (on) {
			OS_REG_SET_BIT(ah, AR_PHY_SFCORR_LOW,
				AR_PHY_SFCORR_LOW_USE_SELF_CORR_LOW);
		} else {
			OS_REG_CLR_BIT(ah, AR_PHY_SFCORR_LOW,
				AR_PHY_SFCORR_LOW_USE_SELF_CORR_LOW);
		}
		if (on)
			ahp->ah_stats.ast_ani_ofdmon++;
		else
			ahp->ah_stats.ast_ani_ofdmoff++;
		aniState->ofdmWeakSigDetectOff = !on;
		break;
	}
	case HAL_ANI_CCK_WEAK_SIGNAL_THR: {
		static const TABLE weakSigThrCck = { 8, 6 };
		u_int high = param ? 1 : 0;

		OS_REG_RMW_FIELD(ah, AR_PHY_CCK_DETECT,
		    AR_PHY_CCK_DETECT_WEAK_SIG_THR_CCK, weakSigThrCck[high]);
		if (high)
			ahp->ah_stats.ast_ani_cckhigh++;
		else
			ahp->ah_stats.ast_ani_ccklow++;
		aniState->cckWeakSigThreshold = high;
		break;
	}
	case HAL_ANI_FIRSTEP_LEVEL: {
		u_int level = param;

		if (level >= params->maxFirstepLevel) {
			HALDEBUG(ah, HAL_DEBUG_ANY,
			    "%s: firstep level out of range (%u > %u)\n",
			    __func__, level, params->maxFirstepLevel);
			return AH_FALSE;
		}
		OS_REG_RMW_FIELD(ah, AR_PHY_FIND_SIG,
		    AR_PHY_FIND_SIG_FIRSTEP, params->firstep[level]);
		if (level > aniState->firstepLevel)
			ahp->ah_stats.ast_ani_stepup++;
		else if (level < aniState->firstepLevel)
			ahp->ah_stats.ast_ani_stepdown++;
		aniState->firstepLevel = level;
		break;
	}
	case HAL_ANI_SPUR_IMMUNITY_LEVEL: {
		u_int level = param;

		if (level >= params->maxSpurImmunityLevel) {
			HALDEBUG(ah, HAL_DEBUG_ANY,
			    "%s: spur immunity level out of range (%u > %u)\n",
			    __func__, level, params->maxSpurImmunityLevel);
			return AH_FALSE;
		}
		OS_REG_RMW_FIELD(ah, AR_PHY_TIMING5,
		    AR_PHY_TIMING5_CYCPWR_THR1, params->cycPwrThr1[level]);
		if (level > aniState->spurImmunityLevel)
			ahp->ah_stats.ast_ani_spurup++;
		else if (level < aniState->spurImmunityLevel)
			ahp->ah_stats.ast_ani_spurdown++;
		aniState->spurImmunityLevel = level;
		break;
	}
	case HAL_ANI_PRESENT:
		break;
	case HAL_ANI_MODE:
		if (param == 0) {
			ahp->ah_procPhyErr &= ~HAL_ANI_ENA;
			/* Turn off HW counters if we have them */
			ar5416AniDetach(ah);
			ar5212SetRxFilter(ah,
				ar5212GetRxFilter(ah) &~ HAL_RX_FILTER_PHYERR);
		} else {			/* normal/auto mode */
			/* don't mess with state if already enabled */
			if (ahp->ah_procPhyErr & HAL_ANI_ENA)
				break;
			ar5212SetRxFilter(ah,
				ar5212GetRxFilter(ah) &~ HAL_RX_FILTER_PHYERR);
			/* Enable MIB Counters */
			enableAniMIBCounters(ah, ahp->ah_curani != AH_NULL ?
			    ahp->ah_curani->params: &ahp->ah_aniParams24 /*XXX*/);
			ahp->ah_procPhyErr |= HAL_ANI_ENA;
		}
		break;
#ifdef AH_PRIVATE_DIAG
	case HAL_ANI_PHYERR_RESET:
		ahp->ah_stats.ast_ani_ofdmerrs = 0;
		ahp->ah_stats.ast_ani_cckerrs = 0;
		break;
#endif /* AH_PRIVATE_DIAG */
	default:
		HALDEBUG(ah, HAL_DEBUG_ANY, "%s: invalid cmd %u\n",
		    __func__, cmd);
		return AH_FALSE;
	}
	return AH_TRUE;
}
Exemplo n.º 2
0
/*
 * Control Adaptive Noise Immunity Parameters
 */
HAL_BOOL
ar5416AniControl(struct ath_hal *ah, HAL_ANI_CMD cmd, int param, HAL_BOOL inISR)
{
#define N(a) (sizeof(a)/sizeof(a[0]))
	typedef int TABLE[];
	struct ath_hal_5416 *ahp = AH5416(ah);
	struct ar5416AniState *aniState = ahp->ah_curani;

	switch (cmd & ahp->ah_ani_function) {
	case HAL_ANI_NOISE_IMMUNITY_LEVEL: {
		u_int level = param;

		if (level >= N(ahp->ah_totalSizeDesired)) {
			HDPRINTF(ah, HAL_DBG_ANI, "%s: level out of range (%u > %u)\n",
				__func__, level, (unsigned) N(ahp->ah_totalSizeDesired));
			return AH_FALSE;
		}

		OS_REG_RMW_FIELD(ah, AR_PHY_DESIRED_SZ,
			AR_PHY_DESIRED_SZ_TOT_DES, ahp->ah_totalSizeDesired[level]);
		OS_REG_RMW_FIELD(ah, AR_PHY_AGC_CTL1,
			  AR_PHY_AGC_CTL1_COARSE_LOW, ahp->ah_coarseLow[level]);
		OS_REG_RMW_FIELD(ah, AR_PHY_AGC_CTL1,
			  AR_PHY_AGC_CTL1_COARSE_HIGH, ahp->ah_coarseHigh[level]);
		OS_REG_RMW_FIELD(ah, AR_PHY_FIND_SIG,
			AR_PHY_FIND_SIG_FIRPWR, ahp->ah_firpwr[level]);

		if (level > aniState->noiseImmunityLevel)
			ahp->ah_stats.ast_ani_niup++;
		else if (level < aniState->noiseImmunityLevel)
			ahp->ah_stats.ast_ani_nidown++;
		aniState->noiseImmunityLevel = level;
		break;
	}
	case HAL_ANI_OFDM_WEAK_SIGNAL_DETECTION: {
		const TABLE m1ThreshLow   = { 127,   50 };
		const TABLE m2ThreshLow   = { 127,   40 };
		const TABLE m1Thresh      = { 127, 0x4d };
		const TABLE m2Thresh      = { 127, 0x40 };
		const TABLE m2CountThr    = {  31,   16 };
		const TABLE m2CountThrLow = {  63,   48 };
		u_int on = param ? 1 : 0;

		OS_REG_RMW_FIELD(ah, AR_PHY_SFCORR_LOW,
			AR_PHY_SFCORR_LOW_M1_THRESH_LOW, m1ThreshLow[on]);
		OS_REG_RMW_FIELD(ah, AR_PHY_SFCORR_LOW,
			AR_PHY_SFCORR_LOW_M2_THRESH_LOW, m2ThreshLow[on]);
		OS_REG_RMW_FIELD(ah, AR_PHY_SFCORR,
			AR_PHY_SFCORR_M1_THRESH, m1Thresh[on]);
		OS_REG_RMW_FIELD(ah, AR_PHY_SFCORR,
			AR_PHY_SFCORR_M2_THRESH, m2Thresh[on]);
		OS_REG_RMW_FIELD(ah, AR_PHY_SFCORR,
			AR_PHY_SFCORR_M2COUNT_THR, m2CountThr[on]);
		OS_REG_RMW_FIELD(ah, AR_PHY_SFCORR_LOW,
			AR_PHY_SFCORR_LOW_M2COUNT_THR_LOW, m2CountThrLow[on]);
                                               
        OS_REG_RMW_FIELD(ah, AR_PHY_SFCORR_EXT, AR_PHY_SFCORR_EXT_M1_THRESH_LOW, m1ThreshLow[on]);
        OS_REG_RMW_FIELD(ah, AR_PHY_SFCORR_EXT, AR_PHY_SFCORR_EXT_M2_THRESH_LOW, m2ThreshLow[on]);
        OS_REG_RMW_FIELD(ah, AR_PHY_SFCORR_EXT, AR_PHY_SFCORR_EXT_M1_THRESH, m1Thresh[on]);
        OS_REG_RMW_FIELD(ah, AR_PHY_SFCORR_EXT, AR_PHY_SFCORR_EXT_M2_THRESH, m2Thresh[on]);
        
		if (on) {
			OS_REG_SET_BIT(ah, AR_PHY_SFCORR_LOW,
				AR_PHY_SFCORR_LOW_USE_SELF_CORR_LOW);
		} else {
			OS_REG_CLR_BIT(ah, AR_PHY_SFCORR_LOW,
				AR_PHY_SFCORR_LOW_USE_SELF_CORR_LOW);
		}
		if (!on != aniState->ofdmWeakSigDetectOff) {
			if (on)
				ahp->ah_stats.ast_ani_ofdmon++;
			else
				ahp->ah_stats.ast_ani_ofdmoff++;
			aniState->ofdmWeakSigDetectOff = !on;
		}
		break;
	}
	case HAL_ANI_CCK_WEAK_SIGNAL_THR: {
		const TABLE weakSigThrCck = { 8, 6 };
		u_int high = param ? 1 : 0;

		OS_REG_RMW_FIELD(ah, AR_PHY_CCK_DETECT,
			AR_PHY_CCK_DETECT_WEAK_SIG_THR_CCK,
			weakSigThrCck[high]);
		if (high != aniState->cckWeakSigThreshold) {
			if (high)
				ahp->ah_stats.ast_ani_cckhigh++;
			else
				ahp->ah_stats.ast_ani_ccklow++;
			aniState->cckWeakSigThreshold = high;
		}
		break;
	}
	case HAL_ANI_FIRSTEP_LEVEL: {
		const TABLE firstep = { 0, 4, 8 };
		u_int level = param;

		if (level >= N(firstep)) {
			HDPRINTF(ah, HAL_DBG_ANI, "%s: level out of range (%u > %u)\n",
				__func__, level, (unsigned) N(firstep));
			return AH_FALSE;
		}
		OS_REG_RMW_FIELD(ah, AR_PHY_FIND_SIG,
			AR_PHY_FIND_SIG_FIRSTEP, firstep[level]);
		if (level > aniState->firstepLevel)
			ahp->ah_stats.ast_ani_stepup++;
		else if (level < aniState->firstepLevel)
			ahp->ah_stats.ast_ani_stepdown++;
		aniState->firstepLevel = level;
		break;
	}
	case HAL_ANI_SPUR_IMMUNITY_LEVEL: {
		const TABLE cycpwrThr1 = { 2, 4, 6, 8, 10, 12, 14, 16 };
		u_int level = param;

		if (level >= N(cycpwrThr1)) {
			HDPRINTF(ah, HAL_DBG_ANI, "%s: level out of range (%u > %u)\n",
				__func__, level, (unsigned) N(cycpwrThr1));
			return AH_FALSE;
		}
		OS_REG_RMW_FIELD(ah, AR_PHY_TIMING5,
			AR_PHY_TIMING5_CYCPWR_THR1, cycpwrThr1[level]);
		if (level > aniState->spurImmunityLevel)
			ahp->ah_stats.ast_ani_spurup++;
		else if (level < aniState->spurImmunityLevel)
			ahp->ah_stats.ast_ani_spurdown++;
		aniState->spurImmunityLevel = level;
		break;
	}
	case HAL_ANI_PRESENT:
		break;
#ifdef AH_PRIVATE_DIAG
	case HAL_ANI_MODE:
		if (param == 0) {
			ahp->ah_procPhyErr &= ~HAL_PROCESS_ANI;
			/* Turn off HW counters if we have them */
			ar5416AniDetach(ah);
			ar5416SetRxFilter(ah,
				ar5416GetRxFilter(ah) &~ HAL_RX_FILTER_PHYERR);
		} else {			/* normal/auto mode */
			ahp->ah_procPhyErr |= HAL_PROCESS_ANI;
			if (ahp->ah_hasHwPhyCounters) {
				ar5416SetRxFilter(ah,
					ar5416GetRxFilter(ah) &~ HAL_RX_FILTER_PHYERR);
			} else {
				ar5416SetRxFilter(ah,
					ar5416GetRxFilter(ah) | HAL_RX_FILTER_PHYERR);
			}
		}
		break;
	case HAL_ANI_PHYERR_RESET:
		ahp->ah_stats.ast_ani_ofdmerrs = 0;
		ahp->ah_stats.ast_ani_cckerrs = 0;
		break;
#endif /* AH_PRIVATE_DIAG */
	default:
		HDPRINTF(ah, HAL_DBG_ANI, "%s: invalid cmd %u\n", __func__, cmd);
		return AH_FALSE;
	}

    HDPRINTF(ah, HAL_DBG_ANI, "%s: ANI parameters:\n", __func__);
    HDPRINTF(ah, HAL_DBG_ANI,
             "noiseImmunityLevel=%d, spurImmunityLevel=%d, ofdmWeakSigDetectOff=%d\n",
             aniState->noiseImmunityLevel, aniState->spurImmunityLevel,
             !aniState->ofdmWeakSigDetectOff);
    HDPRINTF(ah, HAL_DBG_ANI,
             "cckWeakSigThreshold=%d, firstepLevel=%d, listenTime=%d\n",
             aniState->cckWeakSigThreshold, aniState->firstepLevel,
             aniState->listenTime);
    HDPRINTF(ah, HAL_DBG_ANI,
             "cycleCount=%d, ofdmPhyErrCount=%d, cckPhyErrCount=%d\n\n",
             aniState->cycleCount, aniState->ofdmPhyErrCount,
             aniState->cckPhyErrCount);

#ifndef REMOVE_PKT_LOG
    /* do pktlog */
    {
        struct log_ani log_data;

        /* Populate the ani log record */
        log_data.phyStatsDisable = DO_ANI(ah);
        log_data.noiseImmunLvl = aniState->noiseImmunityLevel;
        log_data.spurImmunLvl = aniState->spurImmunityLevel;
        log_data.ofdmWeakDet = aniState->ofdmWeakSigDetectOff;
        log_data.ofdmWeakDet = aniState->ofdmWeakSigDetectOff;
        log_data.cckWeakThr = aniState->cckWeakSigThreshold;
        log_data.firLvl = aniState->firstepLevel;
        log_data.listenTime = aniState->listenTime;
        log_data.cycleCount = aniState->cycleCount;
        log_data.ofdmPhyErrCount = aniState->ofdmPhyErrCount;
        log_data.cckPhyErrCount = aniState->cckPhyErrCount;
        log_data.rssi = 0; /* Was for legacy single antenna rssi */

        /* For HT chips, 2x2 */
        /* Log 6 u_int16_t RSSIs as first in the int32_t 'misc' array */
        /* ToDo: Update pktRssi for valid packets? */
        /* ToDo: Update PhyErr RSSIs in aniState variable - 
                 need Rx Descriptor / PhyErr*/
        /* ToDo: Add parsing support in owldump, if needed */
        
        log_data.misc[0] = aniState->pktRssi[0];
        log_data.misc[1] = aniState->pktRssi[1];
        log_data.misc[2] = aniState->ofdmErrRssi[0];
        log_data.misc[3] = aniState->ofdmErrRssi[1];
        log_data.misc[4] = aniState->cckErrRssi[0];
        log_data.misc[5] = aniState->cckErrRssi[1];
        if (inISR)
            ath_hal_log_ani(ah->ah_sc, &log_data, 1);   // set interrupt context flag
        else
            ath_hal_log_ani(ah->ah_sc, &log_data, 0);   // clear interrupt context flag
    }
    
#endif

    return AH_TRUE;
#undef	N
}
Exemplo n.º 3
0
/*
 * Control Adaptive Noise Immunity Parameters
 */
HAL_BOOL
ar5416AniControl(struct ath_hal *ah, HAL_ANI_CMD cmd, int param)
{
	typedef int TABLE[];
	struct ath_hal_5212 *ahp = AH5212(ah);
	struct ar5212AniState *aniState = ahp->ah_curani;
	const struct ar5212AniParams *params = AH_NULL;

	/*
	 * This function may be called before there's a current
	 * channel (eg to disable ANI.)
	 */
	if (aniState != AH_NULL)
		params = aniState->params;

	OS_MARK(ah, AH_MARK_ANI_CONTROL, cmd);

	/* These commands can't be disabled */
	if (cmd == HAL_ANI_PRESENT)
		return AH_TRUE;

	if (cmd == HAL_ANI_MODE) {
		if (param == 0) {
			ahp->ah_procPhyErr &= ~HAL_ANI_ENA;
			/* Turn off HW counters if we have them */
			ar5416AniDetach(ah);
		} else {			/* normal/auto mode */
			/* don't mess with state if already enabled */
			if (! (ahp->ah_procPhyErr & HAL_ANI_ENA)) {
				/* Enable MIB Counters */
				/*
				 * XXX use 2.4ghz params if no channel is
				 * available
				 */
				enableAniMIBCounters(ah,
				    ahp->ah_curani != AH_NULL ?
				      ahp->ah_curani->params:
				      &ahp->ah_aniParams24);
				ahp->ah_procPhyErr |= HAL_ANI_ENA;
			}
		}
		return AH_TRUE;
	}

	/* Check whether the particular function is enabled */
	if (((1 << cmd) & AH5416(ah)->ah_ani_function) == 0) {
		HALDEBUG(ah, HAL_DEBUG_ANI, "%s: command %d disabled\n",
		    __func__, cmd);
		HALDEBUG(ah, HAL_DEBUG_ANI, "%s: cmd %d; mask %x\n", __func__, cmd, AH5416(ah)->ah_ani_function);
		return AH_FALSE;
	}


	switch (cmd) {
	case HAL_ANI_NOISE_IMMUNITY_LEVEL: {
		u_int level = param;

		HALDEBUG(ah, HAL_DEBUG_ANI, "%s: HAL_ANI_NOISE_IMMUNITY_LEVEL: set level = %d\n", __func__, level);
		if (level > params->maxNoiseImmunityLevel) {
			HALDEBUG(ah, HAL_DEBUG_ANI,
			    "%s: immunity level out of range (%u > %u)\n",
			    __func__, level, params->maxNoiseImmunityLevel);
			return AH_FALSE;
		}

		OS_REG_RMW_FIELD(ah, AR_PHY_DESIRED_SZ,
		    AR_PHY_DESIRED_SZ_TOT_DES, params->totalSizeDesired[level]);
		OS_REG_RMW_FIELD(ah, AR_PHY_AGC_CTL1,
		    AR_PHY_AGC_CTL1_COARSE_LOW, params->coarseLow[level]);
		OS_REG_RMW_FIELD(ah, AR_PHY_AGC_CTL1,
		    AR_PHY_AGC_CTL1_COARSE_HIGH, params->coarseHigh[level]);
		OS_REG_RMW_FIELD(ah, AR_PHY_FIND_SIG,
		    AR_PHY_FIND_SIG_FIRPWR, params->firpwr[level]);

		if (level > aniState->noiseImmunityLevel)
			ahp->ah_stats.ast_ani_niup++;
		else if (level < aniState->noiseImmunityLevel)
			ahp->ah_stats.ast_ani_nidown++;
		aniState->noiseImmunityLevel = level;
		break;
	}
	case HAL_ANI_OFDM_WEAK_SIGNAL_DETECTION: {
		static const TABLE m1ThreshLow   = { 127,   50 };
		static const TABLE m2ThreshLow   = { 127,   40 };
		static const TABLE m1Thresh      = { 127, 0x4d };
		static const TABLE m2Thresh      = { 127, 0x40 };
		static const TABLE m2CountThr    = {  31,   16 };
		static const TABLE m2CountThrLow = {  63,   48 };
		u_int on = param ? 1 : 0;

		HALDEBUG(ah, HAL_DEBUG_ANI, "%s: HAL_ANI_OFDM_WEAK_SIGNAL_DETECTION: %s\n", __func__, on ? "enabled" : "disabled");
		OS_REG_RMW_FIELD(ah, AR_PHY_SFCORR_LOW,
			AR_PHY_SFCORR_LOW_M1_THRESH_LOW, m1ThreshLow[on]);
		OS_REG_RMW_FIELD(ah, AR_PHY_SFCORR_LOW,
			AR_PHY_SFCORR_LOW_M2_THRESH_LOW, m2ThreshLow[on]);
		OS_REG_RMW_FIELD(ah, AR_PHY_SFCORR,
			AR_PHY_SFCORR_M1_THRESH, m1Thresh[on]);
		OS_REG_RMW_FIELD(ah, AR_PHY_SFCORR,
			AR_PHY_SFCORR_M2_THRESH, m2Thresh[on]);
		OS_REG_RMW_FIELD(ah, AR_PHY_SFCORR,
			AR_PHY_SFCORR_M2COUNT_THR, m2CountThr[on]);
		OS_REG_RMW_FIELD(ah, AR_PHY_SFCORR_LOW,
			AR_PHY_SFCORR_LOW_M2COUNT_THR_LOW, m2CountThrLow[on]);

		OS_REG_RMW_FIELD(ah, AR_PHY_SFCORR_EXT,
			AR_PHY_SFCORR_EXT_M1_THRESH_LOW, m1ThreshLow[on]);
		OS_REG_RMW_FIELD(ah, AR_PHY_SFCORR_EXT,
			AR_PHY_SFCORR_EXT_M2_THRESH_LOW, m2ThreshLow[on]);
		OS_REG_RMW_FIELD(ah, AR_PHY_SFCORR_EXT,
			AR_PHY_SFCORR_EXT_M1_THRESH, m1Thresh[on]);
		OS_REG_RMW_FIELD(ah, AR_PHY_SFCORR_EXT,
			AR_PHY_SFCORR_EXT_M2_THRESH, m2Thresh[on]);

		if (on) {
			OS_REG_SET_BIT(ah, AR_PHY_SFCORR_LOW,
				AR_PHY_SFCORR_LOW_USE_SELF_CORR_LOW);
		} else {
			OS_REG_CLR_BIT(ah, AR_PHY_SFCORR_LOW,
				AR_PHY_SFCORR_LOW_USE_SELF_CORR_LOW);
		}
		if (on)
			ahp->ah_stats.ast_ani_ofdmon++;
		else
			ahp->ah_stats.ast_ani_ofdmoff++;
		aniState->ofdmWeakSigDetectOff = !on;
		break;
	}
	case HAL_ANI_CCK_WEAK_SIGNAL_THR: {
		static const TABLE weakSigThrCck = { 8, 6 };
		u_int high = param ? 1 : 0;

		HALDEBUG(ah, HAL_DEBUG_ANI, "%s: HAL_ANI_CCK_WEAK_SIGNAL_THR: %s\n", __func__, high ? "high" : "low");
		OS_REG_RMW_FIELD(ah, AR_PHY_CCK_DETECT,
		    AR_PHY_CCK_DETECT_WEAK_SIG_THR_CCK, weakSigThrCck[high]);
		if (high)
			ahp->ah_stats.ast_ani_cckhigh++;
		else
			ahp->ah_stats.ast_ani_ccklow++;
		aniState->cckWeakSigThreshold = high;
		break;
	}
	case HAL_ANI_FIRSTEP_LEVEL: {
		u_int level = param;

		HALDEBUG(ah, HAL_DEBUG_ANI, "%s: HAL_ANI_FIRSTEP_LEVEL: level = %d\n", __func__, level);
		if (level > params->maxFirstepLevel) {
			HALDEBUG(ah, HAL_DEBUG_ANI,
			    "%s: firstep level out of range (%u > %u)\n",
			    __func__, level, params->maxFirstepLevel);
			return AH_FALSE;
		}
		OS_REG_RMW_FIELD(ah, AR_PHY_FIND_SIG,
		    AR_PHY_FIND_SIG_FIRSTEP, params->firstep[level]);
		if (level > aniState->firstepLevel)
			ahp->ah_stats.ast_ani_stepup++;
		else if (level < aniState->firstepLevel)
			ahp->ah_stats.ast_ani_stepdown++;
		aniState->firstepLevel = level;
		break;
	}
	case HAL_ANI_SPUR_IMMUNITY_LEVEL: {
		u_int level = param;

		HALDEBUG(ah, HAL_DEBUG_ANI, "%s: HAL_ANI_SPUR_IMMUNITY_LEVEL: level = %d\n", __func__, level);
		if (level > params->maxSpurImmunityLevel) {
			HALDEBUG(ah, HAL_DEBUG_ANI,
			    "%s: spur immunity level out of range (%u > %u)\n",
			    __func__, level, params->maxSpurImmunityLevel);
			return AH_FALSE;
		}
		OS_REG_RMW_FIELD(ah, AR_PHY_TIMING5,
		    AR_PHY_TIMING5_CYCPWR_THR1, params->cycPwrThr1[level]);

		if (level > aniState->spurImmunityLevel)
			ahp->ah_stats.ast_ani_spurup++;
		else if (level < aniState->spurImmunityLevel)
			ahp->ah_stats.ast_ani_spurdown++;
		aniState->spurImmunityLevel = level;
		break;
	}
#ifdef AH_PRIVATE_DIAG
	case HAL_ANI_PHYERR_RESET:
		ahp->ah_stats.ast_ani_ofdmerrs = 0;
		ahp->ah_stats.ast_ani_cckerrs = 0;
		break;
#endif /* AH_PRIVATE_DIAG */
	default:
		HALDEBUG(ah, HAL_DEBUG_ANI, "%s: invalid cmd %u\n",
		    __func__, cmd);
		return AH_FALSE;
	}
	return AH_TRUE;
}