XilinxProcessorIPLib/drivers/axidma/src/xaxidma_bdring.c
int XAxiDma_BdRingFromHw(XAxiDma_BdRing * RingPtr, int BdLimit,
			     XAxiDma_Bd ** BdSetPtr)
{
	XAxiDma_Bd *CurBdPtr;
	int BdCount;
	int BdPartialCount;
	u32 BdSts;
	u32 BdCr;

	CurBdPtr = RingPtr->HwHead;
	BdCount = 0;
	BdPartialCount = 0;
	BdSts = 0;
	BdCr = 0;

	/* If no BDs in work group, then there's nothing to search */
	if (RingPtr->HwCnt == 0) {
		*BdSetPtr = (XAxiDma_Bd *)NULL;

		return 0;
	}

	if (BdLimit > RingPtr->HwCnt) {
		BdLimit = RingPtr->HwCnt;
	}

	/* Starting at HwHead, keep moving forward in the list until:
	 *  - A BD is encountered with its completed bit clear in the status
	 *    word which means hardware has not completed processing of that
	 *    BD.
	 *  - RingPtr->HwTail is reached
	 *  - The number of requested BDs has been processed
	 */

	while (BdCount < BdLimit) {
		/* Read the status */
		XAXIDMA_CACHE_INVALIDATE(CurBdPtr);
		BdSts = XAxiDma_BdRead(CurBdPtr, XAXIDMA_BD_STS_OFFSET);
		BdCr = XAxiDma_BdRead(CurBdPtr, XAXIDMA_BD_CTRL_LEN_OFFSET);

		/* If the hardware still hasn't processed this BD then we are
		 * done
		 */
		if (!(BdSts & XAXIDMA_BD_STS_COMPLETE_MASK)) {
			break;
		}

		BdCount++;

		/* Hardware has processed this BD so check the "last" bit. If
		 * it is clear, then there are more BDs for the current packet.
		 * Keep a count of these partial packet BDs.
		 *
		 * For tx BDs, EOF bit is in the control word
		 * For rx BDs, EOF bit is in the status word
		 */
		if (((!(RingPtr->IsRxChannel) &&
		(BdCr & XAXIDMA_BD_CTRL_TXEOF_MASK)) ||
		((RingPtr->IsRxChannel) && (BdSts &
			XAXIDMA_BD_STS_RXEOF_MASK)))) {

			BdPartialCount = 0;
		}
		else {
			BdPartialCount++;
		}

		if (RingPtr->Cyclic) {
			BdSts = BdSts & ~XAXIDMA_BD_STS_COMPLETE_MASK;
			XAxiDma_BdWrite(CurBdPtr, XAXIDMA_BD_STS_OFFSET, BdSts);
			XAXIDMA_CACHE_FLUSH(CurBdPtr);
		}

		/* Reached the end of the work group */
		if (CurBdPtr == RingPtr->HwTail) {
			break;
		}

		/* Move on to the next BD in work group */
		CurBdPtr = (XAxiDma_Bd *)((void *)XAxiDma_BdRingNext(RingPtr, CurBdPtr));
	}

	/* Subtract off any partial packet BDs found */
	BdCount -= BdPartialCount;

	/* If BdCount is non-zero then BDs were found to return. Set return
	 * parameters, update pointers and counters, return success
	 */
	if (BdCount) {
		*BdSetPtr = RingPtr->HwHead;
		if (!RingPtr->Cyclic) {
			RingPtr->HwCnt -= BdCount;
			RingPtr->PostCnt += BdCount;
		}
		XAXIDMA_RING_SEEKAHEAD(RingPtr, RingPtr->HwHead, BdCount);

		return BdCount;
	}
	else {
		*BdSetPtr = (XAxiDma_Bd *)NULL;

		return 0;
	}
}
/*****************************************************************************/
/**
 * Returns a set of BD(s) that have been processed by hardware. The returned
 * BDs may be examined by the application to determine the outcome of the DMA
 * transactions. Once the BDs have been examined, the application must call
 * XAxiDma_BdRingFree() in the same order which they were retrieved here.
 *
 * Example:
 *
 * <pre>
 *        NumBd = XAxiDma_BdRingFromHw(MyRingPtr, XAXIDMA_ALL_BDS, &MyBdSet);
 *
 *        if (NumBd == 0)
 *        {
 *           // hardware has nothing ready for us yet
 *        }
 *
 *        CurBd = MyBdSet;
 *        for (i=0; i<NumBd; i++)
 *        {
 *           // Examine CurBd for post processing.....
 *
 *           // Onto next BD
 *           CurBd = XAxiDma_BdRingNext(MyRingPtr, CurBd);
 *        }
 *
 *        XAxiDma_BdRingFree(MyRingPtr, NumBd, MyBdSet); // Return the list
 * </pre>
 *
 * A more advanced use of this function may allocate multiple sets of BDs.
 * They must be retrieved from hardware and freed in the correct sequence:
 * <pre>
 *        // Legal
 *        XAxiDma_BdRingFromHw(MyRingPtr, NumBd1, &MySet1);
 *        XAxiDma_BdRingFree(MyRingPtr, NumBd1, MySet1);
 *
 *        // Legal
 *        XAxiDma_BdRingFromHw(MyRingPtr, NumBd1, &MySet1);
 *        XAxiDma_BdRingFromHw(MyRingPtr, NumBd2, &MySet2);
 *        XAxiDma_BdRingFree(MyRingPtr, NumBd1, MySet1);
 *        XAxiDma_BdRingFree(MyRingPtr, NumBd2, MySet2);
 *
 *        // Not legal
 *        XAxiDma_BdRingFromHw(MyRingPtr, NumBd1, &MySet1);
 *        XAxiDma_BdRingFromHw(MyRingPtr, NumBd2, &MySet2);
 *        XAxiDma_BdRingFree(MyRingPtr, NumBd2, MySet2);
 *        XAxiDma_BdRingFree(MyRingPtr, NumBd1, MySet1);
 * </pre>
 *
 * If hardware has partially completed a packet spanning multiple BDs, then
 * none of the BDs for that packet will be included in the results.
 *
 * @param	RingPtr is a pointer to the descriptor ring instance to be
 *		worked on.
 * @param	BdLimit is the maximum number of BDs to return in the set. Use
 *		XAXIDMA_ALL_BDS to return all BDs that have been processed.
 * @param	BdSetPtr is an output parameter, it points to the first BD
 *		available for examination.
 *
 * @return	The number of BDs processed by hardware. A value of 0 indicates
 *		that no data is available. No more than BdLimit BDs will be
 *		returned.
 *
 * @note	Treat BDs returned by this function as read-only.
 *
 * 		This function should not be preempted by another XAxiDma ring
 *		function call that modifies the BD space. It is the caller's
 *		responsibility to provide a mutual exclusion mechanism.
 *
 *		This function can be used only when DMA is in SG mode
 *
 *****************************************************************************/
