123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482 |
- /******************************************************************************
- *
- * 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.
- */
- /*
- * 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;
- }
- /*
- * Clear the interrupt status register of transmit statuses
- */
- XIIF_V123B_WRITE_IISR(InstancePtr->BaseAddress,
- IntrStatus & XEM_EIR_XMIT_ALL_MASK);
- /*
- * Collision errors are stored in the transmit status register
- * instead of the interrupt status register
- */
- if (XmitStatus & XEM_TSR_EXCESS_DEFERRAL_MASK) {
- InstancePtr->Stats.XmitExcessDeferral++;
- return XST_EMAC_COLLISION_ERROR;
- }
- if (XmitStatus & XEM_TSR_LATE_COLLISION_MASK) {
- InstancePtr->Stats.XmitLateCollisionErrors++;
- return XST_EMAC_COLLISION_ERROR;
- }
- return XST_SUCCESS;
- }
- /*****************************************************************************/
- /**
- *
- * Receive an Ethernet frame in polled mode. The device/driver must be in polled
- * mode before calling this function. The driver receives the frame directly
- * from the MAC's packet FIFO. This is a non-blocking receive, in that if there
- * is no frame ready to be received at the device, the function returns with an
- * error. The MAC's error status is not checked, so statistics are not updated
- * for polled receive. The buffer into which the frame will be received must be
- * word-aligned.
- *
- * @param InstancePtr is a pointer to the XEmac instance to be worked on.
- * @param BufPtr is a pointer to a word-aligned buffer into which the received
- * Ethernet frame will be copied.
- * @param ByteCountPtr is both an input and an output parameter. It is a pointer
- * to a 32-bit word that contains the size of the buffer on entry into the
- * function and the size the received frame on return from the function.
- *
- * @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_NO_DATA if there is no frame to be received from the FIFO
- * - XST_BUFFER_TOO_SMALL if the buffer to receive the frame is too small for
- * the frame waiting in the FIFO.
- *
- * @note
- *
- * Input buffer must be big enough to hold the largest Ethernet frame. Buffer
- * must also be 32-bit aligned.
- *
- * @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_PollRecv(XEmac * InstancePtr, u8 * BufPtr, u32 * ByteCountPtr)
- {
- XStatus Result;
- u32 PktLength;
- u32 IntrStatus;
- XASSERT_NONVOID(InstancePtr != NULL);
- XASSERT_NONVOID(BufPtr != NULL);
- XASSERT_NONVOID(ByteCountPtr != NULL);
- 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;
- }
- /*
- * Make sure the buffer is big enough to hold the maximum frame size.
- * We need to do this because as soon as we read the MAC's packet length
- * register, which is actually a FIFO, we remove that length from the
- * FIFO. We do not want to read the length FIFO without also reading the
- * data FIFO since this would get the FIFOs out of sync. So we have to
- * make this restriction.
- */
- if (*ByteCountPtr < XEM_MAX_FRAME_SIZE) {
- return XST_BUFFER_TOO_SMALL;
- }
- /*
- * First check for packet FIFO deadlock and return an error if it has
- * occurred. A reset by the caller is necessary to correct this problem.
- */
- if (XPF_V100B_IS_DEADLOCKED(&InstancePtr->RecvFifo)) {
- InstancePtr->Stats.FifoErrors++;
- return XST_FIFO_ERROR;
- }
- /*
- * Get the interrupt status to know what happened (whether an error occurred
- * and/or whether frames have been received successfully). When clearing the
- * intr status register, clear only statuses that pertain to receive.
- */
- IntrStatus = XIIF_V123B_READ_IISR(InstancePtr->BaseAddress);
- XIIF_V123B_WRITE_IISR(InstancePtr->BaseAddress,
- IntrStatus & XEM_EIR_RECV_ALL_MASK);
- /*
- * Check receive errors and bump statistics so the caller will have a clue
- * as to why data may not have been received. We continue on if an error
- * occurred since there still may be frames that were received successfully.
- */
- if (IntrStatus & (XEM_EIR_RECV_LFIFO_OVER_MASK |
- XEM_EIR_RECV_DFIFO_OVER_MASK)) {
- InstancePtr->Stats.RecvOverrunErrors++;
- InstancePtr->Stats.FifoErrors++;
- }
- if (IntrStatus & XEM_EIR_RECV_LFIFO_UNDER_MASK) {
- InstancePtr->Stats.RecvUnderrunErrors++;
- InstancePtr->Stats.FifoErrors++;
- }
- /*
- * General receive errors
- */
- if (IntrStatus & XEM_EIR_RECV_ERROR_MASK) {
- if (IntrStatus & XEM_EIR_RECV_MISSED_FRAME_MASK) {
- InstancePtr->Stats.RecvMissedFrameErrors =
- XIo_In32(InstancePtr->BaseAddress +
- XEM_RMFC_OFFSET);
- }
- if (IntrStatus & XEM_EIR_RECV_COLLISION_MASK) {
- InstancePtr->Stats.RecvCollisionErrors =
- XIo_In32(InstancePtr->BaseAddress + XEM_RCC_OFFSET);
- }
- if (IntrStatus & XEM_EIR_RECV_FCS_ERROR_MASK) {
- InstancePtr->Stats.RecvFcsErrors =
- XIo_In32(InstancePtr->BaseAddress +
- XEM_RFCSEC_OFFSET);
- }
- if (IntrStatus & XEM_EIR_RECV_LEN_ERROR_MASK) {
- InstancePtr->Stats.RecvLengthFieldErrors++;
- }
- if (IntrStatus & XEM_EIR_RECV_SHORT_ERROR_MASK) {
- InstancePtr->Stats.RecvShortErrors++;
- }
- if (IntrStatus & XEM_EIR_RECV_LONG_ERROR_MASK) {
- InstancePtr->Stats.RecvLongErrors++;
- }
- if (IntrStatus & XEM_EIR_RECV_ALIGN_ERROR_MASK) {
- InstancePtr->Stats.RecvAlignmentErrors =
- XIo_In32(InstancePtr->BaseAddress +
- XEM_RAEC_OFFSET);
- }
- }
- /*
- * Before reading from the length FIFO, make sure the length FIFO is not
- * empty. We could cause an underrun error if we try to read from an
- * empty FIFO.
- */
- if ((IntrStatus & XEM_EIR_RECV_DONE_MASK) == 0) {
- return XST_NO_DATA;
- }
- /*
- * Determine, from the MAC, the length of the next packet available
- * in the data FIFO (there should be a non-zero length here)
- */
- PktLength = XIo_In32(InstancePtr->BaseAddress + XEM_RPLR_OFFSET);
- if (PktLength == 0) {
- return XST_NO_DATA;
- }
- /*
- * Write the RECV_DONE bit in the status register to clear it. This bit
- * indicates the RPLR is non-empty, and we know it's set at this point.
- * We clear it so that subsequent entry into this routine will reflect the
- * current status. This is done because the non-empty bit is latched in the
- * IPIF, which means it may indicate a non-empty condition even though
- * there is something in the FIFO.
- */
- XIIF_V123B_WRITE_IISR(InstancePtr->BaseAddress, XEM_EIR_RECV_DONE_MASK);
- /*
- * We assume that the MAC never has a length bigger than the largest
- * Ethernet frame, so no need to make another check here.
- */
- /*
- * This is a non-blocking read. The FIFO returns an error if there is
- * not at least the requested amount of data in the FIFO.
- */
- Result =
- XPacketFifoV100b_Read(&InstancePtr->RecvFifo, BufPtr, PktLength);
- if (Result != XST_SUCCESS) {
- return Result;
- }
- InstancePtr->Stats.RecvFrames++;
- InstancePtr->Stats.RecvBytes += PktLength;
- *ByteCountPtr = PktLength;
- return XST_SUCCESS;
- }
|