1 /******************************************************************************
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.
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.
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.
30 * (c) Copyright 2002-2004 Xilinx Inc.
31 * All rights reserved.
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.
38 ******************************************************************************/
39 /*****************************************************************************/
42 * @file xemac_intr_dma.c
44 * Contains functions used in interrupt mode when configured with scatter-gather
47 * The interrupt handler, XEmac_IntrHandlerDma(), must be connected by the user
48 * to the interrupt controller.
51 * MODIFICATION HISTORY:
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
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.
70 ******************************************************************************/
72 /***************************** Include Files *********************************/
74 #include "xbasic_types.h"
77 #include "xbuf_descriptor.h"
78 #include "xdma_channel.h"
79 #include "xipif_v1_23_b.h" /* Uses v1.23b of the IPIF */
81 /************************** Constant Definitions *****************************/
83 /**************************** Type Definitions *******************************/
85 /***************** Macros (Inline Functions) Definitions *********************/
87 /************************** Variable Definitions *****************************/
89 /************************** Function Prototypes ******************************/
91 static void HandleDmaRecvIntr(XEmac * InstancePtr);
92 static void HandleDmaSendIntr(XEmac * InstancePtr);
93 static void HandleEmacDmaIntr(XEmac * InstancePtr);
95 /*****************************************************************************/
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.
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.
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.
117 * The buffer attached to the descriptor must be word-aligned on the front end.
119 * This call is non-blocking. Notification of error or successful transmission
120 * is done asynchronously through the send or error callback function.
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
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.
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
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.
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
160 ******************************************************************************/
162 XEmac_SgSend(XEmac * InstancePtr, XBufDescriptor * BdPtr, int Delay)
167 XASSERT_NONVOID(InstancePtr != NULL);
168 XASSERT_NONVOID(BdPtr != NULL);
169 XASSERT_NONVOID(InstancePtr->IsReady == XCOMPONENT_IS_READY);
172 * Be sure the device is configured for scatter-gather DMA, then be sure
175 if (!XEmac_mIsSgDma(InstancePtr)) {
176 return XST_NOT_SGDMA;
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.
184 BdControl = XBufDescriptor_GetControl(BdPtr);
185 XBufDescriptor_SetControl(BdPtr, BdControl | XEM_DFT_SEND_BD_MASK);
187 XBufDescriptor_SetDestAddress(BdPtr,
188 InstancePtr->BaseAddress +
189 XEM_PFIFO_TXDATA_OFFSET);
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.
196 XIIF_V123B_GINTR_DISABLE(InstancePtr->BaseAddress);
198 Result = XDmaChannel_PutDescriptor(&InstancePtr->SendChannel, BdPtr);
199 if (Result != XST_SUCCESS) {
200 XIIF_V123B_GINTR_ENABLE(InstancePtr->BaseAddress);
205 * If this is the last buffer in the frame, commit the inserts and start
206 * the DMA engine if necessary
208 if (XBufDescriptor_IsLastControl(BdPtr)) {
209 Result = XDmaChannel_CommitPuts(&InstancePtr->SendChannel);
210 if (Result != XST_SUCCESS) {
211 XIIF_V123B_GINTR_ENABLE(InstancePtr->BaseAddress);
215 if (Delay == XEM_SGDMA_NODELAY) {
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.
223 (void) XDmaChannel_SgStart(&InstancePtr->SendChannel);
227 XIIF_V123B_GINTR_ENABLE(InstancePtr->BaseAddress);
232 /*****************************************************************************/
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.
244 * The buffer attached to the descriptor must be word-aligned on both the front
245 * end and the back end.
247 * Notification of received frames are done asynchronously through the receive
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
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.
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
271 ******************************************************************************/
273 XEmac_SgRecv(XEmac * InstancePtr, XBufDescriptor * BdPtr)
278 XASSERT_NONVOID(InstancePtr != NULL);
279 XASSERT_NONVOID(BdPtr != NULL);
280 XASSERT_NONVOID(InstancePtr->IsReady == XCOMPONENT_IS_READY);
283 * Be sure the device is configured for scatter-gather DMA
285 if (!XEmac_mIsSgDma(InstancePtr)) {
286 return XST_NOT_SGDMA;
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.
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);
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.
307 XIIF_V123B_GINTR_DISABLE(InstancePtr->BaseAddress);
309 Result = XDmaChannel_PutDescriptor(&InstancePtr->RecvChannel, BdPtr);
310 if (Result != XST_SUCCESS) {
311 XIIF_V123B_GINTR_ENABLE(InstancePtr->BaseAddress);
315 Result = XDmaChannel_CommitPuts(&InstancePtr->RecvChannel);
316 if (Result != XST_SUCCESS) {
317 XIIF_V123B_GINTR_ENABLE(InstancePtr->BaseAddress);
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.
327 (void) XDmaChannel_SgStart(&InstancePtr->RecvChannel);
329 XIIF_V123B_GINTR_ENABLE(InstancePtr->BaseAddress);
334 /*****************************************************************************/
337 * The interrupt handler for the Ethernet driver when configured with scatter-
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.
345 * @param InstancePtr is a pointer to the XEmac instance that just interrupted.
355 ******************************************************************************/
357 XEmac_IntrHandlerDma(void *InstancePtr)
360 XEmac *EmacPtr = (XEmac *) InstancePtr;
362 EmacPtr->Stats.TotalIntrs++;
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.
368 IntrStatus = XIIF_V123B_READ_DIPR(EmacPtr->BaseAddress);
371 * See which type of interrupt is being requested, and service it
373 if (IntrStatus & XEM_IPIF_RECV_DMA_MASK) { /* Receive DMA interrupt */
374 EmacPtr->Stats.RecvInterrupts++;
375 HandleDmaRecvIntr(EmacPtr);
378 if (IntrStatus & XEM_IPIF_SEND_DMA_MASK) { /* Send DMA interrupt */
379 EmacPtr->Stats.XmitInterrupts++;
380 HandleDmaSendIntr(EmacPtr);
383 if (IntrStatus & XEM_IPIF_EMAC_MASK) { /* MAC interrupt */
384 EmacPtr->Stats.EmacInterrupts++;
385 HandleEmacDmaIntr(EmacPtr);
388 if (IntrStatus & XEM_IPIF_RECV_FIFO_MASK) { /* Receive FIFO interrupt */
389 EmacPtr->Stats.RecvInterrupts++;
390 XEmac_CheckFifoRecvError(EmacPtr);
393 if (IntrStatus & XEM_IPIF_SEND_FIFO_MASK) { /* Send FIFO interrupt */
394 EmacPtr->Stats.XmitInterrupts++;
395 XEmac_CheckFifoSendError(EmacPtr);
398 if (IntrStatus & XIIF_V123B_ERROR_MASK) {
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.
405 XIIF_V123B_WRITE_DISR(EmacPtr->BaseAddress,
406 XIIF_V123B_ERROR_MASK);
410 /*****************************************************************************/
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.
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
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.
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
446 ******************************************************************************/
448 XEmac_SetPktThreshold(XEmac * InstancePtr, u32 Direction, u8 Threshold)
450 XASSERT_NONVOID(InstancePtr != NULL);
451 XASSERT_NONVOID(Direction == XEM_SEND || Direction == XEM_RECV);
452 XASSERT_NONVOID(InstancePtr->IsReady == XCOMPONENT_IS_READY);
455 * Be sure device is configured for scatter-gather DMA and has been stopped
457 if (!XEmac_mIsSgDma(InstancePtr)) {
458 return XST_NOT_SGDMA;
461 if (InstancePtr->IsStarted == XCOMPONENT_IS_STARTED) {
462 return XST_DEVICE_IS_STARTED;
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).
472 return XDmaChannel_SetPktThreshold(&InstancePtr->SendChannel,
476 return XDmaChannel_SetPktThreshold(&InstancePtr->RecvChannel,
480 return XST_INVALID_PARAM;
484 /*****************************************************************************/
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
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.
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.
513 ******************************************************************************/
515 XEmac_GetPktThreshold(XEmac * InstancePtr, u32 Direction, u8 * ThreshPtr)
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);
522 if (!XEmac_mIsSgDma(InstancePtr)) {
523 return XST_NOT_SGDMA;
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
535 XDmaChannel_GetPktThreshold(&InstancePtr->SendChannel);
540 XDmaChannel_GetPktThreshold(&InstancePtr->RecvChannel);
544 return XST_INVALID_PARAM;
550 /*****************************************************************************/
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.
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.
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.
579 ******************************************************************************/
581 XEmac_SetPktWaitBound(XEmac * InstancePtr, u32 Direction, u32 TimerValue)
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);
589 * Be sure device is configured for scatter-gather DMA and has been stopped
591 if (!XEmac_mIsSgDma(InstancePtr)) {
592 return XST_NOT_SGDMA;
595 if (InstancePtr->IsStarted == XCOMPONENT_IS_STARTED) {
596 return XST_DEVICE_IS_STARTED;
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).
606 XDmaChannel_SetPktWaitBound(&InstancePtr->SendChannel,
611 XDmaChannel_SetPktWaitBound(&InstancePtr->RecvChannel,
616 return XST_INVALID_PARAM;
622 /*****************************************************************************/
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.
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.
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.
650 ******************************************************************************/
652 XEmac_GetPktWaitBound(XEmac * InstancePtr, u32 Direction, u32 * WaitPtr)
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);
659 if (!XEmac_mIsSgDma(InstancePtr)) {
660 return XST_NOT_SGDMA;
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
672 XDmaChannel_GetPktWaitBound(&InstancePtr->SendChannel);
677 XDmaChannel_GetPktWaitBound(&InstancePtr->RecvChannel);
681 return XST_INVALID_PARAM;
687 /*****************************************************************************/
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.
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.
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.
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
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.
716 ******************************************************************************/
718 XEmac_SetSgRecvSpace(XEmac * InstancePtr, u32 * MemoryPtr, u32 ByteCount)
720 XASSERT_NONVOID(InstancePtr != NULL);
721 XASSERT_NONVOID(MemoryPtr != NULL);
722 XASSERT_NONVOID(ByteCount != 0);
723 XASSERT_NONVOID(InstancePtr->IsReady == XCOMPONENT_IS_READY);
725 if (!XEmac_mIsSgDma(InstancePtr)) {
726 return XST_NOT_SGDMA;
729 return XDmaChannel_CreateSgList(&InstancePtr->RecvChannel, MemoryPtr,
733 /*****************************************************************************/
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.
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.
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.
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
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.
762 ******************************************************************************/
764 XEmac_SetSgSendSpace(XEmac * InstancePtr, u32 * MemoryPtr, u32 ByteCount)
766 XASSERT_NONVOID(InstancePtr != NULL);
767 XASSERT_NONVOID(MemoryPtr != NULL);
768 XASSERT_NONVOID(ByteCount != 0);
769 XASSERT_NONVOID(InstancePtr->IsReady == XCOMPONENT_IS_READY);
771 if (!XEmac_mIsSgDma(InstancePtr)) {
772 return XST_NOT_SGDMA;
775 return XDmaChannel_CreateSgList(&InstancePtr->SendChannel, MemoryPtr,
779 /*****************************************************************************/
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.
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.
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
798 * @param FuncPtr is the pointer to the callback function.
808 ******************************************************************************/
810 XEmac_SetSgRecvHandler(XEmac * InstancePtr, void *CallBackRef,
811 XEmac_SgHandler FuncPtr)
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.
817 XASSERT_VOID(InstancePtr != NULL);
818 XASSERT_VOID(FuncPtr != NULL);
819 XASSERT_VOID(XEmac_mIsSgDma(InstancePtr));
820 XASSERT_VOID(InstancePtr->IsReady == XCOMPONENT_IS_READY);
822 InstancePtr->SgRecvHandler = FuncPtr;
823 InstancePtr->SgRecvRef = CallBackRef;
826 /*****************************************************************************/
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
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.
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
844 * @param FuncPtr is the pointer to the callback function.
854 ******************************************************************************/
856 XEmac_SetSgSendHandler(XEmac * InstancePtr, void *CallBackRef,
857 XEmac_SgHandler FuncPtr)
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.
863 XASSERT_VOID(InstancePtr != NULL);
864 XASSERT_VOID(FuncPtr != NULL);
865 XASSERT_VOID(XEmac_mIsSgDma(InstancePtr));
866 XASSERT_VOID(InstancePtr->IsReady == XCOMPONENT_IS_READY);
868 InstancePtr->SgSendHandler = FuncPtr;
869 InstancePtr->SgSendRef = CallBackRef;
872 /*****************************************************************************/
875 * Handle an interrupt from the DMA receive channel. DMA interrupts are:
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
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
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
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.
904 * @param InstancePtr is a pointer to the XEmac instance to be worked on.
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.
919 ******************************************************************************/
921 HandleDmaRecvIntr(XEmac * InstancePtr)
926 * Read the interrupt status
928 IntrStatus = XDmaChannel_GetIntrStatus(&InstancePtr->RecvChannel);
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.
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;
946 XBufDescriptor *FirstBdPtr;
947 XBufDescriptor *BdPtr;
950 * Get the number of unserviced packets
952 NumFrames = XDmaChannel_GetPktCount(&InstancePtr->RecvChannel);
954 for (NumProcessed = 0; NumProcessed < NumFrames; NumProcessed++) {
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.
966 XDmaChannel_GetDescriptor(&InstancePtr->
969 if (Result != XST_SUCCESS) {
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
976 InstancePtr->ErrorHandler(InstancePtr->
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.
988 if (FirstBdPtr == NULL) {
992 NumBytes += XBufDescriptor_GetLength(BdPtr);
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.
998 if (XBufDescriptor_IsLastStatus(BdPtr)) {
1003 * Bump the number of buffers in this packet
1007 } /* end while loop */
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
1014 if (Result != XST_SUCCESS) {
1018 InstancePtr->Stats.RecvFrames++;
1019 InstancePtr->Stats.RecvBytes += NumBytes;
1022 * Make the callback to the upper layers, passing it the first
1023 * descriptor in the packet and the number of descriptors in the
1026 InstancePtr->SgRecvHandler(InstancePtr->SgRecvRef,
1027 FirstBdPtr, NumBuffers);
1030 * Decrement the packet count register to reflect the fact we
1031 * just processed a packet
1033 XDmaChannel_DecrementPktCount(&InstancePtr->
1036 } /* end for loop */
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.
1049 if (IntrStatus & XDC_IXR_SG_END_MASK) {
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.
1054 (void) XDmaChannel_SgStart(&InstancePtr->RecvChannel);
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.
1068 XDmaChannel_SetIntrStatus(&InstancePtr->RecvChannel, IntrStatus);
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.
1075 if (IntrStatus & XDC_IXR_DMA_ERROR_MASK) {
1076 InstancePtr->Stats.DmaErrors++;
1077 InstancePtr->ErrorHandler(InstancePtr->ErrorRef, XST_DMA_ERROR);
1081 /*****************************************************************************/
1084 * Handle an interrupt from the DMA send channel. DMA interrupts are:
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
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
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
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.
1113 * @param InstancePtr is a pointer to the XEmac instance to be worked on.
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.
1128 ******************************************************************************/
1130 HandleDmaSendIntr(XEmac * InstancePtr)
1135 * Read the interrupt status
1137 IntrStatus = XDmaChannel_GetIntrStatus(&InstancePtr->SendChannel);
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.
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;
1155 XBufDescriptor *FirstBdPtr;
1156 XBufDescriptor *BdPtr;
1159 * Get the number of unserviced packets
1161 NumFrames = XDmaChannel_GetPktCount(&InstancePtr->SendChannel);
1163 for (NumProcessed = 0; NumProcessed < NumFrames; NumProcessed++) {
1170 * For each frame, traverse the descriptor list and look for
1171 * errors. On the last one in the frame, make the callback.
1175 XDmaChannel_GetDescriptor(&InstancePtr->
1178 if (Result != XST_SUCCESS) {
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
1185 InstancePtr->ErrorHandler(InstancePtr->
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.
1196 if (FirstBdPtr == NULL) {
1202 XBufDescriptor_GetDeviceStatus
1205 XEM_TSR_EXCESS_DEFERRAL_MASK) {
1207 XmitExcessDeferral++;
1211 XEM_TSR_LATE_COLLISION_MASK) {
1213 XmitLateCollisionErrors++;
1217 NumBytes += XBufDescriptor_GetLength(BdPtr);
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).
1226 if (XBufDescriptor_IsLastControl(BdPtr)) {
1231 * Bump the number of buffers in this packet
1235 } /* end while loop */
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
1242 if (Result != XST_SUCCESS) {
1246 InstancePtr->Stats.XmitFrames++;
1247 InstancePtr->Stats.XmitBytes += NumBytes;
1250 * Make the callback to the upper layers, passing it the first
1251 * descriptor in the packet and the number of descriptors in the
1254 InstancePtr->SgSendHandler(InstancePtr->SgSendRef,
1255 FirstBdPtr, NumBuffers);
1258 * Decrement the packet count register to reflect the fact we
1259 * just processed a packet
1261 XDmaChannel_DecrementPktCount(&InstancePtr->
1264 } /* end for loop */
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.
1277 if (IntrStatus & XDC_IXR_SG_END_MASK) {
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.
1282 (void) XDmaChannel_SgStart(&InstancePtr->SendChannel);
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.
1296 XDmaChannel_SetIntrStatus(&InstancePtr->SendChannel, IntrStatus);
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.
1303 if (IntrStatus & XDC_IXR_DMA_ERROR_MASK) {
1304 InstancePtr->Stats.DmaErrors++;
1305 InstancePtr->ErrorHandler(InstancePtr->ErrorRef, XST_DMA_ERROR);
1309 /*****************************************************************************/
1312 * Handle an interrupt from the Ethernet MAC when configured with scatter-gather
1313 * DMA. The only interrupts handled in this case are errors.
1315 * @param InstancePtr is a pointer to the XEmac instance to be worked on.
1325 ******************************************************************************/
1327 HandleEmacDmaIntr(XEmac * InstancePtr)
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.
1337 IntrStatus = XIIF_V123B_READ_IISR(InstancePtr->BaseAddress);
1338 XIIF_V123B_WRITE_IISR(InstancePtr->BaseAddress, IntrStatus);
1341 * Check the MAC for errors
1343 XEmac_CheckEmacError(InstancePtr, IntrStatus);