]> rtime.felk.cvut.cz Git - lincan.git/blobdiff - lincan/src/unican.c
Changed filling of the chip specific operations.
[lincan.git] / lincan / src / unican.c
index efc5ac276188294976bfabc658822bb714deb670..f2c7ec60d1498d6b91c87a2f21ed6a116eee6f8c 100644 (file)
@@ -3,7 +3,7 @@
  * 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
+ * Version lincan-0.3  17 Jun 2004
  */ 
 
 #include "../include/can.h"
 #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)
 {
@@ -195,14 +193,14 @@ void unican_read(struct chip_t *chip, struct msgobj_t *obj) {
 
        do {
                ptr16 = (__u16*)chipext->rxBufPtr;
-               u = readw(ptr16++);
+               u = unican_readw(ptr16++);
                if ( !(u & CL2_MESSAGE_VALID) ) break; /* No more messages in the queue */
 
                obj->rx_msg.id = ((__u32)(u & 0xFF00 )) << 16;
-               u = readw(ptr16++);
+               u = unican_readw(ptr16++);
                obj->rx_msg.id |= ((__u32)( u & 0x00FF )) << 16;
                obj->rx_msg.id |= (__u32)( u & 0xFF00 );
-               u = readw(ptr16++);
+               u = unican_readw(ptr16++);
                obj->rx_msg.id |= (__u32)( u & 0x00FF );
 
 
@@ -223,17 +221,17 @@ void unican_read(struct chip_t *chip, struct msgobj_t *obj) {
                if(obj->rx_msg.length > CAN_MSG_LENGTH) obj->rx_msg.length = CAN_MSG_LENGTH;
 
                for ( i = 0; i < obj->rx_msg.length; ) {
-                       u = readw(ptr16++);
+                       u = unican_readw(ptr16++);
                        obj->rx_msg.data[i++] = (__u8)( u );
                        obj->rx_msg.data[i++] = (__u8)( u >> 8 );
                }
                if ( obj->rx_msg.length & 0x01 ) {      /* odd */
-                       timestamp = ( (readw(ptr16++) & 0x00FF) | (u & 0xFF00) );
+                       timestamp = ( (unican_readw(ptr16++) & 0x00FF) | (u & 0xFF00) );
                } else {                                /* even */
-                       u = readw(ptr16++);
+                       u = unican_readw(ptr16++);
                        timestamp = (u << 8) | (u >> 8);
                }
-               writew(0x000,(__u16*)chipext->rxBufPtr);
+               unican_writew(0x000,(__u16*)chipext->rxBufPtr);
 
               #ifdef CAN_MSG_VERSION_2
                obj->rx_msg.timestamp.tv_sec = 0;
@@ -462,7 +460,7 @@ void unican_irq_write_handler(struct chip_t *chip, struct msgobj_t *obj)
 
        do {
                ptr16 = (__u16*)chipext->asyncTxBufPtr;
-               if(readw(ptr16) & CL2_MESSAGE_VALID)
+               if(unican_readw(ptr16) & CL2_MESSAGE_VALID)
                        return;         /* No free space in asynchronous Tx queue */
 
                cmd=canque_test_outslot(obj->qends, &obj->tx_qedge, &obj->tx_slot);
@@ -479,7 +477,7 @@ void unican_irq_write_handler(struct chip_t *chip, struct msgobj_t *obj)
                }
                ptr16++;
                u = ((cobid>>16) & 0x00FF ) + (cobid & 0xFF00);
-               writew(u,ptr16++);
+               unican_writew(u,ptr16++);
 
                len = obj->tx_slot->msg.length;
                if(len > CAN_MSG_LENGTH)
@@ -491,24 +489,24 @@ void unican_irq_write_handler(struct chip_t *chip, struct msgobj_t *obj)
                if ( obj->tx_slot->msg.flags & MSG_EXT ) 
                        u |= CL2_EXT_FRAME<<8;
 
-               writew(u,ptr16++);
+               unican_writew(u,ptr16++);
 
                for ( i = 0; i < len-1; )       {
                        u = obj->tx_slot->msg.data[i++];
                        u |= ((__u16)obj->tx_slot->msg.data[i]<<8); i++;
-                       writew(u,ptr16++);
+                       unican_writew(u,ptr16++);
                }
                if(i == len) {
-                       writew(timestamp,ptr16);
+                       unican_writew(timestamp,ptr16);
                } else {
                        u = obj->tx_slot->msg.data[i++];
                        u |= ((timestamp & 0x00FF)<<8);
-                       writew(u,ptr16++);
-                       writew(timestamp & 0x00FF, ptr16);
+                       unican_writew(u,ptr16++);
+                       unican_writew(timestamp & 0x00FF, ptr16);
                }
 
                u = ((cobid>>16) & 0xFF00) | CL2_MESSAGE_VALID;
-               writew(u,(__u16*)chipext->asyncTxBufPtr);
+               unican_writew(u,(__u16*)chipext->asyncTxBufPtr);
 
                if ( (chipext->asyncTxBufBase + chipext->asyncTxBufSize*16) <= 
                                                (chipext->asyncTxBufPtr += 16) ) {
@@ -761,8 +759,6 @@ int unican_init_hw_data(struct candevice_t *candev)
        return 0;
 }
 
-#define CHIP_TYPE "unican"
-
 /**
  * unican_init_chip_data - Initialize chips
  * @candev: Pointer to candevice/board structure
@@ -774,7 +770,7 @@ int unican_init_hw_data(struct candevice_t *candev)
 int unican_init_chip_data(struct candevice_t *candev, int chipnr)
 {
        struct chip_t *chip = candev->chip[chipnr];
-       chip->chip_type = CHIP_TYPE;
+       chip->chip_type = "unican";
        chip->chip_base_addr = 0;
        chip->clock = 10000000;
        chip->int_clk_reg = 0x0;
@@ -848,3 +844,123 @@ 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)
+{
+        unsigned long remap_addr;
+
+    #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))*/
+
+       candev->dev_base_addr=pci_resource_start(candev->sysdevptr.pcidev,0);
+       candev->io_addr=candev->dev_base_addr;
+       candev->res_addr=candev->dev_base_addr;
+
+       if ( !( remap_addr = (long) ioremap( candev->io_addr, IO_RANGE ) ) ) {
+               CANMSG("Unable to access I/O memory at: 0x%lx\n", candev->io_addr);
+           #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 -ENODEV;
+       
+       }
+       can_base_addr_fixup(candev, remap_addr);
+       DEBUGMSG("Registered IO-memory: 0x%lx - 0x%lx\n", candev->io_addr, candev->io_addr + IO_RANGE - 1);
+       DEBUGMSG("VMA: dev_base_addr: 0x%lx chip_base_addr: 0x%lx\n", 
+               candev->dev_base_addr, candev->chip[0]->chip_base_addr);
+
+       return 0;
+}
+
+
+int unican_pci_release_io(struct candevice_t *candev)
+{
+       iounmap((void*)candev->dev_base_addr);
+    #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);
+       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_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
+
+#include "unican_vme.c"
+
+#endif /*CAN_ENABLE_VME_SUPPORT*/