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