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.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;
}

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