XilinxProcessorIPLib/drivers/axidma/src/xaxidma_bdring.c
int XAxiDma_BdRingToHw(XAxiDma_BdRing * RingPtr, int NumBd,
	XAxiDma_Bd * BdSetPtr)
{
	XAxiDma_Bd *CurBdPtr;
	int i;
	u32 BdCr;
	u32 BdSts;
	int RingIndex = RingPtr->RingIndex;

	if (NumBd < 0) {

		xdbg_printf(XDBG_DEBUG_ERROR, "BdRingToHw: negative BD number "
			"%d\r\n", NumBd);

		return XST_INVALID_PARAM;
	}

	/* If the commit set is empty, do nothing */
	if (NumBd == 0) {
		return XST_SUCCESS;
	}

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

		xdbg_printf(XDBG_DEBUG_ERROR, "Bd ring has problems\r\n");
		return XST_DMA_SG_LIST_ERROR;
	}

	CurBdPtr = BdSetPtr;
	BdCr = XAxiDma_BdGetCtrl(CurBdPtr);
	BdSts = XAxiDma_BdGetSts(CurBdPtr);

	/* In case of Tx channel, the first BD should have been marked
	 * as start-of-frame
	 */
	if (!(RingPtr->IsRxChannel) && !(BdCr & XAXIDMA_BD_CTRL_TXSOF_MASK)) {

		xdbg_printf(XDBG_DEBUG_ERROR, "Tx first BD does not have "
								"SOF\r\n");

		return XST_FAILURE;
	}

	/* Clear the completed status bit
	 */
	for (i = 0; i < NumBd - 1; i++) {

		/* Make sure the length value in the BD is non-zero. */
		if (XAxiDma_BdGetLength(CurBdPtr,
				RingPtr->MaxTransferLen) == 0) {

			xdbg_printf(XDBG_DEBUG_ERROR, "0 length bd\r\n");

			return XST_FAILURE;
		}

		BdSts &=  ~XAXIDMA_BD_STS_COMPLETE_MASK;
		XAxiDma_BdWrite(CurBdPtr, XAXIDMA_BD_STS_OFFSET, BdSts);

		/* Flush the current BD so DMA core could see the updates */
		XAXIDMA_CACHE_FLUSH(CurBdPtr);

		CurBdPtr = (XAxiDma_Bd *)((void *)XAxiDma_BdRingNext(RingPtr, CurBdPtr));
		BdCr = XAxiDma_BdRead(CurBdPtr, XAXIDMA_BD_CTRL_LEN_OFFSET);
		BdSts = XAxiDma_BdRead(CurBdPtr, XAXIDMA_BD_STS_OFFSET);
	}

	/* In case of Tx channel, the last BD should have EOF bit set */
	if (!(RingPtr->IsRxChannel) && !(BdCr & XAXIDMA_BD_CTRL_TXEOF_MASK)) {

		xdbg_printf(XDBG_DEBUG_ERROR, "Tx last BD does not have "
								"EOF\r\n");

		return XST_FAILURE;
	}

	/* Make sure the length value in the last BD is non-zero. */
	if (XAxiDma_BdGetLength(CurBdPtr,
			RingPtr->MaxTransferLen) == 0) {

		xdbg_printf(XDBG_DEBUG_ERROR, "0 length bd\r\n");

		return XST_FAILURE;
	}

	/* The last BD should also have the completed status bit cleared
	 */
	BdSts &= ~XAXIDMA_BD_STS_COMPLETE_MASK;
	XAxiDma_BdWrite(CurBdPtr, XAXIDMA_BD_STS_OFFSET, BdSts);

	/* Flush the last BD so DMA core could see the updates */
	XAXIDMA_CACHE_FLUSH(CurBdPtr);
	DATA_SYNC;

	/* This set has completed pre-processing, adjust ring pointers and
	 * counters
	 */
	XAXIDMA_RING_SEEKAHEAD(RingPtr, RingPtr->PreHead, NumBd);
	RingPtr->PreCnt -= NumBd;
	RingPtr->HwTail = CurBdPtr;
	RingPtr->HwCnt += NumBd;

	/* If it is running, signal the engine to begin processing */
	if (RingPtr->RunState == AXIDMA_CHANNEL_NOT_HALTED) {
			if (RingPtr->Cyclic) {
				XAxiDma_WriteReg(RingPtr->ChanBase,
						 XAXIDMA_TDESC_OFFSET,
						 (u32)XAXIDMA_VIRT_TO_PHYS(RingPtr->CyclicBd));
				if (RingPtr->Addr_ext)
					XAxiDma_WriteReg(RingPtr->ChanBase,
							 XAXIDMA_TDESC_MSB_OFFSET,
							 UPPER_32_BITS(XAXIDMA_VIRT_TO_PHYS(RingPtr->CyclicBd)));
				return XST_SUCCESS;
			}

			if (RingPtr->IsRxChannel) {
				if (!RingIndex) {
					XAxiDma_WriteReg(RingPtr->ChanBase,
							XAXIDMA_TDESC_OFFSET, (XAXIDMA_VIRT_TO_PHYS(RingPtr->HwTail) & XAXIDMA_DESC_LSB_MASK));
					if (RingPtr->Addr_ext)
						XAxiDma_WriteReg(RingPtr->ChanBase, XAXIDMA_TDESC_MSB_OFFSET,
								 UPPER_32_BITS(XAXIDMA_VIRT_TO_PHYS(RingPtr->HwTail)));
				}
				else {
					XAxiDma_WriteReg(RingPtr->ChanBase,
						(XAXIDMA_RX_TDESC0_OFFSET +
						(RingIndex - 1) * XAXIDMA_RX_NDESC_OFFSET),
						(XAXIDMA_VIRT_TO_PHYS(RingPtr->HwTail) & XAXIDMA_DESC_LSB_MASK ));
					if (RingPtr->Addr_ext)
						XAxiDma_WriteReg(RingPtr->ChanBase,
							(XAXIDMA_RX_TDESC0_MSB_OFFSET +
							(RingIndex - 1) * XAXIDMA_RX_NDESC_OFFSET),
							UPPER_32_BITS(XAXIDMA_VIRT_TO_PHYS(RingPtr->HwTail)));
				}
			}
			else {
				XAxiDma_WriteReg(RingPtr->ChanBase,
							XAXIDMA_TDESC_OFFSET, (XAXIDMA_VIRT_TO_PHYS(RingPtr->HwTail) & XAXIDMA_DESC_LSB_MASK));
				if (RingPtr->Addr_ext)
					XAxiDma_WriteReg(RingPtr->ChanBase, XAXIDMA_TDESC_MSB_OFFSET,
								UPPER_32_BITS(XAXIDMA_VIRT_TO_PHYS(RingPtr->HwTail)));
			}
	}

	return XST_SUCCESS;
}
/*****************************************************************************/
/**
 * Enqueue a set of BDs to hardware that were previously allocated by
 * XAxiDma_BdRingAlloc(). Once this function returns, the argument BD set goes
 * under hardware control. Changes to these BDs should be held until they are
 * finished by hardware to avoid data corruption and system instability.
 *
 * For transmit, the set will be rejected if the last BD of the set does not
 * mark the end of a packet or the first BD does not mark the start of a packet.
 *
 * @param	RingPtr is a pointer to the descriptor ring 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_INVALID_PARAM if passed in NumBd is negative
 *		- XST_FAILURE if the set of BDs was rejected because the first
 *		BD does not have its start-of-packet bit set, or the last BD
 *		does not have its end-of-packet bit set, or any one of the BDs
 *		has 0 length.
 *		- XST_DMA_SG_LIST_ERROR if this function was called out of
 *		sequence with XAxiDma_BdRingAlloc()
 *
 * @note	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
 *
 *****************************************************************************/
Enqueue a set of BDs to hardware that were previously allocated by
XAxiDma_BdRingAlloc(). Once this function returns, the argument BD set goes
under hardware control. Changes to these BDs should be held until they are
finished by hardware to avoid data corruption and system instability.

For transmit, the set will be rejected if the last BD of the set does not
mark the end of a packet or the first BD does not mark the start of a packet.

@param       RingPtr is a pointer to the descriptor ring 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.



@note        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
Enqueue a set of BDs to hardware that were previously allocated by XAxiDma_BdRingAlloc () . Once this function returns the argument BD set goes under hardware control . Changes to these BDs should be held until they are finished by hardware to avoid data corruption and system instability . For transmit the set will be rejected if the last BD of the set does not mark the end of a packet or the first BD does not mark the start of a packet . @param RingPtr is a pointer to the descriptor ring 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 . @note 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_BdRingToHw(XAxiDma_BdRing * RingPtr, int NumBd,
	XAxiDma_Bd * BdSetPtr)
{
	XAxiDma_Bd *CurBdPtr;
	int i;
	u32 BdCr;
	u32 BdSts;
	int RingIndex = RingPtr->RingIndex;
	if (NumBd < 0) {
		xdbg_printf(XDBG_DEBUG_ERROR, "BdRingToHw: negative BD number "
			"%d\r\n", NumBd);
		return XST_INVALID_PARAM;
	}
	if (NumBd == 0) {
		return XST_SUCCESS;
	}
	if ((RingPtr->PreCnt < NumBd) || (RingPtr->PreHead != BdSetPtr)) {
		xdbg_printf(XDBG_DEBUG_ERROR, "Bd ring has problems\r\n");
		return XST_DMA_SG_LIST_ERROR;
	}
	CurBdPtr = BdSetPtr;
	BdCr = XAxiDma_BdGetCtrl(CurBdPtr);
	BdSts = XAxiDma_BdGetSts(CurBdPtr);
	if (!(RingPtr->IsRxChannel) && !(BdCr & XAXIDMA_BD_CTRL_TXSOF_MASK)) {
		xdbg_printf(XDBG_DEBUG_ERROR, "Tx first BD does not have "
								"SOF\r\n");
		return XST_FAILURE;
	}
	for (i = 0; i < NumBd - 1; i++) {
		if (XAxiDma_BdGetLength(CurBdPtr,
				RingPtr->MaxTransferLen) == 0) {
			xdbg_printf(XDBG_DEBUG_ERROR, "0 length bd\r\n");
			return XST_FAILURE;
		}
		BdSts &=  ~XAXIDMA_BD_STS_COMPLETE_MASK;
		XAxiDma_BdWrite(CurBdPtr, XAXIDMA_BD_STS_OFFSET, BdSts);
		XAXIDMA_CACHE_FLUSH(CurBdPtr);
		CurBdPtr = (XAxiDma_Bd *)((void *)XAxiDma_BdRingNext(RingPtr, CurBdPtr));
		BdCr = XAxiDma_BdRead(CurBdPtr, XAXIDMA_BD_CTRL_LEN_OFFSET);
		BdSts = XAxiDma_BdRead(CurBdPtr, XAXIDMA_BD_STS_OFFSET);
	}
	if (!(RingPtr->IsRxChannel) && !(BdCr & XAXIDMA_BD_CTRL_TXEOF_MASK)) {
		xdbg_printf(XDBG_DEBUG_ERROR, "Tx last BD does not have "
								"EOF\r\n");
		return XST_FAILURE;
	}
	if (XAxiDma_BdGetLength(CurBdPtr,
			RingPtr->MaxTransferLen) == 0) {
		xdbg_printf(XDBG_DEBUG_ERROR, "0 length bd\r\n");
		return XST_FAILURE;
	}
	BdSts &= ~XAXIDMA_BD_STS_COMPLETE_MASK;
	XAxiDma_BdWrite(CurBdPtr, XAXIDMA_BD_STS_OFFSET, BdSts);
	XAXIDMA_CACHE_FLUSH(CurBdPtr);
	DATA_SYNC;
	XAXIDMA_RING_SEEKAHEAD(RingPtr, RingPtr->PreHead, NumBd);
	RingPtr->PreCnt -= NumBd;
	RingPtr->HwTail = CurBdPtr;
	RingPtr->HwCnt += NumBd;
	if (RingPtr->RunState == AXIDMA_CHANNEL_NOT_HALTED) {
			if (RingPtr->Cyclic) {
				XAxiDma_WriteReg(RingPtr->ChanBase,
						 XAXIDMA_TDESC_OFFSET,
						 (u32)XAXIDMA_VIRT_TO_PHYS(RingPtr->CyclicBd));
				if (RingPtr->Addr_ext)
					XAxiDma_WriteReg(RingPtr->ChanBase,
							 XAXIDMA_TDESC_MSB_OFFSET,
							 UPPER_32_BITS(XAXIDMA_VIRT_TO_PHYS(RingPtr->CyclicBd)));
				return XST_SUCCESS;
			}
			if (RingPtr->IsRxChannel) {
				if (!RingIndex) {
					XAxiDma_WriteReg(RingPtr->ChanBase,
							XAXIDMA_TDESC_OFFSET, (XAXIDMA_VIRT_TO_PHYS(RingPtr->HwTail) & XAXIDMA_DESC_LSB_MASK));
					if (RingPtr->Addr_ext)
						XAxiDma_WriteReg(RingPtr->ChanBase, XAXIDMA_TDESC_MSB_OFFSET,
								 UPPER_32_BITS(XAXIDMA_VIRT_TO_PHYS(RingPtr->HwTail)));
				}
				else {
					XAxiDma_WriteReg(RingPtr->ChanBase,
						(XAXIDMA_RX_TDESC0_OFFSET +
						(RingIndex - 1) * XAXIDMA_RX_NDESC_OFFSET),
						(XAXIDMA_VIRT_TO_PHYS(RingPtr->HwTail) & XAXIDMA_DESC_LSB_MASK ));
					if (RingPtr->Addr_ext)
						XAxiDma_WriteReg(RingPtr->ChanBase,
							(XAXIDMA_RX_TDESC0_MSB_OFFSET +
							(RingIndex - 1) * XAXIDMA_RX_NDESC_OFFSET),
							UPPER_32_BITS(XAXIDMA_VIRT_TO_PHYS(RingPtr->HwTail)));
				}
			}
			else {
				XAxiDma_WriteReg(RingPtr->ChanBase,
							XAXIDMA_TDESC_OFFSET, (XAXIDMA_VIRT_TO_PHYS(RingPtr->HwTail) & XAXIDMA_DESC_LSB_MASK));
				if (RingPtr->Addr_ext)
					XAxiDma_WriteReg(RingPtr->ChanBase, XAXIDMA_TDESC_MSB_OFFSET,
								UPPER_32_BITS(XAXIDMA_VIRT_TO_PHYS(RingPtr->HwTail)));
			}
	}
	return XST_SUCCESS;
}
int XAxiDma_BdRingToHw ( XAxiDma_BdRing * RingPtr , int NumBd , XAxiDma_Bd * BdSetPtr ) { XAxiDma_Bd * CurBdPtr ; int i ; u32 BdCr ; u32 BdSts ; int RingIndex = RingPtr -> RingIndex ; if ( NumBd < 0 ) { xdbg_printf ( XDBG_DEBUG_ERROR , " " " \r \n " , NumBd ) ; return XST_INVALID_PARAM ; } if ( NumBd == 0 ) { return XST_SUCCESS ; } if ( ( RingPtr -> PreCnt < NumBd ) || ( RingPtr -> PreHead != BdSetPtr ) ) { xdbg_printf ( XDBG_DEBUG_ERROR , " \r \n " ) ; return XST_DMA_SG_LIST_ERROR ; } CurBdPtr = BdSetPtr ; BdCr = XAxiDma_BdGetCtrl ( CurBdPtr ) ; BdSts = XAxiDma_BdGetSts ( CurBdPtr ) ; if ( ! ( RingPtr -> IsRxChannel ) && ! ( BdCr & XAXIDMA_BD_CTRL_TXSOF_MASK ) ) { xdbg_printf ( XDBG_DEBUG_ERROR , " " " \r \n " ) ; return XST_FAILURE ; } for ( i = 0 ; i < NumBd - 1 ; i ++ ) { if ( XAxiDma_BdGetLength ( CurBdPtr , RingPtr -> MaxTransferLen ) == 0 ) { xdbg_printf ( XDBG_DEBUG_ERROR , " \r \n " ) ; return XST_FAILURE ; } BdSts &= ~ XAXIDMA_BD_STS_COMPLETE_MASK ; XAxiDma_BdWrite ( CurBdPtr , XAXIDMA_BD_STS_OFFSET , BdSts ) ; XAXIDMA_CACHE_FLUSH ( CurBdPtr ) ; CurBdPtr = ( XAxiDma_Bd * ) ( ( void * ) XAxiDma_BdRingNext ( RingPtr , CurBdPtr ) ) ; BdCr = XAxiDma_BdRead ( CurBdPtr , XAXIDMA_BD_CTRL_LEN_OFFSET ) ; BdSts = XAxiDma_BdRead ( CurBdPtr , XAXIDMA_BD_STS_OFFSET ) ; } if ( ! ( RingPtr -> IsRxChannel ) && ! ( BdCr & XAXIDMA_BD_CTRL_TXEOF_MASK ) ) { xdbg_printf ( XDBG_DEBUG_ERROR , " " " \r \n " ) ; return XST_FAILURE ; } if ( XAxiDma_BdGetLength ( CurBdPtr , RingPtr -> MaxTransferLen ) == 0 ) { xdbg_printf ( XDBG_DEBUG_ERROR , " \r \n " ) ; return XST_FAILURE ; } BdSts &= ~ XAXIDMA_BD_STS_COMPLETE_MASK ; XAxiDma_BdWrite ( CurBdPtr , XAXIDMA_BD_STS_OFFSET , BdSts ) ; XAXIDMA_CACHE_FLUSH ( CurBdPtr ) ; DATA_SYNC ; XAXIDMA_RING_SEEKAHEAD ( RingPtr , RingPtr -> PreHead , NumBd ) ; RingPtr -> PreCnt -= NumBd ; RingPtr -> HwTail = CurBdPtr ; RingPtr -> HwCnt += NumBd ; if ( RingPtr -> RunState == AXIDMA_CHANNEL_NOT_HALTED ) { if ( RingPtr -> Cyclic ) { XAxiDma_WriteReg ( RingPtr -> ChanBase , XAXIDMA_TDESC_OFFSET , ( u32 ) XAXIDMA_VIRT_TO_PHYS ( RingPtr -> CyclicBd ) ) ; if ( RingPtr -> Addr_ext ) XAxiDma_WriteReg ( RingPtr -> ChanBase , XAXIDMA_TDESC_MSB_OFFSET , UPPER_32_BITS ( XAXIDMA_VIRT_TO_PHYS ( RingPtr -> CyclicBd ) ) ) ; return XST_SUCCESS ; } if ( RingPtr -> IsRxChannel ) { if ( ! RingIndex ) { XAxiDma_WriteReg ( RingPtr -> ChanBase , XAXIDMA_TDESC_OFFSET , ( XAXIDMA_VIRT_TO_PHYS ( RingPtr -> HwTail ) & XAXIDMA_DESC_LSB_MASK ) ) ; if ( RingPtr -> Addr_ext ) XAxiDma_WriteReg ( RingPtr -> ChanBase , XAXIDMA_TDESC_MSB_OFFSET , UPPER_32_BITS ( XAXIDMA_VIRT_TO_PHYS ( RingPtr -> HwTail ) ) ) ; } else { XAxiDma_WriteReg ( RingPtr -> ChanBase , ( XAXIDMA_RX_TDESC0_OFFSET + ( RingIndex - 1 ) * XAXIDMA_RX_NDESC_OFFSET ) , ( XAXIDMA_VIRT_TO_PHYS ( RingPtr -> HwTail ) & XAXIDMA_DESC_LSB_MASK ) ) ; if ( RingPtr -> Addr_ext ) XAxiDma_WriteReg ( RingPtr -> ChanBase , ( XAXIDMA_RX_TDESC0_MSB_OFFSET + ( RingIndex - 1 ) * XAXIDMA_RX_NDESC_OFFSET ) , UPPER_32_BITS ( XAXIDMA_VIRT_TO_PHYS ( RingPtr -> HwTail ) ) ) ; } } else { XAxiDma_WriteReg ( RingPtr -> ChanBase , XAXIDMA_TDESC_OFFSET , ( XAXIDMA_VIRT_TO_PHYS ( RingPtr -> HwTail ) & XAXIDMA_DESC_LSB_MASK ) ) ; if ( RingPtr -> Addr_ext ) XAxiDma_WriteReg ( RingPtr -> ChanBase , XAXIDMA_TDESC_MSB_OFFSET , UPPER_32_BITS ( XAXIDMA_VIRT_TO_PHYS ( RingPtr -> HwTail ) ) ) ; } } return XST_SUCCESS ; }
Enqueue a set of BDs to hardware that were previously allocated by
 XAxiDma_BdRingAlloc().
Enqueue a set of BDs to hardware that were previously allocated by XAxiDma_BdRingAlloc () .
/* If the commit set is empty, do nothing */ /* Make sure we are in sync with XAxiDma_BdRingAlloc() */ /* In case of Tx channel, the first BD should have been marked
	 * as start-of-frame
	 */ /* Clear the completed status bit
	 */ /* Make sure the length value in the BD is non-zero. */ /* Flush the current BD so DMA core could see the updates */ /* In case of Tx channel, the last BD should have EOF bit set */ /* Make sure the length value in the last BD is non-zero. */ /* The last BD should also have the completed status bit cleared
	 */ /* Flush the last BD so DMA core could see the updates */ /* This set has completed pre-processing, adjust ring pointers and
	 * counters
	 */ /* If it is running, signal the engine to begin processing */