📄 ar5212_misc.c
字号:
HAL_BOOLar5212SetCTSTimeout(struct ath_hal *ah, u_int us){ struct ath_hal_5212 *ahp = AH5212(ah); if (us > ath_hal_mac_usec(ah, MS(0xffffffff, AR_TIME_OUT_CTS))) { HALDEBUG(ah, HAL_DEBUG_ANY, "%s: bad cts timeout %u\n", __func__, us); ahp->ah_ctstimeout = (u_int) -1; /* restore default handling */ return AH_FALSE; } else { /* convert to system clocks */ OS_REG_RMW_FIELD(ah, AR_TIME_OUT, AR_TIME_OUT_CTS, ath_hal_mac_clks(ah, us)); ahp->ah_ctstimeout = us; return AH_TRUE; }}u_intar5212GetCTSTimeout(struct ath_hal *ah){ u_int clks = MS(OS_REG_READ(ah, AR_TIME_OUT), AR_TIME_OUT_CTS); return ath_hal_mac_usec(ah, clks); /* convert from system clocks */}/* Setup decompression for given key index */HAL_BOOLar5212SetDecompMask(struct ath_hal *ah, uint16_t keyidx, int en){ struct ath_hal_5212 *ahp = AH5212(ah); if (keyidx >= HAL_DECOMP_MASK_SIZE) return HAL_EINVAL; OS_REG_WRITE(ah, AR_DCM_A, keyidx); OS_REG_WRITE(ah, AR_DCM_D, en ? AR_DCM_D_EN : 0); ahp->ah_decompMask[keyidx] = en; return AH_TRUE;}/* Setup coverage class */voidar5212SetCoverageClass(struct ath_hal *ah, uint8_t coverageclass, int now){ uint32_t slot, timeout, eifs; u_int clkRate; AH_PRIVATE(ah)->ah_coverageClass = coverageclass; if (now) { if (AH_PRIVATE(ah)->ah_coverageClass == 0) return; /* Don't apply coverage class to non A channels */ if (!IS_CHAN_A(AH_PRIVATE(ah)->ah_curchan)) return; /* Get core clock rate */ clkRate = ath_hal_mac_clks(ah, 1); /* Compute EIFS */ slot = coverageclass * 3 * clkRate; eifs = coverageclass * 6 * clkRate; if (IS_CHAN_HALF_RATE(AH_PRIVATE(ah)->ah_curchan)) { slot += IFS_SLOT_HALF_RATE; eifs += IFS_EIFS_HALF_RATE; } else if (IS_CHAN_QUARTER_RATE(AH_PRIVATE(ah)->ah_curchan)) { slot += IFS_SLOT_QUARTER_RATE; eifs += IFS_EIFS_QUARTER_RATE; } else { /* full rate */ slot += IFS_SLOT_FULL_RATE; eifs += IFS_EIFS_FULL_RATE; } /* * Add additional time for air propagation for ACK and CTS * timeouts. This value is in core clocks. */ timeout = ACK_CTS_TIMEOUT_11A + (coverageclass * 3 * clkRate); /* * Write the values: slot, eifs, ack/cts timeouts. */ OS_REG_WRITE(ah, AR_D_GBL_IFS_SLOT, slot); OS_REG_WRITE(ah, AR_D_GBL_IFS_EIFS, eifs); OS_REG_WRITE(ah, AR_TIME_OUT, SM(timeout, AR_TIME_OUT_CTS) | SM(timeout, AR_TIME_OUT_ACK)); }}voidar5212SetPCUConfig(struct ath_hal *ah){ ar5212SetOperatingMode(ah, AH_PRIVATE(ah)->ah_opmode);}/* * Return whether an external 32KHz crystal should be used * to reduce power consumption when sleeping. We do so if * the crystal is present (obtained from EEPROM) and if we * are not running as an AP and are configured to use it. */HAL_BOOLar5212Use32KHzclock(struct ath_hal *ah, HAL_OPMODE opmode){ if (opmode != HAL_M_HOSTAP) { struct ath_hal_5212 *ahp = AH5212(ah); return ath_hal_eepromGetFlag(ah, AR_EEP_32KHZCRYSTAL) && (ahp->ah_enable32kHzClock == USE_32KHZ || ahp->ah_enable32kHzClock == AUTO_32KHZ); } else return AH_FALSE;}/* * If 32KHz clock exists, use it to lower power consumption during sleep * * Note: If clock is set to 32 KHz, delays on accessing certain * baseband registers (27-31, 124-127) are required. */voidar5212SetupClock(struct ath_hal *ah, HAL_OPMODE opmode){ if (ar5212Use32KHzclock(ah, opmode)) { /* * Enable clocks to be turned OFF in BB during sleep * and also enable turning OFF 32MHz/40MHz Refclk * from A2. */ OS_REG_WRITE(ah, AR_PHY_SLEEP_CTR_CONTROL, 0x1f); OS_REG_WRITE(ah, AR_PHY_REFCLKPD, IS_RAD5112_ANY(ah) || IS_5413(ah) ? 0x14 : 0x18); OS_REG_RMW_FIELD(ah, AR_USEC, AR_USEC_USEC32, 1); OS_REG_WRITE(ah, AR_TSF_PARM, 61); /* 32 KHz TSF incr */ OS_REG_RMW_FIELD(ah, AR_PCICFG, AR_PCICFG_SCLK_SEL, 1); if (IS_2413(ah) || IS_5413(ah) || IS_2417(ah)) { OS_REG_WRITE(ah, AR_PHY_SLEEP_CTR_LIMIT, 0x26); OS_REG_WRITE(ah, AR_PHY_SLEEP_SCAL, 0x0d); OS_REG_WRITE(ah, AR_PHY_M_SLEEP, 0x07); OS_REG_WRITE(ah, AR_PHY_REFCLKDLY, 0x3f); /* # Set sleep clock rate to 32 KHz. */ OS_REG_RMW_FIELD(ah, AR_PCICFG, AR_PCICFG_SCLK_RATE_IND, 0x2); } else { OS_REG_WRITE(ah, AR_PHY_SLEEP_CTR_LIMIT, 0x0a); OS_REG_WRITE(ah, AR_PHY_SLEEP_SCAL, 0x0c); OS_REG_WRITE(ah, AR_PHY_M_SLEEP, 0x03); OS_REG_WRITE(ah, AR_PHY_REFCLKDLY, 0x20); OS_REG_RMW_FIELD(ah, AR_PCICFG, AR_PCICFG_SCLK_RATE_IND, 0x3); } } else { OS_REG_RMW_FIELD(ah, AR_PCICFG, AR_PCICFG_SCLK_RATE_IND, 0x0); OS_REG_RMW_FIELD(ah, AR_PCICFG, AR_PCICFG_SCLK_SEL, 0); OS_REG_WRITE(ah, AR_TSF_PARM, 1); /* 32MHz TSF inc */ OS_REG_WRITE(ah, AR_PHY_SLEEP_CTR_CONTROL, 0x1f); OS_REG_WRITE(ah, AR_PHY_SLEEP_CTR_LIMIT, 0x7f); if (IS_2417(ah)) OS_REG_WRITE(ah, AR_PHY_SLEEP_SCAL, 0x0a); else if (IS_HB63(ah)) OS_REG_WRITE(ah, AR_PHY_SLEEP_SCAL, 0x32); else OS_REG_WRITE(ah, AR_PHY_SLEEP_SCAL, 0x0e); OS_REG_WRITE(ah, AR_PHY_M_SLEEP, 0x0c); OS_REG_WRITE(ah, AR_PHY_REFCLKDLY, 0xff); OS_REG_WRITE(ah, AR_PHY_REFCLKPD, IS_RAD5112_ANY(ah) || IS_5413(ah) || IS_2417(ah) ? 0x14 : 0x18); OS_REG_RMW_FIELD(ah, AR_USEC, AR_USEC_USEC32, IS_RAD5112_ANY(ah) || IS_5413(ah) ? 39 : 31); }}/* * If 32KHz clock exists, turn it off and turn back on the 32Mhz */voidar5212RestoreClock(struct ath_hal *ah, HAL_OPMODE opmode){ if (ar5212Use32KHzclock(ah, opmode)) { /* # Set sleep clock rate back to 32 MHz. */ OS_REG_RMW_FIELD(ah, AR_PCICFG, AR_PCICFG_SCLK_RATE_IND, 0); OS_REG_RMW_FIELD(ah, AR_PCICFG, AR_PCICFG_SCLK_SEL, 0); OS_REG_WRITE(ah, AR_TSF_PARM, 1); /* 32 MHz TSF incr */ OS_REG_RMW_FIELD(ah, AR_USEC, AR_USEC_USEC32, IS_RAD5112_ANY(ah) || IS_5413(ah) ? 39 : 31); /* * Restore BB registers to power-on defaults */ OS_REG_WRITE(ah, AR_PHY_SLEEP_CTR_CONTROL, 0x1f); OS_REG_WRITE(ah, AR_PHY_SLEEP_CTR_LIMIT, 0x7f); OS_REG_WRITE(ah, AR_PHY_SLEEP_SCAL, 0x0e); OS_REG_WRITE(ah, AR_PHY_M_SLEEP, 0x0c); OS_REG_WRITE(ah, AR_PHY_REFCLKDLY, 0xff); OS_REG_WRITE(ah, AR_PHY_REFCLKPD, IS_RAD5112_ANY(ah) || IS_5413(ah) ? 0x14 : 0x18); }}/* * Adjust NF based on statistical values for 5GHz frequencies. * Default method: this may be overridden by the rf backend. */int16_tar5212GetNfAdjust(struct ath_hal *ah, const HAL_CHANNEL_INTERNAL *c){ static const struct { uint16_t freqLow; int16_t adjust; } adjustDef[] = { { 5790, 11 }, /* NB: ordered high -> low */ { 5730, 10 }, { 5690, 9 }, { 5660, 8 }, { 5610, 7 }, { 5530, 5 }, { 5450, 4 }, { 5379, 2 }, { 5209, 0 }, { 3000, 1 }, { 0, 0 }, }; int i; for (i = 0; c->channel <= adjustDef[i].freqLow; i++) ; return adjustDef[i].adjust;}HAL_STATUSar5212GetCapability(struct ath_hal *ah, HAL_CAPABILITY_TYPE type, uint32_t capability, uint32_t *result){#define MACVERSION(ah) AH_PRIVATE(ah)->ah_macVersion struct ath_hal_5212 *ahp = AH5212(ah); const HAL_CAPABILITIES *pCap = &AH_PRIVATE(ah)->ah_caps; const struct ar5212AniState *ani; switch (type) { case HAL_CAP_CIPHER: /* cipher handled in hardware */ switch (capability) { case HAL_CIPHER_AES_CCM: return pCap->halCipherAesCcmSupport ? HAL_OK : HAL_ENOTSUPP; case HAL_CIPHER_AES_OCB: case HAL_CIPHER_TKIP: case HAL_CIPHER_WEP: case HAL_CIPHER_MIC: case HAL_CIPHER_CLR: return HAL_OK; default: return HAL_ENOTSUPP; } case HAL_CAP_TKIP_MIC: /* handle TKIP MIC in hardware */ switch (capability) { case 0: /* hardware capability */ return HAL_OK; case 1: return (ahp->ah_staId1Defaults & AR_STA_ID1_CRPT_MIC_ENABLE) ? HAL_OK : HAL_ENXIO; } case HAL_CAP_TKIP_SPLIT: /* hardware TKIP uses split keys */ switch (capability) { case 0: /* hardware capability */ return pCap->halTkipMicTxRxKeySupport ? HAL_ENXIO : HAL_OK; case 1: /* current setting */ return (ahp->ah_miscMode & AR_MISC_MODE_MIC_NEW_LOC_ENABLE) ? HAL_ENXIO : HAL_OK; } return HAL_EINVAL; case HAL_CAP_WME_TKIPMIC: /* hardware can do TKIP MIC w/ WMM */ /* XXX move to capability bit */ return MACVERSION(ah) > AR_SREV_VERSION_VENICE || (MACVERSION(ah) == AR_SREV_VERSION_VENICE && AH_PRIVATE(ah)->ah_macRev >= 8) ? HAL_OK : HAL_ENOTSUPP; case HAL_CAP_DIVERSITY: /* hardware supports fast diversity */ switch (capability) { case 0: /* hardware capability */ return HAL_OK; case 1: /* current setting */ return ahp->ah_diversity ? HAL_OK : HAL_ENXIO; } return HAL_EINVAL; case HAL_CAP_DIAG: *result = AH_PRIVATE(ah)->ah_diagreg; return HAL_OK; case HAL_CAP_TPC: switch (capability) { case 0: /* hardware capability */ return HAL_OK; case 1: return ahp->ah_tpcEnabled ? HAL_OK : HAL_ENXIO; } return HAL_OK; case HAL_CAP_PHYDIAG: /* radar pulse detection capability */ switch (capability) { case HAL_CAP_RADAR: return ath_hal_eepromGetFlag(ah, AR_EEP_AMODE) ? HAL_OK: HAL_ENXIO; case HAL_CAP_AR: return (ath_hal_eepromGetFlag(ah, AR_EEP_GMODE) || ath_hal_eepromGetFlag(ah, AR_EEP_BMODE)) ? HAL_OK: HAL_ENXIO; } return HAL_ENXIO; case HAL_CAP_MCAST_KEYSRCH: /* multicast frame keycache search */ switch (capability) { case 0: /* hardware capability */ return HAL_OK; case 1: return (ahp->ah_staId1Defaults & AR_STA_ID1_MCAST_KSRCH) ? HAL_OK : HAL_ENXIO; } return HAL_EINVAL; case HAL_CAP_TSF_ADJUST: /* hardware has beacon tsf adjust */ switch (capability) { case 0: /* hardware capability */ return pCap->halTsfAddSupport ? HAL_OK : HAL_ENOTSUPP; case 1: return (ahp->ah_miscMode & AR_MISC_MODE_TX_ADD_TSF) ? HAL_OK : HAL_ENXIO; } return HAL_EINVAL; case HAL_CAP_TPC_ACK: *result = MS(ahp->ah_macTPC, AR_TPC_ACK); return HAL_OK; case HAL_CAP_TPC_CTS: *result = MS(ahp->ah_macTPC, AR_TPC_CTS); return HAL_OK; case HAL_CAP_INTMIT: /* interference mitigation */ switch (capability) { case 0: /* hardware capability */ return HAL_OK; case 1: return (ahp->ah_procPhyErr & HAL_ANI_ENA) ? HAL_OK : HAL_ENXIO; case 2: /* HAL_ANI_NOISE_IMMUNITY_LEVEL */ case 3: /* HAL_ANI_OFDM_WEAK_SIGNAL_DETECTION */ case 4: /* HAL_ANI_CCK_WEAK_SIGNAL_THR */ case 5: /* HAL_ANI_FIRSTEP_LEVEL */ case 6: /* HAL_ANI_SPUR_IMMUNITY_LEVEL */ ani = ar5212AniGetCurrentState(ah); if (ani == AH_NULL) return HAL_ENXIO; switch (capability) { case 2: *result = ani->noiseImmunityLevel; break; case 3: *result = !ani->ofdmWeakSigDetectOff; break; case 4: *result = ani->cckWeakSigThreshold; break; case 5: *result = ani->firstepLevel; break; case 6: *result = ani->spurImmunityLevel; break; } return HAL_OK; } return HAL_EINVAL; default: return ath_hal_getcapability(ah, type, capability, result); }#undef MACVERSION}HAL_BOOLar5212SetCapability(struct ath_hal *ah, HAL_CAPABILITY_TYPE type, uint32_t capability, uint32_t setting, HAL_STATUS *status){#define N(a) (sizeof(a)/sizeof(a[0])) struct ath_hal_5212 *ahp = AH5212(ah); const HAL_CAPABILITIES *pCap = &AH_PRIVATE(ah)->ah_caps; uint32_t v; switch (type) { case HAL_CAP_TKIP_MIC: /* handle TKIP MIC in hardware */ if (setting) ahp->ah_staId1Defaults |= AR_STA_ID1_CRPT_MIC_ENABLE; else ahp->ah_staId1Defaults &= ~AR_STA_ID1_CRPT_MIC_ENABLE; return AH_TRUE; case HAL_CAP_TKIP_SPLIT: /* hardware TKIP uses split keys */ if (!pCap->halTkipMicTxRxKeySupport) return AH_FALSE; /* NB: true =>'s use split key cache layout */ if (setting) ahp->ah_miscMode &= ~AR_MISC_MODE_MIC_NEW_LOC_ENABLE; else ahp->ah_miscMode |= AR_MISC_MODE_MIC_NEW_LOC_ENABLE; /* NB: write here so keys can be setup w/o a reset */ OS_REG_WRITE(ah, AR_MISC_MODE, ahp->ah_miscMode); return AH_TRUE; case HAL_CAP_DIVERSITY: if (ahp->ah_phyPowerOn) { v = OS_REG_READ(ah, AR_PHY_CCK_DETECT); if (setting) v |= AR_PHY_CCK_DETECT_BB_ENABLE_ANT_FAST_DIV; else v &= ~AR_PHY_CCK_DETECT_BB_ENABLE_ANT_FAST_DIV; OS_REG_WRITE(ah, AR_PHY_CCK_DETECT, v); } ahp->ah_diversity = (setting != 0); return AH_TRUE; case HAL_CAP_DIAG: /* hardware diagnostic support */ /* * NB: could split this up into virtual capabilities, * (e.g. 1 => ACK, 2 => CTS, etc.) but it hardly * seems worth the additional complexity. */ AH_PRIVATE(ah)->ah_diagreg = setting; OS_REG_WRITE(ah, AR_DIAG_SW, AH_PRIVATE(ah)->ah_diagreg); return AH_TRUE; case HAL_CAP_TPC: ahp->ah_tpcEnabled = (setting != 0); return AH_TRUE; case HAL_CAP_MCAST_KEYSRCH: /* multicast frame keycache search */ if (setting) ahp->ah_staId1Defaults |= AR_STA_ID1_MCAST_KSRCH; else ahp->ah_staId1Defaults &= ~AR_STA_ID1_MCAST_KSRCH; return AH_TRUE; case HAL_CAP_TPC_ACK: case HAL_CAP_TPC_CTS: setting += ahp->ah_txPowerIndexOffset; if (setting > 63) setting = 63; if (type == HAL_CAP_TPC_ACK) { ahp->ah_macTPC &= AR_TPC_ACK; ahp->ah_macTPC |= MS(setting, AR_TPC_ACK); } else { ahp->ah_macTPC &= AR_TPC_CTS; ahp->ah_macTPC |= MS(setting, AR_TPC_CTS); } OS_REG_WRITE(ah, AR_TPC, ahp->ah_macTPC); return AH_TRUE; case HAL_CAP_INTMIT: { /* interference mitigation */ static const HAL_ANI_CMD cmds[] = { HAL_ANI_PRESENT, HAL_ANI_MODE, HAL_ANI_NOISE_IMMUNITY_LEVEL, HAL_ANI_OFDM_WEAK_SIGNAL_DETECTION, HAL_ANI_CCK_WEAK_SIGNAL_THR, HAL_ANI_FIRSTEP_LEVEL, HAL_ANI_SPUR_IMMUNITY_LEVEL, }; return capability < N(cmds) ? ar5212AniControl(ah, cmds[capability], setting) : AH_FALSE; } case HAL_CAP_TSF_ADJUST: /* hardware has beacon tsf adjust */ if (pCap->halTsfAddSupport) { if (setting) ahp->ah_miscMode |= AR_MISC_MODE_TX_ADD_TSF; else ahp->ah_miscMode &= ~AR_MISC_MODE_TX_ADD_TSF; return AH_TRUE; } /* fall thru... */ default: return ath_hal_setcapability(ah, type, capability, setting, status); }#undef N}HAL_BOOLar5212GetDiagState(struct ath_hal *ah, int request, const void *args, uint32_t argsize, void **result, uint32_t *resultsize){ struct ath_hal_5212 *ahp = AH5212(ah); (void) ahp; if (ath_hal_getdiagstate(ah, request, args, argsize, result, resultsize)) return AH_TRUE; switch (request) { case HAL_DIAG_EEPROM: case HAL_DIAG_EEPROM_EXP_11A: case HAL_DIAG_EEPROM_EXP_11B: case HAL_DIAG_EEPROM_EXP_11G: case HAL_DIAG_RFGAIN: return ath_hal_eepromDiag(ah, request, args, argsize, result, resultsize); case HAL_DIAG_RFGAIN_CURSTEP: *result = __DECONST(void *, ahp->ah_gainValues.currStep); *resultsize = (*result == AH_NULL) ? 0 : sizeof(GAIN_OPTIMIZATION_STEP); return AH_TRUE; case HAL_DIAG_PCDAC: *result = ahp->ah_pcdacTable; *resultsize = ahp->ah_pcdacTableSize; return AH_TRUE; case HAL_DIAG_TXRATES: *result = &ahp->ah_ratesArray[0]; *resultsize = sizeof(ahp->ah_ratesArray); return AH_TRUE; case HAL_DIAG_ANI_CURRENT: *result = ar5212AniGetCurrentState(ah); *resultsize = (*result == AH_NULL) ? 0 : sizeof(struct ar5212AniState); return AH_TRUE; case HAL_DIAG_ANI_STATS: *result = ar5212AniGetCurrentStats(ah); *resultsize = (*result == AH_NULL) ? 0 : sizeof(struct ar5212Stats); return AH_TRUE; case HAL_DIAG_ANI_CMD: if (argsize != 2*sizeof(uint32_t)) return AH_FALSE; ar5212AniControl(ah, ((const uint32_t *)args)[0], ((const uint32_t *)args)[1]); return AH_TRUE; case HAL_DIAG_ANI_PARAMS: /* * NB: We assume struct ar5212AniParams is identical * to HAL_ANI_PARAMS; if they diverge then we'll need * to handle it here */ if (argsize == 0 && args == AH_NULL) { struct ar5212AniState *aniState = ar5212AniGetCurrentState(ah); if (aniState == AH_NULL) return AH_FALSE; *result = __DECONST(void *, aniState->params); *resultsize = sizeof(struct ar5212AniParams); return AH_TRUE; } else { if (argsize != sizeof(struct ar5212AniParams)) return AH_FALSE; return ar5212AniSetParams(ah, args, args); } } return AH_FALSE;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -