X-Git-Url: http://rtime.felk.cvut.cz/gitweb/lincan.git/blobdiff_plain/93ef9c984b4bcee40fbebbb3af94f5a8537141a6..6234a9dc385e5a9258a84227b2eab09bbb099c27:/lincan/src/i82527.c diff --git a/lincan/src/i82527.c b/lincan/src/i82527.c index 60096c5..9210ac4 100644 --- a/lincan/src/i82527.c +++ b/lincan/src/i82527.c @@ -248,7 +248,7 @@ int i82527_clear_objects(struct canchip_t *chip) DEBUGMSG("Cleared all message objects on chip\n"); - for (i=1; i<=15; i++) { + for (i=0; imax_objects; i++) { obj=chip->msgobj[i]; canobj_write_reg(chip,obj,(INTPD_RES|RXIE_RES|TXIE_RES|MVAL_RES),iMSGCTL0); canobj_write_reg(chip,obj,(NEWD_RES|MLST_RES|TXRQ_RES|RMPD_RES), iMSGCTL1); @@ -596,13 +596,16 @@ void i82527_irq_update_filter(struct canchip_t *chip, struct msgobj_t *obj) i82527_pre_read_config(chip, obj); - CANMSG("i82527_irq_update_filter: obj at 0x%08lx\n",obj->obj_base_addr); + CANMSG("i82527_irq_update_filter: obj at 0x%08lx\n", + can_ioptr2ulong(obj->obj_base_addr)); } } -void i82527_irq_sync_activities(struct canchip_t *chip, struct msgobj_t *obj) +int i82527_irq_sync_activities(struct canchip_t *chip, struct msgobj_t *obj) { + int job_done=0; + while(!can_msgobj_test_and_set_fl(obj,TX_LOCK)) { if(can_msgobj_test_and_clear_fl(obj,TX_REQUEST)) { @@ -616,6 +619,8 @@ void i82527_irq_sync_activities(struct canchip_t *chip, struct msgobj_t *obj) } } + job_done=1; + mb(); can_msgobj_clear_fl(obj,TX_LOCK); @@ -625,6 +630,8 @@ void i82527_irq_sync_activities(struct canchip_t *chip, struct msgobj_t *obj) continue; break; } + + return job_done; } int i82527_irq_handler(int irq, struct canchip_t *chip) @@ -632,6 +639,7 @@ int i82527_irq_handler(int irq, struct canchip_t *chip) unsigned char msgcfg; unsigned irq_register; + unsigned status_register; unsigned object; struct msgobj_t *obj; int loop_cnt=CHIP_MAX_IRQLOOP; @@ -658,14 +666,15 @@ int i82527_irq_handler(int irq, struct canchip_t *chip) DEBUGMSG("i82527: iIRQ 0x%02x\n",irq_register); if (irq_register == 0x01) { - DEBUGMSG("Status register: 0x%x\n",can_read_reg(chip, iSTAT)); + status_register=can_read_reg(chip, iSTAT); + CANMSG("Status register: 0x%x\n",status_register); continue; /*return CANCHIP_IRQ_NONE;*/ } if (irq_register == 0x02) object = 14; - else if(irq_register < 14) + else if(irq_register <= 13+3) object = irq_register-3; else return CANCHIP_IRQ_NONE; @@ -677,7 +686,17 @@ int i82527_irq_handler(int irq, struct canchip_t *chip) can_msgobj_set_fl(obj,TX_REQUEST); /* calls i82527_irq_write_handler synchronized with other invocations */ - i82527_irq_sync_activities(chip, obj); + if(i82527_irq_sync_activities(chip, obj)<=0){ + /* The interrupt has to be cleared anyway */ + canobj_write_reg(chip,obj,(MVAL_UNC|TXIE_UNC|RXIE_UNC|INTPD_RES),iMSGCTL0); + + /* + * Rerun for case, that parallel activity on SMP or fully-preemptive + * kernel result in preparation and finished sending of message + * between above if and canobj_write_reg. + */ + i82527_irq_sync_activities(chip, obj); + } } else {