📄 ar5212_attach.c
字号:
/* * Copyright (c) 2002-2005 Sam Leffler, Errno Consulting * Copyright (c) 2002-2005 Atheros Communications, Inc. * All rights reserved. * * $Id: ar5212_attach.c,v 1.3 2006/10/13 07:10:49 steven Exp $ */#include "opt_ah.h"#ifdef AH_SUPPORT_AR5212#if !defined(AH_SUPPORT_5112) && !defined(AH_SUPPORT_5111) && !defined(AH_SUPPORT_2413) && !defined (AH_SUPPORT_5413)#error "No 5212 RF support defined"#endif#include "ah.h"#include "ah_internal.h"#include "ah_devid.h"#include "ar5212/ar5212.h"#include "ar5212/ar5212reg.h"#include "ar5212/ar5212phy.h"#ifdef AH_SUPPORT_AR5311#include "ar5212/ar5311reg.h"#endifstatic HAL_BOOL ar5212GetChipPowerLimits(struct ath_hal *ah, HAL_CHANNEL *chans, u_int32_t nchans);static const struct ath_hal_private ar5212hal = {{ .ah_magic = AR5212_MAGIC, .ah_abi = HAL_ABI_VERSION, .ah_countryCode = CTRY_DEFAULT, .ah_getRateTable = ar5212GetRateTable, .ah_detach = ar5212Detach, /* Reset Functions */ .ah_reset = ar5212Reset, .ah_phyDisable = ar5212PhyDisable, .ah_setPCUConfig = ar5212SetPCUConfig, .ah_perCalibration = ar5212PerCalibration, .ah_setTxPowerLimit = ar5212SetTxPowerLimit, /* AR/Radar Functions */ .ah_checkDfs = ar5212CheckDfs, .ah_dfsFound = ar5212DfsFound, .ah_enableDfs = ar5212EnableDfs, .ah_getDfsThresh = ar5212GetDfsThresh, .ah_radarWait = ar5212RadarWait, /* Xr Functions */ .ah_xrEnable = ar5212XrEnable, .ah_xrDisable = ar5212XrDisable, /* Transmit functions */ .ah_updateTxTrigLevel = ar5212UpdateTxTrigLevel, .ah_setupTxQueue = ar5212SetupTxQueue, .ah_setTxQueueProps = ar5212SetTxQueueProps, .ah_getTxQueueProps = ar5212GetTxQueueProps, .ah_releaseTxQueue = ar5212ReleaseTxQueue, .ah_resetTxQueue = ar5212ResetTxQueue, .ah_getTxDP = ar5212GetTxDP, .ah_setTxDP = ar5212SetTxDP, .ah_numTxPending = ar5212NumTxPending, .ah_startTxDma = ar5212StartTxDma, .ah_stopTxDma = ar5212StopTxDma, .ah_updateCTSForBursting = ar5212UpdateCTSForBursting, .ah_setupTxDesc = ar5212SetupTxDesc, .ah_setupXTxDesc = ar5212SetupXTxDesc, .ah_fillTxDesc = ar5212FillTxDesc, .ah_procTxDesc = ar5212ProcTxDesc, .ah_getTxIntrQueue = ar5212GetTxIntrQueue, .ah_reqTxIntrDesc = ar5212IntrReqTxDesc, /* RX Functions */ .ah_getRxDP = ar5212GetRxDP, .ah_setRxDP = ar5212SetRxDP, .ah_enableReceive = ar5212EnableReceive, .ah_stopDmaReceive = ar5212StopDmaReceive, .ah_startPcuReceive = ar5212StartPcuReceive, .ah_stopPcuReceive = ar5212StopPcuReceive, .ah_setMulticastFilter = ar5212SetMulticastFilter, .ah_setMulticastFilterIndex = ar5212SetMulticastFilterIndex, .ah_clrMulticastFilterIndex = ar5212ClrMulticastFilterIndex, .ah_getRxFilter = ar5212GetRxFilter, .ah_setRxFilter = ar5212SetRxFilter, .ah_setupRxDesc = ar5212SetupRxDesc, .ah_procRxDesc = ar5212ProcRxDesc, .ah_rxMonitor = ar5212AniArPoll, .ah_procMibEvent = ar5212ProcessMibIntr, /* Misc Functions */ .ah_getCapability = ar5212GetCapability, .ah_setCapability = ar5212SetCapability, .ah_getDiagState = ar5212GetDiagState, .ah_getMacAddress = ar5212GetMacAddress, .ah_setMacAddress = ar5212SetMacAddress, .ah_getBssIdMask = ar5212GetBssIdMask, .ah_setBssIdMask = ar5212SetBssIdMask, .ah_setRegulatoryDomain = ar5212SetRegulatoryDomain, .ah_setLedState = ar5212SetLedState, .ah_writeAssocid = ar5212WriteAssocid, .ah_gpioCfgInput = ar5212GpioCfgInput, .ah_gpioCfgOutput = ar5212GpioCfgOutput, .ah_gpioGet = ar5212GpioGet, .ah_gpioSet = ar5212GpioSet, .ah_gpioSetIntr = ar5212GpioSetIntr, .ah_getTsf32 = ar5212GetTsf32, .ah_getTsf64 = ar5212GetTsf64, .ah_resetTsf = ar5212ResetTsf, .ah_detectCardPresent = ar5212DetectCardPresent, .ah_updateMibCounters = ar5212UpdateMibCounters, .ah_getRfGain = ar5212GetRfgain, .ah_getDefAntenna = ar5212GetDefAntenna, .ah_setDefAntenna = ar5212SetDefAntenna, .ah_setSlotTime = ar5212SetSlotTime, .ah_getSlotTime = ar5212GetSlotTime, .ah_setAckTimeout = ar5212SetAckTimeout, .ah_getAckTimeout = ar5212GetAckTimeout, .ah_setCTSTimeout = ar5212SetCTSTimeout, .ah_getCTSTimeout = ar5212GetCTSTimeout, .ah_setDecompMask = ar5212SetDecompMask, .ah_setCoverageClass = ar5212SetCoverageClass, /* Key Cache Functions */ .ah_getKeyCacheSize = ar5212GetKeyCacheSize, .ah_resetKeyCacheEntry = ar5212ResetKeyCacheEntry, .ah_isKeyCacheEntryValid = ar5212IsKeyCacheEntryValid, .ah_setKeyCacheEntry = ar5212SetKeyCacheEntry, .ah_setKeyCacheEntryMac = ar5212SetKeyCacheEntryMac, /* Power Management Functions */ .ah_setPowerMode = ar5212SetPowerMode, .ah_getPowerMode = ar5212GetPowerMode, /* Beacon Functions */ .ah_beaconInit = ar5212BeaconInit, .ah_setStationBeaconTimers = ar5212SetStaBeaconTimers, .ah_resetStationBeaconTimers = ar5212ResetStaBeaconTimers, .ah_waitForBeaconDone = ar5212WaitForBeaconDone, /* Interrupt Functions */ .ah_isInterruptPending = ar5212IsInterruptPending, .ah_getPendingInterrupts = ar5212GetPendingInterrupts, .ah_getInterrupts = ar5212GetInterrupts, .ah_setInterrupts = ar5212SetInterrupts }, .ah_getChannelEdges = ar5212GetChannelEdges, .ah_getWirelessModes = ar5212GetWirelessModes, .ah_eepromAttach = ar5212EepromAttach,#if 0 .ah_eepromRead = ar5212EepromRead, .ah_eepromAttach = ar5212EepromAttach,#ifdef AH_SUPPORT_WRITE_EEPROM .ah_eepromWrite = ar5212EepromWrite,#endif .ah_eepromSetBoardValues = ar5212SetBoardValues,#endif .ah_gpioCfgOutput = ar5212GpioCfgOutput, .ah_gpioCfgInput = ar5212GpioCfgInput, .ah_gpioGet = ar5212GpioGet, .ah_gpioSet = ar5212GpioSet, .ah_gpioSetIntr = ar5212GpioSetIntr,// .ah_getChipPowerLimits = ar5212GetChipPowerLimits,};#if 0/* * TODO: Need to talk to Praveen about this, these are * not valid 2.4 channels, either we change these * or I need to change the beanie coding to accept these */static const u_int16_t channels11b[] = { 2412, 2447, 2484 };static const u_int16_t channels11g[] = { 2312, 2412, 2484 };#endif/* * Disable PLL when in L0s as well as receiver clock when in L1. * This power saving option must be enabled through the Serdes. * * Programming the Serdes must go through the same 288 bit serial shift * register as the other analog registers. Hence the 9 writes. * * XXX Clean up the magic numbers. */voidconfigurePciePowerSave(struct ath_hal *ah){ OS_REG_WRITE(ah, AR_PCIE_SERDES, 0x9248fc00); OS_REG_WRITE(ah, AR_PCIE_SERDES, 0x24924924); /* RX shut off when elecidle is asserted */ OS_REG_WRITE(ah, AR_PCIE_SERDES, 0x28000039); OS_REG_WRITE(ah, AR_PCIE_SERDES, 0x53160824); OS_REG_WRITE(ah, AR_PCIE_SERDES, 0xe5980579); /* Shut off PLL and CLKREQ active in L1 */ OS_REG_WRITE(ah, AR_PCIE_SERDES, 0x001defff); OS_REG_WRITE(ah, AR_PCIE_SERDES, 0x1aaabe40); OS_REG_WRITE(ah, AR_PCIE_SERDES, 0xbe105554); OS_REG_WRITE(ah, AR_PCIE_SERDES, 0x000e3007); /* Load the new settings */ OS_REG_WRITE(ah, AR_PCIE_SERDES2, 0x00000000);}u_int32_tar5212GetRadioRev(struct ath_hal *ah){ u_int32_t val; int i; /* Read Radio Chip Rev Extract */ OS_REG_WRITE(ah, AR_PHY(0x34), 0x00001c16); for (i = 0; i < 8; i++) OS_REG_WRITE(ah, AR_PHY(0x20), 0x00010000); val = (OS_REG_READ(ah, AR_PHY(256)) >> 24) & 0xff; val = ((val & 0xf0) >> 4) | ((val & 0x0f) << 4); return ath_hal_reverseBits(val, 8);}static voidar5212AniSetup(struct ath_hal *ah){ struct ath_hal_5212 *ahp = AH5212(ah); int i;#if 0 const int totalSizeDesired[] = { -55, -55, -55, -55, -62 }; const int coarseHigh[] = { -14, -14, -14, -14, -12 }; const int coarseLow[] = { -64, -64, -64, -64, -70 }; const int firpwr[] = { -78, -78, -78, -78, -80 };#endif const int totalSizeDesired[] = { -55, -55, -55, -55, -68 }; const int coarseHigh[] = { -14, -14, -14, -14, -14 }; const int coarseLow[] = { -64, -64, -64, -64, -64 }; const int firpwr[] = { -78, -78, -78, -78, -78 }; for (i = 0; i < 5; i++) { ahp->ah_totalSizeDesired[i] = totalSizeDesired[i]; ahp->ah_coarseHigh[i] = coarseHigh[i]; ahp->ah_coarseLow[i] = coarseLow[i]; ahp->ah_firpwr[i] = firpwr[i]; }}/* * Attach for an AR5212 part. */struct ath_hal_5212 *ar5212NewState(u_int16_t devid, HAL_SOFTC sc, HAL_BUS_TAG st, HAL_BUS_HANDLE sh, HAL_STATUS *status){#define N(a) (sizeof(a)/sizeof(a[0])) static const u_int8_t defbssidmask[IEEE80211_ADDR_LEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; struct ath_hal_5212 *ahp; struct ath_hal *ah; *status = 0; /* NB: memory is returned zero'd */ ahp = ath_hal_malloc(sizeof (struct ath_hal_5212)); if (ahp == AH_NULL) { HALDEBUG(AH_NULL, "%s: cannot allocate memory for " "state block\n", __func__); *status = HAL_ENOMEM; return AH_NULL; } ah = &ahp->ah_priv.h; /* set initial values */ OS_MEMCPY(&ahp->ah_priv, &ar5212hal, sizeof(struct ath_hal_private)); ah->ah_sc = sc; ah->ah_st = st; ah->ah_sh = sh; AH_PRIVATE(ah)->ah_devid = devid; AH_PRIVATE(ah)->ah_subvendorid = 0; /* XXX */ AH_PRIVATE(ah)->ah_powerLimit = MAX_RATE_POWER; AH_PRIVATE(ah)->ah_tpScale = HAL_TP_SCALE_MAX; /* no scaling */ ahp->ah_atimWindow = 0; /* [0..1000] */ ahp->ah_diversityControl = HAL_ANT_VARIABLE; ahp->ah_bIQCalibration = AH_FALSE; /* * Enable MIC handling. */ ahp->ah_staId1Defaults = AR_STA_ID1_CRPT_MIC_ENABLE; ahp->ah_tpcEnabled = AH_FALSE; /* disabled by default */ ahp->ah_beaconInterval = 100; /* XXX [20..1000] */ ahp->ah_enable32kHzClock = DONT_USE_32KHZ;/* XXX */ ahp->ah_slottime = (u_int) -1; ahp->ah_acktimeout = (u_int) -1; ahp->ah_ctstimeout = (u_int) -1; OS_MEMCPY(&ahp->ah_bssidmask, defbssidmask, IEEE80211_ADDR_LEN); /* * 11g-specific stuff */ ahp->ah_gBeaconRate = 0; /* adhoc beacon fixed rate */ return ahp;#undef N} /* * Attach for an AR5212 part. */struct ath_hal *ar5212Attach(u_int16_t devid, HAL_SOFTC sc, HAL_BUS_TAG st, HAL_BUS_HANDLE sh, HAL_STATUS *status){ struct ath_hal_5212 *ahp=AH_NULL; struct ath_hal *ah=AH_NULL; //u_int i; //u_int32_t sum; u_int32_t val=0; //u_int32_t eepMax; //u_int16_t eeval; HAL_STATUS ecode=0; HAL_BOOL rfStatus=0; HALDEBUG(AH_NULL, "%s: sc %p st %u sh %p\n", __func__, sc, st, (void*) sh); /* NB: memory is returned zero'd */ ahp = ar5212NewState(devid, sc, st, sh, status); if (ahp == AH_NULL) return AH_NULL; ah = &ahp->ah_priv.h; if (!ar5212SetPowerMode(ah, HAL_PM_AWAKE, AH_TRUE)) { HALDEBUG(ah, "%s: couldn't wakeup chip\n", __func__); ecode = HAL_EIO; goto bad; } /* Read Revisions from Chips before taking out of reset */ val = OS_REG_READ(ah, AR_SREV) & AR_SREV_ID; AH_PRIVATE(ah)->ah_macVersion = val >> AR_SREV_ID_S; AH_PRIVATE(ah)->ah_macRev = val & AR_SREV_REVISION; /* copy mac version and revision to public structure */ AH_PRIVATE(ah)->h.ah_macVersion = AH_PRIVATE(ah)->ah_macVersion; AH_PRIVATE(ah)->h.ah_macRev = AH_PRIVATE(ah)->ah_macRev; HALDEBUG(ah, "%s: Mac Chip Rev 0x%02x.%03x \n" , __func__, AH_PRIVATE(ah)->ah_macVersion, AH_PRIVATE(ah)->ah_macRev); if ((AH_PRIVATE(ah)->ah_macVersion != AR_SREV_VERSION_VENICE && AH_PRIVATE(ah)->ah_macVersion != AR_SREV_VERSION_GRIFFIN && AH_PRIVATE(ah)->ah_macVersion != AR_SREV_5413 && AH_PRIVATE(ah)->ah_macVersion != AR_SREV_5424) || AH_PRIVATE(ah)->ah_macRev < AR_SREV_D2PLUS) { HALDEBUG(ah, "%s: Mac Chip Rev 0x%02x.%x is not supported by " "this driver\n", __func__, AH_PRIVATE(ah)->ah_macVersion, AH_PRIVATE(ah)->ah_macRev); ecode = HAL_ENOTSUPP; goto bad; } if (!ar5212ChipReset(ah, AH_NULL)) { /* reset chip */ HALDEBUG(ah, "%s: chip reset failed\n", __func__); ecode = HAL_EIO; goto bad; } AH_PRIVATE(ah)->ah_phyRev = OS_REG_READ(ah, AR_PHY_CHIP_ID); AH_PRIVATE(ah)->h.ah_phyRev = AH_PRIVATE(ah)->ah_phyRev; if (IS_5424(ah)) { /* XXX: build flag to disable this? */ configurePciePowerSave(ah); } if (!ar5212ChipTest(ah)) { HALDEBUG(ah, "%s: hardware self-test failed\n", __func__); ecode = HAL_ESELFTEST; goto bad; } /* * Set correct Baseband to analog shift * setting to access analog chips. */ OS_REG_WRITE(ah, AR_PHY(0), 0x00000007); /* Read Radio Chip Rev Extract */ AH_PRIVATE(ah)->ah_analog5GhzRev = ar5212GetRadioRev(ah); AH_PRIVATE(ah)->h.ah_analog5GhzRev = AH_PRIVATE(ah)->ah_analog5GhzRev; /* NB: silently accept anything in release code per Atheros */ switch (AH_PRIVATE(ah)->ah_analog5GhzRev & AR_RADIO_SREV_MAJOR) { case AR_RAD5111_SREV_MAJOR: case AR_RAD5112_SREV_MAJOR: case AR_RAD2111_SREV_MAJOR: case AR_SREV_2413: case AR_SREV_5413: case AR_RAD2413_SREV_MAJOR: case AR_RAD5413_SREV_MAJOR: case AR_RAD5424_SREV_MAJOR: break; default: if (AH_PRIVATE(ah)->ah_analog5GhzRev == 0) { /* * WAR for bug 10062. When RF_Silent is used, the * analog chip is reset. So when the system boots * up with the radio switch off we cannot determine * the RF chip rev. To workaround this check the * mac+phy revs and if Hainan, set the radio rev * to Derby. */ if (AH_PRIVATE(ah)->ah_macVersion == AR_SREV_VERSION_VENICE && AH_PRIVATE(ah)->ah_macRev == AR_SREV_HAINAN && AH_PRIVATE(ah)->ah_phyRev == AR_PHYREV_HAINAN) { AH_PRIVATE(ah)->ah_analog5GhzRev = AR_ANALOG5REV_HAINAN;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -