xemac_polled.c

来自「适合KS8695X」· C语言 代码 · 共 483 行 · 第 1/2 页

C
483
字号
/******************************************************************************
*
*     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_polled.c
*
* Contains functions used when the driver is in polled mode. Use the
* XEmac_SetOptions() function to put the driver into polled mode.
*
* <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
* </pre>
*
******************************************************************************/

/***************************** Include Files *********************************/

#include "xbasic_types.h"
#include "xemac_i.h"
#include "xio.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 ******************************/

/*****************************************************************************/
/**
*
* Send an Ethernet frame in polled mode.  The device/driver must be in polled
* mode before calling this function. The driver writes the frame directly to
* the MAC's packet FIFO, then enters a loop checking the device status for
* completion or error. Statistics are updated if an error occurs. The buffer
* to be sent must be word-aligned.
*
* 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.
*
* @param InstancePtr is a pointer to the XEmac instance to be worked on.
* @param BufPtr is a pointer to a word-aligned buffer containing the Ethernet
*        frame to be sent.
* @param ByteCount is the size of the Ethernet frame.
*
* @return
*
* - XST_SUCCESS if the frame was sent successfully
* - XST_DEVICE_IS_STOPPED if the device has not yet been started
* - XST_NOT_POLLED if the device is not in polled mode
* - XST_FIFO_NO_ROOM if there is no room in the EMAC's length FIFO for this frame
* - XST_FIFO_ERROR if the FIFO was overrun or underrun. This error is critical
*   and requires the caller to reset the device.
* - XST_EMAC_COLLISION if the send failed due to excess deferral or late
*   collision
*
* @note
*
* There is the possibility that this function will not return if the hardware
* is broken (i.e., it never sets the status bit indicating that transmission is
* done). If this is of concern to the user, the user should provide protection
* from this problem - perhaps by using a different timer thread to monitor the
* PollSend thread. On a 10Mbps MAC, it takes about 1.21 msecs to transmit a
* maximum size Ethernet frame (1518 bytes). On a 100Mbps MAC, it takes about
* 121 usecs to transmit a maximum size Ethernet frame.
*
* @internal
*
* The EMAC uses FIFOs behind its length and status registers. For this reason,
* it is important to keep the length, status, and data FIFOs in sync when
* reading or writing to them.
*
******************************************************************************/
XStatus
XEmac_PollSend(XEmac * InstancePtr, u8 * BufPtr, u32 ByteCount)
{
	u32 IntrStatus;
	u32 XmitStatus;
	XStatus Result;

	XASSERT_NONVOID(InstancePtr != NULL);
	XASSERT_NONVOID(BufPtr != NULL);
	XASSERT_NONVOID(ByteCount > XEM_HDR_SIZE);	/* send at least 1 byte */
	XASSERT_NONVOID(InstancePtr->IsReady == XCOMPONENT_IS_READY);

	/*
	 * Be sure the device is configured for polled mode and it is started
	 */
	if (!InstancePtr->IsPolled) {
		return XST_NOT_POLLED;
	}

	if (InstancePtr->IsStarted != XCOMPONENT_IS_STARTED) {
		return XST_DEVICE_IS_STOPPED;
	}

	/*
	 * Check for overruns and underruns for the transmit status and length
	 * FIFOs and make sure the send packet FIFO is not deadlocked. Any of these
	 * conditions is bad enough that we do not want to continue. The upper layer
	 * software should reset the device to resolve the error.
	 */
	IntrStatus = XIIF_V123B_READ_IISR(InstancePtr->BaseAddress);

	/*
	 * Overrun errors
	 */
	if (IntrStatus & (XEM_EIR_XMIT_SFIFO_OVER_MASK |
			  XEM_EIR_XMIT_LFIFO_OVER_MASK)) {
		InstancePtr->Stats.XmitOverrunErrors++;
		InstancePtr->Stats.FifoErrors++;
		return XST_FIFO_ERROR;
	}

	/*
	 * Underrun errors
	 */
	if (IntrStatus & (XEM_EIR_XMIT_SFIFO_UNDER_MASK |
			  XEM_EIR_XMIT_LFIFO_UNDER_MASK)) {
		InstancePtr->Stats.XmitUnderrunErrors++;
		InstancePtr->Stats.FifoErrors++;
		return XST_FIFO_ERROR;
	}

	if (XPF_V100B_IS_DEADLOCKED(&InstancePtr->SendFifo)) {
		InstancePtr->Stats.FifoErrors++;
		return XST_FIFO_ERROR;
	}

	/*
	 * Before writing to the data FIFO, make sure the length FIFO is not
	 * full.  The data FIFO might not be full yet even though the length FIFO
	 * is. This avoids an overrun condition on the length FIFO and keeps the
	 * FIFOs in sync.
	 */
	if (IntrStatus & XEM_EIR_XMIT_LFIFO_FULL_MASK) {
		/*
		 * Clear the latched LFIFO_FULL bit so next time around the most
		 * current status is represented
		 */
		XIIF_V123B_WRITE_IISR(InstancePtr->BaseAddress,
				      XEM_EIR_XMIT_LFIFO_FULL_MASK);
		return XST_FIFO_NO_ROOM;
	}

	/*
	 * This is a non-blocking write. The packet FIFO returns an error if there
	 * is not enough room in the FIFO for this frame.
	 */
	Result =
	    XPacketFifoV100b_Write(&InstancePtr->SendFifo, BufPtr, ByteCount);
	if (Result != XST_SUCCESS) {
		return Result;
	}

	/*
	 * Loop on the MAC's status to wait for any pause to complete.
	 */
	IntrStatus = XIIF_V123B_READ_IISR(InstancePtr->BaseAddress);

	while ((IntrStatus & XEM_EIR_XMIT_PAUSE_MASK) != 0) {
		IntrStatus = XIIF_V123B_READ_IISR(InstancePtr->BaseAddress);
		/*
		   * Clear the pause status from the transmit status register
		 */
		XIIF_V123B_WRITE_IISR(InstancePtr->BaseAddress,
				      IntrStatus & XEM_EIR_XMIT_PAUSE_MASK);
	}

	/*
	 * Set the MAC's transmit packet length register to tell it to transmit
	 */
	XIo_Out32(InstancePtr->BaseAddress + XEM_TPLR_OFFSET, ByteCount);

	/*
	 * Loop on the MAC's status to wait for the transmit to complete. The
	 * transmit status is in the FIFO when the XMIT_DONE bit is set.
	 */
	do {
		IntrStatus = XIIF_V123B_READ_IISR(InstancePtr->BaseAddress);
	}
	while ((IntrStatus & XEM_EIR_XMIT_DONE_MASK) == 0);

	XmitStatus = XIo_In32(InstancePtr->BaseAddress + XEM_TSR_OFFSET);

	InstancePtr->Stats.XmitFrames++;
	InstancePtr->Stats.XmitBytes += ByteCount;

	/*
	 * Check for various errors, bump statistics, and return an error status.
	 */

	/*

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?