1 /* $Id: xdma_channel_sg.c,v 1.6 2003/02/03 19:50:33 moleres 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 OBTAINING
18 * ANY THIRD PARTY 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 hardware products are not intended for use in life support
27 * appliances, devices, or systems. Use in such applications is
28 * expressly prohibited.
31 * (c) Copyright 2002-2004 Xilinx Inc.
32 * All rights reserved.
35 * You should have received a copy of the GNU General Public License along
36 * with this program; if not, write to the Free Software Foundation, Inc.,
37 * 675 Mass Ave, Cambridge, MA 02139, USA.
45 * This file contains the implementation of the XDmaChannel component which is
46 * related to scatter gather operations.
48 * Scatter Gather Operations
50 * The DMA channel may support scatter gather operations. A scatter gather
51 * operation automates the DMA channel such that multiple buffers can be
52 * sent or received with minimal software interaction with the hardware. Buffer
53 * descriptors, contained in the XBufDescriptor component, are used by the
54 * scatter gather operations of the DMA channel to describe the buffers to be
57 * Scatter Gather List Operations
59 * A scatter gather list may be supported by each DMA channel. The scatter
60 * gather list allows buffer descriptors to be put into the list by a device
61 * driver which requires scatter gather. The hardware processes the buffer
62 * descriptors which are contained in the list and modifies the buffer
63 * descriptors to reflect the status of the DMA operations. The device driver
64 * is notified by interrupt that specific DMA events occur including scatter
65 * gather events. The device driver removes the completed buffer descriptors
66 * from the scatter gather list to evaluate the status of each DMA operation.
68 * The scatter gather list is created and buffer descriptors are inserted into
69 * the list. Buffer descriptors are never removed from the list after it's
70 * creation such that a put operation copies from a temporary buffer descriptor
71 * to a buffer descriptor in the list. Get operations don't copy from the list
72 * to a temporary, but return a pointer to the buffer descriptor in the list.
73 * A buffer descriptor in the list may be locked to prevent it from being
74 * overwritten by a put operation. This allows the device driver to get a
75 * descriptor from a scatter gather list and prevent it from being overwritten
76 * until the buffer associated with the buffer descriptor has been processed.
78 * The get and put functions only operate on the list and are asynchronous from
79 * the hardware which may be using the list of descriptors. This is important
80 * because there are no checks in the get and put functions to ensure that the
81 * hardware has processed the descriptors. This must be handled by the driver
82 * using the DMA scatter gather channel through the use of the other functions.
83 * When a scatter gather operation is started, the start function does ensure
84 * that the descriptor to start has not already been processed by the hardware
85 * and is not the first of a series of descriptors that have not been committed
88 * Descriptors are put into the list but not marked as ready to use by the
89 * hardware until a commit operation is done. This allows multiple descriptors
90 * which may contain a single packet of information for a protocol to be
91 * guaranteed not to cause any underflow conditions during transmission. The
92 * hardware design only allows descriptors to cause it to stop after a descriptor
93 * has been processed rather than before it is processed. A series of
94 * descriptors are put into the list followed by a commit operation, or each
95 * descriptor may be commited. A commit operation is performed by changing a
96 * single descriptor, the first of the series of puts, to indicate that the
97 * hardware may now use all descriptors after it. The last descriptor in the
98 * list is always set to cause the hardware to stop after it is processed.
100 * Typical Scatter Gather Processing
102 * The following steps illustrate the typical processing to use the
103 * scatter gather features of a DMA channel.
105 * 1. Create a scatter gather list for the DMA channel which puts empty buffer
106 * descriptors into the list.
107 * 2. Create buffer descriptors which describe the buffers to be filled with
108 * receive data or the buffers which contain data to be sent.
109 * 3. Put buffer descriptors into the DMA channel scatter list such that scatter
110 * gather operations are requested.
111 * 4. Commit the buffer descriptors in the list such that they are ready to be
112 * used by the DMA channel hardware.
113 * 5. Start the scatter gather operations of the DMA channel.
114 * 6. Process any interrupts which occur as a result of the scatter gather
115 * operations or poll the DMA channel to determine the status. This may
116 * be accomplished by getting the packet count for the channel and then
117 * getting the appropriate number of descriptors from the list for that
120 * Minimizing Interrupts
122 * The Scatter Gather operating mode is designed to reduce the amount of CPU
123 * throughput necessary to manage the hardware for devices. A key to the CPU
124 * throughput is the number and rate of interrupts that the CPU must service.
125 * Devices with higher data rates can cause larger numbers of interrupts and
126 * higher frequency interrupts. Ideally the number of interrupts can be reduced
127 * by only generating an interrupt when a specific amount of data has been
128 * received from the interface. This design suffers from a lack of interrupts
129 * when the amount of data received is less than the specified amount of data
130 * to generate an interrupt. In order to help minimize the number of interrupts
131 * which the CPU must service, an algorithm referred to as "interrupt coalescing"
134 * Interrupt Coalescing
136 * The principle of interrupt coalescing is to wait before generating an
137 * interrupt until a certain number of packets have been received or sent. An
138 * interrupt is also generated if a smaller number of packets have been received
139 * followed by a certain period of time with no packet reception. This is a
140 * trade-off of latency for bandwidth and is accomplished using several
141 * mechanisms of the hardware including a counter for packets received or
142 * transmitted and a packet timer. These two hardware mechanisms work in
143 * combination to allow a reduction in the number of interrupts processed by the
144 * CPU for packet reception.
146 * Unserviced Packet Count
148 * The purpose of the packet counter is to count the number of packets received
149 * or transmitted and provide an interrupt when a specific number of packets
150 * have been processed by the hardware. An interrupt is generated whenever the
151 * counter is greater than or equal to the Packet Count Threshold. This counter
152 * contains an accurate count of the number of packets that the hardware has
153 * processed, either received or transmitted, and the software has not serviced.
155 * The packet counter allows the number of interrupts to be reduced by waiting
156 * to generate an interrupt until enough packets are received. For packet
157 * reception, packet counts of less than the number to generate an interrupt
158 * would not be serviced without the addition of a packet timer. This counter is
159 * continuously updated by the hardware, not latched to the value at the time
160 * the interrupt occurred.
162 * The packet counter can be used within the interrupt service routine for the
163 * device to reduce the number of interrupts. The interrupt service routine
164 * loops while performing processing for each packet which has been received or
165 * transmitted and decrements the counter by a specified value. At the same time,
166 * the hardware is possibly continuing to receive or transmit more packets such
167 * that the software may choose, based upon the value in the packet counter, to
168 * remain in the interrupt service routine rather than exiting and immediately
169 * returning. This feature should be used with caution as reducing the number of
170 * interrupts is beneficial, but unbounded interrupt processing is not desirable.
172 * Since the hardware may be incrementing the packet counter simultaneously
173 * with the software decrementing the counter, there is a need for atomic
174 * operations. The hardware ensures that the operation is atomic such that
175 * simultaneous accesses are properly handled.
179 * The purpose of the packet wait bound is to augment the unserviced packet
180 * count. Whenever there is no pending interrupt for the channel and the
181 * unserviced packet count is non-zero, a timer starts counting timeout at the
182 * value contained the the packet wait bound register. If the timeout is
183 * reached, an interrupt is generated such that the software may service the
184 * data which was buffered.
188 * Special Test Conditions:
190 * The scatter gather list processing must be thoroughly tested if changes are
191 * made. Testing should include putting and committing single descriptors and
192 * putting multiple descriptors followed by a single commit. There are some
193 * conditions in the code which handle the exception conditions.
195 * The Put Pointer points to the next location in the descriptor list to copy
196 * in a new descriptor. The Get Pointer points to the next location in the
197 * list to get a descriptor from. The Get Pointer only allows software to
198 * have a traverse the list after the hardware has finished processing some
199 * number of descriptors. The Commit Pointer points to the descriptor in the
200 * list which is to be committed. It is also used to determine that no
201 * descriptor is waiting to be commited (NULL). The Last Pointer points to
202 * the last descriptor that was put into the list. It typically points
203 * to the previous descriptor to the one pointed to by the Put Pointer.
204 * Comparisons are done between these pointers to determine when the following
205 * special conditions exist.
207 * Single Put And Commit
209 * The buffer descriptor is ready to be used by the hardware so it is important
210 * for the descriptor to not appear to be waiting to be committed. The commit
211 * pointer is reset when a commit is done indicating there are no descriptors
212 * waiting to be committed. In all cases but this one, the descriptor is
213 * changed to cause the hardware to go to the next descriptor after processing
214 * this one. But in this case, this is the last descriptor in the list such
215 * that it must not be changed.
217 * 3 Or More Puts And Commit
219 * A series of 3 or more puts followed by a single commit is different in that
220 * only the 1st descriptor put into the list is changed when the commit is done.
221 * This requires each put starting on the 3rd to change the previous descriptor
222 * so that it allows the hardware to continue to the next descriptor in the list.
224 * The 1st Put Following A Commit
226 * The commit caused the commit pointer to be NULL indicating that there are no
227 * descriptors waiting to be committed. It is necessary for the next put to set
228 * the commit pointer so that a commit must follow the put for the hardware to
229 * use the descriptor.
232 * MODIFICATION HISTORY:
234 * Ver Who Date Changes
235 * ----- ---- -------- ------------------------------------------------------
236 * 1.00a rpm 02/03/03 Removed the XST_DMA_SG_COUNT_EXCEEDED return code
237 * from SetPktThreshold.
240 ******************************************************************************/
242 /***************************** Include Files *********************************/
244 #include "xdma_channel.h"
245 #include "xbasic_types.h"
247 #include "xbuf_descriptor.h"
250 /************************** Constant Definitions *****************************/
252 #define XDC_SWCR_SG_ENABLE_MASK 0x80000000UL /* scatter gather enable */
254 /**************************** Type Definitions *******************************/
256 /***************** Macros (Inline Functions) Definitions *********************/
258 /* the following macro copies selected fields of a buffer descriptor to another
259 * buffer descriptor, this was provided by the buffer descriptor component but
260 * was moved here since it is only used internally to this component and since
261 * it does not copy all fields
263 #define CopyBufferDescriptor(InstancePtr, DestinationPtr) \
265 *((u32 *)DestinationPtr + XBD_CONTROL_OFFSET) = \
266 *((u32 *)InstancePtr + XBD_CONTROL_OFFSET); \
267 *((u32 *)DestinationPtr + XBD_SOURCE_OFFSET) = \
268 *((u32 *)InstancePtr + XBD_SOURCE_OFFSET); \
269 *((u32 *)DestinationPtr + XBD_DESTINATION_OFFSET) = \
270 *((u32 *)InstancePtr + XBD_DESTINATION_OFFSET); \
271 *((u32 *)DestinationPtr + XBD_LENGTH_OFFSET) = \
272 *((u32 *)InstancePtr + XBD_LENGTH_OFFSET); \
273 *((u32 *)DestinationPtr + XBD_STATUS_OFFSET) = \
274 *((u32 *)InstancePtr + XBD_STATUS_OFFSET); \
275 *((u32 *)DestinationPtr + XBD_DEVICE_STATUS_OFFSET) = \
276 *((u32 *)InstancePtr + XBD_DEVICE_STATUS_OFFSET); \
277 *((u32 *)DestinationPtr + XBD_ID_OFFSET) = \
278 *((u32 *)InstancePtr + XBD_ID_OFFSET); \
279 *((u32 *)DestinationPtr + XBD_FLAGS_OFFSET) = \
280 *((u32 *)InstancePtr + XBD_FLAGS_OFFSET); \
281 *((u32 *)DestinationPtr + XBD_RQSTED_LENGTH_OFFSET) = \
282 *((u32 *)InstancePtr + XBD_RQSTED_LENGTH_OFFSET); \
285 /************************** Variable Definitions *****************************/
287 /************************** Function Prototypes ******************************/
289 /******************************************************************************
293 * XDmaChannel_SgStart
297 * This function starts a scatter gather operation for a scatter gather
298 * DMA channel. The first buffer descriptor in the buffer descriptor list
299 * will be started with the scatter gather operation. A scatter gather list
300 * should have previously been created for the DMA channel and buffer
301 * descriptors put into the scatter gather list such that there are scatter
302 * operations ready to be performed.
306 * InstancePtr contains a pointer to the DMA channel to operate on. The DMA
307 * channel should be configured to use scatter gather in order for this function
312 * A status containing XST_SUCCESS if scatter gather was started successfully
313 * for the DMA channel.
315 * A value of XST_DMA_SG_NO_LIST indicates the scatter gather list has not
318 * A value of XST_DMA_SG_LIST_EMPTY indicates scatter gather was not started
319 * because the scatter gather list of the DMA channel does not contain any
320 * buffer descriptors that are ready to be processed by the hardware.
322 * A value of XST_DMA_SG_IS_STARTED indicates scatter gather was not started
323 * because the scatter gather was not stopped, but was already started.
325 * A value of XST_DMA_SG_BD_NOT_COMMITTED indicates the buffer descriptor of
326 * scatter gather list which was to be started is not committed to the list.
327 * This status is more likely if this function is being called from an ISR
328 * and non-ISR processing is putting descriptors into the list.
330 * A value of XST_DMA_SG_NO_DATA indicates that the buffer descriptor of the
331 * scatter gather list which was to be started had already been used by the
332 * hardware for a DMA transfer that has been completed.
336 * It is the responsibility of the caller to get all the buffer descriptors
337 * after performing a stop operation and before performing a start operation.
338 * If buffer descriptors are not retrieved between stop and start operations,
339 * buffer descriptors may be processed by the hardware more than once.
341 ******************************************************************************/
343 XDmaChannel_SgStart(XDmaChannel * InstancePtr)
346 XBufDescriptor *LastDescriptorPtr;
348 /* assert to verify input arguments */
350 XASSERT_NONVOID(InstancePtr != NULL);
351 XASSERT_NONVOID(InstancePtr->IsReady == XCOMPONENT_IS_READY);
353 /* if a scatter gather list has not been created yet, return a status */
355 if (InstancePtr->TotalDescriptorCount == 0) {
356 return XST_DMA_SG_NO_LIST;
359 /* if the scatter gather list exists but is empty then return a status */
361 if (XDmaChannel_IsSgListEmpty(InstancePtr)) {
362 return XST_DMA_SG_LIST_EMPTY;
365 /* if scatter gather is busy for the DMA channel, return a status because
366 * restarting it could lose data
369 Register = XIo_In32(InstancePtr->RegBaseAddress + XDC_DMAS_REG_OFFSET);
370 if (Register & XDC_DMASR_SG_BUSY_MASK) {
371 return XST_DMA_SG_IS_STARTED;
374 /* get the address of the last buffer descriptor which the DMA hardware
375 * finished processing
378 (XBufDescriptor *) XIo_In32(InstancePtr->RegBaseAddress +
381 /* setup the first buffer descriptor that will be sent when the scatter
382 * gather channel is enabled, this is only necessary one time since
383 * the BDA register of the channel maintains the last buffer descriptor
386 if (LastDescriptorPtr == NULL) {
387 XIo_Out32(InstancePtr->RegBaseAddress + XDC_BDA_REG_OFFSET,
388 (u32) InstancePtr->GetPtr);
390 XBufDescriptor *NextDescriptorPtr;
392 /* get the next descriptor to be started, if the status indicates it
393 * hasn't already been used by the h/w, then it's OK to start it,
394 * s/w sets the status of each descriptor to busy and then h/w clears
395 * the busy when it is complete
398 XBufDescriptor_GetNextPtr(LastDescriptorPtr);
400 if ((XBufDescriptor_GetStatus(NextDescriptorPtr) &
401 XDC_DMASR_BUSY_MASK) == 0) {
402 return XST_DMA_SG_NO_DATA;
404 /* don't start the DMA SG channel if the descriptor to be processed
405 * by h/w is to be committed by the s/w, this function can be called
406 * such that it interrupts a thread that was putting into the list
408 if (NextDescriptorPtr == InstancePtr->CommitPtr) {
409 return XST_DMA_SG_BD_NOT_COMMITTED;
413 /* start the scatter gather operation by clearing the stop bit in the
414 * control register and setting the enable bit in the s/w control register,
415 * both of these are necessary to cause it to start, right now the order of
416 * these statements is important, the software control register should be
417 * set 1st. The other order can cause the CPU to have a loss of sync
418 * because it cannot read/write the register while the DMA operation is
422 Register = XIo_In32(InstancePtr->RegBaseAddress + XDC_SWCR_REG_OFFSET);
424 XIo_Out32(InstancePtr->RegBaseAddress + XDC_SWCR_REG_OFFSET,
425 Register | XDC_SWCR_SG_ENABLE_MASK);
427 Register = XIo_In32(InstancePtr->RegBaseAddress + XDC_DMAC_REG_OFFSET);
429 XIo_Out32(InstancePtr->RegBaseAddress + XDC_DMAC_REG_OFFSET,
430 Register & ~XDC_DMACR_SG_DISABLE_MASK);
432 /* indicate the DMA channel scatter gather operation was started
438 /******************************************************************************
446 * This function stops a scatter gather operation for a scatter gather
447 * DMA channel. This function starts the process of stopping a scatter
448 * gather operation that is in progress and waits for the stop to be completed.
449 * Since it waits for the operation to stopped before returning, this function
450 * could take an amount of time relative to the size of the DMA scatter gather
451 * operation which is in progress. The scatter gather list of the DMA channel
452 * is not modified by this function such that starting the scatter gather
453 * channel after stopping it will cause it to resume. This operation is
454 * considered to be a graceful stop in that the scatter gather operation
455 * completes the current buffer descriptor before stopping.
457 * If the interrupt is enabled, an interrupt will be generated when the
458 * operation is stopped and the caller is responsible for handling the
463 * InstancePtr contains a pointer to the DMA channel to operate on. The DMA
464 * channel should be configured to use scatter gather in order for this function
467 * BufDescriptorPtr is also a return value which contains a pointer to the
468 * buffer descriptor which the scatter gather operation completed when it
473 * A status containing XST_SUCCESS if scatter gather was stopped successfully
474 * for the DMA channel.
476 * A value of XST_DMA_SG_IS_STOPPED indicates scatter gather was not stoppped
477 * because the scatter gather is not started, but was already stopped.
479 * BufDescriptorPtr contains a pointer to the buffer descriptor which was
480 * completed when the operation was stopped.
484 * This function implements a loop which polls the hardware for an infinite
485 * amount of time. If the hardware is not operating correctly, this function
488 ******************************************************************************/
490 XDmaChannel_SgStop(XDmaChannel * InstancePtr,
491 XBufDescriptor ** BufDescriptorPtr)
495 /* assert to verify input arguments */
497 XASSERT_NONVOID(InstancePtr != NULL);
498 XASSERT_NONVOID(BufDescriptorPtr != NULL);
499 XASSERT_NONVOID(InstancePtr->IsReady == XCOMPONENT_IS_READY);
501 /* get the contents of the software control register, if scatter gather is not
502 * enabled (started), then return a status because the disable acknowledge
503 * would not be generated
505 Register = XIo_In32(InstancePtr->RegBaseAddress + XDC_SWCR_REG_OFFSET);
507 if ((Register & XDC_SWCR_SG_ENABLE_MASK) == 0) {
508 return XST_DMA_SG_IS_STOPPED;
511 /* Ensure the interrupt status for the scatter gather is cleared such
512 * that this function will wait til the disable has occurred, writing
513 * a 1 to only that bit in the register will clear only it
515 XIo_Out32(InstancePtr->RegBaseAddress + XDC_IS_REG_OFFSET,
516 XDC_IXR_SG_DISABLE_ACK_MASK);
518 /* disable scatter gather by writing to the software control register
519 * without modifying any other bits of the register
521 XIo_Out32(InstancePtr->RegBaseAddress + XDC_SWCR_REG_OFFSET,
522 Register & ~XDC_SWCR_SG_ENABLE_MASK);
524 /* scatter gather does not disable immediately, but after the current
525 * buffer descriptor is complete, so wait for the DMA channel to indicate
526 * the disable is complete
530 XIo_In32(InstancePtr->RegBaseAddress + XDC_IS_REG_OFFSET);
531 } while ((Register & XDC_IXR_SG_DISABLE_ACK_MASK) == 0);
533 /* Ensure the interrupt status for the scatter gather disable is cleared,
534 * writing a 1 to only that bit in the register will clear only it
536 XIo_Out32(InstancePtr->RegBaseAddress + XDC_IS_REG_OFFSET,
537 XDC_IXR_SG_DISABLE_ACK_MASK);
539 /* set the specified buffer descriptor pointer to point to the buffer
540 * descriptor that the scatter gather DMA channel was processing
543 (XBufDescriptor *) XIo_In32(InstancePtr->RegBaseAddress +
549 /******************************************************************************
553 * XDmaChannel_CreateSgList
557 * This function creates a scatter gather list in the DMA channel. A scatter
558 * gather list consists of a list of buffer descriptors that are available to
559 * be used for scatter gather operations. Buffer descriptors are put into the
560 * list to request a scatter gather operation to be performed.
562 * A number of buffer descriptors are created from the specified memory and put
563 * into a buffer descriptor list as empty buffer descriptors. This function must
564 * be called before non-empty buffer descriptors may be put into the DMA channel
565 * to request scatter gather operations.
569 * InstancePtr contains a pointer to the DMA channel to operate on. The DMA
570 * channel should be configured to use scatter gather in order for this function
573 * MemoryPtr contains a pointer to the memory which is to be used for buffer
574 * descriptors and must not be cached.
576 * ByteCount contains the number of bytes for the specified memory to be used
577 * for buffer descriptors.
581 * A status contains XST_SUCCESS if the scatter gather list was successfully
584 * A value of XST_DMA_SG_LIST_EXISTS indicates that the scatter gather list
585 * was not created because the list has already been created.
591 ******************************************************************************/
593 XDmaChannel_CreateSgList(XDmaChannel * InstancePtr,
594 u32 * MemoryPtr, u32 ByteCount)
596 XBufDescriptor *BufferDescriptorPtr = (XBufDescriptor *) MemoryPtr;
597 XBufDescriptor *PreviousDescriptorPtr = NULL;
598 XBufDescriptor *StartOfListPtr = BufferDescriptorPtr;
601 /* assert to verify valid input arguments, alignment for those
602 * arguments that have alignment restrictions, and at least enough
603 * memory for one buffer descriptor
605 XASSERT_NONVOID(InstancePtr != NULL);
606 XASSERT_NONVOID(MemoryPtr != NULL);
607 XASSERT_NONVOID(((u32) MemoryPtr & 3) == 0);
608 XASSERT_NONVOID(ByteCount != 0);
609 XASSERT_NONVOID(ByteCount >= sizeof (XBufDescriptor));
610 XASSERT_NONVOID(InstancePtr->IsReady == XCOMPONENT_IS_READY);
612 /* if the scatter gather list has already been created, then return
615 if (InstancePtr->TotalDescriptorCount != 0) {
616 return XST_DMA_SG_LIST_EXISTS;
619 /* loop thru the specified memory block and create as many buffer
620 * descriptors as possible putting each into the list which is
621 * implemented as a ring buffer, make sure not to use any memory which
622 * is not large enough for a complete buffer descriptor
625 while ((UsedByteCount + sizeof (XBufDescriptor)) <= ByteCount) {
626 /* setup a pointer to the next buffer descriptor in the memory and
627 * update # of used bytes to know when all of memory is used
629 BufferDescriptorPtr = (XBufDescriptor *) ((u32) MemoryPtr +
632 /* initialize the new buffer descriptor such that it doesn't contain
633 * garbage which could be used by the DMA hardware
635 XBufDescriptor_Initialize(BufferDescriptorPtr);
637 /* if this is not the first buffer descriptor to be created,
638 * then link it to the last created buffer descriptor
640 if (PreviousDescriptorPtr != NULL) {
641 XBufDescriptor_SetNextPtr(PreviousDescriptorPtr,
642 BufferDescriptorPtr);
645 /* always keep a pointer to the last created buffer descriptor such
646 * that they can be linked together in the ring buffer
648 PreviousDescriptorPtr = BufferDescriptorPtr;
650 /* keep a count of the number of descriptors in the list to allow
651 * error processing to be performed
653 InstancePtr->TotalDescriptorCount++;
655 UsedByteCount += sizeof (XBufDescriptor);
658 /* connect the last buffer descriptor created and inserted in the list
659 * to the first such that a ring buffer is created
661 XBufDescriptor_SetNextPtr(BufferDescriptorPtr, StartOfListPtr);
663 /* initialize the ring buffer to indicate that there are no
664 * buffer descriptors in the list which point to valid data buffers
666 InstancePtr->PutPtr = BufferDescriptorPtr;
667 InstancePtr->GetPtr = BufferDescriptorPtr;
668 InstancePtr->CommitPtr = NULL;
669 InstancePtr->LastPtr = BufferDescriptorPtr;
670 InstancePtr->ActiveDescriptorCount = 0;
672 /* indicate the scatter gather list was successfully created */
677 /******************************************************************************
681 * XDmaChannel_IsSgListEmpty
685 * This function determines if the scatter gather list of a DMA channel is
686 * empty with regard to buffer descriptors which are pointing to buffers to be
687 * used for scatter gather operations.
691 * InstancePtr contains a pointer to the DMA channel to operate on. The DMA
692 * channel should be configured to use scatter gather in order for this function
697 * A value of TRUE if the scatter gather list is empty, otherwise a value of
704 ******************************************************************************/
706 XDmaChannel_IsSgListEmpty(XDmaChannel * InstancePtr)
708 /* assert to verify valid input arguments */
710 XASSERT_NONVOID(InstancePtr != NULL);
711 XASSERT_NONVOID(InstancePtr->IsReady == XCOMPONENT_IS_READY);
713 /* if the number of descriptors which are being used in the list is zero
714 * then the list is empty
716 return (InstancePtr->ActiveDescriptorCount == 0);
719 /******************************************************************************
723 * XDmaChannel_PutDescriptor
727 * This function puts a buffer descriptor into the DMA channel scatter
728 * gather list. A DMA channel maintains a list of buffer descriptors which are
729 * to be processed. This function puts the specified buffer descriptor
730 * at the next location in the list. Note that since the list is already intact,
731 * the information in the parameter is copied into the list (rather than modify
732 * list pointers on the fly).
734 * After buffer descriptors are put into the list, they must also be committed
735 * by calling another function. This allows multiple buffer descriptors which
736 * span a single packet to be put into the list while preventing the hardware
737 * from starting the first buffer descriptor of the packet.
741 * InstancePtr contains a pointer to the DMA channel to operate on. The DMA
742 * channel should be configured to use scatter gather in order for this function
745 * BufferDescriptorPtr is a pointer to the buffer descriptor to be put into
746 * the next available location of the scatter gather list.
750 * A status which indicates XST_SUCCESS if the buffer descriptor was
751 * successfully put into the scatter gather list.
753 * A value of XST_DMA_SG_NO_LIST indicates the scatter gather list has not
756 * A value of XST_DMA_SG_LIST_FULL indicates the buffer descriptor was not
757 * put into the list because the list was full.
759 * A value of XST_DMA_SG_BD_LOCKED indicates the buffer descriptor was not
760 * put into the list because the buffer descriptor in the list which is to
761 * be overwritten was locked. A locked buffer descriptor indicates the higher
762 * layered software is still using the buffer descriptor.
766 * It is necessary to create a scatter gather list for a DMA channel before
767 * putting buffer descriptors into it.
769 ******************************************************************************/
771 XDmaChannel_PutDescriptor(XDmaChannel * InstancePtr,
772 XBufDescriptor * BufferDescriptorPtr)
776 /* assert to verify valid input arguments and alignment for those
777 * arguments that have alignment restrictions
779 XASSERT_NONVOID(InstancePtr != NULL);
780 XASSERT_NONVOID(BufferDescriptorPtr != NULL);
781 XASSERT_NONVOID(((u32) BufferDescriptorPtr & 3) == 0);
782 XASSERT_NONVOID(InstancePtr->IsReady == XCOMPONENT_IS_READY);
784 /* if a scatter gather list has not been created yet, return a status */
786 if (InstancePtr->TotalDescriptorCount == 0) {
787 return XST_DMA_SG_NO_LIST;
790 /* if the list is full because all descriptors are pointing to valid
791 * buffers, then indicate an error, this code assumes no list or an
792 * empty list is detected above
794 if (InstancePtr->ActiveDescriptorCount ==
795 InstancePtr->TotalDescriptorCount) {
796 return XST_DMA_SG_LIST_FULL;
799 /* if the buffer descriptor in the list which is to be overwritten is
800 * locked, then don't overwrite it and return a status
802 if (XBufDescriptor_IsLocked(InstancePtr->PutPtr)) {
803 return XST_DMA_SG_BD_LOCKED;
806 /* set the scatter gather stop bit in the control word of the descriptor
807 * to cause the h/w to stop after it processes this descriptor since it
808 * will be the last in the list
810 Control = XBufDescriptor_GetControl(BufferDescriptorPtr);
811 XBufDescriptor_SetControl(BufferDescriptorPtr,
812 Control | XDC_DMACR_SG_DISABLE_MASK);
814 /* set both statuses in the descriptor so we tell if they are updated with
815 * the status of the transfer, the hardware should change the busy in the
816 * DMA status to be false when it completes
818 XBufDescriptor_SetStatus(BufferDescriptorPtr, XDC_DMASR_BUSY_MASK);
819 XBufDescriptor_SetDeviceStatus(BufferDescriptorPtr, 0);
821 /* copy the descriptor into the next position in the list so it's ready to
822 * be used by the h/w, this assumes the descriptor in the list prior to this
823 * one still has the stop bit in the control word set such that the h/w
826 CopyBufferDescriptor(BufferDescriptorPtr, InstancePtr->PutPtr);
828 /* only the last in the list and the one to be committed have scatter gather
829 * disabled in the control word, a commit requires only one descriptor
830 * to be changed, when # of descriptors to commit > 2 all others except the
831 * 1st and last have scatter gather enabled
833 if ((InstancePtr->CommitPtr != InstancePtr->LastPtr) &&
834 (InstancePtr->CommitPtr != NULL)) {
835 Control = XBufDescriptor_GetControl(InstancePtr->LastPtr);
836 XBufDescriptor_SetControl(InstancePtr->LastPtr,
837 Control & ~XDC_DMACR_SG_DISABLE_MASK);
840 /* update the list data based upon putting a descriptor into the list,
841 * these operations must be last
843 InstancePtr->ActiveDescriptorCount++;
845 /* only update the commit pointer if it is not already active, this allows
846 * it to be deactivated after every commit such that a single descriptor
847 * which is committed does not appear to be waiting to be committed
849 if (InstancePtr->CommitPtr == NULL) {
850 InstancePtr->CommitPtr = InstancePtr->LastPtr;
853 /* these updates MUST BE LAST after the commit pointer update in order for
854 * the commit pointer to track the correct descriptor to be committed
856 InstancePtr->LastPtr = InstancePtr->PutPtr;
857 InstancePtr->PutPtr = XBufDescriptor_GetNextPtr(InstancePtr->PutPtr);
862 /******************************************************************************
866 * XDmaChannel_CommitPuts
870 * This function commits the buffer descriptors which have been put into the
871 * scatter list for the DMA channel since the last commit operation was
872 * performed. This enables the calling functions to put several buffer
873 * descriptors into the list (e.g.,a packet's worth) before allowing the scatter
874 * gather operations to start. This prevents the DMA channel hardware from
875 * starting to use the buffer descriptors in the list before they are ready
876 * to be used (multiple buffer descriptors for a single packet).
880 * InstancePtr contains a pointer to the DMA channel to operate on. The DMA
881 * channel should be configured to use scatter gather in order for this function
886 * A status indicating XST_SUCCESS if the buffer descriptors of the list were
887 * successfully committed.
889 * A value of XST_DMA_SG_NOTHING_TO_COMMIT indicates that the buffer descriptors
890 * were not committed because there was nothing to commit in the list. All the
891 * buffer descriptors which are in the list are commited.
897 ******************************************************************************/
899 XDmaChannel_CommitPuts(XDmaChannel * InstancePtr)
901 /* assert to verify input arguments */
903 XASSERT_NONVOID(InstancePtr != NULL);
904 XASSERT_NONVOID(InstancePtr->IsReady == XCOMPONENT_IS_READY);
906 /* if the buffer descriptor to be committed is already committed or
907 * the list is empty (none have been put in), then indicate an error
909 if ((InstancePtr->CommitPtr == NULL) ||
910 XDmaChannel_IsSgListEmpty(InstancePtr)) {
911 return XST_DMA_SG_NOTHING_TO_COMMIT;
914 /* last descriptor in the list must have scatter gather disabled so the end
915 * of the list is hit by h/w, if descriptor to commit is not last in list,
916 * commit descriptors by enabling scatter gather in the descriptor
918 if (InstancePtr->CommitPtr != InstancePtr->LastPtr) {
921 Control = XBufDescriptor_GetControl(InstancePtr->CommitPtr);
922 XBufDescriptor_SetControl(InstancePtr->CommitPtr, Control &
923 ~XDC_DMACR_SG_DISABLE_MASK);
925 /* Update the commit pointer to indicate that there is nothing to be
926 * committed, this state is used by start processing to know that the
927 * buffer descriptor to start is not waiting to be committed
929 InstancePtr->CommitPtr = NULL;
934 /******************************************************************************
938 * XDmaChannel_GetDescriptor
942 * This function gets a buffer descriptor from the scatter gather list of the
943 * DMA channel. The buffer descriptor is retrieved from the scatter gather list
944 * and the scatter gather list is updated to not include the retrieved buffer
945 * descriptor. This is typically done after a scatter gather operation
946 * completes indicating that a data buffer has been successfully sent or data
947 * has been received into the data buffer. The purpose of this function is to
948 * allow the device using the scatter gather operation to get the results of the
953 * InstancePtr contains a pointer to the DMA channel to operate on. The DMA
954 * channel should be configured to use scatter gather in order for this function
957 * BufDescriptorPtr is a pointer to a pointer to the buffer descriptor which
958 * was retrieved from the list. The buffer descriptor is not really removed
959 * from the list, but it is changed to a state such that the hardware will not
960 * use it again until it is put into the scatter gather list of the DMA channel.
964 * A status indicating XST_SUCCESS if a buffer descriptor was retrieved from
965 * the scatter gather list of the DMA channel.
967 * A value of XST_DMA_SG_NO_LIST indicates the scatter gather list has not
970 * A value of XST_DMA_SG_LIST_EMPTY indicates no buffer descriptor was
971 * retrieved from the list because there are no buffer descriptors to be
972 * processed in the list.
974 * BufDescriptorPtr is updated to point to the buffer descriptor which was
975 * retrieved from the list if the status indicates success.
981 ******************************************************************************/
983 XDmaChannel_GetDescriptor(XDmaChannel * InstancePtr,
984 XBufDescriptor ** BufDescriptorPtr)
988 /* assert to verify input arguments */
990 XASSERT_NONVOID(InstancePtr != NULL);
991 XASSERT_NONVOID(BufDescriptorPtr != NULL);
992 XASSERT_NONVOID(InstancePtr->IsReady == XCOMPONENT_IS_READY);
994 /* if a scatter gather list has not been created yet, return a status */
996 if (InstancePtr->TotalDescriptorCount == 0) {
997 return XST_DMA_SG_NO_LIST;
1000 /* if the buffer descriptor list is empty, then indicate an error */
1002 if (XDmaChannel_IsSgListEmpty(InstancePtr)) {
1003 return XST_DMA_SG_LIST_EMPTY;
1006 /* retrieve the next buffer descriptor which is ready to be processed from
1007 * the buffer descriptor list for the DMA channel, set the control word
1008 * such that hardware will stop after the descriptor has been processed
1010 Control = XBufDescriptor_GetControl(InstancePtr->GetPtr);
1011 XBufDescriptor_SetControl(InstancePtr->GetPtr,
1012 Control | XDC_DMACR_SG_DISABLE_MASK);
1014 /* set the input argument, which is also an output, to point to the
1015 * buffer descriptor which is to be retrieved from the list
1017 *BufDescriptorPtr = InstancePtr->GetPtr;
1019 /* update the pointer of the DMA channel to reflect the buffer descriptor
1020 * was retrieved from the list by setting it to the next buffer descriptor
1021 * in the list and indicate one less descriptor in the list now
1023 InstancePtr->GetPtr = XBufDescriptor_GetNextPtr(InstancePtr->GetPtr);
1024 InstancePtr->ActiveDescriptorCount--;
1029 /*********************** Interrupt Collescing Functions **********************/
1031 /******************************************************************************
1035 * XDmaChannel_GetPktCount
1039 * This function returns the value of the unserviced packet count register of
1040 * the DMA channel. This count represents the number of packets that have been
1041 * sent or received by the hardware, but not processed by software.
1045 * InstancePtr contains a pointer to the DMA channel to operate on. The DMA
1046 * channel should be configured to use scatter gather in order for this function
1051 * The unserviced packet counter register contents for the DMA channel.
1057 ******************************************************************************/
1059 XDmaChannel_GetPktCount(XDmaChannel * InstancePtr)
1061 /* assert to verify input arguments */
1063 XASSERT_NONVOID(InstancePtr != NULL);
1064 XASSERT_NONVOID(InstancePtr->IsReady == XCOMPONENT_IS_READY);
1066 /* get the unserviced packet count from the register and return it */
1068 return XIo_In32(InstancePtr->RegBaseAddress + XDC_UPC_REG_OFFSET);
1071 /******************************************************************************
1075 * XDmaChannel_DecrementPktCount
1079 * This function decrements the value of the unserviced packet count register.
1080 * This informs the hardware that the software has processed a packet. The
1081 * unserviced packet count register may only be decremented by one in the
1086 * InstancePtr contains a pointer to the DMA channel to operate on. The DMA
1087 * channel should be configured to use scatter gather in order for this function
1098 ******************************************************************************/
1100 XDmaChannel_DecrementPktCount(XDmaChannel * InstancePtr)
1104 /* assert to verify input arguments */
1106 XASSERT_VOID(InstancePtr != NULL);
1107 XASSERT_VOID(InstancePtr->IsReady == XCOMPONENT_IS_READY);
1109 /* if the unserviced packet count register can be decremented (rather
1110 * than rolling over) decrement it by writing a 1 to the register,
1111 * this is the only valid write to the register as it serves as an
1112 * acknowledge that a packet was handled by the software
1114 Register = XIo_In32(InstancePtr->RegBaseAddress + XDC_UPC_REG_OFFSET);
1116 XIo_Out32(InstancePtr->RegBaseAddress + XDC_UPC_REG_OFFSET,
1121 /******************************************************************************
1125 * XDmaChannel_SetPktThreshold
1129 * This function sets the value of the packet count threshold register of the
1130 * DMA channel. It reflects the number of packets that must be sent or
1131 * received before generating an interrupt. This value helps implement
1132 * a concept called "interrupt coalescing", which is used to reduce the number
1133 * of interrupts from devices with high data rates.
1137 * InstancePtr contains a pointer to the DMA channel to operate on. The DMA
1138 * channel should be configured to use scatter gather in order for this function
1141 * Threshold is the value that is written to the threshold register of the
1146 * A status containing XST_SUCCESS if the packet count threshold was
1151 * The packet threshold could be set to larger than the number of descriptors
1152 * allocated to the DMA channel. In this case, the wait bound will take over
1153 * and always indicate data arrival. There was a check in this function that
1154 * returned an error if the treshold was larger than the number of descriptors,
1155 * but that was removed because users would then have to set the threshold
1156 * only after they set descriptor space, which is an order dependency that
1157 * caused confustion.
1159 ******************************************************************************/
1161 XDmaChannel_SetPktThreshold(XDmaChannel * InstancePtr, u8 Threshold)
1163 /* assert to verify input arguments, don't assert the threshold since
1164 * it's range is unknown
1166 XASSERT_NONVOID(InstancePtr != NULL);
1167 XASSERT_NONVOID(InstancePtr->IsReady == XCOMPONENT_IS_READY);
1169 /* set the packet count threshold in the register such that an interrupt
1170 * may be generated, if enabled, when the packet count threshold is
1171 * reached or exceeded
1173 XIo_Out32(InstancePtr->RegBaseAddress + XDC_PCT_REG_OFFSET,
1176 /* indicate the packet count threshold was successfully set */
1181 /******************************************************************************
1185 * XDmaChannel_GetPktThreshold
1189 * This function gets the value of the packet count threshold register of the
1190 * DMA channel. This value reflects the number of packets that must be sent or
1191 * received before generating an interrupt. This value helps implement a concept
1192 * called "interrupt coalescing", which is used to reduce the number of
1193 * interrupts from devices with high data rates.
1197 * InstancePtr contains a pointer to the DMA channel to operate on. The DMA
1198 * channel should be configured to use scatter gather in order for this function
1203 * The packet threshold register contents for the DMA channel and is a value in
1204 * the range 0 - 1023. A value of 0 indicates the packet wait bound timer is
1211 ******************************************************************************/
1213 XDmaChannel_GetPktThreshold(XDmaChannel * InstancePtr)
1215 /* assert to verify input arguments */
1217 XASSERT_NONVOID(InstancePtr != NULL);
1218 XASSERT_NONVOID(InstancePtr->IsReady == XCOMPONENT_IS_READY);
1220 /* get the packet count threshold from the register and return it,
1221 * since only 8 bits are used, cast it to return only those bits */
1223 return (u8) XIo_In32(InstancePtr->RegBaseAddress + XDC_PCT_REG_OFFSET);
1226 /******************************************************************************
1230 * XDmaChannel_SetPktWaitBound
1234 * This function sets the value of the packet wait bound register of the
1235 * DMA channel. This value reflects the timer value used to trigger an
1236 * interrupt when not enough packets have been received to reach the packet
1239 * The timer is in millisecond units with +/- 33% accuracy.
1243 * InstancePtr contains a pointer to the DMA channel to operate on. The DMA
1244 * channel should be configured to use scatter gather in order for this function
1247 * WaitBound is the value, in milliseconds, to be stored in the wait bound
1248 * register of the DMA channel and is a value in the range 0 - 1023. A value
1249 * of 0 disables the packet wait bound timer.
1259 ******************************************************************************/
1261 XDmaChannel_SetPktWaitBound(XDmaChannel * InstancePtr, u32 WaitBound)
1263 /* assert to verify input arguments */
1265 XASSERT_VOID(InstancePtr != NULL);
1266 XASSERT_VOID(WaitBound < 1024);
1267 XASSERT_VOID(InstancePtr->IsReady == XCOMPONENT_IS_READY);
1269 /* set the packet wait bound in the register such that interrupt may be
1270 * generated, if enabled, when packets have not been handled for a specific
1273 XIo_Out32(InstancePtr->RegBaseAddress + XDC_PWB_REG_OFFSET, WaitBound);
1276 /******************************************************************************
1280 * XDmaChannel_GetPktWaitBound
1284 * This function gets the value of the packet wait bound register of the
1285 * DMA channel. This value contains the timer value used to trigger an
1286 * interrupt when not enough packets have been received to reach the packet
1289 * The timer is in millisecond units with +/- 33% accuracy.
1293 * InstancePtr contains a pointer to the DMA channel to operate on. The DMA
1294 * channel should be configured to use scatter gather in order for this function
1299 * The packet wait bound register contents for the DMA channel.
1305 ******************************************************************************/
1307 XDmaChannel_GetPktWaitBound(XDmaChannel * InstancePtr)
1309 /* assert to verify input arguments */
1311 XASSERT_NONVOID(InstancePtr != NULL);
1312 XASSERT_NONVOID(InstancePtr->IsReady == XCOMPONENT_IS_READY);
1314 /* get the packet wait bound from the register and return it */
1316 return XIo_In32(InstancePtr->RegBaseAddress + XDC_PWB_REG_OFFSET);