//****************************************************************************
// 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;
}
/* ------------------------------------------------------------------------- */
/* ------------------------------------------------------------------------- */