//****************************************************************************
 
// 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.11  2006/06/04 12:26:07  klaus
 
// release_20060604; Version 6.9; pci_{en|dis}able_device() added; remap_page_range reorganized
 
//
 
// Revision 1.10  2005/10/07 16:57:10  klaus
 
// fixed a bug with request_irq with IRQs greater than 127
 
//
 
// Revision 1.9  2004/08/12 19:59:19  klaus
 
// conversion to kernel-version 2.6, released version 6.0
 
//
 
// Revision 1.8  2003/06/19 08:23:38  klaus
 
// re-compiled with RH-7.2 (kernel 2.4.10)
 
//
 
// Revision 1.7  2003/05/11 11:12:03  klaus
 
// matched to kernel 2.4 PCI handling, debug messages improved
 
//
 
// Revision 1.5  2003/05/05 18:15:55  klaus
 
// added some debug code and reject if no CONFIG_PCI found, Version 4.7
 
//
 
// Revision 1.4  2001/11/20 20:12:50  klaus
 
// included new header and CVS log
 
//
 
//
 
// derived from code originated from Dirk Muehlenberg               AR   18.02.2000
 
// MODVERSIONS included                                             AR   24.04.2000
 
//
 
//****************************************************************************
 
 
 
 
 
/*
 
      
 
   (c) 2000 ARW Elektronik
 
 
 
   this source code is published under GPL (Open Source). You can use, redistribute and 
 
   modify it unless this header   is not modified or deleted. No warranty is given that 
 
   this software will work like expected.
 
 
 
*/
 
 
 
#include "common.h"  /* must be the first include */
 
 
 
#include <linux/pci.h>
 
#include <asm/types.h>
 
#include "list.h"
 
#include "askpci.h"
 
 
 
 
 
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,10)
 
#define pci_enable_device(x) 0
 
#endif
 
                  
 
 
 
/* fills the configration header */
 
 
 
// init the first time, anchor for next device search
 
static struct pci_dev *from = NULL;
 
 
 
PCIConfigHeader *GetPCIConfigHeader ( __u16 vendor_id, __u16 device_id, short index)
 
{
 
  PCIConfigHeader *pci_ch = (PCIConfigHeader *)NULL;
 
  
 
#ifdef CONFIG_PCI
 
 
 
  int i;
 
        
 
  DPRINTK(KERN_DEBUG "pcicc32 : GetPCIConfigHeader (%d)\n", index);
 
 
 
  #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
 
        if (!CONFIG_PCI)
 
        #else
 
  if (!pci_present())
 
        #endif
 
  {
 
    printk(KERN_ERR "pcicc32 : GetPCIConfigHeader(): no pcibios present!\n");
 
    return (PCIConfigHeader *)NULL;
 
  }
 
 
 
  pci_ch = (PCIConfigHeader *)kmalloc(sizeof(PCIConfigHeader), GFP_ATOMIC);
 
  if (!pci_ch) return (PCIConfigHeader *)NULL;
 
 
 
  pci_ch->vendor_id = vendor_id;
 
  pci_ch->device_id = device_id;
 
  pci_ch->index     = index;
 
  
 
  pci_ch->PCI_dev = pci_get_device(pci_ch->vendor_id, pci_ch->device_id, from);
 
        if ((pci_ch->PCI_dev == NULL) || (pci_enable_device(pci_ch->PCI_dev)))
 
        {
 
                kfree_s(pci_ch, sizeof(*pci_ch)); // FREE(pci_ch);
 
                from = NULL;
 
                return (PCIConfigHeader *)NULL;
 
        }
 
  
 
  for (i=0;i<6;i++)
 
  {
 
                pci_ch->desc[i].base_address = pci_ch->PCI_dev->resource[i].start;
 
                pci_ch->desc[i].size         = pci_ch->PCI_dev->resource[i].end - pci_ch->PCI_dev->resource[i].start;
 
                if (pci_ch->desc[i].size) 
 
                        pci_ch->desc[i].size += 1;
 
                
 
    if (pci_ch->PCI_dev->resource[i].flags & IORESOURCE_IO) /* io space */
 
    {
 
                        pci_ch->desc[i].type         = PCI_BASE_ADDRESS_SPACE_IO; 
 
                        pci_ch->desc[i].prefetchable = 0;
 
    }
 
    else
 
    {
 
                        pci_ch->desc[i].type         = 0;       
 
                        pci_ch->desc[i].prefetchable = (pci_ch->PCI_dev->resource[i].flags & IORESOURCE_PREFETCH) ? 1 : 0;
 
    }   
 
                
 
                DPRINTK(KERN_DEBUG "pcicc32 : address=0x%08x, size=0x%08x, type=%s, prefetch=%s\n", 
 
                           pci_ch->desc[i].base_address, pci_ch->desc[i].size, 
 
                              (pci_ch->desc[i].type) ? "io " : "mem", 
 
                                  (pci_ch->desc[i].prefetchable) ? "yes" : "no ");                        
 
 }
 
 
 
  /* --- now complete PCIConfigHeader for compatibility --- */
 
        pci_ch->subsystem_id         = pci_ch->PCI_dev->subsystem_device;
 
        pci_ch->subsystem_vendor_id  = pci_ch->PCI_dev->subsystem_vendor;
 
        DPRINTK(KERN_DEBUG "pcicc32 : irq=%d, sub-dev-ID=0x%04x, sub-ven-ID=0x%04x\n", pci_ch->PCI_dev->irq, pci_ch->subsystem_id, pci_ch->subsystem_vendor_id);
 
        
 
        /* --- next starting point ---*/
 
        from = pci_ch->PCI_dev;
 
        
 
#else
 
#error "No PCI support, please investigate CONFIG_PCI"
 
#endif  
 
 
 
  return pci_ch;
 
}
 
 
 
/* ------------------------------------------------------------------------- */
 
/* ------------------------------------------------------------------------- */