X-Git-Url: http://rtime.felk.cvut.cz/gitweb/lincan.git/blobdiff_plain/102b0fcc467c77d0a8f82cfee060353e3cf17261..c6d6f58c34e1b6a4c03d1e86d1abf48eeb6f5624:/lincan/src/virtual.c diff --git a/lincan/src/virtual.c b/lincan/src/virtual.c index 42c0f57..d51a5cb 100644 --- a/lincan/src/virtual.c +++ b/lincan/src/virtual.c @@ -6,12 +6,22 @@ * Version lincan-0.2 9 Jul 2003 */ -#include - -#include -#include +#include "../include/can.h" +#include "../include/can_sysdep.h" #include "../include/main.h" + +long virtual_bus_latency(struct msgobj_t *obj) +{ + long latency; + latency=obj->hostchip->baudrate; + if(latency){ + latency=(long)HZ*1000/latency; + } + return latency; +} + + /* * * Virtual Chip Functionality * * */ int virtual_enable_configuration(struct chip_t *chip) @@ -275,6 +285,58 @@ irqreturn_t virtual_irq_handler(int irq, void *dev_id, struct pt_regs *regs) return IRQ_HANDLED; } + +void virtual_schedule_next(struct msgobj_t *obj) +{ + int cmd; + /* dummy lock to prevent preemption fully portable way */ + spinlock_t dummy_lock; + + /* preempt_disable() */ + spin_lock_init(&dummy_lock); + spin_lock(&dummy_lock); + + set_bit(OBJ_TX_REQUEST,&obj->flags); + + while(!test_and_set_bit(OBJ_TX_LOCK,&obj->flags)){ + + clear_bit(OBJ_TX_REQUEST,&obj->flags); + + cmd=canque_test_outslot(obj->qends, &obj->tx_qedge, &obj->tx_slot); + if(cmd>=0) { + mod_timer(&obj->tx_timeout, + jiffies+virtual_bus_latency(obj)); + CANMSG("virtual: scheduled delivery\n"); + + } else + clear_bit(OBJ_TX_LOCK,&obj->flags); + + if(!test_bit(OBJ_TX_REQUEST,&obj->flags)) break; + DEBUGMSG("TX looping in virtual_schedule_next\n"); + } + + /* preempt_enable(); */ + spin_unlock(&dummy_lock); +} + + +void virtual_do_tx_timeout(unsigned long data) +{ + struct msgobj_t *obj=(struct msgobj_t *)data; + + if(obj->tx_slot) { + /* Deliver message to edges */ + 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; + CANMSG("virtual: delayed delivery\n"); + } + clear_bit(OBJ_TX_LOCK,&obj->flags); + + virtual_schedule_next(obj); +} + /** * virtual_wakeup_tx: - wakeups TX processing * @chip: pointer to chip state structure @@ -291,13 +353,17 @@ int virtual_wakeup_tx(struct chip_t *chip, struct msgobj_t *obj) struct canque_slot_t *slot; int cmd; - /* Ensure delivery of all ready slots */ - - while((cmd=canque_test_outslot(obj->qends, &qedge, &slot)) >= 0){ - if(cmd==0) { - canque_filter_msg2edges(obj->qends, &slot->msg); + if(!virtual_bus_latency(obj)) { + /* Ensure delivery of all ready slots */ + while((cmd=canque_test_outslot(obj->qends, &qedge, &slot)) >= 0){ + if(cmd==0) { + canque_filter_msg2edges(obj->qends, &slot->msg); + CANMSG("virtual: direct delivery\n"); + } + canque_free_outslot(obj->qends, qedge, slot); } - canque_free_outslot(obj->qends, qedge, slot); + } else { + virtual_schedule_next(obj); } return 0; @@ -356,7 +422,7 @@ int virtual_init_hw_data(struct candevice_t *candev) candev->nr_82527_chips=0; candev->nr_sja1000_chips=0; candev->nr_all_chips=1; - candev->flags |= PROGRAMMABLE_IRQ*0; + candev->flags |= CANDEV_PROGRAMMABLE_IRQ*0; return 0; } @@ -415,8 +481,11 @@ int virtual_init_chip_data(struct candevice_t *candev, int chipnr) */ int virtual_init_obj_data(struct chip_t *chip, int objnr) { - chip->msgobj[objnr]->obj_base_addr=chip->chip_base_addr; - chip->msgobj[objnr]->flags=0; + struct msgobj_t *obj=chip->msgobj[objnr]; + obj->obj_base_addr=chip->chip_base_addr; + obj->flags=0; + obj->tx_timeout.function=virtual_do_tx_timeout; + obj->tx_timeout.data=(unsigned long)obj; return 0; }