source: rtems/c/src/lib/libbsp/sparc/shared/1553/b1553brm.c @ 3681925

4.115
Last change on this file since 3681925 was 3681925, checked in by Daniel Hellstrom <daniel@…>, on 12/20/11 at 15:27:54

LEON: updated shared drivers to Driver Manger framework

Some bugfixes at the same time. After this patch the drivers
may be used on RASTA systems having a big-endian PCI layout.

Removed not up to date changelogs, rely on git log instead.

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