📄 ar5212_eeprom.c
字号:
* [8..14] --> cck 1L, 2L, 2S, .. 11L, 11S * [15] --> XR (all rates get the same power) * 2. powv[ii] is the pcdac corresponding to ii/2 dBm. */static voidar5212CorrectGainDelta(struct ath_hal *ah, int twiceOfdmCckDelta){#define N(_a) (sizeof(_a) / sizeof(_a[0])) struct ath_hal_5212 *ahp = AH5212(ah); int16_t ratesIndex[N(ahp->ah_ratesArray)]; u_int16_t ii, jj, iter; int32_t cckIndex; int16_t gainDeltaAdjust = ahp->ah_cckOfdmGainDelta; /* make a local copy of desired powers as initial indices */ OS_MEMCPY(ratesIndex, ahp->ah_ratesArray, sizeof(ratesIndex)); /* fix only the CCK indices */ for (ii = 8; ii < 15; ii++) { /* apply a gain_delta correction of -15 for CCK */ ratesIndex[ii] -= gainDeltaAdjust; /* Now check for contention with all ofdm target powers */ jj = 0; iter = 0; /* indicates not all ofdm rates checked forcontention yet */ while (jj < 16) { if (ratesIndex[ii] < 0) ratesIndex[ii] = 0; if (jj == 8) { /* skip CCK rates */ jj = 15; continue; } if (ratesIndex[ii] == ahp->ah_ratesArray[jj]) { if (ahp->ah_ratesArray[jj] == 0) ratesIndex[ii]++; else if (iter > 50) { /* * To avoid pathological case of of * dm target powers 0 and 0.5dBm */ ratesIndex[ii]++; } else ratesIndex[ii]--; /* check with all rates again */ jj = 0; iter++; } else jj++; } if (ratesIndex[ii] >= PWR_TABLE_SIZE) ratesIndex[ii] = PWR_TABLE_SIZE -1; cckIndex = ahp->ah_ratesArray[ii] - twiceOfdmCckDelta; if (cckIndex < 0) cckIndex = 0; /* * Validate that the indexes for the powv are not * out of bounds. BUG 6694 */ HALASSERT(cckIndex < PWR_TABLE_SIZE); HALASSERT(ratesIndex[ii] < PWR_TABLE_SIZE); ahp->ah_pcdacTable[ratesIndex[ii]] = ahp->ah_pcdacTable[cckIndex]; } /* Override rate per power table with new values */ for (ii = 8; ii < 15; ii++) ahp->ah_ratesArray[ii] = ratesIndex[ii];}#undef N/* * Find the maximum conformance test limit for the given channel and CTL info */static u_int16_tar5212GetMaxEdgePower(u_int16_t channel, RD_EDGES_POWER *pRdEdgesPower){ /* temp array for holding edge channels */ u_int16_t tempChannelList[NUM_EDGES]; u_int16_t clo, chi, twiceMaxEdgePower; int i, numEdges; /* Get the edge power */ for (i = 0; i < NUM_EDGES; i++) { if (pRdEdgesPower[i].rdEdge == 0) break; tempChannelList[i] = pRdEdgesPower[i].rdEdge; } numEdges = i; ar5212GetLowerUpperValues(channel, tempChannelList, numEdges, &clo, &chi); /* Get the index for the lower channel */ for (i = 0; i < numEdges && clo != tempChannelList[i]; i++) ; /* Is lower channel ever outside the rdEdge? */ HALASSERT(i != numEdges); if ((clo == chi && clo == channel) || (pRdEdgesPower[i].flag)) { /* * If there's an exact channel match or an inband flag set * on the lower channel use the given rdEdgePower */ twiceMaxEdgePower = pRdEdgesPower[i].twice_rdEdgePower; HALASSERT(twiceMaxEdgePower > 0); } else twiceMaxEdgePower = MAX_RATE_POWER; return twiceMaxEdgePower;}/* * Returns interpolated or the scaled up interpolated value */static u_int16_tinterpolate(u_int16_t target, u_int16_t srcLeft, u_int16_t srcRight, u_int16_t targetLeft, u_int16_t targetRight){ u_int16_t rv; int16_t lRatio; /* to get an accurate ratio, always scale, if want to scale, then don't scale back down */ if ((targetLeft * targetRight) == 0) return 0; 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; } else if (lRatio > EEP_SCALE) { /* Return as Right target if Ratio is greater than 100% (SCALE) */ rv = targetRight; } else { rv = (lRatio * targetRight + (EEP_SCALE - lRatio) * targetLeft) / EEP_SCALE; } } else { rv = targetLeft; } return rv;}/* * Return the four rates of target power for the given target power table * channel, and number of channels */static voidar5212GetTargetPowers(struct ath_hal *ah, HAL_CHANNEL *chan, TRGT_POWER_INFO *powInfo, u_int16_t numChannels, TRGT_POWER_INFO *pNewPower){ /* temp array for holding target power channels */ u_int16_t tempChannelList[NUM_TEST_FREQUENCIES]; u_int16_t clo, chi, ixlo, ixhi; int i; /* Copy the target powers into the temp channel list */ for (i = 0; i < numChannels; i++) tempChannelList[i] = powInfo[i].testChannel; ar5212GetLowerUpperValues(chan->channel, tempChannelList, numChannels, &clo, &chi); /* Get the indices for the channel */ ixlo = ixhi = 0; for (i = 0; i < numChannels; i++) { if (clo == tempChannelList[i]) { ixlo = i; } if (chi == tempChannelList[i]) { ixhi = i; break; } } /* * Get the lower and upper channels, target powers, * and interpolate between them. */ pNewPower->twicePwr6_24 = interpolate(chan->channel, clo, chi, powInfo[ixlo].twicePwr6_24, powInfo[ixhi].twicePwr6_24); pNewPower->twicePwr36 = interpolate(chan->channel, clo, chi, powInfo[ixlo].twicePwr36, powInfo[ixhi].twicePwr36); pNewPower->twicePwr48 = interpolate(chan->channel, clo, chi, powInfo[ixlo].twicePwr48, powInfo[ixhi].twicePwr48); pNewPower->twicePwr54 = interpolate(chan->channel, clo, chi, powInfo[ixlo].twicePwr54, powInfo[ixhi].twicePwr54);}/* * Search a list for a specified value v that is within * EEP_DELTA of the search values. Return the closest * values in the list above and below the desired value. * EEP_DELTA is a factional value; everything is scaled * so only integer arithmetic is used. * * NB: the input list is assumed to be sorted in ascending order */voidar5212GetLowerUpperValues(u_int16_t v, u_int16_t *lp, u_int16_t listSize, u_int16_t *vlo, u_int16_t *vhi){ u_int32_t target = v * EEP_SCALE; u_int16_t *ep = lp+listSize; /* * Check first and last elements for out-of-bounds conditions. */ if (target < (u_int32_t)(lp[0] * EEP_SCALE - EEP_DELTA)) { *vlo = *vhi = lp[0]; return; } if (target > (u_int32_t)(ep[-1] * EEP_SCALE + EEP_DELTA)) { *vlo = *vhi = ep[-1]; return; } /* look for value being near or between 2 values in list */ for (; lp < ep; lp++) { /* * 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(lp[0] * EEP_SCALE - target) < EEP_DELTA) { *vlo = *vhi = lp[0]; return; } /* * Look for value being between current value and next value * if so return these 2 values */ if (target < (u_int32_t)(lp[1] * EEP_SCALE - EEP_DELTA)) { *vlo = lp[0]; *vhi = lp[1]; return; } }}static HAL_BOOLar5212GetChipPowerLimits(struct ath_hal *ah, HAL_CHANNEL *chans, u_int32_t nchans){ struct ath_hal_5212 *ahp = AH5212(ah); static const u_int16_t tpcScaleReductionTable[5] = { 0, 3, 6, 9, MAX_RATE_POWER }; int16_t minPower, maxPower, tpcInDb, powerLimit; HAL_CHANNEL *chan=AH_NULL; u_int32_t i; /* Get Pier table max and min powers */ if (!(*ahp->ah_rfHal.getChipPowerLim)(ah, chans, nchans)) return AH_FALSE; powerLimit = AH_MIN(MAX_RATE_POWER, AH_PRIVATE(ah)->ah_powerLimit); if (powerLimit >= MAX_RATE_POWER || powerLimit == 0) tpcInDb = tpcScaleReductionTable[AH_PRIVATE(ah)->ah_tpScale]; else tpcInDb = 0; for (i=0; i<nchans; i++) { chan = &chans[i]; if (!ar5212SetRateTable(ah, (HAL_CHANNEL *) chan, tpcInDb, powerLimit, AH_FALSE, &minPower, &maxPower)) { HALDEBUG(ah,"%s: unable to find max/min power\n",__func__); return AH_FALSE; } if (maxPower < chan->maxTxPower) chan->maxTxPower= maxPower; if (minPower < chan->minTxPower) chan->minTxPower = minPower; }#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 AH_TRUE;}static HAL_BOOLar5212GetEepromCapabilityInfo(struct ath_hal *ah, u_int16_t *capField) { struct ath_hal_5212 *ahp = AH5212(ah); struct ath_hal_private *ahpriv = AH_PRIVATE(ah); HAL_CAPABILITIES *pCap = &ahpriv->ah_caps; u_int16_t eeval; u_int32_t sum,i; /* Get Reg domain */ if (!ath_hal_eepromRead(ah, AR_EEPROM_REG_DOMAIN, &eeval)) { HALDEBUG(ah, "%s: cannot read regulator domain from EEPROM\n", __func__); return AH_FALSE; } ahp->ah_regdomain = eeval; /* Get RF Silent */ if (!ath_hal_eepromRead(ah, AR_EEPROM_RFSILENT, &ahpriv->ah_rfsilent)) { HALDEBUG(ah, "%s: unable to read rf_silent from eeprom\n", __func__); return AH_FALSE; } if (ahp->ah_rfKill) { /* NB: enabled by default */ ahpriv->ah_rfkillEnabled = AH_TRUE; pCap->halRfSilentSupport = AH_TRUE; } /* Read the capability EEPROM location */ *capField = 0; if (ahp->ah_eeversion >= AR_EEPROM_VER5_1 && !ath_hal_eepromRead(ah, AR_EEPROM_CAPABILITIES_OFFSET, capField)) { HALDEBUG(ah, "%s: unable to read caps from eeprom\n", __func__); return AH_FALSE; } /* Construct wireless mode from EEPROM */ pCap->halWirelessModes = 0; if (ahp->ah_Amode) { pCap->halWirelessModes |= HAL_MODE_11A; if (!ahp->ah_turbo5Disable) pCap->halWirelessModes |= HAL_MODE_TURBO; } if (ahp->ah_Bmode) pCap->halWirelessModes |= HAL_MODE_11B; if (ahp->ah_Gmode && ahpriv->ah_subvendorid != AR_SUBVENDOR_ID_NOG) { pCap->halWirelessModes |= HAL_MODE_11G; if (!ahp->ah_turbo2Disable) pCap->halWirelessModes |= HAL_MODE_108G; } /* Get MAC Address */ sum = 0; for (i = 0; i < 3; i++) { if (!ath_hal_eepromRead(ah, AR_EEPROM_MAC(2-i), &eeval)) { HALDEBUG(ah, "%s: cannot read EEPROM " "location %u\n", __func__, i); return AH_FALSE; } sum += eeval; ahp->ah_macaddr[2*i] = eeval >> 8; ahp->ah_macaddr[2*i + 1] = eeval & 0xff; } if (sum == 0 || sum == 0xffff*3) { HALDEBUG(ah, "%s: mac address read failed: %s\n", __func__, ath_hal_ether_sprintf(ahp->ah_macaddr)); return AH_FALSE; } return AH_TRUE;}static HAL_BOOLar5212GetEepromNoiseFloorThresh(struct ath_hal *ah, const HAL_CHANNEL_INTERNAL *chan, int16_t *nft){ struct ath_hal_5212 *ahp = AH5212(ah); switch (chan->channelFlags & CHANNEL_ALL_NOTURBO) { case CHANNEL_A: *nft = ahp->ah_noiseFloorThresh[headerInfo11A]; break; case CHANNEL_B: *nft = ahp->ah_noiseFloorThresh[headerInfo11B]; break; case CHANNEL_PUREG: *nft = ahp->ah_noiseFloorThresh[headerInfo11G]; break; default: HALDEBUG(ah, "%s: invalid channel flags 0x%x\n", __func__, chan->channelFlags); return AH_FALSE; } return AH_TRUE;} #endif /* AH_SUPPORT_AR5212 */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -