Beispiel #1
0
int ar9003_mci_end_reset(struct ath_hw *ah, struct ath9k_channel *chan,
			 struct ath9k_hw_cal_data *caldata)
{
	struct ath9k_hw_mci *mci_hw = &ah->btcoex_hw.mci;

	if (!mci_hw->ready)
		return 0;

	if (!IS_CHAN_2GHZ(chan) || (mci_hw->bt_state != MCI_BT_SLEEP))
		goto exit;

	if (!ar9003_mci_check_int(ah, AR_MCI_INTERRUPT_RX_MSG_REMOTE_RESET) &&
	    !ar9003_mci_check_int(ah, AR_MCI_INTERRUPT_RX_MSG_REQ_WAKE))
		goto exit;

	/*
	 * BT is sleeping. Check if BT wakes up during
	 * WLAN calibration. If BT wakes up during
	 * WLAN calibration, need to go through all
	 * message exchanges again and recal.
	 */
	REG_WRITE(ah, AR_MCI_INTERRUPT_RX_MSG_RAW,
		  (AR_MCI_INTERRUPT_RX_MSG_REMOTE_RESET |
		   AR_MCI_INTERRUPT_RX_MSG_REQ_WAKE));

	ar9003_mci_remote_reset(ah, true);
	ar9003_mci_send_sys_waking(ah, true);
	udelay(1);

	if (IS_CHAN_2GHZ(chan))
		ar9003_mci_send_lna_transfer(ah, true);

	mci_hw->bt_state = MCI_BT_AWAKE;

	REG_CLR_BIT(ah, AR_PHY_TIMING4,
		    1 << AR_PHY_TIMING_CONTROL4_DO_GAIN_DC_IQ_CAL_SHIFT);

	if (caldata) {
		caldata->done_txiqcal_once = false;
		caldata->done_txclcal_once = false;
		caldata->rtt_done = false;
	}

	if (!ath9k_hw_init_cal(ah, chan))
		return -EIO;

	REG_SET_BIT(ah, AR_PHY_TIMING4,
		    1 << AR_PHY_TIMING_CONTROL4_DO_GAIN_DC_IQ_CAL_SHIFT);

exit:
	ar9003_mci_enable_interrupt(ah);
	return 0;
}
/*
 * This routine returns the index into the aniState array that
 * corresponds to the channel in *chan.  If no match is found and the
 * array is still not fully utilized, a new entry is created for the
 * channel.  We assume the attach function has already initialized the
 * ah_ani values and only the channel field needs to be set.
 */
static int
ar5212GetAniChannelIndex(struct ath_hal *ah, HAL_CHANNEL_INTERNAL *chan)
{
#define N(a)     (sizeof(a) / sizeof(a[0]))
	struct ath_hal_5212 *ahp = AH5212(ah);
	int i;

	for (i = 0; i < N(ahp->ah_ani); i++) {
		struct ar5212AniState *asp = &ahp->ah_ani[i];
		if (asp->c.channel == chan->channel)
			return i;
		if (asp->c.channel == 0) {
			asp->c.channel = chan->channel;
			asp->c.channelFlags = chan->channelFlags;
			asp->c.privFlags = chan->privFlags;
			asp->isSetup = AH_FALSE;
			if (IS_CHAN_2GHZ(chan))
				asp->params = &ahp->ah_aniParams24;
			else
				asp->params = &ahp->ah_aniParams5;
			return i;
		}
	}
	/* XXX statistic */
	HALDEBUG(ah, HAL_DEBUG_ANY,
	    "No more channel states left. Using channel 0\n");
	return 0;		/* XXX gotta return something valid */
#undef N
}
Beispiel #3
0
static void ath9k_hw_nf_sanitize(struct ath_hw *ah, s16 *nf)
{
	struct ath_common *common = ath9k_hw_common(ah);
	struct ath_nf_limits *limit;
	int i;

	if (IS_CHAN_2GHZ(ah->curchan))
		limit = &ah->nf_2g;
	else
		limit = &ah->nf_5g;

	for (i = 0; i < NUM_NF_READINGS; i++) {
		if (!nf[i])
			continue;

		ath_dbg(common, CALIBRATE,
			"NF calibrated [%s] [chain %d] is %d\n",
			(i >= 3 ? "ext" : "ctl"), i % 3, nf[i]);

		if (nf[i] > limit->max) {
			ath_dbg(common, CALIBRATE,
				"NF[%d] (%d) > MAX (%d), correcting to MAX\n",
				i, nf[i], limit->max);
			nf[i] = limit->max;
		} else if (nf[i] < limit->min) {
			ath_dbg(common, CALIBRATE,
				"NF[%d] (%d) < MIN (%d), correcting to NOM\n",
				i, nf[i], limit->min);
			nf[i] = limit->nominal;
		}
	}
}
bool ar9003_mci_start_reset(struct ath_hw *ah, struct ath9k_channel *chan)
{
	struct ath_common *common = ath9k_hw_common(ah);
	struct ath9k_hw_mci *mci_hw = &ah->btcoex_hw.mci;
	u32 payload[4] = {0, 0, 0, 0};

	ar9003_mci_2g5g_changed(ah, IS_CHAN_2GHZ(chan));

	if (mci_hw->bt_state != MCI_BT_CAL_START)
		return false;

	mci_hw->bt_state = MCI_BT_CAL;

	ar9003_mci_disable_interrupt(ah);

	MCI_GPM_SET_CAL_TYPE(payload, MCI_GPM_WLAN_CAL_GRANT);
	ar9003_mci_send_message(ah, MCI_GPM, 0, payload,
				16, true, false);

	

	if (ar9003_mci_wait_for_gpm(ah, MCI_GPM_BT_CAL_DONE,
				    0, 25000))
		ath_dbg(common, MCI, "MCI BT_CAL_DONE received\n");
	else
		ath_dbg(common, MCI,
			"MCI BT_CAL_DONE not received\n");

	mci_hw->bt_state = MCI_BT_AWAKE;
	
	ar9003_mci_enable_interrupt(ah);

	return true;
}
int ar9003_mci_end_reset(struct ath_hw *ah, struct ath9k_channel *chan,
			 struct ath9k_hw_cal_data *caldata)
{
	struct ath9k_hw_mci *mci_hw = &ah->btcoex_hw.mci;

	if (!mci_hw->ready)
		return 0;

	if (!IS_CHAN_2GHZ(chan) || (mci_hw->bt_state != MCI_BT_SLEEP))
		goto exit;

	if (ar9003_mci_check_int(ah, AR_MCI_INTERRUPT_RX_MSG_REMOTE_RESET) ||
	    ar9003_mci_check_int(ah, AR_MCI_INTERRUPT_RX_MSG_REQ_WAKE)) {

		REG_WRITE(ah, AR_MCI_INTERRUPT_RX_MSG_RAW,
			  AR_MCI_INTERRUPT_RX_MSG_REMOTE_RESET |
			  AR_MCI_INTERRUPT_RX_MSG_REQ_WAKE);

		ar9003_mci_remote_reset(ah, true);
		ar9003_mci_send_sys_waking(ah, true);
		udelay(1);

		if (IS_CHAN_2GHZ(chan))
			ar9003_mci_send_lna_transfer(ah, true);

		mci_hw->bt_state = MCI_BT_AWAKE;

		if (caldata) {
			caldata->done_txiqcal_once = false;
			caldata->done_txclcal_once = false;
			caldata->rtt_hist.num_readings = 0;
		}

		if (!ath9k_hw_init_cal(ah, chan))
			return -EIO;

	}
exit:
	ar9003_mci_enable_interrupt(ah);
	return 0;
}
Beispiel #6
0
bool ar9003_hw_rtt_restore(struct ath_hw *ah, struct ath9k_channel *chan)
{
	bool restore;

	if (!ah->caldata)
		return false;

	if (test_bit(SW_PKDET_DONE, &ah->caldata->cal_flags)) {
		if (IS_CHAN_2GHZ(chan)){
			REG_RMW_FIELD(ah, AR_PHY_65NM_RXRF_AGC(0),
				      AR_PHY_65NM_RXRF_AGC_AGC2G_CALDAC_OVR,
				      ah->caldata->caldac[0]);
			REG_RMW_FIELD(ah, AR_PHY_65NM_RXRF_AGC(1),
				      AR_PHY_65NM_RXRF_AGC_AGC2G_CALDAC_OVR,
				      ah->caldata->caldac[1]);
		} else {
			REG_RMW_FIELD(ah, AR_PHY_65NM_RXRF_AGC(0),
				      AR_PHY_65NM_RXRF_AGC_AGC5G_CALDAC_OVR,
				      ah->caldata->caldac[0]);
			REG_RMW_FIELD(ah, AR_PHY_65NM_RXRF_AGC(1),
				      AR_PHY_65NM_RXRF_AGC_AGC5G_CALDAC_OVR,
				      ah->caldata->caldac[1]);
		}
		REG_RMW_FIELD(ah, AR_PHY_65NM_RXRF_AGC(1),
			      AR_PHY_65NM_RXRF_AGC_AGC_OVERRIDE, 0x1);
		REG_RMW_FIELD(ah, AR_PHY_65NM_RXRF_AGC(0),
			      AR_PHY_65NM_RXRF_AGC_AGC_OVERRIDE, 0x1);
	}

	if (!test_bit(RTT_DONE, &ah->caldata->cal_flags))
		return false;

	ar9003_hw_rtt_enable(ah);

	if (test_bit(SW_PKDET_DONE, &ah->caldata->cal_flags))
		ar9003_hw_rtt_set_mask(ah, 0x30);
	else
		ar9003_hw_rtt_set_mask(ah, 0x10);

	if (!ath9k_hw_rfbus_req(ah)) {
		ath_err(ath9k_hw_common(ah), "Could not stop baseband\n");
		restore = false;
		goto fail;
	}

	ar9003_hw_rtt_load_hist(ah);
	restore = ar9003_hw_rtt_force_restore(ah);

fail:
	ath9k_hw_rfbus_done(ah);
	ar9003_hw_rtt_disable(ah);
	return restore;
}
Beispiel #7
0
static struct ath_nf_limits *ath9k_hw_get_nf_limits(struct ath_hw *ah,
						    struct ath9k_channel *chan)
{
	struct ath_nf_limits *limit;

	if (!chan || IS_CHAN_2GHZ(chan))
		limit = &ah->nf_2g;
	else
		limit = &ah->nf_5g;

