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

📄 ar5212_ani.c

📁 最新之atheros芯片driver source code, 基于linux操作系统,內含atheros芯片HAL全部代码
💻 C
📖 第 1 页 / 共 3 页
字号:
/* * 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: ar5212_ani.c,v 1.7 2008/11/21 00:16:21 sam Exp $ */#include "opt_ah.h"#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. */#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_PHYCNTMASK1, AR_PHY_ERR_OFDM_TIMING);	OS_REG_WRITE(ah, AR_PHYCNTMASK2, 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_PHYCNTMASK1, 0);	OS_REG_WRITE(ah, AR_PHYCNTMASK2, 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++) {		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}/* * 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){	struct ath_hal_5212 *ahp = AH5212(ah);	/* update mib stats so we return current data */	/* XXX? side-effects to doing this here? */	ar5212UpdateMibCounters(ah, &ahp->ah_mibStats);	return &ahp->ah_stats;}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 ar5212AniReset should be * called by ar5212Reset before anything else happens and * that's where we force initial settings. */voidar5212AniAttach(struct ath_hal *ah, const struct ar5212AniParams *params24,	const struct ar5212AniParams *params5, HAL_BOOL enable){	struct ath_hal_5212 *ahp = AH5212(ah);	ahp->ah_hasHwPhyCounters =		AH_PRIVATE(ah)->ah_caps.halHwPhyCounterSupport;	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));	if (ahp->ah_hasHwPhyCounters) {		/* 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;	}}HAL_BOOLar5212AniSetParams(struct ath_hal *ah, const struct ar5212AniParams *params24,	const struct ar5212AniParams *params5){	struct ath_hal_5212 *ahp = AH5212(ah);	HAL_BOOL ena = (ahp->ah_procPhyErr & HAL_ANI_ENA) != 0;	ar5212AniControl(ah, HAL_ANI_MODE, AH_FALSE);	OS_MEMCPY(&ahp->ah_aniParams24, params24, sizeof(*params24));	setPhyErrBase(ah, &ahp->ah_aniParams24);	OS_MEMCPY(&ahp->ah_aniParams5, params5, sizeof(*params5));	setPhyErrBase(ah, &ahp->ah_aniParams5);	OS_MEMZERO(ahp->ah_ani, sizeof(ahp->ah_ani));	ar5212AniReset(ah, AH_PRIVATE(ah)->ah_curchan,	    AH_PRIVATE(ah)->ah_opmode, AH_FALSE);	ar5212AniControl(ah, HAL_ANI_MODE, ena);	return AH_TRUE;}/* * Cleanup any ANI state setup. */voidar5212AniDetach(struct ath_hal *ah){	struct ath_hal_5212 *ahp = AH5212(ah);	HALDEBUG(ah, HAL_DEBUG_ANI, "Detaching Ani\n");	if (ahp->ah_hasHwPhyCounters)		disableAniMIBCounters(ah);}/* * Control Adaptive Noise Immunity Parameters */HAL_BOOLar5212AniControl(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]);		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;

⌨️ 快捷键说明

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