⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ar5212_xmit.c

📁 Atheros wifi driver source code
💻 C
📖 第 1 页 / 共 3 页
字号:
	 (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 + -