OpenCores
URL https://opencores.org/ocsvn/1g_ethernet_dpi/1g_ethernet_dpi/trunk

Subversion Repositories 1g_ethernet_dpi

[/] [1g_ethernet_dpi/] [tags/] [v0.0/] [sw/] [dev/] [test_main/] [src/] [_hdl/] [bsp/] [libsrc/] [axidma_v9_0/] [src/] [xaxidma_bdring.c] - Blame information for rev 3

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 3 kuzmi4
/******************************************************************************
2
*
3
* Copyright (C) 2010 - 2015 Xilinx, Inc.  All rights reserved.
4
*
5
* Permission is hereby granted, free of charge, to any person obtaining a copy
6
* of this software and associated documentation files (the "Software"), to deal
7
* in the Software without restriction, including without limitation the rights
8
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
* copies of the Software, and to permit persons to whom the Software is
10
* furnished to do so, subject to the following conditions:
11
*
12
* The above copyright notice and this permission notice shall be included in
13
* all copies or substantial portions of the Software.
14
*
15
* Use of the Software is limited solely to applications:
16
* (a) running on a Xilinx device, or
17
* (b) that interact with a Xilinx device through a bus or interconnect.
18
*
19
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
22
* XILINX  BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
23
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
24
* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
25
* SOFTWARE.
26
*
27
* Except as contained in this notice, the name of the Xilinx shall not be used
28
* in advertising or otherwise to promote the sale, use or other dealings in
29
* this Software without prior written authorization from Xilinx.
30
*
31
******************************************************************************/
32
/*****************************************************************************/
33
/**
34
*
35
* @file xaxidma_bdring.c
36
* @addtogroup axidma_v9_0
37
* @{
38
*
39
* This file implements buffer descriptor ring related functions. For more
40
* information on how to manage the BD ring, please see xaxidma.h.
41
*
42
* <pre>
43
* MODIFICATION HISTORY:
44
*
45
* Ver   Who  Date     Changes
46
* ----- ---- -------- -------------------------------------------------------
47
* 1.00a jz   05/18/10 First release
48
* 2.00a jz   08/10/10 Second release, added in xaxidma_g.c, xaxidma_sinit.c,
49
*                     updated tcl file, added xaxidma_porting_guide.h
50
* 3.00a jz   11/22/10 Support IP core parameters change
51
* 5.00a srt  08/25/11 Added support for memory barrier.
52
* 6.00a srt  01/24/12 Added support for Multi-Channel DMA.
53
*                     - New API
54
*                       * XAxiDma_UpdateBdRingCDesc(XAxiDma_BdRing * RingPtr,
55
*                                               int RingIndex)
56
*                     - Changed APIs
57
*                       * XAxiDma_StartBdRingHw(XAxiDma_BdRing * RingPtr,
58
*                                       int RingIndex)
59
*                       * XAxiDma_BdRingStart(XAxiDma_BdRing * RingPtr,
60
*                                                int RingIndex)
61
*                       * XAxiDma_BdRingToHw(XAxiDma_BdRing * RingPtr,
62
*                               int NumBd, XAxiDma_Bd * BdSetPtr, int RingIndex)
63
*                       * XAxiDma_BdRingDumpRegs(XAxiDma_BdRing * RingPtr,
64
*                                                int RingIndex)
65
*                       * XAxiDma_BdRingSnapShotCurrBd(XAxiDma_BdRing * RingPtr,
66
*                                                int RingIndex)
67
* 7.00a srt  06/18/12  All the APIs changed in v6_00_a are reverted back for
68
*                      backward compatibility.
69
*
70
*
71
* </pre>
72
******************************************************************************/
73
 
74
/***************************** Include Files *********************************/
75
 
76
#include "xaxidma_bdring.h"
77
 
78
/************************** Constant Definitions *****************************/
79
/* Use 100 milliseconds for 100 MHz
80
 * This interval is sufficient for hardware to finish 40MB transfer with
81
 * 32-bit bus.
82
 */
83
#define XAXIDMA_STOP_TIMEOUT    500000   /* about 100 milliseconds on 100MHz */
84
 
85
/**************************** Type Definitions *******************************/
86
 
87
 
88
/***************** Macros (Inline Functions) Definitions *********************/
89
/* The following macros are helper functions inside this file.
90
 */
91
 
92
/******************************************************************************
93
 * Compute the physical address of a descriptor from its virtual address
94
 *
95
 * @param       BdPtr is the virtual address of the BD
96
 *
97
 * @returns     Physical address of BdPtr
98
 *
99
 * @note        Assume virtual and physical mapping is flat.
100
 *              RingPtr is an implicit parameter
101
 *
102
 *****************************************************************************/
103
#define XAXIDMA_VIRT_TO_PHYS(BdPtr) \
104
        ((UINTPTR)(BdPtr) + (RingPtr->FirstBdPhysAddr - RingPtr->FirstBdAddr))
105
 
106
/******************************************************************************
107
 * Move the BdPtr argument ahead an arbitrary number of BDs wrapping around
108
 * to the beginning of the ring if needed.
109
 *
110
 * We know if a wraparound should occur if the new BdPtr is greater than
111
 * the high address in the ring OR if the new BdPtr crosses the 0xFFFFFFFF
112
 * to 0 boundary.
113
 *
114
 * @param       RingPtr is the ring BdPtr appears in
115
 * @param       BdPtr on input is the starting BD position and on output is the
116
 *              final BD position
117
 * @param       NumBd is the number of BD spaces to increment
118
 *
119
 * @returns     None
120
 *
121
 * @note        This function can be used only when DMA is in SG mode
122
 *
123
 *****************************************************************************/
124
#define XAXIDMA_RING_SEEKAHEAD(RingPtr, BdPtr, NumBd)                \
125
    {                                                                \
126
        UINTPTR Addr = (UINTPTR)(void *)(BdPtr);                                     \
127
                                                                     \
128
        Addr += ((RingPtr)->Separation * (NumBd));                   \
129
        if ((Addr > (RingPtr)->LastBdAddr) || ((UINTPTR)(BdPtr) > Addr)) \
130
        {                                                            \
131
            Addr -= (RingPtr)->Length;                               \
132
        }                                                            \
133
                                                                     \
134
        (BdPtr) = (XAxiDma_Bd*)(void *)Addr;                                 \
135
    }
136
/******************************************************************************
137
 * Move the BdPtr argument backwards an arbitrary number of BDs wrapping
138
 * around to the end of the ring if needed.
139
 *
140
 * We know if a wraparound should occur if the new BdPtr is less than
141
 * the base address in the ring OR if the new BdPtr crosses the 0xFFFFFFFF
142
 * to 0 boundary.
143
 *
144
 * @param       RingPtr is the ring BdPtr appears in
145
 * @param       BdPtr on input is the starting BD position and on output is the
146
 *              final BD position
147
 * @param       NumBd is the number of BD spaces to increment
148
 *
149
 * @returns     None
150
 *
151
 * @note        This function can be used only when DMA is in SG mode
152
 *
153
 *****************************************************************************/
154
#define XAXIDMA_RING_SEEKBACK(RingPtr, BdPtr, NumBd)                  \
155
    {                                                                 \
156
        UINTPTR Addr = (UINTPTR)(BdPtr);                                      \
157
                                                                      \
158
        Addr -= ((RingPtr)->Separation * (NumBd));                    \
159
        if ((Addr < (RingPtr)->FirstBdAddr) || ((UINTPTR)(BdPtr) < Addr)) \
160
        {                                                             \
161
            Addr += (RingPtr)->Length;                                \
162
        }                                                             \
163
                                                                      \
164
        (BdPtr) = (XAxiDma_Bd*)Addr;                                  \
165
    }
166
 
167
/************************** Function Prototypes ******************************/
168
 
169
/************************** Variable Definitions *****************************/
170
 
171
 
172
/*****************************************************************************/
173
/**
174
 * Update Current Descriptor
175
 *
176
 * @param       RingPtr is the Channel instance to be worked on
177
 *
178
 * @return
179
 *              - XST_SUCCESS upon success
180
 *              - XST_DMA_ERROR if no valid BD available to put into current
181
 *              BD register
182
 *
183
 * @note        This function can be used only when DMA is in SG mode
184
 *
185
 *****************************************************************************/
186
int XAxiDma_UpdateBdRingCDesc(XAxiDma_BdRing* RingPtr)
187
{
188
        u32 RegBase;
189
        UINTPTR BdPtr;
190
        int RingIndex = RingPtr->RingIndex;
191
 
192
        /* BD list has yet to be created for this channel */
193
        if (RingPtr->AllCnt == 0) {
194
 
195
                xdbg_printf(XDBG_DEBUG_ERROR, "BdRingStart: no bds\r\n");
196
 
197
                return XST_DMA_SG_NO_LIST;
198
        }
199
 
200
        /* Do nothing if already started */
201
        if (RingPtr->RunState == AXIDMA_CHANNEL_NOT_HALTED) {
202
                /* Need to update tail pointer if needed (Engine is not
203
                 * transferring)
204
                 */
205
                return XST_SUCCESS;
206
        }
207
 
208
        if (!XAxiDma_BdRingHwIsStarted(RingPtr)) {
209
                /* If hardware is not running, then we need to put a valid current
210
                 * BD pointer to the current BD register before start the hardware
211
                 */
212
                RegBase = RingPtr->ChanBase;
213
 
214
                /* Put a valid BD pointer in the current BD pointer register
215
                 * So, the hardware is ready to go when tail BD pointer is updated
216
                 */
217
                BdPtr = (UINTPTR)(void *)(RingPtr->BdaRestart);
218
 
219
                if (!XAxiDma_BdHwCompleted(BdPtr)) {
220
                        if (RingPtr->IsRxChannel) {
221
                                if (!RingIndex) {
222
                                        XAxiDma_WriteReg(RegBase,
223
                                                         XAXIDMA_CDESC_OFFSET,
224
                                                         (u32)(BdPtr & XAXIDMA_DESC_LSB_MASK));
225
                                        if (RingPtr->Addr_ext)
226
                                                XAxiDma_WriteReg(RegBase,
227
                                                                 XAXIDMA_CDESC_MSB_OFFSET,
228
                                                                 UPPER_32_BITS(BdPtr));
229
                                }
230
                                else {
231
                                        XAxiDma_WriteReg(RegBase,
232
                                        (XAXIDMA_RX_CDESC0_OFFSET +
233
                                        (RingIndex - 1) * XAXIDMA_RX_NDESC_OFFSET),
234
                                        (u32)(BdPtr & XAXIDMA_DESC_LSB_MASK));
235
                                        if (RingPtr->Addr_ext)
236
                                                XAxiDma_WriteReg(RegBase,
237
                                                                 (XAXIDMA_RX_CDESC0_MSB_OFFSET +
238
                                                                 (RingIndex - 1) * XAXIDMA_RX_NDESC_OFFSET),
239
                                                                 UPPER_32_BITS(BdPtr));
240
                                }
241
                        }
242
                        else {
243
                                XAxiDma_WriteReg(RegBase,
244
                                                 XAXIDMA_CDESC_OFFSET,
245
                                                 (u32)(BdPtr & XAXIDMA_DESC_LSB_MASK));
246
                                if (RingPtr->Addr_ext)
247
                                        XAxiDma_WriteReg(RegBase, XAXIDMA_CDESC_MSB_OFFSET,
248
                                                         UPPER_32_BITS(BdPtr));
249
                        }
250
                }
251
                else {
252
                        /* Look for an uncompleted BD
253
                        */
254
                        while (XAxiDma_BdHwCompleted(BdPtr)) {
255
                                BdPtr = XAxiDma_BdRingNext(RingPtr, BdPtr);
256
 
257
                                if ((UINTPTR)BdPtr == (UINTPTR) RingPtr->BdaRestart) {
258
                                        xdbg_printf(XDBG_DEBUG_ERROR,
259
                                        "StartBdRingHw: Cannot find valid cdesc\r\n");
260
 
261
                                        return XST_DMA_ERROR;
262
                                }
263
 
264
                                if (!XAxiDma_BdHwCompleted(BdPtr)) {
265
                                        if (RingPtr->IsRxChannel) {
266
                                                if (!RingIndex) {
267
                                                        XAxiDma_WriteReg(RegBase,
268
                                                                XAXIDMA_CDESC_OFFSET,(u32) (BdPtr & XAXIDMA_DESC_LSB_MASK));
269
                                                        if (RingPtr->Addr_ext)
270
                                                                XAxiDma_WriteReg(RegBase, XAXIDMA_CDESC_MSB_OFFSET,
271
                                                                        UPPER_32_BITS(BdPtr));
272
                                                }
273
                                                else {
274
                                                        XAxiDma_WriteReg(RegBase,
275
                                                                (XAXIDMA_RX_CDESC0_OFFSET +
276
                                                                (RingIndex - 1) * XAXIDMA_RX_NDESC_OFFSET),
277
                                                                (u32)(BdPtr & XAXIDMA_DESC_LSB_MASK));
278
                                                        if (RingPtr->Addr_ext)
279
                                                                XAxiDma_WriteReg(RegBase,
280
                                                                        (XAXIDMA_RX_CDESC0_MSB_OFFSET +
281
                                                                        (RingIndex - 1) * XAXIDMA_RX_NDESC_OFFSET),
282
                                                                        UPPER_32_BITS(BdPtr));
283
                                                }
284
                                        }
285
                                        else {
286
                                                XAxiDma_WriteReg(RegBase,
287
                                                                XAXIDMA_CDESC_OFFSET, (u32)(BdPtr & XAXIDMA_DESC_LSB_MASK));
288
                                                if (RingPtr->Addr_ext)
289
                                                        XAxiDma_WriteReg(RegBase, XAXIDMA_CDESC_MSB_OFFSET,
290
                                                                         UPPER_32_BITS(BdPtr));
291
                                        }
292
                                        break;
293
                                }
294
                        }
295
                }
296
 
297
        }
298
 
299
        return XST_SUCCESS;
300
}
301
 
302
/*****************************************************************************/
303
/**
304
 * Using a memory segment allocated by the caller, This fundtion creates and
305
 * setup the BD ring.
306
 *
307
 * @param       RingPtr is the BD ring instance to be worked on.
308
 * @param       PhysAddr is the physical base address of application memory
309
 *              region.
310
 * @param       VirtAddr is the virtual base address of the application memory
311
 *              region.If address translation is not being utilized, then
312
 *              VirtAddr should be equivalent to PhysAddr.
313
 * @param       Alignment governs the byte alignment of individual BDs. This
314
 *              function will enforce a minimum alignment of
315
 *              XAXIDMA_BD_MINIMUM_ALIGNMENT bytes with no maximum as long as
316
 *              it is specified as a power of 2.
317
 * @param       BdCount is the number of BDs to setup in the application memory
318
 *              region. It is assumed the region is large enough to contain the
319
 *              BDs.Refer to the "SGDMA Ring Creation" section  in xaxidma.h
320
 *              for more information. The minimum valid value for this
321
 *              parameter is 1.
322
 *
323
 * @return
324
 *              - XST_SUCCESS if initialization was successful
325
 *              - XST_NO_FEATURE if the provided instance is a non SGDMA type
326
 *              of DMA channel.
327
 *              - XST_INVALID_PARAM under any of the following conditions:
328
 *              1) BdCount is not positive
329
 *
330
 *              2) PhysAddr and/or VirtAddr are not aligned to the given
331
 *              Alignment parameter;
332
 *
333
 *              3) Alignment parameter does not meet minimum requirements or
334
 *              is not a power of 2 value.
335
 *
336
 *              - XST_DMA_SG_LIST_ERROR if the memory segment containing the
337
 *              list spans over address 0x00000000 in virtual address space.
338
 *
339
 * @note        This function can be used only when DMA is in SG mode
340
 *
341
 *****************************************************************************/
342
u32 XAxiDma_BdRingCreate(XAxiDma_BdRing *RingPtr, UINTPTR PhysAddr,
343
                        UINTPTR VirtAddr, u32 Alignment, int BdCount)
