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