Added initial support for "virtual" CAN interface
authorppisa <ppisa>
Fri, 29 Aug 2003 01:32:38 +0000 (01:32 +0000)
committerppisa <ppisa>
Fri, 29 Aug 2003 01:32:38 +0000 (01:32 +0000)
and rewrite of board type parsing

lincan/include/main.h
lincan/src/Makefile
lincan/src/boardlist.c [new file with mode: 0644]
lincan/src/main.c
lincan/src/modparms.c
lincan/src/setup.c
lincan/src/virtual.c [new file with mode: 0644]

index 81e8e60..c6a0741 100644 (file)
@@ -263,3 +263,10 @@ void can_release_io_region(unsigned long start, unsigned long n);
 int can_request_mem_region(unsigned long start, unsigned long n, const char *name);
 void can_release_mem_region(unsigned long start, unsigned long n);
 
+struct boardtype_t {
+       const char *boardtype;
+       int (*board_register)(struct hwspecops_t *hwspecops);
+       int irqnum;
+};
+
+const struct boardtype_t* boardtype_find(const char *str);
index 910189f..01c6d09 100644 (file)
@@ -27,7 +27,7 @@
 
 SUPPORTED_CARDS = pip pccan smartcan nsi cc_can104 \
                  pc_i03 pcm3680 aim104 m437 pcccan ssv \
-                 bfadcan pikronisa template
+                 bfadcan pikronisa virtual template
 
 #SUPPORTED_CARDS = pcm3680 bfadcan pikronisa template
 
@@ -92,8 +92,8 @@ endif
 # Regular object files
 O_OBJS      += $(SUPPORTED_CARDS:%=%.o)
 O_OBJS       += can_queue.o devcommon.o main.o modparms.o setup.o \
-               sja1000.o i82527.o close.o ioctl.o \
-               open.o write.o read.o sja1000p.o irq.o select.o
+               sja1000p.o sja1000.o i82527.o irq.o boardlist.o \
+               open.o close.o write.o read.o ioctl.o select.o
 # Objects with exported symbols (-DEXPORT_SYMTAB)
 OX_OBJS      = 
 # Module objects 
