forked from Imagelibrary/rtems
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:
@@ -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:
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
292
c/src/lib/libbsp/shared/vmeUniverse/VMEDMA.h
Normal file
292
c/src/lib/libbsp/shared/vmeUniverse/VMEDMA.h
Normal 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
|
||||
335
c/src/lib/libbsp/shared/vmeUniverse/bspVmeDmaList.c
Normal file
335
c/src/lib/libbsp/shared/vmeUniverse/bspVmeDmaList.c
Normal 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
|
||||
130
c/src/lib/libbsp/shared/vmeUniverse/bspVmeDmaList.h
Normal file
130
c/src/lib/libbsp/shared/vmeUniverse/bspVmeDmaList.h
Normal 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
|
||||
96
c/src/lib/libbsp/shared/vmeUniverse/bspVmeDmaListP.h
Normal file
96
c/src/lib/libbsp/shared/vmeUniverse/bspVmeDmaListP.h
Normal 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
|
||||
@@ -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 */
|
||||
|
||||
88
c/src/lib/libbsp/shared/vmeUniverse/vmeTsi148DMA.h
Normal file
88
c/src/lib/libbsp/shared/vmeUniverse/vmeTsi148DMA.h
Normal 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
|
||||
@@ -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 );
|
||||
|
||||
@@ -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.
|
||||
|
||||
80
c/src/lib/libbsp/shared/vmeUniverse/vmeUniverseDMA.h
Normal file
80
c/src/lib/libbsp/shared/vmeUniverse/vmeUniverseDMA.h
Normal 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
|
||||
@@ -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
|
||||
*/
|
||||
|
||||
|
||||
Reference in New Issue
Block a user