📄 ah_eeprom_v3.c.svn-base
字号:
/* * 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: ah_eeprom_v3.c,v 1.4 2008/11/27 22:39:42 sam Exp $ */#include "opt_ah.h"#include "ah.h"#include "ah_internal.h"#include "ah_eeprom_v3.h"static voidgetPcdacInterceptsFromPcdacMinMax(HAL_EEPROM *ee, uint16_t pcdacMin, uint16_t pcdacMax, uint16_t *vp){ const static uint16_t intercepts3[] = { 0, 5, 10, 20, 30, 50, 70, 85, 90, 95, 100 }; const static uint16_t intercepts3_2[] = { 0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100 }; const uint16_t *ip = ee->ee_version < AR_EEPROM_VER3_2 ? intercepts3 : intercepts3_2; int i; /* loop for the percentages in steps or 5 */ for (i = 0; i < NUM_INTERCEPTS; i++ ) *vp++ = (ip[i] * pcdacMax + (100 - ip[i]) * pcdacMin) / 100;}/* * Get channel value from binary representation held in eeprom */static uint16_tfbin2freq(HAL_EEPROM *ee, uint16_t fbin){ if (fbin == CHANNEL_UNUSED) /* reserved value, don't convert */ return fbin; return ee->ee_version <= AR_EEPROM_VER3_2 ? (fbin > 62 ? 5100 + 10*62 + 5*(fbin-62) : 5100 + 10*fbin) : 4800 + 5*fbin;}static uint16_tfbin2freq_2p4(HAL_EEPROM *ee, uint16_t fbin){ if (fbin == CHANNEL_UNUSED) /* reserved value, don't convert */ return fbin; return ee->ee_version <= AR_EEPROM_VER3_2 ? 2400 + fbin : 2300 + fbin;}/* * Now copy EEPROM frequency pier contents into the allocated space */static HAL_BOOLreadEepromFreqPierInfo(struct ath_hal *ah, HAL_EEPROM *ee){#define EEREAD(_off) do { \ if (!ath_hal_eepromRead(ah, _off, &eeval)) \ return AH_FALSE; \} while (0) uint16_t eeval, off; int i; if (ee->ee_version >= AR_EEPROM_VER4_0 && ee->ee_eepMap && !ee->ee_Amode) { /* * V4.0 EEPROMs with map type 1 have frequency pier * data only when 11a mode is supported. */ return AH_TRUE; } if (ee->ee_version >= AR_EEPROM_VER3_3) { off = GROUPS_OFFSET3_3 + GROUP1_OFFSET; for (i = 0; i < ee->ee_numChannels11a; i += 2) { EEREAD(off++); ee->ee_channels11a[i] = (eeval >> 8) & FREQ_MASK_3_3; ee->ee_channels11a[i+1] = eeval & FREQ_MASK_3_3; } } else { off = GROUPS_OFFSET3_2 + GROUP1_OFFSET; EEREAD(off++); ee->ee_channels11a[0] = (eeval >> 9) & FREQ_MASK; ee->ee_channels11a[1] = (eeval >> 2) & FREQ_MASK; ee->ee_channels11a[2] = (eeval << 5) & FREQ_MASK; EEREAD(off++); ee->ee_channels11a[2] |= (eeval >> 11) & 0x1f; ee->ee_channels11a[3] = (eeval >> 4) & FREQ_MASK; ee->ee_channels11a[4] = (eeval << 3) & FREQ_MASK; EEREAD(off++); ee->ee_channels11a[4] |= (eeval >> 13) & 0x7; ee->ee_channels11a[5] = (eeval >> 6) & FREQ_MASK; ee->ee_channels11a[6] = (eeval << 1) & FREQ_MASK; EEREAD(off++); ee->ee_channels11a[6] |= (eeval >> 15) & 0x1; ee->ee_channels11a[7] = (eeval >> 8) & FREQ_MASK; ee->ee_channels11a[8] = (eeval >> 1) & FREQ_MASK; ee->ee_channels11a[9] = (eeval << 6) & FREQ_MASK; EEREAD(off++); ee->ee_channels11a[9] |= (eeval >> 10) & 0x3f; } for (i = 0; i < ee->ee_numChannels11a; i++) ee->ee_channels11a[i] = fbin2freq(ee, ee->ee_channels11a[i]); return AH_TRUE;#undef EEREAD}/* * Rev 4 Eeprom 5112 Power Extract Functions *//* * Allocate the power information based on the number of channels * recorded by the calibration. These values are then initialized. */static HAL_BOOLeepromAllocExpnPower5112(struct ath_hal *ah, const EEPROM_POWER_5112 *pCalDataset, EEPROM_POWER_EXPN_5112 *pPowerExpn){ uint16_t numChannels = pCalDataset->numChannels; const uint16_t *pChanList = pCalDataset->pChannels; void *data; int i, j; /* Allocate the channel and Power Data arrays together */ data = ath_hal_malloc( roundup(sizeof(uint16_t) * numChannels, sizeof(uint32_t)) + sizeof(EXPN_DATA_PER_CHANNEL_5112) * numChannels); if (data == AH_NULL) { HALDEBUG(ah, HAL_DEBUG_ANY, "%s unable to allocate raw data struct (gen3)\n", __func__); return AH_FALSE; } pPowerExpn->pChannels = data; pPowerExpn->pDataPerChannel = (void *)(((char *)data) + roundup(sizeof(uint16_t) * numChannels, sizeof(uint32_t))); pPowerExpn->numChannels = numChannels; for (i = 0; i < numChannels; i++) { pPowerExpn->pChannels[i] = pPowerExpn->pDataPerChannel[i].channelValue = pChanList[i]; for (j = 0; j < NUM_XPD_PER_CHANNEL; j++) { pPowerExpn->pDataPerChannel[i].pDataPerXPD[j].xpd_gain = j; pPowerExpn->pDataPerChannel[i].pDataPerXPD[j].numPcdacs = 0; } pPowerExpn->pDataPerChannel[i].pDataPerXPD[0].numPcdacs = 4; pPowerExpn->pDataPerChannel[i].pDataPerXPD[3].numPcdacs = 3; } return AH_TRUE;}/* * Expand the dataSet from the calibration information into the * final power structure for 5112 */static HAL_BOOLeepromExpandPower5112(struct ath_hal *ah, const EEPROM_POWER_5112 *pCalDataset, EEPROM_POWER_EXPN_5112 *pPowerExpn){ int ii, jj, kk; int16_t maxPower_t4; EXPN_DATA_PER_XPD_5112 *pExpnXPD; /* ptr to array of info held per channel */ const EEPROM_DATA_PER_CHANNEL_5112 *pCalCh; uint16_t xgainList[2], xpdMask; pPowerExpn->xpdMask = pCalDataset->xpdMask; xgainList[0] = 0xDEAD; xgainList[1] = 0xDEAD; kk = 0; xpdMask = pPowerExpn->xpdMask; for (jj = 0; jj < NUM_XPD_PER_CHANNEL; jj++) { if (((xpdMask >> jj) & 1) > 0) { if (kk > 1) { HALDEBUG(ah, HAL_DEBUG_ANY, "%s: too many xpdGains in dataset: %u\n", __func__, kk); return AH_FALSE; } xgainList[kk++] = jj; } } pPowerExpn->numChannels = pCalDataset->numChannels; if (pPowerExpn->numChannels == 0) { HALDEBUG(ah, HAL_DEBUG_ANY, "%s: no channels\n", __func__); return AH_FALSE; } for (ii = 0; ii < pPowerExpn->numChannels; ii++) { pCalCh = &pCalDataset->pDataPerChannel[ii]; pPowerExpn->pDataPerChannel[ii].channelValue = pCalCh->channelValue; pPowerExpn->pDataPerChannel[ii].maxPower_t4 = pCalCh->maxPower_t4; maxPower_t4 = pPowerExpn->pDataPerChannel[ii].maxPower_t4; for (jj = 0; jj < NUM_XPD_PER_CHANNEL; jj++) pPowerExpn->pDataPerChannel[ii].pDataPerXPD[jj].numPcdacs = 0; if (xgainList[1] == 0xDEAD) { jj = xgainList[0]; pExpnXPD = &pPowerExpn->pDataPerChannel[ii].pDataPerXPD[jj]; pExpnXPD->numPcdacs = 4; pExpnXPD->pcdac[0] = pCalCh->pcd1_xg0; pExpnXPD->pcdac[1] = (uint16_t) (pExpnXPD->pcdac[0] + pCalCh->pcd2_delta_xg0); pExpnXPD->pcdac[2] = (uint16_t) (pExpnXPD->pcdac[1] + pCalCh->pcd3_delta_xg0); pExpnXPD->pcdac[3] = (uint16_t) (pExpnXPD->pcdac[2] + pCalCh->pcd4_delta_xg0); pExpnXPD->pwr_t4[0] = pCalCh->pwr1_xg0; pExpnXPD->pwr_t4[1] = pCalCh->pwr2_xg0; pExpnXPD->pwr_t4[2] = pCalCh->pwr3_xg0; pExpnXPD->pwr_t4[3] = pCalCh->pwr4_xg0; } else { pPowerExpn->pDataPerChannel[ii].pDataPerXPD[xgainList[0]].pcdac[0] = pCalCh->pcd1_xg0; pPowerExpn->pDataPerChannel[ii].pDataPerXPD[xgainList[1]].pcdac[0] = 20; pPowerExpn->pDataPerChannel[ii].pDataPerXPD[xgainList[1]].pcdac[1] = 35; pPowerExpn->pDataPerChannel[ii].pDataPerXPD[xgainList[1]].pcdac[2] = 63; jj = xgainList[0]; pExpnXPD = &pPowerExpn->pDataPerChannel[ii].pDataPerXPD[jj]; pExpnXPD->numPcdacs = 4; pExpnXPD->pcdac[1] = (uint16_t) (pExpnXPD->pcdac[0] + pCalCh->pcd2_delta_xg0); pExpnXPD->pcdac[2] = (uint16_t) (pExpnXPD->pcdac[1] + pCalCh->pcd3_delta_xg0); pExpnXPD->pcdac[3] = (uint16_t) (pExpnXPD->pcdac[2] + pCalCh->pcd4_delta_xg0); pExpnXPD->pwr_t4[0] = pCalCh->pwr1_xg0; pExpnXPD->pwr_t4[1] = pCalCh->pwr2_xg0; pExpnXPD->pwr_t4[2] = pCalCh->pwr3_xg0; pExpnXPD->pwr_t4[3] = pCalCh->pwr4_xg0; jj = xgainList[1]; pExpnXPD = &pPowerExpn->pDataPerChannel[ii].pDataPerXPD[jj]; pExpnXPD->numPcdacs = 3; pExpnXPD->pwr_t4[0] = pCalCh->pwr1_xg3; pExpnXPD->pwr_t4[1] = pCalCh->pwr2_xg3; pExpnXPD->pwr_t4[2] = pCalCh->pwr3_xg3; } } return AH_TRUE;}static HAL_BOOLreadEepromRawPowerCalInfo5112(struct ath_hal *ah, HAL_EEPROM *ee){#define EEREAD(_off) do { \ if (!ath_hal_eepromRead(ah, _off, &eeval)) \ return AH_FALSE; \} while (0) const uint16_t dbmmask = 0xff; const uint16_t pcdac_delta_mask = 0x1f; const uint16_t pcdac_mask = 0x3f; const uint16_t freqmask = 0xff; int i, mode, numPiers; uint32_t off; uint16_t eeval; uint16_t freq[NUM_11A_EEPROM_CHANNELS]; EEPROM_POWER_5112 eePower; HALASSERT(ee->ee_version >= AR_EEPROM_VER4_0); off = GROUPS_OFFSET3_3; for (mode = headerInfo11A; mode <= headerInfo11G; mode++) { numPiers = 0; switch (mode) { case headerInfo11A: if (!ee->ee_Amode) /* no 11a calibration data */ continue; while (numPiers < NUM_11A_EEPROM_CHANNELS) { EEREAD(off++); if ((eeval & freqmask) == 0) break; freq[numPiers++] = fbin2freq(ee, eeval & freqmask); if (((eeval >> 8) & freqmask) == 0) break; freq[numPiers++] = fbin2freq(ee, (eeval>>8) & freqmask); } break; case headerInfo11B: if (!ee->ee_Bmode) /* no 11b calibration data */ continue; for (i = 0; i < NUM_2_4_EEPROM_CHANNELS; i++) if (ee->ee_calPier11b[i] != CHANNEL_UNUSED) freq[numPiers++] = ee->ee_calPier11b[i]; break; case headerInfo11G: if (!ee->ee_Gmode) /* no 11g calibration data */ continue; for (i = 0; i < NUM_2_4_EEPROM_CHANNELS; i++) if (ee->ee_calPier11g[i] != CHANNEL_UNUSED) freq[numPiers++] = ee->ee_calPier11g[i]; break; default: HALDEBUG(ah, HAL_DEBUG_ANY, "%s: invalid mode 0x%x\n", __func__, mode); return AH_FALSE; } OS_MEMZERO(&eePower, sizeof(eePower)); eePower.numChannels = numPiers; for (i = 0; i < numPiers; i++) { eePower.pChannels[i] = freq[i]; eePower.pDataPerChannel[i].channelValue = freq[i]; EEREAD(off++); eePower.pDataPerChannel[i].pwr1_xg0 = (int16_t) ((eeval & dbmmask) - ((eeval >> 7) & 0x1)*256); eePower.pDataPerChannel[i].pwr2_xg0 = (int16_t) (((eeval >> 8) & dbmmask) - ((eeval >> 15) & 0x1)*256); EEREAD(off++); eePower.pDataPerChannel[i].pwr3_xg0 = (int16_t) ((eeval & dbmmask) - ((eeval >> 7) & 0x1)*256); eePower.pDataPerChannel[i].pwr4_xg0 = (int16_t) (((eeval >> 8) & dbmmask) - ((eeval >> 15) & 0x1)*256); EEREAD(off++); eePower.pDataPerChannel[i].pcd2_delta_xg0 = (uint16_t) (eeval & pcdac_delta_mask); eePower.pDataPerChannel[i].pcd3_delta_xg0 = (uint16_t) ((eeval >> 5) & pcdac_delta_mask); eePower.pDataPerChannel[i].pcd4_delta_xg0 = (uint16_t) ((eeval >> 10) & pcdac_delta_mask); EEREAD(off++); eePower.pDataPerChannel[i].pwr1_xg3 = (int16_t) ((eeval & dbmmask) - ((eeval >> 7) & 0x1)*256); eePower.pDataPerChannel[i].pwr2_xg3 = (int16_t) (((eeval >> 8) & dbmmask) - ((eeval >> 15) & 0x1)*256); EEREAD(off++); eePower.pDataPerChannel[i].pwr3_xg3 = (int16_t) ((eeval & dbmmask) - ((eeval >> 7) & 0x1)*256); if (ee->ee_version >= AR_EEPROM_VER4_3) { eePower.pDataPerChannel[i].maxPower_t4 = eePower.pDataPerChannel[i].pwr4_xg0; eePower.pDataPerChannel[i].pcd1_xg0 = (uint16_t) ((eeval >> 8) & pcdac_mask); } else { eePower.pDataPerChannel[i].maxPower_t4 = (int16_t) (((eeval >> 8) & dbmmask) - ((eeval >> 15) & 0x1)*256); eePower.pDataPerChannel[i].pcd1_xg0 = 1; } } eePower.xpdMask = ee->ee_xgain[mode]; if (!eepromAllocExpnPower5112(ah, &eePower, &ee->ee_modePowerArray5112[mode])) { HALDEBUG(ah, HAL_DEBUG_ANY, "%s: did not allocate power struct\n", __func__); return AH_FALSE; } if (!eepromExpandPower5112(ah, &eePower, &ee->ee_modePowerArray5112[mode])) { HALDEBUG(ah, HAL_DEBUG_ANY, "%s: did not expand power struct\n", __func__); return AH_FALSE; } } return AH_TRUE;#undef EEREAD}static voidfreeEepromRawPowerCalInfo5112(struct ath_hal *ah, HAL_EEPROM *ee){ int mode; void *data; for (mode = headerInfo11A; mode <= headerInfo11G; mode++) { EEPROM_POWER_EXPN_5112 *pPowerExpn = &ee->ee_modePowerArray5112[mode]; data = pPowerExpn->pChannels; if (data != AH_NULL) { pPowerExpn->pChannels = AH_NULL; ath_hal_free(data); } }}static voidar2413SetupEEPROMDataset(EEPROM_DATA_STRUCT_2413 *pEEPROMDataset2413, uint16_t myNumRawChannels, uint16_t *pMyRawChanList){ uint16_t i, channelValue; uint32_t xpd_mask; uint16_t numPdGainsUsed; pEEPROMDataset2413->numChannels = myNumRawChannels; xpd_mask = pEEPROMDataset2413->xpd_mask; numPdGainsUsed = 0; if ((xpd_mask >> 0) & 0x1) numPdGainsUsed++; if ((xpd_mask >> 1) & 0x1) numPdGainsUsed++; if ((xpd_mask >> 2) & 0x1) numPdGainsUsed++; if ((xpd_mask >> 3) & 0x1) numPdGainsUsed++; for (i = 0; i < myNumRawChannels; i++) { channelValue = pMyRawChanList[i]; pEEPROMDataset2413->pChannels[i] = channelValue; pEEPROMDataset2413->pDataPerChannel[i].channelValue = channelValue; pEEPROMDataset2413->pDataPerChannel[i].numPdGains = numPdGainsUsed; }}static HAL_BOOLar2413ReadCalDataset(struct ath_hal *ah, HAL_EEPROM *ee, EEPROM_DATA_STRUCT_2413 *pCalDataset, uint32_t start_offset, uint32_t maxPiers, uint8_t mode){#define EEREAD(_off) do { \ if (!ath_hal_eepromRead(ah, _off, &eeval)) \ return AH_FALSE; \} while (0) const uint16_t dbm_I_mask = 0x1F; /* 5-bits. 1dB step. */ const uint16_t dbm_delta_mask = 0xF; /* 4-bits. 0.5dB step. */ const uint16_t Vpd_I_mask = 0x7F; /* 7-bits. 0-128 */ const uint16_t Vpd_delta_mask = 0x3F; /* 6-bits. 0-63 */ const uint16_t freqmask = 0xff; uint16_t ii, eeval; uint16_t idx, numPiers; uint16_t freq[NUM_11A_EEPROM_CHANNELS]; idx = start_offset; for (numPiers = 0; numPiers < maxPiers;) { EEREAD(idx++); if ((eeval & freqmask) == 0) break; if (mode == headerInfo11A) freq[numPiers++] = fbin2freq(ee, (eeval & freqmask)); else freq[numPiers++] = fbin2freq_2p4(ee, (eeval & freqmask)); if (((eeval >> 8) & freqmask) == 0) break;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -