]> rtime.felk.cvut.cz Git - lincan.git/blobdiff - lincan/src/virtual.c
Added glue required for RTL hardware filters updates.
[lincan.git] / lincan / src / virtual.c
index 5b39ecf4257dbbf3af203543d4bc148a203233b5..05a12f9d5026e69ca65f12702fcb4c9484a1f719 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)
@@ -270,9 +280,56 @@ void virtual_irq_write_handler(struct chip_t *chip, struct msgobj_t *obj)
  * message queues.
  * File: src/virtual.c
  */
-irqreturn_t virtual_irq_handler(int irq, void *dev_id, struct pt_regs *regs)
+can_irqreturn_t virtual_irq_handler(int irq, void *dev_id, struct pt_regs *regs)
+{
+       return CAN_IRQ_HANDLED;
+}
+
+
+void virtual_schedule_next(struct msgobj_t *obj)
+{
+       int cmd;
+
+       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);
+               
+               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));
+                       DEBUGMSG("virtual: scheduled delivery\n");
+
+               } else          
+                       can_msgobj_clear_fl(obj,TX_LOCK);
+               
+               if(!can_msgobj_test_fl(obj,TX_REQUEST)) break;
+               DEBUGMSG("TX looping in virtual_schedule_next\n");
+       }
+
+       can_preempt_enable();
+}
+
+
+void virtual_do_tx_timeout(unsigned long data)
 {
-       return IRQ_HANDLED;
+       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;
+               DEBUGMSG("virtual: delayed delivery\n");
+       }
+       can_msgobj_clear_fl(obj,TX_LOCK);
+
+       virtual_schedule_next(obj);
 }
 
 /**
@@ -280,25 +337,38 @@ irqreturn_t virtual_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/virtual.c
  */
 int virtual_wakeup_tx(struct chip_t *chip, struct msgobj_t *obj)
 {
-       /* set_bit(OBJ_TX_REQUEST,&obj->flags); */
+       /* can_msgobj_set_fl(obj,TX_REQUEST); */
        
        struct canque_edge_t *qedge;
        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);
+
+       can_msgobj_clear_fl(obj,TX_REQUEST);
+
+    #ifndef CAN_WITH_RTL
+       if(!virtual_bus_latency(obj)) {
+    #endif /*CAN_WITH_RTL*/
+               /* 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);
+                               DEBUGMSG("virtual: direct delivery\n");
+                       }
+                       canque_free_outslot(obj->qends, qedge, slot);
                }
-               canque_free_outslot(obj->qends, qedge, slot);
+    #ifndef CAN_WITH_RTL
+       } else {
+               virtual_schedule_next(obj);
        }
+    #endif /*CAN_WITH_RTL*/
 
        return 0;
 }
@@ -307,9 +377,9 @@ int virtual_wakeup_tx(struct chip_t *chip, struct msgobj_t *obj)
 /* * * Virtual Board Functionality * * */
 
 /**
- * virtual_request_io: - reserve io memory
- * @io_addr: The reserved memory starts at @io_addr, wich is the module 
- * parameter @io.
+ * virtual_request_io: - reserve io or memory range for can board
+ * @candev: pointer to candevice/board which asks for io. Field @io_addr
+ *     of @candev is used in most cases to define start of the range
  *
  * Return Value: The function returns zero on success or %-ENODEV on failure
  * File: src/virtual.c
@@ -320,8 +390,8 @@ int virtual_request_io(struct candevice_t *candev)
 }
 
 /**
- * virtual_release_io - free reserved io-memory
- * @io_addr: Start of the memory range to be released.
+ * virtual_elease_io - free reserved io memory range
+ * @candev: pointer to candevice/board which releases io
  *
  * Return Value: The function always returns zero
  * File: src/virtual.c
@@ -333,7 +403,7 @@ int virtual_release_io(struct candevice_t *candev)
 
 /**
  * virtual_reset - hardware reset routine
- * @card: Number of the hardware card.
+ * @candev: Pointer to candevice/board structure
  *
  * Return Value: The function returns zero on success or %-ENODEV on failure
  * File: src/virtual.c
@@ -344,8 +414,8 @@ int virtual_reset(struct candevice_t *candev)
 }
 
 /**
- * virtual_init_hw_data - Initialze hardware cards
- * @card: Number of the hardware card.
+ * virtual_init_hw_data - Initialize hardware cards
+ * @candev: Pointer to candevice/board structure
  *
  * Return Value: The function always returns zero
  * File: src/virtual.c
@@ -356,7 +426,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;
 }
@@ -365,7 +435,7 @@ int virtual_init_hw_data(struct candevice_t *candev)
 
 /**
  * virtual_init_chip_data - Initialize chips
- * @card: Number of the hardware card
+ * @candev: Pointer to candevice/board structure
  * @chipnr: Number of the CAN chip on the hardware card
  *
  * Return Value: The function always returns zero
@@ -407,7 +477,7 @@ int virtual_init_chip_data(struct candevice_t *candev, int chipnr)
 
 /**
  * virtual_init_obj_data - Initialize message buffers
- * @chipnr: Number of the CAN chip
+ * @chip: Pointer to chip specific structure
  * @objnr: Number of the message buffer
  *
  * Return Value: The function always returns zero
@@ -415,14 +485,16 @@ 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->tx_timeout.function=virtual_do_tx_timeout;
+       obj->tx_timeout.data=(unsigned long)obj;
        return 0;
 }
 
 /**
  * virtual_program_irq - program interrupts
- * @card: Number of the hardware card.
+ * @candev: Pointer to candevice/board structure
  *
  * Return value: The function returns zero on success or %-ENODEV on failure
  * File: src/virtual.c