source: rtems/bsps/sparc/shared/1553/b1553brm.c @ d60d303c

5
Last change on this file since d60d303c was d60d303c, checked in by Sebastian Huber <sebastian.huber@…>, on 04/20/18 at 11:33:24

bsps/sparc: Move shared files to bsps

This patch is a part of the BSP source reorganization.

Update #3285.

  • 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 <bsp/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", DRVMGR_KT_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", DRVMGR_KT_INT);
509        if ( value ) {
510                pDev->cfg_clksel = value->i & CLKSEL_MASK;
511        }
512
513        value = drvmgr_dev_key_get(pDev->dev, "clkDiv", DRVMGR_KT_INT);
514        if ( value ) {
515                pDev->cfg_clkdiv = value->i & CLKDIV_MASK;
516        }
517
518        value = drvmgr_dev_key_get(pDev->dev, "coreFreq", DRVMGR_KT_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
599unsigned short b1553brm_rt_cmd_legalize[16] = {
600        0,
601        0,
602        0,
603        0,
604        0,
605        0,
606        0xffff,
607        0xffff,
608        0xffff,
609        0xfffd,
610        0xfe01,
611        0xfff2,
612        0xffff,
613        0xfffd,
614        0xfe05,
615        0xffff,
616};
617
618static rtems_device_driver rt_init(brm_priv *brm) {
619        unsigned int i;
620
621        brm->head = brm->tail = 0;
622        brm->rx_blocking = brm->tx_blocking = 1;
623
624        if ( brm->bm_event )
625                free(brm->bm_event);
626        brm->bm_event = NULL;
627
628        if ( brm->rt_event )
629                free(brm->rt_event);
630       
631        brm->bcmem = NULL;
632        brm->rtmem = (void *)brm->mem;
633
634        brm->rt_event = (struct rt_msg *) malloc(EVENT_QUEUE_SIZE*sizeof(struct rt_msg));
635 
636        if (brm->rt_event == NULL) {
637                DBG("BRM driver failed to allocated memory.");
638                return RTEMS_NO_MEMORY;
639        }
640
641        brm->irq_log = (struct irq_log_list *)&brm->rtmem->irq_logs[0];
642
643        brm->regs->ctrl   = 0x1912;  /* enable both buses, circular 1 bufmode, broadcast, interrupt log */
644        brm->regs->oper   = 0x0900;  /* configure as RT, with addr 1 */
645        brm->regs->imask         = BRM_RT_ILLCMD_IRQ|BRM_SUBAD_IRQ|BRM_TAPF_IRQ|BRM_DMAF_IRQ|BRM_WRAPF_IRQ|BRM_MERR_IRQ;
646        brm->regs->dpoint       = 0;
647        brm->regs->ipoint       = OFS(brm->rtmem->irq_logs[0]);
648        brm->regs->enhanced  = 0x0000 | brm->cfg_freq;  /* BRM clocked with freq = 12,16,20 or 24MHz */
649        brm->regs->w_ctrl       = (brm->cfg_clksel<<9) | (brm->cfg_clkdiv<<5) | 1;
650        brm->regs->w_irqctrl = 6;
651        brm->regs->w_ahbaddr = brm->memarea_base_remote;
652               
653        clr_int_logs(brm->irq_log);
654
655        /* Initialize the Legalize register with standard values */
656        for (i = 0; i < 16; i++) {
657                brm->regs->rt_cmd_leg[i] = b1553brm_rt_cmd_legalize[i];
658        }
659
660        /* Init descriptor table
661         *
662         * Each circular buffer has room for 8 messages with up to 34 (32 data + miw + time) words (16b) in each.
663         * The buffers must separated by 34 words.
664         */
665
666 
667        /* RX Sub-address 0 - 31 */
668        for (i = 0; i < 32; i++) {
669                brm->rtmem->rxsubs[i].ctrl = 0x00E0;                            /* Interrupt: INTX, IWA, and IBRD */
670                brm->rtmem->rxsubs[i].top  = OFS(brm->rtmem->rxsuba_msgs[i]);                /* Top address */
671                brm->rtmem->rxsubs[i].cur  = OFS(brm->rtmem->rxsuba_msgs[i]);                /* Current address */
672                brm->rtmem->rxsubs[i].bot  = OFS(brm->rtmem->rxsuba_msgs[i+1]) - sizeof(struct msg)/2; /* Bottom address */     
673                brm->last_read[i] = OFS(brm->rtmem->rxsuba_msgs[i]);
674        }
675        /* TX Sub-address 0 - 31 */
676        for (i = 0; i < 32; i++) {
677                brm->rtmem->txsubs[i].ctrl  = 0x0060;                                   /* Interrupt: IWA and IBRD */
678                brm->rtmem->txsubs[i].top   = OFS(brm->rtmem->txsuba_msgs[i]);                    /* Top address */
679                brm->rtmem->txsubs[i].cur   = OFS(brm->rtmem->txsuba_msgs[i]);                    /* Current address */
680                brm->rtmem->txsubs[i].bot   = OFS(brm->rtmem->txsuba_msgs[i+1]) - sizeof(struct msg)/2; /* Bottom address */
681                brm->last_read[i+32]  = OFS(brm->rtmem->txsuba_msgs[i]);
682                brm->written[i] = OFS(brm->rtmem->txsuba_msgs[i]);
683        }
684        /* RX mode code 0 - 31 */
685        for (i = 0; i < 32; i++) {
686                brm->rtmem->rxmodes[i].ctrl = 0x00E0;                                   /* Interrupt: INTX, IWA, and IBRD */
687                brm->rtmem->rxmodes[i].top  = OFS(brm->rtmem->rxmode_msgs[i]);                    /* Top address */
688                brm->rtmem->rxmodes[i].cur  = OFS(brm->rtmem->rxmode_msgs[i]);                    /* Current address */
689                brm->rtmem->rxmodes[i].bot  = OFS(brm->rtmem->rxmode_msgs[i+1]) - sizeof(struct msg)/2; /* Bottom address */
690                brm->last_read[i+64] = OFS(brm->rtmem->rxmode_msgs[i]);
691        }   
692        /* TX mode code 0 - 31 */
693        for (i = 0; i < 32; i++) {
694                brm->rtmem->txmodes[i].ctrl = 0x0060;                                   /* Interrupt: IWA and IBRD */
695                brm->rtmem->txmodes[i].top  = OFS(brm->rtmem->txmode_msgs[i]);                    /* Top address */
696                brm->rtmem->txmodes[i].cur  = OFS(brm->rtmem->txmode_msgs[i]);                    /* Current address */
697                brm->rtmem->txmodes[i].bot  = OFS(brm->rtmem->txmode_msgs[i+1]) - sizeof(struct msg)/2; /* Bottom address */
698                brm->last_read[i+96] = OFS(brm->rtmem->txmode_msgs[i]);
699        }
700
701#ifdef DEBUG
702        printk("b1553BRM DMA_AREA: 0x%x\n", (unsigned int)brm->rtmem);
703        printk("LOG: 0x%x\n", &brm->log[0]);
704        printk("LOG_I: 0x%x\n", &brm->log_i);
705#endif
706
707        brm->mode = BRM_MODE_RT;
708
709        return RTEMS_SUCCESSFUL;
710}
711
712static rtems_device_driver bc_init(brm_priv *brm){
713
714        if ( brm->bm_event )
715                free(brm->bm_event);
716        brm->bm_event = NULL;
717
718        if ( brm->rt_event )
719                free(brm->rt_event);
720        brm->rt_event = NULL;
721       
722        brm->bcmem = (void *)brm->mem;
723        brm->rtmem = NULL;
724        brm->irq_log = (struct irq_log_list *)&brm->bcmem->irq_logs[0];
725       
726        brm->head = brm->tail = 0;
727        brm->rx_blocking = brm->tx_blocking = 1;
728       
729        brm->regs->ctrl   = 0x0006;  /* ping pong enable and enable interrupt log */
730        brm->regs->oper   = 0x0800;  /* configure as BC */
731        brm->regs->imask         = BRM_EOL_IRQ|BRM_BC_ILLCMD_IRQ|BRM_ILLOP_IRQ|BRM_DMAF_IRQ|BRM_WRAPF_IRQ|BRM_MERR_IRQ;
732        brm->regs->dpoint       = 0;
733        brm->regs->ipoint       = OFS(brm->bcmem->irq_logs[0]);
734        brm->regs->enhanced  = 0x0000 | (brm->cfg_freq&BRM_FREQ_MASK);  /* freq = 24 */
735        brm->regs->w_ctrl       = (brm->cfg_clksel<<9) | (brm->cfg_clkdiv<<5) | 1;
736        brm->regs->w_irqctrl = 6;
737        brm->regs->w_ahbaddr = brm->memarea_base_remote;
738       
739        clr_int_logs(brm->irq_log);
740       
741        brm->mode = BRM_MODE_BC;
742       
743        return RTEMS_SUCCESSFUL;
744}
745
746static rtems_device_driver bm_init(brm_priv *brm) {
747
748
749        brm->head = brm->tail = 0;
750        brm->rx_blocking = brm->tx_blocking = 1;
751
752        if ( brm->rt_event )
753                free(brm->rt_event);
754        brm->rt_event = NULL;
755
756        if ( brm->bm_event )
757                free(brm->bm_event);
758       
759        brm->bcmem = NULL;
760        brm->rtmem = NULL;
761       
762        brm->bm_event    = (struct bm_msg *) malloc(EVENT_QUEUE_SIZE*sizeof(struct bm_msg));
763 
764        if (brm->bm_event == NULL) {
765                DBG("BRM driver failed to allocated memory.");
766                return RTEMS_NO_MEMORY;
767        }
768
769        /* end of 16K, fits all current modes (128K, 16K) */
770        brm->irq_log = (struct irq_log_list *)&brm->mem[8*1024-16*2];
771
772        brm->regs->ctrl   = 0x0006;  /* ping pong enable and enable interrupt log */
773        brm->regs->oper   = 0x0A00;  /* configure as BM */
774        brm->regs->imask        = BRM_MBC_IRQ|BRM_MERR_IRQ|BRM_DMAF_IRQ;
775        brm->regs->dpoint       = 0;
776        brm->regs->ipoint       = OFS(brm->mem[8*1024-16*2]);
777        brm->regs->mcpoint   = 0;          /* Command pointer */
778        brm->regs->mdpoint   = 0x100;   /* Data pointer */
779        brm->regs->mbc     = 1;    /* Block count */
780        brm->regs->enhanced  = 0x0000 | (brm->cfg_freq&BRM_FREQ_MASK);  /* freq = 24 */
781        brm->regs->w_ctrl       = (brm->cfg_clksel<<9) | (brm->cfg_clkdiv<<5) | 1;
782        brm->regs->w_irqctrl = 6;
783        brm->regs->w_ahbaddr = brm->memarea_base_remote;
784       
785        clr_int_logs(brm->irq_log);
786       
787        brm->mode = BRM_MODE_BM;
788       
789        return RTEMS_SUCCESSFUL;
790}
791
792
793static rtems_device_driver brm_initialize(rtems_device_major_number major, rtems_device_minor_number minor, void *arg)
794{
795        return RTEMS_SUCCESSFUL;
796}
797
798static rtems_device_driver brm_open(rtems_device_major_number major, rtems_device_minor_number minor, void *arg) {
799        brm_priv *brm;
800        struct drvmgr_dev *dev;
801
802        FUNCDBG("brm_open\n");
803
804        if ( drvmgr_get_dev(&b1553brm_drv_info.general, minor, &dev) ) {
805                DBG("Wrong minor %d\n", minor);
806                return RTEMS_UNSATISFIED;
807        }
808        brm = (brm_priv *)dev->priv;
809
810        if (rtems_semaphore_obtain(brm->dev_sem, RTEMS_NO_WAIT, RTEMS_NO_TIMEOUT) != RTEMS_SUCCESSFUL) {
811                DBG("brm_open: resource in use\n");
812                return RTEMS_RESOURCE_IN_USE; /* EBUSY */
813        }
814
815        /* Set defaults */
816        brm->event_id = 0;
817
818        start_operation(brm);
819
820        /* Register interrupt routine */
821        if ( drvmgr_interrupt_register(brm->dev, 0, "b1553brm", b1553brm_interrupt, brm) ) {
822                rtems_semaphore_release(brm->dev_sem);
823                return RTEMS_UNSATISFIED;
824        }
825
826        return RTEMS_SUCCESSFUL;
827}
828 
829static rtems_device_driver brm_close(rtems_device_major_number major, rtems_device_minor_number minor, void *arg)
830{
831        brm_priv *brm;
832        struct drvmgr_dev *dev;
833
834        FUNCDBG("brm_close");
835       
836        if ( drvmgr_get_dev(&b1553brm_drv_info.general, minor, &dev) ) {
837                return RTEMS_UNSATISFIED;
838        }
839        brm = (brm_priv *)dev->priv;
840
841        drvmgr_interrupt_unregister(brm->dev, 0, b1553brm_interrupt, brm);
842
843        stop_operation(brm);
844        rtems_semaphore_release(brm->dev_sem);
845
846        return RTEMS_SUCCESSFUL;
847}
848 
849static int get_rt_messages(brm_priv *brm, void *buf, unsigned int msg_count)
850{
851        struct rt_msg *dest = (struct rt_msg *) buf;
852        int count = 0;
853
854        if (brm->head == brm->tail) {
855                return 0;
856        }
857
858        do {
859
860                DBG("rt read - head: %d, tail: %d\n", brm->head, brm->tail);
861                dest[count++] = brm->rt_event[INDEX(brm->tail++)];
862        } while (brm->head != brm->tail && count < msg_count);
863
864        return count;
865}
866
867static int get_bm_messages(brm_priv *brm, void *buf, unsigned int msg_count)
868{
869        struct bm_msg *dest = (struct bm_msg *) buf;
870        int count = 0;
871
872        if (brm->head == brm->tail) {
873                return 0;
874        }
875
876        do {
877
878                DBG("bm read - head: %d, tail: %d\n", brm->head, brm->tail);
879                dest[count++] = brm->bm_event[INDEX(brm->tail++)];
880
881        } while (brm->head != brm->tail && count < msg_count);
882
883        return count;
884}
885
886static rtems_device_driver brm_read(rtems_device_major_number major, rtems_device_minor_number minor, void *arg)
887{
888        rtems_libio_rw_args_t *rw_args;
889        int count = 0;
890        brm_priv *brm;
891        struct drvmgr_dev *dev;
892        int (*get_messages)(brm_priv *brm, void *buf, unsigned int count);
893
894        if ( drvmgr_get_dev(&b1553brm_drv_info.general, minor, &dev) ) {
895                return RTEMS_UNSATISFIED;
896        }
897        brm = (brm_priv *)dev->priv;
898
899        if ( ! (brm->mode & (BRM_MODE_RT | BRM_MODE_BM)) ){
900                return RTEMS_INVALID_NAME;
901        }
902
903        rw_args = (rtems_libio_rw_args_t *) arg;
904
905        if ( ((READ_REG(&brm->regs->oper)>>8) & 3) == 1 ) { /* RT */
906                get_messages = get_rt_messages;
907        } else { /* BM */
908                get_messages = get_bm_messages;
909        }
910
911        FUNCDBG("brm_read [%i,%i]: buf: 0x%x len: %i\n",major, minor, (unsigned int)rw_args->buffer,rw_args->count);
912
913        while ( (count=get_messages(brm,rw_args->buffer, rw_args->count)) == 0 ) {
914                if (brm->rx_blocking) {
915                        rtems_semaphore_obtain(brm->rx_sem, RTEMS_WAIT, RTEMS_NO_TIMEOUT);
916                } else {
917                        /* Translates to EBUSY */
918                        return RTEMS_RESOURCE_IN_USE;
919                }
920        }
921
922        rw_args->bytes_moved = count;
923        return RTEMS_SUCCESSFUL;
924}
925
926static rtems_device_driver brm_write(rtems_device_major_number major, rtems_device_minor_number minor, void *arg)
927{
928        rtems_libio_rw_args_t *rw_args;
929        struct rt_msg *source;
930        unsigned int count=0, current, next, descriptor, wc, suba;
931        brm_priv *brm;
932        struct drvmgr_dev *dev;
933 
934        if ( drvmgr_get_dev(&b1553brm_drv_info.general, minor, &dev) ) {
935                return RTEMS_UNSATISFIED;
936        }
937        brm = (brm_priv *)dev->priv;
938       
939        if ( ! (brm->mode & BRM_MODE_RT) ){
940                return RTEMS_INVALID_NAME;
941        }
942       
943        rw_args = (rtems_libio_rw_args_t *) arg;
944        source = (struct rt_msg *) rw_args->buffer;
945
946        FUNCDBG("brm_write [%i,%i]: buf: 0x%x len: %i\n",major, minor, (unsigned int)rw_args->buffer,rw_args->count);
947
948        do {
949
950                descriptor = source[count].desc & 0x7F;
951                suba       = descriptor-32;
952                wc         = source[count].miw >> 11;
953                wc = wc ? wc : 32;
954
955                /* Only subaddress transmission is allowed with write */
956                if (descriptor < 32 || descriptor >= 64)
957                        return RTEMS_INVALID_NAME;
958
959                current = brm->desc[descriptor].cur;
960                next = brm->written[suba] + 2 + wc;
961
962                if (brm->written[suba] < current) {
963
964                        if (next > current) {
965
966                                /* No room in transmission buffer */
967                                if (brm->tx_blocking && count == 0) {
968                                        rtems_semaphore_obtain(brm->tx_sem, RTEMS_WAIT, RTEMS_NO_TIMEOUT);
969                                } else if ( count > 0 ) {
970                                        /* return the number of messages sent so far */
971                                        break;
972                                } else {       
973                                        /* Translates to posix EBUSY */
974                                        return RTEMS_RESOURCE_IN_USE;
975                                }
976                        }
977                }
978
979                memcpy((void *)&brm->mem[brm->written[suba]], &source[count], (2+wc)*2);
980
981                count++;
982
983                if (next >= brm->desc[descriptor].bot) {
984                        next = brm->desc[descriptor].top;
985                }
986                brm->written[suba] = next;
987
988        }  while (count < rw_args->count);
989
990        rw_args->bytes_moved = count;
991
992        if (count >= 0) {
993                return RTEMS_SUCCESSFUL;
994        }
995        return RTEMS_UNSATISFIED;
996}
997
998static rtems_device_driver brm_control(rtems_device_major_number major, rtems_device_minor_number minor, void *arg)
999{
1000   
1001        unsigned int i=0;
1002        unsigned short ctrl, oper, cw1, cw2;
1003        rtems_libio_ioctl_args_t *ioarg = (rtems_libio_ioctl_args_t *) arg;
1004        unsigned int *data = ioarg->buffer;
1005        struct bc_msg *cmd_list = (struct bc_msg *) ioarg->buffer;
1006        brm_priv *brm;
1007        struct drvmgr_dev *dev;
1008        rtems_device_driver ret;
1009        int len, msglen;
1010
1011        FUNCDBG("brm_control[%d]: [%i,%i]\n", minor, major, minor);
1012
1013        if ( drvmgr_get_dev(&b1553brm_drv_info.general, minor, &dev) ) {
1014                return RTEMS_UNSATISFIED;
1015        }
1016        brm = (brm_priv *)dev->priv;
1017
1018        if (!ioarg) {
1019                DBG("brm_control: invalid argument\n");
1020                return RTEMS_INVALID_NAME;
1021        }
1022
1023        ioarg->ioctl_return = 0;
1024        switch (ioarg->command) {
1025
1026                case BRM_SET_MODE:
1027                if ( data[0] > 2 )
1028                        return RTEMS_INVALID_NAME;
1029                stop_operation(brm);
1030                if (data[0] == 0) {
1031                        ret = bc_init(brm);
1032                } else if (data[0] == 1) {
1033                        ret = rt_init(brm);                             
1034                } else if (data[0] == 2) {
1035                        ret = bm_init(brm);                                             
1036                } else {
1037                        ret = RTEMS_INVALID_NAME;
1038                }
1039                if ( ret != RTEMS_SUCCESSFUL)
1040                        return ret;
1041
1042                if ( brm->mode & (BRM_MODE_RT | BRM_MODE_BM ) )
1043                        start_operation(brm);
1044                break;
1045
1046                case BRM_SET_BUS:
1047                stop_operation(brm);
1048                ctrl = READ_REG(&brm->regs->ctrl);
1049                ctrl &= 0xE7FF;                               /* Clear bit 12-11 ...      */
1050                ctrl |= (data[0]&0x3)<<11;                    /* ... OR in new bus status */
1051                brm->regs->ctrl = ctrl;
1052                start_operation(brm);
1053                break;
1054
1055                case BRM_SET_MSGTO:
1056                stop_operation(brm);
1057                ctrl = READ_REG(&brm->regs->ctrl);
1058                ctrl &= 0xFDFF;                               /* Clear bit 9 ...          */
1059                ctrl |= (data[0]&1)<<9;                       /* ... OR in new MSGTO      */
1060                brm->regs->ctrl = ctrl;
1061                start_operation(brm);
1062                break;
1063
1064                case BRM_SET_RT_ADDR:   
1065                stop_operation(brm);
1066                oper = READ_REG(&brm->regs->oper);
1067                oper &= 0x03FF;                               /* Clear bit 15-10 ...      */
1068                oper |= (data[0]&0x1f)<<11;                   /* ... OR in new address    */
1069                oper |= odd_parity(data[0]&0x1f)<<10;         /* ... OR in parity         */
1070                brm->regs->oper = oper;
1071                start_operation(brm);
1072                break;
1073
1074                case BRM_SET_STD:   
1075                stop_operation(brm);
1076                ctrl = READ_REG(&brm->regs->ctrl);
1077                ctrl &= 0xFF7F;                               /* Clear bit 7 ...           */
1078                ctrl |= (data[0]&1)<<7;                       /* ... OR in new ABSTD (1=A) */
1079                brm->regs->ctrl = ctrl;
1080                start_operation(brm);
1081                break;
1082
1083                case BRM_SET_BCE:
1084                stop_operation(brm);
1085                ctrl = READ_REG(&brm->regs->ctrl);
1086                ctrl &= 0xFFEF;                               /* Clear bit 4 ...           */
1087                ctrl |= (data[0]&1)<<4;                       /* ... OR in new BCE         */
1088                brm->regs->ctrl = ctrl;
1089                start_operation(brm);
1090                break;
1091
1092                case BRM_TX_BLOCK:
1093                brm->tx_blocking     = data[0];     
1094                break;
1095
1096                case BRM_RX_BLOCK:
1097                brm->rx_blocking     = data[0];   
1098                break;
1099
1100                case BRM_DO_LIST:
1101                if ( brm->mode != BRM_MODE_BC ){
1102                        return RTEMS_INVALID_NAME;
1103                }
1104
1105                /* Check if we are bus controller */
1106                if ( ((READ_REG(&brm->regs->oper)>>8) & 3) != 0 ) {
1107                        return RTEMS_INVALID_NAME;
1108                }
1109
1110                /* Already processing list? */
1111                if (is_executing(brm)) {
1112                        return RTEMS_RESOURCE_IN_USE;
1113                }
1114
1115                /* clear any earlier releases */
1116                rtems_semaphore_obtain(brm->tx_sem, RTEMS_NO_WAIT, RTEMS_NO_TIMEOUT);
1117
1118                brm->bc_list_fail = 0;
1119                brm->cur_list = cmd_list;
1120                brm->regs->dpoint = 0;
1121
1122                i = 0;
1123                while ( (cmd_list[i].ctrl & BC_EOL) == 0) {
1124
1125                        ctrl = (4<<12) | (((cmd_list[i].ctrl&BC_BUSA)==BC_BUSA)<<9) | (((cmd_list[i].ctrl&BC_RTRT)==BC_RTRT)<<8);
1126
1127                        if (cmd_list[i].ctrl&BC_RTRT) {
1128                                cw1 = (cmd_list[i].rtaddr[0]<<11) | (0<<10) | (cmd_list[i].subaddr[0]<<5) | (cmd_list[i].wc & 0x1f); /* receive cw */
1129                                cw2 = (cmd_list[i].rtaddr[1]<<11) | (1<<10) | (cmd_list[i].subaddr[1]<<5) | (cmd_list[i].wc & 0x1f); /* transmit cw */
1130                        } else {
1131                                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);
1132                                cw2 = 0;
1133                        }
1134
1135                        /* Set up command block */
1136                        brm->bcmem->descs[i].ctrl = ctrl;
1137                        brm->bcmem->descs[i].cw1 = cw1;
1138                        brm->bcmem->descs[i].cw2 = cw2;
1139                        /* data pointer:
1140                         * (&brm->bcmem->msg_data[i].data[0] & 0x1ffff) / 2
1141                         */
1142                        brm->bcmem->descs[i].dptr = 1024+i*32;  /* data pointer */
1143                        brm->bcmem->descs[i].tsw[0] = 0;
1144                        brm->bcmem->descs[i].tsw[1] = 0;
1145                        brm->bcmem->descs[i].ba = 0;
1146                        brm->bcmem->descs[i].timer = 0;
1147
1148                        msglen = cmd_list[i].wc;
1149                        if ( msglen == 0 )
1150                                msglen = 32;
1151                        memcpy((void *)&brm->bcmem->msg_data[i].data[0], &cmd_list[i].data[0], msglen*2);
1152
1153                        i++;
1154                }
1155
1156                brm->bcmem->descs[i].ctrl = 0; /* end of list */
1157
1158                start_operation(brm);       
1159                break; 
1160
1161                case BRM_LIST_DONE:
1162
1163                if ( brm->mode != BRM_MODE_BC ){
1164                        return RTEMS_INVALID_NAME;
1165                }
1166                               
1167                /* Check if we are bus controller */
1168                if ( ((READ_REG(&brm->regs->oper)>>8) & 3) != 0 ) {
1169                        return RTEMS_INVALID_NAME;
1170                }
1171
1172                if (is_executing(brm)) {
1173
1174                        data[0] = 0;
1175                        if (brm->tx_blocking) {
1176                                rtems_semaphore_obtain(brm->tx_sem, RTEMS_WAIT, RTEMS_NO_TIMEOUT);
1177                                data[0] = 1;
1178                                if ( brm->bc_list_fail ){
1179                                        return RTEMS_INVALID_NAME;
1180                                }
1181                        } else {
1182                                return RTEMS_RESOURCE_IN_USE;
1183                        }
1184                } else {
1185                        data[0] = 1; /* done */
1186                }
1187
1188                /* copy finished list results back into bc_msg array */
1189                i = 0;
1190                while ( (brm->cur_list[i].ctrl & BC_EOL) == 0) {
1191                        if (READ_DMA(&brm->bcmem->descs[i].ctrl) & 1) {
1192                                brm->cur_list[i].ctrl |= 0x8000; /* Set BAME */
1193                        }
1194                        if (brm->cur_list[i].ctrl & BC_TR) {
1195                                /* RT Transmit command, copy received data */
1196                                len = brm->cur_list[i].wc;
1197                                if ( len == 0 )
1198                                        len = 32;
1199                                while ( len-- > 0) {
1200                                        brm->cur_list[i].data[len] = READ_DMA(&brm->bcmem->msg_data[i].data[len]);
1201                                }
1202                        }
1203                        brm->cur_list[i].tsw[0] = READ_DMA(&brm->bcmem->descs[i].tsw[0]);
1204                        brm->cur_list[i].tsw[1] = READ_DMA(&brm->bcmem->descs[i].tsw[1]);
1205
1206                        i++;
1207                }
1208                break;
1209
1210                case BRM_CLR_STATUS:
1211                brm->status = 0;
1212                break;
1213
1214                case BRM_GET_STATUS: /* copy status */
1215                if ( !ioarg->buffer )
1216                        return RTEMS_INVALID_NAME;
1217
1218                *(unsigned int *)ioarg->buffer = brm->status;
1219                break;
1220   
1221                case BRM_SET_EVENTID:
1222                brm->event_id = (rtems_id)ioarg->buffer;
1223                break;
1224
1225                default:
1226                return RTEMS_NOT_DEFINED;
1227        }
1228        return RTEMS_SUCCESSFUL;
1229}
1230
1231static void b1553brm_interrupt(void *arg)
1232{
1233        brm_priv *brm = arg;
1234        unsigned short descriptor, current, pending, miw, wc, tmp, ctrl;
1235        unsigned short msgadr, iaw, iiw;
1236        int len;
1237        int signal_event=0, wake_rx_task=0, wake_tx_task=0;
1238        unsigned int event_status=0;
1239        int accessed;
1240        #define SET_ERROR_DESCRIPTOR(descriptor) (event_status = (event_status & 0x0000ffff) | descriptor<<16)
1241               
1242        while( (iiw=READ_DMA(&brm->irq_log[brm->irq].iiw)) != 0xffff ){
1243                iaw=READ_DMA(&brm->irq_log[brm->irq].iaw);
1244               
1245                /* indicate that the interrupt log entry has been processed */
1246                brm->irq_log[brm->irq].iiw = 0xffff;
1247
1248                /* Interpret interrupt log entry  */
1249                descriptor = iaw >> 2;
1250                pending    = iiw;
1251                brm->irq = (brm->irq + 1) % 16;
1252               
1253                /* Clear the log so that we */
1254
1255
1256                /* Subaddress accessed irq (RT only)
1257                 *
1258                 * Can be either a receive or transmit command
1259                 * as well as a mode code.
1260                */
1261                if (pending & BRM_SUBAD_IRQ) {
1262
1263                        /* Pointer to next free message in circular buffer */
1264                        current = READ_DMA(&brm->desc[descriptor].cur);
1265                        ctrl = READ_DMA(&brm->desc[descriptor].ctrl);
1266#ifdef DEBUG
1267                        brm->log[brm->log_i++ % EVENT_QUEUE_SIZE] = (0xff<<16);
1268                        brm->log[brm->log_i++ % EVENT_QUEUE_SIZE] = current;
1269                        brm->log[brm->log_i++ % EVENT_QUEUE_SIZE] = ctrl;
1270                        brm->log[brm->log_i++ % EVENT_QUEUE_SIZE] = 0;
1271#endif
1272                        accessed = ctrl & 0x10;
1273                        /* Note that current may be equal to bot and top when
1274                         * circular buffer one can handle one message.
1275                         */
1276                        if ( accessed )
1277                          do {
1278                                msgadr = brm->last_read[descriptor];
1279
1280                                /* Get word count */
1281                                miw = READ_DMA(&brm->mem[msgadr]);
1282                                wc  = miw >> 11;
1283
1284                                /* Data received */
1285                                if (descriptor < 32) {
1286                                        wc = wc ? wc : 32;
1287                                }
1288                                /* Data transmitted */
1289                                else if (descriptor < 64) {
1290                                        wc = wc ? wc : 32; 
1291                                        wake_tx_task=1;
1292                                }
1293                                /* RX Mode code */
1294                                else if (descriptor < 96) {
1295                                        wc = (wc>>4);
1296                                }
1297                                /* TX Mode code */
1298                                else if (descriptor < 128) {
1299                                        wc = (wc>>4);
1300                                }
1301
1302#ifdef DEBUG           
1303                                brm->log[brm->log_i++ % EVENT_QUEUE_SIZE] = (descriptor << 16) | wc;
1304                                brm->log[brm->log_i++ % EVENT_QUEUE_SIZE] = current;
1305                                brm->log[brm->log_i++ % EVENT_QUEUE_SIZE] = msgadr;
1306#endif
1307
1308                                /* If there is room in the event queue, copy the event there */
1309                                if (brm->head - brm->tail != EVENT_QUEUE_SIZE) {
1310
1311                                        /* Copy to event queue */
1312                                        brm->rt_event[INDEX(brm->head)].miw = READ_DMA(&brm->mem[msgadr]);
1313                                        brm->rt_event[INDEX(brm->head)].time = READ_DMA(&brm->mem[msgadr+1]);
1314                                        len = wc;
1315                                        while( len-- > 0){
1316                                                brm->rt_event[INDEX(brm->head)].data[len] = READ_DMA(&brm->mem[msgadr+2+len]);
1317                                        }
1318                                        brm->rt_event[INDEX(brm->head)].desc = descriptor;
1319                                        brm->head++;
1320                                }
1321                                else {
1322                                        /* Indicate overrun */
1323                                        brm->rt_event[INDEX(brm->head)].desc |= 0x8000;
1324                                }
1325
1326                                msgadr += (2+wc);
1327
1328                                if (msgadr >= READ_DMA(&brm->desc[descriptor].bot)) {
1329                                        msgadr = READ_DMA(&brm->desc[descriptor].top);
1330                                }
1331                                brm->last_read[descriptor] = msgadr;
1332
1333#ifdef DEBUG
1334                                brm->log[brm->log_i++ % EVENT_QUEUE_SIZE] = msgadr;
1335#endif
1336                                wake_rx_task = 1;
1337                          } while ( (msgadr=brm->last_read[descriptor]) != current );
1338                }
1339
1340                if (pending & BRM_EOL_IRQ) { 
1341                        wake_tx_task = 1;
1342                }
1343
1344                if (pending & BRM_BC_ILLCMD_IRQ) {
1345                        brm->bc_list_fail = 1;
1346                        wake_tx_task = 1;
1347                        SET_ERROR_DESCRIPTOR(descriptor);
1348                        FUNCDBG("BRM: ILLCMD IRQ\n\r");
1349                }
1350
1351                /* Monitor irq */
1352                if (pending & BRM_MBC_IRQ) {
1353
1354                        stop_operation(brm);
1355                        brm->regs->mbc = 1;
1356                        start_operation(brm);
1357
1358                        /* If there is room in the event queue, copy the event there */
1359                        if (brm->head - brm->tail != EVENT_QUEUE_SIZE) {
1360
1361                                /* Copy to event queue */
1362
1363                                brm->bm_event[INDEX(brm->head)].miw  =  READ_DMA(&brm->mem[0]);
1364                                brm->bm_event[INDEX(brm->head)].cw1  =  READ_DMA(&brm->mem[1]);
1365                                brm->bm_event[INDEX(brm->head)].cw2  =  READ_DMA(&brm->mem[2]);
1366                                brm->bm_event[INDEX(brm->head)].sw1  =  READ_DMA(&brm->mem[4]);
1367                                brm->bm_event[INDEX(brm->head)].sw2  =  READ_DMA(&brm->mem[5]);
1368                                brm->bm_event[INDEX(brm->head)].time =  READ_DMA(&brm->mem[6]);
1369
1370                                len = 32;
1371                                while ( len-- ){
1372                                        brm->bm_event[INDEX(brm->head)].data[len] =  READ_DMA(&brm->mem[0x100+len]);
1373                                        len--;
1374                                        brm->bm_event[INDEX(brm->head)].data[len] =  READ_DMA(&brm->mem[0x100+len]);
1375                                        len--;
1376                                        brm->bm_event[INDEX(brm->head)].data[len] =  READ_DMA(&brm->mem[0x100+len]);
1377                                        len--;
1378                                        brm->bm_event[INDEX(brm->head)].data[len] =  READ_DMA(&brm->mem[0x100+len]);
1379                                }
1380/*                              memcpy((void *)brm->bm_event[INDEX(brm->head)].data, &brm->mem[0x100], 32);*/
1381
1382#ifdef DEBUG
1383                                brm->log[brm->log_i++ % EVENT_QUEUE_SIZE] = READ_REG(&brm->regs->mbc) & 0xffff;
1384                                brm->log[brm->log_i++ % EVENT_QUEUE_SIZE] = READ_DMA(&brm->mem[0]);
1385                                brm->log[brm->log_i++ % EVENT_QUEUE_SIZE] = READ_DMA(&brm->mem[1]);
1386                                brm->log[brm->log_i++ % EVENT_QUEUE_SIZE] = READ_DMA(&brm->mem[4]);
1387#endif
1388
1389                                brm->head++;
1390
1391                        }
1392                        else {
1393                                /* Indicate overrun */
1394                                brm->bm_event[INDEX(brm->head)].miw |= 0x8000;
1395                        }
1396
1397                        /* Wake any blocking thread */
1398                        wake_rx_task = 1;
1399                }
1400
1401                /* The reset of the interrupts
1402                 * cause a event to be signalled
1403                 * so that user can handle error.
1404                 */
1405                if ( pending & BRM_RT_ILLCMD_IRQ){
1406                        FUNCDBG("BRM: BRM_RT_ILLCMD_IRQ\n\r");
1407                        brm->status |= BRM_RT_ILLCMD_IRQ;
1408                        event_status |= BRM_RT_ILLCMD_IRQ;
1409                        SET_ERROR_DESCRIPTOR(descriptor);
1410                        signal_event=1;
1411                }
1412
1413                if ( pending & BRM_ILLOP_IRQ){
1414                        FUNCDBG("BRM: BRM_ILLOP_IRQ\n\r");
1415                        brm->bc_list_fail = 1;
1416                        wake_tx_task = 1;
1417                        event_status |= BRM_ILLOP_IRQ;
1418                        SET_ERROR_DESCRIPTOR(descriptor);                       
1419                        signal_event=1;
1420                }
1421
1422                if ( pending & BRM_MERR_IRQ){
1423                        FUNCDBG("BRM: BRM_MERR_IRQ\n\r");
1424                        event_status |= BRM_MERR_IRQ;
1425                        SET_ERROR_DESCRIPTOR(descriptor);
1426                        signal_event=1;
1427                }
1428                /* Clear Block Accessed Bit */
1429                tmp = READ_DMA(&brm->desc[descriptor].ctrl);
1430                brm->desc[descriptor].ctrl = tmp & ~0x10;
1431#ifdef DEBUG
1432                brm->log[brm->log_i++ % EVENT_QUEUE_SIZE] = (0xfe<<16);
1433                brm->log[brm->log_i++ % EVENT_QUEUE_SIZE] = 0;
1434                brm->log[brm->log_i++ % EVENT_QUEUE_SIZE] = tmp & ~0x10;
1435                brm->log[brm->log_i++ % EVENT_QUEUE_SIZE] = tmp;
1436#endif
1437        } /* While */
1438
1439        /* clear interrupt flags & handle Hardware errors */
1440        pending = READ_REG(&brm->regs->ipend);
1441
1442        if ( pending & BRM_DMAF_IRQ){
1443                FUNCDBG("BRM: BRM_DMAF_IRQ\n\r");
1444                event_status |= BRM_DMAF_IRQ;
1445                signal_event=1;
1446        }
1447
1448        if ( pending & BRM_WRAPF_IRQ){
1449                FUNCDBG("BRM: BRM_WRAPF_IRQ\n\r");
1450                event_status |= BRM_WRAPF_IRQ;
1451                signal_event=1;
1452        }
1453
1454        if ( pending & BRM_TAPF_IRQ){
1455                FUNCDBG("BRM: BRM_TAPF_IRQ\n\r");
1456                event_status |= BRM_TAPF_IRQ;
1457                signal_event=1;
1458        }
1459
1460        /* Copy current mask to status mask */
1461        if ( event_status ){
1462                if ( event_status & 0xffff0000 )
1463                        brm->status &= 0x0000ffff;
1464                brm->status |= event_status;
1465        }
1466
1467        /* Wake any blocked rx thread only on receive interrupts */
1468        if ( wake_rx_task ) {
1469                rtems_semaphore_release(brm->rx_sem);
1470        }
1471
1472        /* Wake any blocked tx thread only on transmit interrupts */
1473        if ( wake_tx_task ) {
1474                rtems_semaphore_release(brm->tx_sem);
1475        }       
1476
1477        /* signal event once */
1478        if ( signal_event && (brm->event_id!=0) ){
1479                rtems_event_send(brm->event_id, event_status);
1480        }
1481
1482}
1483
1484void b1553brm_print_dev(struct drvmgr_dev *dev, int options)
1485{
1486        brm_priv *pDev = dev->priv;
1487        struct brm_reg *regs = pDev->regs;
1488
1489        /* Print */
1490        printf("--- B1553BRM[%d] %s ---\n", pDev->minor, pDev->devName);
1491        printf(" REGS:            0x%x\n", (unsigned int)pDev->regs);
1492        printf(" IRQ:             %d\n", pDev->irqno);
1493        switch (pDev->mode) {
1494                case BRM_MODE_BC:
1495                        printf(" MODE:            BC\n");
1496                        printf(" DESCS:           0x%x\n", (unsigned int)&pDev->bcmem->descs[0]);
1497                        printf(" DATA:            0x%x\n", (unsigned int)&pDev->bcmem->msg_data[0].data[0]);
1498                        printf(" IRQLOG:          0x%x\n", (unsigned int)&pDev->bcmem->irq_logs[0]);
1499                        break;
1500                case BRM_MODE_BM:
1501                        printf(" MODE:            BM\n");
1502                        break;
1503                case BRM_MODE_RT:
1504                        printf(" MODE:            RT\n");
1505                        printf(" RXSUBS:          0x%x\n", (unsigned int)&pDev->rtmem->rxsubs[0]);
1506                        printf(" TXSUBS:          0x%x\n", (unsigned int)&pDev->rtmem->txsubs[0]);
1507                        printf(" RXMODES:         0x%x\n", (unsigned int)&pDev->rtmem->rxmodes[0]);
1508                        printf(" TXOMODES:        0x%x\n", (unsigned int)&pDev->rtmem->txmodes[0]);
1509                        printf(" RXSUBS MSGS:     0x%x\n", (unsigned int)&pDev->rtmem->rxsuba_msgs[0]);
1510                        printf(" TXSUBS MSGS:     0x%x\n", (unsigned int)&pDev->rtmem->txsuba_msgs[0]);
1511                        printf(" RXMODES MSGS:    0x%x\n", (unsigned int)&pDev->rtmem->rxmode_msgs[0]);
1512                        printf(" TXMODES MSGS:    0x%x\n", (unsigned int)&pDev->rtmem->txmode_msgs[0]);
1513                        printf(" IRQLOG:          0x%x\n", (unsigned int)&pDev->rtmem->irq_logs[0]);
1514                        break;
1515        }
1516        printf(" CTRL:            0x%x\n", regs->ctrl);
1517        printf(" OPER:            0x%x\n", regs->oper);
1518        printf(" CUR_CMD:         0x%x\n", regs->cur_cmd);
1519        printf(" IMASK:           0x%x\n", regs->imask);
1520        printf(" IPEND:           0x%x\n", regs->ipend);
1521        printf(" IPOINT:          0x%x\n", regs->ipoint);
1522        printf(" BIT_REG:         0x%x\n", regs->bit_reg);
1523        printf(" TTAG:            0x%x\n", regs->ttag);
1524        printf(" DPOINT:          0x%x\n", regs->dpoint);
1525        printf(" SW:              0x%x\n", regs->sw);
1526        printf(" INITCOUNT:       0x%x\n", regs->initcount);
1527        printf(" MCPOINT:         0x%x\n", regs->mcpoint);
1528        printf(" MDPOINT:         0x%x\n", regs->mdpoint);
1529        printf(" MBC:             0x%x\n", regs->mbc);
1530        printf(" MFILTA:          0x%x\n", regs->mfilta);
1531        printf(" MFILTB:          0x%x\n", regs->mfiltb);
1532        printf(" ENHANCED:        0x%x\n", regs->enhanced);
1533        printf(" W_CTRL:          0x%x\n", regs->w_ctrl);
1534        printf(" W_IRQCTRL:       0x%x\n", regs->w_irqctrl);
1535        printf(" W_AHBADDR:       0x%x\n", regs->w_ahbaddr);
1536}
1537
1538void b1553brm_print(int options)
1539{
1540        struct amba_drv_info *drv = &b1553brm_drv_info;
1541        struct drvmgr_dev *dev;
1542
1543        dev = drv->general.dev;
1544        while(dev) {
1545                b1553brm_print_dev(dev, options);
1546                dev = dev->next_in_drv;
1547        }
1548}
Note: See TracBrowser for help on using the repository browser.