* Patch by Peter Ryser, 20 Feb 2004:
[oweals/u-boot.git] / board / xilinx / xilinx_enet / xemac_polled.c
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 ******************************************************************************/
123 XStatus
124 XEmac_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 ******************************************************************************/
324 XStatus
325 XEmac_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 }