344
{
345
        int i;
346
        UINTPTR BdVirtAddr;
347
        UINTPTR BdPhysAddr;
348
 
349
        if (BdCount <= 0) {
350
 
351
                xdbg_printf(XDBG_DEBUG_ERROR, "BdRingCreate: non-positive BD"
352
                                " number %d\r\n", BdCount);
353
 
354
                return XST_INVALID_PARAM;
355
        }
356
 
357
        /* In case there is a failure prior to creating list, make sure the
358
         * following attributes are 0 to prevent calls to other SG functions
359
         * from doing anything
360
         */
361
        RingPtr->AllCnt = 0;
362
        RingPtr->FreeCnt = 0;
363
        RingPtr->HwCnt = 0;
364
        RingPtr->PreCnt = 0;
365
        RingPtr->PostCnt = 0;
366
 
367
        /* Make sure Alignment parameter meets minimum requirements */
368
        if (Alignment < XAXIDMA_BD_MINIMUM_ALIGNMENT) {
369
 
370
                xdbg_printf(XDBG_DEBUG_ERROR, "BdRingCreate: alignment too "
371
                "small %d, need to be at least %d\r\n", (int)Alignment,
372
                        XAXIDMA_BD_MINIMUM_ALIGNMENT);
373
 
374
                return XST_INVALID_PARAM;
375
        }
376
 
377
        /* Make sure Alignment is a power of 2 */
378
        if ((Alignment - 1) & Alignment) {
379
 
380
                xdbg_printf(XDBG_DEBUG_ERROR, "BdRingCreate: alignment not"
381
                                " valid %d\r\n", (int)Alignment);
382
 
383
                return XST_INVALID_PARAM;
384
        }
385
 
386
        /* Make sure PhysAddr and VirtAddr are on same Alignment */
387
        if ((PhysAddr % Alignment) || (VirtAddr % Alignment)) {
388
 
389
                xdbg_printf(XDBG_DEBUG_ERROR, "BdRingCreate: Physical address"
390
                " %x and virtual address %x have different alignment\r\n",
391
                        (unsigned int)PhysAddr, (unsigned int)VirtAddr);
392
 
393
                return XST_INVALID_PARAM;
394
        }
395
 
396
        /* Compute how many bytes will be between the start of adjacent BDs */
397
        RingPtr->Separation =
398
                (sizeof(XAxiDma_Bd) + (Alignment - 1)) & ~(Alignment - 1);
399
 
400
        /* Must make sure the ring doesn't span address 0x00000000. If it does,
401
         * then the next/prev BD traversal macros will fail.
402
         */
403
        if (VirtAddr > (VirtAddr + (RingPtr->Separation * BdCount) - 1)) {
404
 
405
                xdbg_printf(XDBG_DEBUG_ERROR, "BdRingCreate: BD space cross "
406
                        "0x0\r\n");
407
 
408
                return XST_DMA_SG_LIST_ERROR;
409
        }
410
 
411
        /* Initial ring setup:
412
         *  - Clear the entire space
413
         *  - Setup each BD's next pointer with the physical address of the
414
         *    next BD
415
         *  - Put hardware information in each BD
416
         */
417
        memset((void *) VirtAddr, 0, (RingPtr->Separation * BdCount));
418
 
419
        BdVirtAddr = VirtAddr;
420
        BdPhysAddr = PhysAddr + RingPtr->Separation;
421
        for (i = 1; i < BdCount; i++) {
422
                XAxiDma_BdWrite(BdVirtAddr, XAXIDMA_BD_ADDRLEN_OFFSET,
423
                                RingPtr->Addr_ext);
424
                XAxiDma_BdWrite(BdVirtAddr, XAXIDMA_BD_NDESC_OFFSET,
425
                                (BdPhysAddr & XAXIDMA_DESC_LSB_MASK));
426
                XAxiDma_BdWrite(BdVirtAddr, XAXIDMA_BD_NDESC_MSB_OFFSET,
427
                                UPPER_32_BITS(BdPhysAddr));
428
 
429
                /* Put hardware information in the BDs
430
                 */
431
                XAxiDma_BdWrite(BdVirtAddr, XAXIDMA_BD_HAS_STSCNTRL_OFFSET,
432
                                (u32)RingPtr->HasStsCntrlStrm);
433
 
434
                XAxiDma_BdWrite(BdVirtAddr, XAXIDMA_BD_HAS_DRE_OFFSET,
435
                    (((u32)(RingPtr->HasDRE)) << XAXIDMA_BD_HAS_DRE_SHIFT) |
436
                    RingPtr->DataWidth);
437
 
438
                XAXIDMA_CACHE_FLUSH(BdVirtAddr);
439
                BdVirtAddr += RingPtr->Separation;
440
                BdPhysAddr += RingPtr->Separation;
441
        }
442
 
443
        /* At the end of the ring, link the last BD back to the top */
444
        XAxiDma_BdWrite(BdVirtAddr, XAXIDMA_BD_ADDRLEN_OFFSET,
445
                        RingPtr->Addr_ext);
446
        XAxiDma_BdWrite(BdVirtAddr, XAXIDMA_BD_NDESC_OFFSET,
447
                        (PhysAddr & XAXIDMA_DESC_LSB_MASK));
448
        XAxiDma_BdWrite(BdVirtAddr, XAXIDMA_BD_NDESC_MSB_OFFSET,
449
                        UPPER_32_BITS(PhysAddr));
450
 
451
 
452
        /* Setup the last BD's hardware information */
453
        XAxiDma_BdWrite(BdVirtAddr, XAXIDMA_BD_HAS_STSCNTRL_OFFSET,
454
                (u32)RingPtr->HasStsCntrlStrm);
455
 
456
        XAxiDma_BdWrite(BdVirtAddr, XAXIDMA_BD_HAS_DRE_OFFSET,
457
            (((u32)(RingPtr->HasDRE)) << XAXIDMA_BD_HAS_DRE_SHIFT) |
458
            RingPtr->DataWidth);
459
 
460
        /* Setup and initialize pointers and counters */
461
        RingPtr->RunState = AXIDMA_CHANNEL_HALTED;
462
        RingPtr->FirstBdAddr = VirtAddr;
463
        RingPtr->FirstBdPhysAddr = PhysAddr;
464
        RingPtr->LastBdAddr = BdVirtAddr;
465
        RingPtr->Length = RingPtr->LastBdAddr - RingPtr->FirstBdAddr +
466
                RingPtr->Separation;
467
        RingPtr->AllCnt = BdCount;
468
        RingPtr->FreeCnt = BdCount;
469
        RingPtr->FreeHead = (XAxiDma_Bd *) VirtAddr;
470
        RingPtr->PreHead = (XAxiDma_Bd *) VirtAddr;
471
        RingPtr->HwHead = (XAxiDma_Bd *) VirtAddr;
472
        RingPtr->HwTail = (XAxiDma_Bd *) VirtAddr;
473
        RingPtr->PostHead = (XAxiDma_Bd *) VirtAddr;
474
        RingPtr->BdaRestart = (XAxiDma_Bd *) PhysAddr;
475
 
476
        return XST_SUCCESS;
477
}
478
 
479
/*****************************************************************************/
480
/**
481
 * Clone the given BD into every BD in the ring. Only the fields offset from
482
 * XAXIDMA_BD_START_CLEAR are copied, for XAXIDMA_BD_BYTES_TO_CLEAR bytes.
483
 * This covers: BufferAddr, Control/Buffer length, status, APP words 0 - 4,
484
 * and software ID fields.
485
 *
486
 * This function can be called only when all BDs are in the free group such as
487
 * immediately after creation of the ring. This prevents modification
488
 * of BDs while they are in use by hardware or the application.
489
 *
490
 * @param       RingPtr is the BD ring instance to be worked on.
491
 * @param       SrcBdPtr is the source BD template to be cloned into the list.
492
 *
493
 * @return
494
 *              - XST_SUCCESS if the list was modified.
495
 *              - XST_DMA_SG_NO_LIST if a list has not been created.
496
 *              - XST_DEVICE_IS_STARTED if the DMA channel has not been stopped.
497
 *              - XST_DMA_SG_LIST_ERROR if some of the BDs in this channel are
498
 *              under hardware or application control.
499
 *
500
 * @note        This function can be used only when DMA is in SG mode
501
 *
502
 *****************************************************************************/
503
int XAxiDma_BdRingClone(XAxiDma_BdRing * RingPtr, XAxiDma_Bd * SrcBdPtr)
504
{
505
        int i;
506
        UINTPTR CurBd;
507
        u32 Save;
508
        XAxiDma_Bd TmpBd;
509
 
510
        /* Can't do this function if there isn't a ring */
511
        if (RingPtr->AllCnt == 0) {
512
 
513
                xdbg_printf(XDBG_DEBUG_ERROR, "BdRingClone: no bds\r\n");
514
 
515
                return XST_DMA_SG_NO_LIST;
516
        }
517
 
518
        /* Can't do this function with the channel running */
519
        if (RingPtr->RunState == AXIDMA_CHANNEL_NOT_HALTED) {
520
 
521
                xdbg_printf(XDBG_DEBUG_ERROR, "BdRingClone: bd ring started "
522
                        "already, cannot do\r\n");
523
 
524
                return XST_DEVICE_IS_STARTED;
525
        }
526
 
527
        /* Can't do this function with some of the BDs in use */
528
        if (RingPtr->FreeCnt != RingPtr->AllCnt) {
529
 
530
                xdbg_printf(XDBG_DEBUG_ERROR, "BdRingClone: some bds already "
531
                        "in use %d/%d\r\n",RingPtr->FreeCnt, RingPtr->AllCnt);
532
 
533
                return XST_DMA_SG_LIST_ERROR;
534
        }
535
 
536
        /* Make a copy of the template then modify it by clearing
537
         * the complete bit in status/control field
538
         */
539
        memcpy(&TmpBd, SrcBdPtr, sizeof(XAxiDma_Bd));
540
 
541
        Save = XAxiDma_BdRead(&TmpBd, XAXIDMA_BD_STS_OFFSET);
542
        Save &= ~XAXIDMA_BD_STS_COMPLETE_MASK;
543
        XAxiDma_BdWrite(&TmpBd, XAXIDMA_BD_STS_OFFSET, Save);
544
 
545
        for (i = 0, CurBd = RingPtr->FirstBdAddr;
546
             i < RingPtr->AllCnt; i++, CurBd += RingPtr->Separation) {
547
 
548
                memcpy((void *)((UINTPTR)CurBd + XAXIDMA_BD_START_CLEAR),
549
                    (void *)((UINTPTR)(&TmpBd) + XAXIDMA_BD_START_CLEAR),
550
                    XAXIDMA_BD_BYTES_TO_CLEAR);
551
 
552
                XAXIDMA_CACHE_FLUSH(CurBd);
553
        }
554
 
555
        return XST_SUCCESS;
556
}
557
 
558
/*****************************************************************************/
559
/**
560
 * Start a DMA channel and
561
 * Allow DMA transactions to commence on a given channel if descriptors are
562
 * ready to be processed.
563
 *
564
 * After a DMA channel is started, it is not halted, and it is idle (no active
565
 * DMA transfers).
566
 *
567
 * @param       RingPtr is the Channel instance to be worked on
568
 *
569
 * @return
570
 *              - XST_SUCCESS upon success
571
 *              - XST_DMA_ERROR if no valid BD available to put into current
572
 *              BD register
573
 *
574
 * @note        This function can be used only when DMA is in SG mode
575
 *
576
 *****************************************************************************/
577
int XAxiDma_StartBdRingHw(XAxiDma_BdRing * RingPtr)
578
{
579
        u32 RegBase;
580
        int RingIndex = RingPtr->RingIndex;
581
 
582
        if (!XAxiDma_BdRingHwIsStarted(RingPtr)) {
583
                /* Start the hardware
584
                */
585
                RegBase = RingPtr->ChanBase;
586
                XAxiDma_WriteReg(RegBase, XAXIDMA_CR_OFFSET,
587
                        XAxiDma_ReadReg(RegBase, XAXIDMA_CR_OFFSET)
588
                        | XAXIDMA_CR_RUNSTOP_MASK);
589
        }
590
 
591
        if (XAxiDma_BdRingHwIsStarted(RingPtr)) {
592
                /* Note as started */
593
                RingPtr->RunState = AXIDMA_CHANNEL_NOT_HALTED;
594
 
595
                /* If there are unprocessed BDs then we want the channel to begin
596
                 * processing right away
597
                 */
598
                if (RingPtr->HwCnt > 0) {
599
 
600
                        XAXIDMA_CACHE_INVALIDATE(RingPtr->HwTail);
601
 
602
                        if ((XAxiDma_BdRead(RingPtr->HwTail,
603
                                    XAXIDMA_BD_STS_OFFSET) &
604
                                XAXIDMA_BD_STS_COMPLETE_MASK) == 0) {
605
                                if (RingPtr->IsRxChannel) {
606
                                        if (!RingIndex) {
607
                                                XAxiDma_WriteReg(RingPtr->ChanBase,
608
                                                        XAXIDMA_TDESC_OFFSET, (XAXIDMA_VIRT_TO_PHYS(RingPtr->HwTail) & XAXIDMA_DESC_LSB_MASK));
609
                                                if (RingPtr->Addr_ext)
610
                                                        XAxiDma_WriteReg(RingPtr->ChanBase, XAXIDMA_TDESC_MSB_OFFSET,
611
                                                                 UPPER_32_BITS(XAXIDMA_VIRT_TO_PHYS(RingPtr->HwTail)));
612
                                        }
613
                                        else {
614
                                                XAxiDma_WriteReg(RingPtr->ChanBase,
615
                                                        (XAXIDMA_RX_TDESC0_OFFSET +
616
                                                        (RingIndex - 1) * XAXIDMA_RX_NDESC_OFFSET),
617
                                                        (XAXIDMA_VIRT_TO_PHYS(RingPtr->HwTail) & XAXIDMA_DESC_LSB_MASK ));
618
                                                if (RingPtr->Addr_ext)
619
                                                        XAxiDma_WriteReg(RingPtr->ChanBase,
620
                                                                (XAXIDMA_RX_TDESC0_MSB_OFFSET +
621
                                                                (RingIndex - 1) * XAXIDMA_RX_NDESC_OFFSET),
622
                                                                UPPER_32_BITS(XAXIDMA_VIRT_TO_PHYS(RingPtr->HwTail)));
623
                                        }
624
                                }
625
                                else {
626
                                        XAxiDma_WriteReg(RingPtr->ChanBase,
627
                                                        XAXIDMA_TDESC_OFFSET, (XAXIDMA_VIRT_TO_PHYS(RingPtr->HwTail) & XAXIDMA_DESC_LSB_MASK));
628
                                        if (RingPtr->Addr_ext)
629
                                                XAxiDma_WriteReg(RingPtr->ChanBase, XAXIDMA_TDESC_MSB_OFFSET,
630
                                                                 UPPER_32_BITS(XAXIDMA_VIRT_TO_PHYS(RingPtr->HwTail)));
631
                                }
632
                        }
633
                }
634
 
635
                return XST_SUCCESS;
636
        }
637
 
638
        return XST_DMA_ERROR;
639
}
640
 
641
/*****************************************************************************/
642
/**
643
 * Start a DMA channel, updates current descriptors and
644
 * Allow DMA transactions to commence on a given channel if descriptors are
645
 * ready to be processed.
646
 *
647
 * After a DMA channel is started, it is not halted, and it is idle (no active
648
 * DMA transfers).
649
 *
650
 * @param       RingPtr is the Channel instance to be worked on
651
 *
652
 * @return
653
 *              - XST_SUCCESS upon success
654
 *              - XST_DMA_ERROR if no valid BD available to put into current
655
 *              BD register
656
 *
657
 * @note        This function can be used only when DMA is in SG mode
658
 *
659
 *****************************************************************************/
660
int XAxiDma_BdRingStart(XAxiDma_BdRing * RingPtr)
661
{
662
        int Status;
663
 
664
        Status = XAxiDma_UpdateBdRingCDesc(RingPtr);
665
        if (Status != XST_SUCCESS) {
666
                 xdbg_printf(XDBG_DEBUG_ERROR, "BdRingStart: "
667
                        "Updating Current Descriptor Failed\n\r");
668
                return Status;
669
        }
670
 
671
        Status = XAxiDma_StartBdRingHw(RingPtr);
672
        if (Status != XST_SUCCESS) {
673
                 xdbg_printf(XDBG_DEBUG_ERROR, "BdRingStart: "
674
                        "Starting Hardware Failed\n\r");
675
                return Status;
676
        }
677
 
678
        return XST_SUCCESS;
679
}
680
 
681
/*****************************************************************************/
682
/**
683
 * Set interrupt coalescing parameters for the given descriptor ring channel.
684
 *
685
 * @param       RingPtr is a pointer to the descriptor ring instance to be
686
 *              worked on.
687
 * @param       Counter sets the packet counter on the channel. Valid range is
688
 *              - 1..255.
689
 *              - XAXIDMA_NO_CHANGE to leave this setting unchanged.
690
 * @param       Timer sets the waitbound timer on the channel. Valid range is
691
 *              - 0..255.
692
 *              - XAXIDMA_NO_CHANGE to leave this setting unchanged.
693
 *              Each unit depend on hardware building parameter
694
 *              C_DLYTMR_RESOLUTION,which is in the range from 0 to 100,000
695
 *              clock cycles. A value of 0 disables the delay interrupt.
696
 *
697
 * @return
698
 *              - XST_SUCCESS if interrupt coalescing settings updated
699
 *              - XST_FAILURE if Counter or Timer parameters are out of range
700
 *
701
 * @note        This function can be used only when DMA is in SG mode
702
 *
703
 *****************************************************************************/
704
int XAxiDma_BdRingSetCoalesce(XAxiDma_BdRing *RingPtr, u32 Counter, u32 Timer)
705
{
706
        u32 Cr;
707
 
708
        Cr = XAxiDma_ReadReg(RingPtr->ChanBase, XAXIDMA_CR_OFFSET);
709
 
710
        if (Counter != XAXIDMA_NO_CHANGE) {
711
                if ((Counter == 0) || (Counter > 0xFF)) {
712
 
713
                        xdbg_printf(XDBG_DEBUG_ERROR, "BdRingSetCoalesce: "
714
                        "invalid  coalescing threshold %d", (int)Counter);
715
                        return XST_FAILURE;
716
                }
717
 
718
                Cr = (Cr & ~XAXIDMA_COALESCE_MASK) |
719
                        (Counter << XAXIDMA_COALESCE_SHIFT);
720
        }
721
 
722
        if (Timer != XAXIDMA_NO_CHANGE) {
723
                if (Timer > 0xFF) {
724
 
725
                        xdbg_printf(XDBG_DEBUG_ERROR, "BdRingSetCoalesce: "
726
                        "invalid  delay counter %d", (int)Timer);
727
 
728
                        return XST_FAILURE;
729
                }
730
 
731
                Cr = (Cr & ~XAXIDMA_DELAY_MASK) |
732
                        (Timer << XAXIDMA_DELAY_SHIFT);
733
        }
734
 
735
        XAxiDma_WriteReg(RingPtr->ChanBase, XAXIDMA_CR_OFFSET, Cr);
736
 
737
        return XST_SUCCESS;
738
}
739
/*****************************************************************************/
740
/**
741
 * Retrieve current interrupt coalescing parameters from the given descriptor
742
 * ring channel.
743
 *
744
 * @param       RingPtr is a pointer to the descriptor ring instance to be
745
 *              worked on.
746
 * @param       CounterPtr points to a memory location where the current packet
747
 *              counter will be written.
748
 * @param       TimerPtr points to a memory location where the current
749
 *              waitbound timer will be written.
750
 *
751
 * @return      The passed in parameters, CounterPtr and TimerPtr, holds the
752
 *              references to the return values.
753
 *
754
 * @note        This function can be used only when DMA is in SG mode
755
 *
756
 *****************************************************************************/
757
void XAxiDma_BdRingGetCoalesce(XAxiDma_BdRing * RingPtr,
758
                              u32 *CounterPtr, u32 *TimerPtr)
759
{
760
        u32 Cr;
761
 
762
        Cr = XAxiDma_ReadReg(RingPtr->ChanBase, XAXIDMA_CR_OFFSET);
763
 
764
        *CounterPtr = ((Cr & XAXIDMA_COALESCE_MASK) >> XAXIDMA_COALESCE_SHIFT);
765
        *TimerPtr = ((Cr & XAXIDMA_DELAY_MASK) >> XAXIDMA_DELAY_SHIFT);
766
}
767
 
