Merge branch 'master' into can-usb1
authorppisa <pisa@cmp.felk.cvut.cz>
Sat, 1 Nov 2008 12:40:35 +0000 (13:40 +0100)
committerppisa <pisa@cmp.felk.cvut.cz>
Sat, 1 Nov 2008 12:40:35 +0000 (13:40 +0100)
The changes between LinCAN 0.3.3 version and current master head are propagated
into "can-usb1" branch.

Conflicts:

lincan/include/kthread.h
lincan/include/main.h
lincan/src/Makefile.omk
lincan/src/bfadcan.c
lincan/src/boardlist.c
lincan/src/finish.c
lincan/src/kthread.c
lincan/src/main.c
lincan/src/modparms.c
lincan/src/proc.c
lincan/src/setup.c

1  2 
lincan/include/can_sysdep.h
lincan/include/main.h
lincan/src/Makefile.omk
lincan/src/boardlist.c
lincan/src/main.c
lincan/src/modparms.c
lincan/src/proc.c
lincan/src/setup.c

    #define CAN_IRQ_HANDLED IRQ_HANDLED
    #define CAN_IRQ_RETVAL  IRQ_RETVAL
  #endif /* <=2.5.67 */
+ #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19))
+   #define CAN_IRQ_HANDLER_ARGS(irq_number, dev_id) \
+               int irq_number, void *dev_id, struct pt_regs *regs
+ #else /* < 2.6.19 */
+   #define CAN_IRQ_HANDLER_ARGS(irq_number, dev_id) \
+               int irq_number, void *dev_id
+ #endif /* < 2.6.19 */
  #else /*CAN_WITH_RTL*/
    typedef int can_irqreturn_t;
    #define CAN_IRQ_NONE        0
    #define CAN_IRQ_HANDLED     1
    #define CAN_IRQ_RETVAL(x)   ((x) != 0)
+   #define CAN_IRQ_HANDLER_ARGS(irq_number, dev_id) \
+               int irq_number, void *dev_id, struct pt_regs *regs
  #endif /*CAN_WITH_RTL*/
  
  #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,33))
    #define del_timer_sync del_timer
  #endif /* <2.4.0 */
  
+ #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,9))
+    typedef unsigned long can_ioptr_t;
+    #define can_ioptr2ulong(ioaddr) ((unsigned long)(ioaddr))
+    #define can_ulong2ioptr(addr)   ((unsigned long)(addr))
+    #define can_inb(ioaddr) inb(ioaddr)
+    #define can_outb(data,ioaddr) outb(data,ioaddr)
+    #define can_inw(ioaddr) inb(ioaddr)
+    #define can_outw(data,ioaddr) outb(data,ioaddr)
+    #define can_inl(ioaddr) inb(ioaddr)
+    #define can_outl(data,ioaddr) outb(data,ioaddr)
+ #else /* >=2.6.9 */
+    typedef void __iomem * can_ioptr_t;
+    #define can_ioptr2ulong(ioaddr) ((unsigned long __force)(ioaddr))
+    #define can_ulong2ioptr(addr)   ((can_ioptr_t)(addr))
+    #define can_inb(ioaddr) inb(can_ioptr2ulong(ioaddr))
+    #define can_outb(data,ioaddr) outb(data,can_ioptr2ulong(ioaddr))
+    #define can_inw(ioaddr) inb(can_ioptr2ulong(ioaddr))
+    #define can_outw(data,ioaddr) outb(data,can_ioptr2ulong(ioaddr))
+    #define can_inl(ioaddr) inb(can_ioptr2ulong(ioaddr))
+    #define can_outl(data,ioaddr) outb(data,can_ioptr2ulong(ioaddr))
+ #endif
+ #define can_readb  readb
+ #define can_writeb writeb
+ #define can_readw  readw
+ #define can_writew writew
+ #define can_readl  readl
+ #define can_writel writel
+ #define can_ioport2ioptr can_ulong2ioptr
  #ifdef __HAVE_ARCH_CMPXCHG
    #define CAN_HAVE_ARCH_CMPXCHG
  #endif
  #define CAN_DEFINE_SPINLOCK        DEFINE_SPINLOCK
  #endif /*DEFINE_SPINLOCK*/
  
- #if defined(CONFIG_PREEMPT) || (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0))
+ #if !defined(CONFIG_PREEMPT_RT) && ( defined(CONFIG_PREEMPT) || (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)) )
  #define can_preempt_disable        preempt_disable
  #define can_preempt_enable         preempt_enable
  #else /*CONFIG_PREEMPT*/
@@@ -223,20 -263,4 +263,20 @@@ extern can_spinlock_t can_irq_manipulat
  
  #endif /*CAN_WITH_RTL*/
  
 +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,4))
 +      #include <linux/kthread.h>
 +      #define can_kthread_create      kthread_create
 +      #define can_kthread_run kthread_run
 +      #define can_kthread_bind        kthread_bind
 +      #define can_kthread_stop        kthread_stop
 +      #define can_kthread_should_stop kthread_should_stop
 +#else
 +      #define can_kthread_create
 +      #define can_kthread_run
 +      #define can_kthread_bind
 +      #define can_kthread_stop
 +      #define can_kthread_should_stop
 +#endif
 +
 +
  #endif /*_CAN_SYSDEP_H*/
diff --combined lincan/include/main.h
  #include "./can_queue.h"
  
  #ifdef CAN_DEBUG
-       #define DEBUGMSG(fmt,args...) can_printk(KERN_ERR "can.o (debug): " fmt,\
+       #define DEBUGMSG(fmt,args...) can_printk(KERN_ERR "lincan (debug): " fmt,\
        ##args)
  #else
        #define DEBUGMSG(fmt,args...)
  #endif
  
- #define CANMSG(fmt,args...) can_printk(KERN_ERR "can.o: " fmt,##args)
+ #define CANMSG(fmt,args...) can_printk(KERN_ERR "lincan: " fmt,##args)
  
  
  extern can_spinlock_t canuser_manipulation_lock;
@@@ -75,7 -75,8 +75,8 @@@ struct candevice_t 
        int candev_idx;                 /* board index in canhardware_t.candevice[] */
        unsigned long io_addr;          /* IO/physical MEM address */
        unsigned long res_addr;         /* optional reset register port */
