Example #1
0
/**
 * Enqueue a set of BDs to hardware that were previously allocated by
 * XEmacPs_BdRingAlloc(). Once this function returns, the argument BD set goes
 * under hardware control. Any changes made to these BDs after this point will
 * corrupt the BD list leading to data corruption and system instability.
 *
 * The set will be rejected if the last BD of the set does not mark the end of
 * a packet (see XEmacPs_BdSetLast()).
 *
 * @param RingPtr is a pointer to the instance to be worked on.
 * @param NumBd is the number of BDs in the set.
 * @param BdSetPtr is the first BD of the set to commit to hardware.
 *
 * @return
 *   - XST_SUCCESS if the set of BDs was accepted and enqueued to hardware.
 *   - XST_FAILURE if the set of BDs was rejected because the last BD of the set
 *     did not have its "last" bit set.
 *   - XST_DMA_SG_LIST_ERROR if this function was called out of sequence with
 *     XEmacPs_BdRingAlloc().
 *
 * @note This function should not be preempted by another XEmacPs_Bd function
 *       call that modifies the BD space. It is the caller's responsibility to
 *       provide a mutual exclusion mechanism.
 *
 *****************************************************************************/
int XEmacPs_BdRingToHw(XEmacPs_BdRing * RingPtr, unsigned NumBd,
			XEmacPs_Bd * BdSetPtr)
{
	XEmacPs_Bd *CurBdPtr;
	unsigned i;

	/* if no bds to process, simply return. */
	if (0 == NumBd)
		return (XST_SUCCESS);

	/* Make sure we are in sync with XEmacPs_BdRingAlloc() */
	if ((RingPtr->PreCnt < NumBd) || (RingPtr->PreHead != BdSetPtr)) {
		return (XST_DMA_SG_LIST_ERROR);
	}

	CurBdPtr = BdSetPtr;
	for (i = 0; i < NumBd; i++) {
		XEMACPS_CACHE_FLUSH(CurBdPtr);
		CurBdPtr = XEmacPs_BdRingNext(RingPtr, CurBdPtr);
	}

	/* Adjust ring pointers & counters */
	XEMACPS_RING_SEEKAHEAD(RingPtr, RingPtr->PreHead, NumBd);
	RingPtr->PreCnt -= NumBd;

	RingPtr->HwTail = CurBdPtr;
	RingPtr->HwCnt += NumBd;

	return (XST_SUCCESS);
}
/**
 * Enqueue a set of BDs to hardware that were previously allocated by
 * XEmacPs_BdRingAlloc(). Once this function returns, the argument BD set goes
 * under hardware control. Any changes made to these BDs after this point will
 * corrupt the BD list leading to data corruption and system instability.
 *
 * The set will be rejected if the last BD of the set does not mark the end of
 * a packet (see XEmacPs_BdSetLast()).
 *
 * @param RingPtr is a pointer to the instance to be worked on.
 * @param NumBd is the number of BDs in the set.
 * @param BdSetPtr is the first BD of the set to commit to hardware.
 *
 * @return
 *   - XST_SUCCESS if the set of BDs was accepted and enqueued to hardware.
 *   - XST_FAILURE if the set of BDs was rejected because the last BD of the set
 *     did not have its "last" bit set.
 *   - XST_DMA_SG_LIST_ERROR if this function was called out of sequence with
 *     XEmacPs_BdRingAlloc().
 *
 * @note This function should not be preempted by another XEmacPs_Bd function
 *       call that modifies the BD space. It is the caller's responsibility to
 *       provide a mutual exclusion mechanism.
 *
 *****************************************************************************/
LONG XEmacPs_BdRingToHw(XEmacPs_BdRing * RingPtr, u32 NumBd,
			XEmacPs_Bd * BdSetPtr)
{
	XEmacPs_Bd *CurBdPtr;
	u32 i;
	LONG Status;
	/* if no bds to process, simply return. */
	if (0U == NumBd){
		Status = (LONG)(XST_SUCCESS);
	} else {
	/* Make sure we are in sync with XEmacPs_BdRingAlloc() */
	if ((RingPtr->PreCnt < NumBd) || (RingPtr->PreHead != BdSetPtr)) {
			Status = (LONG)(XST_DMA_SG_LIST_ERROR);
		} else {
	CurBdPtr = BdSetPtr;
			for (i = 0U; i < NumBd; i++) {
				CurBdPtr = (XEmacPs_Bd *)((void *)XEmacPs_BdRingNext(RingPtr, CurBdPtr));
	}
	/* Adjust ring pointers & counters */
	XEMACPS_RING_SEEKAHEAD(RingPtr, RingPtr->PreHead, NumBd);
	RingPtr->PreCnt -= NumBd;
	RingPtr->HwTail = CurBdPtr;
	RingPtr->HwCnt += NumBd;

			Status = (LONG)(XST_SUCCESS);
		}
	}
	return Status;
}
Example #3
0
/**
 * Reserve locations in the BD list. The set of returned BDs may be modified
 * in preparation for future DMA transaction(s). Once the BDs are ready to be
 * submitted to hardware, the user must call XEmacPs_BdRingToHw() in the same
 * order which they were allocated here. Example:
 *
 * <pre>
 *        NumBd = 2;
 *        Status = XEmacPs_BdRingAlloc(MyRingPtr, NumBd, &MyBdSet);
 *
 *        if (Status != XST_SUCCESS)
 *        {
 *            // Not enough BDs available for the request
 *        }
 *
 *        CurBd = MyBdSet;
 *        for (i=0; i<NumBd; i++)
 *        {
 *            // Prepare CurBd.....
 *
 *            // Onto next BD
 *            CurBd = XEmacPs_BdRingNext(MyRingPtr, CurBd);
 *        }
 *
 *        // Give list to hardware
 *        Status = XEmacPs_BdRingToHw(MyRingPtr, NumBd, MyBdSet);
 * </pre>
 *
 * A more advanced use of this function may allocate multiple sets of BDs.
 * They must be allocated and given to hardware in the correct sequence:
 * <pre>
 *        // Legal
 *        XEmacPs_BdRingAlloc(MyRingPtr, NumBd1, &MySet1);
 *        XEmacPs_BdRingToHw(MyRingPtr, NumBd1, MySet1);
 *
 *        // Legal
 *        XEmacPs_BdRingAlloc(MyRingPtr, NumBd1, &MySet1);
 *        XEmacPs_BdRingAlloc(MyRingPtr, NumBd2, &MySet2);
 *        XEmacPs_BdRingToHw(MyRingPtr, NumBd1, MySet1);
 *        XEmacPs_BdRingToHw(MyRingPtr, NumBd2, MySet2);
 *
 *        // Not legal
 *        XEmacPs_BdRingAlloc(MyRingPtr, NumBd1, &MySet1);
 *        XEmacPs_BdRingAlloc(MyRingPtr, NumBd2, &MySet2);
 *        XEmacPs_BdRingToHw(MyRingPtr, NumBd2, MySet2);
 *        XEmacPs_BdRingToHw(MyRingPtr, NumBd1, MySet1);
 * </pre>
 *
 * Use the API defined in xemacps_bd.h to modify individual BDs. Traversal
 * of the BD set can be done using XEmacPs_BdRingNext() and
 * XEmacPs_BdRingPrev().
 *
 * @param RingPtr is a pointer to the BD ring instance to be worked on.
 * @param NumBd is the number of BDs to allocate
 * @param BdSetPtr is an output parameter, it points to the first BD available
 *        for modification.
 *
 * @return
 *   - XST_SUCCESS if the requested number of BDs was returned in the BdSetPtr
 *     parameter.
 *   - XST_FAILURE if there were not enough free BDs to satisfy the request.
 *
 * @note This function should not be preempted by another XEmacPs_Bd function
 *       call that modifies the BD space. It is the caller's responsibility to
 *       provide a mutual exclusion mechanism.
 *
 * @note Do not modify more BDs than the number requested with the NumBd
 *       parameter. Doing so will lead to data corruption and system
 *       instability.
 *
 *****************************************************************************/
