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

📄 ar5212_xmit.c.svn-base

📁 最新之atheros芯片driver source code, 基于linux操作系统,內含atheros芯片HAL全部代码
💻 SVN-BASE
📖 第 1 页 / 共 2 页
字号:
	else		ahp->ah_txErrInterruptMask &= ~(1 << q);	if (qi->tqi_qflags & HAL_TXQ_TXDESCINT_ENABLE)		ahp->ah_txDescInterruptMask |= 1 << q;	else		ahp->ah_txDescInterruptMask &= ~(1 << q);	if (qi->tqi_qflags & HAL_TXQ_TXEOLINT_ENABLE)		ahp->ah_txEolInterruptMask |= 1 << q;	else		ahp->ah_txEolInterruptMask &= ~(1 << q);	if (qi->tqi_qflags & HAL_TXQ_TXURNINT_ENABLE)		ahp->ah_txUrnInterruptMask |= 1 << q;	else		ahp->ah_txUrnInterruptMask &= ~(1 << q);	setTxQInterrupts(ah, qi);	return AH_TRUE;}/* * Get the TXDP for the specified queue */uint32_tar5212GetTxDP(struct ath_hal *ah, u_int q){	HALASSERT(q < AH_PRIVATE(ah)->ah_caps.halTotalQueues);	return OS_REG_READ(ah, AR_QTXDP(q));}/* * Set the TxDP for the specified queue */HAL_BOOLar5212SetTxDP(struct ath_hal *ah, u_int q, uint32_t txdp){	HALASSERT(q < AH_PRIVATE(ah)->ah_caps.halTotalQueues);	HALASSERT(AH5212(ah)->ah_txq[q].tqi_type != HAL_TX_QUEUE_INACTIVE);	/*	 * Make sure that TXE is deasserted before setting the TXDP.  If TXE	 * is still asserted, setting TXDP will have no effect.	 */	HALASSERT((OS_REG_READ(ah, AR_Q_TXE) & (1 << q)) == 0);	OS_REG_WRITE(ah, AR_QTXDP(q), txdp);	return AH_TRUE;}/* * Set Transmit Enable bits for the specified queue */HAL_BOOLar5212StartTxDma(struct ath_hal *ah, u_int q){	HALASSERT(q < AH_PRIVATE(ah)->ah_caps.halTotalQueues);	HALASSERT(AH5212(ah)->ah_txq[q].tqi_type != HAL_TX_QUEUE_INACTIVE);	HALDEBUG(ah, HAL_DEBUG_TXQUEUE, "%s: queue %u\n", __func__, q);	/* Check to be sure we're not enabling a q that has its TXD bit set. */	HALASSERT((OS_REG_READ(ah, AR_Q_TXD) & (1 << q)) == 0);	OS_REG_WRITE(ah, AR_Q_TXE, 1 << q);	return AH_TRUE;}/* * Return the number of pending frames or 0 if the specified * queue is stopped. */uint32_tar5212NumTxPending(struct ath_hal *ah, u_int q){	uint32_t npend;	HALASSERT(q < AH_PRIVATE(ah)->ah_caps.halTotalQueues);	HALASSERT(AH5212(ah)->ah_txq[q].tqi_type != HAL_TX_QUEUE_INACTIVE);	npend = OS_REG_READ(ah, AR_QSTS(q)) & AR_Q_STS_PEND_FR_CNT;	if (npend == 0) {		/*		 * Pending frame count (PFC) can momentarily go to zero		 * while TXE remains asserted.  In other words a PFC of		 * zero is not sufficient to say that the queue has stopped.		 */		if (OS_REG_READ(ah, AR_Q_TXE) & (1 << q))			npend = 1;		/* arbitrarily return 1 */	}	return npend;}/* * Stop transmit on the specified queue */HAL_BOOLar5212StopTxDma(struct ath_hal *ah, u_int q){	u_int i;	u_int wait;	HALASSERT(q < AH_PRIVATE(ah)->ah_caps.halTotalQueues);	HALASSERT(AH5212(ah)->ah_txq[q].tqi_type != HAL_TX_QUEUE_INACTIVE);	OS_REG_WRITE(ah, AR_Q_TXD, 1 << q);	for (i = 1000; i != 0; i--) {		if (ar5212NumTxPending(ah, q) == 0)			break;		OS_DELAY(100);        /* XXX get actual value */	}#ifdef AH_DEBUG	if (i == 0) {		HALDEBUG(ah, HAL_DEBUG_ANY,		    "%s: queue %u DMA did not stop in 100 msec\n", __func__, q);		HALDEBUG(ah, HAL_DEBUG_ANY,		    "%s: QSTS 0x%x Q_TXE 0x%x Q_TXD 0x%x Q_CBR 0x%x\n", __func__,		    OS_REG_READ(ah, AR_QSTS(q)), OS_REG_READ(ah, AR_Q_TXE),		    OS_REG_READ(ah, AR_Q_TXD), OS_REG_READ(ah, AR_QCBRCFG(q)));		HALDEBUG(ah, HAL_DEBUG_ANY,		    "%s: Q_MISC 0x%x Q_RDYTIMECFG 0x%x Q_RDYTIMESHDN 0x%x\n",		    __func__, OS_REG_READ(ah, AR_QMISC(q)),		    OS_REG_READ(ah, AR_QRDYTIMECFG(q)),		    OS_REG_READ(ah, AR_Q_RDYTIMESHDN));	}#endif /* AH_DEBUG */	/* 2413+ and up can kill packets at the PCU level */	if (ar5212NumTxPending(ah, q) &&	    (IS_2413(ah) || IS_5413(ah) || IS_2425(ah) || IS_2417(ah))) {		uint32_t tsfLow, j;				HALDEBUG(ah, HAL_DEBUG_TXQUEUE,		    "%s: Num of pending TX Frames %d on Q %d\n",		    __func__, ar5212NumTxPending(ah, q), q);				/* Kill last PCU Tx Frame */		/* TODO - save off and restore current values of Q1/Q2? */		for (j = 0; j < 2; j++) {			tsfLow = OS_REG_READ(ah, AR_TSF_L32);			OS_REG_WRITE(ah, AR_QUIET2, SM(100, AR_QUIET2_QUIET_PER) |				     SM(10, AR_QUIET2_QUIET_DUR));			OS_REG_WRITE(ah, AR_QUIET1, AR_QUIET1_QUIET_ENABLE |				     SM(tsfLow >> 10, AR_QUIET1_NEXT_QUIET));			if ((OS_REG_READ(ah, AR_TSF_L32) >> 10) == (tsfLow >> 10)) {				break;			}			HALDEBUG(ah, HAL_DEBUG_ANY,			    "%s: TSF moved while trying to set quiet time "			    "TSF: 0x%08x\n", __func__, tsfLow);			HALASSERT(j < 1); /* TSF shouldn't count twice or reg access is taking forever */		}				OS_REG_SET_BIT(ah, AR_DIAG_SW, AR_DIAG_CHAN_IDLE);				/* Allow the quiet mechanism to do its work */		OS_DELAY(200);		OS_REG_CLR_BIT(ah, AR_QUIET1, AR_QUIET1_QUIET_ENABLE);				/* Give at least 1 millisec more to wait */		wait = 100;				/* Verify all transmit is dead */		while (ar5212NumTxPending(ah, q)) {			if ((--wait) == 0) {				HALDEBUG(ah, HAL_DEBUG_ANY,				    "%s: Failed to stop Tx DMA in %d msec after killing last frame\n",				    __func__, wait);				break;			}			OS_DELAY(10);		}				OS_REG_CLR_BIT(ah, AR_DIAG_SW, AR_DIAG_CHAN_IDLE);	}	OS_REG_WRITE(ah, AR_Q_TXD, 0);	return (i != 0);}/* * Descriptor Access Functions */#define	VALID_PKT_TYPES \	((1<<HAL_PKT_TYPE_NORMAL)|(1<<HAL_PKT_TYPE_ATIM)|\	 (1<<HAL_PKT_TYPE_PSPOLL)|(1<<HAL_PKT_TYPE_PROBE_RESP)|\	 (1<<HAL_PKT_TYPE_BEACON))#define	isValidPktType(_t)	((1<<(_t)) & VALID_PKT_TYPES)#define	VALID_TX_RATES \	((1<<0x0b)|(1<<0x0f)|(1<<0x0a)|(1<<0x0e)|(1<<0x09)|(1<<0x0d)|\	 (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)		     | (flags & HAL_TXDESC_DURENA ? AR_DurUpdateEna : 0)		     ;	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, HAL_DEBUG_ANY,			    "%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)			     |  AR_DurUpdateEna			     ;		ads->ds_ctl3 |= (txRate1 << AR_XmitRate1_S);	}	if (txTries2) {		HALASSERT(isValidTxRate(txRate2));		ads->ds_ctl2 |= SM(txTries2, AR_XmitDataTries2)			     |  AR_DurUpdateEna			     ;		ads->ds_ctl3 |= (txRate2 << AR_XmitRate2_S);	}	if (txTries3) {		HALASSERT(isValidTxRate(txRate3));		ads->ds_ctl2 |= SM(txTries3, AR_XmitDataTries3)			     |  AR_DurUpdateEna			     ;		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 ath_tx_status *ts){	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 */	ts->ts_seqnum = MS(ads->ds_txstatus1, AR_SeqNum);	ts->ts_tstamp = MS(ads->ds_txstatus0, AR_SendTimestamp);	ts->ts_status = 0;	if ((ads->ds_txstatus0 & AR_FrmXmitOK) == 0) {		if (ads->ds_txstatus0 & AR_ExcessiveRetries)			ts->ts_status |= HAL_TXERR_XRETRY;		if (ads->ds_txstatus0 & AR_Filtered)			ts->ts_status |= HAL_TXERR_FILT;		if (ads->ds_txstatus0 & AR_FIFOUnderrun)			ts->ts_status |= HAL_TXERR_FIFO;	}	/*	 * Extract the transmit rate used and mark the rate as	 * ``alternate'' if it wasn't the series 0 rate.	 */	ts->ts_finaltsi = MS(ads->ds_txstatus1, AR_FinalTSIndex);	switch (ts->ts_finaltsi) {	case 0:		ts->ts_rate = MS(ads->ds_ctl3, AR_XmitRate0);		break;	case 1:		ts->ts_rate = MS(ads->ds_ctl3, AR_XmitRate1) |			HAL_TXSTAT_ALTRATE;		break;	case 2:		ts->ts_rate = MS(ads->ds_ctl3, AR_XmitRate2) |			HAL_TXSTAT_ALTRATE;		break;	case 3:		ts->ts_rate = MS(ads->ds_ctl3, AR_XmitRate3) |			HAL_TXSTAT_ALTRATE;		break;	}	ts->ts_rssi = MS(ads->ds_txstatus1, AR_AckSigStrength);	ts->ts_shortretry = MS(ads->ds_txstatus0, AR_RTSFailCnt);	ts->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 (ts->ts_finaltsi) {	case 3: ts->ts_longretry += MS(ads->ds_ctl2, AR_XmitDataTries2);	case 2: ts->ts_longretry += MS(ads->ds_ctl2, AR_XmitDataTries1);	case 1: ts->ts_longretry += MS(ads->ds_ctl2, AR_XmitDataTries0);	}	ts->ts_virtcol = MS(ads->ds_txstatus0, AR_VirtCollCnt);	ts->ts_antenna = (ads->ds_txstatus1 & AR_XmitAtenna ? 2 : 1);	return HAL_OK;}/* * Determine which tx queues need interrupt servicing. */voidar5212GetTxIntrQueue(struct ath_hal *ah, uint32_t *txqs){	struct ath_hal_5212 *ahp = AH5212(ah);	*txqs &= ahp->ah_intrTxqs;	ahp->ah_intrTxqs &= ~(*txqs);}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -