2007-01-29 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.
This commit is contained in:
Till Straumann
2007-01-30 07:30:12 +00:00
parent 018eb73f2f
commit 985082dff2
13 changed files with 2272 additions and 109 deletions

View File

@@ -1,3 +1,34 @@
2007-01-29 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.
2007-01-19 Till Straumann <strauman@slac.stanford.edu>
* Makefile.am, vmeUniverse/VME.h:

View File

@@ -1,6 +1,17 @@
#
# $Id$
#
#
NOTE: (T.S, 2007/1) The information in this file is outdated
(but some portions may still be useful). Some more information
about how to use the Universe and Tsi148 drivers in new BSPs
can be found in
README.universe,
libbsp/powerpc/shared/vme/VMEConfig.h,
source files in this directory and libbsp/powerpc/shared/vme
The vmeUniverse driver needs some support from the BSP for

View File

@@ -4,18 +4,62 @@ rtems CVS tree. The directory is called 'vmeUniverse'
for historic reasons. 'tundra' would be better
since we now support the tundra tsi148 as well...
Till Straumann <strauman@slac.stanford.edu> 1/2002, 2005
NOTES:
These driver are maintained _outside_ rtems.
Please forward future modifications to me.
Till Straumann <strauman@slac.stanford.edu> 1/2002, 2005, 2007
A BSP that wants to use these drivers
must implement the following headers / functionality:
- <bsp/pci.h> offering an API like 'libbsp/powerpc/shared/pci'
- <bsp/irq.h> offering the 'new style' RTEMS irq API
(like 'libbsp/powerpc/shared/irq').
- <libcpu/io.h> for the I/O operations (out_le32,in_le32, ..., out_be32,...)
- <libcpu/byteorder.h> for byte-swapping (st_le32, ld_le32, ..., st_be32,...)
- glue code that implements the 'VME.h' and 'VMEDMA.h' APIs
using the vmeUniverse and/or vmeTsi148 driver code.
The 'glue' code initializes appropriate VME/PCI windows when booting
and installs the VME interrupt manager.
The BSP should then use "VPATH magic" (to use Joel's
words :-) to reach the vmeUniverse.* / vmeTsi148.* files
in this subdir.
The 'glue' may also use the 'bspVmeDmaList' code to implement generic
parts of linked-list DMA.
Boards with a 'universe' chip may use a pretty generic version of
the glue code that is defined in libbsp/powerpc/shared/vmeconfig.c,
libbsp/powerpc/shared/vme_universe.c, and
libbsp/powerpc/shared/vme_universe_dma.c. The board-specific parameters
are defined in a single BSP-specific file 'VMEConfig.h'. That's where
the actual addresses of VME/PCI windows are configured and where
interrupt wires can be assigned etc.
Read libbsp/powerpc/shared/VMEConfig.h for more information and use
it as a template. Note that BSP implementors should try *not* to
clone 'vmeconfig.c' but use the constants in VMEConfig.h
- The BSP should export 'VME.h' and 'VMEDMA.h' to applications
and encourage them to only use the API defined there in order
to make application code driver-independent. This will ensure
seamless portability of applications between the universe and Tsi148
drivers.
TESTING: A valuable tool for testing are the (substitute XXX for
'Universe' or 'Tsi148') routines:
vmeXXXMapCRG()
maps the controller registers to VME space so you
can test if you successfully can read/write from VME.
You can read or DMA the PCI configuration registers
and compare to what you expect (beware of endianness).
vmeXXXIntLoopbackTest()
this installs an ISR and then asserts an IRQ on the VME
backplane so you can verify that your interrupt routing
and handling really works.
NOTES: The universe may always issue MBLTs if a data width of 64-bit
is enabled (default for non-BLT addressing modes -- the
VME_AM_STD_xx_BLT / VME_AM_EXT_xx_BLT enforce 32-bit transfers).
Therefore, if you want to setup a outbound window that always
uses single cycles then you must explicitely request a data
width < 64, e.g.,
vmeUniverseMasterPortCfg(port, VME_AM_EXT_SUP_DATA | VME_MODE_DBW32, vme_addr, pci_addr, size);

View File

@@ -0,0 +1,292 @@
/* $Id$ */
#ifndef BSP_VME_DMA_H
#define BSP_VME_DMA_H
/* Public interface of DMA routines */
/*
* 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>
#ifdef __cplusplus
extern "C" {
#endif
/* NOTE: Access to DMA Channels is *not* protected / thread-safe.
* It is the responsability of the user to provide appropriate
* locking/serialization.
*/
/* Simple abstraction of DMA controller setup / bus utilization: */
/* Since VME is the bottleneck, the settings for PCI are always
* chosen aggressively.
*/
/* Optimize for throughput; accept longer latencies:
* Choose a large block size (1k) and immediately re-request
* the bus at block boundaries.
*/
#define BSP_VMEDMA_OPT_THROUGHPUT 1
/* Optimize for latency, accept throughput penalty:
* Choose a small block size (32b) and immediately re-request
* the bus at block boundaries.
*/
#define BSP_VMEDMA_OPT_LOWLATENCY 2
/* Optimize for bus sharing with other devices:
* Choose relatively small block size (128) and back off for 64us
* at each block boundary.
*/
#define BSP_VMEDMA_OPT_SHAREDBUS 3
/* Choose bridge default/reset configuration:
* (see manual)
*/
#define BSP_VMEDMA_OPT_DEFAULT 4
/* Provide custom configuration pass pointer to array
* with as many 32-bit words the particular bridge chip
* expects.
*/
#define BSP_VMEDMA_OPT_CUSTOM 5
/* VME Transfer modes */
/* Bitwise OR of the VME address-modifier/transfer-type
* with driver specific (no standard AM code for 2eVME and
* 2eSST defined) and optional special flags (see below)
*/
/* Additional qualifiers: */
/* Don't increment VME address */
#define BSP_VMEDMA_MODE_NOINC_VME (1<<20)
/* Don't increment PCI address */
#define BSP_VMEDMA_MODE_NOINC_PCI (1<<21)
/* Direction */
#define BSP_VMEDMA_MODE_PCI2VME (1<<31)
typedef void *BSP_VMEDmaListDescriptor;
/* Program the device for the selected mode;
*
* 'bus_mode': one of the ...VMEDMA_OPT... choices
* listed above.
* 'xfer_mode': VME address-modifier optionally ORed with
* ...VMEDMA_MODE... bits listed above.
* 'custom': (only used if bus_mode is VMEDMA_OPT_CUSTOM)
* pointer to a list of setup parameters (chip-driver
* specific).
*
* RETURNS: 0 on success, nonzero on error (mode or channel
* unsupported).
*
* NOTES: The setup is preserved across multiple DMA transfers.
* It is the responsibility of the driver to reprogram
* the setup if the hardware does not preserve it.
* However - in linked list mode, some fields may be
* read from the list descriptors.
*
* Usually this routine must be used even in linked-list
* mode to program the 'bus_mode'.
*
* Direction of transfer is specified by a bit in the
* 'xfer_mode' (BSP_VMEDMA_MODE_PCI2VME).
*/
int
BSP_VMEDmaSetup(int channel, uint32_t bus_mode, uint32_t xfer_mode, void *custom_setup);
/* Start direct (not linked-list) transfer.
*
* RETURNS: 0 on success, nonzero on failure
*/
int
BSP_VMEDmaStart(int channel, uint32_t pci_addr, uint32_t vme_addr, uint32_t n_bytes);
/* Transfer status/result */
#define BSP_VMEDMA_STATUS_OK 0
/* Unsupported channel */
#define BSP_VMEDMA_STATUS_UNSUP (-1)
/* Bus error on VME */
#define BSP_VMEDMA_STATUS_BERR_VME 1
/* Bus error on PCI */
#define BSP_VMEDMA_STATUS_BERR_PCI 2
/* Channel busy */
#define BSP_VMEDMA_STATUS_BUSY 3
/* Setup/programming error */
#define BSP_VMEDMA_STATUS_PERR 4
/* Other/unspecified error */
#define BSP_VMEDMA_STATUS_OERR 5
/* Retrieve status of last transfer.
*
* RETURNS: 0 if the transfer was successful,
* nonzero on error (e.g., one of the
* values defined above).
*
* NOTE: Driver is allowed to pass other,
* device specific codes
*/
uint32_t
BSP_VMEDmaStatus(int channel);
/*
* Hook a callback (executed from ISR context) to DMA interrupt and
* enable it.
* If called with NULL callback then an existing callback is removed
* and the interrupt disabled.
*
* RETURNS: 0 on success, nonzero on failure (IRQ in use, unsupported
* channel).
*/
typedef void (*BSP_VMEDmaIRQCallback)(void *usr_arg);
int
BSP_VMEDmaInstallISR(int channel, BSP_VMEDmaIRQCallback cb, void *usr_arg);
/*
* DMA List operations.
*
* Note that the list is totally unprotected, i.e., the user is
* responsible for maintaining coherency against concurrent
* access by multiple threads or hardware.
* We assume the user builds/updates a list, hands it over to
* the hardware (list start command) and leaves it alone until
* the DMA controller is done with it.
*/
/* Modify a list entry. If the list element pointer is NULL
* then a new list element is allocated.
* Only the fields with its corresponding bit set in the mask
* argument are touched.
*
* RETURNS: 'd' or newly allocated descriptor or NULL (no memory,
* or invalid setup).
*/
#define BSP_VMEDMA_MSK_ATTR (1<<0)
#define BSP_VMEDMA_MSK_PCIA (1<<1)
#define BSP_VMEDMA_MSK_VMEA (1<<2)
#define BSP_VMEDMA_MSK_BCNT (1<<3)
#define BSP_VMEDMA_MSK_ALL (0xf)
BSP_VMEDmaListDescriptor
BSP_VMEDmaListDescriptorSetup(
BSP_VMEDmaListDescriptor d,
uint32_t attr_mask,
uint32_t xfer_mode,
uint32_t pci_addr,
uint32_t vme_addr,
uint32_t n_bytes);
/* De-allocate a list descriptor previously obtained by
* BSP_VMEDmaListDescriptorSetup(0,...);
*
* RETURNS: 0 on success, nonzero on failure (d currently on a list)
*/
int
BSP_VMEDmaListDescriptorDestroy(BSP_VMEDmaListDescriptor d);
/* Traverse a list of descriptors and destroy all elements */
int
BSP_VMEDmaListDestroy(BSP_VMEDmaListDescriptor anchor);
/* Enqueue a list descriptor 'd' after 'tail'
*
* If 'tail' is NULL then 'd' is removed from
* the list it is currently on.
*
* RETURNS: 0 on success, nonzero if 'd' is already
* on a list (enqueue) or if it is not currently
* on a list (dequeue).
*
* NOTE: it is obviously the user's responsibility to update
* list queue/tail pointers when changing the
* structure of the list.
*/
int
BSP_VMEDmaListDescriptorEnq(
BSP_VMEDmaListDescriptor tail,
BSP_VMEDmaListDescriptor d);
/* Obtain next and previous descriptors */
BSP_VMEDmaListDescriptor
BSP_VMEDmaListDescriptorNext(BSP_VMEDmaListDescriptor d);
BSP_VMEDmaListDescriptor
BSP_VMEDmaListDescriptorPrev(BSP_VMEDmaListDescriptor d);
/* Set and get a 'usrData' pointer in the descriptor */
void
BSP_VMEDmaListDescriptorSetUsr(BSP_VMEDmaListDescriptor d, void *usrData);
void *
BSP_VMEDmaListDescriptorGetUsr(BSP_VMEDmaListDescriptor d);
/* Refresh an entire list. Some DMA controllers modify certain
* fields (e.g., byte count) and this command restores the original
* setup.
*/
int
BSP_VMEDmaListRefresh(BSP_VMEDmaListDescriptor anchor);
/* Start linked-list operation.
*
* RETURNS: 0 on success, nonzero on failure
*/
int
BSP_VMEDmaListStart(int channel, BSP_VMEDmaListDescriptor list);
#ifdef __cplusplus
}
#endif
#endif

View File

@@ -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

View File

@@ -0,0 +1,130 @@
#ifndef BSP_VME_DMA_LIST_H
#define BSP_VME_DMA_LIST_H
/* $Id$ */
/* The bspVmeDmaList utility implements part of the API defined by
* 'VMEDMA.h' namely all 'VMEDmaListDescriptor' related entry points:
*
* BSP_VMEDmaListDescriptorDestroy(),
* BSP_VMEDmaListDestroy(),
* BSP_VMEDmaListDescriptorEnq(),
* BSP_VMEDmaListDescriptorNext(),
* BSP_VMEDmaListDescriptorPrev(),
* BSP_VMEDmaListDescriptorSetUsr(),
* BSP_VMEDmaListDescriptorGetUsr(),
* BSP_VMEDmaListRefresh()
*
* Also, it provides helper routines to assist BSPs with implementing
*
* BSP_VMEDmaListDescriptorSetup()
*
* and
*
* BSP_VMEDmaListStart()
*
* by providing
*
* BSP_VMEDmaListDescriptorNewTool(),
* BSP_VMEDmaListDescriptorSetupTool(),
*
* and
*
* BSP_VMEDmaListDescriptorStartTool()
*
* This header should only be used inside a BSP
* chosing to use bspVmeDmaList for implementing VMEDMA.h
*/
/*
* 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 <bsp/VMEDMA.h>
#ifdef __cplusplus
extern "C" {
#endif
typedef struct VMEDmaListNodeRec_ *VMEDmaListNode;
typedef struct VMEDmaListClassRec_ *VMEDmaListClass;
/* Create and setup a new descriptor.
* The BSP must supply the appropriate controller class.
*/
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);
/* Setup an existing descriptor */
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);
/* Start a list DMA transfer on 'controller'. The 'controller' information
* must be provided by the BSP.
*/
int
BSP_VMEDmaListDescriptorStartTool(volatile void *controller, int channel, VMEDmaListNode n);
#ifdef __cplusplus
}
#endif
#endif

View File

@@ -0,0 +1,96 @@
/* $Id$ */
#ifndef BSP_VME_DMA_LIST_P_H
#define BSP_VME_DMA_LIST_P_H
#include <bsp/bspVmeDmaList.h>
/* Private Interface to the bspVmeDmaList facility
*
* This is used by chip drivers to implement the
* 'class' members so that 'bspVmeDmaList' can access
* the device in an abstract manner.
*/
/*
* 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
*/
#ifdef __cplusplus
extern "C" {
#endif
typedef void *DmaDescriptor;
/* Member functions to be implemented by chip drivers */
typedef DmaDescriptor (*DmaDescriptorAlloc)(void);
typedef void (*DmaDescriptorFree) (DmaDescriptor d);
typedef void (*DmaDescriptorInit) (DmaDescriptor d);
/* Setup takes the parameters declared in VMEDMA.h */
typedef int (*DmaDescriptorSetup)(DmaDescriptor d, uint32_t, uint32_t, uint32_t, uint32_t, uint32_t);
typedef void (*DmaDescriptorSetNxt)(DmaDescriptor d, DmaDescriptor next);
typedef int (*DmaDescriptorStart)(volatile void *controller_addr, int channel, DmaDescriptor);
typedef int (*DmaDescriptorRefr) (DmaDescriptor);
typedef void (*DmaDescriptorDump) (DmaDescriptor);
typedef struct VMEDmaListClassRec_ {
int desc_size; /* size of a descritor */
int desc_align; /* alignment of a descriptor */
VMEDmaListNode freeList; /* list of free descriptors of this class, MUST be initialized to NULL */
DmaDescriptorAlloc desc_alloc; /* [optional, may be NULL] allocator for one descriptor */
DmaDescriptorFree desc_free; /* [optional, may be NULL] destructor for one descriptor */
DmaDescriptorInit desc_init; /* [optional, may be NULL] set stuff that don't change during lifetime */
DmaDescriptorSetNxt desc_setnxt;/* set 'NEXT' pointer in descriptor; mark as LAST if next == 0 */
DmaDescriptorSetup desc_setup; /* setup a descriptor */
DmaDescriptorStart desc_start; /* start list at a descriptor */
DmaDescriptorRefr desc_refr; /* refresh a descriptor */
DmaDescriptorDump desc_dump; /* dump a descriptor (for debugging) */
} VMEDmaListClassRec;
#ifdef __cplusplus
}
#endif
#endif

View File

