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

5
Last change on this file since 3471d3d was 3471d3d, checked in by Daniel Hellstrom <daniel@…>, on 08/22/17 at 08:32:25

leon,occan: remove dead code.

Fixes #2878

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