-       unsigned long dev_base_addr;    /* CPU translated IO/virtual MEM address */
+       can_ioptr_t dev_base_addr;      /* CPU translated IO/virtual MEM address */
+       can_ioptr_t aux_base_addr;      /* CPU translated IO/virtual MEM address */
        unsigned int flags;
        int nr_all_chips;
        int nr_82527_chips;
@@@ -154,13 -155,13 +155,13 @@@ struct canchip_t 
        char *chip_type;
        int chip_idx;   /* chip index in candevice_t.chip[] */
        int chip_irq;
-       unsigned long chip_base_addr;
+       can_ioptr_t chip_base_addr;
        unsigned int flags;
        long clock; /* Chip clock in Hz */
        long baudrate;
  
-       void (*write_register)(unsigned data,unsigned long address);
-       unsigned (*read_register)(unsigned long address);
+       void (*write_register)(unsigned data, can_ioptr_t address);
+       unsigned (*read_register)(can_ioptr_t address);
  
        void *chip_data;
  
   *             that reuse same object for TX
   */
  struct msgobj_t {
-       unsigned long obj_base_addr;
+       can_ioptr_t obj_base_addr;
        unsigned int minor;     /* associated device minor number  */
        unsigned int object;    /* object number in canchip_t +1 for debug printk */
        unsigned long obj_flags;
@@@ -298,8 -299,8 +299,8 @@@ struct hwspecops_t 
        int (*init_chip_data)(struct candevice_t *candev, int chipnr);
        int (*init_obj_data)(struct canchip_t *chip, int objnr);
        int (*program_irq)(struct candevice_t *candev);
-       void (*write_register)(unsigned data,unsigned long address);
-       unsigned (*read_register)(unsigned long address);
+       void (*write_register)(unsigned data, can_ioptr_t address);
+       unsigned (*read_register)(can_ioptr_t address);
  };
  
  /**
@@@ -379,9 -380,10 +380,10 @@@ extern int major
  extern int minor[MAX_TOT_CHIPS];
  extern int extended;
  extern int baudrate[MAX_TOT_CHIPS];
- extern char *hw[MAX_HW_CARDS];
  extern int irq[MAX_IRQ];
+ extern char *hw[MAX_HW_CARDS];
  extern unsigned long io[MAX_HW_CARDS];
+ extern long clockfreq[MAX_HW_CARDS];
  extern int processlocal;
  
  extern struct canhardware_t *hardware_p;
@@@ -392,43 -394,43 +394,43 @@@ extern struct mem_addr *mem_head
  
  
  #if defined(CONFIG_OC_LINCAN_PORTIO_ONLY)
- extern inline void can_write_reg(const struct canchip_t *chip, unsigned char data, unsigned address)
+ extern inline void can_write_reg(const struct canchip_t *chip, unsigned char data, unsigned reg_offs)
  {
-       outb(data, chip->chip_base_addr+address);
+       can_outb(data, chip->chip_base_addr+reg_offs);
  }
- extern inline unsigned can_read_reg(const struct canchip_t *chip, unsigned address)
+ extern inline unsigned can_read_reg(const struct canchip_t *chip, unsigned reg_offs)
  {
-       return inb(chip->chip_base_addr+address);
+       return can_inb(chip->chip_base_addr+reg_offs);
  }
  extern inline void canobj_write_reg(const struct canchip_t *chip, const struct msgobj_t *obj,
-                               unsigned char data, unsigned address)
+                               unsigned char data, unsigned reg_offs)
  {
-       outb(data, obj->obj_base_addr+address);
+       can_outb(data, obj->obj_base_addr+reg_offs);
  }
  extern inline unsigned canobj_read_reg(const struct canchip_t *chip, const struct msgobj_t *obj,
-                               unsigned address)
+                               unsigned reg_offs)
  {
-       return inb(obj->obj_base_addr+address);
+       return can_inb(obj->obj_base_addr+reg_offs);
  }
  
  #elif defined(CONFIG_OC_LINCAN_MEMIO_ONLY)
- extern inline void can_write_reg(const struct canchip_t *chip, unsigned char data, unsigned address)
+ extern inline void can_write_reg(const struct canchip_t *chip, unsigned char data, unsigned reg_offs)
  {
-       writeb(data, chip->chip_base_addr+address);
+       can_writeb(data, chip->chip_base_addr+reg_offs);
  }
- extern inline unsigned can_read_reg(const struct canchip_t *chip, unsigned address)
+ extern inline unsigned can_read_reg(const struct canchip_t *chip, unsigned reg_offs)
  {
-       return readb(chip->chip_base_addr+address);
+       return can_readb(chip->chip_base_addr+reg_offs);
  }
  extern inline void canobj_write_reg(const struct canchip_t *chip, const struct msgobj_t *obj,
-                               unsigned char data, unsigned address)
+                               unsigned char data, unsigned reg_offs)
  {
-       writeb(data, obj->obj_base_addr+address);
+       can_writeb(data, obj->obj_base_addr+reg_offs);
  }
  extern inline unsigned canobj_read_reg(const struct canchip_t *chip, const struct msgobj_t *obj,
-                               unsigned address)
+                               unsigned reg_offs)
  {
-       return readb(obj->obj_base_addr+address);
+       return can_readb(obj->obj_base_addr+reg_offs);
  }
  
  #else /*CONFIG_OC_LINCAN_DYNAMICIO*/
  #define CONFIG_OC_LINCAN_DYNAMICIO
  #endif
  
- /* Inline function to write to the hardware registers. The argument address is
-  * relative to the memory map of the chip and not the absolute memory address.
+ /* Inline function to write to the hardware registers. The argument reg_offs is
+  * relative to the memory map of the chip and not the absolute memory reg_offs.
   */
- extern inline void can_write_reg(const struct canchip_t *chip, unsigned char data, unsigned address)
+ extern inline void can_write_reg(const struct canchip_t *chip, unsigned char data, unsigned reg_offs)
  {
-       unsigned long address_to_write;
-       address_to_write = chip->chip_base_addr+address;
+       can_ioptr_t address_to_write;
+       address_to_write = chip->chip_base_addr+reg_offs;
        chip->write_register(data, address_to_write);
  }
  
