/**
* @file
*
* @ingroup shared_vmedma
*
* @brief Public interface of DMA routines
*/
#ifndef BSP_VME_DMA_H
#define BSP_VME_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 <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
/**
* @defgroup shared_vmedma VMEDMA Support
*
* @ingroup shared_vmeuniverse
*
* @brief VMEDMA Support Package
*/
/* 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 DEBUG
void
BSP_VMEDmaListDump(BSP_VMEDmaListDescriptor p);
#endif
#ifdef __cplusplus
}
#endif
#endif