diff --git a/lincan/src/boardlist.c b/lincan/src/boardlist.c
new file mode 100644 (file)
index 0000000..569aab2
--- /dev/null
@@ -0,0 +1,108 @@
+/* boards_list.c
+ * Linux CAN-bus device driver.
+ * Written for new CAN driver version by Pavel Pisa - OCERA team member
+ * email:pisa@cmp.felk.cvut.cz
+ * This software is released under the GPL-License.
+ * Version lincan-0.2  9 Jul 2003
+ */
+
+#include <linux/autoconf.h>
+#include <linux/version.h>
+
+#include "../include/main.h"
+
+#include ".supported_cards.h"
+
+#include "../include/pip.h"
+#include "../include/pccan.h"
+#include "../include/smartcan.h"
+#include "../include/pc-i03.h"
+#include "../include/pcm3680.h"
+#include "../include/m437.h"
+#include "../include/template.h"
+#include "../include/i82527.h"
+#include "../include/aim104.h"
+#include "../include/pcccan.h"
+
+extern int template_register(struct hwspecops_t *hwspecops);
+extern int pip5_register(struct hwspecops_t *hwspecops);
+extern int pip6_register(struct hwspecops_t *hwspecops);
+extern int smartcan_register(struct hwspecops_t *hwspecops);
+extern int pccanf_register(struct hwspecops_t *hwspecops);
+extern int pccand_register(struct hwspecops_t *hwspecops);
+extern int pccanq_register(struct hwspecops_t *hwspecops);
+extern int nsi_register(struct hwspecops_t *hwspecops);
+extern int cc104_register(struct hwspecops_t *hwspecops);
+extern int pci03_register(struct hwspecops_t *hwspecops);
+extern int pcm3680_register(struct hwspecops_t *hwspecops);
+extern int aim104_register(struct hwspecops_t *hwspecops);
+extern int pcccan_register(struct hwspecops_t *hwspecops);
+extern int ssv_register(struct hwspecops_t *hwspecops);
+extern int bfadcan_register(struct hwspecops_t *hwspecops);
+extern int pikronisa_register(struct hwspecops_t *hwspecops);
+extern int virtual_register(struct hwspecops_t *hwspecops);
+
+const struct boardtype_t can_boardtypes[]={
+    #ifdef ENABLE_CARD_template
+       {"template", template_register, 1},
+    #endif
+    #ifdef ENABLE_CARD_template
+       {"virtual", virtual_register, 0},
+    #endif
+    #ifdef ENABLE_CARD_pip
+       {"pip5", pip5_register, 1},
+       {"pip6", pip6_register, 1},
+    #endif
+    #ifdef ENABLE_CARD_smartcan
+       {"smartcan", smartcan_register, 1},
+    #endif
+    #ifdef ENABLE_CARD_nsi
+       {"nsican", nsi_register, 1},
+    #endif
+    #ifdef ENABLE_CARD_cc_can104
+       {"cc104", cc104_register, 1},
+    #endif
+    #ifdef ENABLE_CARD_aim104
+       {"aim104", aim104_register, 1},
+    #endif
+    #ifdef ENABLE_CARD_pc_i03
+       {"pc-i03", pci03_register, 1},
+    #endif
+    #ifdef ENABLE_CARD_pcm3680
+       {"pcm3680", pcm3680_register, 2},
+    #endif
+    #ifdef ENABLE_CARD_pccan
+       {"pccan-f", pccanf_register, 1},
+       {"pccan-s", pccanf_register, 1},
+       {"pccan-d", pccand_register, 2},
+       {"pccan-q", pccanq_register, 4},
+    #endif
+    #ifdef ENABLE_CARD_m437
+       {"m437", m437_register, 1},
+    #endif
+    #ifdef ENABLE_CARD_pcccan
+       {"pcccan", pcccan_register, 1},
+    #endif
+    #ifdef ENABLE_CARD_ssv
+       {"ssv", ssv_register, 2},
+    #endif
+    #ifdef ENABLE_CARD_bfadcan
+       {"bfadcan", bfadcan_register, 1},
+    #endif
+    #ifdef ENABLE_CARD_pikronisa
+       {"pikronisa", pikronisa_register, 1},
+    #endif
+       {NULL}
+};
+
+const struct boardtype_t* boardtype_find(const char *str)
+{
+       const struct boardtype_t *brp;
+
+       for(brp=can_boardtypes;brp->boardtype;brp++) {
+               if(!strcmp(str,brp->boardtype))
+                       return brp;
+       }
+
+       return NULL;
+}
index d52cabf..0f5f60a 100644 (file)
@@ -278,7 +278,8 @@ void cleanup_module(void)
 #endif
         i=0;
        while ( (chips_p[i] != NULL) & (i < MAX_TOT_CHIPS) ) {
-               free_irq(chips_p[i]->chip_irq, chips_p[i]);
+               if(chips_p[i]->chipspecops->irq_handler)
+                       free_irq(chips_p[i]->chip_irq, chips_p[i]);
                i++;
        }
 
index 96d66d5..1608bd2 100644 (file)
 
 #include <linux/autoconf.h>
 
