diff options
-rw-r--r-- | .cvsignore | 19 | ||||
-rw-r--r-- | .gitignore | 19 | ||||
-rw-r--r-- | AUTHORS | 1 | ||||
-rw-r--r-- | COPYING | 21 | ||||
-rw-r--r-- | ChangeLog | 32 | ||||
-rw-r--r-- | INSTALL | 236 | ||||
-rw-r--r-- | Makefile.am | 30 | ||||
-rw-r--r-- | NEWS | 0 | ||||
-rw-r--r-- | README | 0 | ||||
-rwxr-xr-x | autogen.sh | 12 | ||||
-rw-r--r-- | configure.ac | 70 | ||||
-rw-r--r-- | include/pciaccess.h | 275 | ||||
-rw-r--r-- | pciaccess.pc.in | 10 | ||||
-rw-r--r-- | src/.cvsignore | 6 | ||||
-rw-r--r-- | src/.gitignore | 6 | ||||
-rw-r--r-- | src/Doxyfile | 1228 | ||||
-rw-r--r-- | src/Makefile.am | 42 | ||||
-rw-r--r-- | src/Makefile.foo | 26 | ||||
-rw-r--r-- | src/Makefile.in | 523 | ||||
-rw-r--r-- | src/common_capability.c | 196 | ||||
-rw-r--r-- | src/common_device_name.c | 435 | ||||
-rw-r--r-- | src/common_init.c | 111 | ||||
-rw-r--r-- | src/common_interface.c | 345 | ||||
-rw-r--r-- | src/common_iterator.c | 210 | ||||
-rw-r--r-- | src/linux_sysfs.c | 493 | ||||
-rw-r--r-- | src/pciaccess_private.h | 85 | ||||
-rw-r--r-- | src/scanpci.c | 159 |
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 @@ -0,0 +1 @@ +Ian Romanick of IBM @@ -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. @@ -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/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; +} |