	return limit;
}
void ath9k_hw_get_target_powers(struct ath_hw *ah,
				struct ath9k_channel *chan,
				struct cal_target_power_ht *powInfo,
				u16 numChannels,
				struct cal_target_power_ht *pNewPower,
				u16 numRates, bool isHt40Target)
{
	struct chan_centers centers;
	u16 clo, chi;
	int i;
	int matchIndex = -1, lowIndex = -1;
	u16 freq;

	ath9k_hw_get_channel_centers(ah, chan, &centers);
	freq = isHt40Target ? centers.synth_center : centers.ctl_center;

	if (freq <= ath9k_hw_fbin2freq(powInfo[0].bChannel, IS_CHAN_2GHZ(chan))) {
		matchIndex = 0;
	} else {
		for (i = 0; (i < numChannels) &&
			     (powInfo[i].bChannel != AR5416_BCHAN_UNUSED); i++) {
			if (freq == ath9k_hw_fbin2freq(powInfo[i].bChannel,
						       IS_CHAN_2GHZ(chan))) {
				matchIndex = i;
				break;
			} else
				if (freq < ath9k_hw_fbin2freq(powInfo[i].bChannel,
						IS_CHAN_2GHZ(chan)) && i > 0 &&
				    freq > ath9k_hw_fbin2freq(powInfo[i - 1].bChannel,
						IS_CHAN_2GHZ(chan))) {
					lowIndex = i - 1;
					break;
				}
		}
		if ((matchIndex == -1) && (lowIndex == -1))
			matchIndex = i - 1;
	}

	if (matchIndex != -1) {
		*pNewPower = powInfo[matchIndex];
	} else {
		clo = ath9k_hw_fbin2freq(powInfo[lowIndex].bChannel,
					 IS_CHAN_2GHZ(chan));
		chi = ath9k_hw_fbin2freq(powInfo[lowIndex + 1].bChannel,
					 IS_CHAN_2GHZ(chan));

		for (i = 0; i < numRates; i++) {
			pNewPower->tPow2x[i] = (u8)ath9k_hw_interpolate(freq,
						clo, chi,
						powInfo[lowIndex].tPow2x[i],
						powInfo[lowIndex + 1].tPow2x[i]);
		}
	}
}
static void
ar5416ForceAGCGain(struct ath_hal *ah)
{
    u_int32_t forced_gain;

    // Use the following code to force Rx gain(through BB interface) in Merlin. 
    // For 2G, set $FORCED_GAIN to 198. For 5G, set $FORCED_GAIN to 202.
    if (AH_PRIVATE(ah)->ah_curchan != NULL &&
        IS_CHAN_2GHZ(AH_PRIVATE(ah)->ah_curchan)) {
        forced_gain = FORCED_GAIN_2G;
    } else {
        forced_gain = FORCED_GAIN_5G;
    }

    OS_REG_WRITE(ah, 0x9848, OS_REG_READ(ah, 0x9848) | (0x1 << 21)); // bb_ch0_gain_force
    OS_REG_WRITE(ah, 0xa848, OS_REG_READ(ah, 0xa848) | (0x1 << 21)); // bb_ch1_gain_force
    OS_REG_WRITE(ah, 0x984c, (OS_REG_READ(ah, 0x984c) & 0x0001ffff) | (forced_gain << 17));
    OS_REG_WRITE(ah, 0xa84c, (OS_REG_READ(ah, 0xa84c) & 0x0001ffff) | (forced_gain << 17));
}
Beispiel #10
0
static int ar9002_hw_is_cal_supported(struct ath_hw *ah,
				struct ath9k_channel *chan,
				enum ar9002_cal_types cal_type)
{
	int supported = 0;
	switch (ah->supp_cals & cal_type) {
	case IQ_MISMATCH_CAL:
		/* Run IQ Mismatch for non-CCK only */
		if (!IS_CHAN_B(chan))
			supported = 1;
		break;
	case ADC_GAIN_CAL:
	case ADC_DC_CAL:
		/* Run ADC Gain Cal for non-CCK & non 2GHz-HT20 only */
		if (!IS_CHAN_B(chan) &&
		    !(IS_CHAN_2GHZ(chan) && IS_CHAN_HT20(chan)))
			supported = 1;
		break;
	}
	return supported;
}
bool ar9003_mci_start_reset(struct ath_hw *ah, struct ath9k_channel *chan)
{
	struct ath_common *common = ath9k_hw_common(ah);
	struct ath9k_hw_mci *mci_hw = &ah->btcoex_hw.mci;
	u32 payload[4] = {0, 0, 0, 0};

	ar9003_mci_2g5g_changed(ah, IS_CHAN_2GHZ(chan));

	if (mci_hw->bt_state != MCI_BT_CAL_START)
		return false;

	mci_hw->bt_state = MCI_BT_CAL;

	/*
	 * MCI FIX: disable mci interrupt here. This is to avoid
	 * SW_MSG_DONE or RX_MSG bits to trigger MCI_INT and
	 * lead to mci_intr reentry.
	 */
	ar9003_mci_disable_interrupt(ah);

	MCI_GPM_SET_CAL_TYPE(payload, MCI_GPM_WLAN_CAL_GRANT);
	ar9003_mci_send_message(ah, MCI_GPM, 0, payload,
				16, true, false);

	/* Wait BT calibration to be completed for 25ms */

	if (ar9003_mci_wait_for_gpm(ah, MCI_GPM_BT_CAL_DONE,
				    0, 25000))
		ath_dbg(common, MCI, "MCI BT_CAL_DONE received\n");
	else
		ath_dbg(common, MCI,
			"MCI BT_CAL_DONE not received\n");

	mci_hw->bt_state = MCI_BT_AWAKE;
	/* MCI FIX: enable mci interrupt here */
	ar9003_mci_enable_interrupt(ah);

	return true;
}
Beispiel #12
0
static bool ath9k_hw_iscal_supported(struct ath_hal *ah,
				     struct ath9k_channel *chan,
				     enum hal_cal_types calType)
{
	struct ath_hal_5416 *ahp = AH5416(ah);
	bool retval = false;

	switch (calType & ahp->ah_suppCals) {
	case IQ_MISMATCH_CAL:
		if (!IS_CHAN_B(chan))
			retval = true;
		break;
	case ADC_GAIN_CAL:
	case ADC_DC_CAL:
		if (!IS_CHAN_B(chan)
		    && !(IS_CHAN_2GHZ(chan) && IS_CHAN_HT20(chan)))
			retval = true;
		break;
	}

	return retval;
}
Beispiel #13
0
/*
 * Restore the ANI parameters in the HAL and reset the statistics.
 * This routine should be called for every hardware reset and for
 * every channel change.
 */
void
ar9300_ani_reset(struct ath_hal *ah, HAL_BOOL is_scanning)
{
    struct ath_hal_9300 *ahp = AH9300(ah);
    struct ar9300_ani_state *ani_state;
    const struct ieee80211_channel *chan = AH_PRIVATE(ah)->ah_curchan;
    HAL_CHANNEL_INTERNAL *ichan = ath_hal_checkchannel(ah, chan);
    int index;

    HALASSERT(chan != AH_NULL);

    if (!DO_ANI(ah)) {
        return;
    }

    /*
     * we need to re-point to the correct ANI state since the channel
     * may have changed due to a fast channel change
    */
    index = ar9300_get_ani_channel_index(ah, chan);
    ani_state = &ahp->ah_ani[index];
    HALASSERT(ani_state != AH_NULL);
    ahp->ah_curani = ani_state;

    ahp->ah_stats.ast_ani_reset++;

    ani_state->phy_noise_spur = 0;

    /* only allow a subset of functions in AP mode */
    if (AH_PRIVATE(ah)->ah_opmode == HAL_M_HOSTAP) {
        if (IS_CHAN_2GHZ(ichan)) {
            ahp->ah_ani_function = (HAL_ANI_SPUR_IMMUNITY_LEVEL |
                                    HAL_ANI_FIRSTEP_LEVEL |
                                    HAL_ANI_MRC_CCK);
        } else {
            ahp->ah_ani_function = 0;
        }
    }
    /* always allow mode (on/off) to be controlled */
    ahp->ah_ani_function |= HAL_ANI_MODE;

    if (is_scanning ||
        (AH_PRIVATE(ah)->ah_opmode != HAL_M_STA &&
         AH_PRIVATE(ah)->ah_opmode != HAL_M_IBSS))
    {
        /*
         * If we're scanning or in AP mode, the defaults (ini) should be
         * in place.
         * For an AP we assume the historical levels for this channel are
         * probably outdated so start from defaults instead.
         */
        if (ani_state->ofdm_noise_immunity_level != HAL_ANI_OFDM_DEF_LEVEL ||
            ani_state->cck_noise_immunity_level != HAL_ANI_CCK_DEF_LEVEL)
        {
            HALDEBUG(ah, HAL_DEBUG_ANI,
                "%s: Restore defaults: opmode %u chan %d Mhz/0x%x "
                "is_scanning=%d restore=%d ofdm:%d cck:%d\n",
                __func__, AH_PRIVATE(ah)->ah_opmode, chan->ic_freq,
                chan->ic_flags, is_scanning, ani_state->must_restore,
                ani_state->ofdm_noise_immunity_level,
                ani_state->cck_noise_immunity_level);
            /*
             * for STA/IBSS, we want to restore the historical values later
             * (when we're not scanning)
             */
            if (AH_PRIVATE(ah)->ah_opmode == HAL_M_STA ||
                AH_PRIVATE(ah)->ah_opmode == HAL_M_IBSS)
            {
                ar9300_ani_control(ah, HAL_ANI_SPUR_IMMUNITY_LEVEL,
                    HAL_ANI_DEF_SPUR_IMMUNE_LVL);
                ar9300_ani_control(
                    ah, HAL_ANI_FIRSTEP_LEVEL, HAL_ANI_DEF_FIRSTEP_LVL);
                ar9300_ani_control(ah, HAL_ANI_OFDM_WEAK_SIGNAL_DETECTION,
                    HAL_ANI_USE_OFDM_WEAK_SIG);
                ar9300_ani_control(ah, HAL_ANI_MRC_CCK, HAL_ANI_ENABLE_MRC_CCK);
                ani_state->must_restore = AH_TRUE;
            } else {
                ar9300_ani_set_odfm_noise_immunity_level(
                    ah, HAL_ANI_OFDM_DEF_LEVEL);
                ar9300_ani_set_cck_noise_immunity_level(
                    ah, HAL_ANI_CCK_DEF_LEVEL);
            }
        }
    } else {
        /*
         * restore historical levels for this channel
         */
        HALDEBUG(ah, HAL_DEBUG_ANI,
            "%s: Restore history: opmode %u chan %d Mhz/0x%x is_scanning=%d "
            "restore=%d ofdm:%d cck:%d\n",
            __func__, AH_PRIVATE(ah)->ah_opmode, chan->ic_freq,
            chan->ic_flags, is_scanning, ani_state->must_restore,
            ani_state->ofdm_noise_immunity_level,
            ani_state->cck_noise_immunity_level);
        ar9300_ani_set_odfm_noise_immunity_level(
            ah, ani_state->ofdm_noise_immunity_level);
        ar9300_ani_set_cck_noise_immunity_level(
            ah, ani_state->cck_noise_immunity_level);
        ani_state->must_restore = AH_FALSE;
    }

    /* enable phy counters */
    ar9300_ani_restart(ah);
    OS_REG_WRITE(ah, AR_PHY_ERR_MASK_1, AR_PHY_ERR_OFDM_TIMING);
    OS_REG_WRITE(ah, AR_PHY_ERR_MASK_2, AR_PHY_ERR_CCK_TIMING);
}
Beispiel #14
0
/*
 * Take the MHz channel value and set the Channel value
 *
 * ASSUMES: Writes enabled to analog bus
 */
