1 /* $Id: xemac_intr_dma.c,v 1.1.1.1 2005/04/11 02:50:33 jack Exp $ */
2 /******************************************************************************
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation; either version 2 of the License, or (at your
10 * option) any later version.
13 * XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION "AS IS" AS A
14 * COURTESY TO YOU. BY PROVIDING THIS DESIGN, CODE, OR INFORMATION AS
15 * ONE POSSIBLE IMPLEMENTATION OF THIS FEATURE, APPLICATION OR STANDARD,
16 * XILINX IS MAKING NO REPRESENTATION THAT THIS IMPLEMENTATION IS FREE
17 * FROM ANY CLAIMS OF INFRINGEMENT, AND YOU ARE RESPONSIBLE FOR
18 * OBTAINING ANY RIGHTS YOU MAY REQUIRE FOR YOUR IMPLEMENTATION.
19 * XILINX EXPRESSLY DISCLAIMS ANY WARRANTY WHATSOEVER WITH RESPECT TO
20 * THE ADEQUACY OF THE IMPLEMENTATION, INCLUDING BUT NOT LIMITED TO ANY
21 * WARRANTIES OR REPRESENTATIONS THAT THIS IMPLEMENTATION IS FREE FROM
22 * CLAIMS OF INFRINGEMENT, IMPLIED WARRANTIES OF MERCHANTABILITY AND
23 * FITNESS FOR A PARTICULAR PURPOSE.
26 * Xilinx products are not intended for use in life support appliances,
27 * devices, or systems. Use in such applications is expressly prohibited.
30 * (c) Copyright 2002 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
59 ******************************************************************************/
61 /***************************** Include Files *********************************/
63 #include "xbasic_types.h"
66 #include "xbuf_descriptor.h"
67 #include "xdma_channel.h"
68 #include "xipif_v1_23_b.h" /* Uses v1.23b of the IPIF */
70 /************************** Constant Definitions *****************************/
72 /**************************** Type Definitions *******************************/
74 /***************** Macros (Inline Functions) Definitions *********************/
76 /************************** Variable Definitions *****************************/
78 /************************** Function Prototypes ******************************/
80 static void HandleDmaRecvIntr(XEmac * InstancePtr);
81 static void HandleDmaSendIntr(XEmac * InstancePtr);
82 static void HandleEmacDmaIntr(XEmac * InstancePtr);
84 /*****************************************************************************/
87 * Send an Ethernet frame using scatter-gather DMA. The caller attaches the
88 * frame to one or more buffer descriptors, then calls this function once for
89 * each descriptor. The caller is responsible for allocating and setting up the
90 * descriptor. An entire Ethernet frame may or may not be contained within one
91 * descriptor. This function simply inserts the descriptor into the scatter-
92 * gather engine's transmit list. The caller is responsible for providing mutual
93 * exclusion to guarantee that a frame is contiguous in the transmit list. The
94 * buffer attached to the descriptor must be word-aligned.
96 * The driver updates the descriptor with the device control register before
97 * being inserted into the transmit list. If this is the last descriptor in
98 * the frame, the inserts are committed, which means the descriptors for this
99 * frame are now available for transmission.
101 * It is assumed that the upper layer software supplies a correctly formatted
102 * Ethernet frame, including the destination and source addresses, the
103 * type/length field, and the data field. It is also assumed that upper layer
104 * software does not append FCS at the end of the frame.
106 * The buffer attached to the descriptor must be word-aligned on the front end.
108 * This call is non-blocking. Notification of error or successful transmission
109 * is done asynchronously through the send or error callback function.
111 * @param InstancePtr is a pointer to the XEmac instance to be worked on.
112 * @param BdPtr is the address of a descriptor to be inserted into the transmit
117 * - XST_SUCCESS if the buffer was successfull sent
118 * - XST_DEVICE_IS_STOPPED if the Ethernet MAC has not been started yet
119 * - XST_NOT_SGDMA if the device is not in scatter-gather DMA mode
120 * - XST_DMA_SG_LIST_FULL if the descriptor list for the DMA channel is full
121 * - XST_DMA_SG_BD_LOCKED if the DMA channel cannot insert the descriptor into
122 * the list because a locked descriptor exists at the insert point
123 * - XST_DMA_SG_NOTHING_TO_COMMIT if even after inserting a descriptor into the
124 * list, the DMA channel believes there are no new descriptors to commit. If
125 * this is ever encountered, there is likely a thread mutual exclusion problem
130 * This function is not thread-safe. The user must provide mutually exclusive
131 * access to this function if there are to be multiple threads that can call it.
135 * A status that should never be returned from this function, although
136 * the code is set up to handle it, is XST_DMA_SG_NO_LIST. Starting the device
137 * requires a list to be created, and this function requires the device to be
140 ******************************************************************************/
142 XEmac_SgSend(XEmac * InstancePtr, XBufDescriptor * BdPtr)
147 XASSERT_NONVOID(InstancePtr != NULL);
148 XASSERT_NONVOID(BdPtr != NULL);
149 XASSERT_NONVOID(InstancePtr->IsReady == XCOMPONENT_IS_READY);
152 * Be sure the device is configured for scatter-gather DMA, then be sure
155 if (!InstancePtr->IsDmaSg) {
156 return XST_NOT_SGDMA;
159 if (InstancePtr->IsStarted != XCOMPONENT_IS_STARTED) {
160 return XST_DEVICE_IS_STOPPED;
164 * Set some descriptor control word defaults (source address increment
165 * and local destination address) and the destination address
166 * (the FIFO). These are the same for every transmit descriptor.
168 BdControl = XBufDescriptor_GetControl(BdPtr);
169 XBufDescriptor_SetControl(BdPtr, BdControl | XEM_DFT_SEND_BD_MASK);
171 XBufDescriptor_SetDestAddress(BdPtr,
172 InstancePtr->BaseAddress +
173 XEM_PFIFO_TXDATA_OFFSET);
176 * Put the descriptor in the send list. The DMA component accesses data
177 * here that can also be modified in interrupt context, so a critical
178 * section is required.
180 XIIF_V123B_GINTR_DISABLE(InstancePtr->BaseAddress);
182 Result = XDmaChannel_PutDescriptor(&InstancePtr->SendChannel, BdPtr);
183 if (Result != XST_SUCCESS) {
184 XIIF_V123B_GINTR_ENABLE(InstancePtr->BaseAddress);
189 * If this is the last buffer in the frame, commit the inserts and start
190 * the DMA engine if necessary
192 if (XBufDescriptor_IsLastControl(BdPtr)) {
193 Result = XDmaChannel_CommitPuts(&InstancePtr->SendChannel);
194 if (Result != XST_SUCCESS) {
195 XIIF_V123B_GINTR_ENABLE(InstancePtr->BaseAddress);
200 * Start the DMA channel. Ignore the return status since we know the
201 * list exists and has at least one entry and we don't care if the
202 * channel is already started. The DMA component accesses data here
203 * that can be modified at interrupt or task levels, so a critical
204 * section is required.
206 (void) XDmaChannel_SgStart(&InstancePtr->SendChannel);
209 XIIF_V123B_GINTR_ENABLE(InstancePtr->BaseAddress);
214 /*****************************************************************************/
217 * Add a descriptor, with an attached empty buffer, into the receive descriptor
218 * list. The buffer attached to the descriptor must be word-aligned. This is
219 * used by the upper layer software during initialization when first setting up
220 * the receive descriptors, and also during reception of frames to replace
221 * filled buffers with empty buffers. This function can be called when the
222 * device is started or stopped. Note that it does start the scatter-gather DMA
223 * engine. Although this is not necessary during initialization, it is not a
224 * problem during initialization because the MAC receiver is not yet started.
226 * The buffer attached to the descriptor must be word-aligned on both the front
227 * end and the back end.
229 * Notification of received frames are done asynchronously through the receive
232 * @param InstancePtr is a pointer to the XEmac instance to be worked on.
233 * @param BdPtr is a pointer to the buffer descriptor that will be added to the
238 * - XST_SUCCESS if a descriptor was successfully returned to the driver
239 * - XST_NOT_SGDMA if the device is not in scatter-gather DMA mode
240 * - XST_DMA_SG_LIST_FULL if the receive descriptor list is full
241 * - XST_DMA_SG_BD_LOCKED if the DMA channel cannot insert the descriptor into
242 * the list because a locked descriptor exists at the insert point.
243 * - XST_DMA_SG_NOTHING_TO_COMMIT if even after inserting a descriptor into the
244 * list, the DMA channel believes there are no new descriptors to commit.
248 * A status that should never be returned from this function, although
249 * the code is set up to handle it, is XST_DMA_SG_NO_LIST. Starting the device
250 * requires a list to be created, and this function requires the device to be
253 ******************************************************************************/
255 XEmac_SgRecv(XEmac * InstancePtr, XBufDescriptor * BdPtr)
260 XASSERT_NONVOID(InstancePtr != NULL);
261 XASSERT_NONVOID(BdPtr != NULL);
262 XASSERT_NONVOID(InstancePtr->IsReady == XCOMPONENT_IS_READY);
265 * Be sure the device is configured for scatter-gather DMA
267 if (!InstancePtr->IsDmaSg) {
268 return XST_NOT_SGDMA;
272 * Set some descriptor control word defaults (destination address increment
273 * and local source address) and the source address (the FIFO). These are
274 * the same for every receive descriptor.
276 BdControl = XBufDescriptor_GetControl(BdPtr);
277 XBufDescriptor_SetControl(BdPtr, BdControl | XEM_DFT_RECV_BD_MASK);
278 XBufDescriptor_SetSrcAddress(BdPtr,
279 InstancePtr->BaseAddress +
280 XEM_PFIFO_RXDATA_OFFSET);
283 * Put the descriptor into the channel's descriptor list and commit.
284 * Although this function is likely called within interrupt context, there
285 * is the possibility that the upper layer software queues it to a task.
286 * In this case, a critical section is needed here to protect shared data
287 * in the DMA component.
289 XIIF_V123B_GINTR_DISABLE(InstancePtr->BaseAddress);
291 Result = XDmaChannel_PutDescriptor(&InstancePtr->RecvChannel, BdPtr);
292 if (Result != XST_SUCCESS) {
293 XIIF_V123B_GINTR_ENABLE(InstancePtr->BaseAddress);
297 Result = XDmaChannel_CommitPuts(&InstancePtr->RecvChannel);
298 if (Result != XST_SUCCESS) {
299 XIIF_V123B_GINTR_ENABLE(InstancePtr->BaseAddress);
304 * Start the DMA channel. Ignore the return status since we know the list
305 * exists and has at least one entry and we don't care if the channel is
306 * already started. The DMA component accesses data here that can be
307 * modified at interrupt or task levels, so a critical section is required.
309 (void) XDmaChannel_SgStart(&InstancePtr->RecvChannel);
311 XIIF_V123B_GINTR_ENABLE(InstancePtr->BaseAddress);
316 /*****************************************************************************/
319 * The interrupt handler for the Ethernet driver when configured with scatter-
322 * Get the interrupt status from the IpIf to determine the source of the
323 * interrupt. The source can be: MAC, Recv Packet FIFO, Send Packet FIFO, Recv
324 * DMA channel, or Send DMA channel. The packet FIFOs only interrupt during
325 * "deadlock" conditions.
327 * @param InstancePtr is a pointer to the XEmac instance that just interrupted.
337 ******************************************************************************/
339 XEmac_IntrHandlerDma(void *InstancePtr)
342 XEmac *EmacPtr = (XEmac *) InstancePtr;
344 EmacPtr->Stats.TotalIntrs++;
347 * Get the interrupt status from the IPIF. There is no clearing of
348 * interrupts in the IPIF. Interrupts must be cleared at the source.
350 IntrStatus = XIIF_V123B_READ_DIPR(EmacPtr->BaseAddress);
353 * See which type of interrupt is being requested, and service it
355 if (IntrStatus & XEM_IPIF_RECV_DMA_MASK) { /* Receive DMA interrupt */
356 EmacPtr->Stats.RecvInterrupts++;
357 HandleDmaRecvIntr(EmacPtr);
360 if (IntrStatus & XEM_IPIF_SEND_DMA_MASK) { /* Send DMA interrupt */
361 EmacPtr->Stats.XmitInterrupts++;
362 HandleDmaSendIntr(EmacPtr);
365 if (IntrStatus & XEM_IPIF_EMAC_MASK) { /* MAC interrupt */
366 EmacPtr->Stats.EmacInterrupts++;
367 HandleEmacDmaIntr(EmacPtr);
370 if (IntrStatus & XEM_IPIF_RECV_FIFO_MASK) { /* Receive FIFO interrupt */
371 EmacPtr->Stats.RecvInterrupts++;
372 XEmac_CheckFifoRecvError(EmacPtr);
375 if (IntrStatus & XEM_IPIF_SEND_FIFO_MASK) { /* Send FIFO interrupt */
376 EmacPtr->Stats.XmitInterrupts++;
377 XEmac_CheckFifoSendError(EmacPtr);
380 if (IntrStatus & XIIF_V123B_ERROR_MASK) {
382 * An error occurred internal to the IPIF. This is more of a debug and
383 * integration issue rather than a production error. Don't do anything
384 * other than clear it, which provides a spot for software to trap
385 * on the interrupt and begin debugging.
387 XIIF_V123B_WRITE_DISR(EmacPtr->BaseAddress,
388 XIIF_V123B_ERROR_MASK);
392 /*****************************************************************************/
395 * Set the packet count threshold for this device. The device must be stopped
396 * before setting the threshold. The packet count threshold is used for interrupt
397 * coalescing, which reduces the frequency of interrupts from the device to the
398 * processor. In this case, the scatter-gather DMA engine only interrupts when
399 * the packet count threshold is reached, instead of interrupting for each packet.
400 * A packet is a generic term used by the scatter-gather DMA engine, and is
401 * equivalent to an Ethernet frame in our case.
403 * @param InstancePtr is a pointer to the XEmac instance to be worked on.
404 * @param Direction indicates the channel, send or receive, from which the
405 * threshold register is read.
406 * @param Threshold is the value of the packet threshold count used during
407 * interrupt coalescing. A value of 0 disables the use of packet threshold
412 * - XST_SUCCESS if the threshold was successfully set
413 * - XST_NOT_SGDMA if the MAC is not configured for scatter-gather DMA
414 * - XST_DEVICE_IS_STARTED if the device has not been stopped
415 * - XST_DMA_SG_COUNT_EXCEEDED if the threshold must be equal to or less than
416 * the number of descriptors in the list
417 * - XST_INVALID_PARAM if the Direction parameter is invalid. Turning on
418 * asserts would also catch this error.
424 ******************************************************************************/
426 XEmac_SetPktThreshold(XEmac * InstancePtr, u32 Direction, u8 Threshold)
428 XASSERT_NONVOID(InstancePtr != NULL);
429 XASSERT_NONVOID(Direction == XEM_SEND || Direction == XEM_RECV);
430 XASSERT_NONVOID(InstancePtr->IsReady == XCOMPONENT_IS_READY);
433 * Be sure device is configured for scatter-gather DMA and has been stopped
435 if (!InstancePtr->IsDmaSg) {
436 return XST_NOT_SGDMA;
439 if (InstancePtr->IsStarted == XCOMPONENT_IS_STARTED) {
440 return XST_DEVICE_IS_STARTED;
444 * Based on the direction, set the packet threshold in the
445 * corresponding DMA channel component. Default to the receive
446 * channel threshold register (if an invalid Direction is passed).
450 return XDmaChannel_SetPktThreshold(&InstancePtr->SendChannel,
454 return XDmaChannel_SetPktThreshold(&InstancePtr->RecvChannel,
458 return XST_INVALID_PARAM;
462 /*****************************************************************************/
465 * Get the value of the packet count threshold for this driver/device. The packet
466 * count threshold is used for interrupt coalescing, which reduces the frequency
467 * of interrupts from the device to the processor. In this case, the
468 * scatter-gather DMA engine only interrupts when the packet count threshold is
469 * reached, instead of interrupting for each packet. A packet is a generic term
470 * used by the scatter-gather DMA engine, and is equivalent to an Ethernet frame
473 * @param InstancePtr is a pointer to the XEmac instance to be worked on.
474 * @param Direction indicates the channel, send or receive, from which the
475 * threshold register is read.
476 * @param ThreshPtr is a pointer to the byte into which the current value of the
477 * packet threshold register will be copied. An output parameter. A value
478 * of 0 indicates the use of packet threshold by the hardware is disabled.
482 * - XST_SUCCESS if the packet threshold was retrieved successfully
483 * - XST_NOT_SGDMA if the MAC is not configured for scatter-gather DMA
484 * - XST_INVALID_PARAM if the Direction parameter is invalid. Turning on
485 * asserts would also catch this error.
491 ******************************************************************************/
493 XEmac_GetPktThreshold(XEmac * InstancePtr, u32 Direction, u8 * ThreshPtr)
495 XASSERT_NONVOID(InstancePtr != NULL);
496 XASSERT_NONVOID(Direction == XEM_SEND || Direction == XEM_RECV);
497 XASSERT_NONVOID(ThreshPtr != NULL);
498 XASSERT_NONVOID(InstancePtr->IsReady == XCOMPONENT_IS_READY);
500 if (!InstancePtr->IsDmaSg) {
501 return XST_NOT_SGDMA;
505 * Based on the direction, return the packet threshold set in the
506 * corresponding DMA channel component. Default to the value in
507 * the receive channel threshold register (if an invalid Direction
513 XDmaChannel_GetPktThreshold(&InstancePtr->SendChannel);
518 XDmaChannel_GetPktThreshold(&InstancePtr->RecvChannel);
522 return XST_INVALID_PARAM;
528 /*****************************************************************************/
531 * Set the packet wait bound timer for this driver/device. The device must be
532 * stopped before setting the timer value. The packet wait bound is used during
533 * interrupt coalescing to trigger an interrupt when not enough packets have been
534 * received to reach the packet count threshold. A packet is a generic term used
535 * by the scatter-gather DMA engine, and is equivalent to an Ethernet frame in
536 * our case. The timer is in milliseconds.
538 * @param InstancePtr is a pointer to the XEmac instance to be worked on.
539 * @param Direction indicates the channel, send or receive, from which the
540 * threshold register is read.
541 * @param TimerValue is the value of the packet wait bound used during interrupt
542 * coalescing. It is in milliseconds in the range 0 - 1023. A value of 0
543 * disables the packet wait bound timer.
547 * - XST_SUCCESS if the packet wait bound was set successfully
548 * - XST_NOT_SGDMA if the MAC is not configured for scatter-gather DMA
549 * - XST_DEVICE_IS_STARTED if the device has not been stopped
550 * - XST_INVALID_PARAM if the Direction parameter is invalid. Turning on
551 * asserts would also catch this error.
557 ******************************************************************************/
559 XEmac_SetPktWaitBound(XEmac * InstancePtr, u32 Direction, u32 TimerValue)
561 XASSERT_NONVOID(InstancePtr != NULL);
562 XASSERT_NONVOID(Direction == XEM_SEND || Direction == XEM_RECV);
563 XASSERT_NONVOID(TimerValue <= XEM_SGDMA_MAX_WAITBOUND);
564 XASSERT_NONVOID(InstancePtr->IsReady == XCOMPONENT_IS_READY);
567 * Be sure device is configured for scatter-gather DMA and has been stopped
569 if (!InstancePtr->IsDmaSg) {
570 return XST_NOT_SGDMA;
573 if (InstancePtr->IsStarted == XCOMPONENT_IS_STARTED) {
574 return XST_DEVICE_IS_STARTED;
578 * Based on the direction, set the packet wait bound in the
579 * corresponding DMA channel component. Default to the receive
580 * channel wait bound register (if an invalid Direction is passed).
584 XDmaChannel_SetPktWaitBound(&InstancePtr->SendChannel,
589 XDmaChannel_SetPktWaitBound(&InstancePtr->RecvChannel,
594 return XST_INVALID_PARAM;
600 /*****************************************************************************/
603 * Get the packet wait bound timer for this driver/device. The packet wait bound
604 * is used during interrupt coalescing to trigger an interrupt when not enough
605 * packets have been received to reach the packet count threshold. A packet is a
606 * generic term used by the scatter-gather DMA engine, and is equivalent to an
607 * Ethernet frame in our case. The timer is in milliseconds.
609 * @param InstancePtr is a pointer to the XEmac instance to be worked on.
610 * @param Direction indicates the channel, send or receive, from which the
611 * threshold register is read.
612 * @param WaitPtr is a pointer to the byte into which the current value of the
613 * packet wait bound register will be copied. An output parameter. Units
614 * are in milliseconds in the range 0 - 1023. A value of 0 indicates the
615 * packet wait bound timer is disabled.
619 * - XST_SUCCESS if the packet wait bound was retrieved successfully
620 * - XST_NOT_SGDMA if the MAC is not configured for scatter-gather DMA
621 * - XST_INVALID_PARAM if the Direction parameter is invalid. Turning on
622 * asserts would also catch this error.
628 ******************************************************************************/
630 XEmac_GetPktWaitBound(XEmac * InstancePtr, u32 Direction, u32 * WaitPtr)
632 XASSERT_NONVOID(InstancePtr != NULL);
633 XASSERT_NONVOID(Direction == XEM_SEND || Direction == XEM_RECV);
634 XASSERT_NONVOID(WaitPtr != NULL);
635 XASSERT_NONVOID(InstancePtr->IsReady == XCOMPONENT_IS_READY);
637 if (!InstancePtr->IsDmaSg) {
638 return XST_NOT_SGDMA;
642 * Based on the direction, return the packet wait bound set in the
643 * corresponding DMA channel component. Default to the value in
644 * the receive channel wait bound register (if an invalid Direction
650 XDmaChannel_GetPktWaitBound(&InstancePtr->SendChannel);
655 XDmaChannel_GetPktWaitBound(&InstancePtr->RecvChannel);
659 return XST_INVALID_PARAM;
665 /*****************************************************************************/
668 * Give the driver the memory space to be used for the scatter-gather DMA
669 * receive descriptor list. This function should only be called once, during
670 * initialization of the Ethernet driver. The memory space must be big enough
671 * to hold some number of descriptors, depending on the needs of the system.
672 * The xemac.h file defines minimum and default numbers of descriptors
673 * which can be used to allocate this memory space.
675 * The memory space must be word-aligned. An assert will occur if asserts are
676 * turned on and the memory is not word-aligned.
678 * @param InstancePtr is a pointer to the XEmac instance to be worked on.
679 * @param MemoryPtr is a pointer to the word-aligned memory.
680 * @param ByteCount is the length, in bytes, of the memory space.
684 * - XST_SUCCESS if the space was initialized successfully
685 * - XST_NOT_SGDMA if the MAC is not configured for scatter-gather DMA
686 * - XST_DMA_SG_LIST_EXISTS if this list space has already been created
690 * If the device is configured for scatter-gather DMA, this function must be
691 * called AFTER the XEmac_Initialize() function because the DMA channel
692 * components must be initialized before the memory space is set.
694 ******************************************************************************/
696 XEmac_SetSgRecvSpace(XEmac * InstancePtr, u32 * MemoryPtr, u32 ByteCount)
698 XASSERT_NONVOID(InstancePtr != NULL);
699 XASSERT_NONVOID(MemoryPtr != NULL);
700 XASSERT_NONVOID(ByteCount != 0);
701 XASSERT_NONVOID(InstancePtr->IsReady == XCOMPONENT_IS_READY);
703 if (!InstancePtr->IsDmaSg) {
704 return XST_NOT_SGDMA;
707 return XDmaChannel_CreateSgList(&InstancePtr->RecvChannel, MemoryPtr,
711 /*****************************************************************************/
714 * Give the driver the memory space to be used for the scatter-gather DMA
715 * transmit descriptor list. This function should only be called once, during
716 * initialization of the Ethernet driver. The memory space must be big enough
717 * to hold some number of descriptors, depending on the needs of the system.
718 * The xemac.h file defines minimum and default numbers of descriptors
719 * which can be used to allocate this memory space.
721 * The memory space must be word-aligned. An assert will occur if asserts are
722 * turned on and the memory is not word-aligned.
724 * @param InstancePtr is a pointer to the XEmac instance to be worked on.
725 * @param MemoryPtr is a pointer to the word-aligned memory.
726 * @param ByteCount is the length, in bytes, of the memory space.
730 * - XST_SUCCESS if the space was initialized successfully
731 * - XST_NOT_SGDMA if the MAC is not configured for scatter-gather DMA
732 * - XST_DMA_SG_LIST_EXISTS if this list space has already been created
736 * If the device is configured for scatter-gather DMA, this function must be
737 * called AFTER the XEmac_Initialize() function because the DMA channel
738 * components must be initialized before the memory space is set.
740 ******************************************************************************/
742 XEmac_SetSgSendSpace(XEmac * InstancePtr, u32 * MemoryPtr, u32 ByteCount)
744 XASSERT_NONVOID(InstancePtr != NULL);
745 XASSERT_NONVOID(MemoryPtr != NULL);
746 XASSERT_NONVOID(ByteCount != 0);
747 XASSERT_NONVOID(InstancePtr->IsReady == XCOMPONENT_IS_READY);
749 if (!InstancePtr->IsDmaSg) {
750 return XST_NOT_SGDMA;
753 return XDmaChannel_CreateSgList(&InstancePtr->SendChannel, MemoryPtr,
757 /*****************************************************************************/
760 * Set the callback function for handling received frames in scatter-gather DMA
761 * mode. The upper layer software should call this function during
762 * initialization. The callback is called once per frame received. The head of
763 * a descriptor list is passed in along with the number of descriptors in the
764 * list. Before leaving the callback, the upper layer software should attach a
765 * new buffer to each descriptor in the list.
767 * The callback is invoked by the driver within interrupt context, so it needs
768 * to do its job quickly. Sending the received frame up the protocol stack
769 * should be done at task-level. If there are other potentially slow operations
770 * within the callback, these too should be done at task-level.
772 * @param InstancePtr is a pointer to the XEmac instance to be worked on.
773 * @param CallBackRef is a reference pointer to be passed back to the adapter in
774 * the callback. This helps the adapter correlate the callback to a
776 * @param FuncPtr is the pointer to the callback function.
786 ******************************************************************************/
788 XEmac_SetSgRecvHandler(XEmac * InstancePtr, void *CallBackRef,
789 XEmac_SgHandler FuncPtr)
792 * Asserted IsDmaSg here instead of run-time check because there is really
793 * no ill-effects of setting these when not configured for scatter-gather.
795 XASSERT_VOID(InstancePtr != NULL);
796 XASSERT_VOID(FuncPtr != NULL);
797 XASSERT_VOID(InstancePtr->IsDmaSg);
798 XASSERT_VOID(InstancePtr->IsReady == XCOMPONENT_IS_READY);
800 InstancePtr->SgRecvHandler = FuncPtr;
801 InstancePtr->SgRecvRef = CallBackRef;
804 /*****************************************************************************/
807 * Set the callback function for handling confirmation of transmitted frames in
808 * scatter-gather DMA mode. The upper layer software should call this function
809 * during initialization. The callback is called once per frame sent. The head
810 * of a descriptor list is passed in along with the number of descriptors in
811 * the list. The callback is responsible for freeing buffers attached to these
814 * The callback is invoked by the driver within interrupt context, so it needs
815 * to do its job quickly. If there are potentially slow operations within the
816 * callback, these should be done at task-level.
818 * @param InstancePtr is a pointer to the XEmac instance to be worked on.
819 * @param CallBackRef is a reference pointer to be passed back to the adapter in
820 * the callback. This helps the adapter correlate the callback to a
822 * @param FuncPtr is the pointer to the callback function.
832 ******************************************************************************/
834 XEmac_SetSgSendHandler(XEmac * InstancePtr, void *CallBackRef,
835 XEmac_SgHandler FuncPtr)
838 * Asserted IsDmaSg here instead of run-time check because there is really
839 * no ill-effects of setting these when not configured for scatter-gather.
841 XASSERT_VOID(InstancePtr != NULL);
842 XASSERT_VOID(FuncPtr != NULL);
843 XASSERT_VOID(InstancePtr->IsDmaSg);
844 XASSERT_VOID(InstancePtr->IsReady == XCOMPONENT_IS_READY);
846 InstancePtr->SgSendHandler = FuncPtr;
847 InstancePtr->SgSendRef = CallBackRef;
850 /*****************************************************************************/
853 * Handle an interrupt from the DMA receive channel. DMA interrupts are:
855 * - DMA error. DMA encountered a bus error or timeout. This is a fatal error
856 * that requires reset of the channel. The driver calls the error handler
857 * of the upper layer software with an error code indicating the device should
859 * - Packet count threshold reached. For scatter-gather operations, indicates
860 * the threshold for the number of packets not serviced by software has been
861 * reached. The driver behaves as follows:
862 * - Get the value of the packet counter, which tells us how many packets
863 * are ready to be serviced
865 * - For each descriptor, remove it from the scatter-gather list
866 * - Check for the last descriptor in the frame, and if set
867 * - Bump frame statistics
868 * - Call the scatter-gather receive callback function
869 * - Decrement the packet counter by one
870 * Note that there are no receive errors reported in the status word of
871 * the buffer descriptor. If receive errors occur, the MAC drops the
872 * packet, and we only find out about the errors through various error
874 * - Packet wait bound reached. For scatter-gather, indicates the time to wait
875 * for the next packet has expired. The driver follows the same logic as when
876 * the packet count threshold interrupt is received.
877 * - Scatter-gather end acknowledge. Hardware has reached the end of the
878 * descriptor list. The driver follows the same logic as when the packet count
879 * threshold interrupt is received. In addition, the driver restarts the DMA
880 * scatter-gather channel in case there are newly inserted descriptors.
882 * @param InstancePtr is a pointer to the XEmac instance to be worked on.
886 * Although the function returns void, there are asynchronous errors that can
887 * be generated (by calling the ErrorHandler) from this function. These are:
888 * - XST_DMA_SG_LIST_EMPTY indicates we tried to get a buffer descriptor from the
889 * DMA channel, but there was not one ready for software.
890 * - XST_DMA_ERROR indicates a DMA bus error or timeout occurred. This is a fatal
891 * error that requires reset.
897 ******************************************************************************/
899 HandleDmaRecvIntr(XEmac * InstancePtr)
904 * Read the interrupt status
906 IntrStatus = XDmaChannel_GetIntrStatus(&InstancePtr->RecvChannel);
909 * For packet threshold or wait bound interrupts, process desciptors. Also
910 * process descriptors on a SG end acknowledgement, which means the end of
911 * the descriptor list has been reached by the hardware. For receive, this
912 * is potentially trouble since it means the descriptor list is full,
913 * unless software can process enough packets quickly enough so the
914 * hardware has room to put new packets.
916 if (IntrStatus & (XDC_IXR_PKT_THRESHOLD_MASK |
917 XDC_IXR_PKT_WAIT_BOUND_MASK | XDC_IXR_SG_END_MASK)) {
924 XBufDescriptor *FirstBdPtr;
925 XBufDescriptor *BdPtr;
928 * Get the number of unserviced packets
930 NumFrames = XDmaChannel_GetPktCount(&InstancePtr->RecvChannel);
932 for (NumProcessed = 0; NumProcessed < NumFrames; NumProcessed++) {
939 * For each packet, get the descriptor from the list. On the
940 * last one in the frame, make the callback to the upper layer.
944 XDmaChannel_GetDescriptor(&InstancePtr->
947 if (Result != XST_SUCCESS) {
949 * An error getting a buffer descriptor from the list.
950 * This should not happen, but if it does, report it to
951 * the error callback and break out of the loops to service
954 InstancePtr->ErrorHandler(InstancePtr->
961 * Keep a pointer to the first descriptor in the list, as it
962 * will be passed to the upper layers in a bit. By the fact
963 * that we received this packet means no errors occurred, so
964 * no need to check the device status word for errors.
966 if (FirstBdPtr == NULL) {
970 NumBytes += XBufDescriptor_GetLength(BdPtr);
973 * Check to see if this is the last descriptor in the frame,
974 * and if so, set the IsLast flag to get out of the loop.
976 if (XBufDescriptor_IsLastStatus(BdPtr)) {
981 * Bump the number of buffers in this packet
985 } /* end while loop */
988 * Check for error that occurred inside the while loop, and break
989 * out of the for loop if there was one so other interrupts can
992 if (Result != XST_SUCCESS) {
996 InstancePtr->Stats.RecvFrames++;
997 InstancePtr->Stats.RecvBytes += NumBytes;
1000 * Make the callback to the upper layers, passing it the first
1001 * descriptor in the packet and the number of descriptors in the
1004 InstancePtr->SgRecvHandler(InstancePtr->SgRecvRef,
1005 FirstBdPtr, NumBuffers);
1008 * Decrement the packet count register to reflect the fact we
1009 * just processed a packet
1011 XDmaChannel_DecrementPktCount(&InstancePtr->
1014 } /* end for loop */
1017 * If the interrupt was an end-ack, check the descriptor list again to
1018 * see if it is empty. If not, go ahead and restart the scatter-gather
1019 * channel. This is to fix a possible race condition where, on receive,
1020 * the driver attempted to start a scatter-gather channel that was
1021 * already started, which resulted in no action from the XDmaChannel
1022 * component. But, just after the XDmaChannel component saw that the
1023 * hardware was already started, the hardware stopped because it
1024 * reached the end of the list. In that case, this interrupt is
1025 * generated and we can restart the hardware here.
1027 if (IntrStatus & XDC_IXR_SG_END_MASK) {
1029 * Ignore the return status since we know the list exists and we
1030 * don't care if the list is empty or the channel is already started.
1032 (void) XDmaChannel_SgStart(&InstancePtr->RecvChannel);
1037 * Check for DMA errors and call the error callback function if an error
1038 * occurred (DMA bus or timeout error), which should result in a reset of
1039 * the device by the upper layer software.
1041 if (IntrStatus & XDC_IXR_DMA_ERROR_MASK) {
1042 InstancePtr->Stats.DmaErrors++;
1043 InstancePtr->ErrorHandler(InstancePtr->ErrorRef, XST_DMA_ERROR);
1047 * All interrupts are handled, so acknowledge (clear) the interrupts
1048 * by writing the value read above back to the status register. The
1049 * packet count interrupt must be acknowledged after the decrement,
1050 * otherwise it will come right back.
1052 XDmaChannel_SetIntrStatus(&InstancePtr->RecvChannel, IntrStatus);
1055 /*****************************************************************************/
1058 * Handle an interrupt from the DMA send channel. DMA interrupts are:
1060 * - DMA error. DMA encountered a bus error or timeout. This is a fatal error
1061 * that requires reset of the channel. The driver calls the error handler
1062 * of the upper layer software with an error code indicating the device should
1064 * - Packet count threshold reached. For scatter-gather operations, indicates
1065 * the threshold for the number of packets not serviced by software has been
1066 * reached. The driver behaves as follows:
1067 * - Get the value of the packet counter, which tells us how many packets
1068 * are ready to be serviced
1070 * - For each descriptor, remove it from the scatter-gather list
1071 * - Check for the last descriptor in the frame, and if set
1072 * - Bump frame statistics
1073 * - Call the scatter-gather receive callback function
1074 * - Decrement the packet counter by one
1075 * Note that there are no receive errors reported in the status word of
1076 * the buffer descriptor. If receive errors occur, the MAC drops the
1077 * packet, and we only find out about the errors through various error
1079 * - Packet wait bound reached. For scatter-gather, indicates the time to wait
1080 * for the next packet has expired. The driver follows the same logic as when
1081 * the packet count threshold interrupt is received.
1082 * - Scatter-gather end acknowledge. Hardware has reached the end of the
1083 * descriptor list. The driver follows the same logic as when the packet count
1084 * threshold interrupt is received. In addition, the driver restarts the DMA
1085 * scatter-gather channel in case there are newly inserted descriptors.
1087 * @param InstancePtr is a pointer to the XEmac instance to be worked on.
1091 * Although the function returns void, there are asynchronous errors
1092 * that can be generated from this function. These are:
1093 * - XST_DMA_SG_LIST_EMPTY indicates we tried to get a buffer descriptor from
1094 * the DMA channel, but there was not one ready for software.
1095 * - XST_DMA_ERROR indicates a DMA bus error or timeout occurred. This is a
1096 * fatal error that requires reset.
1102 ******************************************************************************/
1104 HandleDmaSendIntr(XEmac * InstancePtr)
1109 * Read the interrupt status
1111 IntrStatus = XDmaChannel_GetIntrStatus(&InstancePtr->SendChannel);
1114 * For packet threshold or wait bound interrupt, process descriptors. Also
1115 * process descriptors on a SG end acknowledgement, which means the end of
1116 * the descriptor list has been reached by the hardware. For transmit,
1117 * this is a normal condition during times of light traffic. In fact, the
1118 * wait bound interrupt may be masked for transmit since the end-ack would
1119 * always occur before the wait bound expires.
1121 if (IntrStatus & (XDC_IXR_PKT_THRESHOLD_MASK |
1122 XDC_IXR_PKT_WAIT_BOUND_MASK | XDC_IXR_SG_END_MASK)) {
1129 XBufDescriptor *FirstBdPtr;
1130 XBufDescriptor *BdPtr;
1133 * Get the number of unserviced packets
1135 NumFrames = XDmaChannel_GetPktCount(&InstancePtr->SendChannel);
1137 for (NumProcessed = 0; NumProcessed < NumFrames; NumProcessed++) {
1144 * For each frame, traverse the descriptor list and look for
1145 * errors. On the last one in the frame, make the callback.
1149 XDmaChannel_GetDescriptor(&InstancePtr->
1152 if (Result != XST_SUCCESS) {
1154 * An error getting a buffer descriptor from the list.
1155 * This should not happen, but if it does, report it to
1156 * the error callback and break out of the loops to service
1159 InstancePtr->ErrorHandler(InstancePtr->
1166 * Keep a pointer to the first descriptor in the list and
1167 * check the device status for errors. The device status is
1168 * only available in the first descriptor of a packet.
1170 if (FirstBdPtr == NULL) {
1176 XBufDescriptor_GetDeviceStatus
1179 XEM_TSR_EXCESS_DEFERRAL_MASK) {
1181 XmitExcessDeferral++;
1185 XEM_TSR_LATE_COLLISION_MASK) {
1187 XmitLateCollisionErrors++;
1191 NumBytes += XBufDescriptor_GetLength(BdPtr);
1194 * Check to see if this is the last descriptor in the frame,
1195 * and if so, set the IsLast flag to get out of the loop. The
1196 * transmit channel must check the last bit in the control
1197 * word, not the status word (the DMA engine does not update
1198 * the last bit in the status word for the transmit direction).
1200 if (XBufDescriptor_IsLastControl(BdPtr)) {
1205 * Bump the number of buffers in this packet
1209 } /* end while loop */
1212 * Check for error that occurred inside the while loop, and break
1213 * out of the for loop if there was one so other interrupts can
1216 if (Result != XST_SUCCESS) {
1220 InstancePtr->Stats.XmitFrames++;
1221 InstancePtr->Stats.XmitBytes += NumBytes;
1224 * Make the callback to the upper layers, passing it the first
1225 * descriptor in the packet and the number of descriptors in the
1228 InstancePtr->SgSendHandler(InstancePtr->SgSendRef,
1229 FirstBdPtr, NumBuffers);
1232 * Decrement the packet count register to reflect the fact we
1233 * just processed a packet
1235 XDmaChannel_DecrementPktCount(&InstancePtr->
1238 } /* end for loop */
1241 * If the interrupt was an end-ack, check the descriptor list again to
1242 * see if it is empty. If not, go ahead and restart the scatter-gather
1243 * channel. This is to fix a possible race condition where, on transmit,
1244 * the driver attempted to start a scatter-gather channel that was
1245 * already started, which resulted in no action from the XDmaChannel
1246 * component. But, just after the XDmaChannel component saw that the
1247 * hardware was already started, the hardware stopped because it
1248 * reached the end of the list. In that case, this interrupt is
1249 * generated and we can restart the hardware here.
1251 if (IntrStatus & XDC_IXR_SG_END_MASK) {
1253 * Ignore the return status since we know the list exists and we
1254 * don't care if the list is empty or the channel is already started.
1256 (void) XDmaChannel_SgStart(&InstancePtr->SendChannel);
1261 * Check for DMA errors and call the error callback function if an error
1262 * occurred (DMA bus or timeout error), which should result in a reset of
1263 * the device by the upper layer software.
1265 if (IntrStatus & XDC_IXR_DMA_ERROR_MASK) {
1266 InstancePtr->Stats.DmaErrors++;
1267 InstancePtr->ErrorHandler(InstancePtr->ErrorRef, XST_DMA_ERROR);
1271 * All interrupts are handled, so acknowledge (clear) the interrupts
1272 * by writing the value read above back to the status register. The
1273 * packet count interrupt must be acknowledged after the decrement,
1274 * otherwise it will come right back.
1276 XDmaChannel_SetIntrStatus(&InstancePtr->SendChannel, IntrStatus);
1279 /*****************************************************************************/
1282 * Handle an interrupt from the Ethernet MAC when configured with scatter-gather
1283 * DMA. The only interrupts handled in this case are errors.
1285 * @param InstancePtr is a pointer to the XEmac instance to be worked on.
1295 ******************************************************************************/
1297 HandleEmacDmaIntr(XEmac * InstancePtr)
1302 * When configured with DMA, the EMAC generates interrupts only when errors
1303 * occur. We clear the interrupts immediately so that any latched status
1304 * interrupt bits will reflect the true status of the device, and so any
1305 * pulsed interrupts (non-status) generated during the Isr will not be lost.
1307 IntrStatus = XIIF_V123B_READ_IISR(InstancePtr->BaseAddress);
1308 XIIF_V123B_WRITE_IISR(InstancePtr->BaseAddress, IntrStatus);
1311 * Check the MAC for errors
1313 XEmac_CheckEmacError(InstancePtr, IntrStatus);