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

4.104.114.84.95
Last change on this file since 226455f was 226455f, checked in by Joel Sherrill <joel.sherrill@…>, on 09/06/07 at 13:27:25

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

New drivers: PCI, b1553BRM, SpaceWire?(GRSPW), CAN (GRCAN,OC_CAN),
Raw UART.

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