--- /dev/null
+Ian Romanick of IBM
--- /dev/null
+(C) Copyright IBM Corporation 2006, 2007
+(C) Copyright Eric Anholt 2006
+Copyright 2007, 2008, 2009 Sun Microsystems, Inc.
+Copyright 2009 Red Hat, Inc.
+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.
+
+------------------------------------------------------------------------------
+
+Copyright (c) 2008 Juan Romero Pardines
+Copyright (c) 2008 Mark Kettenis
+
+Permission to use, copy, modify, and distribute this software for any
+purpose with or without fee is hereby granted, provided that the above
+copyright notice and this permission notice appear in all copies.
+
+THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+------------------------------------------------------------------------------
+
+Copyright (C) 2000 The XFree86 Project, Inc. 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 the
+rights to use, copy, modify, merge, publish, distribute, sublicense, 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 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 NONINFRINGEMENT. IN NO EVENT SHALL THE
+XFREE86 PROJECT 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.
+
+Except as contained in this notice, the name of the XFree86 Project shall
+not be used in advertising or otherwise to promote the sale, use or other
+dealings in this Software without prior written authorization from the
+XFree86 Project.
--- /dev/null
+commit fa3f1c1ea8ce4b45976e11520856cfa164f8b92d
+Author: Dave Airlie <airlied@redhat.com>
+Date: Wed Jul 21 09:39:26 2010 +1000
+
+ libpciaccess 0.12.0 - bump version for release
+
+commit 2f98724d1e603268360d704b3c8823b93d5fecb4
+Author: Thomas Hellstrom <thellstrom@vmware.com>
+Date: Tue Jul 20 22:14:22 2010 +0200
+
+ Fix long standing MTRR bug.
+
+ Add an include that makes the file common_vgaarb.c see the same
+ struct pci_system as the file linux_sysfs.c.
+
+ Without this fix, on a MTRR system, the vgaarb_fd member
+ would overwrite the mtrr_fd member and cause the MTRR_IOC_ADD_ENTRY call
+ to be issued to the incorrect device causing the infamous
+ "Inappropriate ioctl for device (25)" error.
+
+ This error would cause MTRR setup to fail on all systems relying on it
+ and is severe enough to warrant a new release.
+
+ Signed-off-by: Thomas Hellstrom <thellstrom@vmware.com>
+ Signed-off-by: Dave Airlie <airlied@redhat.com>
+
+commit e5159771bd0a013201dcef760e9320071c6df59e
+Author: Dave Airlie <airlied@redhat.com>
+Date: Mon Jul 12 13:09:33 2010 +1000
+
+ pciaccess: fix use after free.
+
+ Using the pointer passed to realloc earlier isn't a recipe for success.
+
+ Signed-off-by: Dave Airlie <airlied@redhat.com>
+
+commit 3f59728ddc6f7d2cb17d434e81ac76c9288d0aef
+Author: Alan Coopersmith <alan.coopersmith@oracle.com>
+Date: Sat Jun 19 10:36:24 2010 -0700
+
+ Let libtool handle library flags for scanpci on Solaris
+
+ Stop hardcoding -ldevinfo since configure/libtool already know to add it
+ for static linking, and ELF dependencies handle it for dynamic linking
+
+ Signed-off-by: Alan Coopersmith <alan.coopersmith@oracle.com>
+
+commit e0ae5251cd030b201c14f5888a539aa40f17abfb
+Author: Tiago Vignatti <tiago.vignatti@nokia.com>
+Date: Sat May 22 18:23:33 2010 +0300
+
+ vgaarb: read back vga count when setting new decoding
+
+ Decode kernel operation can also change vga refcount, so we need to read back
+ the information when calling it.
+
+ Signed-off-by: Tiago Vignatti <tiago.vignatti@nokia.com>
+
+commit 0f153de858032c95ea5844aa6e0f1c8dad7531da
+Author: Tiago Vignatti <tiago.vignatti@nokia.com>
+Date: Wed May 12 13:12:47 2010 +0300
+
+ vgaarb: decode should send new information to the kernel
+
+ This was introduced in e360c11c.
+
+ Signed-off-by: Tiago Vignatti <tiago.vignatti@nokia.com>
+
+commit fa7cca617583eb93a862c5ebbb5a56843210e5a8
+Author: Alan Coopersmith <alan.coopersmith@oracle.com>
+Date: Fri Jun 4 16:58:56 2010 -0700
+
+ Delay allocation of agp_info so we don't leak it on prior errors
+
+ Memory leak of pointer 'agp_info'
+ at line 119 of src/common_capability.c in function 'pci_fill_capabilities_generic'.
+ 'agp_info' allocated at line 107 with calloc(1, 12).
+ 'agp_info' leaks when err != 0 at line 118.
+ at line 124 of src/common_capability.c in function 'pci_fill_capabilities_generic'.
+ 'agp_info' allocated at line 107 with calloc(1, 12).
+ 'agp_info' leaks when err != 0 at line 123.
+
+ [ This bug was found by the Parfait bug checking tool.
+ For more information see http://research.sun.com/projects/parfait ]
+
+ Signed-off-by: Alan Coopersmith <alan.coopersmith@oracle.com>
+
+commit b8295f4776912d4c3cef836eb0f158e07b432a25
+Author: Gaetan Nadon <memsize@videotron.ca>
+Date: Mon Mar 29 16:50:34 2010 -0400
+
+ config: update AC_PREREQ statement to 2.60
+
+ Unrelated to the previous patches, the new value simply reflects
+ the reality that the minimum level for autoconf to configure
+ all x.org modules is 2.60 dated June 2006.
+
+ ftp://ftp.gnu.org/gnu/autoconf/autoconf-2.60.tar.gz
+
+ Signed-off-by: Gaetan Nadon <memsize@videotron.ca>
+
+commit a624de7af1d4c0956ecd485e3ae193f93bd78c57
+Author: Gaetan Nadon <memsize@videotron.ca>
+Date: Mon Mar 29 14:53:49 2010 -0400
+
+ config: remove the pkgconfig pc.in file from EXTRA_DIST
+
+ Automake always includes it in the tarball.
+
+ Signed-off-by: Gaetan Nadon <memsize@videotron.ca>
+
+commit af2be74979aeab9a2fc4c933462e97ce70f816b6
+Author: Samuel Thibault <samuel.thibault@ens-lyon.org>
+Date: Tue Jan 19 18:37:43 2010 +0100
+
+ libpciaccess x86 backend
+
+ This adds support on x86 for OSes that do not have a PCI interface,
+ tinkering with I/O ports, and makes use of it on GNU/Hurd.
+
+ Signed-off-by: Julien Cristau <jcristau@debian.org>
+
+commit ebb3c6b69f4e8a844ff95d4e880dde9ede3de347
+Author: Julien Cristau <jcristau@debian.org>
+Date: Sun Jan 17 14:33:13 2010 +0000
+
+ COPYING: add Red Hat's copyright notice
+
+commit b775e6fa006d78cac21bbfe52f1f721947ddc6ca
+Author: Alan Coopersmith <alan.coopersmith@sun.com>
+Date: Thu Jan 14 20:48:20 2010 -0800
+
+ Update Sun license notices to current X.Org standard form
+
+ Signed-off-by: Alan Coopersmith <alan.coopersmith@sun.com>
+
+commit fac83b8116e19d4efbf8438d1cc485656cca5c60
+Author: Adam Jackson <ajax@redhat.com>
+Date: Mon Dec 14 17:27:12 2009 -0500
+
+ libpciaccess 0.11.0
+
+ Signed-off-by: Adam Jackson <ajax@redhat.com>
+
+commit 947ab16f2938e8883503ef679a40684dfe2a90e5
+Author: Adam Jackson <ajax@redhat.com>
+Date: Mon Dec 14 16:26:31 2009 -0500
+
+ Fix I/O handle array allocator to work for devices past the first
+
+ Signed-off-by: Adam Jackson <ajax@redhat.com>
+
+commit d4e008eeb9af7773edadd259cf55da43411f1a7f
+Author: Adam Jackson <ajax@redhat.com>
+Date: Mon Dec 14 16:19:35 2009 -0500
+
+ Fix pci_device_open_io() to actually return something useful
+
+ Remember, code review just means we're all inept.
+
+ Signed-off-by: Adam Jackson <ajax@redhat.com>
+
+commit 5e8d4c19b4f618e22b6e8e1ad3294d8708067474
+Author: Adam Jackson <ajax@redhat.com>
+Date: Wed Nov 18 13:53:49 2009 -0500
+
+ I/O port access routines
+
+ Acked-by: Tiago Vignatti <tiago.vignatti@nokia.com>
+ Acked-by: Matt Turner <mattst88@gmail.com>
+ Signed-off-by: Adam Jackson <ajax@redhat.com>
+
+commit b2fbe63bdf3522c5d3df5eda2ca3c3b8770c02c9
+Author: Adam Jackson <ajax@redhat.com>
+Date: Wed Nov 18 14:12:57 2009 -0500
+
+ Add pci_device_get_parent_bridge()
+
+ Copied from linuxPci.c in the X server.
+
+ Acked-by: Tiago Vignatti <tiago.vignatti@nokia.com>
+ Signed-off-by: Adam Jackson <ajax@redhat.com>
+
+commit b2b3c3bfdac23c1c8e33f47b28f22c1d4a78cc71
+Author: Gaetan Nadon <memsize@videotron.ca>
+Date: Fri Nov 27 20:56:05 2009 -0500
+
+ Makefile.am: add ChangeLog and INSTALL on MAINTAINERCLEANFILES
+
+ Now that the INSTALL file is generated.
+ Allows running make maintainer-clean.
+
+commit 57f4d11fef7021e77549a70cbf40ca43e60ea55f
+Author: Gaetan Nadon <memsize@videotron.ca>
+Date: Wed Oct 28 14:09:10 2009 -0400
+
+ INSTALL, NEWS, README or AUTHORS files are missing/incorrect #24206
+
+ Add missing INSTALL file. Use standard GNU file on building tarball
+ README may have been updated
+ Remove AUTHORS file as it is empty and no content available yet.
+ Remove NEWS file as it is empty and no content available yet.
+
+commit caa398b5305cb4c5299e283b9833ed2251698893
+Author: Gaetan Nadon <memsize@videotron.ca>
+Date: Tue Oct 27 15:07:25 2009 -0400
+
+ Deploy the new XORG_DEFAULT_OPTIONS #24242
+
+ This macro aggregate a number of existing macros that sets commmon
+ X.Org components configuration options. It shields the configuration file from
+ future changes.
+
+commit b8284cb2097601d5934773ab75db388b9fa5a9db
+Author: Gaetan Nadon <memsize@videotron.ca>
+Date: Mon Oct 26 22:08:43 2009 -0400
+
+ Makefile.am: ChangeLog not required: EXTRA_DIST or *CLEANFILES #24432
+
+ ChangeLog filename is known to Automake and requires no further
+ coding in the makefile.
+
+commit 28830993636cc5820842345b511d301af33d9c49
+Author: Gaetan Nadon <memsize@videotron.ca>
+Date: Thu Oct 22 12:34:20 2009 -0400
+
+ .gitignore: use common defaults with custom section # 24239
+
+ Using common defaults will reduce errors and maintenance.
+ Only the very small or inexistent custom section need periodic maintenance
+ when the structure of the component changes. Do not edit defaults.
+
+commit 97d677746cd70ec9eb1f33483cc829a0063953bc
+Author: Dave Airlie <airlied@redhat.com>
+Date: Fri Sep 25 10:25:56 2009 +1000
+
+ shutup stupid gcc warning, strtok_r ignores the first parameter
+
+commit 2a10d510d24c7c0aebb03914dd887f9e92cfa754
+Author: Dave Airlie <airlied@redhat.com>
+Date: Fri Sep 25 10:19:07 2009 +1000
+
+ libpciaccess 0.10.9
+
+commit 1714046ef08ef685bcf1d6c154e64809b12e8d7f
+Author: Tiago Vignatti <tiago.vignatti@nokia.com>
+Date: Fri Sep 18 15:21:19 2009 +0300
+
+ vgaarb: fix newbie typo
+
+ Eh, we don't need to check for the fd anyway. Kudos jcristau for reporting.
+
+ Signed-off-by: Tiago Vignatti <tiago.vignatti@nokia.com>
+
+commit 13c7e6c8f100882718f995f5bf1d478a012cdbdd
+Author: Tiago Vignatti <tiago.vignatti@nokia.com>
+Date: Wed Sep 16 12:56:53 2009 +0300
+
+ vgaarb: check for fd before close it
+
+ Signed-off-by: Tiago Vignatti <tiago.vignatti@nokia.com>
+
+commit cdbdfaf61c05d0d18eae6815b10666f93162148f
+Author: Keith Packard <keithp@keithp.com>
+Date: Thu Sep 17 17:38:56 2009 -0700
+
+ Free return value from scandir instead of leaking it.
+
+ Scandir is defined to return pointers to malloc'd storage, so make
+ sure that memory is nicely freed.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 42b879a203c1c16daa9d0c610c6a217ead7a5829
+Author: Dave Airlie <airlied@linux.ie>
+Date: Wed Sep 2 19:03:11 2009 +1000
+
+ vgaarb: check pci_sys exists before initing vga arb
+
+commit 312cde3c2f3530b031134cfb53a8a54731f02b1b
+Author: Dave Airlie <airlied@redhat.com>
+Date: Mon Aug 31 09:14:16 2009 +1000
+
+ pciaccess: bump to 0.10.8
+
+commit 566a67767e9fea463c24421d99dc12db590a7b5f
+Author: Thomas Klausner <wiz@netbsd.org>
+Date: Mon Aug 31 09:13:27 2009 +1000
+
+ pciaccess: fix vga arb stubs
+
+commit d062dd78baeb28ef2cc59f4fb4a7d82ecd5adf60
+Author: Dave Airlie <airlied@redhat.com>
+Date: Fri Aug 28 11:29:00 2009 +1000
+
+ libpciaccess: bump to 0.10.7 for vga arb interface addition
+
+commit 81b4705525bdf82d75f5b3c740c53fa4a866d9c3
+Merge: f514852 2f997f9
+Author: Dave Airlie <airlied@redhat.com>
+Date: Fri Aug 28 11:25:15 2009 +1000
+
+ Merge branch 'vga'
+
+commit 2f997f90c8d0b54baab85285703550e8df28325e
+Author: Dave Airlie <airlied@redhat.com>
+Date: Fri Aug 28 11:24:53 2009 +1000
+
+ vgaarb: update stub interface
+
+commit b229acdfd10fd61f46d8e711910b5c1bdb727857
+Author: Dave Airlie <airlied@redhat.com>
+Date: Fri Aug 28 11:21:11 2009 +1000
+
+ Revert "vgaarb: delete stub functions"
+
+ This reverts commit b7fd4d06890d801aae93fe1a1af7ab110fd388fd.
+
+commit e70767cb2e574f8544a04903eea3afee33345eea
+Author: Tiago Vignatti <tiago.vignatti@nokia.com>
+Date: Wed Aug 26 11:14:03 2009 +0300
+
+ Revert "vgaarb: fix pci_device_vgaarb_get_info() return value."
+
+ This reverts commit ef8aca5da46155e9ea0d1227215921ad9ce59150.
+
+commit f5148525d546015c12b703a768b5e6c3726446a3
+Merge: 7636348 ef8aca5
+Author: Dave Airlie <airlied@redhat.com>
+Date: Fri Aug 21 13:27:11 2009 +1000
+
+ Merge remote branch 'origin/vga-arbiter'
+
+commit ef8aca5da46155e9ea0d1227215921ad9ce59150
+Author: Tiago Vignatti <tiago.vignatti@nokia.com>
+Date: Sun Aug 16 19:11:15 2009 +0300
+
+ vgaarb: fix pci_device_vgaarb_get_info() return value.
+
+ Signed-off-by: Tiago Vignatti <tiago.vignatti@nokia.com>
+
+commit 25be96885671d22ee3f932769d72cf3a31f355ee
+Author: Tiago Vignatti <tiago.vignatti@nokia.com>
+Date: Sun Aug 16 19:09:35 2009 +0300
+
+ vgaarb: fix indentation and remove trailing white spaces
+
+ Signed-off-by: Tiago Vignatti <tiago.vignatti@nokia.com>
+
+commit b7fd4d06890d801aae93fe1a1af7ab110fd388fd
+Author: Tiago Vignatti <tiago.vignatti@nokia.com>
+Date: Sun Aug 16 18:59:21 2009 +0300
+
+ vgaarb: delete stub functions
+
+ Such stub functions is already with API outdated. Moreover, if some operating
+ system doesn't have arbiter's implementation then the app can set some
+ autoconf tricks like "ifdef HAVE_PCI_DEVICE_VGAARB_INIT".
+
+ Signed-off-by: Tiago Vignatti <tiago.vignatti@nokia.com>
+
+commit 76363486864b325b8f156ece35736ddb64c4e697
+Author: Julien Cristau <jcristau@debian.org>
+Date: Sun Aug 9 11:28:38 2009 +0200
+
+ Silence compiler warning about pci_id_file_open definition
+
+ src/common_device_name.c:59: warning: function declaration isn't a prototype
+ src/common_device_name.c: In function 'pci_id_file_open':
+ src/common_device_name.c:59: warning: old-style function definition
+
+commit 4eac0173588ab9ef67fcadb47b531abb114aa0a7
+Author: Julien Cristau <jcristau@debian.org>
+Date: Sat Aug 8 18:12:08 2009 +0200
+
+ configure.ac: fix help text for the linux-rom-fallback option
+
+ LINUX_ROM defaults to no, fix the help text to reflect that
+
+ Signed-off-by: Julien Cristau <jcristau@debian.org>
+
+commit e9f2db8b867cba8d91a040a0db9be56099fba680
+Merge: 706201e dedd31b
+Author: Dave Airlie <airlied@redhat.com>
+Date: Thu Aug 6 09:43:08 2009 +1000
+
+ Merge branch 'master' into vga-arbiter
+
+commit dedd31b3bcdeea12955bf565b8e3f2a9d3c66057
+Author: Dave Airlie <airlied@redhat.com>
+Date: Thu Aug 6 09:39:01 2009 +1000
+
+ pciaccess: make linux rom reading fallback optional
+
+ On kernels which have ROM files, the boot VGA rom file
+ will contain the 0xc0000 file anyways. If another card
+ is missing a rom file there is no need for this.
+
+ This is fallback is disabled by default, on the premise
+ that distro shipping this new a pciaccess will be running
+ on kernels with working rom support which is been upstream
+ for a long time
+
+commit 706201e900b5664ea35ec498784590275b98c23a
+Merge: 57cf6f1 8aa06cf
+Author: Dave Airlie <airlied@redhat.com>
+Date: Thu Aug 6 09:42:06 2009 +1000
+
+ Merge branch 'master' into vga-arbiter
+
+commit 8aa06cf7ef5e88c53bf6778336ba1a6036b16cc0
+Author: Dave Airlie <airlied@redhat.com>
+Date: Thu Aug 6 09:39:01 2009 +1000
+
+ pciaccess: make linux rom reading fallback optional
+
+ On kernels which have ROM files, the boot VGA rom file
+ will contain the 0xc0000 file anyways. If another card
+ is missing a rom file there is no need for this.
+
+ This is fallback is disabled by default, on the premise
+ that distro shipping this new a pciaccess will be running
+ on kernels with working rom support which is been upstream
+ for a long time
+
+commit 57cf6f1f428ab73fb2a88c39c694e7d14c2c96c6
+Author: Dave Airlie <airlied@redhat.com>
+Date: Thu Aug 6 09:39:01 2009 +1000
+
+ pciaccess: make linux rom reading fallback optional
+
+ On kernels which have ROM files, the boot VGA rom file
+ will contain the 0xc0000 file anyways. If another card
+ is missing a rom file there is no need for this.
+
+ This is fallback is disabled by default, on the premise
+ that distro shipping this new a pciaccess will be running
+ on kernels with working rom support which is been upstream
+ for a long time
+
+commit 7b7999a302c70f1ad9a5c8fc7517e24ab95c3a95
+Author: Dave Airlie <airlied@redhat.com>
+Date: Mon Aug 3 12:43:26 2009 +1000
+
+ vgaarb: add vga count + resource accessor
+
+commit 3a6c1be79c05517cfddbce88157bb352237058ab
+Author: Dave Airlie <airlied@redhat.com>
+Date: Mon Aug 3 09:39:22 2009 +1000
+
+ vgaarb: more api changes + cleanup
+
+ add a comma for ease of parsing,
+ use hex on the interface in both directions instead of hex on one
+ and decimal on the other
+
+commit e5127339c6c48ae6f63f9dc841a94fe960d11496
+Author: Dave Airlie <airlied@redhat.com>
+Date: Fri Jul 31 16:15:55 2009 +1000
+
+ vgaarb: change API to target taking a device + lock/unlock not taking one
+
+ working on the target device - a target device of NULL
+ reselects the target that existed when we started.
+
+ this is mainly to allow a udev posting tool to return to the
+ state of what happened before it ran.
+
+commit 0596c559af5ca277a069b04a6402d21724464cda
+Author: Dave Airlie <airlied@redhat.com>
+Date: Fri Jul 31 15:34:32 2009 +1000
+
+ vgaarb: add support for targetting default device
+
+commit 453928b8485bc7beff69996abe12628efc09405f
+Author: Dave Airlie <airlied@redhat.com>
+Date: Fri Jul 31 11:17:21 2009 +1000
+
+ vgaarb: clean up debug output
+
+commit d22d7c0d5e48d130c89282514e378819e0b98636
+Merge: e360c11 2bda5b7
+Author: Dave Airlie <airlied@redhat.com>
+Date: Fri Jul 31 11:16:16 2009 +1000
+
+ Merge remote branch 'main/master' into vga-arbiter
+
+commit e360c11c37a219534bfd7266caf163870dddced0
+Author: Dave Airlie <airlied@redhat.com>
+Date: Mon Jul 20 13:26:41 2009 +1000
+
+ vgaarb: fixup api for new count reporting + decodes interface was wrong.
+
+ decodes is a information setting interface so it takes new decodes
+ and sends them to the kernel
+
+commit 5d1bdf0cb51c19efd6e2b2c0a463ace9443c48d9
+Author: Dave Airlie <airlied@redhat.com>
+Date: Thu Jul 16 15:36:30 2009 +1000
+
+ add support for finding if something has a kernel driver
+
+commit 2bda5b733bb12854760750c08138db95e77aea0c
+Author: Jesse Barnes <jbarnes@virtuousgeek.org>
+Date: Tue Jun 30 15:24:45 2009 -0700
+
+ Don't try to use bogus bridge data
+
+ If, for whatever reason, we weren't able to read bridge data (therefore
+ leaving bridge.pci or bridge.pcmcia empty), we shouldn't try to look at
+ the bus data inside the pci/pcmcia struct.
+
+commit 9ae22c87743c624bda593a1ef4bd4eca01c65655
+Author: Dave Airlie <airlied@redhat.com>
+Date: Fri Jun 5 09:32:10 2009 +1000
+
+ vgaarb: fixup api and decode rsrc.
+
+ This fixes up the API and stores the vga arb fd in the sys_pci structure,
+ instead of hiding it in a random dev struct.
+
+ It also reads back after setting the target and works out the decodes.
+
+ Signed-off-by: Dave Airlie <airlied@redhat.com>
+
+commit 9ae66143550a6aee25d9a9620c5bebf93fa196e5
+Author: Tiago Vignatti <vignatti@freedesktop.org>
+Date: Thu May 14 17:30:17 2009 -0300
+
+ Comment typo.
+
+commit 6ae00a992714639fd725efd8817dca69b28276c8
+Author: Tiago Vignatti <vignatti@freedesktop.org>
+Date: Thu May 14 17:28:05 2009 -0300
+
+ Reorganize the code.
+
+commit 6ef4e7aebfd2b83e2346e9f8f4ef3c890a6ea73d
+Author: Tiago Vignatti <vignatti@freedesktop.org>
+Date: Thu May 14 03:42:56 2009 -0300
+
+ Fix typo in vgaarb stubs.
+
+commit 18a186804bc4e496a392cb31003cef25798f6c7b
+Author: Tiago Vignatti <vignatti@freedesktop.org>
+Date: Thu May 14 03:40:25 2009 -0300
+
+ Delete vga_arb_rec.
+
+commit 812ad80018d49f6e4f1be8256d86488690c3ba52
+Author: Tiago Vignatti <vignatti@freedesktop.org>
+Date: Wed May 13 18:31:09 2009 -0300
+
+ vgaarb: a bunch of clean ups to fit in libpciaccess style.
+
+commit b77b0fc3fbacc46d55998889f09326d1233339fc
+Author: Tiago Vignatti <vignatti@freedesktop.org>
+Date: Wed May 13 17:55:31 2009 -0300
+
+ vgaarb: make it compile.
+
+commit 67af888bcc5667eadf1e9e9bf15305f742416daf
+Author: Tiago Vignatti <vignatti@freedesktop.org>
+Date: Wed May 13 17:44:46 2009 -0300
+
+ Import libvgaaccess (VGA Arbiter) implementation from C3SL repository:
+ http://git.c3sl.ufpr.br/
+
+commit 8ba6b02ecfa5b03bbf2807e8262bb1253a026493
+Author: Aaron Plattner <aplattner@nvidia.com>
+Date: Fri May 1 15:04:19 2009 -0700
+
+ Don't try to write boot_vga since that fails with EACCES
+
+commit b2838fb61c3542f107014b285cbda097acae1e12
+Author: Dave Airlie <airlied@redhat.com>
+Date: Wed Mar 4 15:55:11 2009 +1000
+
+ pciaccess: provide a method to detect if a device is boot VGA
+
+ When the linux kernel exposes this information, we can use this interface
+ in the X server to detect whether the kernel believes the device we
+ are looking at is the boot VGA device.
+
+ Signed-off-by: Dave Airlie <airlied@redhat.com>
+
+commit f14c6cd626273bd2f8b102ff661d11926619a99b
+Author: Alan Coopersmith <alan.coopersmith@sun.com>
+Date: Fri Apr 24 16:32:12 2009 -0700
+
+ Version bump: 0.10.6
+
+ Signed-off-by: Alan Coopersmith <alan.coopersmith@sun.com>
+
+commit 6df3387173c3ab25e8a618d9ccf628682d8336d5
+Author: Alan Coopersmith <alan.coopersmith@sun.com>
+Date: Fri Apr 24 16:19:34 2009 -0700
+
+ Resync COPYING file with code copyright notices
+
+ Signed-off-by: Alan Coopersmith <alan.coopersmith@sun.com>
+
+commit 7f08a1e19b49c9ffdc62e1dff340b392ac7c42d1
+Author: Alan Coopersmith <alan.coopersmith@sun.com>
+Date: Fri Apr 17 22:05:03 2009 -0700
+
+ Fix unused variable warnings in Solaris code
+
+ solx_devfs.c: In function `find_target_node':
+ solx_devfs.c:672: warning: unused variable `prop'
+ solx_devfs.c:673: warning: unused variable `i'
+
+ Signed-off-by: Alan Coopersmith <alan.coopersmith@sun.com>
+
+commit 0edb2392ede59cadd75915873b52baa188bfa273
+Author: Alan Coopersmith <alan.coopersmith@sun.com>
+Date: Fri Apr 17 21:59:25 2009 -0700
+
+ Fix $CWARNFLAGS addition
+
+ Original addition to configure.ac had typo (missing N) - moving to
+ Makefile.am allows easier override at build time
+
+ Signed-off-by: Alan Coopersmith <alan.coopersmith@sun.com>
+
+commit 146dc2f4ac232bb9d63225c8e72b214dc3120ea6
+Author: Alan Coopersmith <alan.coopersmith@sun.com>
+Date: Fri Apr 17 21:56:31 2009 -0700
+
+ Move included m4 to a subdir so we can more easily update from upstream
+
+ Signed-off-by: Alan Coopersmith <alan.coopersmith@sun.com>
+
+commit a7f8e58d44716a01f4a8dc9826996a0fa78e4196
+Author: Owain Ainsworth <zerooa@googlemail.com>
+Date: Sat Apr 18 06:38:46 2009 +0200
+
+ openbsd_pci.c: use the correct size when mapping the legacy vga rom.
+
+ fixes errors (and probably bugs) on intel hardware (at the least).
+
+ Signed-off-by: Matthieu Herrb <matthieu.herrb@laas.fr>
+
+commit be748a7b512bf5597e162694a3b1769132938fe1
+Author: Alan Coopersmith <alan.coopersmith@sun.com>
+Date: Wed Apr 15 10:06:49 2009 -0700
+
+ Sun bug 6811468: pci_device_solx_devfs_probe accesses freed memory
+
+ di_fini() is being called in pci_device_solx_devfs_probe()
+ The di_fini (3DEVINFO) man page says "All handles associated with this
+ snapshot become invalid after the call to di_fini()". But after that,
+ eight lines down, the subroutine was calling di_prop_lookup_ints with
+ a handle args.node which was stored from walking the device tree, and
+ then using the pointers that returned even further down.
+
+ Signed-off-by: Alan Coopersmith <alan.coopersmith@sun.com>
+
+commit c56da48ee806f73c8ed81afb4a251b24de304620
+Author: Alan Coopersmith <alan.coopersmith@sun.com>
+Date: Tue Apr 14 17:29:10 2009 -0700
+
+ Fix const mismatch compiler warnings in Solaris backend
+
+ Signed-off-by: Alan Coopersmith <alan.coopersmith@sun.com>
+
+commit f6084593c275c5dc1d6154f292991b20bffd68c2
+Author: edward shu <edward.shu@sun.com>
+Date: Tue Apr 14 17:19:09 2009 -0700
+
+ Sun bug 6785726: libpciaccess needs to use the correct BAR index on solaris
+
+ <http://bugs.opensolaris.org/bugdatabase/view_bug.do?bug_id=6785726>
+
+ Signed-off-by: Alan Coopersmith <alan.coopersmith@sun.com>
+
+commit 2355e720ef3c285a44c88f914ebdc163a1c591a7
+Author: Mark Kettenis <mark.kettenis@xs4all.nl>
+Date: Tue Apr 14 21:53:26 2009 +0200
+
+ Make libpciaccess on OpenBSD domain-aware.
+
+ Makes X capable of discovering PCI devices
+ in other domains (on macppc or sparc64 for example).
+
+commit 9ba94caf57e3a8c3e9c6f3f5f068f4a7a7b3ff9d
+Author: Darren Smith <darren.smith@juno.com>
+Date: Tue Apr 14 10:46:26 2009 -0400
+
+ Be more paranoid about reading bridge info (#20786)
+
+commit 72e75b00e4f3f7df3badb10c916126253204ae45
+Author: Robert Noland <rnoland@2hip.net>
+Date: Fri Feb 27 00:34:28 2009 -0600
+
+ FreeBSD: Incorporate several fixes that have accumulated.
+
+ -Don't frob the BARs while they are enabled
+ -Find proper pci bios address / length
+ -Use the new PCIOCGETBAR ioctl if it exists
+ rather than frob the BARs ourself
+ -Write must also be a power of two
+
+commit 5855cf5a2cc7ee920b42052372ab734003799d00
+Author: Alan Coopersmith <alan.coopersmith@sun.com>
+Date: Mon Feb 2 20:34:38 2009 -0800
+
+ Add README with pointers to mailing list, bugzilla & git repos
+
+ Signed-off-by: Alan Coopersmith <alan.coopersmith@sun.com>
+
+commit 42b493490e90e1c5461d36beb3f2dc2580c7d25e
+Author: Paulo Cesar Pereira de Andrade <pcpa@mandriva.com.br>
+Date: Wed Jan 28 18:03:21 2009 -0200
+
+ Janitor: Correct make distcheck and compiler warnings.
+
+commit 5bf4b32c2b3844c50e720be5820f2ce657ddea12
+Author: Alan Coopersmith <alan.coopersmith@sun.com>
+Date: Thu Jan 22 16:14:22 2009 -0800
+
+ Solaris: Use bus-range properties to limit busses scanned on each node
+
+ Based on code provided by Dan.Mick@sun.com
+
+commit 0488a2830a6a0d27d9be032607eda954a8c99801
+Author: Matthieu Herrb <matthieu.herrb@laas.fr>
+Date: Sun Dec 7 19:18:29 2008 +0100
+
+ Fix a logic error in pci_device_netbsd_write()
+
+ This is the same error as in pci_device_openbsd_write() that actually
+ prevented it to write anything.
+
+commit 565c8fcbf39a56319cee4f77f689dfc79e0c6614
+Author: Matthieu Herrb <matthieu.herrb@laas.fr>
+Date: Sun Dec 7 19:00:22 2008 +0100
+
+ Sync with OpenBSD code.
+
+ - implement pci_read_rom()
+ - only set MTRR on x86 cpus
+ - failure to set non-cacheable attributes is not fatal
+ - fix a logic error in pci_write()
+
+commit 8222fb8534cf09e433f0f3d68c35d6c390fbba5e
+Author: Matthieu Herrb <matthieu.herrb@laas.fr>
+Date: Tue Nov 25 12:42:15 2008 +0100
+
+ Fix a logic error in pci_device_openbsd_write().
+
+commit 613c1e6d09930bab47f2c6983f220df002c2e2ce
+Author: Alan Coopersmith <alan.coopersmith@sun.com>
+Date: Wed Nov 19 09:37:49 2008 -0800
+
+ Add AC_SYS_LARGEFILE to configure.ac
+
+commit 0821f3b4eae5428cf1af5c4c056240f8991758f6
+Author: Alan Coopersmith <alan.coopersmith@sun.com>
+Date: Wed Nov 19 08:22:22 2008 -0800
+
+ Don't open/gzopen pci.ids if we're not going to read it
+
+commit ccbfd4cf2a7d203344bd1ffcb9d0024536a0eefa
+Author: Alan Coopersmith <alan.coopersmith@sun.com>
+Date: Tue Nov 18 19:54:42 2008 -0800
+
+ Fill in byte swapping routines for big-endian Solaris machines
+
+commit 7aca9465a61934d57781352f4fcc42b779392cd0
+Author: Julien Cristau <jcristau@debian.org>
+Date: Fri Oct 31 18:07:52 2008 +0100
+
+ Bump to 0.10.5
+
+commit 8b0be8751279f9bc8f15ced4e5384fa2b0f78711
+Author: Julien Cristau <jcristau@debian.org>
+Date: Fri Oct 31 17:33:50 2008 +0100
+
+ Make --without-zlib work
+
+commit 7a5ed759f13c3fc5f379cce2ca02c9ebfae5eae9
+Author: Robert Noland <rnoland@2hip.net>
+Date: Wed Oct 29 22:20:35 2008 -0400
+
+ Fix FreeBSD systems which support pci domains.
+
+ Support for FreeBSD based systems which support pci domains was broken
+ in the commit to support kFreeBSD. Include config.h so that things are
+ happy again.
+
+commit 067f979cbd410ddb82aee702d8434552e35c7154
+Author: Alan Coopersmith <alan.coopersmith@sun.com>
+Date: Fri Oct 17 14:09:52 2008 -0700
+
+ Version 0.10.4
+
+commit 714fef70e66b651e9a535d3d3cb20d055595a12d
+Author: Alan Coopersmith <alan.coopersmith@sun.com>
+Date: Fri Oct 17 14:09:43 2008 -0700
+
+ Add scanpci.man to EXTRA_DIST
+
+commit 77f274b6386301cb31c074061a8c947a78b49da9
+Author: Alan Coopersmith <alan.coopersmith@sun.com>
+Date: Fri Oct 17 13:51:28 2008 -0700
+
+ Update COPYING with the rest of the copyright/license notices from the code
+
+commit 482d1da02498a6a31a6d829a5be41727f6333f94
+Author: Alan Coopersmith <alan.coopersmith@sun.com>
+Date: Fri Oct 17 13:48:46 2008 -0700
+
+ Add scanpci man page from Xorg
+
+commit f537fc50e014063d1a1297bfd82680ae3f170281
+Author: Alan Coopersmith <alan.coopersmith@sun.com>
+Date: Thu Oct 16 21:17:24 2008 -0700
+
+ More minor Solaris cleanups
+
+commit 9a5565c72c13aa107167c9c4a4469dd11ac13714
+Author: Alan Coopersmith <alan.coopersmith@sun.com>
+Date: Thu Oct 16 18:18:09 2008 -0700
+
+ Clean up formatting of solx_devfs.c
+
+commit de97e7e4c63146032c0badb9e0f0b1899dc8debf
+Author: Alan Coopersmith <alan.coopersmith@sun.com>
+Date: Thu Oct 16 16:55:27 2008 -0700
+
+ Fix bus probing on Solaris/SPARC
+
+commit 110cdac97ca1bca3ec811ce0a71b2b24c1f80525
+Author: Alan Coopersmith <alan.coopersmith@sun.com>
+Date: Thu Oct 16 13:33:01 2008 -0700
+
+ Correct Sun license notice
+
+commit 4c0d050c72a38e66a7b4ccb134e7e872eb0bf557
+Author: Alan Coopersmith <alan.coopersmith@sun.com>
+Date: Wed Oct 15 18:23:03 2008 -0700
+
+ scanpci: add -v flag to enable verbose mode like old scanpci
+
+commit 64d0c836d547847b752da6539792b94c803f206b
+Author: Alan Coopersmith <alan.coopersmith@sun.com>
+Date: Wed Oct 15 16:14:18 2008 -0700
+
+ Correct comment about devices used on Solaris
+
+commit d43d21c8cb0f917b65228852a03a7d501636f227
+Author: Alan Coopersmith <alan.coopersmith@sun.com>
+Date: Wed Oct 15 15:35:25 2008 -0700
+
+ Fix various typos (mostly in comments)
+
+commit 4c1c607c602e5e8d9277b9c01edfa7a8d10333cd
+Author: Juan RP <xtraeme@gmail.com>
+Date: Sat Oct 11 20:28:03 2008 +0200
+
+ Add NetBSD support
+
+ It's based in the OpenBSD code, but with differences because on NetBSD,
+ to set MTRRs we have to use i386/x86_64_set_mtrr() and link to libi386
+ or libx86_64.
+
+ X.Org bug#17931 <http://bugs.freedesktop.org/show_bug.cgi?id=17931>
+
+commit 6ae378611bb4caaf57311734d3adcb7e10ac3622
+Author: Petr Salinger <petr.salinger@seznam.cz>
+Date: Sat Oct 11 20:22:28 2008 +0200
+
+ Add support for GNU/kFreeBSD
+
+ We need to initialize the FreeBSD backend on GNU/kFreeBSD and detect
+ whether pci_io.pi_sel.pc_domain member exists.
+
+ X.Org bug#17882 <http://bugs.freedesktop.org/show_bug.cgi?id=17882>
+
+commit 968289fc3137ac0863c62d3c343153fa3e4aeb10
+Author: John Tapsell <johnflux@gmail.com>
+Date: Tue Sep 23 17:26:09 2008 +0300
+
+ configure.ac: Make mtrr.h test more portable
+
+ Use the standard AC_CHECK_HEADERS, which works for cross-compiling as
+ well as in various other locations.
+
+commit 79ed41882fd721a15c8b0bea7efeb98864d85dfb
+Author: Matthieu Herrb <matthieu.herrb@laas.fr>
+Date: Sat Sep 20 18:28:59 2008 +0200
+
+ OpenBSD: allow 2 successives calls to pci_system_init().
+
+ And fix pci_system_cleanup() to make it possible to call pci_system_init()
+ again.
+ ok kettenis at openbsd.
+
+commit 45015ab30b36bdaefd3f3aeab73d287023928826
+Author: Kel Modderman <kel@otaku42.de>
+Date: Tue Jul 8 13:09:52 2008 +0200
+
+ Handle compressed pci.ids
+
+ Add an option to build with zlib support so we can find
+ vendor/device information if the pci.ids file is gzipped.
+
+ Signed-off-by: Julien Cristau <jcristau@debian.org>
+
+commit 32c64bb2386c55d5c7a3878ae9e3f95577f00875
+Author: Julien Cristau <jcristau@debian.org>
+Date: Wed Mar 12 15:00:26 2008 +0100
+
+ Hide one more private symbol
+
+commit 7282b53c47c2435c1ea23948272c9ccf1798178a
+Author: Jesse Barnes <jbarnes@hobbes.(none)>
+Date: Mon Jun 23 11:24:04 2008 -0700
+
+ Support write combine resource files in Linux sysfs
+
+ Starting with version 2.6.26, Linux will support resourceN_wc files which
+ export write combining mappings of PCI resource ranges, so support them if
+ present in libpciaccess.
+
+commit f49f66710b6c3cc5edfd0681cf7b69063cb4b893
+Author: Stefan Dirsch <sndirsch@suse.de>
+Date: Mon Jun 23 10:50:30 2008 +0200
+
+ Fixed typo in output ("performace" --> "performance").
+
+commit ed0555e4225aec26aaaa40f4f3c15fd914390817
+Author: Adam Jackson <ajax@redhat.com>
+Date: Tue Jun 10 15:24:56 2008 -0400
+
+ libpciaccess 0.10.3
+
+commit 07577a875bc9996437cfe30e5a87ca6b1a0f7e4a
+Author: Adam Jackson <ajax@redhat.com>
+Date: Tue Jun 10 15:23:06 2008 -0400
+
+ libpciaccess 0.10.2
+
+commit e3adc06b8b8214478aa1d3e85fd5f83b79d039b4
+Author: Eric Anholt <eric@anholt.net>
+Date: Thu Jun 5 11:39:06 2008 -0700
+
+ Catch and recover from yet another linux kernel bug in mprotect.
+
+commit 4586bb6766983d040bff38b43dc458c47e0ca21f
+Author: Adam Jackson <ajax@redhat.com>
+Date: Wed May 21 13:44:38 2008 -0400
+
+ Linux: Fail gracefully on machines without PCI.
+
+commit 26400575a2a2d10b1014eaf0bfca6cfbf5d9b93b
+Author: Dave Airlie <airlied@redhat.com>
+Date: Wed May 21 16:10:37 2008 +1000
+
+ pciaccess: bump to 0.10.1
+
+commit 4bc9292ff9338e759eb9a73f12edfa5ca87353e0
+Author: Dave Airlie <airlied@redhat.com>
+Date: Wed May 21 16:10:24 2008 +1000
+
+ linux: add pci_device_enable entrypoint and sysfs support for it
+
+commit ded8326f2adadc773b34889474a0d4fc20ef387a
+Author: Alan Coopersmith <alan.coopersmith@sun.com>
+Date: Fri May 9 15:15:42 2008 -0700
+
+ Fix lint warnings in solx_devfs.c
+
+commit 74c976a7bcee3102993cf788850d0b803cf15afd
+Author: Alan Coopersmith <alan.coopersmith@sun.com>
+Date: Fri May 9 15:05:46 2008 -0700
+
+ Add pci_system_solx_devfs_create prototype to pciaccess_private.h
+
+commit 2ac461b2eca788fa0559312d45efd3caf6eea9bb
+Author: Alan Coopersmith <alan.coopersmith@sun.com>
+Date: Fri May 9 14:49:32 2008 -0700
+
+ Initialize err to 0 in pci_device_solx_devfs_map_range
+
+ Prevents returning errors when mapping actually succeeds
+
+commit b30d458202bc0304c705eb081b12ead860584bea
+Author: Keith Packard <keithp@keithp.com>
+Date: Wed Apr 16 12:10:52 2008 -0700
+
+ Kludge around linux bug and turn off write-through and cache-disable bits
+
+ When mmaping the PCI device, the kernel turns on the write-through and
+ cache-disable bits in the allocated PTEs. This disables write-combining mode
+ and dramatically reduces write bandwidth to the frame buffer. While that
+ should be fixed in the kernel, we'll kludge around it here by using mprotect
+ to rewrite the PTEs and get those bits turned off.
+
+commit a3b63c43b960e3b37e1b303214e63c5155192a5d
+Author: Hasso Tepper <hasso@estpak.ee>
+Date: Mon Apr 7 15:28:44 2008 +0300
+
+ Add DragonFly BSD support
+
+ DragonFly behaves exactly like FreeBSD, so no problem here.
+
+commit ec53d6ef2bdf0e7a087ffd45fe112290f2181656
+Author: Danny van Dyk <danny.dyk@uni-dortmund.de>
+Date: Fri Mar 28 17:01:29 2008 -0700
+
+ Fix function prototypes for C++
+
+commit a5c862029846ddd5cecf44819f2a967e2a1672a9
+Author: Stuart Bennett <sb476@cam.ac.uk>
+Date: Fri Mar 14 11:58:33 2008 -0400
+
+ Bug #13988: Fix reads from "0"-sized ROMs.
+
+commit d898072e28ac35f5b3569f48f2e90a9ef8eee2ca
+Author: Mark Kettenis <mark.kettenis@xs4all.nl>
+Date: Wed Mar 12 21:29:58 2008 +0100
+
+ OpenBSD support for libpciaccess.
+
+ xserver and libpciaccess both need to open /dev/xf86, which can only
+ be opened once. I implemented pci_system_init_dev_mem() like Ian
+ suggested. This requires some minor changes to the BSD-specific
+ os-support code. Since pci_system_init_dev_mem() is a no-op on
+ FreeBSD this should be no problem.
+
+commit 4224ff23794500e1455f28fd5689bd0549b72367
+Author: Julien Cristau <jcristau@debian.org>
+Date: Fri Mar 7 14:41:47 2008 +0100
+
+ solaris: add pci_tools.h to OS_SUPPORT
+
+ pci_tools.h was missing from the tarball, but is needed by solx_devfs.c
+
+commit ac119e0b1d5fdbb6bd447b6cef1ddca59840fe40
+Author: Adam Jackson <ajax@redhat.com>
+Date: Thu Mar 6 15:31:51 2008 -0500
+
+ libpciaccess 0.10
+
+commit 0ac748d0da1361075efa48a6238f2328d24ba1a8
+Author: Doug Chapman <doug.chapman@hp.com>
+Date: Thu Mar 6 14:22:17 2008 -0500
+
+ Bug #14818: Actually return the PCI vendor name, instead of NULL.
+
+commit adc46f65d7a097ea0e8427a2496586a420c99d55
+Author: Julien Cristau <jcristau@debian.org>
+Date: Tue Feb 19 14:45:40 2008 +0100
+
+ Don't export private symbols.
+
+commit 25de45d250811474e86cb9a09caf258aef699196
+Author: Julien Cristau <jcristau@debian.org>
+Date: Tue Feb 19 14:26:54 2008 +0100
+
+ Use <byteswap.h> when using glibc, not just on linux
+
+ This fixes the build on GNU/kFreeBSD.
+
+commit ceda00d33fbf3d491e3f7e53302acd2b8b74a305
+Author: James Cloos <cloos@jhcloos.com>
+Date: Thu Dec 6 16:38:51 2007 -0500
+
+ Replace static ChangeLog with dist-hook to generate from git log
+
+commit e392082abb5696c8837224da86cc0af4f21d7010
+Author: Matthias Hopf <mhopf@suse.de>
+Date: Tue Oct 23 15:19:36 2007 +0200
+
+ Bit-fields have to have type _Bool, signed int, or unsigned int.
+
+ ISO/IEC 9899:1999 (E), 6.7.2.1 Structure and union specifiers, (4).
+ _Bool is only supported for C99 and up, and 1-bit signed types don't make
+ sense -> unsigned int.
+
+commit 5b9ca552a17de37bbac84f0cf5b4430d108e576c
+Author: Ian Romanick <idr@us.ibm.com>
+Date: Thu Oct 18 15:59:14 2007 -0700
+
+ Update bug reporting link.
+
+commit 57a942b3cca314a56735e0a4198cac2f25b653dd
+Author: Eric Anholt <eric@anholt.net>
+Date: Wed Oct 10 15:20:51 2007 -0700
+
+ FreeBSD: for 64-bit BARs, skip the resource slot used for the upper 32 bits.
+
+ This gets us the same resource numbering as on Linux.
+
+commit 127ae628a2090bb00df81adce831b8b031d3b4a8
+Author: Eric Anholt <eric@anholt.net>
+Date: Wed Oct 10 14:55:45 2007 -0700
+
+ FreeBSD: Don't try to unset an MTRR if we didn't set it.
+
+commit 28fea32f987a74d365d01bc5870a8bce1c393d59
+Author: Eric Anholt <eric@anholt.net>
+Date: Wed Oct 10 14:32:38 2007 -0700
+
+ Add domain output to scanpci.
+
+commit 393145db90578d7d598fccf949b249217066a67c
+Author: Eric Anholt <eric@anholt.net>
+Date: Wed Oct 10 14:32:09 2007 -0700
+
+ FreeBSD: Add support for multiple PCI domains.
+
+commit 7d809e149b59f22e24723db7360a4c38a9145b45
+Author: Eric Anholt <eric@anholt.net>
+Date: Tue Oct 9 12:13:49 2007 -0700
+
+ FreeBSD: Fix unmap_range to return an error value.
+
+commit 042735df2aa5846fcabfd74c5f73877132728b25
+Author: Eric Anholt <eric@anholt.net>
+Date: Tue Oct 9 12:12:34 2007 -0700
+
+ FreeBSD: don't set the MTRR if it's the default mode (uncacheable).
+
+commit 4bdaca5295eeacdaeb80f2e7d0fa17674dcbc77a
+Author: Alan Coopersmith <alan.coopersmith@sun.com>
+Date: Thu Sep 27 15:22:51 2007 -0700
+
+ Need to link with -ldevinfo on Solaris
+
+commit 63983e2397d813246b851771c13397ff700e239e
+Author: Alan Coopersmith <alan.coopersmith@sun.com>
+Date: Wed Sep 26 17:26:47 2007 -0700
+
+ Fix Solaris build: missing static prototype & typo in variable name
+
+commit 8c77862e70eac7f61cd402e9ef33a5b0ca1c6426
+Author: Eric Anholt <eric@anholt.net>
+Date: Tue Sep 11 15:07:55 2007 +0000
+
+ Add FreeBSD MTRR setting support.
+
+commit 82a2ff0bb091e097bacb66273f55a287afb15abf
+Author: Ian Romanick <idr@us.ibm.com>
+Date: Tue Sep 4 16:13:24 2007 -0700
+
+ Add stub version of pci_device_map_memory_range
+
+ This stub version of pci_device_map_memory_range allows the vesa driver and
+ other users of this interface to continue functioning with current
+ libpciaccess bits. That said, users of this interface should convert over
+ to pci_device_map_range as soon as possible.
+
+commit 9d1596cba90c8fd273e9d1d5488747cc0f34fdc7
+Merge: b1e9117 5cf29b0
+Author: James Cloos <cloos@jhcloos.com>
+Date: Mon Sep 3 06:15:58 2007 -0400
+
+ Merge branch 'master' of ssh://git.freedesktop.org/git/xorg/lib/libpciaccess
+
+commit b1e911784d314fdbd8d938e5fe3671bec128fb61
+Author: James Cloos <cloos@jhcloos.com>
+Date: Mon Sep 3 05:53:57 2007 -0400
+
+ Add *~ to .gitignore to skip patch/emacs droppings
+
+commit 5cf29b06b9b5806056a0b04160b2286eb4158748
+Author: Keith Packard <keithp@koto.keithp.com>
+Date: Fri Aug 31 13:43:18 2007 -0700
+
+ Don't add MTRR for uncached regions. Remove MTRR on unmap.
+
+ MTRR regions aren't needed for uncached mappings, so don't add them. Also,
+ when unmapping memory, remove the MTRR entry.
+
+commit ebc618e7508847307713a59aeeed337a9277629d
+Author: Ian Romanick <idr@us.ibm.com>
+Date: Fri Aug 31 12:40:03 2007 -0700
+
+ Update / add comments in struct pci_mem_region.
+
+commit 08ff9f7fbd26dd2d0e30351b556c71c272f6be6c
+Author: Ian Romanick <idr@us.ibm.com>
+Date: Thu Aug 30 17:52:02 2007 -0700
+
+ New interfaces to map memory with MTRR (or similar) support.
+
+ Added new functions pci_device_map_range and pci_device_unmap_range to
+ handle mapping of PCI device BARs. These new interfaces allow the
+ possiblity of MTRRs on platforms that support them.
+
+ These additional APIs necessitated changing some internal interfaces. The
+ code for FreeBSD and Solaris has been updated but has not been compiled or
+ tested.
+
+ Old interfaces are marked deprecated and will eventually be removed.
+
+commit c87273e8e20c8bff892ded31295dba103f27dd35
+Author: Eric Anholt <eric@anholt.net>
+Date: Tue Aug 28 16:02:46 2007 -0700
+
+ Make the base address printout of scanpci more usable.
+
+commit 47d625ccea7dbcd6b69009aa1ec64a96e97513f6
+Author: Ian Romanick <idr@us.ibm.com>
+Date: Mon Aug 27 16:41:52 2007 -0700
+
+ Bump version to 0.9.1 (sigh).
+
+commit 73197e09c924dabc18b8839180508584b97e03df
+Author: Ian Romanick <idr@us.ibm.com>
+Date: Mon Aug 27 16:41:21 2007 -0700
+
+ Add linux_devmem.h to file list.
+
+commit 5e595d09e7011b82a90f74b149a97bea23ddfbf0
+Author: Ian Romanick <idr@us.ibm.com>
+Date: Mon Aug 27 16:39:00 2007 -0700
+
+ Bump version to 0.9.0.
+
+commit b0c9558c97ee861af240a948c364807e628e49de
+Author: James Cloos <cloos@jhcloos.com>
+Date: Thu Aug 23 21:31:50 2007 -0400
+
+ Remove deprecated .cvsignore files
+
+commit 4e6be0466ad973ee6f63e0cbed466a974908dce8
+Author: Eric Anholt <eric@anholt.net>
+Date: Fri Aug 3 16:47:09 2007 -0700
+
+ FreeBSD: Add VGA rom reading through /dev/mem.
+
+commit ae4aed2821161028dabd8381273f3803a24340ad
+Author: Eric Anholt <eric@anholt.net>
+Date: Fri Aug 3 10:46:55 2007 -0700
+
+ FreeBSD: Fill in the subdevice ID.
+
+commit 14e62c77bd1ae6ef1d4048df2da96eeff8f7538f
+Author: Eric Anholt <eric@anholt.net>
+Date: Fri Aug 3 10:40:53 2007 -0700
+
+ Make scanpci exit cleanly if pci_system_init() fails.
+
+commit a7faac3d2dc49a2130906fbeea3298f32bb9349f
+Author: Ian Romanick <idr@us.ibm.com>
+Date: Mon Jun 18 12:56:40 2007 -0700
+
+ Initial support for reading expansion ROM via VGA BIOS address.
+
+commit 206e29213f92dd639fb4814ed2f3b6ec27e6f985
+Author: edward shu <edward.shu@sun.com>
+Date: Wed Jun 6 23:05:56 2007 +0800
+
+ Libpciaccess on Solaris Initial integration
+
+ Libpciaccess on Solaris Initial integration. It depends on devfs to access
+ pci configuration space, also xsvc is used for memory map.
+
+commit db56c640028d2f8072274f3eb603caa481103f4f
+Author: Ian Romanick <idr@us.ibm.com>
+Date: Tue Mar 27 08:01:39 2007 -0700
+
+ Whitespace police.
+
+commit c6e72deddb3055167fff8007bf039be61e45849e
+Author: Ian Romanick <idr@us.ibm.com>
+Date: Tue Mar 27 07:57:35 2007 -0700
+
+ Don't pci_device_probe until absolutely necessary.
+
+commit 28dc34c2a6045ab95183d708500009bd1eea1659
+Author: Ian Romanick <idr@us.ibm.com>
+Date: Tue Mar 27 07:57:00 2007 -0700
+
+ Make sure header_type is available in read_bridge_info.
+
+commit 061a011ceffc13db3b147dd105d8b7c2edcc3bc8
+Author: Ian Romanick <idr@us.ibm.com>
+Date: Tue Mar 27 07:56:16 2007 -0700
+
+ Populate device and vendor ID fields at device list creation.
+
+commit b36d737d92dbeee7951aded990fa52bac39b2a79
+Author: Eric Anholt <eric@anholt.net>
+Date: Tue Mar 6 10:48:51 2007 -0800
+
+ FreeBSD: Fix a couple of minor issues in cleanup paths.
+
+commit 09be109c223b93d74ea3cc7a12d9a22b44990a14
+Author: Eric Anholt <eric@anholt.net>
+Date: Thu Mar 1 10:49:13 2007 -0800
+
+ FreeBSD: Add system cleanup function.
+
+commit f6502eee20205ec14ce6499251a28962cc36fdd6
+Author: Eric Anholt <eric@anholt.net>
+Date: Wed Feb 28 16:25:07 2007 -0800
+
+ FreeBSD: When mapping regions, use the region's base address, not 0.
+
+commit a4ec2f35ea5b4f74cf455be24f8ad25d4096ab98
+Author: Eric Anholt <eric@anholt.net>
+Date: Wed Feb 28 16:13:44 2007 -0800
+
+ Fix inverted protection typo for mmap in region mapping.
+
+commit 9819ae0c376db57a9de5fcbb2f1d4c3ee1ed2ea8
+Author: Eric Anholt <eric@anholt.net>
+Date: Wed Feb 28 15:42:24 2007 -0800
+
+ scanpci prototype warning fix
+
+commit e70b710133cc552df266d5046a53f7a241a569eb
+Author: Eric Anholt <eric@anholt.net>
+Date: Wed Feb 28 15:39:38 2007 -0800
+
+ Update freebsd code for pci_device_cfg_write API change.
+
+commit d86245be3bd57b29e5b7561b3facecb3298fea3b
+Author: George Sapountzis <gsap7@yahoo.gr>
+Date: Wed Nov 15 02:49:50 2006 +0200
+
+ scanpci: BIST line offsets were off by 4.
+
+commit cc1d08f113140010f49503adc4e7afe5db892a02
+Author: Ian Romanick <idr@us.ibm.com>
+Date: Tue Jan 16 21:24:12 2007 -0800
+
+ Fix bad parameter to pci_device_cfg_write in pci_device_cfg_write_u8.
+
+ When changing the interface of the pci_device_cfg_write_u* functions
+ in commit 37ce43c1804bad9c52b8316eaefd3a57b670ee29, I forgot to modify
+ pci_device_cfg_write_u8 to pass a pointer to data to
+ pci_device_cfg_write instead of just passing data.
+
+commit 54d40b528ab769c4e89aaca87d1728a6194e4378
+Merge: 37ce43c 335d42f
+Author: Ian Romanick <idr@us.ibm.com>
+Date: Mon Jan 15 11:18:29 2007 -0800
+
+ Merge branch 'master' of git+ssh://git.freedesktop.org/git/xorg/lib/libpciaccess
+
+commit 37ce43c1804bad9c52b8316eaefd3a57b670ee29
+Author: Ian Romanick <idr@us.ibm.com>
+Date: Mon Jan 15 11:18:19 2007 -0800
+
+ Convert pci_device_write_u* funtions to take a value instead of a pointer.
+
+ At anholt's request, the pci_device_write_u* functions have been
+ converted to take the value to be written as a parameter instead of a
+ pointer to the value.
+
+ Bump the version to 0.8.0.
+
+commit 335d42f637dd44461bc20ba599ca5dc4971b6eaa
+Author: Eric Anholt <eric@anholt.net>
+Date: Fri Jan 12 16:32:51 2007 -0800
+
+ Add support for getting region information on FreeBSD.
+
+ This could stand a lot more testing -- all it has received is visual inspection
+ of scanpci output on one machine, with some differing results from XFree86
+ scanpci output.
+
+commit 94355b6f49a61e7424ddc7ddfc70a9b344233a47
+Author: Eric Anholt <eric@anholt.net>
+Date: Fri Jan 12 14:15:29 2007 -0800
+
+ Open the pci device read-write so we can read and write config regs.
+
+ With this, we can hook up the IRQ line information. It would probably be nice
+ to have an unpriveleged mode, but for now, write access is required.
+
+commit 253e7f672b8b311b18cf827cd12c9147bba8eb4c
+Author: Eric Anholt <eric@anholt.net>
+Date: Fri Jan 12 13:33:51 2007 -0800
+
+ Remove extra fallback definition of PCIIDS_PATH.
+
+ PCIIDS_PATH should always be provided by configure.ac and config.h.
+
+commit 87ec7de307ab5bd395d01cdb4f8fdf231d9e769e
+Author: Eric Anholt <eric@anholt.net>
+Date: Fri Jan 12 13:13:27 2007 -0800
+
+ Fix many warnings and bugs in the freebsd implementation.
+
+ With this, scanpci gives partially-sane results.
+
+commit 4f6e1a61fc0abe1865e147509af5f7f2bfcaf8f7
+Author: Eric Anholt <eric@anholt.net>
+Date: Fri Jan 12 13:11:21 2007 -0800
+
+ Enable more warnings when the compiler is GCC.
+
+commit c7ce8ee140b01931994030900c0e8238fbb0caa2
+Author: Eric Anholt <eric@anholt.net>
+Date: Fri Jan 12 13:06:50 2007 -0800
+
+ Add pciaccess_private.h to _SOURCES so it gets included in the dist.
+
+commit c65aa7630802c8dfcc06a20e515ace31ab0d0e48
+Author: Ian Romanick <idr@us.ibm.com>
+Date: Thu Jan 11 21:40:57 2007 -0800
+
+ Add interfaces to map / unmap specific memory ranges, bump lib version to 0.7.0.
+
+ Add pci_device_map_memory_range and pci_device_unmap_memory_range to
+ map and unmap specific memory ranges. The unmap bit is still a bit
+ hinkey (unmaps the whole BAR). Works so far for initial conversion of
+ VESA driver. Will need to be revisited.
+
+commit db4a12d09fba381f39af024418e913fb99c34935
+Author: Ian Romanick <idr@us.ibm.com>
+Date: Thu Jan 11 21:39:15 2007 -0800
+
+ Fix bad cast that caused bit truncation.
+
+commit 8948a6c3593d92a50a09baf568b69f164d7e7f59
+Author: Eric Anholt <eric@anholt.net>
+Date: Tue Nov 14 14:38:48 2006 -0800
+
+ Update .gitignores.
+
+commit 1d227d67d35aba4601c4ffd6a2947ee746d5dc47
+Author: Eric Anholt <eric@anholt.net>
+Date: Tue Nov 14 14:37:53 2006 -0800
+
+ Add missing newline at the end of the file.
+
+commit e29843d3b0ff5d32d8ab4bc84c58300782d189d3
+Merge: 07b09d9 d05da65
+Author: Eric Anholt <eric@anholt.net>
+Date: Tue Nov 14 14:37:46 2006 -0800
+
+ Merge branch 'origin'
+
+ Conflicts:
+
+ src/Makefile.am
+
+commit 07b09d930ed2b7eae299ae036ec30099374b95aa
+Author: Eric Anholt <anholt@FreeBSD.org>
+Date: Sun Jul 30 16:19:50 2006 -0700
+
+ Add the beginnings of a FreeBSD port.
+
+commit d05da6520a273ee4c2f0e11b5a9bac65b51835fe
+Author: Ian Romanick <idr@localhost.localdomain>
+Date: Thu Aug 10 09:46:07 2006 -0700
+
+ Fix a segfault in populate_vendor that was triggered when the pci.ids file
+ could not be opened. Thanks to Aaron Plattner for reporting this. Fix a
+ couple possible memory leaks in the same function.
+
+commit 27f0ffca71277371a0b6c0cd1a720a9ce9519da5
+Author: Ian Romanick <idr@localhost.localdomain>
+Date: Sun Jul 30 15:35:41 2006 -0700
+
+ Added some function preamble comments.
+
+commit cf1b4d3ddfcdbaeddefc42b6eb19eb85a0a1e454
+Author: Eric Anholt <anholt@FreeBSD.org>
+Date: Sun Jul 30 14:29:58 2006 -0700
+
+ Add endian macros for BSD.
+
+commit edf3908958eacc20162563b68aa45964f0e38b2c
+Author: Eric Anholt <anholt@FreeBSD.org>
+Date: Sun Jul 30 14:26:38 2006 -0700
+
+ Use ENXIO instead of ENODATA for pci reads returning less than desired.
+
+commit c0e31708e0446b33240d3e1ba3e36c26a618544c
+Author: Ian Romanick <idr@umwelt.(none)>
+Date: Tue Jul 25 15:36:52 2006 -0700
+
+ Add pci_device_get_bridge_buses, bump API version to 0.5.0.
+
+commit 2ba1a0e42928f82e678987c84598e1b9d8ba1ef9
+Author: Ian Romanick <idr@umwelt.(none)>
+Date: Thu Jul 6 17:18:14 2006 -0700
+
+ Files missed (for reasons I still don't understand) on the previous
+ commit. REALLY add support for querying bridge information. Bump to
+ version 0.5.0.
+
+commit c0ff6e6141ee6ebb1f628931ae62f0fa8ef87061
+Author: Ian Romanick <idr@umwelt.(none)>
+Date: Thu Jul 6 17:09:47 2006 -0700
+
+ Add support for querying bridge information. Bump to version 0.5.0.
+
+commit 2467b3c509c7e5b771ca21ee6317b2d72d481439
+Author: Ian Romanick <idr@umwelt.(none)>
+Date: Thu Jul 6 17:07:18 2006 -0700
+
+ Fix byte ordering of the PCI class.
+
+commit 70a66689fc2e44e7cd693947ed5f3f2acb4b6587
+Author: Ian Romanick <idr@us.ibm.com>
+Date: Mon May 22 16:10:37 2006 +0000
+
+ Fix foolish endianess bug. Bump to version 0.4.1.
+
+commit 64af050c3803ed61837d9e9109c7a4e239a5c0b8
+Author: Ian Romanick <idr@us.ibm.com>
+Date: Wed Apr 12 22:56:50 2006 +0000
+
+ Bump to version 0.4.0.
+ Add multiple-inclusion protection.
+ Add new function to write masked bits to PCI config space. This mirrors
+ functionality currently available in X.org that is slated to be
+ removed.
+ Gut old regex based search mechanism with a new mechanism that is modeled
+ after the Linux kernel. In addition to searching for devices by device
+ / vendor ID, it is possible to search for devices by their domain / bus
+ / slot / function.
+ Fix serious bus in the reading of ROMs and in the unmapping of regions. The
+ main point is that the map routine depens on the pci_mem_region::memory
+ pointer being non-NULL only when the region is mapped. Therefore, the
+ unmap routine should set it to NULL after unmapping.
+ Update to use new search API.
+
+commit 5b4db5c392c123f71a7933bd94c789b5e23dd69a
+Author: Ian Romanick <idr@us.ibm.com>
+Date: Mon Mar 27 18:08:42 2006 +0000
+
+ Remove src/pcils.c and src/Makefile.foo. Add src/scanpci.c.
+ Bump version to 0.3.0.
+ Replace pci_get_name with pci_get_strings. This function matches the
+ functionality provided by the Xorg scanpci module almost identically.
+
+commit 6b1e9fae2ab9979b2a3bb3137c5db4d92d2905c8
+Author: Ian Romanick <idr@us.ibm.com>
+Date: Fri Mar 24 16:57:17 2006 +0000
+
+ Remove src/Makefile.foo from CVS since the generated Makefile can do
+ everything now.
+
+commit d890ded5312dc88455fd332e03a4f212ba587e9d
+Author: Kristian Høgsberg <krh@redhat.com>
+Date: Mon Mar 20 20:13:34 2006 +0000
+
+ Add scanpci as a noinst target.
+ Drop from CVS.
+
+commit 5a04522a921cd8737ef921dfd49b750a8c64dfc9
+Author: Ian Romanick <idr@us.ibm.com>
+Date: Sat Mar 18 00:12:48 2006 +0000
+
+ Initial import of libpciaccess.
--- /dev/null
+#
+# (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 autoconf macros from m4 subdir
+ACLOCAL_AMFLAGS = -I m4
+
+SUBDIRS = src
+
+pkgconfigdir = $(libdir)/pkgconfig
+pkgconfig_DATA = pciaccess.pc
+
+MAINTAINERCLEANFILES = ChangeLog INSTALL
+EXTRA_DIST = src/scanpci.c src/scanpci.man
+
+.PHONY: ChangeLog INSTALL
+
+INSTALL:
+ $(INSTALL_CMD)
+
+ChangeLog:
+ $(CHANGELOG_CMD)
+
+dist-hook: ChangeLog INSTALL
--- /dev/null
+xorg/lib/libpciaccess - Generic PCI access library
+
+Documentation of the libpciaccess API's can be generated from the
+sources via the doxygen command. Information about porting Xorg
+drivers to libpciaccess is located at:
+
+ http://www.x.org/wiki/PciReworkHowto
+
+For historical reference, the original proposal for this work is at:
+
+ http://www.x.org/wiki/PciReworkProposal
+
+All questions regarding this software should be directed at the
+Xorg mailing list:
+
+ http://lists.freedesktop.org/mailman/listinfo/xorg
+
+Please submit bug reports to the Xorg bugzilla:
+
+ https://bugs.freedesktop.org/enter_bug.cgi?product=xorg
+
+The master development code repository can be found at:
+
+ git://anongit.freedesktop.org/git/xorg/lib/libpciaccess
+
+ http://cgit.freedesktop.org/xorg/lib/libpciaccess
+
+For patch submission instructions, see:
+
+ http://www.x.org/wiki/Development/Documentation/SubmittingPatches
+
+For more information on the git code manager, see:
+
+ http://wiki.x.org/wiki/GitPage
+
--- /dev/null
+#! /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 "$@"
--- /dev/null
+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_PREREQ([2.60])
+
+AC_INIT(libpciaccess, 0.12.0, [https://bugs.freedesktop.org/enter_bug.cgi?product=xorg&component=libpciaccess], libpciaccess)
+AM_INIT_AUTOMAKE([foreign dist-bzip2])
+AM_MAINTAINER_MODE
+
+# Require xorg-macros: XORG_DEFAULT_OPTIONS
+m4_ifndef([XORG_MACROS_VERSION],
+ [m4_fatal([must install xorg-macros 1.3 or later before running autoconf/autogen])])
+XORG_MACROS_VERSION(1.3)
+XORG_DEFAULT_OPTIONS
+AM_CONFIG_HEADER(config.h)
+
+# Check for progs
+AC_PROG_CC
+AC_PROG_LIBTOOL
+
+pciids_path=/usr/share/hwdata
+AC_ARG_WITH(pciids-path, AC_HELP_STRING([--with-pciids-path=PCIIDS_PATH],
+ [Path to pci.ids file]), [pciids_path="$withval"])
+AC_DEFINE_DIR(PCIIDS_PATH, pciids_path, [Path to pci.ids])
+
+AC_ARG_ENABLE(linux-rom-fallback, AS_HELP_STRING([--enable-linux-rom-fallback],
+ [Enable support for falling back to /dev/mem for roms (default: disabled)]),
+ [LINUX_ROM=$enableval],[LINUX_ROM=no])
+
+if test "x$LINUX_ROM" = xyes; then
+ AC_DEFINE(LINUX_ROM, 1, [Linux ROM read fallback])
+fi
+
+use_zlib=no
+AC_ARG_WITH(zlib, AC_HELP_STRING([--with-zlib],
+ [Enable zlib support to read gzip compressed pci.ids]),
+ [use_zlib="$withval"])
+if test "x$use_zlib" = xyes; then
+ AC_CHECK_LIB(z, gzopen,
+ [PCIACCESS_LIBS="$PCIACCESS_LIBS -lz"],
+ [AC_MSG_ERROR(Check for zlib library failed)])
+ AC_CHECK_HEADER([zlib.h],
+ [AC_DEFINE(HAVE_ZLIB, 1, [Use zlib to read gzip compressed pci.ids])],
+ [AC_MSG_ERROR(Check for zlib.h header file failed)])
+fi
+
+case $host_os in
+ *freebsd* | *dragonfly*)
+ freebsd=yes
+ ;;
+ *linux*)
+ linux=yes
+ ;;
+ *netbsd*)
+ case $host in
+ *i386*)
+ PCIACCESS_LIBS="-li386"
+ ;;
+ *x86_64*|*amd64*)
+ PCIACCESS_LIBS="-lx86_64"
+ ;;
+ esac
+ netbsd=yes
+ ;;
+ *openbsd*)
+ openbsd=yes
+ ;;
+ *solaris*)
+ solaris=yes
+ PCIACCESS_LIBS="$PCIACCESS_LIBS -ldevinfo"
+ ;;
+ gnu*)
+ gnu=yes
+ ;;
+esac
+
+AM_CONDITIONAL(LINUX, [test "x$linux" = xyes])
+AM_CONDITIONAL(FREEBSD, [test "x$freebsd" = xyes])
+AM_CONDITIONAL(NETBSD, [test "x$netbsd" = xyes])
+AM_CONDITIONAL(OPENBSD, [test "x$openbsd" = xyes])
+AM_CONDITIONAL(SOLARIS, [test "x$solaris" = xyes])
+AM_CONDITIONAL(GNU, [test "x$gnu" = xyes])
+
+AC_SYS_LARGEFILE
+
+AC_CHECK_HEADER([asm/mtrr.h], [have_mtrr_h="yes"], [have_mtrr_h="no"])
+
+if test "x$have_mtrr_h" = xyes; then
+ AC_DEFINE(HAVE_MTRR, 1, [Use MTRRs on mappings])
+fi
+
+dnl check for the pci_io.pi_sel.pc_domain
+AC_CHECK_MEMBER([struct pci_io.pi_sel.pc_domain],
+ [AC_DEFINE(HAVE_PCI_IO_PC_DOMAIN,1,[Have the pci_io.pi_sel.pc_domain member.])],
+ [],
+ [ #include <sys/types.h>
+ #include <sys/pciio.h>
+ ])
+
+AC_SUBST(PCIACCESS_CFLAGS)
+AC_SUBST(PCIACCESS_LIBS)
+
+
+AC_OUTPUT([Makefile
+ src/Makefile
+ pciaccess.pc])
--- /dev/null
+This package uses quilt to manage modifications to the upstream source.
+Changes are stored in the source package as diffs in debian/patches and
+applied during the build.
+
+See /usr/share/doc/quilt/README.source in the quilt package for details.
+
+ -- Julien Cristau <jcristau@debian.org> Sat, 08 Aug 2009 18:42:21 +0200
--- /dev/null
+libpciaccess (0.12.0-2slp2) unstable; urgency=low
+
+ * [X11R7.6] upgrade package
+ * Git: 165.213.180.234:slp/pkgs/xorg/lib/libpciaccess
+ * Tag: libpciaccess_0.12.0-2slp2
+
+ -- SooChan Lim <sc1.lim@samsung.com> Mon, 03 Jan 2011 22:02:39 +0900
+
+libpciaccess (0.12.0-1) unstable; urgency=low
+
+ * New upstream release:
+ - x86 backend for hurd
+ - various fixes for vgaarb, leak, use after free
+ - fix long standing MTRR bug
+ * Drop pciaccess-hurd-hack.diff and patch system.
+ * Update debian/copyright from upstream COPYING.
+ * Bump Standards-Version to 3.9.0.
+
+ -- Julien Cristau <jcristau@debian.org> Sat, 24 Jul 2010 11:20:30 +0200
+
+libpciaccess (0.11.0-2) unstable; urgency=low
+
+ [ Julien Cristau ]
+ * Remove myself from Uploaders
+
+ [ Cyril Brulebois ]
+ * Add udeb needed for the graphical installer: libpciaccess0-udeb.
+ * Add myself to Uploaders.
+ * Bump Standards-Version from 3.7.3 to 3.8.4 (no changes needed).
+
+ -- Cyril Brulebois <kibi@debian.org> Tue, 09 Mar 2010 02:05:55 +0100
+
+libpciaccess (0.11.0-1) unstable; urgency=low
+
+ * New upstream release.
+ * Bump xutils-dev build-dep for util-macros 1.4.
+ * Rename the build directory to not include DEB_BUILD_GNU_TYPE for no
+ good reason. Thanks, Colin Watson!
+ * Refresh pciaccess-hurd-hack.diff.
+ * Update libpciaccess0.symbols and bump shlibs.
+ * Add build-dep on pkg-config.
+ * Bump Standards-Version to 3.8.3.
+
+ -- Julien Cristau <jcristau@debian.org> Sun, 17 Jan 2010 14:36:38 +0000
+
+libpciaccess (0.10.9-1) unstable; urgency=low
+
+ * New upstream release.
+ * Refresh pciaccess-hurd-hack.diff.
+ * Update shlibs and symbols file.
+
+ -- Julien Cristau <jcristau@debian.org> Mon, 28 Sep 2009 18:29:27 +0200
+
+libpciaccess (0.10.6-2) unstable; urgency=low
+
+ * Apply patch from Samuel Thibault to tinker with I/O ports on systems
+ without a PCI interface, such as GNU/Hurd (closes: #524111).
+ * debian/rules: clean out libtool m4 files.
+ * Make glob in debian/libpciaccess0.install more strict.
+ * Add README.source pointing at the quilt package.
+ * Bump Standards-Version to 3.8.2.
+ * Version debhelper build-dep to silence lintian.
+
+ -- Julien Cristau <jcristau@debian.org> Sat, 08 Aug 2009 18:49:40 +0200
+
+libpciaccess (0.10.6-1) unstable; urgency=low
+
+ * New upstream release
+ + Update debian/copyright with new information from COPYING
+ + Add versioned xutils-dev to build-dep, as the macros are now required
+ * Update standards version to 3.8.1.0. No changes necessary.
+
+ -- David Nusinow <dnusinow@debian.org> Mon, 27 Apr 2009 21:16:01 -0400
+
+libpciaccess (0.10.5-3) unstable; urgency=low
+
+ * Upload to unstable, for real this time.
+
+ -- Julien Cristau <jcristau@debian.org> Mon, 16 Feb 2009 15:52:10 +0100
+
+libpciaccess (0.10.5-2) experimental; urgency=low
+
+ * Upload to unstable.
+
+ -- Julien Cristau <jcristau@debian.org> Mon, 16 Feb 2009 01:12:29 +0100
+
+libpciaccess (0.10.5-1) experimental; urgency=low
+
+ * New upstream release
+ + Fixes PCI domain support on kfreebsd (closes: #501333)
+ * Run autoreconf at build time, cleanup generated files in clean.
+ * Allow reading compressed pci.ids file (closes: #478696).
+
+ -- Julien Cristau <jcristau@debian.org> Wed, 12 Nov 2008 20:13:13 +0100
+
+libpciaccess (0.10.3-1) unstable; urgency=low
+
+ [ Julien Cristau ]
+ * Add watch file.
+ * New upstream release.
+ * Bump shlibs and update symbols file.
+ * Suggest pciutils, which provides the pci.ids list.
+
+ [ Brice Goglin ]
+ * Update upstream URL in debian/copyright.
+ * Drop the XS- prefix from Vcs-Git and Vcs-Browser fields in debian/control.
+
+ -- Julien Cristau <jcristau@debian.org> Sun, 13 Jul 2008 14:58:51 +0200
+
+libpciaccess (0.10-1) unstable; urgency=low
+
+ * New upstream release.
+ * Install the upstream changelog.
+
+ -- Julien Cristau <jcristau@debian.org> Fri, 07 Mar 2008 14:43:39 +0100
+
+libpciaccess (0.9.1+git20080219-1) unstable; urgency=low
+
+ * Add a symbols file for libpciaccess.so.0.
+ * Bump shlibs to >= 0.8.0+git20071002 (this version added the
+ pci_device_{un,}map_range functions)
+ * Bump Standards-Version to 3.7.3.
+ * New upstream snapshot.
+ * Fix build on non-linux glibc architectures.
+
+ -- Julien Cristau <jcristau@debian.org> Tue, 19 Feb 2008 16:13:05 +0100
+
+libpciaccess (0.8.0+git20071002-1) experimental; urgency=low
+
+ * Debian stores its pci.ids list in /usr/share/misc. Use that for the
+ --with-pciids-path configure option so the library can fill in certain
+ values correctly
+ * New upstream git pull
+ * Add myself to uploaders
+
+ -- David Nusinow <dnusinow@debian.org> Tue, 02 Oct 2007 21:40:38 -0400
+
+libpciaccess (0.8.0+git20070628-1) experimental; urgency=low
+
+ * New upstream snapshot.
+ * Make configure executable in debian/rules clean (closes: #430932); thanks,
+ Frank Lichtenheld!
+
+ -- Julien Cristau <jcristau@debian.org> Fri, 29 Jun 2007 01:02:18 +0100
+
+libpciaccess (0.8.0+git20070613-1) experimental; urgency=low
+
+ * Initial upload (closes: #428776).
+
+ -- Julien Cristau <jcristau@debian.org> Thu, 14 Jun 2007 23:09:50 +0200
--- /dev/null
+Source: libpciaccess
+Section: devel
+Priority: optional
+Maintainer: Sung-Jin Park <sj76.park@samsung.com>, Sangjin Lee <lsj119@samsung.com>, Debian X Strike Force <debian-x@lists.debian.org>
+Uploaders: Sung-Jin Park <sj76.park@samsung.com>, SooChan Lim <sc1.lim@samsung.com>, David Nusinow <dnusinow@debian.org>, Cyril Brulebois <kibi@debian.org>
+Build-Depends: debhelper (>= 5), libtool, automake, zlib1g-dev, xutils-dev (>= 1:7.5), pkg-config,
+Standards-Version: 3.9.0
+
+Package: libpciaccess0
+Section: libs
+Architecture: any
+Depends: ${shlibs:Depends}, ${misc:Depends}
+Suggests: pciutils
+Description: Generic PCI access library for X
+ Provides functionality for X to access the PCI bus and devices
+ in a platform-independant way.
+
+#Package: libpciaccess0-udeb
+#XC-Package-Type: udeb
+#Section: debian-installer
+#Architecture: any
+#Depends: ${shlibs:Depends}, ${misc:Depends}
+#Suggests: pciutils
+#Description: Generic PCI access library for X
+# This is a udeb, or a microdeb, for the debian-installer.
+
+Package: libpciaccess-dev
+Section: libdevel
+Architecture: any
+Depends: libpciaccess0 (= ${binary:Version}), ${shlibs:Depends}, ${misc:Depends}
+Description: Generic PCI access library for X - development files
+ Provides functionality for X to access the PCI bus and devices
+ in a platform-independant way.
+ .
+ This package contains the development files for libpciaccess.
+
+Package: libpciaccess0-dbg
+Section: debug
+Architecture: any
+Depends: ${shlibs:Depends}, ${misc:Depends}, libpciaccess0 (=${Source-Version})
+Description: Debug package os libpciaccess0
--- /dev/null
+This package was downloaded from
+http://xorg.freedesktop.org/releases/individual/lib/
+
+It was debianized by Julien Cristau <jcristau@debian.org> on
+Wed, 13 Jun 2007, with package descriptions taken from a package by
+Matthew Garrett <mjg59@srcf.ucam.org>.
+
+The Debian packaging is (C) 2007, Matthew Garrett <mjg59@srcf.ucam.org> and
+Julien Cristau <jcristau@debian.org>, and is licensed under the GPL, see
+`/usr/share/common-licenses/GPL'.
+
+Upstream authors:
+
+ Ian Romanick <idr@us.ibm.com>
+ Eric Anholt <eric@anholt.com>
+ edward shu <edward.shu@sun.com>
+
+Copyright:
+
+(C) Copyright IBM Corporation 2006, 2007
+(C) Copyright Eric Anholt 2006
+Copyright 2007, 2008, 2009 Sun Microsystems, Inc.
+Copyright 2009 Red Hat, Inc.
+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.
+
+------------------------------------------------------------------------------
+
+Copyright (c) 2008 Juan Romero Pardines
+Copyright (c) 2008 Mark Kettenis
+Copyright (c) 2009 Samuel Thibault
+
+Permission to use, copy, modify, and distribute this software for any
+purpose with or without fee is hereby granted, provided that the above
+copyright notice and this permission notice appear in all copies.
+
+THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+------------------------------------------------------------------------------
+
+Copyright (C) 2000 The XFree86 Project, Inc. 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 the
+rights to use, copy, modify, merge, publish, distribute, sublicense, 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 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 NONINFRINGEMENT. IN NO EVENT SHALL THE
+XFREE86 PROJECT 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.
+
+Except as contained in this notice, the name of the XFree86 Project shall
+not be used in advertising or otherwise to promote the sale, use or other
+dealings in this Software without prior written authorization from the
+XFree86 Project.
--- /dev/null
+usr/lib/pkgconfig
+usr/lib/lib*.a
+usr/lib/lib*.so
+usr/include
--- /dev/null
+usr/lib/libpciaccess.so.0*
--- /dev/null
+usr/lib/libpciaccess.so.0*
--- /dev/null
+libpciaccess.so.0 libpciaccess0 #MINVER#
+ pci_device_next@Base 0
+ pci_device_map_region@Base 0
+ pci_device_cfg_read_u32@Base 0
+ pci_system_init@Base 0
+ pci_system_init_dev_mem@Base 0.10.2
+ pci_device_cfg_write_u16@Base 0
+ pci_device_enable@Base 0.10.2
+ pci_get_strings@Base 0
+ pci_device_map_memory_range@Base 0
+ pci_device_get_subvendor_name@Base 0
+ pci_device_probe@Base 0
+ pci_device_cfg_write@Base 0
+ pci_device_unmap_region@Base 0
+ pci_device_vgaarb_decodes@Base 0.10.7
+ pci_device_vgaarb_fini@Base 0.10.7
+ pci_device_vgaarb_get_info@Base 0.10.7
+ pci_device_vgaarb_init@Base 0.10.7
+ pci_device_vgaarb_lock@Base 0.10.7
+ pci_device_vgaarb_set_target@Base 0.10.7
+ pci_device_vgaarb_trylock@Base 0.10.7
+ pci_device_vgaarb_unlock@Base 0.10.7
+ pci_device_cfg_read_u16@Base 0
+ pci_device_get_device_name@Base 0
+ pci_device_find_by_slot@Base 0
+ pci_id_match_iterator_create@Base 0
+ pci_device_cfg_write_u8@Base 0
+ pci_device_get_subdevice_name@Base 0
+ pci_device_unmap_range@Base 0.8.0+git20071002
+ pci_device_get_bridge_info@Base 0
+ pci_system_cleanup@Base 0
+ pci_device_cfg_read_u8@Base 0
+ pci_iterator_destroy@Base 0
+ pci_device_read_rom@Base 0
+ pci_device_map_range@Base 0.8.0+git20071002
+ pci_slot_match_iterator_create@Base 0
+ pci_device_cfg_write_u32@Base 0
+ pci_device_unmap_memory_range@Base 0
+ pci_device_get_agp_info@Base 0
+ pci_device_get_pcmcia_bridge_info@Base 0
+ pci_device_get_bridge_buses@Base 0
+ pci_device_cfg_write_bits@Base 0
+ pci_device_get_vendor_name@Base 0
+ pci_device_has_kernel_driver@Base 0.10.7
+ pci_device_is_boot_vga@Base 0.10.7
+ pci_device_cfg_read@Base 0
+ pci_device_get_parent_bridge@Base 0.11.0
+ pci_device_open_io@Base 0.11.0
+ pci_device_close_io@Base 0.11.0
+ pci_legacy_open_io@Base 0.11.0
+ pci_io_read8@Base 0.11.0
+ pci_io_read16@Base 0.11.0
+ pci_io_read32@Base 0.11.0
+ pci_io_write8@Base 0.11.0
+ pci_io_write16@Base 0.11.0
+ pci_io_write32@Base 0.11.0
--- /dev/null
+#!/usr/bin/make -f
+
+PACKAGE = libpciaccess0
+
+CFLAGS = -Wall -g
+ifneq (,$(filter noopt,$(DEB_BUILD_OPTIONS)))
+ CFLAGS += -O0
+else
+ CFLAGS += -O2
+endif
+ifneq (,$(filter parallel=%,$(DEB_BUILD_OPTIONS)))
+ NUMJOBS = $(patsubst parallel=%,%,$(filter parallel=%,$(DEB_BUILD_OPTIONS)))
+ MAKEFLAGS += -j$(NUMJOBS)
+endif
+
+DEB_HOST_ARCH ?= $(shell dpkg-architecture -qDEB_HOST_ARCH)
+DEB_HOST_GNU_TYPE ?= $(shell dpkg-architecture -qDEB_HOST_GNU_TYPE)
+DEB_BUILD_GNU_TYPE ?= $(shell dpkg-architecture -qDEB_BUILD_GNU_TYPE)
+ifeq ($(DEB_BUILD_GNU_TYPE), $(DEB_HOST_GNU_TYPE))
+ confflags += --build=$(DEB_HOST_GNU_TYPE)
+else
+ confflags += --build=$(DEB_HOST_GNU_TYPE) --host=$(DEB_HOST_GNU_TYPE)
+# confflags += --build=$(DEB_BUILD_GNU_TYPE) --host=$(DEB_HOST_GNU_TYPE)
+endif
+
+configure:
+ autoreconf -vfi
+
+obj-$(DEB_BUILD_GNU_TYPE)/config.status: configure
+ mkdir -p obj-$(DEB_BUILD_GNU_TYPE)
+ cd obj-$(DEB_BUILD_GNU_TYPE) && \
+ ../configure \
+ --prefix=/usr \
+ --mandir=\$${prefix}/share/man \
+ --infodir=\$${prefix}/share/info \
+ --with-pciids-path=\$${prefix}/share/misc \
+ --with-zlib \
+ $(confflags) \
+ CFLAGS="$(CFLAGS)"
+
+build: build-stamp
+build-stamp: obj-$(DEB_BUILD_GNU_TYPE)/config.status
+ dh_testdir
+ cd obj-$(DEB_BUILD_GNU_TYPE) && $(MAKE)
+
+ touch build-stamp
+
+clean:
+ dh_testdir
+ dh_testroot
+ rm -f build-stamp
+
+ rm -f config.cache config.log config.status
+ rm -f */config.cache */config.log */config.status
+ rm -f conftest* */conftest*
+# rm -rf autom4te.cache */autom4te.cache
+ rm -rf obj-*
+ rm -f $$(find -name Makefile.in)
+ rm -f compile config.guess config.sub configure depcomp install-sh
+ rm -f ltmain.sh missing INSTALL aclocal.m4 mkinstalldirs config.h.in
+ rm -f m4/libtool.m4 m4/lt*.m4
+
+ dh_clean
+
+install: build
+ dh_testdir
+ dh_testroot
+ dh_clean -k
+ dh_installdirs
+
+ cd obj-$(DEB_BUILD_GNU_TYPE) && $(MAKE) DESTDIR=$(CURDIR)/debian/tmp install
+
+# Install architecture-dependent files here.
+binary-arch: build install
+ dh_testdir
+ dh_testroot
+
+# dh_installdocs
+ dh_install --sourcedir=debian/tmp --list-missing
+# dh_installchangelogs ChangeLog
+ dh_link
+ dh_strip --dbg-package=$(PACKAGE)-dbg
+ dh_compress
+ dh_fixperms
+ dh_makeshlibs -V'libpciaccess0 (>= 0.11.0)'
+# dh_makeshlibs -V'libpciaccess0 (>= 0.11.0)' --add-udeb=$(PACKAGE)-udeb
+ dh_shlibdeps
+ dh_installdeb
+ dh_gencontrol
+ dh_md5sums
+ dh_builddeb
+
+binary-indep: build install
+# Nothing to do
+
+binary: binary-indep binary-arch
+.PHONY: build clean binary-indep binary-arch binary install
--- /dev/null
+version=3
+http://xorg.freedesktop.org/releases/individual/lib/ libpciaccess-(.*)\.tar\.gz
--- /dev/null
+/*
+ * (C) Copyright IBM Corporation 2006
+ * Copyright 2009 Red Hat, Inc.
+ * 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.
+ */
+/*
+ * Copyright (c) 2007 Paulo R. Zanoni, Tiago Vignatti
+ *
+ * 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 the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, 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 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
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS 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>
+ */
+
+#ifndef PCIACCESS_H
+#define PCIACCESS_H
+
+#include <inttypes.h>
+
+#if __GNUC__ >= 3
+#define __deprecated __attribute__((deprecated))
+#else
+#define __deprecated
+#endif
+
+typedef uint64_t pciaddr_t;
+
+struct pci_device;
+struct pci_device_iterator;
+struct pci_id_match;
+struct pci_slot_match;
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+int pci_device_has_kernel_driver(struct pci_device *dev);
+
+int pci_device_is_boot_vga(struct pci_device *dev);
+
+int pci_device_read_rom(struct pci_device *dev, void *buffer);
+
+int __deprecated pci_device_map_region(struct pci_device *dev,
+ unsigned region, int write_enable);
+
+int __deprecated pci_device_unmap_region(struct pci_device *dev,
+ unsigned region);
+
+int pci_device_map_range(struct pci_device *dev, pciaddr_t base,
+ pciaddr_t size, unsigned map_flags, void **addr);
+
+int pci_device_unmap_range(struct pci_device *dev, void *memory,
+ pciaddr_t size);
+
+int __deprecated pci_device_map_memory_range(struct pci_device *dev,
+ pciaddr_t base, pciaddr_t size, int write_enable, void **addr);
+
+int __deprecated pci_device_unmap_memory_range(struct pci_device *dev,
+ void *memory, pciaddr_t size);
+
+int pci_device_probe(struct pci_device *dev);
+
+const struct pci_agp_info *pci_device_get_agp_info(struct pci_device *dev);
+
+const struct pci_bridge_info *pci_device_get_bridge_info(
+ struct pci_device *dev);
+
+const struct pci_pcmcia_bridge_info *pci_device_get_pcmcia_bridge_info(
+ struct pci_device *dev);
+
+int pci_device_get_bridge_buses(struct pci_device *dev, int *primary_bus,
+ int *secondary_bus, int *subordinate_bus);
+
+int pci_system_init(void);
+
+void pci_system_init_dev_mem(int fd);
+
+void pci_system_cleanup(void);
+
+struct pci_device_iterator *pci_slot_match_iterator_create(
+ const struct pci_slot_match *match);
+
+struct pci_device_iterator *pci_id_match_iterator_create(
+ const struct pci_id_match *match);
+
+void pci_iterator_destroy(struct pci_device_iterator *iter);
+
+struct pci_device *pci_device_next(struct pci_device_iterator *iter);
+
+struct pci_device *pci_device_find_by_slot(uint32_t domain, uint32_t bus,
+ uint32_t dev, uint32_t func);
+
+struct pci_device *pci_device_get_parent_bridge(struct pci_device *dev);
+
+void pci_get_strings(const struct pci_id_match *m,
+ const char **device_name, const char **vendor_name,
+ const char **subdevice_name, const char **subvendor_name);
+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);
+
+void pci_device_enable(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, uint8_t data,
+ pciaddr_t offset);
+int pci_device_cfg_write_u16(struct pci_device *dev, uint16_t data,
+ pciaddr_t offset);
+int pci_device_cfg_write_u32(struct pci_device *dev, uint32_t data,
+ pciaddr_t offset);
+int pci_device_cfg_write_bits(struct pci_device *dev, uint32_t mask,
+ uint32_t data, pciaddr_t offset);
+
+#ifdef __cplusplus
+}
+#endif
+
+/**
+ * \name Mapping flags passed to \c pci_device_map_range
+ */
+/*@{*/
+#define PCI_DEV_MAP_FLAG_WRITABLE (1U<<0)
+#define PCI_DEV_MAP_FLAG_WRITE_COMBINE (1U<<1)
+#define PCI_DEV_MAP_FLAG_CACHABLE (1U<<2)
+/*@}*/
+
+
+#define PCI_MATCH_ANY (~0)
+
+/**
+ * Compare two PCI ID values (either vendor or device). This is used
+ * internally to compare the fields of \c pci_id_match to the fields of
+ * \c pci_device.
+ */
+#define PCI_ID_COMPARE(a, b) \
+ (((a) == PCI_MATCH_ANY) || ((a) == (b)))
+
+/**
+ */
+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;
+};
+
+
+/**
+ */
+struct pci_slot_match {
+ /**
+ * \name Device slot matching controls
+ *
+ * Control the search based on the domain, bus, slot, and function of
+ * the device. Setting any of these fields to \c PCI_MATCH_ANY will cause
+ * the field to not be used in the comparison.
+ */
+ /*@{*/
+ uint32_t domain;
+ uint32_t bus;
+ uint32_t dev;
+ uint32_t func;
+ /*@}*/
+
+ 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.
+ *
+ * This field is \b only set when the deprecated \c pci_device_map_region
+ * interface is used. Use \c pci_device_map_range instead.
+ *
+ * \deprecated
+ */
+ void *memory;
+
+
+ /**
+ * Base physical address of the region within its bus / domain.
+ *
+ * \warning
+ * This address is really only useful to other devices in the same
+ * domain. It's probably \b not the address applications will ever
+ * use.
+ *
+ * \warning
+ * Most (all?) platform back-ends leave this field unset.
+ */
+ pciaddr_t bus_addr;
+
+
+ /**
+ * Base physical address of the region from the CPU's point of view.
+ *
+ * This address is typically passed to \c pci_device_map_range to create
+ * a mapping of the region to the CPU's virtual address space.
+ */
+ 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, subclass, and programming interface packed into a
+ * single 32-bit value. The class is at bits [23:16], subclass is at
+ * bits [15:8], and programming interface is at [7:0].
+ */
+ 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.
+ */
+ intptr_t user_data;
+
+ /**
+ * Used by the VGA arbiter. Type of resource decoded by the device and
+ * the file descriptor (/dev/vga_arbiter). */
+ int vgaarb_rsrc;
+};
+
+
+/**
+ * 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;
+
+ unsigned int fast_writes:1; /**< Are fast-writes supported? */
+ unsigned int addr64:1;
+ unsigned int htrans:1;
+ unsigned int gart64:1;
+ unsigned int coherent:1;
+ unsigned int sideband:1; /**< Is side-band addressing supported? */
+ unsigned int isochronus:1;
+
+ uint8_t async_req_size;
+ uint8_t calibration_cycle_timing;
+ uint8_t max_requests;
+};
+
+/**
+ * Description of a PCI-to-PCI bridge device.
+ *
+ * \sa pci_device_get_bridge_info
+ */
+struct pci_bridge_info {
+ uint8_t primary_bus;
+ uint8_t secondary_bus;
+ uint8_t subordinate_bus;
+ uint8_t secondary_latency_timer;
+
+ uint8_t io_type;
+ uint8_t mem_type;
+ uint8_t prefetch_mem_type;
+
+ uint16_t secondary_status;
+ uint16_t bridge_control;
+
+ uint32_t io_base;
+ uint32_t io_limit;
+
+ uint32_t mem_base;
+ uint32_t mem_limit;
+
+ uint64_t prefetch_mem_base;
+ uint64_t prefetch_mem_limit;
+};
+
+/**
+ * Description of a PCI-to-PCMCIA bridge device.
+ *
+ * \sa pci_device_get_pcmcia_bridge_info
+ */
+struct pci_pcmcia_bridge_info {
+ uint8_t primary_bus;
+ uint8_t card_bus;
+ uint8_t subordinate_bus;
+ uint8_t cardbus_latency_timer;
+
+ uint16_t secondary_status;
+ uint16_t bridge_control;
+
+ struct {
+ uint32_t base;
+ uint32_t limit;
+ } io[2];
+
+ struct {
+ uint32_t base;
+ uint32_t limit;
+ } mem[2];
+
+};
+
+
+/**
+ * VGA Arbiter definitions, functions and related.
+ */
+
+/* Legacy VGA regions */
+#define VGA_ARB_RSRC_NONE 0x00
+#define VGA_ARB_RSRC_LEGACY_IO 0x01
+#define VGA_ARB_RSRC_LEGACY_MEM 0x02
+/* Non-legacy access */
+#define VGA_ARB_RSRC_NORMAL_IO 0x04
+#define VGA_ARB_RSRC_NORMAL_MEM 0x08
+
+int pci_device_vgaarb_init (void);
+void pci_device_vgaarb_fini (void);
+int pci_device_vgaarb_set_target (struct pci_device *dev);
+/* use the targetted device */
+int pci_device_vgaarb_decodes (int new_vga_rsrc);
+int pci_device_vgaarb_lock (void);
+int pci_device_vgaarb_trylock (void);
+int pci_device_vgaarb_unlock (void);
+/* return the current device count + resource decodes for the device */
+int pci_device_vgaarb_get_info (struct pci_device *dev, int *vga_count, int *rsrc_decodes);
+
+/*
+ * I/O space access.
+ */
+
+struct pci_io_handle;
+
+struct pci_io_handle *pci_device_open_io(struct pci_device *dev, pciaddr_t base,
+ pciaddr_t size);
+struct pci_io_handle *pci_legacy_open_io(struct pci_device *dev, pciaddr_t base,
+ pciaddr_t size);
+void pci_device_close_io(struct pci_device *dev, struct pci_io_handle *handle);
+uint32_t pci_io_read32(struct pci_io_handle *handle, uint32_t reg);
+uint16_t pci_io_read16(struct pci_io_handle *handle, uint32_t reg);
+uint8_t pci_io_read8(struct pci_io_handle *handle, uint32_t reg);
+void pci_io_write32(struct pci_io_handle *handle, uint32_t reg, uint32_t data);
+void pci_io_write16(struct pci_io_handle *handle, uint32_t reg, uint16_t data);
+void pci_io_write8(struct pci_io_handle *handle, uint32_t reg, uint8_t data);
+
+#endif /* PCIACCESS_H */
--- /dev/null
+# ===========================================================================
+# http://autoconf-archive.cryp.to/ac_define_dir.html
+# ===========================================================================
+#
+# SYNOPSIS
+#
+# AC_DEFINE_DIR(VARNAME, DIR [, DESCRIPTION])
+#
+# DESCRIPTION
+#
+# This macro sets VARNAME to the expansion of the DIR variable, taking
+# care of fixing up ${prefix} and such.
+#
+# VARNAME is then offered as both an output variable and a C preprocessor
+# symbol.
+#
+# Example:
+#
+# AC_DEFINE_DIR([DATADIR], [datadir], [Where data are placed to.])
+#
+# LAST MODIFICATION
+#
+# 2008-04-12
+#
+# COPYLEFT
+#
+# Copyright (c) 2008 Stepan Kasal <kasal@ucw.cz>
+# Copyright (c) 2008 Andreas Schwab <schwab@suse.de>
+# Copyright (c) 2008 Guido U. Draheim <guidod@gmx.de>
+# Copyright (c) 2008 Alexandre Oliva
+#
+# Copying and distribution of this file, with or without modification, are
+# permitted in any medium without royalty provided the copyright notice
+# and this notice are preserved.
+
+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
+])
--- /dev/null
+
+Name: libpciaccess
+Summary: PCI access library
+Version: 0.12.0
+Release: 0
+Group: System/Libraries
+License: MIT
+URL: http://www.x.org/
+Source0: http://xorg.freedesktop.org/archive/individual/lib/%{name}-%{version}.tar.bz2
+Requires(post): /sbin/ldconfig
+Requires(postun): /sbin/ldconfig
+BuildRequires: zlib-devel
+
+
+%description
+Generic PCI access library
+
+
+%package devel
+Summary: PCI access library development package
+Group: Development/Libraries
+Requires: %{name} = %{version}-%{release}
+
+%description devel
+Generic PCI access library development package
+
+
+%prep
+%setup -q -n %{name}-%{version}
+
+
+%build
+
+%configure --disable-static \
+ --with-pciids-path=%{_prefix}/share/misc --with-zlib \
+
+make %{?jobs:-j%jobs}
+
+%install
+rm -rf %{buildroot}
+%make_install
+
+
+
+
+%post -p /sbin/ldconfig
+
+%postun -p /sbin/ldconfig
+
+
+
+
+
+%files
+%defattr(-,root,root,-)
+%{_libdir}/libpciaccess.so.0
+%{_libdir}/libpciaccess.so.0.10.8
+
+
+%files devel
+%defattr(-,root,root,-)
+%{_includedir}/pciaccess.h
+%{_libdir}/libpciaccess.so
+%{_libdir}/pkgconfig/pciaccess.pc
+
--- /dev/null
+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
--- /dev/null
+# 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
--- /dev/null
+#
+# (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.
+
+AM_CFLAGS = $(CWARNFLAGS) @PCIACCESS_CFLAGS@
+
+lib_LTLIBRARIES = libpciaccess.la
+
+if LINUX
+OS_SUPPORT = linux_sysfs.c linux_devmem.c linux_devmem.h
+endif
+
+if FREEBSD
+OS_SUPPORT = freebsd_pci.c
+endif
+
+if NETBSD
+OS_SUPPORT = netbsd_pci.c
+endif
+
+if OPENBSD
+OS_SUPPORT = openbsd_pci.c
+endif
+
+if SOLARIS
+OS_SUPPORT = solx_devfs.c pci_tools.h
+endif
+
+if LINUX
+VGA_ARBITER = common_vgaarb.c
+else
+VGA_ARBITER = common_vgaarb_stub.c
+endif
+
+if GNU
+OS_SUPPORT = x86_pci.c
+endif
+
+libpciaccess_la_SOURCES = common_bridge.c \
+ common_iterator.c \
+ common_init.c \
+ common_interface.c \
+ common_io.c \
+ common_capability.c \
+ common_device_name.c \
+ common_map.c \
+ pciaccess_private.h \
+ $(VGA_ARBITER) \
+ $(OS_SUPPORT)
+
+INCLUDES = -I$(top_srcdir)/include
+
+libpciaccess_la_LIBADD = $(PCIACCESS_LIBS)
+
+libpciaccess_la_LDFLAGS = -version-number 0:10:8 -no-undefined
+
+libpciaccessincludedir = $(includedir)
+libpciaccessinclude_HEADERS = \
+ $(top_srcdir)/include/pciaccess.h
+
+noinst_PROGRAMS = scanpci
+
+scanpci_SOURCES = scanpci.c
+scanpci_LDADD = libpciaccess.la
--- /dev/null
+/*
+ * (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_bridge.c
+ * Support routines used to process PCI header information for bridges.
+ *
+ * \author Ian Romanick <idr@us.ibm.com>
+ */
+
+#include "config.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <ctype.h>
+#include <errno.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"
+#include "pciaccess_private.h"
+
+static int
+read_bridge_info( struct pci_device_private * priv )
+{
+ uint8_t buf[0x40];
+ pciaddr_t bytes;
+ int err;
+
+
+ /* Make sure the device has been probed. If not, header_type won't be
+ * set and the rest of this function will fail.
+ */
+ err = pci_device_probe(& priv->base);
+ if (err) {
+ return err;
+ }
+
+ switch ( priv->header_type & 0x7f ) {
+ case 0x00:
+ break;
+
+ case 0x01: {
+ struct pci_bridge_info *info;
+
+ info = malloc(sizeof(*info));
+ if (info != NULL) {
+ pci_device_cfg_read( (struct pci_device *) priv, buf + 0x18, 0x18,
+ 0x40 - 0x18, & bytes );
+
+ info->primary_bus = buf[0x18];
+ info->secondary_bus = buf[0x19];
+ info->subordinate_bus = buf[0x1a];
+ info->secondary_latency_timer = buf[0x1b];
+
+ info->io_type = buf[0x1c] & 0x0f;
+ info->io_base = (((uint32_t) (buf[0x1c] & 0x0f0)) << 8)
+ + (((uint32_t) buf[0x30]) << 16)
+ + (((uint32_t) buf[0x31]) << 24);
+
+ info->io_limit = 0x00000fff
+ + (((uint32_t) (buf[0x1d] & 0x0f0)) << 8)
+ + (((uint32_t) buf[0x32]) << 16)
+ + (((uint32_t) buf[0x33]) << 24);
+
+ info->mem_type = buf[0x20] & 0x0f;
+ info->mem_base = (((uint32_t) (buf[0x20] & 0x0f0)) << 16)
+ + (((uint32_t) buf[0x21]) << 24);
+
+ info->mem_limit = 0x0000ffff
+ + (((uint32_t) (buf[0x22] & 0x0f0)) << 16)
+ + (((uint32_t) buf[0x23]) << 24);
+
+ info->prefetch_mem_type = buf[0x24] & 0x0f;
+ info->prefetch_mem_base = (((uint64_t) (buf[0x24] & 0x0f0)) << 16)
+ + (((uint64_t) buf[0x25]) << 24)
+ + (((uint64_t) buf[0x28]) << 32)
+ + (((uint64_t) buf[0x29]) << 40)
+ + (((uint64_t) buf[0x2a]) << 48)
+ + (((uint64_t) buf[0x2b]) << 56);
+
+ info->prefetch_mem_limit = 0x0000ffff
+ + (((uint64_t) (buf[0x26] & 0x0f0)) << 16)
+ + (((uint64_t) buf[0x27]) << 24)
+ + (((uint64_t) buf[0x2c]) << 32)
+ + (((uint64_t) buf[0x2d]) << 40)
+ + (((uint64_t) buf[0x2e]) << 48)
+ + (((uint64_t) buf[0x2f]) << 56);
+
+ info->bridge_control = ((uint16_t) buf[0x3e])
+ + (((uint16_t) buf[0x3f]) << 8);
+
+ info->secondary_status = ((uint16_t) buf[0x1e])
+ + (((uint16_t) buf[0x1f]) << 8);
+ }
+
+ priv->bridge.pci = info;
+ break;
+ }
+
+ case 0x02: {
+ struct pci_pcmcia_bridge_info *info;
+
+ info = malloc(sizeof(*info));
+ if (info != NULL) {
+ pci_device_cfg_read( (struct pci_device *) priv, buf + 0x16, 0x16,
+ 0x40 - 0x16, & bytes );
+
+ info->primary_bus = buf[0x18];
+ info->card_bus = buf[0x19];
+ info->subordinate_bus = buf[0x1a];
+ info->cardbus_latency_timer = buf[0x1b];
+
+ info->mem[0].base = (((uint32_t) buf[0x1c]))
+ + (((uint32_t) buf[0x1d]) << 8)
+ + (((uint32_t) buf[0x1e]) << 16)
+ + (((uint32_t) buf[0x1f]) << 24);
+
+ info->mem[0].limit = (((uint32_t) buf[0x20]))
+ + (((uint32_t) buf[0x21]) << 8)
+ + (((uint32_t) buf[0x22]) << 16)
+ + (((uint32_t) buf[0x23]) << 24);
+
+ info->mem[1].base = (((uint32_t) buf[0x24]))
+ + (((uint32_t) buf[0x25]) << 8)
+ + (((uint32_t) buf[0x26]) << 16)
+ + (((uint32_t) buf[0x27]) << 24);
+
+ info->mem[1].limit = (((uint32_t) buf[0x28]))
+ + (((uint32_t) buf[0x29]) << 8)
+ + (((uint32_t) buf[0x2a]) << 16)
+ + (((uint32_t) buf[0x2b]) << 24);
+
+ info->io[0].base = (((uint32_t) buf[0x2c]))
+ + (((uint32_t) buf[0x2d]) << 8)
+ + (((uint32_t) buf[0x2e]) << 16)
+ + (((uint32_t) buf[0x2f]) << 24);
+
+ info->io[0].limit = (((uint32_t) buf[0x30]))
+ + (((uint32_t) buf[0x31]) << 8)
+ + (((uint32_t) buf[0x32]) << 16)
+ + (((uint32_t) buf[0x33]) << 24);
+
+ info->io[1].base = (((uint32_t) buf[0x34]))
+ + (((uint32_t) buf[0x35]) << 8)
+ + (((uint32_t) buf[0x36]) << 16)
+ + (((uint32_t) buf[0x37]) << 24);
+
+ info->io[1].limit = (((uint32_t) buf[0x38]))
+ + (((uint32_t) buf[0x39]) << 8)
+ + (((uint32_t) buf[0x3a]) << 16)
+ + (((uint32_t) buf[0x3b]) << 24);
+
+ info->secondary_status = ((uint16_t) buf[0x16])
+ + (((uint16_t) buf[0x17]) << 8);
+
+ info->bridge_control = ((uint16_t) buf[0x3e])
+ + (((uint16_t) buf[0x3f]) << 8);
+ }
+
+ priv->bridge.pcmcia = info;
+ break;
+ }
+ }
+
+ return 0;
+}
+
+
+/**
+ * Get the PCI bridge information for a device
+ *
+ * \returns
+ * If \c dev is a PCI-to-PCI bridge, a pointer to a \c pci_bridge_info
+ * structure. Otherwise, \c NULL is returned.
+ */
+const struct pci_bridge_info *
+pci_device_get_bridge_info( struct pci_device * dev )
+{
+ struct pci_device_private * priv = (struct pci_device_private *) dev;
+
+ if (priv->bridge.pci == NULL) {
+ read_bridge_info(priv);
+ }
+
+ return (priv->header_type == 1) ? priv->bridge.pci : NULL;
+}
+
+
+/**
+ * Get the PCMCIA bridge information for a device
+ *
+ * \returns
+ * If \c dev is a PCI-to-PCMCIA bridge, a pointer to a
+ * \c pci_pcmcia_bridge_info structure. Otherwise, \c NULL is returned.
+ */
+const struct pci_pcmcia_bridge_info *
+pci_device_get_pcmcia_bridge_info( struct pci_device * dev )
+{
+ struct pci_device_private * priv = (struct pci_device_private *) dev;
+
+ if (priv->bridge.pcmcia == NULL) {
+ read_bridge_info(priv);
+ }
+
+ return (priv->header_type == 2) ? priv->bridge.pcmcia : NULL;
+}
+
+
+/**
+ * Determine the primary, secondary, and subordinate buses for a bridge
+ *
+ * Determines the IDs of the primary, secondary, and subordinate buses for
+ * a specified bridge. Not all bridges directly store this information
+ * (e.g., PCI-to-ISA bridges). For those bridges, no error is returned, but
+ * -1 is stored in the bus IDs that don't make sense.
+ *
+ * For example, for a PCI-to-ISA bridge, \c primary_bus will be set to the ID
+ * of the bus containing the device and both \c secondary_bus and
+ * \c subordinate_bus will be set to -1.
+ *
+ * \return
+ * On success, zero is returned. If \c dev is not a bridge, \c ENODEV is
+ * returned.
+ *
+ * \bug
+ * Host bridges are handled the same way as PCI-to-ISA bridges. This is
+ * almost certainly not correct.
+ */
+int
+pci_device_get_bridge_buses(struct pci_device * dev, int *primary_bus,
+ int *secondary_bus, int *subordinate_bus)
+{
+ struct pci_device_private * priv = (struct pci_device_private *) dev;
+
+ /* If the device isn't a bridge, return an error.
+ */
+
+ if (((dev->device_class >> 16) & 0x0ff) != 0x06) {
+ return ENODEV;
+ }
+
+ if (!priv->bridge.pci) {
+ return ENODEV;
+ }
+
+ switch ((dev->device_class >> 8) & 0x0ff) {
+ case 0x00:
+ /* What to do for host bridges? I'm pretty sure this isn't right.
+ */
+ *primary_bus = dev->bus;
+ *secondary_bus = -1;
+ *subordinate_bus = -1;
+ break;
+
+ case 0x01:
+ case 0x02:
+ case 0x03:
+ *primary_bus = dev->bus;
+ *secondary_bus = -1;
+ *subordinate_bus = -1;
+ break;
+
+ case 0x04:
+ if (priv->bridge.pci == NULL)
+ read_bridge_info(priv);
+ if (priv->header_type == 0x01) {
+ *primary_bus = priv->bridge.pci->primary_bus;
+ *secondary_bus = priv->bridge.pci->secondary_bus;
+ *subordinate_bus = priv->bridge.pci->subordinate_bus;
+ } else {
+ *primary_bus = dev->bus;
+ *secondary_bus = -1;
+ *subordinate_bus = -1;
+ }
+ break;
+
+ case 0x07:
+ if (priv->bridge.pcmcia == NULL)
+ read_bridge_info(priv);
+ if (priv->header_type == 0x02) {
+ *primary_bus = priv->bridge.pcmcia->primary_bus;
+ *secondary_bus = priv->bridge.pcmcia->card_bus;
+ *subordinate_bus = priv->bridge.pcmcia->subordinate_bus;
+ } else {
+ *primary_bus = dev->bus;
+ *secondary_bus = -1;
+ *subordinate_bus = -1;
+ }
+ break;
+ }
+
+ return 0;
+}
+
+#define PCI_CLASS_BRIDGE 0x06
+#define PCI_SUBCLASS_BRIDGE_PCI 0x04
+
+struct pci_device *
+pci_device_get_parent_bridge(struct pci_device *dev)
+{
+ struct pci_id_match bridge_match = {
+ PCI_MATCH_ANY, PCI_MATCH_ANY, PCI_MATCH_ANY, PCI_MATCH_ANY,
+ (PCI_CLASS_BRIDGE << 16) | (PCI_SUBCLASS_BRIDGE_PCI << 8),
+ 0
+ };
+
+ struct pci_device *bridge;
+ struct pci_device_iterator *iter;
+
+ if (dev == NULL)
+ return NULL;
+
+ iter = pci_id_match_iterator_create(& bridge_match);
+ if (iter == NULL)
+ return NULL;
+
+ while ((bridge = pci_device_next(iter)) != NULL) {
+ if (bridge->domain == dev->domain) {
+ const struct pci_bridge_info *info =
+ pci_device_get_bridge_info(bridge);
+
+ if (info != NULL) {
+ if (info->secondary_bus == dev->bus) {
+ break;
+ }
+ }
+ }
+ }
+
+ pci_iterator_destroy(iter);
+
+ return bridge;
+}
--- /dev/null
+/*
+ * (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.
+ */
+_pci_hidden 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;
+ uint32_t agp_status;
+ uint8_t agp_ver;
+
+
+ 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 = calloc( 1, sizeof( struct pci_agp_info ) );
+ if ( agp_info == NULL ) {
+ return ENOMEM;
+ }
+
+ 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;
+}
--- /dev/null
+/*
+ * (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"
+#include "pciaccess_private.h"
+
+#define DO_MATCH(a,b) (((a) == PCI_MATCH_ANY) || ((a) == (b)))
+
+#ifdef HAVE_ZLIB
+#include <zlib.h>
+typedef gzFile pci_id_file;
+
+static pci_id_file
+pci_id_file_open(void)
+{
+ pci_id_file result;
+
+ result = gzopen(PCIIDS_PATH "/pci.ids.gz", "rb");
+ if (result)
+ return result;
+
+ return gzopen(PCIIDS_PATH "/pci.ids", "rb");
+}
+
+#define pci_id_file_gets(l, s, f) gzgets(f, l, s)
+#define pci_id_file_close(f) gzclose(f)
+#else
+typedef FILE pci_id_file;
+#define pci_id_file_open() fopen(PCIIDS_PATH "/pci.ids", "r")
+#define pci_id_file_gets(l, s, f) fgets(l, s, f)
+#define pci_id_file_close(f) fclose(f)
+#endif
+
+/**
+ * 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.
+ */
+_pci_hidden struct pci_id_node * tree = NULL;
+
+/**
+ * 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 )
+{
+ pci_id_file * f;
+ char buf[128];
+ unsigned vendor = PCI_MATCH_ANY;
+
+
+ /* If the device tree for this vendor is already populated, don't do
+ * anything. This avoids wasted processing and potential memory leaks.
+ */
+ if (vend->num_devices != 0) {
+ return;
+ }
+
+ f = pci_id_file_open();
+
+ /* If the pci.ids file could not be opened, there's nothing we can do.
+ */
+ if (f == NULL) {
+ return;
+ }
+
+ while( pci_id_file_gets( 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 ) {
+ /* vendor_name may already be set from a previous invocation
+ * of this function with fill_device_data = 0.
+ */
+ if (vend->vendor_name == NULL) {
+ 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 ] );
+ }
+ }
+ }
+
+ pci_id_file_close( f );
+}
+
+
+/**
+ * Find the name of the specified device.
+ *
+ * Finds the actual product name of the specified device. If a subvendor ID
+ * and subdevice ID are specified in \c m, the returned name will be the name
+ * of the subdevice.
+ */
+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;
+}
+
+
+/**
+ * Find the vendor name of the specified device.
+ *
+ * Finds the actual vendor name of the specified device. If a subvendor ID
+ * and subdevice ID are specified in \c m, the returned name will be the name
+ * associated with the subvendor.
+ */
+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.
+ */
+void
+pci_get_strings( const struct pci_id_match * m,
+ const char ** device_name,
+ const char ** vendor_name,
+ const char ** subdevice_name,
+ const char ** subvendor_name )
+{
+ struct pci_id_match temp;
+
+
+ temp = *m;
+ temp.subvendor_id = PCI_MATCH_ANY;
+ temp.subdevice_id = PCI_MATCH_ANY;
+
+ if ( device_name != NULL ) {
+ *device_name = find_device_name( & temp );
+ }
+
+ if ( vendor_name != NULL ) {
+ *vendor_name = find_vendor_name( & temp );
+ }
+
+ if ( subdevice_name != NULL ) {
+ *subdevice_name = find_device_name( m );
+ }
+
+ if ( subvendor_name != NULL ) {
+ *subvendor_name = find_vendor_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 );
+}
--- /dev/null
+/*
+ * (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"
+
+_pci_hidden 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();
+#elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__DragonFly__)
+ err = pci_system_freebsd_create();
+#elif defined(__NetBSD__)
+ err = pci_system_netbsd_create();
+#elif defined(__OpenBSD__)
+ err = pci_system_openbsd_create();
+#elif defined(__sun)
+ err = pci_system_solx_devfs_create();
+#elif defined(__GNU__)
+ err = pci_system_x86_create();
+#endif
+
+ return err;
+}
+
+void
+pci_system_init_dev_mem(int fd)
+{
+#ifdef __OpenBSD__
+ pci_system_openbsd_init_dev_mem(fd);
+#endif
+}
+
+/**
+ * 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;
+ }
+
+ pci_io_cleanup();
+
+ 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;
+}
--- /dev/null
+/*
+ * (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 <string.h>
+#include <errno.h>
+
+#include "pciaccess.h"
+#include "pciaccess_private.h"
+
+#if defined(__linux__) || defined(__GLIBC__)
+#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 /* linux */
+
+#elif defined(__sun)
+
+#include <sys/byteorder.h>
+
+#ifdef _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 /* Solaris */
+
+#else
+
+#include <sys/endian.h>
+
+#define HTOLE_16(x) htole16(x)
+#define HTOLE_32(x) htole32(x)
+
+#if defined(__FreeBSD__) || defined(__DragonFly__) || defined(__NetBSD__)
+#define LETOH_16(x) le16toh(x)
+#define LETOH_32(x) le32toh(x)
+#else
+#define LETOH_16(x) letoh16(x)
+#define LETOH_32(x) letoh32(x)
+#endif
+
+#endif /* others */
+
+/**
+ * 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 (VGA) device to determine if its the boot VGA device
+ *
+ * \param dev Device whose VGA status to query
+ * \return
+ * Zero if not the boot VGA, 1 if the boot VGA.
+ */
+int
+pci_device_is_boot_vga( struct pci_device * dev )
+{
+ if (!pci_sys->methods->boot_vga)
+ return 0;
+ return pci_sys->methods->boot_vga( dev );
+}
+
+/**
+ * Probe a PCI device to determine if a kernel driver is attached.
+ *
+ * \param dev Device to query
+ * \return
+ * Zero if no driver attached, 1 if attached kernel drviver
+ */
+int
+pci_device_has_kernel_driver( struct pci_device * dev )
+{
+ if (!pci_sys->methods->has_kernel_driver)
+ return 0;
+ return pci_sys->methods->has_kernel_driver( dev );
+}
+
+/**
+ * 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 success 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 access 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_map_range, pci_device_unmap_range
+ * \deprecated
+ */
+int
+pci_device_map_region(struct pci_device * dev, unsigned region,
+ int write_enable)
+{
+ const unsigned map_flags =
+ (write_enable) ? PCI_DEV_MAP_FLAG_WRITABLE : 0;
+
+ if ((region > 5) || (dev->regions[region].size == 0)) {
+ return ENOENT;
+ }
+
+ if (dev->regions[region].memory != NULL) {
+ return 0;
+ }
+
+ return pci_device_map_range(dev, dev->regions[region].base_addr,
+ dev->regions[region].size, map_flags,
+ &dev->regions[region].memory);
+}
+
+
+/**
+ * Map the specified memory range so that it can be accessed by the CPU.
+ *
+ * Maps the specified memory range for access by the processor. The pointer
+ * to the mapped region is stored in \c addr. In addition, the
+ * \c pci_mem_region::memory pointer for the BAR will be updated.
+ *
+ * \param dev Device whose memory region is to be mapped.
+ * \param base Base address of the range to be mapped.
+ * \param size Size of the range to be mapped.
+ * \param write_enable Map for writing (non-zero).
+ * \param addr Location to store the mapped address.
+ *
+ * \return
+ * Zero on success or an \c errno value on failure.
+ *
+ * \sa pci_device_map_range
+ */
+int pci_device_map_memory_range(struct pci_device *dev,
+ pciaddr_t base, pciaddr_t size,
+ int write_enable, void **addr)
+{
+ return pci_device_map_range(dev, base, size,
+ (write_enable) ? PCI_DEV_MAP_FLAG_WRITABLE : 0,
+ addr);
+}
+
+
+/**
+ * Map the specified memory range so that it can be accessed by the CPU.
+ *
+ * Maps the specified memory range for access by the processor. The pointer
+ * to the mapped region is stored in \c addr. In addition, the
+ * \c pci_mem_region::memory pointer for the BAR will be updated.
+ *
+ * \param dev Device whose memory region is to be mapped.
+ * \param base Base address of the range to be mapped.
+ * \param size Size of the range to be mapped.
+ * \param map_flags Flag bits controlling how the mapping is accessed.
+ * \param addr Location to store the mapped address.
+ *
+ * \return
+ * Zero on success or an \c errno value on failure.
+ *
+ * \sa pci_device_unmap_range
+ */
+int
+pci_device_map_range(struct pci_device *dev, pciaddr_t base,
+ pciaddr_t size, unsigned map_flags,
+ void **addr)
+{
+ struct pci_device_private *const devp =
+ (struct pci_device_private *) dev;
+ struct pci_device_mapping *mappings;
+ unsigned region;
+ unsigned i;
+ int err = 0;
+
+
+ *addr = NULL;
+
+ if (dev == NULL) {
+ return EFAULT;
+ }
+
+
+ for (region = 0; region < 6; region++) {
+ const struct pci_mem_region const* r = &dev->regions[region];
+
+ if (r->size != 0) {
+ if ((r->base_addr <= base) && ((r->base_addr + r->size) > base)) {
+ if ((base + size) > (r->base_addr + r->size)) {
+ return E2BIG;
+ }
+
+ break;
+ }
+ }
+ }
+
+ if (region > 5) {
+ return ENOENT;
+ }
+
+ /* Make sure that there isn't already a mapping with the same base and
+ * size.
+ */
+ for (i = 0; i < devp->num_mappings; i++) {
+ if ((devp->mappings[i].base == base)
+ && (devp->mappings[i].size == size)) {
+ return EINVAL;
+ }
+ }
+
+
+ mappings = realloc(devp->mappings,
+ (sizeof(devp->mappings[0]) * (devp->num_mappings + 1)));
+ if (mappings == NULL) {
+ return ENOMEM;
+ }
+
+ mappings[devp->num_mappings].base = base;
+ mappings[devp->num_mappings].size = size;
+ mappings[devp->num_mappings].region = region;
+ mappings[devp->num_mappings].flags = map_flags;
+ mappings[devp->num_mappings].memory = NULL;
+
+ if (dev->regions[region].memory == NULL) {
+ err = (*pci_sys->methods->map_range)(dev,
+ &mappings[devp->num_mappings]);
+ }
+
+ if (err == 0) {
+ *addr = mappings[devp->num_mappings].memory;
+ devp->num_mappings++;
+ } else {
+ mappings = realloc(mappings,
+ (sizeof(mappings[0]) * devp->num_mappings));
+ }
+
+ devp->mappings = mappings;
+
+ return err;
+}
+
+
+/**
+ * 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_range, pci_device_unmap_range
+ * \deprecated
+ */
+int
+pci_device_unmap_region( struct pci_device * dev, unsigned region )
+{
+ int err;
+
+ if (dev == NULL) {
+ return EFAULT;
+ }
+
+ if ((region > 5) || (dev->regions[region].size == 0)) {
+ return ENOENT;
+ }
+
+ err = pci_device_unmap_range(dev, dev->regions[region].memory,
+ dev->regions[region].size);
+ if (!err) {
+ dev->regions[region].memory = NULL;
+ }
+
+ return err;
+}
+
+
+/**
+ * Unmap the specified memory range so that it can no longer be accessed by the CPU.
+ *
+ * Unmaps the specified memory range that was previously mapped via
+ * \c pci_device_map_memory_range.
+ *
+ * \param dev Device whose memory is to be unmapped.
+ * \param memory Pointer to the base of the mapped range.
+ * \param size Size, in bytes, of the range to be unmapped.
+ *
+ * \return
+ * Zero on success or an \c errno value on failure.
+ *
+ * \sa pci_device_map_range, pci_device_unmap_range
+ * \deprecated
+ */
+int
+pci_device_unmap_memory_range(struct pci_device *dev, void *memory,
+ pciaddr_t size)
+{
+ return pci_device_unmap_range(dev, memory, size);
+}
+
+
+/**
+ * Unmap the specified memory range so that it can no longer be accessed by the CPU.
+ *
+ * Unmaps the specified memory range that was previously mapped via
+ * \c pci_device_map_memory_range.
+ *
+ * \param dev Device whose memory is to be unmapped.
+ * \param memory Pointer to the base of the mapped range.
+ * \param size Size, in bytes, of the range to be unmapped.
+ *
+ * \return
+ * Zero on success or an \c errno value on failure.
+ *
+ * \sa pci_device_map_range
+ */
+int
+pci_device_unmap_range(struct pci_device *dev, void *memory,
+ pciaddr_t size)
+{
+ struct pci_device_private *const devp =
+ (struct pci_device_private *) dev;
+ unsigned i;
+ int err;
+
+
+ if (dev == NULL) {
+ return EFAULT;
+ }
+
+ for (i = 0; i < devp->num_mappings; i++) {
+ if ((devp->mappings[i].memory == memory)
+ && (devp->mappings[i].size == size)) {
+ break;
+ }
+ }
+
+ if (i == devp->num_mappings) {
+ return ENOENT;
+ }
+
+
+ err = (*pci_sys->methods->unmap_range)(dev, &devp->mappings[i]);
+ if (!err) {
+ const unsigned entries_to_move = (devp->num_mappings - i) - 1;
+
+ if (entries_to_move > 0) {
+ (void) memmove(&devp->mappings[i],
+ &devp->mappings[i + 1],
+ entries_to_move * sizeof(devp->mappings[0]));
+ }
+
+ devp->num_mappings--;
+ devp->mappings = realloc(devp->mappings,
+ (sizeof(devp->mappings[0]) * devp->num_mappings));
+ }
+
+ return err;
+}
+
+
+/**
+ * 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 particularly 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 configuration 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 = ENXIO;
+ }
+
+ 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 = ENXIO;
+ }
+
+ *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 = ENXIO;
+ }
+
+ *data = LETOH_32( *data );
+ return err;
+}
+
+
+/**
+ * Write arbitrary bytes to device's PCI config space
+ *
+ * Writes 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 configuration 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, 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, 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, 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;
+}
+
+
+int
+pci_device_cfg_write_bits( struct pci_device * dev, uint32_t mask,
+ uint32_t data, pciaddr_t offset )
+{
+ uint32_t temp;
+ int err;
+
+ err = pci_device_cfg_read_u32( dev, & temp, offset );
+ if ( ! err ) {
+ temp &= ~mask;
+ temp |= data;
+
+ err = pci_device_cfg_write_u32(dev, temp, offset);
+ }
+
+ return err;
+}
+
+void
+pci_device_enable(struct pci_device *dev)
+{
+ if (dev == NULL) {
+ return;
+ }
+
+ if (pci_sys->methods->enable)
+ pci_sys->methods->enable(dev);
+}
--- /dev/null
+/*
+ * Copyright 2009 Red Hat, Inc.
+ *
+ * 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
+ * them 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 MERCHANTIBILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS 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.
+ *
+ * Author:
+ * Adam Jackson <ajax@redhat.com>
+ */
+
+#include <stdlib.h>
+#include <string.h>
+#include "pciaccess.h"
+#include "pciaccess_private.h"
+
+static struct pci_io_handle *ios;
+static unsigned int num_ios;
+
+static struct pci_io_handle *
+new_io_handle(void)
+{
+ struct pci_io_handle *new;
+
+ new = realloc(ios, sizeof(struct pci_io_handle) * (num_ios + 1));
+ if (!new)
+ return NULL;
+
+ ios = new;
+ num_ios++;
+
+ return ios + num_ios - 1;
+}
+
+static void
+delete_io_handle(struct pci_io_handle *handle)
+{
+ struct pci_io_handle *new;
+ int i = 0;
+
+ if (!handle || !num_ios || (void *)handle < (void *)ios ||
+ (void *)handle > (void *)(ios + num_ios - 1))
+ return;
+
+ for (i = 0; i < num_ios; i++) {
+ if (ios + i == handle) {
+ memmove(&ios[i], &ios[i+1], sizeof(struct pci_io_handle) *
+ (num_ios - i - 1));
+ break;
+ }
+ }
+
+ new = realloc(ios, sizeof(struct pci_io_handle) * (num_ios - 1));
+ if (new)
+ ios = new;
+ num_ios--;
+}
+
+_pci_hidden void
+pci_io_cleanup(void)
+{
+ free(ios);
+ ios = NULL;
+ num_ios = 0;
+}
+
+/**
+ * Open a handle to a PCI device I/O range. The \c base and \c size
+ * requested must fit entirely within a single I/O BAR on the device.
+ * \c size is in bytes.
+ *
+ * \returns
+ * An opaque handle to the I/O BAR, or \c NULL on error.
+ */
+struct pci_io_handle *
+pci_device_open_io(struct pci_device *dev, pciaddr_t base, pciaddr_t size)
+{
+ struct pci_io_handle *ret;
+ int bar;
+
+ if (!pci_sys->methods->open_device_io)
+ return NULL;
+
+ for (bar = 0; bar < 6; bar++) {
+ struct pci_mem_region *region = &(dev->regions[bar]);
+ if (!region->is_IO)
+ continue;
+
+ if (base < region->base_addr || base > (region->base_addr+region->size))
+ continue;
+
+ if ((base + size) > (region->base_addr + region->size))
+ continue;
+
+ ret = new_io_handle();
+ if (!ret)
+ return NULL;
+
+ if (!pci_sys->methods->open_device_io(ret, dev, bar, base, size)) {
+ delete_io_handle(ret);
+ return NULL;
+ }
+
+ return ret;
+ }
+
+ return NULL;
+}
+
+/**
+ * Open a handle to the legacy I/O space for the PCI domain containing
+ * \c dev. \c size is in bytes.
+ *
+ * \returns
+ * An opaque handle to the requested range, or \c NULL on error.
+ */
+struct pci_io_handle *
+pci_legacy_open_io(struct pci_device *dev, pciaddr_t base, pciaddr_t size)
+{
+ struct pci_io_handle *ret;
+
+ if (!pci_sys->methods->open_legacy_io)
+ return NULL;
+
+ ret = new_io_handle();
+ if (!ret)
+ return NULL;
+
+ if (!pci_sys->methods->open_legacy_io(ret, dev, base, size)) {
+ delete_io_handle(ret);
+ return NULL;
+ }
+
+ return ret;
+}
+
+/**
+ * Close an I/O handle.
+ */
+void
+pci_device_close_io(struct pci_device *dev, struct pci_io_handle *handle)
+{
+ if (dev && handle && pci_sys->methods->close_io)
+ pci_sys->methods->close_io(dev, handle);
+
+ delete_io_handle(handle);
+}
+
+/**
+ * Read a 32-bit value from the I/O space. \c reg is relative to the
+ * \c base specified when the handle was opened. Some platforms may
+ * require that \c reg be 32-bit-aligned.
+ *
+ * \returns
+ * The value read from the I/O port, or undefined on any error.
+ */
+uint32_t
+pci_io_read32(struct pci_io_handle *handle, uint32_t reg)
+{
+ if (reg + 4 > handle->size)
+ return UINT32_MAX;
+
+ return pci_sys->methods->read32(handle, reg);
+}
+
+/**
+ * Read a 16-bit value from the I/O space. \c reg is relative to the
+ * \c base specified when the handle was opened. Some platforms may
+ * require that \c reg be 16-bit-aligned.
+ *
+ * \returns
+ * The value read from the I/O port, or undefined on any error.
+ */
+uint16_t
+pci_io_read16(struct pci_io_handle *handle, uint32_t reg)
+{
+ if (reg + 2 > handle->size)
+ return UINT16_MAX;
+
+ return pci_sys->methods->read16(handle, reg);
+}
+
+/**
+ * Read a 8-bit value from the I/O space. \c reg is relative to the
+ * \c base specified when the handle was opened.
+ *
+ * \returns
+ * The value read from the I/O port, or undefined on any error.
+ */
+uint8_t
+pci_io_read8(struct pci_io_handle *handle, uint32_t reg)
+{
+ if (reg + 1 > handle->size)
+ return UINT8_MAX;
+
+ return pci_sys->methods->read8(handle, reg);
+}
+
+/**
+ * Write a 32-bit value to the I/O space. \c reg is relative to the
+ * \c base specified when the handle was opened. Some platforms may
+ * require that \c reg be 32-bit-aligned.
+ */
+void
+pci_io_write32(struct pci_io_handle *handle, uint32_t reg, uint32_t data)
+{
+ if (reg + 4 > handle->size)
+ return;
+
+ pci_sys->methods->write32(handle, reg, data);
+}
+
+/**
+ * Write a 16-bit value to the I/O space. \c reg is relative to the
+ * \c base specified when the handle was opened. Some platforms may
+ * require that \c reg be 16-bit-aligned.
+ */
+void
+pci_io_write16(struct pci_io_handle *handle, uint32_t reg, uint16_t data)
+{
+ if (reg + 2 > handle->size)
+ return;
+
+ pci_sys->methods->write16(handle, reg, data);
+}
+
+/**
+ * Write a 8-bit value to the I/O space. \c reg is relative to the
+ * \c base specified when the handle was opened.
+ */
+void
+pci_io_write8(struct pci_io_handle *handle, uint32_t reg, uint8_t data)
+{
+ if (reg + 1 > handle->size)
+ return;
+
+ pci_sys->methods->write8(handle, reg, data);
+}
--- /dev/null
+/*
+ * (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 <string.h>
+
+#include "pciaccess.h"
+#include "pciaccess_private.h"
+
+/**
+ * Track device iteration state
+ *
+ * \private
+ */
+struct pci_device_iterator {
+ unsigned next_index;
+
+ enum {
+ match_any,
+ match_slot,
+ match_id
+ } mode;
+
+ union {
+ struct pci_slot_match slot;
+ struct pci_id_match id;
+ } match;
+};
+
+
+/**
+ * Create an iterator based on a regular expression.
+ *
+ * \return
+ * A pointer to a fully initialized \c pci_device_iterator structure on
+ * success, or \c NULL on failure.
+ *
+ * \sa pci_id_match_iterator_create, pci_device_next, pci_iterator_destroy
+ */
+struct pci_device_iterator *
+pci_slot_match_iterator_create( const struct pci_slot_match * match )
+{
+ struct pci_device_iterator * iter;
+
+ if ( pci_sys == NULL ) {
+ return NULL;
+ }
+
+ iter = malloc( sizeof( *iter ) );
+ if ( iter != NULL ) {
+ iter->next_index = 0;
+
+ if ( match != NULL ) {
+ iter->mode = match_slot;
+
+ (void) memcpy( & iter->match.slot, match, sizeof( *match ) );
+ }
+ else {
+ iter->mode = match_any;
+ }
+ }
+
+ return iter;
+}
+
+
+/**
+ * Create an iterator based on a regular expression.
+ *
+ * \return
+ * A pointer to a fully initialized \c pci_device_iterator structure on
+ * success, or \c NULL on failure.
+ *
+ * \sa pci_slot_match_iterator_create, pci_device_next, pci_iterator_destroy
+ */
+struct pci_device_iterator *
+pci_id_match_iterator_create( const struct pci_id_match * match )
+{
+ struct pci_device_iterator * iter;
+
+ if ( pci_sys == NULL ) {
+ return NULL;
+ }
+
+ iter = malloc( sizeof( *iter ) );
+ if ( iter != NULL ) {
+ iter->next_index = 0;
+
+ if ( match != NULL ) {
+ iter->mode = match_id;
+
+ (void) memcpy( & iter->match.id, match, sizeof( *match ) );
+ }
+ else {
+ iter->mode = match_any;
+ }
+ }
+
+ 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 ) {
+ free( iter );
+ }
+}
+
+
+/**
+ * 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.
+ */
+struct pci_device *
+pci_device_next( struct pci_device_iterator * iter )
+{
+ struct pci_device_private * d = NULL;
+
+ if (!iter)
+ return NULL;
+
+ switch( iter->mode ) {
+ case match_any:
+ if ( iter->next_index < pci_sys->num_devices ) {
+ d = & pci_sys->devices[ iter->next_index ];
+ iter->next_index++;
+ }
+
+ break;
+
+ case match_slot: {
+ while ( iter->next_index < pci_sys->num_devices ) {
+ struct pci_device_private * const temp =
+ & pci_sys->devices[ iter->next_index ];
+
+ iter->next_index++;
+ if ( PCI_ID_COMPARE( iter->match.slot.domain, temp->base.domain )
+ && PCI_ID_COMPARE( iter->match.slot.bus, temp->base.bus )
+ && PCI_ID_COMPARE( iter->match.slot.dev, temp->base.dev )
+ && PCI_ID_COMPARE( iter->match.slot.func, temp->base.func ) ) {
+ d = temp;
+ break;
+ }
+ }
+
+ break;
+ }
+
+ case match_id: {
+ while ( iter->next_index < pci_sys->num_devices ) {
+ struct pci_device_private * const temp =
+ & pci_sys->devices[ iter->next_index ];
+
+ iter->next_index++;
+ if ( PCI_ID_COMPARE( iter->match.id.vendor_id, temp->base.vendor_id )
+ && PCI_ID_COMPARE( iter->match.id.device_id, temp->base.device_id )
+ && PCI_ID_COMPARE( iter->match.id.subvendor_id, temp->base.subvendor_id )
+ && PCI_ID_COMPARE( iter->match.id.subdevice_id, temp->base.subdevice_id )
+ && ((temp->base.device_class & iter->match.id.device_class_mask)
+ == iter->match.id.device_class) ) {
+ d = temp;
+ break;
+ }
+ }
+
+ break;
+ }
+ }
+
+ return (struct pci_device *) d;
+}
+
+
+struct pci_device *
+pci_device_find_by_slot( uint32_t domain, uint32_t bus, uint32_t dev,
+ uint32_t func )
+{
+ struct pci_device_iterator iter;
+
+
+ iter.next_index = 0;
+ iter.mode = match_slot;
+ iter.match.slot.domain = domain;
+ iter.match.slot.bus = bus;
+ iter.match.slot.dev = dev;
+ iter.match.slot.func = func;
+
+ return pci_device_next( & iter );
+}
--- /dev/null
+/*
+ * (C) Copyright IBM Corporation 2007
+ * 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 <sys/types.h>
+#include <sys/mman.h>
+#include <errno.h>
+
+#include "pciaccess.h"
+#include "pciaccess_private.h"
+
+/**
+ * \file common_map.c
+ * Platform independent memory map routines.
+ *
+ * \author Ian Romanick <idr@us.ibm.com>
+ */
+
+/**
+ * Unmap the specified region using the munmap.
+ *
+ * \param dev Device whose memory region is to be mapped.
+ * \param map Memory mapping that is to be undone.
+ *
+ * \return
+ * Zero on success or an \c errno value on failure.
+ *
+ * \sa pci_device_unmap_range
+ */
+_pci_hidden int
+pci_device_generic_unmap_range(struct pci_device *dev,
+ struct pci_device_mapping *map)
+{
+ return (munmap(map->memory, map->size) == -1) ? errno : 0;
+}
--- /dev/null
+/*
+ * Copyright (c) 2007 Paulo R. Zanoni, Tiago Vignatti
+ * 2009 Tiago Vignatti
+ *
+ * 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 the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, 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 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
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS 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 <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <limits.h>
+
+#include "config.h"
+#include "pciaccess.h"
+#include "pciaccess_private.h"
+
+#define BUFSIZE 64
+
+static int
+parse_string_to_decodes_rsrc(char *input, int *vga_count, struct pci_slot_match *match)
+{
+ char *tok;
+ char *input_sp = NULL, *count_sp, *pci_sp;
+ char tmp[32];
+
+ tok = strtok_r(input,",",&input_sp);
+ if (!tok)
+ goto fail;
+
+ strncpy(tmp, input, 15);
+ tmp[15] = 0;
+
+ tok = strtok_r(tmp,":",&count_sp);
+ if (!tok)
+ goto fail;
+ tok = strtok_r(NULL, ":",&count_sp);
+ if (!tok)
+ goto fail;
+
+ *vga_count = strtoul(tok, NULL, 10);
+ if (*vga_count == LONG_MAX)
+ goto fail;
+
+#ifdef DEBUG
+ fprintf(stderr,"vga count is %d\n", *vga_count);
+#endif
+
+ tok = strtok_r(NULL, ",",&input_sp);
+ if (!tok)
+ goto fail;
+
+ if (match) {
+ strncpy(tmp, tok, 32);
+ tmp[31] = 0;
+ tok = strtok_r(tmp, ":", &pci_sp);
+ if (!tok)
+ goto fail;
+ tok = strtok_r(NULL, ":", &pci_sp);
+ if (!tok)
+ goto fail;
+ match->domain = strtoul(tok, NULL, 16);
+
+ tok = strtok_r(NULL, ":", &pci_sp);
+ if (!tok)
+ goto fail;
+ match->bus = strtoul(tok, NULL, 16);
+
+ tok = strtok_r(NULL, ".", &pci_sp);
+ if (!tok)
+ goto fail;
+ match->dev = strtoul(tok, NULL, 16);
+
+ tok = strtok_r(NULL, ".", &pci_sp);
+ if (!tok)
+ goto fail;
+ match->func = strtoul(tok, NULL, 16);
+ }
+
+ tok = strtok_r(NULL, ",",&input_sp);
+ if (!tok)
+ goto fail;
+ tok = strtok_r(tok, "=", &input_sp);
+ if (!tok)
+ goto fail;
+ tok = strtok_r(NULL, "=", &input_sp);
+ if (!tok)
+ goto fail;
+
+ if (!strncmp(tok, "io+mem", 6))
+ return VGA_ARB_RSRC_LEGACY_IO | VGA_ARB_RSRC_LEGACY_MEM;
+ if (!strncmp(tok, "io", 2))
+ return VGA_ARB_RSRC_LEGACY_IO;
+ if (!strncmp(tok, "mem", 3))
+ return VGA_ARB_RSRC_LEGACY_MEM;
+fail:
+ return VGA_ARB_RSRC_NONE;
+}
+
+int
+pci_device_vgaarb_init(void)
+{
+ struct pci_slot_match match;
+ char buf[BUFSIZE];
+ int ret, rsrc;
+
+ if (!pci_sys)
+ return -1;
+
+ if ((pci_sys->vgaarb_fd = open ("/dev/vga_arbiter", O_RDWR)) < 0) {
+ return errno;
+ }
+
+ ret = read(pci_sys->vgaarb_fd, buf, BUFSIZE);
+ if (ret <= 0)
+ return -1;
+
+ memset(&match, 0xff, sizeof(match));
+ /* need to find the device to go back to and what it was decoding */
+ rsrc = parse_string_to_decodes_rsrc(buf, &pci_sys->vga_count, &match);
+
+ pci_sys->vga_default_dev = pci_device_find_by_slot(match.domain, match.bus, match.dev, match.func);
+
+ if (pci_sys->vga_default_dev)
+ pci_sys->vga_default_dev->vgaarb_rsrc = rsrc;
+ return 0;
+}
+
+void
+pci_device_vgaarb_fini(void)
+{
+ if (!pci_sys)
+ return;
+
+ close(pci_sys->vgaarb_fd);
+}
+
+/**
+ * Writes message on vga device. The messages are defined by the kernel
+ * implementation.
+ *
+ * \param fd vga arbiter device.
+ * \param buf message itself.
+ * \param len message length.
+ *
+ * \return
+ * Zero on success, 1 if something gets wrong and 2 if fd is busy (only for
+ * 'trylock')
+ */
+static int
+vgaarb_write(int fd, char *buf, int len)
+{
+ int ret;
+
+
+ buf[len] = '\0';
+
+ ret = write(fd, buf, len);
+ if (ret == -1) {
+ /* the user may have called "trylock" and didn't get the lock */
+ if (errno == EBUSY)
+ return 2;
+
+#ifdef DEBUG
+ fprintf(stderr, "write error");
+#endif
+ return 1;
+ }
+ else if (ret != len) {
+ /* it's need to receive the exactly amount required. */
+#ifdef DEBUG
+ fprintf(stderr, "write error: wrote different than expected\n");
+#endif
+ return 1;
+ }
+
+#ifdef DEBUG
+ fprintf(stderr, "%s: successfully wrote: '%s'\n", __FUNCTION__, buf);
+#endif
+
+ return 0;
+}
+
+
+static const char *
+rsrc_to_str(int iostate)
+{
+ switch (iostate) {
+ case VGA_ARB_RSRC_LEGACY_IO | VGA_ARB_RSRC_LEGACY_MEM:
+ return "io+mem";
+ case VGA_ARB_RSRC_LEGACY_IO:
+ return "io";
+ case VGA_ARB_RSRC_LEGACY_MEM:
+ return "mem";
+ }
+
+ return "none";
+}
+
+int
+pci_device_vgaarb_set_target(struct pci_device *dev)
+{
+ int len;
+ char buf[BUFSIZE];
+ int ret;
+
+ if (!dev)
+ dev = pci_sys->vga_default_dev;
+ if (!dev)
+ return -1;
+
+ len = snprintf(buf, BUFSIZE, "target PCI:%04x:%02x:%02x.%x",
+ dev->domain, dev->bus, dev->dev, dev->func);
+
+ ret = vgaarb_write(pci_sys->vgaarb_fd, buf, len);
+ if (ret)
+ return ret;
+
+ ret = read(pci_sys->vgaarb_fd, buf, BUFSIZE);
+ if (ret <= 0)
+ return -1;
+
+ dev->vgaarb_rsrc = parse_string_to_decodes_rsrc(buf, &pci_sys->vga_count, NULL);
+ pci_sys->vga_target = dev;
+ return 0;
+}
+
+int
+pci_device_vgaarb_decodes(int new_vgaarb_rsrc)
+{
+ int len;
+ char buf[BUFSIZE];
+ int ret;
+ struct pci_device *dev = pci_sys->vga_target;
+
+ if (!dev)
+ return -1;
+ if (dev->vgaarb_rsrc == new_vgaarb_rsrc)
+ return 0;
+
+ len = snprintf(buf, BUFSIZE, "decodes %s", rsrc_to_str(new_vgaarb_rsrc));
+ ret = vgaarb_write(pci_sys->vgaarb_fd, buf, len);
+ if (ret == 0)
+ dev->vgaarb_rsrc = new_vgaarb_rsrc;
+
+ ret = read(pci_sys->vgaarb_fd, buf, BUFSIZE);
+ if (ret <= 0)
+ return -1;
+
+ parse_string_to_decodes_rsrc(buf, &pci_sys->vga_count, NULL);
+
+ return ret;
+}
+
+int
+pci_device_vgaarb_lock(void)
+{
+ int len;
+ char buf[BUFSIZE];
+ struct pci_device *dev = pci_sys->vga_target;
+
+ if (!dev)
+ return -1;
+
+ if (dev->vgaarb_rsrc == 0 || pci_sys->vga_count == 1)
+ return 0;
+
+ len = snprintf(buf, BUFSIZE, "lock %s", rsrc_to_str(dev->vgaarb_rsrc));
+
+ return vgaarb_write(pci_sys->vgaarb_fd, buf, len);
+}
+
+int
+pci_device_vgaarb_trylock(void)
+{
+ int len;
+ char buf[BUFSIZE];
+ struct pci_device *dev = pci_sys->vga_target;
+
+ if (!dev)
+ return -1;
+
+ if (dev->vgaarb_rsrc == 0 || pci_sys->vga_count == 1)
+ return 0;
+
+ len = snprintf(buf, BUFSIZE, "trylock %s", rsrc_to_str(dev->vgaarb_rsrc));
+
+ return vgaarb_write(pci_sys->vgaarb_fd, buf, len);
+}
+
+int
+pci_device_vgaarb_unlock(void)
+{
+ int len;
+ char buf[BUFSIZE];
+ struct pci_device *dev = pci_sys->vga_target;
+
+ if (!dev)
+ return -1;
+
+ if (dev->vgaarb_rsrc == 0 || pci_sys->vga_count == 1)
+ return 0;
+
+ len = snprintf(buf, BUFSIZE, "unlock %s", rsrc_to_str(dev->vgaarb_rsrc));
+
+ return vgaarb_write(pci_sys->vgaarb_fd, buf, len);
+}
+
+int pci_device_vgaarb_get_info(struct pci_device *dev, int *vga_count, int *rsrc_decodes)
+{
+ *vga_count = pci_sys->vga_count;
+ if (!dev)
+ return 0;
+
+ *rsrc_decodes = dev->vgaarb_rsrc;
+ return 0;
+}
--- /dev/null
+/*
+ * Copyright (c) 2009 Tiago Vignatti
+ *
+ * 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 the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, 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 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
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS 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 <stdio.h>
+#include "pciaccess.h"
+
+int
+pci_device_vgaarb_init(void)
+{
+#ifdef DEBUG
+ fprintf(stderr, "%s: You're using VGA arbiter stub functions!\n",
+ __FUNCTION__);
+#endif
+ return -1;
+}
+
+void
+pci_device_vgaarb_fini(void)
+{
+}
+
+int
+pci_device_vgaarb_set_target(struct pci_device *dev)
+{
+ return -1;
+}
+
+int
+pci_device_vgaarb_decodes(int new_vga_rsrc)
+{
+ return -1;
+}
+
+int
+pci_device_vgaarb_lock(void)
+{
+ return -1;
+}
+
+int
+pci_device_vgaarb_trylock(void)
+{
+ return -1;
+}
+
+int
+pci_device_vgaarb_unlock(void)
+{
+ return 0;
+}
+
+int pci_device_vgaarb_get_info(struct pci_device *dev, int *vga_count,
+ int *rsrc_decodes)
+{
+ return -1;
+}
--- /dev/null
+/*
+ * (C) Copyright Eric Anholt 2006
+ * (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 freebsd_pci.c
+ *
+ * Access the kernel PCI support using /dev/pci's ioctl and mmap interface.
+ *
+ * \author Eric Anholt <eric@anholt.net>
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/pciio.h>
+#include <sys/mman.h>
+#include <sys/memrange.h>
+
+#include "config.h"
+#include "pciaccess.h"
+#include "pciaccess_private.h"
+
+#define PCIC_DISPLAY 0x03
+#define PCIS_DISPLAY_VGA 0x00
+#define PCIS_DISPLAY_XGA 0x01
+#define PCIS_DISPLAY_3D 0x02
+#define PCIS_DISPLAY_OTHER 0x80
+
+/* Registers taken from pcireg.h */
+#define PCIR_COMMAND 0x04
+#define PCIM_CMD_PORTEN 0x0001
+#define PCIM_CMD_MEMEN 0x0002
+#define PCIR_BIOS 0x30
+#define PCIM_BIOS_ENABLE 0x01
+#define PCIM_BIOS_ADDR_MASK 0xfffff800
+
+#define PCIR_BARS 0x10
+#define PCIR_BAR(x) (PCIR_BARS + (x) * 4)
+#define PCI_BAR_IO(x) (((x) & PCIM_BAR_SPACE) == PCIM_BAR_IO_SPACE)
+#define PCI_BAR_MEM(x) (((x) & PCIM_BAR_SPACE) == PCIM_BAR_MEM_SPACE)
+#define PCIM_BAR_MEM_TYPE 0x00000006
+#define PCIM_BAR_MEM_64 4
+#define PCIM_BAR_MEM_PREFETCH 0x00000008
+#define PCIM_BAR_SPACE 0x00000001
+#define PCIM_BAR_MEM_SPACE 0
+#define PCIM_BAR_IO_SPACE 1
+
+/**
+ * FreeBSD private pci_system structure that extends the base pci_system
+ * structure.
+ *
+ * It is initialized once and used as a global, just as pci_system is used.
+ */
+_pci_hidden
+struct freebsd_pci_system {
+ /* This must be the first entry in the structure, as pci_system_cleanup()
+ * frees pci_sys.
+ */
+ struct pci_system pci_sys;
+
+ int pcidev; /**< fd for /dev/pci */
+} *freebsd_pci_sys;
+
+/**
+ * Map a memory region for a device using /dev/mem.
+ *
+ * \param dev Device whose memory region is to be mapped.
+ * \param map Parameters of the mapping that is to be created.
+ *
+ * \return
+ * Zero on success or an \c errno value on failure.
+ */
+static int
+pci_device_freebsd_map_range(struct pci_device *dev,
+ struct pci_device_mapping *map)
+{
+ const int prot = ((map->flags & PCI_DEV_MAP_FLAG_WRITABLE) != 0)
+ ? (PROT_READ | PROT_WRITE) : PROT_READ;
+ struct mem_range_desc mrd;
+ struct mem_range_op mro;
+
+ int fd, err = 0;
+
+ fd = open("/dev/mem", O_RDWR);
+ if (fd == -1)
+ return errno;
+
+ map->memory = mmap(NULL, map->size, prot, MAP_SHARED, fd, map->base);
+
+ if (map->memory == MAP_FAILED) {
+ err = errno;
+ }
+
+ mrd.mr_base = map->base;
+ mrd.mr_len = map->size;
+ strncpy(mrd.mr_owner, "pciaccess", sizeof(mrd.mr_owner));
+ if (map->flags & PCI_DEV_MAP_FLAG_CACHABLE)
+ mrd.mr_flags = MDF_WRITEBACK;
+ else if (map->flags & PCI_DEV_MAP_FLAG_WRITE_COMBINE)
+ mrd.mr_flags = MDF_WRITECOMBINE;
+ else
+ mrd.mr_flags = MDF_UNCACHEABLE;
+ mro.mo_desc = &mrd;
+ mro.mo_arg[0] = MEMRANGE_SET_UPDATE;
+
+ /* No need to set an MTRR if it's the default mode. */
+ if (mrd.mr_flags != MDF_UNCACHEABLE) {
+ if (ioctl(fd, MEMRANGE_SET, &mro)) {
+ fprintf(stderr, "failed to set mtrr: %s\n", strerror(errno));
+ }
+ }
+
+ close(fd);
+
+ return err;
+}
+
+static int
+pci_device_freebsd_unmap_range( struct pci_device *dev,
+ struct pci_device_mapping *map )
+{
+ struct mem_range_desc mrd;
+ struct mem_range_op mro;
+ int fd;
+
+ if ((map->flags & PCI_DEV_MAP_FLAG_CACHABLE) ||
+ (map->flags & PCI_DEV_MAP_FLAG_WRITE_COMBINE))
+ {
+ fd = open("/dev/mem", O_RDWR);
+ if (fd != -1) {
+ mrd.mr_base = map->base;
+ mrd.mr_len = map->size;
+ strncpy(mrd.mr_owner, "pciaccess", sizeof(mrd.mr_owner));
+ mrd.mr_flags = MDF_UNCACHEABLE;
+ mro.mo_desc = &mrd;
+ mro.mo_arg[0] = MEMRANGE_SET_REMOVE;
+
+ if (ioctl(fd, MEMRANGE_SET, &mro)) {
+ fprintf(stderr, "failed to unset mtrr: %s\n", strerror(errno));
+ }
+
+ close(fd);
+ } else {
+ fprintf(stderr, "Failed to open /dev/mem\n");
+ }
+ }
+
+ return pci_device_generic_unmap_range(dev, map);
+}
+
+static int
+pci_device_freebsd_read( struct pci_device * dev, void * data,
+ pciaddr_t offset, pciaddr_t size,
+ pciaddr_t * bytes_read )
+{
+ struct pci_io io;
+
+#if HAVE_PCI_IO_PC_DOMAIN
+ io.pi_sel.pc_domain = dev->domain;
+#endif
+ io.pi_sel.pc_bus = dev->bus;
+ io.pi_sel.pc_dev = dev->dev;
+ io.pi_sel.pc_func = dev->func;
+
+ *bytes_read = 0;
+ while ( size > 0 ) {
+ int toread = (size < 4) ? size : 4;
+
+ /* Only power of two allowed. */
+ if (toread == 3)
+ toread = 2;
+
+ io.pi_reg = offset;
+ io.pi_width = toread;
+
+ if ( ioctl( freebsd_pci_sys->pcidev, PCIOCREAD, &io ) < 0 )
+ return errno;
+
+ memcpy(data, &io.pi_data, toread );
+
+ offset += toread;
+ data = (char *)data + toread;
+ size -= toread;
+ *bytes_read += toread;
+ }
+
+ return 0;
+}
+
+
+static int
+pci_device_freebsd_write( struct pci_device * dev, const void * data,
+ pciaddr_t offset, pciaddr_t size,
+ pciaddr_t * bytes_written )
+{
+ struct pci_io io;
+
+#if HAVE_PCI_IO_PC_DOMAIN
+ io.pi_sel.pc_domain = dev->domain;
+#endif
+ io.pi_sel.pc_bus = dev->bus;
+ io.pi_sel.pc_dev = dev->dev;
+ io.pi_sel.pc_func = dev->func;
+
+ *bytes_written = 0;
+ while ( size > 0 ) {
+ int towrite = (size < 4 ? size : 4);
+
+ /* Only power of two allowed. */
+ if (towrite == 3)
+ towrite = 2;
+
+ io.pi_reg = offset;
+ io.pi_width = towrite;
+ memcpy( &io.pi_data, data, towrite );
+
+ if ( ioctl( freebsd_pci_sys->pcidev, PCIOCWRITE, &io ) < 0 )
+ return errno;
+
+ offset += towrite;
+ data = (char *)data + towrite;
+ size -= towrite;
+ *bytes_written += towrite;
+ }
+
+ return 0;
+}
+
+/**
+ * Read a VGA rom using the 0xc0000 mapping.
+ *
+ * This function should be extended to handle access through PCI resources,
+ * which should be more reliable when available.
+ */
+static int
+pci_device_freebsd_read_rom( struct pci_device * dev, void * buffer )
+{
+ struct pci_device_private *priv = (struct pci_device_private *) dev;
+ void *bios;
+ pciaddr_t rom_base;
+ uint32_t rom;
+ uint16_t reg;
+ int pci_rom, memfd;
+
+ if ( ( dev->device_class & 0x00ffff00 ) !=
+ ( ( PCIC_DISPLAY << 16 ) | ( PCIS_DISPLAY_VGA << 8 ) ) )
+ {
+ return ENOSYS;
+ }
+
+ if (priv->rom_base == 0) {
+#if defined(__amd64__) || defined(__i386__)
+ rom_base = 0xc0000;
+ pci_rom = 0;
+#else
+ return ENOSYS;
+#endif
+ } else {
+ rom_base = priv->rom_base;
+ pci_rom = 1;
+
+ pci_device_cfg_read_u16( dev, ®, PCIR_COMMAND );
+ pci_device_cfg_write_u16( dev, reg | PCIM_CMD_MEMEN, PCIR_COMMAND );
+ pci_device_cfg_read_u32( dev, &rom, PCIR_BIOS );
+ pci_device_cfg_write_u32( dev, rom | PCIM_BIOS_ENABLE, PCIR_BIOS );
+ }
+
+ printf("Using rom_base = 0x%lx\n", (long)rom_base);
+ memfd = open( "/dev/mem", O_RDONLY );
+ if ( memfd == -1 )
+ return errno;
+
+ bios = mmap( NULL, dev->rom_size, PROT_READ, 0, memfd, rom_base );
+ if ( bios == MAP_FAILED ) {
+ close( memfd );
+ return errno;
+ }
+
+ memcpy( buffer, bios, dev->rom_size );
+
+ munmap( bios, dev->rom_size );
+ close( memfd );
+
+ if (pci_rom) {
+ pci_device_cfg_write_u32( dev, PCIR_BIOS, rom );
+ pci_device_cfg_write_u16( dev, PCIR_COMMAND, reg );
+ }
+
+ return 0;
+}
+
+/** Returns the number of regions (base address registers) the device has */
+
+static int
+pci_device_freebsd_get_num_regions( struct pci_device * dev )
+{
+ struct pci_device_private *priv = (struct pci_device_private *) dev;
+
+ switch (priv->header_type) {
+ case 0:
+ return 6;
+ case 1:
+ return 2;
+ case 2:
+ return 1;
+ default:
+ printf("unknown header type %02x\n", priv->header_type);
+ return 0;
+ }
+}
+
+#ifdef PCIOCGETBAR
+
+static int
+pci_device_freebsd_probe( struct pci_device * dev )
+{
+ struct pci_device_private *priv = (struct pci_device_private *) dev;
+ struct pci_bar_io bar;
+ uint8_t irq;
+ int err, i;
+
+#if HAVE_PCI_IO_PC_DOMAIN
+ bar.pbi_sel.pc_domain = dev->domain;
+#endif
+ bar.pbi_sel.pc_bus = dev->bus;
+ bar.pbi_sel.pc_dev = dev->dev;
+ bar.pbi_sel.pc_func = dev->func;
+
+
+ /* Many of the fields were filled in during initial device enumeration.
+ * At this point, we need to fill in regions, rom_size, and irq.
+ */
+
+ err = pci_device_cfg_read_u8( dev, &irq, 60 );
+ if (err)
+ return errno;
+ dev->irq = irq;
+
+ for (i = 0; i < pci_device_freebsd_get_num_regions( dev ); i++) {
+ bar.pbi_reg = PCIR_BAR(i);
+ if ( ioctl( freebsd_pci_sys->pcidev, PCIOCGETBAR, &bar ) < 0 )
+ continue;
+
+ if (PCI_BAR_IO(bar.pbi_base))
+ dev->regions[i].is_IO = 1;
+
+ if ((bar.pbi_base & PCIM_BAR_MEM_TYPE) == PCIM_BAR_MEM_64)
+ dev->regions[i].is_64 = 1;
+
+ if (bar.pbi_base & PCIM_BAR_MEM_PREFETCH)
+ dev->regions[i].is_prefetchable = 1;
+
+ dev->regions[i].base_addr = bar.pbi_base & ~((uint64_t)0xf);
+ dev->regions[i].size = bar.pbi_length;
+ }
+
+ /* If it's a VGA device, set up the rom size for read_rom using the
+ * 0xc0000 mapping.
+ */
+ if ((dev->device_class & 0x00ffff00) ==
+ ((PCIC_DISPLAY << 16) | (PCIS_DISPLAY_VGA << 8))) {
+ dev->rom_size = 64 * 1024;
+ }
+
+ return 0;
+}
+
+#else
+
+/** Masks out the flag bigs of the base address register value */
+static uint32_t
+get_map_base( uint32_t val )
+{
+ if (val & 0x01)
+ return val & ~0x03;
+ else
+ return val & ~0x0f;
+}
+
+/** Returns the size of a region based on the all-ones test value */
+static int
+get_test_val_size( uint32_t testval )
+{
+ if (testval == 0)
+ return 0;
+
+ /* Mask out the flag bits */
+ testval = get_map_base( testval );
+
+ return 1 << (ffs(testval) - 1);
+}
+
+/**
+ * Sets the address and size information for the region from config space
+ * registers.
+ *
+ * This would be much better provided by a kernel interface.
+ *
+ * \return 0 on success, or an errno value.
+ */
+static int
+pci_device_freebsd_get_region_info( struct pci_device * dev, int region,
+ int bar )
+{
+ uint32_t addr, testval;
+ uint16_t cmd;
+ int err;
+
+ /* Get the base address */
+ err = pci_device_cfg_read_u32( dev, &addr, bar );
+ if (err != 0)
+ return err;
+
+ /*
+ * We are going to be doing evil things to the registers here
+ * so disable them via the command register first.
+ */
+ err = pci_device_cfg_read_u16( dev, &cmd, PCIR_COMMAND );
+ if (err != 0)
+ return err;
+
+ err = pci_device_cfg_write_u16( dev,
+ cmd & ~(PCI_BAR_MEM(addr) ? PCIM_CMD_MEMEN : PCIM_CMD_PORTEN),
+ PCIR_COMMAND );
+ if (err != 0)
+ return err;
+
+ /* Test write all ones to the register, then restore it. */
+ err = pci_device_cfg_write_u32( dev, 0xffffffff, bar );
+ if (err != 0)
+ return err;
+ err = pci_device_cfg_read_u32( dev, &testval, bar );
+ if (err != 0)
+ return err;
+ err = pci_device_cfg_write_u32( dev, addr, bar );
+ if (err != 0)
+ return err;
+
+ /* Restore the command register */
+ err = pci_device_cfg_write_u16( dev, cmd, PCIR_COMMAND );
+ if (err != 0)
+ return err;
+
+ if (addr & 0x01)
+ dev->regions[region].is_IO = 1;
+ if (addr & 0x04)
+ dev->regions[region].is_64 = 1;
+ if (addr & 0x08)
+ dev->regions[region].is_prefetchable = 1;
+
+ /* Set the size */
+ dev->regions[region].size = get_test_val_size( testval );
+ printf("size = 0x%lx\n", (long)dev->regions[region].size);
+
+ /* Set the base address value */
+ if (dev->regions[region].is_64) {
+ uint32_t top;
+
+ err = pci_device_cfg_read_u32( dev, &top, bar + 4 );
+ if (err != 0)
+ return err;
+
+ dev->regions[region].base_addr = ((uint64_t)top << 32) |
+ get_map_base(addr);
+ } else {
+ dev->regions[region].base_addr = get_map_base(addr);
+ }
+
+ return 0;
+}
+
+static int
+pci_device_freebsd_probe( struct pci_device * dev )
+{
+ struct pci_device_private *priv = (struct pci_device_private *) dev;
+ uint32_t reg, size;
+ uint8_t irq;
+ int err, i, bar;
+
+ /* Many of the fields were filled in during initial device enumeration.
+ * At this point, we need to fill in regions, rom_size, and irq.
+ */
+
+ err = pci_device_cfg_read_u8( dev, &irq, 60 );
+ if (err)
+ return errno;
+ dev->irq = irq;
+
+ bar = 0x10;
+ for (i = 0; i < pci_device_freebsd_get_num_regions( dev ); i++) {
+ pci_device_freebsd_get_region_info( dev, i, bar );
+ if (dev->regions[i].is_64) {
+ bar += 0x08;
+ i++;
+ } else
+ bar += 0x04;
+ }
+
+ /* If it's a VGA device, set up the rom size for read_rom */
+ if ((dev->device_class & 0x00ffff00) ==
+ ((PCIC_DISPLAY << 16) | (PCIS_DISPLAY_VGA << 8)))
+ {
+ err = pci_device_cfg_read_u32( dev, ®, PCIR_BIOS );
+ if (err)
+ return errno;
+
+ if (reg == 0) {
+ dev->rom_size = 0x10000;
+ return 0;
+ }
+
+ err = pci_device_cfg_write_u32( dev, ~PCIM_BIOS_ENABLE, PCIR_BIOS );
+ if (err)
+ return errno;
+ pci_device_cfg_read_u32( dev, &size, PCIR_BIOS );
+ pci_device_cfg_write_u32( dev, reg, PCIR_BIOS );
+
+ if ((reg & PCIM_BIOS_ADDR_MASK) != 0) {
+ priv->rom_base = (reg & PCIM_BIOS_ADDR_MASK);
+ dev->rom_size = -(size & PCIM_BIOS_ADDR_MASK);
+ }
+ }
+
+ return 0;
+}
+
+#endif
+
+static void
+pci_system_freebsd_destroy(void)
+{
+ close(freebsd_pci_sys->pcidev);
+ free(freebsd_pci_sys->pci_sys.devices);
+ freebsd_pci_sys = NULL;
+}
+
+static const struct pci_system_methods freebsd_pci_methods = {
+ .destroy = pci_system_freebsd_destroy,
+ .destroy_device = NULL, /* nothing to do for this */
+ .read_rom = pci_device_freebsd_read_rom,
+ .probe = pci_device_freebsd_probe,
+ .map_range = pci_device_freebsd_map_range,
+ .unmap_range = pci_device_freebsd_unmap_range,
+ .read = pci_device_freebsd_read,
+ .write = pci_device_freebsd_write,
+ .fill_capabilities = pci_fill_capabilities_generic,
+};
+
+/**
+ * Attempt to access the FreeBSD PCI interface.
+ */
+_pci_hidden int
+pci_system_freebsd_create( void )
+{
+ struct pci_conf_io pciconfio;
+ struct pci_conf pciconf[255];
+ int pcidev;
+ int i;
+
+ /* Try to open the PCI device */
+ pcidev = open( "/dev/pci", O_RDWR );
+ if ( pcidev == -1 )
+ return ENXIO;
+
+ freebsd_pci_sys = calloc( 1, sizeof( struct freebsd_pci_system ) );
+ if ( freebsd_pci_sys == NULL ) {
+ close( pcidev );
+ return ENOMEM;
+ }
+ pci_sys = &freebsd_pci_sys->pci_sys;
+
+ pci_sys->methods = & freebsd_pci_methods;
+ freebsd_pci_sys->pcidev = pcidev;
+
+ /* Probe the list of devices known by the system */
+ bzero( &pciconfio, sizeof( struct pci_conf_io ) );
+ pciconfio.match_buf_len = sizeof(pciconf);
+ pciconfio.matches = pciconf;
+
+ if ( ioctl( pcidev, PCIOCGETCONF, &pciconfio ) == -1) {
+ free( pci_sys );
+ close( pcidev );
+ return errno;
+ }
+
+ if (pciconfio.status == PCI_GETCONF_ERROR ) {
+ free( pci_sys );
+ close( pcidev );
+ return EINVAL;
+ }
+
+ /* Translate the list of devices into pciaccess's format. */
+ pci_sys->num_devices = pciconfio.num_matches;
+ pci_sys->devices = calloc( pciconfio.num_matches,
+ sizeof( struct pci_device_private ) );
+
+ for ( i = 0; i < pciconfio.num_matches; i++ ) {
+ struct pci_conf *p = &pciconf[ i ];
+
+#if HAVE_PCI_IO_PC_DOMAIN
+ pci_sys->devices[ i ].base.domain = p->pc_sel.pc_domain;
+#else
+ pci_sys->devices[ i ].base.domain = 0;
+#endif
+ pci_sys->devices[ i ].base.bus = p->pc_sel.pc_bus;
+ pci_sys->devices[ i ].base.dev = p->pc_sel.pc_dev;
+ pci_sys->devices[ i ].base.func = p->pc_sel.pc_func;
+ pci_sys->devices[ i ].base.vendor_id = p->pc_vendor;
+ pci_sys->devices[ i ].base.device_id = p->pc_device;
+ pci_sys->devices[ i ].base.subvendor_id = p->pc_subvendor;
+ pci_sys->devices[ i ].base.subdevice_id = p->pc_subdevice;
+ pci_sys->devices[ i ].base.revision = p->pc_revid;
+ pci_sys->devices[ i ].base.device_class = (uint32_t)p->pc_class << 16 |
+ (uint32_t)p->pc_subclass << 8 | (uint32_t)p->pc_progif;
+ pci_sys->devices[ i ].header_type = p->pc_hdr & 0x7f;
+ }
+
+ return 0;
+}
--- /dev/null
+/*
+ * (C) Copyright IBM Corporation 2007
+ * 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_devmem.c
+ * Access PCI subsystem using Linux's the old /dev/mem interface.
+ *
+ * \note
+ * This is currently just a skeleton. It only includes the /dev/mem based
+ * function for reading the device ROM.
+ *
+ * \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"
+#include "linux_devmem.h"
+
+/**
+ * Read a device's expansion ROM using /dev/mem.
+ *
+ * \note
+ * This function could probably be used, as-is, on other platforms that have
+ * a /dev/mem interface.
+ *
+ * \bugs
+ * Before using the VGA special case code, this function should check that
+ * VGA access are routed to the device. Right?
+ */
+_pci_hidden int
+pci_device_linux_devmem_read_rom(struct pci_device *dev, void *buffer)
+{
+ struct pci_device_private *priv = (struct pci_device_private *) dev;
+ int fd;
+ int err = 0;
+ uint32_t rom_base_tmp;
+ pciaddr_t rom_base;
+ pciaddr_t rom_size;
+ int PCI_ROM;
+
+
+ /* Handle some special cases of legacy devices.
+ */
+ if (priv->base.rom_size == 0) {
+ /* VGA ROMs are supposed to be at 0xC0000.
+ */
+ if ((priv->base.device_class & 0x00ffff00) == 0x000030000) {
+ rom_base = 0x000C0000;
+ rom_size = 0x00010000;
+ PCI_ROM = 0;
+ }
+ else {
+ /* "Function not implemented."
+ */
+ return ENOSYS;
+ }
+ }
+ else {
+ rom_base = priv->rom_base;
+ rom_size = priv->base.rom_size;
+ PCI_ROM = 1;
+ }
+
+
+
+ /* Enable the device's ROM.
+ */
+ if (PCI_ROM) {
+ err = pci_device_cfg_read_u32(& priv->base, & rom_base_tmp, 48);
+ if (err) {
+ return err;
+ }
+
+ if ((rom_base_tmp & 0x000000001) == 0) {
+ err = pci_device_cfg_write_u32(& priv->base,
+ rom_base_tmp | 1, 48);
+ if (err) {
+ return err;
+ }
+ }
+ }
+
+
+ /* Read the portion of /dev/mem that corresponds to the device's ROM.
+ */
+ fd = open("/dev/mem", O_RDONLY, 0);
+ if (fd < 0) {
+ err = errno;
+ }
+ else {
+ size_t bytes;
+
+ for (bytes = 0; bytes < rom_size; /* empty */) {
+ const ssize_t got = pread(fd, buffer, rom_size - bytes,
+ rom_base + bytes);
+ if (got == -1) {
+ err = errno;
+ break;
+ }
+
+ bytes += got;
+ }
+
+ close(fd);
+ }
+
+
+ /* Disable the device's ROM.
+ */
+ if (PCI_ROM && ((rom_base_tmp & 0x000000001) == 0)) {
+ const int tmp_err = pci_device_cfg_write_u32(& priv->base,
+ rom_base_tmp, 48);
+
+ /* Prefer to return the first error that occurred.
+ */
+ if (err == 0) {
+ err = tmp_err;
+ }
+ }
+
+ return err;
+}
--- /dev/null
+/*
+ * (C) Copyright IBM Corporation 2007
+ * 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_devmem.h
+ * Functions and datastructures that are private to the /dev/mem based
+ * back-end for pciaccess.
+ *
+ * \author Ian Romanick <idr@us.ibm.com>
+ */
+
+extern int pci_device_linux_devmem_read_rom(struct pci_device *dev,
+ void *buffer);
--- /dev/null
+/*
+ * (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
+ * preferred 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 "config.h"
+
+#ifdef HAVE_MTRR
+#include <asm/mtrr.h>
+#include <sys/ioctl.h>
+#endif
+
+#include "pciaccess.h"
+#include "pciaccess_private.h"
+#include "linux_devmem.h"
+
+static const struct pci_system_methods linux_sysfs_methods;
+
+#define SYS_BUS_PCI "/sys/bus/pci/devices"
+
+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 populate_entries(struct pci_system * pci_sys);
+
+/**
+ * Attempt to access PCI subsystem using Linux's sysfs interface.
+ */
+_pci_hidden 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;
+#ifdef HAVE_MTRR
+ pci_sys->mtrr_fd = open("/proc/mtrr", O_WRONLY);
+#endif
+ err = 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));
+}
+
+
+int
+populate_entries( struct pci_system * p )
+{
+ struct dirent ** devices;
+ int n;
+ int i;
+ int err = 0;
+
+
+ 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 ) );
+
+ if (p->devices != NULL) {
+ for (i = 0 ; i < n ; i++) {
+ uint8_t config[48];
+ pciaddr_t bytes;
+ unsigned dom, bus, dev, func;
+ struct pci_device_private *device =
+ (struct pci_device_private *) &p->devices[i];
+
+
+ sscanf(devices[i]->d_name, "%04x:%02x:%02x.%1u",
+ & dom, & bus, & dev, & func);
+
+ device->base.domain = dom;
+ device->base.bus = bus;
+ device->base.dev = dev;
+ device->base.func = func;
+
+
+ err = pci_device_linux_sysfs_read(& device->base, config, 0,
+ 48, & bytes);
+ if ((bytes == 48) && !err) {
+ device->base.vendor_id = (uint16_t)config[0]
+ + ((uint16_t)config[1] << 8);
+ device->base.device_id = (uint16_t)config[2]
+ + ((uint16_t)config[3] << 8);
+ device->base.device_class = (uint32_t)config[9]
+ + ((uint32_t)config[10] << 8)
+ + ((uint32_t)config[11] << 16);
+ device->base.revision = config[8];
+ device->base.subvendor_id = (uint16_t)config[44]
+ + ((uint16_t)config[45] << 8);
+ device->base.subdevice_id = (uint16_t)config[46]
+ + ((uint16_t)config[47] << 8);
+ }
+
+ if (err) {
+ break;
+ }
+ }
+ }
+ else {
+ err = ENOMEM;
+ }
+ }
+
+ for (i = 0; i < n; i++)
+ free(devices[i]);
+ free(devices);
+
+ if (err) {
+ free(p->devices);
+ p->devices = NULL;
+ }
+
+ return err;
+}
+
+
+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 ) {
+ struct pci_device_private *priv = (struct pci_device_private *) dev;
+
+ dev->irq = config[60];
+ priv->header_type = config[14];
+
+
+ /* 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 ) {
+ priv->rom_base = low_addr;
+ 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;
+ size_t rom_size;
+ size_t total_bytes;
+
+
+ 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 ) {
+#ifdef LINUX_ROM
+ /* If reading the ROM using sysfs fails, fall back to the old
+ * /dev/mem based interface.
+ * disable this for newer kernels using configure
+ */
+ return pci_device_linux_devmem_read_rom(dev, buffer);
+#else
+ return errno;
+#endif
+ }
+
+
+ if ( fstat( fd, & st ) == -1 ) {
+ close( fd );
+ return errno;
+ }
+
+ rom_size = st.st_size;
+ if ( rom_size == 0 )
+ rom_size = 0x10000;
+
+ /* 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 );
+
+ for ( total_bytes = 0 ; total_bytes < rom_size ; /* empty */ ) {
+ const int bytes = read( fd, (char *) buffer + total_bytes,
+ rom_size - total_bytes );
+ if ( bytes == -1 ) {
+ err = errno;
+ break;
+ }
+ else if ( bytes == 0 ) {
+ break;
+ }
+
+ total_bytes += bytes;
+ }
+
+
+ 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;
+ char *data_bytes = data;
+
+ 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_bytes, 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 += 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;
+ const char *data_bytes = data;
+
+ 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_bytes, 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 += bytes;
+ }
+
+ if ( bytes_written != NULL ) {
+ *bytes_written = size - temp_size;
+ }
+
+ close( fd );
+ return err;
+}
+
+static int
+pci_device_linux_sysfs_map_range_wc(struct pci_device *dev,
+ struct pci_device_mapping *map)
+{
+ char name[256];
+ int fd;
+ const int prot = ((map->flags & PCI_DEV_MAP_FLAG_WRITABLE) != 0)
+ ? (PROT_READ | PROT_WRITE) : PROT_READ;
+ const int open_flags = ((map->flags & PCI_DEV_MAP_FLAG_WRITABLE) != 0)
+ ? O_RDWR : O_RDONLY;
+ const off_t offset = map->base - dev->regions[map->region].base_addr;
+
+ snprintf(name, 255, "%s/%04x:%02x:%02x.%1u/resource%u_wc",
+ SYS_BUS_PCI,
+ dev->domain,
+ dev->bus,
+ dev->dev,
+ dev->func,
+ map->region);
+ fd = open(name, open_flags);
+ if (fd == -1)
+ return errno;
+
+ map->memory = mmap(NULL, map->size, prot, MAP_SHARED, fd, offset);
+ if (map->memory == MAP_FAILED) {
+ map->memory = NULL;
+ close(fd);
+ return errno;
+ }
+
+ close(fd);
+
+ return 0;
+}
+
+/**
+ * Map a memory region for a device using the Linux sysfs interface.
+ *
+ * \param dev Device whose memory region is to be mapped.
+ * \param map Parameters of the mapping that is to be created.
+ *
+ * \return
+ * Zero on success or an \c errno value on failure.
+ *
+ * \sa pci_device_map_rrange, pci_device_linux_sysfs_unmap_range
+ *
+ * \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_range(struct pci_device *dev,
+ struct pci_device_mapping *map)
+{
+ char name[256];
+ int fd;
+ int err = 0;
+ const int prot = ((map->flags & PCI_DEV_MAP_FLAG_WRITABLE) != 0)
+ ? (PROT_READ | PROT_WRITE) : PROT_READ;
+ const int open_flags = ((map->flags & PCI_DEV_MAP_FLAG_WRITABLE) != 0)
+ ? O_RDWR : O_RDONLY;
+ const off_t offset = map->base - dev->regions[map->region].base_addr;
+#ifdef HAVE_MTRR
+ struct mtrr_sentry sentry = {
+ .base = map->base,
+ .size = map->size,
+ .type = MTRR_TYPE_UNCACHABLE
+ };
+#endif
+
+ /* For WC mappings, try sysfs resourceN_wc file first */
+ if ((map->flags & PCI_DEV_MAP_FLAG_WRITE_COMBINE) &&
+ !pci_device_linux_sysfs_map_range_wc(dev, map))
+ return 0;
+
+ snprintf(name, 255, "%s/%04x:%02x:%02x.%1u/resource%u",
+ SYS_BUS_PCI,
+ dev->domain,
+ dev->bus,
+ dev->dev,
+ dev->func,
+ map->region);
+
+ fd = open(name, open_flags);
+ if (fd == -1) {
+ return errno;
+ }
+
+
+ map->memory = mmap(NULL, map->size, prot, MAP_SHARED, fd, offset);
+ if (map->memory == MAP_FAILED) {
+ map->memory = NULL;
+ close(fd);
+ return errno;
+ }
+
+#ifdef HAVE_MTRR
+ if ((map->flags & PCI_DEV_MAP_FLAG_CACHABLE) != 0) {
+ sentry.type = MTRR_TYPE_WRBACK;
+ } else if ((map->flags & PCI_DEV_MAP_FLAG_WRITE_COMBINE) != 0) {
+ sentry.type = MTRR_TYPE_WRCOMB;
+ }
+
+ if (pci_sys->mtrr_fd != -1 && sentry.type != MTRR_TYPE_UNCACHABLE) {
+ if (ioctl(pci_sys->mtrr_fd, MTRRIOC_ADD_ENTRY, &sentry) < 0) {
+ /* FIXME: Should we report an error in this case?
+ */
+ fprintf(stderr, "error setting MTRR "
+ "(base = 0x%08lx, size = 0x%08x, type = %u) %s (%d)\n",
+ sentry.base, sentry.size, sentry.type,
+ strerror(errno), errno);
+/* err = errno;*/
+ }
+ /* KLUDGE ALERT -- rewrite the PTEs to turn off the CD and WT bits */
+ mprotect (map->memory, map->size, PROT_NONE);
+ err = mprotect (map->memory, map->size, PROT_READ|PROT_WRITE);
+
+ if (err != 0) {
+ fprintf(stderr, "mprotect(PROT_READ | PROT_WRITE) failed: %s\n",
+ strerror(errno));
+ fprintf(stderr, "remapping without mprotect performance kludge.\n");
+
+ munmap(map->memory, map->size);
+ map->memory = mmap(NULL, map->size, prot, MAP_SHARED, fd, offset);
+ if (map->memory == MAP_FAILED) {
+ map->memory = NULL;
+ close(fd);
+ return errno;
+ }
+ }
+ }
+#endif
+
+ close(fd);
+
+ return 0;
+}
+
+/**
+ * Unmap a memory region for a device using the Linux sysfs interface.
+ *
+ * \param dev Device whose memory region is to be unmapped.
+ * \param map Parameters of the mapping that is to be destroyed.
+ *
+ * \return
+ * Zero on success or an \c errno value on failure.
+ *
+ * \sa pci_device_map_rrange, pci_device_linux_sysfs_map_range
+ *
+ * \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_range(struct pci_device *dev,
+ struct pci_device_mapping *map)
+{
+ int err = 0;
+#ifdef HAVE_MTRR
+ struct mtrr_sentry sentry = {
+ .base = map->base,
+ .size = map->size,
+ .type = MTRR_TYPE_UNCACHABLE
+ };
+#endif
+
+ err = pci_device_generic_unmap_range (dev, map);
+ if (err)
+ return err;
+
+#ifdef HAVE_MTRR
+ if ((map->flags & PCI_DEV_MAP_FLAG_CACHABLE) != 0) {
+ sentry.type = MTRR_TYPE_WRBACK;
+ } else if ((map->flags & PCI_DEV_MAP_FLAG_WRITE_COMBINE) != 0) {
+ sentry.type = MTRR_TYPE_WRCOMB;
+ }
+
+ if (pci_sys->mtrr_fd != -1 && sentry.type != MTRR_TYPE_UNCACHABLE) {
+ if (ioctl(pci_sys->mtrr_fd, MTRRIOC_DEL_ENTRY, &sentry) < 0) {
+ /* FIXME: Should we report an error in this case?
+ */
+ fprintf(stderr, "error setting MTRR "
+ "(base = 0x%08lx, size = 0x%08x, type = %u) %s (%d)\n",
+ sentry.base, sentry.size, sentry.type,
+ strerror(errno), errno);
+/* err = errno;*/
+ }
+ }
+#endif
+
+ return err;
+}
+
+static void pci_device_linux_sysfs_enable(struct pci_device *dev)
+{
+ char name[256];
+ int fd;
+
+ snprintf( name, 255, "%s/%04x:%02x:%02x.%1u/enable",
+ SYS_BUS_PCI,
+ dev->domain,
+ dev->bus,
+ dev->dev,
+ dev->func );
+
+ fd = open( name, O_RDWR );
+ if (fd == -1)
+ return;
+
+ write( fd, "1", 1 );
+ close(fd);
+}
+
+static int pci_device_linux_sysfs_boot_vga(struct pci_device *dev)
+{
+ char name[256];
+ char reply[3];
+ int fd, bytes_read;
+ int ret = 0;
+
+ snprintf( name, 255, "%s/%04x:%02x:%02x.%1u/boot_vga",
+ SYS_BUS_PCI,
+ dev->domain,
+ dev->bus,
+ dev->dev,
+ dev->func );
+
+ fd = open( name, O_RDONLY );
+ if (fd == -1)
+ return 0;
+
+ bytes_read = read(fd, reply, 1);
+ if (bytes_read != 1)
+ goto out;
+ if (reply[0] == '1')
+ ret = 1;
+out:
+ close(fd);
+ return ret;
+}
+
+static int pci_device_linux_sysfs_has_kernel_driver(struct pci_device *dev)
+{
+ char name[256];
+ struct stat dummy;
+ int ret;
+
+ snprintf( name, 255, "%s/%04x:%02x:%02x.%1u/driver",
+ SYS_BUS_PCI,
+ dev->domain,
+ dev->bus,
+ dev->dev,
+ dev->func );
+
+ ret = stat(name, &dummy);
+ if (ret < 0)
+ return 0;
+ return 1;
+}
+
+static struct pci_io_handle *
+pci_device_linux_sysfs_open_device_io(struct pci_io_handle *ret,
+ struct pci_device *dev, int bar,
+ pciaddr_t base, pciaddr_t size)
+{
+ char name[PATH_MAX];
+
+ snprintf(name, PATH_MAX, "%s/%04x:%02x:%02x.%1u/resource%d",
+ SYS_BUS_PCI, dev->domain, dev->bus, dev->dev, dev->func, bar);
+
+ ret->fd = open(name, O_RDWR);
+
+ if (ret->fd < 0)
+ return NULL;
+
+ ret->base = base;
+ ret->size = size;
+
+ return ret;
+}
+
+static struct pci_io_handle *
+pci_device_linux_sysfs_open_legacy_io(struct pci_io_handle *ret,
+ struct pci_device *dev, pciaddr_t base,
+ pciaddr_t size)
+{
+ char name[PATH_MAX];
+
+ /* First check if there's a legacy io method for the device */
+ while (dev) {
+ snprintf(name, PATH_MAX, "/sys/class/pci_bus/%04x:%02x/legacy_io",
+ dev->domain, dev->bus);
+
+ ret->fd = open(name, O_RDWR);
+ if (ret->fd >= 0)
+ break;
+
+ dev = pci_device_get_parent_bridge(dev);
+ }
+
+ /* If not, /dev/port is the best we can do */
+ if (!dev)
+ ret->fd = open("/dev/port", O_RDWR);
+
+ if (ret->fd < 0)
+ return NULL;
+
+ ret->base = base;
+ ret->size = size;
+
+ return ret;
+}
+
+static void
+pci_device_linux_sysfs_close_io(struct pci_device *dev,
+ struct pci_io_handle *handle)
+{
+ close(handle->fd);
+}
+
+static uint32_t
+pci_device_linux_sysfs_read32(struct pci_io_handle *handle, uint32_t port)
+{
+ uint32_t ret;
+
+ pread(handle->fd, &ret, 4, port + handle->base);
+
+ return ret;
+}
+
+static uint16_t
+pci_device_linux_sysfs_read16(struct pci_io_handle *handle, uint32_t port)
+{
+ uint16_t ret;
+
+ pread(handle->fd, &ret, 2, port + handle->base);
+
+ return ret;
+}
+
+static uint8_t
+pci_device_linux_sysfs_read8(struct pci_io_handle *handle, uint32_t port)
+{
+ uint8_t ret;
+
+ pread(handle->fd, &ret, 1, port + handle->base);
+
+ return ret;
+}
+
+static void
+pci_device_linux_sysfs_write32(struct pci_io_handle *handle, uint32_t port,
+ uint32_t data)
+{
+ pwrite(handle->fd, &data, 4, port + handle->base);
+}
+
+static void
+pci_device_linux_sysfs_write16(struct pci_io_handle *handle, uint32_t port,
+ uint16_t data)
+{
+ pwrite(handle->fd, &data, 2, port + handle->base);
+}
+
+static void
+pci_device_linux_sysfs_write8(struct pci_io_handle *handle, uint32_t port,
+ uint8_t data)
+{
+ pwrite(handle->fd, &data, 1, port + handle->base);
+}
+
+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_range = pci_device_linux_sysfs_map_range,
+ .unmap_range = pci_device_linux_sysfs_unmap_range,
+
+ .read = pci_device_linux_sysfs_read,
+ .write = pci_device_linux_sysfs_write,
+
+ .fill_capabilities = pci_fill_capabilities_generic,
+ .enable = pci_device_linux_sysfs_enable,
+ .boot_vga = pci_device_linux_sysfs_boot_vga,
+ .has_kernel_driver = pci_device_linux_sysfs_has_kernel_driver,
+
+ .open_device_io = pci_device_linux_sysfs_open_device_io,
+ .open_legacy_io = pci_device_linux_sysfs_open_legacy_io,
+ .close_io = pci_device_linux_sysfs_close_io,
+ .read32 = pci_device_linux_sysfs_read32,
+ .read16 = pci_device_linux_sysfs_read16,
+ .read8 = pci_device_linux_sysfs_read8,
+ .write32 = pci_device_linux_sysfs_write32,
+ .write16 = pci_device_linux_sysfs_write16,
+ .write8 = pci_device_linux_sysfs_write8,
+};
--- /dev/null
+/*
+ * Copyright (c) 2008 Juan Romero Pardines
+ * Copyright (c) 2008 Mark Kettenis
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <sys/param.h>
+#include <sys/ioctl.h>
+#include <sys/mman.h>
+#include <sys/types.h>
+
+#include <machine/sysarch.h>
+#include <machine/mtrr.h>
+
+#include <dev/pci/pciio.h>
+#include <dev/pci/pcireg.h>
+#include <dev/pci/pcidevs.h>
+
+#include <errno.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+
+#include "pciaccess.h"
+#include "pciaccess_private.h"
+
+static int pcifd;
+
+static int
+pci_read(int bus, int dev, int func, uint32_t reg, uint32_t *val)
+{
+ struct pciio_bdf_cfgreg io;
+ int err;
+
+ bzero(&io, sizeof(io));
+ io.bus = bus;
+ io.device = dev;
+ io.function = func;
+ io.cfgreg.reg = reg;
+
+ err = ioctl(pcifd, PCI_IOC_BDF_CFGREAD, &io);
+ if (err)
+ return (err);
+
+ *val = io.cfgreg.val;
+
+ return 0;
+}
+
+static int
+pci_write(int bus, int dev, int func, uint32_t reg, uint32_t val)
+{
+ struct pciio_bdf_cfgreg io;
+
+ bzero(&io, sizeof(io));
+ io.bus = bus;
+ io.device = dev;
+ io.function = func;
+ io.cfgreg.reg = reg;
+ io.cfgreg.val = val;
+
+ return ioctl(pcifd, PCI_IOC_BDF_CFGWRITE, &io);
+}
+
+static int
+pci_nfuncs(int bus, int dev)
+{
+ uint32_t hdr;
+
+ if (pci_read(bus, dev, 0, PCI_BHLC_REG, &hdr) != 0)
+ return -1;
+
+ return (PCI_HDRTYPE_MULTIFN(hdr) ? 8 : 1);
+}
+
+static int
+pci_device_netbsd_map_range(struct pci_device *dev,
+ struct pci_device_mapping *map)
+{
+ struct mtrr mtrr;
+ int fd, error, nmtrr, prot = PROT_READ;
+
+ if ((fd = open("/dev/mem", O_RDWR)) == -1)
+ return errno;
+
+ if (map->flags & PCI_DEV_MAP_FLAG_WRITABLE)
+ prot |= PROT_WRITE;
+
+ map->memory = mmap(NULL, map->size, prot, MAP_SHARED,
+ fd, map->base);
+ if (map->memory == MAP_FAILED)
+ return errno;
+
+ /* No need to set an MTRR if it's the default mode. */
+ if ((map->flags & PCI_DEV_MAP_FLAG_CACHABLE) ||
+ (map->flags & PCI_DEV_MAP_FLAG_WRITE_COMBINE)) {
+ mtrr.base = map->base;
+ mtrr.len = map->size;
+ mtrr.flags = MTRR_VALID;
+
+ if (map->flags & PCI_DEV_MAP_FLAG_CACHABLE)
+ mtrr.type = MTRR_TYPE_WB;
+ if (map->flags & PCI_DEV_MAP_FLAG_WRITE_COMBINE)
+ mtrr.type = MTRR_TYPE_WC;
+#ifdef __i386__
+ error = i386_set_mtrr(&mtrr, &nmtrr);
+#endif
+#ifdef __amd64__
+ error = x86_64_set_mtrr(&mtrr, &nmtrr);
+#endif
+ if (error) {
+ close(fd);
+ return errno;
+ }
+ }
+
+ close(fd);
+
+ return 0;
+}
+
+static int
+pci_device_netbsd_unmap_range(struct pci_device *dev,
+ struct pci_device_mapping *map)
+{
+ struct mtrr mtrr;
+ int nmtrr, error;
+
+ if ((map->flags & PCI_DEV_MAP_FLAG_CACHABLE) ||
+ (map->flags & PCI_DEV_MAP_FLAG_WRITE_COMBINE)) {
+ mtrr.base = map->base;
+ mtrr.len = map->size;
+ mtrr.type = MTRR_TYPE_UC;
+ mtrr.flags = 0; /* clear/set MTRR */
+#ifdef __i386__
+ error = i386_set_mtrr(&mtrr, &nmtrr);
+#endif
+#ifdef __amd64__
+ error = x86_64_set_mtrr(&mtrr, &nmtrr);
+#endif
+ if (error)
+ return errno;
+ }
+
+ return pci_device_generic_unmap_range(dev, map);
+}
+
+static int
+pci_device_netbsd_read(struct pci_device *dev, void *data,
+ pciaddr_t offset, pciaddr_t size, pciaddr_t *bytes_read)
+{
+ struct pciio_bdf_cfgreg io;
+
+ io.bus = dev->bus;
+ io.device = dev->dev;
+ io.function = dev->func;
+
+ *bytes_read = 0;
+ while (size > 0) {
+ int toread = MIN(size, 4 - (offset & 0x3));
+
+ io.cfgreg.reg = (offset & ~0x3);
+
+ if (ioctl(pcifd, PCI_IOC_BDF_CFGREAD, &io) == -1)
+ return errno;
+
+ io.cfgreg.val = htole32(io.cfgreg.val);
+ io.cfgreg.val >>= ((offset & 0x3) * 8);
+
+ memcpy(data, &io.cfgreg.val, toread);
+
+ offset += toread;
+ data = (char *)data + toread;
+ size -= toread;
+ *bytes_read += toread;
+ }
+
+ return 0;
+}
+
+static int
+pci_device_netbsd_write(struct pci_device *dev, const void *data,
+ pciaddr_t offset, pciaddr_t size, pciaddr_t *bytes_written)
+{
+ struct pciio_bdf_cfgreg io;
+
+ if ((offset % 4) != 0 || (size % 4) != 0)
+ return EINVAL;
+
+ io.bus = dev->bus;
+ io.device = dev->dev;
+ io.function = dev->func;
+
+ *bytes_written = 0;
+ while (size > 0) {
+ io.cfgreg.reg = offset;
+ memcpy(&io.cfgreg.val, data, 4);
+
+ if (ioctl(pcifd, PCI_IOC_BDF_CFGWRITE, &io) == -1)
+ return errno;
+
+ offset += 4;
+ data = (char *)data + 4;
+ size -= 4;
+ *bytes_written += 4;
+ }
+
+ return 0;
+}
+
+static void
+pci_system_netbsd_destroy(void)
+{
+ close(pcifd);
+ free(pci_sys);
+ pci_sys = NULL;
+}
+
+static int
+pci_device_netbsd_probe(struct pci_device *device)
+{
+ struct pci_device_private *priv = (struct pci_device_private *)device;
+ struct pci_mem_region *region;
+ uint64_t reg64, size64;
+ uint32_t bar, reg, size;
+ int bus, dev, func, err;
+
+ bus = device->bus;
+ dev = device->dev;
+ func = device->func;
+
+ err = pci_read(bus, dev, func, PCI_BHLC_REG, ®);
+ if (err)
+ return err;
+
+ priv->header_type = PCI_HDRTYPE_TYPE(reg);
+ if (priv->header_type != 0)
+ return 0;
+
+ region = device->regions;
+ for (bar = PCI_MAPREG_START; bar < PCI_MAPREG_END;
+ bar += sizeof(uint32_t), region++) {
+ err = pci_read(bus, dev, func, bar, ®);
+ if (err)
+ return err;
+
+ /* Probe the size of the region. */
+ err = pci_write(bus, dev, func, bar, ~0);
+ if (err)
+ return err;
+ pci_read(bus, dev, func, bar, &size);
+ pci_write(bus, dev, func, bar, reg);
+
+ if (PCI_MAPREG_TYPE(reg) == PCI_MAPREG_TYPE_IO) {
+ region->is_IO = 1;
+ region->base_addr = PCI_MAPREG_IO_ADDR(reg);
+ region->size = PCI_MAPREG_IO_SIZE(size);
+ } else {
+ if (PCI_MAPREG_MEM_PREFETCHABLE(reg))
+ region->is_prefetchable = 1;
+ switch(PCI_MAPREG_MEM_TYPE(reg)) {
+ case PCI_MAPREG_MEM_TYPE_32BIT:
+ case PCI_MAPREG_MEM_TYPE_32BIT_1M:
+ region->base_addr = PCI_MAPREG_MEM_ADDR(reg);
+ region->size = PCI_MAPREG_MEM_SIZE(size);
+ break;
+ case PCI_MAPREG_MEM_TYPE_64BIT:
+ region->is_64 = 1;
+
+ reg64 = reg;
+ size64 = size;
+
+ bar += sizeof(uint32_t);
+
+ err = pci_read(bus, dev, func, bar, ®);
+ if (err)
+ return err;
+ reg64 |= (uint64_t)reg << 32;
+
+ err = pci_write(bus, dev, func, bar, ~0);
+ if (err)
+ return err;
+ pci_read(bus, dev, func, bar, &size);
+ pci_write(bus, dev, func, bar, reg64 >> 32);
+ size64 |= (uint64_t)size << 32;
+
+ region->base_addr = PCI_MAPREG_MEM64_ADDR(reg64);
+ region->size = PCI_MAPREG_MEM64_SIZE(size64);
+ region++;
+ break;
+ }
+ }
+ }
+
+ return 0;
+}
+
+static const struct pci_system_methods netbsd_pci_methods = {
+ pci_system_netbsd_destroy,
+ NULL,
+ NULL,
+ pci_device_netbsd_probe,
+ pci_device_netbsd_map_range,
+ pci_device_netbsd_unmap_range,
+ pci_device_netbsd_read,
+ pci_device_netbsd_write,
+ pci_fill_capabilities_generic
+};
+
+int
+pci_system_netbsd_create(void)
+{
+ struct pci_device_private *device;
+ int bus, dev, func, ndevs, nfuncs;
+ uint32_t reg;
+
+ pcifd = open("/dev/pci0", O_RDWR);
+ if (pcifd == -1)
+ return ENXIO;
+
+ pci_sys = calloc(1, sizeof(struct pci_system));
+ if (pci_sys == NULL) {
+ close(pcifd);
+ return ENOMEM;
+ }
+
+ pci_sys->methods = &netbsd_pci_methods;
+
+ ndevs = 0;
+ for (bus = 0; bus < 256; bus++) {
+ for (dev = 0; dev < 32; dev++) {
+ nfuncs = pci_nfuncs(bus, dev);
+ for (func = 0; func < nfuncs; func++) {
+ if (pci_read(bus, dev, func, PCI_ID_REG,
+ ®) != 0)
+ continue;
+ if (PCI_VENDOR(reg) == PCI_VENDOR_INVALID ||
+ PCI_VENDOR(reg) == 0)
+ continue;
+
+ ndevs++;
+ }
+ }
+ }
+
+ pci_sys->num_devices = ndevs;
+ pci_sys->devices = calloc(ndevs, sizeof(struct pci_device_private));
+ if (pci_sys->devices == NULL) {
+ free(pci_sys);
+ close(pcifd);
+ return ENOMEM;
+ }
+
+ device = pci_sys->devices;
+ for (bus = 0; bus < 256; bus++) {
+ for (dev = 0; dev < 32; dev++) {
+ nfuncs = pci_nfuncs(bus, dev);
+ for (func = 0; func < nfuncs; func++) {
+ if (pci_read(bus, dev, func, PCI_ID_REG,
+ ®) != 0)
+ continue;
+ if (PCI_VENDOR(reg) == PCI_VENDOR_INVALID ||
+ PCI_VENDOR(reg) == 0)
+ continue;
+
+ device->base.domain = 0;
+ device->base.bus = bus;
+ device->base.dev = dev;
+ device->base.func = func;
+ device->base.vendor_id = PCI_VENDOR(reg);
+ device->base.device_id = PCI_PRODUCT(reg);
+
+ if (pci_read(bus, dev, func, PCI_CLASS_REG,
+ ®) != 0)
+ continue;
+
+ device->base.device_class =
+ PCI_INTERFACE(reg) | PCI_CLASS(reg) << 16 |
+ PCI_SUBCLASS(reg) << 8;
+ device->base.revision = PCI_REVISION(reg);
+
+ if (pci_read(bus, dev, func, PCI_SUBSYS_ID_REG,
+ ®) != 0)
+ continue;
+
+ device->base.subvendor_id = PCI_VENDOR(reg);
+ device->base.subdevice_id = PCI_PRODUCT(reg);
+
+ device++;
+ }
+ }
+ }
+
+ return 0;
+}
--- /dev/null
+/*
+ * Copyright (c) 2008 Mark Kettenis
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <sys/param.h>
+#include <sys/ioctl.h>
+#include <sys/memrange.h>
+#include <sys/mman.h>
+#include <sys/pciio.h>
+
+#include <dev/pci/pcireg.h>
+#include <dev/pci/pcidevs.h>
+
+#include <errno.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "pciaccess.h"
+#include "pciaccess_private.h"
+
+/*
+ * This should allow for 16 domains, which should cover everything
+ * except perhaps the really big fridge-sized sparc64 server machines
+ * that are unlikely to have any graphics hardware in them.
+ */
+static int pcifd[16];
+static int ndomains;
+
+static int aperturefd = -1;
+
+static int
+pci_read(int domain, int bus, int dev, int func, uint32_t reg, uint32_t *val)
+{
+ struct pci_io io;
+ int err;
+
+ bzero(&io, sizeof(io));
+ io.pi_sel.pc_bus = bus;
+ io.pi_sel.pc_dev = dev;
+ io.pi_sel.pc_func = func;
+ io.pi_reg = reg;
+ io.pi_width = 4;
+
+ err = ioctl(pcifd[domain], PCIOCREAD, &io);
+ if (err)
+ return (err);
+
+ *val = io.pi_data;
+
+ return 0;
+}
+
+static int
+pci_write(int domain, int bus, int dev, int func, uint32_t reg, uint32_t val)
+{
+ struct pci_io io;
+
+ bzero(&io, sizeof(io));
+ io.pi_sel.pc_bus = bus;
+ io.pi_sel.pc_dev = dev;
+ io.pi_sel.pc_func = func;
+ io.pi_reg = reg;
+ io.pi_width = 4;
+ io.pi_data = val;
+
+ return ioctl(pcifd[domain], PCIOCWRITE, &io);
+}
+
+/**
+ * Read a VGA ROM
+ *
+ */
+static int
+pci_device_openbsd_read_rom(struct pci_device *device, void *buffer)
+{
+ struct pci_device_private *priv = (struct pci_device_private *)device;
+ unsigned char *bios;
+ pciaddr_t rom_base;
+ pciaddr_t rom_size;
+ u_int32_t csr, rom;
+ int pci_rom, domain, bus, dev, func;
+
+ domain = device->domain;
+ if (domain < 0 || domain >= ndomains)
+ return ENXIO;
+
+ bus = device->bus;
+ dev = device->dev;
+ func = device->func;
+
+ if (aperturefd == -1)
+ return ENOSYS;
+
+ if (priv->base.rom_size == 0) {
+#if defined(__alpha__) || defined(__amd64__) || defined(__i386__)
+ if ((device->device_class & 0x00ffff00) ==
+ ((PCI_CLASS_DISPLAY << 16) |
+ (PCI_SUBCLASS_DISPLAY_VGA << 8))) {
+ rom_base = 0xc0000;
+ rom_size = 0x10000;
+ pci_rom = 0;
+ } else
+#endif
+ return ENOSYS;
+ } else {
+ rom_base = priv->rom_base;
+ rom_size = priv->base.rom_size;
+ pci_rom = 1;
+
+ pci_read(domain, bus, dev, func, PCI_COMMAND_STATUS_REG, &csr);
+ pci_write(domain, bus, dev, func, PCI_COMMAND_STATUS_REG,
+ csr | PCI_COMMAND_MEM_ENABLE);
+ pci_read(domain, bus, dev, func, PCI_ROM_REG, &rom);
+ pci_write(domain, bus, dev, func, PCI_ROM_REG,
+ rom | PCI_ROM_ENABLE);
+ }
+
+ bios = mmap(NULL, rom_size, PROT_READ, MAP_SHARED,
+ aperturefd, (off_t)rom_base);
+ if (bios == MAP_FAILED)
+ return errno;
+
+ memcpy(buffer, bios, rom_size);
+ munmap(bios, rom_size);
+
+ if (pci_rom) {
+ /* Restore PCI config space */
+ pci_write(domain, bus, dev, func, PCI_ROM_REG, rom);
+ pci_write(domain, bus, dev, func, PCI_COMMAND_STATUS_REG, csr);
+ }
+ return 0;
+}
+
+static int
+pci_nfuncs(int domain, int bus, int dev)
+{
+ uint32_t hdr;
+
+ if (domain < 0 || domain >= ndomains)
+ return ENXIO;
+
+ if (pci_read(domain, bus, dev, 0, PCI_BHLC_REG, &hdr) != 0)
+ return -1;
+
+ return (PCI_HDRTYPE_MULTIFN(hdr) ? 8 : 1);
+}
+
+static int
+pci_device_openbsd_map_range(struct pci_device *dev,
+ struct pci_device_mapping *map)
+{
+ struct mem_range_desc mr;
+ struct mem_range_op mo;
+ int prot = PROT_READ;
+
+ if (map->flags & PCI_DEV_MAP_FLAG_WRITABLE)
+ prot |= PROT_WRITE;
+
+ map->memory = mmap(NULL, map->size, prot, MAP_SHARED, aperturefd,
+ map->base);
+ if (map->memory == MAP_FAILED)
+ return errno;
+#if defined(__i386__) || defined(__amd64__)
+ /* No need to set an MTRR if it's the default mode. */
+ if ((map->flags & PCI_DEV_MAP_FLAG_CACHABLE) ||
+ (map->flags & PCI_DEV_MAP_FLAG_WRITE_COMBINE)) {
+ mr.mr_base = map->base;
+ mr.mr_len = map->size;
+ mr.mr_flags = 0;
+ if (map->flags & PCI_DEV_MAP_FLAG_CACHABLE)
+ mr.mr_flags |= MDF_WRITEBACK;
+ if (map->flags & PCI_DEV_MAP_FLAG_WRITE_COMBINE)
+ mr.mr_flags |= MDF_WRITECOMBINE;
+ strlcpy(mr.mr_owner, "pciaccess", sizeof(mr.mr_owner));
+
+ mo.mo_desc = &mr;
+ mo.mo_arg[0] = MEMRANGE_SET_UPDATE;
+
+ if (ioctl(aperturefd, MEMRANGE_SET, &mo))
+ (void)fprintf(stderr, "mtrr set failed: %s\n",
+ strerror(errno));
+ }
+#endif
+ return 0;
+}
+
+static int
+pci_device_openbsd_unmap_range(struct pci_device *dev,
+ struct pci_device_mapping *map)
+{
+#if defined(__i386__) || defined(__amd64__)
+ struct mem_range_desc mr;
+ struct mem_range_op mo;
+
+ if ((map->flags & PCI_DEV_MAP_FLAG_CACHABLE) ||
+ (map->flags & PCI_DEV_MAP_FLAG_WRITE_COMBINE)) {
+ mr.mr_base = map->base;
+ mr.mr_len = map->size;
+ mr.mr_flags = MDF_UNCACHEABLE;
+ strlcpy(mr.mr_owner, "pciaccess", sizeof(mr.mr_owner));
+
+ mo.mo_desc = &mr;
+ mo.mo_arg[0] = MEMRANGE_SET_REMOVE;
+
+ (void)ioctl(aperturefd, MEMRANGE_SET, &mo);
+ }
+#endif
+ return pci_device_generic_unmap_range(dev, map);
+}
+
+static int
+pci_device_openbsd_read(struct pci_device *dev, void *data,
+ pciaddr_t offset, pciaddr_t size, pciaddr_t *bytes_read)
+{
+ struct pci_io io;
+
+ io.pi_sel.pc_bus = dev->bus;
+ io.pi_sel.pc_dev = dev->dev;
+ io.pi_sel.pc_func = dev->func;
+
+ *bytes_read = 0;
+ while (size > 0) {
+ int toread = MIN(size, 4 - (offset & 0x3));
+
+ io.pi_reg = (offset & ~0x3);
+ io.pi_width = 4;
+
+ if (ioctl(pcifd[dev->domain], PCIOCREAD, &io) == -1)
+ return errno;
+
+ io.pi_data = htole32(io.pi_data);
+ io.pi_data >>= ((offset & 0x3) * 8);
+
+ memcpy(data, &io.pi_data, toread);
+
+ offset += toread;
+ data = (char *)data + toread;
+ size -= toread;
+ *bytes_read += toread;
+ }
+
+ return 0;
+}
+
+static int
+pci_device_openbsd_write(struct pci_device *dev, const void *data,
+ pciaddr_t offset, pciaddr_t size, pciaddr_t *bytes_written)
+{
+ struct pci_io io;
+
+ if ((offset % 4) != 0 || (size % 4) != 0)
+ return EINVAL;
+
+ io.pi_sel.pc_bus = dev->bus;
+ io.pi_sel.pc_dev = dev->dev;
+ io.pi_sel.pc_func = dev->func;
+
+ *bytes_written = 0;
+ while (size > 0) {
+ io.pi_reg = offset;
+ io.pi_width = 4;
+ memcpy(&io.pi_data, data, 4);
+
+ if (ioctl(pcifd[dev->domain], PCIOCWRITE, &io) == -1)
+ return errno;
+
+ offset += 4;
+ data = (char *)data + 4;
+ size -= 4;
+ *bytes_written += 4;
+ }
+
+ return 0;
+}
+
+static void
+pci_system_openbsd_destroy(void)
+{
+ int domain;
+
+ for (domain = 0; domain < ndomains; domain++)
+ close(pcifd[domain]);
+ ndomains = 0;
+}
+
+static int
+pci_device_openbsd_probe(struct pci_device *device)
+{
+ struct pci_device_private *priv = (struct pci_device_private *)device;
+ struct pci_mem_region *region;
+ uint64_t reg64, size64;
+ uint32_t bar, reg, size;
+ int domain, bus, dev, func, err;
+
+ domain = device->domain;
+ bus = device->bus;
+ dev = device->dev;
+ func = device->func;
+
+ err = pci_read(domain, bus, dev, func, PCI_BHLC_REG, ®);
+ if (err)
+ return err;
+
+ priv->header_type = PCI_HDRTYPE_TYPE(reg);
+ if (priv->header_type != 0)
+ return 0;
+
+ region = device->regions;
+ for (bar = PCI_MAPREG_START; bar < PCI_MAPREG_END;
+ bar += sizeof(uint32_t), region++) {
+ err = pci_read(domain, bus, dev, func, bar, ®);
+ if (err)
+ return err;
+
+ /* Probe the size of the region. */
+ err = pci_write(domain, bus, dev, func, bar, ~0);
+ if (err)
+ return err;
+ pci_read(domain, bus, dev, func, bar, &size);
+ pci_write(domain, bus, dev, func, bar, reg);
+
+ if (PCI_MAPREG_TYPE(reg) == PCI_MAPREG_TYPE_IO) {
+ region->is_IO = 1;
+ region->base_addr = PCI_MAPREG_IO_ADDR(reg);
+ region->size = PCI_MAPREG_IO_SIZE(size);
+ } else {
+ if (PCI_MAPREG_MEM_PREFETCHABLE(reg))
+ region->is_prefetchable = 1;
+ switch(PCI_MAPREG_MEM_TYPE(reg)) {
+ case PCI_MAPREG_MEM_TYPE_32BIT:
+ case PCI_MAPREG_MEM_TYPE_32BIT_1M:
+ region->base_addr = PCI_MAPREG_MEM_ADDR(reg);
+ region->size = PCI_MAPREG_MEM_SIZE(size);
+ break;
+ case PCI_MAPREG_MEM_TYPE_64BIT:
+ region->is_64 = 1;
+
+ reg64 = reg;
+ size64 = size;
+
+ bar += sizeof(uint32_t);
+
+ err = pci_read(domain, bus, dev, func, bar, ®);
+ if (err)
+ return err;
+ reg64 |= (uint64_t)reg << 32;
+
+ err = pci_write(domain, bus, dev, func, bar, ~0);
+ if (err)
+ return err;
+ pci_read(domain, bus, dev, func, bar, &size);
+ pci_write(domain, bus, dev, func, bar, reg64 >> 32);
+ size64 |= (uint64_t)size << 32;
+
+ region->base_addr = PCI_MAPREG_MEM64_ADDR(reg64);
+ region->size = PCI_MAPREG_MEM64_SIZE(size64);
+ region++;
+ break;
+ }
+ }
+ }
+
+ /* Probe expansion ROM if present */
+ err = pci_read(domain, bus, dev, func, PCI_ROM_REG, ®);
+ if (err)
+ return err;
+ if (reg != 0) {
+ err = pci_write(domain, bus, dev, func, PCI_ROM_REG, ~PCI_ROM_ENABLE);
+ if (err)
+ return err;
+ pci_read(domain, bus, dev, func, PCI_ROM_REG, &size);
+ pci_write(domain, bus, dev, func, PCI_ROM_REG, reg);
+
+ if (PCI_ROM_ADDR(reg) != 0) {
+ priv->rom_base = PCI_ROM_ADDR(reg);
+ device->rom_size = PCI_ROM_SIZE(size);
+ }
+ }
+ return 0;
+}
+
+static const struct pci_system_methods openbsd_pci_methods = {
+ pci_system_openbsd_destroy,
+ NULL,
+ pci_device_openbsd_read_rom,
+ pci_device_openbsd_probe,
+ pci_device_openbsd_map_range,
+ pci_device_openbsd_unmap_range,
+ pci_device_openbsd_read,
+ pci_device_openbsd_write,
+ pci_fill_capabilities_generic
+};
+
+int
+pci_system_openbsd_create(void)
+{
+ struct pci_device_private *device;
+ int domain, bus, dev, func, ndevs, nfuncs;
+ char path[MAXPATHLEN];
+ uint32_t reg;
+
+ if (ndomains > 0)
+ return 0;
+
+ for (domain = 0; domain < sizeof(pcifd) / sizeof(pcifd[0]); domain++) {
+ snprintf(path, sizeof(path), "/dev/pci%d", domain);
+ pcifd[domain] = open(path, O_RDWR);
+ if (pcifd[domain] == -1)
+ break;
+ ndomains++;
+ }
+
+ if (ndomains == 0)
+ return ENXIO;
+
+ pci_sys = calloc(1, sizeof(struct pci_system));
+ if (pci_sys == NULL) {
+ for (domain = 0; domain < ndomains; domain++)
+ close(pcifd[domain]);
+ ndomains = 0;
+ return ENOMEM;
+ }
+
+ pci_sys->methods = &openbsd_pci_methods;
+
+ ndevs = 0;
+ for (domain = 0; domain < ndomains; domain++) {
+ for (bus = 0; bus < 256; bus++) {
+ for (dev = 0; dev < 32; dev++) {
+ nfuncs = pci_nfuncs(domain, bus, dev);
+ for (func = 0; func < nfuncs; func++) {
+ if (pci_read(domain, bus, dev, func,
+ PCI_ID_REG, ®) != 0)
+ continue;
+ if (PCI_VENDOR(reg) == PCI_VENDOR_INVALID ||
+ PCI_VENDOR(reg) == 0)
+ continue;
+
+ ndevs++;
+ }
+ }
+ }
+ }
+
+ pci_sys->num_devices = ndevs;
+ pci_sys->devices = calloc(ndevs, sizeof(struct pci_device_private));
+ if (pci_sys->devices == NULL) {
+ free(pci_sys);
+ pci_sys = NULL;
+ for (domain = 0; domain < ndomains; domain++)
+ close(pcifd[domain]);
+ ndomains = 0;
+ return ENOMEM;
+ }
+
+ device = pci_sys->devices;
+ for (domain = 0; domain < ndomains; domain++) {
+ for (bus = 0; bus < 256; bus++) {
+ for (dev = 0; dev < 32; dev++) {
+ nfuncs = pci_nfuncs(domain, bus, dev);
+ for (func = 0; func < nfuncs; func++) {
+ if (pci_read(domain, bus, dev, func,
+ PCI_ID_REG, ®) != 0)
+ continue;
+ if (PCI_VENDOR(reg) == PCI_VENDOR_INVALID ||
+ PCI_VENDOR(reg) == 0)
+ continue;
+
+ device->base.domain = domain;
+ device->base.bus = bus;
+ device->base.dev = dev;
+ device->base.func = func;
+ device->base.vendor_id = PCI_VENDOR(reg);
+ device->base.device_id = PCI_PRODUCT(reg);
+
+ if (pci_read(domain, bus, dev, func,
+ PCI_CLASS_REG, ®) != 0)
+ continue;
+
+ device->base.device_class =
+ PCI_INTERFACE(reg) |
+ PCI_CLASS(reg) << 16 |
+ PCI_SUBCLASS(reg) << 8;
+ device->base.revision = PCI_REVISION(reg);
+
+ if (pci_read(domain, bus, dev, func,
+ PCI_SUBVEND_0, ®) != 0)
+ continue;
+
+ device->base.subvendor_id = PCI_VENDOR(reg);
+ device->base.subdevice_id = PCI_PRODUCT(reg);
+
+ device++;
+ }
+ }
+ }
+ }
+
+ return 0;
+}
+
+void
+pci_system_openbsd_init_dev_mem(int fd)
+{
+ aperturefd = fd;
+}
--- /dev/null
+/*
+ * Copyright © 2007 Sun Microsystems, Inc. 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
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * 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 NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS 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.
+ */
+#ifndef _SYS_PCI_TOOLS_H
+#define _SYS_PCI_TOOLS_H
+
+#pragma ident "@(#)pci_tools.h 1.4 05/09/28 SMI"
+
+#include <sys/modctl.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * Versioning. Have different versions for userland program and drivers, so
+ * they can all stay in sync with each other.
+ */
+#define PCITOOL_USER_VERSION 1
+#define PCITOOL_DRVR_VERSION 1
+
+/* File suffixes for nexus pcitool nodes. */
+#define PCI_MINOR_REG "reg"
+#define PCI_MINOR_INTR "intr"
+
+/*
+ * Ioctls for PCI tools.
+ */
+#define PCITOOL_IOC (('P' << 24) | ('C' << 16) | ('T' << 8))
+
+/* Read/write a device on a PCI bus, in physical space. */
+#define PCITOOL_DEVICE_GET_REG (PCITOOL_IOC | 1)
+#define PCITOOL_DEVICE_SET_REG (PCITOOL_IOC | 2)
+
+/* Read/write the PCI nexus bridge, in physical space. */
+#define PCITOOL_NEXUS_GET_REG (PCITOOL_IOC | 3)
+#define PCITOOL_NEXUS_SET_REG (PCITOOL_IOC | 4)
+
+/* Get/set interrupt-CPU mapping for PCI devices. */
+#define PCITOOL_DEVICE_GET_INTR (PCITOOL_IOC | 5)
+#define PCITOOL_DEVICE_SET_INTR (PCITOOL_IOC | 6)
+
+/* Return the number of supported interrupts on a PCI bus. */
+#define PCITOOL_DEVICE_NUM_INTR (PCITOOL_IOC | 7)
+
+
+/*
+ * This file contains data structures for the pci tool.
+ */
+#define PCITOOL_CONFIG 0
+#define PCITOOL_BAR0 1
+#define PCITOOL_BAR1 2
+#define PCITOOL_BAR2 3
+#define PCITOOL_BAR3 4
+#define PCITOOL_BAR4 5
+#define PCITOOL_BAR5 6
+#define PCITOOL_ROM 7
+
+/*
+ * Pass this through barnum to signal to use a base addr instead.
+ * This is for platforms which do not have a way to automatically map
+ * a selected bank to a base addr.
+ */
+#define PCITOOL_BASE 0xFF
+
+/*
+ * BAR corresponding to space desired.
+ */
+typedef enum {
+ config = PCITOOL_CONFIG,
+ bar0 = PCITOOL_BAR0,
+ bar1 = PCITOOL_BAR1,
+ bar2 = PCITOOL_BAR2,
+ bar3 = PCITOOL_BAR3,
+ bar4 = PCITOOL_BAR4,
+ bar5 = PCITOOL_BAR5,
+ rom = PCITOOL_ROM
+} pcitool_bars_t;
+
+
+/*
+ * PCITOOL error numbers.
+ */
+
+typedef enum {
+ PCITOOL_SUCCESS = 0x0,
+ PCITOOL_INVALID_CPUID,
+ PCITOOL_INVALID_INO,
+ PCITOOL_PENDING_INTRTIMEOUT,
+ PCITOOL_REGPROP_NOTWELLFORMED,
+ PCITOOL_INVALID_ADDRESS,
+ PCITOOL_NOT_ALIGNED,
+ PCITOOL_OUT_OF_RANGE,
+ PCITOOL_END_OF_RANGE,
+ PCITOOL_ROM_DISABLED,
+ PCITOOL_ROM_WRITE,
+ PCITOOL_IO_ERROR,
+ PCITOOL_INVALID_SIZE
+} pcitool_errno_t;
+
+
+/*
+ * PCITOOL_DEVICE_SET_INTR ioctl data structure to re-assign the interrupts.
+ */
+typedef struct pcitool_intr_set {
+ uint16_t user_version; /* Userland program version - to krnl */
+ uint16_t drvr_version; /* Driver version - from kernel */
+ uint32_t ino; /* interrupt to set - to kernel */
+ uint32_t cpu_id; /* to: cpu to set / from: old cpu returned */
+ pcitool_errno_t status; /* from kernel */
+} pcitool_intr_set_t;
+
+
+/*
+ * PCITOOL_DEVICE_GET_INTR ioctl data structure to dump out the
+ * ino mapping information.
+ */
+
+typedef struct pcitool_intr_dev {
+ uint32_t dev_inst; /* device instance - from kernel */
+ char driver_name[MAXMODCONFNAME]; /* from kernel */
+ char path[MAXPATHLEN]; /* device path - from kernel */
+} pcitool_intr_dev_t;
+
+
+typedef struct pcitool_intr_get {
+ uint16_t user_version; /* Userland program version - to krnl */
+ uint16_t drvr_version; /* Driver version - from kernel */
+ uint32_t ino; /* interrupt number - to kernel */
+ uint8_t num_devs_ret; /* room for this # of devs to be */
+ /* returned - to kernel */
+ /* # devs returned - from kernel */
+ uint8_t num_devs; /* # devs on this ino - from kernel */
+ /* intrs enabled for devs if > 0 */
+ uint8_t ctlr; /* controller number - from kernel */
+ uint32_t cpu_id; /* cpu of interrupt - from kernel */
+ pcitool_errno_t status; /* returned status - from kernel */
+ pcitool_intr_dev_t dev[1]; /* start of variable device list */
+ /* from kernel */
+} pcitool_intr_get_t;
+
+/*
+ * Get the size needed to return the number of devices wanted.
+ * Can't say num_devs - 1 as num_devs may be unsigned.
+ */
+#define PCITOOL_IGET_SIZE(num_devs) \
+ (sizeof (pcitool_intr_get_t) - \
+ sizeof (pcitool_intr_dev_t) + \
+ (num_devs * sizeof (pcitool_intr_dev_t)))
+
+/*
+ * Size and endian fields for acc_attr bitmask.
+ */
+#define PCITOOL_ACC_ATTR_SIZE_MASK 0x3
+#define PCITOOL_ACC_ATTR_SIZE_1 0x0
+#define PCITOOL_ACC_ATTR_SIZE_2 0x1
+#define PCITOOL_ACC_ATTR_SIZE_4 0x2
+#define PCITOOL_ACC_ATTR_SIZE_8 0x3
+#define PCITOOL_ACC_ATTR_SIZE(x) (1 << (x & PCITOOL_ACC_ATTR_SIZE_MASK))
+
+#define PCITOOL_ACC_ATTR_ENDN_MASK 0x100
+#define PCITOOL_ACC_ATTR_ENDN_LTL 0x0
+#define PCITOOL_ACC_ATTR_ENDN_BIG 0x100
+#define PCITOOL_ACC_IS_BIG_ENDIAN(x) (x & PCITOOL_ACC_ATTR_ENDN_BIG)
+
+/*
+ * Data structure to read and write to pci device registers.
+ * This is the argument to the following ioctls:
+ * PCITOOL_DEVICE_SET/GET_REG
+ * PCITOOL_NEXUS_SET/GET_REG
+ */
+typedef struct pcitool_reg {
+ uint16_t user_version; /* Userland program version - to krnl */
+ uint16_t drvr_version; /* Driver version - from kernel */
+ uint8_t bus_no; /* pci bus - to kernel */
+ uint8_t dev_no; /* pci dev - to kernel */
+ uint8_t func_no; /* pci function - to kernel */
+ uint8_t barnum; /* bank (DEVCTL_NEXUS_SET/GET_REG) or */
+ /* BAR from pcitools_bar_t */
+ /* (DEVCTL_DEVICE_SET/GET_REG) */
+ /* to kernel */
+ uint64_t offset; /* to kernel */
+ uint32_t acc_attr; /* access attributes - to kernel */
+ uint32_t padding1; /* 8-byte align next uint64_t for X86 */
+ uint64_t data; /* to/from kernel, 64-bit alignment */
+ uint32_t status; /* from kernel */
+ uint32_t padding2; /* 8-byte align next uint64_t for X86 */
+ uint64_t phys_addr; /* from kernel, 64-bit alignment */
+} pcitool_reg_t;
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _SYS_PCI_TOOLS_H */
--- /dev/null
+/*
+ * (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>
+ */
+
+#if defined(__GNUC__) && (__GNUC__ >= 4)
+# define _pci_hidden __attribute__((visibility("hidden")))
+#elif defined(__SUNPRO_C) && (__SUNPRO_C >= 0x550)
+# define _pci_hidden __hidden
+#else /* not gcc >= 4 and not Sun Studio >= 8 */
+# define _pci_hidden
+#endif /* GNUC >= 4 */
+
+struct pci_device_mapping;
+
+int pci_fill_capabilities_generic( struct pci_device * dev );
+int pci_device_generic_unmap_range(struct pci_device *dev,
+ struct pci_device_mapping *map);
+
+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_range)(struct pci_device *dev, struct pci_device_mapping *map);
+ int (*unmap_range)(struct pci_device * dev,
+ struct pci_device_mapping *map);
+
+ 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 );
+ void (*enable)( struct pci_device *dev );
+ int (*boot_vga)( struct pci_device *dev );
+ int (*has_kernel_driver)( struct pci_device *dev );
+ struct pci_io_handle *(*open_device_io)( struct pci_io_handle *handle,
+ struct pci_device *dev, int bar,
+ pciaddr_t base, pciaddr_t size );
+ struct pci_io_handle *(*open_legacy_io)( struct pci_io_handle *handle,
+ struct pci_device *dev,
+ pciaddr_t base, pciaddr_t size );
+ void (*close_io)( struct pci_device *dev, struct pci_io_handle *handle );
+ uint32_t (*read32)( struct pci_io_handle *handle, uint32_t reg );
+ uint16_t (*read16)( struct pci_io_handle *handle, uint32_t reg );
+ uint8_t (*read8)( struct pci_io_handle *handle, uint32_t reg );
+ void (*write32)( struct pci_io_handle *handle, uint32_t reg,
+ uint32_t data );
+ void (*write16)( struct pci_io_handle *handle, uint32_t reg,
+ uint16_t data );
+ void (*write8)( struct pci_io_handle *handle, uint32_t reg, uint8_t data );
+};
+
+struct pci_device_mapping {
+ pciaddr_t base;
+ pciaddr_t size;
+ unsigned region;
+ unsigned flags;
+ void *memory;
+};
+
+struct pci_io_handle {
+ pciaddr_t base;
+ pciaddr_t size;
+ int fd;
+};
+
+struct pci_device_private {
+ struct pci_device base;
+ const char * device_string;
+
+ uint8_t header_type;
+
+ /**
+ * \name PCI Capabilities
+ */
+ /*@{*/
+ const struct pci_agp_info * agp; /**< AGP capability information. */
+ /*@}*/
+
+ /**
+ * Base address of the device's expansion ROM.
+ */
+ pciaddr_t rom_base;
+
+ /**
+ * \name Bridge information.
+ */
+ /*@{*/
+ union {
+ struct pci_bridge_info * pci;
+ struct pci_pcmcia_bridge_info * pcmcia;
+ } bridge;
+ /*@}*/
+
+ /**
+ * \name Mappings active on this device.
+ */
+ /*@{*/
+ struct pci_device_mapping *mappings;
+ unsigned num_mappings;
+ /*@}*/
+};
+
+
+/**
+ * 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;
+
+#ifdef HAVE_MTRR
+ int mtrr_fd;
+#endif
+ int vgaarb_fd;
+ int vga_count;
+ struct pci_device *vga_target;
+ struct pci_device *vga_default_dev;
+};
+
+extern struct pci_system * pci_sys;
+
+extern int pci_system_linux_sysfs_create( void );
+extern int pci_system_freebsd_create( void );
+extern int pci_system_netbsd_create( void );
+extern int pci_system_openbsd_create( void );
+extern void pci_system_openbsd_init_dev_mem( int );
+extern int pci_system_solx_devfs_create( void );
+extern int pci_system_x86_create( void );
+extern void pci_io_cleanup( void );
--- /dev/null
+/*
+ * (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 <err.h>
+#include <unistd.h>
+
+#include "pciaccess.h"
+
+
+static void
+print_pci_bridge( const struct pci_bridge_info * info )
+{
+ printf( " Bus: primary=%02x, secondary=%02x, subordinate=%02x, "
+ "sec-latency=%u\n",
+ info->primary_bus,
+ info->secondary_bus,
+ info->subordinate_bus,
+ info->secondary_latency_timer );
+ printf( " I/O behind bridge: %08x-%08x\n",
+ info->io_base,
+ info->io_limit );
+ printf( " Memory behind bridge: %08x-%08x\n",
+ info->mem_base,
+ info->mem_limit );
+ printf( " Prefetchable memory behind bridge: %08llx-%08llx\n",
+ info->prefetch_mem_base,
+ info->prefetch_mem_limit );
+}
+
+static 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 ");
+ if (dev->domain != 0)
+ printf("domain 0x%04x ", dev->domain);
+ printf("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, 12 );
+ pci_device_cfg_read_u8( dev, & latency_timer, 13 );
+ pci_device_cfg_read_u8( dev, & header_type, 14 );
+ pci_device_cfg_read_u8( dev, & bist, 15 );
+
+ printf( " BIST 0x%02x HEADER 0x%02x LATENCY 0x%02x CACHE 0x%02x\n",
+ bist,
+ header_type,
+ latency_timer,
+ cache_line_size );
+
+ pci_device_probe( dev );
+ for ( i = 0 ; i < 6 ; i++ ) {
+ if ( dev->regions[i].base_addr != 0 ) {
+ printf( " BASE%u 0x%08x SIZE %d %s",
+ i,
+ (intptr_t) dev->regions[i].base_addr,
+ (size_t) dev->regions[i].size,
+ (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 );
+
+ if ( (dev->device_class >> 16) == 0x06 ) {
+ const void * info;
+
+ if ( (info = pci_device_get_bridge_info(dev)) != NULL ) {
+ print_pci_bridge( (const struct pci_bridge_info *) info );
+ }
+ else if ( (info = pci_device_get_pcmcia_bridge_info(dev)) != NULL ) {
+ /* Nothing yet. */
+ }
+ }
+ }
+}
+
+
+int main( int argc, char ** argv )
+{
+ struct pci_device_iterator * iter;
+ struct pci_device * dev;
+ int ret;
+ int verbose = 0;
+ int c;
+ int errors = 0;
+
+ while ((c = getopt(argc, argv, "v")) != -1) {
+ switch (c) {
+ case 'v':
+ verbose = 1;
+ break;
+ case '?':
+ errors++;
+ }
+ }
+ if (errors != 0) {
+ fprintf(stderr, "usage: %s [-v]\n", argv[0]);
+ exit(2);
+ }
+
+ ret = pci_system_init();
+ if (ret != 0)
+ err(1, "Couldn't initialize PCI system");
+
+ iter = pci_slot_match_iterator_create( NULL );
+
+ while ( (dev = pci_device_next( iter )) != NULL ) {
+ print_pci_device( dev, verbose );
+ }
+
+ pci_system_cleanup();
+ return 0;
+}
--- /dev/null
+.\" Copyright (C) 2000 The XFree86 Project, Inc. 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 the
+.\" rights to use, copy, modify, merge, publish, distribute, sublicense, 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 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 NONINFRINGEMENT. IN NO EVENT SHALL THE
+.\" XFREE86 PROJECT 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.
+.\"
+.\" Except as contained in this notice, the name of the XFree86 Project shall
+.\" not be used in advertising or otherwise to promote the sale, use or other
+.\" dealings in this Software without prior written authorization from the
+.\" XFree86 Project.
+.\"
+.TH SCANPCI 1 __xorgversion__
+.SH NAME
+scanpci - scan/probe PCI buses
+.SH SYNOPSIS
+.B scanpci
+.RB [ \-v ]
+.SH DESCRIPTION
+.I Scanpci
+is a utility that can be used to scan PCI buses and report information
+about the configuration space settings for each PCI device.
+On most platforms,
+.I scanpci
+can only be run by the root user.
+.SH OPTIONS
+.TP 8
+.B \-v
+Print the configuration space information for each device in a verbose
+format. Without this option, only a brief description is printed for
+each device.
+
--- /dev/null
+/*
+ * (C) Copyright IBM Corporation 2006
+ * Copyright 2007, 2009 Sun Microsystems, Inc.
+ * 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.
+ */
+/*
+ * Solaris devfs interfaces
+ */
+
+#include <stdlib.h>
+#include <strings.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <fcntl.h>
+#include <sys/mman.h>
+#include <errno.h>
+#include <sys/pci.h>
+#include <libdevinfo.h>
+#include "pci_tools.h"
+
+#include "pciaccess.h"
+#include "pciaccess_private.h"
+
+/* #define DEBUG */
+
+#define MAX_DEVICES 256
+#define CELL_NUMS_1275 (sizeof(pci_regspec_t) / sizeof(uint_t))
+
+typedef union {
+ uint8_t bytes[16 * sizeof (uint32_t)];
+ uint32_t dwords[16];
+} pci_conf_hdr_t;
+
+typedef struct i_devnode {
+ uint8_t bus;
+ uint8_t dev;
+ uint8_t func;
+ di_node_t node;
+} i_devnode_t;
+
+typedef struct nexus {
+ int fd;
+ int first_bus;
+ int last_bus;
+ char *path; /* for errors/debugging; fd is all we need */
+ struct nexus *next;
+} nexus_t;
+
+static nexus_t *nexus_list = NULL;
+static int xsvc_fd = -1;
+
+/*
+ * Read config space in native processor endianness. Endian-neutral
+ * processing can then take place. On big endian machines, MSB and LSB
+ * of little endian data end up switched if read as little endian.
+ * They are in correct order if read as big endian.
+ */
+#if defined(__sparc)
+# define NATIVE_ENDIAN PCITOOL_ACC_ATTR_ENDN_BIG
+#elif defined(__x86)
+# define NATIVE_ENDIAN PCITOOL_ACC_ATTR_ENDN_LTL
+#else
+# error "ISA is neither __sparc nor __x86"
+#endif
+
+/*
+ * Identify problematic southbridges. These have device id 0x5249 and
+ * vendor id 0x10b9. Check for revision ID 0 and class code 060400 as well.
+ * Values are little endian, so they are reversed for SPARC.
+ *
+ * Check for these southbridges on all architectures, as the issue is a
+ * southbridge issue, independent of processor.
+ *
+ * If one of these is found during probing, skip probing other devs/funcs on
+ * the rest of the bus, since the southbridge and all devs underneath will
+ * otherwise disappear.
+ */
+#if (NATIVE_ENDIAN == PCITOOL_ACC_ATTR_ENDN_BIG)
+# define U45_SB_DEVID_VID 0xb9104952
+# define U45_SB_CLASS_RID 0x00000406
+#else
+# define U45_SB_DEVID_VID 0x524910b9
+# define U45_SB_CLASS_RID 0x06040000
+#endif
+
+static int pci_device_solx_devfs_map_range(struct pci_device *dev,
+ struct pci_device_mapping *map);
+
+static int pci_device_solx_devfs_read_rom( struct pci_device * dev,
+ void * buffer );
+
+static int pci_device_solx_devfs_probe( struct pci_device * dev );
+
+static int pci_device_solx_devfs_read( struct pci_device * dev, void * data,
+ pciaddr_t offset, pciaddr_t size, pciaddr_t * bytes_read );
+
+static int pci_device_solx_devfs_write( struct pci_device * dev,
+ const void * data, pciaddr_t offset, pciaddr_t size,
+ pciaddr_t * bytes_written );
+
+static int probe_dev(nexus_t *nexus, pcitool_reg_t *prg_p,
+ struct pci_system *pci_sys);
+
+static int do_probe(nexus_t *nexus, struct pci_system *pci_sys);
+
+static int probe_nexus_node(di_node_t di_node, di_minor_t minor, void *arg);
+
+static void pci_system_solx_devfs_destroy( void );
+
+static int get_config_header(int fd, uint8_t bus_no, uint8_t dev_no,
+ uint8_t func_no, pci_conf_hdr_t *config_hdr_p);
+
+int pci_system_solx_devfs_create( void );
+
+static const struct pci_system_methods solx_devfs_methods = {
+ .destroy = pci_system_solx_devfs_destroy,
+ .destroy_device = NULL,
+ .read_rom = pci_device_solx_devfs_read_rom,
+ .probe = pci_device_solx_devfs_probe,
+ .map_range = pci_device_solx_devfs_map_range,
+ .unmap_range = pci_device_generic_unmap_range,
+
+ .read = pci_device_solx_devfs_read,
+ .write = pci_device_solx_devfs_write,
+
+ .fill_capabilities = pci_fill_capabilities_generic
+};
+
+static nexus_t *
+find_nexus_for_bus( int bus )
+{
+ nexus_t *nexus;
+
+ for (nexus = nexus_list ; nexus != NULL ; nexus = nexus->next) {
+ if ((bus >= nexus->first_bus) && (bus <= nexus->last_bus)) {
+ return nexus;
+ }
+ }
+ return NULL;
+}
+
+#define GET_CONFIG_VAL_8(offset) (config_hdr.bytes[offset])
+#define GET_CONFIG_VAL_16(offset) \
+ (uint16_t) (GET_CONFIG_VAL_8(offset) + (GET_CONFIG_VAL_8(offset+1) << 8))
+#define GET_CONFIG_VAL_32(offset) \
+ (uint32_t) (GET_CONFIG_VAL_8(offset) + \
+ (GET_CONFIG_VAL_8(offset+1) << 8) + \
+ (GET_CONFIG_VAL_8(offset+2) << 16) + \
+ (GET_CONFIG_VAL_8(offset+3) << 24))
+
+/*
+ * Release all the resources
+ * Solaris version
+ */
+static void
+pci_system_solx_devfs_destroy( void )
+{
+ /*
+ * The memory allocated for pci_sys & devices in create routines
+ * will be freed in pci_system_cleanup.
+ * Need to free system-specific allocations here.
+ */
+ nexus_t *nexus, *next;
+
+ for (nexus = nexus_list ; nexus != NULL ; nexus = next) {
+ next = nexus->next;
+ close(nexus->fd);
+ free(nexus->path);
+ free(nexus);
+ }
+ nexus_list = NULL;
+
+ if (xsvc_fd >= 0) {
+ close(xsvc_fd);
+ xsvc_fd = -1;
+ }
+}
+
+/*
+ * Attempt to access PCI subsystem using Solaris's devfs interface.
+ * Solaris version
+ */
+_pci_hidden int
+pci_system_solx_devfs_create( void )
+{
+ int err = 0;
+ di_node_t di_node;
+
+
+ if (nexus_list != NULL) {
+ return 0;
+ }
+
+ /*
+ * Only allow MAX_DEVICES exists
+ * I will fix it later to get
+ * the total devices first
+ */
+ if ((pci_sys = calloc(1, sizeof (struct pci_system))) != NULL) {
+ pci_sys->methods = &solx_devfs_methods;
+
+ if ((pci_sys->devices =
+ calloc(MAX_DEVICES, sizeof (struct pci_device_private)))
+ != NULL) {
+
+ if ((di_node = di_init("/", DINFOCPYALL)) == DI_NODE_NIL) {
+ err = errno;
+ (void) fprintf(stderr, "di_init() failed: %s\n",
+ strerror(errno));
+ } else {
+ (void) di_walk_minor(di_node, DDI_NT_REGACC, 0, pci_sys,
+ probe_nexus_node);
+ di_fini(di_node);
+ }
+ }
+ else {
+ err = errno;
+ }
+ } else {
+ err = errno;
+ }
+
+ if (err != 0) {
+ if (pci_sys != NULL) {
+ free(pci_sys->devices);
+ free(pci_sys);
+ pci_sys = NULL;
+ }
+ }
+
+ return (err);
+}
+
+/*
+ * Retrieve first 16 dwords of device's config header, except for the first
+ * dword. First 16 dwords are defined by the PCI specification.
+ */
+static int
+get_config_header(int fd, uint8_t bus_no, uint8_t dev_no, uint8_t func_no,
+ pci_conf_hdr_t *config_hdr_p)
+{
+ pcitool_reg_t cfg_prg;
+ int i;
+ int rval = 0;
+
+ /* Prepare a local pcitool_reg_t so as to not disturb the caller's. */
+ cfg_prg.offset = 0;
+ cfg_prg.acc_attr = PCITOOL_ACC_ATTR_SIZE_4 + NATIVE_ENDIAN;
+ cfg_prg.bus_no = bus_no;
+ cfg_prg.dev_no = dev_no;
+ cfg_prg.func_no = func_no;
+ cfg_prg.barnum = 0;
+ cfg_prg.user_version = PCITOOL_USER_VERSION;
+
+ /* Get dwords 1-15 of config space. They must be read as uint32_t. */
+ for (i = 1; i < (sizeof (pci_conf_hdr_t) / sizeof (uint32_t)); i++) {
+ cfg_prg.offset += sizeof (uint32_t);
+ if ((rval = ioctl(fd, PCITOOL_DEVICE_GET_REG, &cfg_prg)) != 0) {
+ break;
+ }
+ config_hdr_p->dwords[i] = (uint32_t)cfg_prg.data;
+ }
+
+ return (rval);
+}
+
+
+/*
+ * Probe device's functions. Modifies many fields in the prg_p.
+ */
+static int
+probe_dev(nexus_t *nexus, pcitool_reg_t *prg_p, struct pci_system *pci_sys)
+{
+ pci_conf_hdr_t config_hdr;
+ boolean_t multi_function_device;
+ int8_t func;
+ int8_t first_func = 0;
+ int8_t last_func = PCI_REG_FUNC_M >> PCI_REG_FUNC_SHIFT;
+ int rval = 0;
+ struct pci_device * pci_base;
+
+ /*
+ * Loop through at least func=first_func. Continue looping through
+ * functions if there are no errors and the device is a multi-function
+ * device.
+ *
+ * (Note, if first_func == 0, header will show whether multifunction
+ * device and set multi_function_device. If first_func != 0, then we
+ * will force the loop as the user wants a specific function to be
+ * checked.
+ */
+ for (func = first_func, multi_function_device = B_FALSE;
+ ((func <= last_func) &&
+ ((func == first_func) || (multi_function_device)));
+ func++) {
+ prg_p->func_no = func;
+
+ /*
+ * Four things can happen here:
+ *
+ * 1) ioctl comes back as EFAULT and prg_p->status is
+ * PCITOOL_INVALID_ADDRESS. There is no device at this location.
+ *
+ * 2) ioctl comes back successful and the data comes back as
+ * zero. Config space is mapped but no device responded.
+ *
+ * 3) ioctl comes back successful and the data comes back as
+ * non-zero. We've found a device.
+ *
+ * 4) Some other error occurs in an ioctl.
+ */
+
+ prg_p->status = PCITOOL_SUCCESS;
+ prg_p->offset = 0;
+ prg_p->data = 0;
+ prg_p->user_version = PCITOOL_USER_VERSION;
+
+ errno = 0;
+ if (((rval = ioctl(nexus->fd, PCITOOL_DEVICE_GET_REG, prg_p)) != 0) ||
+ (prg_p->data == 0xffffffff)) {
+
+ /*
+ * Accept errno == EINVAL along with status of
+ * PCITOOL_OUT_OF_RANGE because some systems
+ * don't implement the full range of config space.
+ * Leave the loop quietly in this case.
+ */
+ if ((errno == EINVAL) ||
+ (prg_p->status == PCITOOL_OUT_OF_RANGE)) {
+ break;
+ }
+
+ /*
+ * Exit silently with ENXIO as this means that there are
+ * no devices under the pci root nexus.
+ */
+ else if ((errno == ENXIO) &&
+ (prg_p->status == PCITOOL_IO_ERROR)) {
+ break;
+ }
+
+ /*
+ * Expect errno == EFAULT along with status of
+ * PCITOOL_INVALID_ADDRESS because there won't be
+ * devices at each stop. Quit on any other error.
+ */
+ else if (((errno != EFAULT) ||
+ (prg_p->status != PCITOOL_INVALID_ADDRESS)) &&
+ (prg_p->data != 0xffffffff)) {
+ break;
+ }
+
+ /*
+ * If no function at this location,
+ * just advance to the next function.
+ */
+ else {
+ rval = 0;
+ }
+
+ /*
+ * Data came back as 0.
+ * Treat as unresponsive device and check next device.
+ */
+ } else if (prg_p->data == 0) {
+ rval = 0;
+ break; /* Func loop. */
+
+ /* Found something. */
+ } else {
+ config_hdr.dwords[0] = (uint32_t)prg_p->data;
+
+ /* Get the rest of the PCI header. */
+ if ((rval = get_config_header(nexus->fd, prg_p->bus_no,
+ prg_p->dev_no, prg_p->func_no,
+ &config_hdr)) != 0) {
+ break;
+ }
+
+ /*
+ * Special case for the type of Southbridge found on
+ * Ultra-45 and other sun4u fire workstations.
+ */
+ if ((config_hdr.dwords[0] == U45_SB_DEVID_VID) &&
+ (config_hdr.dwords[2] == U45_SB_CLASS_RID)) {
+ rval = ECANCELED;
+ break;
+ }
+
+ /*
+ * Found one device with bus number, device number and
+ * function number.
+ */
+
+ pci_base = &pci_sys->devices[pci_sys->num_devices].base;
+
+ /*
+ * Domain is peer bus??
+ */
+ pci_base->domain = 0;
+ pci_base->bus = prg_p->bus_no;
+ pci_base->dev = prg_p->dev_no;
+ pci_base->func = func;
+
+ /*
+ * for the format of device_class, see struct pci_device;
+ */
+
+ pci_base->device_class =
+ (GET_CONFIG_VAL_8(PCI_CONF_BASCLASS) << 16) |
+ (GET_CONFIG_VAL_8(PCI_CONF_SUBCLASS) << 8) |
+ GET_CONFIG_VAL_8(PCI_CONF_PROGCLASS);
+
+ pci_base->revision = GET_CONFIG_VAL_8(PCI_CONF_REVID);
+ pci_base->vendor_id = GET_CONFIG_VAL_16(PCI_CONF_VENID);
+ pci_base->device_id = GET_CONFIG_VAL_16(PCI_CONF_DEVID);
+ pci_base->subvendor_id = GET_CONFIG_VAL_16(PCI_CONF_SUBVENID);
+ pci_base->subdevice_id = GET_CONFIG_VAL_16(PCI_CONF_SUBSYSID);
+
+ pci_sys->devices[pci_sys->num_devices].header_type
+ = GET_CONFIG_VAL_8(PCI_CONF_HEADER);
+
+#ifdef DEBUG
+ fprintf(stderr,
+ "nexus = %s, busno = %x, devno = %x, funcno = %x\n",
+ nexus->path, prg_p->bus_no, prg_p->dev_no, func);
+#endif
+
+ if (pci_sys->num_devices < (MAX_DEVICES - 1)) {
+ pci_sys->num_devices++;
+ } else {
+ (void) fprintf(stderr,
+ "Maximum number of PCI devices found,"
+ " discarding additional devices\n");
+ }
+
+
+ /*
+ * Accommodate devices which state their
+ * multi-functionality only in their function 0 config
+ * space. Note multi-functionality throughout probing
+ * of all of this device's functions.
+ */
+ if (config_hdr.bytes[PCI_CONF_HEADER] & PCI_HEADER_MULTI) {
+ multi_function_device = B_TRUE;
+ }
+ }
+ }
+
+ return (rval);
+}
+
+/*
+ * This function is called from di_walk_minor() when any PROBE is processed
+ */
+static int
+probe_nexus_node(di_node_t di_node, di_minor_t minor, void *arg)
+{
+ struct pci_system *pci_sys = (struct pci_system *) arg;
+ char *nexus_name;
+ nexus_t *nexus;
+ int fd;
+ char nexus_path[MAXPATHLEN];
+
+ di_prop_t prop;
+ char *strings;
+ int *ints;
+ int numval;
+ int pci_node = 0;
+ int first_bus = 0, last_bus = PCI_REG_BUS_G(PCI_REG_BUS_M);
+
+#ifdef DEBUG
+ nexus_name = di_devfs_minor_path(minor);
+ fprintf(stderr, "-- device name: %s\n", nexus_name);
+#endif
+
+ for (prop = di_prop_next(di_node, NULL); prop != NULL;
+ prop = di_prop_next(di_node, prop)) {
+
+ const char *prop_name = di_prop_name(prop);
+
+#ifdef DEBUG
+ fprintf(stderr, " property: %s\n", prop_name);
+#endif
+
+ if (strcmp(prop_name, "device_type") == 0) {
+ numval = di_prop_strings(prop, &strings);
+ if (numval != 1 || strncmp(strings, "pci", 3) != 0) {
+ /* not a PCI node, bail */
+ return (DI_WALK_CONTINUE);
+ }
+ pci_node = 1;
+ }
+ else if (strcmp(prop_name, "class-code") == 0) {
+ /* not a root bus node, bail */
+ return (DI_WALK_CONTINUE);
+ }
+ else if (strcmp(prop_name, "bus-range") == 0) {
+ numval = di_prop_ints(prop, &ints);
+ if (numval == 2) {
+ first_bus = ints[0];
+ last_bus = ints[1];
+ }
+ }
+ }
+
+#ifdef __x86 /* sparc pci nodes don't have the device_type set */
+ if (pci_node != 1)
+ return (DI_WALK_CONTINUE);
+#endif
+
+ /* we have a PCI root bus node. */
+ nexus = calloc(1, sizeof(nexus_t));
+ if (nexus == NULL) {
+ (void) fprintf(stderr, "Error allocating memory for nexus: %s\n",
+ strerror(errno));
+ return (DI_WALK_TERMINATE);
+ }
+ nexus->first_bus = first_bus;
+ nexus->last_bus = last_bus;
+
+ nexus_name = di_devfs_minor_path(minor);
+ if (nexus_name == NULL) {
+ (void) fprintf(stderr, "Error getting nexus path: %s\n",
+ strerror(errno));
+ free(nexus);
+ return (DI_WALK_CONTINUE);
+ }
+
+ snprintf(nexus_path, sizeof(nexus_path), "/devices%s", nexus_name);
+ di_devfs_path_free(nexus_name);
+
+#ifdef DEBUG
+ fprintf(stderr, "nexus = %s, bus-range = %d - %d\n",
+ nexus_path, first_bus, last_bus);
+#endif
+
+ if ((fd = open(nexus_path, O_RDWR)) >= 0) {
+ nexus->fd = fd;
+ nexus->path = strdup(nexus_path);
+ if ((do_probe(nexus, pci_sys) != 0) && (errno != ENXIO)) {
+ (void) fprintf(stderr, "Error probing node %s: %s\n",
+ nexus_path, strerror(errno));
+ (void) close(fd);
+ free(nexus->path);
+ free(nexus);
+ } else {
+ nexus->next = nexus_list;
+ nexus_list = nexus;
+ }
+ } else {
+ (void) fprintf(stderr, "Error opening %s: %s\n",
+ nexus_path, strerror(errno));
+ free(nexus);
+ }
+
+ return DI_WALK_CONTINUE;
+}
+
+
+/*
+ * Solaris version
+ * Probe a given nexus config space for devices.
+ *
+ * fd is the file descriptor of the nexus.
+ * input_args contains commandline options as specified by the user.
+ */
+static int
+do_probe(nexus_t *nexus, struct pci_system *pci_sys)
+{
+ pcitool_reg_t prg;
+ uint32_t bus;
+ uint8_t dev;
+ uint32_t last_bus = nexus->last_bus;
+ uint8_t last_dev = PCI_REG_DEV_M >> PCI_REG_DEV_SHIFT;
+ uint8_t first_bus = nexus->first_bus;
+ uint8_t first_dev = 0;
+ int rval = 0;
+
+ prg.barnum = 0; /* Config space. */
+
+ /* Must read in 4-byte quantities. */
+ prg.acc_attr = PCITOOL_ACC_ATTR_SIZE_4 + NATIVE_ENDIAN;
+
+ prg.data = 0;
+
+ /*
+ * Loop through all valid bus / dev / func combinations to check for
+ * all devices, with the following exceptions:
+ *
+ * When nothing is found at function 0 of a bus / dev combination, skip
+ * the other functions of that bus / dev combination.
+ *
+ * When a found device's function 0 is probed and it is determined that
+ * it is not a multifunction device, skip probing of that device's
+ * other functions.
+ */
+ for (bus = first_bus; ((bus <= last_bus) && (rval == 0)); bus++) {
+ prg.bus_no = (uint8_t)bus;
+
+ for (dev = first_dev; ((dev <= last_dev) && (rval == 0)); dev++) {
+ prg.dev_no = dev;
+ rval = probe_dev(nexus, &prg, pci_sys);
+ }
+
+ /*
+ * Ultra-45 southbridge workaround:
+ * ECANCELED tells to skip to the next bus.
+ */
+ if (rval == ECANCELED) {
+ rval = 0;
+ }
+ }
+
+ return (rval);
+}
+
+static int
+find_target_node(di_node_t node, void *arg)
+{
+ int *regbuf = NULL;
+ int len = 0;
+ uint32_t busno, funcno, devno;
+ i_devnode_t *devnode = (i_devnode_t *)arg;
+
+ /*
+ * Test the property functions, only for testing
+ */
+ /*
+ void *prop = DI_PROP_NIL;
+
+ (void) fprintf(stderr, "start of node 0x%x\n", node->nodeid);
+ while ((prop = di_prop_hw_next(node, prop)) != DI_PROP_NIL) {
+ int i;
+ (void) fprintf(stderr, "name=%s: ", di_prop_name(prop));
+ len = 0;
+ if (!strcmp(di_prop_name(prop), "reg")) {
+ len = di_prop_ints(prop, ®buf);
+ }
+ for (i = 0; i < len; i++) {
+ fprintf(stderr, "0x%0x.", regbuf[i]);
+ }
+ fprintf(stderr, "\n");
+ }
+ (void) fprintf(stderr, "end of node 0x%x\n", node->nodeid);
+ */
+
+ len = di_prop_lookup_ints(DDI_DEV_T_ANY, node, "reg", ®buf);
+
+ if (len <= 0) {
+#ifdef DEBUG
+ fprintf(stderr, "error = %x\n", errno);
+ fprintf(stderr, "can not find assigned-address\n");
+#endif
+ return (DI_WALK_CONTINUE);
+ }
+
+ busno = PCI_REG_BUS_G(regbuf[0]);
+ devno = PCI_REG_DEV_G(regbuf[0]);
+ funcno = PCI_REG_FUNC_G(regbuf[0]);
+
+ if ((busno == devnode->bus) &&
+ (devno == devnode->dev) &&
+ (funcno == devnode->func)) {
+ devnode->node = node;
+
+ return (DI_WALK_TERMINATE);
+ }
+
+ return (DI_WALK_CONTINUE);
+}
+
+/*
+ * Solaris version
+ */
+static int
+pci_device_solx_devfs_probe( struct pci_device * dev )
+{
+ uint8_t config[256];
+ int err;
+ di_node_t rnode = DI_NODE_NIL;
+ i_devnode_t args = { 0, 0, 0, DI_NODE_NIL };
+ int *regbuf;
+ pci_regspec_t *reg;
+ int i;
+ pciaddr_t bytes;
+ int len = 0;
+ uint ent = 0;
+
+ err = pci_device_solx_devfs_read( dev, config, 0, 256, & bytes );
+
+ if ( bytes >= 64 ) {
+ struct pci_device_private *priv =
+ (struct pci_device_private *) dev;
+
+ dev->vendor_id = (uint16_t)config[0] + ((uint16_t)config[1] << 8);
+ dev->device_id = (uint16_t)config[2] + ((uint16_t)config[3] << 8);
+ dev->device_class = (uint32_t)config[9] +
+ ((uint32_t)config[10] << 8) +
+ ((uint16_t)config[11] << 16);
+
+ /*
+ * device class code is already there.
+ * see probe_dev function.
+ */
+ dev->revision = config[8];
+ dev->subvendor_id = (uint16_t)config[44] + ((uint16_t)config[45] << 8);
+ dev->subdevice_id = (uint16_t)config[46] + ((uint16_t)config[47] << 8);
+ dev->irq = config[60];
+
+ priv->header_type = config[14];
+ /*
+ * starting to find if it is MEM/MEM64/IO
+ * using libdevinfo
+ */
+ if ((rnode = di_init("/", DINFOCPYALL)) == DI_NODE_NIL) {
+ err = errno;
+ (void) fprintf(stderr, "di_init failed: %s\n", strerror(errno));
+ } else {
+ args.bus = dev->bus;
+ args.dev = dev->dev;
+ args.func = dev->func;
+ (void) di_walk_node(rnode, DI_WALK_CLDFIRST,
+ (void *)&args, find_target_node);
+ }
+ }
+ if (args.node != DI_NODE_NIL) {
+ /*
+ * It will succeed for sure, because it was
+ * successfully called in find_target_node
+ */
+ len = di_prop_lookup_ints(DDI_DEV_T_ANY, args.node,
+ "assigned-addresses",
+ ®buf);
+
+ }
+
+ if (len <= 0)
+ goto cleanup;
+
+
+ /*
+ * how to find the size of rom???
+ * if the device has expansion rom,
+ * it must be listed in the last
+ * cells because solaris find probe
+ * the base address from offset 0x10
+ * to 0x30h. So only check the last
+ * item.
+ */
+ reg = (pci_regspec_t *)®buf[len - CELL_NUMS_1275];
+ if (PCI_REG_REG_G(reg->pci_phys_hi) == PCI_CONF_ROM) {
+ /*
+ * rom can only be 32 bits
+ */
+ dev->rom_size = reg->pci_size_low;
+ len = len - CELL_NUMS_1275;
+ }
+ else {
+ /*
+ * size default to 64K and base address
+ * default to 0xC0000
+ */
+ dev->rom_size = 0x10000;
+ }
+
+ /*
+ * Solaris has its own BAR index.
+ * Linux give two region slot for 64 bit address.
+ */
+ for (i = 0; i < len; i = i + CELL_NUMS_1275) {
+
+ reg = (pci_regspec_t *)®buf[i];
+ ent = reg->pci_phys_hi & 0xff;
+ /*
+ * G35 broken in BAR0
+ */
+ ent = (ent - PCI_CONF_BASE0) >> 2;
+ if (ent >= 6) {
+ fprintf(stderr, "error ent = %d\n", ent);
+ break;
+ }
+
+ /*
+ * non relocatable resource is excluded
+ * such like 0xa0000, 0x3b0. If it is met,
+ * the loop is broken;
+ */
+ if (!PCI_REG_REG_G(reg->pci_phys_hi))
+ break;
+
+ if (reg->pci_phys_hi & PCI_PREFETCH_B) {
+ dev->regions[ent].is_prefetchable = 1;
+ }
+
+
+ /*
+ * We split the shift count 32 into two 16 to
+ * avoid the complaining of the compiler
+ */
+ dev->regions[ent].base_addr = reg->pci_phys_low +
+ ((reg->pci_phys_mid << 16) << 16);
+ dev->regions[ent].size = reg->pci_size_low +
+ ((reg->pci_size_hi << 16) << 16);
+
+ switch (reg->pci_phys_hi & PCI_REG_ADDR_M) {
+ case PCI_ADDR_IO:
+ dev->regions[ent].is_IO = 1;
+ break;
+ case PCI_ADDR_MEM32:
+ break;
+ case PCI_ADDR_MEM64:
+ dev->regions[ent].is_64 = 1;
+ /*
+ * Skip one slot for 64 bit address
+ */
+ break;
+ }
+ }
+
+ cleanup:
+ if (rnode != DI_NODE_NIL) {
+ di_fini(rnode);
+ }
+ return (err);
+}
+
+/*
+ * Solaris version: read the VGA ROM data
+ */
+static int
+pci_device_solx_devfs_read_rom( struct pci_device * dev, void * buffer )
+{
+ int err;
+ struct pci_device_mapping prom = {
+ .base = 0xC0000,
+ .size = dev->rom_size,
+ .flags = 0
+ };
+
+ err = pci_device_solx_devfs_map_range(dev, &prom);
+ if (err == 0) {
+ (void) bcopy(prom.memory, buffer, dev->rom_size);
+
+ if (munmap(prom.memory, dev->rom_size) == -1) {
+ err = errno;
+ }
+ }
+ return err;
+}
+
+/*
+ * solaris version: Read the configurations space of the devices
+ */
+static int
+pci_device_solx_devfs_read( struct pci_device * dev, void * data,
+ pciaddr_t offset, pciaddr_t size,
+ pciaddr_t * bytes_read )
+{
+ pcitool_reg_t cfg_prg;
+ int err = 0;
+ int i = 0;
+ nexus_t *nexus = find_nexus_for_bus(dev->bus);
+
+ *bytes_read = 0;
+
+ if ( nexus == NULL ) {
+ return ENODEV;
+ }
+
+ cfg_prg.offset = offset;
+ cfg_prg.acc_attr = PCITOOL_ACC_ATTR_SIZE_1 + NATIVE_ENDIAN;
+ cfg_prg.bus_no = dev->bus;
+ cfg_prg.dev_no = dev->dev;
+ cfg_prg.func_no = dev->func;
+ cfg_prg.barnum = 0;
+ cfg_prg.user_version = PCITOOL_USER_VERSION;
+
+ for (i = 0; i < size; i += PCITOOL_ACC_ATTR_SIZE(PCITOOL_ACC_ATTR_SIZE_1))
+ {
+ cfg_prg.offset = offset + i;
+
+ if ((err = ioctl(nexus->fd, PCITOOL_DEVICE_GET_REG, &cfg_prg)) != 0) {
+ fprintf(stderr, "read bdf<%s,%x,%x,%x,%llx> config space failure\n",
+ nexus->path,
+ cfg_prg.bus_no,
+ cfg_prg.dev_no,
+ cfg_prg.func_no,
+ cfg_prg.offset);
+ fprintf(stderr, "Failure cause = %x\n", err);
+ break;
+ }
+
+ ((uint8_t *)data)[i] = (uint8_t)cfg_prg.data;
+ /*
+ * DWORDS Offset or bytes Offset ??
+ */
+ }
+ *bytes_read = i;
+
+ return (err);
+}
+
+/*
+ * Solaris version
+ */
+static int
+pci_device_solx_devfs_write( struct pci_device * dev, const void * data,
+ pciaddr_t offset, pciaddr_t size,
+ pciaddr_t * bytes_written )
+{
+ pcitool_reg_t cfg_prg;
+ int err = 0;
+ int cmd;
+ nexus_t *nexus = find_nexus_for_bus(dev->bus);
+
+ if ( bytes_written != NULL ) {
+ *bytes_written = 0;
+ }
+
+ if ( nexus == NULL ) {
+ return ENODEV;
+ }
+
+ cfg_prg.offset = offset;
+ switch (size) {
+ case 1:
+ cfg_prg.acc_attr = PCITOOL_ACC_ATTR_SIZE_1 + NATIVE_ENDIAN;
+ break;
+ case 2:
+ cfg_prg.acc_attr = PCITOOL_ACC_ATTR_SIZE_2 + NATIVE_ENDIAN;
+ break;
+ case 4:
+ cfg_prg.acc_attr = PCITOOL_ACC_ATTR_SIZE_4 + NATIVE_ENDIAN;
+ break;
+ case 8:
+ cfg_prg.acc_attr = PCITOOL_ACC_ATTR_SIZE_8 + NATIVE_ENDIAN;
+ break;
+ default:
+ return EINVAL;
+ }
+ cfg_prg.bus_no = dev->bus;
+ cfg_prg.dev_no = dev->dev;
+ cfg_prg.func_no = dev->func;
+ cfg_prg.barnum = 0;
+ cfg_prg.user_version = PCITOOL_USER_VERSION;
+ cfg_prg.data = *((uint64_t *)data);
+
+ /*
+ * Check if this device is bridge device.
+ * If it is, it is also a nexus node???
+ * It seems that there is no explicit
+ * PCI nexus device for X86, so not applicable
+ * from pcitool_bus_reg_ops in pci_tools.c
+ */
+ cmd = PCITOOL_DEVICE_SET_REG;
+
+ if ((err = ioctl(nexus->fd, cmd, &cfg_prg)) != 0) {
+ return (err);
+ }
+ *bytes_written = size;
+
+ return (err);
+}
+
+
+/**
+ * Map a memory region for a device using /dev/xsvc.
+ *
+ * \param dev Device whose memory region is to be mapped.
+ * \param map Parameters of the mapping that is to be created.
+ *
+ * \return
+ * Zero on success or an \c errno value on failure.
+ */
+static int
+pci_device_solx_devfs_map_range(struct pci_device *dev,
+ struct pci_device_mapping *map)
+{
+ const int prot = ((map->flags & PCI_DEV_MAP_FLAG_WRITABLE) != 0)
+ ? (PROT_READ | PROT_WRITE) : PROT_READ;
+ int err = 0;
+
+ /*
+ * Still used xsvc to do the user space mapping
+ */
+ if (xsvc_fd < 0) {
+ if ((xsvc_fd = open("/dev/xsvc", O_RDWR)) < 0) {
+ err = errno;
+ (void) fprintf(stderr, "can not open /dev/xsvc: %s\n",
+ strerror(errno));
+ return err;
+ }
+ }
+
+ map->memory = mmap(NULL, map->size, prot, MAP_SHARED, xsvc_fd, map->base);
+ if (map->memory == MAP_FAILED) {
+ err = errno;
+
+ (void) fprintf(stderr, "map rom region =%llx failed: %s\n",
+ map->base, strerror(errno));
+ }
+
+ return err;
+}
--- /dev/null
+/*
+ * Copyright (c) 2009 Samuel Thibault
+ * Heavily inspired from the freebsd, netbsd, and openbsd backends
+ * (C) Copyright Eric Anholt 2006
+ * (C) Copyright IBM Corporation 2006
+ * Copyright (c) 2008 Juan Romero Pardines
+ * Copyright (c) 2008 Mark Kettenis
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#define _GNU_SOURCE
+#include <unistd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <sys/mman.h>
+#include <string.h>
+#include <strings.h>
+
+#include "pciaccess.h"
+#include "pciaccess_private.h"
+
+#if defined(__GNU__)
+
+#include <sys/io.h>
+
+static int
+x86_enable_io(void)
+{
+ if (!ioperm(0, 0xffff, 1))
+ return 0;
+ return errno;
+}
+
+static int
+x86_disable_io(void)
+{
+ if (!ioperm(0, 0xffff, 0))
+ return 0;
+ return errno;
+}
+
+#elif defined(__GLIBC__)
+
+#include <sys/io.h>
+
+static int
+x86_enable_io(void)
+{
+ if (!iopl(3))
+ return 0;
+ return errno;
+}
+
+static int
+x86_disable_io(void)
+{
+ if (!iopl(0))
+ return 0;
+ return errno;
+}
+
+#else
+
+#error How to enable IO ports on this system?
+
+#endif
+
+#define PCI_VENDOR(reg) ((reg) & 0xFFFF)
+#define PCI_VENDOR_INVALID 0xFFFF
+
+#define PCI_VENDOR_ID 0x00
+#define PCI_SUB_VENDOR_ID 0x2c
+#define PCI_VENDOR_ID_COMPAQ 0x0e11
+#define PCI_VENDOR_ID_INTEL 0x8086
+
+#define PCI_DEVICE(reg) (((reg) >> 16) & 0xFFFF)
+#define PCI_DEVICE_INVALID 0xFFFF
+
+#define PCI_CLASS 0x08
+#define PCI_CLASS_DEVICE 0x0a
+#define PCI_CLASS_DISPLAY_VGA 0x0300
+#define PCI_CLASS_BRIDGE_HOST 0x0600
+
+#define PCIC_DISPLAY 0x03
+#define PCIS_DISPLAY_VGA 0x00
+
+#define PCI_HDRTYPE 0x0E
+#define PCI_IRQ 0x3C
+
+struct pci_system_x86 {
+ struct pci_system system;
+ int (*read)(unsigned bus, unsigned dev, unsigned func, pciaddr_t reg, void *data, unsigned size);
+ int (*write)(unsigned bus, unsigned dev, unsigned func, pciaddr_t reg, const void *data, unsigned size);
+};
+
+static int
+pci_system_x86_conf1_probe(void)
+{
+ unsigned long sav;
+ int res = ENODEV;
+
+ outb(0x01, 0xCFB);
+ sav = inl(0xCF8);
+ outl(0x80000000, 0xCF8);
+ if (inl(0xCF8) == 0x80000000)
+ res = 0;
+ outl(sav, 0xCF8);
+
+ return res;
+}
+
+static int
+pci_system_x86_conf1_read(unsigned bus, unsigned dev, unsigned func, pciaddr_t reg, void *data, unsigned size)
+{
+ unsigned addr = 0xCFC + (reg & 3);
+ unsigned long sav;
+ int ret = 0;
+
+ if (bus >= 0x100 || dev >= 32 || func >= 8 || reg >= 0x100 || size > 4 || size == 3)
+ return EIO;
+
+ sav = inl(0xCF8);
+ outl(0x80000000 | (bus << 16) | (dev << 11) | (func << 8) | (reg & ~3), 0xCF8);
+ /* NOTE: x86 is already LE */
+ switch (size) {
+ case 1: {
+ uint8_t *val = data;
+ *val = inb(addr);
+ break;
+ }
+ case 2: {
+ uint16_t *val = data;
+ *val = inw(addr);
+ break;
+ }
+ case 4: {
+ uint32_t *val = data;
+ *val = inl(addr);
+ break;
+ }
+ }
+ outl(sav, 0xCF8);
+
+ return ret;
+}
+
+static int
+pci_system_x86_conf1_write(unsigned bus, unsigned dev, unsigned func, pciaddr_t reg, const void *data, unsigned size)
+{
+ unsigned addr = 0xCFC + (reg & 3);
+ unsigned long sav;
+ int ret = 0;
+
+ if (bus >= 0x100 || dev >= 32 || func >= 8 || reg >= 0x100 || size > 4 || size == 3)
+ return EIO;
+
+ sav = inl(0xCF8);
+ outl(0x80000000 | (bus << 16) | (dev << 11) | (func << 8) | (reg & ~3), 0xCF8);
+ /* NOTE: x86 is already LE */
+ switch (size) {
+ case 1: {
+ const uint8_t *val = data;
+ outb(*val, addr);
+ break;
+ }
+ case 2: {
+ const uint16_t *val = data;
+ outw(*val, addr);
+ break;
+ }
+ case 4: {
+ const uint32_t *val = data;
+ outl(*val, addr);
+ break;
+ }
+ }
+ outl(sav, 0xCF8);
+
+ return ret;
+}
+
+static int
+pci_system_x86_conf2_probe(void)
+{
+ outb(0, 0xCFB);
+ outb(0, 0xCF8);
+ outb(0, 0xCFA);
+ if (inb(0xCF8) == 0 && inb(0xCFA) == 0)
+ return 0;
+
+ return ENODEV;
+}
+
+static int
+pci_system_x86_conf2_read(unsigned bus, unsigned dev, unsigned func, pciaddr_t reg, void *data, unsigned size)
+{
+ unsigned addr = 0xC000 | dev << 8 | reg;
+ int ret = 0;
+
+ if (bus >= 0x100 || dev >= 16 || func >= 8 || reg >= 0x100)
+ return EIO;
+
+ outb((func << 1) | 0xF0, 0xCF8);
+ outb(bus, 0xCFA);
+ /* NOTE: x86 is already LE */
+ switch (size) {
+ case 1: {
+ uint8_t *val = data;
+ *val = inb(addr);
+ break;
+ }
+ case 2: {
+ uint16_t *val = data;
+ *val = inw(addr);
+ break;
+ }
+ case 4: {
+ uint32_t *val = data;
+ *val = inl(addr);
+ break;
+ }
+ default:
+ ret = EIO;
+ break;
+ }
+ outb(0, 0xCF8);
+
+ return ret;
+}
+
+static int
+pci_system_x86_conf2_write(unsigned bus, unsigned dev, unsigned func, pciaddr_t reg, const void *data, unsigned size)
+{
+ unsigned addr = 0xC000 | dev << 8 | reg;
+ int ret = 0;
+
+ if (bus >= 0x100 || dev >= 16 || func >= 8 || reg >= 0x100)
+ return EIO;
+
+ outb((func << 1) | 0xF0, 0xCF8);
+ outb(bus, 0xCFA);
+ /* NOTE: x86 is already LE */
+ switch (size) {
+ case 1: {
+ const uint8_t *val = data;
+ outb(*val, addr);
+ break;
+ }
+ case 2: {
+ const uint16_t *val = data;
+ outw(*val, addr);
+ break;
+ }
+ case 4: {
+ const uint32_t *val = data;
+ outl(*val, addr);
+ break;
+ }
+ default:
+ ret = EIO;
+ break;
+ }
+ outb(0, 0xCF8);
+
+ return ret;
+}
+
+/* Check that this really looks like a PCI configuration. */
+static int
+pci_system_x86_check(struct pci_system_x86 *pci_sys_x86)
+{
+ int dev;
+ uint16_t class, vendor;
+
+ /* Look on bus 0 for a device that is a host bridge, a VGA card,
+ * or an intel or compaq device. */
+
+ for (dev = 0; dev < 32; dev++) {
+ if (pci_sys_x86->read(0, dev, 0, PCI_CLASS_DEVICE, &class, sizeof(class)))
+ continue;
+ if (class == PCI_CLASS_BRIDGE_HOST || class == PCI_CLASS_DISPLAY_VGA)
+ return 0;
+ if (pci_sys_x86->read(0, dev, 0, PCI_VENDOR_ID, &vendor, sizeof(vendor)))
+ continue;
+ if (vendor == PCI_VENDOR_ID_INTEL || class == PCI_VENDOR_ID_COMPAQ)
+ return 0;
+ }
+
+ return ENODEV;
+}
+
+static int
+pci_nfuncs(struct pci_system_x86 *pci_sys_x86, int bus, int dev)
+{
+ uint8_t hdr;
+ int err;
+
+ err = pci_sys_x86->read(bus, dev, 0, PCI_HDRTYPE, &hdr, sizeof(hdr));
+
+ if (err)
+ return err;
+
+ return hdr & 0x80 ? 8 : 1;
+}
+
+/**
+ * Read a VGA rom using the 0xc0000 mapping.
+ */
+static int
+pci_device_x86_read_rom(struct pci_device *dev, void *buffer)
+{
+ void *bios;
+ int memfd;
+
+ if ((dev->device_class & 0x00ffff00) !=
+ ((PCIC_DISPLAY << 16) | ( PCIS_DISPLAY_VGA << 8))) {
+ return ENOSYS;
+ }
+
+ memfd = open("/dev/mem", O_RDONLY);
+ if (memfd == -1)
+ return errno;
+
+ bios = mmap(NULL, dev->rom_size, PROT_READ, 0, memfd, 0xc0000);
+ if (bios == MAP_FAILED) {
+ close(memfd);
+ return errno;
+ }
+
+ memcpy(buffer, bios, dev->rom_size);
+
+ munmap(bios, dev->rom_size);
+ close(memfd);
+
+ return 0;
+}
+
+/** Returns the number of regions (base address registers) the device has */
+static int
+pci_device_x86_get_num_regions(uint8_t header_type)
+{
+ switch (header_type & 0x7f) {
+ case 0:
+ return 6;
+ case 1:
+ return 2;
+ case 2:
+ return 1;
+ default:
+ fprintf(stderr,"unknown header type %02x\n", header_type);
+ return 0;
+ }
+}
+
+/** Masks out the flag bigs of the base address register value */
+static uint32_t
+get_map_base( uint32_t val )
+{
+ if (val & 0x01)
+ return val & ~0x03;
+ else
+ return val & ~0x0f;
+}
+
+/** Returns the size of a region based on the all-ones test value */
+static unsigned
+get_test_val_size( uint32_t testval )
+{
+ unsigned size = 1;
+
+ if (testval == 0)
+ return 0;
+
+ /* Mask out the flag bits */
+ testval = get_map_base( testval );
+ if (!testval)
+ return 0;
+
+ while ((testval & 1) == 0) {
+ size <<= 1;
+ testval >>= 1;
+ }
+
+ return size;
+}
+
+static int
+pci_device_x86_probe(struct pci_device *dev)
+{
+ uint8_t irq, hdrtype;
+ int err, i, bar;
+
+ /* Many of the fields were filled in during initial device enumeration.
+ * At this point, we need to fill in regions, rom_size, and irq.
+ */
+
+ err = pci_device_cfg_read_u8(dev, &irq, PCI_IRQ);
+ if (err)
+ return err;
+ dev->irq = irq;
+
+ err = pci_device_cfg_read_u8(dev, &hdrtype, PCI_HDRTYPE);
+ if (err)
+ return err;
+
+ bar = 0x10;
+ for (i = 0; i < pci_device_x86_get_num_regions(hdrtype); i++, bar += 4) {
+ uint32_t addr, testval;
+
+ /* Get the base address */
+ err = pci_device_cfg_read_u32(dev, &addr, bar);
+ if (err != 0)
+ continue;
+
+ /* Test write all ones to the register, then restore it. */
+ err = pci_device_cfg_write_u32(dev, 0xffffffff, bar);
+ if (err != 0)
+ continue;
+ pci_device_cfg_read_u32(dev, &testval, bar);
+ err = pci_device_cfg_write_u32(dev, addr, bar);
+
+ if (addr & 0x01)
+ dev->regions[i].is_IO = 1;
+ if (addr & 0x04)
+ dev->regions[i].is_64 = 1;
+ if (addr & 0x08)
+ dev->regions[i].is_prefetchable = 1;
+
+ /* Set the size */
+ dev->regions[i].size = get_test_val_size(testval);
+
+ /* Set the base address value */
+ if (dev->regions[i].is_64) {
+ uint32_t top;
+
+ err = pci_device_cfg_read_u32(dev, &top, bar + 4);
+ if (err != 0)
+ continue;
+
+ dev->regions[i].base_addr = ((uint64_t)top << 32) |
+ get_map_base(addr);
+ bar += 4;
+ i++;
+ } else {
+ dev->regions[i].base_addr = get_map_base(addr);
+ }
+ }
+
+ /* If it's a VGA device, set up the rom size for read_rom using the
+ * 0xc0000 mapping.
+ */
+ if ((dev->device_class & 0x00ffff00) ==
+ ((PCIC_DISPLAY << 16) | (PCIS_DISPLAY_VGA << 8)))
+ {
+ dev->rom_size = 64 * 1024;
+ }
+
+ return 0;
+}
+
+static int
+pci_device_x86_map_range(struct pci_device *dev,
+ struct pci_device_mapping *map)
+{
+ int memfd = open("/dev/mem", O_RDWR);
+ int prot = PROT_READ;
+
+ if (memfd == -1)
+ return errno;
+
+ if (map->flags & PCI_DEV_MAP_FLAG_WRITABLE)
+ prot |= PROT_WRITE;
+
+ map->memory = mmap(NULL, map->size, prot, MAP_SHARED, memfd, map->base);
+ close(memfd);
+ if (map->memory == MAP_FAILED)
+ return errno;
+
+ return 0;
+}
+
+static int
+pci_device_x86_read(struct pci_device *dev, void *data,
+ pciaddr_t offset, pciaddr_t size, pciaddr_t *bytes_read)
+{
+ struct pci_system_x86 *pci_sys_x86 = (struct pci_system_x86 *) pci_sys;
+ int err;
+
+ *bytes_read = 0;
+ while (size > 0) {
+ int toread = 1 << (ffs(0x4 + (offset & 0x03)) - 1);
+ if (toread > size)
+ toread = size;
+
+ err = pci_sys_x86->read(dev->bus, dev->dev, dev->func, offset, data, toread);
+ if (err)
+ return err;
+
+ offset += toread;
+ data = (char*)data + toread;
+ size -= toread;
+ *bytes_read += toread;
+ }
+ return 0;
+}
+
+static int
+pci_device_x86_write(struct pci_device *dev, const void *data,
+ pciaddr_t offset, pciaddr_t size, pciaddr_t *bytes_written)
+{
+ struct pci_system_x86 *pci_sys_x86 = (struct pci_system_x86 *) pci_sys;
+ int err;
+
+ *bytes_written = 0;
+ while (size > 0) {
+ int towrite = 4;
+ if (towrite > size)
+ towrite = size;
+ if (towrite > 4 - (offset & 0x3))
+ towrite = 4 - (offset & 0x3);
+
+ err = pci_sys_x86->write(dev->bus, dev->dev, dev->func, offset, data, towrite);
+ if (err)
+ return err;
+
+ offset += towrite;
+ data = (const char*)data + towrite;
+ size -= towrite;
+ *bytes_written += towrite;
+ }
+ return 0;
+}
+
+static void
+pci_system_x86_destroy(void)
+{
+ x86_disable_io();
+}
+
+static const struct pci_system_methods x86_pci_methods = {
+ .destroy = pci_system_x86_destroy,
+ .read_rom = pci_device_x86_read_rom,
+ .probe = pci_device_x86_probe,
+ .map_range = pci_device_x86_map_range,
+ .unmap_range = pci_device_generic_unmap_range,
+ .read = pci_device_x86_read,
+ .write = pci_device_x86_write,
+ .fill_capabilities = pci_fill_capabilities_generic,
+};
+
+static int pci_probe(struct pci_system_x86 *pci_sys_x86)
+{
+ if (pci_system_x86_conf1_probe() == 0) {
+ pci_sys_x86->read = pci_system_x86_conf1_read;
+ pci_sys_x86->write = pci_system_x86_conf1_write;
+ if (pci_system_x86_check(pci_sys_x86) == 0)
+ return 0;
+ }
+
+ if (pci_system_x86_conf2_probe() == 0) {
+ pci_sys_x86->read = pci_system_x86_conf2_read;
+ pci_sys_x86->write = pci_system_x86_conf2_write;
+ if (pci_system_x86_check(pci_sys_x86) == 0)
+ return 0;
+ }
+
+ return ENODEV;
+}
+
+_pci_hidden int
+pci_system_x86_create(void)
+{
+ struct pci_device_private *device;
+ int ret, bus, dev, ndevs, func, nfuncs;
+ struct pci_system_x86 *pci_sys_x86;
+ uint32_t reg;
+
+ ret = x86_enable_io();
+ if (ret)
+ return ret;
+
+ pci_sys_x86 = calloc(1, sizeof(struct pci_system_x86));
+ if (pci_sys_x86 == NULL) {
+ x86_disable_io();
+ return ENOMEM;
+ }
+ pci_sys = &pci_sys_x86->system;
+
+ ret = pci_probe(pci_sys_x86);
+ if (ret) {
+ x86_disable_io();
+ free(pci_sys_x86);
+ pci_sys = NULL;
+ return ret;
+ }
+
+ pci_sys->methods = &x86_pci_methods;
+
+ ndevs = 0;
+ for (bus = 0; bus < 256; bus++) {
+ for (dev = 0; dev < 32; dev++) {
+ nfuncs = pci_nfuncs(pci_sys_x86, bus, dev);
+ for (func = 0; func < nfuncs; func++) {
+ if (pci_sys_x86->read(bus, dev, func, PCI_VENDOR_ID, ®, sizeof(reg)) != 0)
+ continue;
+ if (PCI_VENDOR(reg) == PCI_VENDOR_INVALID ||
+ PCI_VENDOR(reg) == 0)
+ continue;
+ ndevs++;
+ }
+ }
+ }
+
+ pci_sys->num_devices = ndevs;
+ pci_sys->devices = calloc(ndevs, sizeof(struct pci_device_private));
+ if (pci_sys->devices == NULL) {
+ x86_disable_io();
+ free(pci_sys_x86);
+ pci_sys = NULL;
+ return ENOMEM;
+ }
+
+ device = pci_sys->devices;
+ for (bus = 0; bus < 256; bus++) {
+ for (dev = 0; dev < 32; dev++) {
+ nfuncs = pci_nfuncs(pci_sys_x86, bus, dev);
+ for (func = 0; func < nfuncs; func++) {
+ if (pci_sys_x86->read(bus, dev, func, PCI_VENDOR_ID, ®, sizeof(reg)) != 0)
+ continue;
+ if (PCI_VENDOR(reg) == PCI_VENDOR_INVALID ||
+ PCI_VENDOR(reg) == 0)
+ continue;
+ device->base.domain = 0;
+ device->base.bus = bus;
+ device->base.dev = dev;
+ device->base.func = func;
+ device->base.vendor_id = PCI_VENDOR(reg);
+ device->base.device_id = PCI_DEVICE(reg);
+
+ if (pci_sys_x86->read(bus, dev, func, PCI_CLASS, ®, sizeof(reg)) != 0)
+ continue;
+ device->base.device_class = reg >> 8;
+ device->base.revision = reg & 0xFF;
+
+ if (pci_sys_x86->read(bus, dev, func, PCI_SUB_VENDOR_ID, ®, sizeof(reg)) != 0)
+ continue;
+ device->base.subvendor_id = PCI_VENDOR(reg);
+ device->base.subdevice_id = PCI_DEVICE(reg);
+
+ device++;
+ }
+ }
+ }
+
+ return 0;
+}