int XEmacPs_BdRingAlloc(XEmacPs_BdRing * RingPtr, unsigned NumBd,
			 XEmacPs_Bd ** BdSetPtr)
{
	/* Enough free BDs available for the request? */
	if (RingPtr->FreeCnt < NumBd) {
		return (XST_FAILURE);
	}

	/* Set the return argument and move FreeHead forward */
	*BdSetPtr = RingPtr->FreeHead;
	XEMACPS_RING_SEEKAHEAD(RingPtr, RingPtr->FreeHead, NumBd);
	RingPtr->FreeCnt -= NumBd;
	RingPtr->PreCnt += NumBd;
	return (XST_SUCCESS);
}
/**
 * Reserve locations in the BD list. The set of returned BDs may be modified
 * in preparation for future DMA transaction(s). Once the BDs are ready to be
 * submitted to hardware, the user must call XEmacPs_BdRingToHw() in the same
 * order which they were allocated here. Example:
 *
 * <pre>
 *        NumBd = 2,
 *        Status = XEmacPs_BdRingAlloc(MyRingPtr, NumBd, &MyBdSet),
 *
 *        if (Status != XST_SUCCESS)
 *        {
 *            *Not enough BDs available for the request*
 *        }
 *
 *        CurBd = MyBdSet,
 *        for (i=0; i<NumBd; i++)
 *        {
 *            * Prepare CurBd *.....
 *
 *            * Onto next BD *
 *            CurBd = XEmacPs_BdRingNext(MyRingPtr, CurBd),
 *        }
 *
 *        * Give list to hardware *
 *        Status = XEmacPs_BdRingToHw(MyRingPtr, NumBd, MyBdSet),
 * </pre>
 *
 * A more advanced use of this function may allocate multiple sets of BDs.
 * They must be allocated and given to hardware in the correct sequence:
 * <pre>
 *        * Legal *
 *        XEmacPs_BdRingAlloc(MyRingPtr, NumBd1, &MySet1),
 *        XEmacPs_BdRingToHw(MyRingPtr, NumBd1, MySet1),
 *
 *        * Legal *
 *        XEmacPs_BdRingAlloc(MyRingPtr, NumBd1, &MySet1),
 *        XEmacPs_BdRingAlloc(MyRingPtr, NumBd2, &MySet2),
 *        XEmacPs_BdRingToHw(MyRingPtr, NumBd1, MySet1),
 *        XEmacPs_BdRingToHw(MyRingPtr, NumBd2, MySet2),
 *
 *        * Not legal *
 *        XEmacPs_BdRingAlloc(MyRingPtr, NumBd1, &MySet1),
 *        XEmacPs_BdRingAlloc(MyRingPtr, NumBd2, &MySet2),
 *        XEmacPs_BdRingToHw(MyRingPtr, NumBd2, MySet2),
 *        XEmacPs_BdRingToHw(MyRingPtr, NumBd1, MySet1),
 * </pre>
 *
 * Use the API defined in xemacps_bd.h to modify individual BDs. Traversal
 * of the BD set can be done using XEmacPs_BdRingNext() and
 * XEmacPs_BdRingPrev().
 *
 * @param RingPtr is a pointer to the BD ring instance to be worked on.
 * @param NumBd is the number of BDs to allocate
 * @param BdSetPtr is an output parameter, it points to the first BD available
 *        for modification.
 *
 * @return
 *   - XST_SUCCESS if the requested number of BDs was returned in the BdSetPtr
 *     parameter.
 *   - XST_FAILURE if there were not enough free BDs to satisfy the request.
 *
 * @note This function should not be preempted by another XEmacPs_Bd function
 *       call that modifies the BD space. It is the caller's responsibility to
 *       provide a mutual exclusion mechanism.
 *
 * @note Do not modify more BDs than the number requested with the NumBd
 *       parameter. Doing so will lead to data corruption and system
 *       instability.
 *
 *****************************************************************************/