@@ -61,8 +61,18 @@
#define __INSIDE_RTEMS_BSP__
#include "vmeTsi148.h"
#include <bsp/VMEDMA.h>
#include "vmeTsi148DMA.h"
#include "bspVmeDmaListP.h"
#define DEBUG
#ifdef DEBUG
#define STATIC
#else
#define STATIC static
#endif
/* The tsi has 4 'local' wires that can be hooked to a PIC */
@@ -300,6 +310,29 @@
typedef unsigned int pci_ulong;
#ifdef __BIG_ENDIAN__
static inline void st_be32( uint32_t *a, uint32_t v)
{
*a = v;
}
static inline uint32_t ld_be32( uint32_t *a )
{
return *a;
}
#elif defined(__LITTLE_ENDIAN__)
#error "You need to implement st_be32/ld_be32"
#else
#error "Undefined endianness??"
#endif
#ifndef BSP_LOCAL2PCI_ADDR
/* try legacy PCI_DRAM_OFFSET */
#ifndef PCI_DRAM_OFFSET
#define PCI_DRAM_OFFSET 0
#endif
#define BSP_LOCAL2PCI_ADDR(l) (((uint32_t)l)+PCI_DRAM_OFFSET)
#endif
/* PCI_MEM_BASE is a possible offset between CPU- and PCI addresses.
* Should be defined by the BSP.
*/
@@ -310,6 +343,8 @@ typedef unsigned int pci_ulong;
#define BSP_PCI2LOCAL_ADDR(memaddr) ((unsigned long)(memaddr) + PCI_MEM_BASE)
#endif
typedef uint32_t BEValue;
typedef struct {
BERegister *base;
int irqLine;
@@ -318,6 +353,8 @@ typedef struct {
static Tsi148Dev devs[NUM_TSI_DEVS] = {{0}};
#define THEBASE (devs[0].base)
/* forward decl */
extern int vmeTsi148RegPort;
extern int vmeTsi148RegCSR;
@@ -445,7 +482,7 @@ int port;
void
vmeTsi148Reset()
{
vmeTsi148ResetXX(devs[0].base);
vmeTsi148ResetXX(THEBASE);
}
/* convert an address space selector to a corresponding
@@ -468,8 +505,19 @@ am2omode(unsigned long address_space, unsigned long *pmode)
unsigned long mode = 0;
unsigned long tm = TSI_TM_SCT_IDX;
if ( ! (VME_MODE_DBW16 & address_space ) )
mode |= TSI_OTAT_DBW(1);
switch ( VME_MODE_DBW_MSK & address_space ) {
case VME_MODE_DBW8:
return -1; /* unsupported */
case VME_MODE_DBW16:
break;
default:
case VME_MODE_DBW32:
mode |= TSI_OTAT_DBW(1);
break;
}
if ( ! (VME_MODE_PREFETCH_ENABLE & address_space) )
mode |= TSI_OTAT_MRPFD;
else {
@@ -701,7 +749,7 @@ int i,s,l;
return -1;
}
if ( base == devs[0].base && isout && vmeTsi148RegPort == port ) {
if ( base == THEBASE && isout && vmeTsi148RegPort == port ) {
uprintf(stderr,"Tsi148 %s Port Cfg: invalid port; reserved by the interrupt manager for CRG\n", name);
return -1;
}
@@ -838,7 +886,7 @@ vmeTsi148InboundPortCfg(
unsigned long pci_address,
unsigned long length)
{
return configTsiPort(devs[0].base, 0, port, address_space, vme_address, pci_address, length);
return configTsiPort(THEBASE, 0, port, address_space, vme_address, pci_address, length);
}
@@ -862,7 +910,7 @@ vmeTsi148OutboundPortCfg(
unsigned long pci_address,
unsigned long length)
{
return configTsiPort(devs[0].base, 1, port, address_space, vme_address, pci_address, length);
return configTsiPort(THEBASE, 1, port, address_space, vme_address, pci_address, length);
}
@@ -975,7 +1023,7 @@ vmeTsi148XlateAddr(
unsigned long *paOut/* where to put result */
)
{
return vmeTsi148XlateAddrXX(devs[0].base, outbound, reverse, as, aIn, paOut);
return vmeTsi148XlateAddrXX(THEBASE, outbound, reverse, as, aIn, paOut);
}
@@ -1055,7 +1103,7 @@ unsigned long long start, limit, offst;
void
vmeTsi148OutboundPortsShow(FILE *f)
{
vmeTsi148OutboundPortsShowXX(devs[0].base, f);
vmeTsi148OutboundPortsShowXX(THEBASE, f);
}
void
@@ -1115,7 +1163,7 @@ unsigned long long start, limit, offst;
void
vmeTsi148InboundPortsShow(FILE *f)
{
vmeTsi148InboundPortsShowXX(devs[0].base, f);
vmeTsi148InboundPortsShowXX(THEBASE, f);
}
@@ -1132,7 +1180,7 @@ int port;
void
vmeTsi148DisableAllInboundPorts(void)
{
vmeTsi148DisableAllInboundPortsXX(devs[0].base);
vmeTsi148DisableAllInboundPortsXX(THEBASE);
}
void
@@ -1148,7 +1196,7 @@ int port;
void
vmeTsi148DisableAllOutboundPorts(void)
{
vmeTsi148DisableAllOutboundPortsXX(devs[0].base);
vmeTsi148DisableAllOutboundPortsXX(THEBASE);
}
@@ -1191,7 +1239,7 @@ uint32_t mode;
int
vmeTsi148MapCRG(uint32_t vme_base, uint32_t as )
{
return vmeTsi148MapCRGXX( devs[0].base, vme_base, as );
return vmeTsi148MapCRGXX( THEBASE, vme_base, as );
}
/* Interrupt Subsystem */
@@ -1326,9 +1374,9 @@ rtems_interrupt_disable(flags);
}
wire_mask[pin] |= mask;
mask = TSI_RD(devs[0].base, mapreg) & ~ (0x3<<shift);
mask = TSI_RD(THEBASE, mapreg) & ~ (0x3<<shift);
mask |= wire;
TSI_WR( devs[0].base, mapreg, mask );
TSI_WR( THEBASE, mapreg, mask );
rtems_interrupt_enable(flags);
return 0;
@@ -1363,7 +1411,7 @@ static void
tsiVMEISR(rtems_irq_hdl_param arg)
{
int pin = (int)arg;
BERegister *b = devs[0].base;
BERegister *b = THEBASE;
IRQEntry ip;
unsigned long msk,lintstat,vector, vecarg;
int lvl;
@@ -1462,7 +1510,7 @@ my_no_op(const rtems_irq_connect_data * arg)
static int
my_isOn(const rtems_irq_connect_data *arg)
{
return (int)(TSI_RD(devs[0].base, TSI_INTEO_REG) & TSI_RD(devs[0].base, TSI_INTEN_REG));
return (int)(TSI_RD(THEBASE, TSI_INTEO_REG) & TSI_RD(THEBASE, TSI_INTEN_REG));
}
static void
@@ -1505,9 +1553,9 @@ va_list ap;
#ifndef BSP_EARLY_PROBE_VME
#define BSP_EARLY_PROBE_VME(addr) \
( \
vmeTsi148ClearVMEBusErrorsXX( devs[0].base, 0 ), \
vmeTsi148ClearVMEBusErrorsXX( THEBASE, 0 ), \
( ((PCI_DEVICE_TSI148 << 16) | PCI_VENDOR_TUNDRA ) == TSI_LE_RD32( ((BERegister*)(addr)), 0 ) \
&& 0 == vmeTsi148ClearVMEBusErrorsXX( devs[0].base, 0 ) ) \
&& 0 == vmeTsi148ClearVMEBusErrorsXX( THEBASE, 0 ) ) \
)
#endif
@@ -1524,7 +1572,7 @@ char *regtype = (as & VME_AM_MASK) == VME_AM_CSR ? "CSR" : "CRG";
/* try to find mapping */
if ( 0 > (j = xlateFindPort(
devs[0].base,
THEBASE,
1, 0,
as | VME_MODE_AS_MATCH,
vme_addr,
@@ -1587,7 +1635,7 @@ unsigned long cpu_base, vme_reg_base;
uprintf(stderr,"vmeTsi148 IRQ manager: looking for registers on VME...\n");
if ( ( i = ((TSI_RD( devs[0].base, TSI_CBAR_REG ) & 0xff) >> 3) ) > 0 ) {
if ( ( i = ((TSI_RD( THEBASE, TSI_CBAR_REG ) & 0xff) >> 3) ) > 0 ) {
uprintf(stderr,"Trying to find CSR on VME...\n");
vme_reg_base = i*0x80000 + TSI_CSR_OFFSET;
i = mappedAndProbed( vme_reg_base, VME_AM_CSR , &cpu_base);
@@ -1603,7 +1651,7 @@ unsigned long cpu_base, vme_reg_base;
/* Next we see if the CRG block is mapped to VME */
if ( (TSI_CRGAT_EN & (j = TSI_RD( devs[0].base, TSI_CRGAT_REG ))) ) {
if ( (TSI_CRGAT_EN & (j = TSI_RD( THEBASE, TSI_CRGAT_REG ))) ) {
switch ( j & TSI_CRGAT_AS_MSK ) {
case TSI_CRGAT_A16 : i = VME_AM_SUP_SHORT_IO; break;
case TSI_CRGAT_A24 : i = VME_AM_STD_SUP_DATA; break;
@@ -1611,7 +1659,7 @@ unsigned long cpu_base, vme_reg_base;
default:
break;
}
vme_reg_base = TSI_RD( devs[0].base, TSI_CBAL_REG ) & ~ (TSI_CRG_SIZE - 1);
vme_reg_base = TSI_RD( THEBASE, TSI_CBAL_REG ) & ~ (TSI_CRG_SIZE - 1);
}
if ( -1 == i ) {
@@ -1625,7 +1673,7 @@ unsigned long cpu_base, vme_reg_base;
uprintf(stderr,"(should open outbound window to CSR space or map CRG [vmeTsi148MapCRG()])\n");
uprintf(stderr,"Falling back to PCI but you might experience spurious VME interrupts; read a register\n");
uprintf(stderr,"back from user ISR to flush posted-write FIFO as a work-around\n");
cpu_base = (unsigned long)devs[0].base;
cpu_base = (unsigned long)THEBASE;
i = -1;
}
@@ -1725,7 +1773,7 @@ volatile IRQEntry *p;
static int
intDoEnDis(unsigned int level, int dis)
{
BERegister *b = devs[0].base;
BERegister *b = THEBASE;
unsigned long flags, v;
int shift;
@@ -1826,7 +1874,7 @@ unsigned long v;
int
vmeTsi148IntRaise(int level, unsigned vector)
{
return vmeTsi148IntRaiseXX(devs[0].base, level, vector);
return vmeTsi148IntRaiseXX(THEBASE, level, vector);
}
/* Loopback test of VME/Tsi148 internal interrupts */
@@ -1850,7 +1898,7 @@ LoopbackTstArgs *pa = arg;
int
vmeTsi148IntLoopbackTst(int level, unsigned vector)
{
BERegister *b = devs[0].base;
BERegister *b = THEBASE;
rtems_status_code sc;
rtems_id q = 0;
int installed = 0;
@@ -2002,7 +2050,531 @@ unsigned long rval;
unsigned long
vmeTsi148ClearVMEBusErrors(uint32_t *paddr)
{
return vmeTsi148ClearVMEBusErrorsXX(devs[0].base, paddr);
return vmeTsi148ClearVMEBusErrorsXX(THEBASE, paddr);
}
/** DMA Support **/
/* descriptor must be 8-byte aligned */
typedef struct VmeTsi148DmaListDescriptorRec_ {
BEValue dsau, dsal;
BEValue ddau, ddal;
BEValue dsat, ddat;
BEValue dnlau, dnlal;
BEValue dcnt, ddbs;
} VmeTsi148DmaListDescriptorRec;
static void tsi_desc_init (DmaDescriptor);
static int tsi_desc_setup (DmaDescriptor, uint32_t, uint32_t, uint32_t, uint32_t, uint32_t);
static void tsi_desc_setnxt(DmaDescriptor, DmaDescriptor);
static void tsi_desc_dump (DmaDescriptor);
static int tsi_desc_start (volatile void *controller_addr, int channel, DmaDescriptor p);
VMEDmaListClassRec vmeTsi148DmaListClass = {
desc_size: sizeof(VmeTsi148DmaListDescriptorRec),
desc_align: 8,
freeList: 0,
desc_alloc: 0,
desc_free: 0,
desc_init: tsi_desc_init,
desc_setnxt:tsi_desc_setnxt,
desc_setup: tsi_desc_setup,
desc_start: tsi_desc_start,
desc_refr: 0,
desc_dump: tsi_desc_dump,
};
/* DMA Control */
#define TSI_DMA_REG(off,i) ((off)+(((i)&1)<<7))
#define TSI_DCTL_REG(i) TSI_DMA_REG(0x500,i)
#define TSI_DCTL0_REG 0x500
#define TSI_DCTL1_REG 0x580
# define TSI_DCTL_ABT (1<<27) /* abort */
# define TSI_DCTL_PAU (1<<26) /* pause */
# define TSI_DCTL_DGO (1<<25) /* GO */
# define TSI_DCTL_MOD (1<<23) /* linked list: 0, direct: 1 */
# define TSI_DCTL_VFAR (1<<17) /* flush FIFO on VME error: 1 (discard: 0) */
# define TSI_DCTL_PFAR (1<<16) /* flush FIFO on PCI error: 1 (discard: 0) */
# define TSI_DCTL_VBKS(i) (((i)&7)<<12) /* VME block size */
# define TSI_DCTL_VBKS_32 TSI_DCTL_VBKS(0)
# define TSI_DCTL_VBKS_64 TSI_DCTL_VBKS(1)
# define TSI_DCTL_VBKS_128 TSI_DCTL_VBKS(2)
# define TSI_DCTL_VBKS_256 TSI_DCTL_VBKS(3)
# define TSI_DCTL_VBKS_512 TSI_DCTL_VBKS(4)
# define TSI_DCTL_VBKS_1024 TSI_DCTL_VBKS(5)
# define TSI_DCTL_VBKS_2048 TSI_DCTL_VBKS(6)
# define TSI_DCTL_VBKS_4096 TSI_DCTL_VBKS(7)
# define TSI_DCTL_VBOT(i) (((i)&7)<< 8) /* VME back-off time */
# define TSI_DCTL_VBOT_0us TSI_DCTL_VBOT(0)
# define TSI_DCTL_VBOT_1us TSI_DCTL_VBOT(1)
# define TSI_DCTL_VBOT_2us TSI_DCTL_VBOT(2)
# define TSI_DCTL_VBOT_4us TSI_DCTL_VBOT(3)
# define TSI_DCTL_VBOT_8us TSI_DCTL_VBOT(4)
# define TSI_DCTL_VBOT_16us TSI_DCTL_VBOT(5)
# define TSI_DCTL_VBOT_32us TSI_DCTL_VBOT(6)
# define TSI_DCTL_VBOT_64us TSI_DCTL_VBOT(7)
# define TSI_DCTL_PBKS(i) (((i)&7)<< 4) /* PCI block size */
# define TSI_DCTL_PBKS_32 TSI_DCTL_PBKS(0)
# define TSI_DCTL_PBKS_64 TSI_DCTL_PBKS(1)
# define TSI_DCTL_PBKS_128 TSI_DCTL_PBKS(2)
# define TSI_DCTL_PBKS_256 TSI_DCTL_PBKS(3)
# define TSI_DCTL_PBKS_512 TSI_DCTL_PBKS(4)
# define TSI_DCTL_PBKS_1024 TSI_DCTL_PBKS(5)
# define TSI_DCTL_PBKS_2048 TSI_DCTL_PBKS(6)
# define TSI_DCTL_PBKS_4096 TSI_DCTL_PBKS(7)
# define TSI_DCTL_PBOT(i) (((i)&7)<< 0) /* PCI back-off time */
# define TSI_DCTL_PBOT_0us TSI_DCTL_PBOT(0)
# define TSI_DCTL_PBOT_1us TSI_DCTL_PBOT(1)
# define TSI_DCTL_PBOT_2us TSI_DCTL_PBOT(2)
# define TSI_DCTL_PBOT_4us TSI_DCTL_PBOT(3)
# define TSI_DCTL_PBOT_8us TSI_DCTL_PBOT(4)
# define TSI_DCTL_PBOT_16us TSI_DCTL_PBOT(5)
# define TSI_DCTL_PBOT_32us TSI_DCTL_PBOT(6)
# define TSI_DCTL_PBOT_64us TSI_DCTL_PBOT(7)
/* DMA Status */
#define TSI_DSTA_REG(i) TSI_DMA_REG(0x504,i)
#define TSI_DSTA0_REG 0x504
#define TSI_DSTA1_REG 0x584
# define TSI_DSTA_ERR (1<<28)
# define TSI_DSTA_ABT (1<<27)
# define TSI_DSTA_PAU (1<<26)
# define TSI_DSTA_DON (1<<25)
# define TSI_DSTA_BSY (1<<24)
# define TSI_DSTA_ERRS (1<<20) /* Error source; PCI:1, VME:0 */
# define TSI_DSTA_ERT_MSK (3<<16) /* Error type */
# define TSI_DSTA_ERT_BERR_E (0<<16) /* 2eVME even or other bus error */
# define TSI_DSTA_ERT_BERR_O (1<<16) /* 2eVME odd bus error */
# define TSI_DSTA_ERT_SLVE_E (2<<16) /* 2eVME even or other slave termination */
# define TSI_DSTA_ERT_SLVE_O (3<<16) /* 2eVME odd slave termination; 2eSST read last word invalid */
/* DMA Current source address upper */
#define TSI_DCSAU_REG(i) TSI_DMA_REG(0x508,i)
#define TSI_DCSAU0_REG 0x508
#define TSI_DCSAU1_REG 0x588
/* DMA Current source address lower */
#define TSI_DCSAL_REG(i) TSI_DMA_REG(0x50c,i)
#define TSI_DCSAL0_REG 0x50c
#define TSI_DCSAL1_REG 0x58c
/* DMA Current destination address upper */
#define TSI_DCDAU_REG(i) TSI_DMA_REG(0x510,i)
#define TSI_DCDAU0_REG 0x510
#define TSI_DCDAU1_REG 0x590
/* DMA Current destination address lower */
#define TSI_DCDAL_REG(i) TSI_DMA_REG(0x514,i)
#define TSI_DCDAL0_REG 0x514
#define TSI_DCDAL1_REG 0x594
/* DMA Current link address upper */
#define TSI_DCLAU_REG(i) TSI_DMA_REG(0x518,i)
#define TSI_DCLAU0_REG 0x518
#define TSI_DCLAU1_REG 0x598
/* DMA Current link address lower */
#define TSI_DCLAL_REG(i) TSI_DMA_REG(0x51c,i)
#define TSI_DCLAL0_REG 0x51c
#define TSI_DCLAL1_REG 0x59c
/* DMA Source address upper */
#define TSI_DSAU_REG(i) TSI_DMA_REG(0x520,i)
#define TSI_DSAU0_REG 0x520
#define TSI_DSAU1_REG 0x5a0
/* DMA Source address lower */
#define TSI_DSAL_REG(i) TSI_DMA_REG(0x524,i)
#define TSI_DSAL0_REG 0x524
#define TSI_DSAL1_REG 0x5a4
/* DMA Destination address upper */
#define TSI_DDAU_REG(i) TSI_DMA_REG(0x528,i)
#define TSI_DDAU0_REG 0x528
#define TSI_DDAU1_REG 0x5a8
/* DMA Destination address lower */
#define TSI_DDAL_REG(i) TSI_DMA_REG(0x52c,i)
#define TSI_DDAL0_REG 0x52c
#define TSI_DDAL1_REG 0x5ac
/* DMA Source Attribute */
#define TSI_DSAT_REG(i) TSI_DMA_REG(0x530,i)
#define TSI_DSAT0_REG 0x530
#define TSI_DSAT1_REG 0x5b0
/* DMA Destination Attribute */
#define TSI_DDAT_REG(i) TSI_DMA_REG(0x534,i)
#define TSI_DDAT0_REG 0x534
#define TSI_DDAT1_REG 0x5b4
# define TSI_DXAT_TYP(i) (((i)&3)<<28) /* Xfer type */
# define TSI_DXAT_TYP_PCI TSI_DXAT_TYP(0)
# define TSI_DXAT_TYP_VME TSI_DXAT_TYP(1)
# define TSI_DSAT_TYP_PAT TSI_DXAT_TYP(2) /* pattern */
# define TSI_DSAT_PSZ (1<<25) /* pattern size 32-bit: 0, 8-bit: 1 */
# define TSI_DSAT_NIN (1<<24) /* no-increment */
# define TSI_DXAT_OTAT_MSK ((1<<13)-1) /* get bits compatible with OTAT */
# define TSI_DXAT_SSTM(i) (((i)&3)<<11) /* 2eSST Xfer rate (MB/s) */
# define TSI_DXAT_SSTM_116 TSI_DXAT_SSTM(0)
# define TSI_DXAT_SSTM_267 TSI_DXAT_SSTM(1)
# define TSI_DXAT_SSTM_320 TSI_DXAT_SSTM(2)
# define TSI_DXAT_TM(i) (((i)&7)<< 8) /* VME Xfer mode */
# define TSI_DXAT_TM_SCT TSI_DXAT_TM(0)
# define TSI_DXAT_TM_BLT TSI_DXAT_TM(1)
# define TSI_DXAT_TM_MBLT TSI_DXAT_TM(2)
# define TSI_DXAT_TM_2eVME TSI_DXAT_TM(3)
# define TSI_DXAT_TM_2eSST TSI_DXAT_TM(4)
# define TSI_DSAT_TM_2eSST_B TSI_DXAT_TM(5) /* 2eSST broadcast */
# define TSI_DXAT_DBW(i) (((i)&3)<< 6) /* VME Data width */
# define TSI_DXAT_DBW_16 TSI_DXAT_DBW(0)
# define TSI_DXAT_DBW_32 TSI_DXAT_DBW(1)
# define TSI_DXAT_SUP (1<<5) /* supervisor access */
# define TSI_DXAT_PGM (1<<4) /* program access */
# define TSI_DXAT_AM(i) (((i)&15)<<0) /* VME Address mode */
# define TSI_DXAT_AM_A16 TSI_DXAT_AM(0)
# define TSI_DXAT_AM_A24 TSI_DXAT_AM(1)
# define TSI_DXAT_AM_A32 TSI_DXAT_AM(2)
# define TSI_DXAT_AM_A64 TSI_DXAT_AM(4)
# define TSI_DXAT_AM_CSR TSI_DXAT_AM(5)
/* DMA Next link address upper */
#define TSI_DNLAU_REG(i) TSI_DMA_REG(0x538,i)
#define TSI_DNLAU0_REG 0x538
#define TSI_DNLAU1_REG 0x5b8
/* DMA Next link address lower */
#define TSI_DNLAL_REG(i) TSI_DMA_REG(0x53c,i)
#define TSI_DNLAL0_REG 0x53c
#define TSI_DNLAL1_REG 0x5bc
# define TSI_DNLAL_LLA 1 /* last element in chain */
/* DMA Byte Count */
#define TSI_DCNT_REG(i) TSI_DMA_REG(0x540,i)
#define TSI_DCNT0_REG 0x540
#define TSI_DCNT1_REG 0x54c
/* DMA 2eSST destination broadcast select */
#define TSI_DDBS_REG(i) TSI_DMA_REG(0x544,i)
#define TSI_DDBS0_REG 0x544
#define TSI_DDBS1_REG 0x5c4
/* Convert canonical xfer_mode into Tsi148 bits; return -1 if invalid */
static uint32_t
vme_attr(uint32_t xfer_mode)
{
uint32_t vme_mode;
if ( am2omode(xfer_mode, &vme_mode) )
return BSP_VMEDMA_STATUS_UNSUP;
/* am2omode may set prefetch and other bits */
vme_mode &= TSI_DXAT_OTAT_MSK;
vme_mode |= TSI_DXAT_TYP_VME;
if ( BSP_VMEDMA_MODE_NOINC_VME & xfer_mode ) {
/* no-incr. only supported on source address */
if ( (BSP_VMEDMA_MODE_PCI2VME & xfer_mode) )
return BSP_VMEDMA_STATUS_UNSUP;
vme_mode |= TSI_DSAT_NIN;
}
return vme_mode;
}
static uint32_t
pci_attr(uint32_t xfer_mode)
{
uint32_t pci_mode = 0;
if ( BSP_VMEDMA_MODE_NOINC_PCI & xfer_mode ) {
/* no-incr. only supported on source address */
if ( ! (BSP_VMEDMA_MODE_PCI2VME & xfer_mode) )
return BSP_VMEDMA_STATUS_UNSUP;
pci_mode |= TSI_DSAT_NIN;
}
return pci_mode;
}
static void tsi_desc_init(DmaDescriptor p)
{
VmeTsi148DmaListDescriptor d = p;
st_be32( &d->dnlau, 0 );
st_be32( &d->dnlal, TSI_DNLAL_LLA );
st_be32( &d->ddbs, (1<<22)-1 ); /* SSTB broadcast not yet fully supported */
}
static void
tsi_desc_setnxt(DmaDescriptor p, DmaDescriptor n)
{
VmeTsi148DmaListDescriptor d = p;
if ( 0 == n ) {
st_be32( &d->dnlal, TSI_DNLAL_LLA );
} else {
st_be32( &d->dnlal, BSP_LOCAL2PCI_ADDR((uint32_t)n) );
}
}
static void
tsi_desc_dump(DmaDescriptor p)
{
VmeTsi148DmaListDescriptor d = p;
printf(" DSA: 0x%08lx%08lx\n", ld_be32(&d->dsau), ld_be32(&d->dsal));
printf(" DDA: 0x%08lx%08lx\n", ld_be32(&d->ddau), ld_be32(&d->ddal));
printf(" NLA: 0x%08lx%08lx\n", ld_be32(&d->dnlau), ld_be32(&d->dnlal));
printf(" SAT: 0x%08lx DAT: 0x%08lx\n", ld_be32(&d->dsat), ld_be32(&d->ddat));
printf(" CNT: 0x%08lx\n", ld_be32(&d->dcnt));
}
int
vmeTsi148DmaSetupXX(BERegister *base, int channel, uint32_t mode, uint32_t xfer_mode, void *custom)
{
uint32_t ctl = 0;
uint32_t vmeatt, pciatt, sat, dat;
if ( channel < 0 || channel > 1 )
return BSP_VMEDMA_STATUS_UNSUP;
/* Check bus mode */
if ( (uint32_t)BSP_VMEDMA_STATUS_UNSUP == (vmeatt = vme_attr(xfer_mode)) )
return -2;
/* Check PCI bus mode */
if ( (uint32_t)BSP_VMEDMA_STATUS_UNSUP == (pciatt = pci_attr(xfer_mode)) )
return -3;
/* Compute control word; bottleneck is VME; */
ctl |= TSI_DCTL_PBKS_32;
ctl |= (BSP_VMEDMA_OPT_THROUGHPUT == mode ? TSI_DCTL_PBOT_0us : TSI_DCTL_PBOT_1us);
switch ( mode ) {
case BSP_VMEDMA_OPT_THROUGHPUT:
ctl |= TSI_DCTL_VBKS_1024;
ctl |= TSI_DCTL_VBOT_0us;
break;
case BSP_VMEDMA_OPT_LOWLATENCY:
ctl |= TSI_DCTL_VBKS_32;
ctl |= TSI_DCTL_VBOT_0us;
break;
case BSP_VMEDMA_OPT_SHAREDBUS:
ctl |= TSI_DCTL_VBKS_128;
ctl |= TSI_DCTL_VBOT_64us;
break;
case BSP_VMEDMA_OPT_CUSTOM:
ctl = *(uint32_t*)custom;
break;
default:
case BSP_VMEDMA_OPT_DEFAULT:
ctl = 0;
break;
}
TSI_WR(base, TSI_DCTL_REG(channel), ctl);
if ( BSP_VMEDMA_MODE_PCI2VME & xfer_mode ) {
dat = vmeatt; sat = pciatt;
} else {
sat = vmeatt; dat = pciatt;
}
TSI_WR(base, TSI_DSAT_REG(channel), sat);
TSI_WR(base, TSI_DDAT_REG(channel), dat);
return 0;
}
int
vmeTsi148DmaSetup(int channel, uint32_t mode, uint32_t xfer_mode, void *custom)
{
BERegister *base = THEBASE;
return vmeTsi148DmaSetupXX(base, channel, mode, xfer_mode, custom);
}
int
vmeTsi148DmaListStartXX(BERegister *base, int channel, VmeTsi148DmaListDescriptor d)
{
uint32_t ctl;
if ( d ) {
/* Set list pointer and start */
if ( channel < 0 || channel > 1 )
return BSP_VMEDMA_STATUS_UNSUP;
if ( TSI_DSTA_BSY & TSI_RD(base, TSI_DSTA_REG(channel)) )
return BSP_VMEDMA_STATUS_BUSY; /* channel busy */
TSI_WR(base, TSI_DNLAL_REG(channel), (uint32_t)BSP_LOCAL2PCI_ADDR(d));
asm volatile("":::"memory");
/* Start transfer */
ctl = TSI_RD(base, TSI_DCTL_REG(channel)) | TSI_DCTL_DGO;
ctl &= ~TSI_DCTL_MOD;
TSI_WR(base, TSI_DCTL_REG(channel), ctl);
}
/* else: list vs. direct mode is set by the respective start commands */
return 0;
}
int
vmeTsi148DmaListStart(int channel, VmeTsi148DmaListDescriptor d)
{
BERegister *base = THEBASE;
return vmeTsi148DmaListStartXX(base, channel, d);
}
int
vmeTsi148DmaStartXX(BERegister *base, int channel, uint32_t pci_addr, uint32_t vme_addr, uint32_t n_bytes)
{
uint32_t src, dst, ctl;
if ( channel < 0 || channel > 1 )
return BSP_VMEDMA_STATUS_UNSUP;
if ( TSI_DSTA_BSY & TSI_RD(base, TSI_DSTA_REG(channel)) )
return BSP_VMEDMA_STATUS_BUSY; /* channel busy */
/* retrieve direction from dst attribute */
if ( TSI_DXAT_TYP_VME & TSI_RD(base, TSI_DDAT_REG(channel)) ) {
dst = vme_addr;
src = pci_addr;
} else {
src = vme_addr;
dst = pci_addr;
}
/* FIXME: we leave the 'upper' registers (topmost 32bits) alone.
* Probably, we should reset them at init...
*/
TSI_WR(base, TSI_DSAL_REG(channel), src);
TSI_WR(base, TSI_DDAL_REG(channel), dst);
TSI_WR(base, TSI_DCNT_REG(channel), n_bytes);
asm volatile("":::"memory");
/* Start transfer */
ctl = TSI_RD(base, TSI_DCTL_REG(channel)) | TSI_DCTL_DGO | TSI_DCTL_MOD;
TSI_WR(base, TSI_DCTL_REG(channel), ctl);
return 0;
}
int
vmeTsi148DmaStart(int channel, uint32_t pci_addr, uint32_t vme_addr, uint32_t n_bytes)
{
BERegister *base = THEBASE;
return vmeTsi148DmaStartXX(base, channel, pci_addr, vme_addr, n_bytes);
}
uint32_t
vmeTsi148DmaStatusXX(BERegister *base, int channel)
{
uint32_t st = TSI_RD(base, TSI_DSTA_REG(channel));
if ( channel < 0 || channel > 1 )
return BSP_VMEDMA_STATUS_UNSUP;
st = TSI_RD(base, TSI_DSTA_REG(channel));
/* Status can be zero if an empty list (all counts == 0) is executed */
if ( (TSI_DSTA_DON & st) || 0 == st )
return BSP_VMEDMA_STATUS_OK;
if ( TSI_DSTA_BSY & st )
return BSP_VMEDMA_STATUS_BUSY; /* channel busy */
if ( TSI_DSTA_ERR & st ) {
if ( TSI_DSTA_ERRS & st )
return BSP_VMEDMA_STATUS_BERR_PCI;
if ( ! (TSI_DSTA_ERT_SLVE_E & st) )
return BSP_VMEDMA_STATUS_BERR_VME;
}
return BSP_VMEDMA_STATUS_OERR;
}
uint32_t
vmeTsi148DmaStatus(int channel)
{
BERegister *base = THEBASE;
return vmeTsi148DmaStatusXX(base, channel);
}
#define ALL_BITS_NEEDED (BSP_VMEDMA_MSK_ATTR | BSP_VMEDMA_MSK_PCIA | BSP_VMEDMA_MSK_VMEA)
static int
tsi_desc_setup (
DmaDescriptor p,
uint32_t attr_mask,
uint32_t xfer_mode,
uint32_t pci_addr,
uint32_t vme_addr,
uint32_t n_bytes)
{
VmeTsi148DmaListDescriptor d = p;
uint32_t vmeatt = 0, pciatt = 0, tmp, src, dst, dat, sat;
/* argument check */
/* since we must vme/pci into src/dst we need the direction
* bit. Reject requests that have only part of the mask
* bits set. It would be possible to be more sophisticated
* by caching more information but we try to be simple here...
*/
tmp = attr_mask & ALL_BITS_NEEDED;
if ( tmp != 0 && tmp != ALL_BITS_NEEDED )
return -1;
if ( BSP_VMEDMA_MSK_ATTR & attr_mask ) {
/* Check VME bus mode */
vmeatt = vme_attr(xfer_mode);
if ( (uint32_t)BSP_VMEDMA_STATUS_UNSUP == vmeatt )
return -1;
/* Check PCI bus mode */
pciatt = pci_attr(xfer_mode);
if ( (uint32_t)BSP_VMEDMA_STATUS_UNSUP == pciatt )
return -1;
}
if ( BSP_VMEDMA_MSK_ATTR & attr_mask ) {
if ( BSP_VMEDMA_MODE_PCI2VME & xfer_mode ) {
dat = vmeatt; sat = pciatt;
dst = vme_addr; src = pci_addr;
} else {
sat = vmeatt; dat = pciatt;
src = vme_addr; dst = pci_addr;
}
st_be32( &d->dsau, 0 ); st_be32( &d->dsal, src );
st_be32( &d->ddau, 0 ); st_be32( &d->ddal, dst );
st_be32( &d->dsat, sat ); st_be32( &d->ddat, dat );
}
if ( BSP_VMEDMA_MSK_BCNT & attr_mask )
st_be32( &d->dcnt, n_bytes);
return 0;
}
static int
tsi_desc_start (volatile void *controller_addr, int channel, DmaDescriptor p)
{
VmeTsi148DmaListDescriptor d = p;
if ( !controller_addr )
controller_addr = THEBASE;
return vmeTsi148DmaListStartXX((BERegister*)controller_addr, channel, d);
}
#ifdef DEBUG_MODULAR
@@ -2030,7 +2602,7 @@ rtems_irq_connect_data xx;
xx.off = my_no_op;
xx.isOn = my_isOn;
TSI_WR(devs[0].base, TSI_INTEO_REG, 0);
TSI_WR(THEBASE, TSI_INTEO_REG, 0);
for ( i=0; i<TSI_NUM_INT_VECS; i++) {
/* Dont even bother to uninstall handlers */

View File

@@ -0,0 +1,88 @@
/* $Id$ */
#ifndef VME_TSI148_DMA_H
#define VME_TSI148_DMA_H
#include <bsp/vmeTsi148.h>
/*
* 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
*/
#ifdef __cplusplus
extern "C" {
#endif
/* DMA List access functions for use by bspVmeDmaList */
extern struct VMEDmaListClassRec_ vmeTsi148DmaListClass;
typedef struct VmeTsi148DmaListDescriptorRec_ *VmeTsi148DmaListDescriptor;
int
vmeTsi148DmaSetupXX(BERegister *base, int channel, uint32_t mode, uint32_t xfer_mode, void *custom);
int
vmeTsi148DmaSetup(int channel, uint32_t mode, uint32_t xfer_mode, void *custom);
int
vmeTsi148DmaListStartXX(BERegister *base, int channel, VmeTsi148DmaListDescriptor d);
int
vmeTsi148DmaListStart(int channel, VmeTsi148DmaListDescriptor d);
int
vmeTsi148DmaStartXX(BERegister *base, int channel, uint32_t pci_addr, uint32_t vme_addr, uint32_t n_bytes);
int
vmeTsi148DmaStart(int channel, uint32_t pci_addr, uint32_t vme_addr, uint32_t n_bytes);
uint32_t
vmeTsi148DmaStatusXX(BERegister *base, int channel);
uint32_t
vmeTsi148DmaStatus(int channel);
#ifdef __cplusplus
}
#endif
#endif

View File

@@ -54,6 +54,7 @@
#endif
#include "vmeUniverse.h"
#include "vmeUniverseDMA.h"
#define UNIV_NUM_MPORTS 8 /* number of master ports */
#define UNIV_NUM_SPORTS 8 /* number of slave ports */
@@ -102,6 +103,7 @@
#include <rtems/error.h>
#include <bsp/pci.h>
#include <bsp.h>
#include <libcpu/byteorder.h>
/* allow the BSP to override the default routines */
#ifndef BSP_PCI_FIND_DEVICE
@@ -132,6 +134,13 @@ typedef unsigned int pci_ulong;
#define BSP_PCI2LOCAL_ADDR(memaddr) ((pci_ulong)(memaddr) + PCI_MEM_BASE)
#endif
#ifndef BSP_LOCAL2PCI_ADDR
#ifndef PCI_DRAM_OFFSET
#define PCI_DRAM_OFFSET 0
#endif
#define BSP_LOCAL2PCI_ADDR(pciaddr) ((uint32_t)(pciaddr) + PCI_DRAM_OFFSET)
#endif
#elif defined(__vxworks)
typedef unsigned long pci_ulong;
@@ -349,6 +358,7 @@ static int
am2mode(int ismaster, unsigned long address_space, unsigned long *pmode)
{
unsigned long mode=0;
unsigned long vdw =0;
/* NOTE: reading the CY961 (Echotek ECDR814) with VDW32
* generated bus errors when reading 32-bit words
@@ -368,11 +378,22 @@ unsigned long mode=0;
mode |= UNIV_SCTL_PWEN | UNIV_SCTL_PREN;
mode |= UNIV_SCTL_EN;
} else {
if ( VME_MODE_DBW16 & address_space )
mode |= UNIV_MCTL_VDW16;
else
mode |= UNIV_MCTL_VDW64;
mode |= UNIV_MCTL_VCT /* enable block transfers */;
switch ( VME_MODE_DBW_MSK & address_space ) {
default:
vdw = UNIV_MCTL_VDW64;
break;
case VME_MODE_DBW8:
break;
case VME_MODE_DBW16:
vdw = UNIV_MCTL_VDW16;
break;
case VME_MODE_DBW32:
vdw = UNIV_MCTL_VDW32;
break;
}
if ( VME_AM_IS_MEMORY & address_space )
mode |= UNIV_MCTL_PWEN;
mode |= UNIV_MCTL_EN;
@@ -388,11 +409,35 @@ unsigned long mode=0;
else {
mode &= ~UNIV_SCTL_DAT;
}
/* fall thru */
case VME_AM_STD_SUP_DATA:
case VME_AM_STD_USR_DATA:
case VME_AM_STD_SUP_BLT:
case VME_AM_STD_SUP_MBLT:
case VME_AM_STD_USR_BLT:
case VME_AM_STD_USR_MBLT:
if ( ismaster ) {
switch ( address_space & 3 ) {
case 0: /* mblt */
if ( UNIV_MCTL_VDW64 != vdw )
return -1;
break;
case 3: /* blt */
mode |= UNIV_MCTL_VCT;
/* universe may do mblt anyways so go back to
* 32-bit width
*/
vdw = UNIV_MCTL_VDW32;
}
}
mode |= UNIV_CTL_VAS24;
break;
case VME_AM_EXT_SUP_PGM:
case VME_AM_EXT_USR_PGM:
@@ -402,9 +447,32 @@ unsigned long mode=0;
mode &= ~UNIV_SCTL_DAT;
}
/* fall thru */
case VME_AM_EXT_SUP_DATA:
case VME_AM_EXT_USR_DATA:
case VME_AM_EXT_SUP_BLT:
case VME_AM_EXT_SUP_MBLT:
case VME_AM_EXT_USR_BLT:
case VME_AM_EXT_USR_MBLT:
if ( ismaster ) {
switch ( address_space & 3 ) {
case 0: /* mblt */
if ( UNIV_MCTL_VDW64 != vdw )
return -1;
break;
case 3: /* blt */
mode |= UNIV_MCTL_VCT;
/* universe may do mblt anyways so go back to
* 32-bit width
*/
vdw = UNIV_MCTL_VDW32;
}
}
mode |= UNIV_CTL_VAS32;
break;
case VME_AM_SUP_SHORT_IO:
@@ -426,6 +494,8 @@ unsigned long mode=0;
}
if ( VME_AM_IS_SUP(address_space) )
mode |= (ismaster ? UNIV_MCTL_SUPER : UNIV_SCTL_SUPER);
mode |= vdw; /* vdw still 0 in slave mode */
*pmode = mode;
return 0;
}
@@ -623,6 +693,40 @@ showUniversePort(
}
if (ismaster) {
unsigned vdw;
switch ( cntrl & UNIV_MCTL_VDW64 ) {
case UNIV_MCTL_VDW64:
vdw = 64;
break;
case UNIV_MCTL_VDW32:
vdw = 32;
break;
case UNIV_MCTL_VDW16:
vdw = 16;
break;
default:
vdw = 8;
break;
}
if ( 64 == vdw ) {
switch ( UNIV_CTL_VAS & cntrl ) {
case UNIV_CTL_VAS24:
case UNIV_CTL_VAS32:
uprintf(f,"D64 [MBLT], ");
break;
default:
uprintf(f,"D64, ");
break;
}
} else {
uprintf(f, "D%u%s, ", vdw, (cntrl & UNIV_MCTL_VCT) ? " [BLT]" : "");
}
uprintf(f,"%s, %s",
cntrl&UNIV_MCTL_PGM ? "Pgm" : "Dat",
cntrl&UNIV_MCTL_SUPER ? "Sup" : "Usr");
@@ -1030,54 +1134,6 @@ vmeUniverseDisableAllMasters(void)
mapOverAll(base,1,disableUniversePort,0);
}
int
vmeUniverseStartDMAXX(
volatile LERegister *base,
unsigned long local_addr,
unsigned long vme_addr,
unsigned long count)
{
if ((local_addr & 7) != (vme_addr & 7)) {
uprintf(stderr,"vmeUniverseStartDMA: misaligned addresses\n");
return -1;
}
{
/* help the compiler allocate registers */
register volatile LERegister *b=base;;
register unsigned long dgcsoff=UNIV_REGOFF_DGCS,dgcs;
dgcs=READ_LE(b, dgcsoff);
/* clear status and make sure CHAIN is clear */
dgcs &= ~UNIV_DGCS_CHAIN;
WRITE_LE(dgcs,
b, dgcsoff);
WRITE_LE(local_addr,
b, UNIV_REGOFF_DLA);
WRITE_LE(vme_addr,
b, UNIV_REGOFF_DVA);
WRITE_LE(count,
b, UNIV_REGOFF_DTBC);
dgcs |= UNIV_DGCS_GO;
EIEIO_REG; /* make sure GO is written after everything else */
WRITE_LE(dgcs,
b, dgcsoff);
}
SYNC; /* enforce command completion */
return 0;
}
int
vmeUniverseStartDMA(
unsigned long local_addr,
unsigned long vme_addr,
unsigned long count)
{
DFLT_BASE; /* vmeUniverseStartDMAXX doesn't check for a valid base address for efficiency reasons */
return vmeUniverseStartDMAXX(base, local_addr, vme_addr, count);
}
unsigned long
vmeUniverseReadRegXX(volatile LERegister *base, unsigned long offset)
{
@@ -1231,11 +1287,428 @@ vmeUniverseMapCRG(unsigned long vme_base, unsigned long as )
return vmeUniverseMapCRGXX( vmeUniverse0BaseAddr, vme_base, as );
}
#ifdef __rtems__
/* DMA Support -- including linked-list implementation */
#include "bspVmeDmaListP.h"
#include <bsp/vmeUniverseDMA.h>
/* Filter valid bits of DCTL */
#define DCTL_MODE_MASK \
( UNIV_DCTL_VDW_MSK | UNIV_DCTL_VAS_MSK | UNIV_DCTL_PGM | UNIV_DCTL_SUPER | UNIV_DCTL_VCT )
static uint32_t
xfer_mode2dctl(uint32_t xfer_mode)
{
uint32_t dctl;
/* Check requested bus mode */
/* Universe does not support 'non-incrementing' DMA */
/* NOTE: Universe IIb/d *does* support NOINC_VME but states
* that the VME address needs to be reprogrammed
* when re-issuing a transfer
*/
if ( xfer_mode & BSP_VMEDMA_MODE_NOINC_PCI )
return BSP_VMEDMA_STATUS_UNSUP;
/* ignore memory hint */
xfer_mode &= ~VME_AM_IS_MEMORY;
if ( VME_AM_IS_2eSST(xfer_mode) )
return BSP_VMEDMA_STATUS_UNSUP;
if ( ! VME_AM_IS_SHORT(xfer_mode) && ! VME_AM_IS_STD(xfer_mode) && ! VME_AM_IS_EXT(xfer_mode) )
return BSP_VMEDMA_STATUS_UNSUP;
/* Luckily DCTL bits match MCTL bits so we can use am2mode */
if ( am2mode( 1, xfer_mode, &dctl ) )
return BSP_VMEDMA_STATUS_UNSUP;
/* However, the book says that for DMA VAS==5 [which would
* be a CSR access] is reserved. Tests indicate that
* CSR access works on the IIb/d but not really (odd 32-bit
* addresses read 0) on the II.
* Nevertheless, we disallow DMA CSR access at this point
* in order to play it safe...
*/
switch ( UNIV_DCTL_VAS_MSK & dctl ) {
case UNIV_DCTL_VAS_A24:
case UNIV_DCTL_VAS_A32:
/* fixup the data width; universe may always use MBLT
* if data width is 64-bit so we go back to 32-bit
* if they didn't explicitely ask for MBLT cycles
*/
if ( (xfer_mode & 0xb) != 8 /* MBLT */
&& ( UNIV_DCTL_VDW_64 == (dctl & UNIV_DCTL_VDW_MSK) ) ) {
dctl &= ~UNIV_DCTL_VDW_MSK;
dctl |= UNIV_DCTL_VDW_32;
}
break;
case UNIV_DCTL_VAS_A16:
break;
default:
return BSP_VMEDMA_STATUS_UNSUP;
}
/* Make sure other MCTL bits are masked */
dctl &= DCTL_MODE_MASK;
if ( xfer_mode & BSP_VMEDMA_MODE_NOINC_VME ) {
/* If they want NOINC_VME then we have to do some
* fixup :-( ('errata' [in this case: feature addition] doc. pp. 11+)
*/
dctl &= ~UNIV_DCTL_VCT; /* clear block xfer flag */
dctl |= UNIV_DCTL_NO_VINC;
/* cannot do 64 bit transfers; go back to 32 */
if ( UNIV_DCTL_VDW_64 == (dctl & UNIV_DCTL_VDW_MSK) ) {
dctl &= ~UNIV_DCTL_VDW_MSK;
dctl |= UNIV_DCTL_VDW_32;
}
}
/* Set direction flag */
if ( BSP_VMEDMA_MODE_PCI2VME & xfer_mode )
dctl |= UNIV_DCTL_L2V;
return dctl;
}
/* Convert canonical xfer_mode into Universe setup bits; return -1 if request
* cannot be satisfied (unsupported features)
*/
int
vmeUniverseDmaSetupXX(volatile LERegister *base, int channel, uint32_t mode, uint32_t xfer_mode, void *custom)
{
uint32_t dctl, dgcs;
if ( channel != 0 )
return BSP_VMEDMA_STATUS_UNSUP;
dctl = xfer_mode2dctl(xfer_mode);
if ( (uint32_t)BSP_VMEDMA_STATUS_UNSUP == dctl )
return BSP_VMEDMA_STATUS_UNSUP;
/* Enable all interrupts at the controller */
dgcs = UNIV_DGCS_INT_MSK;
switch ( mode ) {
case BSP_VMEDMA_OPT_THROUGHPUT:
dgcs |= UNIV_DGCS_VON_1024 | UNIV_DGCS_VOFF_0_US;
/* VON counts are different in NO_VINC mode :-( */
dgcs |= ( xfer_mode & BSP_VMEDMA_MODE_NOINC_VME ) ?
UNIV_DGCS_VON_2048 : UNIV_DGCS_VON_1024;
break;
case BSP_VMEDMA_OPT_LOWLATENCY:
dgcs |= UNIV_DGCS_VOFF_0_US;
/* VON counts are different in NO_VINC mode :-( */
dgcs |= ( xfer_mode & BSP_VMEDMA_MODE_NOINC_VME ) ?
UNIV_DGCS_VON_512 : UNIV_DGCS_VON_256;
break;
case BSP_VMEDMA_OPT_SHAREDBUS:
dgcs |= UNIV_DGCS_VOFF_512_US;
/* VON counts are different in NO_VINC mode :-( */
dgcs |= ( xfer_mode & BSP_VMEDMA_MODE_NOINC_VME ) ?
UNIV_DGCS_VON_512 : UNIV_DGCS_VON_256;
break;
case BSP_VMEDMA_OPT_CUSTOM:
dctl = ((uint32_t*)custom)[0];
dgcs = ((uint32_t*)custom)[1];
break;
default:
case BSP_VMEDMA_OPT_DEFAULT:
break;
}
/* clear status bits */
dgcs |= UNIV_DGCS_STATUS_CLEAR;
vmeUniverseWriteRegXX(base, dctl, UNIV_REGOFF_DCTL);
vmeUniverseWriteRegXX(base, dgcs, UNIV_REGOFF_DGCS);
return BSP_VMEDMA_STATUS_OK;
}
int
vmeUniverseDmaSetup(int channel, uint32_t mode, uint32_t xfer_mode, void *custom)
{
DFLT_BASE;
return vmeUniverseDmaSetupXX(base, channel, mode, xfer_mode, custom);
}
int
vmeUniverseDmaStartXX(volatile LERegister *base, int channel, uint32_t pci_addr, uint32_t vme_addr, uint32_t n_bytes)
{
if ( channel != 0 )
return BSP_VMEDMA_STATUS_UNSUP;
if ((pci_addr & 7) != (vme_addr & 7)) {
uprintf(stderr,"vmeUniverseDmaStartXX: misaligned addresses\n");
return -1;
}
{
/* help the compiler allocate registers */
register volatile LERegister *b=base;;
register unsigned long dgcsoff=UNIV_REGOFF_DGCS,dgcs;
dgcs=READ_LE(b, dgcsoff);
/* clear status and make sure CHAIN is clear */
dgcs &= ~UNIV_DGCS_CHAIN;
WRITE_LE(dgcs,
b, dgcsoff);
WRITE_LE(pci_addr,
b, UNIV_REGOFF_DLA);
WRITE_LE(vme_addr,
b, UNIV_REGOFF_DVA);
WRITE_LE(n_bytes,
b, UNIV_REGOFF_DTBC);
dgcs |= UNIV_DGCS_GO;
EIEIO_REG; /* make sure GO is written after everything else */
WRITE_LE(dgcs,
b, dgcsoff);
}
SYNC; /* enforce command completion */
return 0;
}
/* This entry point is deprecated */
int
vmeUniverseStartDMAXX(
volatile LERegister *base,
unsigned long local_addr,
unsigned long vme_addr,
unsigned long count)
{
return vmeUniverseDmaStartXX(base, 0, local_addr, vme_addr, count);
}
int
vmeUniverseDmaStart(int channel, uint32_t pci_addr, uint32_t vme_addr, uint32_t n_bytes)
{
DFLT_BASE; /* vmeUniverseDmaStartXX doesn't check for a valid base address for efficiency reasons */
return vmeUniverseDmaStartXX(base, channel, pci_addr, vme_addr, n_bytes);
}
/* This entry point is deprecated */
int
vmeUniverseStartDMA(
unsigned long local_addr,
unsigned long vme_addr,
unsigned long count)
{
DFLT_BASE; /* vmeUniverseStartDMAXX doesn't check for a valid base address for efficiency reasons */
return vmeUniverseDmaStartXX(base, 0, local_addr, vme_addr, count);
}
uint32_t
vmeUniverseDmaStatusXX(volatile LERegister *base, int channel)
{
uint32_t dgcs;
if ( channel != 0 )
return BSP_VMEDMA_STATUS_UNSUP;
dgcs = vmeUniverseReadRegXX(base, UNIV_REGOFF_DGCS);
dgcs &= UNIV_DGCS_STATUS_CLEAR;
if ( 0 == dgcs || UNIV_DGCS_DONE == dgcs )
return BSP_VMEDMA_STATUS_OK;
if ( UNIV_DGCS_ACT & dgcs )
return BSP_VMEDMA_STATUS_BUSY;
if ( UNIV_DGCS_LERR & dgcs )
return BSP_VMEDMA_STATUS_BERR_PCI;
if ( UNIV_DGCS_VERR & dgcs )
return BSP_VMEDMA_STATUS_BERR_VME;
return BSP_VMEDMA_STATUS_OERR;
}
uint32_t
vmeUniverseDmaStatus(int channel)
{
DFLT_BASE;
return vmeUniverseDmaStatusXX(base, channel);
}
/* bspVmeDmaList driver interface implementation */
/* Cannot use VmeUniverseDMAPacketRec because st_le32 expects unsigned *
* and we get 'alias' warnings when we submit uint32_t *
*/
typedef volatile unsigned LERegister1;
typedef struct VmeUniverseDmaListDescRec_ {
LERegister1 dctl;
LERegister1 dtbc;
LERegister1 dla;
LERegister1 dummy1;
LERegister1 dva;
LERegister1 dummy2;
LERegister1 dcpp;
LERegister1 dummy3;
} VmeUniverseDmaListDescRec
__attribute__((aligned(32), __may_alias__));
typedef VmeUniverseDmaListDescRec *VmeUniverseDmaListDesc;
static void uni_desc_init (DmaDescriptor);
static int uni_desc_setup (DmaDescriptor, uint32_t, uint32_t, uint32_t, uint32_t, uint32_t);
static void uni_desc_setnxt(DmaDescriptor, DmaDescriptor);
static void uni_desc_dump (DmaDescriptor);
static int uni_desc_start (volatile void *controller_addr, int channel, DmaDescriptor p);
VMEDmaListClassRec vmeUniverseDmaListClass = {
desc_size: sizeof(VmeUniverseDMAPacketRec),
desc_align: 32,
freeList: 0,
desc_alloc: 0,
desc_free: 0,
desc_init: uni_desc_init,
desc_setnxt:uni_desc_setnxt,
desc_setup: uni_desc_setup,
desc_start: uni_desc_start,
desc_refr: 0,
desc_dump: uni_desc_dump,
};
/* gcc complains even if unsigned and uint32 are the same size :-( */
static inline void ST_LE32(volatile uint32_t *a, uint32_t v)
{
st_le32( (volatile unsigned *)a, v);
}
static void uni_desc_init (DmaDescriptor p)
{
VmeUniverseDmaListDesc d = p;
st_le32( &d->dcpp, UNIV_DCPP_IMG_NULL );
}
static void uni_desc_setnxt(DmaDescriptor p, DmaDescriptor n)
{
VmeUniverseDmaListDesc d = p;
if ( 0 == n ) {
st_le32( &d->dcpp, UNIV_DCPP_IMG_NULL );
} else {
st_le32( &d->dcpp, BSP_LOCAL2PCI_ADDR( (uint32_t)n));
}
}
static int
uni_desc_setup (
DmaDescriptor p,
uint32_t attr_mask,
uint32_t xfer_mode,
uint32_t pci_addr,
uint32_t vme_addr,
uint32_t n_bytes)
{
VmeUniverseDmaListDesc d = p;
LERegister1 dctl;
if ( BSP_VMEDMA_MSK_ATTR & attr_mask ) {
dctl = xfer_mode2dctl(xfer_mode);
if ( (uint32_t)BSP_VMEDMA_STATUS_UNSUP == dctl )
return -1;
st_le32( &d->dctl, dctl );
}
/* Last 3 bits of src & destination addresses must be the same.
* For sake of simplicity we enforce (stricter) 8-byte alignment
*/
if ( BSP_VMEDMA_MSK_PCIA & attr_mask ) {
if ( pci_addr & 0x7 )
return -1;
st_le32( &d->dla, pci_addr );
}
if ( BSP_VMEDMA_MSK_VMEA & attr_mask ) {
if ( vme_addr & 0x7 )
return -1;
st_le32( &d->dva, vme_addr );
}
if ( BSP_VMEDMA_MSK_BCNT & attr_mask ) {
st_le32( &d->dtbc, n_bytes );
}
return 0;
}
static int uni_desc_start
(volatile void *controller_addr, int channel, DmaDescriptor p)
{
volatile LERegister *base = controller_addr;
uint32_t dgcs;
if ( !base )
base = vmeUniverse0BaseAddr;
dgcs = vmeUniverseReadRegXX( base, UNIV_REGOFF_DGCS );
if ( UNIV_DGCS_ACT & dgcs )
return BSP_VMEDMA_STATUS_BUSY;
if ( !p ) {
/* Chain bit is cleared by non-linked-list start command
* but do this anyways...
*/
dgcs &= ~UNIV_DGCS_CHAIN;
vmeUniverseWriteRegXX( base, UNIV_REGOFF_DGCS, dgcs);
return 0;
}
/* clear status and set CHAIN bit */
dgcs |= UNIV_DGCS_CHAIN;
vmeUniverseWriteRegXX( base, UNIV_REGOFF_DGCS, dgcs);
/* make sure count is 0 for linked list DMA */
vmeUniverseWriteRegXX( base, 0x0, UNIV_REGOFF_DTBC);
/* set the address of the descriptor chain */
vmeUniverseWriteRegXX( base, BSP_LOCAL2PCI_ADDR((uint32_t)p), UNIV_REGOFF_DCPP);
/* and GO */
dgcs |= UNIV_DGCS_GO;
vmeUniverseWriteReg(dgcs, UNIV_REGOFF_DGCS);
return 0;
}
static void
uni_desc_dump(DmaDescriptor p)
{
VmeUniverseDmaListDesc d = p;
LERegister1 dcpp = ld_le32(&d->dcpp);
printf(" DLA: 0x%08x\n", ld_le32(&d->dla));
printf(" DVA: 0x%08x\n", ld_le32(&d->dva));
printf(" DCPP: 0x%08x%s\n", dcpp, (dcpp & UNIV_DCPP_IMG_NULL) ? " (LAST)" : "");
printf(" CTL: 0x%08x\n", ld_le32(&d->dctl));
printf(" TBC: 0x%08x\n", ld_le32(&d->dtbc));
}
/* RTEMS interrupt subsystem */
#ifdef __rtems__
#include <bsp/irq.h>
typedef struct
@@ -1421,7 +1894,7 @@ int pin = (int)arg;
UniverseIRQEntry ip;
unsigned long msk,lintstat,status;
int lvl;
#ifdef BSP_PIC_DO_EOI
#if defined(BSP_PIC_DO_EOI)
unsigned long linten;
#endif
@@ -1443,7 +1916,7 @@ unsigned long linten;
}
#endif
#ifndef BSP_PIC_DO_EOI /* Software priorities not supported */
#ifndef BSP_PIC_DO_EOI /* Software priorities not supported */
if ( (status = (lintstat & SPECIAL_IRQ_MSK)) )
universeSpecialISR( status );

View File

@@ -71,6 +71,9 @@
typedef unsigned long LERegister; /* emphasize contents are little endian */
/****** NOTE: USE OF VmeUniverseDMAPacket IS DEPRECATED *********
****** USE API IN VMEDMA.h INSTEAD *********/
/* NOTE: DMA packet descriptors MUST be 32 byte aligned */
typedef struct VmeUniverseDMAPacketRec_ {
LERegister dctl __attribute__((aligned(32)));
@@ -81,7 +84,7 @@ typedef struct VmeUniverseDMAPacketRec_ {
LERegister dummy2 __attribute__((packed));
LERegister dcpp __attribute__((packed));
LERegister dummy3 __attribute__((packed));
} VmeUniverseDMAPacketRec, *VmeUniverseDMAPacket;
} VmeUniverseDMAPacketRec, *VmeUniverseDMAPacket; /* DEPRECATED */
/* PCI CSR register */
#define UNIV_REGOFF_PCI_CSR 0x4
@@ -166,6 +169,7 @@ typedef struct VmeUniverseDMAPacketRec_ {
# define UNIV_DCTL_PGM (1<<14) /* VME PGM(1)/DATA(0) */
# define UNIV_DCTL_SUPER_MSK (3<<12) /* VME SUPER/USR mask 0x00003000 */
# define UNIV_DCTL_SUPER (1<<12) /* VME SUPER(1)/USR(0) */
# define UNIV_DCTL_NO_VINC (1<<9) /* VME no VME address increment [Universe IIa/b ONLY */
# define UNIV_DCTL_VCT (1<<8) /* VME enable BLT */
# define UNIV_DCTL_LD64EN (1<<7) /* PCI 64 enable */
@@ -196,10 +200,11 @@ typedef struct VmeUniverseDMAPacketRec_ {
# define UNIV_DGCS_VON_DONE (0<<20) /* VON counter disabled (do until done) */
# define UNIV_DGCS_VON_256 (1<<20) /* VON yield bus after 256 bytes */
# define UNIV_DGCS_VON_512 (2<<20) /* VON yield bus after 512 bytes */
# define UNIV_DGCS_VON_1024 (3<<20) /* VON yield bus after 512 bytes */
# define UNIV_DGCS_VON_2048 (4<<20) /* VON yield bus after 1024 bytes */
# define UNIV_DGCS_VON_1024 (3<<20) /* VON yield bus after 1024 bytes */
# define UNIV_DGCS_VON_2048 (4<<20) /* VON yield bus after 2048 bytes */
# define UNIV_DGCS_VON_4096 (5<<20) /* VON yield bus after 4096 bytes */
# define UNIV_DGCS_VON_8192 (6<<20) /* VON yield bus after 8192 bytes */
# define UNIV_DGCS_VON_16384 (7<<20) /* VON yield bus after 16384 bytes */
# define UNIV_DGCS_VOFF_MSK (15<<16) /* VOFF mask */
# define UNIV_DGCS_VOFF_0_US (0<<16) /* re-request VME master after 0 us */
# define UNIV_DGCS_VOFF_2_US (8<<16) /* re-request VME master after 2 us */
@@ -600,6 +605,9 @@ vmeUniverseSlavePortCfg(
unsigned long local_address,
unsigned long length);
/****** NOTE: USE OF vmeUniverseStartDMA IS DEPRECATED *********
****** USE API IN VMEDMA.h/vmeUniverseDMA.h INSTEAD *********/
/* start a (direct, not linked) DMA transfer
*
* NOTE: DCTL and DGCS must be set up
@@ -609,7 +617,15 @@ int
vmeUniverseStartDMA(
unsigned long local_addr,
unsigned long vme_addr,
unsigned long count);
unsigned long count); /* DEPRECATED */
int
vmeUniverseStartDMAXX(
volatile LERegister *ubase,
unsigned long local_addr,
unsigned long vme_addr,
unsigned long count); /* DEPRECATED */
/* read a register in PCI memory space
* (offset being one of the declared constants)
@@ -696,13 +712,6 @@ void
vmeUniverseSlavePortsShowXX();
#endif
int
vmeUniverseStartDMAXX(
volatile LERegister *ubase,
unsigned long local_addr,
unsigned long vme_addr,
unsigned long count);
/* Raise a VME Interrupt at 'level' and respond with 'vector' to a
* handler on the VME bus. (The handler could be a different board
* or the universe itself - [only works with universe II]).
@@ -879,8 +888,7 @@ vmeUniverseIntIsEnabled(unsigned int level);
* line a given 'level' is using. By default,
* all 7 VME levels use the first wire (pin==0) and
* all internal sources use the (optional) second
* wire (pin==1) [The driver doesn't support more than
* to wires].
* wire (pin==1).
* This feature is useful if you want to make use of
* different hardware priorities of the PIC. Let's
* say you want to give IRQ level 7 the highest priority.

View File

@@ -0,0 +1,80 @@
/* $Id$ */
#ifndef VME_UNIVERSE_DMA_H
#define VME_UNIVERSE_DMA_H
/*
* 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 <bsp/vmeUniverse.h>
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
extern struct VMEDmaListClassRec_ vmeUniverseDmaListClass;
int
vmeUniverseDmaSetupXX(volatile LERegister *base, int channel, uint32_t mode, uint32_t xfer_mode, void *custom);
int
vmeUniverseDmaSetup(int channel, uint32_t mode, uint32_t xfer_mode, void *custom);
int
vmeUniverseDmaStartXX(volatile LERegister *base, int channel, uint32_t pci_addr, uint32_t vme_addr, uint32_t n_bytes);
int
vmeUniverseDmaStart(int channel, uint32_t pci_addr, uint32_t vme_addr, uint32_t n_bytes);
uint32_t
vmeUniverseDmaStatusXX(volatile LERegister *base, int channel);
uint32_t
vmeUniverseDmaStatus(int channel);
#ifdef __cplusplus
}
#endif
#endif

View File

@@ -167,12 +167,15 @@
#define VME_AM_IS_2eSST(am) ((am) & (3<<10))
/* Use 16-bit transfers for coupled- or BLT cycles
/* Use 8/16/32-bit transfers for coupled- or BLT cycles
* (MBLT, 2exxx are probably always 64-bit)
*/
#define VME_MODE_DBW16 (1<<12)
#define VME_MODE_DBW_MSK (3<<12)
#define VME_MODE_DBW8 (1<<12)
#define VME_MODE_DBW16 (2<<12)
#define VME_MODE_DBW32 (3<<12)
/* Unused Flags 1<<12 .. 1<<23 are reserved
/* Unused Flags 1<<14 .. 1<<23 are reserved
* Flags 1<<24 .. 1<<31 are for driver specific options
*/