⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ar5416_ani.c

📁 最新之atheros芯片driver source code, 基于linux操作系统,內含atheros芯片HAL全部代码
💻 C
📖 第 1 页 / 共 2 页
字号:
			if (IS_CHAN_B(chan) || IS_CHAN_G(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;			}		}	}}static voidar5416AniCckErrTrigger(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;	/* first, raise noise immunity level, up to max */	aniState = ahp->ah_curani;	params = aniState->params;	if (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.			 */			/* XXX can optimize */			if (IS_CHAN_B(chan) || IS_CHAN_G(chan)) {				if (aniState->firstepLevel > 0)					ar5416AniControl(ah,					    HAL_ANI_FIRSTEP_LEVEL, 0);			}		}	}}static voidar5416AniRestart(struct ath_hal *ah, struct ar5212AniState *aniState){	struct ath_hal_5212 *ahp = AH5212(ah);	const struct ar5212AniParams *params = aniState->params;	aniState->listenTime = 0;	/*	 * NB: these are written on reset based on the	 *     ini so we must re-write them!	 */	HALDEBUG(ah, HAL_DEBUG_ANI,	    "%s: Writing ofdmbase=%u   cckbase=%u\n", __func__,	    params->ofdmPhyErrBase, params->cckPhyErrBase);	OS_REG_WRITE(ah, AR_PHY_ERR_1, params->ofdmPhyErrBase);	OS_REG_WRITE(ah, AR_PHY_ERR_2, params->cckPhyErrBase);	OS_REG_WRITE(ah, AR_PHY_ERR_MASK_1, AR_PHY_ERR_OFDM_TIMING);	OS_REG_WRITE(ah, AR_PHY_ERR_MASK_1, AR_PHY_ERR_CCK_TIMING);	/* Clear the mib counters and save them in the stats */	ar5212UpdateMibCounters(ah, &ahp->ah_mibStats);	aniState->ofdmPhyErrCount = 0;	aniState->cckPhyErrCount = 0;}/* * Restore/reset the ANI parameters and reset the statistics. * This routine must be called for every channel change. * * NOTE: This is where ah_curani is set; other ani code assumes *       it is setup to reflect the current channel. */voidar5416AniReset(struct ath_hal *ah, HAL_CHANNEL_INTERNAL *chan,	HAL_OPMODE opmode, int restore){	struct ath_hal_5212 *ahp = AH5212(ah);	struct ar5212AniState *aniState;	uint32_t rxfilter;	int index;	index = ar5416GetAniChannelIndex(ah, chan);	aniState = &ahp->ah_ani[index];	ahp->ah_curani = aniState;#if 0	ath_hal_printf(ah,"%s: chan %u/0x%x restore %d setup %d opmode %u\n",	    __func__, chan->channel, chan->channelFlags, restore,	    aniState->isSetup, opmode);#else	HALDEBUG(ah, HAL_DEBUG_ANI,	    "%s: chan %u/0x%x restore %d setup %d opmode %u\n",	    __func__, chan->channel, chan->channelFlags, restore,	    aniState->isSetup, opmode);#endif	OS_MARK(ah, AH_MARK_ANI_RESET, opmode);	/*	 * Turn off PHY error frame delivery while we futz with settings.	 */	rxfilter = ar5212GetRxFilter(ah);	ar5212SetRxFilter(ah, rxfilter &~ HAL_RX_FILTER_PHYERR);	/*	 * 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 && aniState->isSetup) {		ar5416AniControl(ah, HAL_ANI_NOISE_IMMUNITY_LEVEL,				 aniState->noiseImmunityLevel);		ar5416AniControl(ah, HAL_ANI_SPUR_IMMUNITY_LEVEL,				 aniState->spurImmunityLevel);		ar5416AniControl(ah, HAL_ANI_OFDM_WEAK_SIGNAL_DETECTION,				 !aniState->ofdmWeakSigDetectOff);		ar5416AniControl(ah, HAL_ANI_CCK_WEAK_SIGNAL_THR,				 aniState->cckWeakSigThreshold);		ar5416AniControl(ah, HAL_ANI_FIRSTEP_LEVEL,				 aniState->firstepLevel);	} else {		ar5416AniControl(ah, HAL_ANI_NOISE_IMMUNITY_LEVEL, 0);		ar5416AniControl(ah, HAL_ANI_SPUR_IMMUNITY_LEVEL, 0);		ar5416AniControl(ah, HAL_ANI_OFDM_WEAK_SIGNAL_DETECTION,			AH_TRUE);		ar5416AniControl(ah, HAL_ANI_CCK_WEAK_SIGNAL_THR, AH_FALSE);		ar5416AniControl(ah, HAL_ANI_FIRSTEP_LEVEL, 0);		aniState->isSetup = AH_TRUE;	}	ar5416AniRestart(ah, aniState);	/* restore RX filter mask */	ar5212SetRxFilter(ah, rxfilter);}/* * Process a MIB interrupt.  We may potentially be invoked because * any of the MIB counters overflow/trigger so don't assume we're * here because a PHY error counter triggered. */voidar5416ProcessMibIntr(struct ath_hal *ah, const HAL_NODE_STATS *stats){	struct ath_hal_5212 *ahp = AH5212(ah);	uint32_t phyCnt1, phyCnt2;	HALDEBUG(ah, HAL_DEBUG_ANI, "%s: mibc 0x%x phyCnt1 0x%x phyCnt2 0x%x "	    "filtofdm 0x%x filtcck 0x%x\n",	    __func__, OS_REG_READ(ah, AR_MIBC),	    OS_REG_READ(ah, AR_PHYCNT1), OS_REG_READ(ah, AR_PHYCNT2),	    OS_REG_READ(ah, AR_FILTOFDM), OS_REG_READ(ah, AR_FILTCCK));	/*	 * First order of business is to clear whatever caused	 * the interrupt so we don't keep getting interrupted.	 * We have the usual mib counters that are reset-on-read	 * and the additional counters that appeared starting in	 * Hainan.  We collect the mib counters and explicitly	 * zero additional counters we are not using.  Anything	 * else is reset only if it caused the interrupt.	 */	/* NB: these are not reset-on-read */	phyCnt1 = OS_REG_READ(ah, AR_PHY_ERR_1);	phyCnt2 = OS_REG_READ(ah, AR_PHY_ERR_2);	/* not used, always reset them in case they are the cause */	OS_REG_WRITE(ah, AR_FILTOFDM, 0);	OS_REG_WRITE(ah, AR_FILTCCK, 0);	if ((OS_REG_READ(ah, AR_SLP_MIB_CTRL) & AR_SLP_MIB_PENDING) == 0)		OS_REG_WRITE(ah, AR_SLP_MIB_CTRL, AR_SLP_MIB_CLEAR);	/* Clear the mib counters and save them in the stats */	ar5212UpdateMibCounters(ah, &ahp->ah_mibStats);	ahp->ah_stats.ast_nodestats = *stats;	/*	 * Check for an ani stat hitting the trigger threshold.	 * When this happens we get a MIB interrupt and the top	 * 2 bits of the counter register will be 0b11, hence	 * the mask check of phyCnt?.	 */	if (((phyCnt1 & AR_MIBCNT_INTRMASK) == AR_MIBCNT_INTRMASK) || 	    ((phyCnt2 & AR_MIBCNT_INTRMASK) == AR_MIBCNT_INTRMASK)) {		struct ar5212AniState *aniState = ahp->ah_curani;		const struct ar5212AniParams *params = aniState->params;		uint32_t ofdmPhyErrCnt, cckPhyErrCnt;		ofdmPhyErrCnt = phyCnt1 - params->ofdmPhyErrBase;		ahp->ah_stats.ast_ani_ofdmerrs +=			ofdmPhyErrCnt - aniState->ofdmPhyErrCount;		aniState->ofdmPhyErrCount = ofdmPhyErrCnt;		cckPhyErrCnt = phyCnt2 - params->cckPhyErrBase;		ahp->ah_stats.ast_ani_cckerrs +=			cckPhyErrCnt - aniState->cckPhyErrCount;		aniState->cckPhyErrCount = cckPhyErrCnt;		/*		 * NB: figure out which counter triggered.  If both		 * trigger we'll only deal with one as the processing		 * clobbers the error counter so the trigger threshold		 * check will never be true.		 */		if (aniState->ofdmPhyErrCount > params->ofdmTrigHigh)			ar5416AniOfdmErrTrigger(ah);		if (aniState->cckPhyErrCount > params->cckTrigHigh)			ar5416AniCckErrTrigger(ah);		/* NB: always restart to insure the h/w counters are reset */		ar5416AniRestart(ah, aniState);	}}static voidar5416AniLowerImmunity(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;	}}#define CLOCK_RATE 44000	/* XXX use mac_usec or similar *//* convert HW counter values to ms using 11g clock rate, goo9d enough   for 11a and Turbo *//*  * 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_tar5416AniGetListenTime(struct ath_hal *ah){	struct ath_hal_5212 *ahp = AH5212(ah);	struct ar5212AniState *aniState;	uint32_t txFrameCount, rxFrameCount, cycleCount;	int32_t listenTime;	txFrameCount = OS_REG_READ(ah, AR_TFCNT);	rxFrameCount = OS_REG_READ(ah, AR_RFCNT);	cycleCount = OS_REG_READ(ah, AR_CCCNT);	aniState = ahp->ah_curani;	if (aniState->cycleCount == 0 || aniState->cycleCount > cycleCount) {		/*		 * 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 {		int32_t ccdelta = cycleCount - aniState->cycleCount;		int32_t rfdelta = rxFrameCount - aniState->rxFrameCount;		int32_t tfdelta = txFrameCount - aniState->txFrameCount;		listenTime = (ccdelta - rfdelta - tfdelta) / CLOCK_RATE;	}	aniState->cycleCount = cycleCount;	aniState->txFrameCount = txFrameCount;	aniState->rxFrameCount = rxFrameCount;	return listenTime;}/* * Update ani stats in preparation for listen time processing. */static voidupdateMIBStats(struct ath_hal *ah, struct ar5212AniState *aniState){	struct ath_hal_5212 *ahp = AH5212(ah);	const struct ar5212AniParams *params = aniState->params;	uint32_t phyCnt1, phyCnt2;	int32_t ofdmPhyErrCnt, cckPhyErrCnt;	/* Clear the mib counters and save them in the stats */	ar5212UpdateMibCounters(ah, &ahp->ah_mibStats);	/* NB: these are not reset-on-read */	phyCnt1 = OS_REG_READ(ah, AR_PHY_ERR_1);	phyCnt2 = OS_REG_READ(ah, AR_PHY_ERR_2);	/* NB: these are spec'd to never roll-over */	ofdmPhyErrCnt = phyCnt1 - params->ofdmPhyErrBase;	if (ofdmPhyErrCnt < 0) {		HALDEBUG(ah, HAL_DEBUG_ANI, "OFDM phyErrCnt %d phyCnt1 0x%x\n",		    ofdmPhyErrCnt, phyCnt1);		ofdmPhyErrCnt = AR_PHY_COUNTMAX;	}	ahp->ah_stats.ast_ani_ofdmerrs +=	     ofdmPhyErrCnt - aniState->ofdmPhyErrCount;	aniState->ofdmPhyErrCount = ofdmPhyErrCnt;	cckPhyErrCnt = phyCnt2 - params->cckPhyErrBase;	if (cckPhyErrCnt < 0) {		HALDEBUG(ah, HAL_DEBUG_ANI, "CCK phyErrCnt %d phyCnt2 0x%x\n",		    cckPhyErrCnt, phyCnt2);		cckPhyErrCnt = AR_PHY_COUNTMAX;	}	ahp->ah_stats.ast_ani_cckerrs +=		cckPhyErrCnt - aniState->cckPhyErrCount;	aniState->cckPhyErrCount = cckPhyErrCnt;}/* * Do periodic processing.  This routine is called from the * driver's rx interrupt handler after processing frames. */voidar5416AniPoll(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);		}	}}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -