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