Back to home page

LXR

 
 

    


File indexing completed on 2025-05-11 08:24:05

0001 /* SPDX-License-Identifier: BSD-2-Clause */
0002 
0003 /*
0004  *  BRM driver
0005  *
0006  *  COPYRIGHT (c) 2006.
0007  *  Cobham Gaisler AB.
0008  *
0009  * Redistribution and use in source and binary forms, with or without
0010  * modification, are permitted provided that the following conditions
0011  * are met:
0012  * 1. Redistributions of source code must retain the above copyright
0013  *    notice, this list of conditions and the following disclaimer.
0014  * 2. Redistributions in binary form must reproduce the above copyright
0015  *    notice, this list of conditions and the following disclaimer in the
0016  *    documentation and/or other materials provided with the distribution.
0017  *
0018  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
0019  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
0020  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
0021  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
0022  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
0023  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
0024  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
0025  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
0026  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
0027  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
0028  * POSSIBILITY OF SUCH DAMAGE.
0029  */
0030 
0031 /********** Set defaults **********/
0032 
0033 /* default to 16K memory layout */
0034 #define DMA_MEM_128K
0035 #if !defined(DMA_MEM_128K)
0036  #define DMA_MEM_16K
0037 #endif
0038 
0039 #include <bsp.h>
0040 #include <rtems/libio.h>
0041 #include <stdlib.h>
0042 #include <stdio.h>
0043 #include <string.h>
0044 #include <assert.h>
0045 #include <ctype.h>
0046 #include <rtems/bspIo.h>
0047 
0048 #include <drvmgr/drvmgr.h>
0049 #include <grlib/b1553brm.h>
0050 #include <grlib/ambapp.h>
0051 #include <grlib/ambapp_bus.h>
0052 
0053 #include <grlib/grlib_impl.h>
0054 
0055 /* Uncomment for debug output */
0056 /*#define DEBUG 1
0057 #define FUNCDEBUG 1*/
0058 #undef DEBUG
0059 #undef FUNCDEBUG
0060 
0061 /* EVENT_QUEUE_SIZE sets the size of the event queue
0062  */
0063 #define EVENT_QUEUE_SIZE           1024  
0064 
0065 
0066 #define INDEX(x) ( x&(EVENT_QUEUE_SIZE-1) )
0067 
0068 #if 0
0069 #define DBG(x...) printk(x)
0070 #else
0071 #define DBG(x...) 
0072 #endif
0073 
0074 #ifdef FUNCDEBUG
0075 #define FUNCDBG(x...) printk(x)
0076 #else
0077 #define FUNCDBG(x...) 
0078 #endif
0079 
0080 #define READ_REG(address) (*(volatile unsigned int *)address)
0081 #define READ_DMA(address) grlib_read_uncached16((unsigned int)address)
0082 
0083 static rtems_device_driver brm_initialize(rtems_device_major_number major, rtems_device_minor_number minor, void *arg);
0084 static rtems_device_driver brm_open(rtems_device_major_number major, rtems_device_minor_number minor, void *arg);
0085 static rtems_device_driver brm_close(rtems_device_major_number major, rtems_device_minor_number minor, void *arg);
0086 static rtems_device_driver brm_read(rtems_device_major_number major, rtems_device_minor_number minor, void *arg);
0087 static rtems_device_driver brm_write(rtems_device_major_number major, rtems_device_minor_number minor, void *arg);
0088 static rtems_device_driver brm_control(rtems_device_major_number major, rtems_device_minor_number minor, void *arg);
0089 
0090 #define BRM_DRIVER_TABLE_ENTRY { brm_initialize, brm_open, brm_close, brm_read, brm_write, brm_control }
0091 
0092 static rtems_driver_address_table b1553brm_driver = BRM_DRIVER_TABLE_ENTRY;
0093 
0094 struct msg {
0095     unsigned short miw;
0096     unsigned short time;
0097     unsigned short data[32];
0098 };
0099 #if defined(DMA_MEM_128K)
0100 struct circ_buf {
0101     struct msg msgs[9];
0102 };
0103 #elif defined(DMA_MEM_16K)
0104 /* two message queue */
0105 struct circ_buf_2 {
0106     struct msg msgs[2];
0107 };
0108 /* one message queue */
0109 struct circ_buf_1 {
0110     struct msg msgs[1];
0111 };
0112 #endif
0113 
0114 struct irq_log_list {
0115         volatile unsigned short iiw;
0116         volatile unsigned short iaw;
0117 };
0118 
0119 typedef struct { 
0120 
0121     struct drvmgr_dev *dev; /* Driver manager device */
0122     char devName[52]; /* Device Name */
0123     struct brm_reg *regs;
0124 
0125     unsigned int memarea_base;
0126     unsigned int memarea_base_remote;
0127     unsigned int cfg_clksel;
0128     unsigned int cfg_clkdiv;
0129     unsigned int cfg_freq;
0130 
0131     /* BRM descriptors */
0132     struct desc_table {
0133         volatile unsigned short ctrl;        
0134         volatile unsigned short top;
0135         volatile unsigned short cur;
0136         volatile unsigned short bot;
0137     } *desc;
0138 
0139     volatile unsigned short *mem;
0140     /* bc mem struct */
0141     struct {
0142         /* BC Descriptors */
0143         struct {
0144             unsigned short ctrl; /* control */
0145             unsigned short cw1;  /* Command word 1*/
0146             unsigned short cw2;  /* Command word 1*/
0147             unsigned short dptr; /* Data pointer in halfword offset from bcmem */
0148             unsigned short tsw[2]; /* status word 1 & 2 */
0149             unsigned short ba;     /* branch address */
0150             unsigned short timer;  /* timer value */
0151         } descs[128]; /* 2k (1024 half words) */
0152 
0153         /* message data */
0154         struct {
0155             unsigned short data[32]; /* 1 message's data */
0156         } msg_data[128]; /* 8k */
0157 
0158 #if defined(DMA_MEM_128K)
0159         /* offset to last 64bytes of 128k */
0160         unsigned short unused[(64*1024-(128*8+128*32))-16*2];
0161 #elif defined(DMA_MEM_16K)
0162         unsigned short unused[(8*1024-(128*8+128*32))-16*2];
0163 #endif
0164         /* interrupt log at 64 bytes from end */
0165         struct irq_log_list irq_logs[16];
0166     } *bcmem;
0167 
0168 #if defined(DMA_MEM_128K)
0169     /* Memory structure of a RT being inited, just used
0170      * for RT initialization.
0171      *
0172      * *mesgs[32] fit each minimally 8 messages per sub address.
0173      */
0174     struct {
0175         /* RX Sub Address descriptors */
0176         struct desc_table rxsubs[32];
0177         /* TX Sub Address descriptors */
0178         struct desc_table txsubs[32];
0179         /* RX mode code descriptors */
0180         struct desc_table rxmodes[32];
0181         /* TX mode code descriptors */
0182         struct desc_table txmodes[32];
0183 
0184         /* RX Sub Address messages */
0185         struct circ_buf rxsuba_msgs[32];
0186         /* TX Sub Address messages */
0187         struct circ_buf txsuba_msgs[32];
0188         /* RX Mode Code messages */
0189         struct circ_buf rxmode_msgs[32];
0190         /* RX Mode Code messages */
0191         struct circ_buf txmode_msgs[32];
0192 
0193         /* offset to last 64bytes of 128k: tot-used-needed */
0194         unsigned short unused[(64*1024-(4*32*4+4*32*9*34))-16*2];
0195 
0196         /* interrupt log at 64 bytes from end */
0197         struct irq_log_list irq_logs[16];
0198     } *rtmem;
0199 #elif defined(DMA_MEM_16K)
0200     /* Memory structure of a RT being inited, just used
0201      * for RT initialization.
0202      *
0203      * circ_buf_2 *mesgs[32] fit each minimally 2 messages per queue.
0204      * circ_buf_1 *mesgs[32] fit each minimally 1 messages per queue.
0205      */
0206     struct {
0207         /* RX Sub Address descriptors */
0208         struct desc_table rxsubs[32];
0209         /* TX Sub Address descriptors */
0210         struct desc_table txsubs[32];
0211         /* RX mode code descriptors */
0212         struct desc_table rxmodes[32];
0213         /* TX mode code descriptors */
0214         struct desc_table txmodes[32];
0215 
0216         /* RX Sub Address messages */
0217         struct circ_buf_2 rxsuba_msgs[32];
0218         /* TX Sub Address messages */
0219         struct circ_buf_2 txsuba_msgs[32];
0220         /* RX Mode Code messages */
0221         struct circ_buf_2 rxmode_msgs[32];
0222         /* RX Mode Code messages */
0223         struct circ_buf_1 txmode_msgs[32];
0224 
0225         /* offset to last 64bytes of 16k: tot-used-needed */
0226         unsigned short unused[8*1024 -(4*32*4 +3*32*2*34 +1*32*1*34) -16*2];
0227 
0228         /* interrupt log at 64 bytes from end */
0229         struct irq_log_list irq_logs[16];
0230     } *rtmem;
0231 #else
0232     #error You must define one DMA_MEM_???K
0233 #endif
0234 
0235     /* Interrupt log list */
0236     struct irq_log_list *irq_log;
0237     unsigned int irq;
0238 
0239     /* Received events waiting to be read */
0240     struct rt_msg *rt_event;
0241     struct bm_msg *bm_event;
0242 
0243     unsigned int head, tail;
0244 
0245     unsigned int last_read[128];
0246     unsigned int written[32];
0247 
0248     struct bc_msg *cur_list;
0249 
0250     int tx_blocking, rx_blocking;
0251 
0252     rtems_id rx_sem, tx_sem, dev_sem;
0253     int minor;
0254     int irqno;
0255     unsigned int mode;
0256 #ifdef DEBUG            
0257     unsigned int log[EVENT_QUEUE_SIZE*4];
0258     unsigned int log_i;
0259 #endif
0260 
0261     rtems_id event_id; /* event that may be signalled upon errors, needs to be set through ioctl command BRM_SET_EVENTID */
0262     unsigned int status;
0263     int bc_list_fail;
0264 } brm_priv;
0265 
0266 static void b1553brm_interrupt(void *arg);
0267 static rtems_device_driver rt_init(brm_priv *brm);
0268 
0269 #define OFS(ofs) (((unsigned int)&ofs & 0x1ffff)>>1)
0270 
0271 static int b1553brm_driver_io_registered = 0;
0272 static rtems_device_major_number b1553brm_driver_io_major = 0;
0273 
0274 /******************* Driver manager interface ***********************/
0275 
0276 /* Driver prototypes */
0277 int b1553brm_register_io(rtems_device_major_number *m);
0278 int b1553brm_device_init(brm_priv *pDev);
0279 
0280 int b1553brm_init2(struct drvmgr_dev *dev);
0281 int b1553brm_init3(struct drvmgr_dev *dev);
0282 int b1553brm_remove(struct drvmgr_dev *dev);
0283 
0284 struct drvmgr_drv_ops b1553brm_ops = 
0285 {
0286     .init = {NULL, b1553brm_init2, b1553brm_init3, NULL},
0287     .remove = b1553brm_remove,
0288     .info = NULL
0289 };
0290 
0291 struct amba_dev_id b1553brm_ids[] = 
0292 {
0293     {VENDOR_GAISLER, GAISLER_B1553BRM},
0294     {0, 0}      /* Mark end of table */
0295 };
0296 
0297 struct amba_drv_info b1553brm_drv_info =
0298 {
0299     {
0300         DRVMGR_OBJ_DRV,             /* Driver */
0301         NULL,                   /* Next driver */
0302         NULL,                   /* Device list */
0303         DRIVER_AMBAPP_GAISLER_B1553BRM_ID,  /* Driver ID */
0304         "B1553BRM_DRV",             /* Driver Name */
0305         DRVMGR_BUS_TYPE_AMBAPP,         /* Bus Type */
0306         &b1553brm_ops,
0307         NULL,                   /* Funcs */
0308         0,                  /* No devices yet */
0309         0,
0310     },
0311     &b1553brm_ids[0]
0312 };
0313 
0314 void b1553brm_register_drv (void)
0315 {
0316     DBG("Registering B1553BRM driver\n");
0317     drvmgr_drv_register(&b1553brm_drv_info.general);
0318 }
0319 
0320 int b1553brm_init2(struct drvmgr_dev *dev)
0321 {
0322     brm_priv *priv;
0323 
0324     DBG("B1553BRM[%d] on bus %s\n", dev->minor_drv, dev->parent->dev->name);
0325     priv = dev->priv = grlib_calloc(1, sizeof(*priv));
0326     if ( !priv )
0327         return DRVMGR_NOMEM;
0328     priv->dev = dev;
0329 
0330     /* This core will not find other cores, so we wait for init2() */
0331 
0332     return DRVMGR_OK;
0333 }
0334 
0335 int b1553brm_init3(struct drvmgr_dev *dev)
0336 {
0337     brm_priv *priv;
0338     char prefix[32];
0339     rtems_status_code status;
0340 
0341     priv = dev->priv;
0342 
0343     /* Do initialization */
0344 
0345     if ( b1553brm_driver_io_registered == 0) {
0346         /* Register the I/O driver only once for all cores */
0347         if ( b1553brm_register_io(&b1553brm_driver_io_major) ) {
0348             /* Failed to register I/O driver */
0349             dev->priv = NULL;
0350             return DRVMGR_FAIL;
0351         }
0352 
0353         b1553brm_driver_io_registered = 1;
0354     }
0355 
0356     /* I/O system registered and initialized 
0357      * Now we take care of device initialization.
0358      */
0359 
0360     if ( b1553brm_device_init(priv) ) {
0361         return DRVMGR_FAIL;
0362     }
0363 
0364     /* Get Filesystem name prefix */
0365     prefix[0] = '\0';
0366     if ( drvmgr_get_dev_prefix(dev, prefix) ) {
0367         /* Failed to get prefix, make sure of a unique FS name
0368          * by using the driver minor.
0369          */
0370         sprintf(priv->devName, "/dev/b1553brm%d", dev->minor_drv);
0371     } else {
0372         /* Got special prefix, this means we have a bus prefix
0373          * And we should use our "bus minor"
0374          */
0375         sprintf(priv->devName, "/dev/%sb1553brm%d", prefix, dev->minor_bus);
0376     }
0377 
0378     /* Register Device */
0379     status = rtems_io_register_name(priv->devName, b1553brm_driver_io_major, dev->minor_drv);
0380     if (status != RTEMS_SUCCESSFUL) {
0381         return DRVMGR_FAIL;
0382     }
0383 
0384     return DRVMGR_OK;
0385 }
0386 
0387 int b1553brm_remove(struct drvmgr_dev *dev)
0388 {
0389     /* Stop more tasks to open driver */
0390 
0391     /* Throw out all tasks using this driver */
0392 
0393     /* Unregister I/O node */
0394 
0395     /* Unregister and disable Interrupt */
0396 
0397     /* Free device memory */
0398 
0399     /* Return sucessfully */
0400 
0401     return DRVMGR_OK;
0402 }
0403 
0404 /******************* Driver Implementation ***********************/
0405 
0406 int b1553brm_register_io(rtems_device_major_number *m)
0407 {
0408     rtems_status_code r;
0409 
0410     if ((r = rtems_io_register_driver(0, &b1553brm_driver, m)) == RTEMS_SUCCESSFUL) {
0411         DBG("B1553BRM driver successfully registered, major: %d\n", *m);
0412     } else {
0413         switch(r) {
0414         case RTEMS_TOO_MANY:
0415             printk("B1553BRM rtems_io_register_driver failed: RTEMS_TOO_MANY\n");
0416             return -1;
0417         case RTEMS_INVALID_NUMBER:  
0418             printk("B1553BRM rtems_io_register_driver failed: RTEMS_INVALID_NUMBER\n");
0419             return -1;
0420         case RTEMS_RESOURCE_IN_USE:
0421             printk("B1553BRM rtems_io_register_driver failed: RTEMS_RESOURCE_IN_USE\n");
0422             return -1;
0423         default:
0424             printk("B1553BRM rtems_io_register_driver failed\n");
0425             return -1;
0426         }
0427     }
0428     return 0;
0429 }
0430 
0431 int b1553brm_device_init(brm_priv *pDev)
0432 {
0433     struct amba_dev_info *ambadev;
0434     struct ambapp_core *pnpinfo;
0435     union drvmgr_key_value *value;
0436     unsigned int mem;
0437     int size;
0438 
0439     /* Get device information from AMBA PnP information */
0440     ambadev = (struct amba_dev_info *)pDev->dev->businfo;
0441     if ( ambadev == NULL ) {
0442         return -1;
0443     }
0444     pnpinfo = &ambadev->info;
0445     pDev->irqno = pnpinfo->irq;
0446     /* Two versions of the BRM core. One where the registers are accessed using the AHB bus 
0447      * and one where the APB bus is used
0448      */
0449     if ( pnpinfo->ahb_slv ) {
0450         /* Registers accessed over AHB */
0451         pDev->regs = (struct brm_reg *)pnpinfo->ahb_slv->start[0];
0452     } else {
0453         /* Registers accessed over APB */
0454         pDev->regs = (struct brm_reg *)pnpinfo->apb_slv->start;
0455     }
0456     pDev->minor = pDev->dev->minor_drv;
0457 #ifdef DEBUG
0458     pDev->log_i = 0;    
0459     memset(pDev->log,0,sizeof(pDev->log));
0460 #endif
0461 
0462 #ifdef DMA_MEM_128K
0463     size = 128 * 1024;
0464 #else
0465     size = 16 * 1024;
0466 #endif
0467 
0468     /* Get memory configuration from bus resources */
0469     value = drvmgr_dev_key_get(pDev->dev, "dmaBaseAdr", DRVMGR_KT_POINTER);
0470     if (value)
0471         mem = (unsigned int)value->ptr;
0472 
0473     if (value && (mem & 1)) {
0474         /* Remote address, address as BRM looks at it. */
0475 
0476         /* Translate the base address into an address that the the CPU can understand */
0477         pDev->memarea_base_remote = mem & ~1;
0478         drvmgr_translate_check(pDev->dev, DMAMEM_TO_CPU,
0479                     (void *)pDev->memarea_base_remote,
0480                     (void **)&pDev->memarea_base,
0481                     size);
0482     } else {
0483         if (!value) {
0484             /* Use dynamically allocated memory + 128k for
0485              * alignment
0486              */
0487             mem = (unsigned int)grlib_malloc(size + 128 * 1024);
0488             if (!mem){
0489                 printk("BRM: Failed to allocate HW memory\n\r");
0490                 return -1;
0491             }
0492             /* align memory to 128k boundary */
0493             pDev->memarea_base = (mem + 0x1ffff) & ~0x1ffff;
0494         } else {
0495             pDev->memarea_base = mem;
0496         }
0497 
0498         /* Translate the base address into an address that the BRM core can understand */
0499         drvmgr_translate_check(pDev->dev, CPUMEM_TO_DMA,
0500                     (void *)pDev->memarea_base,
0501                     (void **)&pDev->memarea_base_remote,
0502                     size);
0503     }
0504 
0505     /* clear the used memory */
0506     memset((char *)pDev->memarea_base, 0, size);
0507 
0508     /* Set base address of all descriptors */
0509     pDev->desc = (struct desc_table *) pDev->memarea_base;
0510     pDev->mem = (volatile unsigned short *) pDev->memarea_base;
0511     pDev->irq_log   = (struct irq_log_list *)(pDev->memarea_base + (0xFFE0<<1)); /* last 64byte */
0512 
0513     pDev->bm_event = NULL;
0514     pDev->rt_event = NULL;
0515 
0516     pDev->cfg_clksel = 0;
0517     pDev->cfg_clkdiv = 0;
0518     pDev->cfg_freq = BRM_FREQ_24MHZ;
0519 
0520     value = drvmgr_dev_key_get(pDev->dev, "clkSel", DRVMGR_KT_INT);
0521     if ( value ) {
0522         pDev->cfg_clksel = value->i & CLKSEL_MASK;
0523     }
0524 
0525     value = drvmgr_dev_key_get(pDev->dev, "clkDiv", DRVMGR_KT_INT);
0526     if ( value ) {
0527         pDev->cfg_clkdiv = value->i & CLKDIV_MASK;
0528     }
0529 
0530     value = drvmgr_dev_key_get(pDev->dev, "coreFreq", DRVMGR_KT_INT);
0531     if ( value ) {
0532         pDev->cfg_freq = value->i & BRM_FREQ_MASK;
0533     }
0534 
0535     /* Sel clock so that we can write to BRM's registers */
0536     pDev->regs->w_ctrl = (pDev->cfg_clksel<<9) | (pDev->cfg_clkdiv<<5);
0537     /* Reset BRM core */
0538     pDev->regs->w_ctrl = 1<<10 | READ_REG(&pDev->regs->w_ctrl);
0539 
0540     /* RX Semaphore created with count = 0 */
0541     if ( rtems_semaphore_create(rtems_build_name('B', 'M', 'R', '0' + pDev->minor),
0542         0,
0543         RTEMS_FIFO|RTEMS_SIMPLE_BINARY_SEMAPHORE|RTEMS_NO_INHERIT_PRIORITY|RTEMS_LOCAL|RTEMS_NO_PRIORITY_CEILING, 
0544         0,
0545         &pDev->rx_sem) != RTEMS_SUCCESSFUL ) {
0546         printk("BRM: Failed to create rx semaphore\n");
0547         return RTEMS_INTERNAL_ERROR;
0548     }
0549 
0550     /* TX Semaphore created with count = 1 */
0551     if ( rtems_semaphore_create(rtems_build_name('B', 'M', 'T', '0' + pDev->minor),
0552         1,
0553         RTEMS_FIFO|RTEMS_SIMPLE_BINARY_SEMAPHORE|RTEMS_NO_INHERIT_PRIORITY|RTEMS_LOCAL|RTEMS_NO_PRIORITY_CEILING, 
0554         0,
0555         &pDev->tx_sem) != RTEMS_SUCCESSFUL ){
0556         printk("BRM: Failed to create tx semaphore\n");
0557         return RTEMS_INTERNAL_ERROR;
0558     }
0559 
0560     /* Device Semaphore created with count = 1 */
0561     if ( rtems_semaphore_create(rtems_build_name('B', 'M', 'D', '0' + pDev->minor),
0562         1,
0563         RTEMS_FIFO|RTEMS_SIMPLE_BINARY_SEMAPHORE|RTEMS_NO_INHERIT_PRIORITY|RTEMS_LOCAL|RTEMS_NO_PRIORITY_CEILING, 
0564         0,
0565         &pDev->dev_sem) != RTEMS_SUCCESSFUL ){
0566         printk("BRM: Failed to create device semaphore\n");
0567         return RTEMS_INTERNAL_ERROR;
0568     }
0569 
0570     /* Default to RT-mode */
0571     rt_init(pDev);
0572 
0573     return 0;
0574 }
0575 
0576 static int odd_parity(unsigned int data) {
0577     unsigned int i=0;
0578 
0579     while(data)
0580     {
0581         i++;
0582         data &= (data - 1);
0583     } 
0584 
0585     return !(i&1);
0586 }
0587 
0588 static void start_operation(brm_priv *brm) {
0589     unsigned int ctrl = READ_REG(&brm->regs->ctrl);
0590     brm->regs->ctrl = ctrl | 0x8000;
0591 }
0592 
0593 static void stop_operation(brm_priv *brm) {
0594     unsigned int ctrl = READ_REG(&brm->regs->ctrl);
0595   brm->regs->ctrl = ctrl & ~0x8000;
0596 }
0597 
0598 static int is_executing(brm_priv *brm) {
0599     unsigned int ctrl = READ_REG(&brm->regs->ctrl);
0600     return ((ctrl>>15) & 1);
0601 }
0602 
0603 static void clr_int_logs(struct irq_log_list *logs){
0604     int i;
0605     for(i=0; i<16; i++){
0606         logs[i].iiw = 0xffff;
0607         logs[i].iaw = 0x0;
0608     }
0609 }
0610 
0611 unsigned short b1553brm_rt_cmd_legalize[16] = {
0612     0,
0613     0,
0614     0,
0615     0,
0616     0,
0617     0,
0618     0xffff,
0619     0xffff,
0620     0xffff,
0621     0xfffd,
0622     0xfe01,
0623     0xfff2,
0624     0xffff,
0625     0xfffd,
0626     0xfe05,
0627     0xffff,
0628 };
0629 
0630 static rtems_device_driver rt_init(brm_priv *brm) {
0631     unsigned int i;
0632 
0633     brm->head = brm->tail = 0;
0634     brm->rx_blocking = brm->tx_blocking = 1;
0635 
0636     if ( brm->bm_event )
0637         free(brm->bm_event);
0638     brm->bm_event = NULL;
0639 
0640     if ( brm->rt_event )
0641         free(brm->rt_event);
0642     
0643     brm->bcmem = NULL;
0644     brm->rtmem = (void *)brm->mem;
0645 
0646     brm->rt_event = grlib_malloc(EVENT_QUEUE_SIZE*sizeof(*brm->rt_event));
0647   
0648     if (brm->rt_event == NULL) {
0649         DBG("BRM driver failed to allocated memory.");
0650         return RTEMS_NO_MEMORY;
0651     }
0652 
0653     brm->irq_log = (struct irq_log_list *)&brm->rtmem->irq_logs[0];
0654 
0655     brm->regs->ctrl   = 0x1912;  /* enable both buses, circular 1 bufmode, broadcast, interrupt log */
0656     brm->regs->oper   = 0x0900;  /* configure as RT, with addr 1 */
0657     brm->regs->imask     = BRM_RT_ILLCMD_IRQ|BRM_SUBAD_IRQ|BRM_TAPF_IRQ|BRM_DMAF_IRQ|BRM_WRAPF_IRQ|BRM_MERR_IRQ;
0658     brm->regs->dpoint   = 0;
0659     brm->regs->ipoint   = OFS(brm->rtmem->irq_logs[0]);
0660     brm->regs->enhanced  = 0x0000 | brm->cfg_freq;  /* BRM clocked with freq = 12,16,20 or 24MHz */
0661     brm->regs->w_ctrl   = (brm->cfg_clksel<<9) | (brm->cfg_clkdiv<<5) | 1;
0662     brm->regs->w_irqctrl = 6;
0663     brm->regs->w_ahbaddr = brm->memarea_base_remote;
0664         
0665     clr_int_logs(brm->irq_log);
0666 
0667     /* Initialize the Legalize register with standard values */
0668     for (i = 0; i < 16; i++) {
0669         brm->regs->rt_cmd_leg[i] = b1553brm_rt_cmd_legalize[i];
0670     }
0671 
0672     /* Init descriptor table 
0673      * 
0674      * Each circular buffer has room for 8 messages with up to 34 (32 data + miw + time) words (16b) in each.
0675      * The buffers must separated by 34 words.
0676      */
0677 
0678  
0679     /* RX Sub-address 0 - 31 */
0680     for (i = 0; i < 32; i++) {
0681         brm->rtmem->rxsubs[i].ctrl = 0x00E0;                /* Interrupt: INTX, IWA, and IBRD */
0682         brm->rtmem->rxsubs[i].top  = OFS(brm->rtmem->rxsuba_msgs[i]);            /* Top address */
0683         brm->rtmem->rxsubs[i].cur  = OFS(brm->rtmem->rxsuba_msgs[i]);            /* Current address */
0684         brm->rtmem->rxsubs[i].bot  = OFS(brm->rtmem->rxsuba_msgs[i+1]) - sizeof(struct msg)/2; /* Bottom address */ 
0685         brm->last_read[i] = OFS(brm->rtmem->rxsuba_msgs[i]);
0686     }
0687     /* TX Sub-address 0 - 31 */
0688     for (i = 0; i < 32; i++) {
0689         brm->rtmem->txsubs[i].ctrl  = 0x0060;                   /* Interrupt: IWA and IBRD */
0690         brm->rtmem->txsubs[i].top   = OFS(brm->rtmem->txsuba_msgs[i]);            /* Top address */
0691         brm->rtmem->txsubs[i].cur   = OFS(brm->rtmem->txsuba_msgs[i]);            /* Current address */
0692         brm->rtmem->txsubs[i].bot   = OFS(brm->rtmem->txsuba_msgs[i+1]) - sizeof(struct msg)/2; /* Bottom address */
0693         brm->last_read[i+32]  = OFS(brm->rtmem->txsuba_msgs[i]);
0694         brm->written[i] = OFS(brm->rtmem->txsuba_msgs[i]);
0695     }
0696     /* RX mode code 0 - 31 */
0697     for (i = 0; i < 32; i++) {
0698         brm->rtmem->rxmodes[i].ctrl = 0x00E0;                   /* Interrupt: INTX, IWA, and IBRD */
0699         brm->rtmem->rxmodes[i].top  = OFS(brm->rtmem->rxmode_msgs[i]);            /* Top address */
0700         brm->rtmem->rxmodes[i].cur  = OFS(brm->rtmem->rxmode_msgs[i]);            /* Current address */
0701         brm->rtmem->rxmodes[i].bot  = OFS(brm->rtmem->rxmode_msgs[i+1]) - sizeof(struct msg)/2; /* Bottom address */
0702         brm->last_read[i+64] = OFS(brm->rtmem->rxmode_msgs[i]);
0703     }   
0704     /* TX mode code 0 - 31 */
0705     for (i = 0; i < 32; i++) {
0706         brm->rtmem->txmodes[i].ctrl = 0x0060;                   /* Interrupt: IWA and IBRD */
0707         brm->rtmem->txmodes[i].top  = OFS(brm->rtmem->txmode_msgs[i]);            /* Top address */
0708         brm->rtmem->txmodes[i].cur  = OFS(brm->rtmem->txmode_msgs[i]);            /* Current address */
0709         brm->rtmem->txmodes[i].bot  = OFS(brm->rtmem->txmode_msgs[i+1]) - sizeof(struct msg)/2; /* Bottom address */
0710         brm->last_read[i+96] = OFS(brm->rtmem->txmode_msgs[i]);
0711     }
0712 
0713 #ifdef DEBUG
0714     printk("b1553BRM DMA_AREA: 0x%x\n", (unsigned int)brm->rtmem);
0715     printk("LOG: 0x%x\n", &brm->log[0]);
0716     printk("LOG_I: 0x%x\n", &brm->log_i);
0717 #endif
0718 
0719     brm->mode = BRM_MODE_RT;
0720 
0721     return RTEMS_SUCCESSFUL;
0722 }
0723 
0724 static rtems_device_driver bc_init(brm_priv *brm){
0725 
0726     if ( brm->bm_event )
0727         free(brm->bm_event);
0728     brm->bm_event = NULL;
0729 
0730     if ( brm->rt_event )
0731         free(brm->rt_event);
0732     brm->rt_event = NULL;
0733     
0734     brm->bcmem = (void *)brm->mem;
0735     brm->rtmem = NULL;
0736     brm->irq_log = (struct irq_log_list *)&brm->bcmem->irq_logs[0];
0737     
0738     brm->head = brm->tail = 0;
0739     brm->rx_blocking = brm->tx_blocking = 1;
0740     
0741     brm->regs->ctrl   = 0x0006;  /* ping pong enable and enable interrupt log */
0742     brm->regs->oper   = 0x0800;  /* configure as BC */
0743     brm->regs->imask     = BRM_EOL_IRQ|BRM_BC_ILLCMD_IRQ|BRM_ILLOP_IRQ|BRM_DMAF_IRQ|BRM_WRAPF_IRQ|BRM_MERR_IRQ;
0744     brm->regs->dpoint   = 0;
0745     brm->regs->ipoint   = OFS(brm->bcmem->irq_logs[0]);
0746     brm->regs->enhanced  = 0x0000 | (brm->cfg_freq&BRM_FREQ_MASK);  /* freq = 24 */
0747     brm->regs->w_ctrl   = (brm->cfg_clksel<<9) | (brm->cfg_clkdiv<<5) | 1;
0748     brm->regs->w_irqctrl = 6;
0749     brm->regs->w_ahbaddr = brm->memarea_base_remote;
0750     
0751     clr_int_logs(brm->irq_log);
0752     
0753     brm->mode = BRM_MODE_BC;
0754     
0755     return RTEMS_SUCCESSFUL;
0756 }
0757 
0758 static rtems_device_driver bm_init(brm_priv *brm) {
0759 
0760 
0761     brm->head = brm->tail = 0;
0762     brm->rx_blocking = brm->tx_blocking = 1;
0763 
0764     if ( brm->rt_event )
0765         free(brm->rt_event);
0766     brm->rt_event = NULL;
0767 
0768     if ( brm->bm_event )
0769         free(brm->bm_event);
0770     
0771     brm->bcmem = NULL;
0772     brm->rtmem = NULL;
0773     
0774     brm->bm_event    = grlib_malloc(EVENT_QUEUE_SIZE*sizeof(*brm->bm_event));
0775  
0776     if (brm->bm_event == NULL) {
0777         DBG("BRM driver failed to allocated memory.");
0778         return RTEMS_NO_MEMORY;
0779     }
0780 
0781     /* end of 16K, fits all current modes (128K, 16K) */
0782     brm->irq_log = (struct irq_log_list *)&brm->mem[8*1024-16*2];
0783 
0784     brm->regs->ctrl   = 0x0006;  /* ping pong enable and enable interrupt log */
0785     brm->regs->oper   = 0x0A00;  /* configure as BM */
0786     brm->regs->imask    = BRM_MBC_IRQ|BRM_MERR_IRQ|BRM_DMAF_IRQ;
0787     brm->regs->dpoint   = 0;
0788     brm->regs->ipoint   = OFS(brm->mem[8*1024-16*2]);
0789     brm->regs->mcpoint   = 0;      /* Command pointer */
0790     brm->regs->mdpoint   = 0x100;   /* Data pointer */
0791     brm->regs->mbc     = 1;    /* Block count */
0792     brm->regs->enhanced  = 0x0000 | (brm->cfg_freq&BRM_FREQ_MASK);  /* freq = 24 */
0793     brm->regs->w_ctrl   = (brm->cfg_clksel<<9) | (brm->cfg_clkdiv<<5) | 1;
0794     brm->regs->w_irqctrl = 6;
0795     brm->regs->w_ahbaddr = brm->memarea_base_remote;
0796     
0797     clr_int_logs(brm->irq_log);
0798     
0799     brm->mode = BRM_MODE_BM;
0800     
0801     return RTEMS_SUCCESSFUL;
0802 }
0803 
0804 
0805 static rtems_device_driver brm_initialize(rtems_device_major_number major, rtems_device_minor_number minor, void *arg)
0806 {
0807     return RTEMS_SUCCESSFUL;
0808 }
0809 
0810 static rtems_device_driver brm_open(rtems_device_major_number major, rtems_device_minor_number minor, void *arg) {
0811     brm_priv *brm;
0812     struct drvmgr_dev *dev;
0813 
0814     FUNCDBG("brm_open\n");
0815 
0816     if ( drvmgr_get_dev(&b1553brm_drv_info.general, minor, &dev) ) {
0817         DBG("Wrong minor %d\n", minor);
0818         return RTEMS_UNSATISFIED;
0819     }
0820     brm = (brm_priv *)dev->priv;
0821 
0822     if (rtems_semaphore_obtain(brm->dev_sem, RTEMS_NO_WAIT, RTEMS_NO_TIMEOUT) != RTEMS_SUCCESSFUL) {
0823         DBG("brm_open: resource in use\n");
0824         return RTEMS_RESOURCE_IN_USE; /* EBUSY */
0825     }
0826 
0827     /* Set defaults */
0828     brm->event_id = 0;
0829 
0830     start_operation(brm);
0831 
0832     /* Register interrupt routine */
0833     if ( drvmgr_interrupt_register(brm->dev, 0, "b1553brm", b1553brm_interrupt, brm) ) {
0834         rtems_semaphore_release(brm->dev_sem);
0835         return RTEMS_UNSATISFIED;
0836     }
0837 
0838     return RTEMS_SUCCESSFUL;
0839 }
0840  
0841 static rtems_device_driver brm_close(rtems_device_major_number major, rtems_device_minor_number minor, void *arg)
0842 {
0843     brm_priv *brm;
0844     struct drvmgr_dev *dev;
0845 
0846     FUNCDBG("brm_close");
0847     
0848     if ( drvmgr_get_dev(&b1553brm_drv_info.general, minor, &dev) ) {
0849         return RTEMS_UNSATISFIED;
0850     }
0851     brm = (brm_priv *)dev->priv;
0852 
0853     drvmgr_interrupt_unregister(brm->dev, 0, b1553brm_interrupt, brm);
0854 
0855     stop_operation(brm);
0856     rtems_semaphore_release(brm->dev_sem);
0857 
0858     return RTEMS_SUCCESSFUL;
0859 }
0860  
0861 static int get_rt_messages(brm_priv *brm, void *buf, unsigned int msg_count)
0862 {
0863     struct rt_msg *dest = (struct rt_msg *) buf;
0864     int count = 0;
0865 
0866     if (brm->head == brm->tail) {
0867         return 0;
0868     }
0869 
0870     do {
0871 
0872         DBG("rt read - head: %d, tail: %d\n", brm->head, brm->tail);
0873         dest[count++] = brm->rt_event[INDEX(brm->tail++)];
0874     } while (brm->head != brm->tail && count < msg_count);
0875 
0876     return count;
0877 }
0878 
0879 static int get_bm_messages(brm_priv *brm, void *buf, unsigned int msg_count)
0880 {
0881     struct bm_msg *dest = (struct bm_msg *) buf;
0882     int count = 0;
0883 
0884     if (brm->head == brm->tail) {
0885         return 0;
0886     }
0887 
0888     do {
0889 
0890         DBG("bm read - head: %d, tail: %d\n", brm->head, brm->tail);
0891         dest[count++] = brm->bm_event[INDEX(brm->tail++)];
0892 
0893     } while (brm->head != brm->tail && count < msg_count);
0894 
0895     return count;
0896 }
0897 
0898 static rtems_device_driver brm_read(rtems_device_major_number major, rtems_device_minor_number minor, void *arg)
0899 {
0900     rtems_libio_rw_args_t *rw_args;
0901     int count = 0;
0902     brm_priv *brm;
0903     struct drvmgr_dev *dev;
0904     int (*get_messages)(brm_priv *brm, void *buf, unsigned int count);
0905 
0906     if ( drvmgr_get_dev(&b1553brm_drv_info.general, minor, &dev) ) {
0907         return RTEMS_UNSATISFIED;
0908     }
0909     brm = (brm_priv *)dev->priv;
0910 
0911     if ( ! (brm->mode & (BRM_MODE_RT | BRM_MODE_BM)) ){
0912         return RTEMS_INVALID_NAME;
0913     }
0914 
0915     rw_args = (rtems_libio_rw_args_t *) arg;
0916 
0917     if ( ((READ_REG(&brm->regs->oper)>>8) & 3) == 1 ) { /* RT */
0918         get_messages = get_rt_messages;
0919     } else { /* BM */
0920         get_messages = get_bm_messages;
0921     }
0922 
0923     FUNCDBG("brm_read [%i,%i]: buf: 0x%x len: %i\n",major, minor, (unsigned int)rw_args->buffer,rw_args->count);
0924 
0925     while ( (count=get_messages(brm,rw_args->buffer, rw_args->count)) == 0 ) {
0926         if (brm->rx_blocking) {
0927             rtems_semaphore_obtain(brm->rx_sem, RTEMS_WAIT, RTEMS_NO_TIMEOUT);
0928         } else {
0929             /* Translates to EBUSY */
0930             return RTEMS_RESOURCE_IN_USE;
0931         }
0932     }
0933 
0934     rw_args->bytes_moved = count;
0935     return RTEMS_SUCCESSFUL;
0936 }
0937 
0938 static rtems_device_driver brm_write(rtems_device_major_number major, rtems_device_minor_number minor, void *arg)
0939 {
0940     rtems_libio_rw_args_t *rw_args;
0941     struct rt_msg *source;
0942     unsigned int count=0, current, next, descriptor, wc, suba;
0943     brm_priv *brm;
0944     struct drvmgr_dev *dev;
0945   
0946     if ( drvmgr_get_dev(&b1553brm_drv_info.general, minor, &dev) ) {
0947         return RTEMS_UNSATISFIED;
0948     }
0949     brm = (brm_priv *)dev->priv;
0950     
0951     if ( ! (brm->mode & BRM_MODE_RT) ){
0952         return RTEMS_INVALID_NAME;
0953     }
0954     
0955     rw_args = (rtems_libio_rw_args_t *) arg;
0956     source = (struct rt_msg *) rw_args->buffer;
0957 
0958     FUNCDBG("brm_write [%i,%i]: buf: 0x%x len: %i\n",major, minor, (unsigned int)rw_args->buffer,rw_args->count);
0959 
0960     do {
0961 
0962         descriptor = source[count].desc & 0x7F;
0963         suba       = descriptor-32;
0964         wc         = source[count].miw >> 11;
0965         wc = wc ? wc : 32;
0966 
0967         /* Only subaddress transmission is allowed with write */
0968         if (descriptor < 32 || descriptor >= 64)
0969             return RTEMS_INVALID_NAME;
0970 
0971         current = brm->desc[descriptor].cur; 
0972         next = brm->written[suba] + 2 + wc;
0973 
0974         if (brm->written[suba] < current) {
0975 
0976             if (next > current) {
0977 
0978                 /* No room in transmission buffer */ 
0979                 if (brm->tx_blocking && count == 0) {
0980                     rtems_semaphore_obtain(brm->tx_sem, RTEMS_WAIT, RTEMS_NO_TIMEOUT);
0981                 } else if ( count > 0 ) {
0982                     /* return the number of messages sent so far */
0983                     break;
0984                 } else {    
0985                     /* Translates to posix EBUSY */
0986                     return RTEMS_RESOURCE_IN_USE;
0987                 }
0988             }
0989         }
0990 
0991         memcpy((void *)&brm->mem[brm->written[suba]], &source[count], (2+wc)*2);
0992 
0993         count++;
0994 
0995         if (next >= brm->desc[descriptor].bot) {
0996             next = brm->desc[descriptor].top;
0997         }
0998         brm->written[suba] = next;
0999 
1000     }  while (count < rw_args->count);
1001 
1002     rw_args->bytes_moved = count; 
1003 
1004     return RTEMS_SUCCESSFUL;
1005 }
1006 
1007 static rtems_device_driver brm_control(rtems_device_major_number major, rtems_device_minor_number minor, void *arg)
1008 {
1009     
1010     unsigned int i=0;
1011     unsigned short ctrl, oper, cw1, cw2;
1012     rtems_libio_ioctl_args_t *ioarg = (rtems_libio_ioctl_args_t *) arg;
1013     unsigned int *data;
1014     struct bc_msg *cmd_list;
1015     brm_priv *brm;
1016     struct drvmgr_dev *dev;
1017     rtems_device_driver ret;
1018     int len, msglen;
1019 
1020     FUNCDBG("brm_control[%d]: [%i,%i]\n", minor, major, minor);
1021 
1022     if ( drvmgr_get_dev(&b1553brm_drv_info.general, minor, &dev) ) {
1023         return RTEMS_UNSATISFIED;
1024     }
1025     brm = (brm_priv *)dev->priv;
1026 
1027     if (!ioarg) {
1028         DBG("brm_control: invalid argument\n");
1029         return RTEMS_INVALID_NAME;
1030     }
1031 
1032         data = ioarg->buffer;
1033         cmd_list = (struct bc_msg *) ioarg->buffer;
1034 
1035     ioarg->ioctl_return = 0;
1036     switch (ioarg->command) {
1037 
1038         case BRM_SET_MODE:
1039         if ( data[0] > 2 )
1040             return RTEMS_INVALID_NAME;
1041         stop_operation(brm);
1042         if (data[0] == 0) {
1043             ret = bc_init(brm);
1044         } else if (data[0] == 1) { 
1045             ret = rt_init(brm);             
1046         } else if (data[0] == 2) { 
1047             ret = bm_init(brm);                     
1048         } else {
1049             ret = RTEMS_INVALID_NAME;
1050         }
1051         if ( ret != RTEMS_SUCCESSFUL)
1052             return ret;
1053 
1054         if ( brm->mode & (BRM_MODE_RT | BRM_MODE_BM ) )
1055             start_operation(brm);
1056         break;
1057 
1058         case BRM_SET_BUS:
1059         stop_operation(brm);
1060         ctrl = READ_REG(&brm->regs->ctrl);
1061         ctrl &= 0xE7FF;                               /* Clear bit 12-11 ...      */
1062         ctrl |= (data[0]&0x3)<<11;                    /* ... OR in new bus status */
1063         brm->regs->ctrl = ctrl;
1064         start_operation(brm);
1065         break;
1066 
1067         case BRM_SET_MSGTO:
1068         stop_operation(brm);
1069         ctrl = READ_REG(&brm->regs->ctrl);
1070         ctrl &= 0xFDFF;                               /* Clear bit 9 ...          */
1071         ctrl |= (data[0]&1)<<9;                       /* ... OR in new MSGTO      */
1072         brm->regs->ctrl = ctrl;
1073         start_operation(brm);
1074         break;
1075 
1076         case BRM_SET_RT_ADDR:   
1077         stop_operation(brm);
1078         oper = READ_REG(&brm->regs->oper);
1079         oper &= 0x03FF;                               /* Clear bit 15-10 ...      */
1080         oper |= (data[0]&0x1f)<<11;                   /* ... OR in new address    */
1081         oper |= odd_parity(data[0]&0x1f)<<10;         /* ... OR in parity         */
1082         brm->regs->oper = oper;
1083         start_operation(brm);
1084         break;
1085 
1086         case BRM_SET_STD:   
1087         stop_operation(brm);
1088         ctrl = READ_REG(&brm->regs->ctrl);
1089         ctrl &= 0xFF7F;                               /* Clear bit 7 ...           */
1090         ctrl |= (data[0]&1)<<7;                       /* ... OR in new ABSTD (1=A) */
1091         brm->regs->ctrl = ctrl;
1092         start_operation(brm);
1093         break;
1094 
1095         case BRM_SET_BCE:
1096         stop_operation(brm);
1097         ctrl = READ_REG(&brm->regs->ctrl);
1098         ctrl &= 0xFFEF;                               /* Clear bit 4 ...           */
1099         ctrl |= (data[0]&1)<<4;                       /* ... OR in new BCE         */
1100         brm->regs->ctrl = ctrl;
1101         start_operation(brm);
1102         break;
1103 
1104         case BRM_TX_BLOCK:
1105         brm->tx_blocking     = data[0];      
1106         break;
1107 
1108         case BRM_RX_BLOCK: 
1109         brm->rx_blocking     = data[0];   
1110         break;
1111 
1112         case BRM_DO_LIST:
1113         if ( brm->mode != BRM_MODE_BC ){
1114             return RTEMS_INVALID_NAME;
1115         }
1116 
1117         /* Check if we are bus controller */
1118         if ( ((READ_REG(&brm->regs->oper)>>8) & 3) != 0 ) {
1119             return RTEMS_INVALID_NAME;
1120         }
1121 
1122         /* Already processing list? */
1123         if (is_executing(brm)) {
1124             return RTEMS_RESOURCE_IN_USE;
1125         }
1126 
1127         /* clear any earlier releases */
1128         rtems_semaphore_obtain(brm->tx_sem, RTEMS_NO_WAIT, RTEMS_NO_TIMEOUT);
1129 
1130         brm->bc_list_fail = 0;
1131         brm->cur_list = cmd_list;
1132         brm->regs->dpoint = 0;
1133 
1134         i = 0;
1135         while ( (cmd_list[i].ctrl & BC_EOL) == 0) {
1136 
1137             ctrl = (4<<12) | (((cmd_list[i].ctrl&BC_BUSA)==BC_BUSA)<<9) | (((cmd_list[i].ctrl&BC_RTRT)==BC_RTRT)<<8);
1138 
1139             if (cmd_list[i].ctrl&BC_RTRT) {
1140                 cw1 = (cmd_list[i].rtaddr[0]<<11) | (0<<10) | (cmd_list[i].subaddr[0]<<5) | (cmd_list[i].wc & 0x1f); /* receive cw */
1141                 cw2 = (cmd_list[i].rtaddr[1]<<11) | (1<<10) | (cmd_list[i].subaddr[1]<<5) | (cmd_list[i].wc & 0x1f); /* transmit cw */
1142             } else {
1143                 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);
1144                 cw2 = 0;
1145             }
1146 
1147             /* Set up command block */
1148             brm->bcmem->descs[i].ctrl = ctrl;
1149             brm->bcmem->descs[i].cw1 = cw1;
1150             brm->bcmem->descs[i].cw2 = cw2;
1151             /* data pointer:
1152              * (&brm->bcmem->msg_data[i].data[0] & 0x1ffff) / 2 
1153              */
1154             brm->bcmem->descs[i].dptr = 1024+i*32;  /* data pointer */
1155             brm->bcmem->descs[i].tsw[0] = 0;
1156             brm->bcmem->descs[i].tsw[1] = 0;
1157             brm->bcmem->descs[i].ba = 0;
1158             brm->bcmem->descs[i].timer = 0;
1159 
1160             msglen = cmd_list[i].wc;
1161             if ( msglen == 0 ) 
1162                 msglen = 32;
1163             memcpy((void *)&brm->bcmem->msg_data[i].data[0], &cmd_list[i].data[0], msglen*2);
1164 
1165             i++;
1166         }
1167 
1168         brm->bcmem->descs[i].ctrl = 0; /* end of list */
1169 
1170         start_operation(brm);        
1171         break;  
1172 
1173         case BRM_LIST_DONE:
1174 
1175         if ( brm->mode != BRM_MODE_BC ){
1176             return RTEMS_INVALID_NAME;
1177         }
1178                 
1179         /* Check if we are bus controller */
1180         if ( ((READ_REG(&brm->regs->oper)>>8) & 3) != 0 ) {
1181             return RTEMS_INVALID_NAME;
1182         }
1183 
1184         if (is_executing(brm)) {
1185 
1186             data[0] = 0;
1187             if (brm->tx_blocking) {
1188                 rtems_semaphore_obtain(brm->tx_sem, RTEMS_WAIT, RTEMS_NO_TIMEOUT);
1189                 data[0] = 1;
1190                 if ( brm->bc_list_fail ){
1191                     return RTEMS_INVALID_NAME;
1192                 }
1193             } else {
1194                 return RTEMS_RESOURCE_IN_USE;
1195             }
1196         } else {
1197             data[0] = 1; /* done */
1198         }
1199 
1200         /* copy finished list results back into bc_msg array */
1201         i = 0;
1202         while ( (brm->cur_list[i].ctrl & BC_EOL) == 0) {
1203             if (READ_DMA(&brm->bcmem->descs[i].ctrl) & 1) {
1204                 brm->cur_list[i].ctrl |= 0x8000; /* Set BAME */ 
1205             }
1206             if (brm->cur_list[i].ctrl & BC_TR) {
1207                 /* RT Transmit command, copy received data */
1208                 len = brm->cur_list[i].wc;
1209                 if ( len == 0 )
1210                     len = 32;
1211                 while ( len-- > 0) {
1212                     brm->cur_list[i].data[len] = READ_DMA(&brm->bcmem->msg_data[i].data[len]);
1213                 }
1214             }
1215             brm->cur_list[i].tsw[0] = READ_DMA(&brm->bcmem->descs[i].tsw[0]);
1216             brm->cur_list[i].tsw[1] = READ_DMA(&brm->bcmem->descs[i].tsw[1]);
1217 
1218             i++;
1219         }
1220         break;
1221 
1222         case BRM_CLR_STATUS:
1223         brm->status = 0;
1224         break;
1225 
1226         case BRM_GET_STATUS: /* copy status */
1227         if ( !ioarg->buffer )
1228             return RTEMS_INVALID_NAME;
1229 
1230         *(unsigned int *)ioarg->buffer = brm->status;
1231         break;
1232     
1233         case BRM_SET_EVENTID:
1234         brm->event_id = (rtems_id)ioarg->buffer;
1235         break;
1236 
1237         default:
1238         return RTEMS_NOT_DEFINED;
1239     }
1240     return RTEMS_SUCCESSFUL;
1241 }
1242 
1243 static void b1553brm_interrupt(void *arg)
1244 {
1245     brm_priv *brm = arg;
1246     unsigned short descriptor, current, pending, miw, wc, tmp, ctrl;
1247     unsigned short msgadr, iaw, iiw;
1248     int len;
1249     int signal_event=0, wake_rx_task=0, wake_tx_task=0;
1250     unsigned int event_status=0;
1251     int accessed;
1252     #define SET_ERROR_DESCRIPTOR(descriptor) (event_status = (event_status & 0x0000ffff) | descriptor<<16)
1253         
1254     while( (iiw=READ_DMA(&brm->irq_log[brm->irq].iiw)) != 0xffff ){
1255         iaw=READ_DMA(&brm->irq_log[brm->irq].iaw);
1256         
1257         /* indicate that the interrupt log entry has been processed */
1258         brm->irq_log[brm->irq].iiw = 0xffff;
1259 
1260         /* Interpret interrupt log entry  */
1261         descriptor = iaw >> 2;
1262         pending    = iiw;
1263         brm->irq = (brm->irq + 1) % 16;
1264         
1265         /* Clear the log so that we */
1266 
1267 
1268         /* Subaddress accessed irq (RT only) 
1269          *
1270          * Can be either a receive or transmit command
1271          * as well as a mode code.
1272         */
1273         if (pending & BRM_SUBAD_IRQ) {
1274 
1275             /* Pointer to next free message in circular buffer */
1276             current = READ_DMA(&brm->desc[descriptor].cur);
1277             ctrl = READ_DMA(&brm->desc[descriptor].ctrl);
1278 #ifdef DEBUG
1279             brm->log[brm->log_i++ % EVENT_QUEUE_SIZE] = (0xff<<16);
1280             brm->log[brm->log_i++ % EVENT_QUEUE_SIZE] = current;
1281             brm->log[brm->log_i++ % EVENT_QUEUE_SIZE] = ctrl;
1282             brm->log[brm->log_i++ % EVENT_QUEUE_SIZE] = 0;
1283 #endif
1284             accessed = ctrl & 0x10;
1285             /* Note that current may be equal to bot and top when 
1286              * circular buffer one can handle one message.
1287              */
1288             if ( accessed )
1289               do {
1290                 msgadr = brm->last_read[descriptor];
1291 
1292                 /* Get word count */
1293                 miw = READ_DMA(&brm->mem[msgadr]);
1294                 wc  = miw >> 11;
1295 
1296                 /* Data received */
1297                 if (descriptor < 32) {
1298                     wc = wc ? wc : 32;
1299                 }
1300                 /* Data transmitted */ 
1301                 else if (descriptor < 64) {
1302                     wc = wc ? wc : 32;  
1303                     wake_tx_task=1;
1304                 }
1305                 /* RX Mode code */
1306                 else if (descriptor < 96) {
1307                     wc = (wc>>4);
1308                 }
1309                 /* TX Mode code */
1310                 else if (descriptor < 128) {
1311                     wc = (wc>>4);
1312                 }
1313 
1314 #ifdef DEBUG            
1315                 brm->log[brm->log_i++ % EVENT_QUEUE_SIZE] = (descriptor << 16) | wc; 
1316                 brm->log[brm->log_i++ % EVENT_QUEUE_SIZE] = current;
1317                 brm->log[brm->log_i++ % EVENT_QUEUE_SIZE] = msgadr;
1318 #endif
1319 
1320                 /* If there is room in the event queue, copy the event there */
1321                 if (brm->head - brm->tail != EVENT_QUEUE_SIZE) {
1322 
1323                     /* Copy to event queue */
1324                     brm->rt_event[INDEX(brm->head)].miw = READ_DMA(&brm->mem[msgadr]);
1325                     brm->rt_event[INDEX(brm->head)].time = READ_DMA(&brm->mem[msgadr+1]);
1326                     len = wc;
1327                     while( len-- > 0){
1328                         brm->rt_event[INDEX(brm->head)].data[len] = READ_DMA(&brm->mem[msgadr+2+len]);
1329                     }
1330                     brm->rt_event[INDEX(brm->head)].desc = descriptor;
1331                     brm->head++;
1332                 }
1333                 else {
1334                     /* Indicate overrun */
1335                     brm->rt_event[INDEX(brm->head)].desc |= 0x8000;
1336                 }
1337 
1338                 msgadr += (2+wc);
1339 
1340                 if (msgadr >= READ_DMA(&brm->desc[descriptor].bot)) {
1341                     msgadr = READ_DMA(&brm->desc[descriptor].top);
1342                 }
1343                 brm->last_read[descriptor] = msgadr;
1344 
1345 #ifdef DEBUG
1346                 brm->log[brm->log_i++ % EVENT_QUEUE_SIZE] = msgadr;
1347 #endif
1348                 wake_rx_task = 1;
1349               } while ( (msgadr=brm->last_read[descriptor]) != current );
1350         }
1351 
1352         if (pending & BRM_EOL_IRQ) {  
1353             wake_tx_task = 1;
1354         }
1355 
1356         if (pending & BRM_BC_ILLCMD_IRQ) {
1357             brm->bc_list_fail = 1;
1358             wake_tx_task = 1;
1359             SET_ERROR_DESCRIPTOR(descriptor);
1360             FUNCDBG("BRM: ILLCMD IRQ\n\r");
1361         }
1362 
1363         /* Monitor irq */
1364         if (pending & BRM_MBC_IRQ) { 
1365 
1366             stop_operation(brm);
1367             brm->regs->mbc = 1;
1368             start_operation(brm);
1369 
1370             /* If there is room in the event queue, copy the event there */
1371             if (brm->head - brm->tail != EVENT_QUEUE_SIZE) {
1372 
1373                 /* Copy to event queue */
1374 
1375                 brm->bm_event[INDEX(brm->head)].miw  =  READ_DMA(&brm->mem[0]);
1376                 brm->bm_event[INDEX(brm->head)].cw1  =  READ_DMA(&brm->mem[1]);
1377                 brm->bm_event[INDEX(brm->head)].cw2  =  READ_DMA(&brm->mem[2]);
1378                 brm->bm_event[INDEX(brm->head)].sw1  =  READ_DMA(&brm->mem[4]);
1379                 brm->bm_event[INDEX(brm->head)].sw2  =  READ_DMA(&brm->mem[5]);
1380                 brm->bm_event[INDEX(brm->head)].time =  READ_DMA(&brm->mem[6]);
1381 
1382                 len = 32;
1383                 while ( len-- ){
1384                     brm->bm_event[INDEX(brm->head)].data[len] =  READ_DMA(&brm->mem[0x100+len]);
1385                     len--;
1386                     brm->bm_event[INDEX(brm->head)].data[len] =  READ_DMA(&brm->mem[0x100+len]);
1387                     len--;
1388                     brm->bm_event[INDEX(brm->head)].data[len] =  READ_DMA(&brm->mem[0x100+len]);
1389                     len--;
1390                     brm->bm_event[INDEX(brm->head)].data[len] =  READ_DMA(&brm->mem[0x100+len]);
1391                 }
1392 /*              memcpy((void *)brm->bm_event[INDEX(brm->head)].data, &brm->mem[0x100], 32);*/
1393 
1394 #ifdef DEBUG
1395                 brm->log[brm->log_i++ % EVENT_QUEUE_SIZE] = READ_REG(&brm->regs->mbc) & 0xffff;
1396                 brm->log[brm->log_i++ % EVENT_QUEUE_SIZE] = READ_DMA(&brm->mem[0]);
1397                 brm->log[brm->log_i++ % EVENT_QUEUE_SIZE] = READ_DMA(&brm->mem[1]);
1398                 brm->log[brm->log_i++ % EVENT_QUEUE_SIZE] = READ_DMA(&brm->mem[4]);
1399 #endif
1400 
1401                 brm->head++;
1402 
1403             }
1404             else {
1405                 /* Indicate overrun */
1406                 brm->bm_event[INDEX(brm->head)].miw |= 0x8000;
1407             }
1408 
1409             /* Wake any blocking thread */
1410             wake_rx_task = 1;
1411         }
1412 
1413         /* The reset of the interrupts 
1414          * cause a event to be signalled
1415          * so that user can handle error.
1416          */
1417         if ( pending & BRM_RT_ILLCMD_IRQ){
1418             FUNCDBG("BRM: BRM_RT_ILLCMD_IRQ\n\r");
1419             brm->status |= BRM_RT_ILLCMD_IRQ;
1420             event_status |= BRM_RT_ILLCMD_IRQ;
1421             SET_ERROR_DESCRIPTOR(descriptor);
1422             signal_event=1;
1423         }
1424 
1425         if ( pending & BRM_ILLOP_IRQ){
1426             FUNCDBG("BRM: BRM_ILLOP_IRQ\n\r");
1427             brm->bc_list_fail = 1;
1428             wake_tx_task = 1;
1429             event_status |= BRM_ILLOP_IRQ;
1430             SET_ERROR_DESCRIPTOR(descriptor);           
1431             signal_event=1;
1432         }
1433 
1434         if ( pending & BRM_MERR_IRQ){
1435             FUNCDBG("BRM: BRM_MERR_IRQ\n\r");
1436             event_status |= BRM_MERR_IRQ;
1437             SET_ERROR_DESCRIPTOR(descriptor);
1438             signal_event=1;
1439         }
1440         /* Clear Block Accessed Bit */ 
1441         tmp = READ_DMA(&brm->desc[descriptor].ctrl);
1442         brm->desc[descriptor].ctrl = tmp & ~0x10;
1443 #ifdef DEBUG
1444         brm->log[brm->log_i++ % EVENT_QUEUE_SIZE] = (0xfe<<16);
1445         brm->log[brm->log_i++ % EVENT_QUEUE_SIZE] = 0;
1446         brm->log[brm->log_i++ % EVENT_QUEUE_SIZE] = tmp & ~0x10;
1447         brm->log[brm->log_i++ % EVENT_QUEUE_SIZE] = tmp;
1448 #endif
1449     } /* While */
1450 
1451     /* clear interrupt flags & handle Hardware errors */
1452     pending = READ_REG(&brm->regs->ipend);
1453 
1454     if ( pending & BRM_DMAF_IRQ){
1455         FUNCDBG("BRM: BRM_DMAF_IRQ\n\r");
1456         event_status |= BRM_DMAF_IRQ;
1457         signal_event=1;
1458     }
1459 
1460     if ( pending & BRM_WRAPF_IRQ){
1461         FUNCDBG("BRM: BRM_WRAPF_IRQ\n\r");
1462         event_status |= BRM_WRAPF_IRQ;
1463         signal_event=1;
1464     }
1465 
1466     if ( pending & BRM_TAPF_IRQ){
1467         FUNCDBG("BRM: BRM_TAPF_IRQ\n\r");
1468         event_status |= BRM_TAPF_IRQ;
1469         signal_event=1;
1470     }
1471 
1472     /* Copy current mask to status mask */
1473     if ( event_status ){
1474         if ( event_status & 0xffff0000 )
1475             brm->status &= 0x0000ffff;
1476         brm->status |= event_status;
1477     }
1478 
1479     /* Wake any blocked rx thread only on receive interrupts */
1480     if ( wake_rx_task ) {
1481         rtems_semaphore_release(brm->rx_sem);
1482     }
1483 
1484     /* Wake any blocked tx thread only on transmit interrupts */
1485     if ( wake_tx_task ) {
1486         rtems_semaphore_release(brm->tx_sem);
1487     }        
1488 
1489     /* signal event once */
1490     if ( signal_event && (brm->event_id!=0) ){
1491         rtems_event_send(brm->event_id, event_status);
1492     }
1493 
1494 }
1495 
1496 void b1553brm_print_dev(struct drvmgr_dev *dev, int options)
1497 {
1498     brm_priv *pDev = dev->priv;
1499     struct brm_reg *regs = pDev->regs;
1500 
1501     /* Print */
1502     printf("--- B1553BRM[%d] %s ---\n", pDev->minor, pDev->devName);
1503     printf(" REGS:            0x%x\n", (unsigned int)pDev->regs);
1504     printf(" IRQ:             %d\n", pDev->irqno);
1505     switch (pDev->mode) {
1506         case BRM_MODE_BC:
1507             printf(" MODE:            BC\n");
1508             printf(" DESCS:           0x%x\n", (unsigned int)&pDev->bcmem->descs[0]);
1509             printf(" DATA:            0x%x\n", (unsigned int)&pDev->bcmem->msg_data[0].data[0]);
1510             printf(" IRQLOG:          0x%x\n", (unsigned int)&pDev->bcmem->irq_logs[0]);
1511             break;
1512         case BRM_MODE_BM:
1513             printf(" MODE:            BM\n");
1514             break;
1515         case BRM_MODE_RT:
1516             printf(" MODE:            RT\n");
1517             printf(" RXSUBS:          0x%x\n", (unsigned int)&pDev->rtmem->rxsubs[0]);
1518             printf(" TXSUBS:          0x%x\n", (unsigned int)&pDev->rtmem->txsubs[0]);
1519             printf(" RXMODES:         0x%x\n", (unsigned int)&pDev->rtmem->rxmodes[0]);
1520             printf(" TXOMODES:        0x%x\n", (unsigned int)&pDev->rtmem->txmodes[0]);
1521             printf(" RXSUBS MSGS:     0x%x\n", (unsigned int)&pDev->rtmem->rxsuba_msgs[0]);
1522             printf(" TXSUBS MSGS:     0x%x\n", (unsigned int)&pDev->rtmem->txsuba_msgs[0]);
1523             printf(" RXMODES MSGS:    0x%x\n", (unsigned int)&pDev->rtmem->rxmode_msgs[0]);
1524             printf(" TXMODES MSGS:    0x%x\n", (unsigned int)&pDev->rtmem->txmode_msgs[0]);
1525             printf(" IRQLOG:          0x%x\n", (unsigned int)&pDev->rtmem->irq_logs[0]);
1526             break;
1527     }
1528     printf(" CTRL:            0x%x\n", regs->ctrl);
1529     printf(" OPER:            0x%x\n", regs->oper);
1530     printf(" CUR_CMD:         0x%x\n", regs->cur_cmd);
1531     printf(" IMASK:           0x%x\n", regs->imask);
1532     printf(" IPEND:           0x%x\n", regs->ipend);
1533     printf(" IPOINT:          0x%x\n", regs->ipoint);
1534     printf(" BIT_REG:         0x%x\n", regs->bit_reg);
1535     printf(" TTAG:            0x%x\n", regs->ttag);
1536     printf(" DPOINT:          0x%x\n", regs->dpoint);
1537     printf(" SW:              0x%x\n", regs->sw);
1538     printf(" INITCOUNT:       0x%x\n", regs->initcount);
1539     printf(" MCPOINT:         0x%x\n", regs->mcpoint);
1540     printf(" MDPOINT:         0x%x\n", regs->mdpoint);
1541     printf(" MBC:             0x%x\n", regs->mbc);
1542     printf(" MFILTA:          0x%x\n", regs->mfilta);
1543     printf(" MFILTB:          0x%x\n", regs->mfiltb);
1544     printf(" ENHANCED:        0x%x\n", regs->enhanced);
1545     printf(" W_CTRL:          0x%x\n", regs->w_ctrl);
1546     printf(" W_IRQCTRL:       0x%x\n", regs->w_irqctrl);
1547     printf(" W_AHBADDR:       0x%x\n", regs->w_ahbaddr);
1548 }
1549 
1550 void b1553brm_print(int options)
1551 {
1552     struct amba_drv_info *drv = &b1553brm_drv_info;
1553     struct drvmgr_dev *dev;
1554 
1555     dev = drv->general.dev;
1556     while(dev) {
1557         b1553brm_print_dev(dev, options);
1558         dev = dev->next_in_drv;
1559     }
1560 }