* 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)
* 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);
}
/**
* @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;
}
/* * * 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
}
/**
- * 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
/**
* 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
}
/**
- * 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
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;
}
/**
* 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
/**
* 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
*/
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