LONG XEmacPs_BdRingAlloc(XEmacPs_BdRing * RingPtr, u32 NumBd,
			 XEmacPs_Bd ** BdSetPtr)
{
	LONG Status;
	/* Enough free BDs available for the request? */
	if (RingPtr->FreeCnt < NumBd) {
		Status = (LONG)(XST_FAILURE);
	} else {
	/* Set the return argument and move FreeHead forward */
	*BdSetPtr = RingPtr->FreeHead;
	XEMACPS_RING_SEEKAHEAD(RingPtr, RingPtr->FreeHead, NumBd);
	RingPtr->FreeCnt -= NumBd;
	RingPtr->PreCnt += NumBd;
		Status = (LONG)(XST_SUCCESS);
	}
	return Status;
}
Example #5
0
/**
 * Frees a set of BDs that had been previously retrieved with
 * XEmacPs_BdRingFromHw().
 *
 * @param RingPtr is a pointer to the instance to be worked on.
 * @param NumBd is the number of BDs to free.
 * @param BdSetPtr is the head of a list of BDs returned by
 * XEmacPs_BdRingFromHw().
 *
 * @return
 *   - XST_SUCCESS if the set of BDs was freed.
 *   - XST_DMA_SG_LIST_ERROR if this function was called out of sequence with
 *     XEmacPs_BdRingFromHw().
 *
 * @note This function should not be preempted by another XEmacPs_Bd function
 *       call that modifies the BD space. It is the caller's responsibility to
 *       provide a mutual exclusion mechanism.
 *
 *****************************************************************************/
int XEmacPs_BdRingFree(XEmacPs_BdRing * RingPtr, unsigned NumBd,
			XEmacPs_Bd * BdSetPtr)
{
	/* if no bds to process, simply return. */
	if (0 == NumBd)
		return (XST_SUCCESS);

	/* Make sure we are in sync with XEmacPs_BdRingFromHw() */
	if ((RingPtr->PostCnt < NumBd) || (RingPtr->PostHead != BdSetPtr)) {
		return (XST_DMA_SG_LIST_ERROR);
	}

	/* Update pointers and counters */
	RingPtr->FreeCnt += NumBd;
	RingPtr->PostCnt -= NumBd;
	XEMACPS_RING_SEEKAHEAD(RingPtr, RingPtr->PostHead, NumBd);
	return (XST_SUCCESS);
}
/**
 * Frees a set of BDs that had been previously retrieved with
 * XEmacPs_BdRingFromHw().
 *
 * @param RingPtr is a pointer to the instance to be worked on.
 * @param NumBd is the number of BDs to free.
 * @param BdSetPtr is the head of a list of BDs returned by
 * XEmacPs_BdRingFromHw().
 *
 * @return
 *   - XST_SUCCESS if the set of BDs was freed.
 *   - XST_DMA_SG_LIST_ERROR if this function was called out of sequence with
 *     XEmacPs_BdRingFromHw().
 *
 * @note This function should not be preempted by another XEmacPs_Bd function
 *       call that modifies the BD space. It is the caller's responsibility to
 *       provide a mutual exclusion mechanism.
 *
 *****************************************************************************/
LONG XEmacPs_BdRingFree(XEmacPs_BdRing * RingPtr, u32 NumBd,
			XEmacPs_Bd * BdSetPtr)
{
	LONG Status;
	/* if no bds to process, simply return. */
	if (0x00000000U == NumBd){
		Status = (LONG)(XST_SUCCESS);
	} else {
	/* Make sure we are in sync with XEmacPs_BdRingFromHw() */
	if ((RingPtr->PostCnt < NumBd) || (RingPtr->PostHead != BdSetPtr)) {
			Status = (LONG)(XST_DMA_SG_LIST_ERROR);
		} else {
	/* Update pointers and counters */
	RingPtr->FreeCnt += NumBd;
	RingPtr->PostCnt -= NumBd;
	XEMACPS_RING_SEEKAHEAD(RingPtr, RingPtr->PostHead, NumBd);
			Status = (LONG)(XST_SUCCESS);
		}
	}
	return Status;
}
Example #7
0
/**
 * Returns a set of BD(s) that have been processed by hardware. The returned
 * BDs may be examined to determine the outcome of the DMA transaction(s).
 * Once the BDs have been examined, the user must call XEmacPs_BdRingFree()
 * in the same order which they were retrieved here. Example:
 *
 * <pre>
 *        NumBd = XEmacPs_BdRingFromHwRx(MyRingPtr, MaxBd, &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 = XEmacPs_BdRingNext(MyRingPtr, CurBd);
 *           }
 *
 *           XEmacPs_BdRingFree(MyRingPtr, NumBd, MyBdSet); // Return 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
 *        XEmacPs_BdRingFromHwRx(MyRingPtr, NumBd1, &MySet1);
 *        XEmacPs_BdRingFree(MyRingPtr, NumBd1, MySet1);
 *
 *        // Legal
 *        XEmacPs_BdRingFromHwRx(MyRingPtr, NumBd1, &MySet1);
 *        XEmacPs_BdRingFromHwRx(MyRingPtr, NumBd2, &MySet2);
 *        XEmacPs_BdRingFree(MyRingPtr, NumBd1, MySet1);
 *        XEmacPs_BdRingFree(MyRingPtr, NumBd2, MySet2);
 *
 *        // Not legal
 *        XEmacPs_BdRingFromHwRx(MyRingPtr, NumBd1, &MySet1);
 *        XEmacPs_BdRingFromHwRx(MyRingPtr, NumBd2, &MySet2);
 *        XEmacPs_BdRingFree(MyRingPtr, NumBd2, MySet2);
 *        XEmacPs_BdRingFree(MyRingPtr, NumBd1, MySet1);
 * </pre>
 *
 * If hardware has only 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 instance to be worked on.
 * @param BdLimit is the maximum number of BDs to return in the set.
 * @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.
 *
 * @note This function should not be preempted by another XEmacPs_Bd function
 *       call that modifies the BD space. It is the caller's responsibility to
 *       provide a mutual exclusion mechanism.
 *
 *****************************************************************************/
unsigned XEmacPs_BdRingFromHwRx(XEmacPs_BdRing * RingPtr, unsigned BdLimit,
				 XEmacPs_Bd ** BdSetPtr)
{
	XEmacPs_Bd *CurBdPtr;
	u32 BdStr = 0;
	unsigned BdCount;
	unsigned BdPartialCount;

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

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

	/* Starting at HwHead, keep moving forward in the list until:
	 *  - A BD is encountered with its new/used bit set which means
	 *    hardware has completed processing of that BD.
	 *  - RingPtr->HwTail is reached and RingPtr->HwCnt is reached.
	 *  - The number of requested BDs has been processed
	 */
	while (BdCount < BdLimit) {

		/* Read the status */
		XEMACPS_CACHE_INVALIDATE(CurBdPtr);
		BdStr = XEmacPs_BdRead(CurBdPtr, XEMACPS_BD_STAT_OFFSET);

		if (!(XEmacPs_BdIsRxNew(CurBdPtr))) {
			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.
		 */
		if (BdStr & XEMACPS_RXBUF_EOF_MASK) {
			BdPartialCount = 0;
		}
		else {
			BdPartialCount++;
		}

		/* Move on to next BD in work group */
		CurBdPtr = XEmacPs_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 > 0) {
		*BdSetPtr = RingPtr->HwHead;
		RingPtr->HwCnt -= BdCount;
		RingPtr->PostCnt += BdCount;
		XEMACPS_RING_SEEKAHEAD(RingPtr, RingPtr->HwHead, BdCount);
		return (BdCount);
	}
	else {
		*BdSetPtr = NULL;
		return (0);
	}
}
/**
 * Returns a set of BD(s) that have been processed by hardware. The returned
 * BDs may be examined to determine the outcome of the DMA transaction(s).
 * Once the BDs have been examined, the user must call XEmacPs_BdRingFree()
 * in the same order which they were retrieved here. Example:
 *
 * <pre>
 *        NumBd = XEmacPs_BdRingFromHwTx(MyRingPtr, MaxBd, &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 = XEmacPs_BdRingNext(MyRingPtr, CurBd),
 *           }
 *
 *           XEmacPs_BdRingFree(MyRingPtr, NumBd, MyBdSet),  *Return 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 *
 *        XEmacPs_BdRingFromHwTx(MyRingPtr, NumBd1, &MySet1),
 *        XEmacPs_BdRingFree(MyRingPtr, NumBd1, MySet1),
 *
 *        * Legal *
 *        XEmacPs_BdRingFromHwTx(MyRingPtr, NumBd1, &MySet1),
 *        XEmacPs_BdRingFromHwTx(MyRingPtr, NumBd2, &MySet2),
 *        XEmacPs_BdRingFree(MyRingPtr, NumBd1, MySet1),
 *        XEmacPs_BdRingFree(MyRingPtr, NumBd2, MySet2),
 *
 *        * Not legal *
 *        XEmacPs_BdRingFromHwTx(MyRingPtr, NumBd1, &MySet1),
 *        XEmacPs_BdRingFromHwTx(MyRingPtr, NumBd2, &MySet2),
 *        XEmacPs_BdRingFree(MyRingPtr, NumBd2, MySet2),
 *        XEmacPs_BdRingFree(MyRingPtr, NumBd1, MySet1),
 * </pre>
 *
 * If hardware has only 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 instance to be worked on.
 * @param BdLimit is the maximum number of BDs to return in the set.
 * @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.
 *
 * @note This function should not be preempted by another XEmacPs_Bd function
 *       call that modifies the BD space. It is the caller's responsibility to
 *       provide a mutual exclusion mechanism.
 *
 *****************************************************************************/
u32 XEmacPs_BdRingFromHwTx(XEmacPs_BdRing * RingPtr, u32 BdLimit,
				 XEmacPs_Bd ** BdSetPtr)
{
	XEmacPs_Bd *CurBdPtr;
	u32 BdStr = 0U;
	u32 BdCount;
	u32 BdPartialCount;
	u32 Sop = 0U;
	u32 Status;
	u32 BdLimitLoc = BdLimit;
	CurBdPtr = RingPtr->HwHead;
	BdCount = 0U;
	BdPartialCount = 0U;

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

		if (BdLimitLoc > RingPtr->HwCnt){
			BdLimitLoc = RingPtr->HwCnt;
	}
	/* Starting at HwHead, keep moving forward in the list until:
	 *  - A BD is encountered with its new/used bit set which means
	 *    hardware has not completed processing of that BD.
	 *  - RingPtr->HwTail is reached and RingPtr->HwCnt is reached.
	 *  - The number of requested BDs has been processed
	 */
		while (BdCount < BdLimitLoc) {
		/* Read the status */
			if(CurBdPtr != NULL){
		BdStr = XEmacPs_BdRead(CurBdPtr, XEMACPS_BD_STAT_OFFSET);
			}

			if ((Sop == 0x00000000U) && ((BdStr & XEMACPS_TXBUF_USED_MASK)!=0x00000000U)){
				Sop = 1U;
			}
			if (Sop == 0x00000001U) {
			BdCount++;
			BdPartialCount++;
		}

		/* 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.
		 */
			if ((Sop == 0x00000001U) && ((BdStr & XEMACPS_TXBUF_LAST_MASK)!=0x00000000U)) {
				Sop = 0U;
				BdPartialCount = 0U;
		}

		/* Move on to next BD in work group */
		CurBdPtr = XEmacPs_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 > 0x00000000U) {
		*BdSetPtr = RingPtr->HwHead;
		RingPtr->HwCnt -= BdCount;
		RingPtr->PostCnt += BdCount;
		XEMACPS_RING_SEEKAHEAD(RingPtr, RingPtr->HwHead, BdCount);
			Status = (BdCount);
		} else {
			*BdSetPtr = NULL;
			Status = 0U;
	}
	}
	return Status;
}