]> rtime.felk.cvut.cz Git - lincan.git/blobdiff - lincan/src/esdpci200.c
LinCAN sources go through big white-space cleanup.
[lincan.git] / lincan / src / esdpci200.c
index 1b62e7e49972bf9c518476a1363bb02d537ed844..09c44fafdc7bcbd7d50fd8e53acf6b903a2eb364 100644 (file)
@@ -1,10 +1,37 @@
-/* esdpci200.c - support for ESD Electronics' CAN/PCI-200 cards
- * Linux CAN-bus device driver.
- * The card support was added by Manuel Bessler <m.bessler@gmx.net>
- * Based on adlink7841.c and nsi_canpci.c
- * This software is released under the GPL-License.
- * Version lincan-0.3.3
- */ 
+/**************************************************************************/
+/* File: esdpci200.c - support for ESD Electronics' CAN/PCI-200 cards     */
+/*                                                                        */
+/* 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) 2007 Manuel Bessler <m.bessler@gmx.net>                  */
+/* Funded by OCERA and FRESCOR IST projects                               */
+/* Based on CAN driver code by Arnaud Westenberg <arnaud@wanadoo.nl>      */
+/*                                                                        */
+/* 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"
 #define PLX9052_CNTRL  0x50    /* control register, for software reset */
 
 /* The ESD PCI/200 uses (per default) just LINTi1 (Local Interrupt 1)
- * on the PLX. This means that both CAN channels' (SJA1000's) /INT pins 
+ * on the PLX. This means that both CAN channels' (SJA1000's) /INT pins
  * are OR'ed to the LINTi1 pin (actually ANDed in the 74HC08 since both
  * the SJA1000's /INT pins and the LINTi1 pin are active low).
  *
  * The board does have an option to route the 2nd channel to LINTi2,
  * apparently just one or two resistors need to be added.
  *
- * LINTi2 is floating per default, so don't set its interrupt enable flag 
+ * LINTi2 is floating per default, so don't set its interrupt enable flag
  * 'PLX9052_INTCSR_LI2EN', it'll just interrupt all the time.
  */
 #define PLX9052_INTCSR_LI1EN 0x00000001 /* Local Interrupt 1 enable */
@@ -54,7 +81,7 @@
 
 // Standard value: Pushpull  (OCTP1|OCTN1|OCPOL1|OCTP0|OCTN0|OCM1)
 #define ESDPCI200_OCR_DEFAULT_STD 0xFA
-/* Setting the OCR register to 0xFA is a good idea. 
+/* Setting the OCR register to 0xFA is a good idea.
    This means  normal output mode , push-pull and the correct polarity. */
 
 
@@ -86,7 +113,7 @@ void esdpci200_connect_irq(struct candevice_t *candev)
         /* enable interrupts for the SJA1000's, enable PCI interrupts */
        outl(   PLX9052_INTCSR_LI1EN | PLX9052_INTCSR_PIEN,
                candev->res_addr+PLX9052_INTCSR);
-       DEBUGMSG("enabled interrupts on the PLX\n"); 
+       DEBUGMSG("enabled interrupts on the PLX\n");
 }
 
 int esdpci200_irq_handler(int irq, struct canchip_t *chip)
@@ -99,8 +126,8 @@ int esdpci200_irq_handler(int irq, struct canchip_t *chip)
        //DEBUGMSG("Starting to handle an IRQ\n");
        it_reg = inl(candev->res_addr+PLX9052_INTCSR);
        rmb();
-       if((it_reg & (PLX9052_INTCSR_LI1S | PLX9052_INTCSR_LI1EN) ) 
-               == (PLX9052_INTCSR_LI1S | PLX9052_INTCSR_LI1EN) ) 
+       if((it_reg & (PLX9052_INTCSR_LI1S | PLX9052_INTCSR_LI1EN) )
+               == (PLX9052_INTCSR_LI1S | PLX9052_INTCSR_LI1EN) )
        {       /*interrupt enabled and active */
                int chipnum;
                for(chipnum=0; chipnum < candev->nr_sja1000_chips; chipnum++)
@@ -117,7 +144,7 @@ int esdpci200_irq_handler(int irq, struct canchip_t *chip)
                        }
                }
                if( retcode != CANCHIP_IRQ_HANDLED )
-               {/* None of the chips felt they were responsible for this IRQ... 
+               {/* None of the chips felt they were responsible for this IRQ...
                    so it appears we have problems with the IRQ */
                        it_reg &= ~(PLX9052_INTCSR_LI1EN);
                        //Either we have a problem with IRQ malfunctions, or our IRQ is shared with some other device.
@@ -163,7 +190,7 @@ int esdpci200_request_io(struct candevice_t *candev)
        /*MEM window for SJA1000 chips*/
        bar2_addr = pci_resource_start(pcidev,2);
        candev->io_addr = bar2_addr;
-       if( ! (remap_addr=ioremap(bar2_addr, 
+       if( ! (remap_addr=ioremap(bar2_addr,
                pci_resource_len(pcidev,2)))) /*MEM window for SJA1000 chips*/
        {
                CANMSG("Unable to access I/O memory at: 0x%lx\n", (unsigned long)bar2_addr);
@@ -171,9 +198,9 @@ int esdpci200_request_io(struct candevice_t *candev)
        }
 
        can_base_addr_fixup(candev, remap_addr);
-       CANMSG("esdpci200_sja IO-memory: 0x%lx - 0x%lx (VMA 0x%lx)\n", 
+       CANMSG("esdpci200_sja IO-memory: 0x%lx - 0x%lx (VMA 0x%lx)\n",
                (unsigned long) bar2_addr,
-               (unsigned long) bar2_addr + pci_resource_len(pcidev,2) - 1,
+               (unsigned long) (bar2_addr + pci_resource_len(pcidev,2) - 1),
                (long) remap_addr);
 
        return 0;
@@ -208,13 +235,13 @@ int esdpci200_release_io(struct candevice_t *candev)
 
 void esdpci200_write_register(unsigned data, can_ioptr_t address)
 {
-       iowrite8((u8)data,(void*)address);
+       iowrite8((u8)data,address);
        wmb();
 }
 
 unsigned esdpci200_read_register(can_ioptr_t address)
 {
-       return ioread8((void*)address);
+       return ioread8(address);
 }
 
 int esdpci200_reset(struct candevice_t *candev)
@@ -251,27 +278,27 @@ int esdpci200_reset(struct candevice_t *candev)
                esdpci200_write_register(cdr|sjaCDR_PELICAN, chip->chip_base_addr+SJACDR);
 
                esdpci200_write_register(0, chip->chip_base_addr+SJAIER);
-               
+
                esdpci200_read_register(chip->chip_base_addr+SJAIR);
        }
-       
+
 
        esdpci200_connect_irq(candev);
 
        return 0;
-}      
+}
 
 int esdpci200_init_hw_data(struct candevice_t *candev)
 {
-       struct pci_dev *pcidev = NULL;
+       struct pci_dev *pcidev;
+
+       pcidev = can_pci_get_next_untaken_device(ESDPCI200_PCI_VENDOR_ID, ESDPCI200_PCI_PRODUCT_ID);
+       if(pcidev == NULL)
+               return -ENODEV;
 
-       do {
-               pcidev = pci_find_device(ESDPCI200_PCI_VENDOR_ID, ESDPCI200_PCI_PRODUCT_ID, pcidev);
-               if(pcidev == NULL) return -ENODEV;
-       } while(can_check_dev_taken(pcidev));
-       
        if (pci_enable_device (pcidev)){
                printk(KERN_CRIT "Setup of ESDPCI200 failed\n");
+               can_pci_dev_put(pcidev);
                return -EIO;
        }
        candev->sysdevptr.pcidev=pcidev;
@@ -281,17 +308,20 @@ int esdpci200_init_hw_data(struct candevice_t *candev)
        if(!(pci_resource_flags(pcidev, 0)&IORESOURCE_MEM))
        {
           printk(KERN_CRIT "PCI200 region %d is not MEM\n",0);
+          can_pci_dev_put(pcidev);
           return -EIO;
        }
        if(!(pci_resource_flags(pcidev, 1)&IORESOURCE_IO))
        {
           printk(KERN_CRIT "PCI200 region %d is not IO\n",1);
+          can_pci_dev_put(pcidev);
           return -EIO;
        }
 
        if(!(pci_resource_flags(pcidev,2)&IORESOURCE_MEM))
        {
           printk(KERN_CRIT "PCI200 region %d is not MEM\n",2);
+          can_pci_dev_put(pcidev);
           return -EIO;
        }
 
@@ -300,7 +330,7 @@ int esdpci200_init_hw_data(struct candevice_t *candev)
 
        /* Physical address of SJA1000 window, stored for debugging only */
        candev->io_addr = pci_resource_start(pcidev,2);
-       
+
        candev->aux_base_addr=NULL; /* mapped dynamically in esdpci200_request_io() */
        candev->dev_base_addr=NULL; /* mapped dynamically in esdpci200_request_io() */
        /*candev->flags |= CANDEV_PROGRAMMABLE_IRQ;*/
@@ -312,11 +342,17 @@ int esdpci200_init_hw_data(struct candevice_t *candev)
        return 0;
 }
 
+void esdpci200_done_hw_data(struct candevice_t *candev)
+{
+       struct pci_dev *pcidev = candev->sysdevptr.pcidev;
+       can_pci_dev_put(pcidev);
+}
+
 int esdpci200_init_chip_data(struct candevice_t *candev, int chipnr)
 {
 
        if(candev->sysdevptr.pcidev==NULL)
-               return -ENODEV; 
+               return -ENODEV;
 
        CANMSG("initializing esdpci200 chip operations\n");
 
@@ -336,13 +372,13 @@ int esdpci200_init_chip_data(struct candevice_t *candev, int chipnr)
        candev->chip[chipnr]->chip_irq=candev->sysdevptr.pcidev->irq;
        candev->chip[chipnr]->flags |= CHIP_IRQ_PCI;
        if( chipnr > 0 ) /* only one IRQ used for both channels.
-                           CHIP_IRQ_CUSTOM req'd for RTAI, since 
-                           registering two handlers for the same IRQ 
+                           CHIP_IRQ_CUSTOM req'd for RTAI, since
+                           registering two handlers for the same IRQ
                            returns an error */
                candev->chip[chipnr]->flags |= CHIP_IRQ_CUSTOM;
 
        return 0;
-}      
+}
 
 int esdpci200_init_obj_data(struct canchip_t *chip, int objnr)
 {
@@ -362,6 +398,7 @@ int esdpci200_register(struct hwspecops_t *hwspecops)
        hwspecops->release_io = esdpci200_release_io;
        hwspecops->reset = esdpci200_reset;
        hwspecops->init_hw_data = esdpci200_init_hw_data;
+       hwspecops->done_hw_data = esdpci200_done_hw_data;
        hwspecops->init_chip_data = esdpci200_init_chip_data;
        hwspecops->init_obj_data = esdpci200_init_obj_data;
        hwspecops->write_register = esdpci200_write_register;