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

4.104.114.84.95
Last change on this file since 7459fbf was 7459fbf, checked in by Joel Sherrill <joel.sherrill@…>, on 09/12/07 at 15:38:57

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

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