diff options
Diffstat (limited to 'c/src/lib/libbsp/sparc/shared/can/grcan.c')
-rw-r--r-- | c/src/lib/libbsp/sparc/shared/can/grcan.c | 492 |
1 files changed, 246 insertions, 246 deletions
diff --git a/c/src/lib/libbsp/sparc/shared/can/grcan.c b/c/src/lib/libbsp/sparc/shared/can/grcan.c index 0eb08585be..c176490c68 100644 --- a/c/src/lib/libbsp/sparc/shared/can/grcan.c +++ b/c/src/lib/libbsp/sparc/shared/can/grcan.c @@ -1,5 +1,5 @@ /* - * GRCAN driver + * GRCAN driver * * COPYRIGHT (c) 2007. * Gaisler Research. @@ -55,15 +55,15 @@ #endif #ifndef IRQ_CLEAR_PENDING - #define IRQ_CLEAR_PENDING(irqno) + #define IRQ_CLEAR_PENDING(irqno) #endif #ifndef IRQ_UNMASK - #define IRQ_UNMASK(irqno) + #define IRQ_UNMASK(irqno) #endif #ifndef IRQ_MASK - #define IRQ_MASK(irqno) + #define IRQ_MASK(irqno) #endif #ifndef GRCAN_PREFIX @@ -116,53 +116,53 @@ #define BUFFER_ALIGNMENT_NEEDS 1024 #ifdef STATICALLY_ALLOCATED_TX_BUFFER -static unsigned int tx_circbuf[GRCAN_MAX_CORES][TX_BUF_SIZE] +static unsigned int tx_circbuf[GRCAN_MAX_CORES][TX_BUF_SIZE] __attribute__ ((aligned(BUFFER_ALIGNMENT_NEEDS))); #define STATIC_TX_BUF_SIZE TX_BUF_SIZE #define STATIC_TX_BUF_ADDR(core) (&tx_circbuf[(core)][0]) #endif #ifdef STATICALLY_ALLOCATED_RX_BUFFER -static unsigned int rx_circbuf[GRCAN_MAX_CORES][RX_BUF_SIZE] +static unsigned int rx_circbuf[GRCAN_MAX_CORES][RX_BUF_SIZE] __attribute__ ((aligned(BUFFER_ALIGNMENT_NEEDS))); #define STATIC_RX_BUF_SIZE RX_BUF_SIZE #define STATIC_RX_BUF_ADDR(core) (&rx_circbuf[(core)][0]) #endif -/* +/* * 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). * USE_AT697_DMA specifies whether the messages will be fetched using DMA or PIO. * * RASTA_PCI_BASE is the base address of the GRPCI AHB slave - * + * * GRCAN_BUF_SIZE must be set to the size (in bytes) of the GRCAN DMA buffers. * - * RX_QUEUE_SIZE defines the number of messages that fits in the RX message queue. On RX interrupts the messages in the DMA buffer + * RX_QUEUE_SIZE defines the number of messages that fits in the RX message queue. On RX interrupts the messages in the DMA buffer * are copied into the message queue (using dma if the rx buf is not in the AT697 ram). */ /*#define USE_AT697_RAM 1 */ -#define USE_AT697_DMA 1 -#define RASTA_PCI_BASE 0xe0000000 -#define GRCAN_BUF_SIZE 4096 -#define RX_QUEUE_SIZE 1024 +#define USE_AT697_DMA 1 +#define RASTA_PCI_BASE 0xe0000000 +#define GRCAN_BUF_SIZE 4096 +#define RX_QUEUE_SIZE 1024 #define INDEX(x) ( x&(RX_QUEUE_SIZE-1) ) -/* pa(x) +/* pa(x) * * x: address in AT697 address space - * + * * returns the address in the RASTA address space that can be used to access x with dma. - * + * */ #ifdef USE_AT697_RAM static inline unsigned int pa(unsigned int addr) { - return ((addr & 0x0fffffff) | RASTA_PCI_BASE); + return ((addr & 0x0fffffff) | RASTA_PCI_BASE); } #else static inline unsigned int pa(unsigned int addr) { - return ((addr & 0x0fffffff) | 0x40000000); + return ((addr & 0x0fffffff) | 0x40000000); } #endif @@ -188,7 +188,7 @@ struct grcan_priv { unsigned int channel; int flushing; unsigned int corefreq_hz; - + /* Circular DMA buffers */ void *_rx; void *_tx; @@ -200,13 +200,13 @@ struct grcan_priv { int txblock, rxblock; int txcomplete, rxcomplete; int txerror, rxerror; - + struct grcan_filter sfilter; struct grcan_filter afilter; int config_changed; /* 0=no changes, 1=changes ==> a Core reset is needed */ struct grcan_config config; struct grcan_stats stats; - + rtems_id rx_sem, tx_sem, txempty_sem, dev_sem; }; @@ -238,9 +238,9 @@ static unsigned int grcan_hw_write_try( int count); static void grcan_hw_config( - struct grcan_regs *regs, + struct grcan_regs *regs, struct grcan_config *conf); - + static void grcan_hw_accept( struct grcan_regs *regs, struct grcan_filter *afilter); @@ -302,13 +302,13 @@ static rtems_device_driver grcan_start(struct grcan_priv *pDev) { unsigned int tmp; IRQ_GLOBAL_PREPARE(oldLevel); - + FUNCDBG(); - + /* Check that memory has been allocated successfully */ if ( !pDev->tx || !pDev->rx ) return RTEMS_NO_MEMORY; - + /* Configure FIFO configuration register * and Setup timing */ @@ -320,37 +320,37 @@ static rtems_device_driver grcan_start(struct grcan_priv *pDev) /* Setup receiver */ pDev->regs->rx0addr = MEMAREA_TO_HW((unsigned int)pDev->rx); pDev->regs->rx0size = pDev->rxbuf_size; - + /* Setup Transmitter */ pDev->regs->tx0addr = MEMAREA_TO_HW((unsigned int)pDev->tx); pDev->regs->tx0size = pDev->txbuf_size; - + /* Setup acceptance filters */ grcan_hw_accept(pDev->regs,&pDev->afilter); - + /* Sync filters */ grcan_hw_sync(pDev->regs,&pDev->sfilter); - + /* Clear status bits */ tmp = READ_REG(&pDev->regs->stat); pDev->regs->stat = 0; - + /* Setup IRQ handling */ - - /* Clear all IRQs */ + + /* Clear all IRQs */ tmp = READ_REG(&pDev->regs->pir); pDev->regs->picr = 0x1ffff; - + /* unmask TxLoss|TxErrCntr|RxErrCntr|TxAHBErr|RxAHBErr|OR|OFF|PASS */ pDev->regs->imr = 0x1601f; - + /* Enable routing of the IRQs */ IRQ_GLOBAL_DISABLE(oldLevel); IRQ_UNMASK(pDev->irq+GRCAN_IRQ_TXSYNC); IRQ_UNMASK(pDev->irq+GRCAN_IRQ_RXSYNC); IRQ_UNMASK(pDev->irq+GRCAN_IRQ_IRQ); IRQ_GLOBAL_ENABLE(oldLevel); - + /* Reset some software data */ /*pDev->txerror = 0; pDev->rxerror = 0;*/ @@ -358,11 +358,11 @@ static rtems_device_driver grcan_start(struct grcan_priv *pDev) /* Enable receiver/transmitter */ pDev->regs->rx0ctrl = GRCAN_RXCTRL_ENABLE; pDev->regs->tx0ctrl = GRCAN_TXCTRL_ENABLE; - + /* Enable HurriCANe core */ pDev->regs->ctrl = GRCAN_CTRL_ENABLE; - - /* Leave transmitter disabled, it is enabled when + + /* Leave transmitter disabled, it is enabled when * trying to send something. */ return RTEMS_SUCCESSFUL; @@ -371,19 +371,19 @@ static rtems_device_driver grcan_start(struct grcan_priv *pDev) static void grcan_stop(struct grcan_priv *pDev) { FUNCDBG(); - + /* Mask all IRQs */ pDev->regs->imr = 0; IRQ_MASK(pDev->irq+GRCAN_IRQ_TXSYNC); IRQ_MASK(pDev->irq+GRCAN_IRQ_RXSYNC); IRQ_MASK(pDev->irq+GRCAN_IRQ_IRQ); - + /* Disable receiver & transmitter */ pDev->regs->rx0ctrl = 0; pDev->regs->tx0ctrl = 0; - + /* Reset semaphores to the initial state and wakeing - * all threads waiting for an IRQ. The threads that + * all threads waiting for an IRQ. The threads that * get woken up must check for RTEMS_UNSATISFIED in * order to determine that they should return to * user space with error status. @@ -394,40 +394,40 @@ static void grcan_stop(struct grcan_priv *pDev) } static void grcan_hw_config( - struct grcan_regs *regs, + struct grcan_regs *regs, struct grcan_config *conf ) { unsigned int config=0; - + /* Reset HurriCANe Core */ regs->ctrl = 0; - + if ( conf->silent ) config |= GRCAN_CFG_SILENT; - + if ( conf->abort ) config |= GRCAN_CFG_ABORT; - + if ( conf->selection.selection ) config |= GRCAN_CFG_SELECTION; - + if ( conf->selection.enable0 ) config |= GRCAN_CFG_ENABLE0; - + if ( conf->selection.enable1 ) config |= GRCAN_CFG_ENABLE1; - + /* Timing */ config |= (conf->timing.bpr<<GRCAN_CFG_BPR_BIT) & GRCAN_CFG_BPR; config |= (conf->timing.rsj<<GRCAN_CFG_RSJ_BIT) & GRCAN_CFG_RSJ; config |= (conf->timing.ps1<<GRCAN_CFG_PS1_BIT) & GRCAN_CFG_PS1; config |= (conf->timing.ps2<<GRCAN_CFG_PS2_BIT) & GRCAN_CFG_PS2; config |= (conf->timing.scaler<<GRCAN_CFG_SCALER_BIT) & GRCAN_CFG_SCALER; - + /* Write configuration */ regs->conf = config; - + /* Enable HurriCANe Core */ regs->ctrl = GRCAN_CTRL_ENABLE; } @@ -439,9 +439,9 @@ static void grcan_hw_accept( { /* Disable Sync mask totaly (if we change scode or smask * in an unfortunate way we may trigger a sync match) - */ + */ regs->rx0mask = 0xffffffff; - + /* Set Sync Filter in a controlled way */ regs->rx0code = afilter->code; regs->rx0mask = afilter->mask; @@ -454,9 +454,9 @@ static void grcan_hw_sync( { /* Disable Sync mask totaly (if we change scode or smask * in an unfortunate way we may trigger a sync match) - */ + */ regs->smask = 0xffffffff; - + /* Set Sync Filter in a controlled way */ regs->scode = sfilter->code; regs->smask = sfilter->mask; @@ -467,14 +467,14 @@ static unsigned int grcan_hw_rxavail( unsigned int wp, unsigned int size ) -{ +{ if ( rp == wp ) { - /* read pointer and write pointer is equal only + /* read pointer and write pointer is equal only * when RX buffer is empty. */ return 0; } - + if ( wp > rp ) { return (wp-rp)/GRCAN_MSG_SIZE; }else{ @@ -489,21 +489,21 @@ static unsigned int grcan_hw_txspace( ) { unsigned int left; - + if ( rp == wp ) { - /* read pointer and write pointer is equal only + /* read pointer and write pointer is equal only * when TX buffer is empty. */ return size/GRCAN_MSG_SIZE-WRAP_AROUND_TX_MSGS; } - + /* size - 4 - abs(read-write) */ if ( wp > rp ) { left = size-(wp-rp); }else{ left = rp-wp; } - + return left/GRCAN_MSG_SIZE-WRAP_AROUND_TX_MSGS; } @@ -535,7 +535,7 @@ static int grcan_calc_timing( int best_tseg=0, best_brp=0, best_rate=0, brp=0; int tseg=0, tseg1=0, tseg2=0; int sjw = 1; - + /* Default to 90% */ if ( (sampl_pt < 50) || (sampl_pt>99) ){ sampl_pt = GRCAN_SAMPLING_POINT; @@ -545,8 +545,8 @@ static int grcan_calc_timing( /* invalid speed mode */ return -1; } - - /* find best match, return -2 if no good reg + + /* find best match, return -2 if no good reg * combination is available for this frequency */ @@ -563,7 +563,7 @@ static int grcan_calc_timing( tseg++) { brp = core_hz / ((1 + tseg / 2) * baud) + tseg % 2; - if ((brp <= 0) || + if ((brp <= 0) || ( (brp > 256*1) && (brp <= 256*2) && (brp&0x1) ) || ( (brp > 256*2) && (brp <= 256*4) && (brp&0x3) ) || ( (brp > 256*4) && (brp <= 256*8) && (brp&0x7) ) || @@ -611,7 +611,7 @@ static int grcan_calc_timing( tseg1 = MAX_TSEG1; tseg2 = best_tseg - tseg1 - 2; } - + /* Get scaler and BRP from pseudo BRP */ if ( best_brp <= 256 ){ timing->scaler = best_brp; @@ -626,7 +626,7 @@ static int grcan_calc_timing( timing->scaler = ((best_brp+1)>>3) -1; timing->bpr = 3; } - + timing->ps1 = tseg1+1; timing->ps2 = tseg2; timing->rsj = sjw; @@ -637,7 +637,7 @@ static int grcan_calc_timing( static unsigned int grcan_hw_read_try( struct grcan_priv *pDev, struct grcan_regs *regs, - CANMsg *buffer, + CANMsg *buffer, int max ) { @@ -645,14 +645,14 @@ static unsigned int grcan_hw_read_try( CANMsg *dest; struct grcan_msg *source,tmp; unsigned int wp,rp,size,rxmax,addr,trunk_msg_cnt; - + FUNCDBG(); - + wp = READ_REG(®s->rx0wr); rp = READ_REG(®s->rx0rd); - + /* - * Due to hardware wrap around simplification write pointer will + * Due to hardware wrap around simplification write pointer will * never reach the read pointer, at least a gap of 8 bytes. * The only time they are equal is when the read pointer has * reached the write pointer (empty buffer) @@ -663,24 +663,24 @@ static unsigned int grcan_hw_read_try( * Read as much as possible from DMA buffer */ size = READ_REG(®s->rx0size); - + /* Get number of bytes available in RX buffer */ trunk_msg_cnt = grcan_hw_rxavail(rp,wp,size); - - /* truncate size if user space buffer hasn't room for + + /* truncate size if user space buffer hasn't room for * all received chars. */ if ( trunk_msg_cnt > max ) trunk_msg_cnt = max; - + /* Read until i is 0 */ i=trunk_msg_cnt; - + addr = (unsigned int)pDev->rx; source = (struct grcan_msg *)(addr + rp); dest = buffer; rxmax = addr + (size-GRCAN_MSG_SIZE); - + /* Read as many can messages as possible */ while(i>0){ /* Read CAN message from DMA buffer */ @@ -697,14 +697,14 @@ static unsigned int grcan_hw_read_try( dest->len = tmp.head[1] >> 28; for(j=0; j<dest->len; j++) dest->data[j] = READ_DMA_BYTE(&source->data[j]); - + /* wrap around if neccessary */ source = ( (unsigned int)source >= rxmax ) ? (struct grcan_msg *)addr : source+1; dest++; /* straight user buffer */ i--; } /* Increment Hardware READ pointer (mark read byte as read) - * ! wait for registers to be safely re-configurable + * ! wait for registers to be safely re-configurable */ regs->rx0ctrl = 0; /* DISABLE RX CHANNEL */ i=0; @@ -731,31 +731,31 @@ static unsigned int grcan_hw_write_try( int space_left; unsigned int tmp; int i; - + DBGC(DBG_TX,"\n"); /*FUNCDBG();*/ - + rp = READ_REG(®s->tx0rd); wp = READ_REG(®s->tx0wr); size = READ_REG(®s->tx0size); - + space_left = grcan_hw_txspace(rp,wp,size); - + /* is circular fifo full? */ if ( space_left < 1 ) return 0; - + /* Truncate size */ if ( space_left > count ) space_left = count; ret = space_left; - + addr = (unsigned int)pDev->tx; - + dest = (struct grcan_msg *)(addr + wp); source = (CANMsg *)buffer; txmax = addr + (size-GRCAN_MSG_SIZE); - + while ( space_left>0 ) { /* Convert and write CAN message to DMA buffer */ if ( source->extended ){ @@ -773,9 +773,9 @@ static unsigned int grcan_hw_write_try( dest = ((unsigned int)dest >= txmax) ? (struct grcan_msg *)addr : dest+1; space_left--; } - - /* Update write pointer - * ! wait for registers to be safely re-configurable + + /* Update write pointer + * ! wait for registers to be safely re-configurable */ regs->tx0ctrl = 0; /* DISABLE TX CHANNEL */ i=0; @@ -796,19 +796,19 @@ static int grcan_wait_rxdata( unsigned int irq_trunk, dataavail; int wait; IRQ_GLOBAL_PREPARE(oldLevel); - + FUNCDBG(); - /*** block until receive IRQ received - * Set up a valid IRQ point so that an IRQ is received + /*** block until receive IRQ received + * Set up a valid IRQ point so that an IRQ is received * when one or more messages are received */ IRQ_GLOBAL_DISABLE(oldLevel); - + size = READ_REG(&pDev->regs->rx0size); rp = READ_REG(&pDev->regs->rx0rd); wp = READ_REG(&pDev->regs->rx0wr); - + /**** Calculate IRQ Pointer ****/ irq = wp + min*GRCAN_MSG_SIZE; /* wrap irq around */ @@ -816,18 +816,18 @@ static int grcan_wait_rxdata( irq_trunk = irq-size; }else irq_trunk = irq; - + /* init IRQ HW */ pDev->regs->rx0irq = irq_trunk; - + /* Clear pending Rx IRQ */ pDev->regs->picr = GRCAN_RXIRQ_IRQ; - + wp = READ_REG(&pDev->regs->rx0wr); - + /* Calculate messages available */ dataavail = grcan_hw_rxavail(rp,wp,size); - + if ( dataavail < min ){ /* Still empty, proceed with sleep - Turn on IRQ (unmask irq) */ pDev->regs->imr = READ_REG(&pDev->regs->imr) | GRCAN_RXIRQ_IRQ; @@ -837,20 +837,20 @@ static int grcan_wait_rxdata( wait=0; } IRQ_GLOBAL_ENABLE(oldLevel); - + /* Wait for IRQ to fire only if has been triggered */ if ( wait ){ if ( rtems_semaphore_obtain(pDev->rx_sem, RTEMS_WAIT, RTEMS_NO_TIMEOUT) == RTEMS_UNSATISFIED ) return -1; /* Device driver has been closed or stopped, return with error status */ } - + return 0; } /* Wait until min bytes available in TX circular buffer. * The IRQ RxIrq is used to pin point the location of - * - * min must be at least WRAP_AROUND_TX_BYTES bytes less + * + * min must be at least WRAP_AROUND_TX_BYTES bytes less * than max buffer for this algo to work. * */ @@ -863,19 +863,19 @@ static int grcan_wait_txspace( unsigned int irq, rp, wp, size, space_left; unsigned int irq_trunk; IRQ_GLOBAL_PREPARE(oldLevel); - + DBGC(DBG_TX,"\n"); /*FUNCDBG();*/ - + IRQ_GLOBAL_DISABLE(oldLevel); /*pDev->regs->tx0ctrl = GRCAN_TXCTRL_ENABLE;*/ - + size = READ_REG(&pDev->regs->tx0size); - wp = READ_REG(&pDev->regs->tx0wr); - + wp = READ_REG(&pDev->regs->tx0wr); + rp = READ_REG(&pDev->regs->tx0rd); - + /**** Calculate IRQ Pointer ****/ irq = rp + min*GRCAN_MSG_SIZE; /* wrap irq around */ @@ -883,24 +883,24 @@ static int grcan_wait_txspace( irq_trunk = irq - size; }else irq_trunk = irq; - + /* trigger HW to do a IRQ when enough room in buffer */ pDev->regs->tx0irq = irq_trunk; - + /* Clear pending Tx IRQ */ pDev->regs->picr = GRCAN_TXIRQ_IRQ; - - /* One problem, if HW already gone past IRQ place the IRQ will + + /* One problem, if HW already gone past IRQ place the IRQ will * never be received resulting in a thread hang. We check if so * before proceeding. - * - * has the HW already gone past the IRQ generation place? + * + * has the HW already gone past the IRQ generation place? * == does min fit info tx buffer? */ rp = READ_REG(&pDev->regs->tx0rd); - + space_left = grcan_hw_txspace(rp,wp,size); - + if ( space_left < min ){ /* Still too full, proceed with sleep - Turn on IRQ (unmask irq) */ pDev->regs->imr = READ_REG(&pDev->regs->imr) | GRCAN_TXIRQ_IRQ; @@ -910,17 +910,17 @@ static int grcan_wait_txspace( wait=0; } IRQ_GLOBAL_ENABLE(oldLevel); - + /* Wait for IRQ to fire only if it has been triggered */ if ( wait ){ if ( rtems_semaphore_obtain(pDev->tx_sem, RTEMS_WAIT, 100) == RTEMS_UNSATISFIED ){ - /* Device driver has flushed us, this may be due to another thread has + /* Device driver has flushed us, this may be due to another thread has * closed the device, this is to avoid deadlock */ return -1; } } - + /* At this point the TxIRQ has been masked, we ned not to mask it */ return 0; } @@ -931,10 +931,10 @@ static int grcan_tx_flush(struct grcan_priv *pDev) unsigned int rp, wp; IRQ_GLOBAL_PREPARE(oldLevel); FUNCDBG(); - + /* loop until all data in circular buffer has been read by hw. * (write pointer != read pointer ) - * + * * Hardware doesn't update write pointer - we do */ while ( (wp=READ_REG(&pDev->regs->tx0wr)) != (rp=READ_REG(&pDev->regs->tx0rd)) ) { @@ -942,7 +942,7 @@ static int grcan_tx_flush(struct grcan_priv *pDev) IRQ_GLOBAL_DISABLE(oldLevel); /* Clear pending TXEmpty IRQ */ pDev->regs->picr = GRCAN_TXEMPTY_IRQ; - + if ( wp != READ_REG(&pDev->regs->tx0rd) ) { /* Still not empty, proceed with sleep - Turn on IRQ (unmask irq) */ pDev->regs->imr = READ_REG(&pDev->regs->imr) | GRCAN_TXEMPTY_IRQ; @@ -954,7 +954,7 @@ static int grcan_tx_flush(struct grcan_priv *pDev) IRQ_GLOBAL_ENABLE(oldLevel); if ( !wait ) break; - + /* Wait for IRQ to wake us */ if ( rtems_semaphore_obtain(pDev->txempty_sem, RTEMS_WAIT, RTEMS_NO_TIMEOUT) == RTEMS_UNSATISFIED ) { @@ -967,7 +967,7 @@ static int grcan_tx_flush(struct grcan_priv *pDev) static int grcan_alloc_buffers(struct grcan_priv *pDev, int rx, int tx) { FUNCDBG(); - + if ( tx ) { #ifdef STATIC_TX_BUF_ADDR pDev->_tx = STATIC_TX_BUF_ADDR(pDev->minor); @@ -984,11 +984,11 @@ static int grcan_alloc_buffers(struct grcan_priv *pDev, int rx, int tx) /* Align TX buffer */ pDev->tx = (struct grcan_msg *) - (((unsigned int)pDev->_tx + (BUFFER_ALIGNMENT_NEEDS-1)) & + (((unsigned int)pDev->_tx + (BUFFER_ALIGNMENT_NEEDS-1)) & ~(BUFFER_ALIGNMENT_NEEDS-1)); #endif } - + if ( rx ) { #ifdef STATIC_RX_BUF_ADDR pDev->_rx = STATIC_RX_BUF_ADDR(pDev->minor); @@ -1004,8 +1004,8 @@ static int grcan_alloc_buffers(struct grcan_priv *pDev, int rx, int tx) return -1; /* Align TX buffer */ - pDev->rx = (struct grcan_msg *) - (((unsigned int)pDev->_rx + (BUFFER_ALIGNMENT_NEEDS-1)) & + pDev->rx = (struct grcan_msg *) + (((unsigned int)pDev->_rx + (BUFFER_ALIGNMENT_NEEDS-1)) & ~(BUFFER_ALIGNMENT_NEEDS-1)); #endif } @@ -1015,7 +1015,7 @@ static int grcan_alloc_buffers(struct grcan_priv *pDev, int rx, int tx) static void grcan_free_buffers(struct grcan_priv *pDev, int rx, int tx) { FUNCDBG(); - + #ifndef STATIC_TX_BUF_ADDR if ( tx && pDev->_tx ){ free(pDev->_tx); @@ -1043,7 +1043,7 @@ static char *almalloc(int sz) #endif static rtems_device_driver grcan_initialize( - rtems_device_major_number major, + rtems_device_major_number major, rtems_device_minor_number unused, void *arg ) @@ -1059,9 +1059,9 @@ static rtems_device_driver grcan_initialize( printk("grcan_initialize()\n\r"); FUNCDBG(); - + /* find GRCAN cores */ - if ( !grcan_cores ) { + if ( !grcan_cores ) { grcan_core_cnt = amba_get_number_apbslv_devices(amba_bus,VENDOR_GAISLER,deviceid); if ( grcan_core_cnt < 1 ){ deviceid = GAISLER_GRCAN; @@ -1129,7 +1129,7 @@ static rtems_device_driver grcan_initialize( pDev->open = 0; pDev->corefreq_hz = sys_freq_hz; GRCAN_DEVNAME_NO(fs_name,minor); - + /* Find core address & IRQ */ if ( !grcan_cores ) { amba_find_next_apbslv(amba_bus,VENDOR_GAISLER,deviceid,&dev,minor); @@ -1139,28 +1139,28 @@ static rtems_device_driver grcan_initialize( pDev->irq = grcan_cores[minor].irq; pDev->regs = (struct grcan_regs *)grcan_cores[minor].base_address; } - + printk("Registering GRCAN core at [0x%x] irq %d, minor %d as %s\n\r",pDev->regs,pDev->irq,minor,fs_name); - + status = rtems_io_register_name(fs_name, major, 0); if (status != RTEMS_SUCCESSFUL) rtems_fatal_error_occurred(status); - + /* Reset Hardware before attaching IRQ handler */ grcan_hw_reset(pDev->regs); - + /* Register interrupt handler */ GRCAN_REG_INT(GRCAN_PREFIX(_interrupt_handler), pDev->irq+GRCAN_IRQ_IRQ, pDev); /* GRCAN_REG_INT(grcan_interrupt_handler, pDev->irq+GRCAN_IRQ_TXSYNC, pDev); GRCAN_REG_INT(grcan_interrupt_handler, pDev->irq+GRCAN_IRQ_RXSYNC, pDev); */ - + /* RX Semaphore created with count = 0 */ if ( rtems_semaphore_create(rtems_build_name('G', 'C', 'R', '0'+minor), 0, RTEMS_FIFO|RTEMS_SIMPLE_BINARY_SEMAPHORE|RTEMS_NO_INHERIT_PRIORITY|\ - RTEMS_LOCAL|RTEMS_NO_PRIORITY_CEILING, + RTEMS_LOCAL|RTEMS_NO_PRIORITY_CEILING, 0, &pDev->rx_sem) != RTEMS_SUCCESSFUL ) return RTEMS_INTERNAL_ERROR; @@ -1169,7 +1169,7 @@ static rtems_device_driver grcan_initialize( if ( rtems_semaphore_create(rtems_build_name('G', 'C', 'T', '0'+minor), 0, RTEMS_FIFO|RTEMS_SIMPLE_BINARY_SEMAPHORE|RTEMS_NO_INHERIT_PRIORITY|\ - RTEMS_LOCAL|RTEMS_NO_PRIORITY_CEILING, + RTEMS_LOCAL|RTEMS_NO_PRIORITY_CEILING, 0, &pDev->tx_sem) != RTEMS_SUCCESSFUL ) return RTEMS_INTERNAL_ERROR; @@ -1178,7 +1178,7 @@ static rtems_device_driver grcan_initialize( if ( rtems_semaphore_create(rtems_build_name('G', 'C', 'E', '0'+minor), 0, RTEMS_FIFO|RTEMS_SIMPLE_BINARY_SEMAPHORE|RTEMS_NO_INHERIT_PRIORITY|\ - RTEMS_LOCAL|RTEMS_NO_PRIORITY_CEILING, + RTEMS_LOCAL|RTEMS_NO_PRIORITY_CEILING, 0, &pDev->txempty_sem) != RTEMS_SUCCESSFUL ) return RTEMS_INTERNAL_ERROR; @@ -1199,14 +1199,14 @@ static rtems_device_driver grcan_initialize( static rtems_device_driver grcan_open(rtems_device_major_number major, rtems_device_minor_number minor, void *arg) { struct grcan_priv *pDev; rtems_device_driver ret; - + FUNCDBG(); if ( (minor < 0) || (minor>=grcan_core_cnt) ) { DBG("Wrong minor %d\n", minor); return RTEMS_INVALID_NUMBER; } - + pDev = &grcans[minor]; /* Wait until we get semaphore */ @@ -1214,7 +1214,7 @@ static rtems_device_driver grcan_open(rtems_device_major_number major, rtems_dev RTEMS_SUCCESSFUL ){ return RTEMS_INTERNAL_ERROR; } - + /* is device busy/taken? */ if ( pDev->open ) { ret=RTEMS_RESOURCE_IN_USE; @@ -1239,26 +1239,26 @@ static rtems_device_driver grcan_open(rtems_device_major_number major, rtems_dev pDev->txbuf_size = TX_BUF_SIZE; pDev->rxbuf_size = RX_BUF_SIZE; printk("Defaulting to rxbufsize: %d, txbufsize: %d\n",RX_BUF_SIZE,TX_BUF_SIZE); - + /* Default to accept all messages */ pDev->afilter.mask = 0x00000000; pDev->afilter.code = 0x00000000; - + /* Default to disable sync messages (only trigger when id is set to all ones) */ pDev->sfilter.mask = 0xffffffff; pDev->sfilter.code = 0x00000000; - + /* Calculate default timing register values */ grcan_calc_timing(GRCAN_DEFAULT_BAUD,pDev->corefreq_hz,GRCAN_SAMPLING_POINT,&pDev->config.timing); - + if ( grcan_alloc_buffers(pDev,1,1) ) { ret=RTEMS_NO_MEMORY; goto out; } - + /* Clear statistics */ memset(&pDev->stats,0,sizeof(struct grcan_stats)); - + ret = RTEMS_SUCCESSFUL; out: rtems_semaphore_release(pDev->dev_sem); @@ -1268,16 +1268,16 @@ out: static rtems_device_driver grcan_close(rtems_device_major_number major, rtems_device_minor_number minor, void *arg) { struct grcan_priv *pDev = &grcans[minor]; - + FUNCDBG(); - + if ( pDev->started ) grcan_stop(pDev); - + grcan_hw_reset(pDev->regs); - + grcan_free_buffers(pDev,1,1); - + /* Mark Device as closed */ pDev->open = 0; @@ -1287,25 +1287,25 @@ static rtems_device_driver grcan_close(rtems_device_major_number major, rtems_de static rtems_device_driver grcan_read(rtems_device_major_number major, rtems_device_minor_number minor, void *arg) { struct grcan_priv *pDev = &grcans[minor]; - rtems_libio_rw_args_t *rw_args; + rtems_libio_rw_args_t *rw_args; CANMsg *dest; unsigned int count, left; int req_cnt; - + rw_args = (rtems_libio_rw_args_t *) arg; dest = (CANMsg *) rw_args->buffer; req_cnt = rw_args->count / sizeof(CANMsg); FUNCDBG(); - + if ( (!dest) || (req_cnt<1) ) return RTEMS_INVALID_NAME; - + if ( !pDev->started ) return RTEMS_RESOURCE_IN_USE; /* FUNCDBG("grcan_read [%i,%i]: buf: 0x%x len: %i\n",major, minor, (unsigned int)rw_args->buffer,rw_args->count);*/ - + count = grcan_hw_read_try(pDev,pDev->regs,dest,req_cnt); if ( !( pDev->rxblock && pDev->rxcomplete && (count!=req_cnt) ) ){ if ( count > 0 ) { @@ -1313,7 +1313,7 @@ static rtems_device_driver grcan_read(rtems_device_major_number major, rtems_dev rw_args->bytes_moved = count * sizeof(CANMsg); return RTEMS_SUCCESSFUL; } - + /* nothing read, shall we block? */ if ( !pDev->rxblock ) { /* non-blocking mode */ @@ -1323,13 +1323,13 @@ static rtems_device_driver grcan_read(rtems_device_major_number major, rtems_dev } while(count == 0 || (pDev->rxcomplete && (count!=req_cnt)) ){ - + if ( !pDev->rxcomplete ){ left = 1; /* return as soon as there is one message available */ }else{ left = req_cnt - count; /* return as soon as all data are available */ - /* never wait for more than the half the maximum size of the receive buffer + /* never wait for more than the half the maximum size of the receive buffer * Why? We need some time to copy buffer before to catch up with hw, otherwise * we would have to copy everything when the data has been received. */ @@ -1339,14 +1339,14 @@ static rtems_device_driver grcan_read(rtems_device_major_number major, rtems_dev } if ( grcan_wait_rxdata(pDev,left) ) { - /* The wait has been aborted, probably due to + /* The wait has been aborted, probably due to * the device driver has been closed by another * thread. */ rw_args->bytes_moved = count * sizeof(CANMsg); return RTEMS_UNSATISFIED; } - + /* Try read bytes from circular buffer */ count += grcan_hw_read_try( pDev, @@ -1358,7 +1358,7 @@ static rtems_device_driver grcan_read(rtems_device_major_number major, rtems_dev rw_args->bytes_moved = count * sizeof(CANMsg); return RTEMS_SUCCESSFUL; } - + static rtems_device_driver grcan_write(rtems_device_major_number major, rtems_device_minor_number minor, void *arg) { struct grcan_priv *pDev = &grcans[minor]; @@ -1366,22 +1366,22 @@ static rtems_device_driver grcan_write(rtems_device_major_number major, rtems_de CANMsg *source; unsigned int count, left; int req_cnt; - + DBGC(DBG_TX,"\n"); /*FUNCDBG();*/ - + if ( !pDev->started || pDev->config.silent || pDev->flushing ) return RTEMS_RESOURCE_IN_USE; - + rw_args = (rtems_libio_rw_args_t *) arg; req_cnt = rw_args->count / sizeof(CANMsg); source = (CANMsg *) rw_args->buffer; - + /* check proper length and buffer pointer */ if (( req_cnt < 1) || (source == NULL) ){ return RTEMS_INVALID_NAME; } - + count = grcan_hw_write_try(pDev,pDev->regs,source,req_cnt); if ( !(pDev->txblock && pDev->txcomplete && (count!=req_cnt)) ) { if ( count > 0 ) { @@ -1389,7 +1389,7 @@ static rtems_device_driver grcan_write(rtems_device_major_number major, rtems_de rw_args->bytes_moved = count * sizeof(CANMsg); return RTEMS_SUCCESSFUL; } - + /* nothing written, shall we block? */ if ( !pDev->txblock ) { /* non-blocking mode */ @@ -1397,29 +1397,29 @@ static rtems_device_driver grcan_write(rtems_device_major_number major, rtems_de return RTEMS_TIMEOUT; } } - + /* if in txcomplete mode we need to transmit all chars */ while((count == 0) || (pDev->txcomplete && (count!=req_cnt)) ){ /*** block until room to fit all or as much of transmit buffer as possible IRQ comes - * Set up a valid IRQ point so that an IRQ is received + * Set up a valid IRQ point so that an IRQ is received * when we can put a chunk of data into transmit fifo */ if ( !pDev->txcomplete ){ left = 1; /* wait for anything to fit buffer */ }else{ left = req_cnt - count; /* wait for all data to fit in buffer */ - - /* never wait for more than the half the maximum size of the transmitt buffer + + /* never wait for more than the half the maximum size of the transmitt buffer * Why? We need some time to fill buffer before hw catches up. */ if ( left > ((pDev->txbuf_size/GRCAN_MSG_SIZE)/2) ){ left = (pDev->txbuf_size/GRCAN_MSG_SIZE)/2; } } - + /* Wait until more room in transmit buffer */ if ( grcan_wait_txspace(pDev,left) ){ - /* The wait has been aborted, probably due to + /* The wait has been aborted, probably due to * the device driver has been closed by another * thread. To avoid deadlock we return directly * with error status. @@ -1427,15 +1427,15 @@ static rtems_device_driver grcan_write(rtems_device_major_number major, rtems_de rw_args->bytes_moved = count * sizeof(CANMsg); return RTEMS_UNSATISFIED; } - + if ( pDev->txerror ){ /* Return number of bytes sent, compare write pointers */ pDev->txerror = 0; -#if 0 +#if 0 #error HANDLE AMBA error #endif } - + /* Try read bytes from circular buffer */ count += grcan_hw_write_try( pDev, @@ -1444,7 +1444,7 @@ static rtems_device_driver grcan_write(rtems_device_major_number major, rtems_de req_cnt-count); } /* no need to unmask IRQ as IRQ Handler do that for us. */ - + rw_args->bytes_moved = count * sizeof(CANMsg); return RTEMS_SUCCESSFUL; } @@ -1462,9 +1462,9 @@ static rtems_device_driver grcan_ioctl(rtems_device_major_number major, rtems_de struct grcan_stats *stats; struct grcan_filter *filter; IRQ_GLOBAL_PREPARE(oldLevel); - + FUNCDBG(); - + if (!ioarg) return RTEMS_INVALID_NAME; @@ -1473,50 +1473,50 @@ static rtems_device_driver grcan_ioctl(rtems_device_major_number major, rtems_de case GRCAN_IOC_START: if ( pDev->started ) return RTEMS_RESOURCE_IN_USE; /* EBUSY */ - + if ( (status=grcan_start(pDev)) != RTEMS_SUCCESSFUL ){ return status; } /* Read and write are now open... */ pDev->started = 1; break; - + case GRCAN_IOC_STOP: if ( !pDev->started ) return RTEMS_RESOURCE_IN_USE; - + grcan_stop(pDev); pDev->started = 0; break; - + case GRCAN_IOC_ISSTARTED: if ( !pDev->started ) return RTEMS_RESOURCE_IN_USE; break; - + case GRCAN_IOC_FLUSH: if ( !pDev->started || pDev->flushing || pDev->config.silent ) return RTEMS_RESOURCE_IN_USE; - + pDev->flushing = 1; tmp = grcan_tx_flush(pDev); pDev->flushing = 0; if ( tmp ) { - /* The wait has been aborted, probably due to + /* The wait has been aborted, probably due to * the device driver has been closed by another * thread. */ return RTEMS_UNSATISFIED; } break; - -#if 0 + +#if 0 /* Set physical link */ case GRCAN_IOC_SET_LINK: #ifdef REDUNDANT_CHANNELS if ( pDev->started ) return RTEMS_RESOURCE_IN_USE; /* EBUSY */ - + /* switch HW channel */ pDev->channel = (unsigned int)ioargs->buffer; #else @@ -1530,17 +1530,17 @@ static rtems_device_driver grcan_ioctl(rtems_device_major_number major, rtems_de return RTEMS_RESOURCE_IN_USE; pDev->config.silent = (int)ioarg->buffer; pDev->config_changed = 1; - break; + break; case GRCAN_IOC_SET_ABORT: if ( pDev->started ) return RTEMS_RESOURCE_IN_USE; pDev->config.abort = (int)ioarg->buffer; - /* This Configuration parameter doesn't need HurriCANe reset + /* This Configuration parameter doesn't need HurriCANe reset * ==> no pDev->config_changed = 1; */ break; - + case GRCAN_IOC_SET_SELECTION: if ( pDev->started ) return RTEMS_RESOURCE_IN_USE; @@ -1548,19 +1548,19 @@ static rtems_device_driver grcan_ioctl(rtems_device_major_number major, rtems_de selection = (struct grcan_selection *)ioarg->buffer; if ( !selection ) return RTEMS_INVALID_NAME; - + pDev->config.selection = *selection; pDev->config_changed = 1; break; - + case GRCAN_IOC_SET_RXBLOCK: pDev->rxblock = (int)ioarg->buffer; break; - + case GRCAN_IOC_SET_TXBLOCK: pDev->txblock = (int)ioarg->buffer; break; - + case GRCAN_IOC_SET_TXCOMPLETE: pDev->txcomplete = (int)ioarg->buffer; break; @@ -1568,14 +1568,14 @@ static rtems_device_driver grcan_ioctl(rtems_device_major_number major, rtems_de case GRCAN_IOC_SET_RXCOMPLETE: pDev->rxcomplete = (int)ioarg->buffer; break; - + case GRCAN_IOC_GET_STATS: stats = (struct grcan_stats *)ioarg->buffer; if ( !stats ) return RTEMS_INVALID_NAME; *stats = pDev->stats; break; - + case GRCAN_IOC_CLR_STATS: IRQ_GLOBAL_DISABLE(oldLevel); memset(&pDev->stats,0,sizeof(struct grcan_stats)); @@ -1583,36 +1583,36 @@ static rtems_device_driver grcan_ioctl(rtems_device_major_number major, rtems_de break; case GRCAN_IOC_SET_SPEED: - + /* cannot change speed during run mode */ if ( pDev->started ) return RTEMS_RESOURCE_IN_USE; /* EBUSY */ - + /* get speed rate from argument */ speed = (unsigned int)ioarg->buffer; ret = grcan_calc_timing(speed,pDev->corefreq_hz,GRCAN_SAMPLING_POINT,&timing); if ( ret ) return RTEMS_INVALID_NAME; /* EINVAL */ - + /* save timing/speed */ pDev->config.timing = timing; pDev->config_changed = 1; break; - + case GRCAN_IOC_SET_BTRS: - /* Set BTR registers manually + /* Set BTR registers manually * Read GRCAN/HurriCANe Manual. */ if ( pDev->started ) return RTEMS_RESOURCE_IN_USE; /* EBUSY */ - + if ( !ioarg->buffer ) return RTEMS_INVALID_NAME; - + pDev->config.timing = *(struct grcan_timing *)ioarg->buffer; pDev->config_changed = 1; break; - + case GRCAN_IOC_SET_AFILTER: filter = (struct grcan_filter *)ioarg->buffer; if ( !filter ){ @@ -1623,23 +1623,23 @@ static rtems_device_driver grcan_ioctl(rtems_device_major_number major, rtems_de /* Save filter */ pDev->afilter = *filter; } - /* Set hardware acceptance filter */ + /* Set hardware acceptance filter */ grcan_hw_accept(pDev->regs,&pDev->afilter); break; - + case GRCAN_IOC_SET_SFILTER: filter = (struct grcan_filter *)ioarg->buffer; if ( !filter ){ /* disable TX/RX SYNC filtering */ - pDev->sfilter.mask = 0xffffffff; + pDev->sfilter.mask = 0xffffffff; pDev->sfilter.mask = 0; - + /* disable Sync interrupt */ pDev->regs->imr = READ_REG(&pDev->regs->imr) & ~(GRCAN_RXSYNC_IRQ|GRCAN_TXSYNC_IRQ); }else{ /* Save filter */ pDev->sfilter = *filter; - + /* Enable Sync interrupt */ pDev->regs->imr = READ_REG(&pDev->regs->imr) | (GRCAN_RXSYNC_IRQ|GRCAN_TXSYNC_IRQ); } @@ -1653,7 +1653,7 @@ static rtems_device_driver grcan_ioctl(rtems_device_major_number major, rtems_de /* Read out the statsu register from the GRCAN core */ data[0] = READ_REG(&pDev->regs->stat); break; - + default: return RTEMS_NOT_DEFINED; } @@ -1679,23 +1679,23 @@ static void grcan_interrupt(struct grcan_priv *pDev) { unsigned int status = READ_REG(&pDev->regs->pimsr); unsigned int canstat = READ_REG(&pDev->regs->stat); - + /* Spurious IRQ call? */ if ( !status && !canstat ) return; - + FUNCDBG(); - + /* Increment number of interrupts counter */ pDev->stats.ints++; - + if ( (status & GRCAN_ERR_IRQ) || (canstat & GRCAN_STAT_PASS) ){ /* Error-Passive interrupt */ pDev->stats.passive_cnt++; } if ( (status & GRCAN_OFF_IRQ) || (canstat & GRCAN_STAT_OFF) ){ - /* Bus-off condition interrupt + /* Bus-off condition interrupt * The link is brought down by hardware, we wake all threads * that is blocked in read/write calls and stop futher calls * to read/write until user has called ioctl(fd,START,0). @@ -1705,12 +1705,12 @@ static void grcan_interrupt(struct grcan_priv *pDev) status=0x1ffff; /* clear all interrupts */ goto out; } - + if ( (status & GRCAN_OR_IRQ) || (canstat & GRCAN_STAT_OR) ){ /* Over-run during reception interrupt */ pDev->stats.overrun_cnt++; } - + if ( (status & GRCAN_RXAHBERR_IRQ) || (status & GRCAN_TXAHBERR_IRQ) || (canstat & GRCAN_STAT_AHBERR) ){ @@ -1718,40 +1718,40 @@ static void grcan_interrupt(struct grcan_priv *pDev) printk("AHBERROR: status: 0x%x, canstat: 0x%x\n",status,canstat); pDev->stats.ahberr_cnt++; } - + if ( status & GRCAN_TXLOSS_IRQ ) { pDev->stats.txloss_cnt++; } - + if ( status & GRCAN_RXIRQ_IRQ ){ /* RX IRQ pointer interrupt */ /*printk("RxIrq 0x%x\n",status);*/ pDev->regs->imr = READ_REG(&pDev->regs->imr) & ~GRCAN_RXIRQ_IRQ; rtems_semaphore_release(pDev->rx_sem); } - + if ( status & GRCAN_TXIRQ_IRQ ){ /* TX IRQ pointer interrupt */ pDev->regs->imr = READ_REG(&pDev->regs->imr) & ~GRCAN_TXIRQ_IRQ; rtems_semaphore_release(pDev->tx_sem); } - + if ( status & GRCAN_TXSYNC_IRQ ){ /* TxSync message transmitted interrupt */ pDev->stats.txsync_cnt++; } - + if ( status & GRCAN_RXSYNC_IRQ ){ /* RxSync message received interrupt */ pDev->stats.rxsync_cnt++; } - + if ( status & GRCAN_TXEMPTY_IRQ ){ pDev->regs->imr = READ_REG(&pDev->regs->imr) & ~GRCAN_TXEMPTY_IRQ; rtems_semaphore_release(pDev->txempty_sem); } - -out: + +out: /* Clear IRQs */ pDev->regs->picr = status; } @@ -1760,21 +1760,21 @@ static int grcan_register_internal(void) { rtems_status_code r; rtems_device_major_number m; - - if ((r = rtems_io_register_driver(0, &grcan_driver, &m)) != + + if ((r = rtems_io_register_driver(0, &grcan_driver, &m)) != RTEMS_SUCCESSFUL) { switch(r) { case RTEMS_TOO_MANY: - DBG2("failed RTEMS_TOO_MANY\n"); + DBG2("failed RTEMS_TOO_MANY\n"); break; case RTEMS_INVALID_NUMBER: - DBG2("failed RTEMS_INVALID_NUMBER\n"); + DBG2("failed RTEMS_INVALID_NUMBER\n"); break; case RTEMS_RESOURCE_IN_USE: - DBG2("failed RTEMS_RESOURCE_IN_USE\n"); + DBG2("failed RTEMS_RESOURCE_IN_USE\n"); break; default: - DBG("failed %i\n",r); + DBG("failed %i\n",r); break; } return 1; @@ -1788,7 +1788,7 @@ static int grcan_register_internal(void) int GRCAN_PREFIX(_register_abs)(struct grcan_device_info *devices, int dev_cnt) { FUNCDBG(); - + if ( !devices || (dev_cnt<0) ) return 1; grcan_cores = devices; @@ -1802,7 +1802,7 @@ int GRCAN_PREFIX(_register_abs)(struct grcan_device_info *devices, int dev_cnt) int GRCAN_PREFIX(_register)(amba_confarea_type *abus) { FUNCDBG(); - + if ( !abus ) return 1; amba_bus = abus; |