source: rtems/bsps/powerpc/shared/vme/bspVmeDmaList.c @ 814eccb4

5
Last change on this file since 814eccb4 was 814eccb4, checked in by Sebastian Huber <sebastian.huber@…>, on 04/03/18 at 14:41:16

bsps: Move VME support to bsps

The VME support is only used by powerpc BSPs.

This patch is a part of the BSP source reorganization.

Update #3285.

  • Property mode set to 100644
File size: 7.3 KB
Line 
1/* bspVmeDmaList.c:
2 * implementation of generic parts of the 'linked-list VME DMA' API.
3 */
4
5/*
6 * Authorship
7 * ----------
8 * This software was created by
9 *     Till Straumann <strauman@slac.stanford.edu>, 2006, 2007,
10 *         Stanford Linear Accelerator Center, Stanford University.
11 *
12 * Acknowledgement of sponsorship
13 * ------------------------------
14 * This software was produced by
15 *     the Stanford Linear Accelerator Center, Stanford University,
16 *         under Contract DE-AC03-76SFO0515 with the Department of Energy.
17 *
18 * Government disclaimer of liability
19 * ----------------------------------
20 * Neither the United States nor the United States Department of Energy,
21 * nor any of their employees, makes any warranty, express or implied, or
22 * assumes any legal liability or responsibility for the accuracy,
23 * completeness, or usefulness of any data, apparatus, product, or process
24 * disclosed, or represents that its use would not infringe privately owned
25 * rights.
26 *
27 * Stanford disclaimer of liability
28 * --------------------------------
29 * Stanford University makes no representations or warranties, express or
30 * implied, nor assumes any liability for the use of this software.
31 *
32 * Stanford disclaimer of copyright
33 * --------------------------------
34 * Stanford University, owner of the copyright, hereby disclaims its
35 * copyright and all other rights in this software.  Hence, anyone may
36 * freely use it for any purpose without restriction.
37 *
38 * Maintenance of notices
39 * ----------------------
40 * In the interest of clarity regarding the origin and status of this
41 * SLAC software, this and all the preceding Stanford University notices
42 * are to remain affixed to any copy or derivative of this software made
43 * or distributed by the recipient and are to be affixed to any copy of
44 * software made or distributed by the recipient that contains a copy or
45 * derivative of this software.
46 *
47 * ------------------ SLAC Software Notices, Set 4 OTT.002a, 2004 FEB 03
48 */
49
50#include <stdint.h>
51#include <stdlib.h>
52#include <stdio.h>
53#include <string.h>
54
55#define DEBUG
56#include <bsp/VMEDMA.h>
57#include <bsp/bspVmeDmaList.h>
58#include "bspVmeDmaListP.h"
59
60
61typedef struct VMEDmaListNodeRec_ {
62        VMEDmaListNode  p, n;           /* linkage         */
63        DmaDescriptor   d;                      /* real descriptor */
64        void            *usrData;
65        VMEDmaListClass class;          /* pointer to 'class' record */
66} VMEDmaListNodeRec;
67
68#define LCHUNK  10
69
70#ifdef DEBUG
71static void
72lprint(VMEDmaListNode d)
73{
74        printf("n 0x%08lx, p: 0x%08lx, n: 0x%08lx d: 0x%08lx\n",
75                (uint32_t)d, (uint32_t)d->p, (uint32_t)d->n, (uint32_t)d->d);
76}
77#endif
78
79static VMEDmaListNode
80lalloc(VMEDmaListClass pc)
81{
82VMEDmaListNode rval;
83int i;
84
85        if ( !pc->freeList ) {
86                /* alloc block of 10 descriptors */
87                pc->freeList = calloc( (LCHUNK),  sizeof(*pc->freeList));
88
89                if ( ! (pc->freeList) ) {
90                        return 0;
91                }
92
93                /* link together and set 'class' pointer */
94                for (i=0; i<(LCHUNK)-1; i++) {
95                        pc->freeList[i].n     = &pc->freeList[i+1];
96                        pc->freeList[i].class = pc;
97                }
98                pc->freeList[i].n     = 0;
99                pc->freeList[i].class = pc;
100
101                /* Allocate 'real' descriptor memory */
102                if ( pc->desc_alloc ) {
103                        for (i=0; i<(LCHUNK); i++) {
104                                if ( ! (pc->freeList[i].d = pc->desc_alloc()) ) {
105                                        int j;
106                                        if ( pc->desc_free ) {
107                                                for (j=0; j<i; j++)
108                                                        pc->desc_free(pc->freeList[i].d);
109                                        }
110                                        free(pc->freeList);
111                                        pc->freeList = 0;
112                                        return 0;
113                                }
114                        }
115                } else {
116                        int      blksize;
117                        uint32_t algnmsk = pc->desc_align - 1;
118                        char     *memptr;
119
120                        /* ignore their 'free' method */
121                        pc->desc_free = 0;
122
123                        blksize  = (pc->desc_size + algnmsk) & ~algnmsk;
124
125                        if ( ! (memptr = malloc(blksize*(LCHUNK) + pc->desc_align - 1)) ) {
126                                free(pc->freeList);
127                                pc->freeList = 0;
128                                return 0;
129                        }
130
131                        /* align memory ptr; must not be freed() anymore */
132                        memptr = (char*)( ((uint32_t)memptr + algnmsk) & ~ algnmsk );
133
134                        for ( i = 0; i<(LCHUNK); i++, memptr+=blksize ) {
135                                memset(memptr, 0, blksize);
136                                pc->freeList[i].d = (DmaDescriptor)memptr;
137                        }
138                }
139        }
140        rval         = pc->freeList;
141        pc->freeList = pc->freeList->n;
142        rval->n      = rval->p = 0;
143        return rval;
144}
145
146static int
147lfree(VMEDmaListNode d)
148{
149        if ( d->p || d->n )
150                return -1;
151        d->n = d->class->freeList;
152        d->class->freeList = d;
153        return 0;
154}
155
156static int
157lenq(VMEDmaListNode a, VMEDmaListNode d)
158{
159        if ( a ) {
160                /* enqueue */
161                if ( d->n || d->p )
162                        return -1;
163                if ( (d->n = a->n) )
164                        a->n->p = d;
165                d->p = a;
166                a->n = d;
167        } else {
168                /* dequeue */
169                if ( d->n )
170                        d->n->p = d->p;
171                if ( d->p )
172                        d->p->n = d->n;
173                d->n = d->p = 0;
174        }
175        return 0;
176}
177
178
179int
180BSP_VMEDmaListDescriptorStartTool(volatile void *controller, int channel, VMEDmaListNode n)
181{
182        if ( !n )
183                return -1;
184        return n->class->desc_start(controller, channel, n->d);
185}
186
187VMEDmaListNode
188BSP_VMEDmaListDescriptorSetupTool(
189                VMEDmaListNode n,
190                uint32_t        attr_mask,
191                uint32_t        xfer_mode,
192                uint32_t        pci_addr,
193                uint32_t        vme_addr,
194                uint32_t        n_bytes)
195{
196        if ( !n )
197                return 0;
198
199        if ( n->class->desc_setup(n->d, attr_mask, xfer_mode, pci_addr, vme_addr, n_bytes) ) {
200                return 0;
201        }
202
203        return n;
204}
205
206VMEDmaListNode
207BSP_VMEDmaListDescriptorNewTool(
208                VMEDmaListClass pc,
209                uint32_t        attr_mask,
210                uint32_t        xfer_mode,
211                uint32_t        pci_addr,
212                uint32_t        vme_addr,
213                uint32_t        n_bytes)
214{
215VMEDmaListNode n;
216
217        if ( !(n=lalloc(pc)) )
218                return 0;       /* no memory */
219
220        if ( n->class->desc_init )
221                n->class->desc_init(n->d);
222
223        if ( n->class->desc_setup(n->d, attr_mask, xfer_mode, pci_addr, vme_addr, n_bytes) ) {
224                BSP_VMEDmaListDescriptorDestroy(n);
225                return 0;
226        }
227        return n;
228}
229
230int
231BSP_VMEDmaListDescriptorDestroy(BSP_VMEDmaListDescriptor p)
232{
233VMEDmaListNode d = p;
234        return lfree(d);
235}
236
237int
238BSP_VMEDmaListDestroy(BSP_VMEDmaListDescriptor p)
239{
240VMEDmaListNode d = p;
241VMEDmaListNode n;
242        while (d) {
243                n = d->n;
244                if ( BSP_VMEDmaListDescriptorEnq(0, d) ||
245                     BSP_VMEDmaListDescriptorDestroy(d) )
246                        return -1;
247                d = n;
248        }
249        return 0;
250}
251
252int
253BSP_VMEDmaListDescriptorEnq(BSP_VMEDmaListDescriptor p, BSP_VMEDmaListDescriptor q)
254{
255VMEDmaListNode      anchor = p;
256VMEDmaListNode           d = q;
257DmaDescriptorSetNxt setnxt = d->class->desc_setnxt;
258
259        if ( !anchor ) {
260                /* dequeue can't fail - we can update dnlal first (need d->p) */
261                if ( d->p )
262                        setnxt(d->p->d, d->n ? d->n->d : 0);
263                /* paranoia */
264                setnxt(d->d, 0);
265        } else {
266                if ( d->class != anchor->class )
267                        return -1;
268        }
269        if ( lenq(anchor, d) )
270                return -1;
271        /* update descriptor pointers */
272        if ( anchor ) {
273                setnxt(d->d,      d->n ? d->n->d : 0);
274                setnxt(anchor->d, d->d);
275        }
276        return 0;
277}
278
279BSP_VMEDmaListDescriptor
280BSP_VMEDmaListDescriptorNext(BSP_VMEDmaListDescriptor p)
281{
282VMEDmaListNode d = p;
283        return d->n;
284}
285
286BSP_VMEDmaListDescriptor
287BSP_VMEDmaListDescriptorPrev(BSP_VMEDmaListDescriptor p)
288{
289VMEDmaListNode d = p;
290        return d->p;
291}
292
293void
294BSP_VMEDmaListDescriptorSetUsr(BSP_VMEDmaListDescriptor p, void *usrData)
295{
296VMEDmaListNode d = p;
297        d->usrData = usrData;
298}
299
300void *
301BSP_VMEDmaListDescriptorGetUsr(BSP_VMEDmaListDescriptor p)
302{
303VMEDmaListNode d = p;
304        return d->usrData;
305}
306
307int
308BSP_VMEDmaListRefresh(BSP_VMEDmaListDescriptor p)
309{
310VMEDmaListNode    anchor = p;
311DmaDescriptorRefr desc_refr;
312VMEDmaListNode    n;
313        if ( (desc_refr = anchor->class->desc_refr) ) {
314                for ( n = anchor; n; n = n->n ) {
315                        desc_refr(n->d);
316                }
317        }
318        return 0;
319}
320
321#ifdef DEBUG
322void
323BSP_VMEDmaListDump(BSP_VMEDmaListDescriptor p)
324{
325VMEDmaListNode d = p;
326        while (d) {
327                printf("----------\n");
328                lprint(d);
329                if (d->class->desc_dump)
330                        d->class->desc_dump(d->d);
331                d = d->n;
332        }
333}
334#endif
Note: See TracBrowser for help on using the repository browser.