Subversion Repositories f9daq

Rev

Blame | Last modification | View Log | RSS feed

//****************************************************************************
// Copyright (C) 2000-2006  ARW Elektronik Germany
//
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program 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 this program; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
//
// This product is not authorized for use as critical component in
// life support systems without the express written approval of
// ARW Elektronik Germany.
//  
// Please announce changes and hints to ARW Elektronik
//
// Maintainer(s): Klaus Hitschler (klaus.hitschler@gmx.de)
//
//****************************************************************************

//****************************************************************************
//
// askpci.c - a hardware independent tool to get
//            information about searched pci-hardware
//
// $Log: askpci.c,v $
// Revision 1.7  2006/06/04 12:20:46  klaus
// release_20060604; Version 3.2; pci_{en|dis}able_device() added
//
// Revision 1.6  2004/08/13 19:23:26  klaus
// conversion to kernel-version 2.6, released version 3.0
//
// Revision 1.5  2002/10/18 21:56:28  klaus
// completed functional features, untested
//
// Revision 1.4  2002/10/18 21:56:28  klaus
// completed functional features, untested
//
// Revision 1.3  2002/10/10 18:57:46  klaus
// source beautyfied
//
//****************************************************************************

/*--- INCLUDES -------------------------------------------------------------*/
#include "common.h"  /* must be the first include */

#include <linux/pci.h>
#include <asm/types.h>
#include "askpci.h"

/*--- DEFINES ---------------------------------------------------------------*/


/*--- FUNCTIONS -------------------------------------------------------------*/
void DeletePCIConfig(DRIVER_OBJ *drv)
{
    PCIConfig *dev = NULL;

    while (!list_empty(&drv->pciList))     // cycle through the list of pci devices and remove them
    {
        dev = (PCIConfig *)drv->pciList.prev; // empty in reverse order
       
        #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,10)
        if (dev->pciDev)
                      pci_disable_device(dev->pciDev);
        #endif         

        list_del(&dev->list);
        kfree(dev);
    }
}

int GetPCIConfig(DRIVER_OBJ *drv, u16 device_id, u16 vendor_id, u16 subsys_id, u16 subven_id)
{
    int result     = 0;
    PCIConfig *dev = NULL;
    int i          = 0;

    // search pci devices
    PRINTK(KERN_DEBUG "%s : GetPCIConfig(0x%04x, 0x%04x, 0x%04x, 0x%04x)\n", DEVICE_NAME, device_id, vendor_id, subsys_id, subven_id);

#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
        if (CONFIG_PCI)
#else
        if (pci_present())
#endif
    {
        struct pci_dev *pciDev;

        struct pci_dev *from = NULL;
        do
        {
// https://groups.google.com/forum/?fromgroups=#!topic/fa.linux.kernel/aMXNYIFrOP8
//            pciDev = pci_find_device((unsigned int)vendor_id, (unsigned int)device_id, from);
            pciDev = pci_get_device((unsigned int)vendor_id, (unsigned int)device_id, from);

            if (pciDev != NULL)
            {
                u16 wSubSysID;
                u16 wSubVenID;

                // a PCI device with PCAN_PCI_VENDOR_ID and PCAN_PCI_DEVICE_ID was found
                from = pciDev;
               
                #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,10)
                if (pci_enable_device(pciDev))
                  continue;  
                #endif

                // get the PCI Subsystem-ID
                result = pci_read_config_word(pciDev, PCI_SUBSYSTEM_ID, &wSubSysID);
                if (result)
                {
                    result = -ENXIO;
                    goto fail;
                }

                // get the PCI Subvendor-ID
                result = pci_read_config_word(pciDev, PCI_SUBSYSTEM_VENDOR_ID, &wSubVenID);
                if (result)
                {
                    result = -ENXIO;
                    goto fail;
                }

                // get next if the subsys and subvendor ids do not match
                if ((wSubVenID != subven_id) || (wSubSysID != subsys_id))
                    continue;

                // create space for PCIConfig descriptor
                if ((dev = (PCIConfig *)kmalloc(sizeof(PCIConfig), GFP_KERNEL)) == NULL)
                {
                    result = -ENOMEM;
                    goto fail;
                }

                // put data into pci device
                dev->pciDev = pciDev;  

                list_add_tail(&dev->list, &drv->pciList);  // add this device to the list of unchecked devices
                dev->index++;
                i++;
            }
        } while (pciDev != NULL);

        result = 0;
    }
    else
    {
        printk(KERN_ERR "%s: No pcibios present!\n", DEVICE_NAME);  
        result = -ENXIO;
    }

    fail:
    if (result)
        DeletePCIConfig(drv);

    PRINTK(KERN_DEBUG "%s : %d devices found (%d).\n", DEVICE_NAME, i, result);

    return result;  
}


/* ------------------------------------------------------------------------- */
/* ------------------------------------------------------------------------- */