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

4.8
Last change on this file since 125d4c61 was 125d4c61, checked in by Joel Sherrill <joel.sherrill@…>, on 11/30/07 at 16:52:23

2007-11-30 Daniel Hellstrom <daniel@…>

  • shared/can/occan.c: LEON2/3 OCCAN CAN driver. Fixes typecast to volatile integer where needed. Fixes bug where closing the driver and opening it again could make the driver not starting transmission due to the software fifo was not cleared.
  • Property mode set to 100644
File size: 54.3 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.