From 23cc5a6090a4610b96cc593e2d11a6b3c028b41a Mon Sep 17 00:00:00 2001 From: Daniel Hellstrom Date: Fri, 12 Apr 2019 22:49:45 +0200 Subject: leon,grcan: split out GRCAN non-FD specific support in separate file Update #4307. --- bsps/shared/grlib-sources.am | 1 + bsps/shared/grlib/can/grcan.c | 405 ------------------------------------ bsps/shared/grlib/can/grcanstd.c | 435 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 436 insertions(+), 405 deletions(-) create mode 100644 bsps/shared/grlib/can/grcanstd.c diff --git a/bsps/shared/grlib-sources.am b/bsps/shared/grlib-sources.am index 10820dd884..3dd3bdd89e 100644 --- a/bsps/shared/grlib-sources.am +++ b/bsps/shared/grlib-sources.am @@ -24,6 +24,7 @@ librtemsbsp_a_SOURCES += ../../../../../../bsps/shared/grlib/can/canbtrs.c librtemsbsp_a_SOURCES += ../../../../../../bsps/shared/grlib/can/canmux.c librtemsbsp_a_SOURCES += ../../../../../../bsps/shared/grlib/can/grcan.c librtemsbsp_a_SOURCES += ../../../../../../bsps/shared/grlib/can/grcanfd.c +librtemsbsp_a_SOURCES += ../../../../../../bsps/shared/grlib/can/grcanstd.c librtemsbsp_a_SOURCES += ../../../../../../bsps/shared/grlib/can/occan.c librtemsbsp_a_SOURCES += ../../../../../../bsps/shared/grlib/can/satcan.c librtemsbsp_a_SOURCES += ../../../../../../bsps/shared/grlib/drvmgr/ambapp_bus.c diff --git a/bsps/shared/grlib/can/grcan.c b/bsps/shared/grlib/can/grcan.c index e2298d3c94..69f64cc285 100644 --- a/bsps/shared/grlib/can/grcan.c +++ b/bsps/shared/grlib/can/grcan.c @@ -80,18 +80,6 @@ int state2err[4] = { static void __inline__ grcan_hw_reset(struct grcan_regs *regs); -static int grcan_hw_read_try( - struct grcan_priv *pDev, - struct grcan_regs *regs, - CANMsg *buffer, - int max); - -static int grcan_hw_write_try( - struct grcan_priv *pDev, - struct grcan_regs *regs, - CANMsg *buffer, - int count); - static void grcan_hw_config( struct grcan_priv *pDev, struct grcan_config *conf); @@ -501,182 +489,6 @@ static void grcan_hw_sync(struct grcan_regs *regs, struct grcan_filter *sfilter) regs->smask = sfilter->mask; } -static int grcan_hw_read_try( - struct grcan_priv *pDev, - struct grcan_regs *regs, - CANMsg * buffer, - int max -) -{ - int i, j; - CANMsg *dest; - struct grcan_msg *source, tmp; - unsigned int wp, rp, size, rxmax, addr; - int trunk_msg_cnt; - - FUNCDBG(); - - wp = READ_REG(®s->rx0wr); - rp = READ_REG(®s->rx0rd); - - /* - * 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) - * - */ - if (wp != rp) { - /* Not empty, we have received chars... - * 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 - * 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 */ - tmp.head[0] = READ_DMA_WORD(&source->head[0]); - tmp.head[1] = READ_DMA_WORD(&source->head[1]); - if (tmp.head[1] & 0x4) { - DBGC(DBG_RX, "overrun\n"); - } - if (tmp.head[1] & 0x2) { - DBGC(DBG_RX, "bus-off mode\n"); - } - if (tmp.head[1] & 0x1) { - DBGC(DBG_RX, "error-passive mode\n"); - } - /* Convert one grcan CAN message to one "software" CAN message */ - dest->extended = tmp.head[0] >> 31; - dest->rtr = (tmp.head[0] >> 30) & 0x1; - if (dest->extended) { - dest->id = tmp.head[0] & 0x3fffffff; - } else { - dest->id = (tmp.head[0] >> 18) & 0xfff; - } - 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--; - } - { - /* A bus off interrupt may have occured after checking pDev->started */ - SPIN_IRQFLAGS(oldLevel); - - SPIN_LOCK_IRQ(&pDev->devlock, oldLevel); - if (pDev->started == STATE_STARTED) { - regs->rx0rd = (unsigned int) source - addr; - regs->rx0ctrl = GRCAN_RXCTRL_ENABLE; - } else { - DBGC(DBG_STATE, "cancelled due to a BUS OFF error\n"); - trunk_msg_cnt = state2err[pDev->started]; - } - SPIN_UNLOCK_IRQ(&pDev->devlock, oldLevel); - } - return trunk_msg_cnt; - } - return 0; -} - -static int grcan_hw_write_try( - struct grcan_priv *pDev, - struct grcan_regs *regs, - CANMsg * buffer, - int count -) -{ - unsigned int rp, wp, size, txmax, addr; - int ret; - struct grcan_msg *dest; - CANMsg *source; - 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) { - tmp = (1 << 31) | (source->id & 0x3fffffff); - } else { - tmp = (source->id & 0xfff) << 18; - } - if (source->rtr) - tmp |= (1 << 30); - dest->head[0] = tmp; - dest->head[1] = source->len << 28; - for (i = 0; i < source->len; i++) - dest->data[i] = source->data[i]; - source++; /* straight user buffer */ - dest = - ((unsigned int)dest >= txmax) ? - (struct grcan_msg *)addr : dest + 1; - space_left--; - } - - { - /* A bus off interrupt may have occured after checking pDev->started */ - SPIN_IRQFLAGS(oldLevel); - - SPIN_LOCK_IRQ(&pDev->devlock, oldLevel); - if (pDev->started == STATE_STARTED) { - regs->tx0wr = (unsigned int) dest - addr; - regs->tx0ctrl = GRCAN_TXCTRL_ENABLE; - } else { - DBGC(DBG_STATE, "cancelled due to a BUS OFF error\n"); - ret = state2err[pDev->started]; - } - SPIN_UNLOCK_IRQ(&pDev->devlock, oldLevel); - } - return ret; -} - int grcan_wait_rxdata(struct grcan_priv *pDev, int min) { unsigned int wp, rp, size, irq; @@ -1156,176 +968,6 @@ int grcan_canfd_capable(void *d) return pDev->fd_capable; } -int grcan_read(void *d, CANMsg *msg, size_t ucount) -{ - struct grcan_priv *pDev = d; - CANMsg *dest; - unsigned int count, left; - int nread; - int req_cnt; - - FUNCDBG(); - - dest = msg; - req_cnt = ucount; - - if ( (!dest) || (req_cnt<1) ) - return GRCAN_RET_INVARG; - - if (pDev->started != STATE_STARTED) { - return GRCAN_RET_NOTSTARTED; - } - - DBGC(DBG_RX, "grcan_read [%p]: buf: %p len: %u\n", d, msg, (unsigned int) ucount); - - nread = grcan_hw_read_try(pDev,pDev->regs,dest,req_cnt); - if (nread < 0) { - return nread; - } - count = nread; - if ( !( pDev->rxblock && pDev->rxcomplete && (count!=req_cnt) ) ){ - if ( count > 0 ) { - /* Successfully received messages (at least one) */ - return count; - } - - /* nothing read, shall we block? */ - if ( !pDev->rxblock ) { - /* non-blocking mode */ - return GRCAN_RET_TIMEOUT; - } - } - - 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 - * 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. - */ - if (left > ((pDev->rxbuf_size/GRCAN_MSG_SIZE) / 2)){ - left = (pDev->rxbuf_size/GRCAN_MSG_SIZE) / 2; - } - } - - nread = grcan_wait_rxdata(pDev, left); - if (nread) { - /* The wait has been aborted, probably due to - * the device driver has been closed by another - * thread or a bus-off. Return error code. - */ - return nread; - } - - /* Try read bytes from circular buffer */ - nread = grcan_hw_read_try( - pDev, - pDev->regs, - dest+count, - req_cnt-count); - - if (nread < 0) { - /* The read was aborted by bus-off. */ - return nread; - } - count += nread; - } - /* no need to unmask IRQ as IRQ Handler do that for us. */ - return count; -} - -int grcan_write(void *d, CANMsg *msg, size_t ucount) -{ - struct grcan_priv *pDev = d; - CANMsg *source; - unsigned int count, left; - int nwritten; - int req_cnt; - - DBGC(DBG_TX,"\n"); - - if ((pDev->started != STATE_STARTED) || pDev->config.silent || pDev->flushing) - return GRCAN_RET_NOTSTARTED; - - req_cnt = ucount; - source = (CANMsg *) msg; - - /* check proper length and buffer pointer */ - if (( req_cnt < 1) || (source == NULL) ){ - return GRCAN_RET_INVARG; - } - - nwritten = grcan_hw_write_try(pDev,pDev->regs,source,req_cnt); - if (nwritten < 0) { - return nwritten; - } - count = nwritten; - if ( !(pDev->txblock && pDev->txcomplete && (count!=req_cnt)) ) { - if ( count > 0 ) { - /* Successfully transmitted chars (at least one char) */ - return count; - } - - /* nothing written, shall we block? */ - if ( !pDev->txblock ) { - /* non-blocking mode */ - return GRCAN_RET_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 - * 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 transmit - * 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; - } - } - - nwritten = grcan_wait_txspace(pDev,left); - /* Wait until more room in transmit buffer */ - if ( nwritten ) { - /* 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. - */ - return nwritten; - } - - /* Try read bytes from circular buffer */ - nwritten = grcan_hw_write_try( - pDev, - pDev->regs, - source+count, - req_cnt-count); - - if (nwritten < 0) { - /* Write was aborted by bus-off. */ - return nwritten; - } - count += nwritten; - } - /* no need to unmask IRQ as IRQ Handler do that for us. */ - - return count; -} - int grcan_start(void *d) { struct grcan_priv *pDev = d; @@ -1552,53 +1194,6 @@ int grcan_clr_stats(void *d) return 0; } -int grcan_set_speed(void *d, unsigned int speed) -{ - struct grcan_priv *pDev = d; - struct grcan_timing timing; - int ret; - - FUNCDBG(); - - /* cannot change speed during run mode */ - if ((pDev->started == STATE_STARTED) || pDev->fd_capable) - return -1; - - /* get speed rate from argument */ - ret = grlib_canbtrs_calc_timing( - speed, pDev->corefreq_hz, GRCAN_SAMPLING_POINT, - &grcan_btrs_ranges, (struct grlib_canbtrs_timing *)&timing); - if (ret) - return -2; - - /* save timing/speed */ - pDev->config.timing = timing; - pDev->config_changed = 1; - - return 0; -} - -int grcan_set_btrs(void *d, const struct grcan_timing *timing) -{ - struct grcan_priv *pDev = d; - - FUNCDBG(); - - /* Set BTR registers manually - * Read GRCAN/HurriCANe Manual. - */ - if ((pDev->started == STATE_STARTED) || pDev->fd_capable) - return -1; - - if ( !timing ) - return -2; - - pDev->config.timing = *timing; - pDev->config_changed = 1; - - return 0; -} - int grcan_set_afilter(void *d, const struct grcan_filter *filter) { struct grcan_priv *pDev = d; diff --git a/bsps/shared/grlib/can/grcanstd.c b/bsps/shared/grlib/can/grcanstd.c new file mode 100644 index 0000000000..b92c15a32b --- /dev/null +++ b/bsps/shared/grlib/can/grcanstd.c @@ -0,0 +1,435 @@ +/* + * non-FD specific function for GRCAN driver + * + * COPYRIGHT (c) 2007-2019. + * Cobham Gaisler AB. + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.org/license/LICENSE. + */ + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include +#include "grcan_internal.h" + +/* Uncomment for debug output */ +/****************** DEBUG Definitions ********************/ +#define DBG_TX 2 +#define DBG_RX 4 +#define DBG_STATE 8 + +#define DEBUG_FLAGS (DBG_STATE | DBG_RX | DBG_TX ) +/* +#define DEBUG +#define DEBUGFUNCS +*/ +#include + +static int grcan_hw_read_try( + struct grcan_priv *pDev, + struct grcan_regs *regs, + CANMsg * buffer, + int max +) +{ + int i, j; + CANMsg *dest; + struct grcan_msg *source, tmp; + unsigned int wp, rp, size, rxmax, addr; + int trunk_msg_cnt; + + FUNCDBG(); + + wp = READ_REG(®s->rx0wr); + rp = READ_REG(®s->rx0rd); + + /* + * 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) + * + */ + if (wp != rp) { + /* Not empty, we have received chars... + * 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 + * 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 */ + tmp.head[0] = READ_DMA_WORD(&source->head[0]); + tmp.head[1] = READ_DMA_WORD(&source->head[1]); + if (tmp.head[1] & 0x4) { + DBGC(DBG_RX, "overrun\n"); + } + if (tmp.head[1] & 0x2) { + DBGC(DBG_RX, "bus-off mode\n"); + } + if (tmp.head[1] & 0x1) { + DBGC(DBG_RX, "error-passive mode\n"); + } + /* Convert one grcan CAN message to one "software" CAN message */ + dest->extended = tmp.head[0] >> 31; + dest->rtr = (tmp.head[0] >> 30) & 0x1; + if (dest->extended) { + dest->id = tmp.head[0] & 0x3fffffff; + } else { + dest->id = (tmp.head[0] >> 18) & 0xfff; + } + 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--; + } + { + /* A bus off interrupt may have occured after checking pDev->started */ + SPIN_IRQFLAGS(oldLevel); + + SPIN_LOCK_IRQ(&pDev->devlock, oldLevel); + if (pDev->started == STATE_STARTED) { + regs->rx0rd = (unsigned int) source - addr; + regs->rx0ctrl = GRCAN_RXCTRL_ENABLE; + } else { + DBGC(DBG_STATE, "cancelled due to a BUS OFF error\n"); + trunk_msg_cnt = state2err[pDev->started]; + } + SPIN_UNLOCK_IRQ(&pDev->devlock, oldLevel); + } + return trunk_msg_cnt; + } + return 0; +} + +static int grcan_hw_write_try( + struct grcan_priv *pDev, + struct grcan_regs *regs, + CANMsg * buffer, + int count +) +{ + unsigned int rp, wp, size, txmax, addr; + int ret; + struct grcan_msg *dest; + CANMsg *source; + 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) { + tmp = (1 << 31) | (source->id & 0x3fffffff); + } else { + tmp = (source->id & 0xfff) << 18; + } + if (source->rtr) + tmp |= (1 << 30); + dest->head[0] = tmp; + dest->head[1] = source->len << 28; + for (i = 0; i < source->len; i++) + dest->data[i] = source->data[i]; + source++; /* straight user buffer */ + dest = + ((unsigned int)dest >= txmax) ? + (struct grcan_msg *)addr : dest + 1; + space_left--; + } + + { + /* A bus off interrupt may have occured after checking pDev->started */ + SPIN_IRQFLAGS(oldLevel); + + SPIN_LOCK_IRQ(&pDev->devlock, oldLevel); + if (pDev->started == STATE_STARTED) { + regs->tx0wr = (unsigned int) dest - addr; + regs->tx0ctrl = GRCAN_TXCTRL_ENABLE; + } else { + DBGC(DBG_STATE, "cancelled due to a BUS OFF error\n"); + ret = state2err[pDev->started]; + } + SPIN_UNLOCK_IRQ(&pDev->devlock, oldLevel); + } + return ret; +} + + +int grcan_read(void *d, CANMsg *msg, size_t ucount) +{ + struct grcan_priv *pDev = d; + CANMsg *dest; + unsigned int count, left; + int nread; + int req_cnt; + + FUNCDBG(); + + dest = msg; + req_cnt = ucount; + + if ( (!dest) || (req_cnt<1) ) + return GRCAN_RET_INVARG; + + if (pDev->started != STATE_STARTED) { + return GRCAN_RET_NOTSTARTED; + } + + DBGC(DBG_RX, "grcan_read [%p]: buf: %p len: %u\n", d, msg, (unsigned int) ucount); + + nread = grcan_hw_read_try(pDev,pDev->regs,dest,req_cnt); + if (nread < 0) { + return nread; + } + count = nread; + if ( !( pDev->rxblock && pDev->rxcomplete && (count!=req_cnt) ) ){ + if ( count > 0 ) { + /* Successfully received messages (at least one) */ + return count; + } + + /* nothing read, shall we block? */ + if ( !pDev->rxblock ) { + /* non-blocking mode */ + return GRCAN_RET_TIMEOUT; + } + } + + 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 + * 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. + */ + if (left > ((pDev->rxbuf_size/GRCAN_MSG_SIZE) / 2)){ + left = (pDev->rxbuf_size/GRCAN_MSG_SIZE) / 2; + } + } + + nread = grcan_wait_rxdata(pDev, left); + if (nread) { + /* The wait has been aborted, probably due to + * the device driver has been closed by another + * thread or a bus-off. Return error code. + */ + return nread; + } + + /* Try read bytes from circular buffer */ + nread = grcan_hw_read_try( + pDev, + pDev->regs, + dest+count, + req_cnt-count); + + if (nread < 0) { + /* The read was aborted by bus-off. */ + return nread; + } + count += nread; + } + /* no need to unmask IRQ as IRQ Handler do that for us. */ + return count; +} + +int grcan_write(void *d, CANMsg *msg, size_t ucount) +{ + struct grcan_priv *pDev = d; + CANMsg *source; + unsigned int count, left; + int nwritten; + int req_cnt; + + DBGC(DBG_TX,"\n"); + + if ((pDev->started != STATE_STARTED) || pDev->config.silent || pDev->flushing) + return GRCAN_RET_NOTSTARTED; + + req_cnt = ucount; + source = (CANMsg *) msg; + + /* check proper length and buffer pointer */ + if (( req_cnt < 1) || (source == NULL) ){ + return GRCAN_RET_INVARG; + } + + nwritten = grcan_hw_write_try(pDev,pDev->regs,source,req_cnt); + if (nwritten < 0) { + return nwritten; + } + count = nwritten; + if ( !(pDev->txblock && pDev->txcomplete && (count!=req_cnt)) ) { + if ( count > 0 ) { + /* Successfully transmitted chars (at least one char) */ + return count; + } + + /* nothing written, shall we block? */ + if ( !pDev->txblock ) { + /* non-blocking mode */ + return GRCAN_RET_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 + * 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 transmit + * 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; + } + } + + nwritten = grcan_wait_txspace(pDev,left); + /* Wait until more room in transmit buffer */ + if ( nwritten ) { + /* 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. + */ + return nwritten; + } + + /* Try read bytes from circular buffer */ + nwritten = grcan_hw_write_try( + pDev, + pDev->regs, + source+count, + req_cnt-count); + + if (nwritten < 0) { + /* Write was aborted by bus-off. */ + return nwritten; + } + count += nwritten; + } + /* no need to unmask IRQ as IRQ Handler do that for us. */ + + return count; +} + + +int grcan_set_speed(void *d, unsigned int speed) +{ + struct grcan_priv *pDev = d; + struct grcan_timing timing; + int ret; + + FUNCDBG(); + + /* cannot change speed during run mode */ + if ((pDev->started == STATE_STARTED) || pDev->fd_capable) + return -1; + + /* get speed rate from argument */ + ret = grlib_canbtrs_calc_timing( + speed, pDev->corefreq_hz, GRCAN_SAMPLING_POINT, + &grcan_btrs_ranges, (struct grlib_canbtrs_timing *)&timing); + if (ret) + return -2; + + /* save timing/speed */ + pDev->config.timing = timing; + pDev->config_changed = 1; + + return 0; +} + +int grcan_set_btrs(void *d, const struct grcan_timing *timing) +{ + struct grcan_priv *pDev = d; + + FUNCDBG(); + + /* Set BTR registers manually + * Read GRCAN/HurriCANe Manual. + */ + if ((pDev->started == STATE_STARTED) || pDev->fd_capable) + return -1; + + if ( !timing ) + return -2; + + pDev->config.timing = *timing; + pDev->config_changed = 1; + + return 0; +} -- cgit v1.2.3