summaryrefslogtreecommitdiffstats
path: root/c/src/lib/libbsp/sparc/shared/1553/gr1553bc.c
diff options
context:
space:
mode:
Diffstat (limited to 'c/src/lib/libbsp/sparc/shared/1553/gr1553bc.c')
-rw-r--r--c/src/lib/libbsp/sparc/shared/1553/gr1553bc.c1719
1 files changed, 0 insertions, 1719 deletions
diff --git a/c/src/lib/libbsp/sparc/shared/1553/gr1553bc.c b/c/src/lib/libbsp/sparc/shared/1553/gr1553bc.c
deleted file mode 100644
index 3b967d0f37..0000000000
--- a/c/src/lib/libbsp/sparc/shared/1553/gr1553bc.c
+++ /dev/null
@@ -1,1719 +0,0 @@
-/* GR1553B BC 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 <stdlib.h>
-#include <string.h>
-#include <rtems.h>
-#include <drvmgr/drvmgr.h>
-#include <drvmgr/ambapp_bus.h>
-
-#include <bsp/gr1553b.h>
-#include <bsp/gr1553bc.h>
-
-/* 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)
-#define SPIN_FREE(lock) rtems_interrupt_lock_destroy(lock)
-
-#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)
-#define SPIN_FREE(lock)
-
-#ifdef RTEMS_SMP
-#error SMP mode not compatible with these interrupt lock primitives
-#endif
-
-#endif
-
-#define GR1553BC_WRITE_MEM(adr, val) *(volatile uint32_t *)(adr) = (uint32_t)(val)
-#define GR1553BC_READ_MEM(adr) (*(volatile uint32_t *)(adr))
-
-#define GR1553BC_WRITE_REG(adr, val) *(volatile uint32_t *)(adr) = (uint32_t)(val)
-#define GR1553BC_READ_REG(adr) (*(volatile uint32_t *)(adr))
-
-/* Needed by list for data pinter and BD translation */
-struct gr1553bc_priv {
- struct drvmgr_dev **pdev;
- struct gr1553b_regs *regs;
- struct gr1553bc_list *list;
- struct gr1553bc_list *alist;
- int started;
- SPIN_DECLARE(devlock);
-
- /* IRQ log management */
- void *irq_log_p;
- uint32_t *irq_log_base;
- uint32_t *irq_log_curr;
- uint32_t *irq_log_end;
- uint32_t *irq_log_base_hw;
-
- /* Standard IRQ handler function */
- bcirq_func_t irq_func;
- void *irq_data;
-};
-
-
-/*************** LIST HANDLING ROUTINES ***************/
-
-/* This marks that the jump is a jump to next Minor.
- * It is important that it sets one of the two LSB
- * so that we can separate it from a JUMP-IRQ function,
- * function pointers must be aligned to 4bytes.
- *
- * This marker is used to optimize the INDICATION process,
- * from a descriptor pointer we can step to next Jump that
- * has this MARKER set, then we know that the MID is stored
- * there.
- *
- * The marker is limited to 1 byte.
- */
-#define NEXT_MINOR_MARKER 0x01
-
-/* To separate ASYNC list from SYNC list we mark them differently, but with
- * LSB always set. This can be used to get the list the descriptor is a part
- * of.
- */
-#define NEXT_MINOR_MARKER_ASYNC 0x80
-
-struct gr1553bc_list_cfg gr1553bc_def_cfg =
-{
- .rt_timeout =
- {
- 20, 20, 20, 20,
- 20, 20, 20, 20,
- 20, 20, 20, 20,
- 20, 20, 20, 20,
- 20, 20, 20, 20,
- 20, 20, 20, 20,
- 20, 20, 20, 20,
- 20, 20, 20
- },
- .bc_timeout = 30,
- .tropt_irq_on_err = 0,
- .tropt_pause_on_err = 0,
- .async_list = 0,
-};
-
-int gr1553bc_list_alloc(struct gr1553bc_list **list, int max_major)
-{
- int size;
- struct gr1553bc_list *l;
-
- size = sizeof(struct gr1553bc_list) + max_major * sizeof(void *);
- l = malloc(size);
- if ( l == NULL )
- return -1;
- memset(l, 0, size);
-
- l->major_cnt = max_major;
- *list = l;
-
- /* Set default options:
- * - RT timeout tolerance 20us
- * - Global transfer options used when generating transfer descriptors
- * - No BC device, note that this only works when no translation is
- * required
- */
- if ( gr1553bc_list_config(l, &gr1553bc_def_cfg, NULL) ) {
- free(l);
- return -1;
- }
-
- return 0;
-}
-
-void gr1553bc_list_free(struct gr1553bc_list *list)
-{
- gr1553bc_list_table_free(list);
- free(list);
-}
-
-int gr1553bc_list_config
- (
- struct gr1553bc_list *list,
- struct gr1553bc_list_cfg *cfg,
- void *bc
- )
-{
- int timeout, i, tropts;
-
- /* RT Time Tolerances */
- for (i=0; i<31; i++) {
- /* 0=14us, 1=18us ... 0xf=74us
- * round upwards: 15us will be 18us
- */
- timeout = ((cfg->rt_timeout[i] + 1) - 14) / 4;
- if ( (timeout > 0xf) || (timeout < 0) )
- return -1;
- list->rt_timeout[i] = timeout;
- }
- timeout = ((cfg->bc_timeout + 1) - 14) / 4;
- if ( timeout > 0xf )
- return -1;
- list->rt_timeout[i] = timeout;
-
- /* Transfer descriptor generation options */
- tropts = 0;
- if ( cfg->tropt_irq_on_err )
- tropts |= 1<<28;
- if ( cfg->tropt_pause_on_err )
- tropts |= 1<<26;
- list->tropts = tropts;
-
- list->async_list = cfg->async_list;
- list->bc = bc;
-
- return 0;
-}
-
-void gr1553bc_list_link_major(
- struct gr1553bc_major *major,
- struct gr1553bc_major *next
- )
-{
- if ( major ) {
- major->next = next;
- if ( next ) {
- major->minors[major->cfg->minor_cnt-1]->next =
- next->minors[0];
- } else {
- major->minors[major->cfg->minor_cnt-1]->next = NULL;
- }
- }
-}
-
-int gr1553bc_list_set_major(
- struct gr1553bc_list *list,
- struct gr1553bc_major *major,
- int no)
-{
- struct gr1553bc_major *prev, *next;
-
- if ( no >= list->major_cnt )
- return -1;
-
- list->majors[no] = major;
-
- /* Link previous Major frame with this one */
- if ( no > 0 ) {
- prev = list->majors[no-1];
- } else {
- /* First Major is linked with last major */
- prev = list->majors[list->major_cnt-1];
- }
-
- /* Link to next Major if not the last one and if there is
- * a next major
- */
- if ( no == list->major_cnt-1 ) {
- /* The last major, assume that it is connected with the first */
- next = list->majors[0];
- } else {
- next = list->majors[no+1];
- }
-
- /* Link previous frame to jump into this */
- gr1553bc_list_link_major(prev, major);
-
- /* Link This frame to jump into the next */
- gr1553bc_list_link_major(major, next);
-
- return 0;
-}
-
-/* Translate Descriptor address from CPU-address to Hardware Address */
-static inline union gr1553bc_bd *gr1553bc_bd_cpu2hw
- (
- struct gr1553bc_list *list,
- union gr1553bc_bd *bd
- )
-{
- return (union gr1553bc_bd *)(((unsigned int)bd - list->table_cpu) +
- list->table_hw);
-}
-
-/* Translate Descriptor address from HW-address to CPU Address */
-static inline union gr1553bc_bd *gr1553bc_bd_hw2cpu
- (
- struct gr1553bc_list *list,
- union gr1553bc_bd *bd
- )
-{
- return (union gr1553bc_bd *)(((unsigned int)bd - list->table_hw) +
- list->table_cpu);
-}
-
-int gr1553bc_minor_table_size(struct gr1553bc_minor *minor)
-{
- struct gr1553bc_minor_cfg *mincfg = minor->cfg;
- int slot_cnt;
-
- /* SLOTS + JUMP */
- slot_cnt = mincfg->slot_cnt + 1;
- if ( mincfg->timeslot ) {
- /* time management requires 1 extra slot */
- slot_cnt++;
- }
-
- return slot_cnt * GR1553BC_BD_SIZE;
-}
-
-int gr1553bc_list_table_size(struct gr1553bc_list *list)
-{
- struct gr1553bc_major *major;
- int i, j, minor_cnt, size;
-
- size = 0;
- for (i=0; i<list->major_cnt; i++) {
- major = list->majors[i];
- minor_cnt = major->cfg->minor_cnt;
- for (j=0; j<minor_cnt; j++) {
- /* 128-bit Alignment required by HW */
- size += (GR1553BC_BD_ALIGN -
- (size & (GR1553BC_BD_ALIGN-1))) &
- ~(GR1553BC_BD_ALIGN-1);
-
- /* Size required by descriptors */
- size += gr1553bc_minor_table_size(major->minors[j]);
- }
- }
-
- return size;
-}
-
-int gr1553bc_list_table_alloc
- (
- struct gr1553bc_list *list,
- void *bdtab_custom
- )
-{
- struct gr1553bc_major *major;
- int i, j, minor_cnt, size;
- unsigned int table;
- struct gr1553bc_priv *bcpriv = list->bc;
-
- /* Free previous allocated descriptor table */
- gr1553bc_list_table_free(list);
-
- /* Remember user's settings for uninitialization */
- list->_table_custom = bdtab_custom;
-
- /* Get Size required for descriptors */
- size = gr1553bc_list_table_size(list);
-
- if ((unsigned int)bdtab_custom & 0x1) {
- /* Address given in Hardware accessible address, we
- * convert it into CPU-accessible address.
- */
- list->table_hw = (unsigned int)bdtab_custom & ~0x1;
- list->_table = bdtab_custom;
- drvmgr_translate_check(
- *bcpriv->pdev,
- DMAMEM_TO_CPU,
- (void *)list->table_hw,
- (void **)&list->table_cpu,
- size);
- } else {
- if (bdtab_custom == NULL) {
- /* Allocate descriptors */
- list->_table = malloc(size + (GR1553BC_BD_ALIGN-1));
- if ( list->_table == NULL )
- return -1;
- } else {
- /* Custom address, given in CPU-accessible address */
- list->_table = bdtab_custom;
- }
- /* 128-bit Alignment required by HW */
- list->table_cpu =
- (((unsigned int)list->_table + (GR1553BC_BD_ALIGN-1)) &
- ~(GR1553BC_BD_ALIGN-1));
-
- /* We got CPU accessible descriptor table address, now we
- * translate that into an address that the Hardware can
- * understand
- */
- if (bcpriv) {
- drvmgr_translate_check(
- *bcpriv->pdev,
- CPUMEM_TO_DMA,
- (void *)list->table_cpu,
- (void **)&list->table_hw,
- size
- );
- } else {
- list->table_hw = list->table_cpu;
- }
- }
-
- /* Write End-Of-List all over the descriptor table here,
- * For debugging/safety?
- */
-
- /* Assign descriptors to all minor frames. The addresses is
- * CPU-accessible addresses.
- */
- table = list->table_cpu;
- for (i=0; i<list->major_cnt; i++) {
- major = list->majors[i];
- minor_cnt = major->cfg->minor_cnt;
- for (j=0; j<minor_cnt; j++) {
- /* 128-bit Alignment required by HW */
- table = (table + (GR1553BC_BD_ALIGN-1)) &
- ~(GR1553BC_BD_ALIGN-1);
- major->minors[j]->bds = (union gr1553bc_bd *)table;
-
- /* Calc size required by descriptors */
- table += gr1553bc_minor_table_size(major->minors[j]);
- }
- }
-
- return 0;
-}
-
-void gr1553bc_list_table_free(struct gr1553bc_list *list)
-{
- if ( (list->_table_custom == NULL) && list->_table ) {
- free(list->_table);
- }
- list->_table = NULL;
- list->_table_custom = NULL;
- list->table_cpu = 0;
- list->table_hw = 0;
-}
-
-/* Init descriptor table provided by each minor frame,
- * we link them together using unconditional JUMP.
- */
-int gr1553bc_list_table_build(struct gr1553bc_list *list)
-{
- struct gr1553bc_major *major;
- struct gr1553bc_minor *minor;
- struct gr1553bc_minor_cfg *mincfg;
- int i, j, k, minor_cnt, marker;
- union gr1553bc_bd *bds, *hwbd;
-
- marker = NEXT_MINOR_MARKER;
- if ( list->async_list )
- marker |= NEXT_MINOR_MARKER_ASYNC;
-
- /* Create Major linking */
- for (i=0; i<list->major_cnt; i++) {
- major = list->majors[i];
- minor_cnt = major->cfg->minor_cnt;
- for (j=0; j<minor_cnt; j++) {
- minor = major->minors[j];
- mincfg = minor->cfg;
- bds = minor->bds;
-
- /* BD[0..SLOTCNT-1] = message slots
- * BD[SLOTCNT+0] = END
- * BD[SLOTCNT+1] = JUMP
- *
- * or if no optional time slot handling:
- *
- * BD[0..SLOTCNT-1] = message slots
- * BD[SLOTCNT] = JUMP
- */
-
- /* BD[0..SLOTCNT-1] */
- for (k=0; k<mincfg->slot_cnt; k++) {
- gr1553bc_bd_tr_init(
- &bds[k].tr,
- GR1553BC_TR_DUMMY_0,
- GR1553BC_TR_DUMMY_1,
- 0,
- 0);
- }
-
- /* BD[SLOTCNT] (OPTIONAL)
- * If a minor frame is configured to be executed in
- * certain time (given a time slot), this descriptor
- * sums up all unused time. The time slot is
- * decremented when messages are inserted into the
- * minor frame and increased when messages are removed.
- */
- if ( mincfg->timeslot > 0 ) {
- gr1553bc_bd_tr_init(
- &bds[k].tr,
- GR1553BC_TR_DUMMY_0 | (mincfg->timeslot >> 2),
- GR1553BC_TR_DUMMY_1,
- 0,
- 0);
- k++;
- }
-
- /* Last descriptor is a jump to next minor frame, to a
- * synchronization point. If chain ends here, the list
- * is marked with a "end-of-list" marker.
- *
- */
- if ( minor->next ) {
- /* Translate CPU address of BD into HW address */
- hwbd = gr1553bc_bd_cpu2hw(
- list,
- &minor->next->bds[0]
- );
- gr1553bc_bd_init(
- &bds[k],
- 0xf,
- GR1553BC_UNCOND_JMP,
- (uint32_t)hwbd,
- ((GR1553BC_ID(i,j,k) << 8) | marker),
- 0
- );
- } else {
- gr1553bc_bd_init(
- &bds[k],
- 0xf,
- GR1553BC_TR_EOL,
- 0,
- ((GR1553BC_ID(i,j,k) << 8) | marker),
- 0);
- }
- }
- }
-
- return 0;
-}
-
-void gr1553bc_bd_init(
- union gr1553bc_bd *bd,
- unsigned int flags,
- uint32_t word0,
- uint32_t word1,
- uint32_t word2,
- uint32_t word3
- )
-{
- struct gr1553bc_bd_raw *raw = &bd->raw;
-
- if ( flags & 0x1 ) {
- if ( (flags & KEEP_TIMESLOT) &&
- ((word0 & GR1553BC_BD_TYPE) == 0) ) {
- /* Don't touch timeslot previously allocated */
- word0 &= ~GR1553BC_TR_TIME;
- word0 |= GR1553BC_READ_MEM(&raw->words[0]) &
- GR1553BC_TR_TIME;
- }
- GR1553BC_WRITE_MEM(&raw->words[0], word0);
- }
- if ( flags & 0x2 )
- GR1553BC_WRITE_MEM(&raw->words[1], word1);
- if ( flags & 0x4 )
- GR1553BC_WRITE_MEM(&raw->words[2], word2);
- if ( flags & 0x8 )
- GR1553BC_WRITE_MEM(&raw->words[3], word3);
-}
-
-/* Alloc a Major frame according to the configuration structure */
-int gr1553bc_major_alloc_skel
- (
- struct gr1553bc_major **major,
- struct gr1553bc_major_cfg *cfg
- )
-{
- struct gr1553bc_major *maj;
- struct gr1553bc_minor *minor;
- int size, i;
-
- if ( (cfg == NULL) || (major == NULL) || (cfg->minor_cnt <= 0) )
- return -1;
-
- /* Allocate Major Frame description, but no descriptors */
- size = sizeof(struct gr1553bc_major) + cfg->minor_cnt *
- (sizeof(struct gr1553bc_minor) + sizeof(void *));
- maj = (struct gr1553bc_major *)malloc(size);
- if ( maj == NULL )
- return -1;
-
- maj->cfg = cfg;
- maj->next = NULL;
-
- /* Create links between minor frames, and from minor frames
- * to configuration structure.
- */
- minor = (struct gr1553bc_minor *)&maj->minors[cfg->minor_cnt];
- for (i=0; i<cfg->minor_cnt; i++, minor++) {
- maj->minors[i] = minor;
- minor->next = minor + 1;
- minor->cfg = &cfg->minor_cfgs[i];
- minor->alloc = 0;
- minor->bds = NULL;
- }
- /* last Minor should point to next Major frame's first minor,
- * we do that somewhere else.
- */
- (minor - 1)->next = NULL;
-
- *major = maj;
-
- return 0;
-}
-
-struct gr1553bc_major *gr1553bc_major_from_id
- (
- struct gr1553bc_list *list,
- int mid
- )
-{
- int major_no;
-
- /* Find Minor Frame from MID */
- major_no = GR1553BC_MAJID_FROM_ID(mid);
-
- if ( major_no >= list->major_cnt )
- return NULL;
- return list->majors[major_no];
-}
-
-struct gr1553bc_minor *gr1553bc_minor_from_id
- (
- struct gr1553bc_list *list,
- int mid
- )
-{
- int minor_no;
- struct gr1553bc_major *major;
-
- /* Get Major from ID */
- major = gr1553bc_major_from_id(list, mid);
- if ( major == NULL )
- return NULL;
-
- /* Find Minor Frame from MID */
- minor_no = GR1553BC_MINID_FROM_ID(mid);
-
- if ( minor_no >= major->cfg->minor_cnt )
- return NULL;
- return major->minors[minor_no];
-}
-
-union gr1553bc_bd *gr1553bc_slot_bd
- (
- struct gr1553bc_list *list,
- int mid
- )
-{
- struct gr1553bc_minor *minor;
- int slot_no;
-
- /*** look up BD ***/
-
- /* Get minor */
- minor = gr1553bc_minor_from_id(list, mid);
- if ( minor == NULL )
- return NULL;
-
- /* Get Slot */
- slot_no = GR1553BC_SLOTID_FROM_ID(mid);
- if ( slot_no >= 0xff )
- slot_no = 0;
-
- /* Get BD address */
- return &minor->bds[slot_no];
-}
-
-static int gr1553bc_minor_first_avail(struct gr1553bc_minor *minor)
-{
- int slot_num;
- uint32_t alloc;
-
- alloc = minor->alloc;
- if ( alloc == 0xffffffff ) {
- /* No free */
- return -1;
- }
- slot_num = 0;
- while ( alloc & 1 ) {
- alloc = alloc >> 1;
- slot_num++;
- }
- if ( slot_num >= minor->cfg->slot_cnt ) {
- /* no free */
- return -1;
- }
- return slot_num;
-}
-
-int gr1553bc_slot_alloc(
- struct gr1553bc_list *list,
- int *mid,
- int timeslot,
- union gr1553bc_bd **bd
- )
-{
- struct gr1553bc_minor *minor = gr1553bc_minor_from_id(list, *mid);
-
- return gr1553bc_slot_alloc2(minor, mid, timeslot, bd);
-}
-
-/* Same as gr1553bc_slot_alloc but identifies a minor instead of list.
- * The major/minor part of MID is ignored.
- */
-int gr1553bc_slot_alloc2(
- struct gr1553bc_minor *minor,
- int *mid,
- int timeslot,
- union gr1553bc_bd **bd
- )
-{
- int slot_no;
- uint32_t set0;
- int timefree;
- struct gr1553bc_bd_tr *trbd;
- struct gr1553bc_minor_cfg *mincfg;
-
- if ( minor == NULL )
- return -1;
-
- mincfg = minor->cfg;
-
- /* Find first free slot if not a certain slot is requested */
- slot_no = GR1553BC_SLOTID_FROM_ID(*mid);
- if ( slot_no == 0xff ) {
- slot_no = gr1553bc_minor_first_avail(minor);
- if ( slot_no < 0 )
- return -1;
- } else {
- /* Allocate a certain slot, check that it is free */
- if ( slot_no >= mincfg->slot_cnt )
- return -1;
- if ( (1<<slot_no) & minor->alloc )
- return -1;
- }
-
- /* Ok, we got our slot. Lets allocate time for slot if requested by user
- * and time management is enabled for this Minor Frame.
- */
- if ( timeslot > 0 ) {
- /* Make timeslot on a 4us boundary (time resolution of core) */
- timeslot = (timeslot + 0x3) >> 2;
-
- if ( mincfg->timeslot ) {
- /* Subtract requested time from free time */
- trbd = &minor->bds[mincfg->slot_cnt].tr;
- set0 = GR1553BC_READ_MEM(&trbd->settings[0]);
- timefree = set0 & GR1553BC_TR_TIME;
- if ( timefree < timeslot ) {
- /* Not enough time left to schedule slot in minor */
- return -1;
- }
- /* Store back the time left */
- timefree -= timeslot;
- set0 = (set0 & ~GR1553BC_TR_TIME) | timefree;
- GR1553BC_WRITE_MEM(&trbd->settings[0], set0);
- /* Note: at the moment the minor frame can be executed faster
- * than expected, we hurry up writing requested
- * descriptor.
- */
- }
- }
-
- /* Make the allocated descriptor be an empty slot with the
- * timeslot requested.
- */
- trbd = &minor->bds[slot_no].tr;
- gr1553bc_bd_tr_init(
- trbd,
- GR1553BC_TR_DUMMY_0 | timeslot,
- GR1553BC_TR_DUMMY_1,
- 0,
- 0);
-
- /* Allocate slot */
- minor->alloc |= 1<<slot_no;
-
- if ( bd )
- *bd = (union gr1553bc_bd *)trbd;
- *mid = GR1553BC_ID_SET_SLOT(*mid, slot_no);
-
- return 0;
-}
-
-/* Return time slot freed (if time is managed by driver), negative on error */
-int gr1553bc_slot_free(struct gr1553bc_list *list, int mid)
-{
- struct gr1553bc_minor *minor = gr1553bc_minor_from_id(list, mid);
-
- return gr1553bc_slot_free2(minor, mid);
-}
-
-/* Return time slot freed (if time is managed by driver), negative on error */
-int gr1553bc_slot_free2(struct gr1553bc_minor *minor, int mid)
-{
- union gr1553bc_bd *bd;
- struct gr1553bc_bd_tr *endbd;
- struct gr1553bc_minor_cfg *mincfg;
- int slot_no, timeslot, timefree;
- uint32_t word0, set0;
-
- if ( minor == NULL )
- return -1;
-
- slot_no = GR1553BC_SLOTID_FROM_ID(mid);
-
- if ( (minor->alloc & (1<<slot_no)) == 0 )
- return -1;
-
- bd = &minor->bds[slot_no];
-
- /* If the driver handles time for this minor frame, return
- * time if previuosly requested.
- */
- timeslot = 0;
- mincfg = minor->cfg;
- if ( mincfg->timeslot > 0 ) {
- /* Find out if message slot had time allocated */
- word0 = GR1553BC_READ_MEM(&bd->raw.words[0]);
- if ( word0 & GR1553BC_BD_TYPE ) {
- /* Condition ==> no time slot allocated */
- } else {
- /* Transfer descriptor, may have time slot */
- timeslot = word0 & GR1553BC_TR_TIME;
- if ( timeslot > 0 ) {
- /* Return previously allocated time to END
- * TIME descriptor.
- */
- endbd = &minor->bds[mincfg->slot_cnt].tr;
- set0 = GR1553BC_READ_MEM(&endbd->settings[0]);
- timefree = set0 & GR1553BC_TR_TIME;
- timefree += timeslot;
- set0 = (set0 & ~GR1553BC_TR_TIME) | timefree;
- GR1553BC_WRITE_MEM(&endbd->settings[0], set0);
- /* Note: at the moment the minor frame can be
- * executed slower than expected, the
- * timeslot is at two locations.
- */
- }
- }
- }
-
- /* Make slot an empty message */
- gr1553bc_bd_tr_init(
- &bd->tr,
- GR1553BC_TR_DUMMY_0,
- GR1553BC_TR_DUMMY_1,
- 0,
- 0);
-
- /* unallocate descriptor */
- minor->alloc &= ~(1<<slot_no);
-
- /* Return time freed in microseconds */
- return timeslot << 2;
-}
-
-int gr1553bc_list_freetime(struct gr1553bc_list *list, int mid)
-{
- struct gr1553bc_minor *minor = gr1553bc_minor_from_id(list, mid);
-
- return gr1553bc_minor_freetime(minor);
-}
-
-int gr1553bc_minor_freetime(struct gr1553bc_minor *minor)
-{
- struct gr1553bc_bd_tr *endbd;
- struct gr1553bc_minor_cfg *mincfg;
- int timefree;
- uint32_t set0;
-
- if ( minor == NULL )
- return -1;
-
- /* If the driver handles time for this minor frame, return
- * time if previuosly requested.
- */
- timefree = 0;
- mincfg = minor->cfg;
- if ( mincfg->timeslot > 0 ) {
- /* Return previously allocated time to END
- * TIME descriptor.
- */
- endbd = &minor->bds[mincfg->slot_cnt].tr;
- set0 = GR1553BC_READ_MEM(&endbd->settings[0]);
- timefree = (set0 & GR1553BC_TR_TIME) << 2;
- }
-
- /* Return time freed */
- return timefree;
-}
-
-int gr1553bc_slot_raw
- (
- struct gr1553bc_list *list,
- int mid,
- unsigned int flags,
- uint32_t word0,
- uint32_t word1,
- uint32_t word2,
- uint32_t word3
- )
-{
- struct gr1553bc_minor *minor;
- union gr1553bc_bd *bd;
- int slot_no;
-
- minor = gr1553bc_minor_from_id(list, mid);
- if ( minor == NULL )
- return -1;
-
- /* Get Slot */
- slot_no = GR1553BC_SLOTID_FROM_ID(mid);
- if ( slot_no >= minor->cfg->slot_cnt ) {
- return -1;
- }
-
- /* Get descriptor */
- bd = &minor->bds[slot_no];
-
- /* Build empty descriptor. */
- gr1553bc_bd_init(
- bd,
- flags,
- word0,
- word1,
- word2,
- word3);
-
- return 0;
-}
-
-/* Create unconditional IRQ customly defined location
- * The IRQ is disabled, enable it with gr1553bc_slot_irq_enable().
- */
-int gr1553bc_slot_irq_prepare
- (
- struct gr1553bc_list *list,
- int mid,
- bcirq_func_t func,
- void *data
- )
-{
- union gr1553bc_bd *bd;
- int slot_no, to_mid;
-
- /* Build unconditional IRQ descriptor. The padding is used
- * for identifying the MINOR frame and function and custom data.
- *
- * The IRQ is disabled at first, a unconditional jump to next
- * descriptor in table.
- */
-
- /* Get BD address of jump destination */
- slot_no = GR1553BC_SLOTID_FROM_ID(mid);
- to_mid = GR1553BC_ID_SET_SLOT(mid, slot_no + 1);
- bd = gr1553bc_slot_bd(list, to_mid);
- if ( bd == NULL )
- return -1;
- bd = gr1553bc_bd_cpu2hw(list, bd);
-
- return gr1553bc_slot_raw(
- list,
- mid,
- 0xF,
- GR1553BC_UNCOND_JMP,
- (uint32_t)bd,
- (uint32_t)func,
- (uint32_t)data
- );
-}
-
-/* Enable previously prepared unconditional IRQ */
-int gr1553bc_slot_irq_enable(struct gr1553bc_list *list, int mid)
-{
- /* Leave word1..3 untouched:
- * 1. Unconditional Jump address
- * 2. Function
- * 3. Custom Data
- *
- * Since only one bit is changed in word0 (Condition word),
- * no hardware/software races will exist ==> it is safe
- * to enable/disable IRQ at any time independent of where
- * hardware is in table.
- */
- return gr1553bc_slot_raw(
- list,
- mid,
- 0x1, /* change only WORD0 */
- GR1553BC_UNCOND_IRQ,
- 0,
- 0,
- 0);
-}
-
-/* Disable unconditional IRQ point, changed to unconditional JUMP
- * to descriptor following.
- * After disabling it it can be enabled again, or freed.
- */
-int gr1553bc_slot_irq_disable(struct gr1553bc_list *list, int mid)
-{
- return gr1553bc_slot_raw(
- list,
- mid,
- 0x1, /* change only WORD0, JUMP address already set */
- GR1553BC_UNCOND_JMP,
- 0,
- 0,
- 0);
-}
-
-int gr1553bc_slot_empty(struct gr1553bc_list *list, int mid)
-{
- return gr1553bc_slot_raw(
- list,
- mid,
- 0xF | KEEP_TIMESLOT,
- GR1553BC_TR_DUMMY_0,
- GR1553BC_TR_DUMMY_1,
- 0,
- 0);
-}
-
-int gr1553bc_slot_exttrig(struct gr1553bc_list *list, int mid)
-{
- return gr1553bc_slot_raw(
- list,
- mid,
- 0xF | KEEP_TIMESLOT,
- GR1553BC_TR_DUMMY_0 | GR1553BC_TR_EXTTRIG,
- GR1553BC_TR_DUMMY_1,
- 0,
- 0);
-}
-
-int gr1553bc_slot_jump
- (
- struct gr1553bc_list *list,
- int mid,
- uint32_t condition,
- int to_mid
- )
-{
- union gr1553bc_bd *bd;
-
- /* Get BD address */
- bd = gr1553bc_slot_bd(list, to_mid);
- if ( bd == NULL )
- return -1;
- /* Convert into an address that the HW understand */
- bd = gr1553bc_bd_cpu2hw(list, bd);
-
- return gr1553bc_slot_raw(
- list,
- mid,
- 0xF,
- condition,
- (uint32_t)bd,
- 0,
- 0);
-}
-
-int gr1553bc_slot_transfer(
- struct gr1553bc_list *list,
- int mid,
- int options,
- int tt,
- uint16_t *dptr)
-{
- uint32_t set0, set1;
- union gr1553bc_bd *bd;
- int rx_rtadr, tx_rtadr, timeout;
-
- /* Get BD address */
- bd = gr1553bc_slot_bd(list, mid);
- if ( bd == NULL )
- return -1;
-
- /* Translate Data pointer from CPU-local to 1553-core accessible
- * address if user wants that. This may be useful for AMBA-over-PCI
- * cores.
- */
- if ( (unsigned int)dptr & 0x1 ) {
- struct gr1553bc_priv *bcpriv = list->bc;
-
- drvmgr_translate(
- *bcpriv->pdev,
- CPUMEM_TO_DMA,
- (void *)((unsigned int)dptr & ~0x1),
- (void **)&dptr);
- }
-
- /* It is assumed that the descriptor has already been initialized
- * as a empty slot (Dummy bit set), so to avoid races the dummy
- * bit is cleared last.
- *
- * If we knew that the write would do a burst (for example over SpW)
- * it would be safe to write in order.
- */
-
- /* Preserve timeslot */
- set0 = GR1553BC_READ_MEM(&bd->tr.settings[0]);
- set0 &= GR1553BC_TR_TIME;
- set0 |= options & 0x61f00000;
- set0 |= list->tropts; /* Global options */
-
- /* Set transfer type, bus and let RT tolerance table descide
- * responce tolerance.
- *
- * If a destination address is specified the longest timeout
- * tolerance is taken.
- */
- rx_rtadr = (tt >> 22) & 0x1f;
- tx_rtadr = (tt >> 12) & 0x1f;
- if ( (tx_rtadr != 0x1f) &&
- (list->rt_timeout[rx_rtadr] < list->rt_timeout[tx_rtadr]) ) {
- timeout = list->rt_timeout[tx_rtadr];
- } else {
- timeout = list->rt_timeout[rx_rtadr];
- }
- set1 = ((timeout & 0xf) << 27) | (tt & 0x27ffffff) | ((options & 0x3)<<30);
-
- GR1553BC_WRITE_MEM(&bd->tr.settings[0], set0);
- GR1553BC_WRITE_MEM(&bd->tr.dptr, (uint32_t)dptr);
- /* Write UNUSED BIT, when cleared it Indicates that BC has written it */
- GR1553BC_WRITE_MEM(&bd->tr.status, 0x80000000);
- GR1553BC_WRITE_MEM(&bd->tr.settings[1], set1);
-
- return 0;
-}
-
-int gr1553bc_slot_update
- (
- struct gr1553bc_list *list,
- int mid,
- uint16_t *dptr,
- unsigned int *stat
- )
-{
- union gr1553bc_bd *bd;
- unsigned int status;
- unsigned int dataptr = (unsigned int)dptr;
-
- /* Get BD address */
- bd = gr1553bc_slot_bd(list, mid);
- if ( bd == NULL )
- return -1;
-
- /* Write new Data Pointer if needed */
- if ( dataptr ) {
- struct gr1553bc_priv *bcpriv = list->bc;
-
- /* Translate Data pointer from CPU-local to 1553-core accessible
- * address if user wants that. This may be useful for AMBA-over-PCI
- * cores.
- */
- if ( dataptr & 0x1 ) {
- drvmgr_translate(
- *bcpriv->pdev,
- CPUMEM_TO_DMA,
- (void *)(dataptr & ~0x1),
- (void **)&dptr
- );
- }
-
- /* Update Data Pointer */
- GR1553BC_WRITE_MEM(&bd->tr.dptr, dataptr);
- }
-
- /* Get status of transfer descriptor */
- if ( stat ) {
- status = *stat;
- *stat = GR1553BC_READ_MEM(&bd->tr.status);
- if ( status ) {
- /* Clear status fields user selects, then
- * or bit31 if user wants that. The bit31
- * may be used to indicate if the BC has
- * performed the access.
- */
- status = (*stat & (status & 0xffffff)) |
- (status & (1<<31));
- GR1553BC_WRITE_MEM(&bd->tr.status, status);
- }
- }
-
- return 0;
-}
-
-int gr1553bc_slot_dummy(
- struct gr1553bc_list *list,
- int mid,
- unsigned int *dummy)
-{
- union gr1553bc_bd *bd;
- unsigned int set1, new_set1;
-
- /* Get BD address */
- bd = gr1553bc_slot_bd(list, mid);
- if ( bd == NULL )
- return -1;
- /* Update the Dummy Bit */
- set1 = GR1553BC_READ_MEM(&bd->tr.settings[1]);
- new_set1 = (set1 & ~GR1553BC_TR_DUMMY_1) | (*dummy & GR1553BC_TR_DUMMY_1);
- GR1553BC_WRITE_MEM(&bd->tr.settings[1], new_set1);
-
- *dummy = set1;
-
- return 0;
-}
-
-/* Find MID from Descriptor pointer */
-int gr1553bc_mid_from_bd(
- union gr1553bc_bd *bd,
- int *mid,
- int *async
- )
-{
- int i, bdmid, slot_no;
- uint32_t word0, word2;
-
- /* Find Jump to next Minor Frame or End-Of-List,
- * at those locations we have stored a MID
- *
- * GR1553BC_SLOT_MAX+2 = Worst case, BD is max distance from jump
- * descriptor. 2=END and Jump descriptors.
- */
- for (i=0; i<GR1553BC_SLOT_MAX+2; i++) {
- word0 = GR1553BC_READ_MEM(&bd->raw.words[0]);
- if ( word0 & GR1553BC_BD_TYPE ) {
- if ( word0 == GR1553BC_UNCOND_JMP ) {
- /* May be a unconditional IRQ set by user. In
- * that case the function is stored in WORD3,
- * functions must be aligned to 4 byte boudary.
- */
- word2 = GR1553BC_READ_MEM(&bd->raw.words[2]);
- if ( word2 & NEXT_MINOR_MARKER ) {
- goto found_mid;
- }
- } else if ( word0 == GR1553BC_TR_EOL ) {
- /* End-Of-List, does contain a MID */
- word2 = GR1553BC_READ_MEM(&bd->raw.words[2]);
- goto found_mid;
- }
- }
- bd++;
- }
-
- return -1;
-
-found_mid:
- /* Get MID of JUMP descriptor */
- bdmid = word2 >> 8;
- /* Subtract distance from JUMP descriptor to find MID
- * of requested BD.
- */
- slot_no = GR1553BC_SLOTID_FROM_ID(bdmid);
- slot_no -= i;
- bdmid = GR1553BC_ID_SET_SLOT(bdmid, slot_no);
-
- if ( mid )
- *mid = bdmid;
-
- /* Determine which list BD belongs to: async or sync */
- if ( async )
- *async = word2 & NEXT_MINOR_MARKER_ASYNC;
-
- return 0;
-}
-
-/*************** END OF LIST HANDLING ROUTINES ***************/
-
-/*************** DEVICE HANDLING ROUTINES ***************/
-
-void gr1553bc_device_init(struct gr1553bc_priv *priv);
-void gr1553bc_device_uninit(struct gr1553bc_priv *priv);
-void gr1553bc_isr(void *data);
-
-/*** GR1553BC driver ***/
-
-void gr1553bc_register(void)
-{
- /* The BC driver rely on the GR1553B Driver */
- gr1553_register();
-}
-
-static void gr1553bc_isr_std(union gr1553bc_bd *bd, void *data)
-{
- /* Do nothing */
-}
-
-/* Take a GR1553BC hardware device identified by minor.
- * A pointer is returned that is used internally by the GR1553BC
- * driver, it is used as an input paramter 'bc' to all other
- * functions that manipulate the hardware.
- */
-void *gr1553bc_open(int minor)
-{
- struct drvmgr_dev **pdev = NULL;
- struct gr1553bc_priv *priv = NULL;
- struct amba_dev_info *ambadev;
- struct ambapp_core *pnpinfo;
- void *irq_log_p = NULL;
-
- /* Allocate requested device */
- pdev = gr1553_bc_open(minor);
- if ( pdev == NULL )
- goto fail;
-
- irq_log_p = malloc(GR1553BC_IRQLOG_SIZE*2);
- if ( irq_log_p == NULL )
- goto fail;
-
- priv = malloc(sizeof(struct gr1553bc_priv));
- if ( priv == NULL )
- goto fail;
- memset(priv, 0, sizeof(struct gr1553bc_priv));
-
- /* Init BC device */
- priv->pdev = pdev;
- (*pdev)->priv = priv;
- priv->irq_log_p = irq_log_p;
- priv->started = 0;
-
- /* 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, "gr1553bc");
-
- gr1553bc_device_init(priv);
-
- /* Register ISR handler (unmask at IRQ controller) */
- if ( drvmgr_interrupt_register(*priv->pdev, 0, "gr1553bc",
- gr1553bc_isr, priv) ) {
- goto fail;
- }
-
- return priv;
-
-fail:
- if ( pdev )
- gr1553_bc_close(pdev);
- if ( irq_log_p )
- free(irq_log_p);
- if ( priv )
- free(priv);
- return NULL;
-}
-
-void gr1553bc_close(void *bc)
-{
- struct gr1553bc_priv *priv = bc;
-
- /* Stop Hardware */
- gr1553bc_stop(bc, 0x3);
-
- gr1553bc_device_uninit(priv);
-
- /* Remove interrupt handler (mask IRQ at IRQ controller) */
- drvmgr_interrupt_unregister(*priv->pdev, 0, gr1553bc_isr, priv);
-
- /* Free device */
- gr1553_bc_close(priv->pdev);
- SPIN_FREE(&priv->devlock);
- free(priv->irq_log_p);
- free(priv);
-}
-
-/* Return Current Minor frame number */
-int gr1553bc_indication(void *bc, int async, int *mid)
-{
- struct gr1553bc_priv *priv = bc;
- union gr1553bc_bd *bd;
-
- /* Get current descriptor pointer */
- if ( async ) {
- bd = (union gr1553bc_bd *)
- GR1553BC_READ_REG(&priv->regs->bc_aslot);
- bd = gr1553bc_bd_hw2cpu(priv->alist, bd);
- } else {
- bd = (union gr1553bc_bd *)
- GR1553BC_READ_REG(&priv->regs->bc_slot);
- bd = gr1553bc_bd_hw2cpu(priv->list, bd);
- }
-
- return gr1553bc_mid_from_bd(bd, mid, NULL);
-}
-
-/* Start major frame processing, wait for TimerManager tick or start directly */
-int gr1553bc_start(void *bc, struct gr1553bc_list *list, struct gr1553bc_list *list_async)
-{
- struct gr1553bc_priv *priv = bc;
- union gr1553bc_bd *bd = NULL, *bd_async = NULL;
- uint32_t ctrl, irqmask;
- SPIN_IRQFLAGS(irqflags);
-
- if ( (list == NULL) && (list_async == NULL) )
- return 0;
-
- /* Find first descriptor in list, the descriptor
- * first to be executed.
- */
- ctrl = GR1553BC_KEY;
- if ( list ) {
- bd = gr1553bc_slot_bd(list, GR1553BC_ID(0,0,0));
- if ( bd == NULL )
- return -1;
- bd = gr1553bc_bd_cpu2hw(list, bd);
- ctrl |= GR1553B_BC_ACT_SCSRT;
- }
- if ( list_async ) {
- bd_async = gr1553bc_slot_bd(list_async, GR1553BC_ID(0,0,0));
- if ( bd_async == NULL )
- return -1;
- bd_async = gr1553bc_bd_cpu2hw(list_async, bd_async);
- ctrl |= GR1553B_BC_ACT_ASSRT;
- }
-
- /* Do "hot-swapping" of lists */
- SPIN_LOCK_IRQ(&priv->devlock, irqflags);
-
- if ( list ) {
- priv->list = list;
- GR1553BC_WRITE_REG(&priv->regs->bc_bd, (uint32_t)bd);
- }
- if ( list_async ) {
- priv->alist = list_async;
- GR1553BC_WRITE_REG(&priv->regs->bc_abd, (uint32_t)bd_async);
- }
-
- /* If not enabled before, we enable it now. */
- GR1553BC_WRITE_REG(&priv->regs->bc_ctrl, ctrl);
-
- /* Enable IRQ */
- if ( priv->started == 0 ) {
- priv->started = 1;
- irqmask = GR1553BC_READ_REG(&priv->regs->imask);
- irqmask |= GR1553B_IRQEN_BCEVE|GR1553B_IRQEN_BCDE|GR1553B_IRQEN_BCWKE;
- GR1553BC_WRITE_REG(&priv->regs->imask, irqmask);
- }
-
- SPIN_UNLOCK_IRQ(&priv->devlock, irqflags);
-
- return 0;
-}
-
-/* Pause GR1553 BC transfers */
-int gr1553bc_pause(void *bc)
-{
- struct gr1553bc_priv *priv = bc;
- uint32_t ctrl;
- SPIN_IRQFLAGS(irqflags);
-
- /* Do "hot-swapping" of lists */
- SPIN_LOCK_IRQ(&priv->devlock, irqflags);
- ctrl = GR1553BC_KEY | GR1553B_BC_ACT_SCSUS;
- GR1553BC_WRITE_REG(&priv->regs->bc_ctrl, ctrl);
- SPIN_UNLOCK_IRQ(&priv->devlock, irqflags);
-
- return 0;
-}
-
-/* Restart GR1553 BC transfers, after being paused */
-int gr1553bc_restart(void *bc)
-{
- struct gr1553bc_priv *priv = bc;
- uint32_t ctrl;
- SPIN_IRQFLAGS(irqflags);
-
- SPIN_LOCK_IRQ(&priv->devlock, irqflags);
- ctrl = GR1553BC_KEY | GR1553B_BC_ACT_SCSRT;
- GR1553BC_WRITE_REG(&priv->regs->bc_ctrl, ctrl);
- SPIN_UNLOCK_IRQ(&priv->devlock, irqflags);
-
- return 0;
-}
-
-/* Stop BC transmission */
-int gr1553bc_stop(void *bc, int options)
-{
- struct gr1553bc_priv *priv = bc;
- uint32_t ctrl;
- SPIN_IRQFLAGS(irqflags);
-
- ctrl = GR1553BC_KEY;
- if ( options & 0x1 )
- ctrl |= GR1553B_BC_ACT_SCSTP;
- if ( options & 0x2 )
- ctrl |= GR1553B_BC_ACT_ASSTP;
-
- SPIN_LOCK_IRQ(&priv->devlock, irqflags);
- GR1553BC_WRITE_REG(&priv->regs->bc_ctrl, ctrl);
- priv->started = 0;
- SPIN_UNLOCK_IRQ(&priv->devlock, irqflags);
-
- return 0;
-}
-
-/* Reset software and BC hardware into a known "unused/init" state */
-void gr1553bc_device_init(struct gr1553bc_priv *priv)
-{
-/* RESET HARDWARE REGISTERS */
- /* Stop BC if not already stopped */
- GR1553BC_WRITE_REG(&priv->regs->bc_ctrl, GR1553BC_KEY | 0x0204);
-
- /* Since RT can not be used at the same time as BC, we stop
- * RT rx, it should already be stopped...
- */
- GR1553BC_WRITE_REG(&priv->regs->rt_cfg, GR1553RT_KEY);
-
- /* Clear some registers */
- GR1553BC_WRITE_REG(&priv->regs->bc_bd, 0);
- GR1553BC_WRITE_REG(&priv->regs->bc_abd, 0);
- GR1553BC_WRITE_REG(&priv->regs->bc_timer, 0);
- GR1553BC_WRITE_REG(&priv->regs->bc_wake, 0);
- GR1553BC_WRITE_REG(&priv->regs->bc_irqptr, 0);
- GR1553BC_WRITE_REG(&priv->regs->bc_busmsk, 0);
-
-/* PUT SOFTWARE INTO INITIAL STATE */
- priv->list = NULL;
- priv->alist = NULL;
-
- priv->irq_log_base = (uint32_t *)
- (((uint32_t)priv->irq_log_p + (GR1553BC_IRQLOG_SIZE-1)) &
- ~(GR1553BC_IRQLOG_SIZE-1));
- /* Translate into a hardware accessible address */
- drvmgr_translate_check(
- *priv->pdev,
- CPUMEM_TO_DMA,
- (void *)priv->irq_log_base,
- (void **)&priv->irq_log_base_hw,
- GR1553BC_IRQLOG_SIZE);
- priv->irq_log_curr = priv->irq_log_base;
- priv->irq_log_end = &priv->irq_log_base[GR1553BC_IRQLOG_CNT-1];
- priv->irq_func = gr1553bc_isr_std;
- priv->irq_data = NULL;
-
- GR1553BC_WRITE_REG(&priv->regs->bc_irqptr,(uint32_t)priv->irq_log_base_hw);
-}
-
-void gr1553bc_device_uninit(struct gr1553bc_priv *priv)
-{
- uint32_t irqmask;
-
- /* Stop BC if not already stopped */
- GR1553BC_WRITE_REG(&priv->regs->bc_ctrl, GR1553BC_KEY | 0x0204);
-
- /* Since RT can not be used at the same time as BC, we stop
- * RT rx, it should already be stopped...
- */
- GR1553BC_WRITE_REG(&priv->regs->rt_cfg, GR1553RT_KEY);
-
- /* Turn off IRQ generation */
- irqmask=GR1553BC_READ_REG(&priv->regs->imask);
- irqmask&=~(GR1553B_IRQEN_BCEVE|GR1553B_IRQEN_BCDE|GR1553B_IRQEN_BCWKE);
- GR1553BC_WRITE_REG(&priv->regs->irq, irqmask);
-}
-
-/* Interrupt handler */
-void gr1553bc_isr(void *arg)
-{
- struct gr1553bc_priv *priv = arg;
- uint32_t *curr, *pos, word0, word2;
- union gr1553bc_bd *bd;
- bcirq_func_t func;
- void *data;
- int handled, irq;
- SPIN_ISR_IRQFLAGS(irqflags);
-
- /* Did core make IRQ */
- irq = GR1553BC_READ_REG(&priv->regs->irq);
- irq &= (GR1553B_IRQEN_BCEVE|GR1553B_IRQEN_BCDE|GR1553B_IRQEN_BCWKE);
- if ( irq == 0 )
- return; /* Shared IRQ: some one else may have caused the IRQ */
-
- /* Clear handled IRQs */
- GR1553BC_WRITE_REG(&priv->regs->irq, irq);
-
- /* DMA error. This IRQ does not affect the IRQ log.
- * We let standard IRQ handle handle it.
- */
- if ( irq & GR1553B_IRQEN_BCDE ) {
- priv->irq_func(NULL, priv->irq_data);
- }
-
- /* Get current posistion in hardware */
- pos = (uint32_t *)GR1553BC_READ_REG(&priv->regs->bc_irqptr);
- /* Converting into CPU address */
- pos = priv->irq_log_base +
- ((unsigned int)pos - (unsigned int)priv->irq_log_base_hw)/4;
-
- /* Step in IRQ log until we reach the end. */
- handled = 0;
- curr = priv->irq_log_curr;
- while ( curr != pos ) {
- bd = (union gr1553bc_bd *)(GR1553BC_READ_MEM(curr) & ~1);
- GR1553BC_WRITE_MEM(curr, 0x2); /* Mark Handled */
-
- /* Convert Descriptor in IRQ log into CPU address. In order
- * to convert we must know which list the descriptor belongs
- * to, we compare the address of the bd to the ASYNC list
- * descriptor table area.
- */
- SPIN_LOCK(&priv->devlock, irqflags);
- if ( priv->alist && ((unsigned int)bd>=priv->alist->table_hw) &&
- ((unsigned int)bd <
- (priv->alist->table_hw + priv->alist->table_size))) {
- /* BD in async list */
- bd = gr1553bc_bd_hw2cpu(priv->alist, bd);
- } else if (priv->list &&
- ((unsigned int)bd >= priv->list->table_hw) &&
- ((unsigned int)bd <
- (priv->list->table_hw + priv->list->table_size))) {
- /* BD in sync list */
- bd = gr1553bc_bd_hw2cpu(priv->list, bd);
- } else {
- /* error - unknown BD. Should not happen but could
- * if user has switched list. Ignore IRQ entry and
- * continue to next entry.
- */
- bd = NULL;
- }
-
- /* Handle Descriptor that cased IRQ
- *
- * If someone have inserted an IRQ descriptor and tied
- * that to a custom function we call that function, otherwise
- * we let the standard IRQ handle handle it.
- */
- if ( bd ) {
- word0 = GR1553BC_READ_MEM(&bd->raw.words[0]);
- word2 = GR1553BC_READ_MEM(&bd->raw.words[2]);
- SPIN_UNLOCK(&priv->devlock, irqflags);
- if ( word0 == GR1553BC_UNCOND_IRQ ) {
- if ( (word2 & 0x3) == 0 ) {
- func = (bcirq_func_t)(word2 & ~0x3);
- data = (void *)
- GR1553BC_READ_MEM(&bd->raw.words[3]);
- func(bd, data);
- handled = 1;
- }
- }
-
- if ( handled == 0 ) {
- /* Let standard IRQ handle handle it */
- priv->irq_func(bd, priv->irq_data);
- } else {
- handled = 0;
- }
- } else {
- SPIN_UNLOCK(&priv->devlock, irqflags);
- }
-
- /* Increment to next entry in IRQ LOG */
- if ( curr == priv->irq_log_end )
- curr = priv->irq_log_base;
- else
- curr++;
- }
- priv->irq_log_curr = curr;
-}
-
-int gr1553bc_irq_setup
- (
- void *bc,
- bcirq_func_t func,
- void *data
- )
-{
- struct gr1553bc_priv *priv = bc;
-
- if ( func == NULL )
- priv->irq_func = gr1553bc_isr_std;
- else
- priv->irq_func = func;
- priv->irq_data = data;
-
- return 0;
-}
-
-void gr1553bc_ext_trig(void *bc, int trig)
-{
- struct gr1553bc_priv *priv = bc;
- unsigned int trigger;
-
- if ( trig )
- trigger = GR1553B_BC_ACT_SETT;
- else
- trigger = GR1553B_BC_ACT_CLRT;
-
- GR1553BC_WRITE_REG(&priv->regs->bc_ctrl, GR1553BC_KEY | trigger);
-}
-
-void gr1553bc_status(void *bc, struct gr1553bc_status *status)
-{
- struct gr1553bc_priv *priv = bc;
-
- status->status = GR1553BC_READ_REG(&priv->regs->bc_stat);
- status->time = GR1553BC_READ_REG(&priv->regs->bc_timer);
-}
-
-/*** DEBUGGING HELP FUNCTIONS ***/
-
-#include <stdio.h>
-
-void gr1553bc_show_list(struct gr1553bc_list *list, int options)
-{
- struct gr1553bc_major *major;
- struct gr1553bc_minor *minor;
- int i, j, minor_cnt, timefree;
-
- printf("LIST\n");
- printf(" major cnt: %d\n", list->major_cnt);
- for (i=0; i<32; i++) {
- printf(" RT[%d] timeout: %d\n", i, 14+(list->rt_timeout[i]*4));
- }
-
- for (i=0; i<list->major_cnt; i++) {
- major = list->majors[i];
- minor_cnt = major->cfg->minor_cnt;
- printf(" MAJOR[%d]\n", i);
- printf(" minor count: %d\n", minor_cnt);
-
- for (j=0; j<minor_cnt; j++) {
- minor = major->minors[j];
-
- printf(" MINOR[%d]\n", j);
- printf(" bd: 0x%08x (HW:0x%08x)\n",
- (unsigned int)&minor->bds[0],
- (unsigned int)gr1553bc_bd_cpu2hw(list,
- &minor->bds[0]));
- printf(" slot cnt: %d\n", minor->cfg->slot_cnt);
- if ( minor->cfg->timeslot ) {
- timefree = gr1553bc_minor_freetime(minor);
- printf(" timefree: %d\n", timefree);
- printf(" timetotal: %d\n",
- minor->cfg->timeslot);
- } else {
- printf(" no time mgr\n");
- }
- }
- }
-}