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

📄 ar5416_ani.c.svn-base

📁 最新之atheros芯片driver source code, 基于linux操作系统,內含atheros芯片HAL全部代码
💻 SVN-BASE
📖 第 1 页 / 共 2 页
字号:
/* * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting * Copyright (c) 2002-2008 Atheros Communications, Inc. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * * $Id: ar5416_ani.c,v 1.1 2008/11/11 20:46:06 sam Exp $ */#include "opt_ah.h"/* * XXX this is virtually the same code as for 5212; we reuse * storage in the 5212 state block; need to refactor. */#include "ah.h"#include "ah_internal.h"#include "ah_desc.h"#include "ar5416/ar5416.h"#include "ar5416/ar5416reg.h"#include "ar5416/ar5416phy.h"/* * Anti noise immunity support.  We track phy errors and react * to excessive errors by adjusting the noise immunity parameters. */#define HAL_EP_RND(x, mul) \	((((x)%(mul)) >= ((mul)/2)) ? ((x) + ((mul) - 1)) / (mul) : (x)/(mul))#define	BEACON_RSSI(ahp) \	HAL_EP_RND(ahp->ah_stats.ast_nodestats.ns_avgbrssi, \		HAL_RSSI_EP_MULTIPLIER)/* * ANI processing tunes radio parameters according to PHY errors * and related information.  This is done for for noise and spur * immunity in all operating modes if the device indicates it's * capable at attach time.  In addition, when there is a reference * rssi value (e.g. beacon frames from an ap in station mode) * further tuning is done. * * ANI_ENA indicates whether any ANI processing should be done; * this is specified at attach time. * * ANI_ENA_RSSI indicates whether rssi-based processing should * done, this is enabled based on operating mode and is meaningful * only if ANI_ENA is true. * * ANI parameters are typically controlled only by the hal.  The * AniControl interface however permits manual tuning through the * diagnostic api. */#define ANI_ENA(ah) \	(AH5212(ah)->ah_procPhyErr & HAL_ANI_ENA)#define ANI_ENA_RSSI(ah) \	(AH5212(ah)->ah_procPhyErr & HAL_RSSI_ANI_ENA)#define	ah_mibStats	ah_stats.ast_mibstatsstatic voidenableAniMIBCounters(struct ath_hal *ah, const struct ar5212AniParams *params){	struct ath_hal_5212 *ahp = AH5212(ah);	HALDEBUG(ah, HAL_DEBUG_ANI, "%s: Enable mib counters: "	    "OfdmPhyErrBase 0x%x cckPhyErrBase 0x%x\n",	    __func__, params->ofdmPhyErrBase, params->cckPhyErrBase);	OS_REG_WRITE(ah, AR_FILTOFDM, 0);	OS_REG_WRITE(ah, AR_FILTCCK, 0);	OS_REG_WRITE(ah, AR_PHYCNT1, params->ofdmPhyErrBase);	OS_REG_WRITE(ah, AR_PHYCNT2, params->cckPhyErrBase);	OS_REG_WRITE(ah, AR_PHY_ERR_MASK_1, AR_PHY_ERR_OFDM_TIMING);	OS_REG_WRITE(ah, AR_PHY_ERR_MASK_2, AR_PHY_ERR_CCK_TIMING);	ar5212UpdateMibCounters(ah, &ahp->ah_mibStats);	/* save+clear counters*/	ar5212EnableMibCounters(ah);			/* enable everything */}static void disableAniMIBCounters(struct ath_hal *ah){	struct ath_hal_5212 *ahp = AH5212(ah);	HALDEBUG(ah, HAL_DEBUG_ANI, "Disable MIB counters\n");	ar5212UpdateMibCounters(ah, &ahp->ah_mibStats);	/* save stats */	ar5212DisableMibCounters(ah);			/* disable everything */	OS_REG_WRITE(ah, AR_PHY_ERR_MASK_1, 0);	OS_REG_WRITE(ah, AR_PHY_ERR_MASK_2, 0);}/* * This routine returns the index into the aniState array that * corresponds to the channel in *chan.  If no match is found and the * array is still not fully utilized, a new entry is created for the * channel.  We assume the attach function has already initialized the * ah_ani values and only the channel field needs to be set. */static intar5416GetAniChannelIndex(struct ath_hal *ah, HAL_CHANNEL_INTERNAL *chan){#define N(a)     (sizeof(a) / sizeof(a[0]))	struct ath_hal_5212 *ahp = AH5212(ah);	int i;	for (i = 0; i < N(ahp->ah_ani); i++) {		struct ar5212AniState *asp = &ahp->ah_ani[i];		if (asp->c.channel == chan->channel)			return i;		if (asp->c.channel == 0) {			asp->c.channel = chan->channel;			asp->c.channelFlags = chan->channelFlags;			asp->c.privFlags = chan->privFlags;			asp->isSetup = AH_FALSE;			if (IS_CHAN_2GHZ(chan))				asp->params = &ahp->ah_aniParams24;			else				asp->params = &ahp->ah_aniParams5;			return i;		}	}	/* XXX statistic */	HALDEBUG(ah, HAL_DEBUG_ANY,	    "No more channel states left. Using channel 0\n");	return 0;		/* XXX gotta return something valid */#undef N}static voidsetPhyErrBase(struct ath_hal *ah, struct ar5212AniParams *params){	if (params->ofdmTrigHigh >= AR_PHY_COUNTMAX) {		HALDEBUG(ah, HAL_DEBUG_ANY,		    "OFDM Trigger %d is too high for hw counters, using max\n",		    params->ofdmTrigHigh);		params->ofdmPhyErrBase = 0;	} else		params->ofdmPhyErrBase = AR_PHY_COUNTMAX - params->ofdmTrigHigh;	if (params->cckTrigHigh >= AR_PHY_COUNTMAX) {		HALDEBUG(ah, HAL_DEBUG_ANY,		    "CCK Trigger %d is too high for hw counters, using max\n",		    params->cckTrigHigh);		params->cckPhyErrBase = 0;	} else		params->cckPhyErrBase = AR_PHY_COUNTMAX - params->cckTrigHigh;}/* * Setup ANI handling.  Sets all thresholds and reset the * channel statistics.  Note that ar5416AniReset should be * called by ar5416Reset before anything else happens and * that's where we force initial settings. */voidar5416AniAttach(struct ath_hal *ah, const struct ar5212AniParams *params24,	const struct ar5212AniParams *params5, HAL_BOOL enable){	struct ath_hal_5212 *ahp = AH5212(ah);	if (params24 != AH_NULL) {		OS_MEMCPY(&ahp->ah_aniParams24, params24, sizeof(*params24));		setPhyErrBase(ah, &ahp->ah_aniParams24);	}	if (params5 != AH_NULL) {		OS_MEMCPY(&ahp->ah_aniParams5, params5, sizeof(*params5));		setPhyErrBase(ah, &ahp->ah_aniParams5);	}	OS_MEMZERO(ahp->ah_ani, sizeof(ahp->ah_ani));	/* Enable MIB Counters */	enableAniMIBCounters(ah, &ahp->ah_aniParams24 /*XXX*/);	if (enable) {		/* Enable ani now */		HALASSERT(params24 != AH_NULL && params5 != AH_NULL);		ahp->ah_procPhyErr |= HAL_ANI_ENA;	} else {		ahp->ah_procPhyErr &= ~HAL_ANI_ENA;	}}/* * Cleanup any ANI state setup. */voidar5416AniDetach(struct ath_hal *ah){	HALDEBUG(ah, HAL_DEBUG_ANI, "Detaching Ani\n");	disableAniMIBCounters(ah);}/* * Control Adaptive Noise Immunity Parameters */HAL_BOOLar5416AniControl(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: 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: 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: 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;}static voidar5416AniOfdmErrTrigger(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) {		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 			 */			/* XXX can optimize */

⌨️ 快捷键说明

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