diff options
| author | wdenk <wdenk> | 2004-02-23 23:54:43 +0000 | 
|---|---|---|
| committer | wdenk <wdenk> | 2004-02-23 23:54:43 +0000 | 
| commit | 028ab6b598b628326116acd88e0f35aa9f526d12 (patch) | |
| tree | 0d54315bd92d713a405004b6e36fca8d2b7c53e3 /board/xilinx/xilinx_enet/xemac_intr_dma.c | |
| parent | 63e73c9a8ed5b32d9c4067ffaad953e9a8fe8f0a (diff) | |
| download | olio-uboot-2014.01-028ab6b598b628326116acd88e0f35aa9f526d12.tar.xz olio-uboot-2014.01-028ab6b598b628326116acd88e0f35aa9f526d12.zip | |
* Patch by Peter Ryser, 20 Feb 2004:
  Add support for the Xilinx ML300 platform
* Patch by Stephan Linz, 17 Feb 2004:
  Fix watchdog support for NIOS
* Patch by Josh Fryman, 16 Feb 2004:
  Fix byte-swapping for cfi_flash.c for different bus widths
* Patch by Jon Diekema, 14 Jeb 2004:
  Remove duplicate "FPGA Support" notes from the README file
Diffstat (limited to 'board/xilinx/xilinx_enet/xemac_intr_dma.c')
| -rw-r--r-- | board/xilinx/xilinx_enet/xemac_intr_dma.c | 1344 | 
1 files changed, 1344 insertions, 0 deletions
| diff --git a/board/xilinx/xilinx_enet/xemac_intr_dma.c b/board/xilinx/xilinx_enet/xemac_intr_dma.c new file mode 100644 index 000000000..567abb42a --- /dev/null +++ b/board/xilinx/xilinx_enet/xemac_intr_dma.c @@ -0,0 +1,1344 @@ +/****************************************************************************** +* +*     Author: Xilinx, Inc. +* +* +*     This program is free software; you can redistribute it and/or modify it +*     under the terms of the GNU General Public License as published by the +*     Free Software Foundation; either version 2 of the License, or (at your +*     option) any later version. +* +* +*     XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION "AS IS" AS A +*     COURTESY TO YOU. BY PROVIDING THIS DESIGN, CODE, OR INFORMATION AS +*     ONE POSSIBLE IMPLEMENTATION OF THIS FEATURE, APPLICATION OR STANDARD, +*     XILINX IS MAKING NO REPRESENTATION THAT THIS IMPLEMENTATION IS FREE +*     FROM ANY CLAIMS OF INFRINGEMENT, AND YOU ARE RESPONSIBLE FOR OBTAINING +*     ANY THIRD PARTY RIGHTS YOU MAY REQUIRE FOR YOUR IMPLEMENTATION. +*     XILINX EXPRESSLY DISCLAIMS ANY WARRANTY WHATSOEVER WITH RESPECT TO +*     THE ADEQUACY OF THE IMPLEMENTATION, INCLUDING BUT NOT LIMITED TO ANY +*     WARRANTIES OR REPRESENTATIONS THAT THIS IMPLEMENTATION IS FREE FROM +*     CLAIMS OF INFRINGEMENT, IMPLIED WARRANTIES OF MERCHANTABILITY AND +*     FITNESS FOR A PARTICULAR PURPOSE. +* +* +*     Xilinx hardware products are not intended for use in life support +*     appliances, devices, or systems. Use in such applications is +*     expressly prohibited. +* +* +*     (c) Copyright 2002-2004 Xilinx Inc. +*     All rights reserved. +* +* +*     You should have received a copy of the GNU General Public License along +*     with this program; if not, write to the Free Software Foundation, Inc., +*     675 Mass Ave, Cambridge, MA 02139, USA. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xemac_intr_dma.c +* +* Contains functions used in interrupt mode when configured with scatter-gather +* DMA. +* +* The interrupt handler, XEmac_IntrHandlerDma(), must be connected by the user +* to the interrupt controller. +* +* <pre> +* MODIFICATION HISTORY: +* +* Ver   Who  Date     Changes +* ----- ---- -------- --------------------------------------------------------- +* 1.00a rpm  07/31/01 First release +* 1.00b rpm  02/20/02 Repartitioned files and functions +* 1.00c rpm  12/05/02 New version includes support for simple DMA and the delay +*                     argument to SgSend +* 1.00c rpm  02/03/03 The XST_DMA_SG_COUNT_EXCEEDED return code was removed +*                     from SetPktThreshold in the internal DMA driver. Also +*                     avoided compiler warnings by initializing Result in the +*                     interrupt service routines. +* 1.00c rpm  03/26/03 Fixed a problem in the interrupt service routines where +*                     the interrupt status was toggled clear after a call to +*                     ErrorHandler, but if ErrorHandler reset the device the +*                     toggle actually asserted the interrupt because the +*                     reset had cleared it. +* </pre> +* +******************************************************************************/ + +/***************************** Include Files *********************************/ + +#include "xbasic_types.h" +#include "xemac_i.h" +#include "xio.h" +#include "xbuf_descriptor.h" +#include "xdma_channel.h" +#include "xipif_v1_23_b.h"	/* Uses v1.23b of the IPIF */ + +/************************** Constant Definitions *****************************/ + +/**************************** Type Definitions *******************************/ + +/***************** Macros (Inline Functions) Definitions *********************/ + +/************************** Variable Definitions *****************************/ + +/************************** Function Prototypes ******************************/ + +static void HandleDmaRecvIntr(XEmac * InstancePtr); +static void HandleDmaSendIntr(XEmac * InstancePtr); +static void HandleEmacDmaIntr(XEmac * InstancePtr); + +/*****************************************************************************/ +/** +* +* Send an Ethernet frame using scatter-gather DMA. The caller attaches the +* frame to one or more buffer descriptors, then calls this function once for +* each descriptor. The caller is responsible for allocating and setting up the +* descriptor. An entire Ethernet frame may or may not be contained within one +* descriptor.  This function simply inserts the descriptor into the scatter- +* gather engine's transmit list. The caller is responsible for providing mutual +* exclusion to guarantee that a frame is contiguous in the transmit list. The +* buffer attached to the descriptor must be word-aligned. +* +* The driver updates the descriptor with the device control register before +* being inserted into the transmit list.  If this is the last descriptor in +* the frame, the inserts are committed, which means the descriptors for this +* frame are now available for transmission. +* +* It is assumed that the upper layer software supplies a correctly formatted +* Ethernet frame, including the destination and source addresses, the +* type/length field, and the data field.  It is also assumed that upper layer +* software does not append FCS at the end of the frame. +* +* The buffer attached to the descriptor must be word-aligned on the front end. +* +* This call is non-blocking.  Notification of error or successful transmission +* is done asynchronously through the send or error callback function. +* +* @param InstancePtr is a pointer to the XEmac instance to be worked on. +* @param BdPtr is the address of a descriptor to be inserted into the transmit +*        ring. +* @param Delay indicates whether to start the scatter-gather DMA channel +*        immediately, or whether to wait. This allows the user to build up a +*        list of more than one descriptor before starting the transmission of +*        the packets, which allows the application to keep up with DMA and have +*        a constant stream of frames being transmitted. Use XEM_SGDMA_NODELAY or +*        XEM_SGDMA_DELAY, defined in xemac.h, as the value of this argument. If +*        the user chooses to delay and build a list, the user must call this +*        function with the XEM_SGDMA_NODELAY option or call XEmac_Start() to +*        kick off the tranmissions. +* +* @return +* +* - XST_SUCCESS if the buffer was successfull sent +* - XST_DEVICE_IS_STOPPED if the Ethernet MAC has not been started yet +* - XST_NOT_SGDMA if the device is not in scatter-gather DMA mode +* - XST_DMA_SG_LIST_FULL if the descriptor list for the DMA channel is full +* - XST_DMA_SG_BD_LOCKED if the DMA channel cannot insert the descriptor into +*   the list because a locked descriptor exists at the insert point +* - XST_DMA_SG_NOTHING_TO_COMMIT if even after inserting a descriptor into the +*   list, the DMA channel believes there are no new descriptors to commit. If +*   this is ever encountered, there is likely a thread mutual exclusion problem +*   on transmit. +* +* @note +* +* This function is not thread-safe. The user must provide mutually exclusive +* access to this function if there are to be multiple threads that can call it. +* +* @internal +* +* A status that should never be returned from this function, although +* the code is set up to handle it, is XST_DMA_SG_NO_LIST. Starting the device +* requires a list to be created, and this function requires the device to be +* started. +* +******************************************************************************/ +XStatus +XEmac_SgSend(XEmac * InstancePtr, XBufDescriptor * BdPtr, int Delay) +{ +	XStatus Result; +	u32 BdControl; + +	XASSERT_NONVOID(InstancePtr != NULL); +	XASSERT_NONVOID(BdPtr != NULL); +	XASSERT_NONVOID(InstancePtr->IsReady == XCOMPONENT_IS_READY); + +	/* +	 * Be sure the device is configured for scatter-gather DMA, then be sure +	 * it is started. +	 */ +	if (!XEmac_mIsSgDma(InstancePtr)) { +		return XST_NOT_SGDMA; +	} + +	/* +	 * Set some descriptor control word defaults (source address increment +	 * and local destination address) and the destination address +	 * (the FIFO).  These are the same for every transmit descriptor. +	 */ +	BdControl = XBufDescriptor_GetControl(BdPtr); +	XBufDescriptor_SetControl(BdPtr, BdControl | XEM_DFT_SEND_BD_MASK); + +	XBufDescriptor_SetDestAddress(BdPtr, +				      InstancePtr->BaseAddress + +				      XEM_PFIFO_TXDATA_OFFSET); + +	/* +	 * Put the descriptor in the send list. The DMA component accesses data +	 * here that can also be modified in interrupt context, so a critical +	 * section is required. +	 */ +	XIIF_V123B_GINTR_DISABLE(InstancePtr->BaseAddress); + +	Result = XDmaChannel_PutDescriptor(&InstancePtr->SendChannel, BdPtr); +	if (Result != XST_SUCCESS) { +		XIIF_V123B_GINTR_ENABLE(InstancePtr->BaseAddress); +		return Result; +	} + +	/* +	 * If this is the last buffer in the frame, commit the inserts and start +	 * the DMA engine if necessary +	 */ +	if (XBufDescriptor_IsLastControl(BdPtr)) { +		Result = XDmaChannel_CommitPuts(&InstancePtr->SendChannel); +		if (Result != XST_SUCCESS) { +			XIIF_V123B_GINTR_ENABLE(InstancePtr->BaseAddress); +			return Result; +		} + +		if (Delay == XEM_SGDMA_NODELAY) { +			/* +			 * Start the DMA channel. Ignore the return status since we know the +			 * list exists and has at least one entry and we don't care if the +			 * channel is already started.  The DMA component accesses data here +			 * that can be modified at interrupt or task levels, so a critical +			 * section is required. +			 */ +			(void) XDmaChannel_SgStart(&InstancePtr->SendChannel); +		} +	} + +	XIIF_V123B_GINTR_ENABLE(InstancePtr->BaseAddress); + +	return XST_SUCCESS; +} + +/*****************************************************************************/ +/** +* +* Add a descriptor, with an attached empty buffer, into the receive descriptor +* list. The buffer attached to the descriptor must be word-aligned. This is +* used by the upper layer software during initialization when first setting up +* the receive descriptors, and also during reception of frames to replace +* filled buffers with empty buffers. This function can be called when the +* device is started or stopped. Note that it does start the scatter-gather DMA +* engine.  Although this is not necessary during initialization, it is not a +* problem during initialization because the MAC receiver is not yet started. +* +* The buffer attached to the descriptor must be word-aligned on both the front +* end and the back end. +* +* Notification of received frames are done asynchronously through the receive +* callback function. +* +* @param InstancePtr is a pointer to the XEmac instance to be worked on. +* @param BdPtr is a pointer to the buffer descriptor that will be added to the +*        descriptor list. +* +* @return +* +* - XST_SUCCESS if a descriptor was successfully returned to the driver +* - XST_NOT_SGDMA if the device is not in scatter-gather DMA mode +* - XST_DMA_SG_LIST_FULL if the receive descriptor list is full +* - XST_DMA_SG_BD_LOCKED if the DMA channel cannot insert the descriptor into +*   the list because a locked descriptor exists at the insert point. +* - XST_DMA_SG_NOTHING_TO_COMMIT if even after inserting a descriptor into the +*   list, the DMA channel believes there are no new descriptors to commit. +* +* @internal +* +* A status that should never be returned from this function, although +* the code is set up to handle it, is XST_DMA_SG_NO_LIST. Starting the device +* requires a list to be created, and this function requires the device to be +* started. +* +******************************************************************************/ +XStatus +XEmac_SgRecv(XEmac * InstancePtr, XBufDescriptor * BdPtr) +{ +	XStatus Result; +	u32 BdControl; + +	XASSERT_NONVOID(InstancePtr != NULL); +	XASSERT_NONVOID(BdPtr != NULL); +	XASSERT_NONVOID(InstancePtr->IsReady == XCOMPONENT_IS_READY); + +	/* +	 * Be sure the device is configured for scatter-gather DMA +	 */ +	if (!XEmac_mIsSgDma(InstancePtr)) { +		return XST_NOT_SGDMA; +	} + +	/* +	 * Set some descriptor control word defaults (destination address increment +	 * and local source address) and the source address (the FIFO). These are +	 * the same for every receive descriptor. +	 */ +	BdControl = XBufDescriptor_GetControl(BdPtr); +	XBufDescriptor_SetControl(BdPtr, BdControl | XEM_DFT_RECV_BD_MASK); +	XBufDescriptor_SetSrcAddress(BdPtr, +				     InstancePtr->BaseAddress + +				     XEM_PFIFO_RXDATA_OFFSET); + +	/* +	 * Put the descriptor into the channel's descriptor list and commit. +	 * Although this function is likely called within interrupt context, there +	 * is the possibility that the upper layer software queues it to a task. +	 * In this case, a critical section is needed here to protect shared data +	 * in the DMA component. +	 */ +	XIIF_V123B_GINTR_DISABLE(InstancePtr->BaseAddress); + +	Result = XDmaChannel_PutDescriptor(&InstancePtr->RecvChannel, BdPtr); +	if (Result != XST_SUCCESS) { +		XIIF_V123B_GINTR_ENABLE(InstancePtr->BaseAddress); +		return Result; +	} + +	Result = XDmaChannel_CommitPuts(&InstancePtr->RecvChannel); +	if (Result != XST_SUCCESS) { +		XIIF_V123B_GINTR_ENABLE(InstancePtr->BaseAddress); +		return Result; +	} + +	/* +	 * Start the DMA channel. Ignore the return status since we know the list +	 * exists and has at least one entry and we don't care if the channel is +	 * already started. The DMA component accesses data here that can be +	 * modified at interrupt or task levels, so a critical section is required. +	 */ +	(void) XDmaChannel_SgStart(&InstancePtr->RecvChannel); + +	XIIF_V123B_GINTR_ENABLE(InstancePtr->BaseAddress); + +	return XST_SUCCESS; +} + +/*****************************************************************************/ +/** +* +* The interrupt handler for the Ethernet driver when configured with scatter- +* gather DMA. +* +* Get the interrupt status from the IpIf to determine the source of the +* interrupt.  The source can be: MAC, Recv Packet FIFO, Send Packet FIFO, Recv +* DMA channel, or Send DMA channel. The packet FIFOs only interrupt during +* "deadlock" conditions. +* +* @param InstancePtr is a pointer to the XEmac instance that just interrupted. +* +* @return +* +* None. +* +* @note +* +* None. +* +******************************************************************************/ +void +XEmac_IntrHandlerDma(void *InstancePtr) +{ +	u32 IntrStatus; +	XEmac *EmacPtr = (XEmac *) InstancePtr; + +	EmacPtr->Stats.TotalIntrs++; + +	/* +	 * Get the interrupt status from the IPIF. There is no clearing of +	 * interrupts in the IPIF. Interrupts must be cleared at the source. +	 */ +	IntrStatus = XIIF_V123B_READ_DIPR(EmacPtr->BaseAddress); + +	/* +	 * See which type of interrupt is being requested, and service it +	 */ +	if (IntrStatus & XEM_IPIF_RECV_DMA_MASK) {	/* Receive DMA interrupt */ +		EmacPtr->Stats.RecvInterrupts++; +		HandleDmaRecvIntr(EmacPtr); +	} + +	if (IntrStatus & XEM_IPIF_SEND_DMA_MASK) {	/* Send DMA interrupt */ +		EmacPtr->Stats.XmitInterrupts++; +		HandleDmaSendIntr(EmacPtr); +	} + +	if (IntrStatus & XEM_IPIF_EMAC_MASK) {	/* MAC interrupt */ +		EmacPtr->Stats.EmacInterrupts++; +		HandleEmacDmaIntr(EmacPtr); +	} + +	if (IntrStatus & XEM_IPIF_RECV_FIFO_MASK) {	/* Receive FIFO interrupt */ +		EmacPtr->Stats.RecvInterrupts++; +		XEmac_CheckFifoRecvError(EmacPtr); +	} + +	if (IntrStatus & XEM_IPIF_SEND_FIFO_MASK) {	/* Send FIFO interrupt */ +		EmacPtr->Stats.XmitInterrupts++; +		XEmac_CheckFifoSendError(EmacPtr); +	} + +	if (IntrStatus & XIIF_V123B_ERROR_MASK) { +		/* +		 * An error occurred internal to the IPIF. This is more of a debug and +		 * integration issue rather than a production error. Don't do anything +		 * other than clear it, which provides a spot for software to trap +		 * on the interrupt and begin debugging. +		 */ +		XIIF_V123B_WRITE_DISR(EmacPtr->BaseAddress, +				      XIIF_V123B_ERROR_MASK); +	} +} + +/*****************************************************************************/ +/** +* +* Set the packet count threshold for this device. The device must be stopped +* before setting the threshold. The packet count threshold is used for interrupt +* coalescing, which reduces the frequency of interrupts from the device to the +* processor. In this case, the scatter-gather DMA engine only interrupts when +* the packet count threshold is reached, instead of interrupting for each packet. +* A packet is a generic term used by the scatter-gather DMA engine, and is +* equivalent to an Ethernet frame in our case. +* +* @param InstancePtr is a pointer to the XEmac instance to be worked on. +* @param Direction indicates the channel, send or receive, from which the +*        threshold register is read. +* @param Threshold is the value of the packet threshold count used during +*        interrupt coalescing. A value of 0 disables the use of packet threshold +*        by the hardware. +* +* @return +* +* - XST_SUCCESS if the threshold was successfully set +* - XST_NOT_SGDMA if the MAC is not configured for scatter-gather DMA +* - XST_DEVICE_IS_STARTED if the device has not been stopped +* - XST_INVALID_PARAM if the Direction parameter is invalid. Turning on +*   asserts would also catch this error. +* +* @note +* +* The packet threshold could be set to larger than the number of descriptors +* allocated to the DMA channel. In this case, the wait bound will take over +* and always indicate data arrival. There was a check in this function that +* returned an error if the treshold was larger than the number of descriptors, +* but that was removed because users would then have to set the threshold +* only after they set descriptor space, which is an order dependency that +* caused confustion. +* +******************************************************************************/ +XStatus +XEmac_SetPktThreshold(XEmac * InstancePtr, u32 Direction, u8 Threshold) +{ +	XASSERT_NONVOID(InstancePtr != NULL); +	XASSERT_NONVOID(Direction == XEM_SEND || Direction == XEM_RECV); +	XASSERT_NONVOID(InstancePtr->IsReady == XCOMPONENT_IS_READY); + +	/* +	 * Be sure device is configured for scatter-gather DMA and has been stopped +	 */ +	if (!XEmac_mIsSgDma(InstancePtr)) { +		return XST_NOT_SGDMA; +	} + +	if (InstancePtr->IsStarted == XCOMPONENT_IS_STARTED) { +		return XST_DEVICE_IS_STARTED; +	} + +	/* +	 * Based on the direction, set the packet threshold in the +	 * corresponding DMA channel component.  Default to the receive +	 * channel threshold register (if an invalid Direction is passed). +	 */ +	switch (Direction) { +	case XEM_SEND: +		return XDmaChannel_SetPktThreshold(&InstancePtr->SendChannel, +						   Threshold); + +	case XEM_RECV: +		return XDmaChannel_SetPktThreshold(&InstancePtr->RecvChannel, +						   Threshold); + +	default: +		return XST_INVALID_PARAM; +	} +} + +/*****************************************************************************/ +/** +* +* Get the value of the packet count threshold for this driver/device. The packet +* count threshold is used for interrupt coalescing, which reduces the frequency +* of interrupts from the device to the processor. In this case, the +* scatter-gather DMA engine only interrupts when the packet count threshold is +* reached, instead of interrupting for each packet. A packet is a generic term +* used by the scatter-gather DMA engine, and is equivalent to an Ethernet frame +* in our case. +* +* @param InstancePtr is a pointer to the XEmac instance to be worked on. +* @param Direction indicates the channel, send or receive, from which the +*        threshold register is read. +* @param ThreshPtr is a pointer to the byte into which the current value of the +*        packet threshold register will be copied. An output parameter. A value +*        of 0 indicates the use of packet threshold by the hardware is disabled. +* +* @return +* +* - XST_SUCCESS if the packet threshold was retrieved successfully +* - XST_NOT_SGDMA if the MAC is not configured for scatter-gather DMA +* - XST_INVALID_PARAM if the Direction parameter is invalid. Turning on +*   asserts would also catch this error. +* +* @note +* +* None. +* +******************************************************************************/ +XStatus +XEmac_GetPktThreshold(XEmac * InstancePtr, u32 Direction, u8 * ThreshPtr) +{ +	XASSERT_NONVOID(InstancePtr != NULL); +	XASSERT_NONVOID(Direction == XEM_SEND || Direction == XEM_RECV); +	XASSERT_NONVOID(ThreshPtr != NULL); +	XASSERT_NONVOID(InstancePtr->IsReady == XCOMPONENT_IS_READY); + +	if (!XEmac_mIsSgDma(InstancePtr)) { +		return XST_NOT_SGDMA; +	} + +	/* +	 * Based on the direction, return the packet threshold set in the +	 * corresponding DMA channel component.  Default to the value in +	 * the receive channel threshold register (if an invalid Direction +	 * is passed). +	 */ +	switch (Direction) { +	case XEM_SEND: +		*ThreshPtr = +		    XDmaChannel_GetPktThreshold(&InstancePtr->SendChannel); +		break; + +	case XEM_RECV: +		*ThreshPtr = +		    XDmaChannel_GetPktThreshold(&InstancePtr->RecvChannel); +		break; + +	default: +		return XST_INVALID_PARAM; +	} + +	return XST_SUCCESS; +} + +/*****************************************************************************/ +/** +* +* Set the packet wait bound timer for this driver/device. The device must be +* stopped before setting the timer value. The packet wait bound is used during +* interrupt coalescing to trigger an interrupt when not enough packets have been +* received to reach the packet count threshold. A packet is a generic term used +* by the scatter-gather DMA engine, and is equivalent to an Ethernet frame in +* our case. The timer is in milliseconds. +* +* @param InstancePtr is a pointer to the XEmac instance to be worked on. +* @param Direction indicates the channel, send or receive, from which the +*        threshold register is read. +* @param TimerValue is the value of the packet wait bound used during interrupt +*        coalescing. It is in milliseconds in the range 0  - 1023. A value of 0 +*        disables the packet wait bound timer. +* +* @return +* +* - XST_SUCCESS if the packet wait bound was set successfully +* - XST_NOT_SGDMA if the MAC is not configured for scatter-gather DMA +* - XST_DEVICE_IS_STARTED if the device has not been stopped +* - XST_INVALID_PARAM if the Direction parameter is invalid. Turning on +*   asserts would also catch this error. +* +* @note +* +* None. +* +******************************************************************************/ +XStatus +XEmac_SetPktWaitBound(XEmac * InstancePtr, u32 Direction, u32 TimerValue) +{ +	XASSERT_NONVOID(InstancePtr != NULL); +	XASSERT_NONVOID(Direction == XEM_SEND || Direction == XEM_RECV); +	XASSERT_NONVOID(TimerValue <= XEM_SGDMA_MAX_WAITBOUND); +	XASSERT_NONVOID(InstancePtr->IsReady == XCOMPONENT_IS_READY); + +	/* +	 * Be sure device is configured for scatter-gather DMA and has been stopped +	 */ +	if (!XEmac_mIsSgDma(InstancePtr)) { +		return XST_NOT_SGDMA; +	} + +	if (InstancePtr->IsStarted == XCOMPONENT_IS_STARTED) { +		return XST_DEVICE_IS_STARTED; +	} + +	/* +	 * Based on the direction, set the packet wait bound in the +	 * corresponding DMA channel component.  Default to the receive +	 * channel wait bound register (if an invalid Direction is passed). +	 */ +	switch (Direction) { +	case XEM_SEND: +		XDmaChannel_SetPktWaitBound(&InstancePtr->SendChannel, +					    TimerValue); +		break; + +	case XEM_RECV: +		XDmaChannel_SetPktWaitBound(&InstancePtr->RecvChannel, +					    TimerValue); +		break; + +	default: +		return XST_INVALID_PARAM; +	} + +	return XST_SUCCESS; +} + +/*****************************************************************************/ +/** +* +* Get the packet wait bound timer for this driver/device. The packet wait bound +* is used during interrupt coalescing to trigger an interrupt when not enough +* packets have been received to reach the packet count threshold. A packet is a +* generic term used by the scatter-gather DMA engine, and is equivalent to an +* Ethernet frame in our case. The timer is in milliseconds. +* +* @param InstancePtr is a pointer to the XEmac instance to be worked on. +* @param Direction indicates the channel, send or receive, from which the +*        threshold register is read. +* @param WaitPtr is a pointer to the byte into which the current value of the +*        packet wait bound register will be copied. An output parameter. Units +*        are in milliseconds in the range 0  - 1023. A value of 0 indicates the +*        packet wait bound timer is disabled. +* +* @return +* +* - XST_SUCCESS if the packet wait bound was retrieved successfully +* - XST_NOT_SGDMA if the MAC is not configured for scatter-gather DMA +* - XST_INVALID_PARAM if the Direction parameter is invalid. Turning on +*   asserts would also catch this error. +* +* @note +* +* None. +* +******************************************************************************/ +XStatus +XEmac_GetPktWaitBound(XEmac * InstancePtr, u32 Direction, u32 * WaitPtr) +{ +	XASSERT_NONVOID(InstancePtr != NULL); +	XASSERT_NONVOID(Direction == XEM_SEND || Direction == XEM_RECV); +	XASSERT_NONVOID(WaitPtr != NULL); +	XASSERT_NONVOID(InstancePtr->IsReady == XCOMPONENT_IS_READY); + +	if (!XEmac_mIsSgDma(InstancePtr)) { +		return XST_NOT_SGDMA; +	} + +	/* +	 * Based on the direction, return the packet wait bound set in the +	 * corresponding DMA channel component.  Default to the value in +	 * the receive channel wait bound register (if an invalid Direction +	 * is passed). +	 */ +	switch (Direction) { +	case XEM_SEND: +		*WaitPtr = +		    XDmaChannel_GetPktWaitBound(&InstancePtr->SendChannel); +		break; + +	case XEM_RECV: +		*WaitPtr = +		    XDmaChannel_GetPktWaitBound(&InstancePtr->RecvChannel); +		break; + +	default: +		return XST_INVALID_PARAM; +	} + +	return XST_SUCCESS; +} + +/*****************************************************************************/ +/** +* +* Give the driver the memory space to be used for the scatter-gather DMA +* receive descriptor list. This function should only be called once, during +* initialization of the Ethernet driver. The memory space must be big enough +* to hold some number of descriptors, depending on the needs of the system. +* The xemac.h file defines minimum and default numbers of descriptors +* which can be used to allocate this memory space. +* +* The memory space must be word-aligned. An assert will occur if asserts are +* turned on and the memory is not word-aligned. +* +* @param InstancePtr is a pointer to the XEmac instance to be worked on. +* @param MemoryPtr is a pointer to the word-aligned memory. +* @param ByteCount is the length, in bytes, of the memory space. +* +* @return +* +* - XST_SUCCESS if the space was initialized successfully +* - XST_NOT_SGDMA if the MAC is not configured for scatter-gather DMA +* - XST_DMA_SG_LIST_EXISTS if this list space has already been created +* +* @note +* +* If the device is configured for scatter-gather DMA, this function must be +* called AFTER the XEmac_Initialize() function because the DMA channel +* components must be initialized before the memory space is set. +* +******************************************************************************/ +XStatus +XEmac_SetSgRecvSpace(XEmac * InstancePtr, u32 * MemoryPtr, u32 ByteCount) +{ +	XASSERT_NONVOID(InstancePtr != NULL); +	XASSERT_NONVOID(MemoryPtr != NULL); +	XASSERT_NONVOID(ByteCount != 0); +	XASSERT_NONVOID(InstancePtr->IsReady == XCOMPONENT_IS_READY); + +	if (!XEmac_mIsSgDma(InstancePtr)) { +		return XST_NOT_SGDMA; +	} + +	return XDmaChannel_CreateSgList(&InstancePtr->RecvChannel, MemoryPtr, +					ByteCount); +} + +/*****************************************************************************/ +/** +* +* Give the driver the memory space to be used for the scatter-gather DMA +* transmit descriptor list. This function should only be called once, during +* initialization of the Ethernet driver. The memory space must be big enough +* to hold some number of descriptors, depending on the needs of the system. +* The xemac.h file defines minimum and default numbers of descriptors +* which can be used to allocate this memory space. +* +* The memory space must be word-aligned. An assert will occur if asserts are +* turned on and the memory is not word-aligned. +* +* @param InstancePtr is a pointer to the XEmac instance to be worked on. +* @param MemoryPtr is a pointer to the word-aligned memory. +* @param ByteCount is the length, in bytes, of the memory space. +* +* @return +* +* - XST_SUCCESS if the space was initialized successfully +* - XST_NOT_SGDMA if the MAC is not configured for scatter-gather DMA +* - XST_DMA_SG_LIST_EXISTS if this list space has already been created +* +* @note +* +* If the device is configured for scatter-gather DMA, this function must be +* called AFTER the XEmac_Initialize() function because the DMA channel +* components must be initialized before the memory space is set. +* +******************************************************************************/ +XStatus +XEmac_SetSgSendSpace(XEmac * InstancePtr, u32 * MemoryPtr, u32 ByteCount) +{ +	XASSERT_NONVOID(InstancePtr != NULL); +	XASSERT_NONVOID(MemoryPtr != NULL); +	XASSERT_NONVOID(ByteCount != 0); +	XASSERT_NONVOID(InstancePtr->IsReady == XCOMPONENT_IS_READY); + +	if (!XEmac_mIsSgDma(InstancePtr)) { +		return XST_NOT_SGDMA; +	} + +	return XDmaChannel_CreateSgList(&InstancePtr->SendChannel, MemoryPtr, +					ByteCount); +} + +/*****************************************************************************/ +/** +* +* Set the callback function for handling received frames in scatter-gather DMA +* mode.  The upper layer software should call this function during +* initialization.  The callback is called once per frame received. The head of +* a descriptor list is passed in along with the number of descriptors in the +* list. Before leaving the callback, the upper layer software should attach a +* new buffer to each descriptor in the list. +* +* The callback is invoked by the driver within interrupt context, so it needs +* to do its job quickly. Sending the received frame up the protocol stack +* should be done at task-level. If there are other potentially slow operations +* within the callback, these too should be done at task-level. +* +* @param InstancePtr is a pointer to the XEmac instance to be worked on. +* @param CallBackRef is a reference pointer to be passed back to the adapter in +*        the callback. This helps the adapter correlate the callback to a +*        particular driver. +* @param FuncPtr is the pointer to the callback function. +* +* @return +* +* None. +* +* @note +* +* None. +* +******************************************************************************/ +void +XEmac_SetSgRecvHandler(XEmac * InstancePtr, void *CallBackRef, +		       XEmac_SgHandler FuncPtr) +{ +	/* +	 * Asserted IsDmaSg here instead of run-time check because there is really +	 * no ill-effects of setting these when not configured for scatter-gather. +	 */ +	XASSERT_VOID(InstancePtr != NULL); +	XASSERT_VOID(FuncPtr != NULL); +	XASSERT_VOID(XEmac_mIsSgDma(InstancePtr)); +	XASSERT_VOID(InstancePtr->IsReady == XCOMPONENT_IS_READY); + +	InstancePtr->SgRecvHandler = FuncPtr; +	InstancePtr->SgRecvRef = CallBackRef; +} + +/*****************************************************************************/ +/** +* +* Set the callback function for handling confirmation of transmitted frames in +* scatter-gather DMA mode.  The upper layer software should call this function +* during initialization.  The callback is called once per frame sent. The head +* of a descriptor list is passed in along with the number of descriptors in +* the list. The callback is responsible for freeing buffers attached to these +* descriptors. +* +* The callback is invoked by the driver within interrupt context, so it needs +* to do its job quickly. If there are potentially slow operations within the +* callback, these should be done at task-level. +* +* @param InstancePtr is a pointer to the XEmac instance to be worked on. +* @param CallBackRef is a reference pointer to be passed back to the adapter in +*        the callback. This helps the adapter correlate the callback to a +*        particular driver. +* @param FuncPtr is the pointer to the callback function. +* +* @return +* +* None. +* +* @note +* +* None. +* +******************************************************************************/ +void +XEmac_SetSgSendHandler(XEmac * InstancePtr, void *CallBackRef, +		       XEmac_SgHandler FuncPtr) +{ +	/* +	 * Asserted IsDmaSg here instead of run-time check because there is really +	 * no ill-effects of setting these when not configured for scatter-gather. +	 */ +	XASSERT_VOID(InstancePtr != NULL); +	XASSERT_VOID(FuncPtr != NULL); +	XASSERT_VOID(XEmac_mIsSgDma(InstancePtr)); +	XASSERT_VOID(InstancePtr->IsReady == XCOMPONENT_IS_READY); + +	InstancePtr->SgSendHandler = FuncPtr; +	InstancePtr->SgSendRef = CallBackRef; +} + +/*****************************************************************************/ +/* +* +* Handle an interrupt from the DMA receive channel. DMA interrupts are: +* +* - DMA error. DMA encountered a bus error or timeout. This is a fatal error +*   that requires reset of the channel.  The driver calls the error handler +*   of the upper layer software with an error code indicating the device should +*   be reset. +* - Packet count threshold reached.  For scatter-gather operations, indicates +*   the threshold for the number of packets not serviced by software has been +*   reached. The driver behaves as follows: +*       - Get the value of the packet counter, which tells us how many packets +*         are ready to be serviced +*       - For each packet +*           - For each descriptor, remove it from the scatter-gather list +*           - Check for the last descriptor in the frame, and if set +*               - Bump frame statistics +*               - Call the scatter-gather receive callback function +*               - Decrement the packet counter by one +*       Note that there are no receive errors reported in the status word of +*       the buffer descriptor.  If receive errors occur, the MAC drops the +*       packet, and we only find out about the errors through various error +*       count registers. +* - Packet wait bound reached.  For scatter-gather, indicates the time to wait +*   for the next packet has expired.  The driver follows the same logic as when +*   the packet count threshold interrupt is received. +* - Scatter-gather end acknowledge.  Hardware has reached the end of the +*   descriptor list.  The driver follows the same logic as when the packet count +*   threshold interrupt is received. In addition, the driver restarts the DMA +*   scatter-gather channel in case there are newly inserted descriptors. +* +* @param InstancePtr is a pointer to the XEmac instance to be worked on. +* +* @return +* +* Although the function returns void, there are asynchronous errors that can +* be generated (by calling the ErrorHandler) from this function.  These are: +* - XST_DMA_SG_LIST_EMPTY indicates we tried to get a buffer descriptor from the +*   DMA channel, but there was not one ready for software. +* - XST_DMA_ERROR indicates a DMA bus error or timeout occurred. This is a fatal +*   error that requires reset. +* +* @note +* +* None. +* +******************************************************************************/ +static void +HandleDmaRecvIntr(XEmac * InstancePtr) +{ +	u32 IntrStatus; + +	/* +	 * Read the interrupt status +	 */ +	IntrStatus = XDmaChannel_GetIntrStatus(&InstancePtr->RecvChannel); + +	/* +	 * For packet threshold or wait bound interrupts, process desciptors. Also +	 * process descriptors on a SG end acknowledgement, which means the end of +	 * the descriptor list has been reached by the hardware. For receive, this +	 * is potentially trouble since it means the descriptor list is full, +	 * unless software can process enough packets quickly enough so the +	 * hardware has room to put new packets. +	 */ +	if (IntrStatus & (XDC_IXR_PKT_THRESHOLD_MASK | +			  XDC_IXR_PKT_WAIT_BOUND_MASK | XDC_IXR_SG_END_MASK)) { +		XStatus Result = XST_SUCCESS; +		u32 NumFrames; +		u32 NumProcessed; +		u32 NumBuffers; +		u32 NumBytes; +		u32 IsLast; +		XBufDescriptor *FirstBdPtr; +		XBufDescriptor *BdPtr; + +		/* +		 * Get the number of unserviced packets +		 */ +		NumFrames = XDmaChannel_GetPktCount(&InstancePtr->RecvChannel); + +		for (NumProcessed = 0; NumProcessed < NumFrames; NumProcessed++) { +			IsLast = FALSE; +			FirstBdPtr = NULL; +			NumBuffers = 0; +			NumBytes = 0; + +			/* +			 * For each packet, get the descriptor from the list. On the +			 * last one in the frame, make the callback to the upper layer. +			 */ +			while (!IsLast) { +				Result = +				    XDmaChannel_GetDescriptor(&InstancePtr-> +							      RecvChannel, +							      &BdPtr); +				if (Result != XST_SUCCESS) { +					/* +					 * An error getting a buffer descriptor from the list. +					 * This should not happen, but if it does, report it to +					 * the error callback and break out of the loops to service +					 * other interrupts. +					 */ +					InstancePtr->ErrorHandler(InstancePtr-> +								  ErrorRef, +								  Result); +					break; +				} + +				/* +				 * Keep a pointer to the first descriptor in the list, as it +				 * will be passed to the upper layers in a bit. By the fact +				 * that we received this packet means no errors occurred, so +				 * no need to check the device status word for errors. +				 */ +				if (FirstBdPtr == NULL) { +					FirstBdPtr = BdPtr; +				} + +				NumBytes += XBufDescriptor_GetLength(BdPtr); + +				/* +				 * Check to see if this is the last descriptor in the frame, +				 * and if so, set the IsLast flag to get out of the loop. +				 */ +				if (XBufDescriptor_IsLastStatus(BdPtr)) { +					IsLast = TRUE; +				} + +				/* +				 * Bump the number of buffers in this packet +				 */ +				NumBuffers++; + +			}	/* end while loop */ + +			/* +			 * Check for error that occurred inside the while loop, and break +			 * out of the for loop if there was one so other interrupts can +			 * be serviced. +			 */ +			if (Result != XST_SUCCESS) { +				break; +			} + +			InstancePtr->Stats.RecvFrames++; +			InstancePtr->Stats.RecvBytes += NumBytes; + +			/* +			 * Make the callback to the upper layers, passing it the first +			 * descriptor in the packet and the number of descriptors in the +			 * packet. +			 */ +			InstancePtr->SgRecvHandler(InstancePtr->SgRecvRef, +						   FirstBdPtr, NumBuffers); + +			/* +			 * Decrement the packet count register to reflect the fact we +			 * just processed a packet +			 */ +			XDmaChannel_DecrementPktCount(&InstancePtr-> +						      RecvChannel); + +		}		/* end for loop */ + +		/* +		 * If the interrupt was an end-ack, check the descriptor list again to +		 * see if it is empty. If not, go ahead and restart the scatter-gather +		 * channel. This is to fix a possible race condition where, on receive, +		 * the driver attempted to start a scatter-gather channel that was +		 * already started, which resulted in no action from the XDmaChannel +		 * component. But, just after the XDmaChannel component saw that the +		 * hardware was already started, the hardware stopped because it +		 * reached the end of the list.  In that case, this interrupt is +		 * generated and we can restart the hardware here. +		 */ +		if (IntrStatus & XDC_IXR_SG_END_MASK) { +			/* +			 * Ignore the return status since we know the list exists and we +			 * don't care if the list is empty or the channel is already started. +			 */ +			(void) XDmaChannel_SgStart(&InstancePtr->RecvChannel); +		} +	} + +	/* +	 * All interrupts are handled (except the error below) so acknowledge +	 * (clear) the interrupts by writing the value read above back to the status +	 * register. The packet count interrupt must be acknowledged after the +	 * decrement, otherwise it will come right back. We clear the interrupts +	 * before we handle the error interrupt because the ErrorHandler should +	 * result in a reset, which clears the interrupt status register. So we +	 * don't want to toggle the interrupt back on by writing the interrupt +	 * status register with an old value after a reset. +	 */ +	XDmaChannel_SetIntrStatus(&InstancePtr->RecvChannel, IntrStatus); + +	/* +	 * Check for DMA errors and call the error callback function if an error +	 * occurred (DMA bus or timeout error), which should result in a reset of +	 * the device by the upper layer software. +	 */ +	if (IntrStatus & XDC_IXR_DMA_ERROR_MASK) { +		InstancePtr->Stats.DmaErrors++; +		InstancePtr->ErrorHandler(InstancePtr->ErrorRef, XST_DMA_ERROR); +	} +} + +/*****************************************************************************/ +/* +* +* Handle an interrupt from the DMA send channel. DMA interrupts are: +* +* - DMA error. DMA encountered a bus error or timeout. This is a fatal error +*   that requires reset of the channel.  The driver calls the error handler +*   of the upper layer software with an error code indicating the device should +*   be reset. +* - Packet count threshold reached.  For scatter-gather operations, indicates +*   the threshold for the number of packets not serviced by software has been +*   reached. The driver behaves as follows: +*       - Get the value of the packet counter, which tells us how many packets +*         are ready to be serviced +*       - For each packet +*           - For each descriptor, remove it from the scatter-gather list +*           - Check for the last descriptor in the frame, and if set +*               - Bump frame statistics +*               - Call the scatter-gather receive callback function +*               - Decrement the packet counter by one +*       Note that there are no receive errors reported in the status word of +*       the buffer descriptor.  If receive errors occur, the MAC drops the +*       packet, and we only find out about the errors through various error +*       count registers. +* - Packet wait bound reached.  For scatter-gather, indicates the time to wait +*   for the next packet has expired.  The driver follows the same logic as when +*   the packet count threshold interrupt is received. +* - Scatter-gather end acknowledge.  Hardware has reached the end of the +*   descriptor list.  The driver follows the same logic as when the packet count +*   threshold interrupt is received. In addition, the driver restarts the DMA +*   scatter-gather channel in case there are newly inserted descriptors. +* +* @param InstancePtr is a pointer to the XEmac instance to be worked on. +* +* @return +* +* Although the function returns void, there are asynchronous errors +* that can be generated from this function.  These are: +* - XST_DMA_SG_LIST_EMPTY indicates we tried to get a buffer descriptor from +*   the DMA channel, but there was not one ready for software. +* - XST_DMA_ERROR indicates a DMA bus error or timeout occurred. This is a +*   fatal error that requires reset. +* +* @note +* +* None. +* +******************************************************************************/ +static void +HandleDmaSendIntr(XEmac * InstancePtr) +{ +	u32 IntrStatus; + +	/* +	 * Read the interrupt status +	 */ +	IntrStatus = XDmaChannel_GetIntrStatus(&InstancePtr->SendChannel); + +	/* +	 * For packet threshold or wait bound interrupt, process descriptors. Also +	 * process descriptors on a SG end acknowledgement, which means the end of +	 * the descriptor list has been reached by the hardware. For transmit, +	 * this is a normal condition during times of light traffic.  In fact, the +	 * wait bound interrupt may be masked for transmit since the end-ack would +	 * always occur before the wait bound expires. +	 */ +	if (IntrStatus & (XDC_IXR_PKT_THRESHOLD_MASK | +			  XDC_IXR_PKT_WAIT_BOUND_MASK | XDC_IXR_SG_END_MASK)) { +		XStatus Result = XST_SUCCESS; +		u32 NumFrames; +		u32 NumProcessed; +		u32 NumBuffers; +		u32 NumBytes; +		u32 IsLast; +		XBufDescriptor *FirstBdPtr; +		XBufDescriptor *BdPtr; + +		/* +		 * Get the number of unserviced packets +		 */ +		NumFrames = XDmaChannel_GetPktCount(&InstancePtr->SendChannel); + +		for (NumProcessed = 0; NumProcessed < NumFrames; NumProcessed++) { +			IsLast = FALSE; +			FirstBdPtr = NULL; +			NumBuffers = 0; +			NumBytes = 0; + +			/* +			 * For each frame, traverse the descriptor list and look for +			 * errors. On the last one in the frame, make the callback. +			 */ +			while (!IsLast) { +				Result = +				    XDmaChannel_GetDescriptor(&InstancePtr-> +							      SendChannel, +							      &BdPtr); +				if (Result != XST_SUCCESS) { +					/* +					 * An error getting a buffer descriptor from the list. +					 * This should not happen, but if it does, report it to +					 * the error callback and break out of the loops to service +					 * other interrupts +					 */ +					InstancePtr->ErrorHandler(InstancePtr-> +								  ErrorRef, +								  Result); +					break; +				} + +				/* +				 * Keep a pointer to the first descriptor in the list and +				 * check the device status for errors. The device status is +				 * only available in the first descriptor of a packet. +				 */ +				if (FirstBdPtr == NULL) { +					u32 XmitStatus; + +					FirstBdPtr = BdPtr; + +					XmitStatus = +					    XBufDescriptor_GetDeviceStatus +					    (BdPtr); +					if (XmitStatus & +					    XEM_TSR_EXCESS_DEFERRAL_MASK) { +						InstancePtr->Stats. +						    XmitExcessDeferral++; +					} + +					if (XmitStatus & +					    XEM_TSR_LATE_COLLISION_MASK) { +						InstancePtr->Stats. +						    XmitLateCollisionErrors++; +					} +				} + +				NumBytes += XBufDescriptor_GetLength(BdPtr); + +				/* +				 * Check to see if this is the last descriptor in the frame, +				 * and if so, set the IsLast flag to get out of the loop. The +				 * transmit channel must check the last bit in the control +				 * word, not the status word (the DMA engine does not update +				 * the last bit in the status word for the transmit direction). +				 */ +				if (XBufDescriptor_IsLastControl(BdPtr)) { +					IsLast = TRUE; +				} + +				/* +				 * Bump the number of buffers in this packet +				 */ +				NumBuffers++; + +			}	/* end while loop */ + +			/* +			 * Check for error that occurred inside the while loop, and break +			 * out of the for loop if there was one so other interrupts can +			 * be serviced. +			 */ +			if (Result != XST_SUCCESS) { +				break; +			} + +			InstancePtr->Stats.XmitFrames++; +			InstancePtr->Stats.XmitBytes += NumBytes; + +			/* +			 * Make the callback to the upper layers, passing it the first +			 * descriptor in the packet and the number of descriptors in the +			 * packet. +			 */ +			InstancePtr->SgSendHandler(InstancePtr->SgSendRef, +						   FirstBdPtr, NumBuffers); + +			/* +			 * Decrement the packet count register to reflect the fact we +			 * just processed a packet +			 */ +			XDmaChannel_DecrementPktCount(&InstancePtr-> +						      SendChannel); + +		}		/* end for loop */ + +		/* +		 * If the interrupt was an end-ack, check the descriptor list again to +		 * see if it is empty. If not, go ahead and restart the scatter-gather +		 * channel. This is to fix a possible race condition where, on transmit, +		 * the driver attempted to start a scatter-gather channel that was +		 * already started, which resulted in no action from the XDmaChannel +		 * component. But, just after the XDmaChannel component saw that the +		 * hardware was already started, the hardware stopped because it +		 * reached the end of the list.  In that case, this interrupt is +		 * generated and we can restart the hardware here. +		 */ +		if (IntrStatus & XDC_IXR_SG_END_MASK) { +			/* +			 * Ignore the return status since we know the list exists and we +			 * don't care if the list is empty or the channel is already started. +			 */ +			(void) XDmaChannel_SgStart(&InstancePtr->SendChannel); +		} +	} + +	/* +	 * All interrupts are handled (except the error below) so acknowledge +	 * (clear) the interrupts by writing the value read above back to the status +	 * register. The packet count interrupt must be acknowledged after the +	 * decrement, otherwise it will come right back. We clear the interrupts +	 * before we handle the error interrupt because the ErrorHandler should +	 * result in a reset, which clears the interrupt status register. So we +	 * don't want to toggle the interrupt back on by writing the interrupt +	 * status register with an old value after a reset. +	 */ +	XDmaChannel_SetIntrStatus(&InstancePtr->SendChannel, IntrStatus); + +	/* +	 * Check for DMA errors and call the error callback function if an error +	 * occurred (DMA bus or timeout error), which should result in a reset of +	 * the device by the upper layer software. +	 */ +	if (IntrStatus & XDC_IXR_DMA_ERROR_MASK) { +		InstancePtr->Stats.DmaErrors++; +		InstancePtr->ErrorHandler(InstancePtr->ErrorRef, XST_DMA_ERROR); +	} +} + +/*****************************************************************************/ +/* +* +* Handle an interrupt from the Ethernet MAC when configured with scatter-gather +* DMA. The only interrupts handled in this case are errors. +* +* @param InstancePtr is a pointer to the XEmac instance to be worked on. +* +* @return +* +* None. +* +* @note +* +* None. +* +******************************************************************************/ +static void +HandleEmacDmaIntr(XEmac * InstancePtr) +{ +	u32 IntrStatus; + +	/* +	 * When configured with DMA, the EMAC generates interrupts only when errors +	 * occur. We clear the interrupts immediately so that any latched status +	 * interrupt bits will reflect the true status of the device, and so any +	 * pulsed interrupts (non-status) generated during the Isr will not be lost. +	 */ +	IntrStatus = XIIF_V123B_READ_IISR(InstancePtr->BaseAddress); +	XIIF_V123B_WRITE_IISR(InstancePtr->BaseAddress, IntrStatus); + +	/* +	 * Check the MAC for errors +	 */ +	XEmac_CheckEmacError(InstancePtr, IntrStatus); +} |