📄 ar5212_xmit.c
字号:
(1<<0x08)|(1<<0x0c)|(1<<0x1b)|(1<<0x1a)|(1<<0x1e)|(1<<0x19)|\ (1<<0x1d)|(1<<0x18)|(1<<0x1c))#define isValidTxRate(_r) ((1<<(_r)) & VALID_TX_RATES)HAL_BOOLar5212SetupTxDesc(struct ath_hal *ah, struct ath_desc *ds, u_int pktLen, u_int hdrLen, HAL_PKT_TYPE type, u_int txPower, u_int txRate0, u_int txTries0, u_int keyIx, u_int antMode, u_int flags, u_int rtsctsRate, u_int rtsctsDuration, u_int compicvLen, u_int compivLen, u_int comp){#define RTSCTS (HAL_TXDESC_RTSENA|HAL_TXDESC_CTSENA) struct ar5212_desc *ads = AR5212DESC(ds); struct ath_hal_5212 *ahp = AH5212(ah); (void) hdrLen; HALASSERT(txTries0 != 0); HALASSERT(isValidPktType(type)); HALASSERT(isValidTxRate(txRate0)); HALASSERT((flags & RTSCTS) != RTSCTS); /* XXX validate antMode */ txPower = (txPower + ahp->ah_txPowerIndexOffset ); if(txPower > 63) txPower=63; ads->ds_ctl0 = (pktLen & AR_FrameLen) | (txPower << AR_XmitPower_S) | (flags & HAL_TXDESC_VEOL ? AR_VEOL : 0) | (flags & HAL_TXDESC_CLRDMASK ? AR_ClearDestMask : 0) | SM(antMode, AR_AntModeXmit) | (flags & HAL_TXDESC_INTREQ ? AR_TxInterReq : 0) ; ads->ds_ctl1 = (type << AR_FrmType_S) | (flags & HAL_TXDESC_NOACK ? AR_NoAck : 0) | (comp << AR_CompProc_S) | (compicvLen << AR_CompICVLen_S) | (compivLen << AR_CompIVLen_S) ; ads->ds_ctl2 = SM(txTries0, AR_XmitDataTries0) ; ads->ds_ctl3 = (txRate0 << AR_XmitRate0_S) ; if (keyIx != HAL_TXKEYIX_INVALID) { /* XXX validate key index */ ads->ds_ctl1 |= SM(keyIx, AR_DestIdx); ads->ds_ctl0 |= AR_DestIdxValid; } if (flags & RTSCTS) { if (!isValidTxRate(rtsctsRate)) { HALDEBUG(ah, "%s: invalid rts/cts rate 0x%x\n", __func__, rtsctsRate); return AH_FALSE; } /* XXX validate rtsctsDuration */ ads->ds_ctl0 |= (flags & HAL_TXDESC_CTSENA ? AR_CTSEnable : 0) | (flags & HAL_TXDESC_RTSENA ? AR_RTSCTSEnable : 0) ; ads->ds_ctl2 |= SM(rtsctsDuration, AR_RTSCTSDuration); ads->ds_ctl3 |= (rtsctsRate << AR_RTSCTSRate_S); } return AH_TRUE;#undef RTSCTS}HAL_BOOLar5212SetupXTxDesc(struct ath_hal *ah, struct ath_desc *ds, u_int txRate1, u_int txTries1, u_int txRate2, u_int txTries2, u_int txRate3, u_int txTries3){ struct ar5212_desc *ads = AR5212DESC(ds); if (txTries1) { HALASSERT(isValidTxRate(txRate1)); ads->ds_ctl2 |= SM(txTries1, AR_XmitDataTries1); ads->ds_ctl3 |= (txRate1 << AR_XmitRate1_S); } if (txTries2) { HALASSERT(isValidTxRate(txRate2)); ads->ds_ctl2 |= SM(txTries2, AR_XmitDataTries2); ads->ds_ctl3 |= (txRate2 << AR_XmitRate2_S); } if (txTries3) { HALASSERT(isValidTxRate(txRate3)); ads->ds_ctl2 |= SM(txTries3, AR_XmitDataTries3); ads->ds_ctl3 |= (txRate3 << AR_XmitRate3_S); } return AH_TRUE;}voidar5212IntrReqTxDesc(struct ath_hal *ah, struct ath_desc *ds){ struct ar5212_desc *ads = AR5212DESC(ds);#ifdef AH_NEED_DESC_SWAP ads->ds_ctl0 |= __bswap32(AR_TxInterReq);#else ads->ds_ctl0 |= AR_TxInterReq;#endif}HAL_BOOLar5212FillTxDesc(struct ath_hal *ah, struct ath_desc *ds, u_int segLen, HAL_BOOL firstSeg, HAL_BOOL lastSeg, const struct ath_desc *ds0){ struct ar5212_desc *ads = AR5212DESC(ds); HALASSERT((segLen &~ AR_BufLen) == 0); if (firstSeg) { /* * First descriptor, don't clobber xmit control data * setup by ar5212SetupTxDesc. */ ads->ds_ctl1 |= segLen | (lastSeg ? 0 : AR_More); } else if (lastSeg) { /* !firstSeg && lastSeg */ /* * Last descriptor in a multi-descriptor frame, * copy the multi-rate transmit parameters from * the first frame for processing on completion. */ ads->ds_ctl0 = 0; ads->ds_ctl1 = segLen;#ifdef AH_NEED_DESC_SWAP ads->ds_ctl2 = __bswap32(AR5212DESC_CONST(ds0)->ds_ctl2); ads->ds_ctl3 = __bswap32(AR5212DESC_CONST(ds0)->ds_ctl3);#else ads->ds_ctl2 = AR5212DESC_CONST(ds0)->ds_ctl2; ads->ds_ctl3 = AR5212DESC_CONST(ds0)->ds_ctl3;#endif } else { /* !firstSeg && !lastSeg */ /* * Intermediate descriptor in a multi-descriptor frame. */ ads->ds_ctl0 = 0; ads->ds_ctl1 = segLen | AR_More; ads->ds_ctl2 = 0; ads->ds_ctl3 = 0; } ads->ds_txstatus0 = ads->ds_txstatus1 = 0; return AH_TRUE;}#ifdef AH_NEED_DESC_SWAP/* Swap transmit descriptor */static __inline voidar5212SwapTxDesc(struct ath_desc *ds){ ds->ds_data = __bswap32(ds->ds_data); ds->ds_ctl0 = __bswap32(ds->ds_ctl0); ds->ds_ctl1 = __bswap32(ds->ds_ctl1); ds->ds_hw[0] = __bswap32(ds->ds_hw[0]); ds->ds_hw[1] = __bswap32(ds->ds_hw[1]); ds->ds_hw[2] = __bswap32(ds->ds_hw[2]); ds->ds_hw[3] = __bswap32(ds->ds_hw[3]);}#endif/* * Processing of HW TX descriptor. */HAL_STATUSar5212ProcTxDesc(struct ath_hal *ah, struct ath_desc *ds){ struct ar5212_desc *ads = AR5212DESC(ds); #ifdef AH_NEED_DESC_SWAP if ((ads->ds_txstatus1 & __bswap32(AR_Done)) == 0) return HAL_EINPROGRESS; ar5212SwapTxDesc(ds);#else if ((ads->ds_txstatus1 & AR_Done) == 0) return HAL_EINPROGRESS;#endif /* Update software copies of the HW status */ ds->ds_txstat->ts_seqnum = MS(ads->ds_txstatus1, AR_SeqNum); ds->ds_txstat->ts_tstamp = MS(ads->ds_txstatus0, AR_SendTimestamp); ds->ds_txstat->ts_status = 0; if ((ads->ds_txstatus0 & AR_FrmXmitOK) == 0) { if (ads->ds_txstatus0 & AR_ExcessiveRetries) ds->ds_txstat->ts_status |= HAL_TXERR_XRETRY; if (ads->ds_txstatus0 & AR_Filtered) ds->ds_txstat->ts_status |= HAL_TXERR_FILT; if (ads->ds_txstatus0 & AR_FIFOUnderrun) ds->ds_txstat->ts_status |= HAL_TXERR_FIFO; } /* * Extract the transmit rate used and mark the rate as * ``alternate'' if it wasn't the series 0 rate. */ switch (MS(ads->ds_txstatus1, AR_FinalTSIndex)) { case 0: ds->ds_txstat->ts_rate = MS(ads->ds_ctl3, AR_XmitRate0); break; case 1: ds->ds_txstat->ts_rate = MS(ads->ds_ctl3, AR_XmitRate1) | HAL_TXSTAT_ALTRATE; break; case 2: ds->ds_txstat->ts_rate = MS(ads->ds_ctl3, AR_XmitRate2) | HAL_TXSTAT_ALTRATE; break; case 3: ds->ds_txstat->ts_rate = MS(ads->ds_ctl3, AR_XmitRate3) | HAL_TXSTAT_ALTRATE; break; } ds->ds_txstat->ts_rssi = MS(ads->ds_txstatus1, AR_AckSigStrength); ds->ds_txstat->ts_shortretry = MS(ads->ds_txstatus0, AR_RTSFailCnt); ds->ds_txstat->ts_longretry = MS(ads->ds_txstatus0, AR_DataFailCnt); /* * The retry count has the number of un-acked tries for the * final series used. When doing multi-rate retry we must * fixup the retry count by adding in the try counts for * each series that was fully-processed. Beware that this * takes values from the try counts in the final descriptor. * These are not required by the hardware. We assume they * are placed there by the driver as otherwise we have no * access and the driver can't do the calculation because it * doesn't know the descriptor format. */ switch (MS(ads->ds_txstatus1, AR_FinalTSIndex)) { case 3: ds->ds_txstat->ts_longretry += MS(ads->ds_ctl2, AR_XmitDataTries2); case 2: ds->ds_txstat->ts_longretry += MS(ads->ds_ctl2, AR_XmitDataTries1); case 1: ds->ds_txstat->ts_longretry += MS(ads->ds_ctl2, AR_XmitDataTries0); } ds->ds_txstat->ts_virtcol = MS(ads->ds_txstatus0, AR_VirtCollCnt); ds->ds_txstat->ts_antenna = (ads->ds_txstatus1 & AR_XmitAtenna ? 2 : 1); return HAL_OK;}/* * Determine which tx queues need interrupt servicing. */voidar5212GetTxIntrQueue(struct ath_hal *ah, u_int32_t *txqs){ struct ath_hal_5212 *ahp = AH5212(ah); *txqs &= ahp->ah_intrTxqs; ahp->ah_intrTxqs &= ~(*txqs);}#ifdef AH_PRIVATE_DIAGvoidar5212_ContTxMode(struct ath_hal *ah, struct ath_desc *ds, int mode){ static int qnum =0; int i; unsigned int qbits, val, val1, val2; int prefetch; struct ar5212_desc *ads = AR5212DESC(ds); if(mode == 10) return; if (mode==7) { // print status from the cont tx desc if (ads) { val1 = ads->ds_txstatus0; val2 = ads->ds_txstatus1; ath_hal_printf(ah, "s0(%x) s1(%x)\n", (unsigned)val1, (unsigned)val2); } ath_hal_printf(ah, "txe(%x) txd(%x)\n", OS_REG_READ(ah, AR_Q_TXE), OS_REG_READ(ah, AR_Q_TXD) ); 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; ath_hal_printf(ah, "[%d] %x %d\n", i, val, val2); } return; } if (mode==8) { // set TXE for qnum OS_REG_WRITE(ah, AR_Q_TXE, 1<<qnum); return; } if (mode==9) { prefetch = (int)ds; return; } if (mode >= 1) { // initiate cont tx operation /* Disable AGC to A2 */ qnum = (int) ds; 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) | (DIAG_FORCE_RXCLR+DIAG_IGNORE_NAV)) ); 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_VIRT_COLL_POLICY) +(AR_D_MISC_VIR_COL_HANDLING_IGNORE) ); 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) & ~(DIAG_FORCE_RXCLR+DIAG_IGNORE_NAV)) ); }}#endif#endif /* AH_SUPPORT_AR5212 */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -