📄 ar2317.c
字号:
/* * * Copyright (c) 2004-2005 Atheros Communications, Inc. * All rights reserved. * * $Id: ar2317.c,v 1.1.1.1 2006/09/12 03:45:25 steven Exp $ * $File: //depot/sw/releases/linuxsrc/src/802_11/madwifi/hal/main/ar5212/ar2317.c $ * $Author: steven $ * $DateTime: 2006/05/29 05:26:43 $ * $Change: 171765 $ * */#include "opt_ah.h"#ifdef AH_SUPPORT_2317#include "ah.h"#include "ah_internal.h"#include "ar5212/ar5212.h"#include "ar5212/ar5212reg.h"#include "ar5212/ar5212phy.h"/* Add static register initialization vectors */#define AH_5212_2317#include "ar5212/ar5212.ini"#define N(a) (sizeof(a)/sizeof(a[0]))typedef RAW_DATA_STRUCT_2413 RAW_DATA_STRUCT_2317;typedef RAW_DATA_PER_CHANNEL_2413 RAW_DATA_PER_CHANNEL_2317;#define PWR_TABLE_SIZE_2317 PWR_TABLE_SIZE_2413typedef struct { u_int32_t Bank1Data[N(ar5212Bank1_2317)]; u_int32_t Bank2Data[N(ar5212Bank2_2317)]; u_int32_t Bank3Data[N(ar5212Bank3_2317)]; u_int32_t Bank6Data[N(ar5212Bank6_2317)]; u_int32_t Bank7Data[N(ar5212Bank7_2317)];} AR5212_RF_BANKS_2317;/* * WAR for bug 6773. OS_DELAY() does a PIO READ on the PCI bus which allows * other cards' DMA reads to complete in the middle of our reset. */#define WAR_6773(x) do { \ if ((++(x) % 64) == 0) \ OS_DELAY(1); \} while (0)#define REG_WRITE_ARRAY(regArray, column, regWr) do { \ int r; \ for (r = 0; r < N(regArray); r++) { \ OS_REG_WRITE(ah, (regArray)[r][0], (regArray)[r][(column)]);\ WAR_6773(regWr); \ } \} while (0)#define REG_WRITE_RF_ARRAY(regArray, regData, regWr) do { \ int r; \ for (r = 0; r < N(regArray); r++) { \ OS_REG_WRITE(ah, (regArray)[r][0], (regData)[r]); \ WAR_6773(regWr); \ } \} while (0)extern void ar5212ModifyRfBuffer(u_int32_t *rfBuf, u_int32_t reg32, u_int32_t numBits, u_int32_t firstBit, u_int32_t column);static voidar2317WriteRegs(struct ath_hal *ah, u_int modesIndex, u_int freqIndex, int regWrites){ REG_WRITE_ARRAY(ar5212Modes_2317, modesIndex, regWrites); REG_WRITE_ARRAY(ar5212Common_2317, 1, regWrites); REG_WRITE_ARRAY(ar5212BB_RfGain_2317, freqIndex, regWrites);}/* * Take the MHz channel value and set the Channel value * * ASSUMES: Writes enabled to analog bus */static HAL_BOOLar2317SetChannel(struct ath_hal *ah, HAL_CHANNEL_INTERNAL *chan){ u_int32_t channelSel = 0; u_int32_t bModeSynth = 0; u_int32_t aModeRefSel = 0; u_int32_t reg32 = 0; OS_MARK(ah, AH_MARK_SETCHANNEL, chan->channel); if (chan->channel < 4800) { u_int32_t txctl; channelSel = chan->channel - 2272 ; channelSel = ath_hal_reverseBits(channelSel, 8); txctl = OS_REG_READ(ah, AR_PHY_CCK_TX_CTRL); if (chan->channel == 2484) { /* Enable channel spreading for channel 14 */ OS_REG_WRITE(ah, AR_PHY_CCK_TX_CTRL, txctl | AR_PHY_CCK_TX_CTRL_JAPAN); } else { OS_REG_WRITE(ah, AR_PHY_CCK_TX_CTRL, txctl &~ AR_PHY_CCK_TX_CTRL_JAPAN); } } else if ((chan->channel % 20) == 0 && chan->channel >= 5120) { channelSel = ath_hal_reverseBits( ((chan->channel - 4800) / 20 << 2), 8); aModeRefSel = ath_hal_reverseBits(3, 2); } else if ((chan->channel % 10) == 0) { channelSel = ath_hal_reverseBits( ((chan->channel - 4800) / 10 << 1), 8); aModeRefSel = ath_hal_reverseBits(2, 2); } else if ((chan->channel % 5) == 0) { channelSel = ath_hal_reverseBits( (chan->channel - 4800) / 5, 8); aModeRefSel = ath_hal_reverseBits(1, 2); } else { HALDEBUG(ah, "%s: invalid channel %u MHz\n", __func__, chan->channel); return AH_FALSE; } reg32 = (channelSel << 4) | (aModeRefSel << 2) | (bModeSynth << 1) | (1 << 12) | 0x1; OS_REG_WRITE(ah, AR_PHY(0x27), reg32 & 0xff); reg32 >>= 8; OS_REG_WRITE(ah, AR_PHY(0x36), reg32 & 0x7f); AH_PRIVATE(ah)->ah_curchan = chan; return AH_TRUE;}/* * Reads EEPROM header info from device structure and programs * all rf registers * * REQUIRES: Access to the analog rf device */static HAL_BOOLar2317SetRfRegs(struct ath_hal *ah, HAL_CHANNEL_INTERNAL *chan, u_int16_t modesIndex, u_int16_t *rfXpdGain){#define RF_BANK_SETUP(_pb, _ix, _col) do { \ int i; \ for (i = 0; i < N(ar5212Bank##_ix##_2317); i++) \ (_pb)->Bank##_ix##Data[i] = ar5212Bank##_ix##_2317[i][_col];\} while (0) struct ath_hal_5212 *ahp = AH5212(ah); u_int16_t ob2GHz = 0, db2GHz = 0; AR5212_RF_BANKS_2317 *pRfBanks; int regWrites = 0; HALDEBUG(ah, "==>%s:chan 0x%x flag 0x%x modesIndex 0x%x\n", __func__, chan->channel, chan->channelFlags, modesIndex); pRfBanks = ahp->ah_analogBanks; HALASSERT(pRfBanks); /* Setup rf parameters */ switch (chan->channelFlags & CHANNEL_ALL) { case CHANNEL_B: ob2GHz = ahp->ah_obFor24; db2GHz = ahp->ah_dbFor24; break; case CHANNEL_G: case CHANNEL_108G: ob2GHz = ahp->ah_obFor24g; db2GHz = ahp->ah_dbFor24g; break; default: HALDEBUG(ah, "%s: invalid channel flags 0x%x\n", __func__, chan->channelFlags); return AH_FALSE; } /* Bank 1 Write */ RF_BANK_SETUP(pRfBanks, 1, 1); /* Bank 2 Write */ RF_BANK_SETUP(pRfBanks, 2, modesIndex); /* Bank 3 Write */ RF_BANK_SETUP(pRfBanks, 3, modesIndex); /* Bank 6 Write */ RF_BANK_SETUP(pRfBanks, 6, modesIndex); ar5212ModifyRfBuffer(pRfBanks->Bank6Data, ob2GHz, 3, 193, 0); ar5212ModifyRfBuffer(pRfBanks->Bank6Data, db2GHz, 3, 190, 0); /* Bank 7 Setup */ RF_BANK_SETUP(pRfBanks, 7, modesIndex); /* Write Analog registers */ REG_WRITE_RF_ARRAY(ar5212Bank1_2317, pRfBanks->Bank1Data, regWrites); REG_WRITE_RF_ARRAY(ar5212Bank2_2317, pRfBanks->Bank2Data, regWrites); REG_WRITE_RF_ARRAY(ar5212Bank3_2317, pRfBanks->Bank3Data, regWrites); REG_WRITE_RF_ARRAY(ar5212Bank6_2317, pRfBanks->Bank6Data, regWrites); REG_WRITE_RF_ARRAY(ar5212Bank7_2317, pRfBanks->Bank7Data, regWrites); /* Now that we have reprogrammed rfgain value, clear the flag. */ ahp->ah_rfgainState = HAL_RFGAIN_INACTIVE; HALDEBUG(ah, "<==%s\n", __func__); return AH_TRUE;#undef RF_BANK_SETUP}/* * Return a reference to the requested RF Bank. */static u_int32_t *ar2317GetRfBank(struct ath_hal *ah, int bank){ struct ath_hal_5212 *ahp = AH5212(ah); AR5212_RF_BANKS_2317 *pRfBank2317 = ahp->ah_analogBanks; HALASSERT(ahp->ah_analogBanks != AH_NULL); switch (bank) { case 1: return pRfBank2317->Bank1Data; case 2: return pRfBank2317->Bank2Data; case 3: return pRfBank2317->Bank3Data; case 6: return pRfBank2317->Bank6Data; case 7: return pRfBank2317->Bank7Data; } HALDEBUG(ah, "%s: unknown RF Bank %d requested\n", __func__, bank); return AH_NULL;}/* * Return indices surrounding the value in sorted integer lists. * * NB: the input list is assumed to be sorted in ascending order */static voidGetLowerUpperIndex(int16_t v, u_int16_t *lp, u_int16_t listSize, u_int32_t *vlo, u_int32_t *vhi){ int16_t target = v; int16_t *ep = lp+listSize; 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 - (int16_t *) lp; return; } /* * Look for value being between current value and next value * if so return these 2 values */ if (target < tp[1]) { *vlo = tp - (int16_t *) lp; *vhi = *vlo + 1; return; } }}/* * Fill the Vpdlist for indices Pmax-Pmin */static HAL_BOOLar2317FillVpdTable(u_int32_t pdGainIdx, int16_t Pmin, int16_t Pmax, int16_t *pwrList, int16_t *VpdList, u_int16_t numIntercepts, u_int16_t retVpdList[][64]){ u_int16_t ii, jj, kk; int16_t currPwr = (int16_t)(2*Pmin); /* since Pmin is pwr*2 and pwrList is 4*pwr */ u_int32_t idxL, idxR; ii = 0; jj = 0; if (numIntercepts < 2) return AH_FALSE; while (ii <= (u_int16_t)(Pmax - Pmin)) { GetLowerUpperIndex(currPwr, pwrList, numIntercepts, &(idxL), &(idxR)); if (idxR < 1) idxR = 1; /* extrapolate below */ if (idxL == (u_int32_t)(numIntercepts - 1)) idxL = numIntercepts - 2; /* extrapolate above */ if (pwrList[idxL] == pwrList[idxR]) kk = VpdList[idxL]; else kk = (u_int16_t) (((currPwr - pwrList[idxL])*VpdList[idxR]+ (pwrList[idxR] - currPwr)*VpdList[idxL])/ (pwrList[idxR] - pwrList[idxL])); retVpdList[pdGainIdx][ii] = kk; ii++; currPwr += 2; /* half dB steps */ } 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;}/* * Uses the data points read from EEPROM to reconstruct the pdadc power table * Called by ar2317SetPowerTable() */static void ar2317getGainBoundariesAndPdadcsForPowers(struct ath_hal *ah, u_int16_t channel, RAW_DATA_STRUCT_2317 *pRawDataset, u_int16_t pdGainOverlap_t2, int16_t *pMinCalPower, u_int16_t pPdGainBoundaries[], u_int16_t pPdGainValues[], u_int16_t pPDADCValues[]) { /* XXX excessive stack usage? */ u_int32_t ii, jj, kk; int32_t ss;/* potentially -ve index for taking care of pdGainOverlap */ u_int32_t idxL, idxR; u_int32_t numPdGainsUsed = 0; u_int16_t VpdTable_L[MAX_NUM_PDGAINS_PER_CHANNEL][MAX_PWR_RANGE_IN_HALF_DB]; /* filled out Vpd table for all pdGains (chanL) */ u_int16_t VpdTable_R[MAX_NUM_PDGAINS_PER_CHANNEL][MAX_PWR_RANGE_IN_HALF_DB]; /* filled out Vpd table for all pdGains (chanR) */ u_int16_t VpdTable_I[MAX_NUM_PDGAINS_PER_CHANNEL][MAX_PWR_RANGE_IN_HALF_DB]; /* filled out Vpd table for all pdGains (interpolated) */ /* * If desired to support -ve power levels in future, just * change pwr_I_0 to signed 5-bits. */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -