bsps/sparc: Move shared files to bsps

This patch is a part of the BSP source reorganization.

Update #3285.
This commit is contained in:
Sebastian Huber
2018-04-20 13:33:24 +02:00
parent c49896f1c0
commit d60d303cf1
74 changed files with 131 additions and 131 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,856 @@
/*
* B1553RT driver implmenetation
*
* COPYRIGHT (c) 2009.
* 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 <bsp.h>
#include <rtems/libio.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <assert.h>
#include <ctype.h>
#include <rtems/bspIo.h>
#include <drvmgr/drvmgr.h>
#include <bsp/b1553rt.h>
#include <ambapp.h>
#include <drvmgr/ambapp_bus.h>
/* Uncomment for debug output */
/*#define DEBUG 1*/
/*
#define FUNCDEBUG 1*/
/*#undef DEBUG*/
#undef FUNCDEBUG
/* EVENT_QUEUE_SIZE sets the size of the event queue
*/
#define EVENT_QUEUE_SIZE 1024
#define INDEX(x) ( x&(EVENT_QUEUE_SIZE-1) )
#if 0
#define DBG(x...) printk(x)
#else
#define DBG(x...)
#endif
#ifdef FUNCDEBUG
#define FUNCDBG(x...) printk(x)
#else
#define FUNCDBG(x...)
#endif
#define READ_DMA(address) _READ16((unsigned int)address)
static __inline__ unsigned short _READ16(unsigned int addr) {
unsigned short tmp;
asm(" lduha [%1]1, %0 "
: "=r"(tmp)
: "r"(addr)
);
return tmp;
}
static rtems_device_driver rt_initialize(rtems_device_major_number major, rtems_device_minor_number minor, void *arg);
static rtems_device_driver rt_open(rtems_device_major_number major, rtems_device_minor_number minor, void *arg);
static rtems_device_driver rt_close(rtems_device_major_number major, rtems_device_minor_number minor, void *arg);
static rtems_device_driver rt_read(rtems_device_major_number major, rtems_device_minor_number minor, void *arg);
static rtems_device_driver rt_write(rtems_device_major_number major, rtems_device_minor_number minor, void *arg);
static rtems_device_driver rt_control(rtems_device_major_number major, rtems_device_minor_number minor, void *arg);
#define RT_DRIVER_TABLE_ENTRY { rt_initialize, rt_open, rt_close, rt_read, rt_write, rt_control }
static rtems_driver_address_table b1553rt_driver = RT_DRIVER_TABLE_ENTRY;
typedef struct {
struct drvmgr_dev *dev; /* Driver manager device */
char devName[32]; /* Device Name */
struct rt_reg *regs;
unsigned int ctrl_copy; /* Local copy of config register */
unsigned int cfg_freq;
unsigned int memarea_base;
unsigned int memarea_base_remote;
volatile unsigned short *mem;
/* Received events waiting to be read */
struct rt_msg *rt_event;
unsigned int head, tail;
int rx_blocking;
rtems_id rx_sem, tx_sem, dev_sem;
int minor;
int irqno;
#ifdef DEBUG
unsigned int log[EVENT_QUEUE_SIZE*4];
unsigned int log_i;
#endif
unsigned int status;
rtems_id event_id; /* event that may be signalled upon errors, needs to be set through ioctl command RT_SET_EVENTID */
} rt_priv;
static void b1553rt_interrupt(void *arg);
static rtems_device_driver rt_init(rt_priv *rt);
#define OFS(ofs) (((unsigned int)&ofs & 0x1ffff)>>1)
static int b1553rt_driver_io_registered = 0;
static rtems_device_major_number b1553rt_driver_io_major = 0;
/******************* Driver manager interface ***********************/
/* Driver prototypes */
int b1553rt_register_io(rtems_device_major_number *m);
int b1553rt_device_init(rt_priv *pDev);
int b1553rt_init2(struct drvmgr_dev *dev);
int b1553rt_init3(struct drvmgr_dev *dev);
int b1553rt_remove(struct drvmgr_dev *dev);
struct drvmgr_drv_ops b1553rt_ops =
{
.init = {NULL, b1553rt_init2, b1553rt_init3, NULL},
.remove = b1553rt_remove,
.info = NULL
};
struct amba_dev_id b1553rt_ids[] =
{
{VENDOR_GAISLER, GAISLER_B1553RT},
{0, 0} /* Mark end of table */
};
struct amba_drv_info b1553rt_drv_info =
{
{
DRVMGR_OBJ_DRV, /* Driver */
NULL, /* Next driver */
NULL, /* Device list */
DRIVER_AMBAPP_GAISLER_B1553RT_ID, /* Driver ID */
"B1553RT_DRV", /* Driver Name */
DRVMGR_BUS_TYPE_AMBAPP, /* Bus Type */
&b1553rt_ops,
NULL, /* Funcs */
0, /* No devices yet */
0,
},
&b1553rt_ids[0]
};
void b1553rt_register_drv (void)
{
DBG("Registering B1553RT driver\n");
drvmgr_drv_register(&b1553rt_drv_info.general);
}
int b1553rt_init2(struct drvmgr_dev *dev)
{
rt_priv *priv;
DBG("B1553RT[%d] on bus %s\n", dev->minor_drv, dev->parent->dev->name);
priv = dev->priv = malloc(sizeof(rt_priv));
if ( !priv )
return DRVMGR_NOMEM;
memset(priv, 0, sizeof(*priv));
priv->dev = dev;
/* This core will not find other cores, so we wait for init2() */
return DRVMGR_OK;
}
int b1553rt_init3(struct drvmgr_dev *dev)
{
rt_priv *priv;
char prefix[32];
rtems_status_code status;
priv = dev->priv;
/* Do initialization */
if ( b1553rt_driver_io_registered == 0) {
/* Register the I/O driver only once for all cores */
if ( b1553rt_register_io(&b1553rt_driver_io_major) ) {
/* Failed to register I/O driver */
dev->priv = NULL;
return DRVMGR_FAIL;
}
b1553rt_driver_io_registered = 1;
}
/* I/O system registered and initialized
* Now we take care of device initialization.
*/
if ( b1553rt_device_init(priv) ) {
return DRVMGR_FAIL;
}
/* Get Filesystem name prefix */
prefix[0] = '\0';
if ( drvmgr_get_dev_prefix(dev, prefix) ) {
/* Failed to get prefix, make sure of a unique FS name
* by using the driver minor.
*/
sprintf(priv->devName, "/dev/b1553rt%d", dev->minor_drv);
} else {
/* Got special prefix, this means we have a bus prefix
* And we should use our "bus minor"
*/
sprintf(priv->devName, "/dev/%sb1553rt%d", prefix, dev->minor_bus);
}
/* Register Device */
status = rtems_io_register_name(priv->devName, b1553rt_driver_io_major, dev->minor_drv);
if (status != RTEMS_SUCCESSFUL) {
return DRVMGR_FAIL;
}
return DRVMGR_OK;
}
int b1553rt_remove(struct drvmgr_dev *dev)
{
/* Stop more tasks to open driver */
/* Throw out all tasks using this driver */
/* Unregister I/O node */
/* Unregister and disable Interrupt */
/* Free device memory */
/* Return sucessfully */
return DRVMGR_FAIL;
}
/******************* Driver Implementation ***********************/
int b1553rt_register_io(rtems_device_major_number *m)
{
rtems_status_code r;
if ((r = rtems_io_register_driver(0, &b1553rt_driver, m)) == RTEMS_SUCCESSFUL) {
DBG("B1553RT driver successfully registered, major: %d\n", *m);
} else {
switch(r) {
case RTEMS_TOO_MANY:
printk("B1553RT rtems_io_register_driver failed: RTEMS_TOO_MANY\n");
return -1;
case RTEMS_INVALID_NUMBER:
printk("B1553RT rtems_io_register_driver failed: RTEMS_INVALID_NUMBER\n");
return -1;
case RTEMS_RESOURCE_IN_USE:
printk("B1553RT rtems_io_register_driver failed: RTEMS_RESOURCE_IN_USE\n");
return -1;
default:
printk("B1553RT rtems_io_register_driver failed\n");
return -1;
}
}
return 0;
}
int b1553rt_device_init(rt_priv *pDev)
{
struct amba_dev_info *ambadev;
struct ambapp_core *pnpinfo;
union drvmgr_key_value *value;
unsigned int mem;
unsigned int sys_freq_hz;
/* Get device information from AMBA PnP information */
ambadev = (struct amba_dev_info *)pDev->dev->businfo;
if ( ambadev == NULL ) {
return -1;
}
pnpinfo = &ambadev->info;
pDev->irqno = pnpinfo->irq;
pDev->regs = (struct rt_reg *)pnpinfo->apb_slv->start;
pDev->minor = pDev->dev->minor_drv;
#ifdef DEBUG
pDev->log_i = 0;
memset(pDev->log,0,sizeof(pDev->log));
printf("LOG: 0x%x\n", &pDev->log[0]);
printf("LOG_I: 0x%x\n", &pDev->log_i);
#endif
/* Get memory configuration from bus resources */
value = drvmgr_dev_key_get(pDev->dev, "dmaBaseAdr", DRVMGR_KT_POINTER);
if (value)
mem = (unsigned int)value->ptr;
if (value && (mem & 1)) {
/* Remote address, address as RT looks at it. */
/* Translate the base address into an address that the the CPU can understand */
pDev->memarea_base = mem & ~1;
drvmgr_translate_check(pDev->dev, DMAMEM_TO_CPU,
(void *)pDev->memarea_base_remote,
(void **)&pDev->memarea_base,
4 * 1024);
} else {
if (!value) {
/* Use dynamically allocated memory,
* 4k DMA memory + 4k for alignment
*/
mem = (unsigned int)malloc(4 * 1024 * 2);
if ( !mem ){
printk("RT: Failed to allocate HW memory\n\r");
return -1;
}
/* align memory to 4k boundary */
pDev->memarea_base = (mem + 0xfff) & ~0xfff;
} else {
pDev->memarea_base = mem;
}
/* Translate the base address into an address that the RT core can understand */
drvmgr_translate_check(pDev->dev, CPUMEM_TO_DMA,
(void *)pDev->memarea_base,
(void **)&pDev->memarea_base_remote,
4 * 1024);
}
/* clear the used memory */
memset((char *)pDev->memarea_base, 0, 4 * 1024);
/* Set base address of all descriptors */
pDev->memarea_base = (unsigned int)mem;
pDev->mem = (volatile unsigned short *)pDev->memarea_base;
pDev->rt_event = NULL;
/* The RT is always clocked at the same frequency as the bus
* If the frequency doesnt match it is defaulted to 24MHz,
* user can always override it.
*/
pDev->cfg_freq = RT_FREQ_24MHZ;
/* Get frequency in Hz */
if ( drvmgr_freq_get(pDev->dev, DEV_APB_SLV, &sys_freq_hz) == 0 ) {
if ( sys_freq_hz == 20000000 ) {
pDev->cfg_freq = RT_FREQ_20MHZ;
} else if ( sys_freq_hz == 16000000 ) {
pDev->cfg_freq = RT_FREQ_16MHZ;
} else if ( sys_freq_hz == 12000000 ) {
pDev->cfg_freq = RT_FREQ_12MHZ;
}
}
value = drvmgr_dev_key_get(pDev->dev, "coreFreq", DRVMGR_KT_INT);
if ( value ) {
pDev->cfg_freq = value->i & RT_FREQ_MASK;
}
/* RX Semaphore created with count = 0 */
if ( rtems_semaphore_create(rtems_build_name('R', 'T', '0', '0' + pDev->minor),
0,
RTEMS_FIFO|RTEMS_SIMPLE_BINARY_SEMAPHORE|RTEMS_NO_INHERIT_PRIORITY|RTEMS_LOCAL|RTEMS_NO_PRIORITY_CEILING,
0,
&pDev->rx_sem) != RTEMS_SUCCESSFUL ) {
printk("RT: Failed to create rx semaphore\n");
return RTEMS_INTERNAL_ERROR;
}
/* Device Semaphore created with count = 1 */
if ( rtems_semaphore_create(rtems_build_name('R', 'T', '0', '0' + pDev->minor),
1,
RTEMS_FIFO|RTEMS_SIMPLE_BINARY_SEMAPHORE|RTEMS_NO_INHERIT_PRIORITY|RTEMS_LOCAL|RTEMS_NO_PRIORITY_CEILING,
0,
&pDev->dev_sem) != RTEMS_SUCCESSFUL ){
printk("RT: Failed to create device semaphore\n");
return RTEMS_INTERNAL_ERROR;
}
/* Default to RT-mode */
rt_init(pDev);
return 0;
}
static int odd_parity(unsigned int data)
{
unsigned int i=0;
while(data)
{
i++;
data &= (data - 1);
}
return !(i&1);
}
static void start_operation(rt_priv *rt)
{
}
static void stop_operation(rt_priv *rt)
{
}
static void set_extmdata_en(rt_priv *rt, int extmdata)
{
if ( extmdata )
extmdata = 1;
rt->ctrl_copy = (rt->ctrl_copy & ~(1<<16)) | (extmdata<<16);
rt->regs->ctrl = rt->ctrl_copy;
}
static void set_vector_word(rt_priv *rt, unsigned short vword)
{
rt->regs->vword = vword;
}
/* Set clock speed */
static void set_clkspd(rt_priv *rt, int spd)
{
rt->ctrl_copy = (rt->ctrl_copy & ~0xC0) | (spd<<6);
rt->regs->ctrl = rt->ctrl_copy;
asm volatile("nop"::);
rt->regs->ctrl = rt->ctrl_copy | (1<<20);
}
static void set_rtaddr(rt_priv *rt, int addr)
{
rt->ctrl_copy = (rt->ctrl_copy & ~0x3F00) | (addr << 8) | (odd_parity(addr)<<13);
rt->regs->ctrl = rt->ctrl_copy;
}
static void set_broadcast_en(rt_priv *rt, int data)
{
rt->ctrl_copy = (rt->ctrl_copy & ~0x40000) | (data<<18);
rt->regs->ctrl = rt->ctrl_copy;
}
static rtems_device_driver rt_init(rt_priv *rt)
{
rt->rx_blocking = 1;
if ( rt->rt_event )
free(rt->rt_event);
rt->rt_event = NULL;
rt->rt_event = (struct rt_msg *) malloc(EVENT_QUEUE_SIZE*sizeof(struct rt_msg));
if (rt->rt_event == NULL) {
DBG("RT driver failed to allocated memory.");
return RTEMS_NO_MEMORY;
}
rt->ctrl_copy = rt->regs->ctrl & 0x3F00; /* Keep rtaddr and rtaddrp */
rt->ctrl_copy |= 0x3C0D0; /* broadcast disabled, extmdata=1, writetsw = writecmd = 1 */
rt->regs->ctrl = rt->ctrl_copy;
/* Set Clock speed */
set_clkspd(rt, rt->cfg_freq);
rt->regs->addr = rt->memarea_base_remote;
rt->regs->ipm = 0x70000; /* Enable RT RX, MEM Failure and AHB Error interrupts */
DBG("B1553RT DMA_AREA: 0x%x\n", (unsigned int)rt->mem);
return RTEMS_SUCCESSFUL;
}
static rtems_device_driver rt_initialize(rtems_device_major_number major, rtems_device_minor_number minor, void *arg)
{
return RTEMS_SUCCESSFUL;
}
static rtems_device_driver rt_open(rtems_device_major_number major, rtems_device_minor_number minor, void *arg) {
rt_priv *rt;
struct drvmgr_dev *dev;
FUNCDBG("rt_open\n");
if ( drvmgr_get_dev(&b1553rt_drv_info.general, minor, &dev) ) {
DBG("Wrong minor %d\n", minor);
return RTEMS_UNSATISFIED;
}
rt = (rt_priv *)dev->priv;
if (rtems_semaphore_obtain(rt->dev_sem, RTEMS_NO_WAIT, RTEMS_NO_TIMEOUT) != RTEMS_SUCCESSFUL) {
DBG("rt_open: resource in use\n");
return RTEMS_RESOURCE_IN_USE; /* EBUSY */
}
/* Set defaults */
rt->event_id = 0;
start_operation(rt);
/* Register interrupt routine */
if (drvmgr_interrupt_register(rt->dev, 0, "b1553rt", b1553rt_interrupt, rt)) {
rtems_semaphore_release(rt->dev_sem);
return -1;
}
return RTEMS_SUCCESSFUL;
}
static rtems_device_driver rt_close(rtems_device_major_number major, rtems_device_minor_number minor, void *arg)
{
rt_priv *rt;
struct drvmgr_dev *dev;
FUNCDBG("rt_close");
if ( drvmgr_get_dev(&b1553rt_drv_info.general, minor, &dev) ) {
return RTEMS_UNSATISFIED;
}
rt = (rt_priv *)dev->priv;
drvmgr_interrupt_unregister(rt->dev, 0, b1553rt_interrupt, rt);
stop_operation(rt);
rtems_semaphore_release(rt->dev_sem);
return RTEMS_SUCCESSFUL;
}
static int get_messages(rt_priv *rt, void *buf, unsigned int msg_count)
{
struct rt_msg *dest = (struct rt_msg *) buf;
int count = 0;
if (rt->head == rt->tail) {
return 0;
}
do {
DBG("rt read - head: %d, tail: %d\n", rt->head, rt->tail);
dest[count++] = rt->rt_event[INDEX(rt->tail++)];
} while (rt->head != rt->tail && count < msg_count);
return count;
}
static rtems_device_driver rt_read(rtems_device_major_number major, rtems_device_minor_number minor, void *arg)
{
rtems_libio_rw_args_t *rw_args;
int count = 0;
rt_priv *rt;
struct drvmgr_dev *dev;
if ( drvmgr_get_dev(&b1553rt_drv_info.general, minor, &dev) ) {
return RTEMS_UNSATISFIED;
}
rt = (rt_priv *)dev->priv;
rw_args = (rtems_libio_rw_args_t *) arg;
FUNCDBG("rt_read [%i,%i]: buf: 0x%x, len: %i\n",major, minor, (unsigned int)rw_args->buffer, rw_args->count);
while ( (count = get_messages(rt,rw_args->buffer, rw_args->count)) == 0 ) {
if (rt->rx_blocking) {
rtems_semaphore_obtain(rt->rx_sem, RTEMS_WAIT, RTEMS_NO_TIMEOUT);
} else {
/* Translates to EBUSY */
return RTEMS_RESOURCE_IN_USE;
}
}
rw_args->bytes_moved = count;
return RTEMS_SUCCESSFUL;
}
static rtems_device_driver rt_write(rtems_device_major_number major, rtems_device_minor_number minor, void *arg)
{
rtems_libio_rw_args_t *rw_args;
struct rt_msg *source;
rt_priv *rt;
struct drvmgr_dev *dev;
unsigned int descriptor, suba, wc;
if ( drvmgr_get_dev(&b1553rt_drv_info.general, minor, &dev) ) {
return RTEMS_UNSATISFIED;
}
rt = (rt_priv *)dev->priv;
rw_args = (rtems_libio_rw_args_t *) arg;
if ( rw_args->count != 1 ) {
return RTEMS_INVALID_NAME;
}
source = (struct rt_msg *) rw_args->buffer;
descriptor = source[0].desc & 0x7F;
suba = descriptor-32;
wc = source[0].miw >> 11;
wc = wc ? wc : 32;
FUNCDBG("rt_write [%i,%i]: buf: 0x%x\n",major, minor, (unsigned int)rw_args->buffer);
memcpy((void *)&rt->mem[0x400 + suba*32], &source[0].data[0], wc*2);
rw_args->bytes_moved = 1;
return RTEMS_SUCCESSFUL;
}
static rtems_device_driver rt_control(rtems_device_major_number major, rtems_device_minor_number minor, void *arg)
{
rtems_libio_ioctl_args_t *ioarg = (rtems_libio_ioctl_args_t *) arg;
unsigned int *data = ioarg->buffer;
rt_priv *rt;
struct drvmgr_dev *dev;
FUNCDBG("rt_control[%d]: [%i,%i]\n", minor, major, minor);
if ( drvmgr_get_dev(&b1553rt_drv_info.general, minor, &dev) ) {
return RTEMS_UNSATISFIED;
}
rt = (rt_priv *)dev->priv;
if (!ioarg) {
DBG("rt_control: invalid argument\n");
return RTEMS_INVALID_NAME;
}
ioarg->ioctl_return = 0;
switch (ioarg->command) {
case RT_SET_ADDR:
set_rtaddr(rt, data[0]);
break;
case RT_SET_BCE:
set_broadcast_en(rt, data[0]);
break;
case RT_SET_VECTORW:
set_vector_word(rt, data[0]);
break;
case RT_SET_EXTMDATA:
set_extmdata_en(rt, data[0]);
break;
case RT_RX_BLOCK:
rt->rx_blocking = data[0];
break;
case RT_CLR_STATUS:
rt->status = 0;
break;
case RT_GET_STATUS: /* copy status */
if ( !ioarg->buffer )
return RTEMS_INVALID_NAME;
*(unsigned int *)ioarg->buffer = rt->status;
break;
case RT_SET_EVENTID:
rt->event_id = (rtems_id)ioarg->buffer;
break;
default:
return RTEMS_NOT_IMPLEMENTED;
}
return RTEMS_SUCCESSFUL;
}
static void b1553rt_interrupt(void *arg)
{
rt_priv *rt = arg;
unsigned short descriptor;
int signal_event=0, wake_rx_task=0;
unsigned int event_status=0;
unsigned int wc, irqv, cmd, tsw, suba, tx, miw, i;
unsigned int ipend;
#define SET_ERROR_DESCRIPTOR(descriptor) (event_status = (event_status & 0x0000ffff) | descriptor<<16)
ipend = rt->regs->ipm;
if (ipend == 0) {
/* IRQ mask has been cleared, we must have been reset */
/* Restore ctrl registers */
rt->regs->ctrl = rt->ctrl_copy;
rt->regs->addr = rt->memarea_base_remote;
rt->regs->ipm = 0x70000;
/* Send reset mode code event */
if (rt->head - rt->tail != EVENT_QUEUE_SIZE) {
miw = (8<<11);
descriptor = 64 + 32 + 8;
rt->rt_event[INDEX(rt->head)].miw = miw;
rt->rt_event[INDEX(rt->head)].time = 0;
rt->rt_event[INDEX(rt->head)].desc = descriptor;
rt->head++;
}
}
if ( ipend & 0x1 ) {
/* RT IRQ */
if (rt->head - rt->tail != EVENT_QUEUE_SIZE) {
irqv = rt->regs->irq;
cmd = irqv >> 7;
wc = cmd & 0x1F; /* word count / mode code */
suba = irqv & 0x1F; /* sub address (0-31) */
tx = (irqv >> 5) & 1;
/* read status word */
tsw = READ_DMA(&rt->mem[tx*0x3E0+suba]);
/* Build Message Information Word (B1553BRM-style) */
miw = (wc<<11) | (tsw&RT_TSW_BUS)>>4 | !(tsw&RT_TSW_OK)>>7 | (tsw&RT_TSW_ILL)>>5 |
(tsw&RT_TSW_PAR)>>5 | (tsw&RT_TSW_MAN)>>7;
descriptor = (tx << 5) | suba;
/* Mode codes */
if (suba == 0 || suba == 31) {
descriptor = 64 + (tx*32) + wc;
}
/* Data received or transmitted */
if (descriptor < 64) {
wc = wc ? wc : 32; /* wc = 0 means 32 words transmitted */
}
/* RX Mode code */
else if (descriptor < 96) {
wc = (wc>>4);
}
/* TX Mode code */
else if (descriptor < 128) {
wc = (wc>>4);
}
/* Copy to event queue */
rt->rt_event[INDEX(rt->head)].miw = miw;
rt->rt_event[INDEX(rt->head)].time = 0;
for (i = 0; i < wc; i++) {
rt->rt_event[INDEX(rt->head)].data[i] = READ_DMA(&rt->mem[tx*0x400 + suba*32 + i]);
}
rt->rt_event[INDEX(rt->head)].desc = descriptor;
rt->head++;
/* Handle errors */
if ( tsw & RT_TSW_ILL){
FUNCDBG("RT: RT_ILLCMD\n\r");
rt->status |= RT_ILLCMD_IRQ;
event_status |= RT_ILLCMD_IRQ;
SET_ERROR_DESCRIPTOR(descriptor);
signal_event=1;
}
if ( !(tsw & RT_TSW_OK) ) {
FUNCDBG("RT: RT_MERR_IRQ\n\r");
rt->status |= RT_MERR_IRQ;
event_status |= RT_MERR_IRQ;
SET_ERROR_DESCRIPTOR(descriptor);
signal_event=1;
}
}
else {
/* Indicate overrun */
rt->rt_event[INDEX(rt->head)].desc |= 0x8000;
}
}
if ( ipend & 0x2 ) {
/* Memory failure IRQ */
FUNCDBG("B1553RT: Memory failure\n");
event_status |= RT_DMAF_IRQ;
signal_event=1;
}
if ( ipend & 0x4 ) {
/* AHB Error */
FUNCDBG("B1553RT: AHB ERROR\n");
event_status |= RT_DMAF_IRQ;
signal_event=1;
}
#ifdef DEBUG
rt->log[rt->log_i++ % EVENT_QUEUE_SIZE] = descriptor;
rt->log[rt->log_i++ % EVENT_QUEUE_SIZE] = cmd;
rt->log[rt->log_i++ % EVENT_QUEUE_SIZE] = miw;
rt->log[rt->log_i++ % EVENT_QUEUE_SIZE] = tsw;
#endif
wake_rx_task = 1;
/* Wake any blocked rx thread only on receive interrupts */
if ( wake_rx_task ) {
rtems_semaphore_release(rt->rx_sem);
}
/* Copy current mask to status mask */
if ( event_status ) {
if ( event_status & 0xffff0000 )
rt->status &= 0x0000ffff;
rt->status |= event_status;
}
/* signal event once */
if ( signal_event && (rt->event_id != 0) ) {
rtems_event_send(rt->event_id, event_status);
}
}
void b1553rt_print_dev(struct drvmgr_dev *dev, int options)
{
rt_priv *pDev = dev->priv;
/* Print */
printf("--- B1553RT[%d] %s ---\n", pDev->minor, pDev->devName);
printf(" REGS: 0x%x\n", (unsigned int)pDev->regs);
printf(" IRQ: %d\n", pDev->irqno);
}
void b1553rt_print(int options)
{
struct amba_drv_info *drv = &b1553rt_drv_info;
struct drvmgr_dev *dev;
dev = drv->general.dev;
while(dev) {
b1553rt_print_dev(dev, options);
dev = dev->next_in_drv;
}
}

