/*
* 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;
}
/*
* Callback function for the scatter gather transfer.
* It is called by the driver's interrupt handler.
*
* @param	CallBackRef is the reference pointer registered through
*		transfer submission. In this case, it is the pointer to the
*		driver instance
* @param	IrqMask is the interrupt mask the driver interrupt handler
*		passes to the callback function.
* @param	NumBdPtr is the pointer to number of BDs this handler handles
*
* @return	None
*
* @note		None.
*
******************************************************************************/
static void Example_SgCallBack(void *CallBackRef, u32 IrqMask, int *NumBdPtr)
{

	XAxiCdma *InstancePtr;
	int BdCount;
	XAxiCdma_Bd *BdPtr;
	int Status;
	int Tmp;

	InstancePtr = (XAxiCdma *)CallBackRef;
	Tmp = *NumBdPtr;

	/* If error interrupt happened, the driver interrupt handler
	 * has already reset the hardware
	 */
	if (IrqMask & XAXICDMA_XR_IRQ_ERROR_MASK) {
		Error = 1;
	}

	if (IrqMask & XAXICDMA_XR_IRQ_IOC_MASK) {

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

		/* Release finished BDs
		 *
		 * It is ok if BdCount is zero as a previous callback may
		 * have ripen all finished BDs
		 */
		if(BdCount > 0) {

			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;
			}

			Done += BdCount;
			*NumBdPtr = Tmp - BdCount;
		}
	}

	return;
}