summaryrefslogtreecommitdiffstats
path: root/c/src/lib/libbsp/sparc/shared/pci/grpci2dma.c
diff options
context:
space:
mode:
Diffstat (limited to 'c/src/lib/libbsp/sparc/shared/pci/grpci2dma.c')
-rw-r--r--c/src/lib/libbsp/sparc/shared/pci/grpci2dma.c2059
1 files changed, 0 insertions, 2059 deletions
diff --git a/c/src/lib/libbsp/sparc/shared/pci/grpci2dma.c b/c/src/lib/libbsp/sparc/shared/pci/grpci2dma.c
deleted file mode 100644
index d5f1f9942f..0000000000
--- a/c/src/lib/libbsp/sparc/shared/pci/grpci2dma.c
+++ /dev/null
@@ -1,2059 +0,0 @@
-/*
- * GRPCI2 DMA Driver
- *
- * COPYRIGHT (c) 2017
- * Cobham Gaisler AB
- *
- * The license and distribution terms for this file may be
- * found in the file LICENSE in this distribution or at
- * http://www.rtems.org/license/LICENSE.
- */
-
-#include <stdlib.h>
-#include <string.h>
-#include <stddef.h>
-#include <drvmgr/drvmgr.h>
-#include <rtems.h>
-#include <rtems/bspIo.h> /* for printk */
-#include <bsp.h>
-#include <bsp/grpci2dma.h>
-
-/* This driver has been prepared for SMP operation
- */
-/* Use interrupt lock privmitives compatible with SMP defined in
- * RTEMS 4.11.99 and higher.
- */
-#if (((__RTEMS_MAJOR__ << 16) | (__RTEMS_MINOR__ << 8) | __RTEMS_REVISION__) >= 0x040b63)
-
-/* map via rtems_interrupt_lock_* API: */
-#define SPIN_DECLARE(lock) RTEMS_INTERRUPT_LOCK_MEMBER(lock)
-#define SPIN_INIT(lock, name) rtems_interrupt_lock_initialize(lock, name)
-#define SPIN_LOCK(lock, level) rtems_interrupt_lock_acquire_isr(lock, &level)
-#define SPIN_LOCK_IRQ(lock, level) rtems_interrupt_lock_acquire(lock, &level)
-#define SPIN_UNLOCK(lock, level) rtems_interrupt_lock_release_isr(lock, &level)
-#define SPIN_UNLOCK_IRQ(lock, level) rtems_interrupt_lock_release(lock, &level)
-#define SPIN_IRQFLAGS(k) rtems_interrupt_lock_context k
-#define SPIN_ISR_IRQFLAGS(k) SPIN_IRQFLAGS(k)
-
-#else
-
-/* maintain single-core compatibility with older versions of RTEMS: */
-#define SPIN_DECLARE(name)
-#define SPIN_INIT(lock, name)
-#define SPIN_LOCK(lock, level)
-#define SPIN_LOCK_IRQ(lock, level) rtems_interrupt_disable(level)
-#define SPIN_UNLOCK(lock, level)
-#define SPIN_UNLOCK_IRQ(lock, level) rtems_interrupt_enable(level)
-#define SPIN_IRQFLAGS(k) rtems_interrupt_level k
-#define SPIN_ISR_IRQFLAGS(k)
-
-#ifdef RTEMS_SMP
-#error SMP mode not compatible with these interrupt lock primitives
-#endif
-
-#endif
-
-/*#define STATIC*/
-#define STATIC static
-
-/*#define INLINE*/
-#define INLINE inline
-
-/*#define UNUSED*/
-#define UNUSED __attribute__((unused))
-
-/*#define DEBUG 1*/
-
-#ifdef DEBUG
-#define DBG(x...) printf(x)
-#else
-#define DBG(x...)
-#endif
-
-#define BD_CHAN_EN (1<<BD_CHAN_EN_BIT)
-#define BD_CHAN_ID (0x3<<BD_CHAN_ID_BIT)
-#define BD_CHAN_TYPE (0x3<<BD_CHAN_TYPE_BIT)
-#define BD_CHAN_TYPE_DMA (0x1<<BD_CHAN_TYPE_BIT)
-#define BD_CHAN_BDCNT (0xffff<<BD_CHAN_BDCNT_BIT)
-#define BD_CHAN_EN_BIT 31
-#define BD_CHAN_ID_BIT 22
-#define BD_CHAN_TYPE_BIT 20
-#define BD_CHAN_BDCNT_BIT 0
-
-#define BD_DATA_EN (0x1<<BD_DATA_EN_BIT)
-#define BD_DATA_IE (0x1<<BD_DATA_IE_BIT)
-#define BD_DATA_DR (0x1<<BD_DATA_DR_BIT)
-#define BD_DATA_BE (0x1<<BD_DATA_BE_BIT)
-#define BD_DATA_TYPE (0x3<<BD_DATA_TYPE_BIT)
-#define BD_DATA_TYPE_DATA (0x0<<BD_DATA_TYPE_BIT)
-#define BD_DATA_ER (0x1<<BD_DATA_ER_BIT)
-#define BD_DATA_LEN (0xffff<<BD_DATA_LEN_BIT)
-#define BD_DATA_EN_BIT 31
-#define BD_DATA_IE_BIT 30
-#define BD_DATA_DR_BIT 29
-#define BD_DATA_BE_BIT 28
-#define BD_DATA_TYPE_BIT 20
-#define BD_DATA_ER_BIT 19
-#define BD_DATA_LEN_BIT 0
-
-#define DMACTRL_SAFE (0x1<<DMACTRL_SAFE_BIT)
-#define DMACTRL_WCLEAR (0x1fff<<DMACTRL_ERR_BIT)
-#define DMACTRL_ERR (0x1f<<DMACTRL_ERR_BIT)
-#define DMACTRL_CHIRQ (0xff<<DMACTRL_CHIRQ_BIT)
-#define DMACTRL_ERR (0x1f<<DMACTRL_ERR_BIT)
-#define DMACTRL_NUMCH (0x7<<DMACTRL_NUMCH_BIT)
-#define DMACTRL_DIS (0x1<<DMACTRL_DIS_BIT)
-#define DMACTRL_IE (0x1<<DMACTRL_IE_BIT)
-#define DMACTRL_ACT (0x1<<DMACTRL_ACT_BIT)
-#define DMACTRL_EN (0x1<<DMACTRL_EN_BIT)
-
-#define DMACTRL_SAFE_BIT 31
-#define DMACTRL_CHIRQ_BIT 12
-#define DMACTRL_ERR_BIT 7
-#define DMACTRL_NUMCH_BIT 4
-#define DMACTRL_DIS_BIT 2
-#define DMACTRL_IE_BIT 1
-#define DMACTRL_ACT_BIT 3
-#define DMACTRL_EN_BIT 0
-
-/* GRPCI2 DMA does not allow more than 8 DMA chans */
-#define MAX_DMA_CHANS 8
-
-/* GRPCI2 DMA does not allow transfer of more than 0x10000 words */
-#define MAX_DMA_TRANSFER_SIZE (0x10000*4)
-
-/* We use the following limits as default */
-#define MAX_DMA_DATA 128
-
-/* Memory and HW Registers Access routines. All 32-bit access routines */
-#define BD_WRITE(addr, val) (*(volatile unsigned int *)(addr) = (unsigned int)(val))
-/*#define BD_READ(addr) (*(volatile unsigned int *)(addr))*/
-#define BD_READ(addr) leon_r32_no_cache((unsigned long)(addr))
-#define REG_WRITE(addr, val) (*(volatile unsigned int *)(addr) = (unsigned int)(val))
-#define REG_READ(addr) (*(volatile unsigned int *)(addr))
-
-/*
- * GRPCI2 DMA Channel descriptor
- */
-struct grpci2_bd_chan {
- volatile unsigned int ctrl; /* 0x00 DMA Control */
- volatile unsigned int nchan; /* 0x04 Next DMA Channel Address */
- volatile unsigned int nbd; /* 0x08 Next Data Descriptor in channel */
- volatile unsigned int res; /* 0x0C Reserved */
-};
-
-/*
- * GRPCI2 DMA Data descriptor
- */
-struct grpci2_bd_data {
- volatile unsigned int ctrl; /* 0x00 DMA Data Control */
- volatile unsigned int pci_adr; /* 0x04 PCI Start Address */
- volatile unsigned int ahb_adr; /* 0x08 AHB Start address */
- volatile unsigned int next; /* 0x0C Next Data Descriptor in channel */
-};
-
-
-/*
- * GRPCI2 DMA APB Register MAP
- */
-struct grpci2dma_regs {
- volatile unsigned int dma_ctrl; /* 0x00 */
- volatile unsigned int dma_bdbase; /* 0x04 */
- volatile unsigned int dma_chact; /* 0x08 */
-};
-
-#define DEVNAME_LEN 11
-/*
- * GRPCI2 DMA Driver private data struture
- */
-struct grpci2dma_priv {
- /* DMA control registers */
- struct grpci2dma_regs *regs;
- char devname[DEVNAME_LEN];
-
- /* Channel info */
- struct {
- /* Channel pointer. Indicates the assigned channel
- * for a given cid (used as index). NULL if not assigned.
- */
- struct grpci2_bd_chan * ptr;
- /* Is this channel allocated by the driver */
- int allocated;
- /* Last added data descriptor for each channel.
- * This simplifies/speeds up adding data descriptors
- * to the channel*/
- struct grpci2_bd_data * lastdata;
- /* Is this channel active */
- int active;
- /* Interrupt-code Handling
- * - isr: Holds the ISR for each channel
- * - isr_arg: Holds the ISR arg for each channel
- */
- grpci2dma_isr_t isr;
- void * isr_arg;
-
- /* DMA Channel Semaphore */
- rtems_id sem;
- } channel[MAX_DMA_CHANS];
-
- /* Indicates the number of channels. */
- int nchans;
-
- /* Indicates the number of active channels. */
- int nactive;
-
- /* Indicates if the number of DMA ISR that have been registered
- * into the GRPCI2 DRIVER */
- int isr_registered;
-
- /* Callback to register the DMA ISR into the GRPCI2 DRIVER */
- void (*isr_register)( void (*isr)(void*), void * arg);
-
- /* Spin-lock ISR protection */
- SPIN_DECLARE(devlock);
-};
-
-/* The GRPCI2 DMA semaphore */
-rtems_id grpci2dma_sem;
-
-/*
- * GRPCI2 DMA internal prototypes
- */
-/* -Descriptor linked-list functions*/
-STATIC int grpci2dma_channel_list_add(struct grpci2_bd_chan * list,
- struct grpci2_bd_chan * chan);
-STATIC int grpci2dma_channel_list_remove(struct grpci2_bd_chan * chan);
-STATIC int grpci2dma_data_list_add(struct grpci2_bd_chan * chan,
- struct grpci2_bd_data * data, struct grpci2_bd_data * last_chan_data);
-STATIC int grpci2dma_data_list_remove(struct grpci2_bd_chan * chan,
- struct grpci2_bd_data * data);
-STATIC int grpci2dma_channel_list_foreach(struct grpci2_bd_chan * chan,
- int func( struct grpci2_bd_chan * chan), int maxindex);
-STATIC int grpci2dma_data_list_foreach(struct grpci2_bd_data * data,
- int func( struct grpci2_bd_data * data), int maxindex);
-
-/* -DMA ctrl access functions */
-STATIC INLINE int grpci2dma_ctrl_init(void);
-STATIC INLINE int grpci2dma_ctrl_start(struct grpci2_bd_chan * chan);
-STATIC INLINE int grpci2dma_ctrl_stop(void);
-STATIC INLINE int grpci2dma_ctrl_resume(void);
-STATIC INLINE unsigned int grpci2dma_ctrl_status(void);
-STATIC INLINE unsigned int grpci2dma_ctrl_base(void);
-STATIC INLINE unsigned int grpci2dma_ctrl_active(void);
-STATIC INLINE int grpci2dma_ctrl_numch_set(int numch);
-STATIC INLINE int grpci2dma_ctrl_interrupt_status(void);
-STATIC INLINE int grpci2dma_ctrl_interrupt_enable(void);
-STATIC INLINE int grpci2dma_ctrl_interrupt_disable(void);
-STATIC INLINE int grpci2dma_ctrl_interrupt_clear(void);
-
-/* -Descriptor access functions */
-STATIC int grpci2dma_channel_bd_init(struct grpci2_bd_chan * chan);
-STATIC int grpci2dma_data_bd_init(struct grpci2_bd_data * data,
- uint32_t pci_adr, uint32_t ahb_adr, int dir, int endianness,
- int size, struct grpci2_bd_data * next);
-STATIC int grpci2dma_channel_bd_enable(struct grpci2_bd_chan * chan,
- unsigned int options);
-STATIC int grpci2dma_channel_bd_disable(struct grpci2_bd_chan * chan);
-STATIC void grpci2dma_channel_bd_set_cid(struct grpci2_bd_chan * chan,
- int cid);
-STATIC int grpci2dma_channel_bd_get_cid(struct grpci2_bd_chan * chan);
-STATIC int grpci2dma_data_bd_status(struct grpci2_bd_data *data);
-STATIC int grpci2dma_data_bd_disable(struct grpci2_bd_data *desc);
-STATIC int grpci2dma_data_bd_interrupt_enable(struct grpci2_bd_data * data);
-STATIC struct grpci2_bd_data * grpci2dma_channel_bd_get_data(
- struct grpci2_bd_chan * chan);
-STATIC void grpci2dma_channel_bd_set_data(struct grpci2_bd_chan * chan,
- struct grpci2_bd_data * data);
-STATIC struct grpci2_bd_chan * grpci2dma_channel_bd_get_next(
- struct grpci2_bd_chan * chan);
-STATIC struct grpci2_bd_data * grpci2dma_data_bd_get_next(
- struct grpci2_bd_data * data);
-STATIC void grpci2dma_channel_bd_set_next(struct grpci2_bd_chan * chan,
- struct grpci2_bd_chan * next);
-STATIC void grpci2dma_data_bd_set_next(struct grpci2_bd_data * data,
- struct grpci2_bd_data * next);
-
-/* -Channel functions */
-STATIC int grpci2dma_channel_open(struct grpci2_bd_chan * chan, int cid);
-STATIC int grpci2dma_channel_free_id(void);
-STATIC struct grpci2_bd_chan * grpci2dma_channel_get_active_list(void);
-STATIC int grpci2dma_channel_start(int chan_no, int options);
-STATIC int grpci2dma_channel_stop(int chan_no);
-STATIC int grpci2dma_channel_push(int chan_no, void *dataptr, int index,
- int ndata);
-STATIC int grpci2dma_channel_close(int chan_no);
-STATIC int grpci2dma_channel_isr_unregister(int chan_no);
-
-/* -ISR functions*/
-STATIC void grpci2dma_isr(void *arg);
-
-/* -Init function called by GRPCI2*/
-int grpci2dma_init(void * regs,
- void isr_register( void (*isr)(void*), void * arg));
-
-
-#ifdef DEBUG
-STATIC int grpci2dma_channel_print(struct grpci2_bd_chan * chan);
-STATIC int grpci2dma_data_print(struct grpci2_bd_data * data);
-#endif
-
-static struct grpci2dma_priv *grpci2dmapriv = NULL;
-
-/* All data linked list must point to a disabled descriptor at the end.
- * We use this DISABLED_DESCRIPTOR as a list end for all channels.
- */
-#define ALIGNED __attribute__((aligned(GRPCI2DMA_BD_DATA_ALIGN)))
-static ALIGNED struct grpci2_bd_data disabled_data = {
- /*.ctrl=*/0,
- /*.pci_adr=*/0,
- /*.ahb_adr=*/0,
- /*.next=*/0
-};
-#define DISABLED_DESCRIPTOR (&disabled_data)
-
-/*** START OF DESCRIPTOR LINKED-LIST HELPER FUNCTIONS ***/
-
-/* This functions adds a channel descriptor to the DMA channel
- * linked list. It assumes that someone has check the input
- * parameters already.
- */
-STATIC int grpci2dma_channel_list_add(struct grpci2_bd_chan * list,
- struct grpci2_bd_chan * chan)
-{
- DBG("Adding channel (0x%08x) to GRPCI2 DMA driver\n", (unsigned int) chan);
-
- /* Add channel to the linnked list */
- if (list == chan) {
- /* No previous channels. Finish. */
- return GRPCI2DMA_ERR_OK;
- } else {
- /* Get next chan from list */
- struct grpci2_bd_chan * nchan = grpci2dma_channel_bd_get_next(list);
- /* Close the circular linked list */
- grpci2dma_channel_bd_set_next(chan,nchan);
- /* Attach the new channel in the middle */
- grpci2dma_channel_bd_set_next(list, chan);
- return GRPCI2DMA_ERR_OK;
- }
-}
-
-/* This functions removes a channel descriptor from the DMA channel
- * linked list. It assumes that someone has check the input
- * parameters already.
- * It returns 0 if successfull. Otherwise,
- * it can return:
- * - ERROR: Different causes:
- * x Number of channels is corrupted.
- */
-STATIC int grpci2dma_channel_list_remove(struct grpci2_bd_chan * chan)
-{
- DBG("Removing channel (0x%08x) from GRPCI2 DMA driver\n",
- (unsigned int) chan);
-
- /* Remove channel from the linnked list */
- struct grpci2_bd_chan * nchan = grpci2dma_channel_bd_get_next(chan);
- if (nchan != chan){
- /* There are more channels */
- /* Since this is a circular linked list, we need to find last channel
- * and update the pointer to the next element */
- /* Use index to avoid having an infinite loop in case of corrupted
- * channels */
- struct grpci2_bd_chan * new_first_chan = nchan;
- struct grpci2_bd_chan * curr_chan;
- int i=1;
- while((nchan != chan) && (i<MAX_DMA_CHANS)){
- curr_chan = nchan;
- nchan = grpci2dma_channel_bd_get_next(curr_chan);
- i++;
- }
- if (nchan != chan) {
- DBG("Maximum DMA channels exceeded. Maybe corrupted?\n");
- return GRPCI2DMA_ERR_ERROR;
- } else {
- /* Update the pointer */
- grpci2dma_channel_bd_set_next(curr_chan, new_first_chan);
- return GRPCI2DMA_ERR_OK;
- }
- }else{
- /* There are no more channels */
- return GRPCI2DMA_ERR_OK;
- }
-}
-
-/* This functions adds a data descriptor to the channel's data
- * linked list. The function assumes, that the data descriptor
- * points to either a DISABLED_DESCRIPTOR or to linked list of
- * data descriptors that ends with a DISABLED_DESCRIPTOR.
- * It returns the number of active data descriptors
- * if successfull. Otherwise, it can return:
- * - ERROR: Different causes:
- * x Number of channels is corrupted.
- * x Last linked list element is not pointing to the first.
- */
-STATIC int grpci2dma_data_list_add(struct grpci2_bd_chan * chan,
- struct grpci2_bd_data * data, struct grpci2_bd_data * last_chan_data)
-{
- DBG("Adding data (0x%08x) to channel (0x%08x)\n",
- (unsigned int) data, (unsigned int) chan);
-
- /* Add data to the linnked list */
- /* 1st- Get current data */
- struct grpci2_bd_data * first_data = grpci2dma_channel_bd_get_data(chan);
- if (first_data == NULL) {
- /* Channel should always be pointing to a disabled descriptor */
- DBG("Channel not pointing to disabled descpriptor\n");
- return GRPCI2DMA_ERR_ERROR;
- } else if (first_data == DISABLED_DESCRIPTOR){
- /* No previous data. Assign this one and finish. */
- grpci2dma_channel_bd_set_data(chan, data);
- return GRPCI2DMA_ERR_OK;
- } else {
- /* Let's add the data to the last data pointer added to this channel */
- /* Attach the new data */
- grpci2dma_data_bd_set_next(last_chan_data, data);
- /* 2nd- Let's check again to make sure that the DMA did not finished
- * while we were inserting the new data */
- first_data = grpci2dma_channel_bd_get_data(chan);
- if (first_data == DISABLED_DESCRIPTOR){
- grpci2dma_channel_bd_set_data(chan, data);
- }
- return GRPCI2DMA_ERR_OK;
- }
-}
-
-/* This functions removes a data descriptor from the channel's data
- * linked list. Note that in a normal execution, the DMA will remove
- * the data descriptors from the linked list, so there is no need to
- * use this function. It returns 0 if successfull. Otherwise,
- * it can return:
- * - WRONGPTR: The chan (or data) pointer is either NULL or not aligned to
- * 0x10.
- * - STOPDMA: The DMA is running, cannot add channels while DMA is running.
- * - TOOMANY: The max number of data is reached.
- * - ERROR: Different causes:
- * x There are no free channel id numbers.
- * x Number of channels is corrupted.
- * x Last linked list element is not pointing to the first.
- */
-UNUSED STATIC int grpci2dma_data_list_remove(struct grpci2_bd_chan * chan,
- struct grpci2_bd_data * data)
-{
- DBG("Removing data (0x%08x) from channel (0x%08x)\n",
- (unsigned int) data, (unsigned int) chan);
-
- /* Remove data from the linked list */
- /* 1st- Get current DMA data */
- struct grpci2_bd_data * first_data = grpci2dma_channel_bd_get_data(chan);
- if (first_data == NULL) {
- /* Channel should always be pointing to a disabled descriptor */
- DBG("Channel not pointing to disabled descpriptor\n");
- return GRPCI2DMA_ERR_ERROR;
- } else if (first_data == DISABLED_DESCRIPTOR){
- /* No previous data. Cannot detach */
- DBG("No data to detach.\n");
- return GRPCI2DMA_ERR_NOTFOUND;
- } else {
- /* 2nd- Already available data, let's find the data */
- if (first_data == data) {
- /* 3rd- It is the first one. */
- struct grpci2_bd_data *current = first_data;
- struct grpci2_bd_data *next = grpci2dma_data_bd_get_next(current);
- if (next != DISABLED_DESCRIPTOR){
- /* There are more data */
- /* Set channel next data descriptor to data*/
- grpci2dma_channel_bd_set_data(chan, next);
- /* Update the removed data */
- grpci2dma_data_bd_set_next(data, DISABLED_DESCRIPTOR);
- return GRPCI2DMA_ERR_OK;
- }else{
- /* No more data */
- /* Clear DMA NBD */
- grpci2dma_channel_bd_set_data(chan, DISABLED_DESCRIPTOR);
- /* Update the removed data */
- grpci2dma_data_bd_set_next(data, DISABLED_DESCRIPTOR);
- return GRPCI2DMA_ERR_OK;
- }
- } else {
- /* It is not the first data. Let's find it */
- struct grpci2_bd_data * current = first_data;
- struct grpci2_bd_data * next = grpci2dma_data_bd_get_next(current);
- while( (next != data) && (next != DISABLED_DESCRIPTOR) &&
- (next != NULL)){
- current = next;
- next = grpci2dma_data_bd_get_next(current);
- }
- if (next != data) {
- DBG("Maximum DMA data exceeded. Maybe corrupted?\n");
- return GRPCI2DMA_ERR_NOTFOUND;
- } else {
- /* Detach the data */
- next = grpci2dma_data_bd_get_next(data);
- grpci2dma_data_bd_set_next(current, next);
- /* Update the removed data */
- grpci2dma_data_bd_set_next(data, DISABLED_DESCRIPTOR);
- return GRPCI2DMA_ERR_OK;
- }
- }
- }
-}
-
-/* Iterate through all channel starting in FIRST_CHAN up to MAXINDEX
- * and execute FUNC*/
-UNUSED STATIC int grpci2dma_channel_list_foreach(
- struct grpci2_bd_chan * first_chan,
- int func( struct grpci2_bd_chan * chan), int maxindex)
-{
- if (maxindex <= 0) return 0;
- if (first_chan == NULL) {
- /* No previous channels */
- return 0;
- } else {
- /* Available channels */
- /* Iterate through next channels */
- /* Use index to avoid having an infinite loop in case of corrupted
- * channels */
- int i=0;
- int ret;
- struct grpci2_bd_chan * curr_chan = first_chan;
- struct grpci2_bd_chan * nchan;
- do{
- if (curr_chan == NULL) return GRPCI2DMA_ERR_WRONGPTR;
- ret = func(curr_chan);
- if (ret < 0){
- /* error */
- return ret;
- }
- nchan = grpci2dma_channel_bd_get_next(curr_chan);
- curr_chan = nchan;
- i++;
- }while((curr_chan != first_chan) && (i < maxindex));
- }
- return 0;
-}
-
-/* Iterate through all data starting in FIRST_DATA up to MAXINDEX
- * and execute FUNC*/
-STATIC int grpci2dma_data_list_foreach(struct grpci2_bd_data * first_data,
- int func( struct grpci2_bd_data * data), int maxindex)
-{
- if (maxindex <= 0) return 0;
- if (first_data == NULL) return GRPCI2DMA_ERR_WRONGPTR;
- /* Available data */
- /* Iterate through next data */
- /* Use index to avoid having an infinite loop in case of corrupted
- * channels */
- int i=0;
- int ret;
- struct grpci2_bd_data * curr_data = first_data;
- struct grpci2_bd_data * ndata;
- while((curr_data != DISABLED_DESCRIPTOR) && (i < maxindex)){
- if (curr_data == NULL) return GRPCI2DMA_ERR_WRONGPTR;
- ret = func(curr_data);
- if (ret < 0){
- /* error */
- return ret;
- }
- ndata = grpci2dma_data_bd_get_next(curr_data);
- curr_data = ndata;
- i++;
- }
- return 0;
-}
-
-
-/*** END OF DESCRIPTOR LINKED-LIST HELPER FUNCTIONS ***/
-
-/*** START OF DMACTRL ACCESS FUNCTIONS ***/
-
-/* Initialize the DMA Ctrl*/
-STATIC INLINE int grpci2dma_ctrl_init()
-{
- struct grpci2dma_priv *priv = grpci2dmapriv;
-
- /* Clear DMA Control: clear IRQ and ERR status */
- REG_WRITE(&priv->regs->dma_ctrl, 0|DMACTRL_SAFE|DMACTRL_CHIRQ|DMACTRL_ERR);
-
- /* Clear DMA BASE */
- REG_WRITE(&priv->regs->dma_bdbase, 0);
-
- /* Clear DMA Chan */
- REG_WRITE(&priv->regs->dma_chact, 0);
-
- return 0;
-}
-
-
-/* Stop the DMA */
-STATIC INLINE int grpci2dma_ctrl_stop( void )
-{
- struct grpci2dma_priv *priv = grpci2dmapriv;
-
- /* Stop DMA */
- unsigned int ctrl = REG_READ(&priv->regs->dma_ctrl);
- REG_WRITE(&priv->regs->dma_ctrl, (ctrl & ~(DMACTRL_WCLEAR | DMACTRL_EN)) |
- DMACTRL_DIS);
-
- return 0;
-}
-
-/* Start the DMA */
-STATIC INLINE int grpci2dma_ctrl_start( struct grpci2_bd_chan * chan)
-{
- struct grpci2dma_priv *priv = grpci2dmapriv;
-
- /* Set BDBASE to linked list of chans */
- REG_WRITE(&priv->regs->dma_bdbase, (unsigned int) chan);
-
- /* Start DMA */
- unsigned int ctrl = REG_READ(&priv->regs->dma_ctrl);
- REG_WRITE(&priv->regs->dma_ctrl, (ctrl & ~(DMACTRL_WCLEAR | DMACTRL_DIS)) |
- DMACTRL_EN);
-
- return 0;
-}
-
-/* Resume the DMA */
-STATIC INLINE int grpci2dma_ctrl_resume( void )
-{
- struct grpci2dma_priv *priv = grpci2dmapriv;
-
- /* Resume DMA */
- unsigned int ctrl = REG_READ(&priv->regs->dma_ctrl);
- REG_WRITE(&priv->regs->dma_ctrl, (ctrl & ~(DMACTRL_WCLEAR | DMACTRL_DIS)) |
- DMACTRL_EN);
-
- return 0;
-}
-
-/* Interrupt status*/
-STATIC INLINE int grpci2dma_ctrl_interrupt_status(void)
-{
- struct grpci2dma_priv *priv = grpci2dmapriv;
-
- unsigned int ctrl = REG_READ(&priv->regs->dma_ctrl);
- return (ctrl & DMACTRL_IE);
-}
-
-/* Enable interrupts */
-STATIC INLINE int grpci2dma_ctrl_interrupt_enable(void)
-{
- struct grpci2dma_priv *priv = grpci2dmapriv;
-
- unsigned int ctrl = REG_READ(&priv->regs->dma_ctrl);
- if (ctrl & DMACTRL_IE){
- /* Nothing to do. Already enabled */
- return 0;
- }
-
- /* Clear pending CHIRQ and errors */
- ctrl = ctrl | (DMACTRL_CHIRQ | DMACTRL_ERR);
-
- /* Enable interrupts */
- ctrl = ctrl | DMACTRL_IE;
-
- REG_WRITE(&priv->regs->dma_ctrl, ctrl );
- return 0;
-}
-
-/* Disable interrupts */
-STATIC INLINE int grpci2dma_ctrl_interrupt_disable(void)
-{
- struct grpci2dma_priv *priv = grpci2dmapriv;
-
- unsigned int ctrl = REG_READ(&priv->regs->dma_ctrl);
- if ((ctrl & DMACTRL_IE) == 0){
- /* Nothing to do. Already disabled */
- return 0;
- }
-
- /* Clear pending CHIRQ and errors */
- ctrl = ctrl | (DMACTRL_CHIRQ | DMACTRL_ERR);
-
- /* Disable interrupts */
- ctrl = ctrl & ~(DMACTRL_IE);
-
- REG_WRITE(&priv->regs->dma_ctrl, ctrl );
- return 0;
-}
-
-/* Clear interrupts */
-STATIC INLINE int grpci2dma_ctrl_interrupt_clear(void)
-{
- struct grpci2dma_priv *priv = grpci2dmapriv;
-
- unsigned int ctrl = REG_READ(&priv->regs->dma_ctrl);
- REG_WRITE(&priv->regs->dma_ctrl, (ctrl | DMACTRL_ERR | DMACTRL_CHIRQ));
- return 0;
-}
-
-STATIC INLINE unsigned int grpci2dma_ctrl_status()
-{
- struct grpci2dma_priv *priv = grpci2dmapriv;
-
- /* Read DMA */
- return (REG_READ(&priv->regs->dma_ctrl));
-}
-
-STATIC INLINE unsigned int grpci2dma_ctrl_base()
-{
- struct grpci2dma_priv *priv = grpci2dmapriv;
-
- /* Read DMA */
- return (REG_READ(&priv->regs->dma_bdbase));
-}
-
-UNUSED STATIC INLINE unsigned int grpci2dma_ctrl_active()
-{
- struct grpci2dma_priv *priv = grpci2dmapriv;
-
- /* Read DMA */
- return (REG_READ(&priv->regs->dma_chact));
-}
-
-/* Set the DMA CTRL register NUMCH field */
-STATIC INLINE int grpci2dma_ctrl_numch_set(int numch)
-{
- struct grpci2dma_priv *priv = grpci2dmapriv;
-
- unsigned int ctrl = REG_READ(&priv->regs->dma_ctrl);
-
- /* Clear old value */
- ctrl = (ctrl & ~(DMACTRL_NUMCH));
-
- /* Put new value */
- ctrl = (ctrl | ( (numch << DMACTRL_NUMCH_BIT) & DMACTRL_NUMCH));
-
- REG_WRITE(&priv->regs->dma_ctrl, ctrl & ~(DMACTRL_WCLEAR));
- return 0;
-}
-
-/*** END OF DMACTRL ACCESS FUNCTIONS ***/
-
-/*** START OF DESCRIPTOR ACCESS FUNCTIONS ***/
-
-STATIC int grpci2dma_data_bd_init(struct grpci2_bd_data * data,
- uint32_t pci_adr, uint32_t ahb_adr, int dir, int endianness, int size,
- struct grpci2_bd_data * next)
-{
- BD_WRITE(&data->ctrl, 0 |
- (BD_DATA_EN) |
- (BD_DATA_TYPE_DATA) |
- (dir == GRPCI2DMA_AHBTOPCI? BD_DATA_DR:0) |
- (endianness == GRPCI2DMA_LITTLEENDIAN? BD_DATA_BE:0) |
- ( (size << BD_DATA_LEN_BIT) & BD_DATA_LEN )
- );
- BD_WRITE(&data->pci_adr, pci_adr);
- BD_WRITE(&data->ahb_adr, ahb_adr);
- BD_WRITE(&data->next, (unsigned int) next);
- return 0;
-}
-
-STATIC int grpci2dma_channel_bd_init(struct grpci2_bd_chan * chan)
-{
- BD_WRITE(&chan->ctrl, 0 | BD_CHAN_TYPE_DMA | BD_CHAN_EN);
- BD_WRITE(&chan->nchan, (unsigned int) chan);
- BD_WRITE(&chan->nbd, (unsigned int) DISABLED_DESCRIPTOR);
- return 0;
-}
-
-/* Enable a channel with options.
- * options include:
- * - options & 0xFFFF: Maximum data descriptor count before
- * moving to next DMA channel.
- */
-STATIC int grpci2dma_channel_bd_enable(struct grpci2_bd_chan * chan,
- unsigned int options)
-{
- unsigned int ctrl = BD_READ(&chan->ctrl);
- ctrl = (ctrl & ~(BD_CHAN_BDCNT));
- BD_WRITE(&chan->ctrl, (ctrl | BD_CHAN_EN |
- ( (options << BD_CHAN_BDCNT_BIT) & BD_CHAN_BDCNT)));
- return 0;
-}
-
-/* Disable channel.
- */
-STATIC int grpci2dma_channel_bd_disable(struct grpci2_bd_chan * chan)
-{
- unsigned int ctrl = BD_READ(&chan->ctrl);
- BD_WRITE(&chan->ctrl, (ctrl & ~(BD_CHAN_EN)));
- return 0;
-}
-
-/* Get the CID of a channel.
- */
-UNUSED STATIC int grpci2dma_channel_bd_get_cid(struct grpci2_bd_chan * chan)
-{
- /* Get cid from chan */
- unsigned ctrl = BD_READ(&chan->ctrl);
- unsigned cid = (ctrl & (BD_CHAN_ID)) >> BD_CHAN_ID_BIT;
- return cid;
-}
-
-/* Set the CID of a channel. */
-STATIC void grpci2dma_channel_bd_set_cid(struct grpci2_bd_chan * chan, int cid)
-{
- /* Set cid from chan */
- unsigned ctrl = BD_READ(&chan->ctrl);
- ctrl = (ctrl & ~(BD_CHAN_ID)) | ((cid << BD_CHAN_ID_BIT) & BD_CHAN_ID);
- BD_WRITE(&chan->ctrl,ctrl);
- return;
-}
-
-/* Disable data descriptor*/
-UNUSED STATIC int grpci2dma_data_bd_disable(struct grpci2_bd_data *desc)
-{
- BD_WRITE(&desc->ctrl,0);
- return 0;
-}
-
-/* Return status of data descriptor*/
-STATIC int grpci2dma_data_bd_status(struct grpci2_bd_data *desc)
-{
- int status = BD_READ(&desc->ctrl);
- if (status & BD_DATA_ER) {
- return GRPCI2DMA_BD_STATUS_ERR;
- }else if (status & BD_DATA_EN) {
- return GRPCI2DMA_BD_STATUS_ENABLED;
- }else {
- return GRPCI2DMA_BD_STATUS_DISABLED;
- }
- return GRPCI2DMA_BD_STATUS_ERR;
-}
-
-/* Enable interrupts in data descriptor*/
-STATIC int grpci2dma_data_bd_interrupt_enable(struct grpci2_bd_data * data)
-{
- unsigned int ctrl = BD_READ(&data->ctrl);
- BD_WRITE(&data->ctrl, ctrl | BD_DATA_IE);
- return 0;
-}
-
-/* Get data descriptor */
-STATIC struct grpci2_bd_data * grpci2dma_channel_bd_get_data(
- struct grpci2_bd_chan * chan)
-{
- return (struct grpci2_bd_data *) BD_READ(&chan->nbd);
-}
-
-/* Set data descriptorl */
-STATIC void grpci2dma_channel_bd_set_data(struct grpci2_bd_chan * chan,
- struct grpci2_bd_data * data)
-{
- BD_WRITE(&chan->nbd, (unsigned int) data);
-}
-
-/* Get next channel */
-STATIC struct grpci2_bd_chan * grpci2dma_channel_bd_get_next(
- struct grpci2_bd_chan * chan)
-{
- return (struct grpci2_bd_chan *) BD_READ(&chan->nchan);
-}
-
-/* Get next data */
-STATIC struct grpci2_bd_data * grpci2dma_data_bd_get_next(
- struct grpci2_bd_data * data)
-{
- return (struct grpci2_bd_data *) BD_READ(&data->next);
-}
-
-/* Set next channel */
-STATIC void grpci2dma_channel_bd_set_next(struct grpci2_bd_chan * chan,
- struct grpci2_bd_chan * next)
-{
- BD_WRITE(&chan->nchan,(unsigned int) next);
-}
-
-/* Set next data */
-STATIC void grpci2dma_data_bd_set_next(struct grpci2_bd_data * data,
- struct grpci2_bd_data * next)
-{
- BD_WRITE(&data->next,(unsigned int) next);
-}
-
-/*** END OF DESCRIPTOR ACCESS FUNCTIONS ***/
-
-/*** START OF CHANNEL FUNCTIONS ***/
-
-STATIC int grpci2dma_channel_open(struct grpci2_bd_chan * chan, int cid)
-{
- struct grpci2dma_priv *priv = grpci2dmapriv;
- int allocated = 0;
-
- /* Get pointer */
- if (chan == NULL) {
- /* User does not provide channel, let's create it */
- chan = grpci2dma_channel_new(1);
- allocated = 1;
- }else{
- /* Make sure the pointer is not already on the linked list */
- int i;
- for (i=0; i<MAX_DMA_CHANS; i++){
- if (priv->channel[i].ptr == chan){
- return GRPCI2DMA_ERR_WRONGPTR;
- }
- }
- }
-
- DBG("Opening channel %d (0x%08x)\n", cid, (unsigned int) chan);
-
- /* Init channel descriptor */
- grpci2dma_channel_bd_init(chan);
-
- /* Assign cid to chan */
- priv->channel[cid].ptr = chan;
- grpci2dma_channel_bd_set_cid(chan, cid);
-
- /* Increase number of channels */
- priv->nchans++;
-
- DBG("number of channels: %d\n", priv->nchans);
-
- /* Initialize channel data */
- priv->channel[cid].allocated = allocated;
- priv->channel[cid].active = 0;
-
- /* Initialize record of last added data */
- priv->channel[cid].lastdata = DISABLED_DESCRIPTOR;
-
- return cid;
-}
-
-/* Get first free CID.
- */
-STATIC int grpci2dma_channel_free_id()
-{
- struct grpci2dma_priv *priv = grpci2dmapriv;
-
- /* Find the first free CID */
- int i;
- for (i=0; i<MAX_DMA_CHANS; i++){
- if (priv->channel[i].ptr == NULL){
- return i;
- }
- }
- return GRPCI2DMA_ERR_TOOMANY;
-}
-
-/* Get the active channel circular linked list */
-STATIC struct grpci2_bd_chan * grpci2dma_channel_get_active_list()
-{
- struct grpci2dma_priv *priv = grpci2dmapriv;
- int i;
- /* Just get the first non NULL associated cid */
- for (i=0; i< MAX_DMA_CHANS; i++){
- if ((priv->channel[i].ptr != NULL) && (priv->channel[i].active)){
- return priv->channel[i].ptr;
- }
- }
- return NULL;
-}
-
-/* Start a channel */
-STATIC int grpci2dma_channel_start(int chan_no, int options)
-{
- struct grpci2dma_priv *priv = grpci2dmapriv;
- struct grpci2_bd_chan *chan;
- SPIN_IRQFLAGS(irqflags);
-
- /* Get chan pointer */
- chan = priv->channel[chan_no].ptr;
-
- /* Check if channel is active */
- if (priv->channel[chan_no].active){
- /* nothing to do */
- return GRPCI2DMA_ERR_OK;
- }
-
- /* Get the max descriptor count */
- unsigned int desccnt;
- if (options == 0){
- /* Default */
- desccnt = 0xffff;
- }else{
- desccnt = options & 0xffff;
- }
-
- /* Start the channel by enabling it.
- * HWNOTE: In GRPCI2 this bit does not work as it is supposed.
- * So we better add/remove the channel from the active linked
- * list. */
- grpci2dma_channel_bd_enable(chan, desccnt);
- priv->channel[chan_no].active = 1;
- priv->nactive++;
- /* Get active linked list */
- struct grpci2_bd_chan * list = grpci2dma_channel_get_active_list();
- if (list == NULL){
- /* No previous channels. New list */
- list = chan;
- }
- /* Add channel from the linked list */
- if (grpci2dma_channel_list_add(list, chan) < 0){
- return GRPCI2DMA_ERR_ERROR;
- }
-
- /* Increase NUMCH in DMA ctrl */
- SPIN_LOCK_IRQ(&priv->devlock, irqflags);
- grpci2dma_ctrl_numch_set( (priv->nactive? priv->nactive -1:0));
-
- /* Check if DMA is active */
- if (!grpci2dma_active()){
- /* Start DMA */
- grpci2dma_ctrl_start(chan);
- }
- SPIN_UNLOCK_IRQ(&priv->devlock, irqflags);
-
- DBG("Channel %d started (0x%08x)\n", chan_no, (unsigned int) chan);
-
- return GRPCI2DMA_ERR_OK;
-}
-
-/* Stop a channel */
-STATIC int grpci2dma_channel_stop(int chan_no)
-{
- struct grpci2dma_priv *priv = grpci2dmapriv;
- struct grpci2_bd_chan *chan;
- SPIN_IRQFLAGS(irqflags);
- int resume;
-
- /* Get chan pointer */
- chan = priv->channel[chan_no].ptr;
-
- /* Check if channel is active */
- if (!priv->channel[chan_no].active){
- /* nothing to do */
- return GRPCI2DMA_ERR_OK;
- }
-
- /* First remove channel from the linked list */
- if (grpci2dma_channel_list_remove(chan) < 0){
- return GRPCI2DMA_ERR_ERROR;
- }
-
- /* Update driver struct */
- priv->channel[chan_no].active = 0;
- priv->nactive--;
-
- /* Check if DMA is active and it the removed
- * channel is the active */
- resume = 0;
- SPIN_LOCK_IRQ(&priv->devlock, irqflags);
- if (grpci2dma_active() && (grpci2dma_ctrl_active() == (unsigned int)chan)){
- /* We need to stop the DMA */
- grpci2dma_ctrl_stop();
- SPIN_UNLOCK_IRQ(&priv->devlock, irqflags);
- /* Wait until DMA stops */
- while (grpci2dma_active()){}
- /* We need to check later to resume the DMA */
- resume = 1;
- }else{
- SPIN_UNLOCK_IRQ(&priv->devlock, irqflags);
- }
-
-
- /* Now either the DMA is stopped, or it is processing
- * a different channel and the removed channel is no
- * longer in the linked list */
-
- /* Now is safe to update the removed channel */
- grpci2dma_channel_bd_set_next(chan, chan);
-
- /* Stop the channel by disabling it.
- * HWNOTE: In GRPCI2 this bit does not work as it is supposed.
- * So we better remove the channel from the active linked
- * list. */
- grpci2dma_channel_bd_disable(chan);
-
- /* Point channel to disabled descriptor */
- grpci2dma_channel_bd_set_data(chan, DISABLED_DESCRIPTOR);
-
- DBG("Channel %d stoped (0x%08x)\n", chan_no, (unsigned int) chan);
-
- /* Decrease NUMCH in DMA ctrl */
- SPIN_LOCK_IRQ(&priv->devlock, irqflags);
- grpci2dma_ctrl_numch_set( (priv->nactive? priv->nactive -1:0));
-
- /* Reactivate DMA only if we stopped */
- if (resume){
- /* We have two options, either we stopped when the active
- * channel was still the active one, or we stopped when
- * the active channel was a different one */
- if (grpci2dma_ctrl_active() == (unsigned int) chan){
- /* In this case, we need to start the DMA with
- * any active channel on the list */
- int i;
- for (i=0; i<MAX_DMA_CHANS; i++){
- if (priv->channel[i].active){
- grpci2dma_ctrl_start(priv->channel[i].ptr);
- break;
- }
- }
- }else{
- /* In this case, we need to resume the DMA operation */
- /* HWNOTE: The GRPCI2 core does not update the channel next
- * data descriptor if we stopped a channel. This means that
- * we need to resume the DMA from the descriptor is was,
- * by only setting the enable bit, and not changing the
- * base register */
- grpci2dma_ctrl_resume();
- }
- }
- SPIN_UNLOCK_IRQ(&priv->devlock, irqflags);
-
- return GRPCI2DMA_ERR_OK;
-}
-
-STATIC int grpci2dma_channel_push(int chan_no, void *dataptr, int index,
- int ndata)
-{
- struct grpci2dma_priv *priv = grpci2dmapriv;
- struct grpci2_bd_chan * chan;
- struct grpci2_bd_data * data = dataptr;
-
- /* Get channel */
- chan = priv->channel[chan_no].ptr;
-
- DBG("Pushing %d data (starting at 0x%08x) to channel %d (0x%08x)\n",
- ndata, (unsigned int) &data[index], chan_no, (unsigned int) chan);
-
- /* Get last added data */
- struct grpci2_bd_data * last_added = priv->channel[chan_no].lastdata;
-
- /* Add data to channel */
- grpci2dma_data_list_add(chan, &data[index], last_added);
-
- /* Update last added */
- priv->channel[chan_no].lastdata = &data[index + ndata-1];
-
- return GRPCI2DMA_ERR_OK;
-}
-
-STATIC int grpci2dma_channel_close(int chan_no)
-{
- struct grpci2dma_priv *priv = grpci2dmapriv;
- struct grpci2_bd_chan * chan;
-
- /* Get channel */
- chan = priv->channel[chan_no].ptr;
-
- DBG("Closing channel %d (0x%08x)\n", chan_no, (unsigned int) chan);
-
- /* Stop channel */
- if (grpci2dma_channel_stop(chan_no) != GRPCI2DMA_ERR_OK ){
- DBG("Cannot stop channel!.\n");
- return GRPCI2DMA_ERR_STOPDMA;
- }
-
- /* Unregister channel ISR */
- grpci2dma_channel_isr_unregister(chan_no);
-
- /* Free the cid */
- priv->channel[chan_no].ptr = NULL;
-
- /* Remove the ISR */
- priv->channel[chan_no].isr = NULL;
- priv->channel[chan_no].isr_arg = NULL;
-
- /* Deallocate channel if needed */
- if (priv->channel[chan_no].allocated){
- grpci2dma_channel_delete((void *)chan);
- }
-
- /* Decrease number of channels */
- priv->nchans--;
-
- DBG("number of channels: %d\n", priv->nchans);
-
- /* Everything OK */
- return GRPCI2DMA_ERR_OK;
-}
-
-/* Register channel ISR */
-STATIC int grpci2dma_channel_isr_unregister(int chan_no)
-{
- struct grpci2dma_priv *priv = grpci2dmapriv;
- SPIN_IRQFLAGS(irqflags);
-
- /* Unregister channel ISR */
- priv->channel[chan_no].isr = NULL;
- priv->channel[chan_no].isr_arg = NULL;
-
- /* Unregister DMA ISR in GRPCI2 if needed */
- priv->isr_registered--;
- if(priv->isr_registered == 0){
- /* Disable DMA Interrupts */
- SPIN_LOCK_IRQ(&priv->devlock, irqflags);
- grpci2dma_ctrl_interrupt_disable();
- SPIN_UNLOCK_IRQ(&priv->devlock, irqflags);
- (priv->isr_register)( NULL, NULL);
- }
-
- /* Everything OK */
- return GRPCI2DMA_ERR_OK;
-}
-
-/*** END OF CHANNEL FUNCTIONS ***/
-
-/*** START OF ISR FUNCTIONS ***/
-
-/* PCI DMA Interrupt handler, called when there is a PCI DMA interrupt */
-STATIC void grpci2dma_isr(void *arg)
-{
- struct grpci2dma_priv *priv = arg;
- SPIN_ISR_IRQFLAGS(irqflags);
- unsigned int ctrl = grpci2dma_ctrl_status();
- /* Clear Interrupts */
- SPIN_LOCK(&priv->devlock, irqflags);
- grpci2dma_ctrl_interrupt_clear();
- SPIN_UNLOCK(&priv->devlock, irqflags);
- unsigned int sts = (ctrl & DMACTRL_CHIRQ) >> DMACTRL_CHIRQ_BIT;
- unsigned int errsts = (ctrl & DMACTRL_ERR);
-
- /* Error interrupt */
- if(errsts){
- /* Find which channels had the error.
- * The GRPCI2DMA core does not indicate which channel
- * had the error, so we need to get 1st the base descriptor register
- * and see if it a channel. If is not a channel, then the active
- * channel register tells us which channel is.
- * After having the channel we need to find out which channel was. */
- struct grpci2_bd_chan * chan =
- (struct grpci2_bd_chan *) grpci2dma_ctrl_base();
- /* Check if the base is a channel descriptor */
- if ((BD_READ(&chan->ctrl) & BD_CHAN_TYPE) != BD_CHAN_TYPE_DMA){
- /* Is not a channel, so the channel is in the channel active
- * register */
- chan = (struct grpci2_bd_chan *) grpci2dma_ctrl_active();
- }
- int i;
- for (i=0; i<MAX_DMA_CHANS; i++){
- if (chan == priv->channel[i].ptr){
- /* Found */
- if (priv->channel[i].isr != NULL){
- (priv->channel[i].isr)(priv->channel[i].isr_arg,i,errsts);
- }else{
- printk("Unhandled GRPCI2 DMA error interrupt, sts:0x%02x\n", errsts);
- }
- break;
- }
- }
- if (i == MAX_DMA_CHANS){
- printk("Unhandled GRPCI2 DMA error interrupt , sts:0x%02x\n", errsts);
- }
- }
-
- /* Normal packet interrupt */
- int cid=0;
- /* Find which channels have interrupts */
- while(sts){
- /* Find if current channel has an interrupt*/
- if(sts & 0x1){
- /* Find if current channel has an ISR */
- if (priv->channel[cid].isr != NULL){
- (priv->channel[cid].isr)(
- priv->channel[cid].isr_arg, cid, errsts);
- }else{
- printk("Unhandled GRPCI2 DMA interrupt in channel %d, sts:0x%02x\n", cid, 0);
- }
- }
- /* Next channel */
- sts = sts >> 1;
- cid++;
- }
-}
-
-/*** END OF ISR FUNCTIONS ***/
-
-/*** START OF DEBUG HELPERS ***/
-#ifdef DEBUG
-STATIC int grpci2dma_channel_print(struct grpci2_bd_chan * chan)
-{
- printf(" GRPCI2 DMA channel descriptor\n");
- printf(" 0x%08x DMA channel control 0x%08x\n", (unsigned int) chan, chan->ctrl);
- printf(" 31 en 0x%01x Channel descriptor enable.\n", (chan->ctrl >> 31) & (0x1));
- printf(" 24:22 cid 0x%01x Channel ID.\n", (chan->ctrl >> 22) & (0x7));
- printf(" 21:20 type 0x%01x Descriptor type. 01=DMA channel descriptor.\n", (chan->ctrl >> 20) & (0x3));
- printf(" 15:0 dlen 0x%04x Data descriptor count.\n", (chan->ctrl >> 0) & (0xffff));
- printf("\n");
- printf(" 0x%08x Next DMA channel 0x%08x\n", (unsigned int) &(chan->nchan), chan->nchan);
- printf(" 31:0 nc 0x%08x Next DMA channel.\n", chan->nchan);
- printf("\n");
- printf(" 0x%08x Next data descriptor 0x%08x\n" , (unsigned int) &(chan->nbd), chan->nbd);
- printf(" 31:0 nd 0x%08x Next data descriptor.\n", chan->nbd);
- printf("\n");
- return 0;
-}
-
-STATIC int grpci2dma_data_print(struct grpci2_bd_data * data)
-{
- printf(" GRPCI2 DMA data descriptor\n");
- printf(" 0x%08x DMA data control 0x%08x\n", (unsigned int) data, data->ctrl);
- printf(" 31 en 0x%01x Data descriptor enable.\n" , (data->ctrl >> 31) & (0x1));
- printf(" 30 ie 0x%01x Interrupt generation enable.\n" , (data->ctrl >> 30) & (0x1));
- printf(" 29 dr 0x%01x Tranfer direction.\n" , (data->ctrl >> 29) & (0x1));
- printf(" 28 be 0x%01x Bus endianess.\n" , (data->ctrl >> 28) & (0x1));
- printf(" 21:20 type 0x%01x Descriptor type. 00=DMA data descriptor.\n" , (data->ctrl >> 20) & (0x3));
- printf(" 19 er 0x%01x Error status.\n" , (data->ctrl >> 19) & (0x1));
- printf(" 15:0 len 0x%04x Transfer lenght (in words) - 1.\n" , (data->ctrl >> 0) & (0xffff));
- printf("\n");
- printf(" 0x%08x 32-bit PCI start address 0x%08x\n" , (unsigned int) &(data->pci_adr), data->pci_adr);
- printf(" 31:0 pa 0x%08x PCI address.\n" , data->pci_adr);
- printf("\n");
- printf(" 0x%08x 32-bit AHB start address 0x%08x\n" , (unsigned int) &(data->ahb_adr), data->ahb_adr);
- printf(" 31:0 aa 0x%08x AHB address.\n" , data->ahb_adr);
- printf("\n");
- printf(" 0x%08x Next data descriptor 0x%08x\n" , (unsigned int) &(data->next), data->next);
- printf(" 31:0 nd 0x%08x Next data descriptor.\n" , data->next);
- printf("\n");
- return 0;
-}
-#endif
-/*** END OF DEBUG HELPERS ***/
-
-/*** START OF MEMORY ALLOCATION FUNCTIONS ***/
-
-void * grpci2dma_channel_new(int number)
-{
- /* Allocate memory */
- unsigned int * orig_ptr = (unsigned int *) malloc(
- (GRPCI2DMA_BD_CHAN_SIZE)*number + GRPCI2DMA_BD_CHAN_ALIGN);
- if (orig_ptr == NULL) return NULL;
-
- /* Get the aligned pointer */
- unsigned int aligned_ptr = (
- ((unsigned int) orig_ptr + GRPCI2DMA_BD_CHAN_ALIGN) &
- ~(GRPCI2DMA_BD_CHAN_ALIGN - 1));
-
- /* Save the original pointer just before the aligned pointer */
- unsigned int ** tmp_ptr =
- (unsigned int **) (aligned_ptr - sizeof(orig_ptr));
- *tmp_ptr= orig_ptr;
-
- /* Return aligned pointer */
- return (void *) aligned_ptr;
-}
-
-void grpci2dma_channel_delete(void * chan)
-{
- /* Recover orignal pointer placed just before the aligned pointer */
- unsigned int * orig_ptr;
- unsigned int ** tmp_ptr = (unsigned int **) (chan - sizeof(orig_ptr));
- orig_ptr = *tmp_ptr;
-
- /* Deallocate memory */
- free(orig_ptr);
-}
-
-void * grpci2dma_data_new(int number)
-{
- /* Allocate memory */
- unsigned int * orig_ptr = (unsigned int *) malloc(
- (GRPCI2DMA_BD_DATA_SIZE)*number + GRPCI2DMA_BD_DATA_ALIGN);
- if (orig_ptr == NULL) return NULL;
-
- /* Get the aligned pointer */
- unsigned int aligned_ptr = (
- ((unsigned int) orig_ptr + GRPCI2DMA_BD_DATA_ALIGN) &
- ~(GRPCI2DMA_BD_DATA_ALIGN - 1));
-
- /* Save the original pointer before the aligned pointer */
- unsigned int ** tmp_ptr =
- (unsigned int **) (aligned_ptr - sizeof(orig_ptr));
- *tmp_ptr= orig_ptr;
-
- /* Return aligned pointer */
- return (void *) aligned_ptr;
-}
-
-void grpci2dma_data_delete(void * data)
-{
- /* Recover orignal pointer placed just before the aligned pointer */
- unsigned int * orig_ptr;
- unsigned int ** tmp_ptr = (unsigned int **) (data - sizeof(orig_ptr));
- orig_ptr = *tmp_ptr;
-
- /* Deallocate memory */
- free(orig_ptr);
-}
-
-/*** END OF MEMORY ALLOCATION FUNCTIONS ***/
-
-/*** START OF USER API ***/
-
-/* Initialize GRPCI2 DMA: GRPCI2 DRIVER calls this
- * using a weak function definition */
-int grpci2dma_init(
- void * regs, void isr_register( void (*isr)(void*), void * arg))
-{
- struct grpci2dma_priv *priv;
- int i;
-
- DBG("Registering GRPCI2 DMA driver with arg: 0x%08x\n",
- (unsigned int) regs);
-
- /* We only allow one GRPCI2 DMA */
- if (grpci2dmapriv) {
- DBG("Driver only supports one PCI DMA core\n");
- return DRVMGR_FAIL;
- }
-
- /* Device Semaphore created with count = 1 */
- if (rtems_semaphore_create(rtems_build_name('G', 'P', '2', 'D'), 1,
- RTEMS_FIFO | RTEMS_SIMPLE_BINARY_SEMAPHORE | \
- RTEMS_NO_INHERIT_PRIORITY | RTEMS_LOCAL | \
- RTEMS_NO_PRIORITY_CEILING, 0, &grpci2dma_sem) != RTEMS_SUCCESSFUL)
- return -1;
-
- /* Allocate and init Memory for DMA */
- int size = sizeof(struct grpci2dma_priv);
- priv = (struct grpci2dma_priv *) malloc(size);
- if (priv == NULL)
- return DRVMGR_NOMEM;
-
- /* Initialize all fields */
- memset(priv, 0, size);
- priv->regs = regs;
- strncpy(&priv->devname[0], "grpci2dma0", DEVNAME_LEN);
-
- /* Initialize Spin-lock for GRPCI2dma Device. */
- SPIN_INIT(&priv->devlock, priv->devname);
-
- /* Channel Sempahores */
- for (i=0; i<MAX_DMA_CHANS; i++){
- /* set to NULL, they are created when openning channels */
- priv->channel[i].sem = RTEMS_ID_NONE;
- }
-
- /* Register device */
- grpci2dmapriv = priv;
-
- /* Initialize Ctrl regs */
- grpci2dma_ctrl_init();
-
- /* Install DMA ISR */
- priv->isr_register = isr_register;
-
- /* Startup actions:
- * - stop DMA
- */
- grpci2dma_ctrl_stop();
-
- return DRVMGR_OK;
-}
-
-/* Assign ISR Function to DMA IRQ */
-int grpci2dma_isr_register(int chan_no, grpci2dma_isr_t dmaisr, void *data)
-{
- struct grpci2dma_priv *priv = grpci2dmapriv;
- SPIN_IRQFLAGS(irqflags);
-
- if (!priv){
- /* DMA not initialized */
- return GRPCI2DMA_ERR_NOINIT;
- }
-
- /* Check isr */
- if (dmaisr == NULL){
- /* No ISR */
- return GRPCI2DMA_ERR_WRONGPTR;
- }
-
- /* Get chan pointer */
- if ((chan_no < 0 ) || (chan_no >= MAX_DMA_CHANS)) {
- /* Wrong channel id */
- return GRPCI2DMA_ERR_WRONGPTR;
- }
-
- /* Check chan is open */
- if (priv->channel[chan_no].ptr == NULL){
- /* No channel */
- return GRPCI2DMA_ERR_NOTFOUND;
- }
-
- /* Take driver lock - Wait until we get semaphore */
- if (rtems_semaphore_obtain(grpci2dma_sem, RTEMS_WAIT, RTEMS_NO_TIMEOUT)
- != RTEMS_SUCCESSFUL){
- return GRPCI2DMA_ERR_ERROR;
- }
-
- /* Take channel lock - Wait until we get semaphore */
- if (rtems_semaphore_obtain(priv->channel[chan_no].sem, RTEMS_WAIT, RTEMS_NO_TIMEOUT)
- != RTEMS_SUCCESSFUL){
- rtems_semaphore_release(grpci2dma_sem);
- return GRPCI2DMA_ERR_ERROR;
- }
-
- /* Register channel ISR */
- priv->channel[chan_no].isr_arg = data;
- priv->channel[chan_no].isr = dmaisr;
-
- /* Register DMA ISR in GRPCI2 if not done yet */
- if(priv->isr_registered == 0){
- (priv->isr_register)( grpci2dma_isr, (void *) priv);
- /* Enable DMA Interrupts */
- SPIN_LOCK_IRQ(&priv->devlock, irqflags);
- grpci2dma_ctrl_interrupt_enable();
- SPIN_UNLOCK_IRQ(&priv->devlock, irqflags);
- }
- priv->isr_registered++;
-
- /* Release channel sempahore */
- rtems_semaphore_release(priv->channel[chan_no].sem);
-
- /* Release driver sempahore */
- rtems_semaphore_release(grpci2dma_sem);
-
- return GRPCI2DMA_ERR_OK;
-}
-
-/* Assign ISR Function to DMA IRQ */
-int grpci2dma_isr_unregister(int chan_no)
-{
- struct grpci2dma_priv *priv = grpci2dmapriv;
- int ret;
-
- if (!priv){
- /* DMA not initialized */
- return GRPCI2DMA_ERR_NOINIT;
- }
-
- /* Get chan pointer */
- if ((chan_no < 0 ) || (chan_no >= MAX_DMA_CHANS)) {
- /* Wrong channel id */
- return GRPCI2DMA_ERR_WRONGPTR;
- }
-
- /* Check chan is open */
- if (priv->channel[chan_no].ptr == NULL){
- /* No channel */
- return GRPCI2DMA_ERR_NOTFOUND;
- }
-
- /* Get chan ISR */
- if (priv->channel[chan_no].isr == NULL){
- /* Nothing to do */
- return GRPCI2DMA_ERR_OK;
- }
-
- /* Take driver lock - Wait until we get semaphore */
- if (rtems_semaphore_obtain(grpci2dma_sem, RTEMS_WAIT, RTEMS_NO_TIMEOUT)
- != RTEMS_SUCCESSFUL){
- return GRPCI2DMA_ERR_ERROR;
- }
-
- /* Take channel lock - Wait until we get semaphore */
- if (rtems_semaphore_obtain(priv->channel[chan_no].sem, RTEMS_WAIT, RTEMS_NO_TIMEOUT)
- != RTEMS_SUCCESSFUL){
- rtems_semaphore_release(grpci2dma_sem);
- return GRPCI2DMA_ERR_ERROR;
- }
-
- /* Unregister channel ISR */
- ret = grpci2dma_channel_isr_unregister(chan_no);
-
- /* Release channel sempahore */
- rtems_semaphore_release(priv->channel[chan_no].sem);
-
- /* Release driver sempahore */
- rtems_semaphore_release(grpci2dma_sem);
-
- return ret;
-}
-
-int grpci2dma_open(void * chanptr)
-{
- struct grpci2dma_priv *priv = grpci2dmapriv;
- int cid;
- int ret;
-
- if (!priv){
- /* DMA not initialized */
- return GRPCI2DMA_ERR_NOINIT;
- }
-
- /* Check alignment */
- if (((unsigned int ) chanptr) & (GRPCI2DMA_BD_CHAN_ALIGN-1)) {
- /* Channel is not properly aligned */
- return GRPCI2DMA_ERR_WRONGPTR;
- }
-
- /* Take driver lock - Wait until we get semaphore */
- if (rtems_semaphore_obtain(grpci2dma_sem, RTEMS_WAIT, RTEMS_NO_TIMEOUT)
- != RTEMS_SUCCESSFUL){
- return GRPCI2DMA_ERR_ERROR;
- }
-
- /* Get free channel id */
- cid = grpci2dma_channel_free_id();
- if (cid < 0 ){
- rtems_semaphore_release(grpci2dma_sem);
- return GRPCI2DMA_ERR_TOOMANY;
- }
-
- /* Open channel */
- ret = grpci2dma_channel_open((struct grpci2_bd_chan *) chanptr, cid);
-
- /* Create channel semaphore with count = 1 */
- if (ret >= 0){
- if (rtems_semaphore_create(
- rtems_build_name('P', 'D', '0', '0' + cid), 1,
- RTEMS_FIFO | RTEMS_SIMPLE_BINARY_SEMAPHORE | \
- RTEMS_NO_INHERIT_PRIORITY | RTEMS_LOCAL | \
- RTEMS_NO_PRIORITY_CEILING, 0, &priv->channel[cid].sem
- ) != RTEMS_SUCCESSFUL) {
- priv->channel[cid].sem = RTEMS_ID_NONE;
- rtems_semaphore_release(grpci2dma_sem);
- return GRPCI2DMA_ERR_ERROR;
- }
- }
-
- /* Release driver semaphore */
- rtems_semaphore_release(grpci2dma_sem);
-
- /* Return channel id */
- return ret;
-}
-
-int grpci2dma_close(int chan_no)
-{
- struct grpci2dma_priv *priv = grpci2dmapriv;
- int ret;
-
- if (!priv){
- /* DMA not initialized */
- return GRPCI2DMA_ERR_NOINIT;
- }
-
- /* Get chan pointer */
- if ((chan_no < 0) || (chan_no >= MAX_DMA_CHANS)){
- /* Wrong channel id */
- return GRPCI2DMA_ERR_WRONGPTR;
- }
-
- /* Check chan is open */
- if (priv->channel[chan_no].ptr == NULL){
- /* No channel */
- return GRPCI2DMA_ERR_NOTFOUND;
- }
-
- /* Take driver lock - Wait until we get semaphore */
- if (rtems_semaphore_obtain(grpci2dma_sem, RTEMS_WAIT, RTEMS_NO_TIMEOUT)
- != RTEMS_SUCCESSFUL){
- return GRPCI2DMA_ERR_ERROR;
- }
-
- /* Take channel lock - Wait until we get semaphore */
- if (rtems_semaphore_obtain(priv->channel[chan_no].sem, RTEMS_WAIT, RTEMS_NO_TIMEOUT)
- != RTEMS_SUCCESSFUL){
- rtems_semaphore_release(grpci2dma_sem);
- return GRPCI2DMA_ERR_ERROR;
- }
-
- /* Close channel */
- ret = grpci2dma_channel_close(chan_no);
-
- /* Release channel sempahore */
- rtems_semaphore_release(priv->channel[chan_no].sem);
-
- /* Delete channel semaphore */
- if (ret == GRPCI2DMA_ERR_OK){
- if (rtems_semaphore_delete(priv->channel[chan_no].sem)
- != RTEMS_SUCCESSFUL){
- /* Release driver semaphore */
- rtems_semaphore_release(grpci2dma_sem);
- return GRPCI2DMA_ERR_ERROR;
- }
- }
-
- /* Release driver semaphore */
- rtems_semaphore_release(grpci2dma_sem);
-
- return ret;
-}
-
-/* Transfer_size =0 means maximum */
-int grpci2dma_prepare(
- uint32_t pci_start, uint32_t ahb_start, int dir, int endianness,
- int size, void * dataptr, int index, int ndata, int transfer_size)
-{
- struct grpci2_bd_data * data = dataptr;
-
- /* Check data pointer */
- if ((data == NULL) ||
- (((unsigned int ) data) & (GRPCI2DMA_BD_DATA_ALIGN-1))){
- return GRPCI2DMA_ERR_WRONGPTR;
- }
-
- /* Check indexes */
- int maxdata = ndata - index;
- if ((maxdata < 1) || (index < 0)){
- /* No data descriptors to use */
- return GRPCI2DMA_ERR_WRONGPTR;
- }
-
- /* Check PCI transfer size */
- if ( (transfer_size < 0) ||
- (transfer_size > MAX_DMA_TRANSFER_SIZE) ||
- (transfer_size%4 != 0) ) {
- return GRPCI2DMA_ERR_WRONGPTR;
- }
- if (transfer_size == 0){
- transfer_size = MAX_DMA_TRANSFER_SIZE;
- }
-
- /* Check total size */
- if ( (size <=0) || (size % 4 != 0)){
- return GRPCI2DMA_ERR_WRONGPTR;
- }
-
- /* Calculate number of data descriptors needed */
- int words = size/4;
- int blocksize = transfer_size/4;
- int datacnt = words/blocksize + (words%blocksize != 0? 1: 0);
- /* Check that we can transfer the data */
- if (datacnt > maxdata) {
- return GRPCI2DMA_ERR_TOOMANY;
- }
-
- /* Prepare data descriptors */
- int i;
- uint32_t pci_adr;
- uint32_t ahb_adr;
- int remaining=words;
- int datasize;
- struct grpci2_bd_data * next;
- for (i=0; i<datacnt; i++){
- /* Get PCI and AHB start addresses */
- pci_adr = pci_start + i*blocksize;
- ahb_adr = ahb_start + i*blocksize;
- /* Get current data size */
- if (remaining >= blocksize){
- datasize = blocksize - 1;
- remaining -= blocksize;
- } else {
- datasize = remaining -1;
- remaining = 0;
- }
- /* Get linked list pointers */
- if (i == datacnt - 1){
- /* Last transfer */
- next = DISABLED_DESCRIPTOR;
- }else{
- next = &data[i+index+1];
- }
- /* Set Data descriptor */
- grpci2dma_data_bd_init(&data[i+index], pci_adr, ahb_adr, dir, endianness, datasize, next);
- }
- /* Return number of transfers used */
- return datacnt;
-}
-
-int grpci2dma_status(void *dataptr, int index, int ndata)
-{
- struct grpci2_bd_data * data = dataptr;
- int i;
-
- /* Check data pointer */
- if ((data == NULL) ||
- (((unsigned int ) data) & (GRPCI2DMA_BD_DATA_ALIGN-1))){
- return GRPCI2DMA_ERR_WRONGPTR;
- }
-
- /* Check maxdata */
- int maxdata = ndata - index;
- if ((maxdata < 1) || (index < 0)){
- /* No data descriptors to use */
- return GRPCI2DMA_ERR_WRONGPTR;
- }
-
- /* Check status of all packets in transfer */
- int status;
- for (i=0; i< maxdata; i++){
- status = grpci2dma_data_bd_status(&data[i+index]);
- if (status == GRPCI2DMA_BD_STATUS_ERR){
- /* Error in one packet, means error in transfer */
- return status;
- } else if (status == GRPCI2DMA_BD_STATUS_ENABLED){
- /* If one packet is enabled, means transfer is not done */
- return status;
- }
- }
-
- /* If we reach here it means they are all disabled */
- return status;
-}
-
-int grpci2dma_print(int chan_no)
-{
- struct grpci2dma_priv *priv = grpci2dmapriv;
- struct grpci2_bd_chan * chan;
-
- if (!priv){
- /* DMA not initialized */
- DBG("DMA not initialized.\n");
- return GRPCI2DMA_ERR_NOINIT;
- }
-
- if ( (chan_no < 0) || (chan_no >= MAX_DMA_CHANS )){
- /* Wrong chan no*/
- return GRPCI2DMA_ERR_WRONGPTR;
- }
-
- chan = priv->channel[chan_no].ptr;
- if (chan == NULL) {
- return GRPCI2DMA_ERR_WRONGPTR;
- }
-
- #ifdef DEBUG
- /* Print channel state */
- grpci2dma_channel_print(chan);
-
- /* Get current DATA desc */
- struct grpci2_bd_data * first_data = (struct grpci2_bd_data *) BD_READ(&chan->nbd);
-
- /* Print data state */
- grpci2dma_data_list_foreach(first_data, grpci2dma_data_print, MAX_DMA_DATA);
- #endif
- return GRPCI2DMA_ERR_OK;
-}
-
-int grpci2dma_print_bd(void * dataptr)
-{
- struct grpci2dma_priv *priv = grpci2dmapriv;
- struct grpci2_bd_data * data = (struct grpci2_bd_data *) dataptr;
-
- if (!priv){
- /* DMA not initialized */
- DBG("DMA not initialized.\n");
- return GRPCI2DMA_ERR_NOINIT;
- }
-
- if ( data == NULL ){
- /* Wrong chan no*/
- return GRPCI2DMA_ERR_WRONGPTR;
- }
-
- #ifdef DEBUG
- /* Print data state */
- grpci2dma_data_list_foreach(data, grpci2dma_data_print, MAX_DMA_DATA);
- #endif
- return GRPCI2DMA_ERR_OK;
-}
-
-int grpci2dma_interrupt_enable(
- void *dataptr, int index, int maxindex, int options)
-{
- struct grpci2_bd_data * data = dataptr;
- struct grpci2dma_priv *priv = grpci2dmapriv;
- SPIN_IRQFLAGS(irqflags);
-
- if (!priv){
- /* DMA not initialized */
- return GRPCI2DMA_ERR_NOINIT;
- }
-
- /* Check data pointer */
- if ((data == NULL) ||
- (((unsigned int ) data) & (GRPCI2DMA_BD_DATA_ALIGN-1))){
- return GRPCI2DMA_ERR_WRONGPTR;
- }
-
- /* Check index */
- if ((index < 0) || (maxindex < 1) || (index >= maxindex)){
- /* No data descriptors to use */
- return GRPCI2DMA_ERR_WRONGPTR;
- }
-
- if (options & GRPCI2DMA_OPTIONS_ALL){
- /* Enable all interrupts */
- if (grpci2dma_data_list_foreach(
- &data[index],
- grpci2dma_data_bd_interrupt_enable, maxindex -index)){
- return GRPCI2DMA_ERR_ERROR;
- }
- }else{
- /* Enable one packet interrupts */
- grpci2dma_data_bd_interrupt_enable(&data[index]);
- }
-
- /* Finally enable DMA interrupts if they are not already enabled */
- if (grpci2dma_ctrl_interrupt_status()==0){
- SPIN_LOCK_IRQ(&priv->devlock, irqflags);
- grpci2dma_ctrl_interrupt_enable();
- SPIN_UNLOCK_IRQ(&priv->devlock, irqflags);
- }
-
- DBG("Interrupts enabled for data (0x%08x), index:%d, maxindex:%d, %s.\n",
- (unsigned int) data, index, maxindex,
- (options & GRPCI2DMA_OPTIONS_ALL)? "ALL":"ONE" );
-
- return GRPCI2DMA_ERR_OK;
-}
-
-int grpci2dma_push(int chan_no, void *dataptr, int index, int ndata)
-{
- struct grpci2dma_priv *priv = grpci2dmapriv;
- SPIN_IRQFLAGS(irqflags);
- int ret;
-
- if (!priv){
- /* DMA not initialized */
- return GRPCI2DMA_ERR_NOINIT;
- }
-
- /* Check data pointer */
- if ((dataptr == NULL) ||
- (((unsigned int ) dataptr) & (GRPCI2DMA_BD_DATA_ALIGN-1))){
- return GRPCI2DMA_ERR_WRONGPTR;
- }
-
- /* Check index */
- if ((ndata < 1) || (index < 0)){
- /* No data descriptors to use */
- return GRPCI2DMA_ERR_WRONGPTR;
- }
-
- /* Check chan_no */
- if ( (chan_no < 0) || (chan_no >= MAX_DMA_CHANS )){
- /* Wrong chan no*/
- return GRPCI2DMA_ERR_WRONGPTR;
- }
-
- /* Check chan is open */
- if (priv->channel[chan_no].ptr == NULL){
- /* No channel */
- return GRPCI2DMA_ERR_NOTFOUND;
- }
-
- /* Take channel lock - Wait until we get semaphore */
- if (rtems_semaphore_obtain(priv->channel[chan_no].sem, RTEMS_WAIT, RTEMS_NO_TIMEOUT)
- != RTEMS_SUCCESSFUL){
- return GRPCI2DMA_ERR_ERROR;
- }
-
- /* push data to channel */
- ret = grpci2dma_channel_push(chan_no, dataptr, index, ndata);
-
- if (ret != GRPCI2DMA_ERR_OK){
- /* Release channel lock */
- rtems_semaphore_release(priv->channel[chan_no].sem);
- return ret;
- }
-
- /* Start DMA if it is not active and channel is active*/
- SPIN_LOCK_IRQ(&priv->devlock, irqflags);
- if ((!grpci2dma_active()) && (priv->channel[chan_no].active)){
- grpci2dma_ctrl_start(priv->channel[chan_no].ptr);
- }
- SPIN_UNLOCK_IRQ(&priv->devlock, irqflags);
-
- /* Release channel lock */
- rtems_semaphore_release(priv->channel[chan_no].sem);
-
- return ret;
-}
-
-/* Start the channel */
-int grpci2dma_start(int chan_no, int options)
-{
- struct grpci2dma_priv *priv = grpci2dmapriv;
- int ret;
-
- if (!priv){
- /* DMA not initialized */
- return GRPCI2DMA_ERR_NOINIT;
- }
-
- if ((chan_no < 0 ) || (chan_no >= MAX_DMA_CHANS )) {
- /* Wrong channel id */
- return GRPCI2DMA_ERR_WRONGPTR;
- }
-
- if ( options < 0 ) {
- /* Wrong options */
- return GRPCI2DMA_ERR_WRONGPTR;
- }
-
- /* Check chan is open */
- if (priv->channel[chan_no].ptr == NULL){
- /* No channel */
- return GRPCI2DMA_ERR_NOTFOUND;
- }
-
- /* Take driver lock - Wait until we get semaphore */
- if (rtems_semaphore_obtain(grpci2dma_sem, RTEMS_WAIT, RTEMS_NO_TIMEOUT)
- != RTEMS_SUCCESSFUL){
- return GRPCI2DMA_ERR_ERROR;
- }
-
- /* Take channel lock - Wait until we get semaphore */
- if (rtems_semaphore_obtain(priv->channel[chan_no].sem, RTEMS_WAIT, RTEMS_NO_TIMEOUT)
- != RTEMS_SUCCESSFUL){
- rtems_semaphore_release(grpci2dma_sem);
- return GRPCI2DMA_ERR_ERROR;
- }
-
- /* Start the channel */
- ret = grpci2dma_channel_start(chan_no, options);
-
- /* Release channel lock */
- rtems_semaphore_release(priv->channel[chan_no].sem);
-
- /* Release driver lock */
- rtems_semaphore_release(grpci2dma_sem);
-
- return ret;
-}
-
-/* Stop the channel, but don't stop ongoing transfers! */
-int grpci2dma_stop(int chan_no)
-{
- struct grpci2dma_priv *priv = grpci2dmapriv;
- int ret;
-
- if (!priv){
- /* DMA not initialized */
- return GRPCI2DMA_ERR_NOINIT;
- }
-
- if ((chan_no < 0 ) || (chan_no >= MAX_DMA_CHANS)) {
- /* Wrong channel id */
- return GRPCI2DMA_ERR_WRONGPTR;
- }
-
- /* Check chan is open */
- if (priv->channel[chan_no].ptr == NULL){
- /* No channel */
- return GRPCI2DMA_ERR_NOTFOUND;
- }
-
- /* Take driver lock - Wait until we get semaphore */
- if (rtems_semaphore_obtain(grpci2dma_sem, RTEMS_WAIT, RTEMS_NO_TIMEOUT)
- != RTEMS_SUCCESSFUL){
- return GRPCI2DMA_ERR_ERROR;
- }
-
- /* Take channel lock - Wait until we get semaphore */
- if (rtems_semaphore_obtain(priv->channel[chan_no].sem, RTEMS_WAIT, RTEMS_NO_TIMEOUT)
- != RTEMS_SUCCESSFUL){
- rtems_semaphore_release(grpci2dma_sem);
- return GRPCI2DMA_ERR_ERROR;
- }
-
- /* Stop the channel */
- ret = grpci2dma_channel_stop(chan_no);
-
- /* Release channel lock */
- rtems_semaphore_release(priv->channel[chan_no].sem);
-
- /* Release driver lock */
- rtems_semaphore_release(grpci2dma_sem);
-
- return ret;
-}
-
-int grpci2dma_active()
-{
- return ((grpci2dma_ctrl_status()) & DMACTRL_ACT) >> DMACTRL_ACT_BIT;
-}
-