Ejemplo n.º 1
0
static void
print_chaninfo(const struct ieee80211_channel *c)
{
	char buf[14];

	buf[0] = '\0';
	if (IEEE80211_IS_CHAN_FHSS(c))
		strlcat(buf, " FHSS", sizeof(buf));
	if (IEEE80211_IS_CHAN_A(c))
		strlcat(buf, " 11a", sizeof(buf));
	/* XXX 11g schizophrenia */
	if (IEEE80211_IS_CHAN_G(c) ||
	    IEEE80211_IS_CHAN_PUREG(c))
		strlcat(buf, " 11g", sizeof(buf));
	else if (IEEE80211_IS_CHAN_B(c))
		strlcat(buf, " 11b", sizeof(buf));
	if (IEEE80211_IS_CHAN_STURBO(c))
		strlcat(buf, " Static", sizeof(buf));
	if (IEEE80211_IS_CHAN_DTURBO(c))
		strlcat(buf, " Dynamic", sizeof(buf));
	if (IEEE80211_IS_CHAN_HALF(c))
		strlcat(buf, " Half", sizeof(buf));
	if (IEEE80211_IS_CHAN_QUARTER(c))
		strlcat(buf, " Quarter", sizeof(buf));
	printf("Channel %3u : %u%c%c Mhz%-14.14s",
		c->ic_ieee, c->ic_freq,
		IEEE80211_IS_CHAN_PASSIVE(c) ? '*' : ' ', 
	        IEEE80211_IS_CHAN_RADAR(c) ? '!' : ' ', 
	       buf);
}
Ejemplo n.º 2
0
static void
dumpchannels(struct ath_hal *ah, int nc,
	const struct ieee80211_channel *chans, int16_t *txpow)
{
	int i;

	for (i = 0; i < nc; i++) {
		const struct ieee80211_channel *c = &chans[i];
		int type;

		if (showchannels)
			printf("%s%3d", sep,
			    ath_hal_mhz2ieee(ah, c->ic_freq, c->ic_flags));
		else
			printf("%s%u", sep, c->ic_freq);
		if (IEEE80211_IS_CHAN_HALF(c))
			type = 'H';
		else if (IEEE80211_IS_CHAN_QUARTER(c))
			type = 'Q';
		else if (IEEE80211_IS_CHAN_TURBO(c))
			type = 'T';
		else if (IEEE80211_IS_CHAN_HT(c))
			type = 'N';
		else if (IEEE80211_IS_CHAN_A(c))
			type = 'A';
		else if (IEEE80211_IS_CHAN_108G(c))
			type = 'T';
		else if (IEEE80211_IS_CHAN_G(c))
			type = 'G';
		else
			type = 'B';
		if (dopassive && IEEE80211_IS_CHAN_PASSIVE(c))
			type = tolower(type);
		if (isdfs && is4ms)
			printf("%c%c%c %d.%d", type,
			    IEEE80211_IS_CHAN_DFS(c) ? '*' : ' ',
			    IEEE80211_IS_CHAN_4MS(c) ? '4' : ' ',
			    txpow[i]/2, (txpow[i]%2)*5);
		else if (isdfs)
			printf("%c%c %d.%d", type,
			    IEEE80211_IS_CHAN_DFS(c) ? '*' : ' ',
			    txpow[i]/2, (txpow[i]%2)*5);
		else if (is4ms)
			printf("%c%c %d.%d", type,
			    IEEE80211_IS_CHAN_4MS(c) ? '4' : ' ',
			    txpow[i]/2, (txpow[i]%2)*5);
		else
			printf("%c %d.%d", type, txpow[i]/2, (txpow[i]%2)*5);
		if ((n++ % (showchannels ? 7 : 6)) == 0)
			sep = "\n";
		else
			sep = " ";
	}
}
Ejemplo n.º 3
0
static void
ar9160AniSetup(struct ath_hal *ah)
{
	static const struct ar5212AniParams aniparams = {
		.maxNoiseImmunityLevel	= 4,	/* levels 0..4 */
		.totalSizeDesired	= { -55, -55, -55, -55, -62 },
		.coarseHigh		= { -14, -14, -14, -14, -12 },
		.coarseLow		= { -64, -64, -64, -64, -70 },
		.firpwr			= { -78, -78, -78, -78, -80 },
		.maxSpurImmunityLevel	= 7,
		.cycPwrThr1		= { 2, 4, 6, 8, 10, 12, 14, 16 },
		.maxFirstepLevel	= 2,	/* levels 0..2 */
		.firstep		= { 0, 4, 8 },
		.ofdmTrigHigh		= 500,
		.ofdmTrigLow		= 200,
		.cckTrigHigh		= 200,
		.cckTrigLow		= 100,
		.rssiThrHigh		= 40,
		.rssiThrLow		= 7,
		.period			= 100,
	};

	/* NB: disable ANI noise immmunity for reliable RIFS rx */
	AH5416(ah)->ah_ani_function &= ~(1 << HAL_ANI_NOISE_IMMUNITY_LEVEL);
	ar5416AniAttach(ah, &aniparams, &aniparams, AH_TRUE);
}

