Ejemplo n.º 1
0
static void
ath_hal_dumpdcu(FILE *fd, int what)
{
	int i;

	/* DCU registers */
	for (i = 0; i < 10; i++)
		fprintf(fd, "D[%u] MASK %08x IFS %08x RTRY %08x CHNT %08x MISC %06x\n"
			, i
			, OS_REG_READ(ah, AR_DQCUMASK(i))
			, OS_REG_READ(ah, AR_DLCL_IFS(i))
			, OS_REG_READ(ah, AR_DRETRY_LIMIT(i))
			, OS_REG_READ(ah, AR_DCHNTIME(i))
			, OS_REG_READ(ah, AR_DMISC(i))
		);
}
Ejemplo n.º 2
0
void
ar5416_ContTxMode(struct ath_hal *ah, void *ds, int mode)
{
        static int qnum =0;
        int i;
        unsigned int qbits;
#if AH_DEBUG
        struct ar5416_desc *ads = AR5416DESC(ds);
        unsigned int val, val1, val2;
#endif
        if(mode == 10) return;

    if (mode==7) {                      // print status from the cont tx desc
#if AH_DEBUG
                if (ads) {
                        val1 = ads->ds_txstatus0;
                        val2 = ads->ds_txstatus1;
                        HDPRINTF(ah, HAL_DBG_TXDESC, "s0(%x) s1(%x)\n",
                                                   (unsigned)val1, (unsigned)val2);
                }
#endif
                HDPRINTF(ah, HAL_DBG_TXDESC, "txe(%x) txd(%x)\n",
                                           OS_REG_READ(ah, AR_Q_TXE),
                                           OS_REG_READ(ah, AR_Q_TXD)
                        );
#if AH_DEBUG
                for(i=0;i<HAL_NUM_TX_QUEUES; i++) {
                        val = OS_REG_READ(ah, AR_QTXDP(i));
                        val2 = OS_REG_READ(ah, AR_QSTS(i)) & AR_Q_STS_PEND_FR_CNT;
                        HDPRINTF(ah, HAL_DBG_TXDESC, "[%d] %x %d\n", i, val, val2);
                }
#endif
                return;
    }
    if (mode==8) {                      // set TXE for qnum
                OS_REG_WRITE(ah, AR_Q_TXE, 1<<qnum);
                return;
    }
    if (mode==9) {
                return;
    }

    if (mode >= 1) {                    // initiate cont tx operation
                /* Disable AGC to A2 */
#if !_MAVERICK_STA_
		qnum = (int)ds;
#else
		/* handle the x86_64 case - we know ds is 32-bit, so cast is OK */
		qnum = (int)(uintptr_t)ds;
#endif

                OS_REG_WRITE(ah, AR_PHY_TEST,
                                         (OS_REG_READ(ah, AR_PHY_TEST) | PHY_AGC_CLR) );

                OS_REG_WRITE(ah, 0x9864, OS_REG_READ(ah, 0x9864) | 0x7f000);
                OS_REG_WRITE(ah, 0x9924, OS_REG_READ(ah, 0x9924) | 0x7f00fe);
                OS_REG_WRITE(ah, AR_DIAG_SW,
                                         (OS_REG_READ(ah, AR_DIAG_SW) | (AR_DIAG_FORCE_RX_CLEAR+AR_DIAG_IGNORE_VIRT_CS)) );


                OS_REG_WRITE(ah, AR_CR, AR_CR_RXD);     // set receive disable

                if (mode == 3 || mode == 4) {
                        int txcfg;

                        if (mode == 3) {
                                OS_REG_WRITE(ah, AR_DLCL_IFS(qnum), 0);
                                OS_REG_WRITE(ah, AR_DRETRY_LIMIT(qnum), 0xffffffff);
                                OS_REG_WRITE(ah, AR_D_GBL_IFS_SIFS, 100);
                                OS_REG_WRITE(ah, AR_D_GBL_IFS_EIFS, 100);
                                OS_REG_WRITE(ah, AR_TIME_OUT, 2);
                                OS_REG_WRITE(ah, AR_D_GBL_IFS_SLOT, 100);
                        }
                        OS_REG_WRITE(ah, AR_DRETRY_LIMIT(qnum), 0xffffffff);
                        OS_REG_WRITE(ah, AR_D_FPCTL, 0x10|qnum);        // enable prefetch on qnum
                        txcfg = 5 | (6<<AR_FTRIG_S);
                        OS_REG_WRITE(ah, AR_TXCFG, txcfg);

                        OS_REG_WRITE(ah, AR_QMISC(qnum),        // set QCU modes
                                                 AR_Q_MISC_DCU_EARLY_TERM_REQ
                                                 +AR_Q_MISC_FSP_ASAP
                                                 +AR_Q_MISC_CBR_INCR_DIS1
                                                 +AR_Q_MISC_CBR_INCR_DIS0
                                );

                        /* stop tx dma all all except qnum */
                        qbits = 0x3ff;
                        qbits &= ~(1<<qnum);
                        for (i=0; i<10; i++) {
                                if (i==qnum) continue;
                                OS_REG_WRITE(ah, AR_Q_TXD, 1<<i);
                        }
                        OS_REG_WRITE(ah, AR_Q_TXD, qbits);

                        /* clear and freeze MIB counters */
                        OS_REG_WRITE(ah, AR_MIBC, AR_MIBC_CMC);
                        OS_REG_WRITE(ah, AR_MIBC, AR_MIBC_FMC);

                        OS_REG_WRITE(ah, AR_DMISC(qnum),
                                                 (AR_D_MISC_ARB_LOCKOUT_CNTRL_GLOBAL << AR_D_MISC_ARB_LOCKOUT_CNTRL_S)
                                                 +(AR_D_MISC_ARB_LOCKOUT_IGNORE)
                                                 +(AR_D_MISC_POST_FR_BKOFF_DIS)
                                                 +(AR_D_MISC_VIR_COL_HANDLING_IGNORE << AR_D_MISC_VIR_COL_HANDLING_S)
                                );

                        for(i=0; i<HAL_NUM_TX_QUEUES+2; i++) {  // disconnect QCUs
                                if (i==qnum) continue;
                                OS_REG_WRITE(ah, AR_DQCUMASK(i), 0);
                        }
                }
    }
    if (mode == 0) {

                OS_REG_WRITE(ah, AR_PHY_TEST,
                                         (OS_REG_READ(ah, AR_PHY_TEST) & ~PHY_AGC_CLR) );
                OS_REG_WRITE(ah, AR_DIAG_SW,
                                         (OS_REG_READ(ah, AR_DIAG_SW) & ~(AR_DIAG_FORCE_RX_CLEAR+AR_DIAG_IGNORE_VIRT_CS)) );
    }
}
Ejemplo n.º 3
0
void
ar9300DumpRegs(FILE *fd, int what)
{
#define N(a)    (sizeof(a) / sizeof(a[0]))
    static const HAL_REG regs[] = {
        /* NB: keep these sorted by address */
        { "CR",     AR_CR },
        { "HPRXDP", AR_HP_RXDP },
        { "LPRXDP", AR_LP_RXDP },
        { "CFG",    AR_CFG },
        { "IER",    AR_IER },
        { "TXCFG",  AR_TXCFG },
        { "RXCFG",  AR_RXCFG },
        { "MIBC",   AR_MIBC },
        { "TOPS",   AR_TOPS },
        { "RXNPTO", AR_RXNPTO },
        { "TXNPTO", AR_TXNPTO },
        { "RPGTO",  AR_RPGTO },
        { "MACMISC", AR_MACMISC },
        { "D_SIFS", AR_D_GBL_IFS_SIFS },
        { "D_SEQNUM", AR_D_SEQNUM },
        { "D_SLOT", AR_D_GBL_IFS_SLOT },
        { "D_EIFS", AR_D_GBL_IFS_EIFS },
        { "D_MISC", AR_D_GBL_IFS_MISC },
        { "D_TXPSE", AR_D_TXPSE },
        { "RC",     AR9300_HOSTIF_OFFSET(HOST_INTF_RESET_CONTROL) },
//      { "SCR",    AR_SCR },
//      { "INTPEND",    AR_INTPEND },
//      { "SFR",    AR_SFR },
//      { "PCICFG", AR_PCICFG },
//      { "GPIOCR", AR_GPIOCR },
        { "SREV",   AR9300_HOSTIF_OFFSET(HOST_INTF_SREV) },
        { "STA_ID0",    AR_STA_ID0 },
        { "STA_ID1",    AR_STA_ID1 },
        { "BSS_ID0",    AR_BSS_ID0 },
        { "BSS_ID1",    AR_BSS_ID1 },
        { "TIME_OUT",   AR_TIME_OUT },
        { "RSSI_THR",   AR_RSSI_THR },
        { "USEC",   AR_USEC },
//      { "BEACON", AR_BEACON },
//      { "CFP_PER",    AR_CFP_PERIOD },
//      { "TIMER0", AR_TIMER0 },
//      { "TIMER1", AR_TIMER1 },
//      { "TIMER2", AR_TIMER2 },
//      { "TIMER3", AR_TIMER3 },
//      { "CFP_DUR",    AR_CFP_DUR },
        { "RX_FILTR",   AR_RX_FILTER },
        { "MCAST_0",    AR_MCAST_FIL0 },
        { "MCAST_1",    AR_MCAST_FIL1 },
        { "DIAG_SW",    AR_DIAG_SW },
        { "TSF_L32",    AR_TSF_L32 },
        { "TSF_U32",    AR_TSF_U32 },
        { "TST_ADAC",   AR_TST_ADDAC },
        { "DEF_ANT",    AR_DEF_ANTENNA },
        { "LAST_TST",   AR_LAST_TSTP },
        { "NAV",    AR_NAV },
        { "RTS_OK",     AR_RTS_OK },
        { "RTS_FAIL",   AR_RTS_FAIL },
        { "ACK_FAIL",   AR_ACK_FAIL },
        { "FCS_FAIL",   AR_FCS_FAIL },
        { "BEAC_CNT",   AR_BEACON_CNT },
#ifdef AH_SUPPORT_XR
        { "XRMODE", AR_XRMODE },
        { "XRDEL",  AR_XRDEL },
        { "XRTO",   AR_XRTO },
        { "XRCRP",  AR_XRCRP },
        { "XRSTMP", AR_XRSTMP },
#endif /* AH_SUPPORT_XR */
        { "SLEEP1", AR_SLEEP1 },
        { "SLEEP2", AR_SLEEP2 },
//      { "SLEEP3", AR_SLEEP3 },
        { "BSSMSKL",    AR_BSSMSKL },
        { "BSSMSKU",    AR_BSSMSKU },
        { "TPC",    AR_TPC },
        { "TFCNT",  AR_TFCNT },
        { "RFCNT",  AR_RFCNT },
        { "RCCNT",  AR_RCCNT },
        { "CCCNT",  AR_CCCNT },
//      { "NOACK",  AR_NOACK },
        { "PHY_ERR",    AR_PHY_ERR },
//      { "QOSCTL", AR_QOS_CONTROL },
//      { "QOSSEL", AR_QOS_SELECT },
//      { "MISCMODE",   AR_MISC_MODE },
//      { "FILTOFDM",   AR_FILTOFDM },
//      { "FILTCCK",    AR_FILTCCK },
//      { "PHYCNT1",    AR_PHYCNT1 },
//      { "PHYCMSK1",   AR_PHYCNTMASK1 },
//      { "PHYCNT2",    AR_PHYCNT2 },
//      { "PHYCMSK2",   AR_PHYCNTMASK2 },
    };
    int i;
    u_int32_t v;

    if (what & DUMP_BASIC) {
        ath_hal_dumpregs(fd, regs, N(regs));
    }
    if (what & DUMP_INTERRUPT) {
        /* Interrupt registers */
        if (what & DUMP_BASIC)
            fprintf(fd, "\n");
        fprintf(fd, "IMR: %08x S0 %08x S1 %08x S2 %08x S3 %08x S4 %08x\n"
            , OS_REG_READ(ah, AR_IMR)
            , OS_REG_READ(ah, AR_IMR_S0)
            , OS_REG_READ(ah, AR_IMR_S1)
            , OS_REG_READ(ah, AR_IMR_S2)
            , OS_REG_READ(ah, AR_IMR_S3)
            , OS_REG_READ(ah, AR_IMR_S4)
        );
        fprintf(fd, "ISR: %08x S0 %08x S1 %08x S2 %08x S3 %08x S4 %08x\n"
            , OS_REG_READ(ah, AR_ISR)
            , OS_REG_READ(ah, AR_ISR_S0)
            , OS_REG_READ(ah, AR_ISR_S1)
            , OS_REG_READ(ah, AR_ISR_S2)
            , OS_REG_READ(ah, AR_ISR_S3)
            , OS_REG_READ(ah, AR_ISR_S4)
        );
    }
    if (what & DUMP_QCU) {
        /* QCU registers */
        if (what & (DUMP_BASIC|DUMP_INTERRUPT))
            fprintf(fd, "\n");
        fprintf(fd, "%-8s %08x  %-8s %08x  %-8s %08x\n"
            , "Q_TXE", OS_REG_READ(ah, AR_Q_TXE)
            , "Q_TXD", OS_REG_READ(ah, AR_Q_TXD)
            , "Q_RDYTIMSHD", OS_REG_READ(ah, AR_Q_RDYTIMESHDN)
        );
        fprintf(fd, "Q_ONESHOTARM_SC %08x  Q_ONESHOTARM_CC %08x\n"
            , OS_REG_READ(ah, AR_Q_ONESHOTARM_SC)
            , OS_REG_READ(ah, AR_Q_ONESHOTARM_CC)
        );
        for (i = 0; i < 10; i++)
            fprintf(fd, "Q[%u] TXDP %08x CBR %08x RDYT %08x MISC %08x STS %08x\n"
                , i
                , OS_REG_READ(ah, AR_QTXDP(i))
                , OS_REG_READ(ah, AR_QCBRCFG(i))
                , OS_REG_READ(ah, AR_QRDYTIMECFG(i))
                , OS_REG_READ(ah, AR_QMISC(i))
                , OS_REG_READ(ah, AR_QSTS(i))
            );
    }
    if (what & DUMP_DCU) {
        /* DCU registers */
        if (what & (DUMP_BASIC|DUMP_INTERRUPT|DUMP_QCU))
            fprintf(fd, "\n");
        for (i = 0; i < 10; i++)
            fprintf(fd, "D[%u] MASK %08x IFS %08x RTRY %08x CHNT %08x MISC %06x\n"
                , i
                , OS_REG_READ(ah, AR_DQCUMASK(i))
                , OS_REG_READ(ah, AR_DLCL_IFS(i))
                , OS_REG_READ(ah, AR_DRETRY_LIMIT(i))
                , OS_REG_READ(ah, AR_DCHNTIME(i))
                , OS_REG_READ(ah, AR_DMISC(i))
            );
    }
    for (i = 0; i < 10; i++) {
        u_int32_t f0 = OS_REG_READ(ah, AR_D_TXBLK_DATA((i<<8)|0x00));
        u_int32_t f1 = OS_REG_READ(ah, AR_D_TXBLK_DATA((i<<8)|0x40));
        u_int32_t f2 = OS_REG_READ(ah, AR_D_TXBLK_DATA((i<<8)|0x80));
        u_int32_t f3 = OS_REG_READ(ah, AR_D_TXBLK_DATA((i<<8)|0xc0));
        if (f0 || f1 || f2 || f3)
            fprintf(fd,
                "D[%u] XMIT MASK %08x %08x %08x %08x\n",
                i, f0, f1, f2, f3);
    }
    if (what & DUMP_KEYCACHE)
        ath_hal_dumpkeycache(fd, 128,
            OS_REG_READ(ah, AR_STA_ID1) & AR_STA_ID1_CRPT_MIC_ENABLE);

    if (what & DUMP_BASEBAND) {
        int reg;
        if (what &~ DUMP_BASEBAND)
            fprintf(fd, "\n");

        for (reg = 0x9800; reg <= 0xa480; reg += 4) {
            printf("%X %.8X\n", reg, OS_REG_READ(ah, reg));
        }
#if 0
        ath_hal_dumprange(fd, 0x9800, 0x987c);
        ath_hal_dumprange(fd, 0x9900, 0x995c);
        ath_hal_dumprange(fd, 0x9c00, 0x9c1c);
        ath_hal_dumprange(fd, 0xa180, 0xa238);
#endif
    }

    if (what & DUMP_LA) {
        int reg;
        for (reg = AR_MAC_PCU_TRACE_REG_START, i = 0; reg < AR_MAC_PCU_TRACE_REG_END; reg += 16) {
            printf("0x%X: 0x%.8X 0x%.8X 0x%.8X 0x%.8X\n", reg, 
                   OS_REG_READ(ah, reg + 0),
                   OS_REG_READ(ah, reg + 4),
                   OS_REG_READ(ah, reg + 8),
                   OS_REG_READ(ah, reg + 12));
        }
    }
    if (what & DUMP_DMADBG) {
        int reg;
        for (reg = AR_DMADBG_0, i = 0; reg <= AR_DMADBG_7; reg += 4) {
            printf("0x%X: 0x%.8X\n", reg, OS_REG_READ(ah, reg));
        }
    }
#undef N
}
Ejemplo n.º 4
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.º 5
0
static const HAL_REGRANGE ar9300PublicRegs[] = {
    /* NB: keep these sorted by address */
    { AR_CR, AR_IER },
    { AR_TXCFG, AR_RXCFG },
    { AR_MIBC, AR_MACMISC },
    { AR_Q0_TXDP, AR_QTXDP(9) },
    { AR_Q_TXE },
    { AR_Q_TXD },
    { AR_Q0_CBRCFG, AR_QCBRCFG(9) },
    { AR_Q0_RDYTIMECFG, AR_QRDYTIMECFG(9) },
    { AR_Q_ONESHOTARM_SC },
    { AR_Q_ONESHOTARM_CC },
    { AR_Q0_MISC, AR_QMISC(9) },
    { AR_Q0_STS, AR_QSTS(9) },
    { AR_Q_RDYTIMESHDN },
    { AR_D0_QCUMASK, AR_DQCUMASK(9) },
    { AR_D0_LCL_IFS, AR_DLCL_IFS(9) },
    { AR_D0_RETRY_LIMIT, AR_DRETRY_LIMIT(9) },
    { AR_D0_CHNTIME, AR_DCHNTIME(9) },
    { AR_D0_MISC, AR_DMISC(9) },
    { AR_D_SEQNUM },
    { AR_D_GBL_IFS_SIFS },
    { AR_D_GBL_IFS_SLOT },
    { AR_D_GBL_IFS_EIFS },
    { AR_D_GBL_IFS_MISC },
    { AR_D_TXPSE },
#ifdef notdef
    { AR_D_TXBLK_DATA(0),  /* XXX?? */ },
#endif
//  { AR_RC, AR_QSM },
//  { AR_STA_ID0, AR_SEQ_MASK },