diff options
author | Till Straumann <strauman@slac.stanford.edu> | 2007-01-31 04:02:52 +0000 |
---|---|---|
committer | Till Straumann <strauman@slac.stanford.edu> | 2007-01-31 04:02:52 +0000 |
commit | c1b34d5a9269ccdd35c581bc158acbe5888fec06 (patch) | |
tree | 482cc00ac4fba2706aa680b87eeebcc1c8de8df9 /c/src/lib/libbsp/shared/vmeUniverse/bspVmeDmaList.c | |
parent | 2007-01-29 Till Straumann <strauman@slac.stanford.edu> (diff) | |
download | rtems-c1b34d5a9269ccdd35c581bc158acbe5888fec06.tar.bz2 |
2007-01-30 Till Straumann <strauman@slac.stanford.edu>
* vmeUniverse/README.porting, vmeUniverse/README.universe:
updated, added more information for BSP implementors.
* vmeUniverse/VMEDMA.h (added): VME DMA API definition.
* vmeUniverse/bspVmeDmaList.h (added), vmeUniverse/bspVmeDmaListP.h (added),
* vmeUniverse/bspVmeDmaList.c (added):
Driver-independent code for linked-list DMA (public + private headers,
implementation).
* vmeUniverse/vmeUniverseDMA.h (added), vmeUniverse/vmeTsi148DMA.h (added):
interface to new DMA features of drivers.
* vmeUniverse/vme_amd_defs.h: Added definition for data-width
hint bits (VME_MODE_DBWxx).
* vmeUniverse/vmeTsi148.c: added DMA support. Added support for
data-width hint/modifier bits.
* vmeUniverse/vmeUniverse.c, vmeUniverse/vmeUniverse.h:
Added support for data-width hint/modifier bits.
Added support for xxx_BLT, xxx_MBLT address modifiers.
Restrict DBW to 32 in non-MBLT modes (except single-beat;
a comment is in README.universe). Updated DMA support to
implement new VMEDMA.h API. Added support for non-incrementing
VME addresses. Restrict data width to 32 for single-beat AMs
when the universe would use MBLT for DMA.
Diffstat (limited to 'c/src/lib/libbsp/shared/vmeUniverse/bspVmeDmaList.c')
-rw-r--r-- | c/src/lib/libbsp/shared/vmeUniverse/bspVmeDmaList.c | 335 |
1 files changed, 335 insertions, 0 deletions
diff --git a/c/src/lib/libbsp/shared/vmeUniverse/bspVmeDmaList.c b/c/src/lib/libbsp/shared/vmeUniverse/bspVmeDmaList.c new file mode 100644 index 0000000000..80a464b9bd --- /dev/null +++ b/c/src/lib/libbsp/shared/vmeUniverse/bspVmeDmaList.c @@ -0,0 +1,335 @@ +/* $Id$ */ + +/* bspVmeDmaList.c: + * implementation of generic parts of the 'linked-list VME DMA' API. + */ + +/* + * Authorship + * ---------- + * This software was created by + * Till Straumann <strauman@slac.stanford.edu>, 2006, 2007, + * Stanford Linear Accelerator Center, Stanford University. + * + * Acknowledgement of sponsorship + * ------------------------------ + * This software was produced by + * the Stanford Linear Accelerator Center, Stanford University, + * under Contract DE-AC03-76SFO0515 with the Department of Energy. + * + * Government disclaimer of liability + * ---------------------------------- + * Neither the United States nor the United States Department of Energy, + * nor any of their employees, makes any warranty, express or implied, or + * assumes any legal liability or responsibility for the accuracy, + * completeness, or usefulness of any data, apparatus, product, or process + * disclosed, or represents that its use would not infringe privately owned + * rights. + * + * Stanford disclaimer of liability + * -------------------------------- + * Stanford University makes no representations or warranties, express or + * implied, nor assumes any liability for the use of this software. + * + * Stanford disclaimer of copyright + * -------------------------------- + * Stanford University, owner of the copyright, hereby disclaims its + * copyright and all other rights in this software. Hence, anyone may + * freely use it for any purpose without restriction. + * + * Maintenance of notices + * ---------------------- + * In the interest of clarity regarding the origin and status of this + * SLAC software, this and all the preceding Stanford University notices + * are to remain affixed to any copy or derivative of this software made + * or distributed by the recipient and are to be affixed to any copy of + * software made or distributed by the recipient that contains a copy or + * derivative of this software. + * + * ------------------ SLAC Software Notices, Set 4 OTT.002a, 2004 FEB 03 + */ + +#include <stdint.h> +#include <stdlib.h> +#include <stdio.h> +#include <string.h> + +#include <bsp/bspVmeDmaList.h> +#include "bspVmeDmaListP.h" + +#define DEBUG + +typedef struct VMEDmaListNodeRec_ { + VMEDmaListNode p, n; /* linkage */ + DmaDescriptor d; /* real descriptor */ + void *usrData; + VMEDmaListClass class; /* pointer to 'class' record */ +} VMEDmaListNodeRec; + +#define LCHUNK 10 + +#ifdef DEBUG +static void +lprint(VMEDmaListNode d) +{ + printf("n 0x%08lx, p: 0x%08lx, n: 0x%08lx d: 0x%08lx\n", + (uint32_t)d, (uint32_t)d->p, (uint32_t)d->n, (uint32_t)d->d); +} +#endif + +static VMEDmaListNode +lalloc(VMEDmaListClass pc) +{ +VMEDmaListNode rval; +int i; + + if ( !pc->freeList ) { + /* alloc block of 10 descriptors */ + pc->freeList = calloc( (LCHUNK), sizeof(*pc->freeList)); + + if ( ! (pc->freeList) ) { + return 0; + } + + /* link together and set 'class' pointer */ + for (i=0; i<(LCHUNK)-1; i++) { + pc->freeList[i].n = &pc->freeList[i+1]; + pc->freeList[i].class = pc; + } + pc->freeList[i].n = 0; + pc->freeList[i].class = pc; + + /* Allocate 'real' descriptor memory */ + if ( pc->desc_alloc ) { + for (i=0; i<(LCHUNK); i++) { + if ( ! (pc->freeList[i].d = pc->desc_alloc()) ) { + int j; + if ( pc->desc_free ) { + for (j=0; j<i; j++) + pc->desc_free(pc->freeList[i].d); + } + free(pc->freeList); + pc->freeList = 0; + return 0; + } + } + } else { + int blksize; + uint32_t algnmsk = pc->desc_align - 1; + char *memptr; + + /* ignore their 'free' method */ + pc->desc_free = 0; + + blksize = (pc->desc_size + algnmsk) & ~algnmsk; + + if ( ! (memptr = malloc(blksize*(LCHUNK) + pc->desc_align - 1)) ) { + free(pc->freeList); + pc->freeList = 0; + return 0; + } + + /* align memory ptr; must not be freed() anymore */ + memptr = (char*)( ((uint32_t)memptr + algnmsk) & ~ algnmsk ); + + for ( i = 0; i<(LCHUNK); i++, memptr+=blksize ) { + memset(memptr, 0, blksize); + pc->freeList[i].d = (DmaDescriptor)memptr; + } + } + } + rval = pc->freeList; + pc->freeList = pc->freeList->n; + rval->n = rval->p = 0; + return rval; +} + +static int +lfree(VMEDmaListNode d) +{ + if ( d->p || d->n ) + return -1; + d->n = d->class->freeList; + d->class->freeList = d; + return 0; +} + +static int +lenq(VMEDmaListNode a, VMEDmaListNode d) +{ + if ( a ) { + /* enqueue */ + if ( d->n || d->p ) + return -1; + if ( (d->n = a->n) ) + a->n->p = d; + d->p = a; + a->n = d; + } else { + /* dequeue */ + if ( d->n ) + d->n->p = d->p; + if ( d->p ) + d->p->n = d->n; + d->n = d->p = 0; + } + return 0; +} + + +int +BSP_VMEDmaListDescriptorStartTool(volatile void *controller, int channel, VMEDmaListNode n) +{ + if ( !n ) + return -1; + return n->class->desc_start(controller, channel, n->d); +} + +VMEDmaListNode +BSP_VMEDmaListDescriptorSetupTool( + VMEDmaListNode n, + uint32_t attr_mask, + uint32_t xfer_mode, + uint32_t pci_addr, + uint32_t vme_addr, + uint32_t n_bytes) +{ + if ( !n ) + return 0; + + if ( n->class->desc_setup(n->d, attr_mask, xfer_mode, pci_addr, vme_addr, n_bytes) ) { + return 0; + } + + return n; +} + +VMEDmaListNode +BSP_VMEDmaListDescriptorNewTool( + VMEDmaListClass pc, + uint32_t attr_mask, + uint32_t xfer_mode, + uint32_t pci_addr, + uint32_t vme_addr, + uint32_t n_bytes) +{ +VMEDmaListNode n; + + if ( !(n=lalloc(pc)) ) + return 0; /* no memory */ + + if ( n->class->desc_init ) + n->class->desc_init(n->d); + + if ( n->class->desc_setup(n->d, attr_mask, xfer_mode, pci_addr, vme_addr, n_bytes) ) { + BSP_VMEDmaListDescriptorDestroy(n); + return 0; + } + return n; +} + +int +BSP_VMEDmaListDescriptorDestroy(BSP_VMEDmaListDescriptor p) +{ +VMEDmaListNode d = p; + return lfree(d); +} + +int +BSP_VMEDmaListDestroy(BSP_VMEDmaListDescriptor p) +{ +VMEDmaListNode d = p; +VMEDmaListNode n; + while (d) { + n = d->n; + if ( BSP_VMEDmaListDescriptorEnq(0, d) || + BSP_VMEDmaListDescriptorDestroy(d) ) + return -1; + d = n; + } + return 0; +} + +int +BSP_VMEDmaListDescriptorEnq(BSP_VMEDmaListDescriptor p, BSP_VMEDmaListDescriptor q) +{ +VMEDmaListNode anchor = p; +VMEDmaListNode d = q; +DmaDescriptorSetNxt setnxt = d->class->desc_setnxt; + + if ( !anchor ) { + /* dequeue can't fail - we can update dnlal first (need d->p) */ + if ( d->p ) + setnxt(d->p->d, d->n ? d->n->d : 0); + /* paranoia */ + setnxt(d->d, 0); + } else { + if ( d->class != anchor->class ) + return -1; + } + if ( lenq(anchor, d) ) + return -1; + /* update descriptor pointers */ + if ( anchor ) { + setnxt(d->d, d->n ? d->n->d : 0); + setnxt(anchor->d, d->d); + } + return 0; +} + +BSP_VMEDmaListDescriptor +BSP_VMEDmaListDescriptorNext(BSP_VMEDmaListDescriptor p) +{ +VMEDmaListNode d = p; + return d->n; +} + +BSP_VMEDmaListDescriptor +BSP_VMEDmaDescriptorPrev(BSP_VMEDmaListDescriptor p) +{ +VMEDmaListNode d = p; + return d->p; +} + +void +BSP_VMEDmaListDescriptorSetUsr(BSP_VMEDmaListDescriptor p, void *usrData) +{ +VMEDmaListNode d = p; + d->usrData = usrData; +} + +void * +BSP_VMEDmaListDescriptorGetUsr(BSP_VMEDmaListDescriptor p) +{ +VMEDmaListNode d = p; + return d->usrData; +} + +int +BSP_VMEDmaListRefresh(BSP_VMEDmaListDescriptor p) +{ +VMEDmaListNode anchor = p; +DmaDescriptorRefr desc_refr; +VMEDmaListNode n; + if ( (desc_refr = anchor->class->desc_refr) ) { + for ( n = anchor; n; n = n->n ) { + desc_refr(n->d); + } + } + return 0; +} + +#ifdef DEBUG +void +BSP_VMEDmaListDump(BSP_VMEDmaListDescriptor p) +{ +VMEDmaListNode d = p; + while (d) { + printf("----------\n"); + lprint(d); + if (d->class->desc_dump) + d->class->desc_dump(d->d); + d = d->n; + } +} +#endif |