static void 
ar9160InitPLL(struct ath_hal *ah, const struct ieee80211_channel *chan)
{
	uint32_t pll = SM(0x5, AR_RTC_SOWL_PLL_REFDIV);
	if (chan != AH_NULL) {
		if (IEEE80211_IS_CHAN_HALF(chan))
			pll |= SM(0x1, AR_RTC_SOWL_PLL_CLKSEL);
		else if (IEEE80211_IS_CHAN_QUARTER(chan))
			pll |= SM(0x2, AR_RTC_SOWL_PLL_CLKSEL);

		if (IEEE80211_IS_CHAN_5GHZ(chan))
			pll |= SM(0x50, AR_RTC_SOWL_PLL_DIV);
		else
			pll |= SM(0x58, AR_RTC_SOWL_PLL_DIV);
	} else
		pll |= SM(0x58, AR_RTC_SOWL_PLL_DIV);

	OS_REG_WRITE(ah, AR_RTC_PLL_CONTROL, pll);
	OS_DELAY(RTC_PLL_SETTLE_DELAY);
	OS_REG_WRITE(ah, AR_RTC_SLEEP_CLK, AR_RTC_SLEEP_DERIVED_CLK);
}
Ejemplo n.º 4
0
void icm_display_channel_flags(ICM_CHANNEL_T* pch)
{
    ICM_DEV_INFO_T* pdev = get_pdev();
    if (IEEE80211_IS_CHAN_FHSS(pch)) {
        ICM_DPRINTF(pdev, ICM_PRCTRL_FLAG_NONE, ICM_DEBUG_LEVEL_DEFAULT, ICM_MODULE_ID_UTIL, "\tFHSS\n");
    }

    if (IEEE80211_IS_CHAN_11NA(pch)) {
        ICM_DPRINTF(pdev, ICM_PRCTRL_FLAG_NONE, ICM_DEBUG_LEVEL_DEFAULT, ICM_MODULE_ID_UTIL, "\t11na\n");
    } else if (IEEE80211_IS_CHAN_A(pch)) {
        ICM_DPRINTF(pdev, ICM_PRCTRL_FLAG_NONE, ICM_DEBUG_LEVEL_DEFAULT, ICM_MODULE_ID_UTIL, "\t11a\n");
    } else if (IEEE80211_IS_CHAN_11NG(pch)) {
        ICM_DPRINTF(pdev, ICM_PRCTRL_FLAG_NONE, ICM_DEBUG_LEVEL_DEFAULT, ICM_MODULE_ID_UTIL, "\t11ng\n");
    } else if (IEEE80211_IS_CHAN_G(pch) ||
        IEEE80211_IS_CHAN_PUREG(pch)) {
        ICM_DPRINTF(pdev, ICM_PRCTRL_FLAG_NONE, ICM_DEBUG_LEVEL_DEFAULT, ICM_MODULE_ID_UTIL, "\t11g\n");
    } else if (IEEE80211_IS_CHAN_B(pch)) {
        ICM_DPRINTF(pdev, ICM_PRCTRL_FLAG_NONE, ICM_DEBUG_LEVEL_DEFAULT, ICM_MODULE_ID_UTIL, "\t11b\n");
    }
    if (IEEE80211_IS_CHAN_TURBO(pch)) {
        ICM_DPRINTF(pdev, ICM_PRCTRL_FLAG_NONE, ICM_DEBUG_LEVEL_DEFAULT, ICM_MODULE_ID_UTIL, "\tTurbo\n");
    }
    if(IEEE80211_IS_CHAN_11N_CTL_CAPABLE(pch)) {
        ICM_DPRINTF(pdev, ICM_PRCTRL_FLAG_NONE, ICM_DEBUG_LEVEL_DEFAULT, ICM_MODULE_ID_UTIL, "\tControl capable\n");
    }
    if(IEEE80211_IS_CHAN_11N_CTL_U_CAPABLE(pch)) {
        ICM_DPRINTF(pdev, ICM_PRCTRL_FLAG_NONE, ICM_DEBUG_LEVEL_DEFAULT, ICM_MODULE_ID_UTIL, "\tControl capable upper\n");
    }
    if(IEEE80211_IS_CHAN_11N_CTL_L_CAPABLE(pch)) {
        ICM_DPRINTF(pdev, ICM_PRCTRL_FLAG_NONE, ICM_DEBUG_LEVEL_DEFAULT, ICM_MODULE_ID_UTIL, "\tControl capable lower\n");
    }

    if (IEEE80211_IS_CHAN_DFSFLAG(pch)) {
        ICM_DPRINTF(pdev, ICM_PRCTRL_FLAG_NONE, ICM_DEBUG_LEVEL_DEFAULT, ICM_MODULE_ID_UTIL, "\tDFS\n");
    }

    if (IEEE80211_IS_CHAN_HALF(pch)) {
        ICM_DPRINTF(pdev, ICM_PRCTRL_FLAG_NONE, ICM_DEBUG_LEVEL_DEFAULT, ICM_MODULE_ID_UTIL, "\tHalf\n");
    }

    if (IEEE80211_IS_CHAN_PASSIVE(pch)) {
        ICM_DPRINTF(pdev, ICM_PRCTRL_FLAG_NONE, ICM_DEBUG_LEVEL_DEFAULT, ICM_MODULE_ID_UTIL, "\tPassive\n");
    }

    if (IEEE80211_IS_CHAN_QUARTER(pch)) {
        ICM_DPRINTF(pdev, ICM_PRCTRL_FLAG_NONE, ICM_DEBUG_LEVEL_DEFAULT, ICM_MODULE_ID_UTIL, "\tQuarter\n");
    }
}
Ejemplo n.º 5
0
/*
 * Fill in 802.11 available channel set, mark
 * all available channels as active, and pick
 * a default channel if not already specified.
 */
