diff options
Diffstat (limited to 'c/src/lib/libbsp/sparc/shared/1553/gr1553bc.c')
-rw-r--r-- | c/src/lib/libbsp/sparc/shared/1553/gr1553bc.c | 1719 |
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"); - } - } - } -} |