]> rtime.felk.cvut.cz Git - lincan.git/blobdiff - lincan/src/virtual.c
Header-files cleanup and CAN queue edges and ends locking reimplemented.
[lincan.git] / lincan / src / virtual.c
index 42c0f57c6c0ab551c7a60f9d57f64d9ba24ac822..d51a5cbe2ee546b4b7e01431f9de9275ba366c4e 100644 (file)
@@ -6,12 +6,22 @@
  * Version lincan-0.2  9 Jul 2003
  */ 
 
-#include <linux/autoconf.h>
-
-#include <linux/delay.h>
-#include <asm/errno.h>
+#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;
 }