summaryrefslogtreecommitdiffstats
path: root/c/src/lib/libbsp/sparc/shared/1553/gr1553rt.c
diff options
context:
space:
mode:
Diffstat (limited to 'c/src/lib/libbsp/sparc/shared/1553/gr1553rt.c')
-rw-r--r--c/src/lib/libbsp/sparc/shared/1553/gr1553rt.c1218
1 files changed, 0 insertions, 1218 deletions
diff --git a/c/src/lib/libbsp/sparc/shared/1553/gr1553rt.c b/c/src/lib/libbsp/sparc/shared/1553/gr1553rt.c
deleted file mode 100644
index 932e8494f1..0000000000
--- a/c/src/lib/libbsp/sparc/shared/1553/gr1553rt.c
+++ /dev/null
@@ -1,1218 +0,0 @@
-/* GR1553B RT driver
- *
- * COPYRIGHT (c) 2010.
- * 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 <rtems.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-
-#include <bsp/gr1553b.h>
-#include <bsp/gr1553rt.h>
-
-#include <drvmgr/drvmgr.h>
-#include <drvmgr/ambapp_bus.h>
-
-#define GR1553RT_WRITE_MEM(adr, val) *(volatile uint32_t *)(adr) = (uint32_t)(val)
-#define GR1553RT_READ_MEM(adr) (*(volatile uint32_t *)(adr))
-
-#define GR1553RT_WRITE_REG(adr, val) *(volatile uint32_t *)(adr) = (uint32_t)(val)
-#define GR1553RT_READ_REG(adr) (*(volatile uint32_t *)(adr))
-
-/* 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)
-#define SPIN_FREE(lock) rtems_interrupt_lock_destroy(lock)
-
-/* Software representation of one hardware descriptor */
-struct gr1553rt_sw_bd {
- unsigned short this_next;/* Next entry or this entry. 0xffff: no next */
- unsigned char listid; /* ListID of List the descriptor is attached */
- char unused;
-} __attribute__((packed));
-
-/* Software description of a subaddress */
-struct gr1553rt_subadr {
- /* RX LIST */
- unsigned char rxlistid;
- /* TX LIST */
- unsigned char txlistid;
-};
-
-struct gr1553rt_irqerr {
- gr1553rt_irqerr_t func;
- void *data;
-};
-
-struct gr1553rt_irqmc {
- gr1553rt_irqmc_t func;
- void *data;
-};
-
-struct gr1553rt_irq {
- gr1553rt_irq_t func;
- void *data;
-};
-
-struct gr1553rt_priv {
- /* Pointer to Hardware registers */
- struct gr1553b_regs *regs;
-
- /* Software State */
- int started;
- struct gr1553rt_cfg cfg;
- SPIN_DECLARE(devlock);
-
- /* Handle to GR1553B RT device layer */
- struct drvmgr_dev **pdev;
-
- /* Each Index represents one RT Subaddress. 31 = Broadcast */
- struct gr1553rt_subadr subadrs[32];
-
- /* Pointer to array of Software's description of a hardware
- * descriptor.
- */
-#if (RTBD_MAX == 0)
- struct gr1553rt_sw_bd *swbds;
-#else
- struct gr1553rt_sw_bd swbds[RTBD_MAX];
-#endif
-
- /* List of Free descriptors */
- unsigned short swbd_free;
- int swbd_free_cnt;
-
- /* Hardware SubAddress descriptors given for CPU and Hardware */
- void *satab_buffer;
- struct gr1553rt_sa *sas_cpu; /* Translated for CPU */
- struct gr1553rt_sa *sas_hw; /* Translated for Hardware */
-
- /* Hardware descriptors address given for CPU and hardware */
- void *bd_buffer;
- int bds_cnt; /* Number of descriptors */
- struct gr1553rt_bd *bds_cpu; /* Translated for CPU */
- struct gr1553rt_bd *bds_hw; /* Translated for Hardware */
-
-
- /* Event Log buffer in */
- void *evlog_buffer;
- unsigned int *evlog_cpu_next; /* Next LOG entry to be handled */
- unsigned int *evlog_cpu_base; /* First Entry in LOG */
- unsigned int *evlog_cpu_end; /* Last+1 Entry in LOG */
- unsigned int *evlog_hw_base; /* Translated for Hardware */
-
- /* Each Index represents a LIST ID */
- struct gr1553rt_list *lists[RTLISTID_MAX];
-
- /* IRQ handlers, one per SUBADDRESS */
- struct gr1553rt_irq irq_rx[32];
- struct gr1553rt_irq irq_tx[32];
-
- /* ISR called when an ERROR IRQ is received */
- struct gr1553rt_irqerr irq_err;
-
- /* ISR called when an Mode Code is received */
- struct gr1553rt_irqmc irq_mc;
-};
-
-void gr1553rt_sw_init(struct gr1553rt_priv *priv);
-void gr1553rt_sw_free(struct gr1553rt_priv *priv);
-void gr1553rt_isr(void *data);
-
-/* Assign and ID to the list. An LIST ID is needed before scheduling list
- * on an RT subaddress.
- *
- * Only 64 lists can be registered at a time on the same device.
- */
-static int gr1553rt_list_reg(struct gr1553rt_list *list)
-{
- struct gr1553rt_priv *priv = list->rt;
- int i;
-
- /* Find first free list ID */
- for ( i=0; i<RTLISTID_MAX; i++) {
- if ( priv->lists[i] == NULL ) {
- priv->lists[i] = list;
- list->listid = i;
- return i;
- }
- }
-
- /* No available LIST IDs */
- list->listid = -1;
-
- return -1;
-}
-
-#if 0 /* unused for now */
-/* Unregister List from device */
-static void gr1553rt_list_unreg(struct gr1553rt_list *list)
-{
- struct gr1553rt_priv *priv = list->rt;
-
- priv->lists[list->listid] = NULL;
- list->listid = -1;
-}
-#endif
-
-static int gr1553rt_bdid(void *rt, struct gr1553rt_sw_bd *bd)
-{
- struct gr1553rt_priv *priv = rt;
-
- unsigned short index;
-
- /* Get Index of Software BD */
- index = ((unsigned int)bd - (unsigned int)&priv->swbds[0]) /
- sizeof(struct gr1553rt_sw_bd);
-
- return index;
-}
-
-static void gr1553rt_bd_alloc_init(void *rt, int count)
-{
- struct gr1553rt_priv *priv = rt;
- int i;
-
- for (i=0; i<count-1; i++) {
- priv->swbds[i].this_next = i+1;
- }
- priv->swbds[count-1].this_next = 0xffff;
- priv->swbd_free = 0;
- priv->swbd_free_cnt = count;
-}
-
-/* Allocate a Chain of descriptors */
-static int gr1553rt_bd_alloc(void *rt, struct gr1553rt_sw_bd **bd, int cnt)
-{
- struct gr1553rt_priv *priv = rt;
- struct gr1553rt_sw_bd *curr;
- int i;
-
- if ((priv->swbd_free_cnt < cnt) || (cnt <= 0)) {
- *bd = NULL;
- return -1;
- }
-
- *bd = &priv->swbds[priv->swbd_free];
- for (i=0; i<cnt; i++) {
- if ( i == 0) {
- curr = &priv->swbds[priv->swbd_free];
- } else {
- curr = &priv->swbds[curr->this_next];
- }
- if ( curr->this_next == 0xffff ) {
- *bd = NULL;
- return -1;
- }
- }
- priv->swbd_free = curr->this_next;
- priv->swbd_free_cnt -= cnt;
- curr->this_next = 0xffff; /* Mark end of chain on last entry */
-
- return 0;
-}
-
-#if 0 /* unused for now */
-static void gr1553rt_bd_free(void *rt, struct gr1553rt_sw_bd *bd)
-{
- struct gr1553rt_priv *priv = rt;
- unsigned short index;
-
- /* Get Index of Software BD */
- index = gr1553rt_bdid(priv, bd);
-
- /* Insert first in list */
- bd->this_next = priv->swbd_free;
- priv->swbd_free = index;
- priv->swbd_free_cnt++;
-}
-#endif
-
-int gr1553rt_list_init
- (
- void *rt,
- struct gr1553rt_list **plist,
- struct gr1553rt_list_cfg *cfg
- )
-{
- struct gr1553rt_priv *priv = rt;
- int i, size;
- struct gr1553rt_sw_bd *swbd;
- unsigned short index;
- struct gr1553rt_list *list;
-
- /* The user may provide a pre allocated LIST, or
- * let the driver handle allocation by using malloc()
- *
- * If the IN/OUT plist argument points to NULL a list
- * dynamically allocated here.
- */
- list = *plist;
- if ( list == NULL ) {
- /* Dynamically allocate LIST */
- size = offsetof(struct gr1553rt_list, bds) +
- (cfg->bd_cnt * sizeof(unsigned short));
- list = (struct gr1553rt_list *)malloc(size);
- if ( list == NULL )
- return -1;
- *plist = list;
- }
-
- list->rt = rt;
- list->subadr = -1;
- list->listid = gr1553rt_list_reg(list);
- if ( list->listid == -1 )
- return -2; /* Too many lists */
- list->cfg = cfg;
- list->bd_cnt = cfg->bd_cnt;
-
- /* Allocate all BDs needed by list */
- if ( gr1553rt_bd_alloc(rt, &swbd, list->bd_cnt) ) {
- return -3; /* Too few descriptors */
- }
-
- /* Get ID/INDEX of Software BDs */
- index = gr1553rt_bdid(rt, swbd);
- list->bds[0] = index;
- for (i=1; i<list->bd_cnt; i++) {
- list->bds[i] = priv->swbds[list->bds[i-1]].this_next;
- }
-
- /* Now that the next pointer has fullfilled it's job and not
- * needed anymore, we use it as list entry pointer instead.
- * The this_next pointer is a list entry number.
- */
- for (i=0; i<list->bd_cnt; i++) {
- priv->swbds[list->bds[i]].this_next = i;
- }
-
- return 0;
-}
-
-int gr1553rt_bd_init(
- struct gr1553rt_list *list,
- unsigned short entry_no,
- unsigned int flags,
- uint16_t *dptr,
- unsigned short next
- )
-{
- struct gr1553rt_priv *priv;
- unsigned short bdid;
- struct gr1553rt_bd *bd;
- unsigned int nextbd, dataptr;
- SPIN_IRQFLAGS(irqflags);
-
- if ( entry_no >= list->bd_cnt )
- return -1;
-
- /* Find Descriptor */
- bdid = list->bds[entry_no];
- priv = list->rt;
- bd = &priv->bds_cpu[bdid];
-
- if ( next == 0xfffe ) {
- next = entry_no + 1;
- if ( next >= list->bd_cnt )
- next = 0;
- }
-
- /* Find next descriptor in address space that the
- * Hardware understand.
- */
- if ( next >= 0xffff ) {
- nextbd = 0x3; /* End of list */
- } else if ( next >= list->bd_cnt ) {
- return -1;
- } else {
- bdid = list->bds[next];
- nextbd = (unsigned int)&priv->bds_hw[bdid];
- }
-
- dataptr = (unsigned int)dptr;
- if ( dataptr & 1 ) {
- /* Translate address from CPU-local into remote */
- dataptr &= ~1;
- drvmgr_translate(
- *priv->pdev,
- CPUMEM_TO_DMA,
- (void *)dataptr,
- (void **)&dataptr
- );
- }
-
- /* Init BD */
- SPIN_LOCK_IRQ(&priv->devlock, irqflags);
- bd->ctrl = flags & GR1553RT_BD_FLAGS_IRQEN;
- bd->dptr = (unsigned int)dptr;
- bd->next = nextbd;
- SPIN_UNLOCK_IRQ(&priv->devlock, irqflags);
-
- return 0;
-}
-
-int gr1553rt_bd_update(
- struct gr1553rt_list *list,
- int entry_no,
- unsigned int *status,
- uint16_t **dptr
- )
-{
- struct gr1553rt_priv *priv;
- unsigned short bdid;
- struct gr1553rt_bd *bd;
- unsigned int tmp, dataptr;
- SPIN_IRQFLAGS(irqflags);
-
- if ( entry_no >= list->bd_cnt )
- return -1;
-
- /* Find Descriptor */
- bdid = list->bds[entry_no];
- priv = list->rt;
- bd = &priv->bds_cpu[bdid];
-
- /* Prepare translation if needed */
- if ( dptr && (dataptr=(unsigned int)*dptr) ) {
- if ( dataptr & 1 ) {
- /* Translate address from CPU-local into remote. May
- * be used when RT core is accessed over the PCI bus.
- */
- dataptr &= ~1;
- drvmgr_translate(
- *priv->pdev,
- CPUMEM_TO_DMA,
- (void *)dataptr,
- (void **)&dataptr
- );
- }
- }
-
- /* Get current values and then set new values in BD */
- SPIN_LOCK_IRQ(&priv->devlock, irqflags);
- /* READ/WRITE Status/Control word */
- if ( status ) {
- tmp = bd->ctrl;
- if ( *status ) {
- bd->ctrl = *status;
- }
- *status = tmp;
- }
- /* READ/WRITE Data-Pointer word */
- if ( dptr ) {
- tmp = bd->dptr;
- if ( dataptr ) {
- bd->dptr = dataptr;
- }
- *dptr = (uint16_t *)tmp;
- }
- SPIN_LOCK_IRQ(&priv->devlock, irqflags);
-
- return 0;
-}
-
-int gr1553rt_irq_err
- (
- void *rt,
- gr1553rt_irqerr_t func,
- void *data
- )
-{
- struct gr1553rt_priv *priv = rt;
- SPIN_IRQFLAGS(irqflags);
-
- SPIN_LOCK_IRQ(&priv->devlock, irqflags);
- priv->irq_err.func = func;
- priv->irq_err.data = data;
- SPIN_UNLOCK_IRQ(&priv->devlock, irqflags);
-
- return 0;
-}
-
-int gr1553rt_irq_mc
- (
- void *rt,
- gr1553rt_irqmc_t func,
- void *data
- )
-{
- struct gr1553rt_priv *priv = rt;
- SPIN_IRQFLAGS(irqflags);
-
- SPIN_LOCK_IRQ(&priv->devlock, irqflags);
- priv->irq_mc.func = func;
- priv->irq_mc.data = data;
- SPIN_UNLOCK_IRQ(&priv->devlock, irqflags);
-
- return 0;
-}
-
-int gr1553rt_irq_sa
- (
- void *rt,
- int subadr,
- int tx,
- gr1553rt_irq_t func,
- void *data
- )
-{
- struct gr1553rt_priv *priv = rt;
- SPIN_IRQFLAGS(irqflags);
-
- SPIN_LOCK_IRQ(&priv->devlock, irqflags);
- if ( tx ) {
- priv->irq_tx[subadr].func = func;
- priv->irq_tx[subadr].data = data;
- } else {
- priv->irq_rx[subadr].func = func;
- priv->irq_rx[subadr].data = data;
- }
- SPIN_UNLOCK_IRQ(&priv->devlock, irqflags);
-
- return 0;
-}
-
-/* GR1553-RT Interrupt Service Routine */
-void gr1553rt_isr(void *data)
-{
- struct gr1553rt_priv *priv = data;
- unsigned int firstirq, lastpos;
- int index;
- unsigned int *last, *curr, entry, hwbd;
- int type, samc, mcode, subadr;
- int listid;
- struct gr1553rt_irq *pisr, isr;
- struct gr1553rt_irqerr isrerr;
- struct gr1553rt_irqmc isrmc;
- unsigned int irq;
- SPIN_ISR_IRQFLAGS(irqflags);
-
- /* Ack IRQ before reading current write pointer, but after
- * reading current IRQ pointer. This is because RT_EVIRQ
- * may be updated after we ACK the IRQ source.
- */
- irq = priv->regs->irq &
- (GR1553B_IRQ_RTTE|GR1553B_IRQ_RTD|GR1553B_IRQ_RTEV);
- if ( irq == 0 )
- return;
-
- firstirq = priv->regs->rt_evirq;
- priv->regs->irq = irq;
- lastpos = priv->regs->rt_evlog;
-
- /* Quit if nothing has been added to the log */
- if ( lastpos == firstirq )
- return;
-
- if ( irq & (GR1553B_IRQ_RTTE|GR1553B_IRQ_RTD) ) {
- /* copy func and arg while owning lock */
- SPIN_LOCK(&priv->devlock, irqflags);
- isrerr = priv->irq_err;
- SPIN_UNLOCK(&priv->devlock, irqflags);
- if ( isrerr.func ) {
- isrerr.func(irq, isrerr.data);
- }
-
- /* Stop Hardware and enter non-started mode. This will
- * make all future calls to driver result in an error.
- */
- gr1553rt_stop(priv);
- }
-
- /* Step between first log entry causing an IRQ to last
- * entry. Each entry that has caused an IRQ will be handled
- * by calling user-defined function.
- *
- * We convert hardware addresses into CPU accessable addresses
- * first.
- */
- index = (firstirq - (unsigned int)priv->evlog_hw_base) /
- sizeof(unsigned int);
- curr = priv->evlog_cpu_base + index;
- index = (lastpos - (unsigned int)priv->evlog_hw_base) /
- sizeof(unsigned int);
- last = priv->evlog_cpu_base + index;
-
- do {
- /* Process one entry */
- entry = *curr;
-
- if ( entry & 0x80000000 ) {
- /* Entry caused IRQ */
- type = (entry >> 29) & 0x3;
- samc = (entry >> 24) & 0x1f;
- if ( (type & 0x2) == 0 ) {
- /* Transmit/Receive Data */
- subadr = samc;
- if ( type ) {
- /* Receive */
- listid = priv->subadrs[subadr].rxlistid;
- hwbd = priv->sas_cpu[subadr].rxptr;
- pisr = &priv->irq_rx[subadr];
- } else {
- /* Transmit */
- listid = priv->subadrs[subadr].txlistid;
- hwbd = priv->sas_cpu[subadr].txptr;
- pisr = &priv->irq_tx[subadr];
- }
-
- index = ((unsigned int)hwbd - (unsigned int)
- priv->bds_hw)/sizeof(struct gr1553rt_bd);
-
- /* copy func and arg while owning lock */
- SPIN_LOCK(&priv->devlock, irqflags);
- isr = *pisr;
- SPIN_UNLOCK(&priv->devlock, irqflags);
-
- /* Call user ISR of RX/TX transfer */
- if ( isr.func ) {
- isr.func(
- priv->lists[listid],
- entry,
- priv->swbds[index].this_next,
- isr.data
- );
- }
- } else if ( type == 0x2) {
- /* Modecode */
- mcode = samc;
-
- /* copy func and arg while owning lock */
- SPIN_LOCK(&priv->devlock, irqflags);
- isrmc = priv->irq_mc;
- SPIN_UNLOCK(&priv->devlock, irqflags);
-
- /* Call user ISR of ModeCodes RX/TX */
- if ( isrmc.func ) {
- isrmc.func(
- mcode,
- entry,
- isrmc.data
- );
- }
- } else {
- /* ERROR OF SOME KIND, EVLOG OVERWRITTEN? */
- rtems_fatal_error_occurred(RTEMS_IO_ERROR);
- }
- }
-
- /* Calc next entry posistion */
- curr++;
- if ( curr == priv->evlog_cpu_end )
- curr = priv->evlog_cpu_base;
-
- } while ( curr != last );
-}
-
-int gr1553rt_indication(void *rt, int subadr, int *txeno, int *rxeno)
-{
- struct gr1553rt_priv *priv = rt;
- struct gr1553rt_sa *sa;
- unsigned int bd, index;
-
- /* Sub address valid */
- if ( (subadr < 0) || (subadr > 31) )
- return -1;
-
- /* Get SubAddress Descriptor address as accessed from CPU */
- sa = &priv->sas_cpu[subadr];
-
- /* Indication of TX descriptor? */
- if ( txeno ) {
- bd = sa->txptr;
- /* Get Index of Hardware BD */
- index = ((unsigned int)bd - (unsigned int)&priv->bds_hw[0]) /
- sizeof(struct gr1553rt_bd);
- *txeno = priv->swbds[index].this_next;
- }
-
- /* Indication of RX descriptor? */
- if ( rxeno ) {
- bd = sa->rxptr;
- /* Get Index of Hardware BD */
- index = ((unsigned int)bd - (unsigned int)&priv->bds_hw[0]) /
- sizeof(struct gr1553rt_bd);
- *rxeno = priv->swbds[index].this_next;
- }
-
- return 0;
-}
-
-void gr1553rt_hw_stop(struct gr1553rt_priv *priv);
-
-void gr1553rt_register(void)
-{
- /* The RT driver rely on the GR1553B Driver */
- gr1553_register();
-}
-
-void *gr1553rt_open(int minor)
-{
- struct drvmgr_dev **pdev = NULL;
- struct gr1553rt_priv *priv = NULL;
- struct amba_dev_info *ambadev;
- struct ambapp_core *pnpinfo;
-
- /* Allocate requested device */
- pdev = gr1553_rt_open(minor);
- if ( pdev == NULL )
- goto fail;
-
- priv = malloc(sizeof(struct gr1553rt_priv));
- if ( priv == NULL )
- goto fail;
- memset(priv, 0, sizeof(struct gr1553rt_priv));
-
- /* Assign a device private to RT device */
- priv->pdev = pdev;
- (*pdev)->priv = priv;
-
- /* Get device information from AMBA PnP information */
- ambadev = (struct amba_dev_info *)(*pdev)->businfo;
- pnpinfo = &ambadev->info;
- priv->regs = (struct gr1553b_regs *)pnpinfo->apb_slv->start;
-
- SPIN_INIT(&priv->devlock, "gr1553rt");
-
- /* Start with default configuration */
- /*priv->cfg = gr1553rt_default_config;*/
-
- /* Unmask IRQs and so */
- gr1553rt_hw_stop(priv);
-
- /* Register ISR handler. hardware mask IRQ, so it is safe to unmask
- * at IRQ controller.
- */
- if (drvmgr_interrupt_register(*priv->pdev, 0, "gr1553rt", gr1553rt_isr, priv))
- goto fail;
-
- return priv;
-
-fail:
- if ( pdev )
- gr1553_rt_close(pdev);
- if ( priv )
- free(priv);
- return NULL;
-}
-
-void gr1553rt_close(void *rt)
-{
- struct gr1553rt_priv *priv = rt;
-
- if ( priv->started ) {
- gr1553rt_stop(priv);
- }
-
- /* Remove ISR handler */
- drvmgr_interrupt_unregister(*priv->pdev, 0, gr1553rt_isr, priv);
-
- /* Free dynamically allocated buffers if any */
- gr1553rt_sw_free(priv);
- SPIN_FREE(&priv->devlock);
-
- /* Return RT/BC device */
- gr1553_rt_close(priv->pdev);
-}
-
-/* Stop Hardware and disable IRQ */
-void gr1553rt_hw_stop(struct gr1553rt_priv *priv)
-{
- uint32_t irqmask;
-
- /* Disable RT */
- GR1553RT_WRITE_REG(&priv->regs->rt_cfg, GR1553RT_KEY);
-
- /* Stop BC if not already stopped: BC can not be used simultaneously
- * as the RT anyway
- */
- GR1553RT_WRITE_REG(&priv->regs->bc_ctrl, GR1553BC_KEY | 0x0204);
-
- /* Turn off RT IRQ generation */
- irqmask=GR1553RT_READ_REG(&priv->regs->imask);
- irqmask&=~(GR1553B_IRQEN_RTEVE|GR1553B_IRQEN_RTDE);
- GR1553RT_WRITE_REG(&priv->regs->irq, irqmask);
-}
-
-/* Free dynamically allocated buffers, if any */
-void gr1553rt_sw_free(struct gr1553rt_priv *priv)
-{
- /* Event log */
- if ( (priv->cfg.evlog_buffer == NULL) && priv->evlog_buffer ) {
- free(priv->evlog_buffer);
- priv->evlog_buffer = NULL;
- }
-
- /* RX/TX Descriptors */
- if ( (priv->cfg.bd_buffer == NULL) && priv->bd_buffer ) {
- free(priv->bd_buffer);
- priv->bd_buffer = NULL;
- }
-
-#if (RTBD_MAX == 0)
- if ( priv->swbds ) {
- free(priv->swbds);
- priv->swbds = NULL;
- }
-#endif
-
- /* Sub address table */
- if ( (priv->cfg.satab_buffer == NULL) && priv->satab_buffer ) {
- free(priv->satab_buffer);
- priv->satab_buffer = NULL;
- }
-}
-
-/* Free dynamically allocated buffers, if any */
-static int gr1553rt_sw_alloc(struct gr1553rt_priv *priv)
-{
- int size;
-
- /* Allocate Event log */
- if ((unsigned int)priv->cfg.evlog_buffer & 1) {
- /* Translate Address from HARDWARE (REMOTE) to CPU-LOCAL */
- priv->evlog_hw_base = (unsigned int *)
- ((unsigned int)priv->cfg.evlog_buffer & ~0x1);
- priv->evlog_buffer = priv->cfg.evlog_buffer;
- drvmgr_translate_check(
- *priv->pdev,
- DMAMEM_TO_CPU,
- (void *)priv->evlog_hw_base,
- (void **)&priv->evlog_cpu_base,
- priv->cfg.evlog_size
- );
- } else {
- if (priv->cfg.evlog_buffer == NULL) {
- priv->evlog_buffer = malloc(priv->cfg.evlog_size * 2);
- if (priv->evlog_buffer == NULL)
- return -1;
- } else {
- /* Addess already CPU-LOCAL */
- priv->evlog_buffer = priv->cfg.evlog_buffer;
- }
- /* Align to SIZE bytes boundary */
- priv->evlog_cpu_base = (unsigned int *)
- (((unsigned int)priv->evlog_buffer +
- (priv->cfg.evlog_size-1)) & ~(priv->cfg.evlog_size-1));
-
- drvmgr_translate_check(
- *priv->pdev,
- CPUMEM_TO_DMA,
- (void *)priv->evlog_cpu_base,
- (void **)&priv->evlog_hw_base,
- priv->cfg.evlog_size
- );
- }
- priv->evlog_cpu_end = priv->evlog_cpu_base +
- priv->cfg.evlog_size/sizeof(unsigned int *);
-
- /* Allocate Transfer Descriptors */
- priv->bds_cnt = priv->cfg.bd_count;
- size = priv->bds_cnt * sizeof(struct gr1553rt_bd);
- if ((unsigned int)priv->cfg.bd_buffer & 1) {
- /* Translate Address from HARDWARE (REMOTE) to CPU-LOCAL */
- priv->bds_hw = (struct gr1553rt_bd *)
- ((unsigned int)priv->cfg.bd_buffer & ~0x1);
- priv->bd_buffer = priv->cfg.bd_buffer;
- drvmgr_translate_check(
- *priv->pdev,
- DMAMEM_TO_CPU,
- (void *)priv->bds_hw,
- (void **)&priv->bds_cpu,
- size
- );
- } else {
- if ( priv->cfg.bd_buffer == NULL ) {
- priv->bd_buffer = malloc(size + 0xf);
- if (priv->bd_buffer == NULL)
- return -1;
- } else {
- /* Addess already CPU-LOCAL */
- priv->bd_buffer = priv->cfg.bd_buffer;
- }
- /* Align to 16 bytes boundary */
- priv->bds_cpu = (struct gr1553rt_bd *)
- (((unsigned int)priv->bd_buffer + 0xf) & ~0xf);
-
- /* Translate from CPU address to hardware address */
- drvmgr_translate_check(
- *priv->pdev,
- CPUMEM_TO_DMA,
- (void *)priv->bds_cpu,
- (void **)&priv->bds_hw,
- size
- );
- }
-
-#if (RTBD_MAX == 0)
- /* Allocate software description of */
- priv->swbds = malloc(priv->cfg.bd_count * sizeof(struct gr1553rt_sw_bd));
- if ( priv->swbds == NULL ) {
- return -1;
- }
-#endif
-
- /* Allocate Sub address table */
- if ((unsigned int)priv->cfg.satab_buffer & 1) {
- /* Translate Address from HARDWARE (REMOTE) to CPU-LOCAL */
- priv->sas_hw = (struct gr1553rt_sa *)
- ((unsigned int)priv->cfg.satab_buffer & ~0x1);
- priv->satab_buffer = priv->cfg.satab_buffer;
- drvmgr_translate_check(
- *priv->pdev,
- DMAMEM_TO_CPU,
- (void *)priv->sas_hw,
- (void **)&priv->sas_cpu,
- 16 * 32);
- } else {
- if (priv->cfg.satab_buffer == NULL) {
- priv->satab_buffer = malloc((16 * 32) * 2);
- if (priv->satab_buffer == NULL)
- return -1;
- } else {
- /* Addess already CPU-LOCAL */
- priv->satab_buffer = priv->cfg.satab_buffer;
- }
- /* Align to 512 bytes boundary */
- priv->sas_cpu = (struct gr1553rt_sa *)
- (((unsigned int)priv->satab_buffer + 0x1ff) &
- ~0x1ff);
-
- /* Translate Address from CPU-LOCAL to HARDWARE (REMOTE) */
- drvmgr_translate_check(
- *priv->pdev,
- CPUMEM_TO_DMA,
- (void *)priv->sas_cpu,
- (void **)&priv->sas_hw,
- 16 * 32);
- }
-
- return 0;
-}
-
-void gr1553rt_sw_init(struct gr1553rt_priv *priv)
-{
- int i;
-
- /* Clear Sub Address table */
- memset(priv->sas_cpu, 0, 512);
-
- /* Clear Transfer descriptors */
- memset(priv->bds_cpu, 0, priv->bds_cnt * 16);
-
- /* Clear the Event log */
- memset(priv->evlog_cpu_base, 0, priv->cfg.evlog_size);
-
- /* Init descriptor allocation algorithm */
- gr1553rt_bd_alloc_init(priv, priv->bds_cnt);
-
- /* Init table used to convert from sub address to list.
- * Currently non assigned.
- */
- for (i=0; i<32; i++) {
- priv->subadrs[i].rxlistid = 0xff;
- priv->subadrs[i].txlistid = 0xff;
- }
-
- /* Clear all previous IRQ handlers */
- for (i=0; i<32; i++) {
- priv->irq_rx[i].func = NULL;
- priv->irq_tx[i].data = NULL;
- }
- priv->irq_err.func = NULL;
- priv->irq_err.data = NULL;
- priv->irq_mc.func = NULL;
- priv->irq_mc.data = NULL;
-
- /* Clear LIST to LISTID table */
- for (i=0; i<RTLISTID_MAX; i++) {
- priv->lists[i] = NULL;
- }
-}
-
-int gr1553rt_config(void *rt, struct gr1553rt_cfg *cfg)
-{
- struct gr1553rt_priv *priv = rt;
-
- if ( priv->started )
- return -1;
-
- /*** Free dynamically allocated buffers ***/
-
- gr1553rt_sw_free(priv);
-
- /*** Check new config ***/
- if ( cfg->rtaddress > 30 )
- return -1;
- if ( (cfg->evlog_size & (cfg->evlog_size-1)) != 0)
- return -1; /* SIZE: Not aligned to a power of 2 */
- if ( ((unsigned int)priv->cfg.evlog_buffer & (cfg->evlog_size-1)) != 0 )
- return -1; /* Buffer: Not aligned to size */
-#if (RTBD_MAX > 0)
- if ( cfg->bd_count > RTBD_MAX )
- return -1;
-#endif
-
- /*** Make new config current ***/
- priv->cfg = *cfg;
-
- /*** Adapt to new config ***/
-
- if ( gr1553rt_sw_alloc(priv) != 0 )
- return -1;
-
- gr1553rt_sw_init(priv);
-
- return 0;
-}
-
-int gr1553rt_start(void *rt)
-{
- struct gr1553rt_priv *priv = rt;
- SPIN_IRQFLAGS(irqflags);
-
- if ( priv->started )
- return -1;
-
- /*** Initialize software Pointers and stuff ***/
-
- if ( !priv->satab_buffer || !priv->bd_buffer || !priv->evlog_buffer )
- return -2;
-
- priv->evlog_cpu_next = priv->evlog_cpu_base;
-
- /*** Initialize Registers ***/
-
- /* Subaddress table base */
- priv->regs->rt_tab = (unsigned int)priv->sas_hw;
-
- /* Mode code configuration */
- priv->regs->rt_mcctrl = priv->cfg.modecode;
-
- /* RT Time Tag resolution */
- priv->regs->rt_ttag = priv->cfg.time_res << 16;
-
- /* Event LOG base and size */
- priv->regs->rt_evsz = ~(priv->cfg.evlog_size - 1);
- priv->regs->rt_evlog = (unsigned int)priv->evlog_hw_base;
- priv->regs->rt_evirq = 0;
-
- /* Clear and old IRQ flag and Enable IRQ */
- SPIN_LOCK_IRQ(&priv->devlock, irqflags);
- priv->regs->irq = GR1553B_IRQ_RTEV|GR1553B_IRQ_RTD|GR1553B_IRQ_RTTE;
- priv->regs->imask |= GR1553B_IRQEN_RTEVE | GR1553B_IRQEN_RTDE |
- GR1553B_IRQEN_RTTEE;
-
- /* Enable and Set RT address */
- priv->regs->rt_cfg = GR1553RT_KEY |
- (priv->cfg.rtaddress << GR1553B_RT_CFG_RTADDR_BIT) |
- GR1553B_RT_CFG_RTEN;
-
- /* Tell software RT is started */
- priv->started = 1;
- SPIN_UNLOCK_IRQ(&priv->devlock, irqflags);
-
- return 0;
-}
-
-void gr1553rt_stop(void *rt)
-{
- struct gr1553rt_priv *priv = rt;
- SPIN_IRQFLAGS(irqflags);
-
- SPIN_LOCK_IRQ(&priv->devlock, irqflags);
-
- /* Stop Hardware */
- gr1553rt_hw_stop(priv);
-
- /* Software state */
- priv->started = 0;
-
- SPIN_UNLOCK_IRQ(&priv->devlock, irqflags);
-}
-
-void gr1553rt_sa_schedule(
- void *rt,
- int subadr,
- int tx,
- struct gr1553rt_list *list
- )
-{
- struct gr1553rt_priv *priv = rt;
- unsigned short bdid;
- struct gr1553rt_bd *bd;
-
- if ( !list || (list->listid == -1) )
- return;
-
- /* Get Hardware address of first descriptor in list */
- bdid = list->bds[0];
- if ( bdid == 0xffff )
- return;
- bd = &priv->bds_hw[bdid];
-
- list->subadr = subadr;
-
- /* Update Sub address table */
- if ( tx ) {
- list->subadr |= 0x100;
- priv->subadrs[subadr].txlistid = list->listid;
- priv->sas_cpu[subadr].txptr = (unsigned int)bd;
- } else {
- priv->subadrs[subadr].rxlistid = list->listid;
- priv->sas_cpu[subadr].rxptr = (unsigned int)bd;
- }
-}
-
-void gr1553rt_sa_setopts(
- void *rt,
- int subadr,
- unsigned int mask,
- unsigned int options
- )
-{
- struct gr1553rt_priv *priv = rt;
- unsigned int ctrl;
-
- if ( (subadr > 31) || (priv->sas_cpu == NULL) )
- return;
-
- ctrl = priv->sas_cpu[subadr].ctrl;
- priv->sas_cpu[subadr].ctrl = (ctrl & ~mask) | options;
-}
-
-void gr1553rt_set_vecword(void *rt, unsigned int mask, unsigned int words)
-{
- struct gr1553rt_priv *priv = rt;
- unsigned int vword;
-
- if ( mask == 0 )
- return;
-
- vword = priv->regs->rt_statw;
-
- priv->regs->rt_statw = (vword & ~mask) | (words & mask);
-}
-
-void gr1553rt_set_bussts(void *rt, unsigned int mask, unsigned int sts)
-{
- struct gr1553rt_priv *priv = rt;
- unsigned int stat;
-
- stat = priv->regs->rt_stat2;
- priv->regs->rt_stat2 = (stat & ~mask) | (mask & sts);
-}
-
-void gr1553rt_status(void *rt, struct gr1553rt_status *status)
-{
- struct gr1553rt_priv *priv = rt;
- struct gr1553b_regs *regs = priv->regs;
- unsigned int tmp;
- SPIN_IRQFLAGS(irqflags);
-
- SPIN_LOCK_IRQ(&priv->devlock, irqflags);
- status->status = regs->rt_stat;
- status->bus_status = regs->rt_stat2;
-
- tmp = regs->rt_sync;
- status->synctime = tmp >> 16;
- status->syncword = tmp & 0xffff;
-
- tmp = regs->rt_ttag;
- status->time_res = tmp >> 16;
- status->time = tmp & 0xffff;
-
- SPIN_UNLOCK_IRQ(&priv->devlock, irqflags);
-}
-
-void gr1553rt_list_sa(struct gr1553rt_list *list, int *subadr, int *tx)
-{
- int sa, trt;
-
- if ( list->subadr == -1 ) {
- sa = -1;
- trt = -1;
- } else {
- sa = list->subadr & 0xff;
- trt = (list->subadr & 0x100) >> 8;
- }
-
- if ( subadr )
- *subadr = sa;
- if ( tx )
- *tx = trt;
-}
-
-int gr1553rt_evlog_read(void *rt, unsigned int *dst, int max)
-{
- struct gr1553rt_priv *priv = rt;
- int cnt, top, bot, left;
- unsigned int *hwpos;
-
- /* Get address of hardware's current working entry */
- hwpos = (unsigned int *)priv->regs->rt_evlog;
-
- /* Convert into CPU address */
- hwpos = (unsigned int *)
- ((unsigned int)hwpos - (unsigned int)priv->evlog_hw_base +
- (unsigned int)priv->evlog_cpu_base);
-
- if ( priv->evlog_cpu_next == hwpos )
- return 0;
-
- if ( priv->evlog_cpu_next > hwpos ) {
- top = (unsigned int)priv->evlog_cpu_end -
- (unsigned int)priv->evlog_cpu_next;
- bot = (unsigned int)hwpos - (unsigned int)priv->evlog_cpu_base;
- } else {
- top = (unsigned int)hwpos - (unsigned int)priv->evlog_cpu_next;
- bot = 0;
- }
- top = top / 4;
- bot = bot / 4;
-
- left = max;
- if ( top > 0 ) {
- if ( top > left ) {
- cnt = left;
- } else {
- cnt = top;
- }
- memcpy(dst, priv->evlog_cpu_next, cnt*4);
- dst += cnt;
- left -= cnt;
- }
-
- if ( (bot > 0) && (left > 0) ) {
- if ( bot > left ) {
- cnt = left;
- } else {
- cnt = bot;
- }
- memcpy(dst, priv->evlog_cpu_base, cnt*4);
- left -= cnt;
- }
-
- cnt = max - left;
- priv->evlog_cpu_next += cnt;
- if ( priv->evlog_cpu_next >= priv->evlog_cpu_end ) {
- priv->evlog_cpu_next = (unsigned int *)
- ((unsigned int)priv->evlog_cpu_base +
- ((unsigned int)priv->evlog_cpu_next -
- (unsigned int)priv->evlog_cpu_end ));
- }
-
- return max - left;
-}