- extern inline unsigned can_read_reg(const struct canchip_t *chip, unsigned address)
+ extern inline unsigned can_read_reg(const struct canchip_t *chip, unsigned reg_offs)
  {
-       unsigned long address_to_read;
-       address_to_read = chip->chip_base_addr+address;
+       can_ioptr_t address_to_read;
+       address_to_read = chip->chip_base_addr+reg_offs;
        return chip->read_register(address_to_read);
  }
  
  extern inline void canobj_write_reg(const struct canchip_t *chip, const struct msgobj_t *obj,
-                               unsigned char data, unsigned address)
+                               unsigned char data, unsigned reg_offs)
  {
-       unsigned long address_to_write;
-       address_to_write = obj->obj_base_addr+address;
+       can_ioptr_t address_to_write;
+       address_to_write = obj->obj_base_addr+reg_offs;
        chip->write_register(data, address_to_write);
  }
  
  extern inline unsigned canobj_read_reg(const struct canchip_t *chip, const struct msgobj_t *obj,
-                               unsigned address)
+                               unsigned reg_offs)
  {
-       unsigned long address_to_read;
-       address_to_read = obj->obj_base_addr+address;
+       can_ioptr_t address_to_read;
+       address_to_read = obj->obj_base_addr+reg_offs;
        return chip->read_register(address_to_read);
  }
  
  #endif /*CONFIG_OC_LINCAN_DYNAMICIO*/
  
- int can_base_addr_fixup(struct candevice_t *candev, unsigned long new_base);
+ int can_base_addr_fixup(struct candevice_t *candev, can_ioptr_t new_base);
  int can_request_io_region(unsigned long start, unsigned long n, const char *name);
  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);
