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

📄 ar5112.c

📁 Atheros wifi driver source code
💻 C
📖 第 1 页 / 共 2 页
字号:
				return AH_FALSE;			}			OS_MEMCPY(&powTableLXPD[kk][0], &tmpPowerTable[0],				64 * sizeof(int16_t));			jj = xgainList[1];			numPcd = pRawCh->pDataPerXPD[jj].numPcdacs;			OS_MEMCPY(&pcdacs[0], &pRawCh->pDataPerXPD[jj].pcdac[0],				numPcd * sizeof(u_int16_t));			OS_MEMCPY(&powers[0],				&pRawCh->pDataPerXPD[jj].pwr_t4[0],				numPcd * sizeof(int16_t));			if (!getFullPwrTable(numPcd, &pcdacs[0], &powers[0],				pRawCh->maxPower_t4, &tmpPowerTable[0])) {				return AH_FALSE;			}			OS_MEMCPY(&powTableHXPD[kk][0], &tmpPowerTable[0],				64 * sizeof(int16_t));		}		kk++;	}	chan_L = pPowerExpn->pChannels[chan_idx_L];	chan_R = pPowerExpn->pChannels[chan_idx_R];	kk = chan_idx_R - chan_idx_L;	if (xgainList[1] == 0xDEAD) {		for (jj = 0; jj < 64; jj++) {			pwr_table0[jj] = interpolate_signed(				chan->channel, chan_L, chan_R,				powTableLXPD[0][jj], powTableLXPD[kk][jj]);		}		Pmin = getPminAndPcdacTableFromPowerTable(&pwr_table0[0],				ahp->ah_pcdacTable);		*pPowerMin = (int16_t) (Pmin / 2);		*pPowerMid = (int16_t) (pwr_table0[63] / 2);		*pPowerMax = (int16_t) (pwr_table0[63] / 2);		rfXpdGain[0] = xgainList[0];		rfXpdGain[1] = rfXpdGain[0];	} else {		for (jj = 0; jj < 64; jj++) {			pwr_table0[jj] = interpolate_signed(				chan->channel, chan_L, chan_R,				powTableLXPD[0][jj], powTableLXPD[kk][jj]);			pwr_table1[jj] = interpolate_signed(				chan->channel, chan_L, chan_R,				powTableHXPD[0][jj], powTableHXPD[kk][jj]);		}		if (numXpdGain == 2) {			Pmin = getPminAndPcdacTableFromTwoPowerTables(				&pwr_table0[0], &pwr_table1[0],				ahp->ah_pcdacTable, &Pmid);			*pPowerMin = (int16_t) (Pmin / 2);			*pPowerMid = (int16_t) (Pmid / 2);			*pPowerMax = (int16_t) (pwr_table0[63] / 2);			rfXpdGain[0] = xgainList[0];			rfXpdGain[1] = xgainList[1];		} else if (minPwr_t4 <= pwr_table1[63] &&			   maxPwr_t4 <= pwr_table1[63]) {			Pmin = getPminAndPcdacTableFromPowerTable(				&pwr_table1[0], ahp->ah_pcdacTable);			rfXpdGain[0] = xgainList[1];			rfXpdGain[1] = rfXpdGain[0];			*pPowerMin = (int16_t) (Pmin / 2);			*pPowerMid = (int16_t) (pwr_table1[63] / 2);			*pPowerMax = (int16_t) (pwr_table1[63] / 2);		} else {			Pmin = getPminAndPcdacTableFromPowerTable(				&pwr_table0[0], ahp->ah_pcdacTable);			rfXpdGain[0] = xgainList[0];			rfXpdGain[1] = rfXpdGain[0];			*pPowerMin = (int16_t) (Pmin/2);			*pPowerMid = (int16_t) (pwr_table0[63] / 2);			*pPowerMax = (int16_t) (pwr_table0[63] / 2);		}	}	/*	 * Move 5112 rates to match power tables where the max	 * power table entry corresponds with maxPower.	 */	HALASSERT(*pPowerMax <= PCDAC_STOP);	ahp->ah_txPowerIndexOffset = PCDAC_STOP - *pPowerMax;	return AH_TRUE;}/* * Returns interpolated or the scaled up interpolated value */static int16_tinterpolate_signed(u_int16_t target, u_int16_t srcLeft, u_int16_t srcRight,	int16_t targetLeft, int16_t targetRight){	int16_t rv;	if (srcRight != srcLeft) {		rv = ((target - srcLeft)*targetRight +		      (srcRight - target)*targetLeft) / (srcRight - srcLeft);	} else {		rv = targetLeft;	}	return rv;}/* * Return indices surrounding the value in sorted integer lists. * * NB: the input list is assumed to be sorted in ascending order */static voidar5212GetLowerUpperIndex(u_int16_t v, u_int16_t *lp, u_int16_t listSize,                          u_int32_t *vlo, u_int32_t *vhi){	u_int32_t target = v;	u_int16_t *ep = lp+listSize;	u_int16_t *tp;	/*	 * Check first and last elements for out-of-bounds conditions.	 */	if (target < lp[0]) {		*vlo = *vhi = 0;		return;	}	if (target >= ep[-1]) {		*vlo = *vhi = listSize - 1;		return;	}	/* look for value being near or between 2 values in list */	for (tp = lp; tp < ep; tp++) {		/*		 * If value is close to the current value of the list		 * then target is not between values, it is one of the values		 */		if (*tp == target) {			*vlo = *vhi = tp - lp;			return;		}		/*		 * Look for value being between current value and next value		 * if so return these 2 values		 */		if (target < tp[1]) {			*vlo = tp - lp;			*vhi = *vlo + 1;			return;		}	}}static HAL_BOOLgetFullPwrTable(u_int16_t numPcdacs, u_int16_t *pcdacs, int16_t *power, int16_t maxPower, int16_t *retVals){	u_int16_t    ii;	u_int16_t    idxL = 0;	u_int16_t    idxR = 1;	if (numPcdacs < 2) {		HALDEBUG(AH_NULL, "%s: at least 2 pcdac values needed [%d]\n",			__func__, numPcdacs);		return AH_FALSE;	}	for (ii = 0; ii < 64; ii++) {		if (ii>pcdacs[idxR] && idxR < numPcdacs-1) {			idxL++;			idxR++;		}		retVals[ii] = interpolate_signed(ii,			pcdacs[idxL], pcdacs[idxR], power[idxL], power[idxR]);		if (retVals[ii] >= maxPower) {			while (ii < 64)				retVals[ii++] = maxPower;		}	}	return AH_TRUE;}/* * Takes a single calibration curve and creates a power table. * Adjusts the new power table so the max power is relative * to the maximum index in the power table. * * WARNING: rates must be adjusted for this relative power table */static int16_tgetPminAndPcdacTableFromPowerTable(int16_t *pwrTableT4, u_int16_t retVals[]){    int16_t ii, jj, jjMax;    int16_t pMin, currPower, pMax;    /* If the spread is > 31.5dB, keep the upper 31.5dB range */    if ((pwrTableT4[63] - pwrTableT4[0]) > 126) {        pMin = pwrTableT4[63] - 126;    } else {        pMin = pwrTableT4[0];    }    pMax = pwrTableT4[63];    jjMax = 63;    /* Search for highest pcdac 0.25dB below maxPower */    while ((pwrTableT4[jjMax] > (pMax - 1) ) && (jjMax >= 0)) {        jjMax--;    }    jj = jjMax;    currPower = pMax;    for (ii = 63; ii >= 0; ii--) {        while ((jj < 64) && (jj > 0) && (pwrTableT4[jj] >= currPower)) {            jj--;        }        if (jj == 0) {            while (ii >= 0) {                retVals[ii] = retVals[ii + 1];                ii--;            }            break;        }        retVals[ii] = jj;        currPower -= 2;  // corresponds to a 0.5dB step    }    return pMin;}/* * Combines the XPD curves from two calibration sets into a single * power table and adjusts the power table so the max power is relative * to the maximum index in the power table * * WARNING: rates must be adjusted for this relative power table */static int16_tgetPminAndPcdacTableFromTwoPowerTables(int16_t *pwrTableLXpdT4,	int16_t *pwrTableHXpdT4, u_int16_t retVals[], int16_t *pMid){    int16_t     ii, jj, jjMax;    int16_t     pMin, pMax, currPower;    int16_t     *pwrTableT4;    u_int16_t    msbFlag = 0x40;  // turns on the 7th bit of the pcdac    /* If the spread is > 31.5dB, keep the upper 31.5dB range */    if ((pwrTableLXpdT4[63] - pwrTableHXpdT4[0]) > 126) {        pMin = pwrTableLXpdT4[63] - 126;    } else {        pMin = pwrTableHXpdT4[0];    }    pMax = pwrTableLXpdT4[63];    jjMax = 63;    /* Search for highest pcdac 0.25dB below maxPower */    while ((pwrTableLXpdT4[jjMax] > (pMax - 1) ) && (jjMax >= 0)){        jjMax--;    }    *pMid = pwrTableHXpdT4[63];    jj = jjMax;    ii = 63;    currPower = pMax;    pwrTableT4 = &(pwrTableLXpdT4[0]);    while (ii >= 0) {        if ((currPower <= *pMid) || ( (jj == 0) && (msbFlag == 0x40))){            msbFlag = 0x00;            pwrTableT4 = &(pwrTableHXpdT4[0]);            jj = 63;        }        while ((jj > 0) && (pwrTableT4[jj] >= currPower)) {            jj--;        }        if ((jj == 0) && (msbFlag == 0x00)) {            while (ii >= 0) {                retVals[ii] = retVals[ii+1];                ii--;            }            break;        }        retVals[ii] = jj | msbFlag;        currPower -= 2;  // corresponds to a 0.5dB step        ii--;    }    return pMin;}/* * Free memory for analog bank scratch buffers */static voidar5112Detach(struct ath_hal *ah){	struct ath_hal_5212 *ahp = AH5212(ah);	if (ahp->ah_pcdacTable != AH_NULL) {		ath_hal_free(ahp->ah_pcdacTable);		ahp->ah_pcdacTable = AH_NULL;	}	if (ahp->ah_analogBanks != AH_NULL) {		ath_hal_free(ahp->ah_analogBanks);		ahp->ah_analogBanks = AH_NULL;	}}static int16_tar5112GetMinPower(struct ath_hal *ah, EXPN_DATA_PER_CHANNEL_5112 *data){	int i, minIndex;	int16_t minGain,minPwr,minPcdac,retVal;	/* Assume NUM_POINTS_XPD0 > 0 */	minGain = data->pDataPerXPD[0].xpd_gain;	for (minIndex=0,i=1; i<NUM_XPD_PER_CHANNEL; i++) {		if (data->pDataPerXPD[i].xpd_gain < minGain) {			minIndex = i;			minGain = data->pDataPerXPD[i].xpd_gain;		}	}	minPwr = data->pDataPerXPD[minIndex].pwr_t4[0];	minPcdac = data->pDataPerXPD[minIndex].pcdac[0];	for (i=1; i<NUM_POINTS_XPD0; i++) {		if (data->pDataPerXPD[minIndex].pwr_t4[i] < minPwr) {			minPwr = data->pDataPerXPD[minIndex].pwr_t4[i];			minPcdac = data->pDataPerXPD[minIndex].pcdac[i];		}	}	retVal = minPwr - (minPcdac*2);	return(retVal);}	static HAL_BOOLar5112GetChannelMaxMinPower(struct ath_hal *ah, HAL_CHANNEL *chan, int16_t *maxPow,			    int16_t *minPow){	struct ath_hal_5212 *ahp = (struct ath_hal_5212 *) ah;	int numChannels=0,i,last;	int totalD, totalF,totalMin;	EXPN_DATA_PER_CHANNEL_5112 *data=AH_NULL;	EEPROM_POWER_EXPN_5112 *powerArray=AH_NULL;	*maxPow = 0;	if (IS_CHAN_A(chan)) {		powerArray = ahp->ah_modePowerArray5112;		data = powerArray[headerInfo11A].pDataPerChannel;		numChannels = powerArray[headerInfo11A].numChannels;	} else if (IS_CHAN_G(chan) || IS_CHAN_108G(chan)) {		/* XXX - is this correct? Should we also use the same power for turbo G? */		powerArray = ahp->ah_modePowerArray5112;		data = powerArray[headerInfo11G].pDataPerChannel;		numChannels = powerArray[headerInfo11G].numChannels;	} else if (IS_CHAN_B(chan)) {		powerArray = ahp->ah_modePowerArray5112;		data = powerArray[headerInfo11B].pDataPerChannel;		numChannels = powerArray[headerInfo11B].numChannels;	} else {		return (AH_TRUE);	}	/* Make sure the channel is in the range of the TP values 	 *  (freq piers)	 */	if (numChannels < 1)		return(AH_FALSE);	if ((chan->channel < data[0].channelValue) ||	    (chan->channel > data[numChannels-1].channelValue)) {		if (chan->channel < data[0].channelValue) {			*maxPow = data[0].maxPower_t4;			*minPow = ar5112GetMinPower(ah, &data[0]);			return(AH_TRUE);		} else {			*maxPow = data[numChannels - 1].maxPower_t4;			*minPow = ar5112GetMinPower(ah, &data[numChannels - 1]);			return(AH_TRUE);		}	}	/* Linearly interpolate the power value now */	for (last=0,i=0;	     (i<numChannels) && (chan->channel > data[i].channelValue);	     last=i++);	totalD = data[i].channelValue - data[last].channelValue;	if (totalD > 0) {		totalF = data[i].maxPower_t4 - data[last].maxPower_t4;		*maxPow = (int8_t) ((totalF*(chan->channel-data[last].channelValue) + data[last].maxPower_t4*totalD)/totalD);		totalMin = ar5112GetMinPower(ah,&data[i]) - ar5112GetMinPower(ah, &data[last]);		*minPow = (int8_t) ((totalMin*(chan->channel-data[last].channelValue) + ar5112GetMinPower(ah, &data[last])*totalD)/totalD);		return (AH_TRUE);	} else {		if (chan->channel == data[i].channelValue) {			*maxPow = data[i].maxPower_t4;			*minPow = ar5112GetMinPower(ah, &data[i]);			return(AH_TRUE);		} else			return(AH_FALSE);	}}	static HAL_BOOLar5112GetChipPowerLimits(struct ath_hal *ah, HAL_CHANNEL *chans, u_int32_t nchans){	HAL_BOOL retVal = AH_TRUE;	int i;	int16_t maxPow,minPow;		for (i=0; i<nchans; i++) {		if (ar5112GetChannelMaxMinPower(ah, &chans[i], &maxPow, &minPow)) {			/* XXX -Need to adjust pcdac values to indicate dBm */			chans[i].maxTxPower = maxPow;			chans[i].minTxPower = minPow;		} else {			HALDEBUG(ah, "Failed setting power table for nchans=%d\n",i);			retVal= AH_FALSE;		}	}#ifdef AH_DEBUG	for (i=0; i<nchans; i++) {		ath_hal_printf(ah,"Chan %d: MaxPow = %d MinPow = %d\n",			 chans[i].channel,chans[i].maxTxPower, chans[i].minTxPower);	}#endif	return (retVal);}/* * Allocate memory for analog bank scratch buffers * Scratch Buffer will be reinitialized every reset so no need to zero now */HAL_BOOLar5112RfAttach(struct ath_hal *ah, HAL_STATUS *status){	struct ath_hal_5212 *ahp = AH5212(ah);	HALASSERT(ahp->ah_analogBanks == AH_NULL);	ahp->ah_analogBanks = ath_hal_malloc(sizeof(AR5212_RF_BANKS_5112));	if (ahp->ah_analogBanks == AH_NULL) {		ath_hal_printf(ah, "%s: cannot allocate RF banks\n", __func__);		*status = HAL_ENOMEM;		/* XXX */		return AH_FALSE;	}	HALASSERT(ahp->ah_pcdacTable == AH_NULL);	ahp->ah_pcdacTableSize = PWR_TABLE_SIZE * sizeof(u_int16_t);	ahp->ah_pcdacTable = ath_hal_malloc(ahp->ah_pcdacTableSize);	if (ahp->ah_pcdacTable == AH_NULL) {		ath_hal_printf(ah, "%s: cannot allocate PCDAC table\n", __func__);		*status = HAL_ENOMEM;		/* XXX */		return AH_FALSE;	}	ahp->ah_pcdacTableSize = PWR_TABLE_SIZE;	ahp->ah_rfHal.rfDetach		= ar5112Detach;	ahp->ah_rfHal.writeRegs		= ar5112WriteRegs;	ahp->ah_rfHal.getRfBank		= ar5112GetRfBank;	ahp->ah_rfHal.setChannel	= ar5112SetChannel;	ahp->ah_rfHal.setRfRegs		= ar5112SetRfRegs;	ahp->ah_rfHal.setPowerTable	= ar5112SetPowerTable;	ahp->ah_rfHal.getChipPowerLim	= ar5112GetChipPowerLimits;	return AH_TRUE;}#endif /* AH_SUPPORT_5112 */

⌨️ 快捷键说明

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