/*
* Check for transfer completion.
*
* If the DMA engine has errors or any of the finished BDs has error bit set,
* then the example should fail.
*
* @param	InstancePtr is pointer to the XAxiCdma instance.
*
* @return	Number of Bds that have been completed by hardware.
*
* @note		None
*
******************************************************************************/
static int CheckCompletion(XAxiCdma *InstancePtr)
{
	int BdCount;
	XAxiCdma_Bd *BdPtr;
	XAxiCdma_Bd *BdCurPtr;
	int Status;
	int Index;

	/* Check whether the hardware has encountered any problems.
	 * In some error cases, the DMA engine may not able to update the
	 * BD that has caused the problem.
	 */
	if (XAxiCdma_GetError(InstancePtr) != 0x0) {
		xdbg_printf(XDBG_DEBUG_ERROR, "Transfer error %x\r\n",
		    (unsigned int)XAxiCdma_GetError(InstancePtr));

		Error = 1;
		return 0;
	}

	/* Get all processed BDs from hardware
	 */
	BdCount = XAxiCdma_BdRingFromHw(InstancePtr, XAXICDMA_ALL_BDS, &BdPtr);

	/* Check finished BDs then release them
	 */
	if(BdCount > 0) {
		BdCurPtr = BdPtr;

		for (Index = 0; Index < BdCount; Index++) {

			/* If the completed BD has error bit set,
			 * then the example fails
			 */
			if (XAxiCdma_BdGetSts(BdCurPtr) &
			    XAXICDMA_BD_STS_ALL_ERR_MASK)	{
				Error = 1;
				return 0;
			}

			BdCurPtr = XAxiCdma_BdRingNext(InstancePtr, BdCurPtr);
		}

		/* Release the BDs so later submission can use them
		 */
		Status = XAxiCdma_BdRingFree(InstancePtr, BdCount, BdPtr);

		if(Status != XST_SUCCESS) {
			xdbg_printf(XDBG_DEBUG_ERROR,
			    "Error free BD %x\r\n", Status);

			Error = 1;
			return 0;
		}

		Done += BdCount;
	}

	return Done;
}
/*
*
* This function non-blockingly transmits all packets through the DMA engine.
*
* @param	InstancePtr points to the DMA engine instance
*
* @return
*		- XST_SUCCESS if the DMA accepts all the packets successfully,
*		- XST_FAILURE if following error occurs
*			BD ring allocation failed
*			One of the buffer transfer length is invalid
*			Submission to hardware failed
*
* @note		None.
*
******************************************************************************/
static int SubmitSgTransfer(XAxiCdma * InstancePtr)
{
	XAxiCdma_Bd *BdPtr;
	XAxiCdma_Bd *BdCurPtr;
	int Status;
	int Index;
	u32 SrcBufferAddr;
	u32 DstBufferAddr;
	static int Counter = 0;

	Status = XAxiCdma_BdRingAlloc(InstancePtr,
		    NUMBER_OF_BDS_TO_TRANSFER, &BdPtr);
	if (Status != XST_SUCCESS) {
		xdbg_printf(XDBG_DEBUG_ERROR, "Failed bd alloc\r\n");

		return XST_FAILURE;
	}

	SrcBufferAddr = (u32)TransmitBufferPtr;
	DstBufferAddr = (u32)ReceiveBufferPtr;
	BdCurPtr = BdPtr;

	/* Set up the BDs
	 */
	for(Index = 0; Index < NUMBER_OF_BDS_TO_TRANSFER; Index++) {
		Counter += 1;

		Status = XAxiCdma_BdSetSrcBufAddr(BdCurPtr, SrcBufferAddr);
		if(Status != XST_SUCCESS) {
			xdbg_printf(XDBG_DEBUG_ERROR,
			    "Set src addr failed %d, %x/%x\r\n",
			    Status, (unsigned int)BdCurPtr,
			    (unsigned int)SrcBufferAddr);

			return XST_FAILURE;
		}

		Status = XAxiCdma_BdSetDstBufAddr(BdCurPtr, DstBufferAddr);
		if(Status != XST_SUCCESS) {
			xdbg_printf(XDBG_DEBUG_ERROR,
			    "Set dst addr failed %d, %x/%x\r\n",
			    Status, (unsigned int)BdCurPtr,
			    (unsigned int)DstBufferAddr);

			return XST_FAILURE;
		}

		Status = XAxiCdma_BdSetLength(BdCurPtr, MAX_PKT_LEN);
		if(Status != XST_SUCCESS) {
			xdbg_printf(XDBG_DEBUG_ERROR,
			    "Set BD length failed %d\r\n", Status);

			return XST_FAILURE;
		}

		SrcBufferAddr += MAX_PKT_LEN;
		DstBufferAddr += MAX_PKT_LEN;
		BdCurPtr = XAxiCdma_BdRingNext(InstancePtr, BdCurPtr);
	}

	/* Give the BDs to hardware */
	Status = XAxiCdma_BdRingToHw(InstancePtr,
		NUMBER_OF_BDS_TO_TRANSFER, BdPtr,
	    (XAxiCdma_CallBackFn)Example_SgCallBack, (void *)InstancePtr);
	if (Status != XST_SUCCESS) {
		xdbg_printf(XDBG_DEBUG_ERROR, "Failed to hw %d\r\n", Status);

		return XST_FAILURE;
	}

	return XST_SUCCESS;
}
Пример #3
0
/*
 * Change the hardware mode
 *
 * If to switch to SG mode, check whether needs to setup the current BD
 * pointer register.
 *
 * @param	InstancePtr is the driver instance we are working on
 * @param	Mode is the mode to switch to.
 *
 * @return
 *		- XST_SUCCESS if mode switch is successful
 *		- XST_DEVICE_BUSY if the engine is busy, so cannot switch mode
 *		- XST_INVALID_PARAM if pass in invalid mode value
 *		- XST_FAILURE if:Hardware is simple mode only build
 *		Mode switch failed
 *
 * @note	None.
 *
 *****************************************************************************/
