/**
*
* This is the DMA TX Interrupt handler function.
*
* @param    Callback is a pointer to TX channel of the DMA engine.
*
* @return   None.
*
* @note     This Interrupt handler MUST clear pending interrupts before
*           handling them by calling the call back. Otherwise the following
*           corner case could raise some issue:
*
*           - A packet was transmitted and asserted an TX interrupt, and if
*             this interrupt handler calls the call back before clears the
*             interrupt, another packet could get transmitted (and assert the
*             interrupt) between when the call back function returned and when
*             the interrupt clearing operation begins, and the interrupt
*             clearing operation will clear the interrupt raised by the second
*             packet and won't never process its according buffer descriptors
*             until a new interrupt occurs.
*
*           Changing the sequence to "Clear interrupts, then handle" solve this
*           issue. If the interrupt raised by the second packet is before the
*           the interrupt clearing operation, the descriptors associated with
*           the second packet must have been finished by hardware and ready for
*           the handling by the call back; otherwise, the interrupt raised by
*           the second packet is after the interrupt clearing operation,
*           the packet's buffer descriptors will be handled by the call back in
*           current pass, if the descriptors are finished before the call back
*           is invoked, or next pass otherwise. Please note that if the second
*           packet is handled by the call back in current pass, the next pass
*           could find no buffer descriptor finished by the hardware.
*
******************************************************************************/
static void TxIntrHandler(XLlDma_BdRing * TxRingPtr)
{
	u32 IrqStatus;

	/* Read pending interrupts */
	IrqStatus = XLlDma_BdRingGetIrq(TxRingPtr);

	/* Acknowledge pending interrupts */
	XLlDma_BdRingAckIrq(TxRingPtr, 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 Transmit done interrupt is asserted, call TX call back function
	 * to handle the processed BDs and raise the according flag
	 */
	if ((IrqStatus & (XLLDMA_IRQ_DELAY_MASK | XLLDMA_IRQ_COALESCE_MASK))) {
		TxCallBack(TxRingPtr);
	}
}
/*
*
* This is the DMA TX Interrupt handler function.
*
* It gets the interrupt status from the hardware, acknowledges it, and if any
* error happens, it resets the hardware. Otherwise, if a completion interrupt
* presents, then it calls the callback function.
*
* @param	Callback is a pointer to TX channel of the DMA engine.
*
* @return	None.
*
* @note		None.
*
******************************************************************************/
static void TxIntrHandler(void *Callback)
{
	XAxiDma_BdRing *TxRingPtr = (XAxiDma_BdRing *) Callback;
	u32 IrqStatus;
	int TimeOut;

	/* Read pending interrupts */
	IrqStatus = XAxiDma_BdRingGetIrq(TxRingPtr);

	/* Acknowledge pending interrupts */
	XAxiDma_BdRingAckIrq(TxRingPtr, IrqStatus);

	/* If no interrupt is asserted, we do not do anything
	 */
	if (!(IrqStatus & XAXIDMA_IRQ_ALL_MASK)) {

		return;
	}

	/*
	 * If error interrupt is asserted, raise error flag, reset the
	 * hardware to recover from the error, and return with no further
	 * processing.
	 */
	if ((IrqStatus & XAXIDMA_IRQ_ERROR_MASK)) {

		XAxiDma_BdRingDumpRegs(TxRingPtr);

		Error = 1;

		/*
		 * Reset should never fail for transmit channel
		 */
		XAxiDma_Reset(&AxiDma);

		TimeOut = RESET_TIMEOUT_COUNTER;

		while (TimeOut) {
			if (XAxiDma_ResetIsDone(&AxiDma)) {
				break;
			}

			TimeOut -= 1;
		}

		return;
	}

	/*
	 * If Transmit done interrupt is asserted, call TX call back function
	 * to handle the processed BDs and raise the according flag
	 */
	if ((IrqStatus & (XAXIDMA_IRQ_DELAY_MASK | XAXIDMA_IRQ_IOC_MASK))) {
		TxCallBack(TxRingPtr);
	}
}