source: rtems/c/src/lib/libbsp/sparc/shared/can/grcan.c @ f97536d

5
Last change on this file since f97536d was f97536d, checked in by Sebastian Huber <sebastian.huber@…>, on Oct 16, 2015 at 6:21:48 AM

basdefs.h: Add and use RTEMS_UNUSED

  • Property mode set to 100644
File size: 44.8 KB
Line 
1/*
2 *  GRCAN driver
3 *
4 *  COPYRIGHT (c) 2007.
5 *  Cobham Gaisler AB.
6 *
7 *  The license and distribution terms for this file may be
8 *  found in the file LICENSE in this distribution or at
9 *  http://www.rtems.org/license/LICENSE.
10 */
11
12#include <bsp.h>
13#include <rtems/libio.h>
14#include <stdlib.h>
15#include <stdio.h>
16#include <string.h>
17#include <assert.h>
18#include <ctype.h>
19#include <rtems/bspIo.h>
20
21#include <bsp/grcan.h>
22#include <drvmgr/drvmgr.h>
23#include <drvmgr/ambapp_bus.h>
24#include <ambapp.h>
25
26#define WRAP_AROUND_TX_MSGS 1
27#define WRAP_AROUND_RX_MSGS 2
28#define GRCAN_MSG_SIZE sizeof(struct grcan_msg)
29#define BLOCK_SIZE (16*4)
30
31/* grcan needs to have it buffers aligned to 1k boundaries */
32#define BUFFER_ALIGNMENT_NEEDS 1024
33
34/* Default Maximium buffer size for statically allocated buffers */
35#ifndef TX_BUF_SIZE
36 #define TX_BUF_SIZE (BLOCK_SIZE*16)
37#endif
38
39/* Make receiver buffers bigger than transmitt */
40#ifndef RX_BUF_SIZE
41 #define RX_BUF_SIZE ((3*BLOCK_SIZE)*16)
42#endif
43
44#ifndef IRQ_GLOBAL_PREPARE
45 #define IRQ_GLOBAL_PREPARE(level) rtems_interrupt_level level
46#endif
47
48#ifndef IRQ_GLOBAL_DISABLE
49 #define IRQ_GLOBAL_DISABLE(level) rtems_interrupt_disable(level)
50#endif
51
52#ifndef IRQ_GLOBAL_ENABLE
53 #define IRQ_GLOBAL_ENABLE(level) rtems_interrupt_enable(level)
54#endif
55
56#ifndef IRQ_CLEAR_PENDING
57 #define IRQ_CLEAR_PENDING(irqno)
58#endif
59
60#ifndef IRQ_UNMASK
61 #define IRQ_UNMASK(irqno)
62#endif
63
64#ifndef IRQ_MASK
65 #define IRQ_MASK(irqno)
66#endif
67
68#ifndef GRCAN_DEFAULT_BAUD
69 /* default to 500kbits/s */
70 #define GRCAN_DEFAULT_BAUD 500000
71#endif
72
73#ifndef GRCAN_SAMPLING_POINT
74 #define GRCAN_SAMPLING_POINT 80
75#endif
76
77/* Uncomment for debug output */
78/****************** DEBUG Definitions ********************/
79#define DBG_IOCTRL 1
80#define DBG_TX 2
81#define DBG_RX 4
82
83#define DEBUG_FLAGS (DBG_IOCTRL | DBG_RX | DBG_TX )
84/*
85#define DEBUG
86#define DEBUGFUNCS
87*/
88#include <bsp/debug_defs.h>
89
90/*********************************************************/
91
92struct grcan_msg {
93        unsigned int head[2];
94        unsigned char data[8];
95};
96
97struct grcan_config {
98        struct grcan_timing timing;
99        struct grcan_selection selection;
100        int abort;
101        int silent;
102};
103
104struct grcan_priv {
105        struct drvmgr_dev *dev; /* Driver manager device */
106        char devName[32];       /* Device Name */
107        unsigned int baseaddr, ram_base;
108        struct grcan_regs *regs;
109        int irq;
110        int minor;
111        int open;
112        int started;
113        unsigned int channel;
114        int flushing;
115        unsigned int corefreq_hz;
116
117        /* Circular DMA buffers */
118        void *_rx, *_rx_hw;
119        void *_tx, *_tx_hw;
120        void *txbuf_adr;
121        void *rxbuf_adr;
122        struct grcan_msg *rx;
123        struct grcan_msg *tx;
124        unsigned int rxbuf_size;    /* requested RX buf size in bytes */
125        unsigned int txbuf_size;    /* requested TX buf size in bytes */
126
127        int txblock, rxblock;
128        int txcomplete, rxcomplete;
129        int txerror, rxerror;
130
131        struct grcan_filter sfilter;
132        struct grcan_filter afilter;
133        int config_changed; /* 0=no changes, 1=changes ==> a Core reset is needed */
134        struct grcan_config config;
135        struct grcan_stats stats;
136
137        rtems_id rx_sem, tx_sem, txempty_sem, dev_sem;
138};
139
140static rtems_device_driver grcan_initialize(rtems_device_major_number  major, rtems_device_minor_number  minor, void *arg);
141static rtems_device_driver grcan_open(rtems_device_major_number major, rtems_device_minor_number minor, void *arg);
142static rtems_device_driver grcan_close(rtems_device_major_number major, rtems_device_minor_number minor, void *arg);
143static rtems_device_driver grcan_read(rtems_device_major_number major, rtems_device_minor_number minor, void *arg);
144static rtems_device_driver grcan_write(rtems_device_major_number major, rtems_device_minor_number minor, void *arg);
145static rtems_device_driver grcan_ioctl(rtems_device_major_number major, rtems_device_minor_number minor, void *arg);
146
147#define GRCAN_DRIVER_TABLE_ENTRY { grcan_initialize, grcan_open, grcan_close, grcan_read, grcan_write, grcan_ioctl }
148
149static void __inline__ grcan_hw_reset(struct grcan_regs *regs);
150
151static unsigned int grcan_hw_read_try(
152  struct grcan_priv *pDev,
153  struct grcan_regs *regs,
154  CANMsg *buffer,
155  int max);
156
157static unsigned int grcan_hw_write_try(
158  struct grcan_priv *pDev,
159  struct grcan_regs *regs,
160  CANMsg *buffer,
161  int count);
162
163static void grcan_hw_config(
164  struct grcan_regs *regs,
165  struct grcan_config *conf);
166
167static void grcan_hw_accept(
168  struct grcan_regs *regs,
169  struct grcan_filter *afilter);
170
171static void grcan_hw_sync(
172  struct grcan_regs *regs,
173  struct grcan_filter *sfilter);
174
175static void grcan_interrupt(void *arg);
176
177#ifdef GRCAN_REG_BYPASS_CACHE
178#define READ_REG(address) _grcan_read_nocache((unsigned int)(address))
179#else
180#define READ_REG(address) (*(volatile unsigned int *)(address))
181#endif
182
183#ifdef GRCAN_DMA_BYPASS_CACHE
184#define READ_DMA_WORD(address) _grcan_read_nocache((unsigned int)(address))
185#define READ_DMA_BYTE(address) _grcan_read_nocache_byte((unsigned int)(address))
186static unsigned char __inline__ _grcan_read_nocache_byte(unsigned int address)
187{
188        unsigned char tmp;
189        __asm__ (" lduba [%1]1, %0 "
190            : "=r"(tmp)
191            : "r"(address)
192        );
193        return tmp;
194}
195#else
196#define READ_DMA_WORD(address) (*(volatile unsigned int *)(address))
197#define READ_DMA_BYTE(address) (*(volatile unsigned char *)(address))
198#endif
199
200#if defined(GRCAN_REG_BYPASS_CACHE) || defined(GRCAN_DMA_BYPASS_CACHE)
201static unsigned int __inline__ _grcan_read_nocache(unsigned int address)
202{
203        unsigned int tmp;
204        __asm__ (" lda [%1]1, %0 "
205                : "=r"(tmp)
206                : "r"(address)
207        );
208        return tmp;
209}
210#endif
211
212
213static rtems_driver_address_table grcan_driver = GRCAN_DRIVER_TABLE_ENTRY;
214static int grcan_driver_io_registered = 0;
215static rtems_device_major_number grcan_driver_io_major = 0;
216
217/******************* Driver manager interface ***********************/
218
219/* Driver prototypes */
220int grcan_register_io(rtems_device_major_number *m);
221int grcan_device_init(struct grcan_priv *pDev);
222
223int grcan_init2(struct drvmgr_dev *dev);
224int grcan_init3(struct drvmgr_dev *dev);
225
226struct drvmgr_drv_ops grcan_ops = 
227{
228        .init = {NULL, grcan_init2, grcan_init3, NULL},
229        .remove = NULL,
230        .info = NULL
231};
232
233struct amba_dev_id grcan_ids[] = 
234{
235        {VENDOR_GAISLER, GAISLER_GRCAN},
236        {VENDOR_GAISLER, GAISLER_GRHCAN},
237        {0, 0}          /* Mark end of table */
238};
239
240struct amba_drv_info grcan_drv_info =
241{
242        {
243                DRVMGR_OBJ_DRV,                 /* Driver */
244                NULL,                           /* Next driver */
245                NULL,                           /* Device list */
246                DRIVER_AMBAPP_GAISLER_GRCAN_ID, /* Driver ID */
247                "GRCAN_DRV",                    /* Driver Name */
248                DRVMGR_BUS_TYPE_AMBAPP,         /* Bus Type */
249                &grcan_ops,
250                NULL,                           /* Funcs */
251                0,                              /* No devices yet */
252                0,
253        },
254        &grcan_ids[0]
255};
256
257void grcan_register_drv (void)
258{
259        DBG("Registering GRCAN driver\n");
260        drvmgr_drv_register(&grcan_drv_info.general);
261}
262
263int grcan_init2(struct drvmgr_dev *dev)
264{
265        struct grcan_priv *priv;
266
267        DBG("GRCAN[%d] on bus %s\n", dev->minor_drv, dev->parent->dev->name);
268        priv = dev->priv = malloc(sizeof(struct grcan_priv));
269        if ( !priv )
270                return DRVMGR_NOMEM;
271        memset(priv, 0, sizeof(*priv));
272        priv->dev = dev;
273
274        /* This core will not find other cores, so we wait for init2() */
275
276        return DRVMGR_OK;
277}
278
279int grcan_init3(struct drvmgr_dev *dev)
280{
281        struct grcan_priv *priv;
282        char prefix[32];
283        rtems_status_code status;
284
285        priv = dev->priv;
286
287        /* Do initialization */
288
289        if ( grcan_driver_io_registered == 0) {
290                /* Register the I/O driver only once for all cores */
291                if ( grcan_register_io(&grcan_driver_io_major) ) {
292                        /* Failed to register I/O driver */
293                        dev->priv = NULL;
294                        return DRVMGR_FAIL;
295                }
296
297                grcan_driver_io_registered = 1;
298        }
299
300        /* I/O system registered and initialized
301         * Now we take care of device initialization.
302         */
303
304        if ( grcan_device_init(priv) ) {
305                return DRVMGR_FAIL;
306        }
307
308        /* Get Filesystem name prefix */
309        prefix[0] = '\0';
310        if ( drvmgr_get_dev_prefix(dev, prefix) ) {
311                /* Failed to get prefix, make sure of a unique FS name
312                 * by using the driver minor.
313                 */
314                sprintf(priv->devName, "/dev/grcan%d", dev->minor_drv);
315        } else {
316                /* Got special prefix, this means we have a bus prefix
317                 * And we should use our "bus minor"
318                 */
319                sprintf(priv->devName, "/dev/%sgrcan%d", prefix, dev->minor_bus);
320        }
321
322        /* Register Device */
323        status = rtems_io_register_name(priv->devName, grcan_driver_io_major, dev->minor_drv);
324        if (status != RTEMS_SUCCESSFUL) {
325                return DRVMGR_FAIL;
326        }
327
328        return DRVMGR_OK;
329}
330
331/******************* Driver Implementation ***********************/
332
333int grcan_register_io(rtems_device_major_number *m)
334{
335        rtems_status_code r;
336
337        if ((r = rtems_io_register_driver(0, &grcan_driver, m)) == RTEMS_SUCCESSFUL) {
338                DBG("GRCAN driver successfully registered, major: %d\n", *m);
339        } else {
340                switch(r) {
341                case RTEMS_TOO_MANY:
342                        printk("GRCAN rtems_io_register_driver failed: RTEMS_TOO_MANY\n");
343                        return -1;
344                case RTEMS_INVALID_NUMBER: 
345                        printk("GRCAN rtems_io_register_driver failed: RTEMS_INVALID_NUMBER\n");
346                        return -1;
347                case RTEMS_RESOURCE_IN_USE:
348                        printk("GRCAN rtems_io_register_driver failed: RTEMS_RESOURCE_IN_USE\n");
349                        return -1;
350                default:
351                        printk("GRCAN rtems_io_register_driver failed\n");
352                        return -1;
353                }
354        }
355        return 0;
356}
357
358int grcan_device_init(struct grcan_priv *pDev)
359{
360        struct amba_dev_info *ambadev;
361        struct ambapp_core *pnpinfo;
362
363        /* Get device information from AMBA PnP information */
364        ambadev = (struct amba_dev_info *)pDev->dev->businfo;
365        if ( ambadev == NULL ) {
366                return -1;
367        }
368        pnpinfo = &ambadev->info;
369        pDev->irq = pnpinfo->irq;
370        pDev->regs = (struct grcan_regs *)pnpinfo->apb_slv->start;
371        pDev->minor = pDev->dev->minor_drv;
372
373        /* Get frequency in Hz */
374        if ( drvmgr_freq_get(pDev->dev, DEV_APB_SLV, &pDev->corefreq_hz) ) {
375                return -1;
376        }
377
378        DBG("GRCAN frequency: %d Hz\n", pDev->corefreq_hz);
379
380        /* Reset Hardware before attaching IRQ handler */
381        grcan_hw_reset(pDev->regs);
382
383        /* RX Semaphore created with count = 0 */
384        if ( rtems_semaphore_create(rtems_build_name('G', 'C', 'R', '0' + pDev->minor),
385                0,
386                RTEMS_FIFO|RTEMS_SIMPLE_BINARY_SEMAPHORE|RTEMS_NO_INHERIT_PRIORITY|\
387                RTEMS_LOCAL|RTEMS_NO_PRIORITY_CEILING, 
388                0,
389                &pDev->rx_sem) != RTEMS_SUCCESSFUL ) {
390                return RTEMS_INTERNAL_ERROR;
391        }
392
393        /* TX Semaphore created with count = 0 */
394        if ( rtems_semaphore_create(rtems_build_name('G', 'C', 'T', '0' + pDev->minor),
395                0,
396                RTEMS_FIFO|RTEMS_SIMPLE_BINARY_SEMAPHORE|RTEMS_NO_INHERIT_PRIORITY|\
397                RTEMS_LOCAL|RTEMS_NO_PRIORITY_CEILING, 
398                0,
399                &pDev->tx_sem) != RTEMS_SUCCESSFUL ) {
400                return RTEMS_INTERNAL_ERROR;
401        }
402
403        /* TX Empty Semaphore created with count = 0 */
404        if ( rtems_semaphore_create(rtems_build_name('G', 'C', 'E', '0' + pDev->minor),
405                0,
406                RTEMS_FIFO|RTEMS_SIMPLE_BINARY_SEMAPHORE|RTEMS_NO_INHERIT_PRIORITY|\
407                RTEMS_LOCAL|RTEMS_NO_PRIORITY_CEILING, 
408                0,
409                &pDev->txempty_sem) != RTEMS_SUCCESSFUL ) {
410                return RTEMS_INTERNAL_ERROR;
411        }
412
413        /* Device Semaphore created with count = 1 */
414        if ( rtems_semaphore_create(rtems_build_name('G', 'C', 'A', '0' + pDev->minor),
415                1,
416                RTEMS_FIFO|RTEMS_SIMPLE_BINARY_SEMAPHORE|RTEMS_NO_INHERIT_PRIORITY|\
417                RTEMS_LOCAL|RTEMS_NO_PRIORITY_CEILING,
418                0,
419                &pDev->dev_sem) != RTEMS_SUCCESSFUL ) {
420                return RTEMS_INTERNAL_ERROR;
421        }
422
423        return 0;
424}
425
426static void __inline__ grcan_hw_reset(struct grcan_regs *regs)
427{
428        regs->ctrl = GRCAN_CTRL_RESET;
429}
430
431static rtems_device_driver grcan_start(struct grcan_priv *pDev)
432{
433  /*
434   * tmp is set but never used. GCC gives a warning for this
435   * and we need to tell GCC not to complain.
436   */
437  unsigned int tmp RTEMS_UNUSED;
438
439  IRQ_GLOBAL_PREPARE(oldLevel);
440
441  FUNCDBG();
442
443  /* Check that memory has been allocated successfully */
444  if ( !pDev->tx || !pDev->rx )
445    return RTEMS_NO_MEMORY;
446
447  /* Configure FIFO configuration register
448   * and Setup timing
449   */
450  if ( pDev->config_changed ){
451    grcan_hw_config(pDev->regs,&pDev->config);
452    pDev->config_changed = 0;
453  }
454
455  /* Setup receiver */
456  pDev->regs->rx0addr = (unsigned int)pDev->_rx_hw;
457  pDev->regs->rx0size = pDev->rxbuf_size;
458
459  /* Setup Transmitter */
460  pDev->regs->tx0addr = (unsigned int)pDev->_tx_hw;
461  pDev->regs->tx0size = pDev->txbuf_size;
462
463  /* Setup acceptance filters */
464  grcan_hw_accept(pDev->regs,&pDev->afilter);
465
466  /* Sync filters */
467  grcan_hw_sync(pDev->regs,&pDev->sfilter);
468
469  /* Clear status bits */
470  tmp = READ_REG(&pDev->regs->stat);
471  pDev->regs->stat = 0;
472
473  /* Setup IRQ handling */
474
475  /* Clear all IRQs */
476  tmp = READ_REG(&pDev->regs->pir);
477  pDev->regs->picr = 0x1ffff;
478
479  /* unmask TxLoss|TxErrCntr|RxErrCntr|TxAHBErr|RxAHBErr|OR|OFF|PASS */
480  pDev->regs->imr = 0x1601f;
481
482  /* Enable routing of the IRQs */
483  IRQ_GLOBAL_DISABLE(oldLevel);
484  IRQ_UNMASK(pDev->irq+GRCAN_IRQ_TXSYNC);
485  IRQ_UNMASK(pDev->irq+GRCAN_IRQ_RXSYNC);
486  IRQ_UNMASK(pDev->irq+GRCAN_IRQ_IRQ);
487  IRQ_GLOBAL_ENABLE(oldLevel);
488
489  /* Reset some software data */
490  /*pDev->txerror = 0;
491  pDev->rxerror = 0;*/
492
493  /* Enable receiver/transmitter */
494  pDev->regs->rx0ctrl = GRCAN_RXCTRL_ENABLE;
495  pDev->regs->tx0ctrl = GRCAN_TXCTRL_ENABLE;
496
497  /* Enable HurriCANe core */
498  pDev->regs->ctrl = GRCAN_CTRL_ENABLE;
499
500  /* Leave transmitter disabled, it is enabled when
501   * trying to send something.
502   */
503  return RTEMS_SUCCESSFUL;
504}
505
506static void grcan_stop(struct grcan_priv *pDev)
507{
508  FUNCDBG();
509
510  /* Mask all IRQs */
511  pDev->regs->imr = 0;
512  IRQ_MASK(pDev->irq+GRCAN_IRQ_TXSYNC);
513  IRQ_MASK(pDev->irq+GRCAN_IRQ_RXSYNC);
514  IRQ_MASK(pDev->irq+GRCAN_IRQ_IRQ);
515
516  /* Disable receiver & transmitter */
517  pDev->regs->rx0ctrl = 0;
518  pDev->regs->tx0ctrl = 0;
519
520  /* Reset semaphores to the initial state and wakeing
521   * all threads waiting for an IRQ. The threads that
522   * get woken up must check for RTEMS_UNSATISFIED in
523   * order to determine that they should return to
524   * user space with error status.
525   */
526  rtems_semaphore_flush(pDev->rx_sem);
527  rtems_semaphore_flush(pDev->tx_sem);
528  rtems_semaphore_flush(pDev->txempty_sem);
529}
530
531static void grcan_hw_config(
532  struct grcan_regs *regs,
533  struct grcan_config *conf
534  )
535{
536  unsigned int config=0;
537
538  /* Reset HurriCANe Core */
539  regs->ctrl = 0;
540
541  if ( conf->silent )
542    config |= GRCAN_CFG_SILENT;
543
544  if ( conf->abort )
545    config |= GRCAN_CFG_ABORT;
546
547  if ( conf->selection.selection )
548    config |= GRCAN_CFG_SELECTION;
549
550  if ( conf->selection.enable0 )
551    config |= GRCAN_CFG_ENABLE0;
552
553  if ( conf->selection.enable1 )
554    config |= GRCAN_CFG_ENABLE1;
555
556  /* Timing */
557  config |= (conf->timing.bpr<<GRCAN_CFG_BPR_BIT) & GRCAN_CFG_BPR;
558  config |= (conf->timing.rsj<<GRCAN_CFG_RSJ_BIT) & GRCAN_CFG_RSJ;
559  config |= (conf->timing.ps1<<GRCAN_CFG_PS1_BIT) & GRCAN_CFG_PS1;
560  config |= (conf->timing.ps2<<GRCAN_CFG_PS2_BIT) & GRCAN_CFG_PS2;
561  config |= (conf->timing.scaler<<GRCAN_CFG_SCALER_BIT) & GRCAN_CFG_SCALER;
562
563  /* Write configuration */
564  regs->conf = config;
565
566  /* Enable HurriCANe Core */
567  regs->ctrl = GRCAN_CTRL_ENABLE;
568}
569
570static void grcan_hw_accept(
571  struct grcan_regs *regs,
572  struct grcan_filter *afilter
573  )
574{
575  /* Disable Sync mask totaly (if we change scode or smask
576   * in an unfortunate way we may trigger a sync match)
577   */
578  regs->rx0mask = 0xffffffff;
579
580  /* Set Sync Filter in a controlled way */
581  regs->rx0code = afilter->code;
582  regs->rx0mask = afilter->mask;
583}
584
585static void grcan_hw_sync(
586  struct grcan_regs *regs,
587  struct grcan_filter *sfilter
588  )
589{
590  /* Disable Sync mask totaly (if we change scode or smask
591   * in an unfortunate way we may trigger a sync match)
592   */
593  regs->smask = 0xffffffff;
594
595  /* Set Sync Filter in a controlled way */
596  regs->scode = sfilter->code;
597  regs->smask = sfilter->mask;
598}
599
600static unsigned int grcan_hw_rxavail(
601  unsigned int rp,
602  unsigned int wp,
603  unsigned int size
604  )
605{
606  if ( rp == wp ) {
607    /* read pointer and write pointer is equal only
608     * when RX buffer is empty.
609     */
610    return 0;
611  }
612
613  if ( wp > rp ) {
614    return (wp-rp)/GRCAN_MSG_SIZE;
615  }else{
616    return (size-(rp-wp))/GRCAN_MSG_SIZE;
617  }
618}
619
620static unsigned int grcan_hw_txspace(
621  unsigned int rp,
622  unsigned int wp,
623  unsigned int size
624  )
625{
626  unsigned int left;
627
628  if ( rp == wp ) {
629    /* read pointer and write pointer is equal only
630     * when TX buffer is empty.
631     */
632    return size/GRCAN_MSG_SIZE-WRAP_AROUND_TX_MSGS;
633  }
634
635  /* size - 4 - abs(read-write) */
636  if ( wp > rp ) {
637    left = size-(wp-rp);
638  }else{
639    left = rp-wp;
640  }
641
642  return left/GRCAN_MSG_SIZE-WRAP_AROUND_TX_MSGS;
643}
644
645static int grcan_hw_rx_ongoing(struct grcan_regs *regs)
646{
647  return READ_REG(&regs->rx0ctrl) & GRCAN_RXCTRL_ONGOING;
648};
649
650static int grcan_hw_tx_ongoing(struct grcan_regs *regs)
651{
652  return READ_REG(&regs->tx0ctrl) & GRCAN_TXCTRL_ONGOING;
653};
654
655
656#define MIN_TSEG1 1
657#define MIN_TSEG2 2
658#define MAX_TSEG1 14
659#define MAX_TSEG2 8
660
661static int grcan_calc_timing(
662  unsigned int baud,          /* The requested BAUD to calculate timing for */
663  unsigned int core_hz,       /* Frequency in Hz of GRCAN Core */
664  unsigned int sampl_pt,
665  struct grcan_timing *timing /* result is placed here */
666  )
667{
668        int best_error = 1000000000;
669        int error;
670        int best_tseg=0, best_brp=0, brp=0;
671        int tseg=0, tseg1=0, tseg2=0;
672        int sjw = 1;
673
674  /* Default to 90% */
675  if ( (sampl_pt < 50) || (sampl_pt>99) ){
676    sampl_pt = GRCAN_SAMPLING_POINT;
677  }
678
679        if ( (baud<5000) || (baud>1000000) ){
680                /* invalid speed mode */
681                return -1;
682        }
683
684        /* find best match, return -2 if no good reg
685         * combination is available for this frequency
686   */
687
688        /* some heuristic specials */
689        if (baud > ((1000000 + 500000) / 2))
690                sampl_pt = 75;
691
692        if (baud < ((12500 + 10000) / 2))
693                sampl_pt = 75;
694
695        /* tseg even = round down, odd = round up */
696        for (tseg = (MIN_TSEG1 + MIN_TSEG2 + 2) * 2;
697             tseg <= (MAX_TSEG2 + MAX_TSEG1 + 2) * 2 + 1;
698             tseg++)
699        {
700                brp = core_hz / ((1 + tseg / 2) * baud) + tseg % 2;
701                if ((brp <= 0) ||
702        ( (brp > 256*1) && (brp <= 256*2) && (brp&0x1) ) ||
703        ( (brp > 256*2) && (brp <= 256*4) && (brp&0x3) ) ||
704        ( (brp > 256*4) && (brp <= 256*8) && (brp&0x7) ) ||
705        (brp > 256*8)
706        )
707                        continue;
708
709                error = baud - core_hz / (brp * (1 + tseg / 2));
710                if (error < 0)
711                {
712                        error = -error;
713                }
714
715                if (error <= best_error)
716                {
717                        best_error = error;
718                        best_tseg = tseg/2;
719                        best_brp = brp-1;
720                }
721        }
722
723        if (best_error && (baud / best_error < 10))
724        {
725                return -2;
726        }else if ( !timing )
727                return 0; /* nothing to store result in, but a valid bitrate can be calculated */
728
729        tseg2 = best_tseg - (sampl_pt * (best_tseg + 1)) / 100;
730
731        if (tseg2 < MIN_TSEG2)
732        {
733                tseg2 = MIN_TSEG2;
734        }
735
736        if (tseg2 > MAX_TSEG2)
737        {
738                tseg2 = MAX_TSEG2;
739        }
740
741        tseg1 = best_tseg - tseg2 - 2;
742
743        if (tseg1 > MAX_TSEG1)
744        {
745                tseg1 = MAX_TSEG1;
746                tseg2 = best_tseg - tseg1 - 2;
747        }
748
749  /* Get scaler and BRP from pseudo BRP */
750  if ( best_brp <= 256 ){
751    timing->scaler = best_brp;
752    timing->bpr = 0;
753  }else if ( best_brp <= 256*2 ){
754    timing->scaler = ((best_brp+1)>>1) -1;
755    timing->bpr = 1;
756  }else if ( best_brp <= 256*4 ){
757    timing->scaler = ((best_brp+1)>>2) -1;
758    timing->bpr = 2;
759  }else{
760    timing->scaler = ((best_brp+1)>>3) -1;
761    timing->bpr = 3;
762  }
763
764        timing->ps1    = tseg1+1;
765        timing->ps2    = tseg2;
766        timing->rsj    = sjw;
767
768        return 0;
769}
770
771static unsigned int grcan_hw_read_try(
772  struct grcan_priv *pDev,
773  struct grcan_regs *regs,
774  CANMsg *buffer,
775  int max
776  )
777{
778  int i,j;
779  CANMsg *dest;
780  struct grcan_msg *source,tmp;
781  unsigned int wp,rp,size,rxmax,addr,trunk_msg_cnt;
782
783  FUNCDBG();
784
785  wp = READ_REG(&regs->rx0wr);
786  rp = READ_REG(&regs->rx0rd);
787
788  /*
789   * Due to hardware wrap around simplification write pointer will
790   * never reach the read pointer, at least a gap of 8 bytes.
791   * The only time they are equal is when the read pointer has
792   * reached the write pointer (empty buffer)
793   *
794   */
795  if ( wp != rp ){
796    /* Not empty, we have received chars...
797     * Read as much as possible from DMA buffer
798     */
799    size = READ_REG(&regs->rx0size);
800
801    /* Get number of bytes available in RX buffer */
802    trunk_msg_cnt = grcan_hw_rxavail(rp,wp,size);
803
804    /* truncate size if user space buffer hasn't room for
805     * all received chars.
806     */
807    if ( trunk_msg_cnt > max )
808      trunk_msg_cnt = max;
809
810    /* Read until i is 0 */
811    i=trunk_msg_cnt;
812
813    addr = (unsigned int)pDev->rx;
814    source = (struct grcan_msg *)(addr + rp);
815    dest = buffer;
816    rxmax = addr + (size-GRCAN_MSG_SIZE);
817
818    /* Read as many can messages as possible */
819    while(i>0){
820      /* Read CAN message from DMA buffer */
821      tmp.head[0] = READ_DMA_WORD(&source->head[0]);
822      tmp.head[1] = READ_DMA_WORD(&source->head[1]);
823      /* Convert one grcan CAN message to one "software" CAN message */
824      dest->extended = tmp.head[0]>>31;
825      dest->rtr = (tmp.head[0] >>30) & 0x1;
826      if ( dest->extended ){
827        dest->id = tmp.head[0] & 0x3fffffff;
828      }else{
829        dest->id = (tmp.head[0] >>18) & 0xfff;
830      }
831      dest->len = tmp.head[1] >> 28;
832      for(j=0; j<dest->len; j++)
833        dest->data[j] = READ_DMA_BYTE(&source->data[j]);
834
835      /* wrap around if neccessary */
836      source = ( (unsigned int)source >= rxmax ) ? (struct grcan_msg *)addr : source+1;
837      dest++; /* straight user buffer */
838      i--;
839    }
840    /* Increment Hardware READ pointer (mark read byte as read)
841     * ! wait for registers to be safely re-configurable
842     */
843    regs->rx0ctrl = 0; /* DISABLE RX CHANNEL */
844    i=0;
845    while( grcan_hw_rx_ongoing(regs) && (i<1000) ){
846      i++;
847    }
848    regs->rx0rd = (unsigned int)source-addr;
849    regs->rx0ctrl = GRCAN_RXCTRL_ENABLE; /* ENABLE_RX_CHANNEL */
850    return trunk_msg_cnt;
851  }
852  return 0;
853}
854
855static unsigned int grcan_hw_write_try(
856  struct grcan_priv *pDev,
857  struct grcan_regs *regs,
858  CANMsg *buffer,
859  int count
860  )
861{
862  unsigned int rp, wp, size, txmax, addr, ret;
863  struct grcan_msg *dest;
864  CANMsg *source;
865  int space_left;
866  unsigned int tmp;
867  int i;
868
869  DBGC(DBG_TX,"\n");
870  /*FUNCDBG();*/
871
872  rp = READ_REG(&regs->tx0rd);
873  wp = READ_REG(&regs->tx0wr);
874  size = READ_REG(&regs->tx0size);
875
876  space_left = grcan_hw_txspace(rp,wp,size);
877
878  /* is circular fifo full? */
879  if ( space_left < 1 )
880    return 0;
881
882  /* Truncate size */
883  if ( space_left > count )
884    space_left = count;
885  ret = space_left;
886
887  addr = (unsigned int)pDev->tx;
888
889  dest = (struct grcan_msg *)(addr + wp);
890  source = (CANMsg *)buffer;
891  txmax = addr + (size-GRCAN_MSG_SIZE);
892
893  while ( space_left>0 ) {
894    /* Convert and write CAN message to DMA buffer */
895    if ( source->extended ){
896      tmp = (1<<31) | (source->id & 0x3fffffff);
897    }else{
898      tmp = (source->id&0xfff)<<18;
899    }
900    if ( source->rtr )
901      tmp|=(1<<30);
902    dest->head[0] = tmp;
903    dest->head[1] = source->len<<28;
904    for ( i=0; i<source->len; i++)
905      dest->data[i] = source->data[i];
906    source++; /* straight user buffer */
907    dest = ((unsigned int)dest >= txmax) ? (struct grcan_msg *)addr : dest+1;
908    space_left--;
909  }
910
911  /* Update write pointer
912   * ! wait for registers to be safely re-configurable
913   */
914  regs->tx0ctrl = 0; /* DISABLE TX CHANNEL */
915  i=0;
916  while( (grcan_hw_tx_ongoing(regs)) && i<1000 ){
917    i++;
918  }
919  regs->tx0wr = (unsigned int)dest - addr; /* Update write pointer */
920  regs->tx0ctrl = GRCAN_TXCTRL_ENABLE; /* ENABLE_TX_CHANNEL */
921  return ret;
922}
923
924static int grcan_wait_rxdata(
925  struct grcan_priv *pDev,
926  int min
927  )
928{
929  unsigned int wp, rp, size, irq;
930  unsigned int irq_trunk, dataavail;
931  int wait;
932  IRQ_GLOBAL_PREPARE(oldLevel);
933
934  FUNCDBG();
935
936  /*** block until receive IRQ received
937   * Set up a valid IRQ point so that an IRQ is received
938   * when one or more messages are received
939   */
940  IRQ_GLOBAL_DISABLE(oldLevel);
941
942  size = READ_REG(&pDev->regs->rx0size);
943  rp = READ_REG(&pDev->regs->rx0rd);
944  wp = READ_REG(&pDev->regs->rx0wr);
945
946  /**** Calculate IRQ Pointer ****/
947  irq = wp + min*GRCAN_MSG_SIZE;
948  /* wrap irq around */
949  if ( irq >= size ){
950    irq_trunk = irq-size;
951  }else
952    irq_trunk = irq;
953
954  /* init IRQ HW */
955  pDev->regs->rx0irq = irq_trunk;
956
957  /* Clear pending Rx IRQ */
958  pDev->regs->picr = GRCAN_RXIRQ_IRQ;
959
960  wp = READ_REG(&pDev->regs->rx0wr);
961
962  /* Calculate messages available */
963  dataavail = grcan_hw_rxavail(rp,wp,size);
964
965  if ( dataavail < min ){
966    /* Still empty, proceed with sleep - Turn on IRQ (unmask irq) */
967    pDev->regs->imr = READ_REG(&pDev->regs->imr) | GRCAN_RXIRQ_IRQ;
968    wait=1;
969  }else{
970    /* enough message has been received, abort sleep - don't unmask interrupt */
971    wait=0;
972  }
973  IRQ_GLOBAL_ENABLE(oldLevel);
974
975    /* Wait for IRQ to fire only if has been triggered */
976  if ( wait ){
977    if ( rtems_semaphore_obtain(pDev->rx_sem, RTEMS_WAIT, RTEMS_NO_TIMEOUT) == RTEMS_UNSATISFIED )
978      return -1; /* Device driver has been closed or stopped, return with error status */
979  }
980
981  return 0;
982}
983
984/* Wait until min bytes available in TX circular buffer.
985 * The IRQ RxIrq is used to pin point the location of
986 *
987 * min must be at least WRAP_AROUND_TX_BYTES bytes less
988 * than max buffer for this algo to work.
989 *
990 */
991static int grcan_wait_txspace(
992  struct grcan_priv *pDev,
993  int min
994  )
995{
996  int wait;
997  unsigned int irq, rp, wp, size, space_left;
998  unsigned int irq_trunk;
999  IRQ_GLOBAL_PREPARE(oldLevel);
1000
1001  DBGC(DBG_TX,"\n");
1002  /*FUNCDBG();*/
1003
1004  IRQ_GLOBAL_DISABLE(oldLevel);
1005
1006  pDev->regs->tx0ctrl = GRCAN_TXCTRL_ENABLE;
1007
1008  size = READ_REG(&pDev->regs->tx0size);
1009  wp = READ_REG(&pDev->regs->tx0wr);
1010
1011  rp = READ_REG(&pDev->regs->tx0rd);
1012
1013  /**** Calculate IRQ Pointer ****/
1014  irq = rp + min*GRCAN_MSG_SIZE;
1015  /* wrap irq around */
1016  if ( irq >= size ){
1017    irq_trunk = irq - size;
1018  }else
1019    irq_trunk = irq;
1020
1021  /* trigger HW to do a IRQ when enough room in buffer */
1022  pDev->regs->tx0irq = irq_trunk;
1023
1024  /* Clear pending Tx IRQ */
1025  pDev->regs->picr = GRCAN_TXIRQ_IRQ;
1026
1027  /* One problem, if HW already gone past IRQ place the IRQ will
1028   * never be received resulting in a thread hang. We check if so
1029   * before proceeding.
1030   *
1031   * has the HW already gone past the IRQ generation place?
1032   *  == does min fit info tx buffer?
1033   */
1034  rp = READ_REG(&pDev->regs->tx0rd);
1035
1036  space_left = grcan_hw_txspace(rp,wp,size);
1037
1038  if ( space_left < min ){
1039    /* Still too full, proceed with sleep - Turn on IRQ (unmask irq) */
1040    pDev->regs->imr = READ_REG(&pDev->regs->imr) | GRCAN_TXIRQ_IRQ;
1041    wait=1;
1042  }else{
1043    /* There are enough room in buffer, abort wait - don't unmask interrupt */
1044    wait=0;
1045  }
1046  IRQ_GLOBAL_ENABLE(oldLevel);
1047
1048  /* Wait for IRQ to fire only if it has been triggered */
1049  if ( wait ){
1050    if ( rtems_semaphore_obtain(pDev->tx_sem, RTEMS_WAIT, 100) ==
1051         RTEMS_UNSATISFIED ){
1052      /* Device driver has flushed us, this may be due to another thread has
1053       * closed the device, this is to avoid deadlock */
1054      return -1;
1055    }
1056  }
1057
1058  /* At this point the TxIRQ has been masked, we ned not to mask it */
1059  return 0;
1060}
1061
1062static int grcan_tx_flush(struct grcan_priv *pDev)
1063{
1064  int wait;
1065  unsigned int rp, wp;
1066  IRQ_GLOBAL_PREPARE(oldLevel);
1067  FUNCDBG();
1068
1069  /* loop until all data in circular buffer has been read by hw.
1070   * (write pointer != read pointer )
1071   *
1072   * Hardware doesn't update write pointer - we do
1073   */
1074  while ( (wp=READ_REG(&pDev->regs->tx0wr)) != (rp=READ_REG(&pDev->regs->tx0rd)) ) {
1075    /* Wait for TX empty IRQ */
1076    IRQ_GLOBAL_DISABLE(oldLevel);
1077    /* Clear pending TXEmpty IRQ */
1078    pDev->regs->picr = GRCAN_TXEMPTY_IRQ;
1079
1080    if ( wp != READ_REG(&pDev->regs->tx0rd) ) {
1081      /* Still not empty, proceed with sleep - Turn on IRQ (unmask irq) */
1082      pDev->regs->imr = READ_REG(&pDev->regs->imr) | GRCAN_TXEMPTY_IRQ;
1083      wait = 1;
1084    }else{
1085      /* TX fifo is empty */
1086      wait = 0;
1087    }
1088    IRQ_GLOBAL_ENABLE(oldLevel);
1089    if ( !wait )
1090      break;
1091
1092    /* Wait for IRQ to wake us */
1093    if ( rtems_semaphore_obtain(pDev->txempty_sem, RTEMS_WAIT, RTEMS_NO_TIMEOUT) ==
1094         RTEMS_UNSATISFIED ) {
1095      return -1;
1096    }
1097  }
1098  return 0;
1099}
1100
1101static int grcan_alloc_buffers(struct grcan_priv *pDev, int rx, int tx)
1102{
1103        unsigned int adr;
1104        FUNCDBG();
1105
1106        if ( tx ) {
1107                adr = (unsigned int)pDev->txbuf_adr;
1108                if (adr & 0x1) {
1109                        /* User defined "remote" address. Translate it into
1110                         * a CPU accessible address
1111                         */
1112                        pDev->_tx_hw = (void *)(adr & ~0x1);
1113                        drvmgr_translate_check(
1114                                pDev->dev,
1115                                DMAMEM_TO_CPU,
1116                                (void *)pDev->_tx_hw,
1117                                (void **)&pDev->_tx,
1118                                pDev->txbuf_size);
1119                        pDev->tx = (struct grcan_msg *)pDev->_tx;
1120                } else {
1121                        if (adr == 0) {
1122                                pDev->_tx = malloc(pDev->txbuf_size +
1123                                                   BUFFER_ALIGNMENT_NEEDS);
1124                                if (!pDev->_tx)
1125                                        return -1;
1126                        } else {
1127                                /* User defined "cou-local" address. Translate
1128                                 * it into a CPU accessible address
1129                                 */
1130                                pDev->_tx = (void *)adr;
1131                        }
1132                        /* Align TX buffer */
1133                        pDev->tx = (struct grcan_msg *)
1134                                   (((unsigned int)pDev->_tx +
1135                                   (BUFFER_ALIGNMENT_NEEDS-1)) &
1136                                   ~(BUFFER_ALIGNMENT_NEEDS-1));
1137
1138                        /* Translate address into an hardware accessible
1139                         * address
1140                         */
1141                        drvmgr_translate_check(
1142                                pDev->dev,
1143                                CPUMEM_TO_DMA,
1144                                (void *)pDev->tx,
1145                                (void **)&pDev->_tx_hw,
1146                                pDev->txbuf_size);
1147                }
1148        }
1149
1150        if ( rx ) {
1151                adr = (unsigned int)pDev->rxbuf_adr;
1152                if (adr & 0x1) {
1153                        /* User defined "remote" address. Translate it into
1154                         * a CPU accessible address
1155                         */
1156                        pDev->_rx_hw = (void *)(adr & ~0x1);
1157                        drvmgr_translate_check(
1158                                pDev->dev,
1159                                DMAMEM_TO_CPU,
1160                                (void *)pDev->_rx_hw,
1161                                (void **)&pDev->_rx,
1162                                pDev->rxbuf_size);
1163                        pDev->rx = (struct grcan_msg *)pDev->_rx;
1164                } else {
1165                        if (adr == 0) {
1166                                pDev->_rx = malloc(pDev->rxbuf_size +
1167                                                   BUFFER_ALIGNMENT_NEEDS);
1168                                if (!pDev->_rx)
1169                                        return -1;
1170                        } else {
1171                                /* User defined "cou-local" address. Translate
1172                                 * it into a CPU accessible address
1173                                 */
1174                                pDev->_rx = (void *)adr;
1175                        }
1176                        /* Align RX buffer */
1177                        pDev->rx = (struct grcan_msg *)
1178                                   (((unsigned int)pDev->_rx +
1179                                   (BUFFER_ALIGNMENT_NEEDS-1)) &
1180                                   ~(BUFFER_ALIGNMENT_NEEDS-1));
1181
1182                        /* Translate address into an hardware accessible
1183                         * address
1184                         */
1185                        drvmgr_translate_check(
1186                                pDev->dev,
1187                                CPUMEM_TO_DMA,
1188                                (void *)pDev->rx,
1189                                (void **)&pDev->_rx_hw,
1190                                pDev->rxbuf_size);
1191                }
1192        }
1193        return 0;
1194}
1195
1196static void grcan_free_buffers(struct grcan_priv *pDev, int rx, int tx)
1197{
1198  FUNCDBG();
1199
1200  if ( tx && pDev->_tx ){
1201    free(pDev->_tx);
1202    pDev->_tx = NULL;
1203    pDev->tx = NULL;
1204  }
1205
1206  if ( rx && pDev->_rx ){
1207    free(pDev->_rx);
1208    pDev->_rx = NULL;
1209    pDev->rx = NULL;
1210  }
1211}
1212
1213static rtems_device_driver grcan_initialize(
1214  rtems_device_major_number major,
1215  rtems_device_minor_number unused,
1216  void *arg
1217  )
1218{
1219        return RTEMS_SUCCESSFUL;
1220}
1221
1222static rtems_device_driver grcan_open(rtems_device_major_number major, rtems_device_minor_number minor, void *arg)
1223{
1224        struct grcan_priv *pDev;
1225        rtems_device_driver ret;
1226        struct drvmgr_dev *dev;
1227        union drvmgr_key_value *value;
1228
1229        FUNCDBG();
1230
1231        if ( drvmgr_get_dev(&grcan_drv_info.general, minor, &dev) ) {
1232                DBG("Wrong minor %d\n", minor);
1233                return RTEMS_INVALID_NAME;
1234        }
1235        pDev = (struct grcan_priv *)dev->priv;
1236
1237        /* Wait until we get semaphore */
1238        if (rtems_semaphore_obtain(pDev->dev_sem, RTEMS_WAIT, RTEMS_NO_TIMEOUT)
1239            != RTEMS_SUCCESSFUL) {
1240                return RTEMS_INTERNAL_ERROR;
1241        }
1242
1243        /* is device busy/taken? */
1244        if ( pDev->open ) {
1245                ret=RTEMS_RESOURCE_IN_USE;
1246                goto out;
1247        }
1248
1249        /* Mark device taken */
1250        pDev->open = 1;
1251
1252        pDev->txblock = pDev->rxblock = 1;
1253        pDev->txcomplete = pDev->rxcomplete = 0;
1254        pDev->started = 0;
1255        pDev->config_changed = 1;
1256        pDev->config.silent = 0;
1257        pDev->config.abort = 0;
1258        pDev->config.selection.selection = 0;
1259        pDev->config.selection.enable0 = 0;
1260        pDev->config.selection.enable1 = 1;
1261        pDev->flushing = 0;
1262        pDev->rx = pDev->_rx = NULL;
1263        pDev->tx = pDev->_tx = NULL;
1264        pDev->txbuf_adr = 0;
1265        pDev->rxbuf_adr = 0;
1266        pDev->txbuf_size = TX_BUF_SIZE;
1267        pDev->rxbuf_size = RX_BUF_SIZE;
1268
1269        /* Override default buffer sizes if available from bus resource */
1270        value = drvmgr_dev_key_get(pDev->dev, "txBufSize", DRVMGR_KT_INT);
1271        if ( value )
1272                pDev->txbuf_size = value->i;
1273
1274        value = drvmgr_dev_key_get(pDev->dev, "rxBufSize", DRVMGR_KT_INT);
1275        if ( value )
1276                pDev->rxbuf_size = value->i;
1277
1278        value = drvmgr_dev_key_get(pDev->dev, "txBufAdr", DRVMGR_KT_POINTER);
1279        if ( value )
1280                pDev->txbuf_adr = value->ptr;
1281
1282        value = drvmgr_dev_key_get(pDev->dev, "rxBufAdr", DRVMGR_KT_POINTER);
1283        if ( value )
1284                pDev->rxbuf_adr = value->ptr;
1285
1286        DBG("Defaulting to rxbufsize: %d, txbufsize: %d\n",RX_BUF_SIZE,TX_BUF_SIZE);
1287
1288        /* Default to accept all messages */
1289        pDev->afilter.mask = 0x00000000;
1290        pDev->afilter.code = 0x00000000;
1291
1292        /* Default to disable sync messages (only trigger when id is set to all ones) */
1293        pDev->sfilter.mask = 0xffffffff;
1294        pDev->sfilter.code = 0x00000000;
1295
1296        /* Calculate default timing register values */
1297        grcan_calc_timing(GRCAN_DEFAULT_BAUD,pDev->corefreq_hz,GRCAN_SAMPLING_POINT,&pDev->config.timing);
1298
1299        if ( grcan_alloc_buffers(pDev,1,1) ) {
1300                ret=RTEMS_NO_MEMORY;
1301                goto out;
1302        }
1303
1304        /* Clear statistics */
1305        memset(&pDev->stats,0,sizeof(struct grcan_stats));
1306
1307        ret = RTEMS_SUCCESSFUL;
1308out:
1309        rtems_semaphore_release(pDev->dev_sem);
1310        return ret;
1311}
1312
1313static rtems_device_driver grcan_close(rtems_device_major_number major, rtems_device_minor_number minor, void *arg)
1314{
1315        struct grcan_priv *pDev;
1316        struct drvmgr_dev *dev;
1317
1318        FUNCDBG();
1319
1320        if ( drvmgr_get_dev(&grcan_drv_info.general, minor, &dev) ) {
1321                return RTEMS_INVALID_NAME;
1322        }
1323        pDev = (struct grcan_priv *)dev->priv;
1324
1325        if ( pDev->started )
1326                grcan_stop(pDev);
1327
1328        grcan_hw_reset(pDev->regs);
1329
1330        grcan_free_buffers(pDev,1,1);
1331
1332        /* Mark Device as closed */
1333        pDev->open = 0;
1334
1335        return RTEMS_SUCCESSFUL;
1336}
1337
1338static rtems_device_driver grcan_read(rtems_device_major_number major, rtems_device_minor_number minor, void *arg)
1339{
1340        struct grcan_priv *pDev;
1341        struct drvmgr_dev *dev;
1342        rtems_libio_rw_args_t *rw_args; 
1343        CANMsg *dest;
1344        unsigned int count, left;
1345        int req_cnt;
1346
1347        FUNCDBG();
1348
1349        if ( drvmgr_get_dev(&grcan_drv_info.general, minor, &dev) ) {
1350                return RTEMS_INVALID_NAME;
1351        }
1352        pDev = (struct grcan_priv *)dev->priv;
1353
1354        rw_args = (rtems_libio_rw_args_t *) arg;
1355        dest = (CANMsg *) rw_args->buffer;
1356        req_cnt = rw_args->count / sizeof(CANMsg);
1357
1358        if ( (!dest) || (req_cnt<1) )
1359                return RTEMS_INVALID_NAME;
1360
1361        if ( !pDev->started )
1362                return RTEMS_RESOURCE_IN_USE;
1363
1364        /*FUNCDBG("grcan_read [%i,%i]: buf: 0x%x len: %i\n",major, minor, (unsigned int)rw_args->buffer,rw_args->count);*/
1365
1366        count = grcan_hw_read_try(pDev,pDev->regs,dest,req_cnt);
1367        if ( !( pDev->rxblock && pDev->rxcomplete && (count!=req_cnt) ) ){
1368                if ( count > 0 ) {
1369                        /* Successfully received messages (at least one) */
1370                        rw_args->bytes_moved = count * sizeof(CANMsg);
1371                        return RTEMS_SUCCESSFUL;
1372                }
1373
1374                /* nothing read, shall we block? */
1375                if ( !pDev->rxblock ) {
1376                        /* non-blocking mode */
1377                        rw_args->bytes_moved = 0;
1378                        return RTEMS_TIMEOUT;
1379                }
1380        }
1381
1382        while(count == 0 || (pDev->rxcomplete && (count!=req_cnt)) ){
1383
1384        if ( !pDev->rxcomplete ){
1385                left = 1; /* return as soon as there is one message available */
1386        }else{
1387                left = req_cnt - count;     /* return as soon as all data are available */
1388
1389                /* never wait for more than the half the maximum size of the receive buffer
1390                 * Why? We need some time to copy buffer before to catch up with hw,
1391                 * otherwise we would have to copy everything when the data has been
1392                 * received.
1393                 */
1394                if ( left > ((pDev->rxbuf_size/GRCAN_MSG_SIZE)/2) ){
1395                        left = (pDev->rxbuf_size/GRCAN_MSG_SIZE)/2;
1396                }
1397        }
1398
1399        if ( grcan_wait_rxdata(pDev,left) ) {
1400                /* The wait has been aborted, probably due to
1401                 * the device driver has been closed by another
1402                 * thread.
1403                 */
1404                rw_args->bytes_moved = count * sizeof(CANMsg);
1405                return RTEMS_UNSATISFIED;
1406        }
1407
1408        /* Try read bytes from circular buffer */
1409        count += grcan_hw_read_try(
1410                        pDev,
1411                        pDev->regs,
1412                        dest+count,
1413                        req_cnt-count);
1414        }
1415        /* no need to unmask IRQ as IRQ Handler do that for us. */
1416        rw_args->bytes_moved = count * sizeof(CANMsg);
1417        return RTEMS_SUCCESSFUL;
1418}
1419
1420static rtems_device_driver grcan_write(rtems_device_major_number major, rtems_device_minor_number minor, void *arg)
1421{
1422        struct grcan_priv *pDev;
1423        struct drvmgr_dev *dev;
1424        rtems_libio_rw_args_t *rw_args;
1425        CANMsg *source;
1426        unsigned int count, left;
1427        int req_cnt;
1428
1429        DBGC(DBG_TX,"\n");
1430
1431        if ( drvmgr_get_dev(&grcan_drv_info.general, minor, &dev) ) {
1432                return RTEMS_INVALID_NAME;
1433        }
1434        pDev = (struct grcan_priv *)dev->priv;
1435
1436        if ( !pDev->started || pDev->config.silent || pDev->flushing )
1437                return RTEMS_RESOURCE_IN_USE;
1438
1439        rw_args = (rtems_libio_rw_args_t *) arg;
1440        req_cnt = rw_args->count / sizeof(CANMsg);
1441        source = (CANMsg *) rw_args->buffer;
1442
1443        /* check proper length and buffer pointer */
1444        if (( req_cnt < 1) || (source == NULL) ){
1445                return RTEMS_INVALID_NAME;
1446        }
1447
1448        count = grcan_hw_write_try(pDev,pDev->regs,source,req_cnt);
1449        if ( !(pDev->txblock && pDev->txcomplete && (count!=req_cnt)) ) {
1450                if ( count > 0 ) {
1451                        /* Successfully transmitted chars (at least one char) */
1452                        rw_args->bytes_moved = count * sizeof(CANMsg);
1453                        return RTEMS_SUCCESSFUL;
1454                }
1455
1456                /* nothing written, shall we block? */
1457                if ( !pDev->txblock ) {
1458                        /* non-blocking mode */
1459                        rw_args->bytes_moved = 0;
1460                        return RTEMS_TIMEOUT;
1461                }
1462        }
1463
1464        /* if in txcomplete mode we need to transmit all chars */
1465        while((count == 0) || (pDev->txcomplete && (count!=req_cnt)) ){
1466                /*** block until room to fit all or as much of transmit buffer as possible
1467                 * IRQ comes. Set up a valid IRQ point so that an IRQ is received
1468                 * when we can put a chunk of data into transmit fifo
1469                 */
1470                if ( !pDev->txcomplete ){
1471                        left = 1; /* wait for anything to fit buffer */
1472                }else{
1473                        left = req_cnt - count; /* wait for all data to fit in buffer */
1474
1475                        /* never wait for more than the half the maximum size of the transmit
1476                         * buffer
1477                         * Why? We need some time to fill buffer before hw catches up.
1478                         */
1479                        if ( left > ((pDev->txbuf_size/GRCAN_MSG_SIZE)/2) ){
1480                                left = (pDev->txbuf_size/GRCAN_MSG_SIZE)/2;
1481                        }
1482                }
1483
1484                /* Wait until more room in transmit buffer */
1485                if ( grcan_wait_txspace(pDev,left) ){
1486                        /* The wait has been aborted, probably due to
1487                         * the device driver has been closed by another
1488                         * thread. To avoid deadlock we return directly
1489                         * with error status.
1490                         */
1491                        rw_args->bytes_moved = count * sizeof(CANMsg);
1492                        return RTEMS_UNSATISFIED;
1493                }
1494
1495                if ( pDev->txerror ){
1496                        /* Return number of bytes sent, compare write pointers */
1497                        pDev->txerror = 0;
1498#if 0 
1499#error HANDLE AMBA error
1500#endif
1501                }
1502
1503                /* Try read bytes from circular buffer */
1504                count += grcan_hw_write_try(
1505                        pDev,
1506                        pDev->regs,
1507                        source+count,
1508                        req_cnt-count);
1509        }
1510        /* no need to unmask IRQ as IRQ Handler do that for us. */
1511
1512        rw_args->bytes_moved = count * sizeof(CANMsg);
1513        return RTEMS_SUCCESSFUL;
1514}
1515
1516static rtems_device_driver grcan_ioctl(rtems_device_major_number major, rtems_device_minor_number minor, void *arg)
1517{
1518        struct grcan_priv *pDev;
1519        struct drvmgr_dev *dev;
1520        rtems_libio_ioctl_args_t *ioarg = (rtems_libio_ioctl_args_t *)arg;
1521        unsigned int *data = ioarg->buffer;
1522        struct grcan_timing timing;
1523        unsigned int speed;
1524        struct grcan_selection *selection;
1525        int tmp,ret;
1526        rtems_device_driver status;
1527        struct grcan_stats *stats;
1528        struct grcan_filter *filter;
1529        IRQ_GLOBAL_PREPARE(oldLevel);
1530
1531        FUNCDBG();
1532
1533        if ( drvmgr_get_dev(&grcan_drv_info.general, minor, &dev) ) {
1534                return RTEMS_INVALID_NAME;
1535        }
1536        pDev = (struct grcan_priv *)dev->priv;
1537
1538        if (!ioarg)
1539                return RTEMS_INVALID_NAME;
1540
1541        ioarg->ioctl_return = 0;
1542        switch(ioarg->command) {
1543                case GRCAN_IOC_START:
1544                if ( pDev->started )
1545                        return RTEMS_RESOURCE_IN_USE; /* EBUSY */
1546
1547                if ( (status=grcan_start(pDev)) != RTEMS_SUCCESSFUL ){
1548                        return status;
1549                }
1550                /* Read and write are now open... */
1551                pDev->started = 1;
1552
1553                /* Register interrupt routine and enable IRQ at IRQ ctrl */
1554                drvmgr_interrupt_register(dev, 0, "grcan", grcan_interrupt, pDev);
1555
1556                break;
1557
1558                case GRCAN_IOC_STOP:
1559                if ( !pDev->started )
1560                        return RTEMS_RESOURCE_IN_USE;
1561
1562                /* Disable interrupts */
1563                drvmgr_interrupt_unregister(dev, 0, grcan_interrupt, pDev);
1564
1565                grcan_stop(pDev);
1566                pDev->started = 0;
1567                break;
1568
1569                case GRCAN_IOC_ISSTARTED:
1570                if ( !pDev->started )
1571                        return RTEMS_RESOURCE_IN_USE;
1572                break;
1573
1574                case GRCAN_IOC_FLUSH:
1575                if ( !pDev->started || pDev->flushing || pDev->config.silent )
1576                        return RTEMS_RESOURCE_IN_USE;
1577
1578                pDev->flushing = 1;
1579                tmp = grcan_tx_flush(pDev);
1580                pDev->flushing = 0;
1581                if ( tmp ) {
1582                        /* The wait has been aborted, probably due to
1583                         * the device driver has been closed by another
1584                         * thread.
1585                         */
1586                        return RTEMS_UNSATISFIED;
1587                }
1588                break;
1589
1590#if 0
1591                /* Set physical link */
1592                case GRCAN_IOC_SET_LINK:
1593#ifdef REDUNDANT_CHANNELS
1594                if ( pDev->started )
1595                        return RTEMS_RESOURCE_IN_USE; /* EBUSY */
1596
1597                /* switch HW channel */
1598                pDev->channel = (unsigned int)ioargs->buffer;
1599#else
1600                return RTEMS_NOT_IMPLEMENTED;
1601#endif
1602                break;
1603#endif
1604
1605                case GRCAN_IOC_SET_SILENT:
1606                if ( pDev->started )
1607                        return RTEMS_RESOURCE_IN_USE;
1608                pDev->config.silent = (int)ioarg->buffer;
1609                pDev->config_changed = 1;
1610                break;
1611
1612                case GRCAN_IOC_SET_ABORT:
1613                if ( pDev->started )
1614                        return RTEMS_RESOURCE_IN_USE;
1615                pDev->config.abort = (int)ioarg->buffer;
1616                /* This Configuration parameter doesn't need HurriCANe reset
1617                 * ==> no pDev->config_changed = 1;
1618                 */
1619                break;
1620
1621                case GRCAN_IOC_SET_SELECTION:
1622                if ( pDev->started )
1623                        return RTEMS_RESOURCE_IN_USE;
1624
1625                selection = (struct grcan_selection *)ioarg->buffer;
1626                if ( !selection )
1627                        return RTEMS_INVALID_NAME;
1628
1629                pDev->config.selection = *selection;
1630                pDev->config_changed = 1;
1631                break;
1632
1633                case GRCAN_IOC_SET_RXBLOCK:
1634                pDev->rxblock = (int)ioarg->buffer;
1635                break;
1636
1637                case GRCAN_IOC_SET_TXBLOCK:
1638                pDev->txblock = (int)ioarg->buffer;
1639                break;
1640
1641                case GRCAN_IOC_SET_TXCOMPLETE:
1642                pDev->txcomplete = (int)ioarg->buffer;
1643                break;
1644
1645                case GRCAN_IOC_SET_RXCOMPLETE:
1646                pDev->rxcomplete = (int)ioarg->buffer;
1647                break;
1648
1649                case GRCAN_IOC_GET_STATS:
1650                stats = (struct grcan_stats *)ioarg->buffer;
1651                if ( !stats )
1652                        return RTEMS_INVALID_NAME;
1653                *stats = pDev->stats;
1654                break;
1655
1656                case GRCAN_IOC_CLR_STATS:
1657                IRQ_GLOBAL_DISABLE(oldLevel);
1658                memset(&pDev->stats,0,sizeof(struct grcan_stats));
1659                IRQ_GLOBAL_ENABLE(oldLevel);
1660                break;
1661
1662                case GRCAN_IOC_SET_SPEED:
1663                /* cannot change speed during run mode */
1664                if ( pDev->started )
1665                        return RTEMS_RESOURCE_IN_USE; /* EBUSY */
1666
1667                /* get speed rate from argument */
1668                speed = (unsigned int)ioarg->buffer;
1669                ret = grcan_calc_timing(speed, pDev->corefreq_hz, GRCAN_SAMPLING_POINT, &timing);
1670                if ( ret )
1671                        return  RTEMS_INVALID_NAME; /* EINVAL */
1672
1673                /* save timing/speed */
1674                pDev->config.timing = timing;
1675                pDev->config_changed = 1;
1676                break;
1677
1678                case GRCAN_IOC_SET_BTRS:
1679                /* Set BTR registers manually
1680                 * Read GRCAN/HurriCANe Manual.
1681                 */
1682                if ( pDev->started )
1683                        return RTEMS_RESOURCE_IN_USE; /* EBUSY */
1684                if ( !ioarg->buffer )
1685                        return RTEMS_INVALID_NAME;
1686
1687                pDev->config.timing = *(struct grcan_timing *)ioarg->buffer;
1688                pDev->config_changed = 1;
1689                break;
1690
1691                case GRCAN_IOC_SET_AFILTER:
1692                filter = (struct grcan_filter *)ioarg->buffer;
1693                if ( !filter ){
1694                        /* Disable filtering - let all messages pass */
1695                        pDev->afilter.mask = 0x0;
1696                        pDev->afilter.code = 0x0;
1697                }else{
1698                        /* Save filter */
1699                        pDev->afilter = *filter;
1700                }
1701                /* Set hardware acceptance filter */     
1702                grcan_hw_accept(pDev->regs,&pDev->afilter);
1703                break;
1704
1705                case GRCAN_IOC_SET_SFILTER:
1706                filter = (struct grcan_filter *)ioarg->buffer;
1707                if ( !filter ){
1708                        /* disable TX/RX SYNC filtering */
1709                        pDev->sfilter.mask = 0xffffffff; 
1710                        pDev->sfilter.mask = 0;
1711
1712                         /* disable Sync interrupt */
1713                        pDev->regs->imr = READ_REG(&pDev->regs->imr) & ~(GRCAN_RXSYNC_IRQ|GRCAN_TXSYNC_IRQ);
1714                }else{
1715                        /* Save filter */
1716                        pDev->sfilter = *filter;
1717
1718                        /* Enable Sync interrupt */
1719                        pDev->regs->imr = READ_REG(&pDev->regs->imr) | (GRCAN_RXSYNC_IRQ|GRCAN_TXSYNC_IRQ);
1720                }
1721                /* Set Sync RX/TX filter */
1722                grcan_hw_sync(pDev->regs,&pDev->sfilter);
1723                break;
1724
1725                case GRCAN_IOC_GET_STATUS:
1726                if ( !data )
1727                        return RTEMS_INVALID_NAME;
1728                /* Read out the statsu register from the GRCAN core */
1729                data[0] = READ_REG(&pDev->regs->stat);
1730                break;
1731
1732        default:
1733                return RTEMS_NOT_DEFINED;
1734        }
1735        return RTEMS_SUCCESSFUL;
1736}
1737
1738/* Handle the IRQ */
1739static void grcan_interrupt(void *arg)
1740{
1741        struct grcan_priv *pDev = arg;
1742        unsigned int status = READ_REG(&pDev->regs->pimsr);
1743        unsigned int canstat = READ_REG(&pDev->regs->stat);
1744
1745        /* Spurious IRQ call? */
1746        if ( !status && !canstat )
1747                return;
1748
1749        FUNCDBG();
1750
1751        /* Increment number of interrupts counter */
1752        pDev->stats.ints++;
1753
1754        if ( (status & GRCAN_ERR_IRQ) || (canstat & GRCAN_STAT_PASS) ){
1755                /* Error-Passive interrupt */
1756                pDev->stats.passive_cnt++;
1757        }
1758
1759        if ( (status & GRCAN_OFF_IRQ) || (canstat & GRCAN_STAT_OFF) ){
1760                /* Bus-off condition interrupt
1761                 * The link is brought down by hardware, we wake all threads
1762                 * that is blocked in read/write calls and stop futher calls
1763                 * to read/write until user has called ioctl(fd,START,0).
1764                 */
1765                pDev->started = 0;
1766                grcan_stop(pDev); /* this mask all IRQ sources */
1767                status=0x1ffff; /* clear all interrupts */
1768                goto out;
1769        }
1770
1771        if ( (status & GRCAN_OR_IRQ) || (canstat & GRCAN_STAT_OR) ){
1772                /* Over-run during reception interrupt */
1773                pDev->stats.overrun_cnt++;
1774        }
1775
1776        if ( (status & GRCAN_RXAHBERR_IRQ) ||
1777             (status & GRCAN_TXAHBERR_IRQ) ||
1778             (canstat & GRCAN_STAT_AHBERR) ){
1779                /* RX or Tx AHB Error interrupt */
1780                printk("AHBERROR: status: 0x%x, canstat: 0x%x\n",status,canstat);
1781                pDev->stats.ahberr_cnt++;
1782        }
1783
1784        if ( status & GRCAN_TXLOSS_IRQ ) {
1785                pDev->stats.txloss_cnt++;
1786        }
1787
1788        if ( status & GRCAN_RXIRQ_IRQ ){
1789                /* RX IRQ pointer interrupt */
1790                /*printk("RxIrq 0x%x\n",status);*/
1791                pDev->regs->imr = READ_REG(&pDev->regs->imr) & ~GRCAN_RXIRQ_IRQ;
1792                rtems_semaphore_release(pDev->rx_sem);
1793        }
1794
1795        if ( status & GRCAN_TXIRQ_IRQ ){
1796                /* TX IRQ pointer interrupt */
1797                pDev->regs->imr = READ_REG(&pDev->regs->imr) & ~GRCAN_TXIRQ_IRQ;
1798                rtems_semaphore_release(pDev->tx_sem);
1799        }
1800
1801        if ( status & GRCAN_TXSYNC_IRQ ){
1802                /* TxSync message transmitted interrupt */
1803                pDev->stats.txsync_cnt++;
1804        }
1805
1806        if ( status & GRCAN_RXSYNC_IRQ ){
1807                /* RxSync message received interrupt */
1808                pDev->stats.rxsync_cnt++;
1809        }
1810
1811        if ( status & GRCAN_TXEMPTY_IRQ ){
1812                pDev->regs->imr = READ_REG(&pDev->regs->imr) & ~GRCAN_TXEMPTY_IRQ;
1813                rtems_semaphore_release(pDev->txempty_sem);
1814        }
1815
1816out:
1817        /* Clear IRQs */
1818        pDev->regs->picr = status;
1819}
Note: See TracBrowser for help on using the repository browser.