int XAxiCdma_SwitchMode(XAxiCdma *InstancePtr, int Mode)
{

	if (Mode == XAXICDMA_SIMPLE_MODE) {

		if (XAxiCdma_IsSimpleMode(InstancePtr)) {
			return XST_SUCCESS;
		}

		if (XAxiCdma_IsBusy(InstancePtr)) {
			xdbg_printf(XDBG_DEBUG_ERROR,
			    "SwitchMode: engine is busy\r\n");
			return XST_DEVICE_BUSY;
		}

		/* Keep the CDESC so that CDESC will be
		 * reloaded when switch to SG mode again
		 *
		 * We know CDESC is valid because the hardware can only
		 * be in SG mode if a SG transfer has been submitted.
		 */
		InstancePtr->BdaRestart = XAxiCdma_BdRingNext(InstancePtr,
		    XAxiCdma_BdRingGetCurrBd(InstancePtr));

		/* Update the CR register to switch to simple mode
		 */
		XAxiCdma_WriteReg(InstancePtr->BaseAddr, XAXICDMA_CR_OFFSET,
		  (XAxiCdma_ReadReg(InstancePtr->BaseAddr, XAXICDMA_CR_OFFSET)
		  & ~XAXICDMA_CR_SGMODE_MASK));

		/* Hardware mode switch is quick, should succeed right away
		 */
		if (XAxiCdma_IsSimpleMode(InstancePtr)) {

			return XST_SUCCESS;
		}
		else {
			return XST_FAILURE;
		}
	}
	else if (Mode == XAXICDMA_SG_MODE) {

		if (!XAxiCdma_IsSimpleMode(InstancePtr)) {
			return XST_SUCCESS;
		}

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

		if (XAxiCdma_IsBusy(InstancePtr)) {
			xdbg_printf(XDBG_DEBUG_ERROR,
			    "SwitchMode: engine is busy\r\n");
			return XST_DEVICE_BUSY;
		}

		/* Update the CR register to switch to SG mode
		 */
		XAxiCdma_WriteReg(InstancePtr->BaseAddr, XAXICDMA_CR_OFFSET,
		  (XAxiCdma_ReadReg(InstancePtr->BaseAddr, XAXICDMA_CR_OFFSET)
		  | XAXICDMA_CR_SGMODE_MASK));

		/* Hardware mode switch is quick, should succeed right away
		 */
		if (!XAxiCdma_IsSimpleMode(InstancePtr)) {

			/* Update the CDESC register, because the hardware is
			 * to start from the CDESC
			 */
			XAxiCdma_BdSetCurBdPtr(InstancePtr,
				(UINTPTR)InstancePtr->BdaRestart);

			return XST_SUCCESS;
		}
		else {
			return XST_FAILURE;
		}
	}
	else {	/* Invalid mode */
		return XST_INVALID_PARAM;
	}
}