#include "../include/main.h"
#include "../include/sja1000p.h"
-struct chip_t *chip_irq=NULL;
-struct candevice_t *device_irq=NULL;
-struct canfifo_t *fifo_irq=NULL;
-void (*put_reg)(unsigned char data, unsigned long address);
-unsigned (*get_reg)(unsigned long address);
-
-
-
int sja1000p_enable_configuration(struct chip_t *chip)
{
int i=0;
flags=can_read_reg(chip,SJAMOD);
while ((!(flags & MOD_RM)) && (i<=10)) {
- can_write_reg(chip, MOD_RM, SJAMOD);
-// TODO: chinfigurable MOD_AFM (32/16 bit acceptance filter)
+ can_write_reg(chip, MOD_RM, SJAMOD);
+// TODO: configurable MOD_AFM (32/16 bit acceptance filter)
// config MOD_LOM (listen only)
udelay(100);
i++;
flags=can_read_reg(chip,SJAMOD);
- while ( (flags & MOD_RM) && (i<=10) ) {
+ while ( (flags & MOD_RM) && (i<=50) ) {
+// could be as long as 11*128 bit times after buss-off
can_write_reg(chip, 0, SJAMOD);
-// TODO: chinfigurable MOD_AFM (32/16 bit acceptance filter)
+// TODO: configurable MOD_AFM (32/16 bit acceptance filter)
// config MOD_LOM (listen only)
udelay(100);
i++;
do {
flags = can_read_reg(chip,SJAFRM);
if(flags&FRM_FF) {
- fifo->buf_rx_entry[fifo->head].id =
+ fifo->rx_writep->id =
(can_read_reg(chip,SJAID0)<<21) +
(can_read_reg(chip,SJAID1)<<13) +
(can_read_reg(chip,SJAID2)<<5) +
(can_read_reg(chip,SJAID3)>>3);
datastart = SJADATE;
} else {
- fifo->buf_rx_entry[fifo->head].id =
+ fifo->rx_writep->id =
(can_read_reg(chip,SJAID0)<<3) +
(can_read_reg(chip,SJAID1)>>5);
datastart = SJADATS;
}
- fifo->buf_rx_entry[fifo->head].flags =
+ fifo->rx_writep->flags =
((flags & FRM_RTR) ? MSG_RTR : 0) |
((flags & FRM_FF) ? MSG_EXT : 0);
len = flags & FRM_DLC_M;
for(i=0; i< len; i++) {
- fifo->buf_rx_entry[fifo->head].data[i]=
- can_read_reg(chip,datastart+i);
+ fifo->rx_writep->data[i]=can_read_reg(chip,datastart+i);
}
- fifo->buf_rx_entry[fifo->head].length = len;
- fifo->head++; fifo->head %= MAX_BUF_LENGTH;
-// FIXME: what if fifo->head == fifo->tail again ?
+ fifo->rx_writep->length = len;
+
+ fifo->rx_writep++;
+ if (fifo->rx_writep >= fifo->buf_rx_entry + MAX_BUF_LENGTH)
+ fifo->rx_writep = fifo->buf_rx_entry;
+
+// FIXME: what if fifo->rx_writep == fifo->rx_readp again ?
+
can_write_reg(chip, CMR_RRB, SJACMR);
} while (can_read_reg(chip, SJASR) & SR_RBS);
}
int sja1000p_pre_read_config(struct chip_t *chip, struct msgobj_t *obj)
{
- int i;
- i=can_read_reg(chip,SJASR);
+ int status;
+ status=can_read_reg(chip,SJASR);
- if (!(i&SR_RBS)) {
+ if(status & SR_BS) {
+ /* Try to recover from error condition */
+ DEBUGMSG("sja1000p_pre_read_config bus-off recover 0x%x\n",status);
+ sja1000p_enable_configuration(chip);
+ can_write_reg(chip, 0, SJARXERR);
+ can_write_reg(chip, 0, SJATXERR1);
+ can_read_reg(chip, SJAECC);
+ sja1000p_disable_configuration(chip);
+ }
+
+ if (!(status&SR_RBS)) {
return 0;
}
{
int i=0;
unsigned int id;
+ int status;
/* Wait until Transmit Buffer Status is released */
- while ( !(can_read_reg(chip, SJASR) & SR_TBS) &&
+ while ( !((status=can_read_reg(chip, SJASR)) & SR_TBS) &&
i++<MAX_TRANSMIT_WAIT_LOOPS) {
udelay(i);
}
+ if(status & SR_BS) {
+ /* Try to recover from error condition */
+ DEBUGMSG("sja1000p_pre_write_config bus-off recover 0x%x\n",status);
+ sja1000p_enable_configuration(chip);
+ can_write_reg(chip, 0, SJARXERR);
+ can_write_reg(chip, 0, SJATXERR1);
+ can_read_reg(chip, SJAECC);
+ sja1000p_disable_configuration(chip);
+ }
if (!(can_read_reg(chip, SJASR) & SR_TBS)) {
CANMSG("Transmit timed out, cancelling\n");
// here we should check if there is no write/select waiting for this
can_write_reg(chip, msg->data[i], SJADATE+i);
}
} else {
- id=msg->id >> 5;
- can_write_reg(chip, id & 0xff, SJAID0);
- id >>= 8;
+ id=msg->id<<5;
+ can_write_reg(chip, (id >> 8) & 0xff, SJAID0);
can_write_reg(chip, id & 0xff, SJAID1);
for(i=0; i < msg->length; i++) {
can_write_reg(chip, msg->data[i], SJADATS+i);
return -ENOSYS;
}
-void sja1000p_irq_handler(int irq, void *dev_id, struct pt_regs *regs)
+void sja1000p_irq_write_handler(struct chip_t *chip, struct canfifo_t *fifo)
{
- int irq_register;
- chip_irq=(struct chip_t *)dev_id;
- device_irq=(struct candevice_t *)chip_irq->hostdevice;
+ fifo->tx_readp++;
+ if (fifo->tx_readp >= fifo->buf_tx_entry + MAX_BUF_LENGTH)
+ fifo->tx_readp = fifo->buf_tx_entry;
+ if (fifo->tx_readp == fifo->tx_writep) { // Output buffer is empty
+ fifo->tx_in_progress = 0;
+ if (waitqueue_active(&fifo->writeq)) {
+ chip->msgobj[0]->ret = 0; //CHECKME or 26?
+ wake_up_interruptible(&fifo->writeq);
+ }
+ return;
+ }
+ if (chip->chipspecops->pre_write_config(chip, chip->msgobj[0],
+ fifo->tx_readp)) {
+ if (waitqueue_active(&fifo->writeq)) {
+ chip->msgobj[0]->ret = -1;
+ wake_up_interruptible(&fifo->writeq);
+ return;
+ }
+ }
+ if (chip->chipspecops->send_msg(chip, chip->msgobj[0],
+ fifo->tx_readp)) {
+ if (waitqueue_active(&fifo->writeq)) {
+ chip->msgobj[0]->ret = -1;
+ wake_up_interruptible(&fifo->writeq);
+ return;
+ }
+ }
- put_reg=device_irq->hwspecops->write_register;
- get_reg=device_irq->hwspecops->read_register;
+}
+
+#define MAX_RETR 10
- irq_register=get_reg(chip_irq->chip_base_addr+SJAIR);
+void sja1000p_irq_handler(int irq, void *dev_id, struct pt_regs *regs)
+{
+ int irq_register, status, error_code;
+ int static retransmitted=0; /* FIXME - should go into chip struct */
+ struct chip_t *chip=(struct chip_t *)dev_id;
+ struct canfifo_t *fifo;
+
+ irq_register=can_read_reg(chip,SJAIR);
// DEBUGMSG("sja1000_irq_handler: SJAIR:%02x\n",irq_register);
// DEBUGMSG("sja1000_irq_handler: SJASR:%02x\n",
-// get_reg(chip_irq->chip_base_addr+SJASR));
+// can_read_reg(chip,SJASR));
if ((irq_register & (IR_BEI|IR_EPI|IR_DOI|IR_EI|IR_TI|IR_RI)) == 0)
return;
- fifo_irq=chip_irq->msgobj[0]->fifo;
+ if(!chip->msgobj[0]->flags & BUFFERS_ALLOCATED) {
+ CANMSG("sja1000p_irq_handler: called with device closed, irq_register 0x%02x\n", irq_register);
+ return;
+ }
+ fifo=chip->msgobj[0]->fifo;
if ((irq_register & IR_RI) != 0) {
- sja1000p_read(chip_irq,fifo_irq);
- chip_irq->msgobj[0]->ret = 0;
- if (waitqueue_active(&fifo_irq->readq))
- wake_up_interruptible(&fifo_irq->readq);
+ sja1000p_read(chip,fifo);
+ chip->msgobj[0]->ret = 0;
+ if (waitqueue_active(&fifo->readq))
+ wake_up_interruptible(&fifo->readq);
}
if ((irq_register & IR_TI) != 0) {
- chip_irq->msgobj[0]->ret = 0;
- if (waitqueue_active(&fifo_irq->writeq))
- wake_up_interruptible(&fifo_irq->writeq);
+ chip->msgobj[0]->ret = 0;
+ sja1000p_irq_write_handler(chip,fifo);
}
if ((irq_register & (IR_EI|IR_BEI|IR_EPI|IR_DOI)) != 0) {
// Some error happened
- CANMSG("Error: status register: 0x%x irq_register: 0x%02x\n",
- get_reg(chip_irq->chip_base_addr+SJASR), irq_register);
+ status=can_read_reg(chip,SJASR);
+ error_code=can_read_reg(chip,SJAECC);
+ CANMSG("Error: status register: 0x%x irq_register: 0x%02x error: 0x%02x\n",
+ status, irq_register, error_code);
// FIXME: chip should be brought to usable state. Transmission cancelled if in progress.
// Reset flag set to 0 if chip is already off the bus. Full state report
- chip_irq->msgobj[0]->ret=-1;
- if (waitqueue_active(&fifo_irq->writeq))
- wake_up_interruptible(&fifo_irq->writeq);
- if (waitqueue_active(&fifo_irq->readq))
- wake_up_interruptible(&fifo_irq->readq);
+ chip->msgobj[0]->ret=-1;
+
+ if(error_code == 0xd9) {
+ chip->msgobj[0]->ret= -ENXIO;
+ /* no such device or address - no ACK received */
+ }
+ if(retransmitted++>MAX_RETR) {
+ can_write_reg(chip, CMR_AT, SJACMR); // cancel any transmition
+ retransmitted = 0;
+ }
+ if(status&SR_BS) {
+ CANMSG("bus-off, resetting sja1000p\n");
+ can_write_reg(chip, 0, SJAMOD);
+ }
+
+ if (waitqueue_active(&fifo->writeq))
+ wake_up_interruptible(&fifo->writeq);
+ if (waitqueue_active(&fifo->readq))
+ wake_up_interruptible(&fifo->readq);
+ } else {
+ retransmitted=0;
}
return;