diff options
Diffstat (limited to 'c/src/lib/libbsp/sparc/shared/can/occan.c')
-rw-r--r-- | c/src/lib/libbsp/sparc/shared/can/occan.c | 528 |
1 files changed, 264 insertions, 264 deletions
diff --git a/c/src/lib/libbsp/sparc/shared/can/occan.c b/c/src/lib/libbsp/sparc/shared/can/occan.c index 2a62f586f5..8b6dbfd32a 100644 --- a/c/src/lib/libbsp/sparc/shared/can/occan.c +++ b/c/src/lib/libbsp/sparc/shared/can/occan.c @@ -18,11 +18,11 @@ #include <rtems/bspIo.h> /* printk */ #include <leon.h> -#include <ambapp.h> +#include <ambapp.h> #include <occan.h> /* RTEMS -> ERRNO decoding table - + rtems_assoc_t errno_assoc[] = { { "OK", RTEMS_SUCCESSFUL, 0 }, { "BUSY", RTEMS_RESOURCE_IN_USE, EBUSY }, @@ -88,7 +88,7 @@ rtems_assoc_t errno_assoc[] = { #ifdef DEBUG #define DBG(fmt, vargs...) printk(fmt, ## vargs ) #else - #define DBG(fmt, vargs...) + #define DBG(fmt, vargs...) #endif /* fifo interface */ @@ -104,7 +104,7 @@ typedef struct { /* PELICAN */ #ifdef OCCAN_BYTE_REGS typedef struct { - unsigned char + unsigned char mode, cmd, status, @@ -120,7 +120,7 @@ typedef struct { errwarn, rx_err_cnt, tx_err_cnt, - rx_fi_xff; /* this is also acceptance code 0 in reset mode */ + rx_fi_xff; /* this is also acceptance code 0 in reset mode */ union{ struct { unsigned char id[2]; @@ -151,7 +151,7 @@ typedef struct { } pelican_regs; #else typedef struct { - unsigned char + unsigned char mode, unused0[3], cmd, unused1[3], status, unused2[3], @@ -167,7 +167,7 @@ typedef struct { errwarn,unused12[3], rx_err_cnt,unused13[3], tx_err_cnt,unused14[3], - rx_fi_xff, unused15[3]; /* this is also acceptance code 0 in reset mode */ + rx_fi_xff, unused15[3]; /* this is also acceptance code 0 in reset mode */ /* make sure to use pointers when writing (byte access) to these registers */ union{ struct { @@ -216,13 +216,13 @@ typedef struct { } occan_speed_regs; typedef struct { - /* hardware shortcuts */ + /* hardware shortcuts */ pelican_regs *regs; int irq; occan_speed_regs timing; int channel; /* 0=default, 1=second bus */ int single_mode; - + /* driver state */ rtems_id devsem; rtems_id txsem; @@ -233,11 +233,11 @@ typedef struct { int txblk; unsigned int status; occan_stats stats; - + /* rx&tx fifos */ occan_fifo *rxfifo; occan_fifo *txfifo; - + /* Config */ unsigned int speed; /* speed in HZ */ unsigned char acode[4]; @@ -393,7 +393,7 @@ static unsigned int sys_freq_hz; static void pelican_init(occan_priv *priv){ /* Reset core */ priv->regs->mode = PELICAN_MOD_RESET; - + /* wait for core to reset complete */ /*usleep(1);*/ } @@ -414,21 +414,21 @@ static void pelican_open(occan_priv *priv){ priv->amask[1] = 0xff; priv->amask[2] = 0xff; priv->amask[3] = 0xff; - + /* Set clock divider to extended mode, clkdiv not connected */ priv->regs->clkdiv = (1<<PELICAN_CDR_MODE_BITS) | (DEFAULT_CLKDIV & PELICAN_CDR_DIV); - + ret = occan_calc_speedregs(sys_freq_hz,priv->speed,&priv->timing); if ( ret ){ /* failed to set speed for this system freq, try with 50K instead */ priv->speed = OCCAN_SPEED_50K; occan_calc_speedregs(sys_freq_hz,priv->speed,&priv->timing); } - + /* disable all interrupts */ priv->regs->inten = 0; - + /* clear pending interrupts by reading */ tmp = READ_REG(&priv->regs->intflags); } @@ -436,22 +436,22 @@ static void pelican_open(occan_priv *priv){ static int pelican_start(occan_priv *priv){ unsigned char tmp; /* Start HW communication */ - + if ( !priv->rxfifo || !priv->txfifo ) return -1; /* In case we were started before and stopped we - * should empty the TX fifo or try to resend those + * should empty the TX fifo or try to resend those * messages. We make it simple... */ occan_fifo_clr(priv->txfifo); - + /* Clear status bits */ priv->status = 0; - + /* clear pending interrupts */ tmp = READ_REG(&priv->regs->intflags); - + /* clear error counters */ priv->regs->rx_err_cnt = 0; priv->regs->tx_err_cnt = 0; @@ -467,28 +467,28 @@ static int pelican_start(occan_priv *priv){ #endif /* set the speed regs of the CAN core */ occan_set_speedregs(priv,&priv->timing); - + DBG("OCCAN: start: set timing regs btr0: 0x%x, btr1: 0x%x\n\r",READ_REG(&priv->regs->bustim0),READ_REG(&priv->regs->bustim1)); - + /* Set default acceptance filter */ pelican_set_accept(priv,priv->acode,priv->amask); /* turn on interrupts */ priv->regs->inten = PELICAN_IE_RX | PELICAN_IE_TX | PELICAN_IE_ERRW | PELICAN_IE_ERRP | PELICAN_IE_BUS; - + #ifdef DEBUG /* print setup before starting */ pelican_regs_print(priv->regs); occan_stat_print(&priv->stats); #endif - - /* core already in reset mode, - * ¤ Exit reset mode + + /* core already in reset mode, + * ¤ Exit reset mode * ¤ Enter Single/Dual mode filtering. */ priv->regs->mode = (priv->single_mode << 3); - + return 0; } @@ -500,38 +500,38 @@ static void pelican_stop(occan_priv *priv){ pelican_regs_print(priv->regs); occan_stat_print(&priv->stats); #endif - + /* put core in reset mode */ priv->regs->mode = PELICAN_MOD_RESET; /* turn off interrupts */ priv->regs->inten = 0; - + priv->status |= OCCAN_STATUS_RESET; } -/* Try to send message "msg", if hardware txfifo is +/* Try to send message "msg", if hardware txfifo is * full, then -1 is returned. * - * Be sure to have disabled CAN interrupts when + * Be sure to have disabled CAN interrupts when * entering this function. */ static int pelican_send(occan_priv *can, CANMsg *msg){ unsigned char tmp,status; pelican_regs *regs = can->regs; - + /* is there room in send buffer? */ status = READ_REG(®s->status); if ( !(status & PELICAN_STAT_TXBUF) ){ /* tx fifo taken, we have to wait */ return -1; } - + tmp = msg->len & 0xf; if ( msg->rtr ) tmp |= 0x40; - + if ( msg->extended ){ /* Extended Frame */ regs->rx_fi_xff = 0x80 | tmp; @@ -553,7 +553,7 @@ static int pelican_send(occan_priv *can, CANMsg *msg){ WRITE_REG(®s->msg.tx_sff.data[tmp],msg->data[tmp]); } } - + /* let HW know of new message */ if ( msg->sshot ){ regs->cmd = PELICAN_CMD_TXREQ | PELICAN_CMD_ABORT; @@ -561,7 +561,7 @@ static int pelican_send(occan_priv *can, CANMsg *msg){ /* normal case -- try resend until sent */ regs->cmd = PELICAN_CMD_TXREQ; } - + return 0; } @@ -569,17 +569,17 @@ static int pelican_send(occan_priv *can, CANMsg *msg){ static void pelican_set_accept(occan_priv *priv, unsigned char *acode, unsigned char *amask){ unsigned char *acode0, *acode1, *acode2, *acode3; unsigned char *amask0, *amask1, *amask2, *amask3; - + acode0 = &priv->regs->rx_fi_xff; acode1 = (unsigned char *)&priv->regs->msg.rst_accept.code[0]; acode2 = (unsigned char *)&priv->regs->msg.rst_accept.code[1]; acode3 = (unsigned char *)&priv->regs->msg.rst_accept.code[2]; - + amask0 = (unsigned char *)&priv->regs->msg.rst_accept.mask[0]; amask1 = (unsigned char *)&priv->regs->msg.rst_accept.mask[1]; amask2 = (unsigned char *)&priv->regs->msg.rst_accept.mask[2]; amask3 = (unsigned char *)&priv->regs->msg.rst_accept.mask[3]; - + /* Set new mask & code */ *acode0 = acode[0]; *acode1 = acode[1]; @@ -617,7 +617,7 @@ static void pelican_regs_print(pelican_regs *regs){ printk(" AMR1: 0x%02x (0x%lx)\n\r",READ_REG(®s->msg.rst_accept.mask[1]),(unsigned int)®s->msg.rst_accept.mask[1]); printk(" AMR2: 0x%02x (0x%lx)\n\r",READ_REG(®s->msg.rst_accept.mask[2]),(unsigned int)®s->msg.rst_accept.mask[2]); printk(" AMR3: 0x%02x (0x%lx)\n\r",READ_REG(®s->msg.rst_accept.mask[3]),(unsigned int)®s->msg.rst_accept.mask[3]); - + }else{ printk(" RXFI_XFF: 0x%02x\n\r",READ_REG(®s->rx_fi_xff)); } @@ -645,7 +645,7 @@ static void pelican_regadr_print(pelican_regs *regs){ /* in reset mode it is possible to read acceptance filters */ printk(" RXFI_XFF: 0x%lx\n\r",(unsigned int)®s->rx_fi_xff); - + /* reset registers */ printk(" ACR0: 0x%lx\n\r",(unsigned int)®s->rx_fi_xff); printk(" ACR1: 0x%lx\n\r",(unsigned int)®s->msg.rst_accept.code[0]); @@ -655,7 +655,7 @@ static void pelican_regadr_print(pelican_regs *regs){ printk(" AMR1: 0x%lx\n\r",(unsigned int)®s->msg.rst_accept.mask[1]); printk(" AMR2: 0x%lx\n\r",(unsigned int)®s->msg.rst_accept.mask[2]); printk(" AMR3: 0x%lx\n\r",(unsigned int)®s->msg.rst_accept.mask[3]); - + /* TX Extended */ printk(" EFFTX_ID[0]: 0x%lx\n\r",(unsigned int)®s->msg.tx_eff.id[0]); printk(" EFFTX_ID[1]: 0x%lx\n\r",(unsigned int)®s->msg.tx_eff.id[1]); @@ -664,12 +664,12 @@ static void pelican_regadr_print(pelican_regs *regs){ printk(" EFFTX_DATA[0]: 0x%lx\n\r",(unsigned int)®s->msg.tx_eff.data[0]); printk(" EFFTX_DATA[1]: 0x%lx\n\r",(unsigned int)®s->msg.tx_eff.data[1]); - printk(" EFFTX_DATA[2]: 0x%lx\n\r",(unsigned int)®s->msg.tx_eff.data[2]); - printk(" EFFTX_DATA[3]: 0x%lx\n\r",(unsigned int)®s->msg.tx_eff.data[3]); - printk(" EFFTX_DATA[4]: 0x%lx\n\r",(unsigned int)®s->msg.tx_eff.data[4]); - printk(" EFFTX_DATA[5]: 0x%lx\n\r",(unsigned int)®s->msg.tx_eff.data[5]); - printk(" EFFTX_DATA[6]: 0x%lx\n\r",(unsigned int)®s->msg.tx_eff.data[6]); - printk(" EFFTX_DATA[7]: 0x%lx\n\r",(unsigned int)®s->msg.tx_eff.data[7]); + printk(" EFFTX_DATA[2]: 0x%lx\n\r",(unsigned int)®s->msg.tx_eff.data[2]); + printk(" EFFTX_DATA[3]: 0x%lx\n\r",(unsigned int)®s->msg.tx_eff.data[3]); + printk(" EFFTX_DATA[4]: 0x%lx\n\r",(unsigned int)®s->msg.tx_eff.data[4]); + printk(" EFFTX_DATA[5]: 0x%lx\n\r",(unsigned int)®s->msg.tx_eff.data[5]); + printk(" EFFTX_DATA[6]: 0x%lx\n\r",(unsigned int)®s->msg.tx_eff.data[6]); + printk(" EFFTX_DATA[7]: 0x%lx\n\r",(unsigned int)®s->msg.tx_eff.data[7]); /* RX Extended */ printk(" EFFRX_ID[0]: 0x%lx\n\r",(unsigned int)®s->msg.rx_eff.id[0]); @@ -679,12 +679,12 @@ static void pelican_regadr_print(pelican_regs *regs){ printk(" EFFRX_DATA[0]: 0x%lx\n\r",(unsigned int)®s->msg.rx_eff.data[0]); printk(" EFFRX_DATA[1]: 0x%lx\n\r",(unsigned int)®s->msg.rx_eff.data[1]); - printk(" EFFRX_DATA[2]: 0x%lx\n\r",(unsigned int)®s->msg.rx_eff.data[2]); - printk(" EFFRX_DATA[3]: 0x%lx\n\r",(unsigned int)®s->msg.rx_eff.data[3]); - printk(" EFFRX_DATA[4]: 0x%lx\n\r",(unsigned int)®s->msg.rx_eff.data[4]); - printk(" EFFRX_DATA[5]: 0x%lx\n\r",(unsigned int)®s->msg.rx_eff.data[5]); - printk(" EFFRX_DATA[6]: 0x%lx\n\r",(unsigned int)®s->msg.rx_eff.data[6]); - printk(" EFFRX_DATA[7]: 0x%lx\n\r",(unsigned int)®s->msg.rx_eff.data[7]); + printk(" EFFRX_DATA[2]: 0x%lx\n\r",(unsigned int)®s->msg.rx_eff.data[2]); + printk(" EFFRX_DATA[3]: 0x%lx\n\r",(unsigned int)®s->msg.rx_eff.data[3]); + printk(" EFFRX_DATA[4]: 0x%lx\n\r",(unsigned int)®s->msg.rx_eff.data[4]); + printk(" EFFRX_DATA[5]: 0x%lx\n\r",(unsigned int)®s->msg.rx_eff.data[5]); + printk(" EFFRX_DATA[6]: 0x%lx\n\r",(unsigned int)®s->msg.rx_eff.data[6]); + printk(" EFFRX_DATA[7]: 0x%lx\n\r",(unsigned int)®s->msg.rx_eff.data[7]); /* RX Extended */ @@ -693,12 +693,12 @@ static void pelican_regadr_print(pelican_regs *regs){ printk(" SFFRX_DATA[0]: 0x%lx\n\r",(unsigned int)®s->msg.rx_sff.data[0]); printk(" SFFRX_DATA[1]: 0x%lx\n\r",(unsigned int)®s->msg.rx_sff.data[1]); - printk(" SFFRX_DATA[2]: 0x%lx\n\r",(unsigned int)®s->msg.rx_sff.data[2]); - printk(" SFFRX_DATA[3]: 0x%lx\n\r",(unsigned int)®s->msg.rx_sff.data[3]); - printk(" SFFRX_DATA[4]: 0x%lx\n\r",(unsigned int)®s->msg.rx_sff.data[4]); - printk(" SFFRX_DATA[5]: 0x%lx\n\r",(unsigned int)®s->msg.rx_sff.data[5]); - printk(" SFFRX_DATA[6]: 0x%lx\n\r",(unsigned int)®s->msg.rx_sff.data[6]); - printk(" SFFRX_DATA[7]: 0x%lx\n\r",(unsigned int)®s->msg.rx_sff.data[7]); + printk(" SFFRX_DATA[2]: 0x%lx\n\r",(unsigned int)®s->msg.rx_sff.data[2]); + printk(" SFFRX_DATA[3]: 0x%lx\n\r",(unsigned int)®s->msg.rx_sff.data[3]); + printk(" SFFRX_DATA[4]: 0x%lx\n\r",(unsigned int)®s->msg.rx_sff.data[4]); + printk(" SFFRX_DATA[5]: 0x%lx\n\r",(unsigned int)®s->msg.rx_sff.data[5]); + printk(" SFFRX_DATA[6]: 0x%lx\n\r",(unsigned int)®s->msg.rx_sff.data[6]); + printk(" SFFRX_DATA[7]: 0x%lx\n\r",(unsigned int)®s->msg.rx_sff.data[7]); /* TX Extended */ printk(" SFFTX_ID[0]: 0x%lx\n\r",(unsigned int)®s->msg.tx_sff.id[0]); @@ -756,8 +756,8 @@ static int occan_calc_speedregs(unsigned int clock_hz, unsigned int rate, occan_ /* 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 */ /* some heuristic specials */ @@ -823,14 +823,14 @@ static int occan_calc_speedregs(unsigned int clock_hz, unsigned int rate, occan_ result->btr0 = (sjw<<OCCAN_BUSTIM_SJW_BIT) | (best_brp&OCCAN_BUSTIM_BRP); result->btr1 = (0<<7) | (tseg2<<OCCAN_BUSTIM_TSEG2_BIT) | tseg1; - + return 0; } static int occan_set_speedregs(occan_priv *priv, occan_speed_regs *timing){ if ( !timing || !priv || !priv->regs) return -1; - + priv->regs->bustim0 = timing->btr0; priv->regs->bustim1 = timing->btr1; return 0; @@ -851,27 +851,27 @@ static unsigned int pelican_speed_auto_steplist [] = { static int pelican_speed_auto(occan_priv *priv){ return -1; - -#if 0 + +#if 0 int i=0; occan_speed_regs timing; unsigned int speed; unsigned char tmp; while ( (speed=pelican_speed_auto_steplist[i]) > 0){ - + /* Reset core */ priv->regs->mode = PELICAN_MOD_RESET; - + /* tell int handler about the auto speed detection test */ - - + + /* wait for a moment (10ms) */ /*usleep(10000);*/ - + /* No acceptance filter */ pelican_set_accept(priv); - + /* calc timing params for this */ if ( occan_calc_speedregs(sys_freq_hz,speed,&timing) ){ /* failed to get good timings for this frequency @@ -879,34 +879,34 @@ static int pelican_speed_auto(occan_priv *priv){ */ continue; } - + timing.sam = 0; - + /* set timing params for this speed */ occan_set_speedregs(priv,&timing); - + /* Empty previous messages in hardware RX fifo */ /* while( READ_REG(&priv->regs->) ){ - + } */ - + /* Clear pending interrupts */ tmp = READ_REG(&priv->regs->intflags); - + /* enable RX & ERR interrupt */ - priv->regs->inten = - + priv->regs->inten = + /* Get out of reset state */ priv->regs->mode = PELICAN_MOD_LISTEN; - + /* wait for frames or errors */ while(1){ /* sleep 10ms */ - + } - + } #endif } @@ -918,9 +918,9 @@ static rtems_device_driver occan_initialize(rtems_device_major_number major, rte occan_priv *can; char fs_name[20]; rtems_status_code status; - + strcpy(fs_name,OCCAN_DEVNAME); - + /* find device on amba bus */ dev_cnt = amba_get_number_ahbslv_devices(amba_bus,VENDOR_GAISLER,GAISLER_OCCAN); if ( dev_cnt < 1 ){ @@ -932,11 +932,11 @@ static rtems_device_driver occan_initialize(rtems_device_major_number major, rte /* Detect System Frequency from initialized timer */ #ifndef SYS_FREQ_HZ #if defined(LEON3) - /* LEON3: find timer address via AMBA Plug&Play info */ + /* LEON3: find timer address via AMBA Plug&Play info */ { amba_apb_device gptimer; LEON3_Timer_Regs_Map *tregs; - + if ( amba_find_apbslv(&amba_conf,VENDOR_GAISLER,GAISLER_GPTIMER,&gptimer) == 1 ){ tregs = (LEON3_Timer_Regs_Map *)gptimer.start; sys_freq_hz = (tregs->scaler_reload+1)*1000*1000; @@ -945,7 +945,7 @@ static rtems_device_driver occan_initialize(rtems_device_major_number major, rte sys_freq_hz = 40000000; /* Default to 40MHz */ printk("OCCAN: Failed to detect system frequency\n\r"); } - + } #elif defined(LEON2) /* LEON2: use hardcoded address to get to timer */ @@ -960,9 +960,9 @@ static rtems_device_driver occan_initialize(rtems_device_major_number major, rte /* Use hardcoded frequency */ sys_freq_hz = SYS_FREQ_HZ; #endif - + DBG("OCCAN: Detected %dHz system frequency\n\r",sys_freq_hz); - + /* OCCAN speciality: * Mulitple cores are supported through the same amba AHB interface. * The number of "sub cores" can be detected by decoding the AMBA @@ -971,48 +971,48 @@ static rtems_device_driver occan_initialize(rtems_device_major_number major, rte * * Now, lets detect sub cores. */ - + for(subcore_cnt=devi=0; devi<dev_cnt; devi++){ amba_find_next_ahbslv(amba_bus,VENDOR_GAISLER,GAISLER_OCCAN,&ambadev,devi); subcore_cnt += (ambadev.ver & 0x7)+1; } - + printk("OCCAN: Found %d devs, totally %d sub cores\n\r",dev_cnt,subcore_cnt); - + /* allocate memory for cores */ can_cores = subcore_cnt; cans = calloc(subcore_cnt*sizeof(occan_priv),1); - + minor=0; for(devi=0; devi<dev_cnt; devi++){ - + /* Get AHB device info */ amba_find_next_ahbslv(amba_bus,VENDOR_GAISLER,GAISLER_OCCAN,&ambadev,devi); subcores = (ambadev.ver & 0x7)+1; DBG("OCCAN: on dev %d found %d sub cores\n\r",devi,subcores); - + /* loop all subcores, at least 1 */ for(subi=0; subi<subcores; subi++){ can = &cans[minor]; #ifdef OCCAN_BYTE_REGS - /* regs is byte regs */ + /* regs is byte regs */ can->regs = (void *)(ambadev.start[0] + OCCAN_NCORE_OFS*subi); #else /* regs is word regs, accessed 0x100 from base address */ can->regs = (void *)(ambadev.start[0] + OCCAN_NCORE_OFS*subi+ OCCAN_WORD_REG_OFS); #endif - + /* remember IRQ number */ can->irq = ambadev.irq+subi; - + /* bind filesystem name to device */ OCCAN_DEVNAME_NO(fs_name,minor); printk("OCCAN: Registering %s to [%d %d] @ 0x%lx irq %d\n\r",fs_name,major,minor,(unsigned int)can->regs,can->irq); status = rtems_io_register_name(fs_name, major, minor); if (RTEMS_SUCCESSFUL != status ) rtems_fatal_error_occurred(status); - + /* initialize software */ can->open = 0; can->rxfifo = NULL; @@ -1022,7 +1022,7 @@ static rtems_device_driver occan_initialize(rtems_device_major_number major, rte 1, RTEMS_FIFO | RTEMS_SIMPLE_BINARY_SEMAPHORE | RTEMS_NO_INHERIT_PRIORITY | \ RTEMS_NO_PRIORITY_CEILING, - 0, + 0, &can->devsem); if ( status != RTEMS_SUCCESSFUL ){ printk("OCCAN: Failed to create dev semaphore for minor %d, (%d)\n\r",minor,status); @@ -1030,10 +1030,10 @@ static rtems_device_driver occan_initialize(rtems_device_major_number major, rte } status = rtems_semaphore_create( rtems_build_name('C', 't', 'x', '0'+minor), - 0, + 0, RTEMS_FIFO | RTEMS_SIMPLE_BINARY_SEMAPHORE | RTEMS_NO_INHERIT_PRIORITY | \ RTEMS_NO_PRIORITY_CEILING, - 0, + 0, &can->txsem); if ( status != RTEMS_SUCCESSFUL ){ printk("OCCAN: Failed to create tx semaphore for minor %d, (%d)\n\r",minor,status); @@ -1041,7 +1041,7 @@ static rtems_device_driver occan_initialize(rtems_device_major_number major, rte } status = rtems_semaphore_create( rtems_build_name('C', 'r', 'x', '0'+minor), - 0, + 0, RTEMS_FIFO | RTEMS_SIMPLE_BINARY_SEMAPHORE | RTEMS_NO_INHERIT_PRIORITY | \ RTEMS_NO_PRIORITY_CEILING, 0, @@ -1050,34 +1050,34 @@ static rtems_device_driver occan_initialize(rtems_device_major_number major, rte printk("OCCAN: Failed to create rx semaphore for minor %d, (%d)\n\r",minor,status); return RTEMS_UNSATISFIED; } - + /* hardware init/reset */ pelican_init(can); - + /* Setup interrupt handler for each channel */ OCCAN_REG_INT(OCCAN_PREFIX(_interrupt_handler), can->irq, can); - + minor++; #ifdef DEBUG_PRINT_REGMAP pelican_regadr_print(can->regs); #endif } } - + return RTEMS_SUCCESSFUL; } static rtems_device_driver occan_open(rtems_device_major_number major, rtems_device_minor_number minor, void *arg){ occan_priv *can; - + DBG("OCCAN: Opening %d\n\r",minor); - + if ( minor >= can_cores ) return RTEMS_UNSATISFIED; /* NODEV */ - + /* get can device */ can = &cans[minor]; - + /* already opened? */ rtems_semaphore_obtain(can->devsem,RTEMS_WAIT, RTEMS_NO_TIMEOUT); if ( can->open ){ @@ -1093,7 +1093,7 @@ static rtems_device_driver occan_open(rtems_device_major_number major, rtems_dev can->open = 0; return RTEMS_NO_MEMORY; /* ENOMEM */ } - + can->txfifo = occan_fifo_create(DEFAULT_TX_FIFO_LEN); if ( !can->txfifo ){ occan_fifo_free(can->rxfifo); @@ -1101,7 +1101,7 @@ static rtems_device_driver occan_open(rtems_device_major_number major, rtems_dev can->open = 0; return RTEMS_NO_MEMORY; /* ENOMEM */ } - + DBG("OCCAN: Opening %d success\n\r",minor); can->started = 0; @@ -1109,10 +1109,10 @@ static rtems_device_driver occan_open(rtems_device_major_number major, rtems_dev can->txblk = 1; /* Default to Blocking mode */ can->rxblk = 1; /* Default to Blocking mode */ can->single_mode = 1; /* single mode acceptance filter */ - + /* reset stat counters */ memset(&can->stats,0,sizeof(occan_stats)); - + /* HW must be in reset mode here (close and initializes resets core...) * * 1. set default modes/speeds @@ -1124,23 +1124,23 @@ static rtems_device_driver occan_open(rtems_device_major_number major, rtems_dev static rtems_device_driver occan_close(rtems_device_major_number major, rtems_device_minor_number minor, void *arg){ occan_priv *can = &cans[minor]; - + DBG("OCCAN: Closing %d\n\r",minor); - + /* stop if running */ if ( can->started ) pelican_stop(can); - + /* Enter Reset Mode */ can->regs->mode = PELICAN_MOD_RESET; - + /* free fifo memory */ occan_fifo_free(can->rxfifo); occan_fifo_free(can->txfifo); - + can->rxfifo = NULL; can->txfifo = NULL; - + return RTEMS_SUCCESSFUL; } @@ -1150,31 +1150,31 @@ static rtems_device_driver occan_read(rtems_device_major_number major, rtems_dev CANMsg *dstmsg, *srcmsg; rtems_interrupt_level oldLevel; int left; - + if ( !can->started ){ DBG("OCCAN: cannot read from minor %d when not started\n\r",minor); return RTEMS_RESOURCE_IN_USE; /* -EBUSY*/ } - + /* does at least one message fit */ left = rw_args->count; if ( left < sizeof(CANMsg) ){ DBG("OCCAN: minor %d length of buffer must be at least %d, our is %d\n\r",minor,sizeof(CANMsg),left); return RTEMS_INVALID_NAME; /* -EINVAL */ } - + /* get pointer to start where to put CAN messages */ dstmsg = (CANMsg *)rw_args->buffer; if ( !dstmsg ){ DBG("OCCAN: minor %d read: input buffer is NULL\n\r",minor); return RTEMS_INVALID_NAME; /* -EINVAL */ - } + } while (left >= sizeof(CANMsg) ){ - + /* turn off interrupts */ rtems_interrupt_disable(oldLevel); - + /* A bus off interrupt may have occured after checking can->started */ if ( can->status & (OCCAN_STATUS_ERR_BUSOFF|OCCAN_STATUS_RESET) ){ rtems_interrupt_enable(oldLevel); @@ -1182,7 +1182,7 @@ static rtems_device_driver occan_read(rtems_device_major_number major, rtems_dev rw_args->bytes_moved = rw_args->count-left; return RTEMS_IO_ERROR; /* EIO */ } - + srcmsg = occan_fifo_claim_get(can->rxfifo); if ( !srcmsg ){ /* no more messages in reception fifo. @@ -1195,41 +1195,41 @@ static rtems_device_driver occan_read(rtems_device_major_number major, rtems_dev rtems_interrupt_enable(oldLevel); break; } - + /* turn on interrupts again */ rtems_interrupt_enable(oldLevel); - + DBG("OCCAN: Waiting for RX int\n\r"); - + /* wait for incomming messages */ rtems_semaphore_obtain(can->rxsem,RTEMS_WAIT,RTEMS_NO_TIMEOUT); - + /* did we get woken up by a BUS OFF error? */ if ( can->status & (OCCAN_STATUS_ERR_BUSOFF|OCCAN_STATUS_RESET) ){ DBG("OCCAN: Blocking read got woken up by BUS OFF error\n\r"); /* At this point it should not matter how many messages we handled */ - rw_args->bytes_moved = rw_args->count-left; + rw_args->bytes_moved = rw_args->count-left; return RTEMS_IO_ERROR; /* EIO */ } - + /* no errors detected, it must be a message */ continue; } - + /* got message, copy it to userspace buffer */ *dstmsg = *srcmsg; - + /* Return borrowed message, RX interrupt can use it again */ occan_fifo_get(can->rxfifo); - + /* turn on interrupts again */ rtems_interrupt_enable(oldLevel); - + /* increase pointers */ left -= sizeof(CANMsg); dstmsg++; } - + /* save number of read bytes. */ rw_args->bytes_moved = rw_args->count-left; if ( rw_args->bytes_moved == 0 ){ @@ -1245,22 +1245,22 @@ static rtems_device_driver occan_write(rtems_device_major_number major, rtems_de CANMsg *msg,*fifo_msg; rtems_interrupt_level oldLevel; int left; - + DBG("OCCAN: Writing %d bytes from 0x%lx (%d)\n\r",rw_args->count,rw_args->buffer,sizeof(CANMsg)); - + if ( !can->started ) return RTEMS_RESOURCE_IN_USE; /* EBUSY */ - - left = rw_args->count; + + left = rw_args->count; if ( (left < sizeof(CANMsg)) || (!rw_args->buffer) ){ return RTEMS_INVALID_NAME; /* EINVAL */ } - + msg = (CANMsg *)rw_args->buffer; - + /* limit CAN message length to 8 */ msg->len = (msg->len > 8) ? 8 : msg->len; - + #ifdef DEBUG_VERBOSE pelican_regs_print(can->regs); occan_stat_print(&can->stats); @@ -1268,7 +1268,7 @@ static rtems_device_driver occan_write(rtems_device_major_number major, rtems_de /* turn off interrupts */ rtems_interrupt_disable(oldLevel); - + /* A bus off interrupt may have occured after checking can->started */ if ( can->status & (OCCAN_STATUS_ERR_BUSOFF|OCCAN_STATUS_RESET) ){ rtems_interrupt_enable(oldLevel); @@ -1283,35 +1283,35 @@ static rtems_device_driver occan_write(rtems_device_major_number major, rtems_de if ( occan_fifo_empty(can->txfifo) ){ /*pelican_regs_print(cans[minor+1].regs);*/ if ( !pelican_send(can,msg) ) { - /* First message put directly into HW TX fifo + /* First message put directly into HW TX fifo * This will turn TX interrupt on. */ left -= sizeof(CANMsg); msg++; - + /* bump stat counters */ can->stats.tx_msgs++; - + DBG("OCCAN: Sending direct via HW\n\r"); } } /* Put messages into software fifo */ while ( left >= sizeof(CANMsg) ){ - + /* limit CAN message length to 8 */ msg->len = (msg->len > 8) ? 8 : msg->len; - + fifo_msg = occan_fifo_put_claim(can->txfifo,0); if ( !fifo_msg ){ - + DBG("OCCAN: FIFO is full\n\r"); /* Block only if no messages previously sent * and no in blocking mode */ if ( !can->txblk || (left != rw_args->count) ) break; - + /* turn on interupts again and wait INT_ON WAIT FOR FREE BUF; @@ -1319,11 +1319,11 @@ static rtems_device_driver occan_write(rtems_device_major_number major, rtems_de CHECK_IF_FIFO_EMPTY ==> SEND DIRECT VIA HW; */ rtems_interrupt_enable(oldLevel); - + DBG("OCCAN: Waiting for tx int\n\r"); - + rtems_semaphore_obtain(can->txsem, RTEMS_WAIT, RTEMS_NO_TIMEOUT); - + /* did we get woken up by a BUS OFF error? */ if ( can->status & (OCCAN_STATUS_ERR_BUSOFF|OCCAN_STATUS_RESET) ){ DBG("OCCAN: Blocking write got woken up by BUS OFF error or RESET event\n\r"); @@ -1331,44 +1331,44 @@ static rtems_device_driver occan_write(rtems_device_major_number major, rtems_de rw_args->bytes_moved = rw_args->count-left; return RTEMS_IO_ERROR; /* EIO */ } - + rtems_interrupt_disable(oldLevel); - + if ( occan_fifo_empty(can->txfifo) ){ if ( !pelican_send(can,msg) ) { - /* First message put directly into HW TX fifo + /* First message put directly into HW TX fifo * This will turn TX interrupt on. */ left -= sizeof(CANMsg); msg++; - + /* bump stat counters */ can->stats.tx_msgs++; - + DBG("OCCAN: Sending direct2 via HW\n\r"); } } continue; } - + /* copy message into fifo area */ *fifo_msg = *msg; - + /* tell interrupt handler about the message */ occan_fifo_put(can->txfifo); - + DBG("OCCAN: Put info fifo SW\n\r"); - + /* Prepare insert of next message */ msg++; left-=sizeof(CANMsg); } - + rtems_interrupt_enable(oldLevel); - + rw_args->bytes_moved = rw_args->count-left; DBG("OCCAN: Sent %d\n\r",rw_args->bytes_moved); - + if ( left == rw_args->count ) return RTEMS_TIMEOUT; /* ETIMEDOUT should be EAGAIN/EWOULDBLOCK */ return RTEMS_SUCCESSFUL; @@ -1383,38 +1383,38 @@ static rtems_device_driver occan_ioctl(rtems_device_major_number major, rtems_de struct occan_afilter *afilter; occan_stats *dststats; unsigned int rxcnt,txcnt; - + DBG("OCCAN: IOCTL %d\n\r",ioarg->command); - + ioarg->ioctl_return = 0; switch(ioarg->command){ case OCCAN_IOC_SET_SPEED: - + /* cannot change speed during run mode */ if ( can->started ) return RTEMS_RESOURCE_IN_USE; /* EBUSY */ - + /* get speed rate from argument */ speed = (unsigned int)ioarg->buffer; ret = occan_calc_speedregs(sys_freq_hz,speed,&timing); if ( ret ) return RTEMS_INVALID_NAME; /* EINVAL */ - + /* set the speed regs of the CAN core */ /* occan_set_speedregs(can,timing); */ - + /* save timing/speed */ can->speed = speed; can->timing = timing; break; - + case OCCAN_IOC_SET_BTRS: - /* Set BTR registers manually + /* Set BTR registers manually * Read OCCAN Manual. */ if ( can->started ) return RTEMS_RESOURCE_IN_USE; /* EBUSY */ - + can->speed = 0; /* custom */ can->timing.btr1 = (unsigned int)ioarg->buffer & 0xff; can->timing.btr0 = ((unsigned int)ioarg->buffer>>8) & 0xff; @@ -1426,114 +1426,114 @@ static rtems_device_driver occan_ioctl(rtems_device_major_number major, rtems_de can->timing.sam = (btr1 >> 7) & 0x1; */ break; - + case OCCAN_IOC_SPEED_AUTO: return RTEMS_NOT_IMPLEMENTED; if ( can->started ) return RTEMS_RESOURCE_IN_USE; /* EBUSY */ - + if ( (speed=pelican_speed_auto(can)) < 0 ){ /* failed */ return RTEMS_IO_ERROR; } - + /* set new speed */ can->speed = speed; - + if ( (int *)ioarg->buffer ){ *(int *)ioarg->buffer = speed; } return RTEMS_SUCCESSFUL; break; - + case OCCAN_IOC_SET_BUFLEN: /* set rx & tx fifo buffer length */ if ( can->started ) return RTEMS_RESOURCE_IN_USE; /* EBUSY */ - + rxcnt = (unsigned int)ioarg->buffer & 0x0000ffff; txcnt = (unsigned int)ioarg->buffer >> 16; - + occan_fifo_free(can->rxfifo); occan_fifo_free(can->txfifo); - + /* allocate new buffers */ can->rxfifo = occan_fifo_create(rxcnt); can->txfifo = occan_fifo_create(txcnt); - + if ( !can->rxfifo || !can->txfifo ) return RTEMS_NO_MEMORY; /* ENOMEM */ break; - + case OCCAN_IOC_GET_CONF: return RTEMS_NOT_IMPLEMENTED; break; - + case OCCAN_IOC_GET_STATS: dststats = (occan_stats *)ioarg->buffer; if ( !dststats ) return RTEMS_INVALID_NAME; /* EINVAL */ - + /* copy data stats into userspace buffer */ if ( can->rxfifo ) can->stats.rx_sw_dovr = can->rxfifo->ovcnt; *dststats = can->stats; break; - + case OCCAN_IOC_GET_STATUS: /* return the status of the */ if ( !ioarg->buffer ) return RTEMS_INVALID_NAME; - + *(unsigned int *)ioarg->buffer = can->status; break; - + /* Set physical link */ case OCCAN_IOC_SET_LINK: #ifdef REDUNDANT_CHANNELS if ( can->started ) return RTEMS_RESOURCE_IN_USE; /* EBUSY */ - + /* switch HW channel */ can->channel = (unsigned int)ioargs->buffer; #else return RTEMS_NOT_IMPLEMENTED; #endif break; - + case OCCAN_IOC_SET_FILTER: if ( can->started ) return RTEMS_RESOURCE_IN_USE; /* EBUSY */ - + afilter = (struct occan_afilter *)ioarg->buffer; - + if ( !afilter ) return RTEMS_INVALID_NAME; /* EINVAL */ - + /* copy acceptance filter */ can->acode[0] = afilter->code[0]; can->acode[1] = afilter->code[1]; can->acode[2] = afilter->code[2]; can->acode[3] = afilter->code[3]; - + can->amask[0] = afilter->mask[0]; can->amask[1] = afilter->mask[1]; can->amask[2] = afilter->mask[2]; - can->amask[3] = afilter->mask[3]; - + can->amask[3] = afilter->mask[3]; + can->single_mode = ( afilter->single_mode ) ? 1 : 0; - - /* Acceptance filter is written to hardware + + /* Acceptance filter is written to hardware * when starting. */ /* pelican_set_accept(can,can->acode,can->amask);*/ break; - + case OCCAN_IOC_SET_BLK_MODE: can->rxblk = (unsigned int)ioarg->buffer & OCCAN_BLK_MODE_RX; can->txblk = ((unsigned int)ioarg->buffer & OCCAN_BLK_MODE_TX) >> 1; break; - + case OCCAN_IOC_START: if ( can->started ) return RTEMS_RESOURCE_IN_USE; /* EBUSY */ @@ -1541,7 +1541,7 @@ static rtems_device_driver occan_ioctl(rtems_device_major_number major, rtems_de return RTEMS_NO_MEMORY; /* failed because of no memory, can happen if SET_BUFLEN failed */ can->started = 1; break; - + case OCCAN_IOC_STOP: if ( !can->started ) return RTEMS_RESOURCE_IN_USE; /* EBUSY */ @@ -1562,29 +1562,29 @@ static void occan_interrupt(occan_priv *can){ int signal_rx=0, signal_tx=0; unsigned char tmp, errcode, arbcode; int tx_error_cnt,rx_error_cnt; - + can->stats.ints++; - + while ( (iflags = READ_REG(&can->regs->intflags)) != 0 ){ /* still interrupts to handle */ - + if ( iflags & PELICAN_IF_RX ){ /* the rx fifo is not empty - * put 1 message into rxfifo for later use + * put 1 message into rxfifo for later use */ - + /* get empty (or make room) message */ msg = occan_fifo_put_claim(can->rxfifo,1); tmp = READ_REG(®s->rx_fi_xff); msg->extended = tmp >> 7; msg->rtr = (tmp >> 6) & 1; msg->len = tmp = tmp & 0x0f; - + if ( msg->extended ){ /* extended message */ - msg->id = READ_REG(®s->msg.rx_eff.id[0])<<(5+8+8) | - READ_REG(®s->msg.rx_eff.id[1])<<(5+8) | - READ_REG(®s->msg.rx_eff.id[2])<<5 | + msg->id = READ_REG(®s->msg.rx_eff.id[0])<<(5+8+8) | + READ_REG(®s->msg.rx_eff.id[1])<<(5+8) | + READ_REG(®s->msg.rx_eff.id[2])<<5 | READ_REG(®s->msg.rx_eff.id[3])>>3; while(tmp--){ msg->data[tmp] = READ_REG(®s->msg.rx_eff.data[tmp]); @@ -1601,9 +1601,9 @@ static void occan_interrupt(occan_priv *can){ */ }else{ /* standard message */ - msg->id = READ_REG(®s->msg.rx_sff.id[0])<<3 | + msg->id = READ_REG(®s->msg.rx_sff.id[0])<<3 | READ_REG(®s->msg.rx_sff.id[1])>>5; - + while(tmp--){ msg->data[tmp] = READ_REG(®s->msg.rx_sff.data[tmp]); } @@ -1618,29 +1618,29 @@ static void occan_interrupt(occan_priv *can){ msg->data[7] = READ_REG(®s->msg.rx_sff.data[7]); */ } - + /* Re-Enable RX buffer for a new message */ regs->cmd = PELICAN_CMD_RELRXBUF; - + /* make message available to the user */ occan_fifo_put(can->rxfifo); - + /* bump stat counters */ can->stats.rx_msgs++; - + /* signal the semaphore only once */ signal_rx = 1; } - + if ( iflags & PELICAN_IF_TX ){ /* there is room in tx fifo of HW */ - + if ( !occan_fifo_empty(can->txfifo) ){ /* send 1 more messages */ msg = occan_fifo_claim_get(can->txfifo); - + if ( pelican_send(can,msg) ){ - /* ERROR! We got an TX interrupt telling us + /* ERROR! We got an TX interrupt telling us * tx fifo is empty, yet it is not. * * Complain about this max 10 times @@ -1651,86 +1651,86 @@ static void occan_interrupt(occan_priv *can){ can->status |= OCCAN_STATUS_QUEUE_ERROR; can->stats.tx_buf_error++; } - + /* free software-fifo space taken by sent message */ occan_fifo_get(can->txfifo); - + /* bump stat counters */ can->stats.tx_msgs++; - + /* wake any sleeping thread waiting for "fifo not full" */ signal_tx = 1; } } - + if ( iflags & PELICAN_IF_ERRW ){ tx_error_cnt = READ_REG(®s->tx_err_cnt); rx_error_cnt = READ_REG(®s->rx_err_cnt); - + /* 1. if bus off tx error counter = 127 */ if ( (tx_error_cnt > 96) || (rx_error_cnt > 96) ){ /* in Error Active Warning area or BUS OFF */ can->status |= OCCAN_STATUS_WARN; - + /* check reset bit for reset mode */ if ( READ_REG(®s->mode) & PELICAN_MOD_RESET ){ /* in reset mode ==> bus off */ can->status |= OCCAN_STATUS_ERR_BUSOFF | OCCAN_STATUS_RESET; - + /***** pelican_stop(can) ****** * turn off interrupts * enter reset mode (HW already done that for us) */ regs->inten = 0; - + /* Indicate that we are not started any more. - * This will make write/read return with EBUSY + * This will make write/read return with EBUSY * on read/write attempts. * * User must issue a ioctl(START) to get going again. */ can->started = 0; - - /* signal any waiting read/write threads, so that they + + /* signal any waiting read/write threads, so that they * can handle the bus error. */ signal_rx = 1; signal_tx = 1; - + /* ingnore any old pending interrupt */ break; } - + }else{ /* not in Upper Error Active area any more */ can->status &= ~(OCCAN_STATUS_WARN); } can->stats.err_warn++; } - + if ( iflags & PELICAN_IF_DOVR){ can->status |= OCCAN_STATUS_OVERRUN; can->stats.err_dovr++; DBG("OCCAN_INT: DOVR\n\r"); } - + if ( iflags & PELICAN_IF_ERRP){ - /* Let the error counters decide what kind of + /* Let the error counters decide what kind of * interrupt it was. In/Out of EPassive area. */ tx_error_cnt = READ_REG(®s->tx_err_cnt); rx_error_cnt = READ_REG(®s->rx_err_cnt); - + if ( (tx_error_cnt > 127) || (rx_error_cnt > 127) ){ can->status |= OCCAN_STATUS_ERR_PASSIVE; }else{ can->status &= ~(OCCAN_STATUS_ERR_PASSIVE); } - + /* increase Error Passive In/out interrupt counter */ can->stats.err_errp++; } - + if ( iflags & PELICAN_IF_ARB){ arbcode = READ_REG(®s->arbcode); can->stats.err_arb_bitnum[arbcode & PELICAN_ARB_BITS]++; @@ -1739,7 +1739,7 @@ static void occan_interrupt(occan_priv *can){ } if ( iflags & PELICAN_IF_BUS){ - /* Some kind of BUS error, only used for + /* Some kind of BUS error, only used for * statistics. Error Register is decoded * and put into can->stats. */ @@ -1758,27 +1758,27 @@ static void occan_interrupt(occan_priv *can){ can->stats.err_bus_other++; break; } - + /* Get Direction (TX/RX) */ if ( errcode & PELICAN_ECC_DIR ){ can->stats.err_bus_rx++; }else{ can->stats.err_bus_tx++; } - + /* Get Segment in frame that went wrong */ can->stats.err_bus_segs[errcode & PELICAN_ECC_SEG]++; - + /* total number of bus errors */ can->stats.err_bus++; } } - + /* signal Binary semaphore, messages available! */ if ( signal_rx ){ rtems_semaphore_release(can->rxsem); } - + if ( signal_tx ){ rtems_semaphore_release(can->txsem); } @@ -1787,7 +1787,7 @@ static void occan_interrupt(occan_priv *can){ #ifdef OCCAN_DEFINE_INTHANDLER static void occan_interrupt_handler(rtems_vector_number v){ int minor; - + /* convert to */ for(minor = 0; minor < can_cores; minor++) { if ( v == (cans[minor].irq+0x10) ) { @@ -1805,7 +1805,7 @@ static rtems_driver_address_table occan_driver = OCCAN_DRIVER_TABLE_ENTRY; int OCCAN_PREFIX(_register)(amba_confarea_type *bus){ rtems_status_code r; rtems_device_major_number m; - + amba_bus = bus; if ( !bus ) return 1; @@ -1816,7 +1816,7 @@ int OCCAN_PREFIX(_register)(amba_confarea_type *bus){ switch(r) { case RTEMS_TOO_MANY: printk("OCCAN rtems_io_register_driver failed: RTEMS_TOO_MANY\n\r"); break; - case RTEMS_INVALID_NUMBER: + case RTEMS_INVALID_NUMBER: printk("OCCAN rtems_io_register_driver failed: RTEMS_INVALID_NUMBER\n\r"); break; case RTEMS_RESOURCE_IN_USE: printk("OCCAN rtems_io_register_driver failed: RTEMS_RESOURCE_IN_USE\n\r"); break; @@ -1830,7 +1830,7 @@ int OCCAN_PREFIX(_register)(amba_confarea_type *bus){ /******************************************************************************* - * FIFO IMPLEMENTATION + * FIFO IMPLEMENTATION */ static occan_fifo *occan_fifo_create(int cnt){ @@ -1865,17 +1865,17 @@ static int occan_fifo_empty(occan_fifo *fifo){ static CANMsg *occan_fifo_put_claim(occan_fifo *fifo, int force){ if ( !fifo ) return NULL; - + if ( occan_fifo_full(fifo) ){ - + if ( !force ) return NULL; - + /* all buffers already used ==> overwrite the oldest */ fifo->ovcnt++; occan_fifo_get(fifo); } - + return fifo->head; } @@ -1883,10 +1883,10 @@ static CANMsg *occan_fifo_put_claim(occan_fifo *fifo, int force){ static void occan_fifo_put(occan_fifo *fifo){ if ( occan_fifo_full(fifo) ) return; - + /* wrap around */ fifo->head = (fifo->head >= &fifo->base[fifo->cnt-1])? fifo->base : fifo->head+1; - + if ( fifo->head == fifo->tail ) fifo->full = 1; } @@ -1894,7 +1894,7 @@ static void occan_fifo_put(occan_fifo *fifo){ static CANMsg *occan_fifo_claim_get(occan_fifo *fifo){ if ( occan_fifo_empty(fifo) ) return NULL; - + /* return oldest message */ return fifo->tail; } @@ -1906,7 +1906,7 @@ static void occan_fifo_get(occan_fifo *fifo){ if ( occan_fifo_empty(fifo) ) return; - + /* increment indexes */ fifo->tail = (fifo->tail >= &fifo->base[fifo->cnt-1])? fifo->base : fifo->tail+1; fifo->full = 0; |