/**
*
* This is the Receive handler function for examples 1 and 2.
* It will increment a shared  counter, receive and validate the frame.
*
* @param    RxRingPtr is a pointer to the DMA ring instance.
*
* @return   None.
*
* @note     None.
*
******************************************************************************/
static void RxIntrHandler(XLlDma_BdRing * RxRingPtr)
{
	u32 IrqStatus;

	/* Read pending interrupts */
	IrqStatus = XLlDma_mBdRingGetIrq(RxRingPtr);

	/* Acknowledge pending interrupts */
	XLlDma_mBdRingAckIrq(RxRingPtr, IrqStatus);

	/* If error interrupt is asserted, raise error flag, reset the
	 * hardware to recover from the error, and return with no further
	 * processing.
	 */
	if ((IrqStatus & XLLDMA_IRQ_ALL_ERR_MASK)) {
		DeviceErrors++;
		TemacUtilErrorTrap ("LlDma: Error: IrqStatus & XLLDMA_IRQ_ALL_ERR_MASK");
		XLlDma_Reset(&DmaInstance);
		return;
	}

	/*
	 * If Reception done interrupt is asserted, call RX call back function
	 * to handle the processed BDs and then raise the according flag.
	 */
	if ((IrqStatus & (XLLDMA_IRQ_DELAY_MASK | XLLDMA_IRQ_COALESCE_MASK))) {
		RxCallBack(RxRingPtr);
	}
}
예제 #2
0
/**
* Reset both TX and RX channels of a DMA engine.
*
* Any DMA transaction in progress aborts immediately. The DMA engine is in
* stop state after the reset.
*
* @param  InstancePtr is a pointer to the DMA engine instance to be worked on.
*
* @return None.
*
* @note
*         - If the hardware is not working properly, this function will enter
*           infinite loop and never return.
*         - After the reset, the Normal mode is enabled, and the overflow error
*           for both TX/RX channels are disabled.
*         - After the reset, the DMA engine is no longer in pausing state, if
*           the DMA engine is paused before the reset operation.
*         - After the reset, the coalescing count value and the delay timeout
*           value are both set to 1 for TX and RX channels.
*         - After the reset, all interrupts are disabled.
*
******************************************************************************/
void XLlDma_Reset(XLlDma * InstancePtr)
{
	u32 IrqStatus;
	XLlDma_BdRing *TxRingPtr, *RxRingPtr;

	TxRingPtr = &XLlDma_mGetTxRing(InstancePtr);
	RxRingPtr = &XLlDma_mGetRxRing(InstancePtr);

	/* Save the locations of current BDs both rings are working on
	 * before the reset so later we can resume the rings smoothly.
	 */
	XLlDma_mBdRingSnapShotCurrBd(TxRingPtr);
	XLlDma_mBdRingSnapShotCurrBd(RxRingPtr);

	/* Start reset process then wait for completion */
	XLlDma_mSetCr(InstancePtr, XLLDMA_DMACR_SW_RESET_MASK);

	/* Loop until the reset is done */
	while ((XLlDma_mGetCr(InstancePtr) & XLLDMA_DMACR_SW_RESET_MASK)) {
	}

	/* Disable all interrupts after issue software reset */
	XLlDma_mBdRingIntDisable(TxRingPtr, XLLDMA_CR_IRQ_ALL_EN_MASK);
	XLlDma_mBdRingIntDisable(RxRingPtr, XLLDMA_CR_IRQ_ALL_EN_MASK);

	/* Clear Interrupt registers of both channels, as the software reset
	 * does not clear any register values. Not doing so will cause
	 * interrupts asserted after the software reset if there is any
	 * interrupt left over before.
	 */
	IrqStatus = XLlDma_mBdRingGetIrq(TxRingPtr);
	XLlDma_mBdRingAckIrq(TxRingPtr, IrqStatus);
	IrqStatus = XLlDma_mBdRingGetIrq(RxRingPtr);
	XLlDma_mBdRingAckIrq(RxRingPtr, IrqStatus);

	/* Enable Normal mode, and disable overflow errors for both channels */
	XLlDma_mSetCr(InstancePtr, XLLDMA_DMACR_TAIL_PTR_EN_MASK |
		      XLLDMA_DMACR_RX_OVERFLOW_ERR_DIS_MASK |
		      XLLDMA_DMACR_TX_OVERFLOW_ERR_DIS_MASK);

	/* Set TX/RX Channel coalescing setting */
	XLlDma_BdRingSetCoalesce(TxRingPtr, 1, 1);
	XLlDma_BdRingSetCoalesce(RxRingPtr, 1, 1);

	TxRingPtr->RunState = XST_DMA_SG_IS_STOPPED;
	RxRingPtr->RunState = XST_DMA_SG_IS_STOPPED;
}