768
/*****************************************************************************/
769
/**
770
 * Reserve locations in the BD ring. The set of returned BDs may be modified in
771
 * preparation for future DMA transactions. Once the BDs are ready to be
772
 * submitted to hardware, the application must call XAxiDma_BdRingToHw() in the
773
 * same order which they were allocated here. Example:
774
 *
775
 * <pre>
776
 *        NumBd = 2;
777
 *        Status = XDsma_RingBdAlloc(MyRingPtr, NumBd, &MyBdSet);
778
 *
779
 *        if (Status != XST_SUCCESS)
780
 *        {
781
 *            // Not enough BDs available for the request
782
 *        }
783
 *
784
 *        CurBd = MyBdSet;
785
 *        for (i=0; i<NumBd; i++)
786
 *        {
787
 *            // Prepare CurBd.....
788
 *
789
 *            // Onto next BD
790
 *            CurBd = XAxiDma_BdRingNext(MyRingPtr, CurBd);
791
 *        }
792
 *
793
 *        // Give list to hardware
794
 *        Status = XAxiDma_BdRingToHw(MyRingPtr, NumBd, MyBdSet);
795
 * </pre>
796
 *
797
 * A more advanced use of this function may allocate multiple sets of BDs.
798
 * They must be allocated and given to hardware in the correct sequence:
799
 * <pre>
800
 *        // Legal
801
 *        XAxiDma_BdRingAlloc(MyRingPtr, NumBd1, &MySet1);
802
 *        XAxiDma_BdRingToHw(MyRingPtr, NumBd1, MySet1);
803
 *
804
 *        // Legal
805
 *        XAxiDma_BdRingAlloc(MyRingPtr, NumBd1, &MySet1);
806
 *        XAxiDma_BdRingAlloc(MyRingPtr, NumBd2, &MySet2);
807
 *        XAxiDma_BdRingToHw(MyRingPtr, NumBd1, MySet1);
808
 *        XAxiDma_BdRingToHw(MyRingPtr, NumBd2, MySet2);
809
 *
810
 *        // Not legal
811
 *        XAxiDma_BdRingAlloc(MyRingPtr, NumBd1, &MySet1);
812
 *        XAxiDma_BdRingAlloc(MyRingPtr, NumBd2, &MySet2);
813
 *        XAxiDma_BdRingToHw(MyRingPtr, NumBd2, MySet2);
814
 *        XAxiDma_BdRingToHw(MyRingPtr, NumBd1, MySet1);
815
 * </pre>
816
 *
817
 * Use the API defined in xaxidmabd.h to modify individual BDs. Traversal of
818
 * the BD set can be done using XAxiDma_BdRingNext() and XAxiDma_BdRingPrev().
819
 *
820
 * @param       RingPtr is a pointer to the descriptor ring instance to be
821
 *              worked on.
822
 * @param       NumBd is the number of BDs to allocate
823
 * @param       BdSetPtr is an output parameter, it points to the first BD
824
 *              available for modification.
825
 *
826
 * @return
827
 *              - XST_SUCCESS if the requested number of BDs were returned in
828
 *              the BdSetPtr parameter.
829
 *              - XST_INVALID_PARAM if passed in NumBd is not positive
830
 *              - XST_FAILURE if there were not enough free BDs to satisfy
831
 *              the request.
832
 *
833
 * @note        This function should not be preempted by another XAxiDma_BdRing
834
 *              function call that modifies the BD space. It is the caller's
835
 *              responsibility to provide a mutual exclusion mechanism.
836
 *
837
 *              Do not modify more BDs than the number requested with the NumBd
838
 *              parameter. Doing so will lead to data corruption and system
839
 *              instability.
840
 *
841
 *              This function can be used only when DMA is in SG mode
842
 *
843
 *****************************************************************************/
844
int XAxiDma_BdRingAlloc(XAxiDma_BdRing * RingPtr, int NumBd,
845
        XAxiDma_Bd ** BdSetPtr)
846
{
847
        if (NumBd <= 0) {
848
 
849
                xdbg_printf(XDBG_DEBUG_ERROR, "BdRingAlloc: negative BD "
850
                                "number %d\r\n", NumBd);
851
 
852
                return XST_INVALID_PARAM;
853
        }
854
 
855
        /* Enough free BDs available for the request? */
856
        if (RingPtr->FreeCnt < NumBd) {
857
                xdbg_printf(XDBG_DEBUG_ERROR,
858
                "Not enough BDs to alloc %d/%d\r\n", NumBd, RingPtr->FreeCnt);
859
 
860
                return XST_FAILURE;
861
        }
862
 
863
        /* Set the return argument and move FreeHead forward */
864
        *BdSetPtr = RingPtr->FreeHead;
865
        XAXIDMA_RING_SEEKAHEAD(RingPtr, RingPtr->FreeHead, NumBd);
866
        RingPtr->FreeCnt -= NumBd;
867
        RingPtr->PreCnt += NumBd;
868
 
869
        return XST_SUCCESS;
870
}
871
/*****************************************************************************/
872
/**
873
 * Fully or partially undo an XAxiDma_BdRingAlloc() operation. Use this
874
 * function if all the BDs allocated by XAxiDma_BdRingAlloc() could not be
875
 * transferred to hardware with XAxiDma_BdRingToHw().
876
 *
877
 * This function releases the BDs after they have been allocated but before
878
 * they have been given to hardware.
879
 *
880
 * This function is not the same as XAxiDma_BdRingFree(). The Free function
881
 * returns BDs to the free list after they have been processed by hardware,
882
 * while UnAlloc returns them before being processed by hardware.
883
 *
884
 * There are two scenarios where this function can be used. Full UnAlloc or
885
 * Partial UnAlloc. A Full UnAlloc means all the BDs Alloc'd will be returned:
886
 *
887
 * <pre>
888
 *    Status = XAxiDma_BdRingAlloc(MyRingPtr, 10, &BdPtr);
889
 *        ...
890
 *        ...
891
 *    if (Error)
892
 *    {
893
 *        Status = XAxiDma_BdRingUnAlloc(MyRingPtr, 10, &BdPtr);
894
 *    }
895
 * </pre>
896
 *
897
 * A partial UnAlloc means some of the BDs Alloc'd will be returned:
898
 *
899
 * <pre>
900
 *    Status = XAxiDma_BdRingAlloc(MyRingPtr, 10, &BdPtr);
901
 *    BdsLeft = 10;
902
 *    CurBdPtr = BdPtr;
903
 *
904
 *    while (BdsLeft)
905
 *    {
906
 *       if (Error)
907
 *       {
908
 *          Status = XAxiDma_BdRingUnAlloc(MyRingPtr, BdsLeft, CurBdPtr);
909
 *       }
910
 *
911
 *       CurBdPtr = XAxiDma_BdRingNext(MyRingPtr, CurBdPtr);
912
 *       BdsLeft--;
913
 *    }
914
 * </pre>
915
 *
916
 * A partial UnAlloc must include the last BD in the list that was Alloc'd.
917
 *
918
 * @param       RingPtr is a pointer to the descriptor ring instance to be
919
 *              worked on.
920
 * @param       NumBd is the number of BDs to unallocate
921
 * @param       BdSetPtr points to the first of the BDs to be returned.
922
 *
923
 * @return
924
 *              - XST_SUCCESS if the BDs were unallocated.
925
 *              - XST_INVALID_PARAM if passed in NumBd is negative
926
 *              - XST_FAILURE if NumBd parameter was greater that the number of
927
 *              BDs in the preprocessing state.
928
 *
929
 * @note        This function should not be preempted by another XAxiDma ring
930
 *              function call that modifies the BD space. It is the caller's
931
 *              responsibility to provide a mutual exclusion mechanism.
932
 *
933
 *              This function can be used only when DMA is in SG mode
934
 *
935
 *****************************************************************************/
936
int XAxiDma_BdRingUnAlloc(XAxiDma_BdRing * RingPtr, int NumBd,
937
        XAxiDma_Bd * BdSetPtr)
938
{
939
        XAxiDma_Bd *TmpBd;
940
 
941
        if (NumBd <= 0) {
942
 
943
                xdbg_printf(XDBG_DEBUG_ERROR, "BdRingUnAlloc: negative BD"
944
                " number %d\r\n", NumBd);
945
 
946
                return XST_INVALID_PARAM;
947
        }
948
 
949
        /* Enough BDs in the preprocessing state for the request? */
950
        if (RingPtr->PreCnt < NumBd) {
951
                xdbg_printf(XDBG_DEBUG_ERROR,
952
                "Pre-allocated BDs less than requested %d/%d\r\n",
953
                RingPtr->PreCnt, NumBd);
954
 
955
                return XST_FAILURE;
956
        }
957
 
958
        /* The last BD in the BD set must has the FreeHead as its next BD.
959
         * Otherwise, this is not a valid operation.
960
         */
961
        TmpBd = BdSetPtr;
962
        XAXIDMA_RING_SEEKAHEAD(RingPtr, TmpBd, NumBd);
963
 
964
        if (TmpBd != RingPtr->FreeHead) {
965
                xdbg_printf(XDBG_DEBUG_ERROR,
966
                    "Unalloc does not go back to free head\r\n");
967
 
968
                return XST_FAILURE;
969
        }
970
 
971
        /* Set the return argument and move FreeHead backward */
972
        XAXIDMA_RING_SEEKBACK(RingPtr, RingPtr->FreeHead, NumBd);
973
        RingPtr->FreeCnt += NumBd;
974
        RingPtr->PreCnt -= NumBd;
975
 
976
        return XST_SUCCESS;
977
}
978
/*****************************************************************************/
979
/**
980
 * Enqueue a set of BDs to hardware that were previously allocated by
981
 * XAxiDma_BdRingAlloc(). Once this function returns, the argument BD set goes
982
 * under hardware control. Changes to these BDs should be held until they are
983
 * finished by hardware to avoid data corruption and system instability.
984
 *
985
 * For transmit, the set will be rejected if the last BD of the set does not
986
 * mark the end of a packet or the first BD does not mark the start of a packet.
987
 *
988
 * @param       RingPtr is a pointer to the descriptor ring instance to be
989
 *              worked on.
990
 * @param       NumBd is the number of BDs in the set.
991
 * @param       BdSetPtr is the first BD of the set to commit to hardware.
992
 *
993
 * @return
994
 *              - XST_SUCCESS if the set of BDs was accepted and enqueued to
995
 *              hardware
996
 *              - XST_INVALID_PARAM if passed in NumBd is negative
997
 *              - XST_FAILURE if the set of BDs was rejected because the first
998
 *              BD does not have its start-of-packet bit set, or the last BD
999
 *              does not have its end-of-packet bit set, or any one of the BDs
1000
 *              has 0 length.
1001
 *              - XST_DMA_SG_LIST_ERROR if this function was called out of
1002
 *              sequence with XAxiDma_BdRingAlloc()
1003
 *
1004
 * @note        This function should not be preempted by another XAxiDma ring
1005
 *              function call that modifies the BD space. It is the caller's
1006
 *              responsibility to provide a mutual exclusion mechanism.
1007
 *
1008
 *              This function can be used only when DMA is in SG mode
1009
 *
1010
 *****************************************************************************/
