]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - board/xilinx/common/xdma_channel_sg.c
a8e94625bf9f5487ba1272e77490b3b57251d1d2
[karo-tx-uboot.git] / board / xilinx / common / xdma_channel_sg.c
1 /* $Id: xdma_channel_sg.c,v 1.6 2003/02/03 19:50:33 moleres Exp $ */
2 /******************************************************************************
3 *
4 *     Author: Xilinx, Inc.
5 *
6 *
7 *     This program is free software; you can redistribute it and/or modify it
8 *     under the terms of the GNU General Public License as published by the
9 *     Free Software Foundation; either version 2 of the License, or (at your
10 *     option) any later version.
11 *
12 *
13 *     XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION "AS IS" AS A
14 *     COURTESY TO YOU. BY PROVIDING THIS DESIGN, CODE, OR INFORMATION AS
15 *     ONE POSSIBLE IMPLEMENTATION OF THIS FEATURE, APPLICATION OR STANDARD,
16 *     XILINX IS MAKING NO REPRESENTATION THAT THIS IMPLEMENTATION IS FREE
17 *     FROM ANY CLAIMS OF INFRINGEMENT, AND YOU ARE RESPONSIBLE FOR 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.
24 *
25 *
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.
29 *
30 *
31 *     (c) Copyright 2002-2004 Xilinx Inc.
32 *     All rights reserved.
33 *
34 *
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.
38 *
39 * FILENAME:
40 *
41 * xdma_channel_sg.c
42 *
43 * DESCRIPTION:
44 *
45 * This file contains the implementation of the XDmaChannel component which is
46 * related to scatter gather operations.
47 *
48 * Scatter Gather Operations
49 *
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
55 * processed.
56 *
57 * Scatter Gather List Operations
58 *
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.
67 *
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.
77 *
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
86 * yet.
87 *
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.
99 *
100 * Typical Scatter Gather Processing
101 *
102 * The following steps illustrate the typical processing to use the
103 * scatter gather features of a DMA channel.
104 *
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
118 *    number of packets.
119 *
120 * Minimizing Interrupts
121 *
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"
132 * is utilized.
133 *
134 * Interrupt Coalescing
135 *
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.
145 *
146 * Unserviced Packet Count
147 *
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.
154 *
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.
161 *
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.
171 *
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.
176 *
177 * Packet Wait Bound
178 *
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.
185 *
186 * NOTES:
187 *
188 * Special Test Conditions:
189 *
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.
194 *
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.
206
207 * Single Put And Commit
208 *
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.
216 *
217 * 3 Or More Puts And Commit
218 *
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.
223 *
224 * The 1st Put Following A Commit
225 *
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.
230 *
231 * <pre>
232 * MODIFICATION HISTORY:
233 *
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.
238 * </pre>
239 *
240 ******************************************************************************/
241
242 /***************************** Include Files *********************************/
243
244 #include "xdma_channel.h"
245 #include "xbasic_types.h"
246 #include "xio.h"
247 #include "xbuf_descriptor.h"
248 #include "xstatus.h"
249
250 /************************** Constant Definitions *****************************/
251
252 #define XDC_SWCR_SG_ENABLE_MASK 0x80000000UL    /* scatter gather enable */
253
254 /**************************** Type Definitions *******************************/
255
256 /***************** Macros (Inline Functions) Definitions *********************/
257
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
262  */
263 #define CopyBufferDescriptor(InstancePtr, DestinationPtr)          \
264 {                                                                  \
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);      \
283 }
284
285 /************************** Variable Definitions *****************************/
286
287 /************************** Function Prototypes ******************************/
288
289 /******************************************************************************
290 *
291 * FUNCTION:
292 *
293 * XDmaChannel_SgStart
294 *
295 * DESCRIPTION:
296 *
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.
303 *
304 * ARGUMENTS:
305 *
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
308 * to be called.
309 *
310 * RETURN VALUE:
311 *
312 * A status containing XST_SUCCESS if scatter gather was started successfully
313 * for the DMA channel.
314 *
315 * A value of XST_DMA_SG_NO_LIST indicates the scatter gather list has not
316 * been created.
317 *
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.
321 *
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.
324 *
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.
329 *
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.
333 *
334 * NOTES:
335 *
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.
340 *
341 ******************************************************************************/
342 XStatus
343 XDmaChannel_SgStart(XDmaChannel * InstancePtr)
344 {
345         u32 Register;
346         XBufDescriptor *LastDescriptorPtr;
347
348         /* assert to verify input arguments */
349
350         XASSERT_NONVOID(InstancePtr != NULL);
351         XASSERT_NONVOID(InstancePtr->IsReady == XCOMPONENT_IS_READY);
352
353         /* if a scatter gather list has not been created yet, return a status */
354
355         if (InstancePtr->TotalDescriptorCount == 0) {
356                 return XST_DMA_SG_NO_LIST;
357         }
358
359         /* if the scatter gather list exists but is empty then return a status */
360
361         if (XDmaChannel_IsSgListEmpty(InstancePtr)) {
362                 return XST_DMA_SG_LIST_EMPTY;
363         }
364
365         /* if scatter gather is busy for the DMA channel, return a status because
366          * restarting it could lose data
367          */
368
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;
372         }
373
374         /* get the address of the last buffer descriptor which the DMA hardware
375          * finished processing
376          */
377         LastDescriptorPtr =
378             (XBufDescriptor *) XIo_In32(InstancePtr->RegBaseAddress +
379                                         XDC_BDA_REG_OFFSET);
380
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
384          * processed
385          */
386         if (LastDescriptorPtr == NULL) {
387                 XIo_Out32(InstancePtr->RegBaseAddress + XDC_BDA_REG_OFFSET,
388                           (u32) InstancePtr->GetPtr);
389         } else {
390                 XBufDescriptor *NextDescriptorPtr;
391
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
396                  */
397                 NextDescriptorPtr =
398                     XBufDescriptor_GetNextPtr(LastDescriptorPtr);
399
400                 if ((XBufDescriptor_GetStatus(NextDescriptorPtr) &
401                      XDC_DMASR_BUSY_MASK) == 0) {
402                         return XST_DMA_SG_NO_DATA;
403                 }
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
407                  */
408                 if (NextDescriptorPtr == InstancePtr->CommitPtr) {
409                         return XST_DMA_SG_BD_NOT_COMMITTED;
410                 }
411         }
412
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
419          * running
420          */
421
422         Register = XIo_In32(InstancePtr->RegBaseAddress + XDC_SWCR_REG_OFFSET);
423
424         XIo_Out32(InstancePtr->RegBaseAddress + XDC_SWCR_REG_OFFSET,
425                   Register | XDC_SWCR_SG_ENABLE_MASK);
426
427         Register = XIo_In32(InstancePtr->RegBaseAddress + XDC_DMAC_REG_OFFSET);
428
429         XIo_Out32(InstancePtr->RegBaseAddress + XDC_DMAC_REG_OFFSET,
430                   Register & ~XDC_DMACR_SG_DISABLE_MASK);
431
432         /* indicate the DMA channel scatter gather operation was started
433          * successfully
434          */
435         return XST_SUCCESS;
436 }
437
438 /******************************************************************************
439 *
440 * FUNCTION:
441 *
442 * XDmaChannel_SgStop
443 *
444 * DESCRIPTION:
445 *
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.
456 *
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
459 * interrupt.
460 *
461 * ARGUMENTS:
462 *
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
465 * to be called.
466 *
467 * BufDescriptorPtr is also a return value which contains a pointer to the
468 * buffer descriptor which the scatter gather operation completed when it
469 * was stopped.
470 *
471 * RETURN VALUE:
472 *
473 * A status containing XST_SUCCESS if scatter gather was stopped successfully
474 * for the DMA channel.
475 *
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.
478 *
479 * BufDescriptorPtr contains a pointer to the buffer descriptor which was
480 * completed when the operation was stopped.
481 *
482 * NOTES:
483 *
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
486 * may never return.
487 *
488 ******************************************************************************/
489 XStatus
490 XDmaChannel_SgStop(XDmaChannel * InstancePtr,
491                    XBufDescriptor ** BufDescriptorPtr)
492 {
493         u32 Register;
494
495         /* assert to verify input arguments */
496
497         XASSERT_NONVOID(InstancePtr != NULL);
498         XASSERT_NONVOID(BufDescriptorPtr != NULL);
499         XASSERT_NONVOID(InstancePtr->IsReady == XCOMPONENT_IS_READY);
500
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
504          */
505         Register = XIo_In32(InstancePtr->RegBaseAddress + XDC_SWCR_REG_OFFSET);
506
507         if ((Register & XDC_SWCR_SG_ENABLE_MASK) == 0) {
508                 return XST_DMA_SG_IS_STOPPED;
509         }
510
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
514          */
515         XIo_Out32(InstancePtr->RegBaseAddress + XDC_IS_REG_OFFSET,
516                   XDC_IXR_SG_DISABLE_ACK_MASK);
517
518         /* disable scatter gather by writing to the software control register
519          * without modifying any other bits of the register
520          */
521         XIo_Out32(InstancePtr->RegBaseAddress + XDC_SWCR_REG_OFFSET,
522                   Register & ~XDC_SWCR_SG_ENABLE_MASK);
523
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
527          */
528         do {
529                 Register =
530                     XIo_In32(InstancePtr->RegBaseAddress + XDC_IS_REG_OFFSET);
531         } while ((Register & XDC_IXR_SG_DISABLE_ACK_MASK) == 0);
532
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
535          */
536         XIo_Out32(InstancePtr->RegBaseAddress + XDC_IS_REG_OFFSET,
537                   XDC_IXR_SG_DISABLE_ACK_MASK);
538
539         /* set the specified buffer descriptor pointer to point to the buffer
540          * descriptor that the scatter gather DMA channel was processing
541          */
542         *BufDescriptorPtr =
543             (XBufDescriptor *) XIo_In32(InstancePtr->RegBaseAddress +
544                                         XDC_BDA_REG_OFFSET);
545
546         return XST_SUCCESS;
547 }
548
549 /******************************************************************************
550 *
551 * FUNCTION:
552 *
553 * XDmaChannel_CreateSgList
554 *
555 * DESCRIPTION:
556 *
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.
561 *
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.
566 *
567 * ARGUMENTS:
568 *
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
571 * to be called.
572 *
573 * MemoryPtr contains a pointer to the memory which is to be used for buffer
574 * descriptors and must not be cached.
575 *
576 * ByteCount contains the number of bytes for the specified memory to be used
577 * for buffer descriptors.
578 *
579 * RETURN VALUE:
580 *
581 * A status contains XST_SUCCESS if the scatter gather list was successfully
582 * created.
583 *
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.
586 *
587 * NOTES:
588 *
589 * None.
590 *
591 ******************************************************************************/
592 XStatus
593 XDmaChannel_CreateSgList(XDmaChannel * InstancePtr,
594                          u32 * MemoryPtr, u32 ByteCount)
595 {
596         XBufDescriptor *BufferDescriptorPtr = (XBufDescriptor *) MemoryPtr;
597         XBufDescriptor *PreviousDescriptorPtr = NULL;
598         XBufDescriptor *StartOfListPtr = BufferDescriptorPtr;
599         u32 UsedByteCount;
600
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
604          */
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);
611
612         /* if the scatter gather list has already been created, then return
613          * with a status
614          */
615         if (InstancePtr->TotalDescriptorCount != 0) {
616                 return XST_DMA_SG_LIST_EXISTS;
617         }
618
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
623          */
624         UsedByteCount = 0;
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
628                  */
629                 BufferDescriptorPtr = (XBufDescriptor *) ((u32) MemoryPtr +
630                                                           UsedByteCount);
631
632                 /* initialize the new buffer descriptor such that it doesn't contain
633                  * garbage which could be used by the DMA hardware
634                  */
635                 XBufDescriptor_Initialize(BufferDescriptorPtr);
636
637                 /* if this is not the first buffer descriptor to be created,
638                  * then link it to the last created buffer descriptor
639                  */
640                 if (PreviousDescriptorPtr != NULL) {
641                         XBufDescriptor_SetNextPtr(PreviousDescriptorPtr,
642                                                   BufferDescriptorPtr);
643                 }
644
645                 /* always keep a pointer to the last created buffer descriptor such
646                  * that they can be linked together in the ring buffer
647                  */
648                 PreviousDescriptorPtr = BufferDescriptorPtr;
649
650                 /* keep a count of the number of descriptors in the list to allow
651                  * error processing to be performed
652                  */
653                 InstancePtr->TotalDescriptorCount++;
654
655                 UsedByteCount += sizeof (XBufDescriptor);
656         }
657
658         /* connect the last buffer descriptor created and inserted in the list
659          * to the first such that a ring buffer is created
660          */
661         XBufDescriptor_SetNextPtr(BufferDescriptorPtr, StartOfListPtr);
662
663         /* initialize the ring buffer to indicate that there are no
664          * buffer descriptors in the list which point to valid data buffers
665          */
666         InstancePtr->PutPtr = BufferDescriptorPtr;
667         InstancePtr->GetPtr = BufferDescriptorPtr;
668         InstancePtr->CommitPtr = NULL;
669         InstancePtr->LastPtr = BufferDescriptorPtr;
670         InstancePtr->ActiveDescriptorCount = 0;
671
672         /* indicate the scatter gather list was successfully created */
673
674         return XST_SUCCESS;
675 }
676
677 /******************************************************************************
678 *
679 * FUNCTION:
680 *
681 * XDmaChannel_IsSgListEmpty
682 *
683 * DESCRIPTION:
684 *
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.
688 *
689 * ARGUMENTS:
690 *
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
693 * to be called.
694 *
695 * RETURN VALUE:
696 *
697 * A value of TRUE if the scatter gather list is empty, otherwise a value of
698 * FALSE.
699 *
700 * NOTES:
701 *
702 * None.
703 *
704 ******************************************************************************/
705 u32
706 XDmaChannel_IsSgListEmpty(XDmaChannel * InstancePtr)
707 {
708         /* assert to verify valid input arguments */
709
710         XASSERT_NONVOID(InstancePtr != NULL);
711         XASSERT_NONVOID(InstancePtr->IsReady == XCOMPONENT_IS_READY);
712
713         /* if the number of descriptors which are being used in the list is zero
714          * then the list is empty
715          */
716         return (InstancePtr->ActiveDescriptorCount == 0);
717 }
718
719 /******************************************************************************
720 *
721 * FUNCTION:
722 *
723 * XDmaChannel_PutDescriptor
724 *
725 * DESCRIPTION:
726 *
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).
733 *
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.
738 *
739 * ARGUMENTS:
740 *
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
743 * to be called.
744 *
745 * BufferDescriptorPtr is a pointer to the buffer descriptor to be put into
746 * the next available location of the scatter gather list.
747 *
748 * RETURN VALUE:
749 *
750 * A status which indicates XST_SUCCESS if the buffer descriptor was
751 * successfully put into the scatter gather list.
752 *
753 * A value of XST_DMA_SG_NO_LIST indicates the scatter gather list has not
754 * been created.
755 *
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.
758 *
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.
763 *
764 * NOTES:
765 *
766 * It is necessary to create a scatter gather list for a DMA channel before
767 * putting buffer descriptors into it.
768 *
769 ******************************************************************************/
770 XStatus
771 XDmaChannel_PutDescriptor(XDmaChannel * InstancePtr,
772                           XBufDescriptor * BufferDescriptorPtr)
773 {
774         u32 Control;
775
776         /* assert to verify valid input arguments and alignment for those
777          * arguments that have alignment restrictions
778          */
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);
783
784         /* if a scatter gather list has not been created yet, return a status */
785
786         if (InstancePtr->TotalDescriptorCount == 0) {
787                 return XST_DMA_SG_NO_LIST;
788         }
789
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
793          */
794         if (InstancePtr->ActiveDescriptorCount ==
795             InstancePtr->TotalDescriptorCount) {
796                 return XST_DMA_SG_LIST_FULL;
797         }
798
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
801          */
802         if (XBufDescriptor_IsLocked(InstancePtr->PutPtr)) {
803                 return XST_DMA_SG_BD_LOCKED;
804         }
805
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
809          */
810         Control = XBufDescriptor_GetControl(BufferDescriptorPtr);
811         XBufDescriptor_SetControl(BufferDescriptorPtr,
812                                   Control | XDC_DMACR_SG_DISABLE_MASK);
813
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
817          */
818         XBufDescriptor_SetStatus(BufferDescriptorPtr, XDC_DMASR_BUSY_MASK);
819         XBufDescriptor_SetDeviceStatus(BufferDescriptorPtr, 0);
820
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
824          * use this one yet
825          */
826         CopyBufferDescriptor(BufferDescriptorPtr, InstancePtr->PutPtr);
827
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
832          */
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);
838         }
839
840         /* update the list data based upon putting a descriptor into the list,
841          * these operations must be last
842          */
843         InstancePtr->ActiveDescriptorCount++;
844
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
848          */
849         if (InstancePtr->CommitPtr == NULL) {
850                 InstancePtr->CommitPtr = InstancePtr->LastPtr;
851         }
852
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
855          */
856         InstancePtr->LastPtr = InstancePtr->PutPtr;
857         InstancePtr->PutPtr = XBufDescriptor_GetNextPtr(InstancePtr->PutPtr);
858
859         return XST_SUCCESS;
860 }
861
862 /******************************************************************************
863 *
864 * FUNCTION:
865 *
866 * XDmaChannel_CommitPuts
867 *
868 * DESCRIPTION:
869 *
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).
877 *
878 * ARGUMENTS:
879 *
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
882 * to be called.
883 *
884 * RETURN VALUE:
885 *
886 * A status indicating XST_SUCCESS if the buffer descriptors of the list were
887 * successfully committed.
888 *
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.
892 *
893 * NOTES:
894 *
895 * None.
896 *
897 ******************************************************************************/
898 XStatus
899 XDmaChannel_CommitPuts(XDmaChannel * InstancePtr)
900 {
901         /* assert to verify input arguments */
902
903         XASSERT_NONVOID(InstancePtr != NULL);
904         XASSERT_NONVOID(InstancePtr->IsReady == XCOMPONENT_IS_READY);
905
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
908          */
909         if ((InstancePtr->CommitPtr == NULL) ||
910             XDmaChannel_IsSgListEmpty(InstancePtr)) {
911                 return XST_DMA_SG_NOTHING_TO_COMMIT;
912         }
913
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
917          */
918         if (InstancePtr->CommitPtr != InstancePtr->LastPtr) {
919                 u32 Control;
920
921                 Control = XBufDescriptor_GetControl(InstancePtr->CommitPtr);
922                 XBufDescriptor_SetControl(InstancePtr->CommitPtr, Control &
923                                           ~XDC_DMACR_SG_DISABLE_MASK);
924         }
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
928          */
929         InstancePtr->CommitPtr = NULL;
930
931         return XST_SUCCESS;
932 }
933
934 /******************************************************************************
935 *
936 * FUNCTION:
937 *
938 * XDmaChannel_GetDescriptor
939 *
940 * DESCRIPTION:
941 *
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
949 * operation.
950 *
951 * ARGUMENTS:
952 *
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
955 * to be called.
956 *
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.
961 *
962 * RETURN VALUE:
963 *
964 * A status indicating XST_SUCCESS if a buffer descriptor was retrieved from
965 * the scatter gather list of the DMA channel.
966 *
967 * A value of XST_DMA_SG_NO_LIST indicates the scatter gather list has not
968 * been created.
969 *
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.
973 *
974 * BufDescriptorPtr is updated to point to the buffer descriptor which was
975 * retrieved from the list if the status indicates success.
976 *
977 * NOTES:
978 *
979 * None.
980 *
981 ******************************************************************************/
982 XStatus
983 XDmaChannel_GetDescriptor(XDmaChannel * InstancePtr,
984                           XBufDescriptor ** BufDescriptorPtr)
985 {
986         u32 Control;
987
988         /* assert to verify input arguments */
989
990         XASSERT_NONVOID(InstancePtr != NULL);
991         XASSERT_NONVOID(BufDescriptorPtr != NULL);
992         XASSERT_NONVOID(InstancePtr->IsReady == XCOMPONENT_IS_READY);
993
994         /* if a scatter gather list has not been created yet, return a status */
995
996         if (InstancePtr->TotalDescriptorCount == 0) {
997                 return XST_DMA_SG_NO_LIST;
998         }
999
1000         /* if the buffer descriptor list is empty, then indicate an error */
1001
1002         if (XDmaChannel_IsSgListEmpty(InstancePtr)) {
1003                 return XST_DMA_SG_LIST_EMPTY;
1004         }
1005
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
1009          */
1010         Control = XBufDescriptor_GetControl(InstancePtr->GetPtr);
1011         XBufDescriptor_SetControl(InstancePtr->GetPtr,
1012                                   Control | XDC_DMACR_SG_DISABLE_MASK);
1013
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
1016          */
1017         *BufDescriptorPtr = InstancePtr->GetPtr;
1018
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
1022          */
1023         InstancePtr->GetPtr = XBufDescriptor_GetNextPtr(InstancePtr->GetPtr);
1024         InstancePtr->ActiveDescriptorCount--;
1025
1026         return XST_SUCCESS;
1027 }
1028
1029 /*********************** Interrupt Collescing Functions **********************/
1030
1031 /******************************************************************************
1032 *
1033 * FUNCTION:
1034 *
1035 * XDmaChannel_GetPktCount
1036 *
1037 * DESCRIPTION:
1038 *
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.
1042 *
1043 * ARGUMENTS:
1044 *
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
1047 * to be called.
1048 *
1049 * RETURN VALUE:
1050 *
1051 * The unserviced packet counter register contents for the DMA channel.
1052 *
1053 * NOTES:
1054 *
1055 * None.
1056 *
1057 ******************************************************************************/
1058 u32
1059 XDmaChannel_GetPktCount(XDmaChannel * InstancePtr)
1060 {
1061         /* assert to verify input arguments */
1062
1063         XASSERT_NONVOID(InstancePtr != NULL);
1064         XASSERT_NONVOID(InstancePtr->IsReady == XCOMPONENT_IS_READY);
1065
1066         /* get the unserviced packet count from the register and return it */
1067
1068         return XIo_In32(InstancePtr->RegBaseAddress + XDC_UPC_REG_OFFSET);
1069 }
1070
1071 /******************************************************************************
1072 *
1073 * FUNCTION:
1074 *
1075 * XDmaChannel_DecrementPktCount
1076 *
1077 * DESCRIPTION:
1078 *
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
1082 * hardware.
1083 *
1084 * ARGUMENTS:
1085 *
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
1088 * to be called.
1089 *
1090 * RETURN VALUE:
1091 *
1092 * None.
1093 *
1094 * NOTES:
1095 *
1096 * None.
1097 *
1098 ******************************************************************************/
1099 void
1100 XDmaChannel_DecrementPktCount(XDmaChannel * InstancePtr)
1101 {
1102         u32 Register;
1103
1104         /* assert to verify input arguments */
1105
1106         XASSERT_VOID(InstancePtr != NULL);
1107         XASSERT_VOID(InstancePtr->IsReady == XCOMPONENT_IS_READY);
1108
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
1113          */
1114         Register = XIo_In32(InstancePtr->RegBaseAddress + XDC_UPC_REG_OFFSET);
1115         if (Register > 0) {
1116                 XIo_Out32(InstancePtr->RegBaseAddress + XDC_UPC_REG_OFFSET,
1117                           1UL);
1118         }
1119 }
1120
1121 /******************************************************************************
1122 *
1123 * FUNCTION:
1124 *
1125 * XDmaChannel_SetPktThreshold
1126 *
1127 * DESCRIPTION:
1128 *
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.
1134 *
1135 * ARGUMENTS:
1136 *
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
1139 * to be called.
1140 *
1141 * Threshold is the value that is written to the threshold register of the
1142 * DMA channel.
1143 *
1144 * RETURN VALUE:
1145 *
1146 * A status containing XST_SUCCESS if the packet count threshold was
1147 * successfully set.
1148 *
1149 * NOTES:
1150 *
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.
1158 *
1159 ******************************************************************************/
1160 XStatus
1161 XDmaChannel_SetPktThreshold(XDmaChannel * InstancePtr, u8 Threshold)
1162 {
1163         /* assert to verify input arguments, don't assert the threshold since
1164          * it's range is unknown
1165          */
1166         XASSERT_NONVOID(InstancePtr != NULL);
1167         XASSERT_NONVOID(InstancePtr->IsReady == XCOMPONENT_IS_READY);
1168
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
1172          */
1173         XIo_Out32(InstancePtr->RegBaseAddress + XDC_PCT_REG_OFFSET,
1174                   (u32) Threshold);
1175
1176         /* indicate the packet count threshold was successfully set */
1177
1178         return XST_SUCCESS;
1179 }
1180
1181 /******************************************************************************
1182 *
1183 * FUNCTION:
1184 *
1185 * XDmaChannel_GetPktThreshold
1186 *
1187 * DESCRIPTION:
1188 *
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.
1194 *
1195 * ARGUMENTS:
1196 *
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
1199 * to be called.
1200 *
1201 * RETURN VALUE:
1202 *
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
1205 * disabled.
1206 *
1207 * NOTES:
1208 *
1209 * None.
1210 *
1211 ******************************************************************************/
1212 u8
1213 XDmaChannel_GetPktThreshold(XDmaChannel * InstancePtr)
1214 {
1215         /* assert to verify input arguments */
1216
1217         XASSERT_NONVOID(InstancePtr != NULL);
1218         XASSERT_NONVOID(InstancePtr->IsReady == XCOMPONENT_IS_READY);
1219
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 */
1222
1223         return (u8) XIo_In32(InstancePtr->RegBaseAddress + XDC_PCT_REG_OFFSET);
1224 }
1225
1226 /******************************************************************************
1227 *
1228 * FUNCTION:
1229 *
1230 * XDmaChannel_SetPktWaitBound
1231 *
1232 * DESCRIPTION:
1233 *
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
1237 * count threshold.
1238 *
1239 * The timer is in millisecond units with +/- 33% accuracy.
1240 *
1241 * ARGUMENTS:
1242 *
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
1245 * to be called.
1246 *
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.
1250 *
1251 * RETURN VALUE:
1252 *
1253 * None.
1254 *
1255 * NOTES:
1256 *
1257 * None.
1258 *
1259 ******************************************************************************/
1260 void
1261 XDmaChannel_SetPktWaitBound(XDmaChannel * InstancePtr, u32 WaitBound)
1262 {
1263         /* assert to verify input arguments */
1264
1265         XASSERT_VOID(InstancePtr != NULL);
1266         XASSERT_VOID(WaitBound < 1024);
1267         XASSERT_VOID(InstancePtr->IsReady == XCOMPONENT_IS_READY);
1268
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
1271          * amount of time
1272          */
1273         XIo_Out32(InstancePtr->RegBaseAddress + XDC_PWB_REG_OFFSET, WaitBound);
1274 }
1275
1276 /******************************************************************************
1277 *
1278 * FUNCTION:
1279 *
1280 * XDmaChannel_GetPktWaitBound
1281 *
1282 * DESCRIPTION:
1283 *
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
1287 * count threshold.
1288 *
1289 * The timer is in millisecond units with +/- 33% accuracy.
1290 *
1291 * ARGUMENTS:
1292 *
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
1295 * to be called.
1296 *
1297 * RETURN VALUE:
1298 *
1299 * The packet wait bound register contents for the DMA channel.
1300 *
1301 * NOTES:
1302 *
1303 * None.
1304 *
1305 ******************************************************************************/
1306 u32
1307 XDmaChannel_GetPktWaitBound(XDmaChannel * InstancePtr)
1308 {
1309         /* assert to verify input arguments */
1310
1311         XASSERT_NONVOID(InstancePtr != NULL);
1312         XASSERT_NONVOID(InstancePtr->IsReady == XCOMPONENT_IS_READY);
1313
1314         /* get the packet wait bound from the register and return it */
1315
1316         return XIo_In32(InstancePtr->RegBaseAddress + XDC_PWB_REG_OFFSET);
1317 }