X-Git-Url: http://rtime.felk.cvut.cz/gitweb/lincan.git/blobdiff_plain/11132ea490f9e860744ee4f851c67e7fb4444231..bfac169862856611eeb16af24c8943f005f88e12:/lincan/src/sja1000p.c diff --git a/lincan/src/sja1000p.c b/lincan/src/sja1000p.c index 19e2e57..57b33c8 100644 --- a/lincan/src/sja1000p.c +++ b/lincan/src/sja1000p.c @@ -9,21 +9,21 @@ * Version lincan-0.2 9 Jul 2003 */ -#include - -#include -#include -#include - +#include "../include/can.h" +#include "../include/can_sysdep.h" #include "../include/main.h" #include "../include/sja1000p.h" +/** + * sja1000p_enable_configuration - enable chip configuration mode + * @chip: pointer to chip state structure + */ int sja1000p_enable_configuration(struct chip_t *chip) { int i=0; enum sja1000_PeliCAN_MOD flags; - disable_irq(chip->chip_irq); + can_disable_irq(chip->chip_irq); flags=can_read_reg(chip,SJAMOD); @@ -37,13 +37,17 @@ int sja1000p_enable_configuration(struct chip_t *chip) } if (i>=10) { CANMSG("Reset error\n"); - enable_irq(chip->chip_irq); + can_enable_irq(chip->chip_irq); return -ENODEV; } return 0; } +/** + * sja1000p_disable_configuration - disable chip configuration mode + * @chip: pointer to chip state structure + */ int sja1000p_disable_configuration(struct chip_t *chip) { int i=0; @@ -65,7 +69,7 @@ int sja1000p_disable_configuration(struct chip_t *chip) return -ENODEV; } - enable_irq(chip->chip_irq); + can_enable_irq(chip->chip_irq); return 0; } @@ -84,6 +88,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; @@ -91,13 +98,27 @@ 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; - if (!baudrate) - baudrate=1000; - if (sja1000p_baud_rate(chip,1000*baudrate,chip->clock,0,75,0)) + if (!chip->baudrate) + chip->baudrate=1000000; + if (sja1000p_baud_rate(chip,chip->baudrate,chip->clock,0,75,0)) return -ENODEV; /* Enable hardware interrupts */ @@ -240,10 +261,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); @@ -306,6 +328,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) && @@ -339,10 +362,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); @@ -352,14 +376,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); } } @@ -426,7 +450,7 @@ int sja1000p_set_btregs(struct chip_t *chip, unsigned short btr0, } /** - * sja1000p_stop_chip: - starts chip message processing + * sja1000p_start_chip: - starts chip message processing * @chip: pointer to chip state structure * * Return Value: negative value reports error. @@ -533,6 +557,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; } @@ -575,10 +605,9 @@ void sja1000p_irq_write_handler(struct chip_t *chip, struct msgobj_t *obj) * message queues. * File: src/sja1000p.c */ -irqreturn_t sja1000p_irq_handler(int irq, void *dev_id, struct pt_regs *regs) +can_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]; @@ -588,11 +617,11 @@ irqreturn_t sja1000p_irq_handler(int irq, void *dev_id, struct pt_regs *regs) // can_read_reg(chip,SJASR)); if ((irq_register & (IR_BEI|IR_EPI|IR_DOI|IR_EI|IR_TI|IR_RI)) == 0) - return IRQ_NONE; + return CAN_IRQ_NONE; - if(!obj->flags & OBJ_BUFFERS_ALLOCATED) { - CANMSG("sja1000p_irq_handler: called with device closed, irq_register 0x%02x\n", irq_register); - return IRQ_NONE; + if(!(chip->flags&CHIP_CONFIGURED)) { + CANMSG("sja1000p_irq_handler: called for non-configured device, irq_register 0x%02x\n", irq_register); + return CAN_IRQ_NONE; } if ((irq_register & IR_RI) != 0) { @@ -603,15 +632,15 @@ irqreturn_t sja1000p_irq_handler(int irq, void *dev_id, struct pt_regs *regs) if ((irq_register & IR_TI) != 0) { DEBUGMSG("sja1000_irq_handler: TI\n"); obj->ret = 0; - set_bit(OBJ_TX_REQUEST,&obj->flags); - while(!test_and_set_bit(OBJ_TX_LOCK,&obj->flags)){ - clear_bit(OBJ_TX_REQUEST,&obj->flags); + can_msgobj_set_fl(obj,TX_REQUEST); + while(!can_msgobj_test_and_set_fl(obj,TX_LOCK)){ + can_msgobj_clear_fl(obj,TX_REQUEST); if (can_read_reg(chip, SJASR) & SR_TBS) sja1000p_irq_write_handler(chip, obj); - clear_bit(OBJ_TX_LOCK,&obj->flags); - if(!test_bit(OBJ_TX_REQUEST,&obj->flags)) break; + can_msgobj_clear_fl(obj,TX_LOCK); + if(!can_msgobj_test_fl(obj,TX_REQUEST)) break; DEBUGMSG("TX looping in sja1000_irq_handler\n"); } } @@ -629,9 +658,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"); @@ -645,10 +674,10 @@ 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; + return CAN_IRQ_HANDLED; } /** @@ -656,32 +685,32 @@ irqreturn_t sja1000p_irq_handler(int irq, void *dev_id, struct pt_regs *regs) * @chip: pointer to chip state structure * @obj: pointer to message object structure * + * Function is responsible for initiating message transmition. + * It is responsible for clearing of object TX_REQUEST flag + * * Return Value: negative value reports error. * File: src/sja1000p.c */ int sja1000p_wakeup_tx(struct chip_t *chip, struct msgobj_t *obj) { - /* dummy lock to prevent preemption fully portable way */ - spinlock_t dummy_lock; - /* preempt_disable() */ - spin_lock_init(&dummy_lock); - spin_lock(&dummy_lock); + can_preempt_disable(); - set_bit(OBJ_TX_REQUEST,&obj->flags); - while(!test_and_set_bit(OBJ_TX_LOCK,&obj->flags)){ - clear_bit(OBJ_TX_REQUEST,&obj->flags); + can_msgobj_set_fl(obj,TX_REQUEST); + while(!can_msgobj_test_and_set_fl(obj,TX_LOCK)){ + can_msgobj_clear_fl(obj,TX_REQUEST); - 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; + can_msgobj_clear_fl(obj,TX_LOCK); + if(!can_msgobj_test_fl(obj,TX_REQUEST)) break; DEBUGMSG("TX looping in sja1000p_wakeup_tx\n"); } - /* preempt_enable(); */ - spin_unlock(&dummy_lock); + can_preempt_enable(); return 0; }