View File

@@ -0,0 +1,310 @@
/* GR1553B driver, used by BC, RT and/or BM 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 <drvmgr/ambapp_bus.h>
#include <bsp/gr1553b.h>
/* Driver Manager interface for BC, RT, BM, BRM, BC-BM and RT-BM */
#define GR1553B_WRITE_REG(adr, val) *(volatile uint32_t *)(adr) = (val)
#define GR1553B_READ_REG(adr) (*(volatile uint32_t *)(adr))
#define FEAT_BC 0x1
#define FEAT_RT 0x2
#define FEAT_BM 0x4
#define ALLOC_BC 0x1
#define ALLOC_RT 0x2
#define ALLOC_BM 0x4
struct gr1553_device {
struct drvmgr_dev *dev;
int features;
int alloc;
};
struct gr1553_device_feature {
struct gr1553_device_feature *next;
struct gr1553_device *dev;
int minor;
};
/* Device lists */
static struct gr1553_device_feature *gr1553_bm_root = NULL;
static struct gr1553_device_feature *gr1553_rt_root = NULL;
static struct gr1553_device_feature *gr1553_bc_root = NULL;
/* Driver registered */
static int gr1553_driver_registerd = 0;
/* Add 'feat' to linked list pointed to by 'root'. A minor is also assigned. */
static void gr1553_list_add
(
struct gr1553_device_feature **root,
struct gr1553_device_feature *feat
)
{
int minor;
struct gr1553_device_feature *curr;
if ( *root == NULL ) {
*root = feat;
feat->next = NULL;
feat->minor = 0;
return;
}
minor = 0;
retry_new_minor:
curr = *root;
while ( curr->next ) {
if ( curr->minor == minor ) {
minor++;
goto retry_new_minor;
}
curr = curr->next;
}
feat->next = NULL;
feat->minor = minor;
curr->next = feat;
}
static struct gr1553_device_feature *gr1553_list_find
(
struct gr1553_device_feature *root,
int minor
)
{
struct gr1553_device_feature *curr = root;
while ( curr ) {
if ( curr->minor == minor ) {
return curr;
}
curr = curr->next;
}
return NULL;
}
struct drvmgr_dev **gr1553_bc_open(int minor)
{
struct gr1553_device_feature *feat;
feat = gr1553_list_find(gr1553_bc_root, minor);
if ( feat == NULL )
return NULL;
/* Only possible to allocate is RT and BC is free,
* this is beacuse it is not possible to use the
* RT and the BC at the same time.
*/
if ( feat->dev->alloc & (ALLOC_BC|ALLOC_RT) )
return NULL;
/* Alloc BC device */
feat->dev->alloc |= ALLOC_BC;
return &feat->dev->dev;
}
void gr1553_bc_close(struct drvmgr_dev **dev)
{
struct gr1553_device *d = (struct gr1553_device *)dev;
d->alloc &= ~ALLOC_BC;
}
struct drvmgr_dev **gr1553_rt_open(int minor)
{
struct gr1553_device_feature *feat;
feat = gr1553_list_find(gr1553_rt_root, minor);
if ( feat == NULL )
return NULL;
/* Only possible to allocate is RT and BC is free,
* this is beacuse it is not possible to use the
* RT and the BC at the same time.
*/
if ( feat->dev->alloc & (ALLOC_BC|ALLOC_RT) )
return NULL;
/* Alloc RT device */
feat->dev->alloc |= ALLOC_RT;
return &feat->dev->dev;
}
void gr1553_rt_close(struct drvmgr_dev **dev)
{
struct gr1553_device *d = (struct gr1553_device *)dev;
d->alloc &= ~ALLOC_RT;
}
struct drvmgr_dev **gr1553_bm_open(int minor)
{
struct gr1553_device_feature *feat;
feat = gr1553_list_find(gr1553_bm_root, minor);
if ( feat == NULL )
return NULL;
/* Only possible to allocate is RT and BC is free,
* this is beacuse it is not possible to use the
* RT and the BC at the same time.
*/
if ( feat->dev->alloc & ALLOC_BM )
return NULL;
/* Alloc BM device */
feat->dev->alloc |= ALLOC_BM;
return &feat->dev->dev;
}
void gr1553_bm_close(struct drvmgr_dev **dev)
{
struct gr1553_device *d = (struct gr1553_device *)dev;
d->alloc &= ~ALLOC_BM;
}
static int gr1553_init2(struct drvmgr_dev *dev)
{
struct amba_dev_info *ambadev;
struct ambapp_core *pnpinfo;
struct gr1553b_regs *regs;
/* Get device information from AMBA PnP information */
ambadev = (struct amba_dev_info *)dev->businfo;
if ( ambadev == NULL ) {
return DRVMGR_FAIL;
}
pnpinfo = &ambadev->info;
if ( pnpinfo->apb_slv == NULL )
return DRVMGR_EIO;
regs = (struct gr1553b_regs *)pnpinfo->apb_slv->start;
/* Stop IRQ */
GR1553B_WRITE_REG(&regs->imask, 0);
GR1553B_WRITE_REG(&regs->irq, 0xffffffff);
/* Stop BC if not already stopped (just in case) */
GR1553B_WRITE_REG(&regs->bc_ctrl, 0x15520204);
/* Stop RT rx (just in case) */
GR1553B_WRITE_REG(&regs->rt_cfg, 0x15530000);
/* Stop BM logging (just in case) */
GR1553B_WRITE_REG(&regs->bm_ctrl, 0);
return DRVMGR_OK;
}
/* Register the different functionalities that the
* core supports.
*/
static int gr1553_init3(struct drvmgr_dev *dev)
{
struct amba_dev_info *ambadev;
struct ambapp_core *pnpinfo;
struct gr1553_device *priv;
struct gr1553_device_feature *feat;
struct gr1553b_regs *regs;
priv = malloc(sizeof(struct gr1553_device));
if ( priv == NULL )
return DRVMGR_NOMEM;
priv->dev = dev;
priv->alloc = 0;
priv->features = 0;
dev->priv = NULL; /* Let higher level driver handle this */
/* Get device information from AMBA PnP information */
ambadev = (struct amba_dev_info *)dev->businfo;
pnpinfo = &ambadev->info;
regs = (struct gr1553b_regs *)pnpinfo->apb_slv->start;
if ( GR1553B_READ_REG(&regs->bm_stat) & GR1553B_BM_STAT_BMSUP ) {
priv->features |= FEAT_BM;
feat = malloc(sizeof(struct gr1553_device_feature));
feat->dev = priv;
/* Init Minor and Next */
gr1553_list_add(&gr1553_bm_root, feat);
}
if ( GR1553B_READ_REG(&regs->bc_stat) & GR1553B_BC_STAT_BCSUP ) {
priv->features |= FEAT_BC;
feat = malloc(sizeof(struct gr1553_device_feature));
feat->dev = priv;
/* Init Minor and Next */
gr1553_list_add(&gr1553_bc_root, feat);
}
if ( GR1553B_READ_REG(&regs->rt_stat) & GR1553B_RT_STAT_RTSUP ) {
priv->features |= FEAT_RT;
feat = malloc(sizeof(struct gr1553_device_feature));
feat->dev = priv;
/* Init Minor and Next */
gr1553_list_add(&gr1553_rt_root, feat);
}
if ( priv->features == 0 ) {
/* no features in HW should never happen.. an I/O error? */
free(priv);
return DRVMGR_EIO;
}
return DRVMGR_OK;
}
struct drvmgr_drv_ops gr1553_ops =
{
{NULL, gr1553_init2, gr1553_init3, NULL},
NULL,
NULL
};
struct amba_dev_id gr1553_ids[] =
{
{VENDOR_GAISLER, GAISLER_GR1553B},
{0, 0} /* Mark end of table */
};
struct amba_drv_info gr1553_drv_info =
{
{
DRVMGR_OBJ_DRV, /* Driver */
NULL, /* Next driver */
NULL, /* Device list */
DRIVER_AMBAPP_GAISLER_GR1553B_ID,/* Driver ID */
"GR1553_DRV", /* Driver Name */
DRVMGR_BUS_TYPE_AMBAPP, /* Bus Type */
&gr1553_ops,
NULL, /* Funcs */
0, /* No devices yet */
0,
},
&gr1553_ids[0]
};
/* Multiple drivers may call this function. The drivers that depends on
* this driver:
* - BM driver
* - BC driver
* - RT driver
*/
void gr1553_register(void)
{
if ( gr1553_driver_registerd == 0 ) {
gr1553_driver_registerd = 1;
drvmgr_drv_register(&gr1553_drv_info.general);
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,544 @@
/* GR1553B BM 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 <drvmgr/drvmgr.h>
#include <drvmgr/ambapp_bus.h>
#include <bsp/gr1553b.h>
#include <bsp/gr1553bm.h>
#define GR1553BM_WRITE_MEM(adr, val) *(volatile uint32_t *)(adr) = (uint32_t)(val)
#define GR1553BM_READ_MEM(adr) (*(volatile uint32_t *)(adr))
#define GR1553BM_WRITE_REG(adr, val) *(volatile uint32_t *)(adr) = (uint32_t)(val)
#define GR1553BM_READ_REG(adr) (*(volatile uint32_t *)(adr))
/* 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
struct gr1553bm_priv {
struct drvmgr_dev **pdev;
struct gr1553b_regs *regs;
SPIN_DECLARE(devlock);
void *buffer;
unsigned int buffer_base_hw;
unsigned int buffer_base;
unsigned int buffer_end;
unsigned int buffer_size;
unsigned int read_pos;
int started;
struct gr1553bm_config cfg;
/* Time updated by IRQ when 24-bit Time counter overflows */
volatile uint64_t time;
};
void gr1553bm_isr(void *data);
/* Default Driver configuration */
struct gr1553bm_config gr1553bm_default_config =
{
/* Highest resolution, use Time overflow IRQ to track */
.time_resolution = 0,
.time_ovf_irq = 1,
/* No filtering, log all */
.filt_error_options = GR1553BM_ERROPTS_ALL,
.filt_rtadr = 0xffffffff,
.filt_subadr = 0xffffffff,
.filt_mc = 0x0007ffff,
/* 128Kbyte dynamically allocated buffer. */
.buffer_size = 128*1024,
.buffer_custom = NULL,
};
void gr1553bm_register(void)
{
/* The BM driver rely on the GR1553B Driver */
gr1553_register();
}
static void gr1553bm_hw_start(struct gr1553bm_priv *priv)
{
SPIN_IRQFLAGS(irqflags);
/* Enable IRQ source and mark running state */
SPIN_LOCK_IRQ(&priv->devlock, irqflags);
priv->started = 1;
/* Clear old IRQ flags */
priv->regs->irq = GR1553B_IRQ_BMD | GR1553B_IRQ_BMTOF;
/* Unmask IRQ sources */
if ( priv->cfg.time_ovf_irq ) {
priv->regs->imask |= GR1553B_IRQEN_BMDE | GR1553B_IRQEN_BMTOE;
} else {
priv->regs->imask |= GR1553B_IRQEN_BMDE;
}
/* Start logging */
priv->regs->bm_ctrl =
(priv->cfg.filt_error_options &
(GR1553B_BM_CTRL_MANL|GR1553B_BM_CTRL_UDWL|GR1553B_BM_CTRL_IMCL))
| GR1553B_BM_CTRL_BMEN;
SPIN_UNLOCK_IRQ(&priv->devlock, irqflags);
}
static void gr1553bm_hw_stop(struct gr1553bm_priv *priv)
{
SPIN_IRQFLAGS(irqflags);
SPIN_LOCK_IRQ(&priv->devlock, irqflags);
/* Stop Logging */
priv->regs->bm_ctrl = 0;
/* Stop IRQ source */
priv->regs->imask &= ~(GR1553B_IRQEN_BMDE|GR1553B_IRQEN_BMTOE);
/* Clear IRQ flags */
priv->regs->irq = GR1553B_IRQ_BMD | GR1553B_IRQ_BMTOF;
priv->started = 0;
SPIN_UNLOCK_IRQ(&priv->devlock, irqflags);
}
/* Open device by number */
void *gr1553bm_open(int minor)
{
struct drvmgr_dev **pdev = NULL;
struct gr1553bm_priv *priv = NULL;
struct amba_dev_info *ambadev;
struct ambapp_core *pnpinfo;
/* Allocate requested device */
pdev = gr1553_bm_open(minor);
if ( pdev == NULL )
goto fail;
priv = malloc(sizeof(struct gr1553bm_priv));
if ( priv == NULL )
goto fail;
memset(priv, 0, sizeof(struct gr1553bm_priv));
/* Init BC 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, "gr1553bm");
/* Start with default configuration */
priv->cfg = gr1553bm_default_config;
/* Unmask IRQs */
gr1553bm_hw_stop(priv);
return priv;
fail:
if ( pdev )
gr1553_bm_close(pdev);
if ( priv )
free(priv);
return NULL;
}
/* Close previously */
void gr1553bm_close(void *bm)
{
struct gr1553bm_priv *priv = bm;
if ( priv->started ) {
gr1553bm_stop(bm);
}
if ( (priv->cfg.buffer_custom == NULL) && priv->buffer )
free(priv->buffer);
gr1553_bm_close(priv->pdev);
free(priv);
}
/* Configure the BM driver */
int gr1553bm_config(void *bm, struct gr1553bm_config *cfg)
{
struct gr1553bm_priv *priv = bm;
if ( priv->started )
return -1;
/* Check Config validity? */
/*#warning IMPLEMENT.*/
/* Free old buffer if dynamically allocated */
if ( (priv->cfg.buffer_custom == NULL) && priv->buffer ) {
free(priv->buffer);
priv->buffer = NULL;
}
priv->buffer_size = cfg->buffer_size & ~0x7; /* on 8 byte bounadry */
if ((unsigned int)cfg->buffer_custom & 1) {
/* Custom Address Given in Remote address. We need
* to convert it intoTranslate into Hardware a
* hardware accessible address
*/
priv->buffer_base_hw = (unsigned int)cfg->buffer_custom & ~1;
priv->buffer = cfg->buffer_custom;
drvmgr_translate_check(
*priv->pdev,
DMAMEM_TO_CPU,
(void *)priv->buffer_base_hw,
(void **)&priv->buffer_base,
priv->buffer_size);
} else {
if (cfg->buffer_custom == NULL) {
/* Allocate new buffer dynamically */
priv->buffer = malloc(priv->buffer_size + 8);
if (priv->buffer == NULL)
return -1;
} else {
/* Address given in CPU accessible address, no
* translation required.
*/
priv->buffer = cfg->buffer_custom;
}
/* Align to 16 bytes */
priv->buffer_base = ((unsigned int)priv->buffer + (8-1)) &
~(8-1);
/* Translate address of buffer base into address that Hardware must
* use to access the buffer.
*/
drvmgr_translate_check(
*priv->pdev,
CPUMEM_TO_DMA,
(void *)priv->buffer_base,
(void **)&priv->buffer_base_hw,
priv->buffer_size);
}
/* Copy valid config */
priv->cfg = *cfg;
return 0;
}
/* Start logging */
int gr1553bm_start(void *bm)
{
struct gr1553bm_priv *priv = bm;
if ( priv->started )
return -1;
if ( priv->buffer == NULL )
return -2;
/* Start at Time = 0 */
priv->regs->bm_ttag =
priv->cfg.time_resolution << GR1553B_BM_TTAG_RES_BIT;
/* Configure Filters */
priv->regs->bm_adr = priv->cfg.filt_rtadr;
priv->regs->bm_subadr = priv->cfg.filt_subadr;
priv->regs->bm_mc = priv->cfg.filt_mc;
/* Set up buffer */
priv->regs->bm_start = priv->buffer_base_hw;
priv->regs->bm_end = priv->buffer_base_hw + priv->cfg.buffer_size - 4;
priv->regs->bm_pos = priv->buffer_base_hw;
priv->read_pos = priv->buffer_base;
priv->buffer_end = priv->buffer_base + priv->cfg.buffer_size;
/* Register ISR handler and unmask IRQ source at IRQ controller */
if (drvmgr_interrupt_register(*priv->pdev, 0, "gr1553bm", gr1553bm_isr, priv))
return -3;
/* Start hardware and set priv->started */
gr1553bm_hw_start(priv);
return 0;
}
/* Stop logging */
void gr1553bm_stop(void *bm)
{
struct gr1553bm_priv *priv = bm;
/* Stop Hardware */
gr1553bm_hw_stop(priv);
/* At this point the hardware must be stopped and IRQ
* sources unmasked.
*/
/* Unregister ISR handler and unmask 1553 IRQ source at IRQ ctrl */
drvmgr_interrupt_unregister(*priv->pdev, 0, gr1553bm_isr, priv);
}
int gr1553bm_started(void *bm)
{
return ((struct gr1553bm_priv *)bm)->started;
}
/* Get 64-bit 1553 Time.
*
* Update software time counters and return the current time.
*/
void gr1553bm_time(void *bm, uint64_t *time)
{
struct gr1553bm_priv *priv = bm;
unsigned int hwtime, hwtime2;
resample:
if ( priv->started && (priv->cfg.time_ovf_irq == 0) ) {
/* Update Time overflow counter. The carry bit from Time counter
* is located in IRQ Flag.
*
* When IRQ is not used this function must be called often
* enough to avoid that the Time overflows and the carry
* bit is already set. The frequency depends on the Time
* resolution.
*/
if ( priv->regs->irq & GR1553B_IRQ_BMTOF ) {
/* Clear carry bit */
priv->regs->irq = GR1553B_IRQ_BMTOF;
priv->time += (GR1553B_BM_TTAG_VAL + 1);
}
}
/* Report current Time, even if stopped */
hwtime = priv->regs->bm_ttag & GR1553B_BM_TTAG_VAL;
if ( time )
*time = priv->time | hwtime;
if ( priv->cfg.time_ovf_irq ) {
/* Detect wrap around */
hwtime2 = priv->regs->bm_ttag & GR1553B_BM_TTAG_VAL;
if ( hwtime > hwtime2 ) {
/* priv->time and hwtime may be out of sync if
* IRQ updated priv->time just after bm_ttag was read
* here, we resample if we detect inconsistancy.
*/
goto resample;
}
}
}
/* Number of entries available in DMA buffer */
int gr1553bm_available(void *bm, int *nentries)
{
struct gr1553bm_priv *priv = bm;
unsigned int top, bot, pos;
if ( !priv->started )
return -1;
/* Get BM posistion in log */
pos = priv->regs->bm_pos;
/* Convert into CPU accessible address */
pos = priv->buffer_base + (pos - priv->buffer_base_hw);
if ( pos >= priv->read_pos ) {
top = (pos - priv->read_pos)/sizeof(struct gr1553bm_entry);
bot = 0;
} else {
top = (priv->buffer_end - priv->read_pos)/sizeof(struct gr1553bm_entry);
bot = (pos - priv->buffer_base)/sizeof(struct gr1553bm_entry);
}
if ( nentries )
*nentries = top+bot;
return 0;
}
/* Read a maximum number of entries from LOG buffer. */
int gr1553bm_read(void *bm, struct gr1553bm_entry *dst, int *max)
{
struct gr1553bm_priv *priv = bm;
unsigned int dest, pos, left, newPos, len;
unsigned int topAdr, botAdr, topLen, botLen;
if ( !priv || !priv->started )
return -1;
left = *max;
pos = priv->regs->bm_pos & ~0x7;
/* Convert into CPU accessible address */
pos = priv->buffer_base + (pos - priv->buffer_base_hw);
if ( (pos == priv->read_pos) || (left < 1) ) {
/* No data available */
*max = 0;
return 0;
}
newPos = 0;
/* Addresses and lengths of BM log buffer */
if ( pos >= priv->read_pos ) {
/* Read Top only */
topAdr = priv->read_pos;
botAdr = 0;
topLen = (pos - priv->read_pos)/sizeof(struct gr1553bm_entry);
botLen = 0;
} else {
/* Read Top and Bottom */
topAdr = priv->read_pos;
botAdr = priv->buffer_base;
topLen = (priv->buffer_end - priv->read_pos)/sizeof(struct gr1553bm_entry);
botLen = (pos - priv->buffer_base)/sizeof(struct gr1553bm_entry);
}
dest = (unsigned int)dst;
if ( topLen > 0 ) {
/* Copy from top area first */
if ( topLen > left ) {
len = left;
left = 0;
} else {
len = topLen;
left -= topLen;
}
newPos = topAdr + (len * sizeof(struct gr1553bm_entry));
if ( newPos >= priv->buffer_end )
newPos -= priv->buffer_size;
if ( priv->cfg.copy_func ) {
dest += priv->cfg.copy_func(
dest, /*Optional Destination*/
(void *)topAdr, /* DMA start address */
len, /* Number of entries */
priv->cfg.copy_func_arg /* Custom ARG */
);
} else {
memcpy( (void *)dest,
(void *)topAdr,
len * sizeof(struct gr1553bm_entry));
dest += len * sizeof(struct gr1553bm_entry);
}
}
if ( (botLen > 0) && (left > 0) ) {
/* Copy bottom area last */
if ( botLen > left ) {
len = left;
left = 0;
} else {
len = botLen;
left -= botLen;
}
newPos = botAdr + (len * sizeof(struct gr1553bm_entry));
if ( priv->cfg.copy_func ) {
priv->cfg.copy_func(
dest, /*Optional Destination*/
(void *)botAdr, /* DMA start address */
len, /* Number of entries */
priv->cfg.copy_func_arg /* Custom ARG */
);
} else {
memcpy( (void *)dest,
(void *)botAdr,
len * sizeof(struct gr1553bm_entry));
}
}
/* Remember last read posistion in buffer */
/*printf("New pos: 0x%08x (0x%08x), %d\n", newPos, priv->read_pos, *max - left);*/
priv->read_pos = newPos;
/* Return number of entries read */
*max = *max - left;
return 0;
}
/* Note: This is a shared interrupt handler, with BC/RT driver
* we must determine the cause of IRQ before handling it.
*/
void gr1553bm_isr(void *data)
{
struct gr1553bm_priv *priv = data;
uint32_t irqflag;
/* Get Causes */
irqflag = priv->regs->irq & (GR1553B_IRQ_BMD | GR1553B_IRQ_BMTOF);
/* Check spurious IRQs */
if ( (irqflag == 0) || (priv->started == 0) )
return;
if ( (irqflag & GR1553B_IRQ_BMTOF) && priv->cfg.time_ovf_irq ) {
/* 1553 Time Over flow. Time is 24-bits */
priv->time += (GR1553B_BM_TTAG_VAL + 1);
/* Clear cause handled */
priv->regs->irq = GR1553B_IRQ_BMTOF;
}
if ( irqflag & GR1553B_IRQ_BMD ) {
/* BM DMA ERROR. Fatal error, we stop BM hardware and let
* user take care of it. From now on all calls will result
* in an error because the BM is stopped (priv->started=0).
*/
/* Clear cause handled */
priv->regs->irq = GR1553B_IRQ_BMD;
if ( priv->cfg.dma_error_isr )
priv->cfg.dma_error_isr(data, priv->cfg.dma_error_arg);
gr1553bm_hw_stop(priv);
}
}

File diff suppressed because it is too large Load Diff