⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ar5312_reset.c

📁 Atheros wifi driver source code
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * Copyright (c) 2002-2004 Sam Leffler, Errno Consulting * Copyright (c) 2002-2004 Atheros Communications, Inc. * All rights reserved. * * $Id: ar5312_reset.c,v 1.1.1.1 2006/09/12 03:45:23 steven Exp $ */#include "opt_ah.h"#ifdef AH_SUPPORT_AR5312#include "ah.h"#include "ah_internal.h"#include "ah_devid.h"#include "ar5312/ar5312.h"#include "ar5312/ar5312reg.h"#include "ar5312/ar5312phy.h"/* Add static register initialization vectors */#define AH_5212_COMMON#include "ar5212/ar5212.ini"/* Additional Time delay to wait after activiting the Base band */#define BASE_ACTIVATE_DELAY	100	/* 100 usec */#define PLL_SETTLE_DELAY	300	/* 300 usec */extern int16_t ar5212GetNf(struct ath_hal *, HAL_CHANNEL_INTERNAL *);extern void ar5212SetRateDurationTable(struct ath_hal *, HAL_CHANNEL *);extern HAL_BOOL ar5212SetTransmitPower(struct ath_hal *ah,                      HAL_CHANNEL_INTERNAL *chan, u_int16_t *rfXpdGain);extern void ar5212SetDeltaSlope(struct ath_hal *, HAL_CHANNEL_INTERNAL *);extern void ar5212SetOperatingMode(struct ath_hal *, int );extern void ar5212SetCompRegs(struct ath_hal *);extern void ar5212SetIFSTiming(struct ath_hal *, HAL_CHANNEL *);extern HAL_BOOL	ar5212IsSpurChannel(struct ath_hal *, HAL_CHANNEL *);extern HAL_BOOL	ar5212ChannelChange(struct ath_hal *, HAL_CHANNEL *);extern void ar5212SetSpurMitigation(struct ath_hal *, HAL_CHANNEL_INTERNAL *);#ifdef AH_SUPPORT_XRextern HAL_BOOL ar5212SetXrMode(struct ath_hal *ah, HAL_OPMODE opmode,HAL_CHANNEL *chan);#endifstatic HAL_BOOL ar5312SetResetReg(struct ath_hal *, u_int32_t resetMask);/* * 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 IS_NO_RESET_TIMER_ADDR(x)                      \    ( (((x) >= AR_BEACON) && ((x) <= AR_CFP_DUR)) || \      (((x) >= AR_SLEEP1) && ((x) <= AR_SLEEP3)))#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)/* * Places the device in and out of reset and then places sane * values in the registers based on EEPROM config, initialization * vectors (as determined by the mode), and station configuration * * bChannelChange is used to preserve DMA/PCU registers across * a HW Reset during channel change. */HAL_BOOLar5312Reset(struct ath_hal *ah, HAL_OPMODE opmode,	HAL_CHANNEL *chan, HAL_BOOL bChannelChange, HAL_STATUS *status){#define	N(a)	(sizeof (a) / sizeof (a[0]))#define	FAIL(_code)	do { ecode = _code; goto bad; } while (0)	struct ath_hal_5212 *ahp = AH5212(ah);	HAL_CHANNEL_INTERNAL *ichan;	u_int32_t saveFrameSeqCount, saveDefAntenna;	u_int32_t macStaId1, synthDelay, txFrm2TxDStart;	u_int16_t rfXpdGain[2];	int16_t cckOfdmPwrDelta = 0;	u_int modesIndex, freqIndex;	HAL_STATUS ecode;	int i, regWrites = 0;	u_int32_t testReg, powerVal, rssiThrReg;	int8_t twiceAntennaGain, twiceAntennaReduction;	u_int32_t ackTpcPow, ctsTpcPow, chirpTpcPow;#if !( AH_SUPPORT_2316 || AH_SUPPORT_2317)	u_int32_t  saveLedState;#endif	OS_MARK(ah, AH_MARK_RESET, bChannelChange);#define	IS(_c,_f)	(((_c)->channelFlags & _f) || 0)	if ((IS(chan, CHANNEL_2GHZ) ^ IS(chan, CHANNEL_5GHZ)) == 0) {		HALDEBUG(ah, "%s: invalid channel %u/0x%x; not marked as "			 "2GHz or 5GHz\n", __func__,			chan->channel, chan->channelFlags);		FAIL(HAL_EINVAL);	}	if ((IS(chan, CHANNEL_OFDM) ^ IS(chan, CHANNEL_CCK)) == 0) {		HALDEBUG(ah, "%s: invalid channel %u/0x%x; not marked as "			"OFDM or CCK\n", __func__,			chan->channel, chan->channelFlags);		FAIL(HAL_EINVAL);	}#undef IS	/*	 * Map public channel to private.	 */	ichan = ath_hal_checkchannel(ah, chan);	if (ichan == AH_NULL) {		HALDEBUG(ah, "%s: invalid channel %u/0x%x; no mapping\n",			__func__, chan->channel, chan->channelFlags);		FAIL(HAL_EINVAL);	}	switch (opmode) {	case HAL_M_STA:	case HAL_M_IBSS:	case HAL_M_HOSTAP:	case HAL_M_MONITOR:		break;	default:		HALDEBUG(ah, "%s: invalid operating mode %u\n",			__func__, opmode);		FAIL(HAL_EINVAL);		break;	}	HALASSERT(ahp->ah_eeversion >= AR_EEPROM_VER3);	/* Preserve certain DMA hardware registers on a channel change */	if (bChannelChange) {		/*		 * AR5212 WAR		 *		 * On Venice, the TSF is almost preserved across a reset;		 * it requires the WAR of doubling writes to the RESET_TSF		 * bit in the AR_BEACON register; it also has the quirk		 * of the TSF going back in time on the station (station		 * latches onto the last beacon's tsf during a reset 50%		 * of the times); the latter is not a problem for adhoc		 * stations since as long as the TSF is behind, it will		 * get resynchronized on receiving the next beacon; the		 * TSF going backwards in time could be a problem for the		 * sleep operation (supported on infrastructure stations		 * only) - the best and most general fix for this situation		 * is to resynchronize the various sleep/beacon timers on		 * the receipt of the next beacon i.e. when the TSF itself		 * gets resynchronized to the AP's TSF - power save is		 * needed to be temporarily disabled until that time		 *		 * Need to save the sequence number to restore it after		 * the reset!		 */		saveFrameSeqCount = OS_REG_READ(ah, AR_D_SEQNUM);		ar5212GetNf(ah, ichan);	} else		saveFrameSeqCount = 0;		/* NB: silence compiler */	/* If the channel change is across the same mode - perform a fast channel change */	if ((IS_2413(ah) || IS_5413(ah))) {		/*		 * Channel change can only be used when:		 *  -channel change requested - so it's not the initial reset.		 *  -it's not a change to the current channel - often called when switching modes		 *   on a channel		 *  -the modes of the previous and requested channel are the same - some ugly code for XR		 */		if (bChannelChange &&		    (AH_PRIVATE(ah)->ah_curchan != AH_NULL) &&		    (chan->channel != AH_PRIVATE(ah)->ah_curchan->channel) &&		    ((chan->channelFlags & CHANNEL_ALL) ==		     (AH_PRIVATE(ah)->ah_curchan->channelFlags & CHANNEL_ALL))) {			if (ar5212ChannelChange(ah, chan)) {				/* If ChannelChange completed - skip the rest of reset */				return AH_TRUE;			}		}	}	/*	 * Preserve the bmiss rssi threshold and count threshold	 * across resets	 */	rssiThrReg = OS_REG_READ(ah, AR_RSSI_THR);	/* If reg is zero, first time thru set to default val */	if (rssiThrReg == 0) {		rssiThrReg = INIT_RSSI_THR;	}	/*	 * Preserve the antenna on a channel change	 */	saveDefAntenna = OS_REG_READ(ah, AR_DEF_ANTENNA);	if (saveDefAntenna == 0)		/* XXX magic constants */		saveDefAntenna = 1;	/* Save hardware flag before chip reset clears the register */	macStaId1 = OS_REG_READ(ah, AR_STA_ID1) & (AR_STA_ID1_BASE_RATE_11B | AR_STA_ID1_USE_DEFANT);#if !(AH_SUPPORT_2316 || AH_SUPPORT_2317)	/* not yet */	/* Save led state from pci config register */	saveLedState = OS_REG_READ(ah, AR531X_PCICFG) &		(AR_PCICFG_LEDCTL | AR_PCICFG_LEDMODE | AR_PCICFG_LEDBLINK |		 AR_PCICFG_LEDSLOW);#endif	if (!(IS_5416(ah)))		ar5312RestoreClock(ah, opmode);		/* move to refclk operation */	/*	 * Adjust gain parameters before reset if	 * there's an outstanding gain updated.	 */	(void) ar5212GetRfgain(ah);	if (!ar5312ChipReset(ah, chan)) {		HALDEBUG(ah, "%s: chip reset failed\n", __func__);		FAIL(HAL_EIO);	}	/* Restore bmiss rssi & count thresholds */	OS_REG_WRITE(ah, AR_RSSI_THR, rssiThrReg);	/* Setup the indices for the next set of register array writes */	switch (chan->channelFlags & CHANNEL_ALL) {	case CHANNEL_A:	case CHANNEL_XR_A:		modesIndex = 1;		freqIndex  = 1;		break;	case CHANNEL_T:	case CHANNEL_XR_T:		modesIndex = 2;		freqIndex  = 1;		break;	case CHANNEL_B:		modesIndex = 3;		freqIndex  = 2;		break;	case CHANNEL_PUREG:	case CHANNEL_XR_G:		modesIndex = 4;		freqIndex  = 2;		break;	case CHANNEL_108G:		modesIndex = 5;		freqIndex  = 2;		break;	default:		HALDEBUG(ah, "%s: invalid channel flags 0x%x\n",			__func__, chan->channelFlags);		FAIL(HAL_EINVAL);	}	OS_MARK(ah, AH_MARK_RESET_LINE, __LINE__);	/* Set correct Baseband to analog shift setting to access analog chips. */	OS_REG_WRITE(ah, AR_PHY(0), 0x00000007);	if (!IS_5416(ah)) {		REG_WRITE_ARRAY(ar5212Modes, modesIndex, regWrites);		/* Write Common Array Parameters */		for (i = 0; i < N(ar5212Common); i++) {			u_int32_t reg = ar5212Common[i][0];			/* XXX timer/beacon setup registers? */			/* On channel change, don't reset the PCU registers */			if (!(bChannelChange && IS_NO_RESET_TIMER_ADDR(reg))) {				OS_REG_WRITE(ah, reg, ar5212Common[i][1]);				WAR_6773(regWrites);			}		}	}	ahp->ah_rfHal.writeRegs(ah, modesIndex, freqIndex, regWrites);	OS_MARK(ah, AH_MARK_RESET_LINE, __LINE__);	if (IS_CHAN_HALF_RATE(chan) || IS_CHAN_QUARTER_RATE(chan)) {		ar5212SetIFSTiming(ah, chan);	}	/* Overwrite INI values for revised chipsets */	if (AH_PRIVATE(ah)->ah_phyRev >= AR_PHY_CHIP_ID_REV_2) {		/* ADC_CTL */		OS_REG_WRITE(ah, AR_PHY_ADC_CTL,			     SM(2, AR_PHY_ADC_CTL_OFF_INBUFGAIN) |			     SM(2, AR_PHY_ADC_CTL_ON_INBUFGAIN) |			     AR_PHY_ADC_CTL_OFF_PWDDAC |			     AR_PHY_ADC_CTL_OFF_PWDADC);				/* TX_PWR_ADJ */		if (chan->channel == 2484) {			cckOfdmPwrDelta = SCALE_OC_DELTA(ahp->ah_cckOfdmPwrDelta - ahp->ah_scaledCh14FilterCckDelta);		} else {			cckOfdmPwrDelta = SCALE_OC_DELTA(ahp->ah_cckOfdmPwrDelta);		}				if (IS_CHAN_G(chan)) {			OS_REG_WRITE(ah, AR_PHY_TXPWRADJ,				     SM((ahp->ah_cckOfdmPwrDelta*-1), AR_PHY_TXPWRADJ_CCK_GAIN_DELTA) |				     SM((cckOfdmPwrDelta*-1), AR_PHY_TXPWRADJ_CCK_PCDAC_INDEX));		} else {			OS_REG_WRITE(ah, AR_PHY_TXPWRADJ, 0);		}				/* Add barker RSSI thresh enable as disabled */		OS_REG_CLR_BIT(ah, AR_PHY_DAG_CTRLCCK,			       AR_PHY_DAG_CTRLCCK_EN_RSSI_THR);		OS_REG_RMW_FIELD(ah, AR_PHY_DAG_CTRLCCK,				 AR_PHY_DAG_CTRLCCK_RSSI_THR, 2);				/* Set the mute mask to the correct default */		OS_REG_WRITE(ah, AR_SEQ_MASK, 0x0000000F);	}		if (AH_PRIVATE(ah)->ah_phyRev >= AR_PHY_CHIP_ID_REV_3) {		/* Clear reg to alllow RX_CLEAR line debug */		OS_REG_WRITE(ah, AR_PHY_BLUETOOTH,  0);	}	if (AH_PRIVATE(ah)->ah_phyRev >= AR_PHY_CHIP_ID_REV_4) {#ifdef notyet		/* Enable burst prefetch for the data queues */		OS_REG_RMW_FIELD(ah, AR_D_FPCTL, ... );		/* Enable double-buffering */		OS_REG_CLR_BIT(ah, AR_TXCFG, AR_TXCFG_DBL_BUF_DIS);#endif	}	if (IS_5312_2_X(ah)) {		/* ADC_CTRL */		OS_REG_WRITE(ah, AR_PHY_SIGMA_DELTA,			     SM(2, AR_PHY_SIGMA_DELTA_ADC_SEL) |			     SM(4, AR_PHY_SIGMA_DELTA_FILT2) |			     SM(0x16, AR_PHY_SIGMA_DELTA_FILT1) |			     SM(0, AR_PHY_SIGMA_DELTA_ADC_CLIP));		if (IS_CHAN_2GHZ(chan))			OS_REG_RMW_FIELD(ah, AR_PHY_RXGAIN, AR_PHY_RXGAIN_TXRX_RF_MAX, 0x0F);		/* CCK Short parameter adjustment in 11B mode */		if (IS_CHAN_B(chan))			OS_REG_RMW_FIELD(ah, AR_PHY_CCK_RXCTRL4, AR_PHY_CCK_RXCTRL4_FREQ_EST_SHORT, 12);		/* Set ADC/DAC select values */		OS_REG_WRITE(ah, AR_PHY_SLEEP_SCAL, 0x04);		/* Increase 11A AGC Settling */		if ((chan->channelFlags & CHANNEL_ALL) == CHANNEL_A)			OS_REG_RMW_FIELD(ah, AR_PHY_SETTLING, AR_PHY_SETTLING_AGC, 32);	} else {		/* Set ADC/DAC select values */		OS_REG_WRITE(ah, AR_PHY_SLEEP_SCAL, 0x0e);	}	/* Setup the transmit power values. */	if (!AH_PRIVATE(ah)->ah_setTransmitPower(ah, ichan, rfXpdGain)) {		HALDEBUG(ah, "%s: error init'ing transmit power\n", __func__);		FAIL(HAL_EIO);	}	/* Write the analog registers */	if (!ahp->ah_rfHal.setRfRegs(ah, ichan, (IS_5416(ah) ? freqIndex : modesIndex),				     rfXpdGain)) {		HALDEBUG(ah, "%s: ar5212SetRfRegs failed\n", __func__);		FAIL(HAL_EIO);	}	/* Setup board specific options for EEPROM version 3 */	if (!AH_PRIVATE(ah)->ah_eepromSetBoardValues(ah, ichan)) {		HALDEBUG(ah, "%s: error setting board options\n", __func__);		FAIL(HAL_EIO);	}	/* Restore certain DMA hardware registers on a channel change */	if (bChannelChange)		OS_REG_WRITE(ah, AR_D_SEQNUM, saveFrameSeqCount);	OS_MARK(ah, AH_MARK_RESET_LINE, __LINE__);	OS_REG_WRITE(ah, AR_STA_ID0, LE_READ_4(ahp->ah_macaddr));	OS_REG_WRITE(ah, AR_STA_ID1, LE_READ_2(ahp->ah_macaddr + 4)		| macStaId1		| AR_STA_ID1_RTS_USE_DEF		| ahp->ah_staId1Defaults	);	ar5212SetOperatingMode(ah, opmode);	/* Set Venice BSSID mask according to current state */	OS_REG_WRITE(ah, AR_BSSMSKL, LE_READ_4(ahp->ah_bssidmask));	OS_REG_WRITE(ah, AR_BSSMSKU, LE_READ_2(ahp->ah_bssidmask + 4));#if !(AH_SUPPORT_2316 || AH_SUPPORT_2317)	/* not yet */	/* Restore previous led state */	OS_REG_WRITE(ah, AR531X_PCICFG, OS_REG_READ(ah, AR_PCICFG) | saveLedState);#endif	/* Restore previous antenna */	OS_REG_WRITE(ah, AR_DEF_ANTENNA, saveDefAntenna);	/* then our BSSID */	OS_REG_WRITE(ah, AR_BSS_ID0, LE_READ_4(ahp->ah_bssid));	OS_REG_WRITE(ah, AR_BSS_ID1, LE_READ_2(ahp->ah_bssid + 4));	OS_REG_WRITE(ah, AR_ISR, ~0);		/* cleared on write */	OS_REG_WRITE(ah, AR_RSSI_THR, INIT_RSSI_THR);	if (!ahp->ah_rfHal.setChannel(ah, ichan))		FAIL(HAL_EIO);	OS_MARK(ah, AH_MARK_RESET_LINE, __LINE__);	ar5212SetCoverageClass(ah, AH_PRIVATE(ah)->ah_coverageClass, 1);	ar5212SetRateDurationTable(ah, chan);	/* Set Tx frame start to tx data start delay */	if (IS_5112(ah) && (IS_CHAN_HALF_RATE(AH_PRIVATE(ah)->ah_curchan) ||			IS_CHAN_QUARTER_RATE(AH_PRIVATE(ah)->ah_curchan))) {		txFrm2TxDStart = 			(IS_CHAN_HALF_RATE(AH_PRIVATE(ah)->ah_curchan)) ?					TX_FRAME_D_START_HALF_RATE:					TX_FRAME_D_START_QUARTER_RATE;		OS_REG_RMW_FIELD(ah, AR_PHY_TX_CTL, 			AR_PHY_TX_FRAME_TO_TX_DATA_START, txFrm2TxDStart);	}	/*	 * Setup fast diversity.	 * Fast diversity can be enabled or disabled via regadd.txt.	 * Default is enabled.	 * For reference,	 *    Disable: reg        val	 *             0x00009860 0x00009d18 (if 11a / 11g, else no change)	 *             0x00009970 0x192bb514	 *             0x0000a208 0xd03e4648	 *	 *    Enable:  0x00009860 0x00009d10 (if 11a / 11g, else no change)	 *             0x00009970 0x192fb514	 *             0x0000a208 0xd03e6788	 */	/* XXX Setup pre PHY ENABLE EAR additions */	/* WAR for bug 11728 - flush SCAL reg */	if (IS_5312_2_X(ah)) {		OS_REG_READ(ah, AR_PHY_SLEEP_SCAL);	}	/*	 * Wait for the frequency synth to settle (synth goes on	 * via AR_PHY_ACTIVE_EN).  Read the phy active delay register.	 * Value is in 100ns increments.	 */	synthDelay = OS_REG_READ(ah, AR_PHY_RX_DELAY) & AR_PHY_RX_DELAY_DELAY;	if (IS_CHAN_CCK(chan)) {		synthDelay = (4 * synthDelay) / 22;	} else {		synthDelay /= 10;	}	/* Activate the PHY (includes baseband activate and synthesizer on) */	OS_REG_WRITE(ah, AR_PHY_ACTIVE, AR_PHY_ACTIVE_EN);	/* 	 * There is an issue if the AP starts the calibration before	 * the base band timeout completes.  This could result in the	 * rx_clear false triggering.  As a workaround we add delay an	 * extra BASE_ACTIVATE_DELAY usecs to ensure this condition	 * does not happen.	 */	if (IS_CHAN_HALF_RATE(AH_PRIVATE(ah)->ah_curchan)) {		OS_DELAY((synthDelay << 1) + BASE_ACTIVATE_DELAY);	} else if (IS_CHAN_QUARTER_RATE(AH_PRIVATE(ah)->ah_curchan)) {		OS_DELAY((synthDelay << 2) + BASE_ACTIVATE_DELAY);	} else {		OS_DELAY(synthDelay + BASE_ACTIVATE_DELAY);	}	/* Calibrate the AGC and start a NF calculation */	OS_REG_WRITE(ah, AR_PHY_AGC_CONTROL,		  OS_REG_READ(ah, AR_PHY_AGC_CONTROL)		| AR_PHY_AGC_CONTROL_CAL		| AR_PHY_AGC_CONTROL_NF);	if (!IS_CHAN_B(chan) && ahp->ah_bIQCalibration != IQ_CAL_DONE) {		/* Start IQ calibration w/ 2^(INIT_IQCAL_LOG_COUNT_MAX+1) samples */		OS_REG_RMW_FIELD(ah, AR_PHY_TIMING_CTRL4, 

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -