📄 cmm_asic.c
字号:
========================================================================*/VOID AsicAntennaSetting( IN PRTMP_ADAPTER pAd, IN ABGBAND_STATE BandState){}VOID AsicRfTuningExec( IN PVOID SystemSpecific1, IN PVOID FunctionContext, IN PVOID SystemSpecific2, IN PVOID SystemSpecific3){}/* ========================================================================== Description: Gives CCK TX rate 2 more dB TX power. This routine works only in LINK UP in INFRASTRUCTURE mode. calculate desired Tx power in RF R3.Tx0~5, should consider - 0. if current radio is a noisy environment (pAd->DrsCounters.fNoisyEnvironment) 1. TxPowerPercentage 2. auto calibration based on TSSI feedback 3. extra 2 db for CCK 4. -10 db upon very-short distance (AvgRSSI >= -40db) to AP NOTE: Since this routine requires the value of (pAd->DrsCounters.fNoisyEnvironment), it should be called AFTER MlmeDynamicTxRatSwitching() ========================================================================== */VOID AsicAdjustTxPower( IN PRTMP_ADAPTER pAd) { INT i, j; CHAR DeltaPwr = 0; BOOLEAN bAutoTxAgc = FALSE; UCHAR TssiRef, *pTssiMinusBoundary, *pTssiPlusBoundary, TxAgcStep; UCHAR BbpR1 = 0, BbpR49 = 0, idx; PCHAR pTxAgcCompensate; ULONG TxPwr[5]; CHAR Value;#ifdef CONFIG_STA_SUPPORT CHAR Rssi = -127;#endif // CONFIG_STA_SUPPORT // #ifdef CONFIG_STA_SUPPORT if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE) || RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_IDLE_RADIO_OFF) || RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS)) return; IF_DEV_CONFIG_OPMODE_ON_STA(pAd) Rssi = RTMPMaxRssi(pAd, pAd->StaCfg.RssiSample.AvgRssi0, pAd->StaCfg.RssiSample.AvgRssi1, pAd->StaCfg.RssiSample.AvgRssi2);#endif // CONFIG_STA_SUPPORT // if (pAd->CommonCfg.BBPCurrentBW == BW_40) { if (pAd->CommonCfg.CentralChannel > 14) { TxPwr[0] = pAd->Tx40MPwrCfgABand[0]; TxPwr[1] = pAd->Tx40MPwrCfgABand[1]; TxPwr[2] = pAd->Tx40MPwrCfgABand[2]; TxPwr[3] = pAd->Tx40MPwrCfgABand[3]; TxPwr[4] = pAd->Tx40MPwrCfgABand[4]; } else { TxPwr[0] = pAd->Tx40MPwrCfgGBand[0]; TxPwr[1] = pAd->Tx40MPwrCfgGBand[1]; TxPwr[2] = pAd->Tx40MPwrCfgGBand[2]; TxPwr[3] = pAd->Tx40MPwrCfgGBand[3]; TxPwr[4] = pAd->Tx40MPwrCfgGBand[4]; } } else { if (pAd->CommonCfg.Channel > 14) { TxPwr[0] = pAd->Tx20MPwrCfgABand[0]; TxPwr[1] = pAd->Tx20MPwrCfgABand[1]; TxPwr[2] = pAd->Tx20MPwrCfgABand[2]; TxPwr[3] = pAd->Tx20MPwrCfgABand[3]; TxPwr[4] = pAd->Tx20MPwrCfgABand[4]; } else { TxPwr[0] = pAd->Tx20MPwrCfgGBand[0]; TxPwr[1] = pAd->Tx20MPwrCfgGBand[1]; TxPwr[2] = pAd->Tx20MPwrCfgGBand[2]; TxPwr[3] = pAd->Tx20MPwrCfgGBand[3]; TxPwr[4] = pAd->Tx20MPwrCfgGBand[4]; } } // TX power compensation for temperature variation based on TSSI. try every 4 second if (pAd->Mlme.OneSecPeriodicRound % 4 == 0) { if (pAd->CommonCfg.Channel <= 14) { /* bg channel */ bAutoTxAgc = pAd->bAutoTxAgcG; TssiRef = pAd->TssiRefG; pTssiMinusBoundary = &pAd->TssiMinusBoundaryG[0]; pTssiPlusBoundary = &pAd->TssiPlusBoundaryG[0]; TxAgcStep = pAd->TxAgcStepG; pTxAgcCompensate = &pAd->TxAgcCompensateG; } else { /* a channel */ bAutoTxAgc = pAd->bAutoTxAgcA; TssiRef = pAd->TssiRefA; pTssiMinusBoundary = &pAd->TssiMinusBoundaryA[0]; pTssiPlusBoundary = &pAd->TssiPlusBoundaryA[0]; TxAgcStep = pAd->TxAgcStepA; pTxAgcCompensate = &pAd->TxAgcCompensateA; } if (bAutoTxAgc) { /* BbpR1 is unsigned char */ RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R49, &BbpR49); /* (p) TssiPlusBoundaryG[0] = 0 = (m) TssiMinusBoundaryG[0] */ /* compensate: +4 +3 +2 +1 0 -1 -2 -3 -4 * steps */ /* step value is defined in pAd->TxAgcStepG for tx power value */ /* [4]+1+[4] p4 p3 p2 p1 o1 m1 m2 m3 m4 */ /* ex: 0x00 0x15 0x25 0x45 0x88 0xA0 0xB5 0xD0 0xF0 above value are examined in mass factory production */ /* [4] [3] [2] [1] [0] [1] [2] [3] [4] */ /* plus (+) is 0x00 ~ 0x45, minus (-) is 0xa0 ~ 0xf0 */ /* if value is between p1 ~ o1 or o1 ~ s1, no need to adjust tx power */ /* if value is 0xa5, tx power will be -= TxAgcStep*(2-1) */ if (BbpR49 > pTssiMinusBoundary[1]) { // Reading is larger than the reference value // check for how large we need to decrease the Tx power for (idx = 1; idx < 5; idx++) { if (BbpR49 <= pTssiMinusBoundary[idx]) // Found the range break; } // The index is the step we should decrease, idx = 0 means there is nothing to compensate// if (R3 > (ULONG) (TxAgcStep * (idx-1))) *pTxAgcCompensate = -(TxAgcStep * (idx-1));// else// *pTxAgcCompensate = -((UCHAR)R3); DeltaPwr += (*pTxAgcCompensate); DBGPRINT(RT_DEBUG_TRACE, ("-- Tx Power, BBP R1=%x, TssiRef=%x, TxAgcStep=%x, step = -%d\n", BbpR49, TssiRef, TxAgcStep, idx-1)); } else if (BbpR49 < pTssiPlusBoundary[1]) { // Reading is smaller than the reference value // check for how large we need to increase the Tx power for (idx = 1; idx < 5; idx++) { if (BbpR49 >= pTssiPlusBoundary[idx]) // Found the range break; } // The index is the step we should increase, idx = 0 means there is nothing to compensate *pTxAgcCompensate = TxAgcStep * (idx-1); DeltaPwr += (*pTxAgcCompensate); DBGPRINT(RT_DEBUG_TRACE, ("++ Tx Power, BBP R1=%x, TssiRef=%x, TxAgcStep=%x, step = +%d\n", BbpR49, TssiRef, TxAgcStep, idx-1)); } else { *pTxAgcCompensate = 0; DBGPRINT(RT_DEBUG_TRACE, (" Tx Power, BBP R49=%x, TssiRef=%x, TxAgcStep=%x, step = +%d\n", BbpR49, TssiRef, TxAgcStep, 0)); } } } else { if (pAd->CommonCfg.Channel <= 14) { bAutoTxAgc = pAd->bAutoTxAgcG; pTxAgcCompensate = &pAd->TxAgcCompensateG; } else { bAutoTxAgc = pAd->bAutoTxAgcA; pTxAgcCompensate = &pAd->TxAgcCompensateA; } if (bAutoTxAgc) DeltaPwr += (*pTxAgcCompensate); } RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R1, &BbpR1); BbpR1 &= 0xFC;#ifdef SINGLE_SKU // Handle regulatory max tx power constrain do { UCHAR TxPwrInEEPROM = 0xFF, CountryTxPwr = 0xFF, criterion; UCHAR AdjustMaxTxPwr[40]; if (pAd->CommonCfg.Channel > 14) // 5G band TxPwrInEEPROM = ((pAd->CommonCfg.DefineMaxTxPwr & 0xFF00) >> 8); else // 2.4G band TxPwrInEEPROM = (pAd->CommonCfg.DefineMaxTxPwr & 0x00FF); CountryTxPwr = GetCuntryMaxTxPwr(pAd, pAd->CommonCfg.Channel); // error handling, range check if ((TxPwrInEEPROM > 0x50) || (CountryTxPwr > 0x50)) { DBGPRINT(RT_DEBUG_ERROR,("AsicAdjustTxPower - Invalid max tx power (=0x%02x), CountryTxPwr=%d\n", TxPwrInEEPROM, CountryTxPwr)); break; } criterion = *((PUCHAR)TxPwr + 2) & 0xF; // FAE use OFDM 6M as criterion DBGPRINT_RAW(RT_DEBUG_TRACE,("AsicAdjustTxPower (criterion=%d, TxPwrInEEPROM=%d, CountryTxPwr=%d)\n", criterion, TxPwrInEEPROM, CountryTxPwr)); // Adjust max tx power according to the relationship of tx power in E2PROM for (i=0; i<5; i++) { // CCK will have 4dBm larger than OFDM // Therefore, we should separate to parse the tx power field if (i == 0) { for (j=0; j<8; j++) { Value = (CHAR)((TxPwr[i] >> j*4) & 0x0F); if (j < 4) { // CCK will have 4dBm larger than OFDM AdjustMaxTxPwr[i*8+j] = TxPwrInEEPROM + (Value - criterion) + 4; } else { AdjustMaxTxPwr[i*8+j] = TxPwrInEEPROM + (Value - criterion); } DBGPRINT_RAW(RT_DEBUG_TRACE,("AsicAdjustTxPower (i/j=%d/%d, Value=%d, %d)\n", i, j, Value, AdjustMaxTxPwr[i*8+j])); } } else { for (j=0; j<8; j++) { Value = (CHAR)((TxPwr[i] >> j*4) & 0x0F); AdjustMaxTxPwr[i*8+j] = TxPwrInEEPROM + (Value - criterion); DBGPRINT_RAW(RT_DEBUG_TRACE,("AsicAdjustTxPower (i/j=%d/%d, Value=%d, %d)\n", i, j, Value, AdjustMaxTxPwr[i*8+j])); } } } // Adjust tx power according to the relationship for (i=0; i<5; i++) { if (TxPwr[i] != 0xffffffff) { for (j=0; j<8; j++) { Value = (CHAR)((TxPwr[i] >> j*4) & 0x0F); // The system tx power is larger than the regulatory, the power should be restrain if (AdjustMaxTxPwr[i*8+j] > CountryTxPwr) { // decrease to zero and don't need to take care BBPR1 if ((Value - (AdjustMaxTxPwr[i*8+j] - CountryTxPwr)) > 0) Value -= (AdjustMaxTxPwr[i*8+j] - CountryTxPwr); else Value = 0; DBGPRINT_RAW(RT_DEBUG_TRACE,("AsicAdjustTxPower (i/j=%d/%d, Value=%d, %d)\n", i, j, Value, AdjustMaxTxPwr[i*8+j])); } else DBGPRINT_RAW(RT_DEBUG_TRACE,("AsicAdjustTxPower (i/j=%d/%d, Value=%d, %d, no change)\n", i, j, Value, AdjustMaxTxPwr[i*8+j])); TxPwr[i] = (TxPwr[i] & ~(0x0000000F << j*4)) | (Value << j*4); } } } } while (FALSE);#endif // SINGLE_SKU // /* calculate delta power based on the percentage specified from UI */ // E2PROM setting is calibrated for maximum TX power (i.e. 100%) // We lower TX power here according to the percentage specified from UI if (pAd->CommonCfg.TxPowerPercentage == 0xffffffff) // AUTO TX POWER control {#ifdef CONFIG_STA_SUPPORT IF_DEV_CONFIG_OPMODE_ON_STA(pAd) { // to patch high power issue with some APs, like Belkin N1. if (Rssi > -35) { BbpR1 |= 0x02; // DeltaPwr -= 12; } else if (Rssi > -40) { BbpR1 |= 0x01; // DeltaPwr -= 6; } else ; }#endif // CONFIG_STA_SUPPORT // } else if (pAd->CommonCfg.TxPowerPercentage > 90) // 91 ~ 100% & AUTO, treat as 100% in terms of mW ; else if (pAd->CommonCfg.TxPowerPercentage > 60) // 61 ~ 90%, treat as 75% in terms of mW // DeltaPwr -= 1; { DeltaPwr -= 1; } else if (pAd->CommonCfg.TxPowerPercentage > 30) // 31 ~ 60%, treat as 50% in terms of mW // DeltaPwr -= 3; { DeltaPwr -= 3; } else if (pAd->CommonCfg.TxPowerPercentage > 15) // 16 ~ 30%, treat as 25% in terms of mW // DeltaPwr -= 6; { BbpR1 |= 0x01; } else if (pAd->CommonCfg.TxPowerPercentage > 9) // 10 ~ 15%, treat as 12.5% in terms of mW // DeltaPwr -= 9; { BbpR1 |= 0x01; DeltaPwr -= 3; } else // 0 ~ 9 %, treat as MIN(~3%) in terms of mW // DeltaPwr -= 12; { BbpR1 |= 0x02; } RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R1, BbpR1); /* reset different new tx power for different TX rate */ for(i=0; i<5; i++) { if (TxPwr[i] != 0xffffffff) { for (j=0; j<8; j++) { Value = (CHAR)((TxPwr[i] >> j*4) & 0x0F); /* 0 ~ 15 */ if ((Value + DeltaPwr) < 0) { Value = 0; /* min */ } else if ((Value + DeltaPwr) > 0xF) { Value = 0xF; /* max */ } else { Value += DeltaPwr; /* temperature compensation */ } /* fill new value to CSR offset */ TxPwr[i] = (TxPwr[i] & ~(0x0000000F << j*4)) | (Value << j*4); } /* write tx power value to CSR */ /* TX_PWR_CFG_0 (8 tx rate) for TX power for OFDM 12M/18M TX power for OFDM 6M/9M TX power for CCK5.5M/11M TX power for CCK1M/2M */ /* TX_PWR_CFG_1 ~ TX_PWR_CFG_4 */ RTMP_IO_WRITE32(pAd, TX_PWR_CFG_0 + i*4, TxPwr[i]); } }}#ifdef CONFIG_STA_SUPPORT/* ========================================================================== Description: put PHY to sleep here, and set next wakeup timer. PHY doesn't not wakeup automatically. Instead, MCU will issue a TwakeUpInterrupt to host after the wakeup timer timeout. Driver has to issue a separate command to wake PHY up. IRQL = DISPATCH_LEVEL ========================================================================== */VOID AsicSleepThenAutoWakeup( IN PRTMP_ADAPTER pAd, IN USHORT TbttNumToNextWakeUp) { RTMP_STA_SLEEP_THEN_AUTO_WAKEUP(pAd, TbttNumToNextWakeUp);}/* ========================================================================== Description: AsicForceWakeup() is used whenever manual wakeup is required AsicForceSleep() should only be used when not in INFRA BSS. When in INFRA BSS, we should use AsicSleepThenAutoWakeup() instead. ========================================================================== */VOID AsicForceSleep( IN PRTMP_ADAPTER pAd){}/* ========================================================================== Description: AsicForceWakeup() is used whenever Twakeup timer (set via AsicSleepThenAutoWakeup) expired. IRQL = PASSIVE_LEVEL IRQL = DISPATCH_LEVEL ========================================================================== */VOID AsicForceWakeup(
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -