XilinxProcessorIPLib/drivers/axicdma/src/xaxicdma_bdring.c
LONG XAxiCdma_BdRingCreate(XAxiCdma *InstancePtr, UINTPTR PhysAddr,
			UINTPTR VirtAddr, u32 Alignment, int BdCount)
{
	UINTPTR BdVirtAddr;
	UINTPTR BdNxtPhysAddr;
	UINTPTR BdPhysAddr;
	int Index;

	if (InstancePtr->SimpleOnlyBuild) {
		xdbg_printf(XDBG_DEBUG_ERROR, "BdRingCreate: hardware simple "
			"mode only\r\n");
		return XST_FAILURE;
	}

	if (BdCount <= 0) {
		xdbg_printf(XDBG_DEBUG_ERROR, "BdRingCreate: non-positive "
			"BD number %d\r\n", BdCount);

		return XST_INVALID_PARAM;
	}

	/* In case there is a failure prior to creating list, make sure the
	 * following attributes are 0 to prevent calls to other SG functions
	 */
	InstancePtr->AllBdCnt = 0;
	InstancePtr->FreeBdCnt = 0;
	InstancePtr->HwBdCnt = 0;
	InstancePtr->PreBdCnt = 0;
	InstancePtr->PostBdCnt = 0;

	/* Make sure Alignment parameter meets minimum requirements */
	if (Alignment < XAXICDMA_BD_MINIMUM_ALIGNMENT) {

		xdbg_printf(XDBG_DEBUG_ERROR, "BdRingCreate: alignment too small "
			"%d, need to be at least %d\r\n", (int)Alignment,
			(int)XAXICDMA_BD_MINIMUM_ALIGNMENT);

		return XST_INVALID_PARAM;
	}

	/* Make sure Alignment is a power of 2 */
	if ((Alignment - 1) & Alignment) {

		xdbg_printf(XDBG_DEBUG_ERROR, "BdRingCreate: alignment not valid "
			"%d\r\n", (int)Alignment);

		return XST_INVALID_PARAM;
	}

	/* Make sure PhysAddr and VirtAddr have valid Alignment */
	if ((PhysAddr & (Alignment - 1)) || (VirtAddr & (Alignment - 1))) {

		xdbg_printf(XDBG_DEBUG_ERROR, "BdRingCreate: Physical address %x "
			"and/or virtual address %x have invalid alignment\r\n",
			(unsigned int)PhysAddr, (unsigned int)VirtAddr);

		return XST_INVALID_PARAM;
	}

	/* Compute how many bytes will be between the start of adjacent BDs */
	InstancePtr->BdSeparation =
		(sizeof(XAxiCdma_Bd) + (Alignment - 1)) & ~(Alignment - 1);

	/* Must make sure the ring doesn't span address 0x00000000. If it does,
	 * then the next/prev BD traversal macros will fail.
	 */
	if (VirtAddr > (VirtAddr + (InstancePtr->BdSeparation * BdCount) - 1)) {

		xdbg_printf(XDBG_DEBUG_ERROR, "BdRingCreate: BD space cross "
			"0x0\r\n");

		return XST_DMA_SG_LIST_ERROR;
	}

	/* Initial ring setup:
	 *  - Clear the entire space
	 *  - Setup each BD's next pointer with the physical address of the
	 *    next BD
	 */
	memset((void *) VirtAddr, 0, (InstancePtr->BdSeparation * BdCount));

	/* The virtual address is used to reference/flush cache for the BD
	 * The physical address is to be put in the BD for hardware reference
	 */
	BdVirtAddr = VirtAddr;
	BdNxtPhysAddr = PhysAddr + InstancePtr->BdSeparation;
	BdPhysAddr = PhysAddr;

	for (Index = 1; Index < BdCount; Index++) {
		XAxiCdma_BdSetAddrLen((XAxiCdma_Bd *)BdVirtAddr,
		    InstancePtr->AddrWidth);
		XAxiCdma_BdSetNextPtr((XAxiCdma_Bd *)BdVirtAddr, BdNxtPhysAddr);
		XAxiCdma_BdSetPhysAddr((XAxiCdma_Bd *)BdVirtAddr, BdPhysAddr);
		XAxiCdma_BdSetIsLite((XAxiCdma_Bd *)BdVirtAddr,
		    InstancePtr->IsLite);
		XAxiCdma_BdSetHasDRE((XAxiCdma_Bd *)BdVirtAddr,
		    InstancePtr->HasDRE);
		XAxiCdma_BdSetWordLen((XAxiCdma_Bd *)BdVirtAddr,
		    InstancePtr->WordLength);
		XAxiCdma_BdSetMaxLen((XAxiCdma_Bd *)BdVirtAddr,
		    InstancePtr->MaxTransLen);

		XAXICDMA_CACHE_FLUSH(BdVirtAddr);
		BdVirtAddr += InstancePtr->BdSeparation;
		BdNxtPhysAddr += InstancePtr->BdSeparation;
		BdPhysAddr += InstancePtr->BdSeparation;
	}

	/* At the end of the ring, link the last BD back to the top,
	 * and set its fields
	 */
	XAxiCdma_BdSetAddrLen((XAxiCdma_Bd *)BdVirtAddr,
                    InstancePtr->AddrWidth);
	XAxiCdma_BdSetNextPtr((XAxiCdma_Bd *)BdVirtAddr, PhysAddr);
	XAxiCdma_BdSetPhysAddr((XAxiCdma_Bd *)BdVirtAddr, BdPhysAddr);
	XAxiCdma_BdSetIsLite((XAxiCdma_Bd *)BdVirtAddr,
	    InstancePtr->IsLite);
	XAxiCdma_BdSetHasDRE((XAxiCdma_Bd *)BdVirtAddr,
	    InstancePtr->HasDRE);
	XAxiCdma_BdSetWordLen((XAxiCdma_Bd *)BdVirtAddr,
	    InstancePtr->WordLength);
	XAxiCdma_BdSetMaxLen((XAxiCdma_Bd *)BdVirtAddr,
	    InstancePtr->MaxTransLen);

	/* Setup and initialize pointers and counters */
	InstancePtr->FirstBdAddr = VirtAddr;
	InstancePtr->FirstBdPhysAddr = PhysAddr;
	InstancePtr->LastBdAddr = BdVirtAddr;
	InstancePtr->BdRingTotalLen = InstancePtr->LastBdAddr -
		InstancePtr->FirstBdAddr + InstancePtr->BdSeparation;
	InstancePtr->AllBdCnt = BdCount;
	InstancePtr->FreeBdCnt = BdCount;
	InstancePtr->FreeBdHead = (XAxiCdma_Bd *) (void *)VirtAddr;
	InstancePtr->PreBdHead = (XAxiCdma_Bd *) VirtAddr;
	InstancePtr->HwBdHead = (XAxiCdma_Bd *) VirtAddr;
	InstancePtr->HwBdTail = (XAxiCdma_Bd *) VirtAddr;
	InstancePtr->PostBdHead = (XAxiCdma_Bd *) VirtAddr;
	InstancePtr->BdaRestart = (XAxiCdma_Bd *) (void *)PhysAddr;

	return (XST_SUCCESS);
}
/*****************************************************************************/
/**
 * This function creates the BD ring for the driver instance. If a BD ring
 * pre-exist of this ring, the previous ring is lost.
 *
 * @param	InstancePtr is the driver instance we are working on
 * @param	PhysAddr is the physical address of the memory for the BD ring
 * @param	VirtAddr is the virtual address of the memory for the BD ring
 * @param	Alignment is the alignment for the BDs
 * @param	BdCount is the number of BDs to create in the ring
 *
 * @return
 *		- XST_SUCCESS for success
 *		- XST_INVALID_PARAM for invalid parameter
 *		- XST_DMA_SG_LIST_ERROR for invalid memory region
 *		- XST_FAILURE if the hardware build is simple mode only
 *
 * @note	For a system that has flat memory layout, then the PhysAddr
 *		and the VirtAddr are the same.
 *
 *****************************************************************************/
This function creates the BD ring for the driver instance. If a BD ring
pre-exist of this ring, the previous ring is lost.



@return
- XST_SUCCESS for success
- XST_INVALID_PARAM for invalid parameter
- XST_DMA_SG_LIST_ERROR for invalid memory region
- XST_FAILURE if the hardware build is simple mode only

@note        For a system that has flat memory layout, then the PhysAddr
and the VirtAddr are the same.
This function creates the BD ring for the driver instance . If a BD ring pre - exist of this ring the previous ring is lost . @return - XST_SUCCESS for success - XST_INVALID_PARAM for invalid parameter - XST_DMA_SG_LIST_ERROR for invalid memory region - XST_FAILURE if the hardware build is simple mode only @note For a system that has flat memory layout then the PhysAddr and the VirtAddr are the same .
LONG XAxiCdma_BdRingCreate(XAxiCdma *InstancePtr, UINTPTR PhysAddr,
			UINTPTR VirtAddr, u32 Alignment, int BdCount)
{
	UINTPTR BdVirtAddr;
	UINTPTR BdNxtPhysAddr;
	UINTPTR BdPhysAddr;
	int Index;
	if (InstancePtr->SimpleOnlyBuild) {
		xdbg_printf(XDBG_DEBUG_ERROR, "BdRingCreate: hardware simple "
			"mode only\r\n");
		return XST_FAILURE;
	}
	if (BdCount <= 0) {
		xdbg_printf(XDBG_DEBUG_ERROR, "BdRingCreate: non-positive "
			"BD number %d\r\n", BdCount);
		return XST_INVALID_PARAM;
	}
	InstancePtr->AllBdCnt = 0;
	InstancePtr->FreeBdCnt = 0;
	InstancePtr->HwBdCnt = 0;
	InstancePtr->PreBdCnt = 0;
	InstancePtr->PostBdCnt = 0;
	if (Alignment < XAXICDMA_BD_MINIMUM_ALIGNMENT) {
		xdbg_printf(XDBG_DEBUG_ERROR, "BdRingCreate: alignment too small "
			"%d, need to be at least %d\r\n", (int)Alignment,
			(int)XAXICDMA_BD_MINIMUM_ALIGNMENT);
		return XST_INVALID_PARAM;
	}
	if ((Alignment - 1) & Alignment) {
		xdbg_printf(XDBG_DEBUG_ERROR, "BdRingCreate: alignment not valid "
			"%d\r\n", (int)Alignment);
		return XST_INVALID_PARAM;
	}
	if ((PhysAddr & (Alignment - 1)) || (VirtAddr & (Alignment - 1))) {
		xdbg_printf(XDBG_DEBUG_ERROR, "BdRingCreate: Physical address %x "
			"and/or virtual address %x have invalid alignment\r\n",
			(unsigned int)PhysAddr, (unsigned int)VirtAddr);
		return XST_INVALID_PARAM;
	}
	InstancePtr->BdSeparation =
		(sizeof(XAxiCdma_Bd) + (Alignment - 1)) & ~(Alignment - 1);
	if (VirtAddr > (VirtAddr + (InstancePtr->BdSeparation * BdCount) - 1)) {
		xdbg_printf(XDBG_DEBUG_ERROR, "BdRingCreate: BD space cross "
			"0x0\r\n");
		return XST_DMA_SG_LIST_ERROR;
	}
	memset((void *) VirtAddr, 0, (InstancePtr->BdSeparation * BdCount));
	BdVirtAddr = VirtAddr;
	BdNxtPhysAddr = PhysAddr + InstancePtr->BdSeparation;
	BdPhysAddr = PhysAddr;
	for (Index = 1; Index < BdCount; Index++) {
		XAxiCdma_BdSetAddrLen((XAxiCdma_Bd *)BdVirtAddr,
		    InstancePtr->AddrWidth);
		XAxiCdma_BdSetNextPtr((XAxiCdma_Bd *)BdVirtAddr, BdNxtPhysAddr);
		XAxiCdma_BdSetPhysAddr((XAxiCdma_Bd *)BdVirtAddr, BdPhysAddr);
		XAxiCdma_BdSetIsLite((XAxiCdma_Bd *)BdVirtAddr,
		    InstancePtr->IsLite);
		XAxiCdma_BdSetHasDRE((XAxiCdma_Bd *)BdVirtAddr,
		    InstancePtr->HasDRE);
		XAxiCdma_BdSetWordLen((XAxiCdma_Bd *)BdVirtAddr,
		    InstancePtr->WordLength);
		XAxiCdma_BdSetMaxLen((XAxiCdma_Bd *)BdVirtAddr,
		    InstancePtr->MaxTransLen);
		XAXICDMA_CACHE_FLUSH(BdVirtAddr);
		BdVirtAddr += InstancePtr->BdSeparation;
		BdNxtPhysAddr += InstancePtr->BdSeparation;
		BdPhysAddr += InstancePtr->BdSeparation;
	}
	XAxiCdma_BdSetAddrLen((XAxiCdma_Bd *)BdVirtAddr,
                    InstancePtr->AddrWidth);
	XAxiCdma_BdSetNextPtr((XAxiCdma_Bd *)BdVirtAddr, PhysAddr);
	XAxiCdma_BdSetPhysAddr((XAxiCdma_Bd *)BdVirtAddr, BdPhysAddr);
	XAxiCdma_BdSetIsLite((XAxiCdma_Bd *)BdVirtAddr,
	    InstancePtr->IsLite);
	XAxiCdma_BdSetHasDRE((XAxiCdma_Bd *)BdVirtAddr,
	    InstancePtr->HasDRE);
	XAxiCdma_BdSetWordLen((XAxiCdma_Bd *)BdVirtAddr,
	    InstancePtr->WordLength);
	XAxiCdma_BdSetMaxLen((XAxiCdma_Bd *)BdVirtAddr,
	    InstancePtr->MaxTransLen);
	InstancePtr->FirstBdAddr = VirtAddr;
	InstancePtr->FirstBdPhysAddr = PhysAddr;
	InstancePtr->LastBdAddr = BdVirtAddr;
	InstancePtr->BdRingTotalLen = InstancePtr->LastBdAddr -
		InstancePtr->FirstBdAddr + InstancePtr->BdSeparation;
	InstancePtr->AllBdCnt = BdCount;
	InstancePtr->FreeBdCnt = BdCount;
	InstancePtr->FreeBdHead = (XAxiCdma_Bd *) (void *)VirtAddr;
	InstancePtr->PreBdHead = (XAxiCdma_Bd *) VirtAddr;
	InstancePtr->HwBdHead = (XAxiCdma_Bd *) VirtAddr;
	InstancePtr->HwBdTail = (XAxiCdma_Bd *) VirtAddr;
	InstancePtr->PostBdHead = (XAxiCdma_Bd *) VirtAddr;
	InstancePtr->BdaRestart = (XAxiCdma_Bd *) (void *)PhysAddr;
	return (XST_SUCCESS);
}
LONG XAxiCdma_BdRingCreate ( XAxiCdma * InstancePtr , UINTPTR PhysAddr , UINTPTR VirtAddr , u32 Alignment , int BdCount ) { UINTPTR BdVirtAddr ; UINTPTR BdNxtPhysAddr ; UINTPTR BdPhysAddr ; int Index ; if ( InstancePtr -> SimpleOnlyBuild ) { xdbg_printf ( XDBG_DEBUG_ERROR , " " " \r \n " ) ; return XST_FAILURE ; } if ( BdCount <= 0 ) { xdbg_printf ( XDBG_DEBUG_ERROR , " " " \r \n " , BdCount ) ; return XST_INVALID_PARAM ; } InstancePtr -> AllBdCnt = 0 ; InstancePtr -> FreeBdCnt = 0 ; InstancePtr -> HwBdCnt = 0 ; InstancePtr -> PreBdCnt = 0 ; InstancePtr -> PostBdCnt = 0 ; if ( Alignment < XAXICDMA_BD_MINIMUM_ALIGNMENT ) { xdbg_printf ( XDBG_DEBUG_ERROR , " " " \r \n " , ( int ) Alignment , ( int ) XAXICDMA_BD_MINIMUM_ALIGNMENT ) ; return XST_INVALID_PARAM ; } if ( ( Alignment - 1 ) & Alignment ) { xdbg_printf ( XDBG_DEBUG_ERROR , " " " \r \n " , ( int ) Alignment ) ; return XST_INVALID_PARAM ; } if ( ( PhysAddr & ( Alignment - 1 ) ) || ( VirtAddr & ( Alignment - 1 ) ) ) { xdbg_printf ( XDBG_DEBUG_ERROR , " " " \r \n " , ( unsigned int ) PhysAddr , ( unsigned int ) VirtAddr ) ; return XST_INVALID_PARAM ; } InstancePtr -> BdSeparation = ( sizeof ( XAxiCdma_Bd ) + ( Alignment - 1 ) ) & ~ ( Alignment - 1 ) ; if ( VirtAddr > ( VirtAddr + ( InstancePtr -> BdSeparation * BdCount ) - 1 ) ) { xdbg_printf ( XDBG_DEBUG_ERROR , " " " \r \n " ) ; return XST_DMA_SG_LIST_ERROR ; } memset ( ( void * ) VirtAddr , 0 , ( InstancePtr -> BdSeparation * BdCount ) ) ; BdVirtAddr = VirtAddr ; BdNxtPhysAddr = PhysAddr + InstancePtr -> BdSeparation ; BdPhysAddr = PhysAddr ; for ( Index = 1 ; Index < BdCount ; Index ++ ) { XAxiCdma_BdSetAddrLen ( ( XAxiCdma_Bd * ) BdVirtAddr , InstancePtr -> AddrWidth ) ; XAxiCdma_BdSetNextPtr ( ( XAxiCdma_Bd * ) BdVirtAddr , BdNxtPhysAddr ) ; XAxiCdma_BdSetPhysAddr ( ( XAxiCdma_Bd * ) BdVirtAddr , BdPhysAddr ) ; XAxiCdma_BdSetIsLite ( ( XAxiCdma_Bd * ) BdVirtAddr , InstancePtr -> IsLite ) ; XAxiCdma_BdSetHasDRE ( ( XAxiCdma_Bd * ) BdVirtAddr , InstancePtr -> HasDRE ) ; XAxiCdma_BdSetWordLen ( ( XAxiCdma_Bd * ) BdVirtAddr , InstancePtr -> WordLength ) ; XAxiCdma_BdSetMaxLen ( ( XAxiCdma_Bd * ) BdVirtAddr , InstancePtr -> MaxTransLen ) ; XAXICDMA_CACHE_FLUSH ( BdVirtAddr ) ; BdVirtAddr += InstancePtr -> BdSeparation ; BdNxtPhysAddr += InstancePtr -> BdSeparation ; BdPhysAddr += InstancePtr -> BdSeparation ; } XAxiCdma_BdSetAddrLen ( ( XAxiCdma_Bd * ) BdVirtAddr , InstancePtr -> AddrWidth ) ; XAxiCdma_BdSetNextPtr ( ( XAxiCdma_Bd * ) BdVirtAddr , PhysAddr ) ; XAxiCdma_BdSetPhysAddr ( ( XAxiCdma_Bd * ) BdVirtAddr , BdPhysAddr ) ; XAxiCdma_BdSetIsLite ( ( XAxiCdma_Bd * ) BdVirtAddr , InstancePtr -> IsLite ) ; XAxiCdma_BdSetHasDRE ( ( XAxiCdma_Bd * ) BdVirtAddr , InstancePtr -> HasDRE ) ; XAxiCdma_BdSetWordLen ( ( XAxiCdma_Bd * ) BdVirtAddr , InstancePtr -> WordLength ) ; XAxiCdma_BdSetMaxLen ( ( XAxiCdma_Bd * ) BdVirtAddr , InstancePtr -> MaxTransLen ) ; InstancePtr -> FirstBdAddr = VirtAddr ; InstancePtr -> FirstBdPhysAddr = PhysAddr ; InstancePtr -> LastBdAddr = BdVirtAddr ; InstancePtr -> BdRingTotalLen = InstancePtr -> LastBdAddr - InstancePtr -> FirstBdAddr + InstancePtr -> BdSeparation ; InstancePtr -> AllBdCnt = BdCount ; InstancePtr -> FreeBdCnt = BdCount ; InstancePtr -> FreeBdHead = ( XAxiCdma_Bd * ) ( void * ) VirtAddr ; InstancePtr -> PreBdHead = ( XAxiCdma_Bd * ) VirtAddr ; InstancePtr -> HwBdHead = ( XAxiCdma_Bd * ) VirtAddr ; InstancePtr -> HwBdTail = ( XAxiCdma_Bd * ) VirtAddr ; InstancePtr -> PostBdHead = ( XAxiCdma_Bd * ) VirtAddr ; InstancePtr -> BdaRestart = ( XAxiCdma_Bd * ) ( void * ) PhysAddr ; return ( XST_SUCCESS ) ; }
This function creates the BD ring for the driver instance.
This function creates the BD ring for the driver instance .
/* In case there is a failure prior to creating list, make sure the
	 * following attributes are 0 to prevent calls to other SG functions
	 */ /* Make sure Alignment parameter meets minimum requirements */ /* Make sure Alignment is a power of 2 */ /* Make sure PhysAddr and VirtAddr have valid Alignment */ /* Compute how many bytes will be between the start of adjacent BDs */ /* Must make sure the ring doesn't span address 0x00000000. If it does,
	 * then the next/prev BD traversal macros will fail.
	 */ /* Initial ring setup:
	 *  - Clear the entire space
	 *  - Setup each BD's next pointer with the physical address of the
	 *    next BD
	 */ /* The virtual address is used to reference/flush cache for the BD
	 * The physical address is to be put in the BD for hardware reference
	 */ /* At the end of the ring, link the last BD back to the top,
	 * and set its fields
	 */ /* Setup and initialize pointers and counters */