1011
int XAxiDma_BdRingToHw(XAxiDma_BdRing * RingPtr, int NumBd,
1012
        XAxiDma_Bd * BdSetPtr)
1013
{
1014
        XAxiDma_Bd *CurBdPtr;
1015
        int i;
1016
        u32 BdCr;
1017
        u32 BdSts;
1018
        int RingIndex = RingPtr->RingIndex;
1019
 
1020
        if (NumBd < 0) {
1021
 
1022
                xdbg_printf(XDBG_DEBUG_ERROR, "BdRingToHw: negative BD number "
1023
                        "%d\r\n", NumBd);
1024
 
1025
                return XST_INVALID_PARAM;
1026
        }
1027
 
1028
        /* If the commit set is empty, do nothing */
1029
        if (NumBd == 0) {
1030
                return XST_SUCCESS;
1031
        }
1032
 
1033
        /* Make sure we are in sync with XAxiDma_BdRingAlloc() */
1034
        if ((RingPtr->PreCnt < NumBd) || (RingPtr->PreHead != BdSetPtr)) {
1035
 
1036
                xdbg_printf(XDBG_DEBUG_ERROR, "Bd ring has problems\r\n");
1037
                return XST_DMA_SG_LIST_ERROR;
1038
        }
1039
 
1040
        CurBdPtr = BdSetPtr;
1041
        BdCr = XAxiDma_BdGetCtrl(CurBdPtr);
1042
        BdSts = XAxiDma_BdGetSts(CurBdPtr);
1043
 
1044
        /* In case of Tx channel, the first BD should have been marked
1045
         * as start-of-frame
1046
         */
1047
        if (!(RingPtr->IsRxChannel) && !(BdCr & XAXIDMA_BD_CTRL_TXSOF_MASK)) {
1048
 
1049
                xdbg_printf(XDBG_DEBUG_ERROR, "Tx first BD does not have "
1050
                                                                "SOF\r\n");
1051
 
1052
                return XST_FAILURE;
1053
        }
1054
 
1055
        /* Clear the completed status bit
1056
         */
1057
        for (i = 0; i < NumBd - 1; i++) {
1058
 
1059
                /* Make sure the length value in the BD is non-zero. */
1060
                if (XAxiDma_BdGetLength(CurBdPtr,
1061
                                RingPtr->MaxTransferLen) == 0) {
1062
 
1063
                        xdbg_printf(XDBG_DEBUG_ERROR, "0 length bd\r\n");
1064
 
1065
                        return XST_FAILURE;
1066
                }
1067
 
1068
                BdSts &=  ~XAXIDMA_BD_STS_COMPLETE_MASK;
1069
                XAxiDma_BdWrite(CurBdPtr, XAXIDMA_BD_STS_OFFSET, BdSts);
1070
 
1071
                /* Flush the current BD so DMA core could see the updates */
1072
                XAXIDMA_CACHE_FLUSH(CurBdPtr);
1073
 
1074
                CurBdPtr = (XAxiDma_Bd *)((void *)XAxiDma_BdRingNext(RingPtr, CurBdPtr));
1075
                BdCr = XAxiDma_BdRead(CurBdPtr, XAXIDMA_BD_CTRL_LEN_OFFSET);
1076
                BdSts = XAxiDma_BdRead(CurBdPtr, XAXIDMA_BD_STS_OFFSET);
1077
        }
1078
 
1079
        /* In case of Tx channel, the last BD should have EOF bit set */
1080
        if (!(RingPtr->IsRxChannel) && !(BdCr & XAXIDMA_BD_CTRL_TXEOF_MASK)) {
1081
 
1082
                xdbg_printf(XDBG_DEBUG_ERROR, "Tx last BD does not have "
1083
                                                                "EOF\r\n");
1084
 
1085
                return XST_FAILURE;
1086
        }
1087
 
1088
        /* Make sure the length value in the last BD is non-zero. */
1089
        if (XAxiDma_BdGetLength(CurBdPtr,
1090
                        RingPtr->MaxTransferLen) == 0) {
1091
 
1092
                xdbg_printf(XDBG_DEBUG_ERROR, "0 length bd\r\n");
1093
 
1094
                return XST_FAILURE;
1095
        }
1096
 
1097
        /* The last BD should also have the completed status bit cleared
1098
         */
1099
        BdSts &= ~XAXIDMA_BD_STS_COMPLETE_MASK;
1100
        XAxiDma_BdWrite(CurBdPtr, XAXIDMA_BD_STS_OFFSET, BdSts);
1101
 
1102
        /* Flush the last BD so DMA core could see the updates */
1103
        XAXIDMA_CACHE_FLUSH(CurBdPtr);
1104
        DATA_SYNC;
1105
 
1106
        /* This set has completed pre-processing, adjust ring pointers and
1107
         * counters
1108
         */
1109
        XAXIDMA_RING_SEEKAHEAD(RingPtr, RingPtr->PreHead, NumBd);
1110
        RingPtr->PreCnt -= NumBd;
1111
        RingPtr->HwTail = CurBdPtr;
1112
        RingPtr->HwCnt += NumBd;
1113
 
1114
        /* If it is running, signal the engine to begin processing */
1115
        if (RingPtr->RunState == AXIDMA_CHANNEL_NOT_HALTED) {
1116
                        if (RingPtr->IsRxChannel) {
1117
                                if (!RingIndex) {
1118
                                        XAxiDma_WriteReg(RingPtr->ChanBase,
1119
                                                        XAXIDMA_TDESC_OFFSET, (XAXIDMA_VIRT_TO_PHYS(RingPtr->HwTail) & XAXIDMA_DESC_LSB_MASK));
1120
                                        if (RingPtr->Addr_ext)
1121
                                                XAxiDma_WriteReg(RingPtr->ChanBase, XAXIDMA_TDESC_MSB_OFFSET,
1122
                                                                 UPPER_32_BITS(XAXIDMA_VIRT_TO_PHYS(RingPtr->HwTail)));
1123
                                }
1124
                                else {
1125
                                        XAxiDma_WriteReg(RingPtr->ChanBase,
1126
                                                (XAXIDMA_RX_TDESC0_OFFSET +
1127
                                                (RingIndex - 1) * XAXIDMA_RX_NDESC_OFFSET),
1128
                                                (XAXIDMA_VIRT_TO_PHYS(RingPtr->HwTail) & XAXIDMA_DESC_LSB_MASK ));
1129
                                        if (RingPtr->Addr_ext)
1130
                                                XAxiDma_WriteReg(RingPtr->ChanBase,
1131
                                                        (XAXIDMA_RX_TDESC0_MSB_OFFSET +
1132
                                                        (RingIndex - 1) * XAXIDMA_RX_NDESC_OFFSET),
1133
                                                        UPPER_32_BITS(XAXIDMA_VIRT_TO_PHYS(RingPtr->HwTail)));
1134
                                }
1135
                        }
1136
                        else {
1137
                                XAxiDma_WriteReg(RingPtr->ChanBase,
1138
                                                        XAXIDMA_TDESC_OFFSET, (XAXIDMA_VIRT_TO_PHYS(RingPtr->HwTail) & XAXIDMA_DESC_LSB_MASK));
1139
                                if (RingPtr->Addr_ext)
1140
                                        XAxiDma_WriteReg(RingPtr->ChanBase, XAXIDMA_TDESC_MSB_OFFSET,
1141
                                                                UPPER_32_BITS(XAXIDMA_VIRT_TO_PHYS(RingPtr->HwTail)));
1142
                        }
1143
        }
1144
 
1145
        return XST_SUCCESS;
1146
}
1147
 
1148
/*****************************************************************************/
1149
/**
1150
 * Returns a set of BD(s) that have been processed by hardware. The returned
1151
 * BDs may be examined by the application to determine the outcome of the DMA
1152
 * transactions. Once the BDs have been examined, the application must call
1153
 * XAxiDma_BdRingFree() in the same order which they were retrieved here.
1154
 *
1155
 * Example:
1156
 *
1157
 * <pre>
1158
 *        NumBd = XAxiDma_BdRingFromHw(MyRingPtr, XAXIDMA_ALL_BDS, &MyBdSet);
1159
 *
1160
 *        if (NumBd == 0)
1161
 *        {
1162
 *           // hardware has nothing ready for us yet
1163
 *        }
1164
 *
1165
 *        CurBd = MyBdSet;
1166
 *        for (i=0; i<NumBd; i++)
1167
 *        {
1168
 *           // Examine CurBd for post processing.....
1169
 *
1170
 *           // Onto next BD
1171
 *           CurBd = XAxiDma_BdRingNext(MyRingPtr, CurBd);
1172
 *        }
1173
 *
1174
 *        XAxiDma_BdRingFree(MyRingPtr, NumBd, MyBdSet); // Return the list
1175
 * </pre>
1176
 *
1177
 * A more advanced use of this function may allocate multiple sets of BDs.
1178
 * They must be retrieved from hardware and freed in the correct sequence:
1179
 * <pre>
1180
 *        // Legal
1181
 *        XAxiDma_BdRingFromHw(MyRingPtr, NumBd1, &MySet1);
1182
 *        XAxiDma_BdRingFree(MyRingPtr, NumBd1, MySet1);
1183
 *
1184
 *        // Legal
1185
 *        XAxiDma_BdRingFromHw(MyRingPtr, NumBd1, &MySet1);
1186
 *        XAxiDma_BdRingFromHw(MyRingPtr, NumBd2, &MySet2);
1187
 *        XAxiDma_BdRingFree(MyRingPtr, NumBd1, MySet1);
1188
 *        XAxiDma_BdRingFree(MyRingPtr, NumBd2, MySet2);
1189
 *
1190
 *        // Not legal
1191
 *        XAxiDma_BdRingFromHw(MyRingPtr, NumBd1, &MySet1);
1192
 *        XAxiDma_BdRingFromHw(MyRingPtr, NumBd2, &MySet2);
1193
 *        XAxiDma_BdRingFree(MyRingPtr, NumBd2, MySet2);
1194
 *        XAxiDma_BdRingFree(MyRingPtr, NumBd1, MySet1);
1195
 * </pre>
1196
 *
1197
 * If hardware has partially completed a packet spanning multiple BDs, then
1198
 * none of the BDs for that packet will be included in the results.
1199
 *
1200
 * @param       RingPtr is a pointer to the descriptor ring instance to be
1201
 *              worked on.
1202
 * @param       BdLimit is the maximum number of BDs to return in the set. Use
1203
 *              XAXIDMA_ALL_BDS to return all BDs that have been processed.
1204
 * @param       BdSetPtr is an output parameter, it points to the first BD
1205
 *              available for examination.
1206
 *
1207
 * @return      The number of BDs processed by hardware. A value of 0 indicates
1208
 *              that no data is available. No more than BdLimit BDs will be
1209
 *              returned.
1210
 *
1211
 * @note        Treat BDs returned by this function as read-only.
1212
 *
1213
 *              This function should not be preempted by another XAxiDma ring
1214
 *              function call that modifies the BD space. It is the caller's
1215
 *              responsibility to provide a mutual exclusion mechanism.
1216
 *
1217
 *              This function can be used only when DMA is in SG mode
1218
 *
1219
 *****************************************************************************/
