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

4.8
Last change on this file since c2ac7e9 was c2ac7e9, checked in by Joel Sherrill <joel.sherrill@…>, on 09/21/07 at 15:47:53

2007-09-21 Daniel Hellstrom <daniel@…>

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