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

4.104.114.84.95
Last change on this file since a3ae7d7a was a3ae7d7a, checked in by Joel Sherrill <joel.sherrill@…>, on 09/18/07 at 20:59:57

2007-09-18 Joel Sherrill <joel.sherrill@…>

  • shared/1553/b1553brm.c, shared/can/grcan.c: Remove include of sched.h
  • Property mode set to 100644
File size: 39.0 KB
Line 
1/*
2 *  BRM driver 
3 *
4 *  COPYRIGHT (c) 2006.
5 *  Gaisler Research.
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.com/license/LICENSE.
10 *
11 */
12
13/********** Set defaults **********/
14
15/* basic bus/interface of device,
16 * Default to direct accessed AMBA bus.
17 */
18#ifndef B1553BRM_NO_AMBA
19 #define B1553BRM_AMBA
20 #undef B1553BRM_PCI
21#endif
22
23/* default name to /dev/brm */
24#if !defined(B1553BRM_DEVNAME) || !defined(B1553BRM_DEVNAME_NO)
25 #undef B1553BRM_DEVNAME
26 #undef B1553BRM_DEVNAME_NO
27 #define B1553BRM_DEVNAME "/dev/brm0"
28 #define B1553BRM_DEVNAME_NO(devstr,no) ((devstr)[8]='0'+(no))
29#endif
30
31#ifndef B1553BRM_PREFIX
32 #define B1553BRM_PREFIX(name) b1553brm##name
33#endif
34
35/* default to no translation */
36#ifndef B1553BRM_ADR_TO
37 #define memarea_to_hw(x) ((unsigned int)(x))
38#endif
39
40#ifndef B1553BRM_REG_INT
41 #define B1553BRM_REG_INT(handler,irqno,arg) set_vector(handler,(irqno)+0x10,1)
42  #undef  B1553BRM_DEFINE_INTHANDLER
43  #define B1553BRM_DEFINE_INTHANDLER
44#endif
45
46/* default to 128K memory layout */
47#if !defined(DMA_MEM_16K)
48 #define DMA_MEM_128K
49#endif
50
51#include <bsp.h>
52#include <rtems/libio.h>
53#include <stdlib.h>
54#include <stdio.h>
55#include <string.h>
56#include <assert.h>
57#include <ctype.h>
58#include <rtems/bspIo.h>
59
60#include <b1553brm.h>
61#include <ambapp.h>
62
63/* Uncomment for debug output */
64/*#define DEBUG 1
65#define FUNCDEBUG 1*/
66#undef DEBUG
67#undef FUNCDEBUG
68
69/* EVENT_QUEUE_SIZE sets the size of the event queue
70 */
71#define EVENT_QUEUE_SIZE           1024 
72
73
74#define INDEX(x) ( x&(EVENT_QUEUE_SIZE-1) )
75
76#ifdef DEBUG
77#define DBG(x...) printk(x)
78#else
79#define DBG(x...)
80#endif
81
82#ifdef FUNCDEBUG
83#define FUNCDBG(x...) printk(x)
84#else
85#define FUNCDBG(x...)
86#endif
87
88#define READ_REG(address) _BRM_REG_READ16((unsigned int)address)
89#define READ_DMA(address) _BRM_REG_READ16((unsigned int)address)
90static __inline__ unsigned short _BRM_REG_READ16(unsigned int addr) {
91        unsigned short tmp;
92        asm(" lduha [%1]1, %0 "
93          : "=r"(tmp)
94          : "r"(addr)
95        );
96        return tmp;
97}
98
99static rtems_device_driver brm_initialize(rtems_device_major_number major, rtems_device_minor_number minor, void *arg);
100static rtems_device_driver brm_open(rtems_device_major_number major, rtems_device_minor_number minor, void *arg);
101static rtems_device_driver brm_close(rtems_device_major_number major, rtems_device_minor_number minor, void *arg);
102static rtems_device_driver brm_read(rtems_device_major_number major, rtems_device_minor_number minor, void *arg);
103static rtems_device_driver brm_write(rtems_device_major_number major, rtems_device_minor_number minor, void *arg);
104static rtems_device_driver brm_control(rtems_device_major_number major, rtems_device_minor_number minor, void *arg);
105
106#define BRM_DRIVER_TABLE_ENTRY { brm_initialize, brm_open, brm_close, brm_read, brm_write, brm_control }
107
108static rtems_driver_address_table brm_driver = BRM_DRIVER_TABLE_ENTRY;
109
110struct msg {
111        unsigned short miw;
112        unsigned short time;
113        unsigned short data[32];
114};
115#if defined(DMA_MEM_128K)
116struct circ_buf {
117        struct msg msgs[9];
118};
119#elif defined(DMA_MEM_16K)
120/* two message queue */
121struct circ_buf_2 {
122        struct msg msgs[2];
123};
124/* one message queue */
125struct circ_buf_1 {
126        struct msg msgs[1];
127};
128#endif
129
130struct irq_log_list {
131        volatile unsigned short iiw;
132        volatile unsigned short iaw;
133};
134
135typedef struct {
136
137    unsigned int memarea_base;
138    struct brm_reg *regs;
139
140    /* BRM descriptors */
141    struct desc_table {
142
143        volatile unsigned short ctrl;       
144        volatile unsigned short top;
145        volatile unsigned short cur;
146        volatile unsigned short bot;
147
148    } *desc;
149
150    volatile unsigned short *mem;
151                /* bc mem struct */
152                struct {
153                        /* BC Descriptors */
154                        struct {
155                                unsigned short ctrl; /* control */
156                                unsigned short cw1;  /* Command word 1*/
157                                unsigned short cw2;  /* Command word 1*/
158                                unsigned short dptr; /* Data pointer in halfword offset from bcmem */
159                                unsigned short tsw[2]; /* status word 1 & 2 */
160                                unsigned short ba;     /* branch address */
161                                unsigned short timer;  /* timer value */
162                        } descs[128]; /* 2k (1024 half words) */
163                       
164                        /* message data */
165                        struct {
166                                unsigned short data[32]; /* 1 message's data */
167                        } msg_data[128]; /* 8k */
168
169#if defined(DMA_MEM_128K)
170                        /* offset to last 64bytes of 128k */
171                        unsigned short unused[(64*1024-(128*8+128*32))-16*2];
172#elif defined(DMA_MEM_16K)
173                        unsigned short unused[(8*1024-(128*8+128*32))-16*2];
174#endif
175                        /* interrupt log at 64 bytes from end */
176                        struct irq_log_list irq_logs[16];
177                } *bcmem;
178
179#if defined(DMA_MEM_128K)
180                /* Memory structure of a RT being inited, just used
181                 * for RT initialization.
182                 *
183                 * *mesgs[32] fit each minimally 8 messages per sub address.
184                 */
185                struct {
186                        /* RX Sub Address descriptors */
187                        struct desc_table rxsubs[32];
188                        /* TX Sub Address descriptors */
189                        struct desc_table txsubs[32];
190                        /* RX mode code descriptors */
191                        struct desc_table rxmodes[32];
192                        /* TX mode code descriptors */
193                        struct desc_table txmodes[32];
194                       
195                        /* RX Sub Address messages */
196                        struct circ_buf rxsuba_msgs[32];
197                        /* TX Sub Address messages */
198                        struct circ_buf txsuba_msgs[32];
199                        /* RX Mode Code messages */
200                        struct circ_buf rxmode_msgs[32];
201                        /* RX Mode Code messages */
202                        struct circ_buf txmode_msgs[32];
203                       
204                       
205                        /* offset to last 64bytes of 128k: tot-used-needed */
206                        unsigned short unused[(64*1024-(4*32*4+4*32*9*34))-16*2];
207                       
208                        /* interrupt log at 64 bytes from end */
209                        struct irq_log_list irq_logs[16];
210                } *rtmem;
211#elif defined(DMA_MEM_16K)
212                /* Memory structure of a RT being inited, just used
213                 * for RT initialization.
214                 *
215                 * circ_buf_2 *mesgs[32] fit each minimally 2 messages per queue.
216                 * circ_buf_1 *mesgs[32] fit each minimally 1 messages per queue.
217                 */
218                struct {
219                        /* RX Sub Address descriptors */
220                        struct desc_table rxsubs[32];
221                        /* TX Sub Address descriptors */
222                        struct desc_table txsubs[32];
223                        /* RX mode code descriptors */
224                        struct desc_table rxmodes[32];
225                        /* TX mode code descriptors */
226                        struct desc_table txmodes[32];
227                       
228                        /* RX Sub Address messages */
229                        struct circ_buf_2 rxsuba_msgs[32];
230                        /* TX Sub Address messages */
231                        struct circ_buf_2 txsuba_msgs[32];
232                        /* RX Mode Code messages */
233                        struct circ_buf_2 rxmode_msgs[32];
234                        /* RX Mode Code messages */
235                        struct circ_buf_1 txmode_msgs[32];
236                       
237                       
238                        /* offset to last 64bytes of 16k: tot-used-needed */
239                        unsigned short unused[8*1024 -(4*32*4 +3*32*2*34 +1*32*1*34) -16*2];
240                       
241                        /* interrupt log at 64 bytes from end */
242                        struct irq_log_list irq_logs[16];
243                } *rtmem;
244#else
245        #error You must define one DMA_MEM_???K
246#endif
247
248    /* Interrupt log list */
249    struct irq_log_list *irq_log;
250    unsigned int irq;
251
252    /* Received events waiting to be read */
253    struct rt_msg *rt_event;
254    struct bm_msg *bm_event;
255
256    unsigned int head, tail;
257
258    unsigned int last_read[128];
259    unsigned int written[32];
260
261    struct bc_msg *cur_list;
262
263    int tx_blocking, rx_blocking;
264
265    rtems_id rx_sem, tx_sem, dev_sem;
266                int minor;
267                int irqno;
268                unsigned int mode;
269#ifdef DEBUG                   
270                unsigned int log[EVENT_QUEUE_SIZE*4];
271                unsigned int log_i;
272#endif
273               
274                rtems_id event_id; /* event that may be signalled upon errors, needs to be set through ioctl command BRM_SET_EVENTID */
275                unsigned int status;
276                int bc_list_fail;
277} brm_priv;
278
279static int brm_cores;
280static unsigned int allbrm_memarea;
281static brm_priv *brms;
282static amba_confarea_type *amba_bus;
283static unsigned int     allbrm_cfg_clksel;
284static unsigned int allbrm_cfg_clkdiv;
285static unsigned int allbrm_cfg_freq;
286
287static void brm_interrupt(brm_priv *brm);
288#ifdef B1553BRM_DEFINE_INTHANDLER
289static void b1553brm_interrupt_handler(rtems_vector_number v);
290#endif
291
292#define OFS(ofs) (((unsigned int)&ofs & 0x1ffff)>>1)
293
294static int odd_parity(unsigned int data) {
295    unsigned int i=0;
296
297    while(data)
298    {
299        i++;
300        data &= (data - 1);
301    }
302
303    return !(i&1);
304}
305
306
307static void start_operation(brm_priv *brm) {
308        unsigned int ctrl = READ_REG(&brm->regs->ctrl);
309        brm->regs->ctrl = ctrl | 0x8000;
310}
311
312static void stop_operation(brm_priv *brm) {
313        unsigned int ctrl = READ_REG(&brm->regs->ctrl);
314  brm->regs->ctrl = ctrl & ~0x8000;
315}
316static int is_executing(brm_priv *brm) {
317        unsigned int ctrl = READ_REG(&brm->regs->ctrl);
318        return ((ctrl>>15) & 1);
319}
320
321#ifdef LEON3
322#ifndef DONT_DEF_RAMON
323int brm_register_leon3_ramon_fpga(void){
324        /* Clock div & Clock sel is NOT available.
325         * The BRM is always clocked with 24MHz.
326         * 3 in BRM enhanced register will select 24MHz
327         */
328        return b1553brm_register(&amba_conf,0,0,3);
329}
330
331int brm_register_leon3_ramon_asic(void){
332        /* Clock div & Clock sel is available.
333         * Clkdiv only matter when clksel is 1.
334         * clksel=2, clkdiv=don't care, brm_frq=24MHz
335         *
336         * 3 in BRM enhanced register will select 24MHz
337         */
338        return b1553brm_register(&amba_conf,2,0,3);
339}
340#endif
341#endif
342
343int B1553BRM_PREFIX(_register)(amba_confarea_type *bus, unsigned int clksel, unsigned int clkdiv, unsigned int brm_freq)
344{
345    rtems_status_code r;
346    rtems_device_major_number m;
347
348    FUNCDBG("brm_register:\n\r");
349               
350                /* save amba bus pointer */
351                amba_bus = bus;
352                if ( !bus ){
353                        printk("brm_register: bus is NULL\n\r");
354                        return 1;
355                }
356                       
357#ifdef B1553BRM_LOCAL_MEM
358                allbrm_memarea = B1553BRM_LOCAL_MEM_ADR;
359#else
360                allbrm_memarea = 0;
361#endif
362               
363                /* Save clksel, clkdiv and brm_freq for later use */
364                allbrm_cfg_clksel = clksel & CLKSEL_MASK;
365                allbrm_cfg_clkdiv = clkdiv & CLKDIV_MASK;
366                allbrm_cfg_freq = brm_freq & BRM_FREQ_MASK;
367               
368    if ((r = rtems_io_register_driver(0, &brm_driver, &m)) == RTEMS_SUCCESSFUL) {
369        DBG("BRM: driver successfully registered, major: %d\n",m);
370
371    } else {
372        switch(r) {
373        case RTEMS_TOO_MANY:
374            printk("BRM rtems_io_register_driver failed: RTEMS_TOO_MANY\n"); break;
375        case RTEMS_INVALID_NUMBER:
376            printk("BRM rtems_io_register_driver failed: RTEMS_INVALID_NUMBER\n"); break;
377        case RTEMS_RESOURCE_IN_USE:
378            printk("BRM rtems_io_register_driver failed: RTEMS_RESOURCE_IN_USE\n"); break;
379        default:
380           printk("BRM rtems_io_register_driver failed\n");
381        }
382                                return 1;
383    }
384                return 0;
385}
386
387static void clr_int_logs(struct irq_log_list *logs){
388        int i;
389        for(i=0; i<16; i++){
390                logs[i].iiw = 0xffff;
391                logs[i].iaw = 0x0;
392        }
393}
394
395static rtems_device_driver rt_init(brm_priv *brm) {
396        unsigned int i;
397
398        brm->head = brm->tail = 0;
399        brm->rx_blocking = brm->tx_blocking = 1;
400
401  if ( brm->bm_event )
402                free(brm->bm_event);
403        brm->bm_event = NULL;
404
405  if ( brm->rt_event )
406                free(brm->rt_event);
407       
408        brm->bcmem = NULL;
409        brm->rtmem = (void *)brm->mem;
410
411        brm->rt_event = (struct rt_msg *) malloc(EVENT_QUEUE_SIZE*sizeof(struct rt_msg));
412 
413        if (brm->rt_event == NULL) {
414                DBG("BRM driver failed to allocated memory.");
415                return RTEMS_NO_MEMORY;
416        }
417
418        brm->irq_log = (struct irq_log_list *)&brm->rtmem->irq_logs[0];
419
420        brm->regs->ctrl   = 0x1912;  /* enable both buses, circular 1 bufmode, broadcast, interrupt log */
421        brm->regs->oper   = 0x0900;  /* configure as RT, with addr 1 */
422        brm->regs->imask         = BRM_RT_ILLCMD_IRQ|BRM_SUBAD_IRQ|BRM_TAPF_IRQ|BRM_DMAF_IRQ|BRM_WRAPF_IRQ|BRM_MERR_IRQ;
423        brm->regs->dpoint       = 0;
424        brm->regs->ipoint       = OFS(brm->rtmem->irq_logs[0]);
425        brm->regs->enhanced  = 0x0000 | allbrm_cfg_freq;  /* BRM clocked with freq = 12,16,20 or 24MHz */
426        brm->regs->w_ctrl       = (allbrm_cfg_clksel<<9) | (allbrm_cfg_clkdiv<<5) | 1;
427        brm->regs->w_irqctrl = 6;
428        brm->regs->w_ahbaddr = (unsigned int) memarea_to_hw(brm->memarea_base);
429               
430        clr_int_logs(brm->irq_log);
431
432        /* Legalize all commands */
433        for (i = 0; i < 16; i++) {
434                brm->regs->rt_cmd_leg[i] = 0;
435        }
436
437        /* Init descriptor table
438         *
439         * Each circular buffer has room for 8 messages with up to 34 (32 data + miw + time) words (16b) in each.
440         * The buffers must separated by 34 words.
441         */
442
443 
444        /* RX Sub-address 0 - 31 */
445        for (i = 0; i < 32; i++) {
446                brm->rtmem->rxsubs[i].ctrl = 0x00E0;                            /* Interrupt: INTX, IWA, and IBRD */
447                brm->rtmem->rxsubs[i].top  = OFS(brm->rtmem->rxsuba_msgs[i]);                /* Top address */
448                brm->rtmem->rxsubs[i].cur  = OFS(brm->rtmem->rxsuba_msgs[i]);                /* Current address */
449                brm->rtmem->rxsubs[i].bot  = OFS(brm->rtmem->rxsuba_msgs[i+1]) - sizeof(struct msg)/2; /* Bottom address */     
450                brm->last_read[i] = OFS(brm->rtmem->rxsuba_msgs[i]);
451        }
452        /* TX Sub-address 0 - 31 */
453        for (i = 0; i < 32; i++) {
454                brm->rtmem->txsubs[i].ctrl  = 0x0060;                                   /* Interrupt: IWA and IBRD */
455                brm->rtmem->txsubs[i].top   = OFS(brm->rtmem->txsuba_msgs[i]);                    /* Top address */
456                brm->rtmem->txsubs[i].cur   = OFS(brm->rtmem->txsuba_msgs[i]);                    /* Current address */
457                brm->rtmem->txsubs[i].bot   = OFS(brm->rtmem->txsuba_msgs[i+1]) - sizeof(struct msg)/2; /* Bottom address */
458                brm->last_read[i+32]  = OFS(brm->rtmem->txsuba_msgs[i]);
459                brm->written[i] = OFS(brm->rtmem->txsuba_msgs[i]);
460        }
461        /* RX mode code 0 - 31 */
462        for (i = 0; i < 32; i++) {
463                brm->rtmem->rxmodes[i].ctrl = 0x00E0;                                   /* Interrupt: INTX, IWA, and IBRD */
464                brm->rtmem->rxmodes[i].top  = OFS(brm->rtmem->rxmode_msgs[i]);                    /* Top address */
465                brm->rtmem->rxmodes[i].cur  = OFS(brm->rtmem->rxmode_msgs[i]);                    /* Current address */
466                brm->rtmem->rxmodes[i].bot  = OFS(brm->rtmem->rxmode_msgs[i+1]) - sizeof(struct msg)/2; /* Bottom address */
467                brm->last_read[i+64] = OFS(brm->rtmem->rxmode_msgs[i]);
468        }   
469        /* TX mode code 0 - 31 */
470        for (i = 0; i < 32; i++) {
471                brm->rtmem->txmodes[i].ctrl = 0x0060;                                   /* Interrupt: IWA and IBRD */
472                brm->rtmem->txmodes[i].top  = OFS(brm->rtmem->txmode_msgs[i]);                    /* Top address */
473                brm->rtmem->txmodes[i].cur  = OFS(brm->rtmem->txmode_msgs[i]);                    /* Current address */
474                brm->rtmem->txmodes[i].bot  = OFS(brm->rtmem->txmode_msgs[i+1]) - sizeof(struct msg)/2; /* Bottom address */
475                brm->last_read[i+96] = OFS(brm->rtmem->txmode_msgs[i]);
476        }
477       
478        brm->mode = BRM_MODE_RT;
479
480        return RTEMS_SUCCESSFUL;
481}
482
483static rtems_device_driver bc_init(brm_priv *brm){
484
485  if ( brm->bm_event )
486                free(brm->bm_event);
487        brm->bm_event = NULL;
488
489  if ( brm->rt_event )
490                free(brm->rt_event);
491        brm->rt_event = NULL;
492       
493        brm->bcmem = (void *)brm->mem;
494        brm->rtmem = NULL;
495        brm->irq_log = (struct irq_log_list *)&brm->bcmem->irq_logs[0];
496       
497        brm->head = brm->tail = 0;
498        brm->rx_blocking = brm->tx_blocking = 1;
499       
500        brm->regs->ctrl   = 0x0006;  /* ping pong enable and enable interrupt log */
501        brm->regs->oper   = 0x0800;  /* configure as BC */
502        brm->regs->imask         = BRM_EOL_IRQ|BRM_BC_ILLCMD_IRQ|BRM_ILLOP_IRQ|BRM_DMAF_IRQ|BRM_WRAPF_IRQ|BRM_MERR_IRQ;
503        brm->regs->dpoint       = 0;
504        printk("Set BC interrupt log: 0x%lx, 0x%lx, 0x%lx\n",OFS(brm->bcmem->irq_logs[0]),&brm->bcmem->irq_logs[0],brm->bcmem);
505        brm->regs->ipoint       = OFS(brm->bcmem->irq_logs[0]);
506        brm->regs->enhanced  = 0x0000 | (allbrm_cfg_freq&0x3);  /* freq = 24 */
507        brm->regs->w_ctrl       = (allbrm_cfg_clksel<<9) | (allbrm_cfg_clkdiv<<5) | 1;
508        brm->regs->w_irqctrl = 6;
509        brm->regs->w_ahbaddr = (unsigned int) memarea_to_hw(brm->memarea_base);
510       
511        clr_int_logs(brm->irq_log);
512       
513        brm->mode = BRM_MODE_BC;
514       
515        return RTEMS_SUCCESSFUL;
516}
517
518static rtems_device_driver bm_init(brm_priv *brm) {
519
520
521        brm->head = brm->tail = 0;
522        brm->rx_blocking = brm->tx_blocking = 1;
523
524  if ( brm->rt_event )
525                free(brm->rt_event);
526        brm->rt_event = NULL;
527
528  if ( brm->bm_event )
529                free(brm->bm_event);
530       
531        brm->bcmem = NULL;
532        brm->rtmem = NULL;
533       
534        brm->bm_event    = (struct bm_msg *) malloc(EVENT_QUEUE_SIZE*sizeof(struct bm_msg));
535 
536        if (brm->bm_event == NULL) {
537                DBG("BRM driver failed to allocated memory.");
538                return RTEMS_NO_MEMORY;
539        }
540
541        /* end of 16K, fits all current modes (128K, 16K) */
542        brm->irq_log = (struct irq_log_list *)&brm->mem[8*1024-16*2];
543
544        brm->regs->ctrl   = 0x0006;  /* ping pong enable and enable interrupt log */
545        brm->regs->oper   = 0x0A00;  /* configure as BM */
546        brm->regs->imask        = BRM_MBC_IRQ|BRM_MERR_IRQ|BRM_DMAF_IRQ|BRM_MERR_IRQ;
547        brm->regs->dpoint       = 0;
548        brm->regs->ipoint       = OFS(brm->mem[8*1024-16*2]);
549        brm->regs->mcpoint   = 0;          /* Command pointer */
550        brm->regs->mdpoint   = 0x100;   /* Data pointer */
551        brm->regs->mbc     = 1;    /* Block count */
552        brm->regs->enhanced  = 0x0000 | (allbrm_cfg_freq&0x3);  /* freq = 24 */
553        brm->regs->w_ctrl       = (allbrm_cfg_clksel<<9) | (allbrm_cfg_clkdiv<<5) | 1;
554        brm->regs->w_irqctrl = 6;
555        brm->regs->w_ahbaddr = (unsigned int) memarea_to_hw(brm->memarea_base);
556       
557        clr_int_logs(brm->irq_log);
558       
559        brm->mode = BRM_MODE_BM;
560       
561        return RTEMS_SUCCESSFUL;
562}
563
564
565static rtems_device_driver brm_initialize(rtems_device_major_number major, rtems_device_minor_number minor, void *arg)
566{
567        rtems_status_code status;
568        int dev_cnt;
569        char fs_name[20];
570        brm_priv *brm;
571        amba_ahb_device ambadev;
572        char *mem;
573   
574        FUNCDBG("brm_initialize\n");
575
576        brm_cores = 0;
577        strcpy(fs_name,B1553BRM_DEVNAME);
578       
579        /* Find all BRM devices */
580        dev_cnt = amba_get_number_ahbslv_devices(amba_bus,VENDOR_GAISLER,GAISLER_BRM);
581        if ( dev_cnt < 1 ){
582                /* Failed to find any CAN cores! */
583                printk("BRM: Failed to find any BRM cores\n\r");
584                return -1;
585        }
586               
587        /* allocate & zero memory for the brm devices */
588        brms = (brm_priv *)malloc(sizeof(*brms)*dev_cnt);
589        if ( !brms ){
590                printk("BRM: Failed to allocate SW memory\n\r");
591                return -1;
592        }
593        memset(brms,0,sizeof(*brms)*dev_cnt);   
594       
595        /* Allocate memory for all device's descriptors,
596         * they must be aligned to a XXX byte boundary.
597         */
598        #define BRM_DESCS_PER_CTRL 128
599        if ( allbrm_memarea ){
600                mem = (char *)allbrm_memarea;
601        }else{
602                /* sizeof(struct desc_table) * BRM_DESCS_PER_CTRL * dev_cnt */
603                mem = (char *)malloc( (128*1024) * (dev_cnt+1)); /* 128k per core + 128k for alignment */
604                if ( !mem ){
605                        free(brms);
606                        printk("BRM: Failed to allocate HW memory\n\r");
607                        return -1;
608                }
609       
610                /* align memory to 128k boundary */
611                mem = (char *)(((unsigned int)mem+0x1ffff) & ~0x1ffff);
612        }
613
614        /* clear the used memory */
615        memset(mem,0,(128*1024) * dev_cnt);
616
617        /* initialize each brm device, one at a time */
618        for(minor=0; minor<dev_cnt; minor++){
619                brm = &brms[minor];
620               
621                /* Get AMBA AHB device info from Plug&Play */
622                amba_find_next_ahbslv(amba_bus,VENDOR_GAISLER,GAISLER_BRM,&ambadev,minor);
623               
624                /* Copy Basic HW info */
625                brm->regs = (void *)ambadev.start[0];
626                brm->irqno = ambadev.irq;
627                brm->minor = minor;
628                brm->irq = 0;
629#ifdef DEBUG
630                brm->log_i = 0;
631                memset(brm->log,0,sizeof(brm->log));
632#endif
633               
634                /* Set unique name */
635                B1553BRM_DEVNAME_NO(fs_name,minor);
636   
637    DBG("Registering BRM core at [0x%x] irq %d, minor %d as %s\n",brm->regs,brm->irqno,minor,fs_name);
638               
639                /* Bind filesystem name to device number (minor) */
640                status = rtems_io_register_name(fs_name, major, minor);
641    if (status != RTEMS_SUCCESSFUL)
642                        rtems_fatal_error_occurred(status);
643       
644                /* RX Semaphore created with count = 0 */
645                if ( rtems_semaphore_create(rtems_build_name('B', 'M', 'R', '0'+minor),
646                         0,
647                         RTEMS_FIFO|RTEMS_SIMPLE_BINARY_SEMAPHORE|RTEMS_NO_INHERIT_PRIORITY|RTEMS_LOCAL|RTEMS_NO_PRIORITY_CEILING,
648                         0,
649                         &brm->rx_sem) != RTEMS_SUCCESSFUL ){
650      printk("BRM: Failed to create rx semaphore\n");
651                return RTEMS_INTERNAL_ERROR;
652    }
653
654                        /* TX Semaphore created with count = 1 */
655                if ( rtems_semaphore_create(rtems_build_name('B', 'M', 'T', '0'+minor),
656                         1,
657                         RTEMS_FIFO|RTEMS_SIMPLE_BINARY_SEMAPHORE|RTEMS_NO_INHERIT_PRIORITY|RTEMS_LOCAL|RTEMS_NO_PRIORITY_CEILING,
658                         0,
659                         &brm->tx_sem) != RTEMS_SUCCESSFUL ){
660      printk("BRM: Failed to create tx semaphore\n");
661                return RTEMS_INTERNAL_ERROR;
662    }
663
664                /* Device Semaphore created with count = 1 */
665                if ( rtems_semaphore_create(rtems_build_name('B', 'M', 'D', '0'+minor),
666                         1,
667                         RTEMS_FIFO|RTEMS_SIMPLE_BINARY_SEMAPHORE|RTEMS_NO_INHERIT_PRIORITY|RTEMS_LOCAL|RTEMS_NO_PRIORITY_CEILING,
668                         0,
669                         &brm->dev_sem) != RTEMS_SUCCESSFUL ){
670      printk("BRM: Failed to create device semaphore\n");
671                return RTEMS_INTERNAL_ERROR;
672    }
673
674       
675                /* Set base address of all descriptors */
676                brm->memarea_base = (unsigned int)&mem[(128*1024) * minor];
677                brm->desc = (struct desc_table *) brm->memarea_base;
678                brm->mem = (volatile unsigned short *) brm->memarea_base;
679          brm->irq_log  = (struct irq_log_list *)(brm->memarea_base + (0xFFE0<<1)); /* last 64byte */
680               
681                brm->bm_event = NULL;
682                brm->rt_event = NULL;
683               
684                /* Sel clock so that we can write to BRM's registers */
685                brm->regs->w_ctrl = (allbrm_cfg_clksel<<9) | (allbrm_cfg_clkdiv<<5);
686                /* Reset BRM core */
687                brm->regs->w_ctrl = 1<<10 | READ_REG(&brm->regs->w_ctrl);
688               
689                /* Register interrupt handler */
690                B1553BRM_REG_INT(B1553BRM_PREFIX(_interrupt_handler), brm->irqno, brm);
691               
692                rt_init(brm);
693               
694                DBG("BRM: LOG: 0x%lx, 0x%lx\n\r",brm->log,brm);
695        }
696       
697        /* save number of BRM cores found */
698        brm_cores = dev_cnt;
699       
700        DBG("BRM initialisation done.\n");
701       
702        return RTEMS_SUCCESSFUL;
703}
704
705static rtems_device_driver brm_open(rtems_device_major_number major, rtems_device_minor_number minor, void *arg) {
706                brm_priv *brm;
707       
708    FUNCDBG("brm_open\n");
709
710    if (minor >= brm_cores) {
711        DBG("Wrong minor %d\n", minor);
712        return RTEMS_UNSATISFIED; /* ENODEV */
713    }
714               
715                brm = &brms[minor];
716   
717    if (rtems_semaphore_obtain(brm->dev_sem, RTEMS_NO_WAIT, RTEMS_NO_TIMEOUT) != RTEMS_SUCCESSFUL) {
718        DBG("brm_open: resource in use\n");
719        return RTEMS_RESOURCE_IN_USE; /* EBUSY */
720    }
721               
722                /* Set defaults */
723                brm->event_id = 0;
724   
725    start_operation(brm);
726 
727    return RTEMS_SUCCESSFUL;
728}
729 
730static rtems_device_driver brm_close(rtems_device_major_number major, rtems_device_minor_number minor, void *arg)
731{
732        brm_priv *brm = &brms[minor];
733        FUNCDBG("brm_close");
734
735        stop_operation(brm);
736        rtems_semaphore_release(brm->dev_sem);
737
738        return RTEMS_SUCCESSFUL;
739}
740 
741static int get_rt_messages(brm_priv *brm, void *buf, unsigned int msg_count) {
742
743    struct rt_msg *dest = (struct rt_msg *) buf;
744    int count = 0;
745
746    if (brm->head == brm->tail) {
747        return 0;
748    }
749
750    do {
751
752        DBG("rt read - head: %d, tail: %d\n", brm->head, brm->tail);
753        dest[count++] = brm->rt_event[INDEX(brm->tail++)];
754
755    } while (brm->head != brm->tail && count < msg_count);
756
757    return count;
758
759}
760
761static int get_bm_messages(brm_priv *brm, void *buf, unsigned int msg_count) {
762
763    struct bm_msg *dest = (struct bm_msg *) buf;
764    int count = 0;
765
766    if (brm->head == brm->tail) {
767        return 0;
768    }
769
770    do {
771
772        DBG("bm read - head: %d, tail: %d\n", brm->head, brm->tail);
773        dest[count++] = brm->bm_event[INDEX(brm->tail++)];
774
775    } while (brm->head != brm->tail && count < msg_count);
776
777    return count;
778
779}
780
781static rtems_device_driver brm_read(rtems_device_major_number major, rtems_device_minor_number minor, void *arg)
782{
783    rtems_libio_rw_args_t *rw_args;
784    int count = 0;
785                brm_priv *brm = &brms[minor];
786    int (*get_messages)(brm_priv *brm, void *buf, unsigned int count);
787               
788                if ( ! (brm->mode & (BRM_MODE_RT | BRM_MODE_BM)) ){
789                        return RTEMS_INVALID_NAME;
790                }
791 
792    rw_args = (rtems_libio_rw_args_t *) arg;
793   
794    if ( ((READ_REG(&brm->regs->oper)>>8) & 3) == 1 ) { /* RT */
795        get_messages = get_rt_messages;
796    }
797    else { /* BM */
798        get_messages = get_bm_messages;
799    }
800
801
802    FUNCDBG("brm_read [%i,%i]: buf: 0x%x len: %i\n",major, minor, (unsigned int)rw_args->buffer,rw_args->count);
803
804    while ( (count=get_messages(brm,rw_args->buffer, rw_args->count)) == 0 ) {
805
806        if (brm->rx_blocking) {
807            rtems_semaphore_obtain(brm->rx_sem, RTEMS_WAIT, RTEMS_NO_TIMEOUT);
808        }
809        else {
810            /* Translates to EBUSY */
811            return RTEMS_RESOURCE_IN_USE;
812        }
813
814    }
815
816    rw_args->bytes_moved = count;
817    return RTEMS_SUCCESSFUL;
818 
819}
820
821
822static rtems_device_driver brm_write(rtems_device_major_number major, rtems_device_minor_number minor, void *arg)
823{
824    rtems_libio_rw_args_t *rw_args;
825    struct rt_msg *source;
826    unsigned int count=0, current, next, descriptor, wc, suba;
827                brm_priv *brm = &brms[minor];
828 
829                if ( ! (brm->mode & BRM_MODE_RT) ){
830                        return RTEMS_INVALID_NAME;
831                }
832       
833    rw_args = (rtems_libio_rw_args_t *) arg;
834    source = (struct rt_msg *) rw_args->buffer;
835
836    FUNCDBG("brm_write [%i,%i]: buf: 0x%x len: %i\n",major, minor, (unsigned int)rw_args->buffer,rw_args->count);
837 
838    do {
839
840        descriptor = source[count].desc & 0x7F;
841        suba       = descriptor-32;
842        wc         = source[count].miw >> 11;
843        wc = wc ? wc : 32;
844
845        /* Only subaddress transmission is allowed with write */
846        if (descriptor < 32 || descriptor >= 64)
847            return RTEMS_INVALID_NAME;
848
849        current = brm->desc[descriptor].cur;
850        next = brm->written[suba] + 2 + wc;
851
852        if (brm->written[suba] < current) {
853           
854            if (next > current) {
855
856                /* No room in transmission buffer */
857
858                if (brm->tx_blocking && count == 0) {
859                    rtems_semaphore_obtain(brm->tx_sem, RTEMS_WAIT, RTEMS_NO_TIMEOUT);
860                }
861                                                                else if ( brm->tx_blocking && (count != 0) ){
862                                                                        /* return the number of messages sent so far */
863                                                                        break;
864                                                                }
865                else { 
866                    /* Translates to posix EBUSY */
867                    return RTEMS_RESOURCE_IN_USE;
868                }
869            }
870        }
871
872        memcpy((void *)&brm->mem[brm->written[suba]], &source[count], (2+wc)*2);
873       
874        count++;
875
876        if (next >= brm->desc[descriptor].bot) {
877            next = brm->desc[descriptor].top;
878        }
879        brm->written[suba] = next;
880
881    }  while (count < rw_args->count);
882 
883    rw_args->bytes_moved = count;
884
885    if (count >= 0) {
886        return RTEMS_SUCCESSFUL;
887    }
888    return RTEMS_UNSATISFIED;
889}
890
891static rtems_device_driver brm_control(rtems_device_major_number major, rtems_device_minor_number minor, void *arg)
892{
893   
894    unsigned int i=0;
895    unsigned short ctrl, oper, cw1, cw2;
896    rtems_libio_ioctl_args_t *ioarg = (rtems_libio_ioctl_args_t *) arg;
897    unsigned int *data = ioarg->buffer;
898    struct bc_msg *cmd_list = (struct bc_msg *) ioarg->buffer;
899                brm_priv *brm = &brms[minor];
900                rtems_device_driver ret;
901                int len;
902   
903    FUNCDBG("brm_control[%d]: [%i,%i]\n",minor,major, minor);
904 
905    if (!ioarg) {
906        DBG("brm_control: invalid argument\n");
907        return RTEMS_INVALID_NAME;
908    }
909
910    ioarg->ioctl_return = 0;
911    switch(ioarg->command) {
912
913    case BRM_SET_MODE:
914                        if ( data[0] > 2 )
915                                return RTEMS_INVALID_NAME;
916      stop_operation(brm);
917        if (data[0] == 0) {
918            ret = bc_init(brm);
919        }
920        else if (data[0] == 1) {
921            ret = rt_init(brm);                         
922        } 
923        else if (data[0] == 2) {
924            ret = bm_init(brm);                                         
925        }else
926                                        ret = RTEMS_INVALID_NAME;
927
928                                if ( ret != RTEMS_SUCCESSFUL)
929                                                        return ret;
930                               
931        if ( brm->mode & (BRM_MODE_RT | BRM_MODE_BM ) )
932                                        start_operation(brm);
933        break;
934
935    case BRM_SET_BUS:
936        stop_operation(brm);
937                                ctrl = READ_REG(&brm->regs->ctrl);
938        ctrl &= 0xE7FF;                               /* Clear bit 12-11 ...      */
939        ctrl |= (data[0]&0x3)<<11;                    /* ... OR in new bus status */
940                                brm->regs->ctrl = ctrl;
941        start_operation(brm);
942        break;
943
944    case BRM_SET_MSGTO:
945        stop_operation(brm);
946        ctrl = READ_REG(&brm->regs->ctrl);
947                                ctrl &= 0xFDFF;                               /* Clear bit 9 ...          */
948        ctrl |= (data[0]&1)<<9;                       /* ... OR in new MSGTO      */
949                                brm->regs->ctrl = ctrl;
950        start_operation(brm);
951        break;
952
953    case BRM_SET_RT_ADDR:   
954        stop_operation(brm);
955                                oper = READ_REG(&brm->regs->oper);
956        oper &= 0x03FF;                               /* Clear bit 15-10 ...      */
957        oper |= (data[0]&0x1f)<<11;                   /* ... OR in new address    */
958        oper |= odd_parity(data[0]&0x1f)<<10;         /* ... OR in parity         */
959                                brm->regs->oper = oper;
960        start_operation(brm);
961        break;
962 
963    case BRM_SET_STD:   
964        stop_operation(brm);
965                                ctrl = READ_REG(&brm->regs->ctrl);
966        ctrl &= 0xFF7F;                               /* Clear bit 7 ...           */
967        ctrl |= (data[0]&1)<<7;                       /* ... OR in new ABSTD (1=A) */
968                                brm->regs->ctrl = ctrl;
969        start_operation(brm);
970        break;
971
972    case BRM_SET_BCE:
973        stop_operation(brm);
974                                ctrl = READ_REG(&brm->regs->ctrl);
975        ctrl &= 0xFFEF;                               /* Clear bit 4 ...           */
976        ctrl |= (data[0]&1)<<4;                       /* ... OR in new BCE         */
977                                brm->regs->ctrl = ctrl;
978        start_operation(brm);
979     break;
980
981    case BRM_TX_BLOCK:
982        brm->tx_blocking     = data[0];     
983        break;
984
985    case BRM_RX_BLOCK:
986        brm->rx_blocking     = data[0];   
987        break;
988
989    case BRM_DO_LIST:
990
991        if ( brm->mode != BRM_MODE_BC ){
992          return RTEMS_INVALID_NAME;
993                                }
994
995        /* Check if we are bus controller */
996        if ( ((READ_REG(&brm->regs->oper)>>8) & 3) != 0 ) {
997            return RTEMS_INVALID_NAME;
998        }
999
1000        /* Already processing list? */
1001        if (is_executing(brm)) {
1002            return RTEMS_RESOURCE_IN_USE;
1003        }
1004
1005                                /* clear any earlier releases */
1006        rtems_semaphore_obtain(brm->tx_sem, RTEMS_NO_WAIT, RTEMS_NO_TIMEOUT);
1007
1008                                brm->bc_list_fail = 0;
1009        brm->cur_list = cmd_list;
1010                                brm->regs->dpoint = 0;
1011
1012        i = 0;
1013        while ( (cmd_list[i].ctrl & BC_EOL) == 0) {
1014
1015            ctrl = (4<<12) | (((cmd_list[i].ctrl&BC_BUSA)==BC_BUSA)<<9) | (((cmd_list[i].ctrl&BC_RTRT)==BC_RTRT)<<8);
1016
1017            if (cmd_list[i].ctrl&BC_RTRT) {
1018                cw1 = (cmd_list[i].rtaddr[0]<<11) | (0<<10) | (cmd_list[i].subaddr[0]<<5) | (cmd_list[i].wc & 0x1f); /* receive cw */
1019                cw2 = (cmd_list[i].rtaddr[1]<<11) | (1<<10) | (cmd_list[i].subaddr[1]<<5) | (cmd_list[i].wc & 0x1f); /* transmit cw */
1020            }
1021            else {
1022                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);
1023                                                                cw2 = 0;
1024            }
1025
1026
1027            /* Set up command block */
1028            brm->bcmem->descs[i].ctrl = ctrl;
1029            brm->bcmem->descs[i].cw1 = cw1;
1030            brm->bcmem->descs[i].cw2 = cw2;
1031                                                /* data pointer:
1032                                                 * (&brm->bcmem->msg_data[i].data[0] & 0x1ffff) / 2
1033                                                 */
1034            brm->bcmem->descs[i].dptr = 1024+i*32;  /* data pointer */
1035                                                brm->bcmem->descs[i].tsw[0] = 0;
1036                                                brm->bcmem->descs[i].tsw[1] = 0;
1037                                                brm->bcmem->descs[i].ba = 0;
1038                                                brm->bcmem->descs[i].timer = 0;
1039
1040            memcpy((void *)&brm->bcmem->msg_data[i].data[0], &cmd_list[i].data[0], cmd_list[i].wc*2);
1041         
1042            i++;
1043        }
1044
1045        brm->bcmem->descs[i].ctrl = 0; /* end of list */
1046
1047        start_operation(brm);       
1048
1049        break; 
1050
1051    case BRM_LIST_DONE:
1052
1053        if ( brm->mode != BRM_MODE_BC ){
1054          return RTEMS_INVALID_NAME;
1055                                }
1056                               
1057                                /* Check if we are bus controller */
1058        if ( ((READ_REG(&brm->regs->oper)>>8) & 3) != 0 ) {
1059            return RTEMS_INVALID_NAME;
1060        }
1061   
1062        if (is_executing(brm)) {
1063
1064            data[0] = 0;
1065            if (brm->tx_blocking) {
1066                rtems_semaphore_obtain(brm->tx_sem, RTEMS_WAIT, RTEMS_NO_TIMEOUT);
1067                data[0] = 1;
1068                                                                if ( brm->bc_list_fail ){
1069                                                                        return RTEMS_INVALID_NAME;
1070                                                                }
1071            }else{
1072                                                        return RTEMS_RESOURCE_IN_USE;
1073                                                }
1074           
1075           
1076        }
1077        else {
1078            data[0] = 1; /* done */
1079        }
1080
1081        /* copy finished list results back into bc_msg array */
1082        i = 0;
1083        while ( (brm->cur_list[i].ctrl & BC_EOL) == 0) {
1084
1085            if (READ_DMA(&brm->bcmem->descs[i].ctrl) & 1) {
1086                brm->cur_list[i].ctrl |= 0x8000; /* Set BAME */
1087            }
1088            if (brm->cur_list[i].ctrl & BC_TR) {
1089                /* RT Transmit command, copy received data */
1090                                                                len = brm->cur_list[i].wc;
1091                                                                while( len-- > 0){
1092                                                                        brm->cur_list[i].data[len] = READ_DMA(&brm->bcmem->msg_data[i].data[len]);
1093                                                                }
1094            }
1095            brm->cur_list[i].tsw[0] = READ_DMA(&brm->bcmem->descs[i].tsw[0]);
1096            brm->cur_list[i].tsw[1] = READ_DMA(&brm->bcmem->descs[i].tsw[1]);
1097
1098            i++;
1099        }
1100        break;
1101
1102
1103    case BRM_CLR_STATUS:
1104                        brm->status = 0;
1105                        break;
1106               
1107    case BRM_GET_STATUS: /* copy status */
1108
1109                        if ( !ioarg->buffer )
1110                                return RTEMS_INVALID_NAME;
1111                       
1112                        *(unsigned int *)ioarg->buffer = brm->status;
1113                        break;
1114   
1115                case BRM_SET_EVENTID:
1116                        brm->event_id = (rtems_id)ioarg->buffer;
1117                        break;
1118
1119    default:
1120        return RTEMS_NOT_DEFINED;
1121    }
1122    return RTEMS_SUCCESSFUL;
1123}
1124
1125#ifdef B1553BRM_DEFINE_INTHANDLER
1126static void b1553brm_interrupt_handler(rtems_vector_number v){
1127        int i;
1128        /* find minor */
1129        for(i=0; i<brm_cores; i++){
1130                if ( (brms[i].irqno+0x10) == v ){
1131                        brm_interrupt(&brms[i]);
1132                        return;
1133                }
1134        }
1135}
1136#endif
1137
1138static void brm_interrupt(brm_priv *brm) {
1139  unsigned short descriptor, current, pending, miw, wc, tmp;
1140        unsigned short msgadr, iaw, iiw;
1141        int len;
1142        int signal_event=0;
1143        unsigned int event_status=0;
1144        #define SET_ERROR_DESCRIPTOR(descriptor) (event_status = (event_status & 0x0000ffff) | descriptor<<16)
1145               
1146        while( (iiw=READ_REG(&brm->irq_log[brm->irq].iiw)) != 0xffff ){
1147                iaw=READ_REG(&brm->irq_log[brm->irq].iaw);
1148               
1149                /* indicate that the interrupt log entry has been processed */
1150                brm->irq_log[brm->irq].iiw = 0xffff;
1151
1152                /* Interpret interrupt log entry  */
1153    descriptor = iaw >> 2;
1154    pending    = iiw;
1155    brm->irq = (brm->irq + 1) % 16;
1156               
1157                /* Clear the log so that we */
1158               
1159       
1160    /* Subaddress accessed irq (RT only)
1161     *
1162     * Can be either a receive or transmit command
1163     * as well as a mode code.
1164     */
1165    if (pending & BRM_SUBAD_IRQ) {
1166                               
1167        /* Pointer to next free message in circular buffer */
1168        current = READ_DMA(&brm->desc[descriptor].cur);
1169
1170        while  ( (msgadr=brm->last_read[descriptor]) != current) {
1171
1172            /* Get word count */
1173            miw = READ_DMA(&brm->mem[msgadr]);
1174            wc  = miw >> 11;
1175
1176            /* Data received */
1177            if (descriptor < 32) {
1178                wc = wc ? wc : 32;
1179            }
1180            /* Data transmitted */
1181            else if (descriptor < 64) {
1182                wc = wc ? wc : 32; 
1183                rtems_semaphore_release(brm->tx_sem);
1184            }
1185            /* RX Mode code */
1186            else if (descriptor < 96) {
1187                wc = (wc>>4);
1188            } 
1189            /* TX Mode code */
1190            else if (descriptor < 128) {
1191                wc = (wc>>4);
1192            }
1193
1194#ifdef DEBUG           
1195            brm->log[brm->log_i++ % EVENT_QUEUE_SIZE] = (descriptor << 16) | wc;
1196            brm->log[brm->log_i++ % EVENT_QUEUE_SIZE] = current;
1197            brm->log[brm->log_i++ % EVENT_QUEUE_SIZE] = msgadr;
1198#endif
1199
1200            /* If there is room in the event queue, copy the event there */
1201            if (brm->head - brm->tail != EVENT_QUEUE_SIZE) {
1202       
1203                /* Copy to event queue */
1204                                                                brm->rt_event[INDEX(brm->head)].miw = READ_DMA(&brm->mem[msgadr]);
1205                                                                brm->rt_event[INDEX(brm->head)].time = READ_DMA(&brm->mem[msgadr+1]);
1206                                                                len = wc;
1207                                                                while( len-- > 0){
1208                                                                        brm->rt_event[INDEX(brm->head)].data[len] = READ_DMA(&brm->mem[msgadr+2+len]);
1209                                                                }
1210                brm->rt_event[INDEX(brm->head)].desc = descriptor;
1211                brm->head++;
1212
1213            }
1214            else {
1215                /* Indicate overrun */
1216                brm->rt_event[INDEX(brm->head)].desc |= 0x8000;
1217            }
1218
1219            msgadr += (2+wc);
1220
1221            if (msgadr >= brm->desc[descriptor].bot) {
1222                msgadr = brm->desc[descriptor].top;
1223            }
1224                                                brm->last_read[descriptor] = msgadr;
1225
1226#ifdef DEBUG
1227            brm->log[brm->log_i++ % EVENT_QUEUE_SIZE] = msgadr;
1228#endif
1229
1230            /* Wake any blocked rx thread */
1231            rtems_semaphore_release(brm->rx_sem);
1232 
1233        }
1234       
1235    }
1236
1237    if (pending & BRM_EOL_IRQ) { 
1238        rtems_semaphore_release(brm->tx_sem);
1239    }
1240
1241    if (pending & BRM_BC_ILLCMD_IRQ) {
1242                                brm->bc_list_fail = 1;
1243        rtems_semaphore_release(brm->tx_sem);
1244                                SET_ERROR_DESCRIPTOR(descriptor);
1245                                FUNCDBG("BRM: ILLCMD IRQ\n\r");
1246    }
1247
1248    /* Monitor irq */
1249    if (pending & BRM_MBC_IRQ) {
1250                       
1251        stop_operation(brm);
1252        brm->regs->mbc = 1;
1253        start_operation(brm);
1254       
1255        /* If there is room in the event queue, copy the event there */
1256        if (brm->head - brm->tail != EVENT_QUEUE_SIZE) {
1257           
1258            /* Copy to event queue */
1259         
1260            brm->bm_event[INDEX(brm->head)].miw  =  READ_DMA(&brm->mem[0]);
1261            brm->bm_event[INDEX(brm->head)].cw1  =  READ_DMA(&brm->mem[1]);
1262            brm->bm_event[INDEX(brm->head)].cw2  =  READ_DMA(&brm->mem[2]);
1263            brm->bm_event[INDEX(brm->head)].sw1  =  READ_DMA(&brm->mem[4]);
1264            brm->bm_event[INDEX(brm->head)].sw2  =  READ_DMA(&brm->mem[5]);
1265            brm->bm_event[INDEX(brm->head)].time =  READ_DMA(&brm->mem[6]);
1266
1267            len = 32;
1268            while ( len-- ){
1269              brm->bm_event[INDEX(brm->head)].data[len] =  READ_DMA(&brm->mem[0x100+len]);
1270              len--;
1271              brm->bm_event[INDEX(brm->head)].data[len] =  READ_DMA(&brm->mem[0x100+len]);
1272              len--;
1273              brm->bm_event[INDEX(brm->head)].data[len] =  READ_DMA(&brm->mem[0x100+len]);
1274              len--;
1275              brm->bm_event[INDEX(brm->head)].data[len] =  READ_DMA(&brm->mem[0x100+len]);
1276            }
1277/*            memcpy((void *)brm->bm_event[INDEX(brm->head)].data, &brm->mem[0x100], 32);*/
1278
1279#ifdef DEBUG           
1280            brm->log[brm->log_i++ % EVENT_QUEUE_SIZE] = READ_REG(&brm->regs->mbc);
1281            brm->log[brm->log_i++ % EVENT_QUEUE_SIZE] = READ_DMA(&brm->mem[0]);
1282            brm->log[brm->log_i++ % EVENT_QUEUE_SIZE] = READ_DMA(&brm->mem[1]);
1283            brm->log[brm->log_i++ % EVENT_QUEUE_SIZE] = READ_DMA(&brm->mem[4]);
1284#endif
1285
1286            brm->head++;
1287           
1288        }
1289        else {
1290            /* Indicate overrun */
1291            brm->rt_event[INDEX(brm->head)].miw |= 0x8000;
1292        }
1293       
1294        /* Wake any blocking thread */
1295        rtems_semaphore_release(brm->rx_sem);
1296
1297    }
1298               
1299                /* The reset of the interrupts
1300                 * cause a event to be signalled
1301                 * so that user can handle error.
1302                 */
1303                if ( pending & BRM_RT_ILLCMD_IRQ){
1304                        FUNCDBG("BRM: BRM_RT_ILLCMD_IRQ\n\r");
1305                        brm->status |= BRM_RT_ILLCMD_IRQ;
1306                        event_status |= BRM_RT_ILLCMD_IRQ;
1307                        SET_ERROR_DESCRIPTOR(descriptor);
1308                        signal_event=1;
1309                }
1310               
1311                if ( pending & BRM_ILLOP_IRQ){
1312                        FUNCDBG("BRM: BRM_ILLOP_IRQ\n\r");
1313                        brm->bc_list_fail = 1;
1314                        rtems_semaphore_release(brm->tx_sem);
1315                        event_status |= BRM_ILLOP_IRQ;
1316                        SET_ERROR_DESCRIPTOR(descriptor);                       
1317                        signal_event=1;
1318                }
1319               
1320                if ( pending & BRM_MERR_IRQ){
1321                        FUNCDBG("BRM: BRM_MERR_IRQ\n\r");
1322                        event_status |= BRM_MERR_IRQ;
1323                        SET_ERROR_DESCRIPTOR(descriptor);
1324                        signal_event=1;
1325                }
1326            /* Clear Block Accessed Bit */
1327    tmp = READ_REG(&brm->desc[descriptor].ctrl);
1328    brm->desc[descriptor].ctrl = tmp & ~0x10;
1329               
1330        } /* While */
1331       
1332        /* clear interrupt flags & handle Hardware errors */
1333        pending = READ_REG(&brm->regs->ipend);
1334       
1335        if ( pending & BRM_DMAF_IRQ){
1336                FUNCDBG("BRM: BRM_DMAF_IRQ\n\r");
1337                event_status |= BRM_DMAF_IRQ;
1338                signal_event=1;
1339        }
1340       
1341        if ( pending & BRM_WRAPF_IRQ){
1342                FUNCDBG("BRM: BRM_WRAPF_IRQ\n\r");
1343                event_status |= BRM_WRAPF_IRQ;
1344                signal_event=1;
1345        }
1346       
1347        if ( pending & BRM_TAPF_IRQ){
1348                FUNCDBG("BRM: BRM_TAPF_IRQ\n\r");
1349                event_status |= BRM_TAPF_IRQ;
1350                signal_event=1;
1351        }
1352       
1353        /* Copy current mask to status mask */
1354        if ( event_status ){
1355                if ( event_status & 0xffff0000 )
1356                        brm->status &= 0x0000ffff;
1357                brm->status |= event_status;
1358        }
1359       
1360        /* signal event once */
1361        if ( signal_event && (brm->event_id!=0) ){
1362                rtems_event_send(brm->event_id, event_status);
1363        }
1364   
1365}
Note: See TracBrowser for help on using the repository browser.