1220
int XAxiDma_BdRingFromHw(XAxiDma_BdRing * RingPtr, int BdLimit,
1221
                             XAxiDma_Bd ** BdSetPtr)
1222
{
1223
        XAxiDma_Bd *CurBdPtr;
1224
        int BdCount;
1225
        int BdPartialCount;
1226
        u32 BdSts;
1227
        u32 BdCr;
1228
 
1229
        CurBdPtr = RingPtr->HwHead;
1230
        BdCount = 0;
1231
        BdPartialCount = 0;
1232
        BdSts = 0;
1233
        BdCr = 0;
1234
 
1235
        /* If no BDs in work group, then there's nothing to search */
1236
        if (RingPtr->HwCnt == 0) {
1237
                *BdSetPtr = (XAxiDma_Bd *)NULL;
1238
 
1239
                return 0;
1240
        }
1241
 
1242
        if (BdLimit > RingPtr->HwCnt) {
1243
                BdLimit = RingPtr->HwCnt;
1244
        }
1245
 
1246
        /* Starting at HwHead, keep moving forward in the list until:
1247
         *  - A BD is encountered with its completed bit clear in the status
1248
         *    word which means hardware has not completed processing of that
1249
         *    BD.
1250
         *  - RingPtr->HwTail is reached
1251
         *  - The number of requested BDs has been processed
1252
         */
1253
 
1254
        while (BdCount < BdLimit) {
1255
                /* Read the status */
1256
                XAXIDMA_CACHE_INVALIDATE(CurBdPtr);
1257
                BdSts = XAxiDma_BdRead(CurBdPtr, XAXIDMA_BD_STS_OFFSET);
1258
                BdCr = XAxiDma_BdRead(CurBdPtr, XAXIDMA_BD_CTRL_LEN_OFFSET);
1259
 
1260
                /* If the hardware still hasn't processed this BD then we are
1261
                 * done
1262
                 */
1263
                if (!(BdSts & XAXIDMA_BD_STS_COMPLETE_MASK)) {
1264
                        break;
1265
                }
1266
 
1267
                BdCount++;
1268
 
1269
                /* Hardware has processed this BD so check the "last" bit. If
1270
                 * it is clear, then there are more BDs for the current packet.
1271
                 * Keep a count of these partial packet BDs.
1272
                 *
1273
                 * For tx BDs, EOF bit is in the control word
1274
                 * For rx BDs, EOF bit is in the status word
1275
                 */
1276
                if (((!(RingPtr->IsRxChannel) &&
1277
                (BdCr & XAXIDMA_BD_CTRL_TXEOF_MASK)) ||
1278
                ((RingPtr->IsRxChannel) && (BdSts &
1279
                        XAXIDMA_BD_STS_RXEOF_MASK)))) {
1280
 
1281
                        BdPartialCount = 0;
1282
                }
1283
                else {
1284
                        BdPartialCount++;
1285
                }
1286
 
1287
                /* Reached the end of the work group */
1288
                if (CurBdPtr == RingPtr->HwTail) {
1289
                        break;
1290
                }
1291
 
1292
                /* Move on to the next BD in work group */
1293
                CurBdPtr = (XAxiDma_Bd *)((void *)XAxiDma_BdRingNext(RingPtr, CurBdPtr));
1294
        }
1295
 
1296
        /* Subtract off any partial packet BDs found */
1297
        BdCount -= BdPartialCount;
1298
 
1299
        /* If BdCount is non-zero then BDs were found to return. Set return
1300
         * parameters, update pointers and counters, return success
1301
         */
1302
        if (BdCount) {
1303
                *BdSetPtr = RingPtr->HwHead;
1304
                RingPtr->HwCnt -= BdCount;
1305
                RingPtr->PostCnt += BdCount;
1306
                XAXIDMA_RING_SEEKAHEAD(RingPtr, RingPtr->HwHead, BdCount);
1307
 
1308
                return BdCount;
1309
        }
1310
        else {
1311
                *BdSetPtr = (XAxiDma_Bd *)NULL;
1312
 
1313
                return 0;
1314
        }
1315
}
1316
/*****************************************************************************/
1317
/**
1318
 * Frees a set of BDs that had been previously retrieved with
1319
 * XAxiDma_BdRingFromHw().
1320
 *
1321
 * @param       RingPtr is a pointer to the descriptor ring instance to be
1322
 *              worked on.
1323
 * @param       NumBd is the number of BDs to free.
1324
 * @param       BdSetPtr is the head of a list of BDs returned by
1325
 *              XAxiDma_BdRingFromHw().
1326
 *
1327
 * @return
1328
 *              - XST_SUCCESS if the set of BDs was freed.
1329
 *              - XST_INVALID_PARAM if NumBd is negative
1330
 *              - XST_DMA_SG_LIST_ERROR if this function was called out of
1331
 *              sequence with XAxiDma_BdRingFromHw().
1332
 *
1333
 * @note        This function should not be preempted by another XAxiDma
1334
 *              function call that modifies the BD space. It is the caller's
1335
 *              responsibility to ensure mutual exclusion.
1336
 *
1337
 *              This function can be used only when DMA is in SG mode
1338
 *
1339
 *****************************************************************************/
1340
int XAxiDma_BdRingFree(XAxiDma_BdRing * RingPtr, int NumBd,
1341
                      XAxiDma_Bd * BdSetPtr)
1342
{
1343
        if (NumBd < 0) {
1344
 
1345
                xdbg_printf(XDBG_DEBUG_ERROR,
1346
                    "BdRingFree: negative BDs %d\r\n", NumBd);
1347
 
1348
                return XST_INVALID_PARAM;
1349
        }
1350
 
1351
        /* If the BD Set to free is empty, do nothing
1352
         */
1353
        if (NumBd == 0) {
1354
                return XST_SUCCESS;
1355
        }
1356
 
1357
        /* Make sure we are in sync with XAxiDma_BdRingFromHw() */
1358
        if ((RingPtr->PostCnt < NumBd) || (RingPtr->PostHead != BdSetPtr)) {
1359
 
1360
                xdbg_printf(XDBG_DEBUG_ERROR, "BdRingFree: Error free BDs: "
1361
                "post count %d to free %d, PostHead %x to free ptr %x\r\n",
1362
                        RingPtr->PostCnt, NumBd,
1363
                        (UINTPTR)RingPtr->PostHead,
1364
                        (UINTPTR)BdSetPtr);
1365
 
1366
                return XST_DMA_SG_LIST_ERROR;
1367
        }
1368
 
1369
        /* Update pointers and counters */
1370
        RingPtr->FreeCnt += NumBd;
1371
        RingPtr->PostCnt -= NumBd;
1372
        XAXIDMA_RING_SEEKAHEAD(RingPtr, RingPtr->PostHead, NumBd);
1373
 
1374
        return XST_SUCCESS;
1375
}
1376
/*****************************************************************************/
1377
/**
1378
 * Check the internal data structures of the BD ring for the provided channel.
1379
 * The following checks are made:
1380
 *
1381
 *      - The BD ring is linked correctly in physical address space.
1382
 *      - The internal pointers point to BDs in the ring.
1383
 *      - The internal counters add up.
1384
 *
1385
 * The channel should be stopped (through XAxiDma_Pause() or XAxiDma_Reset())
1386
 * prior to calling this function.
1387
 *
1388
 * @param       RingPtr is a pointer to the descriptor ring to be worked on.
1389
 *
1390
 * @return
1391
 *              - XST_SUCCESS if no errors were found.
1392
 *              - XST_DMA_SG_NO_LIST if the ring has not been created.
1393
 *              - XST_IS_STARTED if the channel is not stopped.
1394
 *              - XST_DMA_SG_LIST_ERROR if a problem is found with the internal
1395
 *              data structures. If this value is returned, the channel should
1396
 *              be reset,and the BD ring should be recreated through
1397
 *              XAxiDma_BdRingCreate() to avoid data corruption or system
1398
 *              instability.
1399
 *
1400
 * @note        This function can be used only when DMA is in SG mode
1401
 *
1402
 *****************************************************************************/
