📄 ar5211_reset.c.svn-base
字号:
(OS_REG_READ(ah, AR_PHY_BASE + (25 << 2)) & 0xFFF80FFF) | ((ee->ee_thresh62[arrayMode] << 12) & 0x7F000));#define NO_FALSE_DETECT_BACKOFF 2#define CB22_FALSE_DETECT_BACKOFF 6 /* * False detect backoff - suspected 32 MHz spur causes * false detects in OFDM, causing Tx Hangs. Decrease * weak signal sensitivity for this card. */ falseDectectBackoff = NO_FALSE_DETECT_BACKOFF; if (AH_PRIVATE(ah)->ah_eeversion < AR_EEPROM_VER3_3) { if (AH_PRIVATE(ah)->ah_subvendorid == 0x1022 && IS_CHAN_OFDM(chan)) falseDectectBackoff += CB22_FALSE_DETECT_BACKOFF; } else { uint32_t remainder = chan->channel % 32; if (remainder && (remainder < 10 || remainder > 22)) falseDectectBackoff += ee->ee_falseDetectBackoff[arrayMode]; } OS_REG_WRITE(ah, 0x9924, (OS_REG_READ(ah, 0x9924) & 0xFFFFFF01) | ((falseDectectBackoff << 1) & 0xF7)); return AH_TRUE;#undef NO_FALSE_DETECT_BACKOFF#undef CB22_FALSE_DETECT_BACKOFF}/* * Set the limit on the overall output power. Used for dynamic * transmit power control and the like. * * NOTE: The power is passed in is in units of 0.5 dBm. */HAL_BOOLar5211SetTxPowerLimit(struct ath_hal *ah, uint32_t limit){ AH_PRIVATE(ah)->ah_powerLimit = AH_MIN(limit, MAX_RATE_POWER); OS_REG_WRITE(ah, AR_PHY_POWER_TX_RATE_MAX, limit); return AH_TRUE;}/* * Sets the transmit power in the baseband for the given * operating channel and mode. */HAL_BOOLar5211SetTransmitPower(struct ath_hal *ah, HAL_CHANNEL *chan){ HAL_EEPROM *ee = AH_PRIVATE(ah)->ah_eeprom; TRGT_POWER_INFO *pi; RD_EDGES_POWER *rep; PCDACS_EEPROM eepromPcdacs; u_int nchan, cfgCtl; int i; /* setup the pcdac struct to point to the correct info, based on mode */ switch (chan->channelFlags & CHANNEL_ALL_NOTURBO) { case CHANNEL_A: eepromPcdacs.numChannels = ee->ee_numChannels11a; eepromPcdacs.pChannelList= ee->ee_channels11a; eepromPcdacs.pDataPerChannel = ee->ee_dataPerChannel11a; nchan = ee->ee_numTargetPwr_11a; pi = ee->ee_trgtPwr_11a; break; case CHANNEL_OFDM|CHANNEL_2GHZ: eepromPcdacs.numChannels = ee->ee_numChannels2_4; eepromPcdacs.pChannelList= ee->ee_channels11g; eepromPcdacs.pDataPerChannel = ee->ee_dataPerChannel11g; nchan = ee->ee_numTargetPwr_11g; pi = ee->ee_trgtPwr_11g; break; case CHANNEL_CCK|CHANNEL_2GHZ: eepromPcdacs.numChannels = ee->ee_numChannels2_4; eepromPcdacs.pChannelList= ee->ee_channels11b; eepromPcdacs.pDataPerChannel = ee->ee_dataPerChannel11b; nchan = ee->ee_numTargetPwr_11b; pi = ee->ee_trgtPwr_11b; break; default: HALDEBUG(ah, HAL_DEBUG_ANY, "%s: invalid channel flags 0x%x\n", __func__, chan->channelFlags); return AH_FALSE; } ar5211SetPowerTable(ah, &eepromPcdacs, chan->channel); rep = AH_NULL; /* Match CTL to EEPROM value */ cfgCtl = ath_hal_getctl(ah, chan); for (i = 0; i < ee->ee_numCtls; i++) if (ee->ee_ctl[i] != 0 && ee->ee_ctl[i] == cfgCtl) { rep = &ee->ee_rdEdgesPower[i * NUM_EDGES]; break; } ar5211SetRateTable(ah, rep, pi, nchan, chan); return AH_TRUE;}/* * Read the transmit power levels from the structures taken * from EEPROM. Interpolate read transmit power values for * this channel. Organize the transmit power values into a * table for writing into the hardware. */voidar5211SetPowerTable(struct ath_hal *ah, PCDACS_EEPROM *pSrcStruct, uint16_t channel){ static FULL_PCDAC_STRUCT pcdacStruct; static uint16_t pcdacTable[PWR_TABLE_SIZE]; uint16_t i, j; uint16_t *pPcdacValues; int16_t *pScaledUpDbm; int16_t minScaledPwr; int16_t maxScaledPwr; int16_t pwr; uint16_t pcdacMin = 0; uint16_t pcdacMax = 63; uint16_t pcdacTableIndex; uint16_t scaledPcdac; uint32_t addr; uint32_t temp32; OS_MEMZERO(&pcdacStruct, sizeof(FULL_PCDAC_STRUCT)); OS_MEMZERO(pcdacTable, sizeof(uint16_t) * PWR_TABLE_SIZE); pPcdacValues = pcdacStruct.PcdacValues; pScaledUpDbm = pcdacStruct.PwrValues; /* Initialize the pcdacs to dBM structs pcdacs to be 1 to 63 */ for (i = PCDAC_START, j = 0; i <= PCDAC_STOP; i+= PCDAC_STEP, j++) pPcdacValues[j] = i; pcdacStruct.numPcdacValues = j; pcdacStruct.pcdacMin = PCDAC_START; pcdacStruct.pcdacMax = PCDAC_STOP; /* Fill out the power values for this channel */ for (j = 0; j < pcdacStruct.numPcdacValues; j++ ) pScaledUpDbm[j] = ar5211GetScaledPower(channel, pPcdacValues[j], pSrcStruct); /* Now scale the pcdac values to fit in the 64 entry power table */ minScaledPwr = pScaledUpDbm[0]; maxScaledPwr = pScaledUpDbm[pcdacStruct.numPcdacValues - 1]; /* find minimum and make monotonic */ for (j = 0; j < pcdacStruct.numPcdacValues; j++) { if (minScaledPwr >= pScaledUpDbm[j]) { minScaledPwr = pScaledUpDbm[j]; pcdacMin = j; } /* * Make the full_hsh monotonically increasing otherwise * interpolation algorithm will get fooled gotta start * working from the top, hence i = 63 - j. */ i = (uint16_t)(pcdacStruct.numPcdacValues - 1 - j); if (i == 0) break; if (pScaledUpDbm[i-1] > pScaledUpDbm[i]) { /* * It could be a glitch, so make the power for * this pcdac the same as the power from the * next highest pcdac. */ pScaledUpDbm[i - 1] = pScaledUpDbm[i]; } } for (j = 0; j < pcdacStruct.numPcdacValues; j++) if (maxScaledPwr < pScaledUpDbm[j]) { maxScaledPwr = pScaledUpDbm[j]; pcdacMax = j; } /* Find the first power level with a pcdac */ pwr = (uint16_t)(PWR_STEP * ((minScaledPwr - PWR_MIN + PWR_STEP / 2) / PWR_STEP) + PWR_MIN); /* Write all the first pcdac entries based off the pcdacMin */ pcdacTableIndex = 0; for (i = 0; i < (2 * (pwr - PWR_MIN) / EEP_SCALE + 1); i++) pcdacTable[pcdacTableIndex++] = pcdacMin; i = 0; while (pwr < pScaledUpDbm[pcdacStruct.numPcdacValues - 1]) { pwr += PWR_STEP; /* stop if dbM > max_power_possible */ while (pwr < pScaledUpDbm[pcdacStruct.numPcdacValues - 1] && (pwr - pScaledUpDbm[i])*(pwr - pScaledUpDbm[i+1]) > 0) i++; /* scale by 2 and add 1 to enable round up or down as needed */ scaledPcdac = (uint16_t)(ar5211GetInterpolatedValue(pwr, pScaledUpDbm[i], pScaledUpDbm[i+1], (uint16_t)(pPcdacValues[i] * 2), (uint16_t)(pPcdacValues[i+1] * 2), 0) + 1); pcdacTable[pcdacTableIndex] = scaledPcdac / 2; if (pcdacTable[pcdacTableIndex] > pcdacMax) pcdacTable[pcdacTableIndex] = pcdacMax; pcdacTableIndex++; } /* Write all the last pcdac entries based off the last valid pcdac */ while (pcdacTableIndex < PWR_TABLE_SIZE) { pcdacTable[pcdacTableIndex] = pcdacTable[pcdacTableIndex - 1]; pcdacTableIndex++; } /* Finally, write the power values into the baseband power table */ addr = AR_PHY_BASE + (608 << 2); for (i = 0; i < 32; i++) { temp32 = 0xffff & ((pcdacTable[2 * i + 1] << 8) | 0xff); temp32 = (temp32 << 16) | (0xffff & ((pcdacTable[2 * i] << 8) | 0xff)); OS_REG_WRITE(ah, addr, temp32); addr += 4; }}/* * Set the transmit power in the baseband for the given * operating channel and mode. */voidar5211SetRateTable(struct ath_hal *ah, RD_EDGES_POWER *pRdEdgesPower, TRGT_POWER_INFO *pPowerInfo, uint16_t numChannels, HAL_CHANNEL *chan){ HAL_EEPROM *ee = AH_PRIVATE(ah)->ah_eeprom; struct ath_hal_5211 *ahp = AH5211(ah); static uint16_t ratesArray[NUM_RATES]; static const uint16_t tpcScaleReductionTable[5] = { 0, 3, 6, 9, MAX_RATE_POWER }; uint16_t *pRatesPower; uint16_t lowerChannel, lowerIndex=0, lowerPower=0; uint16_t upperChannel, upperIndex=0, upperPower=0; uint16_t twiceMaxEdgePower=63; uint16_t twicePower = 0; uint16_t i, numEdges; uint16_t tempChannelList[NUM_EDGES]; /* temp array for holding edge channels */ uint16_t twiceMaxRDPower; int16_t scaledPower = 0; /* for gcc -O2 */ uint16_t mask = 0x3f; HAL_BOOL paPreDEnable = 0; int8_t twiceAntennaGain, twiceAntennaReduction = 0; pRatesPower = ratesArray; twiceMaxRDPower = chan->maxRegTxPower * 2; if (IS_CHAN_5GHZ(chan)) { twiceAntennaGain = ee->ee_antennaGainMax[0]; } else { twiceAntennaGain = ee->ee_antennaGainMax[1]; } twiceAntennaReduction = ath_hal_getantennareduction(ah, chan, twiceAntennaGain); if (pRdEdgesPower) { /* Get the edge power */ for (i = 0; i < NUM_EDGES; i++) { if (pRdEdgesPower[i].rdEdge == 0) break; tempChannelList[i] = pRdEdgesPower[i].rdEdge; } numEdges = i; ar5211GetLowerUpperValues(chan->channel, tempChannelList, numEdges, &lowerChannel, &upperChannel); /* Get the index for this channel */ for (i = 0; i < numEdges; i++) if (lowerChannel == tempChannelList[i]) break; HALASSERT(i != numEdges); if ((lowerChannel == upperChannel && lowerChannel == chan->channel) || pRdEdgesPower[i].flag) { twiceMaxEdgePower = pRdEdgesPower[i].twice_rdEdgePower; HALASSERT(twiceMaxEdgePower > 0); } } /* extrapolate the power values for the test Groups */ for (i = 0; i < numChannels; i++) tempChannelList[i] = pPowerInfo[i].testChannel; ar5211GetLowerUpperValues(chan->channel, tempChannelList, numChannels, &lowerChannel, &upperChannel); /* get the index for the channel */ for (i = 0; i < numChannels; i++) { if (lowerChannel == tempChannelList[i]) lowerIndex = i; if (upperChannel == tempChannelList[i]) { upperIndex = i; break; } } for (i = 0; i < NUM_RATES; i++) { if (IS_CHAN_OFDM(chan)) { /* power for rates 6,9,12,18,24 is all the same */ if (i < 5) { lowerPower = pPowerInfo[lowerIndex].twicePwr6_24; upperPower = pPowerInfo[upperIndex].twicePwr6_24; } else if (i == 5) { lowerPower = pPowerInfo[lowerIndex].twicePwr36; upperPower = pPowerInfo[upperIndex].twicePwr36; } else if (i == 6) { lowerPower = pPowerInfo[lowerIndex].twicePwr48; upperPower = pPowerInfo[upperIndex].twicePwr48; } else if (i == 7) { lowerPower = pPowerInfo[lowerIndex].twicePwr54; upperPower = pPowerInfo[upperIndex].twicePwr54; } } else { switch (i) { case 0: case 1: lowerPower = pPowerInfo[lowerIndex].twicePwr6_24; upperPower = pPowerInfo[upperIndex].twicePwr6_24; break; case 2: case 3: lowerPower = pPowerInfo[lowerIndex].twicePwr36; upperPower = pPowerInfo[upperIndex].twicePwr36; break; case 4: case 5: lowerPower = pPowerInfo[lowerIndex].twicePwr48; upperPower = pPowerInfo[upperIndex].twicePwr48; break; case 6: case 7: lowerPower = pPowerInfo[lowerIndex].twicePwr54; 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) && AH_PRIVATE(ah)->ah_eeversion >= AR_EEPROM_VER3_1#ifdef AH_ENABLE_AP_SUPPORT && AH_PRIVATE(ah)->ah_opmode != HAL_M_HOSTAP#endif ) { twicePower = AH_MIN(twicePower, ee->ee_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, HAL_DEBUG_RESET, "%s: final output power setting %d MHz:\n", __func__, chan->channel); HALDEBUG(ah, HAL_DEBUG_RESET, "6 Mb %d dBm, MaxRD: %d dBm, MaxEdge %d dBm\n", scaledPower / 2, twiceMaxRDPower / 2, twiceMaxEdgePower / 2); HALDEBUG(ah, HAL_DEBUG_RESET, "TPC Scale %d dBm - Ant Red %d dBm\n", tpcScaleReductionTable[AH_PRIVATE(ah)->ah_tpScale] * 2, twiceAntennaReduction / 2); if (IS_CHAN_TURBO(chan) && AH_PRIVATE(ah)->ah_eeversion >= AR_EEPROM_VER3_1) HALDEBUG(ah, HAL_DEBUG_RESET, "Max Turbo %d dBm\n", ee->ee_turbo2WMaxPower5); HALDEBUG(ah, HAL_DEBUG_RESET, " %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 */uint16_tar5211GetScaledPower(uint16_t channel, uint16_t pcdacValue, const PCDACS_EEPROM *pSrcStruct)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -