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

📄 ar5211_reset.c

📁 Atheros wifi driver source code
💻 C
📖 第 1 页 / 共 4 页
字号:
				upperPower = pPowerInfo[upperIndex].twicePwr54;				break;			}		}		twicePower = ar5211GetInterpolatedValue(chan->channel,			lowerChannel, upperChannel, lowerPower, upperPower, 0);		/* Reduce power by band edge restrictions */		twicePower = AH_MIN(twicePower, twiceMaxEdgePower);		/*		 * If turbo is set, reduce power to keep power		 * consumption under 2 Watts.  Note that we always do		 * this unless specially configured.  Then we limit		 * power only for non-AP operation.		 */		if (IS_CHAN_TURBO(chan) && ahp->ah_eeversion >= AR_EEPROM_VER3_1#ifdef AH_ENABLE_AP_SUPPORT		    && AH_PRIVATE(ah)->ah_opmode != HAL_M_HOSTAP#endif		) {			twicePower = AH_MIN(twicePower, ahp->ah_turbo2WMaxPower5);		}		/* Reduce power by max regulatory domain allowed restrictions */		pRatesPower[i] = AH_MIN(twicePower, twiceMaxRDPower - twiceAntennaReduction);		/* Use 6 Mb power level for transmit power scaling reduction */		/* We don't want to reduce higher rates if its not needed */		if (i == 0) {			scaledPower = pRatesPower[0] -				(tpcScaleReductionTable[AH_PRIVATE(ah)->ah_tpScale] * 2);			if (scaledPower < 1)				scaledPower = 1;		}		pRatesPower[i] = AH_MIN(pRatesPower[i], scaledPower);	}	/* Record txPower at Rate 6 for info gathering */	ahp->ah_tx6PowerInHalfDbm = pRatesPower[0];#ifdef AH_DEBUG	HALDEBUG(ah, "%s: final output power setting %d MHz:\n",		__func__, chan->channel);	HALDEBUG(ah, "6 Mb %d dBm, MaxRD: %d dBm, MaxEdge %d dBm\n",		scaledPower / 2, twiceMaxRDPower / 2, twiceMaxEdgePower / 2);	HALDEBUG(ah, "TPC Scale %d dBm - Ant Red %d dBm\n",		tpcScaleReductionTable[AH_PRIVATE(ah)->ah_tpScale] * 2,		twiceAntennaReduction / 2);	if (IS_CHAN_TURBO(chan) && ahp->ah_eeversion >= AR_EEPROM_VER3_1)		HALDEBUG(ah, "Max Turbo %d dBm\n", ahp->ah_turbo2WMaxPower5);	HALDEBUG(ah, "  %2d | %2d | %2d | %2d | %2d | %2d | %2d | %2d dBm\n",		pRatesPower[0] / 2, pRatesPower[1] / 2, pRatesPower[2] / 2,		pRatesPower[3] / 2, pRatesPower[4] / 2, pRatesPower[5] / 2,		pRatesPower[6] / 2, pRatesPower[7] / 2);#endif /* AH_DEBUG */	/* Write the power table into the hardware */	OS_REG_WRITE(ah, AR_PHY_POWER_TX_RATE1,		 ((paPreDEnable & 1)<< 30) | ((pRatesPower[3] & mask) << 24) |		 ((paPreDEnable & 1)<< 22) | ((pRatesPower[2] & mask) << 16) |		 ((paPreDEnable & 1)<< 14) | ((pRatesPower[1] & mask) << 8) |		 ((paPreDEnable & 1)<< 6 ) |  (pRatesPower[0] & mask));	OS_REG_WRITE(ah, AR_PHY_POWER_TX_RATE2,		 ((paPreDEnable & 1)<< 30) | ((pRatesPower[7] & mask) << 24) |		 ((paPreDEnable & 1)<< 22) | ((pRatesPower[6] & mask) << 16) |		 ((paPreDEnable & 1)<< 14) | ((pRatesPower[5] & mask) << 8) |		 ((paPreDEnable & 1)<< 6 ) |  (pRatesPower[4] & mask));	/* set max power to the power value at rate 6 */	ar5211SetTxPowerLimit(ah, pRatesPower[0]);	AH_PRIVATE(ah)->ah_maxPowerLevel = pRatesPower[0];}/* * Get or interpolate the pcdac value from the calibrated data */u_int16_tar5211GetScaledPower(u_int16_t channel, u_int16_t pcdacValue, PCDACS_EEPROM *pSrcStruct){	u_int16_t powerValue;	u_int16_t lFreq, rFreq;		/* left and right frequency values */	u_int16_t llPcdac, ulPcdac;	/* lower and upper left pcdac values */	u_int16_t lrPcdac, urPcdac;	/* lower and upper right pcdac values */	u_int16_t lPwr, uPwr;		/* lower and upper temp pwr values */	u_int16_t lScaledPwr, rScaledPwr; /* left and right scaled power */	if (ar5211FindValueInList(channel, pcdacValue, pSrcStruct, &powerValue))		/* value was copied from srcStruct */		return powerValue;	ar5211GetLowerUpperValues(channel, pSrcStruct->pChannelList,		pSrcStruct->numChannels, &lFreq, &rFreq);	ar5211GetLowerUpperPcdacs(pcdacValue, lFreq, pSrcStruct,		&llPcdac, &ulPcdac);	ar5211GetLowerUpperPcdacs(pcdacValue, rFreq, pSrcStruct,		&lrPcdac, &urPcdac);	/* get the power index for the pcdac value */	ar5211FindValueInList(lFreq, llPcdac, pSrcStruct, &lPwr);	ar5211FindValueInList(lFreq, ulPcdac, pSrcStruct, &uPwr);	lScaledPwr = ar5211GetInterpolatedValue(pcdacValue,				llPcdac, ulPcdac, lPwr, uPwr, 0);	ar5211FindValueInList(rFreq, lrPcdac, pSrcStruct, &lPwr);	ar5211FindValueInList(rFreq, urPcdac, pSrcStruct, &uPwr);	rScaledPwr = ar5211GetInterpolatedValue(pcdacValue,				lrPcdac, urPcdac, lPwr, uPwr, 0);	return ar5211GetInterpolatedValue(channel, lFreq, rFreq,		lScaledPwr, rScaledPwr, 0);}/* * Find the value from the calibrated source data struct */HAL_BOOLar5211FindValueInList(u_int16_t channel, u_int16_t pcdacValue, PCDACS_EEPROM *pSrcStruct, u_int16_t *powerValue){	DATA_PER_CHANNEL *pChannelData;	u_int16_t *pPcdac;	u_int16_t i, j;	pChannelData = pSrcStruct->pDataPerChannel;	for (i = 0; i < pSrcStruct->numChannels; i++ ) {		if (pChannelData->channelValue == channel) {			pPcdac = pChannelData->PcdacValues;			for (j = 0; j < pChannelData->numPcdacValues; j++ ) {				if (*pPcdac == pcdacValue) {					*powerValue = pChannelData->PwrValues[j];					return AH_TRUE;				}				pPcdac++;			}		}		pChannelData++;	}	return AH_FALSE;}/* * Returns interpolated or the scaled up interpolated value */u_int16_tar5211GetInterpolatedValue(u_int16_t target,	u_int16_t srcLeft, u_int16_t srcRight,	u_int16_t targetLeft, u_int16_t targetRight,	HAL_BOOL scaleUp){	u_int16_t rv;	int16_t lRatio;	u_int16_t scaleValue = EEP_SCALE;	/* to get an accurate ratio, always scale, if want to scale, then don't scale back down */	if ((targetLeft * targetRight) == 0)		return 0;	if (scaleUp)		scaleValue = 1;	if (srcRight != srcLeft) {		/*		 * Note the ratio always need to be scaled,		 * since it will be a fraction.		 */		lRatio = (target - srcLeft) * EEP_SCALE / (srcRight - srcLeft);		if (lRatio < 0) {		    /* Return as Left target if value would be negative */		    rv = targetLeft * (scaleUp ? EEP_SCALE : 1);		} else if (lRatio > EEP_SCALE) {		    /* Return as Right target if Ratio is greater than 100% (SCALE) */		    rv = targetRight * (scaleUp ? EEP_SCALE : 1);		} else {			rv = (lRatio * targetRight + (EEP_SCALE - lRatio) *					targetLeft) / scaleValue;		}	} else {		rv = targetLeft;		if (scaleUp)			rv *= EEP_SCALE;	}	return rv;}/* *  Look for value being within 0.1 of the search values *  however, NDIS can't do float calculations, so multiply everything *  up by EEP_SCALE so can do integer arithmatic * * INPUT  value	   -value to search for * INPUT  pList	   -ptr to the list to search * INPUT  listSize	-number of entries in list * OUTPUT pLowerValue -return the lower value * OUTPUT pUpperValue -return the upper value */voidar5211GetLowerUpperValues(u_int16_t value,	u_int16_t *pList, u_int16_t listSize,	u_int16_t *pLowerValue, u_int16_t *pUpperValue){	u_int16_t listEndValue = *(pList + listSize - 1);	u_int32_t target = value * EEP_SCALE;	int i;	/*	 * See if value is lower than the first value in the list	 * if so return first value	 */	if (target < (u_int32_t)(*pList * EEP_SCALE - EEP_DELTA)) {		*pLowerValue = *pList;		*pUpperValue = *pList;		return;	}	/*	 * See if value is greater than last value in list	 * if so return last value	 */	if (target > (u_int32_t)(listEndValue * EEP_SCALE + EEP_DELTA)) {		*pLowerValue = listEndValue;		*pUpperValue = listEndValue;		return;	}	/* look for value being near or between 2 values in list */	for (i = 0; i < listSize; i++) {		/*		 * If value is close to the current value of the list		 * then target is not between values, it is one of the values		 */		if (abs(pList[i] * EEP_SCALE - (int32_t) target) < EEP_DELTA) {			*pLowerValue = pList[i];			*pUpperValue = pList[i];			return;		}		/*		 * Look for value being between current value and next value		 * if so return these 2 values		 */		if (target < (u_int32_t)(pList[i + 1] * EEP_SCALE - EEP_DELTA)) {			*pLowerValue = pList[i];			*pUpperValue = pList[i + 1];			return;		}	}}/* * Get the upper and lower pcdac given the channel and the pcdac * used in the search */voidar5211GetLowerUpperPcdacs(u_int16_t pcdac, u_int16_t channel,	PCDACS_EEPROM *pSrcStruct,	u_int16_t *pLowerPcdac, u_int16_t *pUpperPcdac){	DATA_PER_CHANNEL *pChannelData;	int i;	/* Find the channel information */	pChannelData = pSrcStruct->pDataPerChannel;	for (i = 0; i < pSrcStruct->numChannels; i++) {		if (pChannelData->channelValue == channel)			break;		pChannelData++;	}	ar5211GetLowerUpperValues(pcdac, pChannelData->PcdacValues,		pChannelData->numPcdacValues, pLowerPcdac, pUpperPcdac);}#define	DYN_ADJ_UP_MARGIN	15#define	DYN_ADJ_LO_MARGIN	20static const GAIN_OPTIMIZATION_LADDER gainLadder = {	9,					/* numStepsInLadder */	4,					/* defaultStepNum */	{ { {4, 1, 1, 1},  6, "FG8"},	  { {4, 0, 1, 1},  4, "FG7"},	  { {3, 1, 1, 1},  3, "FG6"},	  { {4, 0, 0, 1},  1, "FG5"},	  { {4, 1, 1, 0},  0, "FG4"},	/* noJack */	  { {4, 0, 1, 0}, -2, "FG3"},	/* halfJack */	  { {3, 1, 1, 0}, -3, "FG2"},	/* clip3 */	  { {4, 0, 0, 0}, -4, "FG1"},	/* noJack */	  { {2, 1, 1, 0}, -6, "FG0"} 	/* clip2 */	}};/* * Initialize the gain structure to good values */voidar5211InitializeGainValues(struct ath_hal *ah){	struct ath_hal_5211 *ahp = AH5211(ah);	GAIN_VALUES *gv = &ahp->ah_gainValues;	/* initialize gain optimization values */	gv->currStepNum = gainLadder.defaultStepNum;	gv->currStep = &gainLadder.optStep[gainLadder.defaultStepNum];	gv->active = AH_TRUE;	gv->loTrig = 20;	gv->hiTrig = 35;}static HAL_BOOLar5211InvalidGainReadback(struct ath_hal *ah, GAIN_VALUES *gv){	HAL_CHANNEL_INTERNAL *chan = AH_PRIVATE(ah)->ah_curchan;	u_int32_t gStep, g;	u_int32_t L1, L2, L3, L4;	if (IS_CHAN_CCK(chan)) {		gStep = 0x18;		L1 = 0;		L2 = gStep + 4;		L3 = 0x40;		L4 = L3 + 50;		gv->loTrig = L1;		gv->hiTrig = L4+5;	} else {		gStep = 0x3f;		L1 = 0;		L2 = 50;		L3 = L1;		L4 = L3 + 50;		gv->loTrig = L1 + DYN_ADJ_LO_MARGIN;		gv->hiTrig = L4 - DYN_ADJ_UP_MARGIN;	}	g = gv->currGain;	return !((g >= L1 && g<= L2) || (g >= L3 && g <= L4));}/* * Enable the probe gain check on the next packet */static voidar5211RequestRfgain(struct ath_hal *ah){	struct ath_hal_5211 *ahp = AH5211(ah);	/* Enable the gain readback probe */	OS_REG_WRITE(ah, AR_PHY_PAPD_PROBE,		  SM(ahp->ah_tx6PowerInHalfDbm, AR_PHY_PAPD_PROBE_POWERTX)		| AR_PHY_PAPD_PROBE_NEXT_TX);	ahp->ah_rfgainState = HAL_RFGAIN_READ_REQUESTED;}/* * Exported call to check for a recent gain reading and return * the current state of the thermal calibration gain engine. */HAL_RFGAINar5211GetRfgain(struct ath_hal *ah){	struct ath_hal_5211 *ahp = AH5211(ah);	GAIN_VALUES *gv = &ahp->ah_gainValues;	u_int32_t rddata;	if (!gv->active)		return HAL_RFGAIN_INACTIVE;	if (ahp->ah_rfgainState == HAL_RFGAIN_READ_REQUESTED) {		/* Caller had asked to setup a new reading. Check it. */		rddata = OS_REG_READ(ah, AR_PHY_PAPD_PROBE);		if ((rddata & AR_PHY_PAPD_PROBE_NEXT_TX) == 0) {			/* bit got cleared, we have a new reading. */			gv->currGain = rddata >> AR_PHY_PAPD_PROBE_GAINF_S;			/* inactive by default */			ahp->ah_rfgainState = HAL_RFGAIN_INACTIVE;			if (!ar5211InvalidGainReadback(ah, gv) &&			    ar5211IsGainAdjustNeeded(ah, gv) &&			    ar5211AdjustGain(ah, gv) > 0) {				/*				 * Change needed. Copy ladder info				 * into eeprom info.				 */				ar5211SetRfgain(ah, gv);				ahp->ah_rfgainState = HAL_RFGAIN_NEED_CHANGE;			}		}	}	return ahp->ah_rfgainState;}/* * Check to see if our readback gain level sits within the linear * region of our current variable attenuation window */static HAL_BOOLar5211IsGainAdjustNeeded(struct ath_hal *ah, const GAIN_VALUES *gv){	return (gv->currGain <= gv->loTrig || gv->currGain >= gv->hiTrig);}/* * Move the rabbit ears in the correct direction. */static int32_t ar5211AdjustGain(struct ath_hal *ah, GAIN_VALUES *gv){	/* return > 0 for valid adjustments. */	if (!gv->active)		return -1;	gv->currStep = &gainLadder.optStep[gv->currStepNum];	if (gv->currGain >= gv->hiTrig) {		if (gv->currStepNum == 0) {			HALDEBUG(ah, "%s: Max gain limit.\n", __func__);			return -1;		}		HALDEBUG(ah, "%s: Adding gain: currG=%d [%s] --> ",			__func__, gv->currGain, gv->currStep->stepName);		gv->targetGain = gv->currGain;		while (gv->targetGain >= gv->hiTrig && gv->currStepNum > 0) {			gv->targetGain -= 2 * (gainLadder.optStep[--(gv->currStepNum)].stepGain -				gv->currStep->stepGain);			gv->currStep = &gainLadder.optStep[gv->currStepNum];		}		HALDEBUG(ah, "targG=%d [%s]\n",			gv->targetGain, gv->currStep->stepName);		return 1;	}	if (gv->currGain <= gv->loTrig) {		if (gv->currStepNum == gainLadder.numStepsInLadder-1) {			HALDEBUG(ah, "%s: Min gain limit.\n", __func__);			return -2;		}		HALDEBUG(ah, "%s: Deducting gain: currG=%d [%s] --> ",			__func__, gv->currGain, gv->currStep->stepName);		gv->targetGain = gv->currGain;		while (gv->targetGain <= gv->loTrig &&		      gv->currStepNum < (gainLadder.numStepsInLadder - 1)) {			gv->targetGain -= 2 *				(gainLadder.optStep[++(gv->currStepNum)].stepGain - gv->currStep->stepGain);			gv->currStep = &gainLadder.optStep[gv->currStepNum];		}		HALDEBUG(ah, "targG=%d [%s]\n",			gv->targetGain, gv->currStep->stepName);		return 2;	}	return 0;		/* caller didn't call needAdjGain first */}/* * Adjust the 5GHz EEPROM information with the desired calibration values. */static voidar5211SetRfgain(struct ath_hal *ah, const GAIN_VALUES *gv){	struct ath_hal_5211 *ahp = AH5211(ah);	if (!gv->active)		return;	ahp->ah_cornerCal.clip = gv->currStep->paramVal[0]; /* bb_tx_clip */	ahp->ah_cornerCal.pd90 = gv->currStep->paramVal[1]; /* rf_pwd_90 */	ahp->ah_cornerCal.pd84 = gv->currStep->paramVal[2]; /* rf_pwd_84 */	ahp->ah_cornerCal.gSel = gv->currStep->paramVal[3]; /* rf_rfgainsel */}voidar5211SetPCUConfig(struct ath_hal *ah){	u_int32_t val;	val = OS_REG_READ(ah, AR_STA_ID1) & 0xffff;	switch (AH_PRIVATE(ah)->ah_opmode) {	case HAL_M_HOSTAP:		OS_REG_WRITE(ah, AR_STA_ID1, val			| AR_STA_ID1_STA_AP			| AR_STA_ID1_RTS_USE_DEF);		break;	case HAL_M_IBSS:		OS_REG_WRITE(ah, AR_STA_ID1, val			| AR_STA_ID1_ADHOC			| AR_STA_ID1_DESC_ANTENNA);		break;	case HAL_M_STA:	case HAL_M_MONITOR:		OS_REG_WRITE(ah, AR_STA_ID1, val			| AR_STA_ID1_DEFAULT_ANTENNA);		break;	}}#endif /* AH_SUPPORT_AR5211 */

⌨️ 快捷键说明

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