1403
int XAxiDma_BdRingCheck(XAxiDma_BdRing * RingPtr)
1404
{
1405
        u32 AddrV;
1406
        u32 AddrP;
1407
        int i;
1408
 
1409
        /* Is the list created */
1410
        if (RingPtr->AllCnt == 0) {
1411
 
1412
                xdbg_printf(XDBG_DEBUG_ERROR, "BdRingCheck: no BDs\r\n");
1413
 
1414
                return XST_DMA_SG_NO_LIST;
1415
        }
1416
 
1417
        /* Can't check if channel is running */
1418
        if (RingPtr->RunState == AXIDMA_CHANNEL_NOT_HALTED) {
1419
 
1420
                xdbg_printf(XDBG_DEBUG_ERROR, "BdRingCheck: Bd ring is "
1421
                "running, cannot check it\r\n");
1422
 
1423
                return XST_IS_STARTED;
1424
        }
1425
 
1426
        /* RunState doesn't make sense */
1427
        else if (RingPtr->RunState != AXIDMA_CHANNEL_HALTED) {
1428
 
1429
                xdbg_printf(XDBG_DEBUG_ERROR, "BdRingCheck: unknown BD ring "
1430
                        "state %d ", RingPtr->RunState);
1431
 
1432
                return XST_DMA_SG_LIST_ERROR;
1433
        }
1434
 
1435
        /* Verify internal pointers point to correct memory space */
1436
        AddrV = (UINTPTR) RingPtr->FreeHead;
1437
        if ((AddrV < RingPtr->FirstBdAddr) || (AddrV > RingPtr->LastBdAddr)) {
1438
 
1439
                xdbg_printf(XDBG_DEBUG_ERROR, "BdRingCheck: FreeHead wrong "
1440
                "%x, should be in range of %x/%x\r\n",
1441
                    (unsigned int)AddrV,
1442
                    (unsigned int)RingPtr->FirstBdAddr,
1443
                        (unsigned int)RingPtr->LastBdAddr);
1444
 
1445
                return XST_DMA_SG_LIST_ERROR;
1446
        }
1447
 
1448
        AddrV = (UINTPTR) RingPtr->PreHead;
1449
        if ((AddrV < RingPtr->FirstBdAddr) || (AddrV > RingPtr->LastBdAddr)) {
1450
 
1451
                xdbg_printf(XDBG_DEBUG_ERROR, "BdRingCheck: PreHead wrong %x, "
1452
                        "should be in range of %x/%x\r\n",
1453
                    (unsigned int)AddrV,
1454
                    (unsigned int)RingPtr->FirstBdAddr,
1455
                        (unsigned int)RingPtr->LastBdAddr);
1456
 
1457
                return XST_DMA_SG_LIST_ERROR;
1458
        }
1459
 
1460
        AddrV = (UINTPTR) RingPtr->HwHead;
1461
        if ((AddrV < RingPtr->FirstBdAddr) || (AddrV > RingPtr->LastBdAddr)) {
1462
 
1463
                xdbg_printf(XDBG_DEBUG_ERROR, "BdRingCheck: HwHead wrong %x, "
1464
                        "should be in range of %x/%x\r\n",
1465
                    (unsigned int)AddrV,
1466
                    (unsigned int)RingPtr->FirstBdAddr,
1467
                        (unsigned int)RingPtr->LastBdAddr);
1468
 
1469
                return XST_DMA_SG_LIST_ERROR;
1470
        }
1471
 
1472
        AddrV = (UINTPTR) RingPtr->HwTail;
1473
        if ((AddrV < RingPtr->FirstBdAddr) || (AddrV > RingPtr->LastBdAddr)) {
1474
 
1475
                xdbg_printf(XDBG_DEBUG_ERROR, "BdRingCheck: HwTail wrong %x, "
1476
                        "should be in range of %x/%x\r\n",
1477
                    (unsigned int)AddrV,
1478
                    (unsigned int)RingPtr->FirstBdAddr,
1479
                        (unsigned int)RingPtr->LastBdAddr);
1480
 
1481
                return XST_DMA_SG_LIST_ERROR;
1482
        }
1483
 
1484
        AddrV = (UINTPTR) RingPtr->PostHead;
1485
        if ((AddrV < RingPtr->FirstBdAddr) || (AddrV > RingPtr->LastBdAddr)) {
1486
 
1487
                xdbg_printf(XDBG_DEBUG_ERROR, "BdRingCheck: PostHead wrong "
1488
                "%x, should be in range of %x/%x\r\n",
1489
                    (unsigned int)AddrV,
1490
                    (unsigned int)RingPtr->FirstBdAddr,
1491
                        (unsigned int)RingPtr->LastBdAddr);
1492
 
1493
                return XST_DMA_SG_LIST_ERROR;
1494
        }
1495
 
1496
        /* Verify internal counters add up */
1497
        if ((RingPtr->HwCnt + RingPtr->PreCnt + RingPtr->FreeCnt +
1498
             RingPtr->PostCnt) != RingPtr->AllCnt) {
1499
 
1500
                xdbg_printf(XDBG_DEBUG_ERROR, "BdRingCheck: internal counter "
1501
                        "error\r\n");
1502
 
1503
                return XST_DMA_SG_LIST_ERROR;
1504
        }
1505
 
1506
        /* Verify BDs are linked correctly */
1507
        AddrV = RingPtr->FirstBdAddr;
1508
        AddrP = RingPtr->FirstBdPhysAddr + RingPtr->Separation;
1509
        for (i = 1; i < RingPtr->AllCnt; i++) {
1510
                XAXIDMA_CACHE_INVALIDATE(AddrV);
1511
                /* Check next pointer for this BD. It should equal to the
1512
                 * physical address of next BD
1513
                 */
1514
                if (XAxiDma_BdRead(AddrV, XAXIDMA_BD_NDESC_OFFSET) != AddrP) {
1515
 
1516
                        xdbg_printf(XDBG_DEBUG_ERROR, "BdRingCheck: Next Bd "
1517
                        "ptr %x wrong, expect %x\r\n",
1518
                                (unsigned int)XAxiDma_BdRead(AddrV,
1519
                                XAXIDMA_BD_NDESC_OFFSET),
1520
                                (unsigned int)AddrP);
1521
 
1522
                        return XST_DMA_SG_LIST_ERROR;
1523
                }
1524
 
1525
                /* Move on to next BD */
1526
                AddrV += RingPtr->Separation;
1527
                AddrP += RingPtr->Separation;
1528
        }
1529
 
1530
        XAXIDMA_CACHE_INVALIDATE(AddrV);
1531
        /* Last BD should point back to the beginning of ring */
1532
        if (XAxiDma_BdRead(AddrV, XAXIDMA_BD_NDESC_OFFSET) !=
1533
            RingPtr->FirstBdPhysAddr) {
1534
 
1535
                xdbg_printf(XDBG_DEBUG_ERROR, "BdRingCheck: last Bd Next BD "
1536
                "ptr %x wrong, expect %x\r\n",
1537
                        (unsigned int)XAxiDma_BdRead(AddrV,
1538
                          XAXIDMA_BD_NDESC_OFFSET),
1539
                        (unsigned int)RingPtr->FirstBdPhysAddr);
1540
 
1541
                return XST_DMA_SG_LIST_ERROR;
1542
        }
1543
 
1544
        /* No problems found */
1545
        return XST_SUCCESS;
1546
}
1547
/*****************************************************************************/
1548
/**
1549
 * Dump the registers for a channel.
1550
 *
1551
 * @param       RingPtr is a pointer to the descriptor ring to be worked on.
1552
 *
1553
 * @return      None
1554
 *
1555
 * @note        This function can be used only when DMA is in SG mode
1556
 *
1557
 *****************************************************************************/
1558
void XAxiDma_BdRingDumpRegs(XAxiDma_BdRing *RingPtr) {
1559
        u32 RegBase = RingPtr->ChanBase;
1560
        int RingIndex = RingPtr->RingIndex;
1561
 
1562
        xil_printf("Dump registers %x:\r\n", (unsigned int)RegBase);
1563
        xil_printf("Control REG: %08x\r\n",
1564
                (unsigned int)XAxiDma_ReadReg(RegBase, XAXIDMA_CR_OFFSET));
1565
        xil_printf("Status REG: %08x\r\n",
1566
                (unsigned int)XAxiDma_ReadReg(RegBase, XAXIDMA_SR_OFFSET));
1567
 
1568
        if (RingIndex) {
1569
        xil_printf("Cur BD REG: %08x\r\n",
1570
                (unsigned int)XAxiDma_ReadReg(RegBase,
1571
                XAXIDMA_RX_CDESC0_OFFSET + ((RingIndex - 1) *
1572
                XAXIDMA_RX_NDESC_OFFSET)));
1573
        xil_printf("Tail BD REG: %08x\r\n",
1574
                (unsigned int)XAxiDma_ReadReg(RegBase,
1575
                XAXIDMA_RX_TDESC0_OFFSET + ((RingIndex - 1) *
1576
                XAXIDMA_RX_NDESC_OFFSET)));
1577
        }
1578
        else {
1579
        xil_printf("Cur BD REG: %08x\r\n",
1580
                (unsigned int)XAxiDma_ReadReg(RegBase, XAXIDMA_CDESC_OFFSET));
1581
        xil_printf("Tail BD REG: %08x\r\n",
1582
                (unsigned int)XAxiDma_ReadReg(RegBase, XAXIDMA_TDESC_OFFSET));
1583
        }
1584
 
1585
        xil_printf("\r\n");
1586
}
1587
/** @} */

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.