]> rtime.felk.cvut.cz Git - lincan.git/blobdiff - lincan/src/nsi_canpci.c
LinCAN PCI cards support updated to support PCI devices reference counting.
[lincan.git] / lincan / src / nsi_canpci.c
index 9fbed1117562232dfdc66a94a9a36fe489e95a2e..1fee22726cb4693a5a85a65296e0a699371cd4a5 100644 (file)
@@ -1,13 +1,38 @@
-/* nsi.c
- * Linux CAN-bus device driver.
- * nsi_canpci.c - support for NSI CAN PCI card
- * The card support added by Eric Pennamen <pennamen@gmail.com>
- * Based on code from Arnaud Westenberg email:arnaud@wanadoo.nl
- * Ake Hedman, eurosource, akhe@eurosource.se ,
- * and Pavel Pisa - OCERA team member email:pisa@cmp.felk.cvut.cz
- * This software is released under the GPL-License.
- * Version lincan-0.3  17 Jun 2004
- */ 
+/**************************************************************************/
+/* File: nsi_canpci.c - NSI CAN PCI card (2xi82527)                       */
+/*                                                                        */
+/* LinCAN - (Not only) Linux CAN bus driver                               */
+/* Copyright (C) 2002-2009 DCE FEE CTU Prague <http://dce.felk.cvut.cz>   */
+/* Copyright (C) 2002-2009 Pavel Pisa <pisa@cmp.felk.cvut.cz>             */
+/* Copyright (C) 2004 Eric Pennamen <pennamen@gmail.com>                  */
+/* Funded by OCERA and FRESCOR IST projects                               */
+/* Based on CAN driver code by Arnaud Westenberg <arnaud@wanadoo.nl>      */
+/* and Ake Hedman, eurosource <akhe@eurosource.se>                        */
+/*                                                                        */
+/* LinCAN is free software; you can redistribute it and/or modify it      */
+/* under terms of the GNU General Public License as published by the      */
+/* Free Software Foundation; either version 2, or (at your option) any    */
+/* later version.  LinCAN is distributed in the hope that it will be      */
+/* useful, but WITHOUT ANY WARRANTY; without even the implied warranty    */
+/* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU    */
+/* General Public License for more details. You should have received a    */
+/* copy of the GNU General Public License along with LinCAN; see file     */
+/* COPYING. If not, write to the Free Software Foundation, 675 Mass Ave,  */
+/* Cambridge, MA 02139, USA.                                              */
+/*                                                                        */
+/* To allow use of LinCAN in the compact embedded systems firmware        */
+/* and RT-executives (RTEMS for example), main authors agree with next    */
+/* special exception:                                                     */
+/*                                                                        */
+/* Including LinCAN header files in a file, instantiating LinCAN generics */
+/* or templates, or linking other files with LinCAN objects to produce    */
+/* an application image/executable, does not by itself cause the          */
+/* resulting application image/executable to be covered by                */
+/* the GNU General Public License.                                        */
+/* This exception does not however invalidate any other reasons           */
+/* why the executable file might be covered by the GNU Public License.    */
+/* Publication of enhanced or derived LinCAN files is required although.  */
+/**************************************************************************/
 
 #include "../include/can.h"
 #include "../include/can_sysdep.h"
@@ -23,10 +48,10 @@ extern int mo15mask;
 #include <linux/module.h>
 
 #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,10))
-       #define ioread32        readl
-       #define iowrite32       writel
-       #define ioread8         readb
-       #define iowrite8        writeb
+       #define ioread32        can_readl
+       #define iowrite32       can_writel
+       #define ioread8         can_readb
+       #define iowrite8        can_writeb
 #else
 #endif
 
@@ -350,43 +375,25 @@ int nsi_canpci_reset(struct candevice_t *candev)
  */
 
 int nsi_canpci_init_hw_data(struct candevice_t *candev) 
-     {
-  struct pci_dev *pcidev = NULL;
+{
+       struct pci_dev *pcidev;
 
-  /* looking for NSI CANPCI ident on the pci bus*/
-  do
-  {
-    pcidev = pci_find_device(NSI_VENDOR_ID, NSI_CANPCI_DEVICE_ID, pcidev);
-  }
-  while(can_check_dev_taken(pcidev));
-  
-  if(pcidev == NULL) 
-  {
-       do
-       {
-       pcidev = pci_find_device(NSI_VENDOR_ID, NSI_CANPCI_DEVICE_ID+1, pcidev);
-       }
-       while(can_check_dev_taken(pcidev));
-       if(pcidev == NULL) 
-       {
+       /* looking for NSI CANPCI ident on the pci bus*/
+       pcidev = can_pci_get_next_untaken_device(NSI_VENDOR_ID, NSI_CANPCI_DEVICE_ID);
+       if(pcidev == NULL)
+               pcidev = can_pci_get_next_untaken_device(NSI_VENDOR_ID, NSI_CANPCI_DEVICE_ID+1);
+       if(pcidev == NULL) {
                CANMSG ("Error : NSI CAN PCI device not found\n");
                return -ENODEV;
        }
-       else
-       {
-               CANMSG ("NSI CANPCI OPTO device found\n");
-       }
-  }
-  else
-  {
+
        CANMSG ("NSI CANPCI device found\n");  
-  }
-    
+
   /* enable it */
   if (pci_enable_device (pcidev))
   {
     CANMSG ("Cannot enable PCI device\n");
-    return -EIO;
+    goto error_io;
   }
   CANMSG ("NSI CANPCI device started\n");
   candev->sysdevptr.pcidev = pcidev;
@@ -411,30 +418,30 @@ int nsi_canpci_init_hw_data(struct candevice_t *candev)
                        pci_release_region(pcidev,0);
                        pci_release_region(pcidev,1);
                        pci_release_region(pcidev,2);                   
-                       return -EIO;
+                       goto error_io;
                        }
                }
                else
                {
                pci_release_region(pcidev,0);
                pci_release_region(pcidev,1);
-               return -EIO;
+               goto error_io;
                }
        }
        else
        {
        pci_release_region(pcidev,0);
-       return -EIO;
+       goto error_io;
        }
   }  
   else
   {
-       return -EIO;
+       goto error_io;
   }
   candev->dev_base_addr=(unsigned long)(kmalloc(sizeof(t_CardArray),GFP_ATOMIC));  
   
   if((unsigned long)candev->dev_base_addr==0)
-       return -EIO;
+       goto error_io;
   //PLX register 
   ((t_CardArray*)(candev->dev_base_addr))->addr_BAR_remap[0]=ioremap(pci_resource_start(pcidev,0),pci_resource_len(pcidev,0) );
   //PLX IO
@@ -447,8 +454,20 @@ int nsi_canpci_init_hw_data(struct candevice_t *candev)
   //Short acces to plx register
   candev->io_addr=(unsigned long)(((t_CardArray*)(candev->dev_base_addr))->addr_BAR_remap[0]);
   return 0;  
+
+error_io:
+       can_pci_dev_put(pcidev);
+       return -EIO;
 }
 
+
+void nsi_canpci_done_hw_data(struct candevice_t *candev)
+{
+       struct pci_dev *pcidev = candev->sysdevptr.pcidev;
+       can_pci_dev_put(pcidev);
+}
+
+
 /* The function template_init_chip_data is used to initialize the hardware
  * structure containing information about the CAN chips.
  * CHIP_TYPE represents the type of CAN chip. CHIP_TYPE can be "i82527" or
@@ -517,7 +536,7 @@ int nsi_canpci_program_irq(struct candevice_t *candev)
  * on the CAN chip. You should only have to edit this function if your hardware
  * uses some specific write process.
  */
-void nsi_canpci_write_register(unsigned data, unsigned long address)
+void nsi_canpci_write_register(unsigned data, can_ioptr_t address)
 {
        iowrite8((u8)data,(void*)address);
 }
@@ -526,7 +545,7 @@ void nsi_canpci_write_register(unsigned data, unsigned long address)
  * on the CAN chip. You should only have to edit this function if your hardware
  * uses some specific read process.
  */
-unsigned nsi_canpci_read_register(unsigned long address)
+unsigned nsi_canpci_read_register(can_ioptr_t address)
 {
        return ioread8((void*)address);
 }
@@ -539,6 +558,7 @@ int nsi_canpci_register(struct hwspecops_t *hwspecops)
        hwspecops->release_io = nsi_canpci_release_io;
        hwspecops->reset = nsi_canpci_reset;
        hwspecops->init_hw_data = nsi_canpci_init_hw_data;
+       hwspecops->done_hw_data = nsi_canpci_done_hw_data;
        hwspecops->init_chip_data = nsi_canpci_init_chip_data;
        hwspecops->init_obj_data = nsi_canpci_init_obj_data;
        hwspecops->write_register = nsi_canpci_write_register;