Returns a set of BD(s) that have been processed by hardware. The returned
BDs may be examined by the application to determine the outcome of the DMA
transactions. Once the BDs have been examined, the application must call
XAxiDma_BdRingFree() in the same order which they were retrieved here.





if (NumBd == 0)
{
hardware has nothing ready for us yet
}







A more advanced use of this function may allocate multiple sets of BDs.





If hardware has partially completed a packet spanning multiple BDs, then
none of the BDs for that packet will be included in the results.

@param       RingPtr is a pointer to the descriptor ring instance to be
worked on.
@param       BdLimit is the maximum number of BDs to return in the set. Use
XAXIDMA_ALL_BDS to return all BDs that have been processed.
@param       BdSetPtr is an output parameter, it points to the first BD
available for examination.

@return      The number of BDs processed by hardware. A value of 0 indicates
that no data is available. No more than BdLimit BDs will be
returned.

@note        Treat BDs returned by this function as read-only.

This function should not be preempted by another XAxiDma ring
function call that modifies the BD space. It is the caller's
responsibility to provide a mutual exclusion mechanism.

This function can be used only when DMA is in SG mode
Returns a set of BD ( s ) that have been processed by hardware . The returned BDs may be examined by the application to determine the outcome of the DMA transactions . Once the BDs have been examined the application must call XAxiDma_BdRingFree () in the same order which they were retrieved here . if ( NumBd == 0 ) { hardware has nothing ready for us yet } A more advanced use of this function may allocate multiple sets of BDs . If hardware has partially completed a packet spanning multiple BDs then none of the BDs for that packet will be included in the results . @param RingPtr is a pointer to the descriptor ring instance to be worked on . @param BdLimit is the maximum number of BDs to return in the set . Use XAXIDMA_ALL_BDS to return all BDs that have been processed . @param BdSetPtr is an output parameter it points to the first BD available for examination . @return The number of BDs processed by hardware . A value of 0 indicates that no data is available . No more than BdLimit BDs will be returned . @note Treat BDs returned by this function as read - only . This function should not be preempted by another XAxiDma ring function call that modifies the BD space . It is the caller ' s responsibility to provide a mutual exclusion mechanism . This function can be used only when DMA is in SG mode
int XAxiDma_BdRingFromHw(XAxiDma_BdRing * RingPtr, int BdLimit,
			     XAxiDma_Bd ** BdSetPtr)
{
	XAxiDma_Bd *CurBdPtr;
	int BdCount;
	int BdPartialCount;
	u32 BdSts;
	u32 BdCr;
	CurBdPtr = RingPtr->HwHead;
	BdCount = 0;
	BdPartialCount = 0;
	BdSts = 0;
	BdCr = 0;
	if (RingPtr->HwCnt == 0) {
		*BdSetPtr = (XAxiDma_Bd *)NULL;
		return 0;
	}
	if (BdLimit > RingPtr->HwCnt) {
		BdLimit = RingPtr->HwCnt;
	}
	while (BdCount < BdLimit) {
		XAXIDMA_CACHE_INVALIDATE(CurBdPtr);
		BdSts = XAxiDma_BdRead(CurBdPtr, XAXIDMA_BD_STS_OFFSET);
		BdCr = XAxiDma_BdRead(CurBdPtr, XAXIDMA_BD_CTRL_LEN_OFFSET);
		if (!(BdSts & XAXIDMA_BD_STS_COMPLETE_MASK)) {
			break;
		}
		BdCount++;
		if (((!(RingPtr->IsRxChannel) &&
		(BdCr & XAXIDMA_BD_CTRL_TXEOF_MASK)) ||
		((RingPtr->IsRxChannel) && (BdSts &
			XAXIDMA_BD_STS_RXEOF_MASK)))) {
			BdPartialCount = 0;
		}
		else {
			BdPartialCount++;
		}
		if (RingPtr->Cyclic) {
			BdSts = BdSts & ~XAXIDMA_BD_STS_COMPLETE_MASK;
			XAxiDma_BdWrite(CurBdPtr, XAXIDMA_BD_STS_OFFSET, BdSts);
			XAXIDMA_CACHE_FLUSH(CurBdPtr);
		}
		if (CurBdPtr == RingPtr->HwTail) {
			break;
		}
		CurBdPtr = (XAxiDma_Bd *)((void *)XAxiDma_BdRingNext(RingPtr, CurBdPtr));
	}
	BdCount -= BdPartialCount;
	if (BdCount) {
		*BdSetPtr = RingPtr->HwHead;
		if (!RingPtr->Cyclic) {
			RingPtr->HwCnt -= BdCount;
			RingPtr->PostCnt += BdCount;
		}
		XAXIDMA_RING_SEEKAHEAD(RingPtr, RingPtr->HwHead, BdCount);
		return BdCount;
	}
	else {
		*BdSetPtr = (XAxiDma_Bd *)NULL;
		return 0;
	}
}
int XAxiDma_BdRingFromHw ( XAxiDma_BdRing * RingPtr , int BdLimit , XAxiDma_Bd * * BdSetPtr ) { XAxiDma_Bd * CurBdPtr ; int BdCount ; int BdPartialCount ; u32 BdSts ; u32 BdCr ; CurBdPtr = RingPtr -> HwHead ; BdCount = 0 ; BdPartialCount = 0 ; BdSts = 0 ; BdCr = 0 ; if ( RingPtr -> HwCnt == 0 ) { * BdSetPtr = ( XAxiDma_Bd * ) NULL ; return 0 ; } if ( BdLimit > RingPtr -> HwCnt ) { BdLimit = RingPtr -> HwCnt ; } while ( BdCount < BdLimit ) { XAXIDMA_CACHE_INVALIDATE ( CurBdPtr ) ; BdSts = XAxiDma_BdRead ( CurBdPtr , XAXIDMA_BD_STS_OFFSET ) ; BdCr = XAxiDma_BdRead ( CurBdPtr , XAXIDMA_BD_CTRL_LEN_OFFSET ) ; if ( ! ( BdSts & XAXIDMA_BD_STS_COMPLETE_MASK ) ) { break ; } BdCount ++ ; if ( ( ( ! ( RingPtr -> IsRxChannel ) && ( BdCr & XAXIDMA_BD_CTRL_TXEOF_MASK ) ) || ( ( RingPtr -> IsRxChannel ) && ( BdSts & XAXIDMA_BD_STS_RXEOF_MASK ) ) ) ) { BdPartialCount = 0 ; } else { BdPartialCount ++ ; } if ( RingPtr -> Cyclic ) { BdSts = BdSts & ~ XAXIDMA_BD_STS_COMPLETE_MASK ; XAxiDma_BdWrite ( CurBdPtr , XAXIDMA_BD_STS_OFFSET , BdSts ) ; XAXIDMA_CACHE_FLUSH ( CurBdPtr ) ; } if ( CurBdPtr == RingPtr -> HwTail ) { break ; } CurBdPtr = ( XAxiDma_Bd * ) ( ( void * ) XAxiDma_BdRingNext ( RingPtr , CurBdPtr ) ) ; } BdCount -= BdPartialCount ; if ( BdCount ) { * BdSetPtr = RingPtr -> HwHead ; if ( ! RingPtr -> Cyclic ) { RingPtr -> HwCnt -= BdCount ; RingPtr -> PostCnt += BdCount ; } XAXIDMA_RING_SEEKAHEAD ( RingPtr , RingPtr -> HwHead , BdCount ) ; return BdCount ; } else { * BdSetPtr = ( XAxiDma_Bd * ) NULL ; return 0 ; } }
Returns a set of BD(s) that have been processed by hardware.
Returns a set of BD ( s ) that have been processed by hardware .
/* If no BDs in work group, then there's nothing to search */ /* Starting at HwHead, keep moving forward in the list until:
	 *  - A BD is encountered with its completed bit clear in the status
	 *    word which means hardware has not completed processing of that
	 *    BD.
	 *  - RingPtr->HwTail is reached
	 *  - The number of requested BDs has been processed
	 */ /* Read the status */ /* If the hardware still hasn't processed this BD then we are
		 * done
		 */ /* Hardware has processed this BD so check the "last" bit. If
		 * it is clear, then there are more BDs for the current packet.
		 * Keep a count of these partial packet BDs.
		 *
		 * For tx BDs, EOF bit is in the control word
		 * For rx BDs, EOF bit is in the status word
		 */ /* Reached the end of the work group */ /* Move on to the next BD in work group */ /* Subtract off any partial packet BDs found */ /* If BdCount is non-zero then BDs were found to return. Set return
	 * parameters, update pointers and counters, return success
	 */