static HAL_BOOL
ar5111SetChannel(struct ath_hal *ah,  HAL_CHANNEL_INTERNAL *chan)
{
#define CI_2GHZ_INDEX_CORRECTION 19
	u_int32_t refClk, reg32, data2111;
	int16_t chan5111, chanIEEE;

	/*
	 * Structure to hold 11b tuning information for 5111/2111
	 * 16 MHz mode, divider ratio = 198 = NP+S. N=16, S=4 or 6, P=12
	 */
	typedef struct {
		u_int32_t	refClkSel;	/* reference clock, 1 for 16 MHz */
		u_int32_t	channelSelect;	/* P[7:4]S[3:0] bits */
		u_int16_t	channel5111;	/* 11a channel for 5111 */
	} CHAN_INFO_2GHZ;

	const static CHAN_INFO_2GHZ chan2GHzData[] = {
		{ 1, 0x46, 96  },	/* 2312 -19 */
		{ 1, 0x46, 97  },	/* 2317 -18 */
		{ 1, 0x46, 98  },	/* 2322 -17 */
		{ 1, 0x46, 99  },	/* 2327 -16 */
		{ 1, 0x46, 100 },	/* 2332 -15 */
		{ 1, 0x46, 101 },	/* 2337 -14 */
		{ 1, 0x46, 102 },	/* 2342 -13 */
		{ 1, 0x46, 103 },	/* 2347 -12 */
		{ 1, 0x46, 104 },	/* 2352 -11 */
		{ 1, 0x46, 105 },	/* 2357 -10 */
		{ 1, 0x46, 106 },	/* 2362  -9 */
		{ 1, 0x46, 107 },	/* 2367  -8 */
		{ 1, 0x46, 108 },	/* 2372  -7 */
		/* index -6 to 0 are pad to make this a nolookup table */
		{ 1, 0x46, 116 },	/*       -6 */
		{ 1, 0x46, 116 },	/*       -5 */
		{ 1, 0x46, 116 },	/*       -4 */
		{ 1, 0x46, 116 },	/*       -3 */
		{ 1, 0x46, 116 },	/*       -2 */
		{ 1, 0x46, 116 },	/*       -1 */
		{ 1, 0x46, 116 },	/*        0 */
		{ 1, 0x46, 116 },	/* 2412   1 */
		{ 1, 0x46, 117 },	/* 2417   2 */
		{ 1, 0x46, 118 },	/* 2422   3 */
		{ 1, 0x46, 119 },	/* 2427   4 */
		{ 1, 0x46, 120 },	/* 2432   5 */
		{ 1, 0x46, 121 },	/* 2437   6 */
		{ 1, 0x46, 122 },	/* 2442   7 */
		{ 1, 0x46, 123 },	/* 2447   8 */
		{ 1, 0x46, 124 },	/* 2452   9 */
		{ 1, 0x46, 125 },	/* 2457  10 */
		{ 1, 0x46, 126 },	/* 2462  11 */
		{ 1, 0x46, 127 },	/* 2467  12 */
		{ 1, 0x46, 128 },	/* 2472  13 */
		{ 1, 0x44, 124 },	/* 2484  14 */
		{ 1, 0x46, 136 },	/* 2512  15 */
		{ 1, 0x46, 140 },	/* 2532  16 */
		{ 1, 0x46, 144 },	/* 2552  17 */
		{ 1, 0x46, 148 },	/* 2572  18 */
		{ 1, 0x46, 152 },	/* 2592  19 */
		{ 1, 0x46, 156 },	/* 2612  20 */
		{ 1, 0x46, 160 },	/* 2632  21 */
		{ 1, 0x46, 164 },	/* 2652  22 */
		{ 1, 0x46, 168 },	/* 2672  23 */
		{ 1, 0x46, 172 },	/* 2692  24 */
		{ 1, 0x46, 176 },	/* 2712  25 */
		{ 1, 0x46, 180 } 	/* 2732  26 */
	};

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

	chanIEEE = ath_hal_mhz2ieee(ah, chan->channel, chan->channelFlags);
	if (IS_CHAN_2GHZ(chan)) {
		const CHAN_INFO_2GHZ* ci =
			&chan2GHzData[chanIEEE + CI_2GHZ_INDEX_CORRECTION];
		u_int32_t txctl;

		data2111 = ((ath_hal_reverseBits(ci->channelSelect, 8) & 0xff)
				<< 5)
			 | (ci->refClkSel << 4);
		chan5111 = ci->channel5111;
		txctl = OS_REG_READ(ah, AR_PHY_CCK_TX_CTRL);
		if (chan->channel == 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 {
		chan5111 = chanIEEE;	/* no conversion needed */
		data2111 = 0;
	}

	/* Rest of the code is common for 5 GHz and 2.4 GHz. */
	if (chan5111 >= 145 || (chan5111 & 0x1)) {
		reg32  = ath_hal_reverseBits(chan5111 - 24, 8) & 0xff;
		refClk = 1;
	} else {
		reg32  = ath_hal_reverseBits(((chan5111 - 24)/2), 8) & 0xff;
		refClk = 0;
	}

	reg32 = (reg32 << 2) | (refClk << 1) | (1 << 10) | 0x1;
	OS_REG_WRITE(ah, AR_PHY(0x27), ((data2111 & 0xff) << 8) | (reg32 & 0xff));
	reg32 >>= 8;
	OS_REG_WRITE(ah, AR_PHY(0x34), (data2111 & 0xff00) | (reg32 & 0xff));

	AH_PRIVATE(ah)->ah_curchan = chan;

#ifdef AH_SUPPORT_DFS
	if (chan->privFlags & CHANNEL_DFS) {
		struct ar5212RadarState *rs;
		u_int8_t index;

		rs = ar5212GetRadarChanState(ah, &index);
		if (rs != AH_NULL) {
			AH5212(ah)->ah_curchanRadIndex = (int16_t) index;
		} else {
			HDPRINTF(ah, HAL_DBG_DFS, "%s: Couldn't find radar state information\n",
				 __func__);
			return AH_FALSE;
		}
	} else
#endif
		AH5212(ah)->ah_curchanRadIndex = -1;
	return AH_TRUE;
#undef CI_2GHZ_INDEX_CORRECTION
}
Beispiel #15
0
/*
 * Restore the ANI parameters in the HAL and reset the statistics.
 * This routine should be called for every hardware reset and for
 * every channel change.
 */
void ath9k_ani_reset(struct ath_hw *ah, bool is_scanning)
{
	struct ar5416AniState *aniState = &ah->curchan->ani;
	struct ath9k_channel *chan = ah->curchan;
	struct ath_common *common = ath9k_hw_common(ah);

	if (!DO_ANI(ah))
		return;

	if (!use_new_ani(ah))
		return ath9k_ani_reset_old(ah, is_scanning);

	BUG_ON(aniState == NULL);
	ah->stats.ast_ani_reset++;

	/* only allow a subset of functions in AP mode */
	if (ah->opmode == NL80211_IFTYPE_AP) {
		if (IS_CHAN_2GHZ(chan)) {
			ah->ani_function = (ATH9K_ANI_SPUR_IMMUNITY_LEVEL |
					    ATH9K_ANI_FIRSTEP_LEVEL);
			if (AR_SREV_9300_20_OR_LATER(ah))
				ah->ani_function |= ATH9K_ANI_MRC_CCK;
		} else
			ah->ani_function = 0;
	}

	/* always allow mode (on/off) to be controlled */
	ah->ani_function |= ATH9K_ANI_MODE;

	if (is_scanning ||
	    (ah->opmode != NL80211_IFTYPE_STATION &&
	     ah->opmode != NL80211_IFTYPE_ADHOC)) {
		/*
		 * If we're scanning or in AP mode, the defaults (ini)
		 * should be in place. For an AP we assume the historical
		 * levels for this channel are probably outdated so start
		 * from defaults instead.
		 */
		if (aniState->ofdmNoiseImmunityLevel !=
		    ATH9K_ANI_OFDM_DEF_LEVEL ||
		    aniState->cckNoiseImmunityLevel !=
		    ATH9K_ANI_CCK_DEF_LEVEL) {
			ath_dbg(common, ATH_DBG_ANI,
				"Restore defaults: opmode %u chan %d Mhz/0x%x is_scanning=%d ofdm:%d cck:%d\n",
				ah->opmode,
				chan->channel,
				chan->channelFlags,
				is_scanning,
				aniState->ofdmNoiseImmunityLevel,
				aniState->cckNoiseImmunityLevel);

			aniState->update_ani = false;
			ath9k_hw_set_ofdm_nil(ah, ATH9K_ANI_OFDM_DEF_LEVEL);
			ath9k_hw_set_cck_nil(ah, ATH9K_ANI_CCK_DEF_LEVEL);
		}
	} else {
		/*
		 * restore historical levels for this channel
		 */
		ath_dbg(common, ATH_DBG_ANI,
			"Restore history: opmode %u chan %d Mhz/0x%x is_scanning=%d ofdm:%d cck:%d\n",
			ah->opmode,
			chan->channel,
			chan->channelFlags,
			is_scanning,
			aniState->ofdmNoiseImmunityLevel,
			aniState->cckNoiseImmunityLevel);

			aniState->update_ani = true;
			ath9k_hw_set_ofdm_nil(ah,
					      aniState->ofdmNoiseImmunityLevel);
			ath9k_hw_set_cck_nil(ah,
					     aniState->cckNoiseImmunityLevel);
	}

	/*
	 * enable phy counters if hw supports or if not, enable phy
	 * interrupts (so we can count each one)
	 */
	ath9k_ani_restart(ah);

	ENABLE_REGWRITE_BUFFER(ah);

	REG_WRITE(ah, AR_PHY_ERR_MASK_1, AR_PHY_ERR_OFDM_TIMING);
	REG_WRITE(ah, AR_PHY_ERR_MASK_2, AR_PHY_ERR_CCK_TIMING);

	REGWRITE_BUFFER_FLUSH(ah);
}
Beispiel #16
0
/**************************************************************
 * ar5416GetTargetPowersLeg
 *
 * Return the four rates of target power for the given target power table
 * channel, and number of channels
 */
void
ar5416GetTargetPowersLeg(struct ath_hal *ah,
    HAL_CHANNEL_INTERNAL *chan,
    CAL_TARGET_POWER_LEG *powInfo, u_int16_t numChannels,
    CAL_TARGET_POWER_LEG *pNewPower, u_int16_t numRates,
    HAL_BOOL isExtTarget)
{
    u_int16_t clo, chi;
    int i;
    int matchIndex = -1, lowIndex = -1;
    u_int16_t freq;
    CHAN_CENTERS centers;

    ar5416GetChannelCenters(ah, chan, &centers);
    freq = (isExtTarget) ? centers.ext_center : centers.ctl_center;

    /* Copy the target powers into the temp channel list */
    if (freq <= fbin2freq(powInfo[0].bChannel, IS_CHAN_2GHZ(chan)))
    {
        matchIndex = 0;
    }
    else
    {
        for (i = 0; (i < numChannels) && (powInfo[i].bChannel != AR5416_BCHAN_UNUSED); i++)
        {
            if (freq == fbin2freq(powInfo[i].bChannel, IS_CHAN_2GHZ(chan)))
            {
                matchIndex = i;
                break;
            }
            else if ((freq < fbin2freq(powInfo[i].bChannel, IS_CHAN_2GHZ(chan))) &&
                (freq > fbin2freq(powInfo[i - 1].bChannel, IS_CHAN_2GHZ(chan))))
            {
                lowIndex = i - 1;
                break;
            }
        }
        if ((matchIndex == -1) && (lowIndex == -1))
        {
            HALASSERT(freq > fbin2freq(powInfo[i - 1].bChannel, IS_CHAN_2GHZ(chan)));
            matchIndex = i - 1;
        }
    }

    if (matchIndex != -1)
    {
        *pNewPower = powInfo[matchIndex];
    }
    else
    {
        HALASSERT(lowIndex != -1);
        /*
        * Get the lower and upper channels, target powers,
        * and interpolate between them.
        */
        clo = fbin2freq(powInfo[lowIndex].bChannel, IS_CHAN_2GHZ(chan));
        chi = fbin2freq(powInfo[lowIndex + 1].bChannel, IS_CHAN_2GHZ(chan));

        for (i = 0; i < numRates; i++)
        {
            pNewPower->tPow2x[i] = (u_int8_t)interpolate(freq, clo, chi,
                powInfo[lowIndex].tPow2x[i], powInfo[lowIndex + 1].tPow2x[i]);
        }
    }
}
Beispiel #17
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, HAL_CHANNEL_INTERNAL *chan,
	u_int16_t modesIndex, u_int16_t *rfXpdGain)
{
	struct ath_hal_5212 *ahp = AH5212(ah);
	u_int16_t rfXpdGainFixed, rfPloSel, rfPwdXpd, gainI;
	u_int16_t tempOB, tempDB;
	u_int32_t ob2GHz, db2GHz, rfReg[N(ar5212Bank6_5111)];
	int i, regWrites = 0;

	/* Setup rf parameters */
	switch (chan->channelFlags & CHANNEL_ALL) {
	case CHANNEL_A:
	case CHANNEL_T:
		if (4000 < chan->channel && chan->channel < 5260) {
			tempOB = ahp->ah_ob1;
			tempDB = ahp->ah_db1;
		} else if (5260 <= chan->channel && chan->channel < 5500) {
			tempOB = ahp->ah_ob2;
			tempDB = ahp->ah_db2;
		} else if (5500 <= chan->channel && chan->channel < 5725) {
			tempOB = ahp->ah_ob3;
			tempDB = ahp->ah_db3;
		} else if (chan->channel >= 5725) {
			tempOB = ahp->ah_ob4;
			tempDB = ahp->ah_db4;
		} else {
			/* XXX when does this happen??? */
			tempOB = tempDB = 0;
		}
		ob2GHz = db2GHz = 0;

		rfXpdGainFixed = ahp->ah_xgain[headerInfo11A];
		rfPloSel = ahp->ah_xpd[headerInfo11A];
		rfPwdXpd = !ahp->ah_xpd[headerInfo11A];
		gainI = ahp->ah_gainI[headerInfo11A];
		break;
	case CHANNEL_B:
		tempOB = ahp->ah_obFor24;
		tempDB = ahp->ah_dbFor24;
		ob2GHz = ahp->ah_ob2GHz[0];
		db2GHz = ahp->ah_db2GHz[0];

		rfXpdGainFixed = ahp->ah_xgain[headerInfo11B];
		rfPloSel = ahp->ah_xpd[headerInfo11B];
		rfPwdXpd = !ahp->ah_xpd[headerInfo11B];
		gainI = ahp->ah_gainI[headerInfo11B];
		break;
	case CHANNEL_G:
		tempOB = ahp->ah_obFor24g;
		tempDB = ahp->ah_dbFor24g;
		ob2GHz = ahp->ah_ob2GHz[1];
		db2GHz = ahp->ah_db2GHz[1];

		rfXpdGainFixed = ahp->ah_xgain[headerInfo11G];
		rfPloSel = ahp->ah_xpd[headerInfo11G];
		rfPwdXpd = !ahp->ah_xpd[headerInfo11G];
		gainI = ahp->ah_gainI[headerInfo11G];
		break;
	default:
		HDPRINTF(ah, HAL_DBG_CHANNEL, "%s: invalid channel flags 0x%x\n",
			__func__, chan->channelFlags);
		return AH_FALSE;
	}

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

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

	/* Bank 1 Write */
	REG_WRITE_ARRAY(ar5212Bank1_5111, 1, regWrites);

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

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

	/* Bank 6 Write */
	for (i = 0; i < N(ar5212Bank6_5111); i++)
		rfReg[i] = ar5212Bank6_5111[i][modesIndex];
	if (IS_CHAN_A(chan)) {		/* NB: CHANNEL_A | CHANNEL_T */
		ar5212ModifyRfBuffer(rfReg, ahp->ah_cornerCal.pd84, 1, 51, 3);
		ar5212ModifyRfBuffer(rfReg, ahp->ah_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);
	for (i = 0; i < N(ar5212Bank6_5111); i++) {
		OS_REG_WRITE(ah, ar5212Bank6_5111[i][0], rfReg[i]);
		ALLOW_DMA_READ_COMPLETE(regWrites);
	}

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

	if (IS_CHAN_QUARTER_RATE(chan) || IS_CHAN_HALF_RATE(chan)) {
        	u_int32_t	rfWaitI, rfWaitS, rfMaxTime;

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

	}

	for (i = 0; i < N(ar5212Bank7_5111); i++) {
		OS_REG_WRITE(ah, ar5212Bank7_5111[i][0], rfReg[i]);
		ALLOW_DMA_READ_COMPLETE(regWrites);
	}

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

	return AH_TRUE;
}
Beispiel #18
0
static void
ar9300_force_agc_gain(struct ath_hal *ah)
{
    struct ath_hal_9300 *ahp = AH9300(ah);
    int i;
    static const struct {
        int rxtx1, rxtx2;
    } chn_reg[AR9300_MAX_CHAINS] = {
        {AR_PHY_65NM_CH0_RXTX1, AR_PHY_65NM_CH0_RXTX2},
        {AR_PHY_65NM_CH1_RXTX1, AR_PHY_65NM_CH1_RXTX2},
        {AR_PHY_65NM_CH2_RXTX1, AR_PHY_65NM_CH2_RXTX2}
    };
    /* 
     * for Osprey 1.0, force Rx gain through long shift (analog) interface
     * this works for Osprey 2.0 too
     * TODO: for Osprey 2.0, we can set gain via baseband registers 
     */
    for (i = 0; i < AR9300_MAX_CHAINS; i++) {
        if (ahp->ah_rx_chainmask & (1 << i)) {
            if (AH_PRIVATE(ah)->ah_curchan != NULL &&
                IS_CHAN_2GHZ(AH_PRIVATE(ah)->ah_curchan)) 
            {
                // For 2G band:
                OS_REG_RMW_FIELD(ah, chn_reg[i].rxtx2, 
                    AR_PHY_RX1DB_BIQUAD_LONG_SHIFT, 0x1);  // 10db=3
                OS_REG_RMW_FIELD(ah, chn_reg[i].rxtx2, 
                    AR_PHY_RX6DB_BIQUAD_LONG_SHIFT, 0x2);  // 10db=2
                OS_REG_RMW_FIELD(ah, chn_reg[i].rxtx2, 
                    AR_PHY_LNAGAIN_LONG_SHIFT,      0x7);  // 10db=6
                OS_REG_RMW_FIELD(ah, chn_reg[i].rxtx2, 
                    AR_PHY_MXRGAIN_LONG_SHIFT,      0x3);  // 10db=3
                OS_REG_RMW_FIELD(ah, chn_reg[i].rxtx2, 
                    AR_PHY_VGAGAIN_LONG_SHIFT,      0x0);  // 10db=0
                OS_REG_RMW_FIELD(ah, chn_reg[i].rxtx1, 
                    AR_PHY_SCFIR_GAIN_LONG_SHIFT,   0x1);  // 10db=1
                OS_REG_RMW_FIELD(ah, chn_reg[i].rxtx1, 
                    AR_PHY_MANRXGAIN_LONG_SHIFT,    0x1);  // 10db=1
                /* force external LNA on to disable strong signal mechanism */
                OS_REG_RMW_FIELD(ah, AR_PHY_SWITCH_CHAIN(i), 
                    AR_PHY_SWITCH_TABLE_R0,  0x1); 
                OS_REG_RMW_FIELD(ah, AR_PHY_SWITCH_CHAIN(i), 
                    AR_PHY_SWITCH_TABLE_R1,  0x1); 
                OS_REG_RMW_FIELD(ah, AR_PHY_SWITCH_CHAIN(i), 
                    AR_PHY_SWITCH_TABLE_R12, 0x1); 
            } else {
                // For 5G band:
                OS_REG_RMW_FIELD(ah, chn_reg[i].rxtx2, 
                    AR_PHY_RX1DB_BIQUAD_LONG_SHIFT, 0x2); // was 3=10/15db,
                                                          // 2=+1db
                OS_REG_RMW_FIELD(ah, chn_reg[i].rxtx2, 
                    AR_PHY_RX6DB_BIQUAD_LONG_SHIFT, 0x2); // was 1
                OS_REG_RMW_FIELD(ah, chn_reg[i].rxtx2, 
                    AR_PHY_LNAGAIN_LONG_SHIFT,      0x7);
                OS_REG_RMW_FIELD(ah, chn_reg[i].rxtx2, 
                    AR_PHY_MXRGAIN_LONG_SHIFT,      0x3); // was 2=15db, 3=10db
                OS_REG_RMW_FIELD(ah, chn_reg[i].rxtx2, 
                    AR_PHY_VGAGAIN_LONG_SHIFT,      0x6);
                OS_REG_RMW_FIELD(ah, chn_reg[i].rxtx1, 
                    AR_PHY_SCFIR_GAIN_LONG_SHIFT,   0x1);
                OS_REG_RMW_FIELD(ah, chn_reg[i].rxtx1, 
                    AR_PHY_MANRXGAIN_LONG_SHIFT,    0x1);
                /* force external LNA on to disable strong signal mechanism */
                OS_REG_RMW_FIELD(ah, AR_PHY_SWITCH_CHAIN(i), 
                    AR_PHY_SWITCH_TABLE_R0,  0x0); 
                OS_REG_RMW_FIELD(ah, AR_PHY_SWITCH_CHAIN(i), 
                    AR_PHY_SWITCH_TABLE_R1,  0x0); 
                OS_REG_RMW_FIELD(ah, AR_PHY_SWITCH_CHAIN(i), 
                    AR_PHY_SWITCH_TABLE_R12, 0x0); 
            }
        }
    }
}
Beispiel #19
0
/*
 * Return the next series 0 transmit rate and setup for a callback
 * to install the multi-rate transmit data if appropriate.  We cannot
 * install the multi-rate transmit data here because the caller is
 * going to initialize the tx descriptor and so would clobber whatever
 * we write. Note that we choose an arbitrary series 0 try count to
 * insure we get called back; this permits us to defer calculating
 * the actual number of tries until the callback at which time we
 * can just copy the pre-calculated series data.
 */
void
ath_rate_findrate(struct ath_softc *sc, struct ath_node *an,
                  int shortPreamble, u_int32_t frameLen, int numTries,
                  unsigned int rcflag, u_int8_t ac, struct ath_rc_series rcs[],
                  int *isProbe, int isretry,u_int32_t bf_flags)
{
    struct atheros_node *oan = an->an_rc_node;
    struct atheros_softc *asc = oan->asc;
    struct atheros_vap *avap = oan->avp;
    struct ath_vap *avp = oan->avp->athdev_vap;
    const RATE_TABLE *pRateTable = avap->rateTable;
    u_int8_t *retrySched;
    int       i;
    u_int8_t fixedratecode;
    u_int32_t old_av_fixed_rateset;
    u_int32_t old_av_fixed_retryset;

    ASSERT(rcs != NULL);

    if (sc->sc_ah->ah_magic == 0x19641014 ||
        sc->sc_ah->ah_magic == 0x19741014)
    {
#ifdef ATH_SUPPORT_TxBF     // set calibration and sounding indicator
#define MS(_v, _f)  (((_v) & _f) >> _f##_S)
        sc->sc_txbfsounding = 0;
        oan->txbf_sounding = 0;
        sc->sc_txbfcalibrating = 0;
        if ((MS(bf_flags,HAL_TXDESC_TXBF_SOUND)==HAL_TXDESC_STAG_SOUND)
            ||(MS(bf_flags,HAL_TXDESC_TXBF_SOUND)== HAL_TXDESC_SOUND)){
            sc->sc_txbfsounding = 1;
            oan->txbf_sounding = 1;
        }            
        if (bf_flags & HAL_TXDESC_CAL) {
            sc->sc_txbfcalibrating = 1;
        }
#endif
        /* store the previous values */
        old_av_fixed_rateset = avp->av_config.av_fixed_rateset;
        old_av_fixed_retryset = avp->av_config.av_fixed_retryset;

        /* If fixed node rate is enabled, we fixed the link rate */
        if (an->an_fixedrate_enable) {
            fixedratecode = an->an_fixedratecode;
            avp->av_config.av_fixed_rateset = 0;
            for (i=0; i<4; i++) {
                avp->av_config.av_fixed_rateset <<= 8;
                avp->av_config.av_fixed_rateset |= fixedratecode; 
            }
            avp->av_config.av_fixed_retryset = 0x03030303;
        }

            ath_rate_findrate_11n(sc, an, frameLen, numTries, 4,
                                  rcflag, ac, rcs, isProbe, isretry);

        /* restore the previous values */
        avp->av_config.av_fixed_rateset = old_av_fixed_rateset;
        avp->av_config.av_fixed_retryset = old_av_fixed_retryset;
            return;
    }

    if (asc->fixedrix == IEEE80211_FIXED_RATE_NONE) {
        rcs[0].rix = rcRateFind(sc, oan, frameLen, pRateTable, &sc->sc_curchan, isretry);
	/* multi-rate support implied */
        rcs[0].tries = ATH_TXMAXTRY-1;	/* anything != ATH_TXMAXTRY */
    } else {
        rcs[0].rix = asc->fixedrix;
        rcs[0].tries = ATH_TXMAXTRY;
    }

    /* If fixed node rate is enabled, we fixed the link rate */
    if (an->an_fixedrate_enable) {
        rcs[0].rix = an->an_fixedrix;
        rcs[0].tries = ATH_TXMAXTRY;
    }

    ASSERT(rcs[0].rix != (u_int8_t)-1);
    /* get the corresponding index for the choosen rate in txRateCtrl */
    for (i = 0; oan->txRateCtrl.validRateIndex[i] != rcs[0].rix 
       && i < oan->txRateCtrl.maxValidRate ; i++);

    ASSERT(asc->fixedrix != IEEE80211_FIXED_RATE_NONE || i != oan->txRateCtrl.maxValidRate);

    if (rcs[0].tries != ATH_TXMAXTRY) {

        /* NB: only called for data frames */
        if (oan->txRateCtrl.probeRate) {
            retrySched = shortPreamble ?
                (u_int8_t *)&(oan->txRateCtrl.validRateSeries[i][24]) :
                (u_int8_t *)&(oan->txRateCtrl.validRateSeries[i][16]);
        } else {
            retrySched = shortPreamble ?
                (u_int8_t *)&(oan->txRateCtrl.validRateSeries[i][8]) :
                (u_int8_t *)&(oan->txRateCtrl.validRateSeries[i][0]);
        }
#ifdef ATH_SUPPORT_UAPSD_RATE_CONTROL
        if (oan->uapsd) {
            retrySched = shortPreamble ?
                (u_int8_t *)&(oan->txRateCtrl.validRateSeries[i][40]) :
                (u_int8_t *)&(oan->txRateCtrl.validRateSeries[i][32]);
        }
#endif /* ATH_SUPPORT_UAPSD_RATE_CONTROL */
        /* Update rate seies based on retry schedule */
        rcs[0].tries = retrySched[0];
        rcs[1].tries = retrySched[1];
        rcs[2].tries = retrySched[2];
        rcs[3].tries = retrySched[3];
        
        if (!IS_CHAN_TURBO(&sc->sc_curchan))
            ASSERT(rcs[0].rix == pRateTable->rateCodeToIndex[retrySched[4]]);

        /* 
         * Retry scheduler assumes that all the rates below max rate in the
         * intersection rate table are present and so it takes the next possible
         * lower rates for the retries, which is not correct. So check them
         * before filling the retry rates.
         */
        rcs[1].rix = pRateTable->rateCodeToIndex[retrySched[5]];
        rcs[2].rix = pRateTable->rateCodeToIndex[retrySched[6]];
        rcs[3].rix = pRateTable->rateCodeToIndex[retrySched[7]];

        if (sc->sc_curchan.privFlags & CHANNEL_4MS_LIMIT) {
            u_int32_t  prevrix = rcs[0].rix;

            for (i=1; i<4; i++) {
                if (rcs[i].tries) {
                    if (pRateTable->info[rcs[i].rix].max4msFrameLen < frameLen) {
                        rcs[i].rix = prevrix;
                    } else {
                        prevrix = rcs[i].rix;
                    }
                } else {
                    /* Retries are 0 from here */
                    break;
                }
            }
        }

    }

    if (sc->sc_ieee_ops->update_txrate) {
        sc->sc_ieee_ops->update_txrate(an->an_node, oan->rixMap[rcs[0].rix]);
    }
    
#if ATH_SUPERG_DYNTURBO
    /* XXX map from merged table to split for driver */
    if (IS_CHAN_TURBO(&sc->sc_curchan) && rcs[0].rix >=
        (pRateTable->rateCount - pRateTable->numTurboRates))
    {
        u_int32_t numCCKRates = 5;
        u_int32_t i;

         rcs[0].rix -= (pRateTable->rateCount-pRateTable->numTurboRates);
         if (IS_CHAN_2GHZ(&sc->sc_curchan)) {
            for (i=1;i<=3;i++) { /*Mapping for retry rates from merged table to split table*/
                 if (rcs[i].rix >= numCCKRates) {
                     rcs[i].rix -= numCCKRates;
                 } else { /* For 6Mbps Turbo rate */
                     rcs[i].rix -= numCCKRates-1;
                 }                                
            }
        }

    }
#endif
    if (oan->txRateCtrl.consecRtsFailCount > MAX_CONSEC_RTS_FAILED_FRAMES) {
        rcs[0].flags |= ATH_RC_RTSCTS_FLAG;
        rcs[1].rix = rcs[2].rix = rcs[3].rix = 0;
        rcs[1].tries = rcs[2].tries = rcs[3].tries = 0;
    }
}
Beispiel #20
0
void ath9k_ani_reset(struct ath_hw *ah, bool is_scanning)
{
	struct ar5416AniState *aniState = &ah->curchan->ani;
	struct ath9k_channel *chan = ah->curchan;
	struct ath_common *common = ath9k_hw_common(ah);

	if (!DO_ANI(ah))
		return;

	if (!use_new_ani(ah))
		return ath9k_ani_reset_old(ah, is_scanning);

	BUG_ON(aniState == NULL);
	ah->stats.ast_ani_reset++;

	/*                                             */
	if (ah->opmode == NL80211_IFTYPE_AP) {
		if (IS_CHAN_2GHZ(chan)) {
			ah->ani_function = (ATH9K_ANI_SPUR_IMMUNITY_LEVEL |
					    ATH9K_ANI_FIRSTEP_LEVEL);
			if (AR_SREV_9300_20_OR_LATER(ah))
				ah->ani_function |= ATH9K_ANI_MRC_CCK;
		} else
			ah->ani_function = 0;
	}

	/*                                             */
	ah->ani_function |= ATH9K_ANI_MODE;

	if (is_scanning ||
	    (ah->opmode != NL80211_IFTYPE_STATION &&
	     ah->opmode != NL80211_IFTYPE_ADHOC)) {
		/*
                                                        
                                                           
                                                           
                           
   */
		if (aniState->ofdmNoiseImmunityLevel !=
		    ATH9K_ANI_OFDM_DEF_LEVEL ||
		    aniState->cckNoiseImmunityLevel !=
		    ATH9K_ANI_CCK_DEF_LEVEL) {
			ath_dbg(common, ANI,
				"Restore defaults: opmode %u chan %d Mhz/0x%x is_scanning=%d ofdm:%d cck:%d\n",
				ah->opmode,
				chan->channel,
				chan->channelFlags,
				is_scanning,
				aniState->ofdmNoiseImmunityLevel,
				aniState->cckNoiseImmunityLevel);

			aniState->update_ani = false;
			ath9k_hw_set_ofdm_nil(ah, ATH9K_ANI_OFDM_DEF_LEVEL);
			ath9k_hw_set_cck_nil(ah, ATH9K_ANI_CCK_DEF_LEVEL);
		}
	} else {
		/*
                                               
   */
		ath_dbg(common, ANI,
			"Restore history: opmode %u chan %d Mhz/0x%x is_scanning=%d ofdm:%d cck:%d\n",
			ah->opmode,
			chan->channel,
			chan->channelFlags,
			is_scanning,
			aniState->ofdmNoiseImmunityLevel,
			aniState->cckNoiseImmunityLevel);

			aniState->update_ani = true;
			ath9k_hw_set_ofdm_nil(ah,
					      aniState->ofdmNoiseImmunityLevel);
			ath9k_hw_set_cck_nil(ah,
					     aniState->cckNoiseImmunityLevel);
	}

	/*
                                                            
                                         
  */
	ath9k_ani_restart(ah);

	ENABLE_REGWRITE_BUFFER(ah);

	REG_WRITE(ah, AR_PHY_ERR_MASK_1, AR_PHY_ERR_OFDM_TIMING);
	REG_WRITE(ah, AR_PHY_ERR_MASK_2, AR_PHY_ERR_CCK_TIMING);

	REGWRITE_BUFFER_FLUSH(ah);
}
Beispiel #21
0
void ath9k_ani_reset(struct ath_hw *ah)
{
	struct ar5416AniState *aniState;
	struct ath9k_channel *chan = ah->curchan;
	struct ath_common *common = ath9k_hw_common(ah);
	int index;

	if (!DO_ANI(ah))
		return;

	index = ath9k_hw_get_ani_channel_idx(ah, chan);
	aniState = &ah->ani[index];
	ah->curani = aniState;

	if (DO_ANI(ah) && ah->opmode != NL80211_IFTYPE_STATION
	    && ah->opmode != NL80211_IFTYPE_ADHOC) {
		ath_print(common, ATH_DBG_ANI,
			  "Reset ANI state opmode %u\n", ah->opmode);
		ah->stats.ast_ani_reset++;

		if (ah->opmode == NL80211_IFTYPE_AP) {
			/*
			 * ath9k_hw_ani_control() will only process items set on
			 * ah->ani_function
			 */
			if (IS_CHAN_2GHZ(chan))
				ah->ani_function = (ATH9K_ANI_SPUR_IMMUNITY_LEVEL |
						    ATH9K_ANI_FIRSTEP_LEVEL);
			else
				ah->ani_function = 0;
		}

		ath9k_hw_ani_control(ah, ATH9K_ANI_NOISE_IMMUNITY_LEVEL, 0);
		ath9k_hw_ani_control(ah, ATH9K_ANI_SPUR_IMMUNITY_LEVEL, 0);
		ath9k_hw_ani_control(ah, ATH9K_ANI_FIRSTEP_LEVEL, 0);
		ath9k_hw_ani_control(ah, ATH9K_ANI_OFDM_WEAK_SIGNAL_DETECTION,
				     !ATH9K_ANI_USE_OFDM_WEAK_SIG);
		ath9k_hw_ani_control(ah, ATH9K_ANI_CCK_WEAK_SIGNAL_THR,
				     ATH9K_ANI_CCK_WEAK_SIG_THR);

		ath9k_hw_setrxfilter(ah, ath9k_hw_getrxfilter(ah) |
				     ATH9K_RX_FILTER_PHYERR);

		if (ah->opmode == NL80211_IFTYPE_AP) {
			ah->curani->ofdmTrigHigh =
				ah->config.ofdm_trig_high;
			ah->curani->ofdmTrigLow =
				ah->config.ofdm_trig_low;
			ah->curani->cckTrigHigh =
				ah->config.cck_trig_high;
			ah->curani->cckTrigLow =
				ah->config.cck_trig_low;
		}
		ath9k_ani_restart(ah);
		return;
	}

	if (aniState->noiseImmunityLevel != 0)
		ath9k_hw_ani_control(ah, ATH9K_ANI_NOISE_IMMUNITY_LEVEL,
				     aniState->noiseImmunityLevel);
	if (aniState->spurImmunityLevel != 0)
		ath9k_hw_ani_control(ah, ATH9K_ANI_SPUR_IMMUNITY_LEVEL,
				     aniState->spurImmunityLevel);
	if (aniState->ofdmWeakSigDetectOff)
		ath9k_hw_ani_control(ah, ATH9K_ANI_OFDM_WEAK_SIGNAL_DETECTION,
				     !aniState->ofdmWeakSigDetectOff);
	if (aniState->cckWeakSigThreshold)
		ath9k_hw_ani_control(ah, ATH9K_ANI_CCK_WEAK_SIGNAL_THR,
				     aniState->cckWeakSigThreshold);
	if (aniState->firstepLevel != 0)
		ath9k_hw_ani_control(ah, ATH9K_ANI_FIRSTEP_LEVEL,
				     aniState->firstepLevel);

	ath9k_hw_setrxfilter(ah, ath9k_hw_getrxfilter(ah) &
			     ~ATH9K_RX_FILTER_PHYERR);
	ath9k_ani_restart(ah);

	ENABLE_REGWRITE_BUFFER(ah);

	REG_WRITE(ah, AR_PHY_ERR_MASK_1, AR_PHY_ERR_OFDM_TIMING);
	REG_WRITE(ah, AR_PHY_ERR_MASK_2, AR_PHY_ERR_CCK_TIMING);

	REGWRITE_BUFFER_FLUSH(ah);
	DISABLE_REGWRITE_BUFFER(ah);
}
Beispiel #22
0
void ath9k_hw_get_gain_boundaries_pdadcs(struct ath_hw *ah,
				struct ath9k_channel *chan,
				void *pRawDataSet,
				u8 *bChans, u16 availPiers,
				u16 tPdGainOverlap,
				u16 *pPdGainBoundaries, u8 *pPDADCValues,
				u16 numXpdGains)
{
	int i, j, k;
	int16_t ss;
	u16 idxL = 0, idxR = 0, numPiers;
	static u8 vpdTableL[AR5416_NUM_PD_GAINS]
		[AR5416_MAX_PWR_RANGE_IN_HALF_DB];
	static u8 vpdTableR[AR5416_NUM_PD_GAINS]
		[AR5416_MAX_PWR_RANGE_IN_HALF_DB];
	static u8 vpdTableI[AR5416_NUM_PD_GAINS]
		[AR5416_MAX_PWR_RANGE_IN_HALF_DB];

	u8 *pVpdL, *pVpdR, *pPwrL, *pPwrR;
	u8 minPwrT4[AR5416_NUM_PD_GAINS];
	u8 maxPwrT4[AR5416_NUM_PD_GAINS];
	int16_t vpdStep;
	int16_t tmpVal;
	u16 sizeCurrVpdTable, maxIndex, tgtIndex;
	bool match;
	int16_t minDelta = 0;
	struct chan_centers centers;
	int pdgain_boundary_default;
	struct cal_data_per_freq *data_def = pRawDataSet;
	struct cal_data_per_freq_4k *data_4k = pRawDataSet;
	struct cal_data_per_freq_ar9287 *data_9287 = pRawDataSet;
	bool eeprom_4k = AR_SREV_9285(ah) || AR_SREV_9271(ah);
	int intercepts;

	if (AR_SREV_9287(ah))
		intercepts = AR9287_PD_GAIN_ICEPTS;
	else
		intercepts = AR5416_PD_GAIN_ICEPTS;

	memset(&minPwrT4, 0, AR5416_NUM_PD_GAINS);
	ath9k_hw_get_channel_centers(ah, chan, &centers);

	for (numPiers = 0; numPiers < availPiers; numPiers++) {
		if (bChans[numPiers] == AR5416_BCHAN_UNUSED)
			break;
	}

	match = ath9k_hw_get_lower_upper_index((u8)FREQ2FBIN(centers.synth_center,
							     IS_CHAN_2GHZ(chan)),
					       bChans, numPiers, &idxL, &idxR);

	if (match) {
		if (AR_SREV_9287(ah)) {
			/* FIXME: array overrun? */
			for (i = 0; i < numXpdGains; i++) {
				minPwrT4[i] = data_9287[idxL].pwrPdg[i][0];
				maxPwrT4[i] = data_9287[idxL].pwrPdg[i][4];
				ath9k_hw_fill_vpd_table(minPwrT4[i], maxPwrT4[i],
						data_9287[idxL].pwrPdg[i],
						data_9287[idxL].vpdPdg[i],
						intercepts,
						vpdTableI[i]);
			}
		} else if (eeprom_4k) {
			for (i = 0; i < numXpdGains; i++) {
				minPwrT4[i] = data_4k[idxL].pwrPdg[i][0];
				maxPwrT4[i] = data_4k[idxL].pwrPdg[i][4];
				ath9k_hw_fill_vpd_table(minPwrT4[i], maxPwrT4[i],
						data_4k[idxL].pwrPdg[i],
						data_4k[idxL].vpdPdg[i],
						intercepts,
						vpdTableI[i]);
			}
		} else {
			for (i = 0; i < numXpdGains; i++) {
				minPwrT4[i] = data_def[idxL].pwrPdg[i][0];
				maxPwrT4[i] = data_def[idxL].pwrPdg[i][4];
				ath9k_hw_fill_vpd_table(minPwrT4[i], maxPwrT4[i],
						data_def[idxL].pwrPdg[i],
						data_def[idxL].vpdPdg[i],
						intercepts,
						vpdTableI[i]);
			}
		}
	} else {
		for (i = 0; i < numXpdGains; i++) {
			if (AR_SREV_9287(ah)) {
				pVpdL = data_9287[idxL].vpdPdg[i];
				pPwrL = data_9287[idxL].pwrPdg[i];
				pVpdR = data_9287[idxR].vpdPdg[i];
				pPwrR = data_9287[idxR].pwrPdg[i];
			} else if (eeprom_4k) {
				pVpdL = data_4k[idxL].vpdPdg[i];
				pPwrL = data_4k[idxL].pwrPdg[i];
				pVpdR = data_4k[idxR].vpdPdg[i];
				pPwrR = data_4k[idxR].pwrPdg[i];
			} else {
				pVpdL = data_def[idxL].vpdPdg[i];
				pPwrL = data_def[idxL].pwrPdg[i];
				pVpdR = data_def[idxR].vpdPdg[i];
				pPwrR = data_def[idxR].pwrPdg[i];
			}

			minPwrT4[i] = max(pPwrL[0], pPwrR[0]);

			maxPwrT4[i] =
				min(pPwrL[intercepts - 1],
				    pPwrR[intercepts - 1]);


			ath9k_hw_fill_vpd_table(minPwrT4[i], maxPwrT4[i],
						pPwrL, pVpdL,
						intercepts,
						vpdTableL[i]);
			ath9k_hw_fill_vpd_table(minPwrT4[i], maxPwrT4[i],
						pPwrR, pVpdR,
						intercepts,
						vpdTableR[i]);

			for (j = 0; j <= (maxPwrT4[i] - minPwrT4[i]) / 2; j++) {
				vpdTableI[i][j] =
					(u8)(ath9k_hw_interpolate((u16)
					     FREQ2FBIN(centers.
						       synth_center,
						       IS_CHAN_2GHZ
						       (chan)),
					     bChans[idxL], bChans[idxR],
					     vpdTableL[i][j], vpdTableR[i][j]));
			}
		}
	}

	k = 0;

	for (i = 0; i < numXpdGains; i++) {
		if (i == (numXpdGains - 1))
			pPdGainBoundaries[i] =
				(u16)(maxPwrT4[i] / 2);
		else
			pPdGainBoundaries[i] =
				(u16)((maxPwrT4[i] + minPwrT4[i + 1]) / 4);

		pPdGainBoundaries[i] =
			min((u16)MAX_RATE_POWER, pPdGainBoundaries[i]);

		minDelta = 0;

		if (i == 0) {
			if (AR_SREV_9280_20_OR_LATER(ah))
				ss = (int16_t)(0 - (minPwrT4[i] / 2));
			else
				ss = 0;
		} else {
			ss = (int16_t)((pPdGainBoundaries[i - 1] -
					(minPwrT4[i] / 2)) -
				       tPdGainOverlap + 1 + minDelta);
		}
		vpdStep = (int16_t)(vpdTableI[i][1] - vpdTableI[i][0]);
		vpdStep = (int16_t)((vpdStep < 1) ? 1 : vpdStep);

		while ((ss < 0) && (k < (AR5416_NUM_PDADC_VALUES - 1))) {
			tmpVal = (int16_t)(vpdTableI[i][0] + ss * vpdStep);
			pPDADCValues[k++] = (u8)((tmpVal < 0) ? 0 : tmpVal);
			ss++;
		}

		sizeCurrVpdTable = (u8) ((maxPwrT4[i] - minPwrT4[i]) / 2 + 1);
		tgtIndex = (u8)(pPdGainBoundaries[i] + tPdGainOverlap -
				(minPwrT4[i] / 2));
		maxIndex = (tgtIndex < sizeCurrVpdTable) ?
			tgtIndex : sizeCurrVpdTable;

		while ((ss < maxIndex) && (k < (AR5416_NUM_PDADC_VALUES - 1))) {
			pPDADCValues[k++] = vpdTableI[i][ss++];
		}

		vpdStep = (int16_t)(vpdTableI[i][sizeCurrVpdTable - 1] -
				    vpdTableI[i][sizeCurrVpdTable - 2]);
		vpdStep = (int16_t)((vpdStep < 1) ? 1 : vpdStep);

		if (tgtIndex >= maxIndex) {
			while ((ss <= tgtIndex) &&
			       (k < (AR5416_NUM_PDADC_VALUES - 1))) {
				tmpVal = (int16_t)((vpdTableI[i][sizeCurrVpdTable - 1] +
						    (ss - maxIndex + 1) * vpdStep));
				pPDADCValues[k++] = (u8)((tmpVal > 255) ?
							 255 : tmpVal);
				ss++;
			}
		}
	}

	if (eeprom_4k)
		pdgain_boundary_default = 58;
	else
		pdgain_boundary_default = pPdGainBoundaries[i - 1];

	while (i < AR5416_PD_GAINS_IN_MASK) {
		pPdGainBoundaries[i] = pdgain_boundary_default;
		i++;
	}

	while (k < AR5416_NUM_PDADC_VALUES) {
		pPDADCValues[k] = pPDADCValues[k - 1];
		k++;
	}
}
Beispiel #23
0
/*
 * Restore the ANI parameters in the HAL and reset the statistics.
 * This routine should be called for every hardware reset and for
 * every channel change.  NOTE: This must be called for every channel
 * change for ah_curani to be set correctly.
 */
void
ar5416AniReset(struct ath_hal *ah)
{
	struct ath_hal_5416 *ahp = AH5416(ah);
	struct ar5416AniState *aniState;
	HAL_CHANNEL_INTERNAL *chan = AH_PRIVATE(ah)->ah_curchan;
	HAL_CHANNEL_INTERNAL *ichan = AH_PRIVATE(ah)->ah_curchan;
	struct ath_hal_private  *ap = AH_PRIVATE(ah);
	int index;

	HALASSERT(chan != AH_NULL);
	if (!DO_ANI(ah)) {
		return;
	}

	index = ar5416GetAniChannelIndex(ah, chan);
	aniState = &ahp->ah_ani[index];
	ahp->ah_curani = aniState;

        aniState->phyNoiseSpur = 0;

	/* If ANI follows hardware, we don't care what mode we're
	   in, we should keep the ani parameters */
	/*
	 * ANI is enabled but we're not operating in station
	 * mode.  Reset all parameters.  This can happen, for
	 * example, when starting up AP operation.
	 */
	if (DO_ANI(ah) && AH_PRIVATE(ah)->ah_opmode != HAL_M_STA && AH_PRIVATE(ah)->ah_opmode != HAL_M_IBSS) {
		HDPRINTF(ah, HAL_DBG_ANI, "%s: Reset ANI state opmode %u\n",
			__func__, AH_PRIVATE(ah)->ah_opmode);
		ahp->ah_stats.ast_ani_reset++;
                if (AH_PRIVATE(ah)->ah_opmode == HAL_M_HOSTAP) {
                    if (IS_CHAN_2GHZ(ichan))
                        ahp->ah_ani_function = (HAL_ANI_SPUR_IMMUNITY_LEVEL |
                                                HAL_ANI_FIRSTEP_LEVEL);
                    else
                        ahp->ah_ani_function = 0;
                } 

		ar5416AniControl(ah, HAL_ANI_NOISE_IMMUNITY_LEVEL, 0, AH_FALSE);
		ar5416AniControl(ah, HAL_ANI_SPUR_IMMUNITY_LEVEL, 0, AH_FALSE);
		ar5416AniControl(ah, HAL_ANI_FIRSTEP_LEVEL, 0, AH_FALSE);
		ar5416AniControl(ah, HAL_ANI_OFDM_WEAK_SIGNAL_DETECTION,
			!HAL_ANI_USE_OFDM_WEAK_SIG, AH_FALSE);
		ar5416AniControl(ah, HAL_ANI_CCK_WEAK_SIGNAL_THR,
			HAL_ANI_CCK_WEAK_SIG_THR, AH_FALSE);

        if (AH_PRIVATE(ah)->ah_opmode == HAL_M_HOSTAP) 
        {
                  ahp->ah_curani->ofdmTrigHigh = ap->ah_config.ath_hal_ofdmTrigHigh;
                  ahp->ah_curani->ofdmTrigLow = ap->ah_config.ath_hal_ofdmTrigLow;
                  ahp->ah_curani->cckTrigHigh = ap->ah_config.ath_hal_cckTrigHigh;
                  ahp->ah_curani->cckTrigLow = ap->ah_config.ath_hal_cckTrigLow;
		}
	    ar5416AniRestart(ah);
	}
    else
    {
          if (aniState->noiseImmunityLevel != 0)
	    ar5416AniControl(ah, HAL_ANI_NOISE_IMMUNITY_LEVEL,
	                     aniState->noiseImmunityLevel, AH_FALSE);
          if (aniState->spurImmunityLevel != 0)
	    ar5416AniControl(ah, HAL_ANI_SPUR_IMMUNITY_LEVEL,
	                     aniState->spurImmunityLevel,AH_FALSE);
          if (aniState->ofdmWeakSigDetectOff)
	    ar5416AniControl(ah, HAL_ANI_OFDM_WEAK_SIGNAL_DETECTION,
	                     !aniState->ofdmWeakSigDetectOff, AH_FALSE);
	  if (aniState->cckWeakSigThreshold)
	    ar5416AniControl(ah, HAL_ANI_CCK_WEAK_SIGNAL_THR,
			     aniState->cckWeakSigThreshold, AH_FALSE);
          if (aniState->firstepLevel != 0)
	    ar5416AniControl(ah, HAL_ANI_FIRSTEP_LEVEL, aniState->firstepLevel, AH_FALSE);
    }
   
        /*
         * enable phy counters if hw supports or if not, enable phy interrupts
         * (so we can count each one)
         */
	if (ahp->ah_hasHwPhyCounters) {
		ar5416SetRxFilter(ah,
			  ar5416GetRxFilter(ah) &~ HAL_RX_FILTER_PHYERR);
		ar5416AniRestart(ah);

		ENABLE_REG_WRITE_BUFFER
		OS_REG_WRITE(ah, AR_PHY_ERR_MASK_1, AR_PHY_ERR_OFDM_TIMING);
		OS_REG_WRITE(ah, AR_PHY_ERR_MASK_2, AR_PHY_ERR_CCK_TIMING);
		OS_REG_WRITE_FLUSH(ah);
		DISABLE_REG_WRITE_BUFFER

	} else {
Beispiel #24
0
/*
 * Sets the transmit power in the baseband for the given
 * operating channel and mode.
 */
static HAL_BOOL
setRateTable(struct ath_hal *ah, const struct ieee80211_channel *chan, 
		   int16_t tpcScaleReduction, int16_t powerLimit,
                   int16_t *pMinPower, int16_t *pMaxPower)
{
	u_int16_t ratesArray[16];
	u_int16_t *rpow = ratesArray;
	u_int16_t twiceMaxRDPower, twiceMaxEdgePower, twiceMaxEdgePowerCck;
	int8_t twiceAntennaGain, twiceAntennaReduction;
	TRGT_POWER_INFO targetPowerOfdm, targetPowerCck;
	RD_EDGES_POWER *rep;
	int16_t scaledPower;
	u_int8_t cfgCtl;

	twiceMaxRDPower = chan->ic_maxregpower * 2;
	*pMaxPower = -MAX_RATE_POWER;
	*pMinPower = MAX_RATE_POWER;

	/* Get conformance test limit maximum for this channel */
	cfgCtl = ath_hal_getctl(ah, chan);
	rep = findEdgePower(ah, cfgCtl);
	if (rep != AH_NULL)
		twiceMaxEdgePower = ar5212GetMaxEdgePower(chan->ic_freq, rep);
	else
		twiceMaxEdgePower = MAX_RATE_POWER;

	if (IEEE80211_IS_CHAN_G(chan)) {
		/* Check for a CCK CTL for 11G CCK powers */
		cfgCtl = (cfgCtl & 0xFC) | 0x01;
		rep = findEdgePower(ah, cfgCtl);
		if (rep != AH_NULL)
			twiceMaxEdgePowerCck = ar5212GetMaxEdgePower(chan->ic_freq, rep);
		else
			twiceMaxEdgePowerCck = MAX_RATE_POWER;
	} else {
		/* Set the 11B cck edge power to the one found before */
		twiceMaxEdgePowerCck = twiceMaxEdgePower;
	}

	/* Get Antenna Gain reduction */
	if (IEEE80211_IS_CHAN_5GHZ(chan)) {
		twiceAntennaGain = antennaGainMax[0];
	} else {
		twiceAntennaGain = antennaGainMax[1];
	}
	twiceAntennaReduction =
		ath_hal_getantennareduction(ah, chan, twiceAntennaGain);

	if (IEEE80211_IS_CHAN_OFDM(chan)) {
		/* Get final OFDM target powers */
		if (IEEE80211_IS_CHAN_G(chan)) { 
			/* TODO - add Turbo 2.4 to this mode check */
			ar5212GetTargetPowers(ah, chan, trgtPwr_11g,
				numTargetPwr_11g, &targetPowerOfdm);
		} else {
			ar5212GetTargetPowers(ah, chan, trgtPwr_11a,
				numTargetPwr_11a, &targetPowerOfdm);
		}

		/* Get Maximum OFDM power */
		/* Minimum of target and edge powers */
		scaledPower = AH_MIN(twiceMaxEdgePower,
				twiceMaxRDPower - twiceAntennaReduction);

		/*
		 * If turbo is set, reduce power to keep power
		 * consumption under 2 Watts.  Note that we always do
		 * this unless specially configured.  Then we limit
		 * power only for non-AP operation.
		 */
		if (IEEE80211_IS_CHAN_TURBO(chan)
#ifdef AH_ENABLE_AP_SUPPORT
		    && AH_PRIVATE(ah)->ah_opmode != HAL_M_HOSTAP
#endif
		) {
			/*
			 * If turbo is set, reduce power to keep power
			 * consumption under 2 Watts
			 */
			if (eeversion >= AR_EEPROM_VER3_1)
				scaledPower = AH_MIN(scaledPower,
					turbo2WMaxPower5);
			/*
			 * EEPROM version 4.0 added an additional
			 * constraint on 2.4GHz channels.
			 */
			if (eeversion >= AR_EEPROM_VER4_0 &&
			    IEEE80211_IS_CHAN_2GHZ(chan))
				scaledPower = AH_MIN(scaledPower,
					turbo2WMaxPower2);
		}
		/* Reduce power by max regulatory domain allowed restrictions */
		scaledPower -= (tpcScaleReduction * 2);
		scaledPower = (scaledPower < 0) ? 0 : scaledPower;
		scaledPower = AH_MIN(scaledPower, powerLimit);

		scaledPower = AH_MIN(scaledPower, targetPowerOfdm.twicePwr6_24);

		/* Set OFDM rates 9, 12, 18, 24, 36, 48, 54, XR */
		rpow[0] = rpow[1] = rpow[2] = rpow[3] = rpow[4] = scaledPower;
		rpow[5] = AH_MIN(rpow[0], targetPowerOfdm.twicePwr36);
		rpow[6] = AH_MIN(rpow[0], targetPowerOfdm.twicePwr48);
		rpow[7] = AH_MIN(rpow[0], targetPowerOfdm.twicePwr54);

#ifdef notyet
		if (eeversion >= AR_EEPROM_VER4_0) {
			/* Setup XR target power from EEPROM */
			rpow[15] = AH_MIN(scaledPower, IS_CHAN_2GHZ(chan) ?
				xrTargetPower2 : xrTargetPower5);
		} else {
			/* XR uses 6mb power */
			rpow[15] = rpow[0];
		}
#else
		rpow[15] = rpow[0];
#endif

		*pMinPower = rpow[7];
		*pMaxPower = rpow[0];

#if 0
		ahp->ah_ofdmTxPower = rpow[0];
#endif

		HALDEBUG(ah, HAL_DEBUG_ANY,
		    "%s: MaxRD: %d TurboMax: %d MaxCTL: %d "
		    "TPC_Reduction %d\n", __func__,
		    twiceMaxRDPower, turbo2WMaxPower5,
		    twiceMaxEdgePower, tpcScaleReduction * 2);
	}

	if (IEEE80211_IS_CHAN_CCK(chan)) {
		/* Get final CCK target powers */
		ar5212GetTargetPowers(ah, chan, trgtPwr_11b,
			numTargetPwr_11b, &targetPowerCck);

		/* Reduce power by max regulatory domain allowed restrictions */
		scaledPower = AH_MIN(twiceMaxEdgePowerCck,
			twiceMaxRDPower - twiceAntennaReduction);

		scaledPower -= (tpcScaleReduction * 2);
		scaledPower = (scaledPower < 0) ? 0 : scaledPower;
		scaledPower = AH_MIN(scaledPower, powerLimit);

		rpow[8] = (scaledPower < 1) ? 1 : scaledPower;

		/* Set CCK rates 2L, 2S, 5.5L, 5.5S, 11L, 11S */
		rpow[8]  = AH_MIN(scaledPower, targetPowerCck.twicePwr6_24);
		rpow[9]  = AH_MIN(scaledPower, targetPowerCck.twicePwr36);
		rpow[10] = rpow[9];
		rpow[11] = AH_MIN(scaledPower, targetPowerCck.twicePwr48);
		rpow[12] = rpow[11];
		rpow[13] = AH_MIN(scaledPower, targetPowerCck.twicePwr54);
		rpow[14] = rpow[13];

		/* Set min/max power based off OFDM values or initialization */
		if (rpow[13] < *pMinPower)
		    *pMinPower = rpow[13];
		if (rpow[9] > *pMaxPower)
		    *pMaxPower = rpow[9];

	}
#if 0
	ahp->ah_tx6PowerInHalfDbm = *pMaxPower;
#endif
	return AH_TRUE;
}
/*
 * 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,
	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;
	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);
#define	IS(_c,_f)	(((_c)->channelFlags & _f) || 0)
	if ((IS(chan, CHANNEL_2GHZ) ^ IS(chan, CHANNEL_5GHZ)) == 0) {
		HALDEBUG(ah, HAL_DEBUG_ANY,
		    "%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, HAL_DEBUG_ANY,
		    "%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, HAL_DEBUG_ANY,
		    "%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, 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->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 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 */
	switch (chan->channelFlags & CHANNEL_ALL) {
	case CHANNEL_A:
		modesIndex = 1;
		freqIndex  = 1;
		break;
	case CHANNEL_T:
		modesIndex = 2;
		freqIndex  = 1;
		break;
	case CHANNEL_B:
		modesIndex = 3;
		freqIndex  = 2;
		break;
	case CHANNEL_PUREG:
		modesIndex = 4;
		freqIndex  = 2;
		break;
	case CHANNEL_108G:
		modesIndex = 5;
		freqIndex  = 2;
		break;
	default:
		HALDEBUG(ah, HAL_DEBUG_ANY, "%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);

	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 (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(ee->ee_cckOfdmPwrDelta - ee->ee_scaledCh14FilterCckDelta);
		} else {
			cckOfdmPwrDelta = SCALE_OC_DELTA(ee->ee_cckOfdmPwrDelta);
		}
		
		if (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 (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 (!ar5212SetTransmitPower(ah, ichan, 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, ichan, 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 (IS_CHAN_OFDM(chan)) {
		if ((IS_5413(ah) || (AH_PRIVATE(ah)->ah_eeversion >= AR_EEPROM_VER5_3)) &&
		    (!IS_CHAN_B(chan)))
			ar5212SetSpurMitigation(ah, ichan);
		ar5212SetDeltaSlope(ah, chan);
	}

	/* Setup board specific options for EEPROM version 3 */
	if (!ar5212SetBoardValues(ah, ichan)) {
		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, 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_RAD5112_ANY(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 */

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

	/*
	 * 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 (!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) {
		if (!(ichan->privFlags & CHANNEL_DFS)) 
			ichan->privFlags &= ~CHANNEL_INTERFERENCE;
		chan->channelFlags = ichan->channelFlags;
		chan->privFlags = ichan->privFlags;
	}

	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)
		*status = ecode;
	return AH_FALSE;
#undef FAIL
#undef N
}
Beispiel #26
0
/*
 * Restore the ANI parameters in the HAL and reset the statistics.
 * This routine should be called for every hardware reset and for
 * every channel change.
 */
void ath9k_ani_reset(struct ath_hw *ah, bool is_scanning)
{
	struct ar5416AniState *aniState = &ah->ani;
	struct ath9k_channel *chan = ah->curchan;
	struct ath_common *common = ath9k_hw_common(ah);
	int ofdm_nil, cck_nil;

	if (!ah->curchan)
		return;

	BUG_ON(aniState == NULL);
	ah->stats.ast_ani_reset++;

	/* only allow a subset of functions in AP mode */
	if (ah->opmode == NL80211_IFTYPE_AP) {
		if (IS_CHAN_2GHZ(chan)) {
			ah->ani_function = (ATH9K_ANI_SPUR_IMMUNITY_LEVEL |
					    ATH9K_ANI_FIRSTEP_LEVEL);
			if (AR_SREV_9300_20_OR_LATER(ah))
				ah->ani_function |= ATH9K_ANI_MRC_CCK;
		} else
			ah->ani_function = 0;
	}

	ofdm_nil = max_t(int, ATH9K_ANI_OFDM_DEF_LEVEL,
			 aniState->ofdmNoiseImmunityLevel);
	cck_nil = max_t(int, ATH9K_ANI_CCK_DEF_LEVEL,
			 aniState->cckNoiseImmunityLevel);

	if (is_scanning ||
	    (ah->opmode != NL80211_IFTYPE_STATION &&
	     ah->opmode != NL80211_IFTYPE_ADHOC)) {
		/*
		 * If we're scanning or in AP mode, the defaults (ini)
		 * should be in place. For an AP we assume the historical
		 * levels for this channel are probably outdated so start
		 * from defaults instead.
		 */
		if (aniState->ofdmNoiseImmunityLevel !=
		    ATH9K_ANI_OFDM_DEF_LEVEL ||
		    aniState->cckNoiseImmunityLevel !=
		    ATH9K_ANI_CCK_DEF_LEVEL) {
			ath_dbg(common, ANI,
				"Restore defaults: opmode %u chan %d Mhz/0x%x is_scanning=%d ofdm:%d cck:%d\n",
				ah->opmode,
				chan->channel,
				chan->channelFlags,
				is_scanning,
				aniState->ofdmNoiseImmunityLevel,
				aniState->cckNoiseImmunityLevel);

			ofdm_nil = ATH9K_ANI_OFDM_DEF_LEVEL;
			cck_nil = ATH9K_ANI_CCK_DEF_LEVEL;
		}
	} else {
		/*
		 * restore historical levels for this channel
		 */
		ath_dbg(common, ANI,
			"Restore history: opmode %u chan %d Mhz/0x%x is_scanning=%d ofdm:%d cck:%d\n",
			ah->opmode,
			chan->channel,
			chan->channelFlags,
			is_scanning,
			aniState->ofdmNoiseImmunityLevel,
			aniState->cckNoiseImmunityLevel);
	}
	ath9k_hw_set_ofdm_nil(ah, ofdm_nil, is_scanning);
	ath9k_hw_set_cck_nil(ah, cck_nil, is_scanning);

	ath9k_ani_restart(ah);
}
Beispiel #27
0
static void ath9k_ani_reset_old(struct ath_hw *ah, bool is_scanning)
{
	struct ar5416AniState *aniState;
	struct ath9k_channel *chan = ah->curchan;
	struct ath_common *common = ath9k_hw_common(ah);

	if (!DO_ANI(ah))
		return;

	aniState = &ah->curchan->ani;

	if (ah->opmode != NL80211_IFTYPE_STATION
	    && ah->opmode != NL80211_IFTYPE_ADHOC) {
		ath_dbg(common, ATH_DBG_ANI,
			"Reset ANI state opmode %u\n", ah->opmode);
		ah->stats.ast_ani_reset++;

		if (ah->opmode == NL80211_IFTYPE_AP) {
			/*
			 * ath9k_hw_ani_control() will only process items set on
			 * ah->ani_function
			 */
			if (IS_CHAN_2GHZ(chan))
				ah->ani_function = (ATH9K_ANI_SPUR_IMMUNITY_LEVEL |
						    ATH9K_ANI_FIRSTEP_LEVEL);
			else
				ah->ani_function = 0;
		}

		ath9k_hw_ani_control(ah, ATH9K_ANI_NOISE_IMMUNITY_LEVEL, 0);
		ath9k_hw_ani_control(ah, ATH9K_ANI_SPUR_IMMUNITY_LEVEL, 0);
		ath9k_hw_ani_control(ah, ATH9K_ANI_FIRSTEP_LEVEL, 0);
		ath9k_hw_ani_control(ah, ATH9K_ANI_OFDM_WEAK_SIGNAL_DETECTION,
				     !ATH9K_ANI_USE_OFDM_WEAK_SIG);
		ath9k_hw_ani_control(ah, ATH9K_ANI_CCK_WEAK_SIGNAL_THR,
				     ATH9K_ANI_CCK_WEAK_SIG_THR);

		ath9k_ani_restart(ah);
		return;
	}

	if (aniState->noiseImmunityLevel != 0)
		ath9k_hw_ani_control(ah, ATH9K_ANI_NOISE_IMMUNITY_LEVEL,
				     aniState->noiseImmunityLevel);
	if (aniState->spurImmunityLevel != 0)
		ath9k_hw_ani_control(ah, ATH9K_ANI_SPUR_IMMUNITY_LEVEL,
				     aniState->spurImmunityLevel);
	if (aniState->ofdmWeakSigDetectOff)
		ath9k_hw_ani_control(ah, ATH9K_ANI_OFDM_WEAK_SIGNAL_DETECTION,
				     !aniState->ofdmWeakSigDetectOff);
	if (aniState->cckWeakSigThreshold)
		ath9k_hw_ani_control(ah, ATH9K_ANI_CCK_WEAK_SIGNAL_THR,
				     aniState->cckWeakSigThreshold);
	if (aniState->firstepLevel != 0)
		ath9k_hw_ani_control(ah, ATH9K_ANI_FIRSTEP_LEVEL,
				     aniState->firstepLevel);

	ath9k_ani_restart(ah);

	ENABLE_REGWRITE_BUFFER(ah);

	REG_WRITE(ah, AR_PHY_ERR_MASK_1, AR_PHY_ERR_OFDM_TIMING);
	REG_WRITE(ah, AR_PHY_ERR_MASK_2, AR_PHY_ERR_CCK_TIMING);

	REGWRITE_BUFFER_FLUSH(ah);
}