Back to home page

LXR

 
 

    


File indexing completed on 2025-05-11 08:24:06

0001 /* SPDX-License-Identifier: BSD-2-Clause */
0002 
0003 /*  OC_CAN driver
0004  *
0005  *  COPYRIGHT (c) 2007.
0006  *  Cobham Gaisler AB.
0007  *
0008  * Redistribution and use in source and binary forms, with or without
0009  * modification, are permitted provided that the following conditions
0010  * are met:
0011  * 1. Redistributions of source code must retain the above copyright
0012  *    notice, this list of conditions and the following disclaimer.
0013  * 2. Redistributions in binary form must reproduce the above copyright
0014  *    notice, this list of conditions and the following disclaimer in the
0015  *    documentation and/or other materials provided with the distribution.
0016  *
0017  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
0018  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
0019  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
0020  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
0021  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
0022  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
0023  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
0024  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
0025  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
0026  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
0027  * POSSIBILITY OF SUCH DAMAGE.
0028  */
0029 
0030 #include <rtems.h>
0031 #include <rtems/libio.h>
0032 #include <stdlib.h>
0033 #include <stdio.h>
0034 #include <string.h>
0035 #include <bsp.h>
0036 #include <rtems/bspIo.h> /* printk */
0037 
0038 #include <drvmgr/drvmgr.h>
0039 #include <grlib/ambapp_bus.h>
0040 #include <grlib/occan.h>
0041 #include <grlib/canbtrs.h>
0042 
0043 #include <grlib/grlib_impl.h>
0044 
0045 /* RTEMS -> ERRNO decoding table
0046 
0047 rtems_assoc_t errno_assoc[] = {
0048     { "OK",                 RTEMS_SUCCESSFUL,                0 },
0049     { "BUSY",               RTEMS_RESOURCE_IN_USE,           EBUSY },
0050     { "INVALID NAME",       RTEMS_INVALID_NAME,              EINVAL },
0051     { "NOT IMPLEMENTED",    RTEMS_NOT_IMPLEMENTED,           ENOSYS },
0052     { "TIMEOUT",            RTEMS_TIMEOUT,                   ETIMEDOUT },
0053     { "NO MEMORY",          RTEMS_NO_MEMORY,                 ENOMEM },
0054     { "NO DEVICE",          RTEMS_UNSATISFIED,               ENODEV },
0055     { "INVALID NUMBER",     RTEMS_INVALID_NUMBER,            EBADF},
0056     { "NOT RESOURCE OWNER", RTEMS_NOT_OWNER_OF_RESOURCE,     EPERM},
0057     { "IO ERROR",           RTEMS_IO_ERROR,                  EIO},
0058     { 0, 0, 0 },
0059 };
0060 
0061 */
0062 
0063 /*
0064 #undef DEBUG
0065 #undef DEBUG_EXTRA
0066 #undef DEBUG_PRINT_REGMAP
0067 */
0068 
0069 /* default to byte regs */
0070 #ifndef OCCAN_WORD_REGS
0071  #define OCCAN_BYTE_REGS
0072 #else
0073  #undef OCCAN_BYTE_REGS
0074 #endif
0075 
0076 /* Enable Fixup code older OCCAN with a TX IRQ-FLAG bug */
0077 #define OCCAN_TX_IRQ_FLAG_FIXUP 1
0078 
0079 #define OCCAN_WORD_REG_OFS 0x80
0080 #define OCCAN_NCORE_OFS 0x100
0081 #define DEFAULT_CLKDIV 0x7
0082 #define DEFAULT_EXTENDED_MODE 1
0083 #define DEFAULT_RX_FIFO_LEN 64
0084 #define DEFAULT_TX_FIFO_LEN 64
0085 
0086 /* not implemented yet */
0087 #undef REDUNDANT_CHANNELS
0088 
0089 /* Define common debug macros */
0090 #ifdef DEBUG
0091     #define DBG(fmt, vargs...) printk(fmt, ## vargs )
0092 #else
0093     #define DBG(fmt, vargs...)
0094 #endif
0095 
0096 /* fifo interface */
0097 typedef struct {
0098     int cnt;
0099     int ovcnt; /* overwrite count */
0100     int full; /* 1 = base contain cnt CANMsgs, tail==head */
0101     CANMsg *tail, *head;
0102     CANMsg *base;
0103     CANMsg fifoarea[0];
0104 } occan_fifo;
0105 
0106 /* PELICAN */
0107 
0108 typedef struct {
0109     unsigned char
0110         mode,
0111         cmd,
0112         status,
0113         intflags,
0114         inten,
0115         resv0,
0116         bustim0,
0117         bustim1,
0118         unused0[2],
0119         resv1,
0120         arbcode,
0121         errcode,
0122         errwarn,
0123         rx_err_cnt,
0124         tx_err_cnt,
0125         rx_fi_xff; /* this is also acceptance code 0 in reset mode */
0126         union{
0127             struct {
0128                 unsigned char id[2];
0129                 unsigned char data[8];
0130                 unsigned char next_in_fifo[2];
0131             } rx_sff;
0132             struct {
0133                 unsigned char id[4];
0134                 unsigned char data[8];
0135             } rx_eff;
0136             struct {
0137                 unsigned char id[2];
0138                 unsigned char data[8];
0139                 unsigned char unused[2];
0140             } tx_sff;
0141             struct {
0142                 unsigned char id[4];
0143                 unsigned char data[8];
0144             } tx_eff;
0145             struct {
0146                 unsigned char code[3];
0147                 unsigned char mask[4];
0148             } rst_accept;
0149         } msg;
0150         unsigned char rx_msg_cnt;
0151         unsigned char unused1;
0152         unsigned char clkdiv;
0153 } pelican8_regs;
0154 
0155 typedef struct {
0156     unsigned char
0157         mode, unused0[3],
0158         cmd, unused1[3],
0159         status, unused2[3],
0160         intflags, unused3[3],
0161         inten, unused4[3],
0162         resv0, unused5[3],
0163         bustim0, unused6[3],
0164         bustim1, unused7[3],
0165         unused8[8],
0166         resv1,unused9[3],
0167         arbcode,unused10[3],
0168         errcode,unused11[3],
0169         errwarn,unused12[3],
0170         rx_err_cnt,unused13[3],
0171         tx_err_cnt,unused14[3],
0172         rx_fi_xff, unused15[3]; /* this is also acceptance code 0 in reset mode */
0173         /* make sure to use pointers when writing (byte access) to these registers */
0174         union{
0175             struct {
0176                 unsigned int id[2];
0177                 unsigned int data[8];
0178                 unsigned int next_in_fifo[2];
0179             } rx_sff;
0180             struct {
0181                 unsigned int id[4];
0182                 unsigned int data[8];
0183             } rx_eff;
0184             struct {
0185                 unsigned int id[2];
0186                 unsigned int data[8];
0187             } tx_sff;
0188             struct {
0189                 unsigned int id[4];
0190                 unsigned int data[8];
0191             } tx_eff;
0192             struct {
0193                 unsigned int code[3];
0194                 unsigned int mask[4];
0195             } rst_accept;
0196         } msg;
0197         unsigned char rx_msg_cnt,unused16[3];
0198         unsigned char unused17[4];
0199         unsigned char clkdiv,unused18[3];
0200 } pelican32_regs;
0201 
0202 #ifdef OCCAN_BYTE_REGS
0203 #define pelican_regs pelican8_regs
0204 #else
0205 #define pelican_regs pelican32_regs
0206 #endif
0207 
0208 /* Default sampling point in % */
0209 #define OCCAN_SAMPLING_POINT 90
0210 
0211 /* OCCAN baud-rate paramter boundaries */
0212 struct grlib_canbtrs_ranges occan_btrs_ranges = {
0213     .max_scaler = 64,
0214     .has_bpr = 0,
0215     .divfactor = 1,
0216     .min_tseg1 = 1,
0217     .max_tseg1 = 16,
0218     .min_tseg2 = 1,
0219     .max_tseg2 = 8,
0220 };
0221 
0222 typedef struct {
0223     unsigned char btr0;
0224     unsigned char btr1;
0225 } occan_speed_regs;
0226 
0227 typedef struct {
0228     struct drvmgr_dev *dev;
0229     char devName[52];
0230     SPIN_DECLARE(devlock);
0231 
0232     /* hardware shortcuts */
0233     pelican_regs *regs;
0234     int byte_regs;
0235     int irq;
0236     occan_speed_regs timing;
0237     int channel; /* 0=default, 1=second bus */
0238     int single_mode;
0239     unsigned int sys_freq_hz;
0240 
0241     /* driver state */
0242     rtems_id devsem;
0243     rtems_id txsem;
0244     rtems_id rxsem;
0245     int open;
0246     int started;
0247     int rxblk;
0248     int txblk;
0249     int sending;
0250     unsigned int status;
0251     occan_stats stats;
0252 
0253     /* rx&tx fifos */
0254     occan_fifo *rxfifo;
0255     occan_fifo *txfifo;
0256 
0257     /* Config */
0258     unsigned int speed; /* speed in HZ */
0259     unsigned char acode[4];
0260     unsigned char amask[4];
0261 } occan_priv;
0262 
0263 /********** FIFO INTERFACE **********/
0264 static void occan_fifo_put(occan_fifo *fifo);
0265 static CANMsg *occan_fifo_put_claim(occan_fifo *fifo, int force);
0266 static occan_fifo *occan_fifo_create(int cnt);
0267 static void occan_fifo_free(occan_fifo *fifo);
0268 static int occan_fifo_full(occan_fifo *fifo);
0269 static int occan_fifo_empty(occan_fifo *fifo);
0270 static void occan_fifo_get(occan_fifo *fifo);
0271 static CANMsg *occan_fifo_claim_get(occan_fifo *fifo);
0272 static void occan_fifo_clr(occan_fifo *fifo);
0273 
0274 /**** Hardware related Interface ****/
0275 static void convert_timing_to_btrs(
0276     struct grlib_canbtrs_timing *t,
0277     occan_speed_regs *btrs);
0278 static int occan_set_speedregs(occan_priv *priv, occan_speed_regs *timing);
0279 static void pelican_init(occan_priv *priv);
0280 static void pelican_open(occan_priv *priv);
0281 static int pelican_start(occan_priv *priv);
0282 static void pelican_stop(occan_priv *priv);
0283 static int pelican_send(occan_priv *can, CANMsg *msg);
0284 static void pelican_set_accept(occan_priv *priv, unsigned char *acode, unsigned char *amask);
0285 void occan_interrupt(void *arg);
0286 #ifdef DEBUG_PRINT_REGMAP
0287 static void pelican_regadr_print(pelican_regs *regs);
0288 #endif
0289 
0290 /***** Driver related interface *****/
0291 static rtems_device_driver occan_ioctl(rtems_device_major_number major, rtems_device_minor_number minor, void *arg);
0292 static rtems_device_driver occan_write(rtems_device_major_number major, rtems_device_minor_number minor, void *arg);
0293 static rtems_device_driver occan_read(rtems_device_major_number major, rtems_device_minor_number minor, void *arg);
0294 static rtems_device_driver occan_close(rtems_device_major_number major, rtems_device_minor_number minor, void *arg);
0295 static rtems_device_driver occan_open(rtems_device_major_number major, rtems_device_minor_number minor, void *arg);
0296 static rtems_device_driver occan_initialize(rtems_device_major_number major, rtems_device_minor_number unused, void *arg);
0297 
0298 #define OCCAN_DRIVER_TABLE_ENTRY { occan_initialize, occan_open, occan_close, occan_read, occan_write, occan_ioctl }
0299 static rtems_driver_address_table occan_driver = OCCAN_DRIVER_TABLE_ENTRY;
0300 
0301 
0302 /* Read byte bypassing */
0303 
0304 
0305 /* Bypass cache */
0306 #define READ_REG(priv, address) occan_reg_read(priv, (unsigned int)address)
0307 #define WRITE_REG(priv, address, data) occan_reg_write(priv, (unsigned int)address, data)
0308 
0309 static unsigned int occan_reg_read(occan_priv *priv, unsigned int address)
0310 {
0311     unsigned int adr;
0312     if ( priv->byte_regs ) {
0313         adr = address;
0314     } else {
0315         /* Word accessed registers */
0316         adr = (address & (~0x7f)) | ((address & 0x7f)<<2);
0317     }
0318     return *(volatile unsigned char *)adr;
0319 }
0320 
0321 static void occan_reg_write(
0322     occan_priv *priv, 
0323     unsigned int address,
0324     unsigned char value)
0325 {
0326     unsigned int adr;
0327     if ( priv->byte_regs ) {
0328         adr = address;
0329     } else {
0330         /* Word accessed registers */
0331         adr = (address & (~0x7f)) | ((address & 0x7f)<<2);
0332     }
0333     *(volatile unsigned char *)adr = value;;
0334 }
0335 
0336 /* Mode register bit definitions */
0337 #define PELICAN_MOD_RESET          0x1
0338 #define PELICAN_MOD_LISTEN         0x2
0339 #define PELICAN_MOD_SELFTEST       0x4
0340 #define PELICAN_MOD_ACCEPT         0x8
0341 
0342 /* Command register bit definitions */
0343 #define PELICAN_CMD_TXREQ          0x1
0344 #define PELICAN_CMD_ABORT          0x2
0345 #define PELICAN_CMD_RELRXBUF       0x4
0346 #define PELICAN_CMD_CLRDOVR        0x8
0347 #define PELICAN_CMD_SELFRXRQ       0x10
0348 
0349 /* Status register bit definitions */
0350 #define PELICAN_STAT_RXBUF         0x1
0351 #define PELICAN_STAT_DOVR          0x2
0352 #define PELICAN_STAT_TXBUF         0x4
0353 #define PELICAN_STAT_TXOK          0x8
0354 #define PELICAN_STAT_RX            0x10
0355 #define PELICAN_STAT_TX            0x20
0356 #define PELICAN_STAT_ERR           0x40
0357 #define PELICAN_STAT_BUS           0x80
0358 
0359 /* Interrupt register bit definitions */
0360 #define PELICAN_IF_RX         0x1
0361 #define PELICAN_IF_TX         0x2
0362 #define PELICAN_IF_ERRW       0x4
0363 #define PELICAN_IF_DOVR       0x8
0364 #define PELICAN_IF_ERRP       0x20
0365 #define PELICAN_IF_ARB        0x40
0366 #define PELICAN_IF_BUS        0x80
0367 
0368 /* Interrupt Enable register bit definitions */
0369 #define PELICAN_IE_RX         0x1
0370 #define PELICAN_IE_TX         0x2
0371 #define PELICAN_IE_ERRW       0x4
0372 #define PELICAN_IE_DOVR       0x8
0373 #define PELICAN_IE_ERRP       0x20
0374 #define PELICAN_IE_ARB        0x40
0375 #define PELICAN_IE_BUS        0x80
0376 
0377 /* Arbitration lost capture register bit definitions */
0378 #define PELICAN_ARB_BITS      0x1f
0379 
0380 /*  register bit definitions */
0381 #define PELICAN_ECC_CODE_BIT     0x00
0382 #define PELICAN_ECC_CODE_FORM    0x40
0383 #define PELICAN_ECC_CODE_STUFF   0x80
0384 #define PELICAN_ECC_CODE_OTHER   0xc0
0385 #define PELICAN_ECC_CODE    0xc0
0386 
0387 #define PELICAN_ECC_DIR     0x20
0388 #define PELICAN_ECC_SEG     0x1f
0389 
0390 /* Clock divider register bit definitions */
0391 #define PELICAN_CDR_DIV  0x7
0392 #define PELICAN_CDR_OFF  0x8
0393 #define PELICAN_CDR_MODE 0x80
0394 #define PELICAN_CDR_MODE_PELICAN 0x80
0395 #define PELICAN_CDR_MODE_BITS 7
0396 #define PELICAN_CDR_MODE_BASICAN 0x00
0397 
0398 
0399 /*  register bit definitions */
0400 #define OCCAN_BUSTIM_SJW       0xc0
0401 #define OCCAN_BUSTIM_BRP       0x3f
0402 #define OCCAN_BUSTIM_SJW_BIT   6
0403 
0404 #define OCCAN_BUSTIM_SAM       0x80
0405 #define OCCAN_BUSTIM_TSEG2     0x70
0406 #define OCCAN_BUSTIM_TSEG2_BIT 4
0407 #define OCCAN_BUSTIM_TSEG1     0x0f
0408 
0409 /*  register bit definitions */
0410 /*
0411 #define PELICAN_S_       0x1
0412 #define PELICAN_S_       0x2
0413 #define PELICAN_S_       0x4
0414 #define PELICAN_S_       0x8
0415 #define PELICAN_S_       0x10
0416 #define PELICAN_S_       0x20
0417 #define PELICAN_S_       0x40
0418 #define PELICAN_S_       0x80
0419 */
0420 
0421 static int occan_driver_io_registered = 0;
0422 static rtems_device_major_number occan_driver_io_major = 0;
0423 
0424 /******************* Driver manager interface ***********************/
0425 
0426 /* Driver prototypes */
0427 int occan_register_io(rtems_device_major_number *m);
0428 int occan_device_init(occan_priv *pDev);
0429 
0430 int occan_init2(struct drvmgr_dev *dev);
0431 int occan_init3(struct drvmgr_dev *dev);
0432 
0433 struct drvmgr_drv_ops occan_ops = 
0434 {
0435     .init = {NULL, occan_init2, occan_init3, NULL},
0436     .remove = NULL,
0437     .info = NULL
0438 };
0439 
0440 struct amba_dev_id occan_ids[] = 
0441 {
0442     {VENDOR_GAISLER, GAISLER_CANAHB},
0443     {0, 0}      /* Mark end of table */
0444 };
0445 
0446 struct amba_drv_info occan_drv_info =
0447 {
0448     {
0449         DRVMGR_OBJ_DRV,         /* Driver */
0450         NULL,               /* Next driver */
0451         NULL,               /* Device list */
0452         DRIVER_AMBAPP_GAISLER_OCCAN_ID, /* Driver ID */
0453         "OCCAN_DRV",            /* Driver Name */
0454         DRVMGR_BUS_TYPE_AMBAPP,     /* Bus Type */
0455         &occan_ops,
0456         NULL,               /* Funcs */
0457         0,              /* No devices yet */
0458         0,
0459     },
0460     &occan_ids[0]
0461 };
0462 
0463 void occan_register_drv (void)
0464 {
0465     DBG("Registering OCCAN driver\n");
0466     drvmgr_drv_register(&occan_drv_info.general);
0467 }
0468 
0469 int occan_init2(struct drvmgr_dev *dev)
0470 {
0471     occan_priv *priv;
0472 
0473     DBG("OCCAN[%d] on bus %s\n", dev->minor_drv, dev->parent->dev->name);
0474     priv = dev->priv = grlib_calloc(1, sizeof(*priv));
0475     if ( !priv )
0476         return DRVMGR_NOMEM;
0477     priv->dev = dev;
0478 
0479     return DRVMGR_OK;
0480 }
0481 
0482 int occan_init3(struct drvmgr_dev *dev)
0483 {
0484     occan_priv *priv;
0485     char prefix[32];
0486     rtems_status_code status;
0487 
0488     priv = dev->priv;
0489 
0490     /* Do initialization */
0491 
0492     if ( occan_driver_io_registered == 0) {
0493         /* Register the I/O driver only once for all cores */
0494         if ( occan_register_io(&occan_driver_io_major) ) {
0495             /* Failed to register I/O driver */
0496             dev->priv = NULL;
0497             return DRVMGR_FAIL;
0498         }
0499 
0500         occan_driver_io_registered = 1;
0501     }
0502 
0503     /* I/O system registered and initialized 
0504      * Now we take care of device initialization.
0505      */
0506 
0507     if ( occan_device_init(priv) ) {
0508         return DRVMGR_FAIL;
0509     }
0510 
0511     /* Get Filesystem name prefix */
0512     prefix[0] = '\0';
0513     if ( drvmgr_get_dev_prefix(dev, prefix) ) {
0514         /* Failed to get prefix, make sure of a unique FS name
0515          * by using the driver minor.
0516          */
0517         sprintf(priv->devName, "/dev/occan%d", dev->minor_drv);
0518     } else {
0519         /* Got special prefix, this means we have a bus prefix
0520          * And we should use our "bus minor"
0521          */
0522         sprintf(priv->devName, "/dev/%soccan%d", prefix, dev->minor_bus);
0523     }
0524 
0525     /* Register Device */
0526     DBG("OCCAN[%d]: Registering %s\n", dev->minor_drv, priv->devName);
0527     status = rtems_io_register_name(priv->devName, occan_driver_io_major, dev->minor_drv);
0528     if (status != RTEMS_SUCCESSFUL) {
0529         return DRVMGR_FAIL;
0530     }
0531 
0532     return DRVMGR_OK;
0533 }
0534 
0535 /******************* Driver Implementation ***********************/
0536 
0537 int occan_register_io(rtems_device_major_number *m)
0538 {
0539     rtems_status_code r;
0540 
0541     if ((r = rtems_io_register_driver(0, &occan_driver, m)) == RTEMS_SUCCESSFUL) {
0542         DBG("OCCAN driver successfully registered, major: %d\n", *m);
0543     } else {
0544         switch(r) {
0545         case RTEMS_TOO_MANY:
0546             printk("OCCAN rtems_io_register_driver failed: RTEMS_TOO_MANY\n");
0547             return -1;
0548         case RTEMS_INVALID_NUMBER:  
0549             printk("OCCAN rtems_io_register_driver failed: RTEMS_INVALID_NUMBER\n");
0550             return -1;
0551         case RTEMS_RESOURCE_IN_USE:
0552             printk("OCCAN rtems_io_register_driver failed: RTEMS_RESOURCE_IN_USE\n");
0553             return -1;
0554         default:
0555             printk("OCCAN rtems_io_register_driver failed\n");
0556             return -1;
0557         }
0558     }
0559     return 0;
0560 }
0561 
0562 int occan_device_init(occan_priv *pDev)
0563 {
0564     struct amba_dev_info *ambadev;
0565     struct ambapp_core *pnpinfo;
0566     rtems_status_code status;
0567     int minor;
0568 
0569     /* Get device information from AMBA PnP information */
0570     ambadev = (struct amba_dev_info *)pDev->dev->businfo;
0571     if ( ambadev == NULL ) {
0572         return -1;
0573     }
0574     pnpinfo = &ambadev->info;
0575     pDev->irq = pnpinfo->irq;
0576     pDev->regs = (pelican_regs *)(pnpinfo->ahb_slv->start[0] + OCCAN_NCORE_OFS*pnpinfo->index);
0577     pDev->byte_regs = 1;
0578     minor = pDev->dev->minor_drv;
0579 
0580     /* Get frequency in Hz */
0581     if ( drvmgr_freq_get(pDev->dev, DEV_AHB_SLV, &pDev->sys_freq_hz) ) {
0582         return -1;
0583     }
0584 
0585     DBG("OCCAN frequency: %d Hz\n", pDev->sys_freq_hz);
0586 
0587     /* initialize software */
0588     pDev->open = 0;
0589     pDev->started = 0; /* Needed for spurious interrupts */
0590     pDev->rxfifo = NULL;
0591     pDev->txfifo = NULL;
0592     status = rtems_semaphore_create(
0593             rtems_build_name('C', 'd', 'v', '0'+minor),
0594             1,
0595             RTEMS_FIFO | RTEMS_SIMPLE_BINARY_SEMAPHORE | RTEMS_NO_INHERIT_PRIORITY | \
0596             RTEMS_NO_PRIORITY_CEILING,
0597             0, 
0598             &pDev->devsem);
0599     if ( status != RTEMS_SUCCESSFUL ){
0600         printk("OCCAN[%d]: Failed to create dev semaphore, (%d)\n\r",minor, status);
0601         return RTEMS_UNSATISFIED;
0602     }
0603     status = rtems_semaphore_create(
0604             rtems_build_name('C', 't', 'x', '0'+minor),
0605             0, 
0606             RTEMS_FIFO | RTEMS_SIMPLE_BINARY_SEMAPHORE | RTEMS_NO_INHERIT_PRIORITY | \
0607             RTEMS_NO_PRIORITY_CEILING,
0608                         0, 
0609             &pDev->txsem);
0610     if ( status != RTEMS_SUCCESSFUL ){
0611         printk("OCCAN[%d]: Failed to create tx semaphore, (%d)\n\r",minor, status);
0612         return RTEMS_UNSATISFIED;
0613     }
0614     status = rtems_semaphore_create(
0615             rtems_build_name('C', 'r', 'x', '0'+minor),
0616             0, 
0617             RTEMS_FIFO | RTEMS_SIMPLE_BINARY_SEMAPHORE | RTEMS_NO_INHERIT_PRIORITY | \
0618             RTEMS_NO_PRIORITY_CEILING,
0619             0,
0620             &pDev->rxsem);
0621     if ( status != RTEMS_SUCCESSFUL ){
0622         printk("OCCAN[%d]: Failed to create rx semaphore, (%d)\n\r",minor, status);
0623         return RTEMS_UNSATISFIED;
0624     }
0625 
0626     /* hardware init/reset */
0627     pelican_init(pDev);
0628 
0629 #ifdef DEBUG_PRINT_REGMAP
0630     pelican_regadr_print(pDev->regs);
0631 #endif
0632 
0633     return 0;
0634 }
0635 
0636 
0637 #ifdef DEBUG
0638 static void pelican_regs_print(occan_priv *pDev){
0639     pelican_regs *regs = pDev->regs;
0640     printk("--- PELICAN 0x%lx ---\n\r",(unsigned int)regs);
0641     printk(" MODE: 0x%02x\n\r",READ_REG(pDev, &regs->mode));
0642     printk(" CMD: 0x%02x\n\r",READ_REG(pDev, &regs->cmd));
0643     printk(" STATUS: 0x%02x\n\r",READ_REG(pDev, &regs->status));
0644     /*printk(" INTFLG: 0x%02x\n\r",READ_REG(pDev, &regs->intflags));*/
0645     printk(" INTEN: 0x%02x\n\r",READ_REG(pDev, &regs->inten));
0646     printk(" BTR0: 0x%02x\n\r",READ_REG(pDev, &regs->bustim0));
0647     printk(" BTR1: 0x%02x\n\r",READ_REG(pDev, &regs->bustim1));
0648     printk(" ARBCODE: 0x%02x\n\r",READ_REG(pDev, &regs->arbcode));
0649     printk(" ERRCODE: 0x%02x\n\r",READ_REG(pDev, &regs->errcode));
0650     printk(" ERRWARN: 0x%02x\n\r",READ_REG(pDev, &regs->errwarn));
0651     printk(" RX_ERR_CNT: 0x%02x\n\r",READ_REG(pDev, &regs->rx_err_cnt));
0652     printk(" TX_ERR_CNT: 0x%02x\n\r",READ_REG(pDev, &regs->tx_err_cnt));
0653     if ( READ_REG(pDev, &regs->mode) & PELICAN_MOD_RESET ){
0654         /* in reset mode it is possible to read acceptance filters */
0655         printk(" ACR0: 0x%02x (0x%lx)\n\r",READ_REG(pDev, &regs->rx_fi_xff),&regs->rx_fi_xff);
0656         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]);
0657         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]);
0658         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]);
0659         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]);
0660         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]);
0661         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]);
0662         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]);
0663         
0664     }else{
0665         printk(" RXFI_XFF: 0x%02x\n\r",READ_REG(pDev, &regs->rx_fi_xff));
0666     }
0667     printk(" RX_MSG_CNT: 0x%02x\n\r",READ_REG(pDev, &regs->rx_msg_cnt));
0668     printk(" CLKDIV: 0x%02x\n\r",READ_REG(pDev, &regs->clkdiv));
0669     printk("-------------------\n\r");
0670 }
0671 #endif
0672 
0673 #ifdef DEBUG_PRINT_REGMAP
0674 static void pelican_regadr_print(pelican_regs *regs){
0675     printk("--- PELICAN 0x%lx ---\n\r",(unsigned int)regs);
0676     printk(" MODE: 0x%lx\n\r",(unsigned int)&regs->mode);
0677     printk(" CMD: 0x%lx\n\r",(unsigned int)&regs->cmd);
0678     printk(" STATUS: 0x%lx\n\r",(unsigned int)&regs->status);
0679     /*printk(" INTFLG: 0x%lx\n\r",&regs->intflags);*/
0680     printk(" INTEN: 0x%lx\n\r",(unsigned int)&regs->inten);
0681     printk(" BTR0: 0x%lx\n\r",(unsigned int)&regs->bustim0);
0682     printk(" BTR1: 0x%lx\n\r",(unsigned int)&regs->bustim1);
0683     printk(" ARBCODE: 0x%lx\n\r",(unsigned int)&regs->arbcode);
0684     printk(" ERRCODE: 0x%lx\n\r",(unsigned int)&regs->errcode);
0685     printk(" ERRWARN: 0x%lx\n\r",(unsigned int)&regs->errwarn);
0686     printk(" RX_ERR_CNT: 0x%lx\n\r",(unsigned int)&regs->rx_err_cnt);
0687     printk(" TX_ERR_CNT: 0x%lx\n\r",(unsigned int)&regs->tx_err_cnt);
0688 
0689     /* in reset mode it is possible to read acceptance filters */
0690     printk(" RXFI_XFF: 0x%lx\n\r",(unsigned int)&regs->rx_fi_xff);
0691     
0692     /* reset registers */
0693     printk(" ACR0: 0x%lx\n\r",(unsigned int)&regs->rx_fi_xff);
0694     printk(" ACR1: 0x%lx\n\r",(unsigned int)&regs->msg.rst_accept.code[0]);
0695     printk(" ACR2: 0x%lx\n\r",(unsigned int)&regs->msg.rst_accept.code[1]);
0696     printk(" ACR3: 0x%lx\n\r",(unsigned int)&regs->msg.rst_accept.code[2]);
0697     printk(" AMR0: 0x%lx\n\r",(unsigned int)&regs->msg.rst_accept.mask[0]);
0698     printk(" AMR1: 0x%lx\n\r",(unsigned int)&regs->msg.rst_accept.mask[1]);
0699     printk(" AMR2: 0x%lx\n\r",(unsigned int)&regs->msg.rst_accept.mask[2]);
0700     printk(" AMR3: 0x%lx\n\r",(unsigned int)&regs->msg.rst_accept.mask[3]);
0701     
0702     /* TX Extended */
0703     printk(" EFFTX_ID[0]: 0x%lx\n\r",(unsigned int)&regs->msg.tx_eff.id[0]);
0704     printk(" EFFTX_ID[1]: 0x%lx\n\r",(unsigned int)&regs->msg.tx_eff.id[1]);
0705     printk(" EFFTX_ID[2]: 0x%lx\n\r",(unsigned int)&regs->msg.tx_eff.id[2]);
0706     printk(" EFFTX_ID[3]: 0x%lx\n\r",(unsigned int)&regs->msg.tx_eff.id[3]);
0707 
0708     printk(" EFFTX_DATA[0]: 0x%lx\n\r",(unsigned int)&regs->msg.tx_eff.data[0]);
0709     printk(" EFFTX_DATA[1]: 0x%lx\n\r",(unsigned int)&regs->msg.tx_eff.data[1]);
0710     printk(" EFFTX_DATA[2]: 0x%lx\n\r",(unsigned int)&regs->msg.tx_eff.data[2]);    
0711     printk(" EFFTX_DATA[3]: 0x%lx\n\r",(unsigned int)&regs->msg.tx_eff.data[3]);    
0712     printk(" EFFTX_DATA[4]: 0x%lx\n\r",(unsigned int)&regs->msg.tx_eff.data[4]);    
0713     printk(" EFFTX_DATA[5]: 0x%lx\n\r",(unsigned int)&regs->msg.tx_eff.data[5]);    
0714     printk(" EFFTX_DATA[6]: 0x%lx\n\r",(unsigned int)&regs->msg.tx_eff.data[6]);    
0715     printk(" EFFTX_DATA[7]: 0x%lx\n\r",(unsigned int)&regs->msg.tx_eff.data[7]);    
0716 
0717     /* RX Extended */
0718     printk(" EFFRX_ID[0]: 0x%lx\n\r",(unsigned int)&regs->msg.rx_eff.id[0]);
0719     printk(" EFFRX_ID[1]: 0x%lx\n\r",(unsigned int)&regs->msg.rx_eff.id[1]);
0720     printk(" EFFRX_ID[2]: 0x%lx\n\r",(unsigned int)&regs->msg.rx_eff.id[2]);
0721     printk(" EFFRX_ID[3]: 0x%lx\n\r",(unsigned int)&regs->msg.rx_eff.id[3]);
0722 
0723     printk(" EFFRX_DATA[0]: 0x%lx\n\r",(unsigned int)&regs->msg.rx_eff.data[0]);
0724     printk(" EFFRX_DATA[1]: 0x%lx\n\r",(unsigned int)&regs->msg.rx_eff.data[1]);
0725     printk(" EFFRX_DATA[2]: 0x%lx\n\r",(unsigned int)&regs->msg.rx_eff.data[2]);    
0726     printk(" EFFRX_DATA[3]: 0x%lx\n\r",(unsigned int)&regs->msg.rx_eff.data[3]);    
0727     printk(" EFFRX_DATA[4]: 0x%lx\n\r",(unsigned int)&regs->msg.rx_eff.data[4]);    
0728     printk(" EFFRX_DATA[5]: 0x%lx\n\r",(unsigned int)&regs->msg.rx_eff.data[5]);    
0729     printk(" EFFRX_DATA[6]: 0x%lx\n\r",(unsigned int)&regs->msg.rx_eff.data[6]);    
0730     printk(" EFFRX_DATA[7]: 0x%lx\n\r",(unsigned int)&regs->msg.rx_eff.data[7]);    
0731 
0732 
0733     /* RX Extended */
0734     printk(" SFFRX_ID[0]: 0x%lx\n\r",(unsigned int)&regs->msg.rx_sff.id[0]);
0735     printk(" SFFRX_ID[1]: 0x%lx\n\r",(unsigned int)&regs->msg.rx_sff.id[1]);
0736 
0737     printk(" SFFRX_DATA[0]: 0x%lx\n\r",(unsigned int)&regs->msg.rx_sff.data[0]);
0738     printk(" SFFRX_DATA[1]: 0x%lx\n\r",(unsigned int)&regs->msg.rx_sff.data[1]);
0739     printk(" SFFRX_DATA[2]: 0x%lx\n\r",(unsigned int)&regs->msg.rx_sff.data[2]);    
0740     printk(" SFFRX_DATA[3]: 0x%lx\n\r",(unsigned int)&regs->msg.rx_sff.data[3]);    
0741     printk(" SFFRX_DATA[4]: 0x%lx\n\r",(unsigned int)&regs->msg.rx_sff.data[4]);    
0742     printk(" SFFRX_DATA[5]: 0x%lx\n\r",(unsigned int)&regs->msg.rx_sff.data[5]);    
0743     printk(" SFFRX_DATA[6]: 0x%lx\n\r",(unsigned int)&regs->msg.rx_sff.data[6]);    
0744     printk(" SFFRX_DATA[7]: 0x%lx\n\r",(unsigned int)&regs->msg.rx_sff.data[7]);    
0745 
0746     /* TX Extended */
0747     printk(" SFFTX_ID[0]: 0x%lx\n\r",(unsigned int)&regs->msg.tx_sff.id[0]);
0748     printk(" SFFTX_ID[1]: 0x%lx\n\r",(unsigned int)&regs->msg.tx_sff.id[1]);
0749 
0750     printk(" SFFTX_DATA[0]: 0x%lx\n\r",(unsigned int)&regs->msg.tx_sff.data[0]);
0751     printk(" SFFTX_DATA[1]: 0x%lx\n\r",(unsigned int)&regs->msg.tx_sff.data[1]);
0752     printk(" SFFTX_DATA[2]: 0x%lx\n\r",(unsigned int)&regs->msg.tx_sff.data[2]);
0753     printk(" SFFTX_DATA[3]: 0x%lx\n\r",(unsigned int)&regs->msg.tx_sff.data[3]);
0754     printk(" SFFTX_DATA[4]: 0x%lx\n\r",(unsigned int)&regs->msg.tx_sff.data[4]);
0755     printk(" SFFTX_DATA[5]: 0x%lx\n\r",(unsigned int)&regs->msg.tx_sff.data[5]);
0756     printk(" SFFTX_DATA[6]: 0x%lx\n\r",(unsigned int)&regs->msg.tx_sff.data[6]);
0757     printk(" SFFTX_DATA[7]: 0x%lx\n\r",(unsigned int)&regs->msg.tx_sff.data[7]);
0758 
0759     printk(" RX_MSG_CNT: 0x%lx\n\r",(unsigned int)&regs->rx_msg_cnt);
0760     printk(" CLKDIV: 0x%lx\n\r",(unsigned int)&regs->clkdiv);
0761     printk("-------------------\n\r");
0762 }
0763 #endif
0764 
0765 #ifdef DEBUG
0766 static void occan_stat_print(occan_stats *stats){
0767     printk("----Stats----\n\r");
0768     printk("rx_msgs: %d\n\r",stats->rx_msgs);
0769     printk("tx_msgs: %d\n\r",stats->tx_msgs);
0770     printk("err_warn: %d\n\r",stats->err_warn);
0771     printk("err_dovr: %d\n\r",stats->err_dovr);
0772     printk("err_errp: %d\n\r",stats->err_errp);
0773     printk("err_arb: %d\n\r",stats->err_arb);
0774     printk("err_bus: %d\n\r",stats->err_bus);
0775     printk("Int cnt: %d\n\r",stats->ints);
0776     printk("tx_buf_err: %d\n\r",stats->tx_buf_error);
0777     printk("-------------\n\r");
0778 }
0779 #endif
0780 
0781 static void pelican_init(occan_priv *priv){
0782     /* Reset core */
0783     WRITE_REG(priv, &priv->regs->mode, PELICAN_MOD_RESET);
0784 
0785     /* wait for core to reset complete */
0786     /*usleep(1);*/
0787 }
0788 
0789 static void pelican_open(occan_priv *priv){
0790     int ret;
0791     struct grlib_canbtrs_timing timing;
0792 
0793     /* Set defaults */
0794     priv->speed = OCCAN_SPEED_250K;
0795 
0796     /* set acceptance filters to accept all messages */
0797     priv->acode[0] = 0;
0798     priv->acode[1] = 0;
0799     priv->acode[2] = 0;
0800     priv->acode[3] = 0;
0801     priv->amask[0] = 0xff;
0802     priv->amask[1] = 0xff;
0803     priv->amask[2] = 0xff;
0804     priv->amask[3] = 0xff;
0805 
0806     /* Set clock divider to extended mode, clkdiv not connected
0807      */
0808     WRITE_REG(priv, &priv->regs->clkdiv, (1<<PELICAN_CDR_MODE_BITS) | (DEFAULT_CLKDIV & PELICAN_CDR_DIV));
0809 
0810     ret = grlib_canbtrs_calc_timing(
0811             priv->speed, priv->sys_freq_hz,
0812             OCCAN_SAMPLING_POINT, &occan_btrs_ranges,
0813             (struct grlib_canbtrs_timing *)&timing);
0814     if ( ret ) {
0815         /* failed to set speed for this system freq, try with 50K instead */
0816         priv->speed = OCCAN_SPEED_50K;
0817         grlib_canbtrs_calc_timing(
0818             priv->speed, priv->sys_freq_hz,
0819             OCCAN_SAMPLING_POINT, &occan_btrs_ranges,
0820             (struct grlib_canbtrs_timing *)&timing);
0821     }
0822     convert_timing_to_btrs(&timing, &priv->timing);
0823 
0824     /* disable all interrupts */
0825     WRITE_REG(priv, &priv->regs->inten, 0);
0826 
0827     /* clear pending interrupts by reading */
0828     READ_REG(priv, &priv->regs->intflags);
0829 }
0830 
0831 static int pelican_start(occan_priv *priv){
0832     /* Start HW communication */
0833 
0834     if ( !priv->rxfifo || !priv->txfifo )
0835         return -1;
0836 
0837     /* In case we were started before and stopped we
0838      * should empty the TX fifo or try to resend those
0839      * messages. We make it simple...
0840      */
0841     occan_fifo_clr(priv->txfifo);
0842 
0843     /* Clear status bits */
0844     priv->status = 0;
0845     priv->sending = 0;
0846 
0847     /* clear pending interrupts */
0848     READ_REG(priv, &priv->regs->intflags);
0849 
0850     /* clear error counters */
0851     WRITE_REG(priv, &priv->regs->rx_err_cnt, 0);
0852     WRITE_REG(priv, &priv->regs->tx_err_cnt, 0);
0853 
0854 #ifdef REDUNDANT_CHANNELS
0855     if ( (priv->channel == 0) || (priv->channel >= REDUNDANT_CHANNELS) ){
0856         /* Select the first (default) channel */
0857         OCCAN_SET_CHANNEL(priv,0);
0858     }else{
0859         /* set gpio bit, or something */
0860         OCCAN_SET_CHANNEL(priv,priv->channel);
0861     }
0862 #endif
0863     /* set the speed regs of the CAN core */
0864     occan_set_speedregs(priv,&priv->timing);
0865 
0866     DBG("OCCAN: start: set timing regs btr0: 0x%x, btr1: 0x%x\n\r",
0867         READ_REG(priv, &priv->regs->bustim0),
0868         READ_REG(priv, &priv->regs->bustim1));
0869 
0870     /* Set default acceptance filter */
0871     pelican_set_accept(priv,priv->acode,priv->amask);
0872 
0873     /* Nothing can fail from here, this must be set before interrupts are
0874      * enabled */
0875     priv->started = 1;
0876 
0877     /* turn on interrupts */
0878     WRITE_REG(priv, &priv->regs->inten,
0879         PELICAN_IE_RX | PELICAN_IE_TX | PELICAN_IE_ERRW |
0880         PELICAN_IE_ERRP | PELICAN_IE_BUS);
0881 #ifdef DEBUG
0882     /* print setup before starting */
0883     pelican_regs_print(priv->regs);
0884     occan_stat_print(&priv->stats);
0885 #endif
0886 
0887     /* core already in reset mode,
0888      *  * Exit reset mode
0889      *  * Enter Single/Dual mode filtering.
0890      */
0891     WRITE_REG(priv, &priv->regs->mode, (priv->single_mode << 3));
0892 
0893     /* Register interrupt routine and unmask IRQ at IRQ controller */
0894     drvmgr_interrupt_register(priv->dev, 0, "occan", occan_interrupt, priv);
0895 
0896     return 0;
0897 }
0898 
0899 static void pelican_stop(occan_priv *priv)
0900 {
0901     /* stop HW */
0902 
0903     drvmgr_interrupt_unregister(priv->dev, 0, occan_interrupt, priv);
0904 
0905 #ifdef DEBUG
0906     /* print setup before stopping */
0907     pelican_regs_print(priv->regs);
0908     occan_stat_print(&priv->stats);
0909 #endif
0910 
0911     /* put core in reset mode */
0912     WRITE_REG(priv, &priv->regs->mode, PELICAN_MOD_RESET);
0913 
0914     /* turn off interrupts */
0915     WRITE_REG(priv, &priv->regs->inten, 0);
0916 
0917     priv->status |= OCCAN_STATUS_RESET;
0918 }
0919 
0920 static inline int pelican_tx_ready(occan_priv *can)
0921 {
0922     unsigned char status;
0923     pelican_regs *regs = can->regs;
0924 
0925     /* is there room in send buffer? */
0926     status = READ_REG(can, &regs->status);
0927     if ( !(status & PELICAN_STAT_TXBUF) ) {
0928         /* tx fifo taken, we have to wait */
0929         return 0;
0930     }
0931 
0932     return 1;
0933 }
0934 
0935 /* Try to send message "msg", if hardware txfifo is
0936  * full, then -1 is returned.
0937  *
0938  * Be sure to have disabled CAN interrupts when
0939  * entering this function.
0940  */
0941 static int pelican_send(occan_priv *can, CANMsg *msg){
0942     unsigned char tmp;
0943     pelican_regs *regs = can->regs;
0944 
0945     /* is there room in send buffer? */
0946     if ( !pelican_tx_ready(can) ) {
0947         /* tx fifo taken, we have to wait */
0948         return -1;
0949     }
0950 
0951     tmp = msg->len & 0xf;
0952     if ( msg->rtr )
0953         tmp |= 0x40;
0954 
0955     if ( msg->extended ){
0956         /* Extended Frame */
0957         WRITE_REG(can, &regs->rx_fi_xff, 0x80 | tmp);
0958         WRITE_REG(can, &regs->msg.tx_eff.id[0],(msg->id >> (5+8+8)) & 0xff);
0959         WRITE_REG(can, &regs->msg.tx_eff.id[1],(msg->id >> (5+8)) & 0xff);
0960         WRITE_REG(can, &regs->msg.tx_eff.id[2],(msg->id >> (5)) & 0xff);
0961         WRITE_REG(can, &regs->msg.tx_eff.id[3],(msg->id << 3) & 0xf8);
0962         tmp = msg->len;
0963         while(tmp--){
0964             WRITE_REG(can, &regs->msg.tx_eff.data[tmp], msg->data[tmp]);
0965         }
0966     }else{
0967         /* Standard Frame */
0968         WRITE_REG(can, &regs->rx_fi_xff, tmp);
0969         WRITE_REG(can, &regs->msg.tx_sff.id[0],(msg->id >> 3) & 0xff);
0970         WRITE_REG(can, &regs->msg.tx_sff.id[1],(msg->id << 5) & 0xe0);
0971         tmp = msg->len;
0972         while(tmp--){
0973             WRITE_REG(can, &regs->msg.tx_sff.data[tmp],msg->data[tmp]);
0974         }
0975     }
0976 
0977     /* let HW know of new message */
0978     if ( msg->sshot ){
0979         WRITE_REG(can, &regs->cmd, PELICAN_CMD_TXREQ | PELICAN_CMD_ABORT);
0980     }else{
0981         /* normal case -- try resend until sent */
0982         WRITE_REG(can, &regs->cmd, PELICAN_CMD_TXREQ);
0983     }
0984 
0985     return 0;
0986 }
0987 
0988 
0989 static void pelican_set_accept(occan_priv *priv, unsigned char *acode, unsigned char *amask)
0990 {
0991     unsigned char *acode0, *acode1, *acode2, *acode3;
0992     unsigned char *amask0, *amask1, *amask2, *amask3;
0993 
0994     acode0 = &priv->regs->rx_fi_xff;
0995     acode1 = (unsigned char *)&priv->regs->msg.rst_accept.code[0];
0996     acode2 = (unsigned char *)&priv->regs->msg.rst_accept.code[1];
0997     acode3 = (unsigned char *)&priv->regs->msg.rst_accept.code[2];
0998 
0999     amask0 = (unsigned char *)&priv->regs->msg.rst_accept.mask[0];
1000     amask1 = (unsigned char *)&priv->regs->msg.rst_accept.mask[1];
1001     amask2 = (unsigned char *)&priv->regs->msg.rst_accept.mask[2];
1002     amask3 = (unsigned char *)&priv->regs->msg.rst_accept.mask[3];
1003 
1004     /* Set new mask & code */
1005     WRITE_REG(priv, acode0, acode[0]);
1006     WRITE_REG(priv, acode1, acode[1]);
1007     WRITE_REG(priv, acode2, acode[2]);
1008     WRITE_REG(priv, acode3, acode[3]);
1009 
1010     WRITE_REG(priv, amask0, amask[0]);
1011     WRITE_REG(priv, amask1, amask[1]);
1012     WRITE_REG(priv, amask2, amask[2]);
1013     WRITE_REG(priv, amask3, amask[3]);
1014 }
1015 
1016 static void convert_timing_to_btrs(
1017     struct grlib_canbtrs_timing *t,
1018     occan_speed_regs *btrs)
1019 {
1020     btrs->btr0 = (t->rsj << OCCAN_BUSTIM_SJW_BIT) |
1021                  (t->scaler & OCCAN_BUSTIM_BRP);
1022     btrs->btr1 = (0<<7) | (t->ps2 << OCCAN_BUSTIM_TSEG2_BIT) | t->ps1;
1023 }
1024 
1025 static int occan_set_speedregs(occan_priv *priv, occan_speed_regs *timing)
1026 {
1027     if ( !timing || !priv || !priv->regs)
1028         return -1;
1029 
1030     WRITE_REG(priv, &priv->regs->bustim0, timing->btr0);
1031     WRITE_REG(priv, &priv->regs->bustim1, timing->btr1);
1032 
1033     return 0;
1034 }
1035 
1036 static rtems_device_driver occan_initialize(rtems_device_major_number major, rtems_device_minor_number unused, void *arg)
1037 {
1038     return RTEMS_SUCCESSFUL;
1039 }
1040 
1041 static rtems_device_driver occan_open(rtems_device_major_number major, rtems_device_minor_number minor, void *arg)
1042 {
1043     occan_priv *can;
1044     struct drvmgr_dev *dev;
1045 
1046     DBG("OCCAN: Opening %d\n\r",minor);
1047 
1048     /* get can device */    
1049     if ( drvmgr_get_dev(&occan_drv_info.general, minor, &dev) ) {
1050         DBG("Wrong minor %d\n", minor);
1051         return RTEMS_UNSATISFIED; /* NODEV */
1052     }
1053     can = (occan_priv *)dev->priv;
1054 
1055     /* already opened? */
1056     rtems_semaphore_obtain(can->devsem, RTEMS_WAIT, RTEMS_NO_TIMEOUT);
1057     if ( can->open ){
1058         rtems_semaphore_release(can->devsem);
1059         return RTEMS_RESOURCE_IN_USE; /* EBUSY */
1060     }
1061     can->open = 1;
1062     rtems_semaphore_release(can->devsem);
1063 
1064     SPIN_INIT(&can->devlock, can->devName);
1065 
1066     /* allocate fifos */
1067     can->rxfifo = occan_fifo_create(DEFAULT_RX_FIFO_LEN);
1068     if ( !can->rxfifo ){
1069         can->open = 0;
1070         return RTEMS_NO_MEMORY; /* ENOMEM */
1071     }
1072 
1073     can->txfifo = occan_fifo_create(DEFAULT_TX_FIFO_LEN);
1074     if ( !can->txfifo ){
1075         occan_fifo_free(can->rxfifo);
1076         can->rxfifo= NULL;
1077         can->open = 0;
1078         return RTEMS_NO_MEMORY; /* ENOMEM */
1079     }
1080 
1081     DBG("OCCAN: Opening %d success\n\r",minor);
1082 
1083     can->started = 0;
1084     can->channel = 0; /* Default to first can link */
1085     can->txblk = 1; /* Default to Blocking mode */
1086     can->rxblk = 1; /* Default to Blocking mode */
1087     can->single_mode = 1; /* single mode acceptance filter */
1088 
1089     /* reset stat counters */
1090     memset(&can->stats,0,sizeof(occan_stats));
1091 
1092     /* HW must be in reset mode here (close and initializes resets core...)
1093      *
1094      * 1. set default modes/speeds
1095      */
1096     pelican_open(can);
1097 
1098     return RTEMS_SUCCESSFUL;
1099 }
1100 
1101 static rtems_device_driver occan_close(rtems_device_major_number major, rtems_device_minor_number minor, void *arg)
1102 {
1103     occan_priv *can;
1104     struct drvmgr_dev *dev;
1105 
1106     DBG("OCCAN: Closing %d\n\r",minor);
1107 
1108     if ( drvmgr_get_dev(&occan_drv_info.general, minor, &dev) ) {
1109         return RTEMS_INVALID_NAME;
1110     }
1111     can = (occan_priv *)dev->priv;
1112 
1113     /* stop if running */
1114     if ( can->started )
1115         pelican_stop(can);
1116 
1117     /* Enter Reset Mode */
1118     WRITE_REG(can, &can->regs->mode, PELICAN_MOD_RESET);
1119 
1120     /* free fifo memory */
1121     occan_fifo_free(can->rxfifo);
1122     occan_fifo_free(can->txfifo);
1123 
1124     can->rxfifo = NULL;
1125     can->txfifo = NULL;
1126 
1127     can->open = 0;
1128 
1129     return RTEMS_SUCCESSFUL;
1130 }
1131 
1132 static rtems_device_driver occan_read(rtems_device_major_number major, rtems_device_minor_number minor, void *arg)
1133 {
1134     occan_priv *can;
1135     struct drvmgr_dev *dev;
1136     rtems_libio_rw_args_t *rw_args=(rtems_libio_rw_args_t *) arg;
1137     CANMsg *dstmsg, *srcmsg;
1138     SPIN_IRQFLAGS(oldLevel);
1139     int left;
1140 
1141     if ( drvmgr_get_dev(&occan_drv_info.general, minor, &dev) ) {
1142         return RTEMS_INVALID_NAME;
1143     }
1144     can = (occan_priv *)dev->priv;
1145 
1146     if ( !can->started ){
1147         DBG("OCCAN: cannot read from minor %d when not started\n\r",minor);
1148         return RTEMS_RESOURCE_IN_USE; /* -EBUSY*/
1149     }
1150 
1151     /* does at least one message fit */
1152     left = rw_args->count;
1153     if ( left < sizeof(CANMsg) ){
1154         DBG("OCCAN: minor %d length of buffer must be at least %d, our is %d\n\r",minor,sizeof(CANMsg),left);
1155         return  RTEMS_INVALID_NAME; /* -EINVAL */
1156     }
1157 
1158     /* get pointer to start where to put CAN messages */
1159     dstmsg = (CANMsg *)rw_args->buffer;
1160     if ( !dstmsg ){
1161         DBG("OCCAN: minor %d read: input buffer is NULL\n\r",minor);
1162         return  RTEMS_INVALID_NAME; /* -EINVAL */
1163     }
1164 
1165     while (left >= sizeof(CANMsg) ){
1166 
1167         /* turn off interrupts */
1168         SPIN_LOCK_IRQ(&can->devlock, oldLevel);
1169 
1170         /* A bus off interrupt may have occured after checking can->started */
1171         if ( can->status & (OCCAN_STATUS_ERR_BUSOFF|OCCAN_STATUS_RESET) ){
1172             SPIN_UNLOCK_IRQ(&can->devlock, oldLevel);
1173             DBG("OCCAN: read is cancelled due to a BUS OFF error\n\r");
1174             rw_args->bytes_moved = rw_args->count-left;
1175             return RTEMS_IO_ERROR; /* EIO */
1176         }
1177 
1178         srcmsg = occan_fifo_claim_get(can->rxfifo);
1179         if ( !srcmsg ){
1180             /* no more messages in reception fifo.
1181              * Wait for incoming packets only if in
1182              * blocking mode AND no messages been
1183              * read before.
1184              */
1185             if ( !can->rxblk || (left != rw_args->count) ){
1186                 /* turn on interrupts again */
1187                 SPIN_UNLOCK_IRQ(&can->devlock, oldLevel);
1188                 break;
1189             }
1190 
1191             /* turn on interrupts again */
1192             SPIN_UNLOCK_IRQ(&can->devlock, oldLevel);
1193 
1194             DBG("OCCAN: Waiting for RX int\n\r");
1195 
1196             /* wait for incoming messages */
1197             rtems_semaphore_obtain(can->rxsem, RTEMS_WAIT,
1198                 RTEMS_NO_TIMEOUT);
1199 
1200             /* did we get woken up by a BUS OFF error? */
1201             if ( can->status & (OCCAN_STATUS_ERR_BUSOFF|OCCAN_STATUS_RESET) ){
1202                 DBG("OCCAN: Blocking read got woken up by BUS OFF error\n\r");
1203                 /* At this point it should not matter how many messages we handled */
1204                 rw_args->bytes_moved = rw_args->count-left;
1205                 return RTEMS_IO_ERROR; /* EIO */
1206             }
1207 
1208             /* no errors detected, it must be a message */
1209             continue;
1210         }
1211 
1212         /* got message, copy it to userspace buffer */
1213         *dstmsg = *srcmsg;
1214 
1215         /* Return borrowed message, RX interrupt can use it again */
1216         occan_fifo_get(can->rxfifo);
1217 
1218         /* turn on interrupts again */
1219         SPIN_UNLOCK_IRQ(&can->devlock, oldLevel);
1220 
1221         /* increase pointers */
1222         left -= sizeof(CANMsg);
1223         dstmsg++;
1224     }
1225 
1226     /* save number of read bytes. */
1227     rw_args->bytes_moved = rw_args->count-left;
1228     if ( rw_args->bytes_moved == 0 ){
1229         DBG("OCCAN: minor %d read would block, returning\n\r",minor);
1230         return RTEMS_TIMEOUT; /* ETIMEDOUT should be EAGAIN/EWOULDBLOCK */
1231     }
1232     return RTEMS_SUCCESSFUL;
1233 }
1234 
1235 static rtems_device_driver occan_write(rtems_device_major_number major, rtems_device_minor_number minor, void *arg)
1236 {
1237     occan_priv *can;
1238     struct drvmgr_dev *dev;
1239     rtems_libio_rw_args_t *rw_args=(rtems_libio_rw_args_t *) arg;
1240     CANMsg *msg,*fifo_msg;
1241     SPIN_IRQFLAGS(oldLevel);
1242     int left;
1243 
1244     DBG("OCCAN: Writing %d bytes from 0x%lx (%d)\n\r",rw_args->count,rw_args->buffer,sizeof(CANMsg));
1245 
1246     if ( drvmgr_get_dev(&occan_drv_info.general, minor, &dev) ) {
1247         return RTEMS_INVALID_NAME;
1248     }
1249     can = (occan_priv *)dev->priv;
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     SPIN_LOCK_IRQ(&can->devlock, 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         SPIN_UNLOCK_IRQ(&can->devlock, 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 #ifdef OCCAN_TX_IRQ_FLAG_FIXUP
1293             /* Mark that we have put at least one msg in TX FIFO */
1294             can->sending = 1;
1295 #endif
1296 
1297             /* bump stat counters */
1298             can->stats.tx_msgs++;
1299 
1300             DBG("OCCAN: Sending direct via HW\n\r");
1301         }
1302     }
1303 
1304     /* Put messages into software fifo */
1305     while ( left >= sizeof(CANMsg) ){
1306 
1307         /* limit CAN message length to 8 */
1308         msg->len = (msg->len > 8) ? 8 : msg->len;
1309 
1310         fifo_msg = occan_fifo_put_claim(can->txfifo,0);
1311         if ( !fifo_msg ){
1312 
1313             DBG("OCCAN: FIFO is full\n\r");
1314             /* Block only if no messages previously sent
1315              * and no in blocking mode
1316              */
1317             if ( !can->txblk  || (left != rw_args->count) )
1318                 break;
1319 
1320             /* turn on interupts again and wait
1321                 INT_ON
1322                 WAIT FOR FREE BUF;
1323                 INT_OFF;
1324                 CHECK_IF_FIFO_EMPTY ==> SEND DIRECT VIA HW;
1325             */
1326             SPIN_UNLOCK_IRQ(&can->devlock, oldLevel);
1327 
1328             DBG("OCCAN: Waiting for tx int\n\r");
1329 
1330             rtems_semaphore_obtain(can->txsem, RTEMS_WAIT, RTEMS_NO_TIMEOUT);
1331 
1332             /* did we get woken up by a BUS OFF error? */
1333             if ( can->status & (OCCAN_STATUS_ERR_BUSOFF|OCCAN_STATUS_RESET) ){
1334                 DBG("OCCAN: Blocking write got woken up by BUS OFF error or RESET event\n\r");
1335                 /* At this point it should not matter how many messages we handled */
1336                 rw_args->bytes_moved = rw_args->count-left;
1337                 return RTEMS_IO_ERROR; /* EIO */
1338             }
1339 
1340             SPIN_LOCK_IRQ(&can->devlock, oldLevel);
1341 
1342             if ( occan_fifo_empty(can->txfifo) ){
1343                 if ( !pelican_send(can,msg) ) {
1344                     /* First message put directly into HW TX fifo
1345                      * This will turn TX interrupt on.
1346                      */
1347                     left -= sizeof(CANMsg);
1348                     msg++;
1349 
1350 #ifdef OCCAN_TX_IRQ_FLAG_FIXUP
1351                     /* Mark that we have put at least one msg in TX FIFO */
1352                     can->sending = 1;
1353 #endif
1354 
1355                     /* bump stat counters */
1356                     can->stats.tx_msgs++;
1357 
1358                     DBG("OCCAN: Sending direct2 via HW\n\r");
1359                 }
1360             }
1361             continue;
1362         }
1363 
1364         /* copy message into fifo area */
1365         *fifo_msg = *msg;
1366 
1367         /* tell interrupt handler about the message */
1368         occan_fifo_put(can->txfifo);
1369 
1370         DBG("OCCAN: Put info fifo SW\n\r");
1371 
1372         /* Prepare insert of next message */
1373         msg++;
1374         left-=sizeof(CANMsg);
1375     }
1376 
1377     SPIN_UNLOCK_IRQ(&can->devlock, oldLevel);
1378 
1379     rw_args->bytes_moved = rw_args->count-left;
1380     DBG("OCCAN: Sent %d\n\r",rw_args->bytes_moved);
1381 
1382     if ( left == rw_args->count )
1383         return RTEMS_TIMEOUT; /* ETIMEDOUT should be EAGAIN/EWOULDBLOCK */
1384     return RTEMS_SUCCESSFUL;
1385 }
1386 
1387 static rtems_device_driver occan_ioctl(rtems_device_major_number major, rtems_device_minor_number minor, void *arg)
1388 {
1389     int ret;
1390     struct grlib_canbtrs_timing timing;
1391     occan_priv *can;
1392     struct drvmgr_dev *dev;
1393     unsigned int speed;
1394     rtems_libio_ioctl_args_t *ioarg = (rtems_libio_ioctl_args_t *) arg;
1395     struct occan_afilter *afilter;
1396     occan_stats *dststats;
1397     unsigned int rxcnt,txcnt;
1398 
1399     DBG("OCCAN: IOCTL %d\n\r",ioarg->command);
1400 
1401     if ( drvmgr_get_dev(&occan_drv_info.general, minor, &dev) ) {
1402         return RTEMS_INVALID_NAME;
1403     }
1404     can = (occan_priv *)dev->priv;
1405 
1406     ioarg->ioctl_return = 0;
1407     switch(ioarg->command){
1408         case OCCAN_IOC_SET_SPEED:
1409 
1410             /* cannot change speed during run mode */
1411             if ( can->started )
1412                 return RTEMS_RESOURCE_IN_USE; /* EBUSY */
1413 
1414             /* get speed rate from argument */
1415             speed = (unsigned int)ioarg->buffer;
1416             /* Calculate default timing register values */
1417             ret = grlib_canbtrs_calc_timing(
1418                 speed, can->sys_freq_hz,
1419                 OCCAN_SAMPLING_POINT, &occan_btrs_ranges,
1420                 (struct grlib_canbtrs_timing *)&timing);
1421             if ( ret )
1422                 return  RTEMS_INVALID_NAME; /* EINVAL */
1423 
1424             /* set the speed regs of the CAN core */
1425             /* occan_set_speedregs(can,timing); */
1426 
1427             /* save timing/speed */
1428             can->speed = speed;
1429             convert_timing_to_btrs(&timing, &can->timing);
1430             break;
1431 
1432         case OCCAN_IOC_SET_BTRS:
1433             /* Set BTR registers manually
1434              * Read OCCAN Manual.
1435              */
1436             if ( can->started )
1437                 return RTEMS_RESOURCE_IN_USE; /* EBUSY */
1438 
1439             can->speed = 0; /* custom */
1440             can->timing.btr1 = (unsigned int)ioarg->buffer & 0xff;
1441             can->timing.btr0 = ((unsigned int)ioarg->buffer>>8) & 0xff;
1442 /*
1443             can->timing.sjw = (btr0 >> OCCAN_BUSTIM_SJW_BIT) & 0x3;
1444             can->timing.brp = btr0 & OCCAN_BUSTIM_BRP;
1445             can->timing.tseg1 = btr1 & 0xf;
1446             can->timing.tseg2 = (btr1 >> OCCAN_BUSTIM_TSEG2_BIT) & 0x7;
1447             can->timing.sam = (btr1 >> 7) & 0x1;
1448             */
1449             break;
1450 
1451         case OCCAN_IOC_SPEED_AUTO:
1452             return RTEMS_NOT_IMPLEMENTED;
1453 
1454         case OCCAN_IOC_SET_BUFLEN:
1455             /* set rx & tx fifo buffer length */
1456             if ( can->started )
1457                 return RTEMS_RESOURCE_IN_USE; /* EBUSY */
1458 
1459             rxcnt = (unsigned int)ioarg->buffer & 0x0000ffff;
1460             txcnt = (unsigned int)ioarg->buffer >> 16;
1461 
1462             occan_fifo_free(can->rxfifo);
1463             occan_fifo_free(can->txfifo);
1464 
1465             /* allocate new buffers */
1466             can->rxfifo = occan_fifo_create(rxcnt);
1467             can->txfifo = occan_fifo_create(txcnt);
1468 
1469             if ( !can->rxfifo || !can->txfifo )
1470                 return RTEMS_NO_MEMORY; /* ENOMEM */
1471             break;
1472 
1473         case OCCAN_IOC_GET_CONF:
1474             return RTEMS_NOT_IMPLEMENTED;
1475             break;
1476 
1477         case OCCAN_IOC_GET_STATS:
1478             dststats = (occan_stats *)ioarg->buffer;
1479             if ( !dststats )
1480                 return  RTEMS_INVALID_NAME; /* EINVAL */
1481 
1482             /* copy data stats into userspace buffer */
1483             if ( can->rxfifo )
1484                 can->stats.rx_sw_dovr = can->rxfifo->ovcnt;
1485             *dststats = can->stats;
1486             break;
1487 
1488         case OCCAN_IOC_GET_STATUS:
1489             /* return the status of the */
1490             if ( !ioarg->buffer )
1491                 return RTEMS_INVALID_NAME;
1492 
1493             *(unsigned int *)ioarg->buffer = can->status;
1494             break;
1495 
1496         /* Set physical link */
1497         case OCCAN_IOC_SET_LINK:
1498 #ifdef REDUNDANT_CHANNELS
1499             if ( can->started )
1500                 return RTEMS_RESOURCE_IN_USE; /* EBUSY */
1501 
1502             /* switch HW channel */
1503             can->channel = (unsigned int)ioargs->buffer;
1504 #else
1505             return RTEMS_NOT_IMPLEMENTED;
1506 #endif
1507             break;
1508 
1509         case OCCAN_IOC_SET_FILTER:
1510             if ( can->started )
1511                 return RTEMS_RESOURCE_IN_USE; /* EBUSY */
1512 
1513             afilter = (struct occan_afilter *)ioarg->buffer;
1514 
1515             if ( !afilter )
1516                 return RTEMS_INVALID_NAME; /* EINVAL */
1517 
1518             /* copy acceptance filter */
1519             can->acode[0] = afilter->code[0];
1520             can->acode[1] = afilter->code[1];
1521             can->acode[2] = afilter->code[2];
1522             can->acode[3] = afilter->code[3];
1523 
1524             can->amask[0] = afilter->mask[0];
1525             can->amask[1] = afilter->mask[1];
1526             can->amask[2] = afilter->mask[2];
1527             can->amask[3] = afilter->mask[3];
1528 
1529             can->single_mode = ( afilter->single_mode ) ? 1 : 0;
1530 
1531             /* Acceptance filter is written to hardware
1532              * when starting.
1533              */
1534             /* pelican_set_accept(can,can->acode,can->amask);*/
1535             break;
1536 
1537         case OCCAN_IOC_SET_BLK_MODE:
1538             can->rxblk = (unsigned int)ioarg->buffer & OCCAN_BLK_MODE_RX;
1539             can->txblk = ((unsigned int)ioarg->buffer & OCCAN_BLK_MODE_TX) >> 1;
1540             break;
1541 
1542         case OCCAN_IOC_START:
1543             if ( can->started )
1544                 return RTEMS_RESOURCE_IN_USE; /* EBUSY */
1545             if ( pelican_start(can) )
1546                 return RTEMS_NO_MEMORY; /* failed because of no memory, can happen if SET_BUFLEN failed */
1547             /* can->started = 1; -- Is set in pelican_start due to interrupt may occur before we 
1548              * get here.
1549              */
1550             break;
1551 
1552         case OCCAN_IOC_STOP:
1553             if ( !can->started )
1554                 return RTEMS_RESOURCE_IN_USE; /* EBUSY */
1555             pelican_stop(can);
1556             can->started = 0;
1557             break;
1558 
1559         default:
1560             return RTEMS_NOT_DEFINED;
1561     }
1562     return RTEMS_SUCCESSFUL;
1563 }
1564 
1565 void occan_interrupt(void *arg)
1566 {
1567     occan_priv *can = arg;
1568     unsigned char iflags;
1569     pelican_regs *regs = can->regs;
1570     CANMsg *msg;
1571     int signal_rx=0, signal_tx=0;
1572     unsigned char tmp, errcode, arbcode;
1573     int tx_error_cnt,rx_error_cnt;
1574     SPIN_ISR_IRQFLAGS(irqflags);
1575 
1576     if ( !can->started )
1577         return; /* Spurious Interrupt, do nothing */
1578 
1579     SPIN_LOCK(&can->devlock, irqflags);
1580     while (1) {
1581 
1582         iflags = READ_REG(can, &can->regs->intflags);
1583 
1584 #ifdef OCCAN_TX_IRQ_FLAG_FIXUP
1585         /* TX IRQ may be cleared when reading regs->intflags due
1586          * to a bug in some chips. Instead of looking at the TX_IRQ_FLAG
1587          * the TX-fifo emoty register is looked at when something has
1588          * been scheduled for transmission.
1589          */
1590         if ((iflags & PELICAN_IF_TX) == 0) {
1591             if (can->sending && pelican_tx_ready(can)) {
1592                 can->sending = 0;
1593                 iflags |= PELICAN_IF_TX;
1594             }
1595         }
1596 #endif
1597 
1598         if (iflags == 0)
1599             break;
1600         /* still interrupts to handle */
1601 
1602         can->stats.ints++;
1603 
1604         if ( iflags & PELICAN_IF_RX ){
1605             /* the rx fifo is not empty
1606              * put 1 message into rxfifo for later use
1607              */
1608 
1609             /* get empty (or make room) message */
1610             msg = occan_fifo_put_claim(can->rxfifo,1);
1611             tmp = READ_REG(can, &regs->rx_fi_xff);
1612             msg->extended = tmp >> 7;
1613             msg->rtr = (tmp >> 6) & 1;
1614             msg->len = tmp = tmp & 0x0f;
1615 
1616             if ( msg->extended ){
1617                 /* extended message */
1618                 msg->id =  READ_REG(can, &regs->msg.rx_eff.id[0])<<(5+8+8) |
1619                            READ_REG(can, &regs->msg.rx_eff.id[1])<<(5+8) |
1620                            READ_REG(can, &regs->msg.rx_eff.id[2])<<5 |
1621                            READ_REG(can, &regs->msg.rx_eff.id[3])>>3;
1622 
1623                 while(tmp--){
1624                     msg->data[tmp] = READ_REG(can, &regs->msg.rx_eff.data[tmp]);
1625                 }
1626                 /*
1627                 msg->data[0] = READ_REG(can, &regs->msg.rx_eff.data[0]);
1628                 msg->data[1] = READ_REG(can, &regs->msg.rx_eff.data[1]);
1629                 msg->data[2] = READ_REG(can, &regs->msg.rx_eff.data[2]);
1630                 msg->data[3] = READ_REG(can, &regs->msg.rx_eff.data[3]);
1631                 msg->data[4] = READ_REG(can, &regs->msg.rx_eff.data[4]);
1632                 msg->data[5] = READ_REG(can, &regs->msg.rx_eff.data[5]);
1633                 msg->data[6] = READ_REG(can, &regs->msg.rx_eff.data[6]);
1634                 msg->data[7] = READ_REG(can, &regs->msg.rx_eff.data[7]);
1635                 */
1636             }else{
1637                 /* standard message */
1638                 msg->id = READ_REG(can, &regs->msg.rx_sff.id[0])<<3 |
1639                           READ_REG(can, &regs->msg.rx_sff.id[1])>>5;
1640 
1641                 while(tmp--){
1642                     msg->data[tmp] = READ_REG(can, &regs->msg.rx_sff.data[tmp]);
1643                 }
1644                 /*
1645                 msg->data[0] = READ_REG(can, &regs->msg.rx_sff.data[0]);
1646                 msg->data[1] = READ_REG(can, &regs->msg.rx_sff.data[1]);
1647                 msg->data[2] = READ_REG(can, &regs->msg.rx_sff.data[2]);
1648                 msg->data[3] = READ_REG(can, &regs->msg.rx_sff.data[3]);
1649                 msg->data[4] = READ_REG(can, &regs->msg.rx_sff.data[4]);
1650                 msg->data[5] = READ_REG(can, &regs->msg.rx_sff.data[5]);
1651                 msg->data[6] = READ_REG(can, &regs->msg.rx_sff.data[6]);
1652                 msg->data[7] = READ_REG(can, &regs->msg.rx_sff.data[7]);
1653                 */
1654             }
1655 
1656             /* Re-Enable RX buffer for a new message */
1657             WRITE_REG(can, &regs->cmd, PELICAN_CMD_RELRXBUF);
1658 
1659             /* make message available to the user */
1660             occan_fifo_put(can->rxfifo);
1661 
1662             /* bump stat counters */
1663             can->stats.rx_msgs++;
1664 
1665             /* signal the semaphore only once */
1666             signal_rx = 1;
1667         }
1668 
1669         if ( iflags & PELICAN_IF_TX ) {
1670 
1671             /* there is room in tx fifo of HW */
1672 
1673             if ( !occan_fifo_empty(can->txfifo) ){
1674                 /* send 1 more messages */
1675                 msg = occan_fifo_claim_get(can->txfifo);
1676 
1677                 if ( pelican_send(can,msg) ){
1678                     /* ERROR! We got an TX interrupt telling us
1679                      * tx fifo is empty, yet it is not.
1680                      *
1681                      * Complain about this max 10 times
1682                      */
1683                     if ( can->stats.tx_buf_error < 10 ){
1684                         printk("OCCAN: got TX interrupt but TX fifo in not empty (%d)\n\r",can->stats.tx_buf_error);
1685                     }
1686                     can->status |= OCCAN_STATUS_QUEUE_ERROR;
1687                     can->stats.tx_buf_error++;
1688                 }
1689 #ifdef OCCAN_TX_IRQ_FLAG_FIXUP
1690                 can->sending = 1;
1691 #endif
1692 
1693                 /* free software-fifo space taken by sent message */
1694                 occan_fifo_get(can->txfifo);
1695 
1696                 /* bump stat counters */
1697                 can->stats.tx_msgs++;
1698 
1699                 /* wake any sleeping thread waiting for "fifo not full" */
1700                 signal_tx = 1;
1701             }
1702         }
1703 
1704         if ( iflags & PELICAN_IF_ERRW ){
1705             tx_error_cnt = READ_REG(can, &regs->tx_err_cnt);
1706             rx_error_cnt = READ_REG(can, &regs->rx_err_cnt);
1707 
1708             /* 1. if bus off tx error counter = 127 */
1709             if ( (tx_error_cnt > 96) || (rx_error_cnt > 96) ){
1710                 /* in Error Active Warning area or BUS OFF */
1711                 can->status |= OCCAN_STATUS_WARN;
1712 
1713                 /* check reset bit for reset mode */
1714                 if ( READ_REG(can, &regs->mode) & PELICAN_MOD_RESET ){
1715                     /* in reset mode ==> bus off */
1716                     can->status |= OCCAN_STATUS_ERR_BUSOFF | OCCAN_STATUS_RESET;
1717 
1718                     /***** pelican_stop(can) ******
1719                      * turn off interrupts
1720                      * enter reset mode (HW already done that for us)
1721                      */
1722                     WRITE_REG(can, &regs->inten,0);
1723 
1724                     /* Indicate that we are not started any more.
1725                      * This will make write/read return with EBUSY
1726                      * on read/write attempts.
1727                      *
1728                      * User must issue a ioctl(START) to get going again.
1729                      */
1730                     can->started = 0;
1731 
1732                     /* signal any waiting read/write threads, so that they
1733                      * can handle the bus error.
1734                      */
1735                     signal_rx = 1;
1736                     signal_tx = 1;
1737 
1738                     /* ingnore any old pending interrupt */
1739                     break;
1740                 }
1741 
1742             }else{
1743                 /* not in Upper Error Active area any more */
1744                 can->status &= ~(OCCAN_STATUS_WARN);
1745             }
1746             can->stats.err_warn++;
1747         }
1748 
1749         if ( iflags & PELICAN_IF_DOVR){
1750             can->status |= OCCAN_STATUS_OVERRUN;
1751             can->stats.err_dovr++;
1752             DBG("OCCAN_INT: DOVR\n\r");
1753         }
1754 
1755         if ( iflags & PELICAN_IF_ERRP){
1756             /* Let the error counters decide what kind of
1757              * interrupt it was. In/Out of EPassive area.
1758              */
1759             tx_error_cnt = READ_REG(can, &regs->tx_err_cnt);
1760             rx_error_cnt = READ_REG(can, &regs->rx_err_cnt);
1761 
1762             if ( (tx_error_cnt > 127) || (rx_error_cnt > 127) ){
1763                 can->status |= OCCAN_STATUS_ERR_PASSIVE;
1764             }else{
1765                 can->status &= ~(OCCAN_STATUS_ERR_PASSIVE);
1766             }
1767 
1768             /* increase Error Passive In/out interrupt counter */
1769             can->stats.err_errp++;
1770         }
1771 
1772         if ( iflags & PELICAN_IF_ARB){
1773             arbcode = READ_REG(can, &regs->arbcode);
1774             can->stats.err_arb_bitnum[arbcode & PELICAN_ARB_BITS]++;
1775             can->stats.err_arb++;
1776             DBG("OCCAN_INT: ARB (0x%x)\n\r",arbcode & PELICAN_ARB_BITS);
1777         }
1778 
1779         if ( iflags & PELICAN_IF_BUS){
1780             /* Some kind of BUS error, only used for
1781              * statistics. Error Register is decoded
1782              * and put into can->stats.
1783              */
1784             errcode = READ_REG(can, &regs->errcode);
1785             switch( errcode & PELICAN_ECC_CODE ){
1786                 case PELICAN_ECC_CODE_BIT:
1787                     can->stats.err_bus_bit++;
1788                     break;
1789                 case PELICAN_ECC_CODE_FORM:
1790                     can->stats.err_bus_form++;
1791                     break;
1792                 case PELICAN_ECC_CODE_STUFF:
1793                     can->stats.err_bus_stuff++;
1794                     break;
1795                 case PELICAN_ECC_CODE_OTHER:
1796                     can->stats.err_bus_other++;
1797                     break;
1798             }
1799 
1800             /* Get Direction (TX/RX) */
1801             if ( errcode & PELICAN_ECC_DIR ){
1802                 can->stats.err_bus_rx++;
1803             }else{
1804                 can->stats.err_bus_tx++;
1805             }
1806 
1807             /* Get Segment in frame that went wrong */
1808             can->stats.err_bus_segs[errcode & PELICAN_ECC_SEG]++;
1809 
1810             /* total number of bus errors */
1811             can->stats.err_bus++;
1812         }
1813     }
1814     SPIN_UNLOCK(&can->devlock, irqflags);
1815 
1816     /* signal Binary semaphore, messages available! */
1817     if ( signal_rx ){
1818         rtems_semaphore_release(can->rxsem);
1819     }
1820 
1821     if ( signal_tx ){
1822         rtems_semaphore_release(can->txsem);
1823     }
1824 }
1825 
1826 /*******************************************************************************
1827  * FIFO IMPLEMENTATION
1828  */
1829 
1830 static occan_fifo *occan_fifo_create(int cnt)
1831 {
1832     occan_fifo *fifo;
1833     fifo = grlib_calloc(1, sizeof(*fifo)+cnt*sizeof(CANMsg));
1834     if ( fifo ){
1835         fifo->cnt = cnt;
1836         fifo->base = &fifo->fifoarea[0];
1837         fifo->tail = fifo->head = fifo->base;
1838     }
1839     return fifo;
1840 }
1841 
1842 static void occan_fifo_free(occan_fifo *fifo)
1843 {
1844     if ( fifo )
1845         free(fifo);
1846 }
1847 
1848 static int occan_fifo_full(occan_fifo *fifo)
1849 {
1850     return fifo->full;
1851 }
1852 
1853 static int occan_fifo_empty(occan_fifo *fifo)
1854 {
1855     return (!fifo->full) && (fifo->head == fifo->tail);
1856 }
1857 
1858 /* Stage 1 - get buffer to fill (never fails if force!=0) */
1859 static CANMsg *occan_fifo_put_claim(occan_fifo *fifo, int force)
1860 {
1861     if ( !fifo )
1862         return NULL;
1863 
1864     if ( occan_fifo_full(fifo) ){
1865 
1866         if ( !force )
1867             return NULL;
1868 
1869         /* all buffers already used ==> overwrite the oldest */
1870         fifo->ovcnt++;
1871         occan_fifo_get(fifo);
1872     }
1873 
1874     return fifo->head;
1875 }
1876 
1877 /* Stage 2 - increment indexes */
1878 static void occan_fifo_put(occan_fifo *fifo)
1879 {
1880     if ( occan_fifo_full(fifo) )
1881         return;
1882 
1883     /* wrap around */
1884     fifo->head = (fifo->head >= &fifo->base[fifo->cnt-1])? fifo->base : fifo->head+1;
1885 
1886     if ( fifo->head == fifo->tail )
1887         fifo->full = 1;
1888 }
1889 
1890 static CANMsg *occan_fifo_claim_get(occan_fifo *fifo)
1891 {
1892     if ( occan_fifo_empty(fifo) )
1893         return NULL;
1894 
1895     /* return oldest message */
1896     return fifo->tail;
1897 }
1898 
1899 
1900 static void occan_fifo_get(occan_fifo *fifo)
1901 {
1902     if ( !fifo )
1903         return;
1904 
1905     if ( occan_fifo_empty(fifo) )
1906         return;
1907 
1908     /* increment indexes */
1909     fifo->tail = (fifo->tail >= &fifo->base[fifo->cnt-1]) ?
1910                  fifo->base : fifo->tail+1;
1911     fifo->full = 0;
1912 }
1913 
1914 static void occan_fifo_clr(occan_fifo *fifo)
1915 {
1916     fifo->full  = 0;
1917     fifo->ovcnt = 0;
1918     fifo->head  = fifo->tail = fifo->base;
1919 }
1920 
1921 /******************************************************************************/