source: rtems/bsps/shared/grlib/1553/b1553brm.c @ 7eb606d3

5
Last change on this file since 7eb606d3 was 7eb606d3, checked in by Sebastian Huber <sebastian.huber@…>, on 12/22/18 at 17:31:04

grlib: Move source files

Update #3678.

  • Property mode set to 100644
File size: 42.2 KB
Line 
1/*
2 *  BRM driver
3 *
4 *  COPYRIGHT (c) 2006.
5 *  Cobham Gaisler AB.
6 *
7 *  The license and distribution terms for this file may be
8 *  found in the file LICENSE in this distribution or at
9 *  http://www.rtems.org/license/LICENSE.
10 */
11
12/********** Set defaults **********/
13
14/* default to 16K memory layout */
15#define DMA_MEM_128K
16#if !defined(DMA_MEM_128K)
17 #define DMA_MEM_16K
18#endif
19
20#include <bsp.h>
21#include <rtems/libio.h>
22#include <stdlib.h>
23#include <stdio.h>
24#include <string.h>
25#include <assert.h>
26#include <ctype.h>
27#include <rtems/bspIo.h>
28
29#include <drvmgr/drvmgr.h>
30#include <grlib/b1553brm.h>
31#include <grlib/ambapp.h>
32#include <grlib/ambapp_bus.h>
33
34#include <grlib/grlib_impl.h>
35
36/* Uncomment for debug output */
37/*#define DEBUG 1
38#define FUNCDEBUG 1*/
39#undef DEBUG
40#undef FUNCDEBUG
41
42/* EVENT_QUEUE_SIZE sets the size of the event queue
43 */
44#define EVENT_QUEUE_SIZE           1024 
45
46
47#define INDEX(x) ( x&(EVENT_QUEUE_SIZE-1) )
48
49#if 0
50#define DBG(x...) printk(x)
51#else
52#define DBG(x...)
53#endif
54
55#ifdef FUNCDEBUG
56#define FUNCDBG(x...) printk(x)
57#else
58#define FUNCDBG(x...)
59#endif
60
61#define READ_REG(address) (*(volatile unsigned int *)address)
62#define READ_DMA(address) _BRM_REG_READ16((unsigned int)address)
63static __inline__ unsigned short _BRM_REG_READ16(unsigned int addr) {
64        unsigned short tmp;
65        __asm__ (" lduha [%1]1, %0 "
66          : "=r"(tmp)
67          : "r"(addr)
68        );
69        return tmp;
70}
71
72static rtems_device_driver brm_initialize(rtems_device_major_number major, rtems_device_minor_number minor, void *arg);
73static rtems_device_driver brm_open(rtems_device_major_number major, rtems_device_minor_number minor, void *arg);
74static rtems_device_driver brm_close(rtems_device_major_number major, rtems_device_minor_number minor, void *arg);
75static rtems_device_driver brm_read(rtems_device_major_number major, rtems_device_minor_number minor, void *arg);
76static rtems_device_driver brm_write(rtems_device_major_number major, rtems_device_minor_number minor, void *arg);
77static rtems_device_driver brm_control(rtems_device_major_number major, rtems_device_minor_number minor, void *arg);
78
79#define BRM_DRIVER_TABLE_ENTRY { brm_initialize, brm_open, brm_close, brm_read, brm_write, brm_control }
80
81static rtems_driver_address_table b1553brm_driver = BRM_DRIVER_TABLE_ENTRY;
82
83struct msg {
84        unsigned short miw;
85        unsigned short time;
86        unsigned short data[32];
87};
88#if defined(DMA_MEM_128K)
89struct circ_buf {
90        struct msg msgs[9];
91};
92#elif defined(DMA_MEM_16K)
93/* two message queue */
94struct circ_buf_2 {
95        struct msg msgs[2];
96};
97/* one message queue */
98struct circ_buf_1 {
99        struct msg msgs[1];
100};
101#endif
102
103struct irq_log_list {
104        volatile unsigned short iiw;
105        volatile unsigned short iaw;
106};
107
108typedef struct {
109
110        struct drvmgr_dev *dev; /* Driver manager device */
111        char devName[32]; /* Device Name */
112        struct brm_reg *regs;
113
114        unsigned int memarea_base;
115        unsigned int memarea_base_remote;
116        unsigned int cfg_clksel;
117        unsigned int cfg_clkdiv;
118        unsigned int cfg_freq;
119
120        /* BRM descriptors */
121        struct desc_table {
122                volatile unsigned short ctrl;       
123                volatile unsigned short top;
124                volatile unsigned short cur;
125                volatile unsigned short bot;
126        } *desc;
127
128        volatile unsigned short *mem;
129        /* bc mem struct */
130        struct {
131                /* BC Descriptors */
132                struct {
133                        unsigned short ctrl; /* control */
134                        unsigned short cw1;  /* Command word 1*/
135                        unsigned short cw2;  /* Command word 1*/
136                        unsigned short dptr; /* Data pointer in halfword offset from bcmem */
137                        unsigned short tsw[2]; /* status word 1 & 2 */
138                        unsigned short ba;     /* branch address */
139                        unsigned short timer;  /* timer value */
140                } descs[128]; /* 2k (1024 half words) */
141
142                /* message data */
143                struct {
144                        unsigned short data[32]; /* 1 message's data */
145                } msg_data[128]; /* 8k */
146
147#if defined(DMA_MEM_128K)
148                /* offset to last 64bytes of 128k */
149                unsigned short unused[(64*1024-(128*8+128*32))-16*2];
150#elif defined(DMA_MEM_16K)
151                unsigned short unused[(8*1024-(128*8+128*32))-16*2];
152#endif
153                /* interrupt log at 64 bytes from end */
154                struct irq_log_list irq_logs[16];
155        } *bcmem;
156
157#if defined(DMA_MEM_128K)
158        /* Memory structure of a RT being inited, just used
159         * for RT initialization.
160         *
161         * *mesgs[32] fit each minimally 8 messages per sub address.
162         */
163        struct {
164                /* RX Sub Address descriptors */
165                struct desc_table rxsubs[32];
166                /* TX Sub Address descriptors */
167                struct desc_table txsubs[32];
168                /* RX mode code descriptors */
169                struct desc_table rxmodes[32];
170                /* TX mode code descriptors */
171                struct desc_table txmodes[32];
172
173                /* RX Sub Address messages */
174                struct circ_buf rxsuba_msgs[32];
175                /* TX Sub Address messages */
176                struct circ_buf txsuba_msgs[32];
177                /* RX Mode Code messages */
178                struct circ_buf rxmode_msgs[32];
179                /* RX Mode Code messages */
180                struct circ_buf txmode_msgs[32];
181
182                /* offset to last 64bytes of 128k: tot-used-needed */
183                unsigned short unused[(64*1024-(4*32*4+4*32*9*34))-16*2];
184
185                /* interrupt log at 64 bytes from end */
186                struct irq_log_list irq_logs[16];
187        } *rtmem;
188#elif defined(DMA_MEM_16K)
189        /* Memory structure of a RT being inited, just used
190         * for RT initialization.
191         *
192         * circ_buf_2 *mesgs[32] fit each minimally 2 messages per queue.
193         * circ_buf_1 *mesgs[32] fit each minimally 1 messages per queue.
194         */
195        struct {
196                /* RX Sub Address descriptors */
197                struct desc_table rxsubs[32];
198                /* TX Sub Address descriptors */
199                struct desc_table txsubs[32];
200                /* RX mode code descriptors */
201                struct desc_table rxmodes[32];
202                /* TX mode code descriptors */
203                struct desc_table txmodes[32];
204
205                /* RX Sub Address messages */
206                struct circ_buf_2 rxsuba_msgs[32];
207                /* TX Sub Address messages */
208                struct circ_buf_2 txsuba_msgs[32];
209                /* RX Mode Code messages */
210                struct circ_buf_2 rxmode_msgs[32];
211                /* RX Mode Code messages */
212                struct circ_buf_1 txmode_msgs[32];
213
214                /* offset to last 64bytes of 16k: tot-used-needed */
215                unsigned short unused[8*1024 -(4*32*4 +3*32*2*34 +1*32*1*34) -16*2];
216
217                /* interrupt log at 64 bytes from end */
218                struct irq_log_list irq_logs[16];
219        } *rtmem;
220#else
221        #error You must define one DMA_MEM_???K
222#endif
223
224        /* Interrupt log list */
225        struct irq_log_list *irq_log;
226        unsigned int irq;
227
228        /* Received events waiting to be read */
229        struct rt_msg *rt_event;
230        struct bm_msg *bm_event;
231
232        unsigned int head, tail;
233
234        unsigned int last_read[128];
235        unsigned int written[32];
236
237        struct bc_msg *cur_list;
238
239        int tx_blocking, rx_blocking;
240
241        rtems_id rx_sem, tx_sem, dev_sem;
242        int minor;
243        int irqno;
244        unsigned int mode;
245#ifdef DEBUG                   
246        unsigned int log[EVENT_QUEUE_SIZE*4];
247        unsigned int log_i;
248#endif
249
250        rtems_id event_id; /* event that may be signalled upon errors, needs to be set through ioctl command BRM_SET_EVENTID */
251        unsigned int status;
252        int bc_list_fail;
253} brm_priv;
254
255static void b1553brm_interrupt(void *arg);
256static rtems_device_driver rt_init(brm_priv *brm);
257
258#define OFS(ofs) (((unsigned int)&ofs & 0x1ffff)>>1)
259
260static int b1553brm_driver_io_registered = 0;
261static rtems_device_major_number b1553brm_driver_io_major = 0;
262
263/******************* Driver manager interface ***********************/
264
265/* Driver prototypes */
266int b1553brm_register_io(rtems_device_major_number *m);
267int b1553brm_device_init(brm_priv *pDev);
268
269int b1553brm_init2(struct drvmgr_dev *dev);
270int b1553brm_init3(struct drvmgr_dev *dev);
271int b1553brm_remove(struct drvmgr_dev *dev);
272
273struct drvmgr_drv_ops b1553brm_ops =
274{
275        .init = {NULL, b1553brm_init2, b1553brm_init3, NULL},
276        .remove = b1553brm_remove,
277        .info = NULL
278};
279
280struct amba_dev_id b1553brm_ids[] =
281{
282        {VENDOR_GAISLER, GAISLER_B1553BRM},
283        {0, 0}          /* Mark end of table */
284};
285
286struct amba_drv_info b1553brm_drv_info =
287{
288        {
289                DRVMGR_OBJ_DRV,                         /* Driver */
290                NULL,                                   /* Next driver */
291                NULL,                                   /* Device list */
292                DRIVER_AMBAPP_GAISLER_B1553BRM_ID,      /* Driver ID */
293                "B1553BRM_DRV",                         /* Driver Name */
294                DRVMGR_BUS_TYPE_AMBAPP,                 /* Bus Type */
295                &b1553brm_ops,
296                NULL,                                   /* Funcs */
297                0,                                      /* No devices yet */
298                0,
299        },
300        &b1553brm_ids[0]
301};
302
303void b1553brm_register_drv (void)
304{
305        DBG("Registering B1553BRM driver\n");
306        drvmgr_drv_register(&b1553brm_drv_info.general);
307}
308
309int b1553brm_init2(struct drvmgr_dev *dev)
310{
311        brm_priv *priv;
312
313        DBG("B1553BRM[%d] on bus %s\n", dev->minor_drv, dev->parent->dev->name);
314        priv = dev->priv = grlib_calloc(1, sizeof(*priv));
315        if ( !priv )
316                return DRVMGR_NOMEM;
317        priv->dev = dev;
318
319        /* This core will not find other cores, so we wait for init2() */
320
321        return DRVMGR_OK;
322}
323
324int b1553brm_init3(struct drvmgr_dev *dev)
325{
326        brm_priv *priv;
327        char prefix[32];
328        rtems_status_code status;
329
330        priv = dev->priv;
331
332        /* Do initialization */
333
334        if ( b1553brm_driver_io_registered == 0) {
335                /* Register the I/O driver only once for all cores */
336                if ( b1553brm_register_io(&b1553brm_driver_io_major) ) {
337                        /* Failed to register I/O driver */
338                        dev->priv = NULL;
339                        return DRVMGR_FAIL;
340                }
341
342                b1553brm_driver_io_registered = 1;
343        }
344
345        /* I/O system registered and initialized
346         * Now we take care of device initialization.
347         */
348
349        if ( b1553brm_device_init(priv) ) {
350                return DRVMGR_FAIL;
351        }
352
353        /* Get Filesystem name prefix */
354        prefix[0] = '\0';
355        if ( drvmgr_get_dev_prefix(dev, prefix) ) {
356                /* Failed to get prefix, make sure of a unique FS name
357                 * by using the driver minor.
358                 */
359                sprintf(priv->devName, "/dev/b1553brm%d", dev->minor_drv);
360        } else {
361                /* Got special prefix, this means we have a bus prefix
362                 * And we should use our "bus minor"
363                 */
364                sprintf(priv->devName, "/dev/%sb1553brm%d", prefix, dev->minor_bus);
365        }
366
367        /* Register Device */
368        status = rtems_io_register_name(priv->devName, b1553brm_driver_io_major, dev->minor_drv);
369        if (status != RTEMS_SUCCESSFUL) {
370                return DRVMGR_FAIL;
371        }
372
373        return DRVMGR_OK;
374}
375
376int b1553brm_remove(struct drvmgr_dev *dev)
377{
378        /* Stop more tasks to open driver */
379
380        /* Throw out all tasks using this driver */
381
382        /* Unregister I/O node */
383
384        /* Unregister and disable Interrupt */
385
386        /* Free device memory */
387
388        /* Return sucessfully */
389
390        return DRVMGR_OK;
391}
392
393/******************* Driver Implementation ***********************/
394
395int b1553brm_register_io(rtems_device_major_number *m)
396{
397        rtems_status_code r;
398
399        if ((r = rtems_io_register_driver(0, &b1553brm_driver, m)) == RTEMS_SUCCESSFUL) {
400                DBG("B1553BRM driver successfully registered, major: %d\n", *m);
401        } else {
402                switch(r) {
403                case RTEMS_TOO_MANY:
404                        printk("B1553BRM rtems_io_register_driver failed: RTEMS_TOO_MANY\n");
405                        return -1;
406                case RTEMS_INVALID_NUMBER: 
407                        printk("B1553BRM rtems_io_register_driver failed: RTEMS_INVALID_NUMBER\n");
408                        return -1;
409                case RTEMS_RESOURCE_IN_USE:
410                        printk("B1553BRM rtems_io_register_driver failed: RTEMS_RESOURCE_IN_USE\n");
411                        return -1;
412                default:
413                        printk("B1553BRM rtems_io_register_driver failed\n");
414                        return -1;
415                }
416        }
417        return 0;
418}
419
420int b1553brm_device_init(brm_priv *pDev)
421{
422        struct amba_dev_info *ambadev;
423        struct ambapp_core *pnpinfo;
424        union drvmgr_key_value *value;
425        unsigned int mem;
426        int size;
427
428        /* Get device information from AMBA PnP information */
429        ambadev = (struct amba_dev_info *)pDev->dev->businfo;
430        if ( ambadev == NULL ) {
431                return -1;
432        }
433        pnpinfo = &ambadev->info;
434        pDev->irqno = pnpinfo->irq;
435        /* Two versions of the BRM core. One where the registers are accessed using the AHB bus
436         * and one where the APB bus is used
437         */
438        if ( pnpinfo->ahb_slv ) {
439                /* Registers accessed over AHB */
440                pDev->regs = (struct brm_reg *)pnpinfo->ahb_slv->start[0];
441        } else {
442                /* Registers accessed over APB */
443                pDev->regs = (struct brm_reg *)pnpinfo->apb_slv->start;
444        }
445        pDev->minor = pDev->dev->minor_drv;
446#ifdef DEBUG
447        pDev->log_i = 0;       
448        memset(pDev->log,0,sizeof(pDev->log));
449#endif
450
451#ifdef DMA_MEM_128K
452        size = 128 * 1024;
453#else
454        size = 16 * 1024;
455#endif
456
457        /* Get memory configuration from bus resources */
458        value = drvmgr_dev_key_get(pDev->dev, "dmaBaseAdr", DRVMGR_KT_POINTER);
459        if (value)
460                mem = (unsigned int)value->ptr;
461
462        if (value && (mem & 1)) {
463                /* Remote address, address as BRM looks at it. */
464
465                /* Translate the base address into an address that the the CPU can understand */
466                pDev->memarea_base_remote = mem & ~1;
467                drvmgr_translate_check(pDev->dev, DMAMEM_TO_CPU,
468                                        (void *)pDev->memarea_base_remote,
469                                        (void **)&pDev->memarea_base,
470                                        size);
471        } else {
472                if (!value) {
473                        /* Use dynamically allocated memory + 128k for
474                         * alignment
475                         */
476                        mem = (unsigned int)grlib_malloc(size + 128 * 1024);
477                        if (!mem){
478                                printk("BRM: Failed to allocate HW memory\n\r");
479                                return -1;
480                        }
481                        /* align memory to 128k boundary */
482                        pDev->memarea_base = (mem + 0x1ffff) & ~0x1ffff;
483                } else {
484                        pDev->memarea_base = mem;
485                }
486
487                /* Translate the base address into an address that the BRM core can understand */
488                drvmgr_translate_check(pDev->dev, CPUMEM_TO_DMA,
489                                        (void *)pDev->memarea_base,
490                                        (void **)&pDev->memarea_base_remote,
491                                        size);
492        }
493
494        /* clear the used memory */
495        memset((char *)pDev->memarea_base, 0, size);
496
497        /* Set base address of all descriptors */
498        pDev->desc = (struct desc_table *) pDev->memarea_base;
499        pDev->mem = (volatile unsigned short *) pDev->memarea_base;
500        pDev->irq_log   = (struct irq_log_list *)(pDev->memarea_base + (0xFFE0<<1)); /* last 64byte */
501
502        pDev->bm_event = NULL;
503        pDev->rt_event = NULL;
504
505        pDev->cfg_clksel = 0;
506        pDev->cfg_clkdiv = 0;
507        pDev->cfg_freq = BRM_FREQ_24MHZ;
508
509        value = drvmgr_dev_key_get(pDev->dev, "clkSel", DRVMGR_KT_INT);
510        if ( value ) {
511                pDev->cfg_clksel = value->i & CLKSEL_MASK;
512        }
513
514        value = drvmgr_dev_key_get(pDev->dev, "clkDiv", DRVMGR_KT_INT);
515        if ( value ) {
516                pDev->cfg_clkdiv = value->i & CLKDIV_MASK;
517        }
518
519        value = drvmgr_dev_key_get(pDev->dev, "coreFreq", DRVMGR_KT_INT);
520        if ( value ) {
521                pDev->cfg_freq = value->i & BRM_FREQ_MASK;
522        }
523
524        /* Sel clock so that we can write to BRM's registers */
525        pDev->regs->w_ctrl = (pDev->cfg_clksel<<9) | (pDev->cfg_clkdiv<<5);
526        /* Reset BRM core */
527        pDev->regs->w_ctrl = 1<<10 | READ_REG(&pDev->regs->w_ctrl);
528
529        /* RX Semaphore created with count = 0 */
530        if ( rtems_semaphore_create(rtems_build_name('B', 'M', 'R', '0' + pDev->minor),
531                0,
532                RTEMS_FIFO|RTEMS_SIMPLE_BINARY_SEMAPHORE|RTEMS_NO_INHERIT_PRIORITY|RTEMS_LOCAL|RTEMS_NO_PRIORITY_CEILING,
533                0,
534                &pDev->rx_sem) != RTEMS_SUCCESSFUL ) {
535                printk("BRM: Failed to create rx semaphore\n");
536                return RTEMS_INTERNAL_ERROR;
537        }
538
539        /* TX Semaphore created with count = 1 */
540        if ( rtems_semaphore_create(rtems_build_name('B', 'M', 'T', '0' + pDev->minor),
541                1,
542                RTEMS_FIFO|RTEMS_SIMPLE_BINARY_SEMAPHORE|RTEMS_NO_INHERIT_PRIORITY|RTEMS_LOCAL|RTEMS_NO_PRIORITY_CEILING,
543                0,
544                &pDev->tx_sem) != RTEMS_SUCCESSFUL ){
545                printk("BRM: Failed to create tx semaphore\n");
546                return RTEMS_INTERNAL_ERROR;
547        }
548
549        /* Device Semaphore created with count = 1 */
550        if ( rtems_semaphore_create(rtems_build_name('B', 'M', 'D', '0' + pDev->minor),
551                1,
552                RTEMS_FIFO|RTEMS_SIMPLE_BINARY_SEMAPHORE|RTEMS_NO_INHERIT_PRIORITY|RTEMS_LOCAL|RTEMS_NO_PRIORITY_CEILING,
553                0,
554                &pDev->dev_sem) != RTEMS_SUCCESSFUL ){
555                printk("BRM: Failed to create device semaphore\n");
556                return RTEMS_INTERNAL_ERROR;
557        }
558
559        /* Default to RT-mode */
560        rt_init(pDev);
561
562        return 0;
563}
564
565static int odd_parity(unsigned int data) {
566    unsigned int i=0;
567
568    while(data)
569    {
570        i++;
571        data &= (data - 1);
572    }
573
574    return !(i&1);
575}
576
577static void start_operation(brm_priv *brm) {
578        unsigned int ctrl = READ_REG(&brm->regs->ctrl);
579        brm->regs->ctrl = ctrl | 0x8000;
580}
581
582static void stop_operation(brm_priv *brm) {
583        unsigned int ctrl = READ_REG(&brm->regs->ctrl);
584  brm->regs->ctrl = ctrl & ~0x8000;
585}
586
587static int is_executing(brm_priv *brm) {
588        unsigned int ctrl = READ_REG(&brm->regs->ctrl);
589        return ((ctrl>>15) & 1);
590}
591
592static void clr_int_logs(struct irq_log_list *logs){
593        int i;
594        for(i=0; i<16; i++){
595                logs[i].iiw = 0xffff;
596                logs[i].iaw = 0x0;
597        }
598}
599
600unsigned short b1553brm_rt_cmd_legalize[16] = {
601        0,
602        0,
603        0,
604        0,
605        0,
606        0,
607        0xffff,
608        0xffff,
609        0xffff,
610        0xfffd,
611        0xfe01,
612        0xfff2,
613        0xffff,
614        0xfffd,
615        0xfe05,
616        0xffff,
617};
618
619static rtems_device_driver rt_init(brm_priv *brm) {
620        unsigned int i;
621
622        brm->head = brm->tail = 0;
623        brm->rx_blocking = brm->tx_blocking = 1;
624
625        if ( brm->bm_event )
626                free(brm->bm_event);
627        brm->bm_event = NULL;
628
629        if ( brm->rt_event )
630                free(brm->rt_event);
631       
632        brm->bcmem = NULL;
633        brm->rtmem = (void *)brm->mem;
634
635        brm->rt_event = grlib_malloc(EVENT_QUEUE_SIZE*sizeof(*brm->rt_event));
636 
637        if (brm->rt_event == NULL) {
638                DBG("BRM driver failed to allocated memory.");
639                return RTEMS_NO_MEMORY;
640        }
641
642        brm->irq_log = (struct irq_log_list *)&brm->rtmem->irq_logs[0];
643
644        brm->regs->ctrl   = 0x1912;  /* enable both buses, circular 1 bufmode, broadcast, interrupt log */
645        brm->regs->oper   = 0x0900;  /* configure as RT, with addr 1 */
646        brm->regs->imask         = BRM_RT_ILLCMD_IRQ|BRM_SUBAD_IRQ|BRM_TAPF_IRQ|BRM_DMAF_IRQ|BRM_WRAPF_IRQ|BRM_MERR_IRQ;
647        brm->regs->dpoint       = 0;
648        brm->regs->ipoint       = OFS(brm->rtmem->irq_logs[0]);
649        brm->regs->enhanced  = 0x0000 | brm->cfg_freq;  /* BRM clocked with freq = 12,16,20 or 24MHz */
650        brm->regs->w_ctrl       = (brm->cfg_clksel<<9) | (brm->cfg_clkdiv<<5) | 1;
651        brm->regs->w_irqctrl = 6;
652        brm->regs->w_ahbaddr = brm->memarea_base_remote;
653               
654        clr_int_logs(brm->irq_log);
655
656        /* Initialize the Legalize register with standard values */
657        for (i = 0; i < 16; i++) {
658                brm->regs->rt_cmd_leg[i] = b1553brm_rt_cmd_legalize[i];
659        }
660
661        /* Init descriptor table
662         *
663         * Each circular buffer has room for 8 messages with up to 34 (32 data + miw + time) words (16b) in each.
664         * The buffers must separated by 34 words.
665         */
666
667 
668        /* RX Sub-address 0 - 31 */
669        for (i = 0; i < 32; i++) {
670                brm->rtmem->rxsubs[i].ctrl = 0x00E0;                            /* Interrupt: INTX, IWA, and IBRD */
671                brm->rtmem->rxsubs[i].top  = OFS(brm->rtmem->rxsuba_msgs[i]);                /* Top address */
672                brm->rtmem->rxsubs[i].cur  = OFS(brm->rtmem->rxsuba_msgs[i]);                /* Current address */
673                brm->rtmem->rxsubs[i].bot  = OFS(brm->rtmem->rxsuba_msgs[i+1]) - sizeof(struct msg)/2; /* Bottom address */     
674                brm->last_read[i] = OFS(brm->rtmem->rxsuba_msgs[i]);
675        }
676        /* TX Sub-address 0 - 31 */
677        for (i = 0; i < 32; i++) {
678                brm->rtmem->txsubs[i].ctrl  = 0x0060;                                   /* Interrupt: IWA and IBRD */
679                brm->rtmem->txsubs[i].top   = OFS(brm->rtmem->txsuba_msgs[i]);                    /* Top address */
680                brm->rtmem->txsubs[i].cur   = OFS(brm->rtmem->txsuba_msgs[i]);                    /* Current address */
681                brm->rtmem->txsubs[i].bot   = OFS(brm->rtmem->txsuba_msgs[i+1]) - sizeof(struct msg)/2; /* Bottom address */
682                brm->last_read[i+32]  = OFS(brm->rtmem->txsuba_msgs[i]);
683                brm->written[i] = OFS(brm->rtmem->txsuba_msgs[i]);
684        }
685        /* RX mode code 0 - 31 */
686        for (i = 0; i < 32; i++) {
687                brm->rtmem->rxmodes[i].ctrl = 0x00E0;                                   /* Interrupt: INTX, IWA, and IBRD */
688                brm->rtmem->rxmodes[i].top  = OFS(brm->rtmem->rxmode_msgs[i]);                    /* Top address */
689                brm->rtmem->rxmodes[i].cur  = OFS(brm->rtmem->rxmode_msgs[i]);                    /* Current address */
690                brm->rtmem->rxmodes[i].bot  = OFS(brm->rtmem->rxmode_msgs[i+1]) - sizeof(struct msg)/2; /* Bottom address */
691                brm->last_read[i+64] = OFS(brm->rtmem->rxmode_msgs[i]);
692        }   
693        /* TX mode code 0 - 31 */
694        for (i = 0; i < 32; i++) {
695                brm->rtmem->txmodes[i].ctrl = 0x0060;                                   /* Interrupt: IWA and IBRD */
696                brm->rtmem->txmodes[i].top  = OFS(brm->rtmem->txmode_msgs[i]);                    /* Top address */
697                brm->rtmem->txmodes[i].cur  = OFS(brm->rtmem->txmode_msgs[i]);                    /* Current address */
698                brm->rtmem->txmodes[i].bot  = OFS(brm->rtmem->txmode_msgs[i+1]) - sizeof(struct msg)/2; /* Bottom address */
699                brm->last_read[i+96] = OFS(brm->rtmem->txmode_msgs[i]);
700        }
701
702#ifdef DEBUG
703        printk("b1553BRM DMA_AREA: 0x%x\n", (unsigned int)brm->rtmem);
704        printk("LOG: 0x%x\n", &brm->log[0]);
705        printk("LOG_I: 0x%x\n", &brm->log_i);
706#endif
707
708        brm->mode = BRM_MODE_RT;
709
710        return RTEMS_SUCCESSFUL;
711}
712
713static rtems_device_driver bc_init(brm_priv *brm){
714
715        if ( brm->bm_event )
716                free(brm->bm_event);
717        brm->bm_event = NULL;
718
719        if ( brm->rt_event )
720                free(brm->rt_event);
721        brm->rt_event = NULL;
722       
723        brm->bcmem = (void *)brm->mem;
724        brm->rtmem = NULL;
725        brm->irq_log = (struct irq_log_list *)&brm->bcmem->irq_logs[0];
726       
727        brm->head = brm->tail = 0;
728        brm->rx_blocking = brm->tx_blocking = 1;
729       
730        brm->regs->ctrl   = 0x0006;  /* ping pong enable and enable interrupt log */
731        brm->regs->oper   = 0x0800;  /* configure as BC */
732        brm->regs->imask         = BRM_EOL_IRQ|BRM_BC_ILLCMD_IRQ|BRM_ILLOP_IRQ|BRM_DMAF_IRQ|BRM_WRAPF_IRQ|BRM_MERR_IRQ;
733        brm->regs->dpoint       = 0;
734        brm->regs->ipoint       = OFS(brm->bcmem->irq_logs[0]);
735        brm->regs->enhanced  = 0x0000 | (brm->cfg_freq&BRM_FREQ_MASK);  /* freq = 24 */
736        brm->regs->w_ctrl       = (brm->cfg_clksel<<9) | (brm->cfg_clkdiv<<5) | 1;
737        brm->regs->w_irqctrl = 6;
738        brm->regs->w_ahbaddr = brm->memarea_base_remote;
739       
740        clr_int_logs(brm->irq_log);
741       
742        brm->mode = BRM_MODE_BC;
743       
744        return RTEMS_SUCCESSFUL;
745}
746
747static rtems_device_driver bm_init(brm_priv *brm) {
748
749
750        brm->head = brm->tail = 0;
751        brm->rx_blocking = brm->tx_blocking = 1;
752
753        if ( brm->rt_event )
754                free(brm->rt_event);
755        brm->rt_event = NULL;
756
757        if ( brm->bm_event )
758                free(brm->bm_event);
759       
760        brm->bcmem = NULL;
761        brm->rtmem = NULL;
762       
763        brm->bm_event    = grlib_malloc(EVENT_QUEUE_SIZE*sizeof(*brm->bm_event));
764 
765        if (brm->bm_event == NULL) {
766                DBG("BRM driver failed to allocated memory.");
767                return RTEMS_NO_MEMORY;
768        }
769
770        /* end of 16K, fits all current modes (128K, 16K) */
771        brm->irq_log = (struct irq_log_list *)&brm->mem[8*1024-16*2];
772
773        brm->regs->ctrl   = 0x0006;  /* ping pong enable and enable interrupt log */
774        brm->regs->oper   = 0x0A00;  /* configure as BM */
775        brm->regs->imask        = BRM_MBC_IRQ|BRM_MERR_IRQ|BRM_DMAF_IRQ;
776        brm->regs->dpoint       = 0;
777        brm->regs->ipoint       = OFS(brm->mem[8*1024-16*2]);
778        brm->regs->mcpoint   = 0;          /* Command pointer */
779        brm->regs->mdpoint   = 0x100;   /* Data pointer */
780        brm->regs->mbc     = 1;    /* Block count */
781        brm->regs->enhanced  = 0x0000 | (brm->cfg_freq&BRM_FREQ_MASK);  /* freq = 24 */
782        brm->regs->w_ctrl       = (brm->cfg_clksel<<9) | (brm->cfg_clkdiv<<5) | 1;
783        brm->regs->w_irqctrl = 6;
784        brm->regs->w_ahbaddr = brm->memarea_base_remote;
785       
786        clr_int_logs(brm->irq_log);
787       
788        brm->mode = BRM_MODE_BM;
789       
790        return RTEMS_SUCCESSFUL;
791}
792
793
794static rtems_device_driver brm_initialize(rtems_device_major_number major, rtems_device_minor_number minor, void *arg)
795{
796        return RTEMS_SUCCESSFUL;
797}
798
799static rtems_device_driver brm_open(rtems_device_major_number major, rtems_device_minor_number minor, void *arg) {
800        brm_priv *brm;
801        struct drvmgr_dev *dev;
802
803        FUNCDBG("brm_open\n");
804
805        if ( drvmgr_get_dev(&b1553brm_drv_info.general, minor, &dev) ) {
806                DBG("Wrong minor %d\n", minor);
807                return RTEMS_UNSATISFIED;
808        }
809        brm = (brm_priv *)dev->priv;
810
811        if (rtems_semaphore_obtain(brm->dev_sem, RTEMS_NO_WAIT, RTEMS_NO_TIMEOUT) != RTEMS_SUCCESSFUL) {
812                DBG("brm_open: resource in use\n");
813                return RTEMS_RESOURCE_IN_USE; /* EBUSY */
814        }
815
816        /* Set defaults */
817        brm->event_id = 0;
818
819        start_operation(brm);
820
821        /* Register interrupt routine */
822        if ( drvmgr_interrupt_register(brm->dev, 0, "b1553brm", b1553brm_interrupt, brm) ) {
823                rtems_semaphore_release(brm->dev_sem);
824                return RTEMS_UNSATISFIED;
825        }
826
827        return RTEMS_SUCCESSFUL;
828}
829 
830static rtems_device_driver brm_close(rtems_device_major_number major, rtems_device_minor_number minor, void *arg)
831{
832        brm_priv *brm;
833        struct drvmgr_dev *dev;
834
835        FUNCDBG("brm_close");
836       
837        if ( drvmgr_get_dev(&b1553brm_drv_info.general, minor, &dev) ) {
838                return RTEMS_UNSATISFIED;
839        }
840        brm = (brm_priv *)dev->priv;
841
842        drvmgr_interrupt_unregister(brm->dev, 0, b1553brm_interrupt, brm);
843
844        stop_operation(brm);
845        rtems_semaphore_release(brm->dev_sem);
846
847        return RTEMS_SUCCESSFUL;
848}
849 
850static int get_rt_messages(brm_priv *brm, void *buf, unsigned int msg_count)
851{
852        struct rt_msg *dest = (struct rt_msg *) buf;
853        int count = 0;
854
855        if (brm->head == brm->tail) {
856                return 0;
857        }
858
859        do {
860
861                DBG("rt read - head: %d, tail: %d\n", brm->head, brm->tail);
862                dest[count++] = brm->rt_event[INDEX(brm->tail++)];
863        } while (brm->head != brm->tail && count < msg_count);
864
865        return count;
866}
867
868static int get_bm_messages(brm_priv *brm, void *buf, unsigned int msg_count)
869{
870        struct bm_msg *dest = (struct bm_msg *) buf;
871        int count = 0;
872
873        if (brm->head == brm->tail) {
874                return 0;
875        }
876
877        do {
878
879                DBG("bm read - head: %d, tail: %d\n", brm->head, brm->tail);
880                dest[count++] = brm->bm_event[INDEX(brm->tail++)];
881
882        } while (brm->head != brm->tail && count < msg_count);
883
884        return count;
885}
886
887static rtems_device_driver brm_read(rtems_device_major_number major, rtems_device_minor_number minor, void *arg)
888{
889        rtems_libio_rw_args_t *rw_args;
890        int count = 0;
891        brm_priv *brm;
892        struct drvmgr_dev *dev;
893        int (*get_messages)(brm_priv *brm, void *buf, unsigned int count);
894
895        if ( drvmgr_get_dev(&b1553brm_drv_info.general, minor, &dev) ) {
896                return RTEMS_UNSATISFIED;
897        }
898        brm = (brm_priv *)dev->priv;
899
900        if ( ! (brm->mode & (BRM_MODE_RT | BRM_MODE_BM)) ){
901                return RTEMS_INVALID_NAME;
902        }
903
904        rw_args = (rtems_libio_rw_args_t *) arg;
905
906        if ( ((READ_REG(&brm->regs->oper)>>8) & 3) == 1 ) { /* RT */
907                get_messages = get_rt_messages;
908        } else { /* BM */
909                get_messages = get_bm_messages;
910        }
911
912        FUNCDBG("brm_read [%i,%i]: buf: 0x%x len: %i\n",major, minor, (unsigned int)rw_args->buffer,rw_args->count);
913
914        while ( (count=get_messages(brm,rw_args->buffer, rw_args->count)) == 0 ) {
915                if (brm->rx_blocking) {
916                        rtems_semaphore_obtain(brm->rx_sem, RTEMS_WAIT, RTEMS_NO_TIMEOUT);
917                } else {
918                        /* Translates to EBUSY */
919                        return RTEMS_RESOURCE_IN_USE;
920                }
921        }
922
923        rw_args->bytes_moved = count;
924        return RTEMS_SUCCESSFUL;
925}
926
927static rtems_device_driver brm_write(rtems_device_major_number major, rtems_device_minor_number minor, void *arg)
928{
929        rtems_libio_rw_args_t *rw_args;
930        struct rt_msg *source;
931        unsigned int count=0, current, next, descriptor, wc, suba;
932        brm_priv *brm;
933        struct drvmgr_dev *dev;
934 
935        if ( drvmgr_get_dev(&b1553brm_drv_info.general, minor, &dev) ) {
936                return RTEMS_UNSATISFIED;
937        }
938        brm = (brm_priv *)dev->priv;
939       
940        if ( ! (brm->mode & BRM_MODE_RT) ){
941                return RTEMS_INVALID_NAME;
942        }
943       
944        rw_args = (rtems_libio_rw_args_t *) arg;
945        source = (struct rt_msg *) rw_args->buffer;
946
947        FUNCDBG("brm_write [%i,%i]: buf: 0x%x len: %i\n",major, minor, (unsigned int)rw_args->buffer,rw_args->count);
948
949        do {
950
951                descriptor = source[count].desc & 0x7F;
952                suba       = descriptor-32;
953                wc         = source[count].miw >> 11;
954                wc = wc ? wc : 32;
955
956                /* Only subaddress transmission is allowed with write */
957                if (descriptor < 32 || descriptor >= 64)
958                        return RTEMS_INVALID_NAME;
959
960                current = brm->desc[descriptor].cur;
961                next = brm->written[suba] + 2 + wc;
962
963                if (brm->written[suba] < current) {
964
965                        if (next > current) {
966
967                                /* No room in transmission buffer */
968                                if (brm->tx_blocking && count == 0) {
969                                        rtems_semaphore_obtain(brm->tx_sem, RTEMS_WAIT, RTEMS_NO_TIMEOUT);
970                                } else if ( count > 0 ) {
971                                        /* return the number of messages sent so far */
972                                        break;
973                                } else {       
974                                        /* Translates to posix EBUSY */
975                                        return RTEMS_RESOURCE_IN_USE;
976                                }
977                        }
978                }
979
980                memcpy((void *)&brm->mem[brm->written[suba]], &source[count], (2+wc)*2);
981
982                count++;
983
984                if (next >= brm->desc[descriptor].bot) {
985                        next = brm->desc[descriptor].top;
986                }
987                brm->written[suba] = next;
988
989        }  while (count < rw_args->count);
990
991        rw_args->bytes_moved = count;
992
993        if (count >= 0) {
994                return RTEMS_SUCCESSFUL;
995        }
996        return RTEMS_UNSATISFIED;
997}
998
999static rtems_device_driver brm_control(rtems_device_major_number major, rtems_device_minor_number minor, void *arg)
1000{
1001   
1002        unsigned int i=0;
1003        unsigned short ctrl, oper, cw1, cw2;
1004        rtems_libio_ioctl_args_t *ioarg = (rtems_libio_ioctl_args_t *) arg;
1005        unsigned int *data = ioarg->buffer;
1006        struct bc_msg *cmd_list = (struct bc_msg *) ioarg->buffer;
1007        brm_priv *brm;
1008        struct drvmgr_dev *dev;
1009        rtems_device_driver ret;
1010        int len, msglen;
1011
1012        FUNCDBG("brm_control[%d]: [%i,%i]\n", minor, major, minor);
1013
1014        if ( drvmgr_get_dev(&b1553brm_drv_info.general, minor, &dev) ) {
1015                return RTEMS_UNSATISFIED;
1016        }
1017        brm = (brm_priv *)dev->priv;
1018
1019        if (!ioarg) {
1020                DBG("brm_control: invalid argument\n");
1021                return RTEMS_INVALID_NAME;
1022        }
1023
1024        ioarg->ioctl_return = 0;
1025        switch (ioarg->command) {
1026
1027                case BRM_SET_MODE:
1028                if ( data[0] > 2 )
1029                        return RTEMS_INVALID_NAME;
1030                stop_operation(brm);
1031                if (data[0] == 0) {
1032                        ret = bc_init(brm);
1033                } else if (data[0] == 1) {
1034                        ret = rt_init(brm);                             
1035                } else if (data[0] == 2) {
1036                        ret = bm_init(brm);                                             
1037                } else {
1038                        ret = RTEMS_INVALID_NAME;
1039                }
1040                if ( ret != RTEMS_SUCCESSFUL)
1041                        return ret;
1042
1043                if ( brm->mode & (BRM_MODE_RT | BRM_MODE_BM ) )
1044                        start_operation(brm);
1045                break;
1046
1047                case BRM_SET_BUS:
1048                stop_operation(brm);
1049                ctrl = READ_REG(&brm->regs->ctrl);
1050                ctrl &= 0xE7FF;                               /* Clear bit 12-11 ...      */
1051                ctrl |= (data[0]&0x3)<<11;                    /* ... OR in new bus status */
1052                brm->regs->ctrl = ctrl;
1053                start_operation(brm);
1054                break;
1055
1056                case BRM_SET_MSGTO:
1057                stop_operation(brm);
1058                ctrl = READ_REG(&brm->regs->ctrl);
1059                ctrl &= 0xFDFF;                               /* Clear bit 9 ...          */
1060                ctrl |= (data[0]&1)<<9;                       /* ... OR in new MSGTO      */
1061                brm->regs->ctrl = ctrl;
1062                start_operation(brm);
1063                break;
1064
1065                case BRM_SET_RT_ADDR:   
1066                stop_operation(brm);
1067                oper = READ_REG(&brm->regs->oper);
1068                oper &= 0x03FF;                               /* Clear bit 15-10 ...      */
1069                oper |= (data[0]&0x1f)<<11;                   /* ... OR in new address    */
1070                oper |= odd_parity(data[0]&0x1f)<<10;         /* ... OR in parity         */
1071                brm->regs->oper = oper;
1072                start_operation(brm);
1073                break;
1074
1075                case BRM_SET_STD:   
1076                stop_operation(brm);
1077                ctrl = READ_REG(&brm->regs->ctrl);
1078                ctrl &= 0xFF7F;                               /* Clear bit 7 ...           */
1079                ctrl |= (data[0]&1)<<7;                       /* ... OR in new ABSTD (1=A) */
1080                brm->regs->ctrl = ctrl;
1081                start_operation(brm);
1082                break;
1083
1084                case BRM_SET_BCE:
1085                stop_operation(brm);
1086                ctrl = READ_REG(&brm->regs->ctrl);
1087                ctrl &= 0xFFEF;                               /* Clear bit 4 ...           */
1088                ctrl |= (data[0]&1)<<4;                       /* ... OR in new BCE         */
1089                brm->regs->ctrl = ctrl;
1090                start_operation(brm);
1091                break;
1092
1093                case BRM_TX_BLOCK:
1094                brm->tx_blocking     = data[0];     
1095                break;
1096
1097                case BRM_RX_BLOCK:
1098                brm->rx_blocking     = data[0];   
1099                break;
1100
1101                case BRM_DO_LIST:
1102                if ( brm->mode != BRM_MODE_BC ){
1103                        return RTEMS_INVALID_NAME;
1104                }
1105
1106                /* Check if we are bus controller */
1107                if ( ((READ_REG(&brm->regs->oper)>>8) & 3) != 0 ) {
1108                        return RTEMS_INVALID_NAME;
1109                }
1110
1111                /* Already processing list? */
1112                if (is_executing(brm)) {
1113                        return RTEMS_RESOURCE_IN_USE;
1114                }
1115
1116                /* clear any earlier releases */
1117                rtems_semaphore_obtain(brm->tx_sem, RTEMS_NO_WAIT, RTEMS_NO_TIMEOUT);
1118
1119                brm->bc_list_fail = 0;
1120                brm->cur_list = cmd_list;
1121                brm->regs->dpoint = 0;
1122
1123                i = 0;
1124                while ( (cmd_list[i].ctrl & BC_EOL) == 0) {
1125
1126                        ctrl = (4<<12) | (((cmd_list[i].ctrl&BC_BUSA)==BC_BUSA)<<9) | (((cmd_list[i].ctrl&BC_RTRT)==BC_RTRT)<<8);
1127
1128                        if (cmd_list[i].ctrl&BC_RTRT) {
1129                                cw1 = (cmd_list[i].rtaddr[0]<<11) | (0<<10) | (cmd_list[i].subaddr[0]<<5) | (cmd_list[i].wc & 0x1f); /* receive cw */
1130                                cw2 = (cmd_list[i].rtaddr[1]<<11) | (1<<10) | (cmd_list[i].subaddr[1]<<5) | (cmd_list[i].wc & 0x1f); /* transmit cw */
1131                        } else {
1132                                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);
1133                                cw2 = 0;
1134                        }
1135
1136                        /* Set up command block */
1137                        brm->bcmem->descs[i].ctrl = ctrl;
1138                        brm->bcmem->descs[i].cw1 = cw1;
1139                        brm->bcmem->descs[i].cw2 = cw2;
1140                        /* data pointer:
1141                         * (&brm->bcmem->msg_data[i].data[0] & 0x1ffff) / 2
1142                         */
1143                        brm->bcmem->descs[i].dptr = 1024+i*32;  /* data pointer */
1144                        brm->bcmem->descs[i].tsw[0] = 0;
1145                        brm->bcmem->descs[i].tsw[1] = 0;
1146                        brm->bcmem->descs[i].ba = 0;
1147                        brm->bcmem->descs[i].timer = 0;
1148
1149                        msglen = cmd_list[i].wc;
1150                        if ( msglen == 0 )
1151                                msglen = 32;
1152                        memcpy((void *)&brm->bcmem->msg_data[i].data[0], &cmd_list[i].data[0], msglen*2);
1153
1154                        i++;
1155                }
1156
1157                brm->bcmem->descs[i].ctrl = 0; /* end of list */
1158
1159                start_operation(brm);       
1160                break; 
1161
1162                case BRM_LIST_DONE:
1163
1164                if ( brm->mode != BRM_MODE_BC ){
1165                        return RTEMS_INVALID_NAME;
1166                }
1167                               
1168                /* Check if we are bus controller */
1169                if ( ((READ_REG(&brm->regs->oper)>>8) & 3) != 0 ) {
1170                        return RTEMS_INVALID_NAME;
1171                }
1172
1173                if (is_executing(brm)) {
1174
1175                        data[0] = 0;
1176                        if (brm->tx_blocking) {
1177                                rtems_semaphore_obtain(brm->tx_sem, RTEMS_WAIT, RTEMS_NO_TIMEOUT);
1178                                data[0] = 1;
1179                                if ( brm->bc_list_fail ){
1180                                        return RTEMS_INVALID_NAME;
1181                                }
1182                        } else {
1183                                return RTEMS_RESOURCE_IN_USE;
1184                        }
1185                } else {
1186                        data[0] = 1; /* done */
1187                }
1188
1189                /* copy finished list results back into bc_msg array */
1190                i = 0;
1191                while ( (brm->cur_list[i].ctrl & BC_EOL) == 0) {
1192                        if (READ_DMA(&brm->bcmem->descs[i].ctrl) & 1) {
1193                                brm->cur_list[i].ctrl |= 0x8000; /* Set BAME */
1194                        }
1195                        if (brm->cur_list[i].ctrl & BC_TR) {
1196                                /* RT Transmit command, copy received data */
1197                                len = brm->cur_list[i].wc;
1198                                if ( len == 0 )
1199                                        len = 32;
1200                                while ( len-- > 0) {
1201                                        brm->cur_list[i].data[len] = READ_DMA(&brm->bcmem->msg_data[i].data[len]);
1202                                }
1203                        }
1204                        brm->cur_list[i].tsw[0] = READ_DMA(&brm->bcmem->descs[i].tsw[0]);
1205                        brm->cur_list[i].tsw[1] = READ_DMA(&brm->bcmem->descs[i].tsw[1]);
1206
1207                        i++;
1208                }
1209                break;
1210
1211                case BRM_CLR_STATUS:
1212                brm->status = 0;
1213                break;
1214
1215                case BRM_GET_STATUS: /* copy status */
1216                if ( !ioarg->buffer )
1217                        return RTEMS_INVALID_NAME;
1218
1219                *(unsigned int *)ioarg->buffer = brm->status;
1220                break;
1221   
1222                case BRM_SET_EVENTID:
1223                brm->event_id = (rtems_id)ioarg->buffer;
1224                break;
1225
1226                default:
1227                return RTEMS_NOT_DEFINED;
1228        }
1229        return RTEMS_SUCCESSFUL;
1230}
1231
1232static void b1553brm_interrupt(void *arg)
1233{
1234        brm_priv *brm = arg;
1235        unsigned short descriptor, current, pending, miw, wc, tmp, ctrl;
1236        unsigned short msgadr, iaw, iiw;
1237        int len;
1238        int signal_event=0, wake_rx_task=0, wake_tx_task=0;
1239        unsigned int event_status=0;
1240        int accessed;
1241        #define SET_ERROR_DESCRIPTOR(descriptor) (event_status = (event_status & 0x0000ffff) | descriptor<<16)
1242               
1243        while( (iiw=READ_DMA(&brm->irq_log[brm->irq].iiw)) != 0xffff ){
1244                iaw=READ_DMA(&brm->irq_log[brm->irq].iaw);
1245               
1246                /* indicate that the interrupt log entry has been processed */
1247                brm->irq_log[brm->irq].iiw = 0xffff;
1248
1249                /* Interpret interrupt log entry  */
1250                descriptor = iaw >> 2;
1251                pending    = iiw;
1252                brm->irq = (brm->irq + 1) % 16;
1253               
1254                /* Clear the log so that we */
1255
1256
1257                /* Subaddress accessed irq (RT only)
1258                 *
1259                 * Can be either a receive or transmit command
1260                 * as well as a mode code.
1261                */
1262                if (pending & BRM_SUBAD_IRQ) {
1263
1264                        /* Pointer to next free message in circular buffer */
1265                        current = READ_DMA(&brm->desc[descriptor].cur);
1266                        ctrl = READ_DMA(&brm->desc[descriptor].ctrl);
1267#ifdef DEBUG
1268                        brm->log[brm->log_i++ % EVENT_QUEUE_SIZE] = (0xff<<16);
1269                        brm->log[brm->log_i++ % EVENT_QUEUE_SIZE] = current;
1270                        brm->log[brm->log_i++ % EVENT_QUEUE_SIZE] = ctrl;
1271                        brm->log[brm->log_i++ % EVENT_QUEUE_SIZE] = 0;
1272#endif
1273                        accessed = ctrl & 0x10;
1274                        /* Note that current may be equal to bot and top when
1275                         * circular buffer one can handle one message.
1276                         */
1277                        if ( accessed )
1278                          do {
1279                                msgadr = brm->last_read[descriptor];
1280
1281                                /* Get word count */
1282                                miw = READ_DMA(&brm->mem[msgadr]);
1283                                wc  = miw >> 11;
1284
1285                                /* Data received */
1286                                if (descriptor < 32) {
1287                                        wc = wc ? wc : 32;
1288                                }
1289                                /* Data transmitted */
1290                                else if (descriptor < 64) {
1291                                        wc = wc ? wc : 32; 
1292                                        wake_tx_task=1;
1293                                }
1294                                /* RX Mode code */
1295                                else if (descriptor < 96) {
1296                                        wc = (wc>>4);
1297                                }
1298                                /* TX Mode code */
1299                                else if (descriptor < 128) {
1300                                        wc = (wc>>4);
1301                                }
1302
1303#ifdef DEBUG           
1304                                brm->log[brm->log_i++ % EVENT_QUEUE_SIZE] = (descriptor << 16) | wc;
1305                                brm->log[brm->log_i++ % EVENT_QUEUE_SIZE] = current;
1306                                brm->log[brm->log_i++ % EVENT_QUEUE_SIZE] = msgadr;
1307#endif
1308
1309                                /* If there is room in the event queue, copy the event there */
1310                                if (brm->head - brm->tail != EVENT_QUEUE_SIZE) {
1311
1312                                        /* Copy to event queue */
1313                                        brm->rt_event[INDEX(brm->head)].miw = READ_DMA(&brm->mem[msgadr]);
1314                                        brm->rt_event[INDEX(brm->head)].time = READ_DMA(&brm->mem[msgadr+1]);
1315                                        len = wc;
1316                                        while( len-- > 0){
1317                                                brm->rt_event[INDEX(brm->head)].data[len] = READ_DMA(&brm->mem[msgadr+2+len]);
1318                                        }
1319                                        brm->rt_event[INDEX(brm->head)].desc = descriptor;
1320                                        brm->head++;
1321                                }
1322                                else {
1323                                        /* Indicate overrun */
1324                                        brm->rt_event[INDEX(brm->head)].desc |= 0x8000;
1325                                }
1326
1327                                msgadr += (2+wc);
1328
1329                                if (msgadr >= READ_DMA(&brm->desc[descriptor].bot)) {
1330                                        msgadr = READ_DMA(&brm->desc[descriptor].top);
1331                                }
1332                                brm->last_read[descriptor] = msgadr;
1333
1334#ifdef DEBUG
1335                                brm->log[brm->log_i++ % EVENT_QUEUE_SIZE] = msgadr;
1336#endif
1337                                wake_rx_task = 1;
1338                          } while ( (msgadr=brm->last_read[descriptor]) != current );
1339                }
1340
1341                if (pending & BRM_EOL_IRQ) { 
1342                        wake_tx_task = 1;
1343                }
1344
1345                if (pending & BRM_BC_ILLCMD_IRQ) {
1346                        brm->bc_list_fail = 1;
1347                        wake_tx_task = 1;
1348                        SET_ERROR_DESCRIPTOR(descriptor);
1349                        FUNCDBG("BRM: ILLCMD IRQ\n\r");
1350                }
1351
1352                /* Monitor irq */
1353                if (pending & BRM_MBC_IRQ) {
1354
1355                        stop_operation(brm);
1356                        brm->regs->mbc = 1;
1357                        start_operation(brm);
1358
1359                        /* If there is room in the event queue, copy the event there */
1360                        if (brm->head - brm->tail != EVENT_QUEUE_SIZE) {
1361
1362                                /* Copy to event queue */
1363
1364                                brm->bm_event[INDEX(brm->head)].miw  =  READ_DMA(&brm->mem[0]);
1365                                brm->bm_event[INDEX(brm->head)].cw1  =  READ_DMA(&brm->mem[1]);
1366                                brm->bm_event[INDEX(brm->head)].cw2  =  READ_DMA(&brm->mem[2]);
1367                                brm->bm_event[INDEX(brm->head)].sw1  =  READ_DMA(&brm->mem[4]);
1368                                brm->bm_event[INDEX(brm->head)].sw2  =  READ_DMA(&brm->mem[5]);
1369                                brm->bm_event[INDEX(brm->head)].time =  READ_DMA(&brm->mem[6]);
1370
1371                                len = 32;
1372                                while ( len-- ){
1373                                        brm->bm_event[INDEX(brm->head)].data[len] =  READ_DMA(&brm->mem[0x100+len]);
1374                                        len--;
1375                                        brm->bm_event[INDEX(brm->head)].data[len] =  READ_DMA(&brm->mem[0x100+len]);
1376                                        len--;
1377                                        brm->bm_event[INDEX(brm->head)].data[len] =  READ_DMA(&brm->mem[0x100+len]);
1378                                        len--;
1379                                        brm->bm_event[INDEX(brm->head)].data[len] =  READ_DMA(&brm->mem[0x100+len]);
1380                                }
1381/*                              memcpy((void *)brm->bm_event[INDEX(brm->head)].data, &brm->mem[0x100], 32);*/
1382
1383#ifdef DEBUG
1384                                brm->log[brm->log_i++ % EVENT_QUEUE_SIZE] = READ_REG(&brm->regs->mbc) & 0xffff;
1385                                brm->log[brm->log_i++ % EVENT_QUEUE_SIZE] = READ_DMA(&brm->mem[0]);
1386                                brm->log[brm->log_i++ % EVENT_QUEUE_SIZE] = READ_DMA(&brm->mem[1]);
1387                                brm->log[brm->log_i++ % EVENT_QUEUE_SIZE] = READ_DMA(&brm->mem[4]);
1388#endif
1389
1390                                brm->head++;
1391
1392                        }
1393                        else {
1394                                /* Indicate overrun */
1395                                brm->bm_event[INDEX(brm->head)].miw |= 0x8000;
1396                        }
1397
1398                        /* Wake any blocking thread */
1399                        wake_rx_task = 1;
1400                }
1401
1402                /* The reset of the interrupts
1403                 * cause a event to be signalled
1404                 * so that user can handle error.
1405                 */
1406                if ( pending & BRM_RT_ILLCMD_IRQ){
1407                        FUNCDBG("BRM: BRM_RT_ILLCMD_IRQ\n\r");
1408                        brm->status |= BRM_RT_ILLCMD_IRQ;
1409                        event_status |= BRM_RT_ILLCMD_IRQ;
1410                        SET_ERROR_DESCRIPTOR(descriptor);
1411                        signal_event=1;
1412                }
1413
1414                if ( pending & BRM_ILLOP_IRQ){
1415                        FUNCDBG("BRM: BRM_ILLOP_IRQ\n\r");
1416                        brm->bc_list_fail = 1;
1417                        wake_tx_task = 1;
1418                        event_status |= BRM_ILLOP_IRQ;
1419                        SET_ERROR_DESCRIPTOR(descriptor);                       
1420                        signal_event=1;
1421                }
1422
1423                if ( pending & BRM_MERR_IRQ){
1424                        FUNCDBG("BRM: BRM_MERR_IRQ\n\r");
1425                        event_status |= BRM_MERR_IRQ;
1426                        SET_ERROR_DESCRIPTOR(descriptor);
1427                        signal_event=1;
1428                }
1429                /* Clear Block Accessed Bit */
1430                tmp = READ_DMA(&brm->desc[descriptor].ctrl);
1431                brm->desc[descriptor].ctrl = tmp & ~0x10;
1432#ifdef DEBUG
1433                brm->log[brm->log_i++ % EVENT_QUEUE_SIZE] = (0xfe<<16);
1434                brm->log[brm->log_i++ % EVENT_QUEUE_SIZE] = 0;
1435                brm->log[brm->log_i++ % EVENT_QUEUE_SIZE] = tmp & ~0x10;
1436                brm->log[brm->log_i++ % EVENT_QUEUE_SIZE] = tmp;
1437#endif
1438        } /* While */
1439
1440        /* clear interrupt flags & handle Hardware errors */
1441        pending = READ_REG(&brm->regs->ipend);
1442
1443        if ( pending & BRM_DMAF_IRQ){
1444                FUNCDBG("BRM: BRM_DMAF_IRQ\n\r");
1445                event_status |= BRM_DMAF_IRQ;
1446                signal_event=1;
1447        }
1448
1449        if ( pending & BRM_WRAPF_IRQ){
1450                FUNCDBG("BRM: BRM_WRAPF_IRQ\n\r");
1451                event_status |= BRM_WRAPF_IRQ;
1452                signal_event=1;
1453        }
1454
1455        if ( pending & BRM_TAPF_IRQ){
1456                FUNCDBG("BRM: BRM_TAPF_IRQ\n\r");
1457                event_status |= BRM_TAPF_IRQ;
1458                signal_event=1;
1459        }
1460
1461        /* Copy current mask to status mask */
1462        if ( event_status ){
1463                if ( event_status & 0xffff0000 )
1464                        brm->status &= 0x0000ffff;
1465                brm->status |= event_status;
1466        }
1467
1468        /* Wake any blocked rx thread only on receive interrupts */
1469        if ( wake_rx_task ) {
1470                rtems_semaphore_release(brm->rx_sem);
1471        }
1472
1473        /* Wake any blocked tx thread only on transmit interrupts */
1474        if ( wake_tx_task ) {
1475                rtems_semaphore_release(brm->tx_sem);
1476        }       
1477
1478        /* signal event once */
1479        if ( signal_event && (brm->event_id!=0) ){
1480                rtems_event_send(brm->event_id, event_status);
1481        }
1482
1483}
1484
1485void b1553brm_print_dev(struct drvmgr_dev *dev, int options)
1486{
1487        brm_priv *pDev = dev->priv;
1488        struct brm_reg *regs = pDev->regs;
1489
1490        /* Print */
1491        printf("--- B1553BRM[%d] %s ---\n", pDev->minor, pDev->devName);
1492        printf(" REGS:            0x%x\n", (unsigned int)pDev->regs);
1493        printf(" IRQ:             %d\n", pDev->irqno);
1494        switch (pDev->mode) {
1495                case BRM_MODE_BC:
1496                        printf(" MODE:            BC\n");
1497                        printf(" DESCS:           0x%x\n", (unsigned int)&pDev->bcmem->descs[0]);
1498                        printf(" DATA:            0x%x\n", (unsigned int)&pDev->bcmem->msg_data[0].data[0]);
1499                        printf(" IRQLOG:          0x%x\n", (unsigned int)&pDev->bcmem->irq_logs[0]);
1500                        break;
1501                case BRM_MODE_BM:
1502                        printf(" MODE:            BM\n");
1503                        break;
1504                case BRM_MODE_RT:
1505                        printf(" MODE:            RT\n");
1506                        printf(" RXSUBS:          0x%x\n", (unsigned int)&pDev->rtmem->rxsubs[0]);
1507                        printf(" TXSUBS:          0x%x\n", (unsigned int)&pDev->rtmem->txsubs[0]);
1508                        printf(" RXMODES:         0x%x\n", (unsigned int)&pDev->rtmem->rxmodes[0]);
1509                        printf(" TXOMODES:        0x%x\n", (unsigned int)&pDev->rtmem->txmodes[0]);
1510                        printf(" RXSUBS MSGS:     0x%x\n", (unsigned int)&pDev->rtmem->rxsuba_msgs[0]);
1511                        printf(" TXSUBS MSGS:     0x%x\n", (unsigned int)&pDev->rtmem->txsuba_msgs[0]);
1512                        printf(" RXMODES MSGS:    0x%x\n", (unsigned int)&pDev->rtmem->rxmode_msgs[0]);
1513                        printf(" TXMODES MSGS:    0x%x\n", (unsigned int)&pDev->rtmem->txmode_msgs[0]);
1514                        printf(" IRQLOG:          0x%x\n", (unsigned int)&pDev->rtmem->irq_logs[0]);
1515                        break;
1516        }
1517        printf(" CTRL:            0x%x\n", regs->ctrl);
1518        printf(" OPER:            0x%x\n", regs->oper);
1519        printf(" CUR_CMD:         0x%x\n", regs->cur_cmd);
1520        printf(" IMASK:           0x%x\n", regs->imask);
1521        printf(" IPEND:           0x%x\n", regs->ipend);
1522        printf(" IPOINT:          0x%x\n", regs->ipoint);
1523        printf(" BIT_REG:         0x%x\n", regs->bit_reg);
1524        printf(" TTAG:            0x%x\n", regs->ttag);
1525        printf(" DPOINT:          0x%x\n", regs->dpoint);
1526        printf(" SW:              0x%x\n", regs->sw);
1527        printf(" INITCOUNT:       0x%x\n", regs->initcount);
1528        printf(" MCPOINT:         0x%x\n", regs->mcpoint);
1529        printf(" MDPOINT:         0x%x\n", regs->mdpoint);
1530        printf(" MBC:             0x%x\n", regs->mbc);
1531        printf(" MFILTA:          0x%x\n", regs->mfilta);
1532        printf(" MFILTB:          0x%x\n", regs->mfiltb);
1533        printf(" ENHANCED:        0x%x\n", regs->enhanced);
1534        printf(" W_CTRL:          0x%x\n", regs->w_ctrl);
1535        printf(" W_IRQCTRL:       0x%x\n", regs->w_irqctrl);
1536        printf(" W_AHBADDR:       0x%x\n", regs->w_ahbaddr);
1537}
1538
1539void b1553brm_print(int options)
1540{
1541        struct amba_drv_info *drv = &b1553brm_drv_info;
1542        struct drvmgr_dev *dev;
1543
1544        dev = drv->general.dev;
1545        while(dev) {
1546                b1553brm_print_dev(dev, options);
1547                dev = dev->next_in_drv;
1548        }
1549}
Note: See TracBrowser for help on using the repository browser.