]> git.sur5r.net Git - u-boot/blob - board/xilinx/xilinx_enet/xemac_intr_dma.c
* Patch by Peter Ryser, 20 Feb 2004:
[u-boot] / board / xilinx / xilinx_enet / xemac_intr_dma.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_intr_dma.c
43 *
44 * Contains functions used in interrupt mode when configured with scatter-gather
45 * DMA.
46 *
47 * The interrupt handler, XEmac_IntrHandlerDma(), must be connected by the user
48 * to the interrupt controller.
49 *
50 * <pre>
51 * MODIFICATION HISTORY:
52 *
53 * Ver   Who  Date     Changes
54 * ----- ---- -------- ---------------------------------------------------------
55 * 1.00a rpm  07/31/01 First release
56 * 1.00b rpm  02/20/02 Repartitioned files and functions
57 * 1.00c rpm  12/05/02 New version includes support for simple DMA and the delay
58 *                     argument to SgSend
59 * 1.00c rpm  02/03/03 The XST_DMA_SG_COUNT_EXCEEDED return code was removed
60 *                     from SetPktThreshold in the internal DMA driver. Also
61 *                     avoided compiler warnings by initializing Result in the
62 *                     interrupt service routines.
63 * 1.00c rpm  03/26/03 Fixed a problem in the interrupt service routines where
64 *                     the interrupt status was toggled clear after a call to
65 *                     ErrorHandler, but if ErrorHandler reset the device the
66 *                     toggle actually asserted the interrupt because the
67 *                     reset had cleared it.
68 * </pre>
69 *
70 ******************************************************************************/
71
72 /***************************** Include Files *********************************/
73
74 #include "xbasic_types.h"
75 #include "xemac_i.h"
76 #include "xio.h"
77 #include "xbuf_descriptor.h"
78 #include "xdma_channel.h"
79 #include "xipif_v1_23_b.h"      /* Uses v1.23b of the IPIF */
80
81 /************************** Constant Definitions *****************************/
82
83 /**************************** Type Definitions *******************************/
84
85 /***************** Macros (Inline Functions) Definitions *********************/
86
87 /************************** Variable Definitions *****************************/
88
89 /************************** Function Prototypes ******************************/
90
91 static void HandleDmaRecvIntr(XEmac * InstancePtr);
92 static void HandleDmaSendIntr(XEmac * InstancePtr);
93 static void HandleEmacDmaIntr(XEmac * InstancePtr);
94
95 /*****************************************************************************/
96 /**
97 *
98 * Send an Ethernet frame using scatter-gather DMA. The caller attaches the
99 * frame to one or more buffer descriptors, then calls this function once for
100 * each descriptor. The caller is responsible for allocating and setting up the
101 * descriptor. An entire Ethernet frame may or may not be contained within one
102 * descriptor.  This function simply inserts the descriptor into the scatter-
103 * gather engine's transmit list. The caller is responsible for providing mutual
104 * exclusion to guarantee that a frame is contiguous in the transmit list. The
105 * buffer attached to the descriptor must be word-aligned.
106 *
107 * The driver updates the descriptor with the device control register before
108 * being inserted into the transmit list.  If this is the last descriptor in
109 * the frame, the inserts are committed, which means the descriptors for this
110 * frame are now available for transmission.
111 *
112 * It is assumed that the upper layer software supplies a correctly formatted
113 * Ethernet frame, including the destination and source addresses, the
114 * type/length field, and the data field.  It is also assumed that upper layer
115 * software does not append FCS at the end of the frame.
116 *
117 * The buffer attached to the descriptor must be word-aligned on the front end.
118 *
119 * This call is non-blocking.  Notification of error or successful transmission
120 * is done asynchronously through the send or error callback function.
121 *
122 * @param InstancePtr is a pointer to the XEmac instance to be worked on.
123 * @param BdPtr is the address of a descriptor to be inserted into the transmit
124 *        ring.
125 * @param Delay indicates whether to start the scatter-gather DMA channel
126 *        immediately, or whether to wait. This allows the user to build up a
127 *        list of more than one descriptor before starting the transmission of
128 *        the packets, which allows the application to keep up with DMA and have
129 *        a constant stream of frames being transmitted. Use XEM_SGDMA_NODELAY or
130 *        XEM_SGDMA_DELAY, defined in xemac.h, as the value of this argument. If
131 *        the user chooses to delay and build a list, the user must call this
132 *        function with the XEM_SGDMA_NODELAY option or call XEmac_Start() to
133 *        kick off the tranmissions.
134 *
135 * @return
136 *
137 * - XST_SUCCESS if the buffer was successfull sent
138 * - XST_DEVICE_IS_STOPPED if the Ethernet MAC has not been started yet
139 * - XST_NOT_SGDMA if the device is not in scatter-gather DMA mode
140 * - XST_DMA_SG_LIST_FULL if the descriptor list for the DMA channel is full
141 * - XST_DMA_SG_BD_LOCKED if the DMA channel cannot insert the descriptor into
142 *   the list because a locked descriptor exists at the insert point
143 * - XST_DMA_SG_NOTHING_TO_COMMIT if even after inserting a descriptor into the
144 *   list, the DMA channel believes there are no new descriptors to commit. If
145 *   this is ever encountered, there is likely a thread mutual exclusion problem
146 *   on transmit.
147 *
148 * @note
149 *
150 * This function is not thread-safe. The user must provide mutually exclusive
151 * access to this function if there are to be multiple threads that can call it.
152 *
153 * @internal
154 *
155 * A status that should never be returned from this function, although
156 * the code is set up to handle it, is XST_DMA_SG_NO_LIST. Starting the device
157 * requires a list to be created, and this function requires the device to be
158 * started.
159 *
160 ******************************************************************************/
161 XStatus
162 XEmac_SgSend(XEmac * InstancePtr, XBufDescriptor * BdPtr, int Delay)
163 {
164         XStatus Result;
165         u32 BdControl;
166
167         XASSERT_NONVOID(InstancePtr != NULL);
168         XASSERT_NONVOID(BdPtr != NULL);
169         XASSERT_NONVOID(InstancePtr->IsReady == XCOMPONENT_IS_READY);
170
171         /*
172          * Be sure the device is configured for scatter-gather DMA, then be sure
173          * it is started.
174          */
175         if (!XEmac_mIsSgDma(InstancePtr)) {
176                 return XST_NOT_SGDMA;
177         }
178
179         /*
180          * Set some descriptor control word defaults (source address increment
181          * and local destination address) and the destination address
182          * (the FIFO).  These are the same for every transmit descriptor.
183          */
184         BdControl = XBufDescriptor_GetControl(BdPtr);
185         XBufDescriptor_SetControl(BdPtr, BdControl | XEM_DFT_SEND_BD_MASK);
186
187         XBufDescriptor_SetDestAddress(BdPtr,
188                                       InstancePtr->BaseAddress +
189                                       XEM_PFIFO_TXDATA_OFFSET);
190
191         /*
192          * Put the descriptor in the send list. The DMA component accesses data
193          * here that can also be modified in interrupt context, so a critical
194          * section is required.
195          */
196         XIIF_V123B_GINTR_DISABLE(InstancePtr->BaseAddress);
197
198         Result = XDmaChannel_PutDescriptor(&InstancePtr->SendChannel, BdPtr);
199         if (Result != XST_SUCCESS) {
200                 XIIF_V123B_GINTR_ENABLE(InstancePtr->BaseAddress);
201                 return Result;
202         }
203
204         /*
205          * If this is the last buffer in the frame, commit the inserts and start
206          * the DMA engine if necessary
207          */
208         if (XBufDescriptor_IsLastControl(BdPtr)) {
209                 Result = XDmaChannel_CommitPuts(&InstancePtr->SendChannel);
210                 if (Result != XST_SUCCESS) {
211                         XIIF_V123B_GINTR_ENABLE(InstancePtr->BaseAddress);
212                         return Result;
213                 }
214
215                 if (Delay == XEM_SGDMA_NODELAY) {
216                         /*
217                          * Start the DMA channel. Ignore the return status since we know the
218                          * list exists and has at least one entry and we don't care if the
219                          * channel is already started.  The DMA component accesses data here
220                          * that can be modified at interrupt or task levels, so a critical
221                          * section is required.
222                          */
223                         (void) XDmaChannel_SgStart(&InstancePtr->SendChannel);
224                 }
225         }
226
227         XIIF_V123B_GINTR_ENABLE(InstancePtr->BaseAddress);
228
229         return XST_SUCCESS;
230 }
231
232 /*****************************************************************************/
233 /**
234 *
235 * Add a descriptor, with an attached empty buffer, into the receive descriptor
236 * list. The buffer attached to the descriptor must be word-aligned. This is
237 * used by the upper layer software during initialization when first setting up
238 * the receive descriptors, and also during reception of frames to replace
239 * filled buffers with empty buffers. This function can be called when the
240 * device is started or stopped. Note that it does start the scatter-gather DMA
241 * engine.  Although this is not necessary during initialization, it is not a
242 * problem during initialization because the MAC receiver is not yet started.
243 *
244 * The buffer attached to the descriptor must be word-aligned on both the front
245 * end and the back end.
246 *
247 * Notification of received frames are done asynchronously through the receive
248 * callback function.
249 *
250 * @param InstancePtr is a pointer to the XEmac instance to be worked on.
251 * @param BdPtr is a pointer to the buffer descriptor that will be added to the
252 *        descriptor list.
253 *
254 * @return
255 *
256 * - XST_SUCCESS if a descriptor was successfully returned to the driver
257 * - XST_NOT_SGDMA if the device is not in scatter-gather DMA mode
258 * - XST_DMA_SG_LIST_FULL if the receive descriptor list is full
259 * - XST_DMA_SG_BD_LOCKED if the DMA channel cannot insert the descriptor into
260 *   the list because a locked descriptor exists at the insert point.
261 * - XST_DMA_SG_NOTHING_TO_COMMIT if even after inserting a descriptor into the
262 *   list, the DMA channel believes there are no new descriptors to commit.
263 *
264 * @internal
265 *
266 * A status that should never be returned from this function, although
267 * the code is set up to handle it, is XST_DMA_SG_NO_LIST. Starting the device
268 * requires a list to be created, and this function requires the device to be
269 * started.
270 *
271 ******************************************************************************/
272 XStatus
273 XEmac_SgRecv(XEmac * InstancePtr, XBufDescriptor * BdPtr)
274 {
275         XStatus Result;
276         u32 BdControl;
277
278         XASSERT_NONVOID(InstancePtr != NULL);
279         XASSERT_NONVOID(BdPtr != NULL);
280         XASSERT_NONVOID(InstancePtr->IsReady == XCOMPONENT_IS_READY);
281
282         /*
283          * Be sure the device is configured for scatter-gather DMA
284          */
285         if (!XEmac_mIsSgDma(InstancePtr)) {
286                 return XST_NOT_SGDMA;
287         }
288
289         /*
290          * Set some descriptor control word defaults (destination address increment
291          * and local source address) and the source address (the FIFO). These are
292          * the same for every receive descriptor.
293          */
294         BdControl = XBufDescriptor_GetControl(BdPtr);
295         XBufDescriptor_SetControl(BdPtr, BdControl | XEM_DFT_RECV_BD_MASK);
296         XBufDescriptor_SetSrcAddress(BdPtr,
297                                      InstancePtr->BaseAddress +
298                                      XEM_PFIFO_RXDATA_OFFSET);
299
300         /*
301          * Put the descriptor into the channel's descriptor list and commit.
302          * Although this function is likely called within interrupt context, there
303          * is the possibility that the upper layer software queues it to a task.
304          * In this case, a critical section is needed here to protect shared data
305          * in the DMA component.
306          */
307         XIIF_V123B_GINTR_DISABLE(InstancePtr->BaseAddress);
308
309         Result = XDmaChannel_PutDescriptor(&InstancePtr->RecvChannel, BdPtr);
310         if (Result != XST_SUCCESS) {
311                 XIIF_V123B_GINTR_ENABLE(InstancePtr->BaseAddress);
312                 return Result;
313         }
314
315         Result = XDmaChannel_CommitPuts(&InstancePtr->RecvChannel);
316         if (Result != XST_SUCCESS) {
317                 XIIF_V123B_GINTR_ENABLE(InstancePtr->BaseAddress);
318                 return Result;
319         }
320
321         /*
322          * Start the DMA channel. Ignore the return status since we know the list
323          * exists and has at least one entry and we don't care if the channel is
324          * already started. The DMA component accesses data here that can be
325          * modified at interrupt or task levels, so a critical section is required.
326          */
327         (void) XDmaChannel_SgStart(&InstancePtr->RecvChannel);
328
329         XIIF_V123B_GINTR_ENABLE(InstancePtr->BaseAddress);
330
331         return XST_SUCCESS;
332 }
333
334 /*****************************************************************************/
335 /**
336 *
337 * The interrupt handler for the Ethernet driver when configured with scatter-
338 * gather DMA.
339 *
340 * Get the interrupt status from the IpIf to determine the source of the
341 * interrupt.  The source can be: MAC, Recv Packet FIFO, Send Packet FIFO, Recv
342 * DMA channel, or Send DMA channel. The packet FIFOs only interrupt during
343 * "deadlock" conditions.
344 *
345 * @param InstancePtr is a pointer to the XEmac instance that just interrupted.
346 *
347 * @return
348 *
349 * None.
350 *
351 * @note
352 *
353 * None.
354 *
355 ******************************************************************************/
356 void
357 XEmac_IntrHandlerDma(void *InstancePtr)
358 {
359         u32 IntrStatus;
360         XEmac *EmacPtr = (XEmac *) InstancePtr;
361
362         EmacPtr->Stats.TotalIntrs++;
363
364         /*
365          * Get the interrupt status from the IPIF. There is no clearing of
366          * interrupts in the IPIF. Interrupts must be cleared at the source.
367          */
368         IntrStatus = XIIF_V123B_READ_DIPR(EmacPtr->BaseAddress);
369
370         /*
371          * See which type of interrupt is being requested, and service it
372          */
373         if (IntrStatus & XEM_IPIF_RECV_DMA_MASK) {      /* Receive DMA interrupt */
374                 EmacPtr->Stats.RecvInterrupts++;
375                 HandleDmaRecvIntr(EmacPtr);
376         }
377
378         if (IntrStatus & XEM_IPIF_SEND_DMA_MASK) {      /* Send DMA interrupt */
379                 EmacPtr->Stats.XmitInterrupts++;
380                 HandleDmaSendIntr(EmacPtr);
381         }
382
383         if (IntrStatus & XEM_IPIF_EMAC_MASK) {  /* MAC interrupt */
384                 EmacPtr->Stats.EmacInterrupts++;
385                 HandleEmacDmaIntr(EmacPtr);
386         }
387
388         if (IntrStatus & XEM_IPIF_RECV_FIFO_MASK) {     /* Receive FIFO interrupt */
389                 EmacPtr->Stats.RecvInterrupts++;
390                 XEmac_CheckFifoRecvError(EmacPtr);
391         }
392
393         if (IntrStatus & XEM_IPIF_SEND_FIFO_MASK) {     /* Send FIFO interrupt */
394                 EmacPtr->Stats.XmitInterrupts++;
395                 XEmac_CheckFifoSendError(EmacPtr);
396         }
397
398         if (IntrStatus & XIIF_V123B_ERROR_MASK) {
399                 /*
400                  * An error occurred internal to the IPIF. This is more of a debug and
401                  * integration issue rather than a production error. Don't do anything
402                  * other than clear it, which provides a spot for software to trap
403                  * on the interrupt and begin debugging.
404                  */
405                 XIIF_V123B_WRITE_DISR(EmacPtr->BaseAddress,
406                                       XIIF_V123B_ERROR_MASK);
407         }
408 }
409
410 /*****************************************************************************/
411 /**
412 *
413 * Set the packet count threshold for this device. The device must be stopped
414 * before setting the threshold. The packet count threshold is used for interrupt
415 * coalescing, which reduces the frequency of interrupts from the device to the
416 * processor. In this case, the scatter-gather DMA engine only interrupts when
417 * the packet count threshold is reached, instead of interrupting for each packet.
418 * A packet is a generic term used by the scatter-gather DMA engine, and is
419 * equivalent to an Ethernet frame in our case.
420 *
421 * @param InstancePtr is a pointer to the XEmac instance to be worked on.
422 * @param Direction indicates the channel, send or receive, from which the
423 *        threshold register is read.
424 * @param Threshold is the value of the packet threshold count used during
425 *        interrupt coalescing. A value of 0 disables the use of packet threshold
426 *        by the hardware.
427 *
428 * @return
429 *
430 * - XST_SUCCESS if the threshold was successfully set
431 * - XST_NOT_SGDMA if the MAC is not configured for scatter-gather DMA
432 * - XST_DEVICE_IS_STARTED if the device has not been stopped
433 * - XST_INVALID_PARAM if the Direction parameter is invalid. Turning on
434 *   asserts would also catch this error.
435 *
436 * @note
437 *
438 * The packet threshold could be set to larger than the number of descriptors
439 * allocated to the DMA channel. In this case, the wait bound will take over
440 * and always indicate data arrival. There was a check in this function that
441 * returned an error if the treshold was larger than the number of descriptors,
442 * but that was removed because users would then have to set the threshold
443 * only after they set descriptor space, which is an order dependency that
444 * caused confustion.
445 *
446 ******************************************************************************/
447 XStatus
448 XEmac_SetPktThreshold(XEmac * InstancePtr, u32 Direction, u8 Threshold)
449 {
450         XASSERT_NONVOID(InstancePtr != NULL);
451         XASSERT_NONVOID(Direction == XEM_SEND || Direction == XEM_RECV);
452         XASSERT_NONVOID(InstancePtr->IsReady == XCOMPONENT_IS_READY);
453
454         /*
455          * Be sure device is configured for scatter-gather DMA and has been stopped
456          */
457         if (!XEmac_mIsSgDma(InstancePtr)) {
458                 return XST_NOT_SGDMA;
459         }
460
461         if (InstancePtr->IsStarted == XCOMPONENT_IS_STARTED) {
462                 return XST_DEVICE_IS_STARTED;
463         }
464
465         /*
466          * Based on the direction, set the packet threshold in the
467          * corresponding DMA channel component.  Default to the receive
468          * channel threshold register (if an invalid Direction is passed).
469          */
470         switch (Direction) {
471         case XEM_SEND:
472                 return XDmaChannel_SetPktThreshold(&InstancePtr->SendChannel,
473                                                    Threshold);
474
475         case XEM_RECV:
476                 return XDmaChannel_SetPktThreshold(&InstancePtr->RecvChannel,
477                                                    Threshold);
478
479         default:
480                 return XST_INVALID_PARAM;
481         }
482 }
483
484 /*****************************************************************************/
485 /**
486 *
487 * Get the value of the packet count threshold for this driver/device. The packet
488 * count threshold is used for interrupt coalescing, which reduces the frequency
489 * of interrupts from the device to the processor. In this case, the
490 * scatter-gather DMA engine only interrupts when the packet count threshold is
491 * reached, instead of interrupting for each packet. A packet is a generic term
492 * used by the scatter-gather DMA engine, and is equivalent to an Ethernet frame
493 * in our case.
494 *
495 * @param InstancePtr is a pointer to the XEmac instance to be worked on.
496 * @param Direction indicates the channel, send or receive, from which the
497 *        threshold register is read.
498 * @param ThreshPtr is a pointer to the byte into which the current value of the
499 *        packet threshold register will be copied. An output parameter. A value
500 *        of 0 indicates the use of packet threshold by the hardware is disabled.
501 *
502 * @return
503 *
504 * - XST_SUCCESS if the packet threshold was retrieved successfully
505 * - XST_NOT_SGDMA if the MAC is not configured for scatter-gather DMA
506 * - XST_INVALID_PARAM if the Direction parameter is invalid. Turning on
507 *   asserts would also catch this error.
508 *
509 * @note
510 *
511 * None.
512 *
513 ******************************************************************************/
514 XStatus
515 XEmac_GetPktThreshold(XEmac * InstancePtr, u32 Direction, u8 * ThreshPtr)
516 {
517         XASSERT_NONVOID(InstancePtr != NULL);
518         XASSERT_NONVOID(Direction == XEM_SEND || Direction == XEM_RECV);
519         XASSERT_NONVOID(ThreshPtr != NULL);
520         XASSERT_NONVOID(InstancePtr->IsReady == XCOMPONENT_IS_READY);
521
522         if (!XEmac_mIsSgDma(InstancePtr)) {
523                 return XST_NOT_SGDMA;
524         }
525
526         /*
527          * Based on the direction, return the packet threshold set in the
528          * corresponding DMA channel component.  Default to the value in
529          * the receive channel threshold register (if an invalid Direction
530          * is passed).
531          */
532         switch (Direction) {
533         case XEM_SEND:
534                 *ThreshPtr =
535                     XDmaChannel_GetPktThreshold(&InstancePtr->SendChannel);
536                 break;
537
538         case XEM_RECV:
539                 *ThreshPtr =
540                     XDmaChannel_GetPktThreshold(&InstancePtr->RecvChannel);
541                 break;
542
543         default:
544                 return XST_INVALID_PARAM;
545         }
546
547         return XST_SUCCESS;
548 }
549
550 /*****************************************************************************/
551 /**
552 *
553 * Set the packet wait bound timer for this driver/device. The device must be
554 * stopped before setting the timer value. The packet wait bound is used during
555 * interrupt coalescing to trigger an interrupt when not enough packets have been
556 * received to reach the packet count threshold. A packet is a generic term used
557 * by the scatter-gather DMA engine, and is equivalent to an Ethernet frame in
558 * our case. The timer is in milliseconds.
559 *
560 * @param InstancePtr is a pointer to the XEmac instance to be worked on.
561 * @param Direction indicates the channel, send or receive, from which the
562 *        threshold register is read.
563 * @param TimerValue is the value of the packet wait bound used during interrupt
564 *        coalescing. It is in milliseconds in the range 0  - 1023. A value of 0
565 *        disables the packet wait bound timer.
566 *
567 * @return
568 *
569 * - XST_SUCCESS if the packet wait bound was set successfully
570 * - XST_NOT_SGDMA if the MAC is not configured for scatter-gather DMA
571 * - XST_DEVICE_IS_STARTED if the device has not been stopped
572 * - XST_INVALID_PARAM if the Direction parameter is invalid. Turning on
573 *   asserts would also catch this error.
574 *
575 * @note
576 *
577 * None.
578 *
579 ******************************************************************************/
580 XStatus
581 XEmac_SetPktWaitBound(XEmac * InstancePtr, u32 Direction, u32 TimerValue)
582 {
583         XASSERT_NONVOID(InstancePtr != NULL);
584         XASSERT_NONVOID(Direction == XEM_SEND || Direction == XEM_RECV);
585         XASSERT_NONVOID(TimerValue <= XEM_SGDMA_MAX_WAITBOUND);
586         XASSERT_NONVOID(InstancePtr->IsReady == XCOMPONENT_IS_READY);
587
588         /*
589          * Be sure device is configured for scatter-gather DMA and has been stopped
590          */
591         if (!XEmac_mIsSgDma(InstancePtr)) {
592                 return XST_NOT_SGDMA;
593         }
594
595         if (InstancePtr->IsStarted == XCOMPONENT_IS_STARTED) {
596                 return XST_DEVICE_IS_STARTED;
597         }
598
599         /*
600          * Based on the direction, set the packet wait bound in the
601          * corresponding DMA channel component.  Default to the receive
602          * channel wait bound register (if an invalid Direction is passed).
603          */
604         switch (Direction) {
605         case XEM_SEND:
606                 XDmaChannel_SetPktWaitBound(&InstancePtr->SendChannel,
607                                             TimerValue);
608                 break;
609
610         case XEM_RECV:
611                 XDmaChannel_SetPktWaitBound(&InstancePtr->RecvChannel,
612                                             TimerValue);
613                 break;
614
615         default:
616                 return XST_INVALID_PARAM;
617         }
618
619         return XST_SUCCESS;
620 }
621
622 /*****************************************************************************/
623 /**
624 *
625 * Get the packet wait bound timer for this driver/device. The packet wait bound
626 * is used during interrupt coalescing to trigger an interrupt when not enough
627 * packets have been received to reach the packet count threshold. A packet is a
628 * generic term used by the scatter-gather DMA engine, and is equivalent to an
629 * Ethernet frame in our case. The timer is in milliseconds.
630 *
631 * @param InstancePtr is a pointer to the XEmac instance to be worked on.
632 * @param Direction indicates the channel, send or receive, from which the
633 *        threshold register is read.
634 * @param WaitPtr is a pointer to the byte into which the current value of the
635 *        packet wait bound register will be copied. An output parameter. Units
636 *        are in milliseconds in the range 0  - 1023. A value of 0 indicates the
637 *        packet wait bound timer is disabled.
638 *
639 * @return
640 *
641 * - XST_SUCCESS if the packet wait bound was retrieved successfully
642 * - XST_NOT_SGDMA if the MAC is not configured for scatter-gather DMA
643 * - XST_INVALID_PARAM if the Direction parameter is invalid. Turning on
644 *   asserts would also catch this error.
645 *
646 * @note
647 *
648 * None.
649 *
650 ******************************************************************************/
651 XStatus
652 XEmac_GetPktWaitBound(XEmac * InstancePtr, u32 Direction, u32 * WaitPtr)
653 {
654         XASSERT_NONVOID(InstancePtr != NULL);
655         XASSERT_NONVOID(Direction == XEM_SEND || Direction == XEM_RECV);
656         XASSERT_NONVOID(WaitPtr != NULL);
657         XASSERT_NONVOID(InstancePtr->IsReady == XCOMPONENT_IS_READY);
658
659         if (!XEmac_mIsSgDma(InstancePtr)) {
660                 return XST_NOT_SGDMA;
661         }
662
663         /*
664          * Based on the direction, return the packet wait bound set in the
665          * corresponding DMA channel component.  Default to the value in
666          * the receive channel wait bound register (if an invalid Direction
667          * is passed).
668          */
669         switch (Direction) {
670         case XEM_SEND:
671                 *WaitPtr =
672                     XDmaChannel_GetPktWaitBound(&InstancePtr->SendChannel);
673                 break;
674
675         case XEM_RECV:
676                 *WaitPtr =
677                     XDmaChannel_GetPktWaitBound(&InstancePtr->RecvChannel);
678                 break;
679
680         default:
681                 return XST_INVALID_PARAM;
682         }
683
684         return XST_SUCCESS;
685 }
686
687 /*****************************************************************************/
688 /**
689 *
690 * Give the driver the memory space to be used for the scatter-gather DMA
691 * receive descriptor list. This function should only be called once, during
692 * initialization of the Ethernet driver. The memory space must be big enough
693 * to hold some number of descriptors, depending on the needs of the system.
694 * The xemac.h file defines minimum and default numbers of descriptors
695 * which can be used to allocate this memory space.
696 *
697 * The memory space must be word-aligned. An assert will occur if asserts are
698 * turned on and the memory is not word-aligned.
699 *
700 * @param InstancePtr is a pointer to the XEmac instance to be worked on.
701 * @param MemoryPtr is a pointer to the word-aligned memory.
702 * @param ByteCount is the length, in bytes, of the memory space.
703 *
704 * @return
705 *
706 * - XST_SUCCESS if the space was initialized successfully
707 * - XST_NOT_SGDMA if the MAC is not configured for scatter-gather DMA
708 * - XST_DMA_SG_LIST_EXISTS if this list space has already been created
709 *
710 * @note
711 *
712 * If the device is configured for scatter-gather DMA, this function must be
713 * called AFTER the XEmac_Initialize() function because the DMA channel
714 * components must be initialized before the memory space is set.
715 *
716 ******************************************************************************/
717 XStatus
718 XEmac_SetSgRecvSpace(XEmac * InstancePtr, u32 * MemoryPtr, u32 ByteCount)
719 {
720         XASSERT_NONVOID(InstancePtr != NULL);
721         XASSERT_NONVOID(MemoryPtr != NULL);
722         XASSERT_NONVOID(ByteCount != 0);
723         XASSERT_NONVOID(InstancePtr->IsReady == XCOMPONENT_IS_READY);
724
725         if (!XEmac_mIsSgDma(InstancePtr)) {
726                 return XST_NOT_SGDMA;
727         }
728
729         return XDmaChannel_CreateSgList(&InstancePtr->RecvChannel, MemoryPtr,
730                                         ByteCount);
731 }
732
733 /*****************************************************************************/
734 /**
735 *
736 * Give the driver the memory space to be used for the scatter-gather DMA
737 * transmit descriptor list. This function should only be called once, during
738 * initialization of the Ethernet driver. The memory space must be big enough
739 * to hold some number of descriptors, depending on the needs of the system.
740 * The xemac.h file defines minimum and default numbers of descriptors
741 * which can be used to allocate this memory space.
742 *
743 * The memory space must be word-aligned. An assert will occur if asserts are
744 * turned on and the memory is not word-aligned.
745 *
746 * @param InstancePtr is a pointer to the XEmac instance to be worked on.
747 * @param MemoryPtr is a pointer to the word-aligned memory.
748 * @param ByteCount is the length, in bytes, of the memory space.
749 *
750 * @return
751 *
752 * - XST_SUCCESS if the space was initialized successfully
753 * - XST_NOT_SGDMA if the MAC is not configured for scatter-gather DMA
754 * - XST_DMA_SG_LIST_EXISTS if this list space has already been created
755 *
756 * @note
757 *
758 * If the device is configured for scatter-gather DMA, this function must be
759 * called AFTER the XEmac_Initialize() function because the DMA channel
760 * components must be initialized before the memory space is set.
761 *
762 ******************************************************************************/
763 XStatus
764 XEmac_SetSgSendSpace(XEmac * InstancePtr, u32 * MemoryPtr, u32 ByteCount)
765 {
766         XASSERT_NONVOID(InstancePtr != NULL);
767         XASSERT_NONVOID(MemoryPtr != NULL);
768         XASSERT_NONVOID(ByteCount != 0);
769         XASSERT_NONVOID(InstancePtr->IsReady == XCOMPONENT_IS_READY);
770
771         if (!XEmac_mIsSgDma(InstancePtr)) {
772                 return XST_NOT_SGDMA;
773         }
774
775         return XDmaChannel_CreateSgList(&InstancePtr->SendChannel, MemoryPtr,
776                                         ByteCount);
777 }
778
779 /*****************************************************************************/
780 /**
781 *
782 * Set the callback function for handling received frames in scatter-gather DMA
783 * mode.  The upper layer software should call this function during
784 * initialization.  The callback is called once per frame received. The head of
785 * a descriptor list is passed in along with the number of descriptors in the
786 * list. Before leaving the callback, the upper layer software should attach a
787 * new buffer to each descriptor in the list.
788 *
789 * The callback is invoked by the driver within interrupt context, so it needs
790 * to do its job quickly. Sending the received frame up the protocol stack
791 * should be done at task-level. If there are other potentially slow operations
792 * within the callback, these too should be done at task-level.
793 *
794 * @param InstancePtr is a pointer to the XEmac instance to be worked on.
795 * @param CallBackRef is a reference pointer to be passed back to the adapter in
796 *        the callback. This helps the adapter correlate the callback to a
797 *        particular driver.
798 * @param FuncPtr is the pointer to the callback function.
799 *
800 * @return
801 *
802 * None.
803 *
804 * @note
805 *
806 * None.
807 *
808 ******************************************************************************/
809 void
810 XEmac_SetSgRecvHandler(XEmac * InstancePtr, void *CallBackRef,
811                        XEmac_SgHandler FuncPtr)
812 {
813         /*
814          * Asserted IsDmaSg here instead of run-time check because there is really
815          * no ill-effects of setting these when not configured for scatter-gather.
816          */
817         XASSERT_VOID(InstancePtr != NULL);
818         XASSERT_VOID(FuncPtr != NULL);
819         XASSERT_VOID(XEmac_mIsSgDma(InstancePtr));
820         XASSERT_VOID(InstancePtr->IsReady == XCOMPONENT_IS_READY);
821
822         InstancePtr->SgRecvHandler = FuncPtr;
823         InstancePtr->SgRecvRef = CallBackRef;
824 }
825
826 /*****************************************************************************/
827 /**
828 *
829 * Set the callback function for handling confirmation of transmitted frames in
830 * scatter-gather DMA mode.  The upper layer software should call this function
831 * during initialization.  The callback is called once per frame sent. The head
832 * of a descriptor list is passed in along with the number of descriptors in
833 * the list. The callback is responsible for freeing buffers attached to these
834 * descriptors.
835 *
836 * The callback is invoked by the driver within interrupt context, so it needs
837 * to do its job quickly. If there are potentially slow operations within the
838 * callback, these should be done at task-level.
839 *
840 * @param InstancePtr is a pointer to the XEmac instance to be worked on.
841 * @param CallBackRef is a reference pointer to be passed back to the adapter in
842 *        the callback. This helps the adapter correlate the callback to a
843 *        particular driver.
844 * @param FuncPtr is the pointer to the callback function.
845 *
846 * @return
847 *
848 * None.
849 *
850 * @note
851 *
852 * None.
853 *
854 ******************************************************************************/
855 void
856 XEmac_SetSgSendHandler(XEmac * InstancePtr, void *CallBackRef,
857                        XEmac_SgHandler FuncPtr)
858 {
859         /*
860          * Asserted IsDmaSg here instead of run-time check because there is really
861          * no ill-effects of setting these when not configured for scatter-gather.
862          */
863         XASSERT_VOID(InstancePtr != NULL);
864         XASSERT_VOID(FuncPtr != NULL);
865         XASSERT_VOID(XEmac_mIsSgDma(InstancePtr));
866         XASSERT_VOID(InstancePtr->IsReady == XCOMPONENT_IS_READY);
867
868         InstancePtr->SgSendHandler = FuncPtr;
869         InstancePtr->SgSendRef = CallBackRef;
870 }
871
872 /*****************************************************************************/
873 /*
874 *
875 * Handle an interrupt from the DMA receive channel. DMA interrupts are:
876 *
877 * - DMA error. DMA encountered a bus error or timeout. This is a fatal error
878 *   that requires reset of the channel.  The driver calls the error handler
879 *   of the upper layer software with an error code indicating the device should
880 *   be reset.
881 * - Packet count threshold reached.  For scatter-gather operations, indicates
882 *   the threshold for the number of packets not serviced by software has been
883 *   reached. The driver behaves as follows:
884 *       - Get the value of the packet counter, which tells us how many packets
885 *         are ready to be serviced
886 *       - For each packet
887 *           - For each descriptor, remove it from the scatter-gather list
888 *           - Check for the last descriptor in the frame, and if set
889 *               - Bump frame statistics
890 *               - Call the scatter-gather receive callback function
891 *               - Decrement the packet counter by one
892 *       Note that there are no receive errors reported in the status word of
893 *       the buffer descriptor.  If receive errors occur, the MAC drops the
894 *       packet, and we only find out about the errors through various error
895 *       count registers.
896 * - Packet wait bound reached.  For scatter-gather, indicates the time to wait
897 *   for the next packet has expired.  The driver follows the same logic as when
898 *   the packet count threshold interrupt is received.
899 * - Scatter-gather end acknowledge.  Hardware has reached the end of the
900 *   descriptor list.  The driver follows the same logic as when the packet count
901 *   threshold interrupt is received. In addition, the driver restarts the DMA
902 *   scatter-gather channel in case there are newly inserted descriptors.
903 *
904 * @param InstancePtr is a pointer to the XEmac instance to be worked on.
905 *
906 * @return
907 *
908 * Although the function returns void, there are asynchronous errors that can
909 * be generated (by calling the ErrorHandler) from this function.  These are:
910 * - XST_DMA_SG_LIST_EMPTY indicates we tried to get a buffer descriptor from the
911 *   DMA channel, but there was not one ready for software.
912 * - XST_DMA_ERROR indicates a DMA bus error or timeout occurred. This is a fatal
913 *   error that requires reset.
914 *
915 * @note
916 *
917 * None.
918 *
919 ******************************************************************************/
920 static void
921 HandleDmaRecvIntr(XEmac * InstancePtr)
922 {
923         u32 IntrStatus;
924
925         /*
926          * Read the interrupt status
927          */
928         IntrStatus = XDmaChannel_GetIntrStatus(&InstancePtr->RecvChannel);
929
930         /*
931          * For packet threshold or wait bound interrupts, process desciptors. Also
932          * process descriptors on a SG end acknowledgement, which means the end of
933          * the descriptor list has been reached by the hardware. For receive, this
934          * is potentially trouble since it means the descriptor list is full,
935          * unless software can process enough packets quickly enough so the
936          * hardware has room to put new packets.
937          */
938         if (IntrStatus & (XDC_IXR_PKT_THRESHOLD_MASK |
939                           XDC_IXR_PKT_WAIT_BOUND_MASK | XDC_IXR_SG_END_MASK)) {
940                 XStatus Result = XST_SUCCESS;
941                 u32 NumFrames;
942                 u32 NumProcessed;
943                 u32 NumBuffers;
944                 u32 NumBytes;
945                 u32 IsLast;
946                 XBufDescriptor *FirstBdPtr;
947                 XBufDescriptor *BdPtr;
948
949                 /*
950                  * Get the number of unserviced packets
951                  */
952                 NumFrames = XDmaChannel_GetPktCount(&InstancePtr->RecvChannel);
953
954                 for (NumProcessed = 0; NumProcessed < NumFrames; NumProcessed++) {
955                         IsLast = FALSE;
956                         FirstBdPtr = NULL;
957                         NumBuffers = 0;
958                         NumBytes = 0;
959
960                         /*
961                          * For each packet, get the descriptor from the list. On the
962                          * last one in the frame, make the callback to the upper layer.
963                          */
964                         while (!IsLast) {
965                                 Result =
966                                     XDmaChannel_GetDescriptor(&InstancePtr->
967                                                               RecvChannel,
968                                                               &BdPtr);
969                                 if (Result != XST_SUCCESS) {
970                                         /*
971                                          * An error getting a buffer descriptor from the list.
972                                          * This should not happen, but if it does, report it to
973                                          * the error callback and break out of the loops to service
974                                          * other interrupts.
975                                          */
976                                         InstancePtr->ErrorHandler(InstancePtr->
977                                                                   ErrorRef,
978                                                                   Result);
979                                         break;
980                                 }
981
982                                 /*
983                                  * Keep a pointer to the first descriptor in the list, as it
984                                  * will be passed to the upper layers in a bit. By the fact
985                                  * that we received this packet means no errors occurred, so
986                                  * no need to check the device status word for errors.
987                                  */
988                                 if (FirstBdPtr == NULL) {
989                                         FirstBdPtr = BdPtr;
990                                 }
991
992                                 NumBytes += XBufDescriptor_GetLength(BdPtr);
993
994                                 /*
995                                  * Check to see if this is the last descriptor in the frame,
996                                  * and if so, set the IsLast flag to get out of the loop.
997                                  */
998                                 if (XBufDescriptor_IsLastStatus(BdPtr)) {
999                                         IsLast = TRUE;
1000                                 }
1001
1002                                 /*
1003                                  * Bump the number of buffers in this packet
1004                                  */
1005                                 NumBuffers++;
1006
1007                         }       /* end while loop */
1008
1009                         /*
1010                          * Check for error that occurred inside the while loop, and break
1011                          * out of the for loop if there was one so other interrupts can
1012                          * be serviced.
1013                          */
1014                         if (Result != XST_SUCCESS) {
1015                                 break;
1016                         }
1017
1018                         InstancePtr->Stats.RecvFrames++;
1019                         InstancePtr->Stats.RecvBytes += NumBytes;
1020
1021                         /*
1022                          * Make the callback to the upper layers, passing it the first
1023                          * descriptor in the packet and the number of descriptors in the
1024                          * packet.
1025                          */
1026                         InstancePtr->SgRecvHandler(InstancePtr->SgRecvRef,
1027                                                    FirstBdPtr, NumBuffers);
1028
1029                         /*
1030                          * Decrement the packet count register to reflect the fact we
1031                          * just processed a packet
1032                          */
1033                         XDmaChannel_DecrementPktCount(&InstancePtr->
1034                                                       RecvChannel);
1035
1036                 }               /* end for loop */
1037
1038                 /*
1039                  * If the interrupt was an end-ack, check the descriptor list again to
1040                  * see if it is empty. If not, go ahead and restart the scatter-gather
1041                  * channel. This is to fix a possible race condition where, on receive,
1042                  * the driver attempted to start a scatter-gather channel that was
1043                  * already started, which resulted in no action from the XDmaChannel
1044                  * component. But, just after the XDmaChannel component saw that the
1045                  * hardware was already started, the hardware stopped because it
1046                  * reached the end of the list.  In that case, this interrupt is
1047                  * generated and we can restart the hardware here.
1048                  */
1049                 if (IntrStatus & XDC_IXR_SG_END_MASK) {
1050                         /*
1051                          * Ignore the return status since we know the list exists and we
1052                          * don't care if the list is empty or the channel is already started.
1053                          */
1054                         (void) XDmaChannel_SgStart(&InstancePtr->RecvChannel);
1055                 }
1056         }
1057
1058         /*
1059          * All interrupts are handled (except the error below) so acknowledge
1060          * (clear) the interrupts by writing the value read above back to the status
1061          * register. The packet count interrupt must be acknowledged after the
1062          * decrement, otherwise it will come right back. We clear the interrupts
1063          * before we handle the error interrupt because the ErrorHandler should
1064          * result in a reset, which clears the interrupt status register. So we
1065          * don't want to toggle the interrupt back on by writing the interrupt
1066          * status register with an old value after a reset.
1067          */
1068         XDmaChannel_SetIntrStatus(&InstancePtr->RecvChannel, IntrStatus);
1069
1070         /*
1071          * Check for DMA errors and call the error callback function if an error
1072          * occurred (DMA bus or timeout error), which should result in a reset of
1073          * the device by the upper layer software.
1074          */
1075         if (IntrStatus & XDC_IXR_DMA_ERROR_MASK) {
1076                 InstancePtr->Stats.DmaErrors++;
1077                 InstancePtr->ErrorHandler(InstancePtr->ErrorRef, XST_DMA_ERROR);
1078         }
1079 }
1080
1081 /*****************************************************************************/
1082 /*
1083 *
1084 * Handle an interrupt from the DMA send channel. DMA interrupts are:
1085 *
1086 * - DMA error. DMA encountered a bus error or timeout. This is a fatal error
1087 *   that requires reset of the channel.  The driver calls the error handler
1088 *   of the upper layer software with an error code indicating the device should
1089 *   be reset.
1090 * - Packet count threshold reached.  For scatter-gather operations, indicates
1091 *   the threshold for the number of packets not serviced by software has been
1092 *   reached. The driver behaves as follows:
1093 *       - Get the value of the packet counter, which tells us how many packets
1094 *         are ready to be serviced
1095 *       - For each packet
1096 *           - For each descriptor, remove it from the scatter-gather list
1097 *           - Check for the last descriptor in the frame, and if set
1098 *               - Bump frame statistics
1099 *               - Call the scatter-gather receive callback function
1100 *               - Decrement the packet counter by one
1101 *       Note that there are no receive errors reported in the status word of
1102 *       the buffer descriptor.  If receive errors occur, the MAC drops the
1103 *       packet, and we only find out about the errors through various error
1104 *       count registers.
1105 * - Packet wait bound reached.  For scatter-gather, indicates the time to wait
1106 *   for the next packet has expired.  The driver follows the same logic as when
1107 *   the packet count threshold interrupt is received.
1108 * - Scatter-gather end acknowledge.  Hardware has reached the end of the
1109 *   descriptor list.  The driver follows the same logic as when the packet count
1110 *   threshold interrupt is received. In addition, the driver restarts the DMA
1111 *   scatter-gather channel in case there are newly inserted descriptors.
1112 *
1113 * @param InstancePtr is a pointer to the XEmac instance to be worked on.
1114 *
1115 * @return
1116 *
1117 * Although the function returns void, there are asynchronous errors
1118 * that can be generated from this function.  These are:
1119 * - XST_DMA_SG_LIST_EMPTY indicates we tried to get a buffer descriptor from
1120 *   the DMA channel, but there was not one ready for software.
1121 * - XST_DMA_ERROR indicates a DMA bus error or timeout occurred. This is a
1122 *   fatal error that requires reset.
1123 *
1124 * @note
1125 *
1126 * None.
1127 *
1128 ******************************************************************************/
1129 static void
1130 HandleDmaSendIntr(XEmac * InstancePtr)
1131 {
1132         u32 IntrStatus;
1133
1134         /*
1135          * Read the interrupt status
1136          */
1137         IntrStatus = XDmaChannel_GetIntrStatus(&InstancePtr->SendChannel);
1138
1139         /*
1140          * For packet threshold or wait bound interrupt, process descriptors. Also
1141          * process descriptors on a SG end acknowledgement, which means the end of
1142          * the descriptor list has been reached by the hardware. For transmit,
1143          * this is a normal condition during times of light traffic.  In fact, the
1144          * wait bound interrupt may be masked for transmit since the end-ack would
1145          * always occur before the wait bound expires.
1146          */
1147         if (IntrStatus & (XDC_IXR_PKT_THRESHOLD_MASK |
1148                           XDC_IXR_PKT_WAIT_BOUND_MASK | XDC_IXR_SG_END_MASK)) {
1149                 XStatus Result = XST_SUCCESS;
1150                 u32 NumFrames;
1151                 u32 NumProcessed;
1152                 u32 NumBuffers;
1153                 u32 NumBytes;
1154                 u32 IsLast;
1155                 XBufDescriptor *FirstBdPtr;
1156                 XBufDescriptor *BdPtr;
1157
1158                 /*
1159                  * Get the number of unserviced packets
1160                  */
1161                 NumFrames = XDmaChannel_GetPktCount(&InstancePtr->SendChannel);
1162
1163                 for (NumProcessed = 0; NumProcessed < NumFrames; NumProcessed++) {
1164                         IsLast = FALSE;
1165                         FirstBdPtr = NULL;
1166                         NumBuffers = 0;
1167                         NumBytes = 0;
1168
1169                         /*
1170                          * For each frame, traverse the descriptor list and look for
1171                          * errors. On the last one in the frame, make the callback.
1172                          */
1173                         while (!IsLast) {
1174                                 Result =
1175                                     XDmaChannel_GetDescriptor(&InstancePtr->
1176                                                               SendChannel,
1177                                                               &BdPtr);
1178                                 if (Result != XST_SUCCESS) {
1179                                         /*
1180                                          * An error getting a buffer descriptor from the list.
1181                                          * This should not happen, but if it does, report it to
1182                                          * the error callback and break out of the loops to service
1183                                          * other interrupts
1184                                          */
1185                                         InstancePtr->ErrorHandler(InstancePtr->
1186                                                                   ErrorRef,
1187                                                                   Result);
1188                                         break;
1189                                 }
1190
1191                                 /*
1192                                  * Keep a pointer to the first descriptor in the list and
1193                                  * check the device status for errors. The device status is
1194                                  * only available in the first descriptor of a packet.
1195                                  */
1196                                 if (FirstBdPtr == NULL) {
1197                                         u32 XmitStatus;
1198
1199                                         FirstBdPtr = BdPtr;
1200
1201                                         XmitStatus =
1202                                             XBufDescriptor_GetDeviceStatus
1203                                             (BdPtr);
1204                                         if (XmitStatus &
1205                                             XEM_TSR_EXCESS_DEFERRAL_MASK) {
1206                                                 InstancePtr->Stats.
1207                                                     XmitExcessDeferral++;
1208                                         }
1209
1210                                         if (XmitStatus &
1211                                             XEM_TSR_LATE_COLLISION_MASK) {
1212                                                 InstancePtr->Stats.
1213                                                     XmitLateCollisionErrors++;
1214                                         }
1215                                 }
1216
1217                                 NumBytes += XBufDescriptor_GetLength(BdPtr);
1218
1219                                 /*
1220                                  * Check to see if this is the last descriptor in the frame,
1221                                  * and if so, set the IsLast flag to get out of the loop. The
1222                                  * transmit channel must check the last bit in the control
1223                                  * word, not the status word (the DMA engine does not update
1224                                  * the last bit in the status word for the transmit direction).
1225                                  */
1226                                 if (XBufDescriptor_IsLastControl(BdPtr)) {
1227                                         IsLast = TRUE;
1228                                 }
1229
1230                                 /*
1231                                  * Bump the number of buffers in this packet
1232                                  */
1233                                 NumBuffers++;
1234
1235                         }       /* end while loop */
1236
1237                         /*
1238                          * Check for error that occurred inside the while loop, and break
1239                          * out of the for loop if there was one so other interrupts can
1240                          * be serviced.
1241                          */
1242                         if (Result != XST_SUCCESS) {
1243                                 break;
1244                         }
1245
1246                         InstancePtr->Stats.XmitFrames++;
1247                         InstancePtr->Stats.XmitBytes += NumBytes;
1248
1249                         /*
1250                          * Make the callback to the upper layers, passing it the first
1251                          * descriptor in the packet and the number of descriptors in the
1252                          * packet.
1253                          */
1254                         InstancePtr->SgSendHandler(InstancePtr->SgSendRef,
1255                                                    FirstBdPtr, NumBuffers);
1256
1257                         /*
1258                          * Decrement the packet count register to reflect the fact we
1259                          * just processed a packet
1260                          */
1261                         XDmaChannel_DecrementPktCount(&InstancePtr->
1262                                                       SendChannel);
1263
1264                 }               /* end for loop */
1265
1266                 /*
1267                  * If the interrupt was an end-ack, check the descriptor list again to
1268                  * see if it is empty. If not, go ahead and restart the scatter-gather
1269                  * channel. This is to fix a possible race condition where, on transmit,
1270                  * the driver attempted to start a scatter-gather channel that was
1271                  * already started, which resulted in no action from the XDmaChannel
1272                  * component. But, just after the XDmaChannel component saw that the
1273                  * hardware was already started, the hardware stopped because it
1274                  * reached the end of the list.  In that case, this interrupt is
1275                  * generated and we can restart the hardware here.
1276                  */
1277                 if (IntrStatus & XDC_IXR_SG_END_MASK) {
1278                         /*
1279                          * Ignore the return status since we know the list exists and we
1280                          * don't care if the list is empty or the channel is already started.
1281                          */
1282                         (void) XDmaChannel_SgStart(&InstancePtr->SendChannel);
1283                 }
1284         }
1285
1286         /*
1287          * All interrupts are handled (except the error below) so acknowledge
1288          * (clear) the interrupts by writing the value read above back to the status
1289          * register. The packet count interrupt must be acknowledged after the
1290          * decrement, otherwise it will come right back. We clear the interrupts
1291          * before we handle the error interrupt because the ErrorHandler should
1292          * result in a reset, which clears the interrupt status register. So we
1293          * don't want to toggle the interrupt back on by writing the interrupt
1294          * status register with an old value after a reset.
1295          */
1296         XDmaChannel_SetIntrStatus(&InstancePtr->SendChannel, IntrStatus);
1297
1298         /*
1299          * Check for DMA errors and call the error callback function if an error
1300          * occurred (DMA bus or timeout error), which should result in a reset of
1301          * the device by the upper layer software.
1302          */
1303         if (IntrStatus & XDC_IXR_DMA_ERROR_MASK) {
1304                 InstancePtr->Stats.DmaErrors++;
1305                 InstancePtr->ErrorHandler(InstancePtr->ErrorRef, XST_DMA_ERROR);
1306         }
1307 }
1308
1309 /*****************************************************************************/
1310 /*
1311 *
1312 * Handle an interrupt from the Ethernet MAC when configured with scatter-gather
1313 * DMA. The only interrupts handled in this case are errors.
1314 *
1315 * @param InstancePtr is a pointer to the XEmac instance to be worked on.
1316 *
1317 * @return
1318 *
1319 * None.
1320 *
1321 * @note
1322 *
1323 * None.
1324 *
1325 ******************************************************************************/
1326 static void
1327 HandleEmacDmaIntr(XEmac * InstancePtr)
1328 {
1329         u32 IntrStatus;
1330
1331         /*
1332          * When configured with DMA, the EMAC generates interrupts only when errors
1333          * occur. We clear the interrupts immediately so that any latched status
1334          * interrupt bits will reflect the true status of the device, and so any
1335          * pulsed interrupts (non-status) generated during the Isr will not be lost.
1336          */
1337         IntrStatus = XIIF_V123B_READ_IISR(InstancePtr->BaseAddress);
1338         XIIF_V123B_WRITE_IISR(InstancePtr->BaseAddress, IntrStatus);
1339
1340         /*
1341          * Check the MAC for errors
1342          */
1343         XEmac_CheckEmacError(InstancePtr, IntrStatus);
1344 }