Added support for Unicontrols PCI CAN card.
authorppisa <ppisa>
Tue, 6 Apr 2004 10:15:26 +0000 (10:15 +0000)
committerppisa <ppisa>
Tue, 6 Apr 2004 10:15:26 +0000 (10:15 +0000)
Will be tested, when I get to the hardware at school.

lincan/include/can_sysdep.h
lincan/include/main.h
lincan/src/boardlist.c
lincan/src/kv_pcican.c
lincan/src/setup.c
lincan/src/unican.c
lincan/src/write.c
lincan/src/write_rtl.c

index 0dd0e55..f8499d1 100644 (file)
 /*optional features*/
 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0))
 #define CAN_ENABLE_KERN_FASYNC
+#ifdef CONFIG_PCI
 #define CAN_ENABLE_PCI_SUPPORT
 #endif
+#ifdef CONFIG_VME_some_option_there
+#define CAN_ENABLE_VME_SUPPORT
+#endif
+#endif
 
 #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0))
 #include <linux/malloc.h>
index 78eace8..506e262 100644 (file)
@@ -88,6 +88,7 @@ struct candevice_t {
        struct canhardware_t *hosthardware_p;
        
        union {
+               void *anydev;
            #ifdef CAN_ENABLE_PCI_SUPPORT
                struct pci_dev *pcidev;
            #endif /*CAN_ENABLE_PCI_SUPPORT*/
@@ -474,6 +475,8 @@ struct boardtype_t {
 
 const struct boardtype_t* boardtype_find(const char *str);
 
+int can_check_dev_taken(void *anydev);
+
 #ifdef CAN_WITH_RTL
 extern int can_rtl_priority;
 #endif /*CAN_WITH_RTL*/
index f0b7dff..b04636c 100644 (file)
@@ -33,6 +33,8 @@ extern int bfadcan_register(struct hwspecops_t *hwspecops);
 extern int pikronisa_register(struct hwspecops_t *hwspecops);
 extern int msmcan_register(struct hwspecops_t *hwspecops);
 extern int unican_register(struct hwspecops_t *hwspecops);
+extern int unican_pci_register(struct hwspecops_t *hwspecops);
+extern int unican_vme_register(struct hwspecops_t *hwspecops);
 
 const struct boardtype_t can_boardtypes[]={
     #ifdef CONFIG_OC_LINCAN_CARD_template
@@ -94,6 +96,12 @@ const struct boardtype_t can_boardtypes[]={
     #endif
     #ifdef CONFIG_OC_LINCAN_CARD_unican
        {"unican", unican_register, 1},
+    #endif
+    #if defined(CONFIG_OC_LINCAN_CARD_unican)&&defined(CAN_ENABLE_PCI_SUPPORT)
+       {"unican-pci", unican_pci_register, 0},
+    #endif
+    #if defined(CONFIG_OC_LINCAN_CARD_unican)&&defined(CAN_ENABLE_VME_SUPPORT)
+       {"unican-vme", unican_vme_register, 1},
     #endif
        {NULL}
 };
index c49a3de..e7f36e3 100644 (file)
@@ -183,8 +183,10 @@ int kv_pcican_init_hw_data(struct candevice_t *candev)
        struct pci_dev *pcidev = NULL;
        int i;
 
-       pcidev = pci_find_device(KV_PCICAN_PCICAN_VENDOR, KV_PCICAN_PCICAN_ID, pcidev);
-       if(pcidev == NULL) return -ENODEV;
+       do {
+               pcidev = pci_find_device(KV_PCICAN_PCICAN_VENDOR, KV_PCICAN_PCICAN_ID, pcidev);
+               if(pcidev == NULL) return -ENODEV;
+       } while(can_check_dev_taken(pcidev));
        
        if (pci_enable_device (pcidev)){
                printk(KERN_CRIT "Setup of PCICAN failed\n");
@@ -193,7 +195,7 @@ int kv_pcican_init_hw_data(struct candevice_t *candev)
        candev->sysdevptr.pcidev=pcidev;
        
        for(i=0;i<3;i++){
-               if(!(pci_resource_flags(pcidev,0)&IORESOURCE_IO)){
+               if(!(pci_resource_flags(pcidev,i)&IORESOURCE_IO)){
                        printk(KERN_CRIT "PCICAN region %d is not IO\n",i);
                        return -EIO;
                }
index 6a59e2f..83eef72 100644 (file)
@@ -215,6 +215,29 @@ int can_base_addr_fixup(struct candevice_t *candev, unsigned long new_base)
        return 0;
 }
 
+/**
+ * can_check_dev_taken - checks if bus device description is already taken by driver
+ * @anydev:    pointer to bus specific Linux device description 
+ *
+ * Returns: Returns 1 if device is already used by LinCAN driver, 0 otherwise.
+ */
+int can_check_dev_taken(void *anydev)
+{
+       int board_nr;
+       struct candevice_t *candev;
+       void *boarddev;
+
+       for (board_nr=hardware_p->nr_boards; board_nr--; ) {
+               if((candev=hardware_p->candevice[board_nr])==NULL)
+                       continue;
+               boarddev=candev->sysdevptr.anydev;
+               if(boarddev == anydev)
+                       return 1;
+       }
+       
+       return 0;
+}
+
 
 /**
  * register_obj_struct - registers message object into global array
index efc5ac2..5cab054 100644 (file)
 #include "../include/unican_cl2.h"
 #include "../include/setup.h"
 
-#ifdef CAN_WITH_RTL
-    
-#endif /*CAN_WITH_RTL*/
-
+#define UNICAN_PCI_VENDOR  0xFA3C
+#define UNICAN_PCI_ID      0x0101
 
 static void unican_delay(long msdelay)
 {
@@ -848,3 +846,121 @@ int unican_register(struct hwspecops_t *hwspecops)
        hwspecops->program_irq = unican_program_irq;
        return 0;
 }
+
+
+/* Unicontrols PCI board specific functions */
+
+#ifdef CAN_ENABLE_PCI_SUPPORT
+
+int unican_pci_request_io(struct candevice_t *candev)
+{
+    #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,4,21))
+       if(pci_request_region(candev->sysdevptr.pcidev, 0, "unican_pci") != 0){
+               CANMSG("Request of Unican PCI range failed\n");
+               return -ENODEV;
+       }
+    #else /*(LINUX_VERSION_CODE > KERNEL_VERSION(2,4,21))*/
+       if(pci_request_regions(candev->sysdevptr.pcidev, "kv_pcican") != 0){
+               CANMSG("Request of Unican PCI range failed\n");
+               return -ENODEV;
+       }
+    #endif /*(LINUX_VERSION_CODE > KERNEL_VERSION(2,4,21))*/
+
+       return 0;
+}
+
+
+int unican_pci_release_io(struct candevice_t *candev)
+{
+    #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,4,21))
+       pci_release_region(candev->sysdevptr.pcidev, 0);
+    #else /*(LINUX_VERSION_CODE > KERNEL_VERSION(2,4,21))*/
+       pci_release_regions(candev->sysdevptr.pcidev);
+    #endif /*(LINUX_VERSION_CODE > KERNEL_VERSION(2,4,21))*/
+       return 0;
+}
+
+
+int unican_pci_init_hw_data(struct candevice_t *candev)
+{
+       struct pci_dev *pcidev = NULL;
+
+       do {
+               pcidev = pci_find_device(UNICAN_PCI_VENDOR, UNICAN_PCI_ID, pcidev);
+               if(pcidev == NULL) return -ENODEV;
+       } while(can_check_dev_taken(pcidev));
+       
+       if (pci_enable_device (pcidev)){
+               printk(KERN_CRIT "Setup of Unican PCI failed\n");
+               return -EIO;
+       }
+       candev->sysdevptr.pcidev=pcidev;
+       
+       if(!(pci_resource_flags(pcidev,0)&IORESOURCE_MEM)){
+               printk(KERN_CRIT "Unican PCI region 0 is not MEM\n");
+               return -EIO;
+       }
+       candev->dev_base_addr=pci_resource_start(pcidev,0); /*S5920*/
+       candev->io_addr=candev->dev_base_addr;
+       candev->res_addr=candev->dev_base_addr;
+       
+       /*candev->flags |= CANDEV_PROGRAMMABLE_IRQ;*/
+
+       candev->nr_82527_chips=0;
+       candev->nr_sja1000_chips=0;
+       candev->nr_all_chips=1;
+
+       return 0;
+}
+
+
+int unican_pci_init_chip_data(struct candevice_t *candev, int chipnr)
+{
+       int ret;
+       candev->chip[chipnr]->chip_irq=candev->sysdevptr.pcidev->irq;
+       ret = unican_pci_init_chip_data(candev, chipnr);
+       candev->chip[chipnr]->flags |= CHIP_IRQ_PCI;
+       return ret;
+}
+
+int unican_pci_register(struct hwspecops_t *hwspecops)
+{
+       hwspecops->request_io = unican_pci_request_io;
+       hwspecops->release_io = unican_pci_release_io;
+       hwspecops->reset = unican_reset;
+       hwspecops->init_hw_data = unican_pci_init_hw_data;
+       hwspecops->init_chip_data = unican_pci_init_chip_data;
+       hwspecops->init_obj_data = unican_init_obj_data;
+       hwspecops->write_register = NULL;
+       hwspecops->read_register = NULL;
+       hwspecops->program_irq = unican_program_irq;
+       return 0;
+}
+
+#endif /*CAN_ENABLE_PCI_SUPPORT*/
+
+#ifdef CAN_ENABLE_VME_SUPPORT
+
+int unican_vme_reset(struct candevice_t *candev)
+{
+       struct chip_t *chip = candev->chip[0];
+       writew(chip->chip_irq,chip->chip_base_addr+CL2_VME_INT_VECTOR);
+       return unican_reset(candev);
+}
+
+
+int unican_vme_register(struct hwspecops_t *hwspecops)
+{
+       hwspecops->request_io = unican_request_io;
+       hwspecops->release_io = unican_release_io;
+       hwspecops->reset = unican_vme_reset;
+       hwspecops->init_hw_data = unican_init_hw_data;
+       hwspecops->init_chip_data = unican_init_chip_data;
+       hwspecops->init_obj_data = unican_init_obj_data;
+       hwspecops->write_register = NULL;
+       hwspecops->read_register = NULL;
+       hwspecops->program_irq = unican_program_irq;
+       return 0;
+}
+
+#endif /*CAN_ENABLE_VME_SUPPORT*/
index 1760bc2..e3809b0 100644 (file)
@@ -53,8 +53,10 @@ ssize_t can_write(struct file *file, const char *buffer, size_t length, loff_t *
 
        /* Prepare first message */
        copy_from_user(&msg_buff, buffer, sizeof(struct canmsg_t));
-       /* Automatic selection of extended format if "extended" set and ID>2047 */
-       if (extended) if (msg_buff.id & ~0x7ffl ) msg_buff.flags |= MSG_EXT;
+
+       /* Automatic selection of extended format if ID>2047 */
+       if (msg_buff.id & ~0x7ffl & MSG_ID_MASK ) msg_buff.flags |= MSG_EXT;
+       /* has been dependent on "extended" option */
 
        /* If the output buffer is full, return immediately in case O_NONBLOCK
         * has been specified or loop until space becomes available.
@@ -89,8 +91,11 @@ ssize_t can_write(struct file *file, const char *buffer, size_t length, loff_t *
                bytes_to_copy -= sizeof(struct canmsg_t);
                /* Prepare first message */
                copy_from_user(&msg_buff, buffer, sizeof(struct canmsg_t));
-               /* Automatic selection of extended format if "extended" set and ID>2047 */
-               if (extended) if (msg_buff.id & ~0x7ffl ) msg_buff.flags |= MSG_EXT;
+
+               /* Automatic selection of extended format if ID>2047 */
+               if (msg_buff.id & ~0x7ffl & MSG_ID_MASK ) msg_buff.flags |= MSG_EXT;
+               /* has been dependent on "extended" option */
+
                /* Get slot */
                if(canque_get_inslot4id(qends, &qedge, &slot, 
                        0, msg_buff.id, 0) < 0) break;
index a1d4647..70af511 100644 (file)
@@ -47,8 +47,10 @@ ssize_t can_write_rtl_posix(struct rtl_file *fptr, const char *buffer,
        qends = canuser->qends;
 
        msg_flags=msg_buff->flags;
-       /* Automatic selection of extended format if "extended" set and ID>2047 */
-       if (extended) if (msg_buff->id & ~0x7ffl ) msg_flags |= MSG_EXT;
+
+       /* Automatic selection of extended format if ID>2047 */
+       if (msg_buff->id & ~0x7ffl & MSG_ID_MASK ) msg_flags |= MSG_EXT;
+       /* has been dependent on "extended" option */
 
        /* If the output buffer is full, return immediately in case O_NONBLOCK
         * has been specified or loop until space becomes available.
@@ -82,8 +84,11 @@ ssize_t can_write_rtl_posix(struct rtl_file *fptr, const char *buffer,
        while (bytes_to_copy >= sizeof(struct canmsg_t)) {
                bytes_to_copy -= sizeof(struct canmsg_t);
                msg_flags=msg_buff->flags;
-               /* Automatic selection of extended format if "extended" set and ID>2047 */
-               if (extended) if (msg_buff->id & ~0x7ffl ) msg_flags |= MSG_EXT;
+
+               /* Automatic selection of extended format if ID>2047 */
+               if (msg_buff->id & ~0x7ffl & MSG_ID_MASK ) msg_flags |= MSG_EXT;
+               /* has been dependent on "extended" option */
+
                /* Get slot */
                if(canque_get_inslot4id(qends, &qedge, &slot, 
                        0, msg_buff->id, 0) < 0) break;