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

📄 ar5212_ani.c

📁 Atheros wifi driver source code
💻 C
📖 第 1 页 / 共 3 页
字号:
/* * Copyright (c) 2002-2005 Sam Leffler, Errno Consulting * Copyright (c) 2002-2005 Atheros Communications, Inc. * All rights reserved. * * $Id: ar5212_ani.c,v 1.14 2006/10/13 08:38:26 steven Exp $ */#include "opt_ah.h"#ifdef AH_SUPPORT_AR5212#include "ah.h"#include "ah_internal.h"#include "ah_desc.h"#include "ar5212/ar5212.h"#include "ar5212/ar5212reg.h"#include "ar5212/ar5212phy.h"/* * Anti noise immunity support.  We track phy errors and react * to excessive errors by adjusting the noise immunity parameters. *//****************************************************************************** * * New Ani Algorithm for Station side only * *****************************************************************************/#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)#define	DATA_RSSI(ahp) \	HAL_EP_RND(ahp->ah_stats.ast_nodestats.ns_avgrssi, \		HAL_RSSI_EP_MULTIPLIER)#define	ah_mibStats	ah_stats.ast_mibstats#define STRONG_RSSI 55#define MAX(a,b) (((a) > (b))?(a):(b))voidar5212EnableMIBCounters(struct ath_hal *ah){	struct ath_hal_5212 *ahp = AH5212(ah);	HALDEBUG(ah, "Enable mib counters\n");	/* Clear the mib counters and save them in the stats */	ar5212UpdateMibCounters(ah, &ahp->ah_mibStats);		OS_REG_WRITE(ah, AR_FILTOFDM, 0);	OS_REG_WRITE(ah, AR_FILTCCK, 0);	OS_REG_WRITE(ah, AR_MIBC, 		     ~(AR_MIBC_COW | AR_MIBC_FMC | AR_MIBC_CMC | AR_MIBC_MCS)		     & 0x0f);	OS_REG_WRITE(ah, AR_PHYCNTMASK1, AR_PHY_ERR_OFDM_TIMING);	OS_REG_WRITE(ah, AR_PHYCNTMASK2, AR_PHY_ERR_CCK_TIMING);}void ar5212DisableMIBCounters(struct ath_hal *ah){	struct ath_hal_5212 *ahp = AH5212(ah);	HALDEBUG(ah, "Disabling MIB counters\n");	OS_REG_WRITE(ah, AR_MIBC,  AR_MIBC_FMC | AR_MIBC_CMC);		/* Clear the mib counters and save them in the stats */	ar5212UpdateMibCounters(ah, &ahp->ah_mibStats);		OS_REG_WRITE(ah, AR_FILTOFDM, 0);	OS_REG_WRITE(ah, AR_FILTCCK, 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 intar5212GetAniChannelIndex(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++) {		if (ahp->ah_ani[i].c.channel == chan->channel)			return i;		if (ahp->ah_ani[i].c.channel == 0) {			ahp->ah_ani[i].c.channel = chan->channel;			ahp->ah_ani[i].c.channelFlags = chan->channelFlags;			ahp->ah_ani[i].c.privFlags = chan->privFlags;			return i;		}	}	/* XXX statistic */	HALDEBUG(ah, "No more channel states left. Using channel 0\n");	return 0;		/* XXX gotta return something valid */#undef N}/* * Return the current ANI state of the channel we're on */struct ar5212AniState *ar5212AniGetCurrentState(struct ath_hal *ah){	return AH5212(ah)->ah_curani;}/* * Return the current statistics. */struct ar5212Stats *ar5212AniGetCurrentStats(struct ath_hal *ah){	AH5212(ah)->ah_stats.ast_ani_state = DO_ANI(ah)?1:0;	return &AH5212(ah)->ah_stats;}/* * Setup ANI handling.  Sets all thresholds and levels to default level AND * resets the channel statistics */voidar5212AniAttach(struct ath_hal *ah){#define N(a)     (sizeof(a) / sizeof(a[0]))	struct ath_hal_5212 *ahp = AH5212(ah);	int i;	ahp->ah_hasHwPhyCounters =	    (AH_PRIVATE(ah)->ah_macVersion == AR_SREV_VERSION_VENICE &&	    AH_PRIVATE(ah)->ah_macRev == AR_SREV_HAINAN);	OS_MEMZERO(ahp->ah_ani, sizeof(ahp->ah_ani));	for (i = 0; i < N(ahp->ah_ani); i++) {		/* New ANI stuff */		if (AH_PRIVATE(ah)->ah_macVersion < AR_SREV_VERSION_GRIFFIN)			ahp->ah_ani[i].maxSpurImmunity = HAL_SPUR_IMMUNE_MAX_VENICE;		else			ahp->ah_ani[i].maxSpurImmunity = HAL_SPUR_IMMUNE_MAX;		ahp->ah_ani[i].ofdmTrigHigh = HAL_ANI_OFDM_TRIG_HIGH/2;		ahp->ah_ani[i].ofdmTrigLow = HAL_ANI_OFDM_TRIG_LOW/2;		ahp->ah_ani[i].cckTrigHigh = HAL_ANI_CCK_TRIG_HIGH/2;		ahp->ah_ani[i].cckTrigLow = HAL_ANI_CCK_TRIG_LOW/2;		ahp->ah_ani[i].rssiThrHigh = HAL_ANI_RSSI_THR_HIGH;		ahp->ah_ani[i].rssiThrLow = HAL_ANI_RSSI_THR_LOW;		ahp->ah_ani[i].ofdmWeakSigDetectOff = !HAL_ANI_USE_OFDM_WEAK_SIG;		ahp->ah_ani[i].cckWeakSigThreshold = HAL_ANI_CCK_WEAK_SIG_THR;		// Steven Kuo: To improve the receive sensitivity.		ahp->ah_ani[i].spurImmunityLevel = 0;		ahp->ah_ani[i].firstepLevel = HAL_ANI_FIRSTEP_LVL;		ahp->ah_ani[i].attenOnThreshold = 65;		ahp->ah_ani[i].attenOffThreshold = 40;		ahp->ah_ani[i].rssiThrMaxNoiseImmunity = 65;		ahp->ah_ani[i].rssiThrDefNoiseImmunity = 55;		if (ahp->ah_hasHwPhyCounters) {			ahp->ah_ani[i].ofdmPhyErrBase = 				AR_PHY_COUNTMAX - HAL_ANI_OFDM_TRIG_HIGH;			ahp->ah_ani[i].cckPhyErrBase = 				AR_PHY_COUNTMAX - HAL_ANI_CCK_TRIG_HIGH;		}	}	if (ahp->ah_hasHwPhyCounters) {		HALDEBUG(ah, "Setting OfdmErrBase = 0x%08x\n",			 ahp->ah_ani[0].ofdmPhyErrBase);		HALDEBUG(ah, "Setting cckErrBase = 0x%08x\n",			 ahp->ah_ani[0].cckPhyErrBase);		/* Enable MIB Counters */		OS_REG_WRITE(ah, AR_PHYCNT1, ahp->ah_ani[0].ofdmPhyErrBase);		OS_REG_WRITE(ah, AR_PHYCNT2, ahp->ah_ani[0].cckPhyErrBase);		ar5212EnableMIBCounters(ah);	}	ahp->ah_aniPeriod = HAL_ANI_PERIOD;	ahp->ah_procPhyErr |= HAL_PROCESS_ANI;  /* Enable ani by default */#undef N}/* * Cleanup any ANI state setup. */voidar5212AniDetach(struct ath_hal *ah){	struct ath_hal_5212 *ahp = AH5212(ah);	HALDEBUG(ah, "Detaching Ani\n");	if (ahp->ah_hasHwPhyCounters) {		ar5212DisableMIBCounters(ah);		OS_REG_WRITE(ah, AR_PHYCNT1, 0);		OS_REG_WRITE(ah, AR_PHYCNT2, 0);	}}/* * Control Adaptive Noise Immunity Parameters */HAL_BOOLar5212AniControl(struct ath_hal *ah, HAL_ANI_CMD cmd, int param){#define N(a) (sizeof(a)/sizeof(a[0]))	typedef int TABLE[];	struct ath_hal_5212 *ahp = AH5212(ah);	struct ar5212AniState *aniState = ahp->ah_curani;	HAL_CHANNEL_INTERNAL *chan = AH_PRIVATE(ah)->ah_curchan;	switch (cmd) {	case HAL_RSSI_MAX_THR:		ahp->ah_curani->rssiThrMaxNoiseImmunity = param;		break;	case HAL_RSSI_DEF_THR:		ahp->ah_curani->rssiThrDefNoiseImmunity = param;		break;	case HAL_ATT_ON_THR:		ahp->ah_curani->attenOnThreshold = param;		break;	case HAL_ATT_OFF_THR:		ahp->ah_curani->attenOffThreshold = param;		break;	case HAL_ANT_SW_OPT:		if (((ahp->ah_diversityControl & HAL_ANT_OPT_MASK) >> HAL_ANT_OPT_SHIFT) == param) {			return;		}		ahp->ah_diversityControl = (ahp->ah_diversityControl &~ HAL_ANT_OPT_MASK) | 				(param << HAL_ANT_OPT_SHIFT);		ar5212SetAntennaSwitch(ah, ahp->ah_diversityControl, (HAL_CHANNEL *) chan);		break;	case HAL_ANI_TOTAL_SIZE_DESIRED:		OS_REG_RMW_FIELD(ah, AR_PHY_DESIRED_SZ,			AR_PHY_DESIRED_SZ_TOT_DES, param);		aniState->totalSizeDesired = 			OS_REG_RMR_FIELD(ah, AR_PHY_DESIRED_SZ, AR_PHY_DESIRED_SZ_TOT_DES);		break;	case HAL_ANI_COARSE_HIGH:		OS_REG_RMW_FIELD(ah, AR_PHY_AGC_CTL1,			  AR_PHY_AGC_CTL1_COARSE_HIGH, param);		aniState->coarseHigh = 			OS_REG_RMR_FIELD(ah, AR_PHY_AGC_CTL1, AR_PHY_AGC_CTL1_COARSE_HIGH);		break;	case HAL_ANI_COARSE_LOW:		OS_REG_RMW_FIELD(ah, AR_PHY_AGC_CTL1,			  AR_PHY_AGC_CTL1_COARSE_LOW, param);		aniState->coarseLow = 			OS_REG_RMR_FIELD(ah, AR_PHY_AGC_CTL1, AR_PHY_AGC_CTL1_COARSE_LOW);		break;	case HAL_ANI_FIRPWR_LEVEL:		OS_REG_RMW_FIELD(ah, AR_PHY_FIND_SIG,			AR_PHY_FIND_SIG_FIRPWR, param);		aniState->firpwr = 			OS_REG_RMR_FIELD(ah, AR_PHY_FIND_SIG, AR_PHY_FIND_SIG_FIRPWR);		break;	case HAL_ANI_NOISE_IMMUNITY_LEVEL: {		u_int level = param;		if (level >= N(ahp->ah_totalSizeDesired)) {			HALDEBUG(ah, "%s: level out of range (%u > %u)\n",				__func__, level, N(ahp->ah_totalSizeDesired));			return AH_FALSE;		}		printk("%s: ********** HAL_ANI_NOISE_IMMUNITY_LEVEL: %u **********\n", __func__, level);		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]);		aniState->totalSizeDesired = 			OS_REG_RMR_FIELD(ah, AR_PHY_DESIRED_SZ, AR_PHY_DESIRED_SZ_TOT_DES);		aniState->coarseHigh = 			OS_REG_RMR_FIELD(ah, AR_PHY_AGC_CTL1, AR_PHY_AGC_CTL1_COARSE_HIGH);		aniState->coarseLow = 			OS_REG_RMR_FIELD(ah, AR_PHY_AGC_CTL1, AR_PHY_AGC_CTL1_COARSE_LOW);		aniState->firpwr = 			OS_REG_RMR_FIELD(ah, AR_PHY_FIND_SIG, AR_PHY_FIND_SIG_FIRPWR);				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;		printk("%s: Ani OFDM weak signal detection:%s\n", __func__, on ? "on":"off");		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]);		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++;

⌨️ 快捷键说明

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