static void
ieee80211_chan_init(struct ieee80211com *ic)
{
#define	DEFAULTRATES(m, def) do { \
	if (ic->ic_sup_rates[m].rs_nrates == 0) \
		ic->ic_sup_rates[m] = def; \
} while (0)
	struct ieee80211_channel *c;
	int i;

	KASSERT(0 < ic->ic_nchans && ic->ic_nchans <= IEEE80211_CHAN_MAX,
		("invalid number of channels specified: %u", ic->ic_nchans));
	memset(ic->ic_chan_avail, 0, sizeof(ic->ic_chan_avail));
	memset(ic->ic_modecaps, 0, sizeof(ic->ic_modecaps));
	setbit(ic->ic_modecaps, IEEE80211_MODE_AUTO);
	for (i = 0; i < ic->ic_nchans; i++) {
		c = &ic->ic_channels[i];
		KASSERT(c->ic_flags != 0, ("channel with no flags"));
		/*
		 * Help drivers that work only with frequencies by filling
		 * in IEEE channel #'s if not already calculated.  Note this
		 * mimics similar work done in ieee80211_setregdomain when
		 * changing regulatory state.
		 */
		if (c->ic_ieee == 0)
			c->ic_ieee = ieee80211_mhz2ieee(c->ic_freq,c->ic_flags);
		if (IEEE80211_IS_CHAN_HT40(c) && c->ic_extieee == 0)
			c->ic_extieee = ieee80211_mhz2ieee(c->ic_freq +
			    (IEEE80211_IS_CHAN_HT40U(c) ? 20 : -20),
			    c->ic_flags);
		/* default max tx power to max regulatory */
		if (c->ic_maxpower == 0)
			c->ic_maxpower = 2*c->ic_maxregpower;
		setbit(ic->ic_chan_avail, c->ic_ieee);
		/*
		 * Identify mode capabilities.
		 */
		if (IEEE80211_IS_CHAN_A(c))
			setbit(ic->ic_modecaps, IEEE80211_MODE_11A);
		if (IEEE80211_IS_CHAN_B(c))
			setbit(ic->ic_modecaps, IEEE80211_MODE_11B);
		if (IEEE80211_IS_CHAN_ANYG(c))
			setbit(ic->ic_modecaps, IEEE80211_MODE_11G);
		if (IEEE80211_IS_CHAN_FHSS(c))
			setbit(ic->ic_modecaps, IEEE80211_MODE_FH);
		if (IEEE80211_IS_CHAN_108A(c))
			setbit(ic->ic_modecaps, IEEE80211_MODE_TURBO_A);
		if (IEEE80211_IS_CHAN_108G(c))
			setbit(ic->ic_modecaps, IEEE80211_MODE_TURBO_G);
		if (IEEE80211_IS_CHAN_ST(c))
			setbit(ic->ic_modecaps, IEEE80211_MODE_STURBO_A);
		if (IEEE80211_IS_CHAN_HALF(c))
			setbit(ic->ic_modecaps, IEEE80211_MODE_HALF);
		if (IEEE80211_IS_CHAN_QUARTER(c))
			setbit(ic->ic_modecaps, IEEE80211_MODE_QUARTER);
		if (IEEE80211_IS_CHAN_HTA(c))
			setbit(ic->ic_modecaps, IEEE80211_MODE_11NA);
		if (IEEE80211_IS_CHAN_HTG(c))
			setbit(ic->ic_modecaps, IEEE80211_MODE_11NG);
	}
	/* initialize candidate channels to all available */
	memcpy(ic->ic_chan_active, ic->ic_chan_avail,
		sizeof(ic->ic_chan_avail));

	/* sort channel table to allow lookup optimizations */
	ieee80211_sort_channels(ic->ic_channels, ic->ic_nchans);

	/* invalidate any previous state */
	ic->ic_bsschan = IEEE80211_CHAN_ANYC;
	ic->ic_prevchan = NULL;
	ic->ic_csa_newchan = NULL;
	/* arbitrarily pick the first channel */
	ic->ic_curchan = &ic->ic_channels[0];
	ic->ic_rt = ieee80211_get_ratetable(ic->ic_curchan);

	/* fillin well-known rate sets if driver has not specified */
	DEFAULTRATES(IEEE80211_MODE_11B,	 ieee80211_rateset_11b);
	DEFAULTRATES(IEEE80211_MODE_11G,	 ieee80211_rateset_11g);
	DEFAULTRATES(IEEE80211_MODE_11A,	 ieee80211_rateset_11a);
	DEFAULTRATES(IEEE80211_MODE_TURBO_A,	 ieee80211_rateset_11a);
	DEFAULTRATES(IEEE80211_MODE_TURBO_G,	 ieee80211_rateset_11g);
	DEFAULTRATES(IEEE80211_MODE_STURBO_A,	 ieee80211_rateset_11a);
	DEFAULTRATES(IEEE80211_MODE_HALF,	 ieee80211_rateset_half);
	DEFAULTRATES(IEEE80211_MODE_QUARTER,	 ieee80211_rateset_quarter);
	DEFAULTRATES(IEEE80211_MODE_11NA,	 ieee80211_rateset_11a);
	DEFAULTRATES(IEEE80211_MODE_11NG,	 ieee80211_rateset_11g);

	/*
	 * Set auto mode to reset active channel state and any desired channel.
	 */
	(void) ieee80211_setmode(ic, IEEE80211_MODE_AUTO);
#undef DEFAULTRATES
}
Ejemplo n.º 6
0
static void
ar9280AniSetup(struct ath_hal *ah)
{
	/*
	 * These are the parameters from the AR5416 ANI code;
	 * they likely need quite a bit of adjustment for the
	 * AR9280.
	 */
        static const struct ar5212AniParams aniparams = {
                .maxNoiseImmunityLevel  = 4,    /* levels 0..4 */
                .totalSizeDesired       = { -55, -55, -55, -55, -62 },
                .coarseHigh             = { -14, -14, -14, -14, -12 },
                .coarseLow              = { -64, -64, -64, -64, -70 },
                .firpwr                 = { -78, -78, -78, -78, -80 },
                .maxSpurImmunityLevel   = 2,
                .cycPwrThr1             = { 2, 4, 6 },
                .maxFirstepLevel        = 2,    /* levels 0..2 */
                .firstep                = { 0, 4, 8 },
                .ofdmTrigHigh           = 500,
                .ofdmTrigLow            = 200,
                .cckTrigHigh            = 200,
                .cckTrigLow             = 100,
                .rssiThrHigh            = 40,
                .rssiThrLow             = 7,
                .period                 = 100,
        };
	/* NB: disable ANI noise immmunity for reliable RIFS rx */
	AH5416(ah)->ah_ani_function &= ~(1 << HAL_ANI_NOISE_IMMUNITY_LEVEL);

        /* NB: ANI is not enabled yet */
        ar5416AniAttach(ah, &aniparams, &aniparams, AH_TRUE);
}

