summaryrefslogtreecommitdiffstats
path: root/c/src/lib/libbsp/sparc/shared/1553/b1553brm.c
diff options
context:
space:
mode:
authorDaniel Hellstrom <daniel@gaisler.com>2011-12-20 16:27:54 +0100
committerDaniel Hellstrom <daniel@gaisler.com>2015-04-17 01:10:17 +0200
commit3681925508c0da88fee6325ea35ead7b112856c6 (patch)
tree0886351bec0218ed4689c68e5442b75341cbc169 /c/src/lib/libbsp/sparc/shared/1553/b1553brm.c
parentLEON: updated and added PCI peripherals for LEON BSPs (diff)
downloadrtems-3681925508c0da88fee6325ea35ead7b112856c6.tar.bz2
LEON: updated shared drivers to Driver Manger framework
Some bugfixes at the same time. After this patch the drivers may be used on RASTA systems having a big-endian PCI layout. Removed not up to date changelogs, rely on git log instead.
Diffstat (limited to 'c/src/lib/libbsp/sparc/shared/1553/b1553brm.c')
-rw-r--r--c/src/lib/libbsp/sparc/shared/1553/b1553brm.c1975
1 files changed, 1068 insertions, 907 deletions
diff --git a/c/src/lib/libbsp/sparc/shared/1553/b1553brm.c b/c/src/lib/libbsp/sparc/shared/1553/b1553brm.c
index 045146a58b..19ad36ca5f 100644
--- a/c/src/lib/libbsp/sparc/shared/1553/b1553brm.c
+++ b/c/src/lib/libbsp/sparc/shared/1553/b1553brm.c
@@ -2,52 +2,19 @@
* BRM driver
*
* COPYRIGHT (c) 2006.
- * Gaisler Research.
+ * 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.
- *
*/
/********** Set defaults **********/
-/* basic bus/interface of device,
- * Default to direct accessed AMBA bus.
- */
-#ifndef B1553BRM_NO_AMBA
- #define B1553BRM_AMBA
- #undef B1553BRM_PCI
-#endif
-
-/* default name to /dev/brm */
-#if !defined(B1553BRM_DEVNAME) || !defined(B1553BRM_DEVNAME_NO)
- #undef B1553BRM_DEVNAME
- #undef B1553BRM_DEVNAME_NO
- #define B1553BRM_DEVNAME "/dev/brm0"
- #define B1553BRM_DEVNAME_NO(devstr,no) ((devstr)[8]='0'+(no))
-#endif
-
-#ifndef B1553BRM_PREFIX
- #define B1553BRM_PREFIX(name) b1553brm##name
-#else
- #define B1553BRM_REGISTER_STATIC
-#endif
-
-/* default to no translation */
-#ifndef B1553BRM_ADR_TO
- #define memarea_to_hw(x) ((unsigned int)(x))
-#endif
-
-#ifndef B1553BRM_REG_INT
- #define B1553BRM_REG_INT(handler,irqno,arg) set_vector(handler,(irqno)+0x10,1)
- #undef B1553BRM_DEFINE_INTHANDLER
- #define B1553BRM_DEFINE_INTHANDLER
-#endif
-
-/* default to 128K memory layout */
-#if !defined(DMA_MEM_16K)
- #define DMA_MEM_128K
+/* default to 16K memory layout */
+#define DMA_MEM_128K
+#if !defined(DMA_MEM_128K)
+ #define DMA_MEM_16K
#endif
#include <bsp.h>
@@ -59,8 +26,10 @@
#include <ctype.h>
#include <rtems/bspIo.h>
+#include <drvmgr/drvmgr.h>
#include <b1553brm.h>
#include <ambapp.h>
+#include <drvmgr/ambapp_bus.h>
/* Uncomment for debug output */
/*#define DEBUG 1
@@ -70,24 +39,24 @@
/* EVENT_QUEUE_SIZE sets the size of the event queue
*/
-#define EVENT_QUEUE_SIZE 1024
+#define EVENT_QUEUE_SIZE 1024
#define INDEX(x) ( x&(EVENT_QUEUE_SIZE-1) )
-#ifdef DEBUG
+#if 0
#define DBG(x...) printk(x)
#else
-#define DBG(x...)
+#define DBG(x...)
#endif
#ifdef FUNCDEBUG
#define FUNCDBG(x...) printk(x)
#else
-#define FUNCDBG(x...)
+#define FUNCDBG(x...)
#endif
-#define READ_REG(address) _BRM_REG_READ16((unsigned int)address)
+#define READ_REG(address) (*(volatile unsigned int *)address)
#define READ_DMA(address) _BRM_REG_READ16((unsigned int)address)
static __inline__ unsigned short _BRM_REG_READ16(unsigned int addr) {
unsigned short tmp;
@@ -107,7 +76,7 @@ static rtems_device_driver brm_control(rtems_device_major_number major, rtems_de
#define BRM_DRIVER_TABLE_ENTRY { brm_initialize, brm_open, brm_close, brm_read, brm_write, brm_control }
-static rtems_driver_address_table brm_driver = BRM_DRIVER_TABLE_ENTRY;
+static rtems_driver_address_table b1553brm_driver = BRM_DRIVER_TABLE_ENTRY;
struct msg {
unsigned short miw;
@@ -134,165 +103,464 @@ struct irq_log_list {
volatile unsigned short iaw;
};
-typedef struct {
-
- unsigned int memarea_base;
- struct brm_reg *regs;
-
- /* BRM descriptors */
- struct desc_table {
-
- volatile unsigned short ctrl;
- volatile unsigned short top;
- volatile unsigned short cur;
- volatile unsigned short bot;
-
- } *desc;
-
- volatile unsigned short *mem;
- /* bc mem struct */
+typedef struct {
+
+ struct drvmgr_dev *dev; /* Driver manager device */
+ char devName[32]; /* Device Name */
+ struct brm_reg *regs;
+
+ unsigned int memarea_base;
+ unsigned int memarea_base_remote;
+ unsigned int cfg_clksel;
+ unsigned int cfg_clkdiv;
+ unsigned int cfg_freq;
+
+ /* BRM descriptors */
+ struct desc_table {
+ volatile unsigned short ctrl;
+ volatile unsigned short top;
+ volatile unsigned short cur;
+ volatile unsigned short bot;
+ } *desc;
+
+ volatile unsigned short *mem;
+ /* bc mem struct */
+ struct {
+ /* BC Descriptors */
struct {
- /* BC Descriptors */
- struct {
- unsigned short ctrl; /* control */
- unsigned short cw1; /* Command word 1*/
- unsigned short cw2; /* Command word 1*/
- unsigned short dptr; /* Data pointer in halfword offset from bcmem */
- unsigned short tsw[2]; /* status word 1 & 2 */
- unsigned short ba; /* branch address */
- unsigned short timer; /* timer value */
- } descs[128]; /* 2k (1024 half words) */
-
- /* message data */
- struct {
- unsigned short data[32]; /* 1 message's data */
- } msg_data[128]; /* 8k */
+ unsigned short ctrl; /* control */
+ unsigned short cw1; /* Command word 1*/
+ unsigned short cw2; /* Command word 1*/
+ unsigned short dptr; /* Data pointer in halfword offset from bcmem */
+ unsigned short tsw[2]; /* status word 1 & 2 */
+ unsigned short ba; /* branch address */
+ unsigned short timer; /* timer value */
+ } descs[128]; /* 2k (1024 half words) */
+
+ /* message data */
+ struct {
+ unsigned short data[32]; /* 1 message's data */
+ } msg_data[128]; /* 8k */
#if defined(DMA_MEM_128K)
- /* offset to last 64bytes of 128k */
- unsigned short unused[(64*1024-(128*8+128*32))-16*2];
+ /* offset to last 64bytes of 128k */
+ unsigned short unused[(64*1024-(128*8+128*32))-16*2];
#elif defined(DMA_MEM_16K)
- unsigned short unused[(8*1024-(128*8+128*32))-16*2];
+ unsigned short unused[(8*1024-(128*8+128*32))-16*2];
#endif
- /* interrupt log at 64 bytes from end */
- struct irq_log_list irq_logs[16];
- } *bcmem;
+ /* interrupt log at 64 bytes from end */
+ struct irq_log_list irq_logs[16];
+ } *bcmem;
#if defined(DMA_MEM_128K)
- /* Memory structure of a RT being inited, just used
- * for RT initialization.
- *
- * *mesgs[32] fit each minimally 8 messages per sub address.
- */
- struct {
- /* RX Sub Address descriptors */
- struct desc_table rxsubs[32];
- /* TX Sub Address descriptors */
- struct desc_table txsubs[32];
- /* RX mode code descriptors */
- struct desc_table rxmodes[32];
- /* TX mode code descriptors */
- struct desc_table txmodes[32];
-
- /* RX Sub Address messages */
- struct circ_buf rxsuba_msgs[32];
- /* TX Sub Address messages */
- struct circ_buf txsuba_msgs[32];
- /* RX Mode Code messages */
- struct circ_buf rxmode_msgs[32];
- /* RX Mode Code messages */
- struct circ_buf txmode_msgs[32];
-
-
- /* offset to last 64bytes of 128k: tot-used-needed */
- unsigned short unused[(64*1024-(4*32*4+4*32*9*34))-16*2];
-
- /* interrupt log at 64 bytes from end */
- struct irq_log_list irq_logs[16];
- } *rtmem;
+ /* Memory structure of a RT being inited, just used
+ * for RT initialization.
+ *
+ * *mesgs[32] fit each minimally 8 messages per sub address.
+ */
+ struct {
+ /* RX Sub Address descriptors */
+ struct desc_table rxsubs[32];
+ /* TX Sub Address descriptors */
+ struct desc_table txsubs[32];
+ /* RX mode code descriptors */
+ struct desc_table rxmodes[32];
+ /* TX mode code descriptors */
+ struct desc_table txmodes[32];
+
+ /* RX Sub Address messages */
+ struct circ_buf rxsuba_msgs[32];
+ /* TX Sub Address messages */
+ struct circ_buf txsuba_msgs[32];
+ /* RX Mode Code messages */
+ struct circ_buf rxmode_msgs[32];
+ /* RX Mode Code messages */
+ struct circ_buf txmode_msgs[32];
+
+ /* offset to last 64bytes of 128k: tot-used-needed */
+ unsigned short unused[(64*1024-(4*32*4+4*32*9*34))-16*2];
+
+ /* interrupt log at 64 bytes from end */
+ struct irq_log_list irq_logs[16];
+ } *rtmem;
#elif defined(DMA_MEM_16K)
- /* Memory structure of a RT being inited, just used
- * for RT initialization.
- *
- * circ_buf_2 *mesgs[32] fit each minimally 2 messages per queue.
- * circ_buf_1 *mesgs[32] fit each minimally 1 messages per queue.
- */
- struct {
- /* RX Sub Address descriptors */
- struct desc_table rxsubs[32];
- /* TX Sub Address descriptors */
- struct desc_table txsubs[32];
- /* RX mode code descriptors */
- struct desc_table rxmodes[32];
- /* TX mode code descriptors */
- struct desc_table txmodes[32];
-
- /* RX Sub Address messages */
- struct circ_buf_2 rxsuba_msgs[32];
- /* TX Sub Address messages */
- struct circ_buf_2 txsuba_msgs[32];
- /* RX Mode Code messages */
- struct circ_buf_2 rxmode_msgs[32];
- /* RX Mode Code messages */
- struct circ_buf_1 txmode_msgs[32];
-
-
- /* offset to last 64bytes of 16k: tot-used-needed */
- unsigned short unused[8*1024 -(4*32*4 +3*32*2*34 +1*32*1*34) -16*2];
-
- /* interrupt log at 64 bytes from end */
- struct irq_log_list irq_logs[16];
- } *rtmem;
+ /* Memory structure of a RT being inited, just used
+ * for RT initialization.
+ *
+ * circ_buf_2 *mesgs[32] fit each minimally 2 messages per queue.
+ * circ_buf_1 *mesgs[32] fit each minimally 1 messages per queue.
+ */
+ struct {
+ /* RX Sub Address descriptors */
+ struct desc_table rxsubs[32];
+ /* TX Sub Address descriptors */
+ struct desc_table txsubs[32];
+ /* RX mode code descriptors */
+ struct desc_table rxmodes[32];
+ /* TX mode code descriptors */
+ struct desc_table txmodes[32];
+
+ /* RX Sub Address messages */
+ struct circ_buf_2 rxsuba_msgs[32];
+ /* TX Sub Address messages */
+ struct circ_buf_2 txsuba_msgs[32];
+ /* RX Mode Code messages */
+ struct circ_buf_2 rxmode_msgs[32];
+ /* RX Mode Code messages */
+ struct circ_buf_1 txmode_msgs[32];
+
+ /* offset to last 64bytes of 16k: tot-used-needed */
+ unsigned short unused[8*1024 -(4*32*4 +3*32*2*34 +1*32*1*34) -16*2];
+
+ /* interrupt log at 64 bytes from end */
+ struct irq_log_list irq_logs[16];
+ } *rtmem;
#else
#error You must define one DMA_MEM_???K
#endif
- /* Interrupt log list */
- struct irq_log_list *irq_log;
- unsigned int irq;
+ /* Interrupt log list */
+ struct irq_log_list *irq_log;
+ unsigned int irq;
- /* Received events waiting to be read */
- struct rt_msg *rt_event;
- struct bm_msg *bm_event;
+ /* Received events waiting to be read */
+ struct rt_msg *rt_event;
+ struct bm_msg *bm_event;
- unsigned int head, tail;
+ unsigned int head, tail;
- unsigned int last_read[128];
- unsigned int written[32];
+ unsigned int last_read[128];
+ unsigned int written[32];
- struct bc_msg *cur_list;
+ struct bc_msg *cur_list;
- int tx_blocking, rx_blocking;
+ int tx_blocking, rx_blocking;
- rtems_id rx_sem, tx_sem, dev_sem;
- int minor;
- int irqno;
- unsigned int mode;
-#ifdef DEBUG
- unsigned int log[EVENT_QUEUE_SIZE*4];
- unsigned int log_i;
+ rtems_id rx_sem, tx_sem, dev_sem;
+ int minor;
+ int irqno;
+ unsigned int mode;
+#ifdef DEBUG
+ unsigned int log[EVENT_QUEUE_SIZE*4];
+ unsigned int log_i;
#endif
- rtems_id event_id; /* event that may be signalled upon errors, needs to be set through ioctl command BRM_SET_EVENTID */
- unsigned int status;
- int bc_list_fail;
+ rtems_id event_id; /* event that may be signalled upon errors, needs to be set through ioctl command BRM_SET_EVENTID */
+ unsigned int status;
+ int bc_list_fail;
} brm_priv;
-static int brm_cores;
-static unsigned int allbrm_memarea;
-static brm_priv *brms;
-static struct ambapp_bus *amba_bus;
-static unsigned int allbrm_cfg_clksel;
-static unsigned int allbrm_cfg_clkdiv;
-static unsigned int allbrm_cfg_freq;
-
-static void brm_interrupt(brm_priv *brm);
-#ifdef B1553BRM_DEFINE_INTHANDLER
-static void b1553brm_interrupt_handler(rtems_vector_number v);
-#endif
+static void b1553brm_interrupt(void *arg);
+static rtems_device_driver rt_init(brm_priv *brm);
#define OFS(ofs) (((unsigned int)&ofs & 0x1ffff)>>1)
+static int b1553brm_driver_io_registered = 0;
+static rtems_device_major_number b1553brm_driver_io_major = 0;
+
+/******************* Driver manager interface ***********************/
+
+/* Driver prototypes */
+int b1553brm_register_io(rtems_device_major_number *m);
+int b1553brm_device_init(brm_priv *pDev);
+
+int b1553brm_init2(struct drvmgr_dev *dev);
+int b1553brm_init3(struct drvmgr_dev *dev);
+int b1553brm_remove(struct drvmgr_dev *dev);
+
+struct drvmgr_drv_ops b1553brm_ops =
+{
+ .init = {NULL, b1553brm_init2, b1553brm_init3, NULL},
+ .remove = b1553brm_remove,
+ .info = NULL
+};
+
+struct amba_dev_id b1553brm_ids[] =
+{
+ {VENDOR_GAISLER, GAISLER_B1553BRM},
+ {0, 0} /* Mark end of table */
+};
+
+struct amba_drv_info b1553brm_drv_info =
+{
+ {
+ DRVMGR_OBJ_DRV, /* Driver */
+ NULL, /* Next driver */
+ NULL, /* Device list */
+ DRIVER_AMBAPP_GAISLER_B1553BRM_ID, /* Driver ID */
+ "B1553BRM_DRV", /* Driver Name */
+ DRVMGR_BUS_TYPE_AMBAPP, /* Bus Type */
+ &b1553brm_ops,
+ NULL, /* Funcs */
+ 0, /* No devices yet */
+ 0,
+ },
+ &b1553brm_ids[0]
+};
+
+void b1553brm_register_drv (void)
+{
+ DBG("Registering B1553BRM driver\n");
+ drvmgr_drv_register(&b1553brm_drv_info.general);
+}
+
+int b1553brm_init2(struct drvmgr_dev *dev)
+{
+ brm_priv *priv;
+
+ DBG("B1553BRM[%d] on bus %s\n", dev->minor_drv, dev->parent->dev->name);
+ priv = dev->priv = malloc(sizeof(brm_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 b1553brm_init3(struct drvmgr_dev *dev)
+{
+ brm_priv *priv;
+ char prefix[32];
+ rtems_status_code status;
+
+ priv = dev->priv;
+
+ /* Do initialization */
+
+ if ( b1553brm_driver_io_registered == 0) {
+ /* Register the I/O driver only once for all cores */
+ if ( b1553brm_register_io(&b1553brm_driver_io_major) ) {
+ /* Failed to register I/O driver */
+ dev->priv = NULL;
+ return DRVMGR_FAIL;
+ }
+
+ b1553brm_driver_io_registered = 1;
+ }
+
+ /* I/O system registered and initialized
+ * Now we take care of device initialization.
+ */
+
+ if ( b1553brm_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/b1553brm%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/%sb1553brm%d", prefix, dev->minor_bus);
+ }
+
+ /* Register Device */
+ status = rtems_io_register_name(priv->devName, b1553brm_driver_io_major, dev->minor_drv);
+ if (status != RTEMS_SUCCESSFUL) {
+ return DRVMGR_FAIL;
+ }
+
+ return DRVMGR_OK;
+}
+
+int b1553brm_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_OK;
+}
+
+/******************* Driver Implementation ***********************/
+
+int b1553brm_register_io(rtems_device_major_number *m)
+{
+ rtems_status_code r;
+
+ if ((r = rtems_io_register_driver(0, &b1553brm_driver, m)) == RTEMS_SUCCESSFUL) {
+ DBG("B1553BRM driver successfully registered, major: %d\n", *m);
+ } else {
+ switch(r) {
+ case RTEMS_TOO_MANY:
+ printk("B1553BRM rtems_io_register_driver failed: RTEMS_TOO_MANY\n");
+ return -1;
+ case RTEMS_INVALID_NUMBER:
+ printk("B1553BRM rtems_io_register_driver failed: RTEMS_INVALID_NUMBER\n");
+ return -1;
+ case RTEMS_RESOURCE_IN_USE:
+ printk("B1553BRM rtems_io_register_driver failed: RTEMS_RESOURCE_IN_USE\n");
+ return -1;
+ default:
+ printk("B1553BRM rtems_io_register_driver failed\n");
+ return -1;
+ }
+ }
+ return 0;
+}
+
+int b1553brm_device_init(brm_priv *pDev)
+{
+ struct amba_dev_info *ambadev;
+ struct ambapp_core *pnpinfo;
+ union drvmgr_key_value *value;
+ unsigned int mem;
+ int size;
+
+ /* 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;
+ /* Two versions of the BRM core. One where the registers are accessed using the AHB bus
+ * and one where the APB bus is used
+ */
+ if ( pnpinfo->ahb_slv ) {
+ /* Registers accessed over AHB */
+ pDev->regs = (struct brm_reg *)pnpinfo->ahb_slv->start[0];
+ } else {
+ /* Registers accessed over APB */
+ pDev->regs = (struct brm_reg *)pnpinfo->apb_slv->start;
+ }
+ pDev->minor = pDev->dev->minor_drv;
+#ifdef DEBUG
+ pDev->log_i = 0;
+ memset(pDev->log,0,sizeof(pDev->log));
+#endif
+
+#ifdef DMA_MEM_128K
+ size = 128 * 1024;
+#else
+ size = 16 * 1024;
+#endif
+
+ /* Get memory configuration from bus resources */
+ value = drvmgr_dev_key_get(pDev->dev, "dmaBaseAdr", KEY_TYPE_POINTER);
+ if (value)
+ mem = (unsigned int)value->ptr;
+
+ if (value && (mem & 1)) {
+ /* Remote address, address as BRM looks at it. */
+
+ /* Translate the base address into an address that the the CPU can understand */
+ pDev->memarea_base_remote = mem & ~1;
+ drvmgr_translate_check(pDev->dev, DMAMEM_TO_CPU,
+ (void *)pDev->memarea_base_remote,
+ (void **)&pDev->memarea_base,
+ size);
+ } else {
+ if (!value) {
+ /* Use dynamically allocated memory + 128k for
+ * alignment
+ */
+ mem = (unsigned int)malloc(size + 128 * 1024);
+ if (!mem){
+ printk("BRM: Failed to allocate HW memory\n\r");
+ return -1;
+ }
+ /* align memory to 128k boundary */
+ pDev->memarea_base = (mem + 0x1ffff) & ~0x1ffff;
+ } else {
+ pDev->memarea_base = mem;
+ }
+
+ /* Translate the base address into an address that the BRM core can understand */
+ drvmgr_translate_check(pDev->dev, CPUMEM_TO_DMA,
+ (void *)pDev->memarea_base,
+ (void **)&pDev->memarea_base_remote,
+ size);
+ }
+
+ /* clear the used memory */
+ memset((char *)pDev->memarea_base, 0, size);
+
+ /* Set base address of all descriptors */
+ pDev->desc = (struct desc_table *) pDev->memarea_base;
+ pDev->mem = (volatile unsigned short *) pDev->memarea_base;
+ pDev->irq_log = (struct irq_log_list *)(pDev->memarea_base + (0xFFE0<<1)); /* last 64byte */
+
+ pDev->bm_event = NULL;
+ pDev->rt_event = NULL;
+
+ pDev->cfg_clksel = 0;
+ pDev->cfg_clkdiv = 0;
+ pDev->cfg_freq = BRM_FREQ_24MHZ;
+
+ value = drvmgr_dev_key_get(pDev->dev, "clkSel", KEY_TYPE_INT);
+ if ( value ) {
+ pDev->cfg_clksel = value->i & CLKSEL_MASK;
+ }
+
+ value = drvmgr_dev_key_get(pDev->dev, "clkDiv", KEY_TYPE_INT);
+ if ( value ) {
+ pDev->cfg_clkdiv = value->i & CLKDIV_MASK;
+ }
+
+ value = drvmgr_dev_key_get(pDev->dev, "coreFreq", KEY_TYPE_INT);
+ if ( value ) {
+ pDev->cfg_freq = value->i & BRM_FREQ_MASK;
+ }
+
+ /* Sel clock so that we can write to BRM's registers */
+ pDev->regs->w_ctrl = (pDev->cfg_clksel<<9) | (pDev->cfg_clkdiv<<5);
+ /* Reset BRM core */
+ pDev->regs->w_ctrl = 1<<10 | READ_REG(&pDev->regs->w_ctrl);
+
+ /* RX Semaphore created with count = 0 */
+ if ( rtems_semaphore_create(rtems_build_name('B', 'M', 'R', '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("BRM: Failed to create rx semaphore\n");
+ return RTEMS_INTERNAL_ERROR;
+ }
+
+ /* TX Semaphore created with count = 1 */
+ if ( rtems_semaphore_create(rtems_build_name('B', 'M', 'T', '0' + pDev->minor),
+ 1,
+ RTEMS_FIFO|RTEMS_SIMPLE_BINARY_SEMAPHORE|RTEMS_NO_INHERIT_PRIORITY|RTEMS_LOCAL|RTEMS_NO_PRIORITY_CEILING,
+ 0,
+ &pDev->tx_sem) != RTEMS_SUCCESSFUL ){
+ printk("BRM: Failed to create tx semaphore\n");
+ return RTEMS_INTERNAL_ERROR;
+ }
+
+ /* Device Semaphore created with count = 1 */
+ if ( rtems_semaphore_create(rtems_build_name('B', 'M', 'D', '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("BRM: 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;
@@ -300,12 +568,11 @@ static int odd_parity(unsigned int data) {
{
i++;
data &= (data - 1);
- }
+ }
return !(i&1);
}
-
static void start_operation(brm_priv *brm) {
unsigned int ctrl = READ_REG(&brm->regs->ctrl);
brm->regs->ctrl = ctrl | 0x8000;
@@ -315,80 +582,12 @@ static void stop_operation(brm_priv *brm) {
unsigned int ctrl = READ_REG(&brm->regs->ctrl);
brm->regs->ctrl = ctrl & ~0x8000;
}
+
static int is_executing(brm_priv *brm) {
unsigned int ctrl = READ_REG(&brm->regs->ctrl);
return ((ctrl>>15) & 1);
}
-#ifdef LEON3
-#ifndef DONT_DEF_RAMON
-int brm_register_leon3_ramon_fpga(void){
- /* Clock div & Clock sel is NOT available.
- * The BRM is always clocked with 24MHz.
- * 3 in BRM enhanced register will select 24MHz
- */
- return b1553brm_register(&ambapp_plb, 0, 0, 3);
-}
-
-int brm_register_leon3_ramon_asic(void){
- /* Clock div & Clock sel is available.
- * Clkdiv only matter when clksel is 1.
- * clksel=2, clkdiv=don't care, brm_frq=24MHz
- *
- * 3 in BRM enhanced register will select 24MHz
- */
- return b1553brm_register(&ambapp_plb, 2, 0, 3);
-}
-#endif
-#endif
-
-#ifdef B1553BRM_REGISTER_STATIC
-static
-#endif
-int B1553BRM_PREFIX(_register)(struct ambapp_bus *bus, unsigned int clksel, unsigned int clkdiv, unsigned int brm_freq)
-{
- rtems_status_code r;
- rtems_device_major_number m;
-
- FUNCDBG("brm_register:\n\r");
-
- /* save amba bus pointer */
- amba_bus = bus;
- if ( !bus ){
- printk("brm_register: bus is NULL\n\r");
- return 1;
- }
-
-#ifdef B1553BRM_LOCAL_MEM
- allbrm_memarea = B1553BRM_LOCAL_MEM_ADR;
-#else
- allbrm_memarea = 0;
-#endif
-
- /* Save clksel, clkdiv and brm_freq for later use */
- allbrm_cfg_clksel = clksel & CLKSEL_MASK;
- allbrm_cfg_clkdiv = clkdiv & CLKDIV_MASK;
- allbrm_cfg_freq = brm_freq & BRM_FREQ_MASK;
-
- if ((r = rtems_io_register_driver(0, &brm_driver, &m)) == RTEMS_SUCCESSFUL) {
- DBG("BRM: driver successfully registered, major: %d\n",m);
-
- } else {
- switch(r) {
- case RTEMS_TOO_MANY:
- printk("BRM rtems_io_register_driver failed: RTEMS_TOO_MANY\n"); break;
- case RTEMS_INVALID_NUMBER:
- printk("BRM rtems_io_register_driver failed: RTEMS_INVALID_NUMBER\n"); break;
- case RTEMS_RESOURCE_IN_USE:
- printk("BRM rtems_io_register_driver failed: RTEMS_RESOURCE_IN_USE\n"); break;
- default:
- printk("BRM rtems_io_register_driver failed\n");
- }
- return 1;
- }
- return 0;
-}
-
static void clr_int_logs(struct irq_log_list *logs){
int i;
for(i=0; i<16; i++){
@@ -403,18 +602,18 @@ static rtems_device_driver rt_init(brm_priv *brm) {
brm->head = brm->tail = 0;
brm->rx_blocking = brm->tx_blocking = 1;
- if ( brm->bm_event )
+ if ( brm->bm_event )
free(brm->bm_event);
brm->bm_event = NULL;
- if ( brm->rt_event )
+ if ( brm->rt_event )
free(brm->rt_event);
-
+
brm->bcmem = NULL;
brm->rtmem = (void *)brm->mem;
brm->rt_event = (struct rt_msg *) malloc(EVENT_QUEUE_SIZE*sizeof(struct rt_msg));
-
+
if (brm->rt_event == NULL) {
DBG("BRM driver failed to allocated memory.");
return RTEMS_NO_MEMORY;
@@ -427,11 +626,11 @@ static rtems_device_driver rt_init(brm_priv *brm) {
brm->regs->imask = BRM_RT_ILLCMD_IRQ|BRM_SUBAD_IRQ|BRM_TAPF_IRQ|BRM_DMAF_IRQ|BRM_WRAPF_IRQ|BRM_MERR_IRQ;
brm->regs->dpoint = 0;
brm->regs->ipoint = OFS(brm->rtmem->irq_logs[0]);
- brm->regs->enhanced = 0x0000 | allbrm_cfg_freq; /* BRM clocked with freq = 12,16,20 or 24MHz */
- brm->regs->w_ctrl = (allbrm_cfg_clksel<<9) | (allbrm_cfg_clkdiv<<5) | 1;
+ brm->regs->enhanced = 0x0000 | brm->cfg_freq; /* BRM clocked with freq = 12,16,20 or 24MHz */
+ brm->regs->w_ctrl = (brm->cfg_clksel<<9) | (brm->cfg_clkdiv<<5) | 1;
brm->regs->w_irqctrl = 6;
- brm->regs->w_ahbaddr = (unsigned int) memarea_to_hw(brm->memarea_base);
-
+ brm->regs->w_ahbaddr = brm->memarea_base_remote;
+
clr_int_logs(brm->irq_log);
/* Legalize all commands */
@@ -439,19 +638,19 @@ static rtems_device_driver rt_init(brm_priv *brm) {
brm->regs->rt_cmd_leg[i] = 0;
}
- /* Init descriptor table
- *
+ /* Init descriptor table
+ *
* Each circular buffer has room for 8 messages with up to 34 (32 data + miw + time) words (16b) in each.
* The buffers must separated by 34 words.
*/
-
+
/* RX Sub-address 0 - 31 */
for (i = 0; i < 32; i++) {
brm->rtmem->rxsubs[i].ctrl = 0x00E0; /* Interrupt: INTX, IWA, and IBRD */
brm->rtmem->rxsubs[i].top = OFS(brm->rtmem->rxsuba_msgs[i]); /* Top address */
brm->rtmem->rxsubs[i].cur = OFS(brm->rtmem->rxsuba_msgs[i]); /* Current address */
- brm->rtmem->rxsubs[i].bot = OFS(brm->rtmem->rxsuba_msgs[i+1]) - sizeof(struct msg)/2; /* Bottom address */
+ brm->rtmem->rxsubs[i].bot = OFS(brm->rtmem->rxsuba_msgs[i+1]) - sizeof(struct msg)/2; /* Bottom address */
brm->last_read[i] = OFS(brm->rtmem->rxsuba_msgs[i]);
}
/* TX Sub-address 0 - 31 */
@@ -470,7 +669,7 @@ static rtems_device_driver rt_init(brm_priv *brm) {
brm->rtmem->rxmodes[i].cur = OFS(brm->rtmem->rxmode_msgs[i]); /* Current address */
brm->rtmem->rxmodes[i].bot = OFS(brm->rtmem->rxmode_msgs[i+1]) - sizeof(struct msg)/2; /* Bottom address */
brm->last_read[i+64] = OFS(brm->rtmem->rxmode_msgs[i]);
- }
+ }
/* TX mode code 0 - 31 */
for (i = 0; i < 32; i++) {
brm->rtmem->txmodes[i].ctrl = 0x0060; /* Interrupt: IWA and IBRD */
@@ -480,6 +679,12 @@ static rtems_device_driver rt_init(brm_priv *brm) {
brm->last_read[i+96] = OFS(brm->rtmem->txmode_msgs[i]);
}
+#ifdef DEBUG
+ printk("b1553BRM DMA_AREA: 0x%x\n", (unsigned int)brm->rtmem);
+ printk("LOG: 0x%x\n", &brm->log[0]);
+ printk("LOG_I: 0x%x\n", &brm->log_i);
+#endif
+
brm->mode = BRM_MODE_RT;
return RTEMS_SUCCESSFUL;
@@ -487,36 +692,35 @@ static rtems_device_driver rt_init(brm_priv *brm) {
static rtems_device_driver bc_init(brm_priv *brm){
- if ( brm->bm_event )
+ if ( brm->bm_event )
free(brm->bm_event);
brm->bm_event = NULL;
- if ( brm->rt_event )
+ if ( brm->rt_event )
free(brm->rt_event);
brm->rt_event = NULL;
-
+
brm->bcmem = (void *)brm->mem;
brm->rtmem = NULL;
brm->irq_log = (struct irq_log_list *)&brm->bcmem->irq_logs[0];
-
+
brm->head = brm->tail = 0;
brm->rx_blocking = brm->tx_blocking = 1;
-
+
brm->regs->ctrl = 0x0006; /* ping pong enable and enable interrupt log */
brm->regs->oper = 0x0800; /* configure as BC */
brm->regs->imask = BRM_EOL_IRQ|BRM_BC_ILLCMD_IRQ|BRM_ILLOP_IRQ|BRM_DMAF_IRQ|BRM_WRAPF_IRQ|BRM_MERR_IRQ;
brm->regs->dpoint = 0;
- printk("Set BC interrupt log: 0x%lx, 0x%lx, 0x%lx\n",OFS(brm->bcmem->irq_logs[0]),&brm->bcmem->irq_logs[0],brm->bcmem);
brm->regs->ipoint = OFS(brm->bcmem->irq_logs[0]);
- brm->regs->enhanced = 0x0000 | (allbrm_cfg_freq&0x3); /* freq = 24 */
- brm->regs->w_ctrl = (allbrm_cfg_clksel<<9) | (allbrm_cfg_clkdiv<<5) | 1;
+ brm->regs->enhanced = 0x0000 | (brm->cfg_freq&BRM_FREQ_MASK); /* freq = 24 */
+ brm->regs->w_ctrl = (brm->cfg_clksel<<9) | (brm->cfg_clkdiv<<5) | 1;
brm->regs->w_irqctrl = 6;
- brm->regs->w_ahbaddr = (unsigned int) memarea_to_hw(brm->memarea_base);
-
+ brm->regs->w_ahbaddr = brm->memarea_base_remote;
+
clr_int_logs(brm->irq_log);
-
+
brm->mode = BRM_MODE_BC;
-
+
return RTEMS_SUCCESSFUL;
}
@@ -526,18 +730,18 @@ static rtems_device_driver bm_init(brm_priv *brm) {
brm->head = brm->tail = 0;
brm->rx_blocking = brm->tx_blocking = 1;
- if ( brm->rt_event )
+ if ( brm->rt_event )
free(brm->rt_event);
brm->rt_event = NULL;
- if ( brm->bm_event )
+ if ( brm->bm_event )
free(brm->bm_event);
-
+
brm->bcmem = NULL;
brm->rtmem = NULL;
-
+
brm->bm_event = (struct bm_msg *) malloc(EVENT_QUEUE_SIZE*sizeof(struct bm_msg));
-
+
if (brm->bm_event == NULL) {
DBG("BRM driver failed to allocated memory.");
return RTEMS_NO_MEMORY;
@@ -548,761 +752,634 @@ static rtems_device_driver bm_init(brm_priv *brm) {
brm->regs->ctrl = 0x0006; /* ping pong enable and enable interrupt log */
brm->regs->oper = 0x0A00; /* configure as BM */
- brm->regs->imask = BRM_MBC_IRQ|BRM_MERR_IRQ|BRM_DMAF_IRQ|BRM_MERR_IRQ;
+ brm->regs->imask = BRM_MBC_IRQ|BRM_MERR_IRQ|BRM_DMAF_IRQ;
brm->regs->dpoint = 0;
brm->regs->ipoint = OFS(brm->mem[8*1024-16*2]);
brm->regs->mcpoint = 0; /* Command pointer */
brm->regs->mdpoint = 0x100; /* Data pointer */
brm->regs->mbc = 1; /* Block count */
- brm->regs->enhanced = 0x0000 | (allbrm_cfg_freq&0x3); /* freq = 24 */
- brm->regs->w_ctrl = (allbrm_cfg_clksel<<9) | (allbrm_cfg_clkdiv<<5) | 1;
+ brm->regs->enhanced = 0x0000 | (brm->cfg_freq&BRM_FREQ_MASK); /* freq = 24 */
+ brm->regs->w_ctrl = (brm->cfg_clksel<<9) | (brm->cfg_clkdiv<<5) | 1;
brm->regs->w_irqctrl = 6;
- brm->regs->w_ahbaddr = (unsigned int) memarea_to_hw(brm->memarea_base);
-
+ brm->regs->w_ahbaddr = brm->memarea_base_remote;
+
clr_int_logs(brm->irq_log);
-
+
brm->mode = BRM_MODE_BM;
-
+
return RTEMS_SUCCESSFUL;
}
static rtems_device_driver brm_initialize(rtems_device_major_number major, rtems_device_minor_number minor, void *arg)
{
- rtems_status_code status;
- int dev_cnt;
- char fs_name[20];
- brm_priv *brm;
- struct ambapp_ahb_info ambadev;
- char *mem;
-
- FUNCDBG("brm_initialize\n");
+ return RTEMS_SUCCESSFUL;
+}
- brm_cores = 0;
- strcpy(fs_name,B1553BRM_DEVNAME);
+static rtems_device_driver brm_open(rtems_device_major_number major, rtems_device_minor_number minor, void *arg) {
+ brm_priv *brm;
+ struct drvmgr_dev *dev;
- /* Find all BRM devices */
- dev_cnt = ambapp_get_number_ahbslv_devices(amba_bus, VENDOR_GAISLER, GAISLER_B1553BRM);
- if ( dev_cnt < 1 ){
- /* Failed to find any CAN cores! */
- printk("BRM: Failed to find any BRM cores\n\r");
- return -1;
- }
+ FUNCDBG("brm_open\n");
- /* allocate & zero memory for the brm devices */
- brms = (brm_priv *)malloc(sizeof(*brms)*dev_cnt);
- if ( !brms ){
- printk("BRM: Failed to allocate SW memory\n\r");
- return -1;
+ if ( drvmgr_get_dev(&b1553brm_drv_info.general, minor, &dev) ) {
+ DBG("Wrong minor %d\n", minor);
+ return RTEMS_UNSATISFIED;
}
- memset(brms,0,sizeof(*brms)*dev_cnt);
-
- /* Allocate memory for all device's descriptors,
- * they must be aligned to a XXX byte boundary.
- */
- #define BRM_DESCS_PER_CTRL 128
- if ( allbrm_memarea ){
- mem = (char *)allbrm_memarea;
- }else{
- /* sizeof(struct desc_table) * BRM_DESCS_PER_CTRL * dev_cnt */
- mem = (char *)malloc( (128*1024) * (dev_cnt+1)); /* 128k per core + 128k for alignment */
- if ( !mem ){
- free(brms);
- printk("BRM: Failed to allocate HW memory\n\r");
- return -1;
- }
+ brm = (brm_priv *)dev->priv;
- /* align memory to 128k boundary */
- mem = (char *)(((unsigned int)mem+0x1ffff) & ~0x1ffff);
+ if (rtems_semaphore_obtain(brm->dev_sem, RTEMS_NO_WAIT, RTEMS_NO_TIMEOUT) != RTEMS_SUCCESSFUL) {
+ DBG("brm_open: resource in use\n");
+ return RTEMS_RESOURCE_IN_USE; /* EBUSY */
}
- /* clear the used memory */
- memset(mem,0,(128*1024) * dev_cnt);
-
- /* initialize each brm device, one at a time */
- for(minor=0; minor<dev_cnt; minor++){
- brm = &brms[minor];
-
- /* Get AMBA AHB device info from Plug&Play */
- ambapp_find_ahbslv_next(amba_bus, VENDOR_GAISLER,
- GAISLER_B1553BRM, &ambadev, minor);
+ /* Set defaults */
+ brm->event_id = 0;
- /* Copy Basic HW info */
- brm->regs = (void *)ambadev.start[0];
- brm->irqno = ambadev.irq;
- brm->minor = minor;
- brm->irq = 0;
-#ifdef DEBUG
- brm->log_i = 0;
- memset(brm->log,0,sizeof(brm->log));
-#endif
+ start_operation(brm);
- /* Set unique name */
- B1553BRM_DEVNAME_NO(fs_name,minor);
-
- DBG("Registering BRM core at [0x%x] irq %d, minor %d as %s\n",brm->regs,brm->irqno,minor,fs_name);
-
- /* Bind filesystem name to device number (minor) */
- status = rtems_io_register_name(fs_name, major, minor);
- if (status != RTEMS_SUCCESSFUL)
- rtems_fatal_error_occurred(status);
-
- /* RX Semaphore created with count = 0 */
- if ( rtems_semaphore_create(rtems_build_name('B', 'M', 'R', '0'+minor),
- 0,
- RTEMS_FIFO|RTEMS_SIMPLE_BINARY_SEMAPHORE|RTEMS_NO_INHERIT_PRIORITY|RTEMS_LOCAL|RTEMS_NO_PRIORITY_CEILING,
- 0,
- &brm->rx_sem) != RTEMS_SUCCESSFUL ){
- printk("BRM: Failed to create rx semaphore\n");
- return RTEMS_INTERNAL_ERROR;
- }
-
- /* TX Semaphore created with count = 1 */
- if ( rtems_semaphore_create(rtems_build_name('B', 'M', 'T', '0'+minor),
- 1,
- RTEMS_FIFO|RTEMS_SIMPLE_BINARY_SEMAPHORE|RTEMS_NO_INHERIT_PRIORITY|RTEMS_LOCAL|RTEMS_NO_PRIORITY_CEILING,
- 0,
- &brm->tx_sem) != RTEMS_SUCCESSFUL ){
- printk("BRM: Failed to create tx semaphore\n");
- return RTEMS_INTERNAL_ERROR;
- }
-
- /* Device Semaphore created with count = 1 */
- if ( rtems_semaphore_create(rtems_build_name('B', 'M', 'D', '0'+minor),
- 1,
- RTEMS_FIFO|RTEMS_SIMPLE_BINARY_SEMAPHORE|RTEMS_NO_INHERIT_PRIORITY|RTEMS_LOCAL|RTEMS_NO_PRIORITY_CEILING,
- 0,
- &brm->dev_sem) != RTEMS_SUCCESSFUL ){
- printk("BRM: Failed to create device semaphore\n");
- return RTEMS_INTERNAL_ERROR;
- }
-
-
- /* Set base address of all descriptors */
- brm->memarea_base = (unsigned int)&mem[(128*1024) * minor];
- brm->desc = (struct desc_table *) brm->memarea_base;
- brm->mem = (volatile unsigned short *) brm->memarea_base;
- brm->irq_log = (struct irq_log_list *)(brm->memarea_base + (0xFFE0<<1)); /* last 64byte */
-
- brm->bm_event = NULL;
- brm->rt_event = NULL;
-
- /* Sel clock so that we can write to BRM's registers */
- brm->regs->w_ctrl = (allbrm_cfg_clksel<<9) | (allbrm_cfg_clkdiv<<5);
- /* Reset BRM core */
- brm->regs->w_ctrl = 1<<10 | READ_REG(&brm->regs->w_ctrl);
-
- /* Register interrupt handler */
- B1553BRM_REG_INT(B1553BRM_PREFIX(_interrupt_handler), brm->irqno, brm);
-
- rt_init(brm);
-
- DBG("BRM: LOG: 0x%lx, 0x%lx\n\r",brm->log,brm);
+ /* Register interrupt routine */
+ if ( drvmgr_interrupt_register(brm->dev, 0, "b1553brm", b1553brm_interrupt, brm) ) {
+ rtems_semaphore_release(brm->dev_sem);
+ return RTEMS_UNSATISFIED;
}
- /* save number of BRM cores found */
- brm_cores = dev_cnt;
-
- DBG("BRM initialisation done.\n");
-
return RTEMS_SUCCESSFUL;
}
-
-static rtems_device_driver brm_open(rtems_device_major_number major, rtems_device_minor_number minor, void *arg) {
- brm_priv *brm;
-
- FUNCDBG("brm_open\n");
-
- if (minor >= brm_cores) {
- DBG("Wrong minor %d\n", minor);
- return RTEMS_UNSATISFIED; /* ENODEV */
- }
-
- brm = &brms[minor];
-
- if (rtems_semaphore_obtain(brm->dev_sem, RTEMS_NO_WAIT, RTEMS_NO_TIMEOUT) != RTEMS_SUCCESSFUL) {
- DBG("brm_open: resource in use\n");
- return RTEMS_RESOURCE_IN_USE; /* EBUSY */
- }
-
- /* Set defaults */
- brm->event_id = 0;
-
- start_operation(brm);
-
- return RTEMS_SUCCESSFUL;
-}
-
+
static rtems_device_driver brm_close(rtems_device_major_number major, rtems_device_minor_number minor, void *arg)
{
- brm_priv *brm = &brms[minor];
+ brm_priv *brm;
+ struct drvmgr_dev *dev;
+
FUNCDBG("brm_close");
+
+ if ( drvmgr_get_dev(&b1553brm_drv_info.general, minor, &dev) ) {
+ return RTEMS_UNSATISFIED;
+ }
+ brm = (brm_priv *)dev->priv;
+
+ drvmgr_interrupt_unregister(brm->dev, 0, b1553brm_interrupt, brm);
stop_operation(brm);
rtems_semaphore_release(brm->dev_sem);
return RTEMS_SUCCESSFUL;
}
+
+static int get_rt_messages(brm_priv *brm, void *buf, unsigned int msg_count)
+{
+ struct rt_msg *dest = (struct rt_msg *) buf;
+ int count = 0;
-static int get_rt_messages(brm_priv *brm, void *buf, unsigned int msg_count) {
-
- struct rt_msg *dest = (struct rt_msg *) buf;
- int count = 0;
-
- if (brm->head == brm->tail) {
- return 0;
- }
-
- do {
-
- DBG("rt read - head: %d, tail: %d\n", brm->head, brm->tail);
- dest[count++] = brm->rt_event[INDEX(brm->tail++)];
+ if (brm->head == brm->tail) {
+ return 0;
+ }
- } while (brm->head != brm->tail && count < msg_count);
+ do {
- return count;
+ DBG("rt read - head: %d, tail: %d\n", brm->head, brm->tail);
+ dest[count++] = brm->rt_event[INDEX(brm->tail++)];
+ } while (brm->head != brm->tail && count < msg_count);
+ return count;
}
-static int get_bm_messages(brm_priv *brm, void *buf, unsigned int msg_count) {
-
- struct bm_msg *dest = (struct bm_msg *) buf;
- int count = 0;
-
- if (brm->head == brm->tail) {
- return 0;
- }
+static int get_bm_messages(brm_priv *brm, void *buf, unsigned int msg_count)
+{
+ struct bm_msg *dest = (struct bm_msg *) buf;
+ int count = 0;
- do {
+ if (brm->head == brm->tail) {
+ return 0;
+ }
- DBG("bm read - head: %d, tail: %d\n", brm->head, brm->tail);
- dest[count++] = brm->bm_event[INDEX(brm->tail++)];
+ do {
- } while (brm->head != brm->tail && count < msg_count);
+ DBG("bm read - head: %d, tail: %d\n", brm->head, brm->tail);
+ dest[count++] = brm->bm_event[INDEX(brm->tail++)];
- return count;
+ } while (brm->head != brm->tail && count < msg_count);
+ return count;
}
static rtems_device_driver brm_read(rtems_device_major_number major, rtems_device_minor_number minor, void *arg)
{
- rtems_libio_rw_args_t *rw_args;
- int count = 0;
- brm_priv *brm = &brms[minor];
- int (*get_messages)(brm_priv *brm, void *buf, unsigned int count);
-
- if ( ! (brm->mode & (BRM_MODE_RT | BRM_MODE_BM)) ){
- return RTEMS_INVALID_NAME;
- }
-
- rw_args = (rtems_libio_rw_args_t *) arg;
-
- if ( ((READ_REG(&brm->regs->oper)>>8) & 3) == 1 ) { /* RT */
- get_messages = get_rt_messages;
- }
- else { /* BM */
- get_messages = get_bm_messages;
- }
+ rtems_libio_rw_args_t *rw_args;
+ int count = 0;
+ brm_priv *brm;
+ struct drvmgr_dev *dev;
+ int (*get_messages)(brm_priv *brm, void *buf, unsigned int count);
+ if ( drvmgr_get_dev(&b1553brm_drv_info.general, minor, &dev) ) {
+ return RTEMS_UNSATISFIED;
+ }
+ brm = (brm_priv *)dev->priv;
- FUNCDBG("brm_read [%i,%i]: buf: 0x%x len: %i\n",major, minor, (unsigned int)rw_args->buffer,rw_args->count);
+ if ( ! (brm->mode & (BRM_MODE_RT | BRM_MODE_BM)) ){
+ return RTEMS_INVALID_NAME;
+ }
- while ( (count=get_messages(brm,rw_args->buffer, rw_args->count)) == 0 ) {
+ rw_args = (rtems_libio_rw_args_t *) arg;
- if (brm->rx_blocking) {
- rtems_semaphore_obtain(brm->rx_sem, RTEMS_WAIT, RTEMS_NO_TIMEOUT);
- }
- else {
- /* Translates to EBUSY */
- return RTEMS_RESOURCE_IN_USE;
- }
+ if ( ((READ_REG(&brm->regs->oper)>>8) & 3) == 1 ) { /* RT */
+ get_messages = get_rt_messages;
+ } else { /* BM */
+ get_messages = get_bm_messages;
+ }
- }
+ FUNCDBG("brm_read [%i,%i]: buf: 0x%x len: %i\n",major, minor, (unsigned int)rw_args->buffer,rw_args->count);
- rw_args->bytes_moved = count;
- return RTEMS_SUCCESSFUL;
+ while ( (count=get_messages(brm,rw_args->buffer, rw_args->count)) == 0 ) {
+ if (brm->rx_blocking) {
+ rtems_semaphore_obtain(brm->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 brm_write(rtems_device_major_number major, rtems_device_minor_number minor, void *arg)
{
- rtems_libio_rw_args_t *rw_args;
- struct rt_msg *source;
- unsigned int count=0, current, next, descriptor, wc, suba;
- brm_priv *brm = &brms[minor];
-
- if ( ! (brm->mode & BRM_MODE_RT) ){
- return RTEMS_INVALID_NAME;
- }
-
- rw_args = (rtems_libio_rw_args_t *) arg;
- source = (struct rt_msg *) rw_args->buffer;
-
- FUNCDBG("brm_write [%i,%i]: buf: 0x%x len: %i\n",major, minor, (unsigned int)rw_args->buffer,rw_args->count);
+ rtems_libio_rw_args_t *rw_args;
+ struct rt_msg *source;
+ unsigned int count=0, current, next, descriptor, wc, suba;
+ brm_priv *brm;
+ struct drvmgr_dev *dev;
+
+ if ( drvmgr_get_dev(&b1553brm_drv_info.general, minor, &dev) ) {
+ return RTEMS_UNSATISFIED;
+ }
+ brm = (brm_priv *)dev->priv;
+
+ if ( ! (brm->mode & BRM_MODE_RT) ){
+ return RTEMS_INVALID_NAME;
+ }
+
+ rw_args = (rtems_libio_rw_args_t *) arg;
+ source = (struct rt_msg *) rw_args->buffer;
- do {
+ FUNCDBG("brm_write [%i,%i]: buf: 0x%x len: %i\n",major, minor, (unsigned int)rw_args->buffer,rw_args->count);
- descriptor = source[count].desc & 0x7F;
- suba = descriptor-32;
- wc = source[count].miw >> 11;
- wc = wc ? wc : 32;
+ do {
- /* Only subaddress transmission is allowed with write */
- if (descriptor < 32 || descriptor >= 64)
- return RTEMS_INVALID_NAME;
+ descriptor = source[count].desc & 0x7F;
+ suba = descriptor-32;
+ wc = source[count].miw >> 11;
+ wc = wc ? wc : 32;
- current = brm->desc[descriptor].cur;
- next = brm->written[suba] + 2 + wc;
+ /* Only subaddress transmission is allowed with write */
+ if (descriptor < 32 || descriptor >= 64)
+ return RTEMS_INVALID_NAME;
- if (brm->written[suba] < current) {
+ current = brm->desc[descriptor].cur;
+ next = brm->written[suba] + 2 + wc;
- if (next > current) {
+ if (brm->written[suba] < current) {
- /* No room in transmission buffer */
+ if (next > current) {
- if (brm->tx_blocking && count == 0) {
- rtems_semaphore_obtain(brm->tx_sem, RTEMS_WAIT, RTEMS_NO_TIMEOUT);
- }
- else if ( brm->tx_blocking && (count != 0) ){
- /* return the number of messages sent so far */
- break;
- }
- else {
- /* Translates to posix EBUSY */
- return RTEMS_RESOURCE_IN_USE;
- }
- }
- }
+ /* No room in transmission buffer */
+ if (brm->tx_blocking && count == 0) {
+ rtems_semaphore_obtain(brm->tx_sem, RTEMS_WAIT, RTEMS_NO_TIMEOUT);
+ } else if ( count > 0 ) {
+ /* return the number of messages sent so far */
+ break;
+ } else {
+ /* Translates to posix EBUSY */
+ return RTEMS_RESOURCE_IN_USE;
+ }
+ }
+ }
- memcpy((void *)&brm->mem[brm->written[suba]], &source[count], (2+wc)*2);
+ memcpy((void *)&brm->mem[brm->written[suba]], &source[count], (2+wc)*2);
- count++;
+ count++;
- if (next >= brm->desc[descriptor].bot) {
- next = brm->desc[descriptor].top;
- }
- brm->written[suba] = next;
+ if (next >= brm->desc[descriptor].bot) {
+ next = brm->desc[descriptor].top;
+ }
+ brm->written[suba] = next;
- } while (count < rw_args->count);
+ } while (count < rw_args->count);
- rw_args->bytes_moved = count;
+ rw_args->bytes_moved = count;
- if (count >= 0) {
- return RTEMS_SUCCESSFUL;
- }
- return RTEMS_UNSATISFIED;
+ if (count >= 0) {
+ return RTEMS_SUCCESSFUL;
+ }
+ return RTEMS_UNSATISFIED;
}
static rtems_device_driver brm_control(rtems_device_major_number major, rtems_device_minor_number minor, void *arg)
{
+
+ unsigned int i=0;
+ unsigned short ctrl, oper, cw1, cw2;
+ rtems_libio_ioctl_args_t *ioarg = (rtems_libio_ioctl_args_t *) arg;
+ unsigned int *data = ioarg->buffer;
+ struct bc_msg *cmd_list = (struct bc_msg *) ioarg->buffer;
+ brm_priv *brm;
+ struct drvmgr_dev *dev;
+ rtems_device_driver ret;
+ int len, msglen;
+
+ FUNCDBG("brm_control[%d]: [%i,%i]\n", minor, major, minor);
+
+ if ( drvmgr_get_dev(&b1553brm_drv_info.general, minor, &dev) ) {
+ return RTEMS_UNSATISFIED;
+ }
+ brm = (brm_priv *)dev->priv;
- unsigned int i=0;
- unsigned short ctrl, oper, cw1, cw2;
- rtems_libio_ioctl_args_t *ioarg = (rtems_libio_ioctl_args_t *) arg;
- unsigned int *data = ioarg->buffer;
- struct bc_msg *cmd_list = (struct bc_msg *) ioarg->buffer;
- brm_priv *brm = &brms[minor];
- rtems_device_driver ret;
- int len;
-
- FUNCDBG("brm_control[%d]: [%i,%i]\n",minor,major, minor);
-
- if (!ioarg) {
- DBG("brm_control: invalid argument\n");
- return RTEMS_INVALID_NAME;
- }
-
- ioarg->ioctl_return = 0;
- switch(ioarg->command) {
-
- case BRM_SET_MODE:
- if ( data[0] > 2 )
- return RTEMS_INVALID_NAME;
- stop_operation(brm);
- if (data[0] == 0) {
- ret = bc_init(brm);
- }
- else if (data[0] == 1) {
- ret = rt_init(brm);
- }
- else if (data[0] == 2) {
- ret = bm_init(brm);
- }else
- ret = RTEMS_INVALID_NAME;
-
- if ( ret != RTEMS_SUCCESSFUL)
- return ret;
-
- if ( brm->mode & (BRM_MODE_RT | BRM_MODE_BM ) )
- start_operation(brm);
- break;
-
- case BRM_SET_BUS:
- stop_operation(brm);
- ctrl = READ_REG(&brm->regs->ctrl);
- ctrl &= 0xE7FF; /* Clear bit 12-11 ... */
- ctrl |= (data[0]&0x3)<<11; /* ... OR in new bus status */
- brm->regs->ctrl = ctrl;
- start_operation(brm);
- break;
-
- case BRM_SET_MSGTO:
- stop_operation(brm);
- ctrl = READ_REG(&brm->regs->ctrl);
- ctrl &= 0xFDFF; /* Clear bit 9 ... */
- ctrl |= (data[0]&1)<<9; /* ... OR in new MSGTO */
- brm->regs->ctrl = ctrl;
- start_operation(brm);
- break;
-
- case BRM_SET_RT_ADDR:
- stop_operation(brm);
- oper = READ_REG(&brm->regs->oper);
- oper &= 0x03FF; /* Clear bit 15-10 ... */
- oper |= (data[0]&0x1f)<<11; /* ... OR in new address */
- oper |= odd_parity(data[0]&0x1f)<<10; /* ... OR in parity */
- brm->regs->oper = oper;
- start_operation(brm);
- break;
-
- case BRM_SET_STD:
- stop_operation(brm);
- ctrl = READ_REG(&brm->regs->ctrl);
- ctrl &= 0xFF7F; /* Clear bit 7 ... */
- ctrl |= (data[0]&1)<<7; /* ... OR in new ABSTD (1=A) */
- brm->regs->ctrl = ctrl;
- start_operation(brm);
- break;
-
- case BRM_SET_BCE:
- stop_operation(brm);
- ctrl = READ_REG(&brm->regs->ctrl);
- ctrl &= 0xFFEF; /* Clear bit 4 ... */
- ctrl |= (data[0]&1)<<4; /* ... OR in new BCE */
- brm->regs->ctrl = ctrl;
- start_operation(brm);
- break;
-
- case BRM_TX_BLOCK:
- brm->tx_blocking = data[0];
- break;
-
- case BRM_RX_BLOCK:
- brm->rx_blocking = data[0];
- break;
-
- case BRM_DO_LIST:
-
- if ( brm->mode != BRM_MODE_BC ){
- return RTEMS_INVALID_NAME;
- }
-
- /* Check if we are bus controller */
- if ( ((READ_REG(&brm->regs->oper)>>8) & 3) != 0 ) {
- return RTEMS_INVALID_NAME;
- }
-
- /* Already processing list? */
- if (is_executing(brm)) {
- return RTEMS_RESOURCE_IN_USE;
- }
-
- /* clear any earlier releases */
- rtems_semaphore_obtain(brm->tx_sem, RTEMS_NO_WAIT, RTEMS_NO_TIMEOUT);
-
- brm->bc_list_fail = 0;
- brm->cur_list = cmd_list;
- brm->regs->dpoint = 0;
-
- i = 0;
- while ( (cmd_list[i].ctrl & BC_EOL) == 0) {
+ if (!ioarg) {
+ DBG("brm_control: invalid argument\n");
+ return RTEMS_INVALID_NAME;
+ }
- ctrl = (4<<12) | (((cmd_list[i].ctrl&BC_BUSA)==BC_BUSA)<<9) | (((cmd_list[i].ctrl&BC_RTRT)==BC_RTRT)<<8);
+ ioarg->ioctl_return = 0;
+ switch (ioarg->command) {
- if (cmd_list[i].ctrl&BC_RTRT) {
- cw1 = (cmd_list[i].rtaddr[0]<<11) | (0<<10) | (cmd_list[i].subaddr[0]<<5) | (cmd_list[i].wc & 0x1f); /* receive cw */
- cw2 = (cmd_list[i].rtaddr[1]<<11) | (1<<10) | (cmd_list[i].subaddr[1]<<5) | (cmd_list[i].wc & 0x1f); /* transmit cw */
- }
- else {
- cw1 = (cmd_list[i].rtaddr[0]<<11) | (((cmd_list[i].ctrl&BC_TR)==BC_TR)<<10) | (cmd_list[i].subaddr[0]<<5) | (cmd_list[i].wc&0x1f);
- cw2 = 0;
- }
+ case BRM_SET_MODE:
+ if ( data[0] > 2 )
+ return RTEMS_INVALID_NAME;
+ stop_operation(brm);
+ if (data[0] == 0) {
+ ret = bc_init(brm);
+ } else if (data[0] == 1) {
+ ret = rt_init(brm);
+ } else if (data[0] == 2) {
+ ret = bm_init(brm);
+ } else {
+ ret = RTEMS_INVALID_NAME;
+ }
+ if ( ret != RTEMS_SUCCESSFUL)
+ return ret;
+
+ if ( brm->mode & (BRM_MODE_RT | BRM_MODE_BM ) )
+ start_operation(brm);
+ break;
+
+ case BRM_SET_BUS:
+ stop_operation(brm);
+ ctrl = READ_REG(&brm->regs->ctrl);
+ ctrl &= 0xE7FF; /* Clear bit 12-11 ... */
+ ctrl |= (data[0]&0x3)<<11; /* ... OR in new bus status */
+ brm->regs->ctrl = ctrl;
+ start_operation(brm);
+ break;
+
+ case BRM_SET_MSGTO:
+ stop_operation(brm);
+ ctrl = READ_REG(&brm->regs->ctrl);
+ ctrl &= 0xFDFF; /* Clear bit 9 ... */
+ ctrl |= (data[0]&1)<<9; /* ... OR in new MSGTO */
+ brm->regs->ctrl = ctrl;
+ start_operation(brm);
+ break;
+
+ case BRM_SET_RT_ADDR:
+ stop_operation(brm);
+ oper = READ_REG(&brm->regs->oper);
+ oper &= 0x03FF; /* Clear bit 15-10 ... */
+ oper |= (data[0]&0x1f)<<11; /* ... OR in new address */
+ oper |= odd_parity(data[0]&0x1f)<<10; /* ... OR in parity */
+ brm->regs->oper = oper;
+ start_operation(brm);
+ break;
+
+ case BRM_SET_STD:
+ stop_operation(brm);
+ ctrl = READ_REG(&brm->regs->ctrl);
+ ctrl &= 0xFF7F; /* Clear bit 7 ... */
+ ctrl |= (data[0]&1)<<7; /* ... OR in new ABSTD (1=A) */
+ brm->regs->ctrl = ctrl;
+ start_operation(brm);
+ break;
+
+ case BRM_SET_BCE:
+ stop_operation(brm);
+ ctrl = READ_REG(&brm->regs->ctrl);
+ ctrl &= 0xFFEF; /* Clear bit 4 ... */
+ ctrl |= (data[0]&1)<<4; /* ... OR in new BCE */
+ brm->regs->ctrl = ctrl;
+ start_operation(brm);
+ break;
+
+ case BRM_TX_BLOCK:
+ brm->tx_blocking = data[0];
+ break;
+
+ case BRM_RX_BLOCK:
+ brm->rx_blocking = data[0];
+ break;
+
+ case BRM_DO_LIST:
+ if ( brm->mode != BRM_MODE_BC ){
+ return RTEMS_INVALID_NAME;
+ }
+ /* Check if we are bus controller */
+ if ( ((READ_REG(&brm->regs->oper)>>8) & 3) != 0 ) {
+ return RTEMS_INVALID_NAME;
+ }
- /* Set up command block */
- brm->bcmem->descs[i].ctrl = ctrl;
- brm->bcmem->descs[i].cw1 = cw1;
- brm->bcmem->descs[i].cw2 = cw2;
- /* data pointer:
- * (&brm->bcmem->msg_data[i].data[0] & 0x1ffff) / 2
- */
- brm->bcmem->descs[i].dptr = 1024+i*32; /* data pointer */
- brm->bcmem->descs[i].tsw[0] = 0;
- brm->bcmem->descs[i].tsw[1] = 0;
- brm->bcmem->descs[i].ba = 0;
- brm->bcmem->descs[i].timer = 0;
+ /* Already processing list? */
+ if (is_executing(brm)) {
+ return RTEMS_RESOURCE_IN_USE;
+ }
- memcpy((void *)&brm->bcmem->msg_data[i].data[0], &cmd_list[i].data[0], cmd_list[i].wc*2);
+ /* clear any earlier releases */
+ rtems_semaphore_obtain(brm->tx_sem, RTEMS_NO_WAIT, RTEMS_NO_TIMEOUT);
+
+ brm->bc_list_fail = 0;
+ brm->cur_list = cmd_list;
+ brm->regs->dpoint = 0;
+
+ i = 0;
+ while ( (cmd_list[i].ctrl & BC_EOL) == 0) {
+
+ ctrl = (4<<12) | (((cmd_list[i].ctrl&BC_BUSA)==BC_BUSA)<<9) | (((cmd_list[i].ctrl&BC_RTRT)==BC_RTRT)<<8);
+
+ if (cmd_list[i].ctrl&BC_RTRT) {
+ cw1 = (cmd_list[i].rtaddr[0]<<11) | (0<<10) | (cmd_list[i].subaddr[0]<<5) | (cmd_list[i].wc & 0x1f); /* receive cw */
+ cw2 = (cmd_list[i].rtaddr[1]<<11) | (1<<10) | (cmd_list[i].subaddr[1]<<5) | (cmd_list[i].wc & 0x1f); /* transmit cw */
+ } else {
+ cw1 = (cmd_list[i].rtaddr[0]<<11) | (((cmd_list[i].ctrl&BC_TR)==BC_TR)<<10) | (cmd_list[i].subaddr[0]<<5) | (cmd_list[i].wc&0x1f);
+ cw2 = 0;
+ }
+
+ /* Set up command block */
+ brm->bcmem->descs[i].ctrl = ctrl;
+ brm->bcmem->descs[i].cw1 = cw1;
+ brm->bcmem->descs[i].cw2 = cw2;
+ /* data pointer:
+ * (&brm->bcmem->msg_data[i].data[0] & 0x1ffff) / 2
+ */
+ brm->bcmem->descs[i].dptr = 1024+i*32; /* data pointer */
+ brm->bcmem->descs[i].tsw[0] = 0;
+ brm->bcmem->descs[i].tsw[1] = 0;
+ brm->bcmem->descs[i].ba = 0;
+ brm->bcmem->descs[i].timer = 0;
+
+ msglen = cmd_list[i].wc;
+ if ( msglen == 0 )
+ msglen = 32;
+ memcpy((void *)&brm->bcmem->msg_data[i].data[0], &cmd_list[i].data[0], msglen*2);
+
+ i++;
+ }
- i++;
- }
+ brm->bcmem->descs[i].ctrl = 0; /* end of list */
- brm->bcmem->descs[i].ctrl = 0; /* end of list */
+ start_operation(brm);
+ break;
- start_operation(brm);
+ case BRM_LIST_DONE:
- break;
+ if ( brm->mode != BRM_MODE_BC ){
+ return RTEMS_INVALID_NAME;
+ }
+
+ /* Check if we are bus controller */
+ if ( ((READ_REG(&brm->regs->oper)>>8) & 3) != 0 ) {
+ return RTEMS_INVALID_NAME;
+ }
- case BRM_LIST_DONE:
+ if (is_executing(brm)) {
- if ( brm->mode != BRM_MODE_BC ){
- return RTEMS_INVALID_NAME;
+ data[0] = 0;
+ if (brm->tx_blocking) {
+ rtems_semaphore_obtain(brm->tx_sem, RTEMS_WAIT, RTEMS_NO_TIMEOUT);
+ data[0] = 1;
+ if ( brm->bc_list_fail ){
+ return RTEMS_INVALID_NAME;
}
+ } else {
+ return RTEMS_RESOURCE_IN_USE;
+ }
+ } else {
+ data[0] = 1; /* done */
+ }
- /* Check if we are bus controller */
- if ( ((READ_REG(&brm->regs->oper)>>8) & 3) != 0 ) {
- return RTEMS_INVALID_NAME;
- }
-
- if (is_executing(brm)) {
-
- data[0] = 0;
- if (brm->tx_blocking) {
- rtems_semaphore_obtain(brm->tx_sem, RTEMS_WAIT, RTEMS_NO_TIMEOUT);
- data[0] = 1;
- if ( brm->bc_list_fail ){
- return RTEMS_INVALID_NAME;
- }
- }else{
- return RTEMS_RESOURCE_IN_USE;
- }
-
-
- }
- else {
- data[0] = 1; /* done */
- }
-
- /* copy finished list results back into bc_msg array */
- i = 0;
- while ( (brm->cur_list[i].ctrl & BC_EOL) == 0) {
-
- if (READ_DMA(&brm->bcmem->descs[i].ctrl) & 1) {
- brm->cur_list[i].ctrl |= 0x8000; /* Set BAME */
- }
- if (brm->cur_list[i].ctrl & BC_TR) {
- /* RT Transmit command, copy received data */
- len = brm->cur_list[i].wc;
- while( len-- > 0){
- brm->cur_list[i].data[len] = READ_DMA(&brm->bcmem->msg_data[i].data[len]);
- }
- }
- brm->cur_list[i].tsw[0] = READ_DMA(&brm->bcmem->descs[i].tsw[0]);
- brm->cur_list[i].tsw[1] = READ_DMA(&brm->bcmem->descs[i].tsw[1]);
-
- i++;
- }
- break;
-
-
- case BRM_CLR_STATUS:
- brm->status = 0;
- break;
+ /* copy finished list results back into bc_msg array */
+ i = 0;
+ while ( (brm->cur_list[i].ctrl & BC_EOL) == 0) {
+ if (READ_DMA(&brm->bcmem->descs[i].ctrl) & 1) {
+ brm->cur_list[i].ctrl |= 0x8000; /* Set BAME */
+ }
+ if (brm->cur_list[i].ctrl & BC_TR) {
+ /* RT Transmit command, copy received data */
+ len = brm->cur_list[i].wc;
+ if ( len == 0 )
+ len = 32;
+ while ( len-- > 0) {
+ brm->cur_list[i].data[len] = READ_DMA(&brm->bcmem->msg_data[i].data[len]);
+ }
+ }
+ brm->cur_list[i].tsw[0] = READ_DMA(&brm->bcmem->descs[i].tsw[0]);
+ brm->cur_list[i].tsw[1] = READ_DMA(&brm->bcmem->descs[i].tsw[1]);
- case BRM_GET_STATUS: /* copy status */
+ i++;
+ }
+ break;
- if ( !ioarg->buffer )
- return RTEMS_INVALID_NAME;
+ case BRM_CLR_STATUS:
+ brm->status = 0;
+ break;
- *(unsigned int *)ioarg->buffer = brm->status;
- break;
+ case BRM_GET_STATUS: /* copy status */
+ if ( !ioarg->buffer )
+ return RTEMS_INVALID_NAME;
+ *(unsigned int *)ioarg->buffer = brm->status;
+ break;
+
case BRM_SET_EVENTID:
- brm->event_id = (rtems_id)ioarg->buffer;
- break;
+ brm->event_id = (rtems_id)ioarg->buffer;
+ break;
- default:
- return RTEMS_NOT_DEFINED;
- }
- return RTEMS_SUCCESSFUL;
-}
-
-#ifdef B1553BRM_DEFINE_INTHANDLER
-static void b1553brm_interrupt_handler(rtems_vector_number v){
- int i;
- /* find minor */
- for(i=0; i<brm_cores; i++){
- if ( (brms[i].irqno+0x10) == v ){
- brm_interrupt(&brms[i]);
- return;
- }
+ default:
+ return RTEMS_NOT_DEFINED;
}
+ return RTEMS_SUCCESSFUL;
}
-#endif
-static void brm_interrupt(brm_priv *brm) {
- unsigned short descriptor, current, pending, miw, wc, tmp;
+static void b1553brm_interrupt(void *arg)
+{
+ brm_priv *brm = arg;
+ unsigned short descriptor, current, pending, miw, wc, tmp, ctrl;
unsigned short msgadr, iaw, iiw;
int len;
- int signal_event=0;
+ int signal_event=0, wake_rx_task=0, wake_tx_task=0;
unsigned int event_status=0;
+ int accessed;
#define SET_ERROR_DESCRIPTOR(descriptor) (event_status = (event_status & 0x0000ffff) | descriptor<<16)
-
- while( (iiw=READ_REG(&brm->irq_log[brm->irq].iiw)) != 0xffff ){
- iaw=READ_REG(&brm->irq_log[brm->irq].iaw);
-
+
+ while( (iiw=READ_DMA(&brm->irq_log[brm->irq].iiw)) != 0xffff ){
+ iaw=READ_DMA(&brm->irq_log[brm->irq].iaw);
+
/* indicate that the interrupt log entry has been processed */
brm->irq_log[brm->irq].iiw = 0xffff;
/* Interpret interrupt log entry */
- descriptor = iaw >> 2;
- pending = iiw;
- brm->irq = (brm->irq + 1) % 16;
-
+ descriptor = iaw >> 2;
+ pending = iiw;
+ brm->irq = (brm->irq + 1) % 16;
+
/* Clear the log so that we */
- /* Subaddress accessed irq (RT only)
- *
- * Can be either a receive or transmit command
- * as well as a mode code.
- */
- if (pending & BRM_SUBAD_IRQ) {
-
- /* Pointer to next free message in circular buffer */
- current = READ_DMA(&brm->desc[descriptor].cur);
-
- while ( (msgadr=brm->last_read[descriptor]) != current) {
-
- /* Get word count */
- miw = READ_DMA(&brm->mem[msgadr]);
- wc = miw >> 11;
-
- /* Data received */
- if (descriptor < 32) {
- wc = wc ? wc : 32;
- }
- /* Data transmitted */
- else if (descriptor < 64) {
- wc = wc ? wc : 32;
- rtems_semaphore_release(brm->tx_sem);
- }
- /* RX Mode code */
- else if (descriptor < 96) {
- wc = (wc>>4);
- }
- /* TX Mode code */
- else if (descriptor < 128) {
- wc = (wc>>4);
- }
-
+ /* Subaddress accessed irq (RT only)
+ *
+ * Can be either a receive or transmit command
+ * as well as a mode code.
+ */
+ if (pending & BRM_SUBAD_IRQ) {
+
+ /* Pointer to next free message in circular buffer */
+ current = READ_DMA(&brm->desc[descriptor].cur);
+ ctrl = READ_DMA(&brm->desc[descriptor].ctrl);
#ifdef DEBUG
- brm->log[brm->log_i++ % EVENT_QUEUE_SIZE] = (descriptor << 16) | wc;
- brm->log[brm->log_i++ % EVENT_QUEUE_SIZE] = current;
- brm->log[brm->log_i++ % EVENT_QUEUE_SIZE] = msgadr;
+ brm->log[brm->log_i++ % EVENT_QUEUE_SIZE] = (0xff<<16);
+ brm->log[brm->log_i++ % EVENT_QUEUE_SIZE] = current;
+ brm->log[brm->log_i++ % EVENT_QUEUE_SIZE] = ctrl;
+ brm->log[brm->log_i++ % EVENT_QUEUE_SIZE] = 0;
#endif
+ accessed = ctrl & 0x10;
+ /* Note that current may be equal to bot and top when
+ * circular buffer one can handle one message.
+ */
+ if ( accessed )
+ do {
+ msgadr = brm->last_read[descriptor];
+
+ /* Get word count */
+ miw = READ_DMA(&brm->mem[msgadr]);
+ wc = miw >> 11;
+
+ /* Data received */
+ if (descriptor < 32) {
+ wc = wc ? wc : 32;
+ }
+ /* Data transmitted */
+ else if (descriptor < 64) {
+ wc = wc ? wc : 32;
+ wake_tx_task=1;
+ }
+ /* RX Mode code */
+ else if (descriptor < 96) {
+ wc = (wc>>4);
+ }
+ /* TX Mode code */
+ else if (descriptor < 128) {
+ wc = (wc>>4);
+ }
- /* If there is room in the event queue, copy the event there */
- if (brm->head - brm->tail != EVENT_QUEUE_SIZE) {
-
- /* Copy to event queue */
- brm->rt_event[INDEX(brm->head)].miw = READ_DMA(&brm->mem[msgadr]);
- brm->rt_event[INDEX(brm->head)].time = READ_DMA(&brm->mem[msgadr+1]);
- len = wc;
- while( len-- > 0){
- brm->rt_event[INDEX(brm->head)].data[len] = READ_DMA(&brm->mem[msgadr+2+len]);
- }
- brm->rt_event[INDEX(brm->head)].desc = descriptor;
- brm->head++;
+#ifdef DEBUG
+ brm->log[brm->log_i++ % EVENT_QUEUE_SIZE] = (descriptor << 16) | wc;
+ brm->log[brm->log_i++ % EVENT_QUEUE_SIZE] = current;
+ brm->log[brm->log_i++ % EVENT_QUEUE_SIZE] = msgadr;
+#endif
- }
- else {
- /* Indicate overrun */
- brm->rt_event[INDEX(brm->head)].desc |= 0x8000;
- }
+ /* If there is room in the event queue, copy the event there */
+ if (brm->head - brm->tail != EVENT_QUEUE_SIZE) {
+
+ /* Copy to event queue */
+ brm->rt_event[INDEX(brm->head)].miw = READ_DMA(&brm->mem[msgadr]);
+ brm->rt_event[INDEX(brm->head)].time = READ_DMA(&brm->mem[msgadr+1]);
+ len = wc;
+ while( len-- > 0){
+ brm->rt_event[INDEX(brm->head)].data[len] = READ_DMA(&brm->mem[msgadr+2+len]);
+ }
+ brm->rt_event[INDEX(brm->head)].desc = descriptor;
+ brm->head++;
+ }
+ else {
+ /* Indicate overrun */
+ brm->rt_event[INDEX(brm->head)].desc |= 0x8000;
+ }
- msgadr += (2+wc);
+ msgadr += (2+wc);
- if (msgadr >= brm->desc[descriptor].bot) {
- msgadr = brm->desc[descriptor].top;
- }
- brm->last_read[descriptor] = msgadr;
+ if (msgadr >= READ_DMA(&brm->desc[descriptor].bot)) {
+ msgadr = READ_DMA(&brm->desc[descriptor].top);
+ }
+ brm->last_read[descriptor] = msgadr;
#ifdef DEBUG
- brm->log[brm->log_i++ % EVENT_QUEUE_SIZE] = msgadr;
+ brm->log[brm->log_i++ % EVENT_QUEUE_SIZE] = msgadr;
#endif
+ wake_rx_task = 1;
+ } while ( (msgadr=brm->last_read[descriptor]) != current );
+ }
- /* Wake any blocked rx thread */
- rtems_semaphore_release(brm->rx_sem);
-
- }
-
- }
-
- if (pending & BRM_EOL_IRQ) {
- rtems_semaphore_release(brm->tx_sem);
- }
-
- if (pending & BRM_BC_ILLCMD_IRQ) {
- brm->bc_list_fail = 1;
- rtems_semaphore_release(brm->tx_sem);
- SET_ERROR_DESCRIPTOR(descriptor);
- FUNCDBG("BRM: ILLCMD IRQ\n\r");
- }
-
- /* Monitor irq */
- if (pending & BRM_MBC_IRQ) {
-
- stop_operation(brm);
- brm->regs->mbc = 1;
- start_operation(brm);
-
- /* If there is room in the event queue, copy the event there */
- if (brm->head - brm->tail != EVENT_QUEUE_SIZE) {
-
- /* Copy to event queue */
+ if (pending & BRM_EOL_IRQ) {
+ wake_tx_task = 1;
+ }
- brm->bm_event[INDEX(brm->head)].miw = READ_DMA(&brm->mem[0]);
- brm->bm_event[INDEX(brm->head)].cw1 = READ_DMA(&brm->mem[1]);
- brm->bm_event[INDEX(brm->head)].cw2 = READ_DMA(&brm->mem[2]);
- brm->bm_event[INDEX(brm->head)].sw1 = READ_DMA(&brm->mem[4]);
- brm->bm_event[INDEX(brm->head)].sw2 = READ_DMA(&brm->mem[5]);
- brm->bm_event[INDEX(brm->head)].time = READ_DMA(&brm->mem[6]);
+ if (pending & BRM_BC_ILLCMD_IRQ) {
+ brm->bc_list_fail = 1;
+ wake_tx_task = 1;
+ SET_ERROR_DESCRIPTOR(descriptor);
+ FUNCDBG("BRM: ILLCMD IRQ\n\r");
+ }
- len = 32;
- while ( len-- ){
- brm->bm_event[INDEX(brm->head)].data[len] = READ_DMA(&brm->mem[0x100+len]);
- len--;
- brm->bm_event[INDEX(brm->head)].data[len] = READ_DMA(&brm->mem[0x100+len]);
- len--;
- brm->bm_event[INDEX(brm->head)].data[len] = READ_DMA(&brm->mem[0x100+len]);
- len--;
- brm->bm_event[INDEX(brm->head)].data[len] = READ_DMA(&brm->mem[0x100+len]);
- }
-/* memcpy((void *)brm->bm_event[INDEX(brm->head)].data, &brm->mem[0x100], 32);*/
+ /* Monitor irq */
+ if (pending & BRM_MBC_IRQ) {
+
+ stop_operation(brm);
+ brm->regs->mbc = 1;
+ start_operation(brm);
+
+ /* If there is room in the event queue, copy the event there */
+ if (brm->head - brm->tail != EVENT_QUEUE_SIZE) {
+
+ /* Copy to event queue */
+
+ brm->bm_event[INDEX(brm->head)].miw = READ_DMA(&brm->mem[0]);
+ brm->bm_event[INDEX(brm->head)].cw1 = READ_DMA(&brm->mem[1]);
+ brm->bm_event[INDEX(brm->head)].cw2 = READ_DMA(&brm->mem[2]);
+ brm->bm_event[INDEX(brm->head)].sw1 = READ_DMA(&brm->mem[4]);
+ brm->bm_event[INDEX(brm->head)].sw2 = READ_DMA(&brm->mem[5]);
+ brm->bm_event[INDEX(brm->head)].time = READ_DMA(&brm->mem[6]);
+
+ len = 32;
+ while ( len-- ){
+ brm->bm_event[INDEX(brm->head)].data[len] = READ_DMA(&brm->mem[0x100+len]);
+ len--;
+ brm->bm_event[INDEX(brm->head)].data[len] = READ_DMA(&brm->mem[0x100+len]);
+ len--;
+ brm->bm_event[INDEX(brm->head)].data[len] = READ_DMA(&brm->mem[0x100+len]);
+ len--;
+ brm->bm_event[INDEX(brm->head)].data[len] = READ_DMA(&brm->mem[0x100+len]);
+ }
+/* memcpy((void *)brm->bm_event[INDEX(brm->head)].data, &brm->mem[0x100], 32);*/
#ifdef DEBUG
- brm->log[brm->log_i++ % EVENT_QUEUE_SIZE] = READ_REG(&brm->regs->mbc);
- brm->log[brm->log_i++ % EVENT_QUEUE_SIZE] = READ_DMA(&brm->mem[0]);
- brm->log[brm->log_i++ % EVENT_QUEUE_SIZE] = READ_DMA(&brm->mem[1]);
- brm->log[brm->log_i++ % EVENT_QUEUE_SIZE] = READ_DMA(&brm->mem[4]);
+ brm->log[brm->log_i++ % EVENT_QUEUE_SIZE] = READ_REG(&brm->regs->mbc) & 0xffff;
+ brm->log[brm->log_i++ % EVENT_QUEUE_SIZE] = READ_DMA(&brm->mem[0]);
+ brm->log[brm->log_i++ % EVENT_QUEUE_SIZE] = READ_DMA(&brm->mem[1]);
+ brm->log[brm->log_i++ % EVENT_QUEUE_SIZE] = READ_DMA(&brm->mem[4]);
#endif
- brm->head++;
-
- }
- else {
- /* Indicate overrun */
- brm->rt_event[INDEX(brm->head)].miw |= 0x8000;
- }
+ brm->head++;
- /* Wake any blocking thread */
- rtems_semaphore_release(brm->rx_sem);
+ }
+ else {
+ /* Indicate overrun */
+ brm->bm_event[INDEX(brm->head)].miw |= 0x8000;
+ }
- }
+ /* Wake any blocking thread */
+ wake_rx_task = 1;
+ }
- /* The reset of the interrupts
+ /* The reset of the interrupts
* cause a event to be signalled
* so that user can handle error.
*/
@@ -1317,9 +1394,9 @@ static void brm_interrupt(brm_priv *brm) {
if ( pending & BRM_ILLOP_IRQ){
FUNCDBG("BRM: BRM_ILLOP_IRQ\n\r");
brm->bc_list_fail = 1;
- rtems_semaphore_release(brm->tx_sem);
+ wake_tx_task = 1;
event_status |= BRM_ILLOP_IRQ;
- SET_ERROR_DESCRIPTOR(descriptor);
+ SET_ERROR_DESCRIPTOR(descriptor);
signal_event=1;
}
@@ -1329,10 +1406,15 @@ static void brm_interrupt(brm_priv *brm) {
SET_ERROR_DESCRIPTOR(descriptor);
signal_event=1;
}
- /* Clear Block Accessed Bit */
- tmp = READ_REG(&brm->desc[descriptor].ctrl);
- brm->desc[descriptor].ctrl = tmp & ~0x10;
-
+ /* Clear Block Accessed Bit */
+ tmp = READ_DMA(&brm->desc[descriptor].ctrl);
+ brm->desc[descriptor].ctrl = tmp & ~0x10;
+#ifdef DEBUG
+ brm->log[brm->log_i++ % EVENT_QUEUE_SIZE] = (0xfe<<16);
+ brm->log[brm->log_i++ % EVENT_QUEUE_SIZE] = 0;
+ brm->log[brm->log_i++ % EVENT_QUEUE_SIZE] = tmp & ~0x10;
+ brm->log[brm->log_i++ % EVENT_QUEUE_SIZE] = tmp;
+#endif
} /* While */
/* clear interrupt flags & handle Hardware errors */
@@ -1363,9 +1445,88 @@ static void brm_interrupt(brm_priv *brm) {
brm->status |= event_status;
}
+ /* Wake any blocked rx thread only on receive interrupts */
+ if ( wake_rx_task ) {
+ rtems_semaphore_release(brm->rx_sem);
+ }
+
+ /* Wake any blocked tx thread only on transmit interrupts */
+ if ( wake_tx_task ) {
+ rtems_semaphore_release(brm->tx_sem);
+ }
+
/* signal event once */
if ( signal_event && (brm->event_id!=0) ){
rtems_event_send(brm->event_id, event_status);
}
}
+
+void b1553brm_print_dev(struct drvmgr_dev *dev, int options)
+{
+ brm_priv *pDev = dev->priv;
+ struct amba_dev_info *devinfo;
+ struct brm_reg *regs = pDev->regs;
+
+ devinfo = (struct amba_dev_info *)pDev->dev->businfo;
+
+ /* Print */
+ printf("--- B1553BRM[%d] %s ---\n", pDev->minor, pDev->devName);
+ printf(" REGS: 0x%x\n", (unsigned int)pDev->regs);
+ printf(" IRQ: %d\n", pDev->irqno);
+ switch (pDev->mode) {
+ case BRM_MODE_BC:
+ printf(" MODE: BC\n");
+ printf(" DESCS: 0x%x\n", (unsigned int)&pDev->bcmem->descs[0]);
+ printf(" DATA: 0x%x\n", (unsigned int)&pDev->bcmem->msg_data[0].data[0]);
+ printf(" IRQLOG: 0x%x\n", (unsigned int)&pDev->bcmem->irq_logs[0]);
+ break;
+ case BRM_MODE_BM:
+ printf(" MODE: BM\n");
+ break;
+ case BRM_MODE_RT:
+ printf(" MODE: RT\n");
+ printf(" RXSUBS: 0x%x\n", (unsigned int)&pDev->rtmem->rxsubs[0]);
+ printf(" TXSUBS: 0x%x\n", (unsigned int)&pDev->rtmem->txsubs[0]);
+ printf(" RXMODES: 0x%x\n", (unsigned int)&pDev->rtmem->rxmodes[0]);
+ printf(" TXOMODES: 0x%x\n", (unsigned int)&pDev->rtmem->txmodes[0]);
+ printf(" RXSUBS MSGS: 0x%x\n", (unsigned int)&pDev->rtmem->rxsuba_msgs[0]);
+ printf(" TXSUBS MSGS: 0x%x\n", (unsigned int)&pDev->rtmem->txsuba_msgs[0]);
+ printf(" RXMODES MSGS: 0x%x\n", (unsigned int)&pDev->rtmem->rxmode_msgs[0]);
+ printf(" TXMODES MSGS: 0x%x\n", (unsigned int)&pDev->rtmem->txmode_msgs[0]);
+ printf(" IRQLOG: 0x%x\n", (unsigned int)&pDev->rtmem->irq_logs[0]);
+ break;
+ }
+ printf(" CTRL: 0x%x\n", regs->ctrl);
+ printf(" OPER: 0x%x\n", regs->oper);
+ printf(" CUR_CMD: 0x%x\n", regs->cur_cmd);
+ printf(" IMASK: 0x%x\n", regs->imask);
+ printf(" IPEND: 0x%x\n", regs->ipend);
+ printf(" IPOINT: 0x%x\n", regs->ipoint);
+ printf(" BIT_REG: 0x%x\n", regs->bit_reg);
+ printf(" TTAG: 0x%x\n", regs->ttag);
+ printf(" DPOINT: 0x%x\n", regs->dpoint);
+ printf(" SW: 0x%x\n", regs->sw);
+ printf(" INITCOUNT: 0x%x\n", regs->initcount);
+ printf(" MCPOINT: 0x%x\n", regs->mcpoint);
+ printf(" MDPOINT: 0x%x\n", regs->mdpoint);
+ printf(" MBC: 0x%x\n", regs->mbc);
+ printf(" MFILTA: 0x%x\n", regs->mfilta);
+ printf(" MFILTB: 0x%x\n", regs->mfiltb);
+ printf(" ENHANCED: 0x%x\n", regs->enhanced);
+ printf(" W_CTRL: 0x%x\n", regs->w_ctrl);
+ printf(" W_IRQCTRL: 0x%x\n", regs->w_irqctrl);
+ printf(" W_AHBADDR: 0x%x\n", regs->w_ahbaddr);
+}
+
+void b1553brm_print(int options)
+{
+ struct amba_drv_info *drv = &b1553brm_drv_info;
+ struct drvmgr_dev *dev;
+
+ dev = drv->general.dev;
+ while(dev) {
+ b1553brm_print_dev(dev, options);
+ dev = dev->next_in_drv;
+ }
+}