-#include ".supported_cards.h"
-
-#ifndef ENABLE_CARD_pip
-#define ENABLE_CARD_pip 0
-#endif
-#ifndef ENABLE_CARD_smartcan
-#define ENABLE_CARD_smartcan 0
-#endif
-#ifndef ENABLE_CARD_pccan
-#define ENABLE_CARD_pccan 0
-#endif
-#ifndef ENABLE_CARD_nsi
-#define ENABLE_CARD_nsi 0
-#endif
-#ifndef ENABLE_CARD_cc_can104
-#define ENABLE_CARD_cc_can104 0
-#endif
-#ifndef ENABLE_CARD_aim104
-#define ENABLE_CARD_aim104 0
-#endif
-#ifndef ENABLE_CARD_pc_i03
-#define ENABLE_CARD_pc_i03 0
-#endif
-#ifndef ENABLE_CARD_pcm3680
-#define ENABLE_CARD_pcm3680 0
-#endif
-#ifndef ENABLE_CARD_m437
-#define ENABLE_CARD_m437 0
-#endif
-#ifndef ENABLE_CARD_pcccan
-#define ENABLE_CARD_pcccan 0
-#endif
-#ifndef ENABLE_CARD_ssv
-#define ENABLE_CARD_ssv 0
-#endif
-#ifndef ENABLE_CARD_bfadcan
-#define ENABLE_CARD_bfadcan 0
-#endif
-#ifndef ENABLE_CARD_pikronisa
-#define ENABLE_CARD_pikronisa 0
-#endif
-#ifndef ENABLE_CARD_template
-#define ENABLE_CARD_template 0
-#endif
-
 #include <linux/string.h>
 #include <linux/fs.h>
 
 int parse_mod_parms(void)
 {
        int i=0,j=0,irq_needed=0,irq_supplied=0,io_needed=0,io_supplied=0,minor_needed=0,minor_supplied=0;
+       const struct boardtype_t *brp;
 
-       if ( (hw[0] == NULL) | (irq[0] == -1) | (io[0] == -1) ) {
+       if ( (hw[0] == NULL) | (io[0] == -1) ) {
                CANMSG("You must supply your type of hardware, interrupt numbers and io address.\n");
                CANMSG("Example: # insmod can.o hw=pip5 irq=4 io=0x8000\n");
                return -ENODEV;
        }
 
        while ( (hw[i] != NULL) && (i < MAX_HW_CARDS) ) {
-               if ( !strcmp(hw[i],"pip5") && ENABLE_CARD_pip )
-                       irq_needed++;
-               else if (!strcmp(hw[i],"pip6") && ENABLE_CARD_pip)
-                       irq_needed++;
-               else if (!strcmp(hw[i],"smartcan") && ENABLE_CARD_smartcan)
-                       irq_needed++;
-               else if (!strcmp(hw[i],"pccan-q") && ENABLE_CARD_pccan)
-                       irq_needed=irq_needed+4;
-               else if (!strcmp(hw[i],"pccan-f") && ENABLE_CARD_pccan)
-                       irq_needed++;
-               else if (!strcmp(hw[i],"pccan-s") && ENABLE_CARD_pccan)
-                       irq_needed++;
-               else if (!strcmp(hw[i],"pccan-d") && ENABLE_CARD_pccan)
-                       irq_needed=irq_needed+2;
-               else if (!strcmp(hw[i],"nsican") && ENABLE_CARD_nsi)
-                       irq_needed++;
-               else if (!strcmp(hw[i],"cc104") && ENABLE_CARD_cc_can104)
-                       irq_needed++;
-               else if (!strcmp(hw[i],"aim104") && ENABLE_CARD_aim104)
-                       irq_needed++;
-               else if (!strcmp(hw[i],"pc-i03") && ENABLE_CARD_pc_i03)
-                       irq_needed++;
-               else if (!strcmp(hw[i],"pcm3680") && ENABLE_CARD_pcm3680)
-                       irq_needed=irq_needed+2;
-               else if (!strcmp(hw[i],"m437") && ENABLE_CARD_m437)
-                       irq_needed++;
-               else if (!strcmp(hw[i],"pcccan") && ENABLE_CARD_pcccan)
-                       irq_needed++;
-               else if (!strcmp(hw[i],"ssv") && ENABLE_CARD_ssv)
-                       irq_needed=irq_needed+2;
-               else if (!strcmp(hw[i],"bfadcan") && ENABLE_CARD_bfadcan)
-                       irq_needed++;
-               else if (!strcmp(hw[i],"pikronisa") && ENABLE_CARD_pikronisa)
-                       irq_needed++;
-               else if (!strcmp(hw[i],"template") && ENABLE_CARD_template);
-               else {
+               brp = boardtype_find(hw[i]);
+               if(!brp) {
                        CANMSG("Sorry, hardware \"%s\" is currently not supported.\n",hw[i]);
                        return -EINVAL;
                }
+               irq_needed += brp->irqnum;
                i++;
        }
 
@@ -128,7 +51,7 @@ int parse_mod_parms(void)
        while ( (irq[irq_supplied] != -1) & (irq_supplied<MAX_IRQ) )
                irq_supplied++;
        while ( (hw[j] != NULL) && (j<MAX_HW_CARDS) ) {
-               if (!strcmp(hw[j],"template") && ENABLE_CARD_template)
+               if (!strcmp(hw[j],"template"))
                        irq_needed = irq_supplied;
                j++;
        }
index 88f0450..49b4315 100644 (file)
 #include <linux/fs.h>
 #include <linux/ioport.h>
 
-#include ".supported_cards.h"
-
 #include "../include/main.h"
 #include "../include/devcommon.h"
 #include "../include/setup.h"
-#include "../include/pip.h"
-#include "../include/pccan.h"
-#include "../include/smartcan.h"
-#include "../include/pc-i03.h"
-#include "../include/pcm3680.h"
-#include "../include/m437.h"
-#include "../include/template.h"
-#include "../include/i82527.h"
-#include "../include/aim104.h"
-#include "../include/pcccan.h"
 
 extern int sja1000_register(struct chipspecops_t *chipspecops);
 extern int sja1000p_register(struct chipspecops_t *chipspecops);
 extern int i82527_register(struct chipspecops_t *chipspecops);
-extern int template_register(struct hwspecops_t *hwspecops);
-extern int pip5_register(struct hwspecops_t *hwspecops);
-extern int pip6_register(struct hwspecops_t *hwspecops);
-extern int smartcan_register(struct hwspecops_t *hwspecops);
-extern int pccanf_register(struct hwspecops_t *hwspecops);
-extern int pccand_register(struct hwspecops_t *hwspecops);
-extern int pccanq_register(struct hwspecops_t *hwspecops);
-extern int nsi_register(struct hwspecops_t *hwspecops);
-extern int cc104_register(struct hwspecops_t *hwspecops);
-extern int pci03_register(struct hwspecops_t *hwspecops);
-extern int pcm3680_register(struct hwspecops_t *hwspecops);
-extern int aim104_register(struct hwspecops_t *hwspecops);
-extern int pcccan_register(struct hwspecops_t *hwspecops);
-extern int ssv_register(struct hwspecops_t *hwspecops);
-extern int bfadcan_register(struct hwspecops_t *hwspecops);
-extern int pikronisa_register(struct hwspecops_t *hwspecops);
 
 int init_device_struct(int card);
 int init_hwspecops(struct candevice_t *candev);
@@ -242,6 +214,7 @@ int init_device_struct(int card)
        else
                if ( add_mem_to_list(candev->hwspecops) )
                        return -ENOMEM;
+       memset(candev->hwspecops, 0, sizeof(struct hwspecops_t));
 
        if (init_hwspecops(candev))
                return -ENODEV;
@@ -353,93 +326,22 @@ int init_obj_struct(struct candevice_t *candev, struct chip_t *hostchip, int min
 
 int init_hwspecops(struct candevice_t *candev)
 {
-       #ifdef ENABLE_CARD_template
-       if (!strcmp(candev->hwname,"template")) {
-               template_register(candev->hwspecops);
-       }
-       #endif
-       #ifdef ENABLE_CARD_pip
-       if (!strcmp(candev->hwname,"pip5")) {
-               pip5_register(candev->hwspecops);
-       }
-       else if (!strcmp(candev->hwname,"pip6")) {
-               pip6_register(candev->hwspecops);
-       }
-       #endif
-       #ifdef ENABLE_CARD_smartcan
-       if (!strcmp(candev->hwname,"smartcan")) {
-               smartcan_register(candev->hwspecops);
-       }
-       #endif
-       #ifdef ENABLE_CARD_nsi
-       if (!strcmp(candev->hwname,"nsican")) {
-               nsi_register(candev->hwspecops);
-       }
-       #endif
-       #ifdef ENABLE_CARD_cc_can104
-       if (!strcmp(candev->hwname,"cc104")) {
-               cc104_register(candev->hwspecops);
-       }
-       #endif
-       #ifdef ENABLE_CARD_aim104
-       if (!strcmp(candev->hwname,"aim104")) {
-               aim104_register(candev->hwspecops);
-       }
-       #endif
-       #ifdef ENABLE_CARD_pc_i03
-       if (!strcmp(candev->hwname,"pc-i03")) {
-               pci03_register(candev->hwspecops);
-       }
-       #endif
-       #ifdef ENABLE_CARD_pcm3680
-       if (!strcmp(candev->hwname,"pcm3680")) {
-               pcm3680_register(candev->hwspecops);
-       }
-       #endif
-       #ifdef ENABLE_CARD_pccan
-       if (!strcmp(candev->hwname,"pccan-f") |
-                !strcmp(candev->hwname,"pccan-s") ) {
-               pccanf_register(candev->hwspecops);
-       }
-       if (!strcmp(candev->hwname,"pccan-d")) {
-               pccand_register(candev->hwspecops);
-       }
-       if (!strcmp(candev->hwname,"pccan-q")) {
-               pccanq_register(candev->hwspecops);
-       }
-       #endif
-       #ifdef ENABLE_CARD_m437
-       if (!strcmp(candev->hwname,"m437")) {
-               m437_register(candev->hwspecops);
-       }
-       #endif
-       #ifdef ENABLE_CARD_pcccan
-       if (!strcmp(candev->hwname,"pcccan")) {
-               pcccan_register(candev->hwspecops);
-       }
-       #endif
-       #ifdef ENABLE_CARD_ssv
-       if (!strcmp(candev->hwname,"ssv")) {
-               ssv_register(candev->hwspecops);
-       }
-       #endif
-       #ifdef ENABLE_CARD_bfadcan
-       if (!strcmp(candev->hwname,"bfadcan")) {
-               bfadcan_register(candev->hwspecops);
-       }
-       #endif
-       #ifdef ENABLE_CARD_pikronisa
-       if (!strcmp(candev->hwname,"pikronisa")) {
-               pikronisa_register(candev->hwspecops);
+       const struct boardtype_t *brp;
+       
+       brp = boardtype_find(candev->hwname);
+       
+       if(!brp) {
+               CANMSG("Sorry, hardware \"%s\" is currently not supported.\n",candev->hwname);
+               return -EINVAL;
        }
-       #endif
+       
+       brp->board_register(candev->hwspecops);
+
        return 0;
 }
 
 int init_chipspecops(struct candevice_t *candev, int chipnr)
 {
-       candev->chip[chipnr]->max_objects=0;
-       
        if (!strcmp(candev->chip[chipnr]->chip_type,"i82527")) {
                candev->chip[chipnr]->max_objects=15;
                i82527_register(candev->chip[chipnr]->chipspecops);
diff --git a/lincan/src/virtual.c b/lincan/src/virtual.c
new file mode 100644 (file)
index 0000000..5b39ecf
--- /dev/null
@@ -0,0 +1,447 @@
+/* virtual.c
+ * Linux CAN-bus device driver.
+ * Written for new CAN driver version by Pavel Pisa - OCERA team member
+ * email:pisa@cmp.felk.cvut.cz
+ * This software is released under the GPL-License.
+ * Version lincan-0.2  9 Jul 2003
+ */ 
+
+#include <linux/autoconf.h>
+
+#include <linux/delay.h>
+#include <asm/errno.h>
+#include "../include/main.h"
+
+/* * * Virtual Chip Functionality * * */
+
+int virtual_enable_configuration(struct chip_t *chip)
+{
+       return 0;
+}
+
+int virtual_disable_configuration(struct chip_t *chip)
+{
+       return 0;
+}
+
+/**
+ * virtual_chip_config: - can chip configuration
+ * @chip: pointer to chip state structure
+ *
+ * Return Value: negative value reports error.
+ * File: src/virtual.c
+ */
+int virtual_chip_config(struct chip_t *chip)
+{
+       return 0;
+}
+
+/**
+ * virtual_extended_mask: - setup of extended mask for message filtering
+ * @chip: pointer to chip state structure
+ * @code: can message acceptance code
+ * @mask: can message acceptance mask
+ *
+ * Return Value: negative value reports error.
+ * File: src/virtual.c
+ */
+int virtual_extended_mask(struct chip_t *chip, unsigned long code, unsigned  long mask)
+{
+       return 0;
+}
+
+/**
+ * virtual_baud_rate: - set communication parameters.
+ * @chip: pointer to chip state structure
+ * @rate: baud rate in Hz
+ * @clock: frequency of sja1000 clock in Hz (ISA osc is 14318000)
+ * @sjw: synchronization jump width (0-3) prescaled clock cycles
+ * @sampl_pt: sample point in % (0-100) sets (TSEG1+1)/(TSEG1+TSEG2+2) ratio
+ * @flags: fields %BTR1_SAM, %OCMODE, %OCPOL, %OCTP, %OCTN, %CLK_OFF, %CBP
+ *
+ * Return Value: negative value reports error.
+ * File: src/virtual.c
+ */
+int virtual_baud_rate(struct chip_t *chip, int rate, int clock, int sjw,
+                                                       int sampl_pt, int flags)
+{
+       return 0;
+}
+
+/**
+ * virtual_read: - reads and distributes one or more received messages
+ * @chip: pointer to chip state structure
+ * @obj: pinter to CAN message queue information
+ *
+ * File: src/virtual.c
+ */
+void virtual_read(struct chip_t *chip, struct msgobj_t *obj) {
+
+}
+
+/**
+ * virtual_pre_read_config: - prepares message object for message reception
+ * @chip: pointer to chip state structure
+ * @obj: pointer to message object state structure
+ *
+ * Return Value: negative value reports error.
+ *     Positive value indicates immediate reception of message.
+ * File: src/virtual.c
+ */
+int virtual_pre_read_config(struct chip_t *chip, struct msgobj_t *obj)
+{
+       return 0;
+}
+
+#define MAX_TRANSMIT_WAIT_LOOPS 10
+/**
+ * virtual_pre_write_config: - prepares message object for message transmission
+ * @chip: pointer to chip state structure
+ * @obj: pointer to message object state structure
+ * @msg: pointer to CAN message
+ *
+ * Return Value: negative value reports error.
+ * File: src/virtual.c
+ */
+int virtual_pre_write_config(struct chip_t *chip, struct msgobj_t *obj, 
+                                                       struct canmsg_t *msg)
+{
+       return 0;
+}
+
+/**
+ * virtual_send_msg: - initiate message transmission
+ * @chip: pointer to chip state structure
+ * @obj: pointer to message object state structure
+ * @msg: pointer to CAN message
+ *
+ * This function is called after virtual_pre_write_config() function,
+ * which prepares data in chip buffer.
+ * Return Value: negative value reports error.
+ * File: src/virtual.c
+ */
+int virtual_send_msg(struct chip_t *chip, struct msgobj_t *obj, 
+                                                       struct canmsg_t *msg)
+{
+       return 0;
+}
+
+/**
+ * virtual_check_tx_stat: - checks state of transmission engine
+ * @chip: pointer to chip state structure
+ *
+ * Return Value: negative value reports error.
+ *     Positive return value indicates transmission under way status.
+ *     Zero value indicates finishing of all issued transmission requests.
+ * File: src/virtual.c
+ */
+int virtual_check_tx_stat(struct chip_t *chip)
+{
+       return 0;
+}
+
+/**
+ * virtual_set_btregs: -  configures bitrate registers
+ * @chip: pointer to chip state structure
+ * @btr0: bitrate register 0
+ * @btr1: bitrate register 1
+ *
+ * Return Value: negative value reports error.
+ * File: src/virtual.c
+ */
+int virtual_set_btregs(struct chip_t *chip, unsigned short btr0, 
+                                                       unsigned short btr1)
+{
+       return 0;
+}
+
+/**
+ * virtual_stop_chip: -  starts chip message processing
+ * @chip: pointer to chip state structure
+ *
+ * Return Value: negative value reports error.
+ * File: src/virtual.c
+ */
+int virtual_start_chip(struct chip_t *chip)
+{
+       return 0;
+}
+
+/**
+ * virtual_stop_chip: -  stops chip message processing
+ * @chip: pointer to chip state structure
+ *
+ * Return Value: negative value reports error.
+ * File: src/virtual.c
+ */
+int virtual_stop_chip(struct chip_t *chip)
+{
+       return 0;
+}
+
+
+/**
+ * virtual_remote_request: - configures message object and asks for RTR message
+ * @chip: pointer to chip state structure
+ * @obj: pointer to message object structure
+ *
+ * Return Value: negative value reports error.
+ * File: src/virtual.c
+ */
+int virtual_remote_request(struct chip_t *chip, struct msgobj_t *obj)
+{
+       CANMSG("virtual_remote_request not implemented\n");
+       return -ENOSYS;
+}
+
+/**
+ * virtual_standard_mask: - setup of mask for message filtering
+ * @chip: pointer to chip state structure
+ * @code: can message acceptance code
+ * @mask: can message acceptance mask
+ *
+ * Return Value: negative value reports error.
+ * File: src/virtual.c
+ */
+int virtual_standard_mask(struct chip_t *chip, unsigned short code,
+               unsigned short mask)
+{
+       CANMSG("virtual_standard_mask not implemented\n");
+       return -ENOSYS;
+}
+
+/**
+ * virtual_clear_objects: - clears state of all message object residing in chip
+ * @chip: pointer to chip state structure
+ *
+ * Return Value: negative value reports error.
+ * File: src/virtual.c
+ */
+int virtual_clear_objects(struct chip_t *chip)
+{
+       CANMSG("virtual_clear_objects not implemented\n");
+       return -ENOSYS;
+}
+
+/**
+ * virtual_config_irqs: - tunes chip hardware interrupt delivery
+ * @chip: pointer to chip state structure
+ * @irqs: requested chip IRQ configuration
+ *
+ * Return Value: negative value reports error.
+ * File: src/virtual.c
+ */
+int virtual_config_irqs(struct chip_t *chip, short irqs)
+{
+       CANMSG("virtual_config_irqs not implemented\n");
+       return -ENOSYS;
+}
+
+/**
+ * virtual_irq_write_handler: - part of ISR code responsible for transmit events
+ * @chip: pointer to chip state structure
+ * @obj: pointer to attached queue description
+ *
+ * The main purpose of this function is to read message from attached queues
+ * and transfer message contents into CAN controller chip.
+ * This subroutine is called by
+ * virtual_irq_write_handler() for transmit events.
+ * File: src/virtual.c
+ */
+void virtual_irq_write_handler(struct chip_t *chip, struct msgobj_t *obj)
+{
+
+}
+
+#define MAX_RETR 10
+
+/**
+ * virtual_irq_handler: - interrupt service routine
+ * @irq: interrupt vector number, this value is system specific
+ * @dev_id: driver private pointer registered at time of request_irq() call.
+ *     The CAN driver uses this pointer to store relationship of interrupt
+ *     to chip state structure - @struct chip_t
+ * @regs: system dependent value pointing to registers stored in exception frame
+ * 
+ * Interrupt handler is activated when state of CAN controller chip changes,
+ * there is message to be read or there is more space for new messages or
+ * error occurs. The receive events results in reading of the message from
+ * CAN controller chip and distribution of message through attached
+ * message queues.
+ * File: src/virtual.c
+ */
+irqreturn_t virtual_irq_handler(int irq, void *dev_id, struct pt_regs *regs)
+{
+       return IRQ_HANDLED;
+}
+
+/**
+ * virtual_wakeup_tx: - wakeups TX processing
+ * @chip: pointer to chip state structure
+ * @obj: pointer to message object structure
+ *
+ * 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); */
+       
+       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);
+               }
+               canque_free_outslot(obj->qends, qedge, slot);
+       }
+
+       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.
+ *
+ * Return Value: The function returns zero on success or %-ENODEV on failure
+ * File: src/virtual.c
+ */
+int virtual_request_io(struct candevice_t *candev)
+{
+       return 0;
+}
+
+/**
+ * virtual_release_io - free reserved io-memory
+ * @io_addr: Start of the memory range to be released.
+ *
+ * Return Value: The function always returns zero
+ * File: src/virtual.c
+ */
+int virtual_release_io(struct candevice_t *candev)
+{
+       return 0;
+}
+
+/**
+ * virtual_reset - hardware reset routine
+ * @card: Number of the hardware card.
+ *
+ * Return Value: The function returns zero on success or %-ENODEV on failure
+ * File: src/virtual.c
+ */
+int virtual_reset(struct candevice_t *candev)
+{
+       return 0;
+}
+
+/**
+ * virtual_init_hw_data - Initialze hardware cards
+ * @card: Number of the hardware card.
+ *
+ * Return Value: The function always returns zero
+ * File: src/virtual.c
+ */
+int virtual_init_hw_data(struct candevice_t *candev) 
+{
+       candev->res_addr=0;
+       candev->nr_82527_chips=0;
+       candev->nr_sja1000_chips=0;
+       candev->nr_all_chips=1;
+       candev->flags |= PROGRAMMABLE_IRQ*0;
+
+       return 0;
+}
+
+#define CHIP_TYPE "virtual"
+
+/**
+ * virtual_init_chip_data - Initialize chips
+ * @card: Number of the hardware card
+ * @chipnr: Number of the CAN chip on the hardware card
+ *
+ * Return Value: The function always returns zero
+ * File: src/virtual.c
+ */
+int virtual_init_chip_data(struct candevice_t *candev, int chipnr)
+{
+       struct chip_t *chip = candev->chip[chipnr];
+       chip->chip_type = CHIP_TYPE;
+       chip->chip_base_addr = 0;
+       chip->clock = 10000000;
+       chip->int_clk_reg = 0x0;
+       chip->int_bus_reg = 0x0;
+       chip->max_objects = 1;
+
+       CANMSG("initializing virtual chip operations\n");
+       chip->chipspecops->chip_config=virtual_chip_config;
+       chip->chipspecops->baud_rate=virtual_baud_rate;
+       chip->chipspecops->standard_mask=virtual_standard_mask;
+       chip->chipspecops->extended_mask=virtual_extended_mask;
+       chip->chipspecops->message15_mask=virtual_extended_mask;
+       chip->chipspecops->clear_objects=virtual_clear_objects;
+       chip->chipspecops->config_irqs=virtual_config_irqs;
+       chip->chipspecops->pre_read_config=virtual_pre_read_config;
+       chip->chipspecops->pre_write_config=virtual_pre_write_config;
+       chip->chipspecops->send_msg=virtual_send_msg;
+       chip->chipspecops->check_tx_stat=virtual_check_tx_stat;
+       chip->chipspecops->wakeup_tx=virtual_wakeup_tx;
+       chip->chipspecops->remote_request=virtual_remote_request;
+       chip->chipspecops->enable_configuration=virtual_enable_configuration;
+       chip->chipspecops->disable_configuration=virtual_disable_configuration;
+       chip->chipspecops->set_btregs=virtual_set_btregs;
+       chip->chipspecops->start_chip=virtual_start_chip;
+       chip->chipspecops->stop_chip=virtual_stop_chip;
+       chip->chipspecops->irq_handler=NULL;
+
+       return 0;
+}
+
+/**
+ * virtual_init_obj_data - Initialize message buffers
+ * @chipnr: Number of the CAN chip
+ * @objnr: Number of the message buffer
+ *
+ * Return Value: The function always returns zero
+ * File: src/virtual.c
+ */
+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;
+       return 0;
+}
+
+/**
+ * virtual_program_irq - program interrupts
+ * @card: Number of the hardware card.
+ *
+ * Return value: The function returns zero on success or %-ENODEV on failure
+ * File: src/virtual.c
+ */
+int virtual_program_irq(struct candevice_t *candev)
+{
+       return 0;
+}
+
+int virtual_register(struct hwspecops_t *hwspecops)
+{
+       hwspecops->request_io = virtual_request_io;
+       hwspecops->release_io = virtual_release_io;
+       hwspecops->reset = virtual_reset;
+       hwspecops->init_hw_data = virtual_init_hw_data;
+       hwspecops->init_chip_data = virtual_init_chip_data;
+       hwspecops->init_obj_data = virtual_init_obj_data;
+       hwspecops->write_register = NULL;
+       hwspecops->read_register = NULL;
+       hwspecops->program_irq = virtual_program_irq;
+       return 0;
+}