void
ar9280InitPLL(struct ath_hal *ah, const struct ieee80211_channel *chan)
{
	uint32_t pll = SM(0x5, AR_RTC_SOWL_PLL_REFDIV);

	if (AR_SREV_MERLIN_20(ah) &&
	    chan != AH_NULL && IEEE80211_IS_CHAN_5GHZ(chan)) {
		/*
		 * PLL WAR for Merlin 2.0/2.1
		 * When doing fast clock, set PLL to 0x142c
		 * Else, set PLL to 0x2850 to prevent reset-to-reset variation 
		 */
		pll = IS_5GHZ_FAST_CLOCK_EN(ah, chan) ? 0x142c : 0x2850;
	} else if (AR_SREV_MERLIN_10_OR_LATER(ah)) {
		pll = SM(0x5, AR_RTC_SOWL_PLL_REFDIV);
		if (chan != AH_NULL) {
			if (IEEE80211_IS_CHAN_HALF(chan))
				pll |= SM(0x1, AR_RTC_SOWL_PLL_CLKSEL);
			else if (IEEE80211_IS_CHAN_QUARTER(chan))
				pll |= SM(0x2, AR_RTC_SOWL_PLL_CLKSEL);
			if (IEEE80211_IS_CHAN_5GHZ(chan))
				pll |= SM(0x28, AR_RTC_SOWL_PLL_DIV);
			else
				pll |= SM(0x2c, AR_RTC_SOWL_PLL_DIV);
		} else
			pll |= SM(0x2c, AR_RTC_SOWL_PLL_DIV);
	}

	OS_REG_WRITE(ah, AR_RTC_PLL_CONTROL, pll);
	OS_DELAY(RTC_PLL_SETTLE_DELAY);
	OS_REG_WRITE(ah, AR_RTC_SLEEP_CLK, AR_RTC_SLEEP_DERIVED_CLK);
}
Ejemplo n.º 7
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_BOOL
ar5312Reset(struct ath_hal *ah, HAL_OPMODE opmode,
	struct ieee80211_channel *chan,
	HAL_BOOL bChannelChange,
	HAL_RESET_TYPE resetType,
	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;
	const HAL_EEPROM *ee;
	uint32_t saveFrameSeqCount, saveDefAntenna;
	uint32_t macStaId1, synthDelay, txFrm2TxDStart;
	uint16_t rfXpdGain[MAX_NUM_PDGAINS_PER_CHANNEL];
	int16_t cckOfdmPwrDelta = 0;
	u_int modesIndex, freqIndex;
	HAL_STATUS ecode;
	int i, regWrites = 0;
	uint32_t testReg;
	uint32_t saveLedState = 0;

	HALASSERT(ah->ah_magic == AR5212_MAGIC);
	ee = AH_PRIVATE(ah)->ah_eeprom;

	OS_MARK(ah, AH_MARK_RESET, bChannelChange);
	/*
	 * Map public channel to private.
	 */
	ichan = ath_hal_checkchannel(ah, chan);
	if (ichan == AH_NULL) {
		HALDEBUG(ah, HAL_DEBUG_ANY,
		    "%s: invalid channel %u/0x%x; no mapping\n",
		    __func__, chan->ic_freq, chan->ic_flags);
		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, HAL_DEBUG_ANY, "%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) {
		/*
		 * On Venice, the TSF is almost preserved across a reset;
		 * it requires the 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);
	} 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->ic_freq != AH_PRIVATE(ah)->ah_curchan->ic_freq) &&
		    ((chan->ic_flags & IEEE80211_CHAN_ALLTURBO) ==
		     (AH_PRIVATE(ah)->ah_curchan->ic_flags & IEEE80211_CHAN_ALLTURBO))) {
			if (ar5212ChannelChange(ah, chan))
				/* If ChannelChange completed - skip the rest of reset */
				return AH_TRUE;
		}
	}

	/*
	 * 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);

	/* Save led state from pci config register */
	if (!IS_5315(ah))
		saveLedState = OS_REG_READ(ah, AR5312_PCICFG) &
			(AR_PCICFG_LEDCTL | AR_PCICFG_LEDMODE | AR_PCICFG_LEDBLINK |
			 AR_PCICFG_LEDSLOW);

	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, HAL_DEBUG_ANY, "%s: chip reset failed\n", __func__);
		FAIL(HAL_EIO);
	}

	/* Setup the indices for the next set of register array writes */
	if (IEEE80211_IS_CHAN_2GHZ(chan)) {
		freqIndex  = 2;
		modesIndex = IEEE80211_IS_CHAN_108G(chan) ? 5 :
			     IEEE80211_IS_CHAN_G(chan) ? 4 : 3;
	} else {
		freqIndex  = 1;
		modesIndex = IEEE80211_IS_CHAN_ST(chan) ? 2 : 1;
	}

	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);

	regWrites = ath_hal_ini_write(ah, &ahp->ah_ini_modes, modesIndex, 0);
	regWrites = write_common(ah, &ahp->ah_ini_common, bChannelChange,
		regWrites);
	ahp->ah_rfHal->writeRegs(ah, modesIndex, freqIndex, regWrites);

	OS_MARK(ah, AH_MARK_RESET_LINE, __LINE__);

	if (IEEE80211_IS_CHAN_HALF(chan) || IEEE80211_IS_CHAN_QUARTER(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(ee->ee_cckOfdmPwrDelta - ee->ee_scaledCh14FilterCckDelta);
		} else {
			cckOfdmPwrDelta = SCALE_OC_DELTA(ee->ee_cckOfdmPwrDelta);
		}
		
		if (IEEE80211_IS_CHAN_G(chan)) {
			OS_REG_WRITE(ah, AR_PHY_TXPWRADJ,
				     SM((ee->ee_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 (IEEE80211_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 (IEEE80211_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 (IEEE80211_IS_CHAN_A(chan))
			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 (!ar5212SetTransmitPower(ah, chan, rfXpdGain)) {
		HALDEBUG(ah, HAL_DEBUG_ANY,
		    "%s: error init'ing transmit power\n", __func__);
		FAIL(HAL_EIO);
	}

	/* Write the analog registers */
	if (!ahp->ah_rfHal->setRfRegs(ah, chan, modesIndex, rfXpdGain)) {
		HALDEBUG(ah, HAL_DEBUG_ANY, "%s: ar5212SetRfRegs failed\n",
		    __func__);
		FAIL(HAL_EIO);
	}

	/* Write delta slope for OFDM enabled modes (A, G, Turbo) */
	if (IEEE80211_IS_CHAN_OFDM(chan)) {
		if (IS_5413(ah) ||
		   AH_PRIVATE(ah)->ah_eeversion >= AR_EEPROM_VER5_3)
			ar5212SetSpurMitigation(ah, chan);
		ar5212SetDeltaSlope(ah, chan);
	}

	/* Setup board specific options for EEPROM version 3 */
	if (!ar5212SetBoardValues(ah, chan)) {
		HALDEBUG(ah, HAL_DEBUG_ANY,
		    "%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));

	/* Restore previous led state */
	if (!IS_5315(ah))
		OS_REG_WRITE(ah, AR5312_PCICFG, OS_REG_READ(ah, AR_PCICFG) | saveLedState);

	/* 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));

	/* Restore bmiss rssi & count thresholds */
	OS_REG_WRITE(ah, AR_RSSI_THR, ahp->ah_rssiThr);

	OS_REG_WRITE(ah, AR_ISR, ~0);		/* cleared on write */

	if (!ar5212SetChannel(ah, chan))
		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_RAD5112_ANY(ah) &&
	    (IEEE80211_IS_CHAN_HALF(chan) || IEEE80211_IS_CHAN_QUARTER(chan))) {
		txFrm2TxDStart = 
			IEEE80211_IS_CHAN_HALF(chan) ?
					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 */

	/* flush SCAL reg */
	if (IS_5312_2_X(ah)) {
		(void) 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 (IEEE80211_IS_CHAN_B(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 (IEEE80211_IS_CHAN_HALF(chan)) {
		OS_DELAY((synthDelay << 1) + BASE_ACTIVATE_DELAY);
	} else if (IEEE80211_IS_CHAN_QUARTER(chan)) {
		OS_DELAY((synthDelay << 2) + BASE_ACTIVATE_DELAY);
	} else {
		OS_DELAY(synthDelay + BASE_ACTIVATE_DELAY);
	}

	/*
	 * The udelay method is not reliable with notebooks.
	 * Need to check to see if the baseband is ready
	 */
	testReg = OS_REG_READ(ah, AR_PHY_TESTCTRL);
	/* Selects the Tx hold */
	OS_REG_WRITE(ah, AR_PHY_TESTCTRL, AR_PHY_TESTCTRL_TXHOLD);
	i = 0;
	while ((i++ < 20) &&
	       (OS_REG_READ(ah, 0x9c24) & 0x10)) /* test if baseband not ready */		OS_DELAY(200);
	OS_REG_WRITE(ah, AR_PHY_TESTCTRL, testReg);

	/* 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 (!IEEE80211_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, 
			AR_PHY_TIMING_CTRL4_IQCAL_LOG_COUNT_MAX,
			INIT_IQCAL_LOG_COUNT_MAX);
		OS_REG_SET_BIT(ah, AR_PHY_TIMING_CTRL4,
			AR_PHY_TIMING_CTRL4_DO_IQCAL);
		ahp->ah_bIQCalibration = IQ_CAL_RUNNING;
	} else
		ahp->ah_bIQCalibration = IQ_CAL_INACTIVE;

	/* Setup compression registers */
	ar5212SetCompRegs(ah);

	/* Set 1:1 QCU to DCU mapping for all queues */
	for (i = 0; i < AR_NUM_DCU; i++)
		OS_REG_WRITE(ah, AR_DQCUMASK(i), 1 << i);

	ahp->ah_intrTxqs = 0;
	for (i = 0; i < AH_PRIVATE(ah)->ah_caps.halTotalQueues; i++)
		ar5212ResetTxQueue(ah, i);

	/*
	 * Setup interrupt handling.  Note that ar5212ResetTxQueue
	 * manipulates the secondary IMR's as queues are enabled
	 * and disabled.  This is done with RMW ops to insure the
	 * settings we make here are preserved.
	 */
	ahp->ah_maskReg = AR_IMR_TXOK | AR_IMR_TXERR | AR_IMR_TXURN
			| AR_IMR_RXOK | AR_IMR_RXERR | AR_IMR_RXORN
			| AR_IMR_HIUERR
			;
	if (opmode == HAL_M_HOSTAP)
		ahp->ah_maskReg |= AR_IMR_MIB;
	OS_REG_WRITE(ah, AR_IMR, ahp->ah_maskReg);
	/* Enable bus errors that are OR'd to set the HIUERR bit */
	OS_REG_WRITE(ah, AR_IMR_S2,
		OS_REG_READ(ah, AR_IMR_S2)
		| AR_IMR_S2_MCABT | AR_IMR_S2_SSERR | AR_IMR_S2_DPERR);

	if (AH_PRIVATE(ah)->ah_rfkillEnabled)
		ar5212EnableRfKill(ah);

	if (!ath_hal_wait(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_CAL, 0)) {
		HALDEBUG(ah, HAL_DEBUG_ANY,
		    "%s: offset calibration failed to complete in 1ms;"
		    " noisy environment?\n", __func__);
	}

	/*
	 * Set clocks back to 32kHz if they had been using refClk, then
	 * use an external 32kHz crystal when sleeping, if one exists.
	 */
	ar5312SetupClock(ah, opmode);

	/*
	 * Writing to AR_BEACON will start timers. Hence it should
	 * be the last register to be written. Do not reset tsf, do
	 * not enable beacons at this point, but preserve other values
	 * like beaconInterval.
	 */
	OS_REG_WRITE(ah, AR_BEACON,
		(OS_REG_READ(ah, AR_BEACON) &~ (AR_BEACON_EN | AR_BEACON_RESET_TSF)));

	/* XXX Setup post reset EAR additions */

	/*  QoS support */
	if (AH_PRIVATE(ah)->ah_macVersion > AR_SREV_VERSION_VENICE ||
	    (AH_PRIVATE(ah)->ah_macVersion == AR_SREV_VERSION_VENICE &&
	     AH_PRIVATE(ah)->ah_macRev >= AR_SREV_GRIFFIN_LITE)) {
		OS_REG_WRITE(ah, AR_QOS_CONTROL, 0x100aa);	/* XXX magic */
		OS_REG_WRITE(ah, AR_QOS_SELECT, 0x3210);	/* XXX magic */
	}

	/* Turn on NOACK Support for QoS packets */
	OS_REG_WRITE(ah, AR_NOACK,
		     SM(2, AR_NOACK_2BIT_VALUE) |
		     SM(5, AR_NOACK_BIT_OFFSET) |
		     SM(0, AR_NOACK_BYTE_OFFSET));

	/* Restore user-specified settings */
	if (ahp->ah_miscMode != 0)
		OS_REG_WRITE(ah, AR_MISC_MODE, ahp->ah_miscMode);
	if (ahp->ah_slottime != (u_int) -1)
		ar5212SetSlotTime(ah, ahp->ah_slottime);
	if (ahp->ah_acktimeout != (u_int) -1)
		ar5212SetAckTimeout(ah, ahp->ah_acktimeout);
	if (ahp->ah_ctstimeout != (u_int) -1)
		ar5212SetCTSTimeout(ah, ahp->ah_ctstimeout);
	if (ahp->ah_sifstime != (u_int) -1)
		ar5212SetSifsTime(ah, ahp->ah_sifstime);
	if (AH_PRIVATE(ah)->ah_diagreg != 0)
		OS_REG_WRITE(ah, AR_DIAG_SW, AH_PRIVATE(ah)->ah_diagreg);

	AH_PRIVATE(ah)->ah_opmode = opmode;	/* record operating mode */

	if (bChannelChange && !IEEE80211_IS_CHAN_DFS(chan)) 
		chan->ic_state &= ~IEEE80211_CHANSTATE_CWINT;

	HALDEBUG(ah, HAL_DEBUG_RESET, "%s: done\n", __func__);

	OS_MARK(ah, AH_MARK_RESET_DONE, 0);

	return AH_TRUE;
bad:
	OS_MARK(ah, AH_MARK_RESET_DONE, ecode);
	if (status != AH_NULL)
		*status = ecode;
	return AH_FALSE;
#undef FAIL
#undef N
}
Ejemplo n.º 8
0
/*
 * Places the hardware into reset and then pulls it out of reset
 *
 * TODO: Only write the PLL if we're changing to or from CCK mode
 * 
 * WARNING: The order of the PLL and mode registers must be correct.
 */
HAL_BOOL
ar5312ChipReset(struct ath_hal *ah, const struct ieee80211_channel *chan)
{

	OS_MARK(ah, AH_MARK_CHIPRESET, chan ? chan->ic_freq : 0);

	/*
	 * Reset the HW 
	 */
	if (!ar5312SetResetReg(ah, AR_RC_MAC | AR_RC_BB)) {
		HALDEBUG(ah, HAL_DEBUG_ANY, "%s: ar5312SetResetReg failed\n",
		    __func__);
		return AH_FALSE;
	}

	/* Bring out of sleep mode (AGAIN) */
	if (!ar5312SetPowerMode(ah, HAL_PM_AWAKE, AH_TRUE)) {
		HALDEBUG(ah, HAL_DEBUG_ANY, "%s: ar5312SetPowerMode failed\n",
		    __func__);
		return AH_FALSE;
	}

	/* Clear warm reset register */
	if (!ar5312SetResetReg(ah, 0)) {
		HALDEBUG(ah, HAL_DEBUG_ANY, "%s: ar5312SetResetReg failed\n",
		    __func__);
		return AH_FALSE;
	}

	/*
	 * Perform warm reset before the mode/PLL/turbo registers
	 * are changed in order to deactivate the radio.  Mode changes
	 * with an active radio can result in corrupted shifts to the
	 * radio device.
	 */

	/*
	 * Set CCK and Turbo modes correctly.
	 */
	if (chan != AH_NULL) {		/* NB: can be null during attach */
		uint32_t rfMode, phyPLL = 0, curPhyPLL, turbo;

		if (IS_RAD5112_ANY(ah)) {
			rfMode = AR_PHY_MODE_AR5112;
			if (!IS_5315(ah)) {
				if (IEEE80211_IS_CHAN_CCK(chan)) {
					phyPLL = AR_PHY_PLL_CTL_44_5312;
				} else {
					if (IEEE80211_IS_CHAN_HALF(chan)) {
						phyPLL = AR_PHY_PLL_CTL_40_5312_HALF;
					} else if (IEEE80211_IS_CHAN_QUARTER(chan)) {
						phyPLL = AR_PHY_PLL_CTL_40_5312_QUARTER;
					} else {
						phyPLL = AR_PHY_PLL_CTL_40_5312;
					}
				}
			} else {
				if (IEEE80211_IS_CHAN_CCK(chan))
					phyPLL = AR_PHY_PLL_CTL_44_5112;
				else
					phyPLL = AR_PHY_PLL_CTL_40_5112;
				if (IEEE80211_IS_CHAN_HALF(chan))
					phyPLL |= AR_PHY_PLL_CTL_HALF;
				else if (IEEE80211_IS_CHAN_QUARTER(chan))
					phyPLL |= AR_PHY_PLL_CTL_QUARTER;
			}
		} else {
			rfMode = AR_PHY_MODE_AR5111;
			if (IEEE80211_IS_CHAN_CCK(chan))
				phyPLL = AR_PHY_PLL_CTL_44;
			else
				phyPLL = AR_PHY_PLL_CTL_40;
			if (IEEE80211_IS_CHAN_HALF(chan))
				phyPLL = AR_PHY_PLL_CTL_HALF;
			else if (IEEE80211_IS_CHAN_QUARTER(chan))
				phyPLL = AR_PHY_PLL_CTL_QUARTER;
		}
		if (IEEE80211_IS_CHAN_G(chan))
			rfMode |= AR_PHY_MODE_DYNAMIC;
		else if (IEEE80211_IS_CHAN_OFDM(chan))
			rfMode |= AR_PHY_MODE_OFDM;
		else
			rfMode |= AR_PHY_MODE_CCK;
		if (IEEE80211_IS_CHAN_5GHZ(chan))
			rfMode |= AR_PHY_MODE_RF5GHZ;
		else
			rfMode |= AR_PHY_MODE_RF2GHZ;
		turbo = IEEE80211_IS_CHAN_TURBO(chan) ?
			(AR_PHY_FC_TURBO_MODE | AR_PHY_FC_TURBO_SHORT) : 0;
		curPhyPLL = OS_REG_READ(ah, AR_PHY_PLL_CTL);
		/*
		 * PLL, Mode, and Turbo values must be written in the correct
		 * order to ensure:
		 * - The PLL cannot be set to 44 unless the CCK or DYNAMIC
		 *   mode bit is set
		 * - Turbo cannot be set at the same time as CCK or DYNAMIC
		 */
		if (IEEE80211_IS_CHAN_CCK(chan)) {
			OS_REG_WRITE(ah, AR_PHY_TURBO, turbo);
			OS_REG_WRITE(ah, AR_PHY_MODE, rfMode);
			if (curPhyPLL != phyPLL) {
				OS_REG_WRITE(ah,  AR_PHY_PLL_CTL,  phyPLL);
				/* Wait for the PLL to settle */
				OS_DELAY(PLL_SETTLE_DELAY);
			}
		} else {
			if (curPhyPLL != phyPLL) {
				OS_REG_WRITE(ah,  AR_PHY_PLL_CTL,  phyPLL);
				/* Wait for the PLL to settle */
				OS_DELAY(PLL_SETTLE_DELAY);
			}
			OS_REG_WRITE(ah, AR_PHY_TURBO, turbo);
			OS_REG_WRITE(ah, AR_PHY_MODE, rfMode);
		}
	}
	return AH_TRUE;
}
Ejemplo n.º 9
0
/*
 * Reads EEPROM header info from device structure and programs
 * all rf registers
 *
 * REQUIRES: Access to the analog rf device
 */
static HAL_BOOL
ar5111SetRfRegs(struct ath_hal *ah, const struct ieee80211_channel *chan,
	uint16_t modesIndex, uint16_t *rfXpdGain)
{
	uint16_t freq = ath_hal_gethwchannel(ah, chan);
	struct ath_hal_5212 *ahp = AH5212(ah);
	const HAL_EEPROM *ee = AH_PRIVATE(ah)->ah_eeprom;
	uint16_t rfXpdGainFixed, rfPloSel, rfPwdXpd, gainI;
	uint16_t tempOB, tempDB;
	uint32_t ob2GHz, db2GHz, rfReg[NELEM(ar5212Bank6_5111)];
	int i, regWrites = 0;

	HALDEBUG(ah, HAL_DEBUG_RFPARAM, "%s: chan %u/0x%x modesIndex %u\n",
	    __func__, chan->ic_freq, chan->ic_flags, modesIndex);

	/* Setup rf parameters */
	switch (chan->ic_flags & IEEE80211_CHAN_ALLFULL) {
	case IEEE80211_CHAN_A:
		if (4000 < freq && freq < 5260) {
			tempOB = ee->ee_ob1;
			tempDB = ee->ee_db1;
		} else if (5260 <= freq && freq < 5500) {
			tempOB = ee->ee_ob2;
			tempDB = ee->ee_db2;
		} else if (5500 <= freq && freq < 5725) {
			tempOB = ee->ee_ob3;
			tempDB = ee->ee_db3;
		} else if (freq >= 5725) {
			tempOB = ee->ee_ob4;
			tempDB = ee->ee_db4;
		} else {
			/* XXX when does this happen??? */
			tempOB = tempDB = 0;
		}
		ob2GHz = db2GHz = 0;

		rfXpdGainFixed = ee->ee_xgain[headerInfo11A];
		rfPloSel = ee->ee_xpd[headerInfo11A];
		rfPwdXpd = !ee->ee_xpd[headerInfo11A];
		gainI = ee->ee_gainI[headerInfo11A];
		break;
	case IEEE80211_CHAN_B:
		tempOB = ee->ee_obFor24;
		tempDB = ee->ee_dbFor24;
		ob2GHz = ee->ee_ob2GHz[0];
		db2GHz = ee->ee_db2GHz[0];

		rfXpdGainFixed = ee->ee_xgain[headerInfo11B];
		rfPloSel = ee->ee_xpd[headerInfo11B];
		rfPwdXpd = !ee->ee_xpd[headerInfo11B];
		gainI = ee->ee_gainI[headerInfo11B];
		break;
	case IEEE80211_CHAN_G:
	case IEEE80211_CHAN_PUREG:	/* NB: really 108G */
		tempOB = ee->ee_obFor24g;
		tempDB = ee->ee_dbFor24g;
		ob2GHz = ee->ee_ob2GHz[1];
		db2GHz = ee->ee_db2GHz[1];

		rfXpdGainFixed = ee->ee_xgain[headerInfo11G];
		rfPloSel = ee->ee_xpd[headerInfo11G];
		rfPwdXpd = !ee->ee_xpd[headerInfo11G];
		gainI = ee->ee_gainI[headerInfo11G];
		break;
	default:
		HALDEBUG(ah, HAL_DEBUG_ANY, "%s: invalid channel flags 0x%x\n",
		    __func__, chan->ic_flags);
		return AH_FALSE;
	}

	HALASSERT(1 <= tempOB && tempOB <= 5);
	HALASSERT(1 <= tempDB && tempDB <= 5);

	/* Bank 0 Write */
	for (i = 0; i < NELEM(ar5212Bank0_5111); i++)
		rfReg[i] = ar5212Bank0_5111[i][modesIndex];
	if (IEEE80211_IS_CHAN_2GHZ(chan)) {
		ar5212ModifyRfBuffer(rfReg, ob2GHz, 3, 119, 0);
		ar5212ModifyRfBuffer(rfReg, db2GHz, 3, 122, 0);
	}
	HAL_INI_WRITE_BANK(ah, ar5212Bank0_5111, rfReg, regWrites);

	/* Bank 1 Write */
	HAL_INI_WRITE_ARRAY(ah, ar5212Bank1_5111, 1, regWrites);

	/* Bank 2 Write */
	HAL_INI_WRITE_ARRAY(ah, ar5212Bank2_5111, modesIndex, regWrites);

	/* Bank 3 Write */
	HAL_INI_WRITE_ARRAY(ah, ar5212Bank3_5111, modesIndex, regWrites);

	/* Bank 6 Write */
	for (i = 0; i < NELEM(ar5212Bank6_5111); i++)
		rfReg[i] = ar5212Bank6_5111[i][modesIndex];
	if (IEEE80211_IS_CHAN_A(chan)) {	/* NB: CHANNEL_A | CHANNEL_T */
		ar5212ModifyRfBuffer(rfReg, ee->ee_cornerCal.pd84, 1, 51, 3);
		ar5212ModifyRfBuffer(rfReg, ee->ee_cornerCal.pd90, 1, 45, 3);
	}
	ar5212ModifyRfBuffer(rfReg, rfPwdXpd, 1, 95, 0);
	ar5212ModifyRfBuffer(rfReg, rfXpdGainFixed, 4, 96, 0);
	/* Set 5212 OB & DB */
	ar5212ModifyRfBuffer(rfReg, tempOB, 3, 104, 0);
	ar5212ModifyRfBuffer(rfReg, tempDB, 3, 107, 0);
	HAL_INI_WRITE_BANK(ah, ar5212Bank6_5111, rfReg, regWrites);

	/* Bank 7 Write */
	for (i = 0; i < NELEM(ar5212Bank7_5111); i++)
		rfReg[i] = ar5212Bank7_5111[i][modesIndex];
	ar5212ModifyRfBuffer(rfReg, gainI, 6, 29, 0);   
	ar5212ModifyRfBuffer(rfReg, rfPloSel, 1, 4, 0);   

	if (IEEE80211_IS_CHAN_QUARTER(chan) || IEEE80211_IS_CHAN_HALF(chan)) {
        	uint32_t	rfWaitI, rfWaitS, rfMaxTime;

        	rfWaitS = 0x1f;
        	rfWaitI = (IEEE80211_IS_CHAN_HALF(chan)) ?  0x10 : 0x1f;
        	rfMaxTime = 3;
        	ar5212ModifyRfBuffer(rfReg, rfWaitS, 5, 19, 0);
        	ar5212ModifyRfBuffer(rfReg, rfWaitI, 5, 24, 0);
        	ar5212ModifyRfBuffer(rfReg, rfMaxTime, 2, 49, 0);

	}

	HAL_INI_WRITE_BANK(ah, ar5212Bank7_5111, rfReg, regWrites);

	/* Now that we have reprogrammed rfgain value, clear the flag. */
	ahp->ah_rfgainState = HAL_RFGAIN_INACTIVE;

	return AH_TRUE;
}
Ejemplo n.º 10
0
/*
 * Take the MHz channel value and set the Channel value
 *
 * ASSUMES: Writes enabled to analog bus
 *
 * Actual Expression,
 *
 * For 2GHz channel, 
 * Channel Frequency = (3/4) * freq_ref * (chansel[8:0] + chanfrac[16:0]/2^17) 
 * (freq_ref = 40MHz)
 *
 * For 5GHz channel,
 * Channel Frequency = (3/2) * freq_ref * (chansel[8:0] + chanfrac[16:0]/2^10)
 * (freq_ref = 40MHz/(24>>amodeRefSel))
 *
 * For 5GHz channels which are 5MHz spaced,
 * Channel Frequency = (3/2) * freq_ref * (chansel[8:0] + chanfrac[16:0]/2^17)
 * (freq_ref = 40MHz)
 */
static HAL_BOOL
ar9280SetChannel(struct ath_hal *ah, const struct ieee80211_channel *chan)
{
	uint16_t bMode, fracMode, aModeRefSel = 0;
	uint32_t freq, ndiv, channelSel = 0, channelFrac = 0, reg32 = 0;
	CHAN_CENTERS centers;
	uint32_t refDivA = 24;
	uint8_t frac_n_5g;

	OS_MARK(ah, AH_MARK_SETCHANNEL, chan->ic_freq);

	ar5416GetChannelCenters(ah, chan, &centers);
	freq = centers.synth_center;

	reg32 = OS_REG_READ(ah, AR_PHY_SYNTH_CONTROL);
	reg32 &= 0xc0000000;

	if (ath_hal_eepromGet(ah, AR_EEP_FRAC_N_5G, &frac_n_5g) != HAL_OK)
		frac_n_5g = 0;

	if (freq < 4800) {     /* 2 GHz, fractional mode */
		uint32_t txctl;

		bMode = 1;
		fracMode = 1;
		aModeRefSel = 0;       
		channelSel = (freq * 0x10000)/15;

		txctl = OS_REG_READ(ah, AR_PHY_CCK_TX_CTRL);
		if (freq == 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 {
		bMode = 0;
		fracMode = 0;

		switch (frac_n_5g) {
		case 0:
			/*
			 * Enable fractional mode for half/quarter rate
			 * channels.
			 *
			 * This is from the Linux ath9k code, rather than
			 * the Atheros HAL code.
			 */
			if (IEEE80211_IS_CHAN_QUARTER(chan) ||
			    IEEE80211_IS_CHAN_HALF(chan))
				aModeRefSel = 0;
			else if ((freq % 20) == 0) {
				aModeRefSel = 3;
			} else if ((freq % 10) == 0) {
				aModeRefSel = 2;
			}
			if (aModeRefSel) break;
		case 1:
		default:
			aModeRefSel = 0;
			/* Enable 2G (fractional) mode for channels which are 5MHz spaced */

			/*
			 * Workaround for talking on PSB non-5MHz channels;
			 * the pre-Merlin chips only had a 2.5MHz channel
			 * spacing so some channels aren't reachable.

			 *
			 * This interoperates on the quarter rate channels
			 * with the AR5112 and later RF synths.  Please note
			 * that the synthesiser isn't able to completely
			 * accurately represent these frequencies (as the
			 * resolution in this reference is 2.5MHz) and thus
			 * it will be slightly "off centre."  This matches
			 * the same slightly incorrect centre frequency
			 * behaviour that the AR5112 and later channel
			 * selection code has.
			 *
			 * This also interoperates with the AR5416
			 * synthesiser modification for programming
			 * fractional frequencies in 5GHz mode.  However
			 * that modification is also disabled by default.
			 *
			 * This is disabled because it hasn't been tested for
			 * regulatory compliance and neither have the NICs
			 * which would use it.  So if you enable this code,
			 * you must first ensure that you've re-certified the
			 * NICs in question beforehand or you will be
			 * violating your local regulatory rules and breaking
			 * the law.
			 */
#if 0
			if (freq % 5 == 0) {
#endif
				/* Normal */
				fracMode = 1;
				refDivA = 1;
				channelSel = (freq * 0x8000)/15;
#if 0
			} else {
				/* Offset by 500KHz */
				uint32_t f, ch, ch2;

				fracMode = 1;
				refDivA = 1;

				/* Calculate the "adjusted" frequency */
				f = freq - 2;
				ch = (((f - 4800) * 10) / 25) + 1;

				ch2 = ((ch * 25) / 5) + 9600;
				channelSel = (ch2 * 0x4000) / 15;
				//ath_hal_printf(ah,
				//    "%s: freq=%d, ch=%d, ch2=%d, "
				//    "channelSel=%d\n",
				//    __func__, freq, ch, ch2, channelSel);
			}
#endif

			/* RefDivA setting */
			OS_A_REG_RMW_FIELD(ah, AR_AN_SYNTH9,
			    AR_AN_SYNTH9_REFDIVA, refDivA);
		}

		if (!fracMode) {
			ndiv = (freq * (refDivA >> aModeRefSel))/60;
			channelSel =  ndiv & 0x1ff;         
			channelFrac = (ndiv & 0xfffffe00) * 2;
			channelSel = (channelSel << 17) | channelFrac;
		}
	}
Ejemplo n.º 11
0
/*
 * Build the country information element.
 */
void
ieee80211_build_countryie(struct ieee80211vap *vap)
{
    struct country_ie_triplet *pTriplet;
    struct ieee80211_channel *c;
    int i, j, chanflags, chancnt, isnewband;
    u_int8_t chanlist[IEEE80211_CHAN_MAX + 1];
    u_int8_t prevchan;
    struct ieee80211com *ic = vap->iv_ic;

    if (!ic->ic_country_iso[0] || !ic->ic_country_iso[1] || !ic->ic_country_iso[2]) {
        /* Default, no country is set */
        vap->iv_country_ie_data.country_len = 0;
        IEEE80211_DISABLE_COUNTRYIE(ic);
        return;
    }

    IEEE80211_ENABLE_COUNTRYIE(ic);

    /*
     * Construct the country IE:
     * 1. The country string come first.
     * 2. Then construct the channel triplets from lowest channel to highest channel.
     * 3. If we support the regulatory domain class (802.11J)
     *    then add the class triplets before the channel triplets of each band.
     */
    OS_MEMZERO(&vap->iv_country_ie_data, sizeof(vap->iv_country_ie_data));  
    vap->iv_country_ie_data.country_id = IEEE80211_ELEMID_COUNTRY;
    vap->iv_country_ie_data.country_len = 3;

    vap->iv_country_ie_data.country_str[0] = ic->ic_country_iso[0];
    vap->iv_country_ie_data.country_str[1] = ic->ic_country_iso[1];
    vap->iv_country_ie_data.country_str[2] = ic->ic_country_iso[2];

    pTriplet = (struct country_ie_triplet*)&vap->iv_country_ie_data.country_triplet;

    if(IEEE80211_IS_CHAN_2GHZ(vap->iv_bsschan))
        chanflags = IEEE80211_CHAN_2GHZ;
    else
        chanflags = IEEE80211_CHAN_5GHZ;

    vap->iv_country_ie_chanflags = chanflags;
    OS_MEMZERO(&chanlist[0], sizeof(chanlist));
    prevchan = 0;
    chancnt = 0;
    isnewband = 1;
    ieee80211_enumerate_channels(c, ic, i) {
        /* Does channel belong to current operation mode */
        if (!(c->ic_flags & chanflags))
            continue;

        /* Skip previously reported channels */
        for (j=0; j < chancnt; j++) {
            if (c->ic_ieee == chanlist[j])
                break;
        }
    
        if (j != chancnt) /* found a match */
            continue;

        chanlist[chancnt] = c->ic_ieee;
        chancnt++;

        /* Skip turbo channels */
        if (IEEE80211_IS_CHAN_TURBO(c))
            continue;

        /* Skip half/quarter rate channels */
        if (IEEE80211_IS_CHAN_HALF(c) || 
                IEEE80211_IS_CHAN_QUARTER(c))
            continue;

        if (isnewband) {
            isnewband = 0;
        } else if ((pTriplet->maxtxpwr == c->ic_maxregpower) && (c->ic_ieee == prevchan + 1)) {
            pTriplet->nchan ++;
            prevchan = c->ic_ieee;
            continue;
        } else {
            pTriplet ++;
        }

        prevchan = c->ic_ieee;
        pTriplet->schan = c->ic_ieee;
        pTriplet->nchan = 1; /* init as 1 channel */
        pTriplet->maxtxpwr = c->ic_maxregpower;
        vap->iv_country_ie_data.country_len += 3;
    }

    /* pad */
    if (vap->iv_country_ie_data.country_len & 1) {
        vap->iv_country_ie_data.country_triplet[vap->iv_country_ie_data.country_len] = 0;
        vap->iv_country_ie_data.country_len++;
    }
}