blob: 567abb42abbfed76b93df324208376930332c206 [file] [log] [blame]
wdenke537b3b2004-02-23 23:54:43 +00001/******************************************************************************
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
91static void HandleDmaRecvIntr(XEmac * InstancePtr);
92static void HandleDmaSendIntr(XEmac * InstancePtr);
93static 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******************************************************************************/
161XStatus
162XEmac_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******************************************************************************/
272XStatus
273XEmac_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******************************************************************************/
356void
357XEmac_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******************************************************************************/
447XStatus
448XEmac_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******************************************************************************/
514XStatus
515XEmac_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******************************************************************************/
580XStatus
581XEmac_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******************************************************************************/
651XStatus
652XEmac_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******************************************************************************/
717XStatus
718XEmac_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******************************************************************************/
763XStatus
764XEmac_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******************************************************************************/
809void
810XEmac_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******************************************************************************/
855void
856XEmac_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******************************************************************************/
920static void
921HandleDmaRecvIntr(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******************************************************************************/
1129static void
1130HandleDmaSendIntr(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******************************************************************************/
1326static void
1327HandleEmacDmaIntr(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}