@@@ -510,6 -512,3 +512,6 @@@ void can_filltimestamp(canmsg_tstamp_t 
  #ifdef CAN_WITH_RTL
  extern int can_rtl_priority;
  #endif /*CAN_WITH_RTL*/
 +
 +extern struct candevice_t* register_usbdev(const char *hwname,void *devdata,void (*chipdataregfnc)(struct canchip_t *chip,void *data));
 +extern void cleanup_usbdev(struct candevice_t *dev);
diff --combined lincan/src/Makefile.omk
@@@ -1,8 -1,8 +1,8 @@@
  lincan_cards_NAMES = pip pccan smartcan nsi cc_can104 ems_cpcpci \
-               pc_i03 pcm3680 aim104 m437 pcccan ssv bfadcan pikronisa eb8245 \
-               kv_pcican msmcan oscar adlink7841 unican virtual template usbcan
+               pc_i03 pcm3680 aim104 m437 pcccan ssv bfadcan gensja1000io pikronisa eb8245 \
 -              kv_pcican msmcan oscar adlink7841 pcan_pci esdpci200 unican virtual template
++              kv_pcican msmcan oscar adlink7841 pcan_pci esdpci200 unican usbcan virtual template
  
- lincan_morecards_NAMES = hms30c7202_can ns_dev_can ipci165 pimx1 tscan1 nsi_canpci
+ lincan_morecards_NAMES = hms30c7202_can ns_dev_can ipci165 pimx1 tscan1 nsi_canpci sh7760
  
  default_CONFIG = CONFIG_OC_LINCAN=y CONFIG_OC_LINCANRTL=n CONFIG_OC_LINCANVME=n
  default_CONFIG += CONFIG_OC_LINCAN_PORTIO_ONLY=n CONFIG_OC_LINCAN_MEMIO_ONLY=n
@@@ -21,7 -21,7 +21,7 @@@ ifeq ($(CONFIG_OC_LINCAN),y
  rtlinux_INCLUDES = -I $(srcdir)/../include -I .
  kernel_INCLUDES = -I $(srcdir)/../include -I .
  #kernel_INCLUDES += -DCAN_DEBUG
- kernel_INCLUDES += -DWITH_DEVFS_FS -DKBUILD_MODNAME
+ kernel_INCLUDES += -DWITH_DEVFS_FS
  
  lincan_cards_SOURCES = $(lincan_cards_SELECTED:%=%.c)
  
@@@ -33,10 -33,10 +33,14 @@@ ifeq ($(CONFIG_OC_LINCAN_CARD_ipci165),
  lincan_cards_SOURCES += ipci165_fw.c kthread.c
  endif
  
+ ifeq ($(CONFIG_OC_LINCAN_CARD_sh7760),y)
+ lincan_cards_SOURCES += sh7760.c
+ endif
 +ifeq ($(CONFIG_OC_LINCAN_CARD_usbcan),y)
 +lincan_cards_SOURCES += kthread.c
 +endif
 +
  ifneq ($(filter hms30c7202_can ns_dev_can,$(lincan_cards_SELECTED)),)
  $(warning Not finished C_CAN support requested)
  lincan_cards_SOURCES += c_can.c c_can_irq.c
@@@ -57,7 -57,7 +61,7 @@@ endif #CONFIG_OC_LINCANRT
  
  lincan_SOURCES = can_queue.c can_quekern.c main.c modparms.c \
                devcommon.c setup.c finish.c irq.c sysdep_lnx.c boardlist.c \
-               sja1000p.c sja1000.c i82527.c  \
+               sja1000p.c sja1000.c i82527.c hcan2.c \
                open.c close.c read.c write.c ioctl.c select.c fasync.c \
                proc.c ioctl_query.c ioctl_remote.c \
                $(lincan_cards_SOURCES) $(lincan_rtl_SOURCES)
diff --combined lincan/src/boardlist.c
@@@ -30,6 -30,7 +30,7 @@@ extern int pcccan_register(struct hwspe
  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 gensja1000io_register(struct hwspecops_t *hwspecops);
  extern int pimx1_register(struct hwspecops_t *hwspecops);
  extern int msmcan_register(struct hwspecops_t *hwspecops);
  extern int unican_register(struct hwspecops_t *hwspecops);
@@@ -44,7 -45,9 +45,10 @@@ extern int ts7kv_register(struct hwspec
  extern int ns_dev_register(struct hwspecops_t *hwspecops);
  extern int hms30c7202_register(struct hwspecops_t *hwspecops);
  extern int nsi_canpci_register(struct hwspecops_t *hwspecops);
 +extern int usbcan_register(struct hwspecops_t *hwspecops);
+ extern int pcan_pci_register(struct hwspecops_t *hwspecops);
+ extern int esdpci200_register(struct hwspecops_t *hwspecops);
+ extern int sh7760_register(struct hwspecops_t *hwspecops);
  
  const struct boardtype_t can_boardtypes[]={
      #ifdef CONFIG_OC_LINCAN_CARD_template
      #ifdef CONFIG_OC_LINCAN_CARD_pikronisa
        {"pikronisa", pikronisa_register, 1},
      #endif
+     #ifdef CONFIG_OC_LINCAN_CARD_gensja1000io
+       {"gensja1000io", gensja1000io_register, 1},
+     #endif
      #ifdef CONFIG_OC_LINCAN_CARD_pimx1
        {"pimx1", pimx1_register, 0},
      #endif
      #if defined(CONFIG_OC_LINCAN_CARD_adlink7841)
        {"adlink7841", adlink7841_register, 0},
      #endif
+     #if defined(CONFIG_OC_LINCAN_CARD_esdpci200)
+       {"esdpci200", esdpci200_register, 0},
+     #endif
      #if defined(CONFIG_OC_LINCAN_CARD_tscan1)
        {"tscan1", tscan1_register, 1},
        {"ts7kv",  ts7kv_register, 1},
      #if defined(CONFIG_OC_LINCAN_CARD_ns_dev_can)
        {"ns_dev", ns_dev_register, 1},
      #endif
+     #if defined(CONFIG_OC_LINCAN_CARD_sh7760)
+       {"sh7760", sh7760_register, 2},
+     #endif
      #if defined(CONFIG_OC_LINCAN_CARD_hms30c7202_can)
        {"hms30c7202", hms30c7202_register, 1},
      #endif
      #if defined(CONFIG_OC_LINCAN_CARD_nsi_canpci)&&defined(CAN_ENABLE_PCI_SUPPORT)
        {"nsicanpci", nsi_canpci_register, 1},
      #endif
+     #if defined(CONFIG_OC_LINCAN_CARD_pcan_pci)&&defined(CAN_ENABLE_PCI_SUPPORT)
+       {"pcan_pci", pcan_pci_register, 0},
++    #endif
 +    #if defined(CONFIG_OC_LINCAN_CARD_usbcan)
 +      {"usbcan", usbcan_register, 0},
      #endif
        {NULL}
  };
diff --combined lincan/src/main.c
  #include "../include/can_iortl.h"
  #endif /*CAN_WITH_RTL*/
  
 +#if defined(CONFIG_OC_LINCAN_CARD_usbcan)
 +      #include "../include/usbcan.h"
 +#endif
 +
  can_spinlock_t canuser_manipulation_lock;
  
  int major=CAN_MAJOR;
@@@ -88,6 -84,7 +88,7 @@@ int baudrate[MAX_TOT_CHIPS]
  char *hw[MAX_HW_CARDS]={NULL,};
  int irq[MAX_IRQ]={-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1};
  unsigned long io[MAX_HW_CARDS]={-1,-1,-1,-1,-1,-1,-1,-1};
+ long clockfreq[MAX_HW_CARDS];
  int stdmask=0;
  int extmask=0;
  int mo15mask=0;
@@@ -98,8 -95,9 +99,9 @@@ unsigned int baudrate_specified
  unsigned int hw_specified;
  unsigned int irq_specified;
  unsigned int io_specified;
+ unsigned int clockfreq_specified;
  
- #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0))
+ #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,12))
  /* Module parameters, some must be supplied at module loading time */
  MODULE_PARM(major,"1i");
  /*MODULE_PARM(minor, "1-" __MODULE_STRING(MAX_TOT_CHIPS)"i");*/
@@@ -110,12 -108,13 +112,13 @@@ MODULE_PARM(baudrate, "1-" __MODULE_STR
  MODULE_PARM(hw, "1-" __MODULE_STRING(MAX_HW_CARDS)"s");
  MODULE_PARM(irq, "1-" __MODULE_STRING(MAX_IRQ)"i");
  MODULE_PARM(io, "1-" __MODULE_STRING(MAX_HW_CARDS)"i");
+ MODULE_PARM(clockfreq, "1-" __MODULE_STRING(MAX_HW_CARDS)"i");
  MODULE_PARM(stdmask, "1i");
  MODULE_PARM(extmask, "1i");
  MODULE_PARM(mo15mask, "1i");
  MODULE_PARM(processlocal, "1i");
  
- #else /* LINUX_VERSION_CODE >= 2,6,0 */
+ #else /* LINUX_VERSION_CODE >= 2,6,12 */
  module_param(major, int, 0);
  module_param_array(minor, int, &minor_specified, 0);
  module_param(extended, int, 0);
@@@ -123,12 -122,13 +126,13 @@@ module_param(pelican, int, 0)
  module_param_array(baudrate, int, &baudrate_specified, 0);
  module_param_array(hw, charp, &hw_specified, 0);
  module_param_array(irq, int, &irq_specified, 0);
- module_param_array(io, int, &io_specified, 0);
+ module_param_array(io, ulong, &io_specified, 0);
+ module_param_array(clockfreq, long, &clockfreq_specified, 0);
  module_param(stdmask, int, 0);
  module_param(extmask, int, 0);
  module_param(mo15mask, int, 0);
  module_param(processlocal, int, 0);
- #endif /* LINUX_VERSION_CODE >= 2,6,0 */
+ #endif /* LINUX_VERSION_CODE >= 2,6,12 */
  
  MODULE_PARM_DESC(major,"can be used to change default major [" __MODULE_STRING(CAN_MAJOR) "]");
  MODULE_PARM_DESC(minor,"can be used to change default starting minor for each channel");
@@@ -139,6 -139,7 +143,7 @@@ MODULE_PARM_DESC(baudrate,"baudrate fo
  MODULE_PARM_DESC(hw,"list of boards types to initialize - virtual,pip5,...");
  MODULE_PARM_DESC(irq,"list of iterrupt signal numbers, most ISA has one per chip, no value for PCI or virtual");
  MODULE_PARM_DESC(io,"IO address for each board, use 0 for PCI or virtual");
+ MODULE_PARM_DESC(clockfreq,"base board clock source frequency in step of 1kHz");
  MODULE_PARM_DESC(stdmask,"default standard mask for i82527 chips");
  MODULE_PARM_DESC(extmask,"default extended mask for i82527 chips");
  MODULE_PARM_DESC(mo15mask,"mask for communication object 15 of i82527 chips");
@@@ -323,8 -324,10 +328,10 @@@ int init_module(void
          {
            #if (LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,0))
                char dev_name[32];
-           #else
+           #elif  LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,25) /* >= 2.6.15 */
                struct class_device *this_dev;
+           #else
+               struct device *this_dev;
            #endif
                int dev_minor;
                for(i=0;i<MAX_TOT_MSGOBJS;i++) {
                    #else
                      #if (LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,14))
                        this_dev=class_device_create(can_class, MKDEV(major, dev_minor), NULL,  "can%d", dev_minor);
-                     #else /* >= 2.6.15 */
+                     #elif  LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,25) /* >= 2.6.15 */
                        this_dev=class_device_create(can_class, NULL, MKDEV(major, dev_minor), NULL,  "can%d", dev_minor);
-                     #endif /* >= 2.6.15 */
+                     #else /* >= 2.6.26 */
+                       this_dev=device_create_drvdata(can_class, NULL, MKDEV(major, dev_minor), objects_p[i],  "can%d", dev_minor);
+                     #endif /* >= 2.6.26 */
                        if(IS_ERR(this_dev)){
                                CANMSG("problem to create device \"can%d\" in the class \"can\"\n", dev_minor);
+                     #if  LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,25)
                        }else{
                                /*this_dev->class_data=objects_p[i];*/
                                class_set_devdata(this_dev,objects_p[i]);
+                     #endif /* <= 2.6.25 */
                        }
                      #ifdef CONFIG_DEVFS_FS
                        devfs_mk_cdev(MKDEV(major, dev_minor), S_IFCHR | S_IRUGO | S_IWUGO, "can%d", dev_minor);
                }
          }
  #endif
 +
 +#if defined(CONFIG_OC_LINCAN_CARD_usbcan)
 +      res = usbcan_init();
 +      if (res){
 +              CANMSG("usb_register for usbcan failed. Error number %d.\n", res);
 +              return -ENODEV;
 +      }
 +#endif
 +
        return 0;
  
  #ifdef CONFIG_PROC_FS
                canqueue_rtl_done();
                #endif /*CAN_WITH_RTL*/
  
-               #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0))
                unregister_chrdev(major,DEVICE_NAME);
-               #else /*LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0)*/
-               res=unregister_chrdev(major,DEVICE_NAME);
-               if (res<0)
-                       CANMSG("Error unloading CAN driver, error: %d\n",res);
-               else
-                       CANMSG("No CAN devices or driver setup error.\n");
-               #endif /*LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0)*/
+               CANMSG("No CAN devices or driver setup error.\n");
  
        register_error:
                if ( can_del_mem_list() )
                return -ENODEV;
  }
  
-                       #else /* >= 2.6.15 */
 +
 +
 +
 +
 +struct candevice_t* register_usbdev(const char *hwname,void *devdata,void (*chipdataregfnc)(struct canchip_t *ch,void *data)){
 +      int i=0, j, board=0;
 +      struct candevice_t *candev;
 +      struct canchip_t *chip;
 +      struct boardtype_t *brp;
 +
 +      while ( (hw[board] != NULL) && (board < MAX_HW_CARDS) )
 +              board++;
 +      if (board>=MAX_HW_CARDS){
 +              CANMSG("Maximum number of devices has been reached, no space for new device");
 +              return NULL;
 +      }
 +      brp = boardtype_find(hwname);
 +      if(!brp) {
 +              CANMSG("Sorry, hardware \"%s\" is currently not supported.\n",hw[board]);
 +              return NULL;
 +      }
 +      if (board==MAX_HW_CARDS){
 +                      CANMSG("Device \"%s\" could not be registered due to internal limits.\n",hw[board]);
 +                      return NULL;
 +      }
 +      hw[board]=brp->boardtype;
 +
 +      if (init_new_hw_struct(board))
 +              return NULL;
 +
 +      #ifdef CAN_DEBUG
 +              list_hw();
 +      #endif
 +
 +      candev=hardware_p->candevice[board];
 +
 +      /* Adding link to usb device structure into can device */
 +      candev->sysdevptr.anydev=devdata;
 +
 +      if (candev->hwspecops->request_io(candev))
 +              goto request_io_error;
 +      candev->flags|=CANDEV_IO_RESERVED;
 +
 +      if (candev->hwspecops->reset(candev))
 +              goto reset_error;
 +
 +      for(j=0; j<candev->nr_all_chips; j++) {
 +              if((chip=candev->chip[j])==NULL)
 +                      continue;
 +
 +              chipdataregfnc(chip,devdata);
 +
 +              if(chip->chipspecops->attach_to_chip(chip)<0) {
 +                      CANMSG("Initial attach to the chip HW failed\n");
 +                      goto interrupt_error;
 +              }
 +
 +              chip->flags |= CHIP_ATTACHED;
 +
 +              if(can_chip_setup_irq(chip)<0) {
 +                      CANMSG("Error to setup chip IRQ\n");
 +                      goto interrupt_error;
 +              }
 +      }
 +
 +      if (candev->flags & CANDEV_PROGRAMMABLE_IRQ)
 +              if (candev->hwspecops->program_irq(candev)){
 +                      CANMSG("Error to program board interrupt\n");
 +                      goto interrupt_error;
 +              }
 +
 +#ifdef CONFIG_PROC_FS
 +      if (can_init_procentry(board))
 +              goto proc_error;
 +#endif
 +
 +#if defined(CONFIG_DEVFS_FS) || (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0))
 +      {
 +              #if (LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,0))
 +              char dev_name[32];
 +              #else
 +              struct class_device *this_dev;
 +              #endif
 +              int dev_minor;
 +              for(i=0;i<MAX_TOT_MSGOBJS;i++) {
 +                      if(!objects_p[i]) continue;
 +                      if(objects_p[i]->hostchip->hostdevice != candev) continue;
 +
 +                      dev_minor=objects_p[i]->minor;
 +                      #if (LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,0))
 +                      sprintf (dev_name, "can%d", dev_minor);
 +                      devfs_handles[i]=devfs_register(NULL, dev_name,
 +                      DEVFS_FL_DEFAULT, major, dev_minor,
 +                      S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP,
 +                      &can_fops, (void*)objects_p[i]);
 +                      #else
 +                      #if (LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,14))
 +                      this_dev=class_device_create(can_class, MKDEV(major, dev_minor), NULL,  "can%d", dev_minor);
-                       #endif /* >= 2.6.15 */
++                      #elif  LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,25) /* >= 2.6.15 */
 +                      this_dev=class_device_create(can_class, NULL, MKDEV(major, dev_minor), NULL,  "can%d", dev_minor);
++                      #else /* >= 2.6.26 */
++                      this_dev=device_create_drvdata(can_class, NULL, MKDEV(major, dev_minor), objects_p[i],  "can%d", dev_minor);
++                      #endif /* >= 2.6.26 */
 +                      if(IS_ERR(this_dev)){
 +                              CANMSG("problem to create device \"can%d\" in the class \"can\"\n", dev_minor);
++                    #if  LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,25)
 +                      }else{
 +                              /*this_dev->class_data=objects_p[i];*/
 +                              class_set_devdata(this_dev,objects_p[i]);
++                    #endif /* <= 2.6.25 */
 +                      }
 +                      #ifdef CONFIG_DEVFS_FS
 +                      devfs_mk_cdev(MKDEV(major, dev_minor), S_IFCHR | S_IRUGO | S_IWUGO, "can%d", dev_minor);
 +                      #endif
 +                      #endif
 +              }
 +      }
 +#endif
 +      return candev;
 +
 +#ifdef CONFIG_PROC_FS
 +      proc_error: ;
 +              CANMSG("Error registering /proc entry.\n");
 +              goto memory_error;
 +#endif
 +
 +      interrupt_error: ;
 +              goto memory_error;
 +
 +      reset_error: ;
 +              CANMSG("Error resetting device.\n");
 +              goto memory_error;
 +
 +      request_io_error: ;
 +              CANMSG("Error to request IO resources for device.\n");
 +              goto memory_error;
 +
 +      memory_error: ;
 +
 +              #ifdef CAN_WITH_RTL
 +      rtldev_error:
 +              #endif /*CAN_WITH_RTL*/
 +
 +//    register_error:
 +              if ( can_del_mem_list() )
 +                      CANMSG("Error deallocating memory\n");
 +
 +              return NULL;
 +}
 +
 +
 +
 +
 +
 +
 +
 +void cleanup_usbdev(struct candevice_t *dev)
 +{
 +      int i=0;
 +      int dev_minor;
 +
 +      if (!dev)
 +              return;
 +
 +#ifdef CONFIG_PROC_FS
 +      if (can_delete_procentry(dev))
 +              CANMSG("Error unregistering /proc/can entry.\n");
 +#endif
 +
 +#if defined(CONFIG_DEVFS_FS) || (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0))
 +      for(i=0;i<MAX_TOT_MSGOBJS;i++) {
 +              if(!objects_p[i]) continue;
 +              if(objects_p[i]->hostchip->hostdevice != dev) continue;
 +              #if (LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,0))
 +              if(devfs_handles[i])
 +                      devfs_unregister(devfs_handles[i]);
 +              #else
 +              dev_minor=objects_p[i]->minor;
 +              if(dev_minor>=0){
 +                      #ifdef CONFIG_DEVFS_FS
 +                      devfs_remove("can%d", dev_minor);
 +                      #endif
++                      #if  LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,25)
 +                      class_device_destroy(can_class, MKDEV(major, dev_minor));
++                      #else /* >= 2.6.26 */
++                      device_destroy(can_class, MKDEV(major, dev_minor));
++                      #endif /* >= 2.6.26 */
 +              }
 +              #endif
 +      }
 +#endif
 +
 +      for(i=0;i<MAX_TOT_CHIPS;i++){
 +              if(!chips_p[i]) continue;
 +              if(chips_p[i]->hostdevice != dev) continue;
 +              chips_p[i]=NULL;
 +      }
 +
 +      hardware_p->candevice[dev->candev_idx]=NULL;
 +      hardware_p->nr_boards--;
 +      hw[dev->candev_idx]=NULL;
 +
 +      candevice_done(dev);
 +      can_checked_free(dev);
 +}
 +
 +
 +
 +
  void cleanup_module(void)
  {
-       int res=0,i=0;
+ #if defined(CONFIG_DEVFS_FS) || (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0))
+       int i=0;
+ #endif
  
 +#if defined(CONFIG_OC_LINCAN_CARD_usbcan)
 +      usbcan_exit();
 +#endif
 +
  #ifdef CONFIG_PROC_FS
        if (can_delete_procdir())
                CANMSG("Error unregistering /proc/can entry.\n");
                    #ifdef CONFIG_DEVFS_FS
                        devfs_remove("can%d", dev_minor);
                    #endif
+                   #if  LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,25)
                        class_device_destroy(can_class, MKDEV(major, dev_minor));
+                   #else /* >= 2.6.26 */
+                       device_destroy(can_class, MKDEV(major, dev_minor));
+                   #endif /* >= 2.6.26 */
                }
            #endif
                }
        if ( can_del_mem_list() )
                CANMSG("Error deallocating memory\n");
  
-       #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0))
        unregister_chrdev(major,DEVICE_NAME);
-       #else /*LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0)*/
-       res=unregister_chrdev(major,DEVICE_NAME);
-       if (res<0)
-               CANMSG("Error unregistering CAN driver, error: %d\n",res);
-       #endif /*LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0)*/
  }
diff --combined lincan/src/modparms.c
@@@ -19,10 -19,9 +19,10 @@@ int parse_mod_parms(void
        const struct boardtype_t *brp;
  
        if ( (hw[0] == NULL) | (io[0] == -1) ) {
 -              CANMSG("You must supply your type of hardware, interrupt numbers and io address.\n");
 +              //CANMSG("You must supply your type of hardware, interrupt numbers and io address.\n");
 +              CANMSG("Autodetection works only for USB devices, supply your type of hardware for PCI devices \n");
-               CANMSG("Example: # insmod can.o hw=pip5 irq=4 io=0x8000\n");
+               CANMSG("Example: # insmod lincan.ko hw=pip5 irq=4 io=0x8000\n");
 -              return -ENODEV;
 +              //return -ENODEV;
        }
  
        while ( (hw[i] != NULL) && (i < MAX_HW_CARDS) ) {
diff --combined lincan/src/proc.c
  
  #define __NO_VERSION__
  #include <linux/module.h>
 +#include <linux/mutex.h>
  
  int add_channel_to_procdir(struct candevice_t *candev);
 -int remove_channel_from_procdir(void);
 +int remove_channels_from_procdir(void);
 +int remove_channel_from_procdir(struct candevice_t *candev);
  int add_object_to_procdir(int chip_nr);
  int remove_object_from_procdir(int chip_nr);
  
  static int can_proc_readlink(struct proc_dir_entry *ent, char *page);
  #endif
  
+ #if  LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,25)
+ #define CAN_PROC_ROOT (&proc_root)
+ #else /* >= 2.6.26 */
+ #define CAN_PROC_ROOT (NULL)
+ #endif /* >= 2.6.26 */
  static int cc=0; /* static counter for each CAN chip */
  
  static struct canproc_t can_proc_base;
  static struct canproc_t *base=&can_proc_base;
 +DEFINE_MUTEX(proc_mutex);             /* synchronize access to canproc_t array */
  
  /* The following functions are needed only for kernel version 2.2. Kernel
   * version 2.4 already defines them for us.
@@@ -152,11 -155,8 +158,11 @@@ int can_init_procdir(void
  {
        int board;
        struct candevice_t *candev;
 +
 +      mutex_init(&proc_mutex);
 +
        base->can_proc_entry = can_create_proc_entry("can", S_IFDIR | S_IRUGO |
-                                       S_IXUGO, &proc_root);
+                                       S_IXUGO, CAN_PROC_ROOT);
        if (base->can_proc_entry == NULL)
                return -ENODEV;
  
        return 0;
  }
  
 +/* can_init_procentry registers entry of a new board in CAN directory tree at
 + * the proc system.
 + */
 +int can_init_procentry(int board)
 +{
 +      struct candevice_t *candev;
 +      candev=hardware_p->candevice[board];
 +      if(candev)
 +              return add_channel_to_procdir(candev);
 +      return -ENODEV;
 +}
 +
  /* can_delete_procdir removes the entire CAN tree from the proc system */
  int can_delete_procdir(void)
  {
 -      if (remove_channel_from_procdir()) 
 +      if (remove_channels_from_procdir())
                return -ENODEV;
        /* name: "can" */
-       if (can_remove_proc_entry(base->can_proc_entry, &proc_root))
 -      if (can_remove_proc_entry(base->can_proc_entry, CAN_PROC_ROOT)) 
++      if (can_remove_proc_entry(base->can_proc_entry, CAN_PROC_ROOT))
 +              return -ENODEV;
 +
 +      return 0;
 +}
 +
 +/* can_delete_procentry removes device entries from CAN tree in the proc system */
 +int can_delete_procentry(struct candevice_t *candev)
 +{
 +      if (remove_channel_from_procdir(candev))
                return -ENODEV;
  
        return 0;
@@@ -211,9 -190,10 +217,10 @@@ static int can_chip_procinfo(char *buf
        len += sprintf(buf+len,"type    : %s\n",chip->chip_type);
        len += sprintf(buf+len,"index   : %d\n",chip->chip_idx);
        len += sprintf(buf+len,"irq     : %d\n",chip->chip_irq);
-       len += sprintf(buf+len,"addr    : %lu\n",chip->chip_base_addr);
+       len += sprintf(buf+len,"addr    : %lu\n",
+                       can_ioptr2ulong(chip->chip_base_addr));
        len += sprintf(buf+len,"config  : %s\n",
-                      (chip->flags & CHIP_CONFIGURED) ? "yes":"no");
+                       (chip->flags & CHIP_CONFIGURED) ? "yes":"no");
        len += sprintf(buf+len,"clock   : %ld Hz\n",chip->clock);
        len += sprintf(buf+len,"baud    : %ld\n",chip->baudrate);
        len += sprintf(buf+len,"num obj : %d\n",chip->max_objects);
@@@ -234,108 -214,58 +241,108 @@@ int add_channel_to_procdir(struct cande
  {
        int i=0;
  
 -      for (i=0; i < candev->nr_all_chips; i++) {
 +      mutex_lock(&proc_mutex);
 +      for (i=0; i < MAX_TOT_CHIPS; i++){
 +              if (!chips_p[i]) continue;
 +              if (chips_p[i]->hostdevice != candev) continue;
  
 -              base->channel[cc] = (struct channelproc_t *)
 +              base->channel[i] = (struct channelproc_t *)
                        can_checked_malloc(sizeof(struct channelproc_t));
 -              if (base->channel[cc] == NULL)
 +              if (base->channel[i] == NULL){
 +                      mutex_unlock(&proc_mutex);
                        return -ENOMEM;
 +              }
  
 -              sprintf(base->channel[cc]->ch_name, "channel%d",cc);
 +              sprintf(base->channel[i]->ch_name, "channel%d",i);
  
 -              base->channel[cc]->ch_entry = can_create_proc_entry(
 -                                              base->channel[cc]->ch_name,
 +              base->channel[i]->ch_entry = can_create_proc_entry(
 +                                              base->channel[i]->ch_name,
                                                S_IFDIR | S_IRUGO |S_IXUGO,
                                                base->can_proc_entry);
  
 -              if (base->channel[cc]->ch_entry == NULL)
 +              if (base->channel[i]->ch_entry == NULL){
 +                      mutex_unlock(&proc_mutex);
                        return -ENODEV;
 +              }
  
 -              add_object_to_procdir(cc);
 +              add_object_to_procdir(i);
  
                create_proc_read_entry("chip_info",        /* proc entry name */
                                       0,                  /* protection mask, 0->default */
 -                                     base->channel[cc]->ch_entry,  /* parent dir, NULL->/proc */
 +                                     base->channel[i]->ch_entry,  /* parent dir, NULL->/proc */
                                       can_chip_procinfo,
 -                                     candev->chip[i]);
 -
 +                                     chips_p[i]);
                cc++;
        }
 +      mutex_unlock(&proc_mutex);
  
        return 0;
  }
  
 -int remove_channel_from_procdir(void)
 +int remove_channels_from_procdir(void)
  {
 +      int i=0;
 +
 +      mutex_lock(&proc_mutex);
 +      for (i=0; i < MAX_TOT_CHIPS; i++){
 +              if (!chips_p[i]) continue;
  
 -      while (cc != 0) {
                cc--;
  
 -              if(!base->channel[cc]) continue;
 +              if(!base->channel[i]) continue;
  
 -              remove_proc_entry("chip_info", base->channel[cc]->ch_entry);
 +              remove_proc_entry("chip_info", base->channel[i]->ch_entry);
  
 -              if (remove_object_from_procdir(cc))
 +              if (remove_object_from_procdir(i)){
 +                      mutex_unlock(&proc_mutex);
                        return -ENODEV;
 +              }
  
                /* name: base->channel[cc]->ch_name */
 -              if (can_remove_proc_entry(base->channel[cc]->ch_entry,
 -                                                      base->can_proc_entry))
 +              if (can_remove_proc_entry(base->channel[i]->ch_entry,
 +                                                      base->can_proc_entry)){
 +                      mutex_unlock(&proc_mutex);
                        return -ENODEV;
 +              }
  
 -              can_checked_free(base->channel[cc]);
 -              base->channel[cc] = NULL;
 +              can_checked_free(base->channel[i]);
 +              base->channel[i] = NULL;
 +      }
 +      mutex_unlock(&proc_mutex);
 +
 +      return 0;
 +}
 +
 +int remove_channel_from_procdir(struct candevice_t *candev)
 +{
 +      int i=0,j=0;
 +
 +      mutex_lock(&proc_mutex);
 +      for (i=0; i < MAX_TOT_CHIPS; i++){
 +              if (!chips_p[i]) continue;
 +              if (chips_p[i]->hostdevice != candev) continue;
 +              if (!base->channel[i]) continue;
 +
 +              remove_proc_entry("chip_info", base->channel[i]->ch_entry);
 +
 +              if (remove_object_from_procdir(i)){
 +                      mutex_unlock(&proc_mutex);
 +                      return -ENODEV;
 +              }
 +
 +              /* name: base->channel[cc]->ch_name */
 +              if (can_remove_proc_entry(base->channel[i]->ch_entry,
 +                                                      base->can_proc_entry)){
 +                      mutex_unlock(&proc_mutex);
 +                      return -ENODEV;
 +              }
 +
 +              can_checked_free(base->channel[i]);
 +              base->channel[i] = NULL;
 +
 +              cc--;
        }
 +      mutex_unlock(&proc_mutex);
  
        return 0;
  }
diff --combined lincan/src/setup.c
  
  int init_hwspecops(struct candevice_t *candev, int *irqnum_p);
  int init_device_struct(int card, int *chan_param_idx_p, int *irq_param_idx_p);
- int init_chip_struct(struct candevice_t *candev, int chipnr, int irq, long baudrate);
+ int init_chip_struct(struct candevice_t *candev, int chipnr, int irq, long baudrate, long clock);
  int init_obj_struct(struct candevice_t *candev, struct canchip_t *hostchip, int objnr);
  
 +int next_minor=0;
 +
  /**
   * can_base_addr_fixup - relocates board physical memory addresses to the CPU accessible ones
   * @candev: pointer to the previously filled device/board, chips and message objects structures
@@@ -32,9 -30,9 +32,9 @@@
   * This function is prepared to simplify board specific xxx_request_io() function
   * for memory mapped devices.
   */
- int can_base_addr_fixup(struct candevice_t *candev, unsigned long new_base)
+ int can_base_addr_fixup(struct candevice_t *candev, can_ioptr_t new_base)
  {
-       unsigned long offs;
+       long offs;
        int i, j;
  
        offs=new_base-candev->dev_base_addr;
@@@ -80,6 -78,7 +80,6 @@@ int can_check_dev_taken(void *anydev
   */
  int register_obj_struct(struct msgobj_t *obj, int minorbase)
  {
 -      static int next_minor=0;
        int i;
  
        if(minorbase>=0)
@@@ -157,30 -156,6 +157,30 @@@ int init_hw_struct(void
        return 0;
  }
  
 +/**
 + * init_new_hw_struct - initializes driver description structures for new hardware
 + *
 + * The function init_new_hw_struct() is used to initialize the hardware structure.
 + *
 + * Return Value: returns negative number in the case of fail
 + */
 +int init_new_hw_struct(int devnr)
 +{
 +      int irq_param_idx=0;
 +      int chan_param_idx=0;
 +
 +      if ( (hw[devnr] != NULL) & (devnr < MAX_HW_CARDS) ) {
 +              hardware_p->nr_boards++;
 +
 +              if (init_device_struct(devnr, &chan_param_idx, &irq_param_idx)) {
 +                      CANMSG("Error initializing candevice_t structures.\n");
 +                      return -ENODEV;
 +              }
 +      }
 +
 +      return 0;
 +}
 +
  /**
   * init_device_struct - initializes single CAN device/board
   * @card: index into @hardware_p HW description
@@@ -212,6 -187,7 +212,7 @@@ int init_device_struct(int card, int *c
        int chipnr;
        long bd;
        int irqsig=-1;
+       long clock;
  
        candev=(struct candevice_t *)can_checked_malloc(sizeof(struct candevice_t));
        if (candev==NULL)
        candev->hwname=hw[card];
        candev->io_addr=io[card];
        candev->dev_base_addr=io[card];
+       clock=clockfreq[card];
  
        candev->hwspecops=(struct hwspecops_t *)can_checked_malloc(sizeof(struct hwspecops_t));
        if (candev->hwspecops==NULL)
                bd=baudrate[*chan_param_idx_p+chipnr];
                if(!bd) bd=baudrate[0];
  
-               if ((ret=init_chip_struct(candev, chipnr, irqsig, bd*1000)))
+               if ((ret=init_chip_struct(candev, chipnr, irqsig, bd*1000, clock*1000)))
                        goto error_chip;
        }
  
   * @chipnr: index of the chip in the corresponding device/board structure
   * @irq: chip IRQ number or (-1) if not appropriate
   * @baudrate: baudrate in the units of 1Bd
+  * @clock: optional chip base clock frequency in 1Hz step
   *
   * Chip structure is allocated and chip specific operations are filled by
   * call to board specific init_chip_data() which calls chip specific
   *
   * Return Value: returns negative number in the case of fail
   */
- int init_chip_struct(struct candevice_t *candev, int chipnr, int irq, long baudrate)
+ int init_chip_struct(struct candevice_t *candev, int chipnr, int irq, long baudrate, long clock)
  {
        struct canchip_t *chip;
        int objnr;
        chip->hostdevice=candev;
        chip->chip_irq=irq;
        chip->baudrate=baudrate;
+       chip->clock=clock;
        chip->flags=0x0;
  
        if(candev->hwspecops->init_chip_data(candev,chipnr)<0)