X-Git-Url: http://rtime.felk.cvut.cz/gitweb/lincan.git/blobdiff_plain/3e5b474f9cd113def3be02af0cf6d5401a7427c9..659b098309c2bca57ac60a35a1b9900d6f28e74d:/lincan/src/sja1000p.c diff --git a/lincan/src/sja1000p.c b/lincan/src/sja1000p.c index ef587dd..b71b5a0 100644 --- a/lincan/src/sja1000p.c +++ b/lincan/src/sja1000p.c @@ -92,6 +92,9 @@ int sja1000p_disable_configuration(struct chip_t *chip) */ int sja1000p_chip_config(struct chip_t *chip) { + int i; + unsigned char n, r; + if (sja1000p_enable_configuration(chip)) return -ENODEV; @@ -99,6 +102,20 @@ int sja1000p_chip_config(struct chip_t *chip) can_write_reg(chip,CDR_PELICAN|chip->sja_cdr_reg,SJACDR); /* Set driver output configuration */ can_write_reg(chip,chip->sja_ocr_reg,SJAOCR); + + /* Simple check for chip presence */ + for (i=0, n=0x5a; i<8; i++, n+=0xf) { + can_write_reg(chip,n,SJAACR0+i); + } + for (i=0, n=0x5a; i<8; i++, n+=0xf) { + r = n^can_read_reg(chip,SJAACR0+i); + if (r) { + CANMSG("sja1000p_chip_config: chip connection broken," + " readback differ 0x%02x\n", r); + return -ENODEV; + } + } + if (sja1000p_extended_mask(chip,0x00000000, 0xffffffff)) return -ENODEV; @@ -248,10 +265,11 @@ void sja1000p_read(struct chip_t *chip, struct msgobj_t *obj) { ((flags & FRM_RTR) ? MSG_RTR : 0) | ((flags & FRM_FF) ? MSG_EXT : 0); len = flags & FRM_DLC_M; + obj->rx_msg.length = len; + if(len > CAN_MSG_LENGTH) len = CAN_MSG_LENGTH; for(i=0; i< len; i++) { obj->rx_msg.data[i]=can_read_reg(chip,datastart+i); } - obj->rx_msg.length = len; canque_filter_msg2edges(obj->qends, &obj->rx_msg); @@ -314,6 +332,7 @@ int sja1000p_pre_write_config(struct chip_t *chip, struct msgobj_t *obj, int i=0; unsigned int id; int status; + int len; /* Wait until Transmit Buffer Status is released */ while ( !((status=can_read_reg(chip, SJASR)) & SR_TBS) && @@ -347,10 +366,11 @@ int sja1000p_pre_write_config(struct chip_t *chip, struct msgobj_t *obj, return -EIO; } } - msg->length &= FRM_DLC_M; + len = msg->length; + if(len > CAN_MSG_LENGTH) len = CAN_MSG_LENGTH; + /* len &= FRM_DLC_M; ensured by above condition already */ can_write_reg(chip, ((msg->flags&MSG_EXT)?FRM_FF:0) | - ((msg->flags & MSG_RTR) ? FRM_RTR : 0) | - msg->length, SJAFRM); + ((msg->flags & MSG_RTR) ? FRM_RTR : 0) | len, SJAFRM); if(msg->flags&MSG_EXT) { id=msg->id<<3; can_write_reg(chip, id & 0xff, SJAID3); @@ -360,14 +380,14 @@ int sja1000p_pre_write_config(struct chip_t *chip, struct msgobj_t *obj, can_write_reg(chip, id & 0xff, SJAID1); id >>= 8; can_write_reg(chip, id, SJAID0); - for(i=0; i < msg->length; i++) { + for(i=0; i < len; i++) { can_write_reg(chip, msg->data[i], SJADATE+i); } } else { 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++) { + for(i=0; i < len; i++) { can_write_reg(chip, msg->data[i], SJADATS+i); } } @@ -541,6 +561,12 @@ void sja1000p_irq_write_handler(struct chip_t *chip, struct msgobj_t *obj) int cmd; if(obj->tx_slot){ + /* Do local transmitted message distribution if enabled */ + if (processlocal){ + obj->tx_slot->msg.flags |= MSG_LOCAL; + canque_filter_msg2edges(obj->qends, &obj->tx_slot->msg); + } + /* Free transmitted slot */ canque_free_outslot(obj->qends, obj->tx_qedge, obj->tx_slot); obj->tx_slot=NULL; } @@ -586,7 +612,6 @@ void sja1000p_irq_write_handler(struct chip_t *chip, struct msgobj_t *obj) irqreturn_t 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 msgobj_t *obj=chip->msgobj[0]; @@ -637,9 +662,9 @@ irqreturn_t sja1000p_irq_handler(int irq, void *dev_id, struct pt_regs *regs) obj->ret= -ENXIO; /* no such device or address - no ACK received */ } - if(retransmitted++>MAX_RETR) { + if(obj->tx_retry_cnt++>MAX_RETR) { can_write_reg(chip, CMR_AT, SJACMR); // cancel any transmition - retransmitted = 0; + obj->tx_retry_cnt = 0; } if(status&SR_BS) { CANMSG("bus-off, resetting sja1000p\n"); @@ -653,7 +678,7 @@ irqreturn_t sja1000p_irq_handler(int irq, void *dev_id, struct pt_regs *regs) } } else { - retransmitted=0; + obj->tx_retry_cnt=0; } return IRQ_HANDLED; @@ -680,8 +705,10 @@ int sja1000p_wakeup_tx(struct chip_t *chip, struct msgobj_t *obj) while(!test_and_set_bit(OBJ_TX_LOCK,&obj->flags)){ clear_bit(OBJ_TX_REQUEST,&obj->flags); - if (can_read_reg(chip, SJASR) & SR_TBS) + if (can_read_reg(chip, SJASR) & SR_TBS){ + obj->tx_retry_cnt=0; sja1000p_irq_write_handler(chip, obj); + } clear_bit(OBJ_TX_LOCK,&obj->flags); if(!test_bit(OBJ_TX_REQUEST,&obj->flags)) break;