source: rtems/c/src/lib/libbsp/sparc/shared/can/occan.c @ d6d3eb7

4.115
Last change on this file since d6d3eb7 was d6d3eb7, checked in by Ralf Corsepius <ralf.corsepius@…>, on 02/11/11 at 12:22:07

2011-02-11 Ralf Corsépius <ralf.corsepius@…>

  • shared/1553/b1553brm.c, shared/can/grcan.c, shared/can/occan.c, shared/spw/grspw.c, shared/uart/apbuart.c: Use "asm" instead of "asm" for improved c99-compliance.
  • Property mode set to 100644
File size: 53.8 KB
Line 
1/*  OC_CAN driver
2 *
3 *  COPYRIGHT (c) 2007.
4 *  Gaisler Research.
5 *
6 *  The license and distribution terms for this file may be
7 *  found in the file LICENSE in this distribution or at
8 *  http://www.rtems.com/license/LICENSE.
9 *
10 *  Author: Daniel Hellström, Gaisler Research AB, www.gaisler.com
11 */
12
13#include <rtems/libio.h>
14#include <stdlib.h>
15#include <stdio.h>
16#include <string.h>
17#include <bsp.h>
18#include <rtems/bspIo.h> /* printk */
19
20#include <leon.h>
21#include <ambapp.h>
22#include <occan.h>
23
24/* RTEMS -> ERRNO decoding table
25
26rtems_assoc_t errno_assoc[] = {
27    { "OK",                 RTEMS_SUCCESSFUL,                0 },
28    { "BUSY",               RTEMS_RESOURCE_IN_USE,           EBUSY },
29    { "INVALID NAME",       RTEMS_INVALID_NAME,              EINVAL },
30    { "NOT IMPLEMENTED",    RTEMS_NOT_IMPLEMENTED,           ENOSYS },
31    { "TIMEOUT",            RTEMS_TIMEOUT,                   ETIMEDOUT },
32    { "NO MEMORY",          RTEMS_NO_MEMORY,                 ENOMEM },
33    { "NO DEVICE",          RTEMS_UNSATISFIED,               ENODEV },
34    { "INVALID NUMBER",     RTEMS_INVALID_NUMBER,            EBADF},
35    { "NOT RESOURCE OWNER", RTEMS_NOT_OWNER_OF_RESOURCE,     EPERM},
36    { "IO ERROR",           RTEMS_IO_ERROR,                  EIO},
37    { 0, 0, 0 },
38};
39
40*/
41
42/*
43#undef DEBUG
44#undef DEBUG_EXTRA
45#undef DEBUG_PRINT_REGMAP
46*/
47
48/* default to byte regs */
49#ifndef OCCAN_WORD_REGS
50 #define OCCAN_BYTE_REGS
51#else
52 #undef OCCAN_BYTE_REGS
53#endif
54
55#ifndef OCCAN_PREFIX
56 #define OCCAN_PREFIX(name) occan##name
57#endif
58
59#if !defined(OCCAN_DEVNAME) || !defined(OCCAN_DEVNAME_NO)
60 #undef OCCAN_DEVNAME
61 #undef OCCAN_DEVNAME_NO
62 #define OCCAN_DEVNAME "/dev/occan0"
63 #define OCCAN_DEVNAME_NO(devstr,no) ((devstr)[10]='0'+(no))
64#endif
65
66#ifndef OCCAN_REG_INT
67        #define OCCAN_REG_INT(handler,irq,arg) set_vector(handler,irq+0x10,1)
68  #undef  OCCAN_DEFINE_INTHANDLER
69  #define OCCAN_DEFINE_INTHANDLER
70#endif
71
72/* Default to 40MHz system clock */
73/*#ifndef SYS_FREQ_HZ
74 #define SYS_FREQ_HZ 40000000
75#endif*/
76
77#define OCCAN_WORD_REG_OFS 0x80
78#define OCCAN_NCORE_OFS 0x100
79#define DEFAULT_CLKDIV 0x7
80#define DEFAULT_EXTENDED_MODE 1
81#define DEFAULT_RX_FIFO_LEN 64
82#define DEFAULT_TX_FIFO_LEN 64
83
84/* not implemented yet */
85#undef REDUNDANT_CHANNELS
86
87/* Define common debug macros */
88#ifdef DEBUG
89        #define DBG(fmt, vargs...) printk(fmt, ## vargs )
90#else
91        #define DBG(fmt, vargs...)
92#endif
93
94/* fifo interface */
95typedef struct {
96        int cnt;
97        int ovcnt; /* overwrite count */
98        int full; /* 1 = base contain cnt CANMsgs, tail==head */
99        CANMsg *tail, *head;
100        CANMsg *base;
101        char fifoarea[0];
102} occan_fifo;
103
104/* PELICAN */
105#ifdef OCCAN_BYTE_REGS
106typedef struct {
107        unsigned char
108                mode,
109                cmd,
110                status,
111                intflags,
112                inten,
113                resv0,
114                bustim0,
115                bustim1,
116                unused0[2],
117                resv1,
118                arbcode,
119                errcode,
120                errwarn,
121                rx_err_cnt,
122                tx_err_cnt,
123                rx_fi_xff; /* this is also acceptance code 0 in reset mode */
124                union{
125                        struct {
126                                unsigned char id[2];
127                                unsigned char data[8];
128                                unsigned char next_in_fifo[2];
129                        } rx_sff;
130                        struct {
131                                unsigned char id[4];
132                                unsigned char data[8];
133                        } rx_eff;
134                        struct {
135                                unsigned char id[2];
136                                unsigned char data[8];
137                                unsigned char unused[2];
138                        } tx_sff;
139                        struct {
140                                unsigned char id[4];
141                                unsigned char data[8];
142                        } tx_eff;
143                        struct {
144                                unsigned char code[3];
145                                unsigned char mask[4];
146                        } rst_accept;
147                } msg;
148                unsigned char rx_msg_cnt;
149                unsigned char unused1;
150                unsigned char clkdiv;
151} pelican_regs;
152#else
153typedef struct {
154        unsigned char
155                mode, unused0[3],
156                cmd, unused1[3],
157                status, unused2[3],
158                intflags, unused3[3],
159                inten, unused4[3],
160                resv0, unused5[3],
161                bustim0, unused6[3],
162                bustim1, unused7[3],
163                unused8[8],
164                resv1,unused9[3],
165                arbcode,unused10[3],
166                errcode,unused11[3],
167                errwarn,unused12[3],
168                rx_err_cnt,unused13[3],
169                tx_err_cnt,unused14[3],
170                rx_fi_xff, unused15[3]; /* this is also acceptance code 0 in reset mode */
171                /* make sure to use pointers when writing (byte access) to these registers */
172                union{
173                        struct {
174                                unsigned int id[2];
175                                unsigned int data[8];
176                                unsigned int next_in_fifo[2];
177                        } rx_sff;
178                        struct {
179                                unsigned int id[4];
180                                unsigned int data[8];
181                        } rx_eff;
182                        struct {
183                                unsigned int id[2];
184                                unsigned int data[8];
185                        } tx_sff;
186                        struct {
187                                unsigned int id[4];
188                                unsigned int data[8];
189                        } tx_eff;
190                        struct {
191                                unsigned int code[3];
192                                unsigned int mask[4];
193                        } rst_accept;
194                } msg;
195                unsigned char rx_msg_cnt,unused16[3];
196                unsigned char unused17[4];
197                unsigned char clkdiv,unused18[3];
198} pelican_regs;
199#endif
200
201#define MAX_TSEG2 7
202#define MAX_TSEG1 15
203
204#if 0
205typedef struct {
206        unsigned char brp;
207        unsigned char sjw;
208        unsigned char tseg1;
209        unsigned char tseg2;
210        unsigned char sam;
211} occan_speed_regs;
212#endif
213typedef struct {
214        unsigned char btr0;
215        unsigned char btr1;
216} occan_speed_regs;
217
218typedef struct {
219        /* hardware shortcuts */
220        pelican_regs *regs;
221        int irq;
222        occan_speed_regs timing;
223        int channel; /* 0=default, 1=second bus */
224        int single_mode;
225
226        /* driver state */
227        rtems_id devsem;
228        rtems_id txsem;
229        rtems_id rxsem;
230        int open;
231        int started;
232        int rxblk;
233        int txblk;
234        unsigned int status;
235        occan_stats stats;
236
237        /* rx&tx fifos */
238        occan_fifo *rxfifo;
239        occan_fifo *txfifo;
240
241        /* Config */
242        unsigned int speed; /* speed in HZ */
243        unsigned char acode[4];
244        unsigned char amask[4];
245} occan_priv;
246
247/********** FIFO INTERFACE **********/
248static void occan_fifo_put(occan_fifo *fifo);
249static CANMsg *occan_fifo_put_claim(occan_fifo *fifo, int force);
250static occan_fifo *occan_fifo_create(int cnt);
251static void occan_fifo_free(occan_fifo *fifo);
252static int occan_fifo_full(occan_fifo *fifo);
253static int occan_fifo_empty(occan_fifo *fifo);
254static void occan_fifo_get(occan_fifo *fifo);
255static CANMsg *occan_fifo_claim_get(occan_fifo *fifo);
256static void occan_fifo_clr(occan_fifo *fifo);
257
258/**** Hardware related Interface ****/
259static int occan_calc_speedregs(unsigned int clock_hz, unsigned int rate, occan_speed_regs *result);
260static int occan_set_speedregs(occan_priv *priv, occan_speed_regs *timing);
261static int pelican_speed_auto(occan_priv *priv);
262static void pelican_init(occan_priv *priv);
263static void pelican_open(occan_priv *priv);
264static int pelican_start(occan_priv *priv);
265static void pelican_stop(occan_priv *priv);
266static int pelican_send(occan_priv *can, CANMsg *msg);
267static void pelican_set_accept(occan_priv *priv, unsigned char *acode, unsigned char *amask);
268static void occan_interrupt(occan_priv *can);
269#ifdef DEBUG_PRINT_REGMAP
270static void pelican_regadr_print(pelican_regs *regs);
271#endif
272
273/***** Driver related interface *****/
274static rtems_device_driver occan_ioctl(rtems_device_major_number major, rtems_device_minor_number minor, void *arg);
275static rtems_device_driver occan_write(rtems_device_major_number major, rtems_device_minor_number minor, void *arg);
276static rtems_device_driver occan_read(rtems_device_major_number major, rtems_device_minor_number minor, void *arg);
277static rtems_device_driver occan_close(rtems_device_major_number major, rtems_device_minor_number minor, void *arg);
278static rtems_device_driver occan_open(rtems_device_major_number major, rtems_device_minor_number minor, void *arg);
279static rtems_device_driver occan_initialize(rtems_device_major_number major, rtems_device_minor_number unused, void *arg);
280#ifdef OCCAN_DEFINE_INTHANDLER
281static void occan_interrupt_handler(rtems_vector_number v);
282#endif
283static int can_cores;
284static occan_priv *cans;
285static amba_confarea_type *amba_bus;
286static unsigned int sys_freq_hz;
287
288
289/* Read byte bypassing */
290
291#ifdef OCCAN_DONT_BYPASS_CACHE
292 #define READ_REG(address) (*(volatile unsigned char *)(address))
293#else
294 /* Bypass cache */
295 #define READ_REG(address) _OCCAN_REG_READ((unsigned int)(address))
296 static __inline__ unsigned char _OCCAN_REG_READ(unsigned int addr) {
297        unsigned char tmp;
298        __asm__ (" lduba [%1]1, %0 "
299            : "=r"(tmp)
300            : "r"(addr)
301           );
302        return tmp;
303        }
304#endif
305
306#define WRITE_REG(address,data) (*(volatile unsigned char *)(address) = (data))
307
308/* Mode register bit definitions */
309#define PELICAN_MOD_RESET          0x1
310#define PELICAN_MOD_LISTEN         0x2
311#define PELICAN_MOD_SELFTEST       0x4
312#define PELICAN_MOD_ACCEPT         0x8
313
314/* Command register bit definitions */
315#define PELICAN_CMD_TXREQ          0x1
316#define PELICAN_CMD_ABORT          0x2
317#define PELICAN_CMD_RELRXBUF       0x4
318#define PELICAN_CMD_CLRDOVR        0x8
319#define PELICAN_CMD_SELFRXRQ       0x10
320
321/* Status register bit definitions */
322#define PELICAN_STAT_RXBUF         0x1
323#define PELICAN_STAT_DOVR          0x2
324#define PELICAN_STAT_TXBUF         0x4
325#define PELICAN_STAT_TXOK          0x8
326#define PELICAN_STAT_RX            0x10
327#define PELICAN_STAT_TX            0x20
328#define PELICAN_STAT_ERR           0x40
329#define PELICAN_STAT_BUS           0x80
330
331/* Interrupt register bit definitions */
332#define PELICAN_IF_RX         0x1
333#define PELICAN_IF_TX         0x2
334#define PELICAN_IF_ERRW       0x4
335#define PELICAN_IF_DOVR       0x8
336#define PELICAN_IF_ERRP       0x20
337#define PELICAN_IF_ARB        0x40
338#define PELICAN_IF_BUS        0x80
339
340/* Interrupt Enable register bit definitions */
341#define PELICAN_IE_RX         0x1
342#define PELICAN_IE_TX         0x2
343#define PELICAN_IE_ERRW       0x4
344#define PELICAN_IE_DOVR       0x8
345#define PELICAN_IE_ERRP       0x20
346#define PELICAN_IE_ARB        0x40
347#define PELICAN_IE_BUS        0x80
348
349/* Arbitration lost capture register bit definitions */
350#define PELICAN_ARB_BITS      0x1f
351
352/*  register bit definitions */
353#define PELICAN_ECC_CODE_BIT     0x00
354#define PELICAN_ECC_CODE_FORM    0x40
355#define PELICAN_ECC_CODE_STUFF   0x80
356#define PELICAN_ECC_CODE_OTHER   0xc0
357#define PELICAN_ECC_CODE    0xc0
358
359#define PELICAN_ECC_DIR     0x20
360#define PELICAN_ECC_SEG     0x1f
361
362/* Clock divider register bit definitions */
363#define PELICAN_CDR_DIV  0x7
364#define PELICAN_CDR_OFF  0x8
365#define PELICAN_CDR_MODE 0x80
366#define PELICAN_CDR_MODE_PELICAN 0x80
367#define PELICAN_CDR_MODE_BITS 7
368#define PELICAN_CDR_MODE_BASICAN 0x00
369
370
371/*  register bit definitions */
372#define OCCAN_BUSTIM_SJW       0xc0
373#define OCCAN_BUSTIM_BRP       0x3f
374#define OCCAN_BUSTIM_SJW_BIT   6
375
376#define OCCAN_BUSTIM_SAM       0x80
377#define OCCAN_BUSTIM_TSEG2     0x70
378#define OCCAN_BUSTIM_TSEG2_BIT 4
379#define OCCAN_BUSTIM_TSEG1     0x0f
380
381/*  register bit definitions */
382/*
383#define PELICAN_S_       0x1
384#define PELICAN_S_       0x2
385#define PELICAN_S_       0x4
386#define PELICAN_S_       0x8
387#define PELICAN_S_       0x10
388#define PELICAN_S_       0x20
389#define PELICAN_S_       0x40
390#define PELICAN_S_       0x80
391*/
392
393static void pelican_init(occan_priv *priv){
394        /* Reset core */
395        priv->regs->mode = PELICAN_MOD_RESET;
396
397        /* wait for core to reset complete */
398        /*usleep(1);*/
399}
400
401static void pelican_open(occan_priv *priv){
402        unsigned char tmp;
403        int ret;
404
405        /* Set defaults */
406        priv->speed = OCCAN_SPEED_250K;
407
408        /* set acceptance filters to accept all messages */
409        priv->acode[0] = 0;
410        priv->acode[1] = 0;
411        priv->acode[2] = 0;
412        priv->acode[3] = 0;
413        priv->amask[0] = 0xff;
414        priv->amask[1] = 0xff;
415        priv->amask[2] = 0xff;
416        priv->amask[3] = 0xff;
417
418        /* Set clock divider to extended mode, clkdiv not connected
419         */
420        priv->regs->clkdiv = (1<<PELICAN_CDR_MODE_BITS) | (DEFAULT_CLKDIV & PELICAN_CDR_DIV);
421
422        ret = occan_calc_speedregs(sys_freq_hz,priv->speed,&priv->timing);
423        if ( ret ){
424                /* failed to set speed for this system freq, try with 50K instead */
425                priv->speed = OCCAN_SPEED_50K;
426                occan_calc_speedregs(sys_freq_hz,priv->speed,&priv->timing);
427        }
428
429        /* disable all interrupts */
430        priv->regs->inten = 0;
431
432        /* clear pending interrupts by reading */
433        tmp = READ_REG(&priv->regs->intflags);
434}
435
436static int pelican_start(occan_priv *priv){
437        unsigned char tmp;
438        /* Start HW communication */
439
440        if ( !priv->rxfifo || !priv->txfifo )
441                return -1;
442
443  /* In case we were started before and stopped we
444   * should empty the TX fifo or try to resend those
445   * messages. We make it simple...
446   */
447  occan_fifo_clr(priv->txfifo);
448
449        /* Clear status bits */
450        priv->status = 0;
451
452        /* clear pending interrupts */
453        tmp = READ_REG(&priv->regs->intflags);
454
455        /* clear error counters */
456        priv->regs->rx_err_cnt = 0;
457        priv->regs->tx_err_cnt = 0;
458
459#ifdef REDUNDANT_CHANNELS
460        if ( (priv->channel == 0) || (priv->channel >= REDUNDANT_CHANNELS) ){
461                /* Select the first (default) channel */
462                OCCAN_SET_CHANNEL(priv,0);
463        }else{
464                /* set gpio bit, or something */
465                OCCAN_SET_CHANNEL(priv,priv->channel);
466        }
467#endif
468        /* set the speed regs of the CAN core */
469        occan_set_speedregs(priv,&priv->timing);
470
471        DBG("OCCAN: start: set timing regs btr0: 0x%x, btr1: 0x%x\n\r",READ_REG(&priv->regs->bustim0),READ_REG(&priv->regs->bustim1));
472
473        /* Set default acceptance filter */
474        pelican_set_accept(priv,priv->acode,priv->amask);
475
476        /* turn on interrupts */
477        priv->regs->inten = PELICAN_IE_RX | PELICAN_IE_TX | PELICAN_IE_ERRW |
478                            PELICAN_IE_ERRP | PELICAN_IE_BUS;
479
480#ifdef DEBUG
481        /* print setup before starting */
482        pelican_regs_print(priv->regs);
483        occan_stat_print(&priv->stats);
484#endif
485
486        /* core already in reset mode,
487         *  € Exit reset mode
488         *  € Enter Single/Dual mode filtering.
489         */
490        priv->regs->mode =  (priv->single_mode << 3);
491
492        return 0;
493}
494
495static void pelican_stop(occan_priv *priv){
496        /* stop HW */
497
498#ifdef DEBUG
499        /* print setup before stopping */
500        pelican_regs_print(priv->regs);
501        occan_stat_print(&priv->stats);
502#endif
503
504        /* put core in reset mode */
505        priv->regs->mode = PELICAN_MOD_RESET;
506
507        /* turn off interrupts */
508        priv->regs->inten = 0;
509
510        priv->status |= OCCAN_STATUS_RESET;
511}
512
513
514/* Try to send message "msg", if hardware txfifo is
515 * full, then -1 is returned.
516 *
517 * Be sure to have disabled CAN interrupts when
518 * entering this function.
519 */
520static int pelican_send(occan_priv *can, CANMsg *msg){
521        unsigned char tmp,status;
522        pelican_regs *regs = can->regs;
523
524        /* is there room in send buffer? */
525        status = READ_REG(&regs->status);
526        if ( !(status & PELICAN_STAT_TXBUF) ){
527                /* tx fifo taken, we have to wait */
528                return -1;
529        }
530
531        tmp = msg->len & 0xf;
532        if ( msg->rtr )
533                tmp |= 0x40;
534
535        if ( msg->extended ){
536                /* Extended Frame */
537                regs->rx_fi_xff = 0x80 | tmp;
538                WRITE_REG(&regs->msg.tx_eff.id[0],(msg->id >> (5+8+8)) & 0xff);
539                WRITE_REG(&regs->msg.tx_eff.id[1],(msg->id >> (5+8)) & 0xff);
540                WRITE_REG(&regs->msg.tx_eff.id[2],(msg->id >> (5)) & 0xff);
541                WRITE_REG(&regs->msg.tx_eff.id[3],(msg->id << 3) & 0xf8);
542                tmp = msg->len;
543                while(tmp--){
544                        WRITE_REG(&regs->msg.tx_eff.data[tmp],msg->data[tmp]);
545                }
546        }else{
547                /* Standard Frame */
548                regs->rx_fi_xff = tmp;
549                WRITE_REG(&regs->msg.tx_sff.id[0],(msg->id >> 3) & 0xff);
550                WRITE_REG(&regs->msg.tx_sff.id[1],(msg->id << 5) & 0xe0);
551                tmp = msg->len;
552                while(tmp--){
553                        WRITE_REG(&regs->msg.tx_sff.data[tmp],msg->data[tmp]);
554                }
555        }
556
557        /* let HW know of new message */
558        if ( msg->sshot ){
559                regs->cmd = PELICAN_CMD_TXREQ | PELICAN_CMD_ABORT;
560        }else{
561                /* normal case -- try resend until sent */
562                regs->cmd = PELICAN_CMD_TXREQ;
563        }
564
565        return 0;
566}
567
568
569static void pelican_set_accept(occan_priv *priv, unsigned char *acode, unsigned char *amask){
570        unsigned char *acode0, *acode1, *acode2, *acode3;
571        unsigned char *amask0, *amask1, *amask2, *amask3;
572
573        acode0 = &priv->regs->rx_fi_xff;
574        acode1 = (unsigned char *)&priv->regs->msg.rst_accept.code[0];
575        acode2 = (unsigned char *)&priv->regs->msg.rst_accept.code[1];
576        acode3 = (unsigned char *)&priv->regs->msg.rst_accept.code[2];
577
578        amask0 = (unsigned char *)&priv->regs->msg.rst_accept.mask[0];
579        amask1 = (unsigned char *)&priv->regs->msg.rst_accept.mask[1];
580        amask2 = (unsigned char *)&priv->regs->msg.rst_accept.mask[2];
581        amask3 = (unsigned char *)&priv->regs->msg.rst_accept.mask[3];
582
583        /* Set new mask & code */
584        *acode0 = acode[0];
585        *acode1 = acode[1];
586        *acode2 = acode[2];
587        *acode3 = acode[3];
588
589        *amask0 = amask[0];
590        *amask1 = amask[1];
591        *amask2 = amask[2];
592        *amask3 = amask[3];
593}
594
595#ifdef DEBUG
596static void pelican_regs_print(pelican_regs *regs){
597        printk("--- PELICAN 0x%lx ---\n\r",(unsigned int)regs);
598        printk(" MODE: 0x%02x\n\r",READ_REG(&regs->mode));
599        printk(" CMD: 0x%02x\n\r",READ_REG(&regs->cmd));
600        printk(" STATUS: 0x%02x\n\r",READ_REG(&regs->status));
601        /*printk(" INTFLG: 0x%02x\n\r",READ_REG(&regs->intflags));*/
602        printk(" INTEN: 0x%02x\n\r",READ_REG(&regs->inten));
603        printk(" BTR0: 0x%02x\n\r",READ_REG(&regs->bustim0));
604        printk(" BTR1: 0x%02x\n\r",READ_REG(&regs->bustim1));
605        printk(" ARBCODE: 0x%02x\n\r",READ_REG(&regs->arbcode));
606        printk(" ERRCODE: 0x%02x\n\r",READ_REG(&regs->errcode));
607        printk(" ERRWARN: 0x%02x\n\r",READ_REG(&regs->errwarn));
608        printk(" RX_ERR_CNT: 0x%02x\n\r",READ_REG(&regs->rx_err_cnt));
609        printk(" TX_ERR_CNT: 0x%02x\n\r",READ_REG(&regs->tx_err_cnt));
610        if ( READ_REG(&regs->mode) & PELICAN_MOD_RESET ){
611                /* in reset mode it is possible to read acceptance filters */
612                printk(" ACR0: 0x%02x (0x%lx)\n\r",READ_REG(&regs->rx_fi_xff),&regs->rx_fi_xff);
613                printk(" ACR1: 0x%02x (0x%lx)\n\r",READ_REG(&regs->msg.rst_accept.code[0]),(unsigned int)&regs->msg.rst_accept.code[0]);
614                printk(" ACR1: 0x%02x (0x%lx)\n\r",READ_REG(&regs->msg.rst_accept.code[1]),(unsigned int)&regs->msg.rst_accept.code[1]);
615                printk(" ACR1: 0x%02x (0x%lx)\n\r",READ_REG(&regs->msg.rst_accept.code[2]),(unsigned int)&regs->msg.rst_accept.code[2]);
616                printk(" AMR0: 0x%02x (0x%lx)\n\r",READ_REG(&regs->msg.rst_accept.mask[0]),(unsigned int)&regs->msg.rst_accept.mask[0]);
617                printk(" AMR1: 0x%02x (0x%lx)\n\r",READ_REG(&regs->msg.rst_accept.mask[1]),(unsigned int)&regs->msg.rst_accept.mask[1]);
618                printk(" AMR2: 0x%02x (0x%lx)\n\r",READ_REG(&regs->msg.rst_accept.mask[2]),(unsigned int)&regs->msg.rst_accept.mask[2]);
619                printk(" AMR3: 0x%02x (0x%lx)\n\r",READ_REG(&regs->msg.rst_accept.mask[3]),(unsigned int)&regs->msg.rst_accept.mask[3]);
620
621        }else{
622                printk(" RXFI_XFF: 0x%02x\n\r",READ_REG(&regs->rx_fi_xff));
623        }
624        printk(" RX_MSG_CNT: 0x%02x\n\r",READ_REG(&regs->rx_msg_cnt));
625        printk(" CLKDIV: 0x%02x\n\r",READ_REG(&regs->clkdiv));
626        printk("-------------------\n\r");
627}
628#endif
629
630#ifdef DEBUG_PRINT_REGMAP
631static void pelican_regadr_print(pelican_regs *regs){
632        printk("--- PELICAN 0x%lx ---\n\r",(unsigned int)regs);
633        printk(" MODE: 0x%lx\n\r",(unsigned int)&regs->mode);
634        printk(" CMD: 0x%lx\n\r",(unsigned int)&regs->cmd);
635        printk(" STATUS: 0x%lx\n\r",(unsigned int)&regs->status);
636        /*printk(" INTFLG: 0x%lx\n\r",&regs->intflags);*/
637        printk(" INTEN: 0x%lx\n\r",(unsigned int)&regs->inten);
638        printk(" BTR0: 0x%lx\n\r",(unsigned int)&regs->bustim0);
639        printk(" BTR1: 0x%lx\n\r",(unsigned int)&regs->bustim1);
640        printk(" ARBCODE: 0x%lx\n\r",(unsigned int)&regs->arbcode);
641        printk(" ERRCODE: 0x%lx\n\r",(unsigned int)&regs->errcode);
642        printk(" ERRWARN: 0x%lx\n\r",(unsigned int)&regs->errwarn);
643        printk(" RX_ERR_CNT: 0x%lx\n\r",(unsigned int)&regs->rx_err_cnt);
644        printk(" TX_ERR_CNT: 0x%lx\n\r",(unsigned int)&regs->tx_err_cnt);
645
646        /* in reset mode it is possible to read acceptance filters */
647        printk(" RXFI_XFF: 0x%lx\n\r",(unsigned int)&regs->rx_fi_xff);
648
649        /* reset registers */
650        printk(" ACR0: 0x%lx\n\r",(unsigned int)&regs->rx_fi_xff);
651        printk(" ACR1: 0x%lx\n\r",(unsigned int)&regs->msg.rst_accept.code[0]);
652        printk(" ACR2: 0x%lx\n\r",(unsigned int)&regs->msg.rst_accept.code[1]);
653        printk(" ACR3: 0x%lx\n\r",(unsigned int)&regs->msg.rst_accept.code[2]);
654        printk(" AMR0: 0x%lx\n\r",(unsigned int)&regs->msg.rst_accept.mask[0]);
655        printk(" AMR1: 0x%lx\n\r",(unsigned int)&regs->msg.rst_accept.mask[1]);
656        printk(" AMR2: 0x%lx\n\r",(unsigned int)&regs->msg.rst_accept.mask[2]);
657        printk(" AMR3: 0x%lx\n\r",(unsigned int)&regs->msg.rst_accept.mask[3]);
658
659        /* TX Extended */
660        printk(" EFFTX_ID[0]: 0x%lx\n\r",(unsigned int)&regs->msg.tx_eff.id[0]);
661        printk(" EFFTX_ID[1]: 0x%lx\n\r",(unsigned int)&regs->msg.tx_eff.id[1]);
662        printk(" EFFTX_ID[2]: 0x%lx\n\r",(unsigned int)&regs->msg.tx_eff.id[2]);
663        printk(" EFFTX_ID[3]: 0x%lx\n\r",(unsigned int)&regs->msg.tx_eff.id[3]);
664
665        printk(" EFFTX_DATA[0]: 0x%lx\n\r",(unsigned int)&regs->msg.tx_eff.data[0]);
666        printk(" EFFTX_DATA[1]: 0x%lx\n\r",(unsigned int)&regs->msg.tx_eff.data[1]);
667        printk(" EFFTX_DATA[2]: 0x%lx\n\r",(unsigned int)&regs->msg.tx_eff.data[2]);
668        printk(" EFFTX_DATA[3]: 0x%lx\n\r",(unsigned int)&regs->msg.tx_eff.data[3]);
669        printk(" EFFTX_DATA[4]: 0x%lx\n\r",(unsigned int)&regs->msg.tx_eff.data[4]);
670        printk(" EFFTX_DATA[5]: 0x%lx\n\r",(unsigned int)&regs->msg.tx_eff.data[5]);
671        printk(" EFFTX_DATA[6]: 0x%lx\n\r",(unsigned int)&regs->msg.tx_eff.data[6]);
672        printk(" EFFTX_DATA[7]: 0x%lx\n\r",(unsigned int)&regs->msg.tx_eff.data[7]);
673
674        /* RX Extended */
675        printk(" EFFRX_ID[0]: 0x%lx\n\r",(unsigned int)&regs->msg.rx_eff.id[0]);
676        printk(" EFFRX_ID[1]: 0x%lx\n\r",(unsigned int)&regs->msg.rx_eff.id[1]);
677        printk(" EFFRX_ID[2]: 0x%lx\n\r",(unsigned int)&regs->msg.rx_eff.id[2]);
678        printk(" EFFRX_ID[3]: 0x%lx\n\r",(unsigned int)&regs->msg.rx_eff.id[3]);
679
680        printk(" EFFRX_DATA[0]: 0x%lx\n\r",(unsigned int)&regs->msg.rx_eff.data[0]);
681        printk(" EFFRX_DATA[1]: 0x%lx\n\r",(unsigned int)&regs->msg.rx_eff.data[1]);
682        printk(" EFFRX_DATA[2]: 0x%lx\n\r",(unsigned int)&regs->msg.rx_eff.data[2]);
683        printk(" EFFRX_DATA[3]: 0x%lx\n\r",(unsigned int)&regs->msg.rx_eff.data[3]);
684        printk(" EFFRX_DATA[4]: 0x%lx\n\r",(unsigned int)&regs->msg.rx_eff.data[4]);
685        printk(" EFFRX_DATA[5]: 0x%lx\n\r",(unsigned int)&regs->msg.rx_eff.data[5]);
686        printk(" EFFRX_DATA[6]: 0x%lx\n\r",(unsigned int)&regs->msg.rx_eff.data[6]);
687        printk(" EFFRX_DATA[7]: 0x%lx\n\r",(unsigned int)&regs->msg.rx_eff.data[7]);
688
689
690        /* RX Extended */
691        printk(" SFFRX_ID[0]: 0x%lx\n\r",(unsigned int)&regs->msg.rx_sff.id[0]);
692        printk(" SFFRX_ID[1]: 0x%lx\n\r",(unsigned int)&regs->msg.rx_sff.id[1]);
693
694        printk(" SFFRX_DATA[0]: 0x%lx\n\r",(unsigned int)&regs->msg.rx_sff.data[0]);
695        printk(" SFFRX_DATA[1]: 0x%lx\n\r",(unsigned int)&regs->msg.rx_sff.data[1]);
696        printk(" SFFRX_DATA[2]: 0x%lx\n\r",(unsigned int)&regs->msg.rx_sff.data[2]);
697        printk(" SFFRX_DATA[3]: 0x%lx\n\r",(unsigned int)&regs->msg.rx_sff.data[3]);
698        printk(" SFFRX_DATA[4]: 0x%lx\n\r",(unsigned int)&regs->msg.rx_sff.data[4]);
699        printk(" SFFRX_DATA[5]: 0x%lx\n\r",(unsigned int)&regs->msg.rx_sff.data[5]);
700        printk(" SFFRX_DATA[6]: 0x%lx\n\r",(unsigned int)&regs->msg.rx_sff.data[6]);
701        printk(" SFFRX_DATA[7]: 0x%lx\n\r",(unsigned int)&regs->msg.rx_sff.data[7]);
702
703        /* TX Extended */
704        printk(" SFFTX_ID[0]: 0x%lx\n\r",(unsigned int)&regs->msg.tx_sff.id[0]);
705        printk(" SFFTX_ID[1]: 0x%lx\n\r",(unsigned int)&regs->msg.tx_sff.id[1]);
706
707        printk(" SFFTX_DATA[0]: 0x%lx\n\r",(unsigned int)&regs->msg.tx_sff.data[0]);
708        printk(" SFFTX_DATA[1]: 0x%lx\n\r",(unsigned int)&regs->msg.tx_sff.data[1]);
709        printk(" SFFTX_DATA[2]: 0x%lx\n\r",(unsigned int)&regs->msg.tx_sff.data[2]);
710        printk(" SFFTX_DATA[3]: 0x%lx\n\r",(unsigned int)&regs->msg.tx_sff.data[3]);
711        printk(" SFFTX_DATA[4]: 0x%lx\n\r",(unsigned int)&regs->msg.tx_sff.data[4]);
712        printk(" SFFTX_DATA[5]: 0x%lx\n\r",(unsigned int)&regs->msg.tx_sff.data[5]);
713        printk(" SFFTX_DATA[6]: 0x%lx\n\r",(unsigned int)&regs->msg.tx_sff.data[6]);
714        printk(" SFFTX_DATA[7]: 0x%lx\n\r",(unsigned int)&regs->msg.tx_sff.data[7]);
715
716        printk(" RX_MSG_CNT: 0x%lx\n\r",(unsigned int)&regs->rx_msg_cnt);
717        printk(" CLKDIV: 0x%lx\n\r",(unsigned int)&regs->clkdiv);
718        printk("-------------------\n\r");
719}
720#endif
721
722#ifdef DEBUG
723static void occan_stat_print(occan_stats *stats){
724        printk("----Stats----\n\r");
725        printk("rx_msgs: %d\n\r",stats->rx_msgs);
726        printk("tx_msgs: %d\n\r",stats->tx_msgs);
727        printk("err_warn: %d\n\r",stats->err_warn);
728        printk("err_dovr: %d\n\r",stats->err_dovr);
729        printk("err_errp: %d\n\r",stats->err_errp);
730        printk("err_arb: %d\n\r",stats->err_arb);
731        printk("err_bus: %d\n\r",stats->err_bus);
732        printk("Int cnt: %d\n\r",stats->ints);
733        printk("tx_buf_err: %d\n\r",stats->tx_buf_error);
734        printk("-------------\n\r");
735}
736#endif
737
738/* This function calculates BTR0 and BTR1 values for a given bitrate.
739 *
740 * Set communication parameters.
741 * \param clock_hz OC_CAN Core frequency in Hz.
742 * \param rate Requested baud rate in bits/second.
743 * \param result Pointer to where resulting BTRs will be stored.
744 * \return zero if successful to calculate a baud rate.
745 */
746static int occan_calc_speedregs(unsigned int clock_hz, unsigned int rate, occan_speed_regs *result){
747        int best_error = 1000000000;
748        int error;
749        int best_tseg=0, best_brp=0, best_rate=0, brp=0;
750        int tseg=0, tseg1=0, tseg2=0;
751        int sjw = 0;
752        int clock = clock_hz / 2;
753        int sampl_pt = 90;
754
755        if ( (rate<5000) || (rate>1000000) ){
756                /* invalid speed mode */
757                return -1;
758        }
759
760        /* find best match, return -2 if no good reg
761         * combination is available for this frequency */
762
763        /* some heuristic specials */
764        if (rate > ((1000000 + 500000) / 2))
765                sampl_pt = 75;
766
767        if (rate < ((12500 + 10000) / 2))
768                sampl_pt = 75;
769
770        if (rate < ((100000 + 125000) / 2))
771                sjw = 1;
772
773        /* tseg even = round down, odd = round up */
774        for (tseg = (0 + 0 + 2) * 2;
775             tseg <= (MAX_TSEG2 + MAX_TSEG1 + 2) * 2 + 1;
776             tseg++)
777        {
778                brp = clock / ((1 + tseg / 2) * rate) + tseg % 2;
779                if ((brp == 0) || (brp > 64))
780                        continue;
781
782                error = rate - clock / (brp * (1 + tseg / 2));
783                if (error < 0)
784                {
785                        error = -error;
786                }
787
788                if (error <= best_error)
789                {
790                        best_error = error;
791                        best_tseg = tseg/2;
792                        best_brp = brp-1;
793                        best_rate = clock/(brp*(1+tseg/2));
794                }
795        }
796
797        if (best_error && (rate / best_error < 10))
798        {
799                printk("OCCAN: bitrate %d is not possible with %d Hz clock\n\r",rate, clock);
800                return -2;
801        }else if ( !result )
802                return 0; /* nothing to store result in, but a valid bitrate can be calculated */
803
804        tseg2 = best_tseg - (sampl_pt * (best_tseg + 1)) / 100;
805
806        if (tseg2 < 0)
807        {
808                tseg2 = 0;
809        }
810
811        if (tseg2 > MAX_TSEG2)
812        {
813                tseg2 = MAX_TSEG2;
814        }
815
816        tseg1 = best_tseg - tseg2 - 2;
817
818        if (tseg1 > MAX_TSEG1)
819        {
820                tseg1 = MAX_TSEG1;
821                tseg2 = best_tseg - tseg1 - 2;
822        }
823
824        result->btr0 = (sjw<<OCCAN_BUSTIM_SJW_BIT) | (best_brp&OCCAN_BUSTIM_BRP);
825        result->btr1 = (0<<7) | (tseg2<<OCCAN_BUSTIM_TSEG2_BIT) | tseg1;
826
827        return 0;
828}
829
830static int occan_set_speedregs(occan_priv *priv, occan_speed_regs *timing){
831        if ( !timing || !priv || !priv->regs)
832                return -1;
833
834        priv->regs->bustim0 = timing->btr0;
835        priv->regs->bustim1 = timing->btr1;
836        return 0;
837}
838
839#if 0
840static unsigned int pelican_speed_auto_steplist [] = {
841        OCCAN_SPEED_500K,
842        OCCAN_SPEED_250K,
843        OCCAN_SPEED_125K,
844        OCCAN_SPEED_75K,
845        OCCAN_SPEED_50K,
846        OCCAN_SPEED_25K,
847        OCCAN_SPEED_10K,
848        0
849};
850#endif
851
852static int pelican_speed_auto(occan_priv *priv){
853        return -1;
854
855#if 0
856        int i=0;
857        occan_speed_regs timing;
858        unsigned int speed;
859        unsigned char tmp;
860
861        while ( (speed=pelican_speed_auto_steplist[i]) > 0){
862
863                /* Reset core */
864                priv->regs->mode = PELICAN_MOD_RESET;
865
866                /* tell int handler about the auto speed detection test */
867
868
869                /* wait for a moment (10ms) */
870                /*usleep(10000);*/
871
872                /* No acceptance filter */
873                pelican_set_accept(priv);
874
875                /* calc timing params for this */
876                if ( occan_calc_speedregs(sys_freq_hz,speed,&timing) ){
877                        /* failed to get good timings for this frequency
878                         * test with next
879                         */
880                         continue;
881                }
882
883                timing.sam = 0;
884
885                /* set timing params for this speed */
886                occan_set_speedregs(priv,&timing);
887
888                /* Empty previous messages in hardware RX fifo */
889                /*
890                while( READ_REG(&priv->regs->) ){
891
892                }
893                */
894
895                /* Clear pending interrupts */
896                tmp = READ_REG(&priv->regs->intflags);
897
898                /* enable RX & ERR interrupt */
899                priv->regs->inten =
900
901                /* Get out of reset state */
902                priv->regs->mode = PELICAN_MOD_LISTEN;
903
904                /* wait for frames or errors */
905                while(1){
906                        /* sleep 10ms */
907
908                }
909
910        }
911#endif
912}
913
914
915static rtems_device_driver occan_initialize(rtems_device_major_number major, rtems_device_minor_number unused, void *arg){
916        int dev_cnt,minor,subcore_cnt,devi,subi,subcores;
917        amba_ahb_device ambadev;
918        occan_priv *can;
919        char fs_name[20];
920        rtems_status_code status;
921
922        strcpy(fs_name,OCCAN_DEVNAME);
923
924        /* find device on amba bus */
925        dev_cnt = amba_get_number_ahbslv_devices(amba_bus,VENDOR_GAISLER,GAISLER_OCCAN);
926        if ( dev_cnt < 1 ){
927                /* Failed to find any CAN cores! */
928                printk("OCCAN: Failed to find any CAN cores\n\r");
929                return -1;
930        }
931
932        /* Detect System Frequency from initialized timer */
933#ifndef SYS_FREQ_HZ
934#if defined(LEON3)
935        /* LEON3: find timer address via AMBA Plug&Play info */
936        {
937                amba_apb_device gptimer;
938                LEON3_Timer_Regs_Map *tregs;
939
940                if ( amba_find_apbslv(&amba_conf,VENDOR_GAISLER,GAISLER_GPTIMER,&gptimer) == 1 ){
941                        tregs = (LEON3_Timer_Regs_Map *)gptimer.start;
942                        sys_freq_hz = (tregs->scaler_reload+1)*1000*1000;
943                        DBG("OCCAN: detected %dHZ system frequency\n\r",sys_freq_hz);
944                }else{
945                        sys_freq_hz = 40000000; /* Default to 40MHz */
946                        printk("OCCAN: Failed to detect system frequency\n\r");
947                }
948
949        }
950#elif defined(LEON2)
951        /* LEON2: use hardcoded address to get to timer */
952        {
953                LEON_Register_Map *regs = (LEON_Register_Map *)0x80000000;
954                sys_freq_hz = (regs->Scaler_Reload+1)*1000*1000;
955        }
956#else
957  #error CPU not supported for OC_CAN driver
958#endif
959#else
960        /* Use hardcoded frequency */
961        sys_freq_hz = SYS_FREQ_HZ;
962#endif
963
964        DBG("OCCAN: Detected %dHz system frequency\n\r",sys_freq_hz);
965
966        /* OCCAN speciality:
967         *  Mulitple cores are supported through the same amba AHB interface.
968         *  The number of "sub cores" can be detected by decoding the AMBA
969         *  Plug&Play version information. verion = ncores. A maximum of 8
970         *  sub cores are supported, each separeated with 0x100 inbetween.
971         *
972         *  Now, lets detect sub cores.
973         */
974
975        for(subcore_cnt=devi=0; devi<dev_cnt; devi++){
976                amba_find_next_ahbslv(amba_bus,VENDOR_GAISLER,GAISLER_OCCAN,&ambadev,devi);
977                subcore_cnt += (ambadev.ver & 0x7)+1;
978        }
979
980        printk("OCCAN: Found %d devs, totally %d sub cores\n\r",dev_cnt,subcore_cnt);
981
982        /* allocate memory for cores */
983        can_cores = subcore_cnt;
984        cans = calloc(subcore_cnt*sizeof(occan_priv),1);
985
986        minor=0;
987        for(devi=0; devi<dev_cnt; devi++){
988
989                /* Get AHB device info */
990                amba_find_next_ahbslv(amba_bus,VENDOR_GAISLER,GAISLER_OCCAN,&ambadev,devi);
991                subcores = (ambadev.ver & 0x7)+1;
992                DBG("OCCAN: on dev %d found %d sub cores\n\r",devi,subcores);
993
994                /* loop all subcores, at least 1 */
995                for(subi=0; subi<subcores; subi++){
996                        can = &cans[minor];
997
998#ifdef OCCAN_BYTE_REGS
999                        /* regs is byte regs */
1000                        can->regs = (void *)(ambadev.start[0] + OCCAN_NCORE_OFS*subi);
1001#else
1002                        /* regs is word regs, accessed 0x100 from base address */
1003                        can->regs = (void *)(ambadev.start[0] + OCCAN_NCORE_OFS*subi+ OCCAN_WORD_REG_OFS);
1004#endif
1005
1006                        /* remember IRQ number */
1007                        can->irq = ambadev.irq+subi;
1008
1009                        /* bind filesystem name to device */
1010                        OCCAN_DEVNAME_NO(fs_name,minor);
1011                        printk("OCCAN: Registering %s to [%d %d] @ 0x%lx irq %d\n\r",fs_name,major,minor,(unsigned int)can->regs,can->irq);
1012                        status = rtems_io_register_name(fs_name, major, minor);
1013                        if (RTEMS_SUCCESSFUL != status )
1014                                rtems_fatal_error_occurred(status);
1015
1016                        /* initialize software */
1017                        can->open = 0;
1018                        can->rxfifo = NULL;
1019                        can->txfifo = NULL;
1020                        status = rtems_semaphore_create(
1021                        rtems_build_name('C', 'd', 'v', '0'+minor),
1022                        1,
1023                        RTEMS_FIFO | RTEMS_SIMPLE_BINARY_SEMAPHORE | RTEMS_NO_INHERIT_PRIORITY | \
1024                        RTEMS_NO_PRIORITY_CEILING,
1025                        0,
1026                        &can->devsem);
1027                        if ( status != RTEMS_SUCCESSFUL ){
1028                                printk("OCCAN: Failed to create dev semaphore for minor %d, (%d)\n\r",minor,status);
1029                                return RTEMS_UNSATISFIED;
1030                        }
1031                        status = rtems_semaphore_create(
1032                        rtems_build_name('C', 't', 'x', '0'+minor),
1033                        0,
1034                        RTEMS_FIFO | RTEMS_SIMPLE_BINARY_SEMAPHORE | RTEMS_NO_INHERIT_PRIORITY | \
1035                        RTEMS_NO_PRIORITY_CEILING,
1036                        0,
1037                        &can->txsem);
1038                        if ( status != RTEMS_SUCCESSFUL ){
1039                                printk("OCCAN: Failed to create tx semaphore for minor %d, (%d)\n\r",minor,status);
1040                                return RTEMS_UNSATISFIED;
1041                        }
1042                        status = rtems_semaphore_create(
1043                        rtems_build_name('C', 'r', 'x', '0'+minor),
1044                        0,
1045                        RTEMS_FIFO | RTEMS_SIMPLE_BINARY_SEMAPHORE | RTEMS_NO_INHERIT_PRIORITY | \
1046                        RTEMS_NO_PRIORITY_CEILING,
1047                        0,
1048                        &can->rxsem);
1049                        if ( status != RTEMS_SUCCESSFUL ){
1050                                printk("OCCAN: Failed to create rx semaphore for minor %d, (%d)\n\r",minor,status);
1051                                return RTEMS_UNSATISFIED;
1052                        }
1053
1054                        /* hardware init/reset */
1055                        pelican_init(can);
1056
1057                        /* Setup interrupt handler for each channel */
1058        OCCAN_REG_INT(OCCAN_PREFIX(_interrupt_handler), can->irq, can);
1059
1060                        minor++;
1061#ifdef DEBUG_PRINT_REGMAP
1062                        pelican_regadr_print(can->regs);
1063#endif
1064                }
1065        }
1066
1067        return RTEMS_SUCCESSFUL;
1068}
1069
1070static rtems_device_driver occan_open(rtems_device_major_number major, rtems_device_minor_number minor, void *arg){
1071        occan_priv *can;
1072
1073        DBG("OCCAN: Opening %d\n\r",minor);
1074
1075        if ( minor >= can_cores )
1076                return RTEMS_UNSATISFIED; /* NODEV */
1077
1078        /* get can device */
1079        can = &cans[minor];
1080
1081        /* already opened? */
1082        rtems_semaphore_obtain(can->devsem,RTEMS_WAIT, RTEMS_NO_TIMEOUT);
1083        if ( can->open ){
1084                rtems_semaphore_release(can->devsem);
1085                return RTEMS_RESOURCE_IN_USE; /* EBUSY */
1086        }
1087        can->open = 1;
1088        rtems_semaphore_release(can->devsem);
1089
1090        /* allocate fifos */
1091        can->rxfifo = occan_fifo_create(DEFAULT_RX_FIFO_LEN);
1092        if ( !can->rxfifo ){
1093                can->open = 0;
1094                return RTEMS_NO_MEMORY; /* ENOMEM */
1095        }
1096
1097        can->txfifo = occan_fifo_create(DEFAULT_TX_FIFO_LEN);
1098        if ( !can->txfifo ){
1099                occan_fifo_free(can->rxfifo);
1100                can->rxfifo= NULL;
1101                can->open = 0;
1102                return RTEMS_NO_MEMORY; /* ENOMEM */
1103        }
1104
1105        DBG("OCCAN: Opening %d success\n\r",minor);
1106
1107        can->started = 0;
1108        can->channel = 0; /* Default to first can link */
1109        can->txblk = 1; /* Default to Blocking mode */
1110        can->rxblk = 1; /* Default to Blocking mode */
1111        can->single_mode = 1; /* single mode acceptance filter */
1112
1113        /* reset stat counters */
1114        memset(&can->stats,0,sizeof(occan_stats));
1115
1116        /* HW must be in reset mode here (close and initializes resets core...)
1117         *
1118         * 1. set default modes/speeds
1119         */
1120        pelican_open(can);
1121
1122        return RTEMS_SUCCESSFUL;
1123}
1124
1125static rtems_device_driver occan_close(rtems_device_major_number major, rtems_device_minor_number minor, void *arg){
1126        occan_priv *can = &cans[minor];
1127
1128        DBG("OCCAN: Closing %d\n\r",minor);
1129
1130        /* stop if running */
1131        if ( can->started )
1132                pelican_stop(can);
1133
1134        /* Enter Reset Mode */
1135        can->regs->mode = PELICAN_MOD_RESET;
1136
1137        /* free fifo memory */
1138        occan_fifo_free(can->rxfifo);
1139        occan_fifo_free(can->txfifo);
1140
1141        can->rxfifo = NULL;
1142        can->txfifo = NULL;
1143
1144        return RTEMS_SUCCESSFUL;
1145}
1146
1147static rtems_device_driver occan_read(rtems_device_major_number major, rtems_device_minor_number minor, void *arg){
1148        occan_priv *can = &cans[minor];
1149        rtems_libio_rw_args_t *rw_args=(rtems_libio_rw_args_t *) arg;
1150        CANMsg *dstmsg, *srcmsg;
1151        rtems_interrupt_level oldLevel;
1152        int left;
1153
1154        if ( !can->started ){
1155                DBG("OCCAN: cannot read from minor %d when not started\n\r",minor);
1156                return RTEMS_RESOURCE_IN_USE; /* -EBUSY*/
1157        }
1158
1159        /* does at least one message fit */
1160        left = rw_args->count;
1161        if ( left < sizeof(CANMsg) ){
1162                DBG("OCCAN: minor %d length of buffer must be at least %d, our is %d\n\r",minor,sizeof(CANMsg),left);
1163                return  RTEMS_INVALID_NAME; /* -EINVAL */
1164        }
1165
1166        /* get pointer to start where to put CAN messages */
1167        dstmsg = (CANMsg *)rw_args->buffer;
1168        if ( !dstmsg ){
1169                DBG("OCCAN: minor %d read: input buffer is NULL\n\r",minor);
1170                return  RTEMS_INVALID_NAME; /* -EINVAL */
1171        }
1172
1173        while (left >= sizeof(CANMsg) ){
1174
1175                /* turn off interrupts */
1176                rtems_interrupt_disable(oldLevel);
1177
1178                /* A bus off interrupt may have occured after checking can->started */
1179                if ( can->status & (OCCAN_STATUS_ERR_BUSOFF|OCCAN_STATUS_RESET) ){
1180                        rtems_interrupt_enable(oldLevel);
1181                        DBG("OCCAN: read is cancelled due to a BUS OFF error\n\r");
1182                        rw_args->bytes_moved = rw_args->count-left;
1183                        return RTEMS_IO_ERROR; /* EIO */
1184                }
1185
1186                srcmsg = occan_fifo_claim_get(can->rxfifo);
1187                if ( !srcmsg ){
1188                        /* no more messages in reception fifo.
1189                         * Wait for incoming packets only if in
1190                         * blocking mode AND no messages been
1191                         * read before.
1192                         */
1193                        if ( !can->rxblk || (left != rw_args->count) ){
1194                                /* turn on interrupts again */
1195                                rtems_interrupt_enable(oldLevel);
1196                                break;
1197                        }
1198
1199                        /* turn on interrupts again */
1200                        rtems_interrupt_enable(oldLevel);
1201
1202                        DBG("OCCAN: Waiting for RX int\n\r");
1203
1204                        /* wait for incomming messages */
1205                        rtems_semaphore_obtain(can->rxsem,RTEMS_WAIT,RTEMS_NO_TIMEOUT);
1206
1207                        /* did we get woken up by a BUS OFF error? */
1208                        if ( can->status & (OCCAN_STATUS_ERR_BUSOFF|OCCAN_STATUS_RESET) ){
1209                                DBG("OCCAN: Blocking read got woken up by BUS OFF error\n\r");
1210                                /* At this point it should not matter how many messages we handled */
1211                                rw_args->bytes_moved = rw_args->count-left;
1212                                return RTEMS_IO_ERROR; /* EIO */
1213                        }
1214
1215                        /* no errors detected, it must be a message */
1216                        continue;
1217                }
1218
1219                /* got message, copy it to userspace buffer */
1220                *dstmsg = *srcmsg;
1221
1222                /* Return borrowed message, RX interrupt can use it again */
1223                occan_fifo_get(can->rxfifo);
1224
1225                /* turn on interrupts again */
1226                rtems_interrupt_enable(oldLevel);
1227
1228                /* increase pointers */
1229                left -= sizeof(CANMsg);
1230                dstmsg++;
1231        }
1232
1233        /* save number of read bytes. */
1234        rw_args->bytes_moved = rw_args->count-left;
1235        if ( rw_args->bytes_moved == 0 ){
1236                DBG("OCCAN: minor %d read would block, returning\n\r",minor);
1237                return RTEMS_TIMEOUT; /* ETIMEDOUT should be EAGAIN/EWOULDBLOCK */
1238        }
1239        return RTEMS_SUCCESSFUL;
1240}
1241
1242static rtems_device_driver occan_write(rtems_device_major_number major, rtems_device_minor_number minor, void *arg){
1243        occan_priv *can = &cans[minor];
1244        rtems_libio_rw_args_t *rw_args=(rtems_libio_rw_args_t *) arg;
1245        CANMsg *msg,*fifo_msg;
1246        rtems_interrupt_level oldLevel;
1247        int left;
1248
1249        DBG("OCCAN: Writing %d bytes from 0x%lx (%d)\n\r",rw_args->count,rw_args->buffer,sizeof(CANMsg));
1250
1251        if ( !can->started )
1252                return RTEMS_RESOURCE_IN_USE; /* EBUSY */
1253
1254        left = rw_args->count;
1255        if ( (left < sizeof(CANMsg)) || (!rw_args->buffer) ){
1256                return RTEMS_INVALID_NAME; /* EINVAL */
1257        }
1258
1259        msg = (CANMsg *)rw_args->buffer;
1260
1261        /* limit CAN message length to 8 */
1262        msg->len = (msg->len > 8) ? 8 : msg->len;
1263
1264#ifdef DEBUG_VERBOSE
1265        pelican_regs_print(can->regs);
1266        occan_stat_print(&can->stats);
1267#endif
1268
1269        /* turn off interrupts */
1270        rtems_interrupt_disable(oldLevel);
1271
1272        /* A bus off interrupt may have occured after checking can->started */
1273        if ( can->status & (OCCAN_STATUS_ERR_BUSOFF|OCCAN_STATUS_RESET) ){
1274                rtems_interrupt_enable(oldLevel);
1275                rw_args->bytes_moved = 0;
1276                return RTEMS_IO_ERROR; /* EIO */
1277        }
1278
1279        /* If no messages in software tx fifo, we will
1280         * try to send first message by putting it directly
1281         * into the HW TX fifo.
1282         */
1283        if ( occan_fifo_empty(can->txfifo) ){
1284                /*pelican_regs_print(cans[minor+1].regs);*/
1285                if ( !pelican_send(can,msg) ) {
1286                        /* First message put directly into HW TX fifo
1287                         * This will turn TX interrupt on.
1288                         */
1289                        left -= sizeof(CANMsg);
1290                        msg++;
1291
1292                        /* bump stat counters */
1293                        can->stats.tx_msgs++;
1294
1295                        DBG("OCCAN: Sending direct via HW\n\r");
1296                }
1297        }
1298
1299        /* Put messages into software fifo */
1300        while ( left >= sizeof(CANMsg) ){
1301
1302                /* limit CAN message length to 8 */
1303                msg->len = (msg->len > 8) ? 8 : msg->len;
1304
1305                fifo_msg = occan_fifo_put_claim(can->txfifo,0);
1306                if ( !fifo_msg ){
1307
1308                        DBG("OCCAN: FIFO is full\n\r");
1309                        /* Block only if no messages previously sent
1310                         * and no in blocking mode
1311                         */
1312                        if ( !can->txblk  || (left != rw_args->count) )
1313                                break;
1314
1315                        /* turn on interupts again and wait
1316                                INT_ON
1317                                WAIT FOR FREE BUF;
1318                                INT_OFF;
1319                                CHECK_IF_FIFO_EMPTY ==> SEND DIRECT VIA HW;
1320                        */
1321                        rtems_interrupt_enable(oldLevel);
1322
1323                        DBG("OCCAN: Waiting for tx int\n\r");
1324
1325                        rtems_semaphore_obtain(can->txsem, RTEMS_WAIT, RTEMS_NO_TIMEOUT);
1326
1327                        /* did we get woken up by a BUS OFF error? */
1328                        if ( can->status & (OCCAN_STATUS_ERR_BUSOFF|OCCAN_STATUS_RESET) ){
1329                                DBG("OCCAN: Blocking write got woken up by BUS OFF error or RESET event\n\r");
1330                                /* At this point it should not matter how many messages we handled */
1331                                rw_args->bytes_moved = rw_args->count-left;
1332                                return RTEMS_IO_ERROR; /* EIO */
1333                        }
1334
1335                        rtems_interrupt_disable(oldLevel);
1336
1337                        if ( occan_fifo_empty(can->txfifo) ){
1338                                if ( !pelican_send(can,msg) ) {
1339                                        /* First message put directly into HW TX fifo
1340                                   * This will turn TX interrupt on.
1341                                   */
1342                                        left -= sizeof(CANMsg);
1343                                        msg++;
1344
1345                                        /* bump stat counters */
1346                                        can->stats.tx_msgs++;
1347
1348                                        DBG("OCCAN: Sending direct2 via HW\n\r");
1349                                }
1350                        }
1351                        continue;
1352                }
1353
1354                /* copy message into fifo area */
1355                *fifo_msg = *msg;
1356
1357                /* tell interrupt handler about the message */
1358                occan_fifo_put(can->txfifo);
1359
1360                DBG("OCCAN: Put info fifo SW\n\r");
1361
1362                /* Prepare insert of next message */
1363                msg++;
1364                left-=sizeof(CANMsg);
1365        }
1366
1367        rtems_interrupt_enable(oldLevel);
1368
1369        rw_args->bytes_moved = rw_args->count-left;
1370        DBG("OCCAN: Sent %d\n\r",rw_args->bytes_moved);
1371
1372        if ( left == rw_args->count )
1373                return RTEMS_TIMEOUT; /* ETIMEDOUT should be EAGAIN/EWOULDBLOCK */
1374        return RTEMS_SUCCESSFUL;
1375}
1376
1377static rtems_device_driver occan_ioctl(rtems_device_major_number major, rtems_device_minor_number minor, void *arg){
1378        int ret;
1379        occan_speed_regs timing;
1380        occan_priv *can = &cans[minor];
1381        unsigned int speed;
1382        rtems_libio_ioctl_args_t        *ioarg = (rtems_libio_ioctl_args_t *) arg;
1383        struct occan_afilter *afilter;
1384        occan_stats *dststats;
1385        unsigned int rxcnt,txcnt;
1386
1387        DBG("OCCAN: IOCTL %d\n\r",ioarg->command);
1388
1389        ioarg->ioctl_return = 0;
1390        switch(ioarg->command){
1391                case OCCAN_IOC_SET_SPEED:
1392
1393                        /* cannot change speed during run mode */
1394                        if ( can->started )
1395                                return RTEMS_RESOURCE_IN_USE; /* EBUSY */
1396
1397                        /* get speed rate from argument */
1398                        speed = (unsigned int)ioarg->buffer;
1399                        ret = occan_calc_speedregs(sys_freq_hz,speed,&timing);
1400                        if ( ret )
1401                                return  RTEMS_INVALID_NAME; /* EINVAL */
1402
1403                        /* set the speed regs of the CAN core */
1404                        /* occan_set_speedregs(can,timing); */
1405
1406                        /* save timing/speed */
1407                        can->speed = speed;
1408                        can->timing = timing;
1409                        break;
1410
1411                case OCCAN_IOC_SET_BTRS:
1412                        /* Set BTR registers manually
1413                         * Read OCCAN Manual.
1414                         */
1415                        if ( can->started )
1416                                return RTEMS_RESOURCE_IN_USE; /* EBUSY */
1417
1418                        can->speed = 0; /* custom */
1419                        can->timing.btr1 = (unsigned int)ioarg->buffer & 0xff;
1420                        can->timing.btr0 = ((unsigned int)ioarg->buffer>>8) & 0xff;
1421/*
1422                        can->timing.sjw = (btr0 >> OCCAN_BUSTIM_SJW_BIT) & 0x3;
1423                        can->timing.brp = btr0 & OCCAN_BUSTIM_BRP;
1424                        can->timing.tseg1 = btr1 & 0xf;
1425                        can->timing.tseg2 = (btr1 >> OCCAN_BUSTIM_TSEG2_BIT) & 0x7;
1426                        can->timing.sam = (btr1 >> 7) & 0x1;
1427                        */
1428                        break;
1429
1430                case OCCAN_IOC_SPEED_AUTO:
1431                        return RTEMS_NOT_IMPLEMENTED;
1432                        if ( can->started )
1433                                return RTEMS_RESOURCE_IN_USE; /* EBUSY */
1434
1435                        if ( (speed=pelican_speed_auto(can)) < 0 ){
1436                                /* failed */
1437                                return RTEMS_IO_ERROR;
1438                        }
1439
1440                        /* set new speed */
1441                        can->speed = speed;
1442
1443                        if ( (int *)ioarg->buffer ){
1444                                *(int *)ioarg->buffer = speed;
1445                        }
1446                        return RTEMS_SUCCESSFUL;
1447                        break;
1448
1449                case OCCAN_IOC_SET_BUFLEN:
1450                        /* set rx & tx fifo buffer length */
1451                        if ( can->started )
1452                                return RTEMS_RESOURCE_IN_USE; /* EBUSY */
1453
1454                        rxcnt = (unsigned int)ioarg->buffer & 0x0000ffff;
1455                        txcnt = (unsigned int)ioarg->buffer >> 16;
1456
1457                        occan_fifo_free(can->rxfifo);
1458                        occan_fifo_free(can->txfifo);
1459
1460                        /* allocate new buffers */
1461                        can->rxfifo = occan_fifo_create(rxcnt);
1462                        can->txfifo = occan_fifo_create(txcnt);
1463
1464                        if ( !can->rxfifo || !can->txfifo )
1465                                return RTEMS_NO_MEMORY; /* ENOMEM */
1466                        break;
1467
1468                case OCCAN_IOC_GET_CONF:
1469                        return RTEMS_NOT_IMPLEMENTED;
1470                        break;
1471
1472                case OCCAN_IOC_GET_STATS:
1473                        dststats = (occan_stats *)ioarg->buffer;
1474                        if ( !dststats )
1475                                return  RTEMS_INVALID_NAME; /* EINVAL */
1476
1477                        /* copy data stats into userspace buffer */
1478      if ( can->rxfifo )
1479        can->stats.rx_sw_dovr = can->rxfifo->ovcnt;
1480                        *dststats = can->stats;
1481                        break;
1482
1483                case OCCAN_IOC_GET_STATUS:
1484                        /* return the status of the */
1485                        if ( !ioarg->buffer )
1486                                return RTEMS_INVALID_NAME;
1487
1488                        *(unsigned int *)ioarg->buffer = can->status;
1489                        break;
1490
1491                /* Set physical link */
1492                case OCCAN_IOC_SET_LINK:
1493#ifdef REDUNDANT_CHANNELS
1494                        if ( can->started )
1495                                return RTEMS_RESOURCE_IN_USE; /* EBUSY */
1496
1497                        /* switch HW channel */
1498                        can->channel = (unsigned int)ioargs->buffer;
1499#else
1500                        return RTEMS_NOT_IMPLEMENTED;
1501#endif
1502                        break;
1503
1504                case OCCAN_IOC_SET_FILTER:
1505                        if ( can->started )
1506                                return RTEMS_RESOURCE_IN_USE; /* EBUSY */
1507
1508                        afilter = (struct occan_afilter *)ioarg->buffer;
1509
1510                        if ( !afilter )
1511                                return RTEMS_INVALID_NAME; /* EINVAL */
1512
1513                        /* copy acceptance filter */
1514                        can->acode[0] = afilter->code[0];
1515                        can->acode[1] = afilter->code[1];
1516                        can->acode[2] = afilter->code[2];
1517                        can->acode[3] = afilter->code[3];
1518
1519                        can->amask[0] = afilter->mask[0];
1520                        can->amask[1] = afilter->mask[1];
1521                        can->amask[2] = afilter->mask[2];
1522                        can->amask[3] = afilter->mask[3];
1523
1524                        can->single_mode = ( afilter->single_mode ) ? 1 : 0;
1525
1526                        /* Acceptance filter is written to hardware
1527                         * when starting.
1528                         */
1529                        /* pelican_set_accept(can,can->acode,can->amask);*/
1530                        break;
1531
1532                case OCCAN_IOC_SET_BLK_MODE:
1533                        can->rxblk = (unsigned int)ioarg->buffer & OCCAN_BLK_MODE_RX;
1534                        can->txblk = ((unsigned int)ioarg->buffer & OCCAN_BLK_MODE_TX) >> 1;
1535                        break;
1536
1537                case OCCAN_IOC_START:
1538                        if ( can->started )
1539                                return RTEMS_RESOURCE_IN_USE; /* EBUSY */
1540                        if ( pelican_start(can) )
1541                                return RTEMS_NO_MEMORY; /* failed because of no memory, can happen if SET_BUFLEN failed */
1542                        can->started = 1;
1543                        break;
1544
1545                case OCCAN_IOC_STOP:
1546                        if ( !can->started )
1547                                return RTEMS_RESOURCE_IN_USE; /* EBUSY */
1548                        pelican_stop(can);
1549                        can->started = 0;
1550                        break;
1551
1552                default:
1553                        return RTEMS_NOT_DEFINED;
1554        }
1555        return RTEMS_SUCCESSFUL;
1556}
1557
1558static void occan_interrupt(occan_priv *can){
1559        unsigned char iflags;
1560        pelican_regs *regs = can->regs;
1561        CANMsg *msg;
1562        int signal_rx=0, signal_tx=0;
1563        unsigned char tmp, errcode, arbcode;
1564        int tx_error_cnt,rx_error_cnt;
1565
1566        can->stats.ints++;
1567
1568        while ( (iflags = READ_REG(&can->regs->intflags)) != 0 ){
1569                /* still interrupts to handle */
1570
1571                if ( iflags & PELICAN_IF_RX ){
1572                        /* the rx fifo is not empty
1573                         * put 1 message into rxfifo for later use
1574                         */
1575
1576                        /* get empty (or make room) message */
1577                        msg = occan_fifo_put_claim(can->rxfifo,1);
1578                        tmp = READ_REG(&regs->rx_fi_xff);
1579                        msg->extended = tmp >> 7;
1580                        msg->rtr = (tmp >> 6) & 1;
1581                        msg->len = tmp = tmp & 0x0f;
1582
1583                        if ( msg->extended ){
1584                                /* extended message */
1585                                msg->id =  READ_REG(&regs->msg.rx_eff.id[0])<<(5+8+8) |
1586                                           READ_REG(&regs->msg.rx_eff.id[1])<<(5+8) |
1587                                           READ_REG(&regs->msg.rx_eff.id[2])<<5 |
1588                                           READ_REG(&regs->msg.rx_eff.id[3])>>3;
1589                                while(tmp--){
1590                                        msg->data[tmp] = READ_REG(&regs->msg.rx_eff.data[tmp]);
1591                                }
1592                                /*
1593                                msg->data[0] = READ_REG(&regs->msg.rx_eff.data[0]);
1594                                msg->data[1] = READ_REG(&regs->msg.rx_eff.data[1]);
1595                                msg->data[2] = READ_REG(&regs->msg.rx_eff.data[2]);
1596                                msg->data[3] = READ_REG(&regs->msg.rx_eff.data[3]);
1597                                msg->data[4] = READ_REG(&regs->msg.rx_eff.data[4]);
1598                                msg->data[5] = READ_REG(&regs->msg.rx_eff.data[5]);
1599                                msg->data[6] = READ_REG(&regs->msg.rx_eff.data[6]);
1600                                msg->data[7] = READ_REG(&regs->msg.rx_eff.data[7]);
1601                                */
1602                        }else{
1603                                /* standard message */
1604                                msg->id =  READ_REG(&regs->msg.rx_sff.id[0])<<3 |
1605                                           READ_REG(&regs->msg.rx_sff.id[1])>>5;
1606
1607                                while(tmp--){
1608                                        msg->data[tmp] = READ_REG(&regs->msg.rx_sff.data[tmp]);
1609                                }
1610                                /*
1611                                msg->data[0] = READ_REG(&regs->msg.rx_sff.data[0]);
1612                                msg->data[1] = READ_REG(&regs->msg.rx_sff.data[1]);
1613                                msg->data[2] = READ_REG(&regs->msg.rx_sff.data[2]);
1614                                msg->data[3] = READ_REG(&regs->msg.rx_sff.data[3]);
1615                                msg->data[4] = READ_REG(&regs->msg.rx_sff.data[4]);
1616                                msg->data[5] = READ_REG(&regs->msg.rx_sff.data[5]);
1617                                msg->data[6] = READ_REG(&regs->msg.rx_sff.data[6]);
1618                                msg->data[7] = READ_REG(&regs->msg.rx_sff.data[7]);
1619                                */
1620                        }
1621
1622                        /* Re-Enable RX buffer for a new message */
1623                        regs->cmd = PELICAN_CMD_RELRXBUF;
1624
1625                        /* make message available to the user */
1626                        occan_fifo_put(can->rxfifo);
1627
1628                        /* bump stat counters */
1629                        can->stats.rx_msgs++;
1630
1631                        /* signal the semaphore only once */
1632                        signal_rx = 1;
1633                }
1634
1635                if ( iflags & PELICAN_IF_TX ){
1636                        /* there is room in tx fifo of HW */
1637
1638                        if ( !occan_fifo_empty(can->txfifo) ){
1639                                /* send 1 more messages */
1640                                msg = occan_fifo_claim_get(can->txfifo);
1641
1642                                if ( pelican_send(can,msg) ){
1643                                        /* ERROR! We got an TX interrupt telling us
1644                                         * tx fifo is empty, yet it is not.
1645                                         *
1646                                         * Complain about this max 10 times
1647                                         */
1648                                        if ( can->stats.tx_buf_error < 10 ){
1649                                                printk("OCCAN: got TX interrupt but TX fifo in not empty (%d)\n\r",can->stats.tx_buf_error);
1650                                        }
1651                                        can->status |= OCCAN_STATUS_QUEUE_ERROR;
1652                                        can->stats.tx_buf_error++;
1653                                }
1654
1655                                /* free software-fifo space taken by sent message */
1656                                occan_fifo_get(can->txfifo);
1657
1658                                /* bump stat counters */
1659                                can->stats.tx_msgs++;
1660
1661                                /* wake any sleeping thread waiting for "fifo not full" */
1662                                signal_tx = 1;
1663                        }
1664                }
1665
1666                if ( iflags & PELICAN_IF_ERRW ){
1667                        tx_error_cnt = READ_REG(&regs->tx_err_cnt);
1668                        rx_error_cnt = READ_REG(&regs->rx_err_cnt);
1669
1670                        /* 1. if bus off tx error counter = 127 */
1671                        if ( (tx_error_cnt > 96) || (rx_error_cnt > 96) ){
1672                                /* in Error Active Warning area or BUS OFF */
1673                                can->status |= OCCAN_STATUS_WARN;
1674
1675                                /* check reset bit for reset mode */
1676                                if ( READ_REG(&regs->mode) & PELICAN_MOD_RESET ){
1677                                        /* in reset mode ==> bus off */
1678                                        can->status |= OCCAN_STATUS_ERR_BUSOFF | OCCAN_STATUS_RESET;
1679
1680                                        /***** pelican_stop(can) ******
1681                                         * turn off interrupts
1682                                         * enter reset mode (HW already done that for us)
1683                                         */
1684                                        regs->inten = 0;
1685
1686                                        /* Indicate that we are not started any more.
1687                                         * This will make write/read return with EBUSY
1688                                         * on read/write attempts.
1689                                         *
1690                                         * User must issue a ioctl(START) to get going again.
1691                                         */
1692                                        can->started = 0;
1693
1694                                        /* signal any waiting read/write threads, so that they
1695                                         * can handle the bus error.
1696                                         */
1697                                        signal_rx = 1;
1698                                        signal_tx = 1;
1699
1700                                        /* ingnore any old pending interrupt */
1701                                        break;
1702                                }
1703
1704                        }else{
1705                                /* not in Upper Error Active area any more */
1706                                can->status &= ~(OCCAN_STATUS_WARN);
1707                        }
1708                        can->stats.err_warn++;
1709                }
1710
1711                if ( iflags & PELICAN_IF_DOVR){
1712                        can->status |= OCCAN_STATUS_OVERRUN;
1713                        can->stats.err_dovr++;
1714                        DBG("OCCAN_INT: DOVR\n\r");
1715                }
1716
1717                if ( iflags & PELICAN_IF_ERRP){
1718                        /* Let the error counters decide what kind of
1719                         * interrupt it was. In/Out of EPassive area.
1720                         */
1721                        tx_error_cnt = READ_REG(&regs->tx_err_cnt);
1722                        rx_error_cnt = READ_REG(&regs->rx_err_cnt);
1723
1724                        if ( (tx_error_cnt > 127) || (rx_error_cnt > 127) ){
1725                                can->status |= OCCAN_STATUS_ERR_PASSIVE;
1726                        }else{
1727                                can->status &= ~(OCCAN_STATUS_ERR_PASSIVE);
1728                        }
1729
1730                        /* increase Error Passive In/out interrupt counter */
1731                        can->stats.err_errp++;
1732                }
1733
1734                if ( iflags & PELICAN_IF_ARB){
1735                        arbcode = READ_REG(&regs->arbcode);
1736                        can->stats.err_arb_bitnum[arbcode & PELICAN_ARB_BITS]++;
1737                        can->stats.err_arb++;
1738                        DBG("OCCAN_INT: ARB (0x%x)\n\r",arbcode & PELICAN_ARB_BITS);
1739                }
1740
1741                if ( iflags & PELICAN_IF_BUS){
1742                        /* Some kind of BUS error, only used for
1743                         * statistics. Error Register is decoded
1744                         * and put into can->stats.
1745                         */
1746                        errcode = READ_REG(&regs->errcode);
1747                        switch( errcode & PELICAN_ECC_CODE ){
1748                                case PELICAN_ECC_CODE_BIT:
1749                                        can->stats.err_bus_bit++;
1750                                        break;
1751                                case PELICAN_ECC_CODE_FORM:
1752                                        can->stats.err_bus_form++;
1753                                        break;
1754                                case PELICAN_ECC_CODE_STUFF:
1755                                        can->stats.err_bus_stuff++;
1756                                        break;
1757                                case PELICAN_ECC_CODE_OTHER:
1758                                        can->stats.err_bus_other++;
1759                                        break;
1760                        }
1761
1762                        /* Get Direction (TX/RX) */
1763                        if ( errcode & PELICAN_ECC_DIR ){
1764                                can->stats.err_bus_rx++;
1765                        }else{
1766                                can->stats.err_bus_tx++;
1767                        }
1768
1769                        /* Get Segment in frame that went wrong */
1770                        can->stats.err_bus_segs[errcode & PELICAN_ECC_SEG]++;
1771
1772                        /* total number of bus errors */
1773                        can->stats.err_bus++;
1774                }
1775        }
1776
1777        /* signal Binary semaphore, messages available! */
1778        if ( signal_rx ){
1779                rtems_semaphore_release(can->rxsem);
1780        }
1781
1782        if ( signal_tx ){
1783                rtems_semaphore_release(can->txsem);
1784        }
1785}
1786
1787#ifdef OCCAN_DEFINE_INTHANDLER
1788static void occan_interrupt_handler(rtems_vector_number v){
1789        int minor;
1790
1791        /* convert to */
1792  for(minor = 0; minor < can_cores; minor++) {
1793        if ( v == (cans[minor].irq+0x10) ) {
1794                        occan_interrupt(&cans[minor]);
1795                        return;
1796                }
1797        }
1798}
1799#endif
1800
1801#define OCCAN_DRIVER_TABLE_ENTRY { occan_initialize, occan_open, occan_close, occan_read, occan_write, occan_ioctl }
1802
1803static rtems_driver_address_table occan_driver = OCCAN_DRIVER_TABLE_ENTRY;
1804
1805int OCCAN_PREFIX(_register)(amba_confarea_type *bus){
1806        rtems_status_code r;
1807        rtems_device_major_number m;
1808
1809        amba_bus = bus;
1810        if ( !bus )
1811                return 1;
1812
1813  if ((r = rtems_io_register_driver(0, &occan_driver, &m)) == RTEMS_SUCCESSFUL) {
1814                DBG("OCCAN driver successfully registered, major: %d\n\r", m);
1815        }else{
1816                switch(r) {
1817                        case RTEMS_TOO_MANY:
1818                                printk("OCCAN rtems_io_register_driver failed: RTEMS_TOO_MANY\n\r"); break;
1819                        case RTEMS_INVALID_NUMBER:
1820                                printk("OCCAN rtems_io_register_driver failed: RTEMS_INVALID_NUMBER\n\r"); break;
1821                        case RTEMS_RESOURCE_IN_USE:
1822                                printk("OCCAN rtems_io_register_driver failed: RTEMS_RESOURCE_IN_USE\n\r"); break;
1823                        default:
1824                                printk("OCCAN rtems_io_register_driver failed\n\r");
1825                }
1826                return 1;
1827        }
1828        return 0;
1829}
1830
1831
1832/*******************************************************************************
1833 * FIFO IMPLEMENTATION
1834 */
1835
1836static occan_fifo *occan_fifo_create(int cnt){
1837        occan_fifo *fifo;
1838        fifo = malloc(sizeof(occan_fifo)+cnt*sizeof(CANMsg));
1839        if ( fifo ){
1840                fifo->cnt = cnt;
1841                fifo->full = 0;
1842                fifo->ovcnt = 0;
1843                fifo->base = (CANMsg *)&fifo->fifoarea[0];
1844                fifo->tail = fifo->head = fifo->base;
1845                /* clear CAN Messages */
1846                memset(fifo->base,0,cnt * sizeof(CANMsg));
1847        }
1848        return fifo;
1849}
1850
1851static void occan_fifo_free(occan_fifo *fifo){
1852        if ( fifo )
1853                free(fifo);
1854}
1855
1856static int occan_fifo_full(occan_fifo *fifo){
1857        return fifo->full;
1858}
1859
1860static int occan_fifo_empty(occan_fifo *fifo){
1861        return (!fifo->full) && (fifo->head == fifo->tail);
1862}
1863
1864/* Stage 1 - get buffer to fill (never fails if force!=0) */
1865static CANMsg *occan_fifo_put_claim(occan_fifo *fifo, int force){
1866        if ( !fifo )
1867                return NULL;
1868
1869        if ( occan_fifo_full(fifo) ){
1870
1871                if ( !force )
1872                        return NULL;
1873
1874                /* all buffers already used ==> overwrite the oldest */
1875                fifo->ovcnt++;
1876                occan_fifo_get(fifo);
1877        }
1878
1879        return fifo->head;
1880}
1881
1882/* Stage 2 - increment indexes */
1883static void occan_fifo_put(occan_fifo *fifo){
1884        if ( occan_fifo_full(fifo) )
1885                return;
1886
1887        /* wrap around */
1888        fifo->head = (fifo->head >= &fifo->base[fifo->cnt-1])? fifo->base : fifo->head+1;
1889
1890        if ( fifo->head == fifo->tail )
1891                fifo->full = 1;
1892}
1893
1894static CANMsg *occan_fifo_claim_get(occan_fifo *fifo){
1895        if ( occan_fifo_empty(fifo) )
1896                return NULL;
1897
1898        /* return oldest message */
1899        return fifo->tail;
1900}
1901
1902
1903static void occan_fifo_get(occan_fifo *fifo){
1904        if ( !fifo )
1905                return;
1906
1907        if ( occan_fifo_empty(fifo) )
1908                return;
1909
1910        /* increment indexes */
1911        fifo->tail = (fifo->tail >= &fifo->base[fifo->cnt-1])? fifo->base : fifo->tail+1;
1912        fifo->full = 0;
1913}
1914
1915static void occan_fifo_clr(occan_fifo *fifo){
1916  fifo->full  = 0;
1917  fifo->ovcnt = 0;
1918  fifo->head  = fifo->tail = fifo->base;
1919}
1920
1921/*******************************************************************************/
Note: See TracBrowser for help on using the repository browser.