summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.cvsignore19
-rw-r--r--.gitignore19
-rw-r--r--AUTHORS1
-rw-r--r--COPYING21
-rw-r--r--ChangeLog32
-rw-r--r--INSTALL236
-rw-r--r--Makefile.am30
-rw-r--r--NEWS0
-rw-r--r--README0
-rwxr-xr-xautogen.sh12
-rw-r--r--configure.ac70
-rw-r--r--include/pciaccess.h275
-rw-r--r--pciaccess.pc.in10
-rw-r--r--src/.cvsignore6
-rw-r--r--src/.gitignore6
-rw-r--r--src/Doxyfile1228
-rw-r--r--src/Makefile.am42
-rw-r--r--src/Makefile.foo26
-rw-r--r--src/Makefile.in523
-rw-r--r--src/common_capability.c196
-rw-r--r--src/common_device_name.c435
-rw-r--r--src/common_init.c111
-rw-r--r--src/common_interface.c345
-rw-r--r--src/common_iterator.c210
-rw-r--r--src/linux_sysfs.c493
-rw-r--r--src/pciaccess_private.h85
-rw-r--r--src/scanpci.c159
27 files changed, 4590 insertions, 0 deletions
diff --git a/.cvsignore b/.cvsignore
new file mode 100644
index 0000000..5eb8ffa
--- /dev/null
+++ b/.cvsignore
@@ -0,0 +1,19 @@
+aclocal.m4
+autom4te.cache
+config.guess
+config.h
+config.h.in
+config.log
+config.status
+config.sub
+configure
+depcomp
+pciaccess.pc
+install-sh
+libtool
+ltmain.sh
+Makefile
+Makefile.in
+missing
+mkinstalldirs
+stamp-h1
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..5eb8ffa
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,19 @@
+aclocal.m4
+autom4te.cache
+config.guess
+config.h
+config.h.in
+config.log
+config.status
+config.sub
+configure
+depcomp
+pciaccess.pc
+install-sh
+libtool
+ltmain.sh
+Makefile
+Makefile.in
+missing
+mkinstalldirs
+stamp-h1
diff --git a/AUTHORS b/AUTHORS
new file mode 100644
index 0000000..3fc0435
--- /dev/null
+++ b/AUTHORS
@@ -0,0 +1 @@
+Ian Romanick of IBM
diff --git a/COPYING b/COPYING
new file mode 100644
index 0000000..2f825cb
--- /dev/null
+++ b/COPYING
@@ -0,0 +1,21 @@
+(C) Copyright IBM Corporation 2006
+All Rights Reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to
+deal in the Software without restriction, including without limitation on
+the rights to use, copy, modify, merge, publish, distribute, sub license,
+and/or sell copies of the Software, and to permit persons to whom the
+Software is furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice (including the next
+paragraph) shall be included in all copies or substantial portions of the
+Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+IBM AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+IN THE SOFTWARE.
diff --git a/ChangeLog b/ChangeLog
new file mode 100644
index 0000000..8691ae9
--- /dev/null
+++ b/ChangeLog
@@ -0,0 +1,32 @@
+2006-03-17 Ian D. Romanick <idr@us.ibm.com>
+
+ * configure.ac, src/common_device_name.c
+ Added configure option (--with-pciids-path) to set the default
+ place to look for the pci.ids file.
+
+2006-03-16 Ian D. Romanick <idr@us.ibm.com>
+
+ * src/pcils.c, src/scanpci.c, src/Makefile.foo
+ Made pcils more like XFree86's scanpci utility than lspci. Changed
+ the name of the source file from pcils.c to scanpci.c. Eventually
+ this will be it's own project somewhere else (or it will whither and
+ die).
+
+2006-03-15 Ian D. Romanick <idr@us.ibm.com>
+
+ * First round of autotools madness.
+
+2006-02-24 Ian D. Romanick <idr@us.ibm.com>
+
+ * common_device_name.c, pciaccess.h, pcils.c:
+ Add interfaces for querying the device, vendor, subdevice, and
+ subvendor name strings from pci.ids.
+
+2006-02-20 Ian D. Romanick <idr@us.ibm.com>
+
+ * common_agp.c:
+ Removed this file. It was an old version of what became
+ common_capability.c.
+
+ * common_capability.c:
+ Fixed an issue with AGP rate detection for AGP3 devices.
diff --git a/INSTALL b/INSTALL
new file mode 100644
index 0000000..56b077d
--- /dev/null
+++ b/INSTALL
@@ -0,0 +1,236 @@
+Installation Instructions
+*************************
+
+Copyright (C) 1994, 1995, 1996, 1999, 2000, 2001, 2002, 2004, 2005 Free
+Software Foundation, Inc.
+
+This file is free documentation; the Free Software Foundation gives
+unlimited permission to copy, distribute and modify it.
+
+Basic Installation
+==================
+
+These are generic installation instructions.
+
+ The `configure' shell script attempts to guess correct values for
+various system-dependent variables used during compilation. It uses
+those values to create a `Makefile' in each directory of the package.
+It may also create one or more `.h' files containing system-dependent
+definitions. Finally, it creates a shell script `config.status' that
+you can run in the future to recreate the current configuration, and a
+file `config.log' containing compiler output (useful mainly for
+debugging `configure').
+
+ It can also use an optional file (typically called `config.cache'
+and enabled with `--cache-file=config.cache' or simply `-C') that saves
+the results of its tests to speed up reconfiguring. (Caching is
+disabled by default to prevent problems with accidental use of stale
+cache files.)
+
+ If you need to do unusual things to compile the package, please try
+to figure out how `configure' could check whether to do them, and mail
+diffs or instructions to the address given in the `README' so they can
+be considered for the next release. If you are using the cache, and at
+some point `config.cache' contains results you don't want to keep, you
+may remove or edit it.
+
+ The file `configure.ac' (or `configure.in') is used to create
+`configure' by a program called `autoconf'. You only need
+`configure.ac' if you want to change it or regenerate `configure' using
+a newer version of `autoconf'.
+
+The simplest way to compile this package is:
+
+ 1. `cd' to the directory containing the package's source code and type
+ `./configure' to configure the package for your system. If you're
+ using `csh' on an old version of System V, you might need to type
+ `sh ./configure' instead to prevent `csh' from trying to execute
+ `configure' itself.
+
+ Running `configure' takes awhile. While running, it prints some
+ messages telling which features it is checking for.
+
+ 2. Type `make' to compile the package.
+
+ 3. Optionally, type `make check' to run any self-tests that come with
+ the package.
+
+ 4. Type `make install' to install the programs and any data files and
+ documentation.
+
+ 5. You can remove the program binaries and object files from the
+ source code directory by typing `make clean'. To also remove the
+ files that `configure' created (so you can compile the package for
+ a different kind of computer), type `make distclean'. There is
+ also a `make maintainer-clean' target, but that is intended mainly
+ for the package's developers. If you use it, you may have to get
+ all sorts of other programs in order to regenerate files that came
+ with the distribution.
+
+Compilers and Options
+=====================
+
+Some systems require unusual options for compilation or linking that the
+`configure' script does not know about. Run `./configure --help' for
+details on some of the pertinent environment variables.
+
+ You can give `configure' initial values for configuration parameters
+by setting variables in the command line or in the environment. Here
+is an example:
+
+ ./configure CC=c89 CFLAGS=-O2 LIBS=-lposix
+
+ *Note Defining Variables::, for more details.
+
+Compiling For Multiple Architectures
+====================================
+
+You can compile the package for more than one kind of computer at the
+same time, by placing the object files for each architecture in their
+own directory. To do this, you must use a version of `make' that
+supports the `VPATH' variable, such as GNU `make'. `cd' to the
+directory where you want the object files and executables to go and run
+the `configure' script. `configure' automatically checks for the
+source code in the directory that `configure' is in and in `..'.
+
+ If you have to use a `make' that does not support the `VPATH'
+variable, you have to compile the package for one architecture at a
+time in the source code directory. After you have installed the
+package for one architecture, use `make distclean' before reconfiguring
+for another architecture.
+
+Installation Names
+==================
+
+By default, `make install' will install the package's files in
+`/usr/local/bin', `/usr/local/man', etc. You can specify an
+installation prefix other than `/usr/local' by giving `configure' the
+option `--prefix=PREFIX'.
+
+ You can specify separate installation prefixes for
+architecture-specific files and architecture-independent files. If you
+give `configure' the option `--exec-prefix=PREFIX', the package will
+use PREFIX as the prefix for installing programs and libraries.
+Documentation and other data files will still use the regular prefix.
+
+ In addition, if you use an unusual directory layout you can give
+options like `--bindir=DIR' to specify different values for particular
+kinds of files. Run `configure --help' for a list of the directories
+you can set and what kinds of files go in them.
+
+ If the package supports it, you can cause programs to be installed
+with an extra prefix or suffix on their names by giving `configure' the
+option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'.
+
+Optional Features
+=================
+
+Some packages pay attention to `--enable-FEATURE' options to
+`configure', where FEATURE indicates an optional part of the package.
+They may also pay attention to `--with-PACKAGE' options, where PACKAGE
+is something like `gnu-as' or `x' (for the X Window System). The
+`README' should mention any `--enable-' and `--with-' options that the
+package recognizes.
+
+ For packages that use the X Window System, `configure' can usually
+find the X include and library files automatically, but if it doesn't,
+you can use the `configure' options `--x-includes=DIR' and
+`--x-libraries=DIR' to specify their locations.
+
+Specifying the System Type
+==========================
+
+There may be some features `configure' cannot figure out automatically,
+but needs to determine by the type of machine the package will run on.
+Usually, assuming the package is built to be run on the _same_
+architectures, `configure' can figure that out, but if it prints a
+message saying it cannot guess the machine type, give it the
+`--build=TYPE' option. TYPE can either be a short name for the system
+type, such as `sun4', or a canonical name which has the form:
+
+ CPU-COMPANY-SYSTEM
+
+where SYSTEM can have one of these forms:
+
+ OS KERNEL-OS
+
+ See the file `config.sub' for the possible values of each field. If
+`config.sub' isn't included in this package, then this package doesn't
+need to know the machine type.
+
+ If you are _building_ compiler tools for cross-compiling, you should
+use the `--target=TYPE' option to select the type of system they will
+produce code for.
+
+ If you want to _use_ a cross compiler, that generates code for a
+platform different from the build platform, you should specify the
+"host" platform (i.e., that on which the generated programs will
+eventually be run) with `--host=TYPE'.
+
+Sharing Defaults
+================
+
+If you want to set default values for `configure' scripts to share, you
+can create a site shell script called `config.site' that gives default
+values for variables like `CC', `cache_file', and `prefix'.
+`configure' looks for `PREFIX/share/config.site' if it exists, then
+`PREFIX/etc/config.site' if it exists. Or, you can set the
+`CONFIG_SITE' environment variable to the location of the site script.
+A warning: not all `configure' scripts look for a site script.
+
+Defining Variables
+==================
+
+Variables not defined in a site shell script can be set in the
+environment passed to `configure'. However, some packages may run
+configure again during the build, and the customized values of these
+variables may be lost. In order to avoid this problem, you should set
+them in the `configure' command line, using `VAR=value'. For example:
+
+ ./configure CC=/usr/local2/bin/gcc
+
+causes the specified `gcc' to be used as the C compiler (unless it is
+overridden in the site shell script). Here is a another example:
+
+ /bin/bash ./configure CONFIG_SHELL=/bin/bash
+
+Here the `CONFIG_SHELL=/bin/bash' operand causes subsequent
+configuration-related scripts to be executed by `/bin/bash'.
+
+`configure' Invocation
+======================
+
+`configure' recognizes the following options to control how it operates.
+
+`--help'
+`-h'
+ Print a summary of the options to `configure', and exit.
+
+`--version'
+`-V'
+ Print the version of Autoconf used to generate the `configure'
+ script, and exit.
+
+`--cache-file=FILE'
+ Enable the cache: use and save the results of the tests in FILE,
+ traditionally `config.cache'. FILE defaults to `/dev/null' to
+ disable caching.
+
+`--config-cache'
+`-C'
+ Alias for `--cache-file=config.cache'.
+
+`--quiet'
+`--silent'
+`-q'
+ Do not print messages saying which checks are being made. To
+ suppress all normal output, redirect it to `/dev/null' (any error
+ messages will still be shown).
+
+`--srcdir=DIR'
+ Look for the package's source code in directory DIR. Usually
+ `configure' can determine that directory automatically.
+
+`configure' also accepts some other, not widely useful, options. Run
+`configure --help' for more details.
+
diff --git a/Makefile.am b/Makefile.am
new file mode 100644
index 0000000..8a112b4
--- /dev/null
+++ b/Makefile.am
@@ -0,0 +1,30 @@
+#
+# (C) Copyright IBM Corporation 2006
+# All Rights Reserved.
+#
+# Permission is hereby granted, free of charge, to any person obtaining a
+# copy of this software and associated documentation files (the "Software"),
+# to deal in the Software without restriction, including without limitation
+# on the rights to use, copy, modify, merge, publish, distribute, sub
+# license, and/or sell copies of the Software, and to permit persons to whom
+# the Software is furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice (including the next
+# paragraph) shall be included in all copies or substantial portions of the
+# Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+# IBM AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+# DEALINGS IN THE SOFTWARE.
+
+SUBDIRS = src
+
+pkgconfigdir = $(libdir)/pkgconfig
+pkgconfig_DATA = pciaccess.pc
+
+EXTRA_DIST = pciaccess.pc.in autogen.sh src/pcils.c src/Makefile.foo
+
diff --git a/NEWS b/NEWS
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/NEWS
diff --git a/README b/README
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/README
diff --git a/autogen.sh b/autogen.sh
new file mode 100755
index 0000000..904cd67
--- /dev/null
+++ b/autogen.sh
@@ -0,0 +1,12 @@
+#! /bin/sh
+
+srcdir=`dirname $0`
+test -z "$srcdir" && srcdir=.
+
+ORIGDIR=`pwd`
+cd $srcdir
+
+autoreconf -v --install || exit 1
+cd $ORIGDIR || exit $?
+
+$srcdir/configure --enable-maintainer-mode "$@"
diff --git a/configure.ac b/configure.ac
new file mode 100644
index 0000000..a0c2746
--- /dev/null
+++ b/configure.ac
@@ -0,0 +1,70 @@
+
+dnl (C) Copyright IBM Corporation 2006
+dnl All Rights Reserved.
+dnl
+dnl Permission is hereby granted, free of charge, to any person obtaining a
+dnl copy of this software and associated documentation files (the "Software"),
+dnl to deal in the Software without restriction, including without limitation
+dnl on the rights to use, copy, modify, merge, publish, distribute, sub
+dnl license, and/or sell copies of the Software, and to permit persons to whom
+dnl the Software is furnished to do so, subject to the following conditions:
+dnl
+dnl The above copyright notice and this permission notice (including the next
+dnl paragraph) shall be included in all copies or substantial portions of the
+dnl Software.
+dnl
+dnl THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+dnl IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+dnl FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+dnl IBM AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+dnl LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+dnl FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+dnl DEALINGS IN THE SOFTWARE.
+dnl
+dnl Process this file with autoconf to create configure.
+
+# AC_DEFINE_DIR macro from autoconf-archive.cryp.to
+AC_DEFUN([AC_DEFINE_DIR], [
+ prefix_NONE=
+ exec_prefix_NONE=
+ test "x$prefix" = xNONE && prefix_NONE=yes && prefix=$ac_default_prefix
+ test "x$exec_prefix" = xNONE && exec_prefix_NONE=yes && exec_prefix=$prefix
+dnl In Autoconf 2.60, ${datadir} refers to ${datarootdir}, which in turn
+dnl refers to ${prefix}. Thus we have to use `eval' twice.
+ eval ac_define_dir="\"[$]$2\""
+ eval ac_define_dir="\"$ac_define_dir\""
+ AC_SUBST($1, "$ac_define_dir")
+ AC_DEFINE_UNQUOTED($1, "$ac_define_dir", [$3])
+ test "$prefix_NONE" && prefix=NONE
+ test "$exec_prefix_NONE" && exec_prefix=NONE
+])
+
+AC_PREREQ([2.57])
+
+AC_INIT(libpciaccess, 0.2, [none yet], libpciaccess)
+AM_INIT_AUTOMAKE([dist-bzip2])
+AM_MAINTAINER_MODE
+
+AM_CONFIG_HEADER(config.h)
+
+# Check for progs
+AC_PROG_CC
+AC_PROG_LIBTOOL
+
+m4_ifdef([AS_HELP_STRING], , [m4_define([AS_HELP_STRING], m4_defn([AC_HELP_STRING]))])
+
+DEFAULT_PCIIDS_PATH=/usr/share/hwdata
+AC_ARG_WITH(pciids-path,
+ AS_HELP_STRING([--with-pciids-path=PCIIDS_PATH], [Path to pci.ids file]),
+ [PCIIDS_PATH="$withval"],
+ [PCIIDS_PATH="$DEFAULT_PCIIDS_PATH"])
+AC_DEFINE_DIR(PCIIDS_PATH, PCIIDS_PATH, [Path to pci.ids])
+
+AC_SUBST(PCIACCESS_CFLAGS)
+AC_SUBST(PCIACCESS_LIBS)
+
+XORG_RELEASE_VERSION
+
+AC_OUTPUT([Makefile
+ src/Makefile
+ pciaccess.pc])
diff --git a/include/pciaccess.h b/include/pciaccess.h
new file mode 100644
index 0000000..fec8271
--- /dev/null
+++ b/include/pciaccess.h
@@ -0,0 +1,275 @@
+/*
+ * (C) Copyright IBM Corporation 2006
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * on the rights to use, copy, modify, merge, publish, distribute, sub
+ * license, and/or sell copies of the Software, and to permit persons to whom
+ * the Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ * IBM AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+/**
+ * \file pciaccess.h
+ *
+ * \author Ian Romanick <idr@us.ibm.com>
+ */
+
+#include <inttypes.h>
+
+typedef uint64_t pciaddr_t;
+
+struct pci_device;
+struct pci_device_iterator;
+struct pci_id_match;
+
+int pci_device_read_rom( struct pci_device * dev, void * buffer );
+
+int pci_device_map_region( struct pci_device * dev, unsigned region,
+ int write_enable );
+
+int pci_device_unmap_region( struct pci_device * dev, unsigned region );
+
+int pci_device_probe( struct pci_device * dev );
+
+const struct pci_agp_info * pci_device_get_agp_info( struct pci_device * dev );
+
+int pci_system_init( void );
+
+void pci_system_cleanup( void );
+
+struct pci_device_iterator * pci_iterator_create( const char *regex );
+
+void pci_iterator_destroy( struct pci_device_iterator * iter );
+
+struct pci_device * pci_device_next( struct pci_device_iterator * iter );
+
+const char * pci_get_name( const struct pci_id_match * m );
+const char * pci_device_get_device_name( const struct pci_device * dev );
+const char * pci_device_get_subdevice_name( const struct pci_device * dev );
+const char * pci_device_get_vendor_name( const struct pci_device * dev );
+const char * pci_device_get_subvendor_name( const struct pci_device * dev );
+
+int pci_device_cfg_read ( struct pci_device * dev, void * data,
+ pciaddr_t offset, pciaddr_t size, pciaddr_t * bytes_read );
+int pci_device_cfg_read_u8 ( struct pci_device * dev, uint8_t * data,
+ pciaddr_t offset );
+int pci_device_cfg_read_u16( struct pci_device * dev, uint16_t * data,
+ pciaddr_t offset );
+int pci_device_cfg_read_u32( struct pci_device * dev, uint32_t * data,
+ pciaddr_t offset );
+
+int pci_device_cfg_write ( struct pci_device * dev, const void * data,
+ pciaddr_t offset, pciaddr_t size, pciaddr_t * bytes_written );
+int pci_device_cfg_write_u8 ( struct pci_device * dev, const uint8_t * data,
+ pciaddr_t offset );
+int pci_device_cfg_write_u16( struct pci_device * dev, const uint16_t * data,
+ pciaddr_t offset );
+int pci_device_cfg_write_u32( struct pci_device * dev, const uint32_t * data,
+ pciaddr_t offset );
+
+
+#define PCI_MATCH_ANY (~0)
+
+/**
+ */
+struct pci_id_match {
+ /**
+ * \name Device / vendor matching controls
+ *
+ * Control the search based on the device, vendor, subdevice, or subvendor
+ * IDs. Setting any of these fields to \c PCI_MATCH_ANY will cause the
+ * field to not be used in the comparison.
+ */
+ /*@{*/
+ uint32_t vendor_id;
+ uint32_t device_id;
+ uint32_t subvendor_id;
+ uint32_t subdevice_id;
+ /*@}*/
+
+
+ /**
+ * \name Device class matching controls
+ *
+ */
+ /*@{*/
+ uint32_t device_class;
+ uint32_t device_class_mask;
+ /*@}*/
+
+ intptr_t match_data;
+};
+
+
+/**
+ * BAR descriptor for a PCI device.
+ */
+struct pci_mem_region {
+ /**
+ * When the region is mapped, this is the pointer to the memory.
+ */
+ void * memory;
+
+ pciaddr_t bus_addr;
+ pciaddr_t base_addr;
+
+
+ /**
+ * Size, in bytes, of the region.
+ */
+ pciaddr_t size;
+
+
+ /**
+ * Is the region I/O ports or memory?
+ */
+ unsigned is_IO:1;
+
+ /**
+ * Is the memory region prefetchable?
+ *
+ * \note
+ * This can only be set if \c is_IO is not set.
+ */
+ unsigned is_prefetchable:1;
+
+
+ /**
+ * Is the memory at a 64-bit address?
+ *
+ * \note
+ * This can only be set if \c is_IO is not set.
+ */
+ unsigned is_64:1;
+};
+
+
+/**
+ * PCI device.
+ *
+ * Contains all of the information about a particular PCI device.
+ */
+struct pci_device {
+ /**
+ * \name Device bus identification.
+ *
+ * Complete bus identification, including domain, of the device. On
+ * platforms that do not support PCI domains (e.g., 32-bit x86 hardware),
+ * the domain will always be zero.
+ */
+ /*@{*/
+ uint16_t domain;
+ uint8_t bus;
+ uint8_t dev;
+ uint8_t func;
+ /*@}*/
+
+
+ /**
+ * \name Vendor / device ID
+ *
+ * The vendor ID, device ID, and sub-IDs for the device.
+ */
+ /*@{*/
+ uint16_t vendor_id;
+ uint16_t device_id;
+ uint16_t subvendor_id;
+ uint16_t subdevice_id;
+ /*@}*/
+
+ /**
+ * Device's class and subclass packed into a single 32-bit value.
+ */
+ uint32_t device_class;
+
+
+ /**
+ * Device revision number, as read from the configuration header.
+ */
+ uint8_t revision;
+
+
+ /**
+ * BAR descriptors for the device.
+ */
+ struct pci_mem_region regions[6];
+
+
+ /**
+ * Size, in bytes, of the device's expansion ROM.
+ */
+ pciaddr_t rom_size;
+
+
+ /**
+ * IRQ associated with the device. If there is no IRQ, this value will
+ * be -1.
+ */
+ int irq;
+
+
+ /**
+ * Storage for user data. Users of the library can store arbitrary
+ * data in this pointer. The library will not use it for any purpose.
+ * It is the user's responsability to free this memory before destroying
+ * the \c pci_device structure.
+ */
+ void * user_data;
+};
+
+
+/**
+ * Description of the AGP capability of the device.
+ *
+ * \sa pci_device_get_agp_info
+ */
+struct pci_agp_info {
+ /**
+ * Offset of the AGP registers in the devices configuration register
+ * space. This is generally used so that the offset of the AGP command
+ * register can be determined.
+ */
+ unsigned config_offset;
+
+
+ /**
+ * \name AGP major / minor version.
+ */
+ /*@{*/
+ uint8_t major_version;
+ uint8_t minor_version;
+ /*@}*/
+
+ /**
+ * Logical OR of the supported AGP rates. For example, a value of 0x07
+ * means that the device can support 1x, 2x, and 4x. A value of 0x0c
+ * means that the device can support 8x and 4x.
+ */
+ uint8_t rates;
+
+ uint8_t fast_writes:1; /**< Are fast-writes supported? */
+ uint8_t addr64:1;
+ uint8_t htrans:1;
+ uint8_t gart64:1;
+ uint8_t coherent:1;
+ uint8_t sideband:1; /**< Is side-band addressing supported? */
+ uint8_t isochronus:1;
+
+ uint8_t async_req_size;
+ uint8_t calibration_cycle_timing;
+ uint8_t max_requests;
+};
diff --git a/pciaccess.pc.in b/pciaccess.pc.in
new file mode 100644
index 0000000..706c5f7
--- /dev/null
+++ b/pciaccess.pc.in
@@ -0,0 +1,10 @@
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+libdir=@libdir@
+includedir=@includedir@
+
+Name: pciaccess
+Description: Library providing generic access to the PCI bus and devices.
+Version: @PACKAGE_VERSION@
+Cflags: -I${includedir}
+Libs: -L${libdir} -lpciaccess
diff --git a/src/.cvsignore b/src/.cvsignore
new file mode 100644
index 0000000..7a5734c
--- /dev/null
+++ b/src/.cvsignore
@@ -0,0 +1,6 @@
+.deps
+.libs
+*.lo
+libpciaccess.la
+Makefile
+Makefile.in
diff --git a/src/.gitignore b/src/.gitignore
new file mode 100644
index 0000000..7a5734c
--- /dev/null
+++ b/src/.gitignore
@@ -0,0 +1,6 @@
+.deps
+.libs
+*.lo
+libpciaccess.la
+Makefile
+Makefile.in
diff --git a/src/Doxyfile b/src/Doxyfile
new file mode 100644
index 0000000..87a4123
--- /dev/null
+++ b/src/Doxyfile
@@ -0,0 +1,1228 @@
+# Doxyfile 1.4.4
+
+# This file describes the settings to be used by the documentation system
+# doxygen (www.doxygen.org) for a project
+#
+# All text after a hash (#) is considered a comment and will be ignored
+# The format is:
+# TAG = value [value, ...]
+# For lists items can also be appended using:
+# TAG += value [value, ...]
+# Values that contain spaces should be placed between quotes (" ")
+
+#---------------------------------------------------------------------------
+# Project related configuration options
+#---------------------------------------------------------------------------
+
+# The PROJECT_NAME tag is a single word (or a sequence of words surrounded
+# by quotes) that should identify the project.
+
+PROJECT_NAME = libpciaccess
+
+# The PROJECT_NUMBER tag can be used to enter a project or revision number.
+# This could be handy for archiving the generated documentation or
+# if some version control system is used.
+
+PROJECT_NUMBER =
+
+# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute)
+# base path where the generated documentation will be put.
+# If a relative path is entered, it will be relative to the location
+# where doxygen was started. If left blank the current directory will be used.
+
+OUTPUT_DIRECTORY =
+
+# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create
+# 4096 sub-directories (in 2 levels) under the output directory of each output
+# format and will distribute the generated files over these directories.
+# Enabling this option can be useful when feeding doxygen a huge amount of
+# source files, where putting all generated files in the same directory would
+# otherwise cause performance problems for the file system.
+
+CREATE_SUBDIRS = NO
+
+# The OUTPUT_LANGUAGE tag is used to specify the language in which all
+# documentation generated by doxygen is written. Doxygen will use this
+# information to generate all constant output in the proper language.
+# The default language is English, other supported languages are:
+# Brazilian, Catalan, Chinese, Chinese-Traditional, Croatian, Czech, Danish,
+# Dutch, Finnish, French, German, Greek, Hungarian, Italian, Japanese,
+# Japanese-en (Japanese with English messages), Korean, Korean-en, Norwegian,
+# Polish, Portuguese, Romanian, Russian, Serbian, Slovak, Slovene, Spanish,
+# Swedish, and Ukrainian.
+
+OUTPUT_LANGUAGE = English
+
+# This tag can be used to specify the encoding used in the generated output.
+# The encoding is not always determined by the language that is chosen,
+# but also whether or not the output is meant for Windows or non-Windows users.
+# In case there is a difference, setting the USE_WINDOWS_ENCODING tag to YES
+# forces the Windows encoding (this is the default for the Windows binary),
+# whereas setting the tag to NO uses a Unix-style encoding (the default for
+# all platforms other than Windows).
+
+USE_WINDOWS_ENCODING = NO
+
+# If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will
+# include brief member descriptions after the members that are listed in
+# the file and class documentation (similar to JavaDoc).
+# Set to NO to disable this.
+
+BRIEF_MEMBER_DESC = YES
+
+# If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend
+# the brief description of a member or function before the detailed description.
+# Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the
+# brief descriptions will be completely suppressed.
+
+REPEAT_BRIEF = YES
+
+# This tag implements a quasi-intelligent brief description abbreviator
+# that is used to form the text in various listings. Each string
+# in this list, if found as the leading text of the brief description, will be
+# stripped from the text and the result after processing the whole list, is
+# used as the annotated text. Otherwise, the brief description is used as-is.
+# If left blank, the following values are used ("$name" is automatically
+# replaced with the name of the entity): "The $name class" "The $name widget"
+# "The $name file" "is" "provides" "specifies" "contains"
+# "represents" "a" "an" "the"
+
+ABBREVIATE_BRIEF =
+
+# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then
+# Doxygen will generate a detailed section even if there is only a brief
+# description.
+
+ALWAYS_DETAILED_SEC = NO
+
+# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all
+# inherited members of a class in the documentation of that class as if those
+# members were ordinary class members. Constructors, destructors and assignment
+# operators of the base classes will not be shown.
+
+INLINE_INHERITED_MEMB = NO
+
+# If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full
+# path before files name in the file list and in the header files. If set
+# to NO the shortest path that makes the file name unique will be used.
+
+FULL_PATH_NAMES = YES
+
+# If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag
+# can be used to strip a user-defined part of the path. Stripping is
+# only done if one of the specified strings matches the left-hand part of
+# the path. The tag can be used to show relative paths in the file list.
+# If left blank the directory from which doxygen is run is used as the
+# path to strip.
+
+STRIP_FROM_PATH =
+
+# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of
+# the path mentioned in the documentation of a class, which tells
+# the reader which header file to include in order to use a class.
+# If left blank only the name of the header file containing the class
+# definition is used. Otherwise one should specify the include paths that
+# are normally passed to the compiler using the -I flag.
+
+STRIP_FROM_INC_PATH =
+
+# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter
+# (but less readable) file names. This can be useful is your file systems
+# doesn't support long names like on DOS, Mac, or CD-ROM.
+
+SHORT_NAMES = NO
+
+# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen
+# will interpret the first line (until the first dot) of a JavaDoc-style
+# comment as the brief description. If set to NO, the JavaDoc
+# comments will behave just like the Qt-style comments (thus requiring an
+# explicit @brief command for a brief description.
+
+JAVADOC_AUTOBRIEF = NO
+
+# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen
+# treat a multi-line C++ special comment block (i.e. a block of //! or ///
+# comments) as a brief description. This used to be the default behaviour.
+# The new default is to treat a multi-line C++ comment block as a detailed
+# description. Set this tag to YES if you prefer the old behaviour instead.
+
+MULTILINE_CPP_IS_BRIEF = NO
+
+# If the DETAILS_AT_TOP tag is set to YES then Doxygen
+# will output the detailed description near the top, like JavaDoc.
+# If set to NO, the detailed description appears after the member
+# documentation.
+
+DETAILS_AT_TOP = NO
+
+# If the INHERIT_DOCS tag is set to YES (the default) then an undocumented
+# member inherits the documentation from any documented member that it
+# re-implements.
+
+INHERIT_DOCS = YES
+
+# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC
+# tag is set to YES, then doxygen will reuse the documentation of the first
+# member in the group (if any) for the other members of the group. By default
+# all members of a group must be documented explicitly.
+
+DISTRIBUTE_GROUP_DOC = NO
+
+# If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce
+# a new page for each member. If set to NO, the documentation of a member will
+# be part of the file/class/namespace that contains it.
+
+SEPARATE_MEMBER_PAGES = NO
+
+# The TAB_SIZE tag can be used to set the number of spaces in a tab.
+# Doxygen uses this value to replace tabs by spaces in code fragments.
+
+TAB_SIZE = 8
+
+# This tag can be used to specify a number of aliases that acts
+# as commands in the documentation. An alias has the form "name=value".
+# For example adding "sideeffect=\par Side Effects:\n" will allow you to
+# put the command \sideeffect (or @sideeffect) in the documentation, which
+# will result in a user-defined paragraph with heading "Side Effects:".
+# You can put \n's in the value part of an alias to insert newlines.
+
+ALIASES =
+
+# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C
+# sources only. Doxygen will then generate output that is more tailored for C.
+# For instance, some of the names that are used will be different. The list
+# of all members will be omitted, etc.
+
+OPTIMIZE_OUTPUT_FOR_C = YES
+
+# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java sources
+# only. Doxygen will then generate output that is more tailored for Java.
+# For instance, namespaces will be presented as packages, qualified scopes
+# will look different, etc.
+
+OPTIMIZE_OUTPUT_JAVA = NO
+
+# Set the SUBGROUPING tag to YES (the default) to allow class member groups of
+# the same type (for instance a group of public functions) to be put as a
+# subgroup of that type (e.g. under the Public Functions section). Set it to
+# NO to prevent subgrouping. Alternatively, this can be done per class using
+# the \nosubgrouping command.
+
+SUBGROUPING = YES
+
+#---------------------------------------------------------------------------
+# Build related configuration options
+#---------------------------------------------------------------------------
+
+# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in
+# documentation are documented, even if no documentation was available.
+# Private class members and static file members will be hidden unless
+# the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES
+
+EXTRACT_ALL = NO
+
+# If the EXTRACT_PRIVATE tag is set to YES all private members of a class
+# will be included in the documentation.
+
+EXTRACT_PRIVATE = NO
+
+# If the EXTRACT_STATIC tag is set to YES all static members of a file
+# will be included in the documentation.
+
+EXTRACT_STATIC = NO
+
+# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs)
+# defined locally in source files will be included in the documentation.
+# If set to NO only classes defined in header files are included.
+
+EXTRACT_LOCAL_CLASSES = YES
+
+# This flag is only useful for Objective-C code. When set to YES local
+# methods, which are defined in the implementation section but not in
+# the interface are included in the documentation.
+# If set to NO (the default) only methods in the interface are included.
+
+EXTRACT_LOCAL_METHODS = NO
+
+# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all
+# undocumented members of documented classes, files or namespaces.
+# If set to NO (the default) these members will be included in the
+# various overviews, but no documentation section is generated.
+# This option has no effect if EXTRACT_ALL is enabled.
+
+HIDE_UNDOC_MEMBERS = NO
+
+# If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all
+# undocumented classes that are normally visible in the class hierarchy.
+# If set to NO (the default) these classes will be included in the various
+# overviews. This option has no effect if EXTRACT_ALL is enabled.
+
+HIDE_UNDOC_CLASSES = NO
+
+# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all
+# friend (class|struct|union) declarations.
+# If set to NO (the default) these declarations will be included in the
+# documentation.
+
+HIDE_FRIEND_COMPOUNDS = NO
+
+# If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any
+# documentation blocks found inside the body of a function.
+# If set to NO (the default) these blocks will be appended to the
+# function's detailed documentation block.
+
+HIDE_IN_BODY_DOCS = NO
+
+# The INTERNAL_DOCS tag determines if documentation
+# that is typed after a \internal command is included. If the tag is set
+# to NO (the default) then the documentation will be excluded.
+# Set it to YES to include the internal documentation.
+
+INTERNAL_DOCS = NO
+
+# If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate
+# file names in lower-case letters. If set to YES upper-case letters are also
+# allowed. This is useful if you have classes or files whose names only differ
+# in case and if your file system supports case sensitive file names. Windows
+# and Mac users are advised to set this option to NO.
+
+CASE_SENSE_NAMES = YES
+
+# If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen
+# will show members with their full class and namespace scopes in the
+# documentation. If set to YES the scope will be hidden.
+
+HIDE_SCOPE_NAMES = NO
+
+# If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen
+# will put a list of the files that are included by a file in the documentation
+# of that file.
+
+SHOW_INCLUDE_FILES = YES
+
+# If the INLINE_INFO tag is set to YES (the default) then a tag [inline]
+# is inserted in the documentation for inline members.
+
+INLINE_INFO = YES
+
+# If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen
+# will sort the (detailed) documentation of file and class members
+# alphabetically by member name. If set to NO the members will appear in
+# declaration order.
+
+SORT_MEMBER_DOCS = YES
+
+# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the
+# brief documentation of file, namespace and class members alphabetically
+# by member name. If set to NO (the default) the members will appear in
+# declaration order.
+
+SORT_BRIEF_DOCS = NO
+
+# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be
+# sorted by fully-qualified names, including namespaces. If set to
+# NO (the default), the class list will be sorted only by class name,
+# not including the namespace part.
+# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES.
+# Note: This option applies only to the class list, not to the
+# alphabetical list.
+
+SORT_BY_SCOPE_NAME = NO
+
+# The GENERATE_TODOLIST tag can be used to enable (YES) or
+# disable (NO) the todo list. This list is created by putting \todo
+# commands in the documentation.
+
+GENERATE_TODOLIST = YES
+
+# The GENERATE_TESTLIST tag can be used to enable (YES) or
+# disable (NO) the test list. This list is created by putting \test
+# commands in the documentation.
+
+GENERATE_TESTLIST = YES
+
+# The GENERATE_BUGLIST tag can be used to enable (YES) or
+# disable (NO) the bug list. This list is created by putting \bug
+# commands in the documentation.
+
+GENERATE_BUGLIST = YES
+
+# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or
+# disable (NO) the deprecated list. This list is created by putting
+# \deprecated commands in the documentation.
+
+GENERATE_DEPRECATEDLIST= YES
+
+# The ENABLED_SECTIONS tag can be used to enable conditional
+# documentation sections, marked by \if sectionname ... \endif.
+
+ENABLED_SECTIONS =
+
+# The MAX_INITIALIZER_LINES tag determines the maximum number of lines
+# the initial value of a variable or define consists of for it to appear in
+# the documentation. If the initializer consists of more lines than specified
+# here it will be hidden. Use a value of 0 to hide initializers completely.
+# The appearance of the initializer of individual variables and defines in the
+# documentation can be controlled using \showinitializer or \hideinitializer
+# command in the documentation regardless of this setting.
+
+MAX_INITIALIZER_LINES = 30
+
+# Set the SHOW_USED_FILES tag to NO to disable the list of files generated
+# at the bottom of the documentation of classes and structs. If set to YES the
+# list will mention the files that were used to generate the documentation.
+
+SHOW_USED_FILES = YES
+
+# If the sources in your project are distributed over multiple directories
+# then setting the SHOW_DIRECTORIES tag to YES will show the directory hierarchy
+# in the documentation. The default is YES.
+
+SHOW_DIRECTORIES = YES
+
+# The FILE_VERSION_FILTER tag can be used to specify a program or script that
+# doxygen should invoke to get the current version for each file (typically from the
+# version control system). Doxygen will invoke the program by executing (via
+# popen()) the command <command> <input-file>, where <command> is the value of
+# the FILE_VERSION_FILTER tag, and <input-file> is the name of an input file
+# provided by doxygen. Whatever the progam writes to standard output
+# is used as the file version. See the manual for examples.
+
+FILE_VERSION_FILTER =
+
+#---------------------------------------------------------------------------
+# configuration options related to warning and progress messages
+#---------------------------------------------------------------------------
+
+# The QUIET tag can be used to turn on/off the messages that are generated
+# by doxygen. Possible values are YES and NO. If left blank NO is used.
+
+QUIET = NO
+
+# The WARNINGS tag can be used to turn on/off the warning messages that are
+# generated by doxygen. Possible values are YES and NO. If left blank
+# NO is used.
+
+WARNINGS = YES
+
+# If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings
+# for undocumented members. If EXTRACT_ALL is set to YES then this flag will
+# automatically be disabled.
+
+WARN_IF_UNDOCUMENTED = YES
+
+# If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for
+# potential errors in the documentation, such as not documenting some
+# parameters in a documented function, or documenting parameters that
+# don't exist or using markup commands wrongly.
+
+WARN_IF_DOC_ERROR = YES
+
+# This WARN_NO_PARAMDOC option can be abled to get warnings for
+# functions that are documented, but have no documentation for their parameters
+# or return value. If set to NO (the default) doxygen will only warn about
+# wrong or incomplete parameter documentation, but not about the absence of
+# documentation.
+
+WARN_NO_PARAMDOC = NO
+
+# The WARN_FORMAT tag determines the format of the warning messages that
+# doxygen can produce. The string should contain the $file, $line, and $text
+# tags, which will be replaced by the file and line number from which the
+# warning originated and the warning text. Optionally the format may contain
+# $version, which will be replaced by the version of the file (if it could
+# be obtained via FILE_VERSION_FILTER)
+
+WARN_FORMAT = "$file:$line: $text"
+
+# The WARN_LOGFILE tag can be used to specify a file to which warning
+# and error messages should be written. If left blank the output is written
+# to stderr.
+
+WARN_LOGFILE =
+
+#---------------------------------------------------------------------------
+# configuration options related to the input files
+#---------------------------------------------------------------------------
+
+# The INPUT tag can be used to specify the files and/or directories that contain
+# documented source files. You may enter file names like "myfile.cpp" or
+# directories like "/usr/src/myproject". Separate the files or directories
+# with spaces.
+
+INPUT =
+
+# If the value of the INPUT tag contains directories, you can use the
+# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp
+# and *.h) to filter out the source-files in the directories. If left
+# blank the following patterns are tested:
+# *.c *.cc *.cxx *.cpp *.c++ *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh *.hxx
+# *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm
+
+FILE_PATTERNS =
+
+# The RECURSIVE tag can be used to turn specify whether or not subdirectories
+# should be searched for input files as well. Possible values are YES and NO.
+# If left blank NO is used.
+
+RECURSIVE = NO
+
+# The EXCLUDE tag can be used to specify files and/or directories that should
+# excluded from the INPUT source files. This way you can easily exclude a
+# subdirectory from a directory tree whose root is specified with the INPUT tag.
+
+EXCLUDE =
+
+# The EXCLUDE_SYMLINKS tag can be used select whether or not files or
+# directories that are symbolic links (a Unix filesystem feature) are excluded
+# from the input.
+
+EXCLUDE_SYMLINKS = NO
+
+# If the value of the INPUT tag contains directories, you can use the
+# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude
+# certain files from those directories. Note that the wildcards are matched
+# against the file with absolute path, so to exclude all test directories
+# for example use the pattern */test/*
+
+EXCLUDE_PATTERNS =
+
+# The EXAMPLE_PATH tag can be used to specify one or more files or
+# directories that contain example code fragments that are included (see
+# the \include command).
+
+EXAMPLE_PATH =
+
+# If the value of the EXAMPLE_PATH tag contains directories, you can use the
+# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp
+# and *.h) to filter out the source-files in the directories. If left
+# blank all files are included.
+
+EXAMPLE_PATTERNS =
+
+# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be
+# searched for input files to be used with the \include or \dontinclude
+# commands irrespective of the value of the RECURSIVE tag.
+# Possible values are YES and NO. If left blank NO is used.
+
+EXAMPLE_RECURSIVE = NO
+
+# The IMAGE_PATH tag can be used to specify one or more files or
+# directories that contain image that are included in the documentation (see
+# the \image command).
+
+IMAGE_PATH =
+
+# The INPUT_FILTER tag can be used to specify a program that doxygen should
+# invoke to filter for each input file. Doxygen will invoke the filter program
+# by executing (via popen()) the command <filter> <input-file>, where <filter>
+# is the value of the INPUT_FILTER tag, and <input-file> is the name of an
+# input file. Doxygen will then use the output that the filter program writes
+# to standard output. If FILTER_PATTERNS is specified, this tag will be
+# ignored.
+
+INPUT_FILTER =
+
+# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern
+# basis. Doxygen will compare the file name with each pattern and apply the
+# filter if there is a match. The filters are a list of the form:
+# pattern=filter (like *.cpp=my_cpp_filter). See INPUT_FILTER for further
+# info on how filters are used. If FILTER_PATTERNS is empty, INPUT_FILTER
+# is applied to all files.
+
+FILTER_PATTERNS =
+
+# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using
+# INPUT_FILTER) will be used to filter the input files when producing source
+# files to browse (i.e. when SOURCE_BROWSER is set to YES).
+
+FILTER_SOURCE_FILES = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to source browsing
+#---------------------------------------------------------------------------
+
+# If the SOURCE_BROWSER tag is set to YES then a list of source files will
+# be generated. Documented entities will be cross-referenced with these sources.
+# Note: To get rid of all source code in the generated output, make sure also
+# VERBATIM_HEADERS is set to NO.
+
+SOURCE_BROWSER = NO
+
+# Setting the INLINE_SOURCES tag to YES will include the body
+# of functions and classes directly in the documentation.
+
+INLINE_SOURCES = NO
+
+# Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct
+# doxygen to hide any special comment blocks from generated source code
+# fragments. Normal C and C++ comments will always remain visible.
+
+STRIP_CODE_COMMENTS = YES
+
+# If the REFERENCED_BY_RELATION tag is set to YES (the default)
+# then for each documented function all documented
+# functions referencing it will be listed.
+
+REFERENCED_BY_RELATION = YES
+
+# If the REFERENCES_RELATION tag is set to YES (the default)
+# then for each documented function all documented entities
+# called/used by that function will be listed.
+
+REFERENCES_RELATION = YES
+
+# If the USE_HTAGS tag is set to YES then the references to source code
+# will point to the HTML generated by the htags(1) tool instead of doxygen
+# built-in source browser. The htags tool is part of GNU's global source
+# tagging system (see http://www.gnu.org/software/global/global.html). You
+# will need version 4.8.6 or higher.
+
+USE_HTAGS = NO
+
+# If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen
+# will generate a verbatim copy of the header file for each class for
+# which an include is specified. Set to NO to disable this.
+
+VERBATIM_HEADERS = YES
+
+#---------------------------------------------------------------------------
+# configuration options related to the alphabetical class index
+#---------------------------------------------------------------------------
+
+# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index
+# of all compounds will be generated. Enable this if the project
+# contains a lot of classes, structs, unions or interfaces.
+
+ALPHABETICAL_INDEX = NO
+
+# If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then
+# the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns
+# in which this list will be split (can be a number in the range [1..20])
+
+COLS_IN_ALPHA_INDEX = 5
+
+# In case all classes in a project start with a common prefix, all
+# classes will be put under the same header in the alphabetical index.
+# The IGNORE_PREFIX tag can be used to specify one or more prefixes that
+# should be ignored while generating the index headers.
+
+IGNORE_PREFIX =
+
+#---------------------------------------------------------------------------
+# configuration options related to the HTML output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_HTML tag is set to YES (the default) Doxygen will
+# generate HTML output.
+
+GENERATE_HTML = YES
+
+# The HTML_OUTPUT tag is used to specify where the HTML docs will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `html' will be used as the default path.
+
+HTML_OUTPUT = html
+
+# The HTML_FILE_EXTENSION tag can be used to specify the file extension for
+# each generated HTML page (for example: .htm,.php,.asp). If it is left blank
+# doxygen will generate files with .html extension.
+
+HTML_FILE_EXTENSION = .html
+
+# The HTML_HEADER tag can be used to specify a personal HTML header for
+# each generated HTML page. If it is left blank doxygen will generate a
+# standard header.
+
+HTML_HEADER =
+
+# The HTML_FOOTER tag can be used to specify a personal HTML footer for
+# each generated HTML page. If it is left blank doxygen will generate a
+# standard footer.
+
+HTML_FOOTER =
+
+# The HTML_STYLESHEET tag can be used to specify a user-defined cascading
+# style sheet that is used by each HTML page. It can be used to
+# fine-tune the look of the HTML output. If the tag is left blank doxygen
+# will generate a default style sheet. Note that doxygen will try to copy
+# the style sheet file to the HTML output directory, so don't put your own
+# stylesheet in the HTML output directory as well, or it will be erased!
+
+HTML_STYLESHEET =
+
+# If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes,
+# files or namespaces will be aligned in HTML using tables. If set to
+# NO a bullet list will be used.
+
+HTML_ALIGN_MEMBERS = YES
+
+# If the GENERATE_HTMLHELP tag is set to YES, additional index files
+# will be generated that can be used as input for tools like the
+# Microsoft HTML help workshop to generate a compressed HTML help file (.chm)
+# of the generated HTML documentation.
+
+GENERATE_HTMLHELP = NO
+
+# If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can
+# be used to specify the file name of the resulting .chm file. You
+# can add a path in front of the file if the result should not be
+# written to the html output directory.
+
+CHM_FILE =
+
+# If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can
+# be used to specify the location (absolute path including file name) of
+# the HTML help compiler (hhc.exe). If non-empty doxygen will try to run
+# the HTML help compiler on the generated index.hhp.
+
+HHC_LOCATION =
+
+# If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag
+# controls if a separate .chi index file is generated (YES) or that
+# it should be included in the master .chm file (NO).
+
+GENERATE_CHI = NO
+
+# If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag
+# controls whether a binary table of contents is generated (YES) or a
+# normal table of contents (NO) in the .chm file.
+
+BINARY_TOC = NO
+
+# The TOC_EXPAND flag can be set to YES to add extra items for group members
+# to the contents of the HTML help documentation and to the tree view.
+
+TOC_EXPAND = NO
+
+# The DISABLE_INDEX tag can be used to turn on/off the condensed index at
+# top of each HTML page. The value NO (the default) enables the index and
+# the value YES disables it.
+
+DISABLE_INDEX = NO
+
+# This tag can be used to set the number of enum values (range [1..20])
+# that doxygen will group on one line in the generated HTML documentation.
+
+ENUM_VALUES_PER_LINE = 4
+
+# If the GENERATE_TREEVIEW tag is set to YES, a side panel will be
+# generated containing a tree-like index structure (just like the one that
+# is generated for HTML Help). For this to work a browser that supports
+# JavaScript, DHTML, CSS and frames is required (for instance Mozilla 1.0+,
+# Netscape 6.0+, Internet explorer 5.0+, or Konqueror). Windows users are
+# probably better off using the HTML help feature.
+
+GENERATE_TREEVIEW = NO
+
+# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be
+# used to set the initial width (in pixels) of the frame in which the tree
+# is shown.
+
+TREEVIEW_WIDTH = 250
+
+#---------------------------------------------------------------------------
+# configuration options related to the LaTeX output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_LATEX tag is set to YES (the default) Doxygen will
+# generate Latex output.
+
+GENERATE_LATEX = YES
+
+# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `latex' will be used as the default path.
+
+LATEX_OUTPUT = latex
+
+# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be
+# invoked. If left blank `latex' will be used as the default command name.
+
+LATEX_CMD_NAME = latex
+
+# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to
+# generate index for LaTeX. If left blank `makeindex' will be used as the
+# default command name.
+
+MAKEINDEX_CMD_NAME = makeindex
+
+# If the COMPACT_LATEX tag is set to YES Doxygen generates more compact
+# LaTeX documents. This may be useful for small projects and may help to
+# save some trees in general.
+
+COMPACT_LATEX = NO
+
+# The PAPER_TYPE tag can be used to set the paper type that is used
+# by the printer. Possible values are: a4, a4wide, letter, legal and
+# executive. If left blank a4wide will be used.
+
+PAPER_TYPE = a4wide
+
+# The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX
+# packages that should be included in the LaTeX output.
+
+EXTRA_PACKAGES =
+
+# The LATEX_HEADER tag can be used to specify a personal LaTeX header for
+# the generated latex document. The header should contain everything until
+# the first chapter. If it is left blank doxygen will generate a
+# standard header. Notice: only use this tag if you know what you are doing!
+
+LATEX_HEADER =
+
+# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated
+# is prepared for conversion to pdf (using ps2pdf). The pdf file will
+# contain links (just like the HTML output) instead of page references
+# This makes the output suitable for online browsing using a pdf viewer.
+
+PDF_HYPERLINKS = NO
+
+# If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of
+# plain latex in the generated Makefile. Set this option to YES to get a
+# higher quality PDF documentation.
+
+USE_PDFLATEX = NO
+
+# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode.
+# command to the generated LaTeX files. This will instruct LaTeX to keep
+# running if errors occur, instead of asking the user for help.
+# This option is also used when generating formulas in HTML.
+
+LATEX_BATCHMODE = NO
+
+# If LATEX_HIDE_INDICES is set to YES then doxygen will not
+# include the index chapters (such as File Index, Compound Index, etc.)
+# in the output.
+
+LATEX_HIDE_INDICES = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the RTF output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output
+# The RTF output is optimized for Word 97 and may not look very pretty with
+# other RTF readers or editors.
+
+GENERATE_RTF = NO
+
+# The RTF_OUTPUT tag is used to specify where the RTF docs will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `rtf' will be used as the default path.
+
+RTF_OUTPUT = rtf
+
+# If the COMPACT_RTF tag is set to YES Doxygen generates more compact
+# RTF documents. This may be useful for small projects and may help to
+# save some trees in general.
+
+COMPACT_RTF = NO
+
+# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated
+# will contain hyperlink fields. The RTF file will
+# contain links (just like the HTML output) instead of page references.
+# This makes the output suitable for online browsing using WORD or other
+# programs which support those fields.
+# Note: wordpad (write) and others do not support links.
+
+RTF_HYPERLINKS = NO
+
+# Load stylesheet definitions from file. Syntax is similar to doxygen's
+# config file, i.e. a series of assignments. You only have to provide
+# replacements, missing definitions are set to their default value.
+
+RTF_STYLESHEET_FILE =
+
+# Set optional variables used in the generation of an rtf document.
+# Syntax is similar to doxygen's config file.
+
+RTF_EXTENSIONS_FILE =
+
+#---------------------------------------------------------------------------
+# configuration options related to the man page output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_MAN tag is set to YES (the default) Doxygen will
+# generate man pages
+
+GENERATE_MAN = NO
+
+# The MAN_OUTPUT tag is used to specify where the man pages will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `man' will be used as the default path.
+
+MAN_OUTPUT = man
+
+# The MAN_EXTENSION tag determines the extension that is added to
+# the generated man pages (default is the subroutine's section .3)
+
+MAN_EXTENSION = .3
+
+# If the MAN_LINKS tag is set to YES and Doxygen generates man output,
+# then it will generate one additional man file for each entity
+# documented in the real man page(s). These additional files
+# only source the real man page, but without them the man command
+# would be unable to find the correct page. The default is NO.
+
+MAN_LINKS = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the XML output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_XML tag is set to YES Doxygen will
+# generate an XML file that captures the structure of
+# the code including all documentation.
+
+GENERATE_XML = NO
+
+# The XML_OUTPUT tag is used to specify where the XML pages will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `xml' will be used as the default path.
+
+XML_OUTPUT = xml
+
+# The XML_SCHEMA tag can be used to specify an XML schema,
+# which can be used by a validating XML parser to check the
+# syntax of the XML files.
+
+XML_SCHEMA =
+
+# The XML_DTD tag can be used to specify an XML DTD,
+# which can be used by a validating XML parser to check the
+# syntax of the XML files.
+
+XML_DTD =
+
+# If the XML_PROGRAMLISTING tag is set to YES Doxygen will
+# dump the program listings (including syntax highlighting
+# and cross-referencing information) to the XML output. Note that
+# enabling this will significantly increase the size of the XML output.
+
+XML_PROGRAMLISTING = YES
+
+#---------------------------------------------------------------------------
+# configuration options for the AutoGen Definitions output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will
+# generate an AutoGen Definitions (see autogen.sf.net) file
+# that captures the structure of the code including all
+# documentation. Note that this feature is still experimental
+# and incomplete at the moment.
+
+GENERATE_AUTOGEN_DEF = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the Perl module output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_PERLMOD tag is set to YES Doxygen will
+# generate a Perl module file that captures the structure of
+# the code including all documentation. Note that this
+# feature is still experimental and incomplete at the
+# moment.
+
+GENERATE_PERLMOD = NO
+
+# If the PERLMOD_LATEX tag is set to YES Doxygen will generate
+# the necessary Makefile rules, Perl scripts and LaTeX code to be able
+# to generate PDF and DVI output from the Perl module output.
+
+PERLMOD_LATEX = NO
+
+# If the PERLMOD_PRETTY tag is set to YES the Perl module output will be
+# nicely formatted so it can be parsed by a human reader. This is useful
+# if you want to understand what is going on. On the other hand, if this
+# tag is set to NO the size of the Perl module output will be much smaller
+# and Perl will parse it just the same.
+
+PERLMOD_PRETTY = YES
+
+# The names of the make variables in the generated doxyrules.make file
+# are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX.
+# This is useful so different doxyrules.make files included by the same
+# Makefile don't overwrite each other's variables.
+
+PERLMOD_MAKEVAR_PREFIX =
+
+#---------------------------------------------------------------------------
+# Configuration options related to the preprocessor
+#---------------------------------------------------------------------------
+
+# If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will
+# evaluate all C-preprocessor directives found in the sources and include
+# files.
+
+ENABLE_PREPROCESSING = YES
+
+# If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro
+# names in the source code. If set to NO (the default) only conditional
+# compilation will be performed. Macro expansion can be done in a controlled
+# way by setting EXPAND_ONLY_PREDEF to YES.
+
+MACRO_EXPANSION = NO
+
+# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES
+# then the macro expansion is limited to the macros specified with the
+# PREDEFINED and EXPAND_AS_PREDEFINED tags.
+
+EXPAND_ONLY_PREDEF = NO
+
+# If the SEARCH_INCLUDES tag is set to YES (the default) the includes files
+# in the INCLUDE_PATH (see below) will be search if a #include is found.
+
+SEARCH_INCLUDES = YES
+
+# The INCLUDE_PATH tag can be used to specify one or more directories that
+# contain include files that are not input files but should be processed by
+# the preprocessor.
+
+INCLUDE_PATH =
+
+# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard
+# patterns (like *.h and *.hpp) to filter out the header-files in the
+# directories. If left blank, the patterns specified with FILE_PATTERNS will
+# be used.
+
+INCLUDE_FILE_PATTERNS =
+
+# The PREDEFINED tag can be used to specify one or more macro names that
+# are defined before the preprocessor is started (similar to the -D option of
+# gcc). The argument of the tag is a list of macros of the form: name
+# or name=definition (no spaces). If the definition and the = are
+# omitted =1 is assumed. To prevent a macro definition from being
+# undefined via #undef or recursively expanded use the := operator
+# instead of the = operator.
+
+PREDEFINED =
+
+# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then
+# this tag can be used to specify a list of macro names that should be expanded.
+# The macro definition that is found in the sources will be used.
+# Use the PREDEFINED tag if you want to use a different macro definition.
+
+EXPAND_AS_DEFINED =
+
+# If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then
+# doxygen's preprocessor will remove all function-like macros that are alone
+# on a line, have an all uppercase name, and do not end with a semicolon. Such
+# function macros are typically used for boiler-plate code, and will confuse
+# the parser if not removed.
+
+SKIP_FUNCTION_MACROS = YES
+
+#---------------------------------------------------------------------------
+# Configuration::additions related to external references
+#---------------------------------------------------------------------------
+
+# The TAGFILES option can be used to specify one or more tagfiles.
+# Optionally an initial location of the external documentation
+# can be added for each tagfile. The format of a tag file without
+# this location is as follows:
+# TAGFILES = file1 file2 ...
+# Adding location for the tag files is done as follows:
+# TAGFILES = file1=loc1 "file2 = loc2" ...
+# where "loc1" and "loc2" can be relative or absolute paths or
+# URLs. If a location is present for each tag, the installdox tool
+# does not have to be run to correct the links.
+# Note that each tag file must have a unique name
+# (where the name does NOT include the path)
+# If a tag file is not located in the directory in which doxygen
+# is run, you must also specify the path to the tagfile here.
+
+TAGFILES =
+
+# When a file name is specified after GENERATE_TAGFILE, doxygen will create
+# a tag file that is based on the input files it reads.
+
+GENERATE_TAGFILE =
+
+# If the ALLEXTERNALS tag is set to YES all external classes will be listed
+# in the class index. If set to NO only the inherited external classes
+# will be listed.
+
+ALLEXTERNALS = NO
+
+# If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed
+# in the modules index. If set to NO, only the current project's groups will
+# be listed.
+
+EXTERNAL_GROUPS = YES
+
+# The PERL_PATH should be the absolute path and name of the perl script
+# interpreter (i.e. the result of `which perl').
+
+PERL_PATH = /usr/bin/perl
+
+#---------------------------------------------------------------------------
+# Configuration options related to the dot tool
+#---------------------------------------------------------------------------
+
+# If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will
+# generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base
+# or super classes. Setting the tag to NO turns the diagrams off. Note that
+# this option is superseded by the HAVE_DOT option below. This is only a
+# fallback. It is recommended to install and use dot, since it yields more
+# powerful graphs.
+
+CLASS_DIAGRAMS = YES
+
+# If set to YES, the inheritance and collaboration graphs will hide
+# inheritance and usage relations if the target is undocumented
+# or is not a class.
+
+HIDE_UNDOC_RELATIONS = YES
+
+# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is
+# available from the path. This tool is part of Graphviz, a graph visualization
+# toolkit from AT&T and Lucent Bell Labs. The other options in this section
+# have no effect if this option is set to NO (the default)
+
+HAVE_DOT = NO
+
+# If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen
+# will generate a graph for each documented class showing the direct and
+# indirect inheritance relations. Setting this tag to YES will force the
+# the CLASS_DIAGRAMS tag to NO.
+
+CLASS_GRAPH = YES
+
+# If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen
+# will generate a graph for each documented class showing the direct and
+# indirect implementation dependencies (inheritance, containment, and
+# class references variables) of the class with other documented classes.
+
+COLLABORATION_GRAPH = YES
+
+# If the GROUP_GRAPHS and HAVE_DOT tags are set to YES then doxygen
+# will generate a graph for groups, showing the direct groups dependencies
+
+GROUP_GRAPHS = YES
+
+# If the UML_LOOK tag is set to YES doxygen will generate inheritance and
+# collaboration diagrams in a style similar to the OMG's Unified Modeling
+# Language.
+
+UML_LOOK = NO
+
+# If set to YES, the inheritance and collaboration graphs will show the
+# relations between templates and their instances.
+
+TEMPLATE_RELATIONS = NO
+
+# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT
+# tags are set to YES then doxygen will generate a graph for each documented
+# file showing the direct and indirect include dependencies of the file with
+# other documented files.
+
+INCLUDE_GRAPH = YES
+
+# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and
+# HAVE_DOT tags are set to YES then doxygen will generate a graph for each
+# documented header file showing the documented files that directly or
+# indirectly include this file.
+
+INCLUDED_BY_GRAPH = YES
+
+# If the CALL_GRAPH and HAVE_DOT tags are set to YES then doxygen will
+# generate a call dependency graph for every global function or class method.
+# Note that enabling this option will significantly increase the time of a run.
+# So in most cases it will be better to enable call graphs for selected
+# functions only using the \callgraph command.
+
+CALL_GRAPH = NO
+
+# If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen
+# will graphical hierarchy of all classes instead of a textual one.
+
+GRAPHICAL_HIERARCHY = YES
+
+# If the DIRECTORY_GRAPH, SHOW_DIRECTORIES and HAVE_DOT tags are set to YES
+# then doxygen will show the dependencies a directory has on other directories
+# in a graphical way. The dependency relations are determined by the #include
+# relations between the files in the directories.
+
+DIRECTORY_GRAPH = YES
+
+# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images
+# generated by dot. Possible values are png, jpg, or gif
+# If left blank png will be used.
+
+DOT_IMAGE_FORMAT = png
+
+# The tag DOT_PATH can be used to specify the path where the dot tool can be
+# found. If left blank, it is assumed the dot tool can be found in the path.
+
+DOT_PATH =
+
+# The DOTFILE_DIRS tag can be used to specify one or more directories that
+# contain dot files that are included in the documentation (see the
+# \dotfile command).
+
+DOTFILE_DIRS =
+
+# The MAX_DOT_GRAPH_WIDTH tag can be used to set the maximum allowed width
+# (in pixels) of the graphs generated by dot. If a graph becomes larger than
+# this value, doxygen will try to truncate the graph, so that it fits within
+# the specified constraint. Beware that most browsers cannot cope with very
+# large images.
+
+MAX_DOT_GRAPH_WIDTH = 1024
+
+# The MAX_DOT_GRAPH_HEIGHT tag can be used to set the maximum allows height
+# (in pixels) of the graphs generated by dot. If a graph becomes larger than
+# this value, doxygen will try to truncate the graph, so that it fits within
+# the specified constraint. Beware that most browsers cannot cope with very
+# large images.
+
+MAX_DOT_GRAPH_HEIGHT = 1024
+
+# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the
+# graphs generated by dot. A depth value of 3 means that only nodes reachable
+# from the root by following a path via at most 3 edges will be shown. Nodes
+# that lay further from the root node will be omitted. Note that setting this
+# option to 1 or 2 may greatly reduce the computation time needed for large
+# code bases. Also note that a graph may be further truncated if the graph's
+# image dimensions are not sufficient to fit the graph (see MAX_DOT_GRAPH_WIDTH
+# and MAX_DOT_GRAPH_HEIGHT). If 0 is used for the depth value (the default),
+# the graph is not depth-constrained.
+
+MAX_DOT_GRAPH_DEPTH = 0
+
+# Set the DOT_TRANSPARENT tag to YES to generate images with a transparent
+# background. This is disabled by default, which results in a white background.
+# Warning: Depending on the platform used, enabling this option may lead to
+# badly anti-aliased labels on the edges of a graph (i.e. they become hard to
+# read).
+
+DOT_TRANSPARENT = NO
+
+# Set the DOT_MULTI_TARGETS tag to YES allow dot to generate multiple output
+# files in one run (i.e. multiple -o and -T options on the command line). This
+# makes dot run faster, but since only newer versions of dot (>1.8.10)
+# support this, this feature is disabled by default.
+
+DOT_MULTI_TARGETS = NO
+
+# If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will
+# generate a legend page explaining the meaning of the various boxes and
+# arrows in the dot generated graphs.
+
+GENERATE_LEGEND = YES
+
+# If the DOT_CLEANUP tag is set to YES (the default) Doxygen will
+# remove the intermediate dot files that are used to generate
+# the various graphs.
+
+DOT_CLEANUP = YES
+
+#---------------------------------------------------------------------------
+# Configuration::additions related to the search engine
+#---------------------------------------------------------------------------
+
+# The SEARCHENGINE tag specifies whether or not a search engine should be
+# used. If set to NO the values of all tags below this one will be ignored.
+
+SEARCHENGINE = NO
diff --git a/src/Makefile.am b/src/Makefile.am
new file mode 100644
index 0000000..6bdf5ad
--- /dev/null
+++ b/src/Makefile.am
@@ -0,0 +1,42 @@
+#
+# (C) Copyright IBM Corporation 2006
+# All Rights Reserved.
+#
+# Permission is hereby granted, free of charge, to any person obtaining a
+# copy of this software and associated documentation files (the "Software"),
+# to deal in the Software without restriction, including without limitation
+# on the rights to use, copy, modify, merge, publish, distribute, sub
+# license, and/or sell copies of the Software, and to permit persons to whom
+# the Software is furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice (including the next
+# paragraph) shall be included in all copies or substantial portions of the
+# Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+# IBM AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+# DEALINGS IN THE SOFTWARE.
+
+lib_LTLIBRARIES = libpciaccess.la
+
+libpciaccess_la_SOURCES = common_iterator.c \
+ common_init.c \
+ common_interface.c \
+ common_capability.c \
+ common_device_name.c \
+ linux_sysfs.c
+
+INCLUDES = -I$(top_srcdir)/include
+
+libpciaccess_la_LIBADD = @PCIACCESS_LIBS@
+
+libpciaccess_la_LDFLAGS = -version-number 0:2:0 -no-undefined
+
+libpciaccessincludedir = $(includedir)
+libpciaccessinclude_HEADERS = \
+ $(top_srcdir)/include/pciaccess.h
+
diff --git a/src/Makefile.foo b/src/Makefile.foo
new file mode 100644
index 0000000..b577dbc
--- /dev/null
+++ b/src/Makefile.foo
@@ -0,0 +1,26 @@
+SOURCES = common_iterator.c \
+ common_init.c \
+ common_interface.c \
+ common_capability.c \
+ common_device_name.c \
+ linux_sysfs.c
+
+OBJECTS = $(SOURCES:.c=.o)
+
+CFLAGS = -ggdb3 -Wall -O0 -I$(VPATH)../include
+
+.PHONY: docs
+
+scanpci: scanpci.o
+ $(CC) $(CFLAGS) $(LDFLAGS) scanpci.o -o scanpci -L.libs -lpciaccess
+
+scanpci.o : scanpci.c ../include/pciaccess.h
+
+$(OBJECTS) : pciaccess.h pciaccess_private.h
+
+docs:
+ doxygen Doxyfile | grep Warning: ; echo
+
+clean:
+ rm -f $(OBJECTS) libpciaccess.a *~
+ rm -f scanpci scanpci.o
diff --git a/src/Makefile.in b/src/Makefile.in
new file mode 100644
index 0000000..e265207
--- /dev/null
+++ b/src/Makefile.in
@@ -0,0 +1,523 @@
+# Makefile.in generated by automake 1.9.5 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005 Free Software Foundation, Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+#
+# (C) Copyright IBM Corporation 2006
+# All Rights Reserved.
+#
+# Permission is hereby granted, free of charge, to any person obtaining a
+# copy of this software and associated documentation files (the "Software"),
+# to deal in the Software without restriction, including without limitation
+# on the rights to use, copy, modify, merge, publish, distribute, sub
+# license, and/or sell copies of the Software, and to permit persons to whom
+# the Software is furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice (including the next
+# paragraph) shall be included in all copies or substantial portions of the
+# Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+# IBM AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+# DEALINGS IN THE SOFTWARE.
+
+
+SOURCES = $(libpciaccess_la_SOURCES)
+
+srcdir = @srcdir@
+top_srcdir = @top_srcdir@
+VPATH = @srcdir@
+pkgdatadir = $(datadir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+top_builddir = ..
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+INSTALL = @INSTALL@
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+subdir = src
+DIST_COMMON = $(libpciaccessinclude_HEADERS) $(srcdir)/Makefile.am \
+ $(srcdir)/Makefile.in
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/config.h
+CONFIG_CLEAN_FILES =
+am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
+am__vpath_adj = case $$p in \
+ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
+ *) f=$$p;; \
+ esac;
+am__strip_dir = `echo $$p | sed -e 's|^.*/||'`;
+am__installdirs = "$(DESTDIR)$(libdir)" \
+ "$(DESTDIR)$(libpciaccessincludedir)"
+libLTLIBRARIES_INSTALL = $(INSTALL)
+LTLIBRARIES = $(lib_LTLIBRARIES)
+libpciaccess_la_DEPENDENCIES =
+am_libpciaccess_la_OBJECTS = common_iterator.lo common_init.lo \
+ common_interface.lo common_capability.lo common_device_name.lo \
+ linux_sysfs.lo
+libpciaccess_la_OBJECTS = $(am_libpciaccess_la_OBJECTS)
+DEFAULT_INCLUDES = -I. -I$(srcdir) -I$(top_builddir)
+depcomp = $(SHELL) $(top_srcdir)/depcomp
+am__depfiles_maybe = depfiles
+COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+LTCOMPILE = $(LIBTOOL) --tag=CC --mode=compile $(CC) $(DEFS) \
+ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \
+ $(AM_CFLAGS) $(CFLAGS)
+CCLD = $(CC)
+LINK = $(LIBTOOL) --tag=CC --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+ $(AM_LDFLAGS) $(LDFLAGS) -o $@
+SOURCES = $(libpciaccess_la_SOURCES)
+DIST_SOURCES = $(libpciaccess_la_SOURCES)
+libpciaccessincludeHEADERS_INSTALL = $(INSTALL_HEADER)
+HEADERS = $(libpciaccessinclude_HEADERS)
+ETAGS = etags
+CTAGS = ctags
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+AMDEP_FALSE = @AMDEP_FALSE@
+AMDEP_TRUE = @AMDEP_TRUE@
+AMTAR = @AMTAR@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CXX = @CXX@
+CXXCPP = @CXXCPP@
+CXXDEPMODE = @CXXDEPMODE@
+CXXFLAGS = @CXXFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+ECHO = @ECHO@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+F77 = @F77@
+FFLAGS = @FFLAGS@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+LDFLAGS = @LDFLAGS@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+MAINT = @MAINT@
+MAINTAINER_MODE_FALSE = @MAINTAINER_MODE_FALSE@
+MAINTAINER_MODE_TRUE = @MAINTAINER_MODE_TRUE@
+MAKEINFO = @MAKEINFO@
+OBJEXT = @OBJEXT@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PCIACCESS_CFLAGS = @PCIACCESS_CFLAGS@
+PCIACCESS_LIBS = @PCIACCESS_LIBS@
+RANLIB = @RANLIB@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+STRIP = @STRIP@
+VERSION = @VERSION@
+ac_ct_AR = @ac_ct_AR@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_CXX = @ac_ct_CXX@
+ac_ct_F77 = @ac_ct_F77@
+ac_ct_RANLIB = @ac_ct_RANLIB@
+ac_ct_STRIP = @ac_ct_STRIP@
+am__fastdepCC_FALSE = @am__fastdepCC_FALSE@
+am__fastdepCC_TRUE = @am__fastdepCC_TRUE@
+am__fastdepCXX_FALSE = @am__fastdepCXX_FALSE@
+am__fastdepCXX_TRUE = @am__fastdepCXX_TRUE@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+datadir = @datadir@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+lib_LTLIBRARIES = libpciaccess.la
+libpciaccess_la_SOURCES = common_iterator.c \
+ common_init.c \
+ common_interface.c \
+ common_capability.c \
+ common_device_name.c \
+ linux_sysfs.c
+
+INCLUDES = -I$(top_srcdir)/include
+libpciaccess_la_LIBADD = @PCIACCESS_LIBS@
+libpciaccess_la_LDFLAGS = -version-number 0:2:0 -no-undefined
+libpciaccessincludedir = $(includedir)
+libpciaccessinclude_HEADERS = \
+ $(top_srcdir)/include/pciaccess.h
+
+all: all-am
+
+.SUFFIXES:
+.SUFFIXES: .c .lo .o .obj
+$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps)
+ @for dep in $?; do \
+ case '$(am__configure_deps)' in \
+ *$$dep*) \
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh \
+ && exit 0; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/Makefile'; \
+ cd $(top_srcdir) && \
+ $(AUTOMAKE) --gnu src/Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ @case '$?' in \
+ *config.status*) \
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+ *) \
+ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+ esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+install-libLTLIBRARIES: $(lib_LTLIBRARIES)
+ @$(NORMAL_INSTALL)
+ test -z "$(libdir)" || $(mkdir_p) "$(DESTDIR)$(libdir)"
+ @list='$(lib_LTLIBRARIES)'; for p in $$list; do \
+ if test -f $$p; then \
+ f=$(am__strip_dir) \
+ echo " $(LIBTOOL) --mode=install $(libLTLIBRARIES_INSTALL) $(INSTALL_STRIP_FLAG) '$$p' '$(DESTDIR)$(libdir)/$$f'"; \
+ $(LIBTOOL) --mode=install $(libLTLIBRARIES_INSTALL) $(INSTALL_STRIP_FLAG) "$$p" "$(DESTDIR)$(libdir)/$$f"; \
+ else :; fi; \
+ done
+
+uninstall-libLTLIBRARIES:
+ @$(NORMAL_UNINSTALL)
+ @set -x; list='$(lib_LTLIBRARIES)'; for p in $$list; do \
+ p=$(am__strip_dir) \
+ echo " $(LIBTOOL) --mode=uninstall rm -f '$(DESTDIR)$(libdir)/$$p'"; \
+ $(LIBTOOL) --mode=uninstall rm -f "$(DESTDIR)$(libdir)/$$p"; \
+ done
+
+clean-libLTLIBRARIES:
+ -test -z "$(lib_LTLIBRARIES)" || rm -f $(lib_LTLIBRARIES)
+ @list='$(lib_LTLIBRARIES)'; for p in $$list; do \
+ dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
+ test "$$dir" != "$$p" || dir=.; \
+ echo "rm -f \"$${dir}/so_locations\""; \
+ rm -f "$${dir}/so_locations"; \
+ done
+libpciaccess.la: $(libpciaccess_la_OBJECTS) $(libpciaccess_la_DEPENDENCIES)
+ $(LINK) -rpath $(libdir) $(libpciaccess_la_LDFLAGS) $(libpciaccess_la_OBJECTS) $(libpciaccess_la_LIBADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/common_capability.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/common_device_name.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/common_init.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/common_interface.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/common_iterator.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/linux_sysfs.Plo@am__quote@
+
+.c.o:
+@am__fastdepCC_TRUE@ if $(COMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ $<; \
+@am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(COMPILE) -c $<
+
+.c.obj:
+@am__fastdepCC_TRUE@ if $(COMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ `$(CYGPATH_W) '$<'`; \
+@am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'`
+
+.c.lo:
+@am__fastdepCC_TRUE@ if $(LTCOMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ $<; \
+@am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Plo"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $<
+
+mostlyclean-libtool:
+ -rm -f *.lo
+
+clean-libtool:
+ -rm -rf .libs _libs
+
+distclean-libtool:
+ -rm -f libtool
+uninstall-info-am:
+install-libpciaccessincludeHEADERS: $(libpciaccessinclude_HEADERS)
+ @$(NORMAL_INSTALL)
+ test -z "$(libpciaccessincludedir)" || $(mkdir_p) "$(DESTDIR)$(libpciaccessincludedir)"
+ @list='$(libpciaccessinclude_HEADERS)'; for p in $$list; do \
+ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
+ f=$(am__strip_dir) \
+ echo " $(libpciaccessincludeHEADERS_INSTALL) '$$d$$p' '$(DESTDIR)$(libpciaccessincludedir)/$$f'"; \
+ $(libpciaccessincludeHEADERS_INSTALL) "$$d$$p" "$(DESTDIR)$(libpciaccessincludedir)/$$f"; \
+ done
+
+uninstall-libpciaccessincludeHEADERS:
+ @$(NORMAL_UNINSTALL)
+ @list='$(libpciaccessinclude_HEADERS)'; for p in $$list; do \
+ f=$(am__strip_dir) \
+ echo " rm -f '$(DESTDIR)$(libpciaccessincludedir)/$$f'"; \
+ rm -f "$(DESTDIR)$(libpciaccessincludedir)/$$f"; \
+ done
+
+ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) ' { files[$$0] = 1; } \
+ END { for (i in files) print i; }'`; \
+ mkid -fID $$unique
+tags: TAGS
+
+TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ tags=; \
+ here=`pwd`; \
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) ' { files[$$0] = 1; } \
+ END { for (i in files) print i; }'`; \
+ if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \
+ test -n "$$unique" || unique=$$empty_fix; \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ $$tags $$unique; \
+ fi
+ctags: CTAGS
+CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ tags=; \
+ here=`pwd`; \
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) ' { files[$$0] = 1; } \
+ END { for (i in files) print i; }'`; \
+ test -z "$(CTAGS_ARGS)$$tags$$unique" \
+ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+ $$tags $$unique
+
+GTAGS:
+ here=`$(am__cd) $(top_builddir) && pwd` \
+ && cd $(top_srcdir) \
+ && gtags -i $(GTAGS_ARGS) $$here
+
+distclean-tags:
+ -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(DISTFILES)
+ $(mkdir_p) $(distdir)/../include
+ @srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's|.|.|g'`; \
+ list='$(DISTFILES)'; for file in $$list; do \
+ case $$file in \
+ $(srcdir)/*) file=`echo "$$file" | sed "s|^$$srcdirstrip/||"`;; \
+ $(top_srcdir)/*) file=`echo "$$file" | sed "s|^$$topsrcdirstrip/|$(top_builddir)/|"`;; \
+ esac; \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test "$$dir" != "$$file" && test "$$dir" != "."; then \
+ dir="/$$dir"; \
+ $(mkdir_p) "$(distdir)$$dir"; \
+ else \
+ dir=''; \
+ fi; \
+ if test -d $$d/$$file; then \
+ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+ cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \
+ fi; \
+ cp -pR $$d/$$file $(distdir)$$dir || exit 1; \
+ else \
+ test -f $(distdir)/$$file \
+ || cp -p $$d/$$file $(distdir)/$$file \
+ || exit 1; \
+ fi; \
+ done
+check-am: all-am
+check: check-am
+all-am: Makefile $(LTLIBRARIES) $(HEADERS)
+installdirs:
+ for dir in "$(DESTDIR)$(libdir)" "$(DESTDIR)$(libpciaccessincludedir)"; do \
+ test -z "$$dir" || $(mkdir_p) "$$dir"; \
+ done
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ `test -z '$(STRIP)' || \
+ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+
+maintainer-clean-generic:
+ @echo "This command is intended for maintainers to use"
+ @echo "it deletes files that may require special tools to rebuild."
+clean: clean-am
+
+clean-am: clean-generic clean-libLTLIBRARIES clean-libtool \
+ mostlyclean-am
+
+distclean: distclean-am
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+distclean-am: clean-am distclean-compile distclean-generic \
+ distclean-libtool distclean-tags
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+info: info-am
+
+info-am:
+
+install-data-am: install-libpciaccessincludeHEADERS
+
+install-exec-am: install-libLTLIBRARIES
+
+install-info: install-info-am
+
+install-man:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-compile mostlyclean-generic \
+ mostlyclean-libtool
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am: uninstall-info-am uninstall-libLTLIBRARIES \
+ uninstall-libpciaccessincludeHEADERS
+
+.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \
+ clean-libLTLIBRARIES clean-libtool ctags distclean \
+ distclean-compile distclean-generic distclean-libtool \
+ distclean-tags distdir dvi dvi-am html html-am info info-am \
+ install install-am install-data install-data-am install-exec \
+ install-exec-am install-info install-info-am \
+ install-libLTLIBRARIES install-libpciaccessincludeHEADERS \
+ install-man install-strip installcheck installcheck-am \
+ installdirs maintainer-clean maintainer-clean-generic \
+ mostlyclean mostlyclean-compile mostlyclean-generic \
+ mostlyclean-libtool pdf pdf-am ps ps-am tags uninstall \
+ uninstall-am uninstall-info-am uninstall-libLTLIBRARIES \
+ uninstall-libpciaccessincludeHEADERS
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/src/common_capability.c b/src/common_capability.c
new file mode 100644
index 0000000..48f6ed4
--- /dev/null
+++ b/src/common_capability.c
@@ -0,0 +1,196 @@
+/*
+ * (C) Copyright IBM Corporation 2006
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * on the rights to use, copy, modify, merge, publish, distribute, sub
+ * license, and/or sell copies of the Software, and to permit persons to whom
+ * the Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ * IBM AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+/**
+ * \file common_capability.c
+ * Platform independent PCI capability related routines.
+ *
+ * In addition to including the interface glue for \c pci_device_get_agp_info,
+ * this file also contains a generic implementation of that function.
+ *
+ * \author Ian Romanick <idr@us.ibm.com>
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <errno.h>
+
+#include "pciaccess.h"
+#include "pciaccess_private.h"
+
+/**
+ * Generic implementation of \c pci_system_methods::fill_capabilities.
+ *
+ * \param dev Device whose capability information is to be processed.
+ *
+ * \return
+ * Zero on success or an errno value on failure.
+ *
+ * \todo
+ * Once more than just the AGP capability is supported, the body of each of
+ * the cases in the capability processing loop should probably be broken out
+ * into its own function.
+ *
+ * \todo
+ * Once more than just the AGP capability is supported, some care will need
+ * to be taken in partial failure cases. If, say, the first capability is
+ * correctly processed but the second fails, the function would be re-called
+ * later to try again for the second capability. This could lead to memory
+ * leaks or other quirky behavior.
+ */
+int
+pci_fill_capabilities_generic( struct pci_device * dev )
+{
+ struct pci_device_private * const dev_priv =
+ (struct pci_device_private *) dev;
+ int err;
+ uint16_t status;
+ uint8_t cap_offset;
+
+
+ err = pci_device_cfg_read_u16( dev, & status, 6 );
+ if ( err ) {
+ return err;
+ }
+
+ /* Are PCI capabilities supported by this device?
+ */
+ if ( (status & 0x0010) == 0 ) {
+ return ENOSYS;
+ }
+
+ err = pci_device_cfg_read_u8( dev, & cap_offset, 52 );
+ if ( err ) {
+ return err;
+ }
+
+
+ /* Process each of the capabilities list in the PCI header.
+ */
+ while ( cap_offset != 0 ) {
+ uint8_t cap_id;
+ uint8_t next_cap;
+
+ err = pci_device_cfg_read_u8( dev, & cap_id, cap_offset );
+ if ( err ) {
+ return err;
+ }
+
+ err = pci_device_cfg_read_u8( dev, & next_cap, cap_offset + 1 );
+ if ( err ) {
+ return err;
+ }
+
+ switch ( cap_id ) {
+ case 2: {
+ struct pci_agp_info * agp_info = calloc( 1, sizeof( struct pci_agp_info ) );
+ uint32_t agp_status;
+ uint8_t agp_ver;
+
+
+ if ( agp_info == NULL ) {
+ return ENOMEM;
+ }
+
+
+ err = pci_device_cfg_read_u8( dev, & agp_ver, cap_offset + 2 );
+ if ( err ) {
+ return err;
+ }
+
+ err = pci_device_cfg_read_u32( dev, & agp_status, cap_offset + 4 );
+ if ( err ) {
+ return err;
+ }
+
+ agp_info->config_offset = cap_offset;
+
+ agp_info->major_version = (agp_ver & 0x0f0) >> 4;
+ agp_info->minor_version = (agp_ver & 0x00f);
+
+ agp_info->rates = (agp_status & 0x07);
+
+ /* If AGP3 is supported, then the meaning of the rates values
+ * changes.
+ */
+ if ( (agp_status & 0x08) != 0 ) {
+ agp_info->rates <<= 2;
+ }
+
+ /* Some devices, notably motherboard chipsets, have the AGP3
+ * capability set and the 4x bit set. This results in an
+ * impossible 16x mode being listed as available. I'm not 100%
+ * sure this is the right solution.
+ */
+ agp_info->rates &= 0x0f;
+
+
+ agp_info->fast_writes = (agp_status & 0x0010) != 0;
+ agp_info->addr64 = (agp_status & 0x0020) != 0;
+ agp_info->htrans = (agp_status & 0x0040) == 0;
+ agp_info->gart64 = (agp_status & 0x0080) != 0;
+ agp_info->coherent = (agp_status & 0x0100) != 0;
+ agp_info->sideband = (agp_status & 0x0200) != 0;
+ agp_info->isochronus = (agp_status & 0x10000) != 0;
+
+ agp_info->async_req_size = 4 + (1 << ((agp_status & 0xe000) >> 13));
+ agp_info->calibration_cycle_timing = ((agp_status & 0x1c00) >> 10);
+ agp_info->max_requests = 1 + ((agp_status & 0xff000000) >> 24);
+
+ dev_priv->agp = agp_info;
+ break;
+ }
+
+ /* No other capabilities are currently handled.
+ */
+ default:
+ printf( "Unknown cap 0x%02x @ 0x%02x\n", cap_id, cap_offset );
+ break;
+ }
+
+ cap_offset = next_cap;
+ }
+
+ return 0;
+}
+
+
+/**
+ * Get AGP capability data for a device.
+ */
+const struct pci_agp_info *
+pci_device_get_agp_info( struct pci_device * dev )
+{
+ struct pci_device_private * dev_priv = (struct pci_device_private *) dev;
+
+ if ( dev == NULL ) {
+ return NULL;
+ }
+
+ if ( dev_priv->agp == NULL ) {
+ (void) (*pci_sys->methods->fill_capabilities)( dev );
+ }
+
+ return dev_priv->agp;
+}
diff --git a/src/common_device_name.c b/src/common_device_name.c
new file mode 100644
index 0000000..2a0d5bf
--- /dev/null
+++ b/src/common_device_name.c
@@ -0,0 +1,435 @@
+/*
+ * (C) Copyright IBM Corporation 2006
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * on the rights to use, copy, modify, merge, publish, distribute, sub
+ * license, and/or sell copies of the Software, and to permit persons to whom
+ * the Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ * IBM AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+/**
+ * \file common_device_name.c
+ * Support routines used to determine the vendor or device names associated
+ * with a particular device or vendor.
+ */
+
+#include "config.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <ctype.h>
+
+#if defined(HAVE_STRING_H)
+# include <string.h>
+#elif defined(HAVE_STRINGS_H)
+# include <strings.h>
+#endif
+
+#if defined(HAVE_INTTYPES_H)
+# include <inttypes.h>
+#elif defined(HAVE_STDINT_H)
+# include <stdint.h>
+#endif
+
+#include "pciaccess.h"
+
+#ifndef PCIIDS_PATH
+# define PCIIDS_PATH "/usr/share/hwdata"
+#endif
+
+#define DO_MATCH(a,b) (((a) == PCI_MATCH_ANY) || ((a) == (b)))
+
+/**
+ * Node for sorting vendor IDs.
+ *
+ * Each structure forms an internal node of an n-way tree. Each node selects
+ * \c pci_id_node::bits number of bits from the vendor ID. Starting from the
+ * root of the tree, a slice of the low-order bits of the vendor ID are
+ * selected and used as an index into the \c pci_id_node::children array.
+ *
+ * At the leaf nodes (i.e., the node entered when all 16 bits of the vendor ID
+ * have been used), the \c pci_id_node::children is actually an array of
+ * pointers to \c pci_id_leaf structures.
+ *
+ * \todo
+ * Determine if there is a cleaner way (in the source code) to have the
+ * \c children array change type based on whether the node is internal or
+ * a leaf.
+ *
+ * \todo
+ * Currently \c bits is always 4. Decide if this value can ever change
+ * (i.e., to pull-up levels of the n-way tree when all the children's children
+ * are full). If it can, rip it out and hard-code it to 4 everywhere.
+ */
+struct pci_id_node {
+ unsigned bits;
+ struct pci_id_node * children[16];
+};
+
+struct pci_id_leaf {
+ uint16_t vendor;
+ const char * vendor_name;
+
+ size_t num_devices;
+ struct pci_device_leaf * devices;
+};
+
+struct pci_device_leaf {
+ struct pci_id_match id;
+ const char * device_name;
+};
+
+/**
+ * Root of the PCI vendor ID search tree.
+ */
+struct pci_id_node * tree = NULL;
+
+/**
+ * Name of the file containing the PCI ID information.
+ */
+static const char pci_id_file[] = PCIIDS_PATH "/pci.ids";
+
+
+/**
+ * Get a pointer to the leaf node for a vendor ID.
+ *
+ * If the vendor ID does not exist in the tree, it is added.
+ */
+static struct pci_id_leaf *
+insert( uint16_t vendor )
+{
+ struct pci_id_node * n;
+ unsigned bits = 0;
+
+ if ( tree == NULL ) {
+ tree = calloc( 1, sizeof( struct pci_id_node ) );
+ tree->bits = 4;
+ }
+
+ n = tree;
+ while ( n != NULL ) {
+ const unsigned used_bits = n->bits;
+ const unsigned mask = (1 << used_bits) - 1;
+ const unsigned idx = (vendor & (mask << bits)) >> bits;
+
+
+ if ( bits >= 16 ) {
+ break;
+ }
+
+ bits += used_bits;
+
+ if ( n->children[ idx ] == NULL ) {
+ if ( bits < 16 ) {
+ struct pci_id_node * child =
+ calloc( 1, sizeof( struct pci_id_node ) );
+
+ child->bits = 4;
+
+ n->children[ idx ] = child;
+ }
+ else {
+ struct pci_id_leaf * leaf =
+ calloc( 1, sizeof( struct pci_id_leaf ) );
+
+ leaf->vendor = vendor;
+
+ n->children[ idx ] = (struct pci_id_node *) leaf;
+ }
+ }
+
+ n = n->children[ idx ];
+ }
+
+ return (struct pci_id_leaf *) n;
+}
+
+
+/**
+ * Populate a vendor node with all the devices associated with that vendor
+ *
+ * \param vend Vendor node that is to be filled from the pci.ids file.
+ *
+ * \todo
+ * The parsing in this function should be more rhobust. There are some error
+ * cases (i.e., a 0-tab line followed by a 2-tab line) that aren't handled
+ * correctly. I don't think there are any security problems with the code,
+ * but it's not impossible.
+ */
+static void
+populate_vendor( struct pci_id_leaf * vend, int fill_device_data )
+{
+ FILE * f = fopen( pci_id_file, "r" );
+ char buf[128];
+ unsigned vendor = PCI_MATCH_ANY;
+
+
+ while( fgets( buf, sizeof( buf ), f ) != NULL ) {
+ unsigned num_tabs;
+ char * new_line;
+ size_t length;
+
+ /* Each line either starts with zero, one, or two tabs followed by
+ * a series of 4 hex digits. Any lines not matching that are ignored.
+ */
+
+ for ( num_tabs = 0 ; num_tabs < 3 ; num_tabs++ ) {
+ if ( buf[ num_tabs ] != '\t' ) {
+ break;
+ }
+ }
+
+ if ( !isxdigit( buf[ num_tabs + 0 ] )
+ || !isxdigit( buf[ num_tabs + 1 ] )
+ || !isxdigit( buf[ num_tabs + 2 ] )
+ || !isxdigit( buf[ num_tabs + 3 ] ) ) {
+ continue;
+ }
+
+ new_line = strchr( buf, '\n' );
+ if ( new_line != NULL ) {
+ *new_line = '\0';
+ }
+
+ length = strlen( buf );
+ (void) memset( buf + length, 0, sizeof( buf ) - length );
+
+
+ if ( num_tabs == 0 ) {
+ vendor = (unsigned) strtoul( & buf[ num_tabs ], NULL, 16 );
+ if ( vend->vendor == vendor ) {
+ vend->vendor_name = strdup( & buf[ num_tabs + 6 ] );
+
+ /* If we're not going to fill in all of the device data as
+ * well, then bail out now. We have all the information that
+ * we need.
+ */
+ if ( ! fill_device_data ) {
+ break;
+ }
+ }
+ }
+ else if ( vendor == vend->vendor ) {
+ struct pci_device_leaf * d;
+ struct pci_device_leaf * dev;
+ struct pci_device_leaf * last_dev;
+
+
+
+ d = realloc( vend->devices, (vend->num_devices + 1)
+ * sizeof( struct pci_device_leaf ) );
+ if ( d == NULL ) {
+ return;
+ }
+
+ last_dev = & d[ vend->num_devices - 1 ];
+ dev = & d[ vend->num_devices ];
+ vend->num_devices++;
+ vend->devices = d;
+
+ if ( num_tabs == 1 ) {
+ dev->id.vendor_id = vend->vendor;
+ dev->id.device_id = (unsigned) strtoul( & buf[ num_tabs ],
+ NULL, 16 );
+ dev->id.subvendor_id = PCI_MATCH_ANY;
+ dev->id.subdevice_id = PCI_MATCH_ANY;
+
+ dev->id.device_class = 0;
+ dev->id.device_class_mask = 0;
+ dev->id.match_data = 0;
+
+ dev->device_name = strdup( & buf[ num_tabs + 6 ] );
+ }
+ else {
+ dev->id = last_dev->id;
+
+ dev->id.subvendor_id= (unsigned) strtoul( & buf[ num_tabs ],
+ NULL, 16 );
+ dev->id.subdevice_id = (unsigned) strtoul( & buf[ num_tabs + 5 ],
+ NULL, 16 );
+ dev->device_name = strdup( & buf[ num_tabs + 5 + 6 ] );
+ }
+ }
+ }
+
+ fclose( f );
+}
+
+
+static const char *
+find_device_name( const struct pci_id_match * m )
+{
+ struct pci_id_leaf * vend;
+ unsigned i;
+
+
+ if ( m->vendor_id == PCI_MATCH_ANY ) {
+ return NULL;
+ }
+
+
+ vend = insert( m->vendor_id );
+ if ( vend == NULL ) {
+ return NULL;
+ }
+
+ if ( vend->num_devices == 0 ) {
+ populate_vendor( vend, 1 );
+ }
+
+
+ for ( i = 0 ; i < vend->num_devices ; i++ ) {
+ struct pci_device_leaf * d = & vend->devices[ i ];
+
+ if ( DO_MATCH( m->vendor_id, d->id.vendor_id )
+ && DO_MATCH( m->device_id, d->id.device_id )
+ && DO_MATCH( m->subvendor_id, d->id.subvendor_id )
+ && DO_MATCH( m->subdevice_id, d->id.subdevice_id ) ) {
+ return d->device_name;
+ }
+ }
+
+ return NULL;
+}
+
+
+static const char *
+find_vendor_name( const struct pci_id_match * m )
+{
+ struct pci_id_leaf * vend;
+
+
+ if ( m->vendor_id == PCI_MATCH_ANY ) {
+ return NULL;
+ }
+
+
+ vend = insert( m->vendor_id );
+ if ( vend == NULL ) {
+ return NULL;
+ }
+
+ if ( vend->vendor_name == NULL ) {
+ populate_vendor( vend, 0 );
+ }
+
+
+ return vend->vendor_name;
+}
+
+
+/**
+ * Get a name based on an arbitrary PCI search structure.
+ */
+const char *
+pci_get_name( const struct pci_id_match * m )
+{
+ return find_device_name( m );
+}
+
+
+/**
+ * Get the name associated with the device's primary device ID.
+ */
+const char *
+pci_device_get_device_name( const struct pci_device * dev )
+{
+ struct pci_id_match m;
+
+
+ m.vendor_id = dev->vendor_id;
+ m.device_id = dev->device_id;
+ m.subvendor_id = PCI_MATCH_ANY;
+ m.subdevice_id = PCI_MATCH_ANY;
+ m.device_class = 0;
+ m.device_class_mask = 0;
+ m.match_data = 0;
+
+ return find_device_name( & m );
+}
+
+
+/**
+ * Get the name associated with the device's subdevice ID.
+ */
+const char *
+pci_device_get_subdevice_name( const struct pci_device * dev )
+{
+ struct pci_id_match m;
+
+
+ if ( (dev->subvendor_id == 0) || (dev->subdevice_id == 0) ) {
+ return NULL;
+ }
+
+ m.vendor_id = dev->vendor_id;
+ m.device_id = dev->device_id;
+ m.subvendor_id = dev->subvendor_id;
+ m.subdevice_id = dev->subdevice_id;
+ m.device_class = 0;
+ m.device_class_mask = 0;
+ m.match_data = 0;
+
+ return find_device_name( & m );
+}
+
+
+/**
+ * Get the name associated with the device's primary vendor ID.
+ */
+const char *
+pci_device_get_vendor_name( const struct pci_device * dev )
+{
+ struct pci_id_match m;
+
+
+ m.vendor_id = dev->vendor_id;
+ m.device_id = PCI_MATCH_ANY;
+ m.subvendor_id = PCI_MATCH_ANY;
+ m.subdevice_id = PCI_MATCH_ANY;
+ m.device_class = 0;
+ m.device_class_mask = 0;
+ m.match_data = 0;
+
+ return find_vendor_name( & m );
+}
+
+
+/**
+ * Get the name associated with the device's subvendor ID.
+ */
+const char *
+pci_device_get_subvendor_name( const struct pci_device * dev )
+{
+ struct pci_id_match m;
+
+
+ if ( dev->subvendor_id == 0 ) {
+ return NULL;
+ }
+
+
+ m.vendor_id = dev->subvendor_id;
+ m.device_id = PCI_MATCH_ANY;
+ m.subvendor_id = PCI_MATCH_ANY;
+ m.subdevice_id = PCI_MATCH_ANY;
+ m.device_class = 0;
+ m.device_class_mask = 0;
+ m.match_data = 0;
+
+ return find_vendor_name( & m );
+}
diff --git a/src/common_init.c b/src/common_init.c
new file mode 100644
index 0000000..cabda5e
--- /dev/null
+++ b/src/common_init.c
@@ -0,0 +1,111 @@
+/*
+ * (C) Copyright IBM Corporation 2006
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * on the rights to use, copy, modify, merge, publish, distribute, sub
+ * license, and/or sell copies of the Software, and to permit persons to whom
+ * the Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ * IBM AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+/**
+ * \file common_init.c
+ * Platform independent routines for initializing access to the PCI system.
+ *
+ * \author Ian Romanick <idr@us.ibm.com>
+ */
+
+#include <stdlib.h>
+#include <errno.h>
+
+#include "pciaccess.h"
+#include "pciaccess_private.h"
+
+extern int pci_system_linux_sysfs_create( void );
+
+struct pci_system * pci_sys;
+
+/**
+ * Initialize the PCI subsystem for access.
+ *
+ * \return
+ * Zero on success or an errno value on failure. In particular, if no
+ * platform-specific initializers are available, \c ENOSYS will be returned.
+ *
+ * \sa pci_system_cleanup
+ */
+
+int
+pci_system_init( void )
+{
+ int err = ENOSYS;
+
+#ifdef linux
+ err = pci_system_linux_sysfs_create();
+#endif
+
+ return err;
+}
+
+
+/**
+ * Shutdown all access to the PCI subsystem.
+ *
+ * \sa pci_system_init
+ */
+void
+pci_system_cleanup( void )
+{
+ unsigned i;
+ unsigned j;
+
+
+ if ( pci_sys == NULL ) {
+ return;
+ }
+
+
+ if ( pci_sys->devices ) {
+ for ( i = 0 ; i < pci_sys->num_devices ; i++ ) {
+ for ( j = 0 ; j < 6 ; j++ ) {
+ (void) pci_device_unmap_region( & pci_sys->devices[i].base, j );
+ }
+
+ free( (char *) pci_sys->devices[i].device_string );
+ free( (char *) pci_sys->devices[i].agp );
+
+ pci_sys->devices[i].device_string = NULL;
+ pci_sys->devices[i].agp = NULL;
+
+ if ( pci_sys->methods->destroy_device != NULL ) {
+ (*pci_sys->methods->destroy_device)( & pci_sys->devices[i].base );
+ }
+ }
+
+ free( pci_sys->devices );
+ pci_sys->devices = NULL;
+ pci_sys->num_devices = 0;
+ }
+
+
+ if ( pci_sys->methods->destroy != NULL ) {
+ (*pci_sys->methods->destroy)();
+ }
+
+ free( pci_sys );
+ pci_sys = NULL;
+}
diff --git a/src/common_interface.c b/src/common_interface.c
new file mode 100644
index 0000000..811d9a1
--- /dev/null
+++ b/src/common_interface.c
@@ -0,0 +1,345 @@
+/*
+ * (C) Copyright IBM Corporation 2006
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * on the rights to use, copy, modify, merge, publish, distribute, sub
+ * license, and/or sell copies of the Software, and to permit persons to whom
+ * the Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ * IBM AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+/**
+ * \file common_interface.c
+ * Platform independent interface glue.
+ *
+ * \author Ian Romanick <idr@us.ibm.com>
+ */
+
+#include <stdlib.h>
+#include <errno.h>
+
+#include "pciaccess.h"
+#include "pciaccess_private.h"
+
+#include <byteswap.h>
+
+#if __BYTE_ORDER == __BIG_ENDIAN
+# define LETOH_16(x) bswap_16(x)
+# define HTOLE_16(x) bswap_16(x)
+# define LETOH_32(x) bswap_32(x)
+# define HTOLE_32(x) bswap_32(x)
+#else
+# define LETOH_16(x) (x)
+# define HTOLE_16(x) (x)
+# define LETOH_32(x) (x)
+# define HTOLE_32(x) (x)
+#endif
+
+/**
+ * Read a device's expansion ROM.
+ *
+ * Reads the device's expansion ROM and stores the data in the memory pointed
+ * to by \c buffer. The buffer must be at least \c pci_device::rom_size
+ * bytes.
+ *
+ * \param dev Device whose expansion ROM is to be read.
+ * \param buffer Memory in which to store the ROM.
+ *
+ * \return
+ * Zero on success or an \c errno value on failure.
+ */
+int
+pci_device_read_rom( struct pci_device * dev, void * buffer )
+{
+ if ( (dev == NULL) || (buffer == NULL) ) {
+ return EFAULT;
+ }
+
+
+ return (pci_sys->methods->read_rom)( dev, buffer );
+}
+
+
+/**
+ * Probe a PCI device to learn information about the device.
+ *
+ * Probes a PCI device to learn various information about the device. Before
+ * calling this function, the only public fields in the \c pci_device
+ * structure that have valid values are \c pci_device::domain,
+ * \c pci_device::bus, \c pci_device::dev, and \c pci_device::func.
+ *
+ * \param dev Device to be probed.
+ *
+ * \return
+ * Zero on succes or an \c errno value on failure.
+ */
+int
+pci_device_probe( struct pci_device * dev )
+{
+ if ( dev == NULL ) {
+ return EFAULT;
+ }
+
+
+ return (pci_sys->methods->probe)( dev );
+}
+
+
+/**
+ * Map the specified BAR so that it can be accessed by the CPU.
+ *
+ * Maps the specified BAR for acces by the processor. The pointer to the
+ * mapped region is stored in the \c pci_mem_region::memory pointer for the
+ * BAR.
+ *
+ * \param dev Device whose memory region is to be mapped.
+ * \param region Region, on the range [0, 5], that is to be mapped.
+ * \param write_enable Map for writing (non-zero).
+ *
+ * \return
+ * Zero on success or an \c errno value on failure.
+ *
+ * \sa pci_device_unmap_region
+ */
+int
+pci_device_map_region( struct pci_device * dev, unsigned region,
+ int write_enable )
+{
+ if ( dev == NULL ) {
+ return EFAULT;
+ }
+
+ if ( (region > 5) || (dev->regions[ region ].size == 0) ) {
+ return ENOENT;
+ }
+
+ if ( dev->regions[ region ].memory != NULL ) {
+ return 0;
+ }
+
+ return (pci_sys->methods->map)( dev, region, write_enable );
+}
+
+
+/**
+ * Unmap the specified BAR so that it can no longer be accessed by the CPU.
+ *
+ * Unmaps the specified BAR that was previously mapped via
+ * \c pci_device_map_region.
+ *
+ * \param dev Device whose memory region is to be mapped.
+ * \param region Region, on the range [0, 5], that is to be mapped.
+ *
+ * \return
+ * Zero on success or an \c errno value on failure.
+ *
+ * \sa pci_device_map_region
+ */
+int
+pci_device_unmap_region( struct pci_device * dev, unsigned region )
+{
+ if ( dev == NULL ) {
+ return EFAULT;
+ }
+
+ if ( (region > 5) || (dev->regions[ region ].size == 0) ) {
+ return ENOENT;
+ }
+
+ if ( dev->regions[ region ].memory == NULL ) {
+ return 0;
+ }
+
+ return (pci_sys->methods->unmap)( dev, region );
+}
+
+
+/**
+ * Read arbitrary bytes from device's PCI config space
+ *
+ * Reads data from the device's PCI configuration space. As with the system
+ * read command, less data may be returned, without an error, than was
+ * requested. This is particuarly the case if a non-root user tries to read
+ * beyond the first 64-bytes of configuration space.
+ *
+ * \param dev Device whose PCI configuration data is to be read.
+ * \param data Location to store the data
+ * \param offset Initial byte offset to read
+ * \param size Total number of bytes to read
+ * \param bytes_read Location to store the actual number of bytes read. This
+ * pointer may be \c NULL.
+ *
+ * \returns
+ * Zero on success or an errno value on failure.
+ *
+ * \note
+ * Data read from PCI configuartion space using this routine is \b not
+ * byte-swapped to the host's byte order. PCI configuration data is always
+ * stored in little-endian order, and that is what this routine returns.
+ */
+int
+pci_device_cfg_read( struct pci_device * dev, void * data,
+ pciaddr_t offset, pciaddr_t size,
+ pciaddr_t * bytes_read )
+{
+ pciaddr_t scratch;
+
+ if ( (dev == NULL) || (data == NULL) ) {
+ return EFAULT;
+ }
+
+ return pci_sys->methods->read( dev, data, offset, size,
+ (bytes_read == NULL)
+ ? & scratch : bytes_read );
+}
+
+
+int
+pci_device_cfg_read_u8( struct pci_device * dev, uint8_t * data,
+ pciaddr_t offset )
+{
+ pciaddr_t bytes;
+ int err = pci_device_cfg_read( dev, data, offset, 1, & bytes );
+
+ if ( (err == 0) && (bytes != 1) ) {
+ err = ENODATA;
+ }
+
+ return err;
+}
+
+
+int
+pci_device_cfg_read_u16( struct pci_device * dev, uint16_t * data,
+ pciaddr_t offset )
+{
+ pciaddr_t bytes;
+ int err = pci_device_cfg_read( dev, data, offset, 2, & bytes );
+
+ if ( (err == 0) && (bytes != 2) ) {
+ err = ENODATA;
+ }
+
+ *data = LETOH_16( *data );
+ return err;
+}
+
+
+int
+pci_device_cfg_read_u32( struct pci_device * dev, uint32_t * data,
+ pciaddr_t offset )
+{
+ pciaddr_t bytes;
+ int err = pci_device_cfg_read( dev, data, offset, 4, & bytes );
+
+ if ( (err == 0) && (bytes != 4) ) {
+ err = ENODATA;
+ }
+
+ *data = LETOH_32( *data );
+ return err;
+}
+
+
+/**
+ * Write arbitrary bytes to device's PCI config space
+ *
+ * Writess data to the device's PCI configuration space. As with the system
+ * write command, less data may be written, without an error, than was
+ * requested.
+ *
+ * \param dev Device whose PCI configuration data is to be written.
+ * \param data Location of the source data
+ * \param offset Initial byte offset to write
+ * \param size Total number of bytes to write
+ * \param bytes_read Location to store the actual number of bytes written.
+ * This pointer may be \c NULL.
+ *
+ * \returns
+ * Zero on success or an errno value on failure.
+ *
+ * \note
+ * Data written to PCI configuartion space using this routine is \b not
+ * byte-swapped from the host's byte order. PCI configuration data is always
+ * stored in little-endian order, so data written with this routine should be
+ * put in that order in advance.
+ */
+int
+pci_device_cfg_write( struct pci_device * dev, const void * data,
+ pciaddr_t offset, pciaddr_t size,
+ pciaddr_t * bytes_written )
+{
+ pciaddr_t scratch;
+
+ if ( (dev == NULL) || (data == NULL) ) {
+ return EFAULT;
+ }
+
+ return pci_sys->methods->write( dev, data, offset, size,
+ (bytes_written == NULL)
+ ? & scratch : bytes_written );
+}
+
+
+int
+pci_device_cfg_write_u8( struct pci_device * dev, const uint8_t * data,
+ pciaddr_t offset )
+{
+ pciaddr_t bytes;
+ int err = pci_device_cfg_write( dev, data, offset, 1, & bytes );
+
+ if ( (err == 0) && (bytes != 1) ) {
+ err = ENOSPC;
+ }
+
+
+ return err;
+}
+
+
+int
+pci_device_cfg_write_u16( struct pci_device * dev, const uint16_t * data,
+ pciaddr_t offset )
+{
+ pciaddr_t bytes;
+ const uint16_t temp = HTOLE_16( *data );
+ int err = pci_device_cfg_write( dev, & temp, offset, 2, & bytes );
+
+ if ( (err == 0) && (bytes != 2) ) {
+ err = ENOSPC;
+ }
+
+
+ return err;
+}
+
+
+int
+pci_device_cfg_write_u32( struct pci_device * dev, const uint32_t * data,
+ pciaddr_t offset )
+{
+ pciaddr_t bytes;
+ const uint32_t temp = HTOLE_32( *data );
+ int err = pci_device_cfg_write( dev, & temp, offset, 4, & bytes );
+
+ if ( (err == 0) && (bytes != 4) ) {
+ err = ENOSPC;
+ }
+
+
+ return err;
+}
diff --git a/src/common_iterator.c b/src/common_iterator.c
new file mode 100644
index 0000000..ffff041
--- /dev/null
+++ b/src/common_iterator.c
@@ -0,0 +1,210 @@
+/*
+ * (C) Copyright IBM Corporation 2006
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * on the rights to use, copy, modify, merge, publish, distribute, sub
+ * license, and/or sell copies of the Software, and to permit persons to whom
+ * the Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ * IBM AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+/**
+ * \file common_iterator.c
+ * Platform independent iterator support routines.
+ *
+ * \author Ian Romanick <idr@us.ibm.com>
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <regex.h>
+
+#include "pciaccess.h"
+#include "pciaccess_private.h"
+
+/**
+ * Track device iteration state
+ *
+ * \private
+ */
+struct pci_device_iterator {
+ unsigned next_index;
+ regex_t reg;
+ int no_regex;
+};
+
+
+
+/**
+ * Create an iterator based on a regular expression.
+ *
+ * The set of devices to be iterated is selected by the regular expression
+ * passed in \c regex. The expression matches against an extended PCI bus
+ * identifier string. The format of this string is
+ * "domain:bus:slot.function:vendor:device_id:subvendor:subdevice_id:class".
+ * Unlike classic X bus IDs, all values in the extened bus identifier string
+ * are in hexadecimal. To simplify the required regular expressions, all hex
+ * digits greater than 9 will be lower-case.
+ *
+ * To match all devices in domain 0, the expression "0:.+" would be used. To
+ * match all devices by ATI, the expression ".+:1002:.+". To match all devices
+ * with a class of display, a class of multimedia and a subclass of video, or
+ * a class of processor and a subclass of coprocessor, the expression
+ * ".+:(03[[:hex:]]2|0400|0b40|0001)$" would be used. Since this is a fully
+ * function regular expression, arbitrarilly complex matches can be requested.
+ *
+ * \param pci_sys Handle for the PCI subsystem.
+ * \param regex Pointer to the regular expression to match against. If
+ * \c NULL is passed, all devices will be matched.
+ *
+ * \return
+ * A pointer to a fully initialized \c pci_device_iterator structure on
+ * success, or \c NULL on failure.
+ *
+ * \sa pci_device_next, pci_iterator_destroy
+ */
+struct pci_device_iterator *
+pci_iterator_create( const char * re )
+{
+ struct pci_device_iterator * iter;
+
+ if ( pci_sys == NULL ) {
+ return NULL;
+ }
+
+ iter = malloc( sizeof( *iter ) );
+ if ( iter != NULL ) {
+ iter->next_index = 0;
+
+ /* If the caller passed a NULL or empty expression, then we don't try
+ * to compile the expression. Instead we set a flag that tells the
+ * iterator routine to iterate every device in the list.
+ */
+ if ( (re != NULL) && (strlen( re ) > 0) ) {
+ int err = regcomp( & iter->reg, re, REG_EXTENDED | REG_NOSUB );
+ if ( err != 0 ) {
+ free( iter );
+ iter = NULL;
+ }
+
+ iter->no_regex = 0;
+ }
+ else {
+ iter->no_regex = 1;
+ }
+ }
+
+ return iter;
+}
+
+
+/**
+ * Destroy an iterator previously created with \c pci_iterator_create.
+ *
+ * \param iter Iterator to be destroyed.
+ *
+ * \sa pci_device_next, pci_iterator_create
+ */
+void
+pci_iterator_destroy( struct pci_device_iterator * iter )
+{
+ if ( iter != NULL ) {
+ if ( ! iter->no_regex ) {
+ regfree( & iter->reg );
+ }
+
+ free( iter );
+ }
+}
+
+
+static void
+fill_device_string( struct pci_device_private * d )
+{
+
+ if ( d->device_string == NULL ) {
+ char * const string = malloc( 40 );
+ if ( string != NULL ) {
+ pci_device_probe( (struct pci_device *) d );
+ sprintf( string, "%04x:%02x:%02x.%u:%04x:%04x:%04x:%04x:%06x",
+ d->base.domain,
+ d->base.bus,
+ d->base.dev,
+ d->base.func,
+ d->base.vendor_id,
+ d->base.device_id,
+ d->base.subvendor_id,
+ d->base.subdevice_id,
+ d->base.device_class );
+
+ d->device_string = string;
+ }
+ }
+}
+
+
+/**
+ * Iterate to the next PCI device.
+ *
+ * \param iter Device iterator returned by \c pci_device_iterate.
+ *
+ * \return
+ * A pointer to a \c pci_device, or \c NULL when all devices have been
+ * iterated.
+ *
+ * \bug
+ * The only time this routine should be able to return \c NULL is when the
+ * end of the list is hit. However, there is a memory allocation (via
+ * \c fill_device_string) that can fail. If this allocation fails, \c NULL
+ * will be erroneously returned. What should be done here? Pre-fill the
+ * device strings in \c pci_iterator_create?
+ */
+struct pci_device *
+pci_device_next( struct pci_device_iterator * iter )
+{
+ struct pci_device_private * d = NULL;
+
+ if ( iter->no_regex ) {
+ if ( iter->next_index < pci_sys->num_devices ) {
+ d = & pci_sys->devices[ iter->next_index ];
+ iter->next_index++;
+ }
+ }
+ else {
+ while ( iter->next_index < pci_sys->num_devices ) {
+ struct pci_device_private * const temp =
+ & pci_sys->devices[ iter->next_index ];
+
+ if ( temp->device_string == NULL ) {
+ fill_device_string( temp );
+ if ( temp->device_string == NULL ) {
+ break;
+ }
+ }
+
+ iter->next_index++;
+
+ if ( regexec( & iter->reg, temp->device_string, 0, NULL, 0 ) == 0 ) {
+ d = temp;
+ break;
+ }
+ }
+ }
+
+ return (struct pci_device *) d;
+}
diff --git a/src/linux_sysfs.c b/src/linux_sysfs.c
new file mode 100644
index 0000000..d6d6b10
--- /dev/null
+++ b/src/linux_sysfs.c
@@ -0,0 +1,493 @@
+/*
+ * (C) Copyright IBM Corporation 2006
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * on the rights to use, copy, modify, merge, publish, distribute, sub
+ * license, and/or sell copies of the Software, and to permit persons to whom
+ * the Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ * IBM AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+/**
+ * \file linux_sysfs.c
+ * Access PCI subsystem using Linux's sysfs interface. This interface is
+ * available starting somewhere in the late 2.5.x kernel phase, and is the
+ * prefered method on all 2.6.x kernels.
+ *
+ * \author Ian Romanick <idr@us.ibm.com>
+ */
+
+#define _GNU_SOURCE
+
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <sys/mman.h>
+#include <dirent.h>
+#include <errno.h>
+
+#include "pciaccess.h"
+#include "pciaccess_private.h"
+
+static int pci_device_linux_sysfs_read_rom( struct pci_device * dev,
+ void * buffer );
+
+static int pci_device_linux_sysfs_probe( struct pci_device * dev );
+
+static int pci_device_linux_sysfs_map_region( struct pci_device * dev,
+ unsigned region, int write_enable );
+
+static int pci_device_linux_sysfs_unmap_region( struct pci_device * dev,
+ unsigned region );
+
+static int pci_device_linux_sysfs_read( struct pci_device * dev, void * data,
+ pciaddr_t offset, pciaddr_t size, pciaddr_t * bytes_read );
+
+static int pci_device_linux_sysfs_write( struct pci_device * dev,
+ const void * data, pciaddr_t offset, pciaddr_t size,
+ pciaddr_t * bytes_wrtten );
+
+static const struct pci_system_methods linux_sysfs_methods = {
+ .destroy = NULL,
+ .destroy_device = NULL,
+ .read_rom = pci_device_linux_sysfs_read_rom,
+ .probe = pci_device_linux_sysfs_probe,
+ .map = pci_device_linux_sysfs_map_region,
+ .unmap = pci_device_linux_sysfs_unmap_region,
+
+ .read = pci_device_linux_sysfs_read,
+ .write = pci_device_linux_sysfs_write,
+
+ .fill_capabilities = pci_fill_capabilities_generic
+};
+
+#define SYS_BUS_PCI "/sys/bus/pci/devices"
+
+
+static void populate_entries( struct pci_system * pci_sys );
+
+
+/**
+ * Attempt to access PCI subsystem using Linux's sysfs interface.
+ */
+int
+pci_system_linux_sysfs_create( void )
+{
+ int err = 0;
+ struct stat st;
+
+
+ /* If the directory "/sys/bus/pci/devices" exists, then the PCI subsystem
+ * can be accessed using this interface.
+ */
+
+ if ( stat( SYS_BUS_PCI, & st ) == 0 ) {
+ pci_sys = calloc( 1, sizeof( struct pci_system ) );
+ if ( pci_sys != NULL ) {
+ pci_sys->methods = & linux_sysfs_methods;
+ populate_entries( pci_sys );
+ }
+ else {
+ err = ENOMEM;
+ }
+ }
+ else {
+ err = errno;
+ }
+
+ return err;
+}
+
+
+/**
+ * Filter out the names "." and ".." from the scanned sysfs entries.
+ *
+ * \param d Directory entry being processed by \c scandir.
+ *
+ * \return
+ * Zero if the entry name matches either "." or "..", non-zero otherwise.
+ *
+ * \sa scandir, populate_entries
+ */
+static int
+scan_sys_pci_filter( const struct dirent * d )
+{
+ return !((strcmp( d->d_name, "." ) == 0)
+ || (strcmp( d->d_name, ".." ) == 0));
+}
+
+
+void
+populate_entries( struct pci_system * p )
+{
+ struct dirent ** devices;
+ int n;
+ int i;
+
+
+ n = scandir( SYS_BUS_PCI, & devices, scan_sys_pci_filter, alphasort );
+ if ( n > 0 ) {
+ p->num_devices = n;
+ p->devices = calloc( n, sizeof( struct pci_device_private ) );
+
+
+ for ( i = 0 ; i < n ; i++ ) {
+ unsigned dom, bus, dev, func;
+
+
+ sscanf( devices[ i ]->d_name, "%04x:%02x:%02x.%1u",
+ & dom, & bus, & dev, & func );
+
+ p->devices[ i ].base.domain = dom;
+ p->devices[ i ].base.bus = bus;
+ p->devices[ i ].base.dev = dev;
+ p->devices[ i ].base.func = func;
+ }
+ }
+}
+
+
+static int
+pci_device_linux_sysfs_probe( struct pci_device * dev )
+{
+ char name[256];
+ uint8_t config[256];
+ char resource[512];
+ int fd;
+ pciaddr_t bytes;
+ unsigned i;
+ int err;
+
+
+ err = pci_device_linux_sysfs_read( dev, config, 0, 256, & bytes );
+ if ( bytes >= 64 ) {
+ dev->vendor_id = ((uint16_t *) config)[0];
+ dev->device_id = ((uint16_t *) config)[1];
+ dev->device_class = (((uint32_t *) config)[2]) >> 8;
+ dev->revision = config[8];
+ dev->subvendor_id = ((uint16_t *) config)[22];
+ dev->subdevice_id = ((uint16_t *) config)[23];
+ dev->irq = config[60];
+
+
+ /* The PCI config registers can be used to obtain information
+ * about the memory and I/O regions for the device. However,
+ * doing so requires some tricky parsing (to correctly handle
+ * 64-bit memory regions) and requires writing to the config
+ * registers. Since we'd like to avoid having to deal with the
+ * parsing issues and non-root users can write to PCI config
+ * registers, we use a different file in the device's sysfs
+ * directory called "resource".
+ *
+ * The resource file contains all of the needed information in
+ * a format that is consistent across all platforms. Each BAR
+ * and the expansion ROM have a single line of data containing
+ * 3, 64-bit hex values: the first address in the region,
+ * the last address in the region, and the region's flags.
+ */
+ snprintf( name, 255, "%s/%04x:%02x:%02x.%1u/resource",
+ SYS_BUS_PCI,
+ dev->domain,
+ dev->bus,
+ dev->dev,
+ dev->func );
+ fd = open( name, O_RDONLY );
+ if ( fd != -1 ) {
+ char * next;
+ pciaddr_t low_addr;
+ pciaddr_t high_addr;
+ pciaddr_t flags;
+
+
+ bytes = read( fd, resource, 512 );
+ resource[511] = '\0';
+
+ close( fd );
+
+ next = resource;
+ for ( i = 0 ; i < 6 ; i++ ) {
+
+ dev->regions[i].base_addr = strtoull( next, & next, 16 );
+ high_addr = strtoull( next, & next, 16 );
+ flags = strtoull( next, & next, 16 );
+
+ if ( dev->regions[i].base_addr != 0 ) {
+ dev->regions[i].size = (high_addr
+ - dev->regions[i].base_addr) + 1;
+
+ dev->regions[i].is_IO = (flags & 0x01);
+ dev->regions[i].is_64 = (flags & 0x04);
+ dev->regions[i].is_prefetchable = (flags & 0x08);
+ }
+ }
+
+ low_addr = strtoull( next, & next, 16 );
+ high_addr = strtoull( next, & next, 16 );
+ flags = strtoull( next, & next, 16 );
+ if ( low_addr != 0 ) {
+ dev->rom_size = (high_addr - low_addr) + 1;
+ }
+ }
+ }
+
+ return err;
+}
+
+
+static int
+pci_device_linux_sysfs_read_rom( struct pci_device * dev, void * buffer )
+{
+ char name[256];
+ int fd;
+ struct stat st;
+ int err = 0;
+
+
+ snprintf( name, 255, "%s/%04x:%02x:%02x.%1u/rom",
+ SYS_BUS_PCI,
+ dev->domain,
+ dev->bus,
+ dev->dev,
+ dev->func );
+
+ fd = open( name, O_RDWR );
+ if ( fd == -1 ) {
+ return errno;
+ }
+
+
+ if ( fstat( fd, & st ) == -1 ) {
+ close( fd );
+ return errno;
+ }
+
+
+ /* This is a quirky thing on Linux. Even though the ROM and the file
+ * for the ROM in sysfs are read-only, the string "1" must be written to
+ * the file to enable the ROM. After the data has been read, "0" must be
+ * written to the file to disable the ROM.
+ */
+ write( fd, "1", 1 );
+ lseek( fd, 0, SEEK_SET );
+
+ if ( read( fd, buffer, st.st_size ) == -1 ) {
+ err = errno;
+ }
+
+ lseek( fd, 0, SEEK_SET );
+ write( fd, "0", 1 );
+
+ close( fd );
+ return err;
+}
+
+
+static int
+pci_device_linux_sysfs_read( struct pci_device * dev, void * data,
+ pciaddr_t offset, pciaddr_t size,
+ pciaddr_t * bytes_read )
+{
+ char name[256];
+ pciaddr_t temp_size = size;
+ int err = 0;
+ int fd;
+
+
+ if ( bytes_read != NULL ) {
+ *bytes_read = 0;
+ }
+
+ /* Each device has a directory under sysfs. Within that directory there
+ * is a file named "config". This file used to access the PCI config
+ * space. It is used here to obtain most of the information about the
+ * device.
+ */
+ snprintf( name, 255, "%s/%04x:%02x:%02x.%1u/config",
+ SYS_BUS_PCI,
+ dev->domain,
+ dev->bus,
+ dev->dev,
+ dev->func );
+
+ fd = open( name, O_RDONLY );
+ if ( fd == -1 ) {
+ return errno;
+ }
+
+
+ while ( temp_size > 0 ) {
+ const ssize_t bytes = pread64( fd, data, temp_size, offset );
+
+ /* If zero bytes were read, then we assume it's the end of the
+ * config file.
+ */
+ if ( bytes <= 0 ) {
+ err = errno;
+ break;
+ }
+
+ temp_size -= bytes;
+ offset += bytes;
+ data += bytes;
+ }
+
+ if ( bytes_read != NULL ) {
+ *bytes_read = size - temp_size;
+ }
+
+ close( fd );
+ return err;
+}
+
+
+static int
+pci_device_linux_sysfs_write( struct pci_device * dev, const void * data,
+ pciaddr_t offset, pciaddr_t size,
+ pciaddr_t * bytes_written )
+{
+ char name[256];
+ pciaddr_t temp_size = size;
+ int err = 0;
+ int fd;
+
+
+ if ( bytes_written != NULL ) {
+ *bytes_written = 0;
+ }
+
+ /* Each device has a directory under sysfs. Within that directory there
+ * is a file named "config". This file used to access the PCI config
+ * space. It is used here to obtain most of the information about the
+ * device.
+ */
+ snprintf( name, 255, "%s/%04x:%02x:%02x.%1u/config",
+ SYS_BUS_PCI,
+ dev->domain,
+ dev->bus,
+ dev->dev,
+ dev->func );
+
+ fd = open( name, O_WRONLY );
+ if ( fd == -1 ) {
+ return errno;
+ }
+
+
+ while ( temp_size > 0 ) {
+ const ssize_t bytes = pwrite64( fd, data, temp_size, offset );
+
+ /* If zero bytes were written, then we assume it's the end of the
+ * config file.
+ */
+ if ( bytes <= 0 ) {
+ err = errno;
+ break;
+ }
+
+ temp_size -= bytes;
+ offset += bytes;
+ data += bytes;
+ }
+
+ if ( bytes_written != NULL ) {
+ *bytes_written = size - temp_size;
+ }
+
+ close( fd );
+ return err;
+}
+
+
+/**
+ * Map a memory region for a device using the Linux sysfs interface.
+ *
+ * \param dev Device whose memory region is to be mapped.
+ * \param region Region, on the range [0, 5], that is to be mapped.
+ * \param write_enable Map for writing (non-zero).
+ *
+ * \return
+ * Zero on success or an \c errno value on failure.
+ *
+ * \sa pci_device_map_region, pci_device_linux_sysfs_unmap_region
+ *
+ * \todo
+ * Some older 2.6.x kernels don't implement the resourceN files. On those
+ * systems /dev/mem must be used. On these systems it is also possible that
+ * \c mmap64 may need to be used.
+ */
+static int
+pci_device_linux_sysfs_map_region( struct pci_device * dev, unsigned region,
+ int write_enable )
+{
+ char name[256];
+ int fd;
+ int err = 0;
+ int prot = (write_enable) ? (PROT_READ | PROT_WRITE) : PROT_READ;
+
+
+ snprintf( name, 255, "%s/%04x:%02x:%02x.%1u/resource%u",
+ SYS_BUS_PCI,
+ dev->domain,
+ dev->bus,
+ dev->dev,
+ dev->func,
+ region );
+
+ fd = open( name, (write_enable) ? O_RDWR : O_RDONLY );
+ if ( fd == -1 ) {
+ return errno;
+ }
+
+
+ dev->regions[ region ].memory = mmap( NULL, dev->regions[ region ].size,
+ prot, MAP_SHARED, fd, 0 );
+ if ( dev->regions[ region ].memory == MAP_FAILED ) {
+ err = errno;
+ dev->regions[ region ].memory = NULL;
+ }
+
+ close( fd );
+ return err;
+}
+
+
+/**
+ * Unmap the specified region using the Linux sysfs interface.
+ *
+ * \param dev Device whose memory region is to be mapped.
+ * \param region Region, on the range [0, 5], that is to be mapped.
+ *
+ * \return
+ * Zero on success or an \c errno value on failure.
+ *
+ * \sa pci_device_unmap_region, pci_device_linux_sysfs_map_region
+ *
+ * \todo
+ * Some older 2.6.x kernels don't implement the resourceN files. On those
+ * systems /dev/mem must be used. On these systems it is also possible that
+ * \c mmap64 may need to be used.
+ */
+static int
+pci_device_linux_sysfs_unmap_region( struct pci_device * dev, unsigned region )
+{
+ return munmap( dev->regions[ region ].memory,
+ dev->regions[ region ].size );
+}
diff --git a/src/pciaccess_private.h b/src/pciaccess_private.h
new file mode 100644
index 0000000..bc35f7f
--- /dev/null
+++ b/src/pciaccess_private.h
@@ -0,0 +1,85 @@
+/*
+ * (C) Copyright IBM Corporation 2006
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * on the rights to use, copy, modify, merge, publish, distribute, sub
+ * license, and/or sell copies of the Software, and to permit persons to whom
+ * the Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ * IBM AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+/**
+ * \file pciaccess_private.h
+ * Functions and datastructures that are private to the pciaccess library.
+ *
+ * \author Ian Romanick <idr@us.ibm.com>
+ */
+
+
+int pci_fill_capabilities_generic( struct pci_device * dev );
+
+struct pci_system_methods {
+ void (*destroy)( void );
+ void (*destroy_device)( struct pci_device * dev );
+ int (*read_rom)( struct pci_device * dev, void * buffer );
+ int (*probe)( struct pci_device * dev );
+ int (*map)( struct pci_device * dev, unsigned region, int write_enable );
+ int (*unmap)( struct pci_device * dev, unsigned region );
+
+ int (*read)(struct pci_device * dev, void * data, pciaddr_t offset,
+ pciaddr_t size, pciaddr_t * bytes_read );
+
+ int (*write)(struct pci_device * dev, const void * data, pciaddr_t offset,
+ pciaddr_t size, pciaddr_t * bytes_written );
+
+ int (*fill_capabilities)( struct pci_device * dev );
+};
+
+struct pci_device_private {
+ struct pci_device base;
+ const char * device_string;
+
+ /**
+ * \name PCI Capabilities
+ */
+ /*@{*/
+ const struct pci_agp_info * agp; /**< AGP capability information. */
+ /*@}*/
+};
+
+
+/**
+ * Base type for tracking PCI subsystem information.
+ */
+struct pci_system {
+ /**
+ * Platform dependent implementations of specific API routines.
+ */
+ const struct pci_system_methods * methods;
+
+ /**
+ * Number of known devices in the system.
+ */
+ size_t num_devices;
+
+ /**
+ * Array of known devices.
+ */
+ struct pci_device_private * devices;
+};
+
+extern struct pci_system * pci_sys;
diff --git a/src/scanpci.c b/src/scanpci.c
new file mode 100644
index 0000000..1c4622f
--- /dev/null
+++ b/src/scanpci.c
@@ -0,0 +1,159 @@
+/*
+ * (C) Copyright IBM Corporation 2006
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * on the rights to use, copy, modify, merge, publish, distribute, sub
+ * license, and/or sell copies of the Software, and to permit persons to whom
+ * the Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ * IBM AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+
+#include "pciaccess.h"
+
+
+void
+print_pci_device( struct pci_device * dev, int verbose )
+{
+ const char * dev_name;
+ const char * vend_name;
+
+ vend_name = pci_device_get_vendor_name( dev );
+ dev_name = pci_device_get_device_name( dev );
+ if ( dev_name == NULL ) {
+ dev_name = "Device unknown";
+ }
+
+ printf("\npci bus 0x%04x cardnum 0x%02x function 0x%02x:"
+ " vendor 0x%04x device 0x%04x\n",
+ dev->bus,
+ dev->dev,
+ dev->func,
+ dev->vendor_id,
+ dev->device_id );
+ if ( vend_name != NULL ) {
+ printf( " %s %s\n", vend_name, dev_name );
+ }
+ else {
+ printf( " %s\n", dev_name );
+ }
+
+ if ( verbose ) {
+ unsigned i;
+ uint16_t command, status;
+ uint8_t bist;
+ uint8_t header_type;
+ uint8_t latency_timer;
+ uint8_t cache_line_size;
+ uint8_t max_latency;
+ uint8_t min_grant;
+ uint8_t int_pin;
+
+
+ vend_name = pci_device_get_subvendor_name( dev );
+ dev_name = pci_device_get_subdevice_name( dev );
+ if ( dev_name == NULL ) {
+ dev_name = "Card unknown";
+ }
+
+ printf( " CardVendor 0x%04x card 0x%04x (",
+ dev->subvendor_id,
+ dev->subdevice_id );
+ if ( vend_name != NULL ) {
+ printf( "%s, %s)\n", vend_name, dev_name );
+ }
+ else {
+ printf( "%s)\n", dev_name );
+ }
+
+ pci_device_cfg_read_u16( dev, & command, 4 );
+ pci_device_cfg_read_u16( dev, & status, 6 );
+ printf( " STATUS 0x%04x COMMAND 0x%04x\n",
+ status,
+ command );
+ printf( " CLASS 0x%02x 0x%02x 0x%02x REVISION 0x%02x\n",
+ (dev->device_class >> 16) & 0x0ff,
+ (dev->device_class >> 8) & 0x0ff,
+ (dev->device_class >> 0) & 0x0ff,
+ dev->revision );
+
+ pci_device_cfg_read_u8( dev, & cache_line_size, 8 );
+ pci_device_cfg_read_u8( dev, & latency_timer, 9 );
+ pci_device_cfg_read_u8( dev, & header_type, 10 );
+ pci_device_cfg_read_u8( dev, & bist, 11 );
+
+ printf( " BIST 0x%02x HEADER 0x%02x LATENCY 0x%02x CACHE 0x%02x\n",
+ bist,
+ header_type,
+ latency_timer,
+ cache_line_size );
+
+ for ( i = 0 ; i < 6 ; i++ ) {
+ if ( dev->regions[i].base_addr != 0 ) {
+ printf( " BASE%u 0x%08x addr 0x%08x %s",
+ i,
+ 0,
+ (intptr_t) dev->regions[i].base_addr,
+ (dev->regions[i].is_IO) ? "I/O" : "MEM" );
+
+ if ( ! dev->regions[i].is_IO ) {
+ if ( dev->regions[i].is_prefetchable ) {
+ printf( " PREFETCHABLE" );
+ }
+ }
+
+ printf( "\n" );
+ }
+ }
+
+ if ( dev->rom_size ) {
+ printf( " BASEROM 0x%08x addr 0x%08x\n",
+ 0, 0 );
+ }
+
+ pci_device_cfg_read_u8( dev, & int_pin, 61 );
+ pci_device_cfg_read_u8( dev, & min_grant, 62 );
+ pci_device_cfg_read_u8( dev, & max_latency, 63 );
+
+ printf( " MAX_LAT 0x%02x MIN_GNT 0x%02x INT_PIN 0x%02x INT_LINE 0x%02x\n",
+ max_latency,
+ min_grant,
+ int_pin,
+ dev->irq );
+ }
+}
+
+
+int main( int argc, char ** argv )
+{
+ struct pci_device_iterator * iter;
+ struct pci_device * dev;
+
+ pci_system_init();
+
+ iter = pci_iterator_create( (argc > 1) ? argv[1] : NULL );
+
+ while ( (dev = pci_device_next( iter )) != NULL ) {
+ pci_device_probe( dev );
+ print_pci_device( dev, 1 );
+ }
+
+ pci_system_cleanup();
+ return 0;
+}