source: SVN/rincon/u-boot/board/xilinx/xilinx_enet/xemac_polled.c @ 55

Last change on this file since 55 was 55, checked in by Tim Harvey, 2 years ago

rincon: added latest u-boot source

restored form server backup

Signed-off-by: Tim Harvey <tharvey@…>

File size: 15.8 KB
Line 
1/******************************************************************************
2*
3*     Author: Xilinx, Inc.
4*
5*
6*     This program is free software; you can redistribute it and/or modify it
7*     under the terms of the GNU General Public License as published by the
8*     Free Software Foundation; either version 2 of the License, or (at your
9*     option) any later version.
10*
11*
12*     XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION "AS IS" AS A
13*     COURTESY TO YOU. BY PROVIDING THIS DESIGN, CODE, OR INFORMATION AS
14*     ONE POSSIBLE IMPLEMENTATION OF THIS FEATURE, APPLICATION OR STANDARD,
15*     XILINX IS MAKING NO REPRESENTATION THAT THIS IMPLEMENTATION IS FREE
16*     FROM ANY CLAIMS OF INFRINGEMENT, AND YOU ARE RESPONSIBLE FOR OBTAINING
17*     ANY THIRD PARTY RIGHTS YOU MAY REQUIRE FOR YOUR IMPLEMENTATION.
18*     XILINX EXPRESSLY DISCLAIMS ANY WARRANTY WHATSOEVER WITH RESPECT TO
19*     THE ADEQUACY OF THE IMPLEMENTATION, INCLUDING BUT NOT LIMITED TO ANY
20*     WARRANTIES OR REPRESENTATIONS THAT THIS IMPLEMENTATION IS FREE FROM
21*     CLAIMS OF INFRINGEMENT, IMPLIED WARRANTIES OF MERCHANTABILITY AND
22*     FITNESS FOR A PARTICULAR PURPOSE.
23*
24*
25*     Xilinx hardware products are not intended for use in life support
26*     appliances, devices, or systems. Use in such applications is
27*     expressly prohibited.
28*
29*
30*     (c) Copyright 2002-2004 Xilinx Inc.
31*     All rights reserved.
32*
33*
34*     You should have received a copy of the GNU General Public License along
35*     with this program; if not, write to the Free Software Foundation, Inc.,
36*     675 Mass Ave, Cambridge, MA 02139, USA.
37*
38******************************************************************************/
39/*****************************************************************************/
40/**
41*
42* @file xemac_polled.c
43*
44* Contains functions used when the driver is in polled mode. Use the
45* XEmac_SetOptions() function to put the driver into polled mode.
46*
47* <pre>
48* MODIFICATION HISTORY:
49*
50* Ver   Who  Date     Changes
51* ----- ---- -------- -----------------------------------------------
52* 1.00a rpm  07/31/01 First release
53* 1.00b rpm  02/20/02 Repartitioned files and functions
54* 1.00c rpm  12/05/02 New version includes support for simple DMA
55* </pre>
56*
57******************************************************************************/
58
59/***************************** Include Files *********************************/
60
61#include "xbasic_types.h"
62#include "xemac_i.h"
63#include "xio.h"
64#include "xipif_v1_23_b.h"      /* Uses v1.23b of the IPIF */
65
66/************************** Constant Definitions *****************************/
67
68/**************************** Type Definitions *******************************/
69
70/***************** Macros (Inline Functions) Definitions *********************/
71
72/************************** Variable Definitions *****************************/
73
74/************************** Function Prototypes ******************************/
75
76/*****************************************************************************/
77/**
78*
79* Send an Ethernet frame in polled mode.  The device/driver must be in polled
80* mode before calling this function. The driver writes the frame directly to
81* the MAC's packet FIFO, then enters a loop checking the device status for
82* completion or error. Statistics are updated if an error occurs. The buffer
83* to be sent must be word-aligned.
84*
85* It is assumed that the upper layer software supplies a correctly formatted
86* Ethernet frame, including the destination and source addresses, the
87* type/length field, and the data field.  It is also assumed that upper layer
88* software does not append FCS at the end of the frame.
89*
90* @param InstancePtr is a pointer to the XEmac instance to be worked on.
91* @param BufPtr is a pointer to a word-aligned buffer containing the Ethernet
92*        frame to be sent.
93* @param ByteCount is the size of the Ethernet frame.
94*
95* @return
96*
97* - XST_SUCCESS if the frame was sent successfully
98* - XST_DEVICE_IS_STOPPED if the device has not yet been started
99* - XST_NOT_POLLED if the device is not in polled mode
100* - XST_FIFO_NO_ROOM if there is no room in the EMAC's length FIFO for this frame
101* - XST_FIFO_ERROR if the FIFO was overrun or underrun. This error is critical
102*   and requires the caller to reset the device.
103* - XST_EMAC_COLLISION if the send failed due to excess deferral or late
104*   collision
105*
106* @note
107*
108* There is the possibility that this function will not return if the hardware
109* is broken (i.e., it never sets the status bit indicating that transmission is
110* done). If this is of concern to the user, the user should provide protection
111* from this problem - perhaps by using a different timer thread to monitor the
112* PollSend thread. On a 10Mbps MAC, it takes about 1.21 msecs to transmit a
113* maximum size Ethernet frame (1518 bytes). On a 100Mbps MAC, it takes about
114* 121 usecs to transmit a maximum size Ethernet frame.
115*
116* @internal
117*
118* The EMAC uses FIFOs behind its length and status registers. For this reason,
119* it is important to keep the length, status, and data FIFOs in sync when
120* reading or writing to them.
121*
122******************************************************************************/
123XStatus
124XEmac_PollSend(XEmac * InstancePtr, u8 * BufPtr, u32 ByteCount)
125{
126        u32 IntrStatus;
127        u32 XmitStatus;
128        XStatus Result;
129
130        XASSERT_NONVOID(InstancePtr != NULL);
131        XASSERT_NONVOID(BufPtr != NULL);
132        XASSERT_NONVOID(ByteCount > XEM_HDR_SIZE);      /* send at least 1 byte */
133        XASSERT_NONVOID(InstancePtr->IsReady == XCOMPONENT_IS_READY);
134
135        /*
136         * Be sure the device is configured for polled mode and it is started
137         */
138        if (!InstancePtr->IsPolled) {
139                return XST_NOT_POLLED;
140        }
141
142        if (InstancePtr->IsStarted != XCOMPONENT_IS_STARTED) {
143                return XST_DEVICE_IS_STOPPED;
144        }
145
146        /*
147         * Check for overruns and underruns for the transmit status and length
148         * FIFOs and make sure the send packet FIFO is not deadlocked. Any of these
149         * conditions is bad enough that we do not want to continue. The upper layer
150         * software should reset the device to resolve the error.
151         */
152        IntrStatus = XIIF_V123B_READ_IISR(InstancePtr->BaseAddress);
153
154        /*
155         * Overrun errors
156         */
157        if (IntrStatus & (XEM_EIR_XMIT_SFIFO_OVER_MASK |
158                          XEM_EIR_XMIT_LFIFO_OVER_MASK)) {
159                InstancePtr->Stats.XmitOverrunErrors++;
160                InstancePtr->Stats.FifoErrors++;
161                return XST_FIFO_ERROR;
162        }
163
164        /*
165         * Underrun errors
166         */
167        if (IntrStatus & (XEM_EIR_XMIT_SFIFO_UNDER_MASK |
168                          XEM_EIR_XMIT_LFIFO_UNDER_MASK)) {
169                InstancePtr->Stats.XmitUnderrunErrors++;
170                InstancePtr->Stats.FifoErrors++;
171                return XST_FIFO_ERROR;
172        }
173
174        if (XPF_V100B_IS_DEADLOCKED(&InstancePtr->SendFifo)) {
175                InstancePtr->Stats.FifoErrors++;
176                return XST_FIFO_ERROR;
177        }
178
179        /*
180         * Before writing to the data FIFO, make sure the length FIFO is not
181         * full.  The data FIFO might not be full yet even though the length FIFO
182         * is. This avoids an overrun condition on the length FIFO and keeps the
183         * FIFOs in sync.
184         */
185        if (IntrStatus & XEM_EIR_XMIT_LFIFO_FULL_MASK) {
186                /*
187                 * Clear the latched LFIFO_FULL bit so next time around the most
188                 * current status is represented
189                 */
190                XIIF_V123B_WRITE_IISR(InstancePtr->BaseAddress,
191                                      XEM_EIR_XMIT_LFIFO_FULL_MASK);
192                return XST_FIFO_NO_ROOM;
193        }
194
195        /*
196         * This is a non-blocking write. The packet FIFO returns an error if there
197         * is not enough room in the FIFO for this frame.
198         */
199        Result =
200            XPacketFifoV100b_Write(&InstancePtr->SendFifo, BufPtr, ByteCount);
201        if (Result != XST_SUCCESS) {
202                return Result;
203        }
204
205        /*
206         * Loop on the MAC's status to wait for any pause to complete.
207         */
208        IntrStatus = XIIF_V123B_READ_IISR(InstancePtr->BaseAddress);
209
210        while ((IntrStatus & XEM_EIR_XMIT_PAUSE_MASK) != 0) {
211                IntrStatus = XIIF_V123B_READ_IISR(InstancePtr->BaseAddress);
212                /*
213                   * Clear the pause status from the transmit status register
214                 */
215                XIIF_V123B_WRITE_IISR(InstancePtr->BaseAddress,
216                                      IntrStatus & XEM_EIR_XMIT_PAUSE_MASK);
217        }
218
219        /*
220         * Set the MAC's transmit packet length register to tell it to transmit
221         */
222        XIo_Out32(InstancePtr->BaseAddress + XEM_TPLR_OFFSET, ByteCount);
223
224        /*
225         * Loop on the MAC's status to wait for the transmit to complete. The
226         * transmit status is in the FIFO when the XMIT_DONE bit is set.
227         */
228        do {
229                IntrStatus = XIIF_V123B_READ_IISR(InstancePtr->BaseAddress);
230        }
231        while ((IntrStatus & XEM_EIR_XMIT_DONE_MASK) == 0);
232
233        XmitStatus = XIo_In32(InstancePtr->BaseAddress + XEM_TSR_OFFSET);
234
235        InstancePtr->Stats.XmitFrames++;
236        InstancePtr->Stats.XmitBytes += ByteCount;
237
238        /*
239         * Check for various errors, bump statistics, and return an error status.
240         */
241
242        /*
243         * Overrun errors
244         */
245        if (IntrStatus & (XEM_EIR_XMIT_SFIFO_OVER_MASK |
246                          XEM_EIR_XMIT_LFIFO_OVER_MASK)) {
247                InstancePtr->Stats.XmitOverrunErrors++;
248                InstancePtr->Stats.FifoErrors++;
249                return XST_FIFO_ERROR;
250        }
251
252        /*
253         * Underrun errors
254         */
255        if (IntrStatus & (XEM_EIR_XMIT_SFIFO_UNDER_MASK |
256                          XEM_EIR_XMIT_LFIFO_UNDER_MASK)) {
257                InstancePtr->Stats.XmitUnderrunErrors++;
258                InstancePtr->Stats.FifoErrors++;
259                return XST_FIFO_ERROR;
260        }
261
262        /*
263         * Clear the interrupt status register of transmit statuses
264         */
265        XIIF_V123B_WRITE_IISR(InstancePtr->BaseAddress,
266                              IntrStatus & XEM_EIR_XMIT_ALL_MASK);
267
268        /*
269         * Collision errors are stored in the transmit status register
270         * instead of the interrupt status register
271         */
272        if (XmitStatus & XEM_TSR_EXCESS_DEFERRAL_MASK) {
273                InstancePtr->Stats.XmitExcessDeferral++;
274                return XST_EMAC_COLLISION_ERROR;
275        }
276
277        if (XmitStatus & XEM_TSR_LATE_COLLISION_MASK) {
278                InstancePtr->Stats.XmitLateCollisionErrors++;
279                return XST_EMAC_COLLISION_ERROR;
280        }
281
282        return XST_SUCCESS;
283}
284
285/*****************************************************************************/
286/**
287*
288* Receive an Ethernet frame in polled mode. The device/driver must be in polled
289* mode before calling this function. The driver receives the frame directly
290* from the MAC's packet FIFO. This is a non-blocking receive, in that if there
291* is no frame ready to be received at the device, the function returns with an
292* error. The MAC's error status is not checked, so statistics are not updated
293* for polled receive. The buffer into which the frame will be received must be
294* word-aligned.
295*
296* @param InstancePtr is a pointer to the XEmac instance to be worked on.
297* @param BufPtr is a pointer to a word-aligned buffer into which the received
298*        Ethernet frame will be copied.
299* @param ByteCountPtr is both an input and an output parameter. It is a pointer
300*        to a 32-bit word that contains the size of the buffer on entry into the
301*        function and the size the received frame on return from the function.
302*
303* @return
304*
305* - XST_SUCCESS if the frame was sent successfully
306* - XST_DEVICE_IS_STOPPED if the device has not yet been started
307* - XST_NOT_POLLED if the device is not in polled mode
308* - XST_NO_DATA if there is no frame to be received from the FIFO
309* - XST_BUFFER_TOO_SMALL if the buffer to receive the frame is too small for
310*   the frame waiting in the FIFO.
311*
312* @note
313*
314* Input buffer must be big enough to hold the largest Ethernet frame. Buffer
315* must also be 32-bit aligned.
316*
317* @internal
318*
319* The EMAC uses FIFOs behind its length and status registers. For this reason,
320* it is important to keep the length, status, and data FIFOs in sync when
321* reading or writing to them.
322*
323******************************************************************************/
324XStatus
325XEmac_PollRecv(XEmac * InstancePtr, u8 * BufPtr, u32 * ByteCountPtr)
326{
327        XStatus Result;
328        u32 PktLength;
329        u32 IntrStatus;
330
331        XASSERT_NONVOID(InstancePtr != NULL);
332        XASSERT_NONVOID(BufPtr != NULL);
333        XASSERT_NONVOID(ByteCountPtr != NULL);
334        XASSERT_NONVOID(InstancePtr->IsReady == XCOMPONENT_IS_READY);
335
336        /*
337         * Be sure the device is configured for polled mode and it is started
338         */
339        if (!InstancePtr->IsPolled) {
340                return XST_NOT_POLLED;
341        }
342
343        if (InstancePtr->IsStarted != XCOMPONENT_IS_STARTED) {
344                return XST_DEVICE_IS_STOPPED;
345        }
346
347        /*
348         * Make sure the buffer is big enough to hold the maximum frame size.
349         * We need to do this because as soon as we read the MAC's packet length
350         * register, which is actually a FIFO, we remove that length from the
351         * FIFO.  We do not want to read the length FIFO without also reading the
352         * data FIFO since this would get the FIFOs out of sync.  So we have to
353         * make this restriction.
354         */
355        if (*ByteCountPtr < XEM_MAX_FRAME_SIZE) {
356                return XST_BUFFER_TOO_SMALL;
357        }
358
359        /*
360         * First check for packet FIFO deadlock and return an error if it has
361         * occurred. A reset by the caller is necessary to correct this problem.
362         */
363        if (XPF_V100B_IS_DEADLOCKED(&InstancePtr->RecvFifo)) {
364                InstancePtr->Stats.FifoErrors++;
365                return XST_FIFO_ERROR;
366        }
367
368        /*
369         * Get the interrupt status to know what happened (whether an error occurred
370         * and/or whether frames have been received successfully). When clearing the
371         * intr status register, clear only statuses that pertain to receive.
372         */
373        IntrStatus = XIIF_V123B_READ_IISR(InstancePtr->BaseAddress);
374        XIIF_V123B_WRITE_IISR(InstancePtr->BaseAddress,
375                              IntrStatus & XEM_EIR_RECV_ALL_MASK);
376
377        /*
378         * Check receive errors and bump statistics so the caller will have a clue
379         * as to why data may not have been received. We continue on if an error
380         * occurred since there still may be frames that were received successfully.
381         */
382        if (IntrStatus & (XEM_EIR_RECV_LFIFO_OVER_MASK |
383                          XEM_EIR_RECV_DFIFO_OVER_MASK)) {
384                InstancePtr->Stats.RecvOverrunErrors++;
385                InstancePtr->Stats.FifoErrors++;
386        }
387
388        if (IntrStatus & XEM_EIR_RECV_LFIFO_UNDER_MASK) {
389                InstancePtr->Stats.RecvUnderrunErrors++;
390                InstancePtr->Stats.FifoErrors++;
391        }
392
393        /*
394         * General receive errors
395         */
396        if (IntrStatus & XEM_EIR_RECV_ERROR_MASK) {
397                if (IntrStatus & XEM_EIR_RECV_MISSED_FRAME_MASK) {
398                        InstancePtr->Stats.RecvMissedFrameErrors =
399                            XIo_In32(InstancePtr->BaseAddress +
400                                     XEM_RMFC_OFFSET);
401                }
402
403                if (IntrStatus & XEM_EIR_RECV_COLLISION_MASK) {
404                        InstancePtr->Stats.RecvCollisionErrors =
405                            XIo_In32(InstancePtr->BaseAddress + XEM_RCC_OFFSET);
406                }
407
408                if (IntrStatus & XEM_EIR_RECV_FCS_ERROR_MASK) {
409                        InstancePtr->Stats.RecvFcsErrors =
410                            XIo_In32(InstancePtr->BaseAddress +
411                                     XEM_RFCSEC_OFFSET);
412                }
413
414                if (IntrStatus & XEM_EIR_RECV_LEN_ERROR_MASK) {
415                        InstancePtr->Stats.RecvLengthFieldErrors++;
416                }
417
418                if (IntrStatus & XEM_EIR_RECV_SHORT_ERROR_MASK) {
419                        InstancePtr->Stats.RecvShortErrors++;
420                }
421
422                if (IntrStatus & XEM_EIR_RECV_LONG_ERROR_MASK) {
423                        InstancePtr->Stats.RecvLongErrors++;
424                }
425
426                if (IntrStatus & XEM_EIR_RECV_ALIGN_ERROR_MASK) {
427                        InstancePtr->Stats.RecvAlignmentErrors =
428                            XIo_In32(InstancePtr->BaseAddress +
429                                     XEM_RAEC_OFFSET);
430                }
431        }
432
433        /*
434         * Before reading from the length FIFO, make sure the length FIFO is not
435         * empty. We could cause an underrun error if we try to read from an
436         * empty FIFO.
437         */
438        if ((IntrStatus & XEM_EIR_RECV_DONE_MASK) == 0) {
439                return XST_NO_DATA;
440        }
441
442        /*
443         * Determine, from the MAC, the length of the next packet available
444         * in the data FIFO (there should be a non-zero length here)
445         */
446        PktLength = XIo_In32(InstancePtr->BaseAddress + XEM_RPLR_OFFSET);
447        if (PktLength == 0) {
448                return XST_NO_DATA;
449        }
450
451        /*
452         * Write the RECV_DONE bit in the status register to clear it. This bit
453         * indicates the RPLR is non-empty, and we know it's set at this point.
454         * We clear it so that subsequent entry into this routine will reflect the
455         * current status. This is done because the non-empty bit is latched in the
456         * IPIF, which means it may indicate a non-empty condition even though
457         * there is something in the FIFO.
458         */
459        XIIF_V123B_WRITE_IISR(InstancePtr->BaseAddress, XEM_EIR_RECV_DONE_MASK);
460
461        /*
462         * We assume that the MAC never has a length bigger than the largest
463         * Ethernet frame, so no need to make another check here.
464         */
465
466        /*
467         * This is a non-blocking read. The FIFO returns an error if there is
468         * not at least the requested amount of data in the FIFO.
469         */
470        Result =
471            XPacketFifoV100b_Read(&InstancePtr->RecvFifo, BufPtr, PktLength);
472        if (Result != XST_SUCCESS) {
473                return Result;
474        }
475
476        InstancePtr->Stats.RecvFrames++;
477        InstancePtr->Stats.RecvBytes += PktLength;
478
479        *ByteCountPtr = PktLength;
480
481        return XST_SUCCESS;
482}
Note: See TracBrowser for help on using the repository browser.