diff options
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, 0 insertions, 1344 deletions
| diff --git a/board/xilinx/xilinx_enet/xemac_intr_dma.c b/board/xilinx/xilinx_enet/xemac_intr_dma.c deleted file mode 100644 index 567abb42a..000000000 --- a/board/xilinx/xilinx_enet/xemac_intr_dma.c +++ /dev/null @@ -1,1344 +0,0 @@ -/****************************************************************************** -* -*     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); -} |