X-Git-Url: http://rtime.felk.cvut.cz/gitweb/lincan.git/blobdiff_plain/cfabb1cb554e19976ed4ecd60c3d7eb9de24a43f..bfac169862856611eeb16af24c8943f005f88e12:/lincan/src/i82527.c diff --git a/lincan/src/i82527.c b/lincan/src/i82527.c index 86e340d..6897948 100644 --- a/lincan/src/i82527.c +++ b/lincan/src/i82527.c @@ -402,7 +402,8 @@ int i82527_stop_chip(struct chip_t *chip) return 0; } -inline void i82527_irq_write_handler(struct chip_t *chip, struct msgobj_t *obj) +static inline +void i82527_irq_write_handler(struct chip_t *chip, struct msgobj_t *obj) { int cmd; @@ -436,10 +437,12 @@ inline void i82527_irq_write_handler(struct chip_t *chip, struct msgobj_t *obj) canque_free_outslot(obj->qends, obj->tx_qedge, obj->tx_slot); obj->tx_slot=NULL; return; - } + } + return; } -inline void i82527_irq_read_handler(struct chip_t *chip, struct msgobj_t *obj, int objnum) +static inline +void i82527_irq_read_handler(struct chip_t *chip, struct msgobj_t *obj, int objnum) { int i; unsigned long message_id; @@ -541,6 +544,66 @@ inline void i82527_irq_read_handler(struct chip_t *chip, struct msgobj_t *obj, i i82527_irq_read_handler(chip, obj, message_id); */ + +static inline +void i82527_irq_update_filter(struct chip_t *chip, struct msgobj_t *obj) +{ + struct canfilt_t filt; + unsigned long id; + + if(canqueue_ends_filt_conjuction(obj->qends, &filt)) { + canobj_write_reg(chip,obj,(MVAL_RES|TXIE_RES|RXIE_RES|INTPD_RES),iMSGCTL0); + if(obj->object == 15) { + i82527_message15_mask(chip,filt.id,filt.mask); + } + if (filt.flags&MSG_EXT) { + id=filt.id<<3; + canobj_write_reg(chip,obj,id,iMSGID3); + canobj_write_reg(chip,obj,id>>8,iMSGID2); + canobj_write_reg(chip,obj,id>>16,iMSGID1); + canobj_write_reg(chip,obj,id>>24,iMSGID0); + canobj_write_reg(chip,obj,MCFG_XTD,iMSGCFG); + } + else { + id=filt.id<<5; + canobj_write_reg(chip,obj,id,iMSGID1); + canobj_write_reg(chip,obj,id>>8,iMSGID0); + canobj_write_reg(chip,obj,0x00,iMSGCFG); + } + + canobj_write_reg(chip,obj,(NEWD_RES|MLST_RES|TXRQ_RES|RMPD_RES), iMSGCTL1); + canobj_write_reg(chip,obj,(MVAL_SET|TXIE_RES|RXIE_SET|INTPD_RES),iMSGCTL0); + + CANMSG("i82527_irq_update_filter: obj at 0x%08lx\n",obj->obj_base_addr); + + } +} + + +void i82527_irq_sync_activities(struct chip_t *chip, struct msgobj_t *obj) +{ + while(!can_msgobj_test_and_set_fl(obj,TX_LOCK)) { + + if(can_msgobj_test_and_clear_fl(obj,TX_REQUEST)) { + if(canobj_read_reg(chip,obj,iMSGCTL1)&TXRQ_RES) + i82527_irq_write_handler(chip, obj); + } + + if(!obj->tx_slot) { + if(can_msgobj_test_and_clear_fl(obj,FILTCH_REQUEST)) { + i82527_irq_update_filter(chip, obj); + } + } + + can_msgobj_clear_fl(obj,TX_LOCK); + if(can_msgobj_test_fl(obj,TX_REQUEST)) + continue; + if(can_msgobj_test_fl(obj,FILTCH_REQUEST) && !obj->tx_slot) + continue; + break; + } +} + can_irqreturn_t i82527_irq_handler(int irq, void *dev_id, struct pt_regs *regs) { unsigned char msgcfg; @@ -583,15 +646,9 @@ can_irqreturn_t i82527_irq_handler(int irq, void *dev_id, struct pt_regs *regs) msgcfg = canobj_read_reg(chip,obj,iMSGCFG); if (msgcfg & MCFG_DIR) { 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(canobj_read_reg(chip,obj,iMSGCTL1)&TXRQ_RES) - i82527_irq_write_handler(chip, obj); - - can_msgobj_clear_fl(obj,TX_LOCK); - if(!can_msgobj_test_fl(obj,TX_REQUEST)) break; - } + + /* calls i82527_irq_write_handler synchronized with other invocations */ + i82527_irq_sync_activities(chip, obj); } else { @@ -624,23 +681,44 @@ void i82527_irq_rtr_handler(struct chip_t *chip, struct msgobj_t *obj, wake_up(&rtr_search->rtr_wq); } +/** + * i82527_wakeup_tx: - wakeups TX processing + * @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/i82527.c + */ int i82527_wakeup_tx(struct chip_t *chip, struct msgobj_t *obj) { can_preempt_disable(); 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(canobj_read_reg(chip,obj,iMSGCTL1)&TXRQ_RES) - i82527_irq_write_handler(chip, obj); + /* calls i82527_irq_write_handler synchronized with other invocations + from kernel and IRQ context */ + i82527_irq_sync_activities(chip, obj); + + can_preempt_enable(); + return 0; +} + +int i82527_filtch_rq(struct chip_t *chip, struct msgobj_t *obj) +{ + can_preempt_disable(); - can_msgobj_clear_fl(obj,TX_LOCK); - if(!can_msgobj_test_fl(obj,TX_REQUEST)) break; - } + can_msgobj_set_fl(obj,FILTCH_REQUEST); + + /* setups filter synchronized with other invocations from kernel and IRQ context */ + i82527_irq_sync_activities(chip, obj); can_preempt_enable(); return 0; + + return 0; } int i82527_register(struct chipspecops_t *chipspecops) @@ -657,6 +735,7 @@ int i82527_register(struct chipspecops_t *chipspecops) chipspecops->send_msg = i82527_send_msg; chipspecops->check_tx_stat = i82527_check_tx_stat; chipspecops->wakeup_tx = i82527_wakeup_tx; + chipspecops->filtch_rq = i82527_filtch_rq; chipspecops->remote_request = i82527_remote_request; chipspecops->enable_configuration = i82527_enable_configuration; chipspecops->disable_configuration = i82527_disable_configuration;