[PATCH 007/111] LIBPCI: added PCI layer to cpukit/libpci

Daniel Hellstrom daniel at gaisler.com
Thu Feb 26 16:38:09 UTC 2015


---
 cpukit/Makefile.am                 |    3 +
 cpukit/configure.ac                |   12 +
 cpukit/libpci/CHANGES              |   46 ++
 cpukit/libpci/Makefile.am          |   46 ++
 cpukit/libpci/README               |    4 +
 cpukit/libpci/pci.h                |  375 +++++++++++++
 cpukit/libpci/pci/access.h         |  351 +++++++++++++
 cpukit/libpci/pci/cfg.h            |  244 +++++++++
 cpukit/libpci/pci/cfg_auto.h       |   59 +++
 cpukit/libpci/pci/cfg_peripheral.h |   20 +
 cpukit/libpci/pci/cfg_read.h       |   22 +
 cpukit/libpci/pci/cfg_static.h     |   22 +
 cpukit/libpci/pci/ids.h            |  802 ++++++++++++++++++++++++++++
 cpukit/libpci/pci/ids_extra.h      |   19 +
 cpukit/libpci/pci/irq.h            |  105 ++++
 cpukit/libpci/pci_access.c         |   74 +++
 cpukit/libpci/pci_access_func.c    |   73 +++
 cpukit/libpci/pci_access_io.c      |   48 ++
 cpukit/libpci/pci_access_mem.c     |   22 +
 cpukit/libpci/pci_access_mem_be.c  |   67 +++
 cpukit/libpci/pci_access_mem_le.c  |   66 +++
 cpukit/libpci/pci_cfg.c            |   55 ++
 cpukit/libpci/pci_cfg_auto.c       | 1014 ++++++++++++++++++++++++++++++++++++
 cpukit/libpci/pci_cfg_peripheral.c |   32 ++
 cpukit/libpci/pci_cfg_print_code.c |  172 ++++++
 cpukit/libpci/pci_cfg_read.c       |  357 +++++++++++++
 cpukit/libpci/pci_cfg_static.c     |  157 ++++++
 cpukit/libpci/pci_find.c           |   52 ++
 cpukit/libpci/pci_find_dev.c       |   49 ++
 cpukit/libpci/pci_for_each.c       |   62 +++
 cpukit/libpci/pci_for_each_child.c |   41 ++
 cpukit/libpci/pci_for_each_dev.c   |   18 +
 cpukit/libpci/pci_get_dev.c        |   36 ++
 cpukit/libpci/pci_irq.c            |   20 +
 cpukit/libpci/pci_print.c          |  190 +++++++
 cpukit/libpci/preinstall.am        |   66 +++
 cpukit/preinstall.am               |    3 +-
 cpukit/sapi/include/confdefs.h     |   46 ++
 cpukit/wrapup/Makefile.am          |    2 +
 doc/ada_user/Makefile.am           |    1 +
 doc/ada_user/ada_user.texi         |    2 +
 doc/develenv/direct.t              |    3 +
 doc/user/Makefile.am               |    9 +-
 doc/user/c_user.texi               |    2 +
 doc/user/conf.t                    |   53 ++
 doc/user/libpci.t                  |  409 +++++++++++++++
 46 files changed, 5328 insertions(+), 3 deletions(-)
 create mode 100644 cpukit/libpci/CHANGES
 create mode 100644 cpukit/libpci/Makefile.am
 create mode 100644 cpukit/libpci/README
 create mode 100644 cpukit/libpci/pci.h
 create mode 100644 cpukit/libpci/pci/access.h
 create mode 100644 cpukit/libpci/pci/cfg.h
 create mode 100644 cpukit/libpci/pci/cfg_auto.h
 create mode 100644 cpukit/libpci/pci/cfg_peripheral.h
 create mode 100644 cpukit/libpci/pci/cfg_read.h
 create mode 100644 cpukit/libpci/pci/cfg_static.h
 create mode 100644 cpukit/libpci/pci/ids.h
 create mode 100644 cpukit/libpci/pci/ids_extra.h
 create mode 100644 cpukit/libpci/pci/irq.h
 create mode 100644 cpukit/libpci/pci_access.c
 create mode 100644 cpukit/libpci/pci_access_func.c
 create mode 100644 cpukit/libpci/pci_access_io.c
 create mode 100644 cpukit/libpci/pci_access_mem.c
 create mode 100644 cpukit/libpci/pci_access_mem_be.c
 create mode 100644 cpukit/libpci/pci_access_mem_le.c
 create mode 100644 cpukit/libpci/pci_cfg.c
 create mode 100644 cpukit/libpci/pci_cfg_auto.c
 create mode 100644 cpukit/libpci/pci_cfg_peripheral.c
 create mode 100644 cpukit/libpci/pci_cfg_print_code.c
 create mode 100644 cpukit/libpci/pci_cfg_read.c
 create mode 100644 cpukit/libpci/pci_cfg_static.c
 create mode 100644 cpukit/libpci/pci_find.c
 create mode 100644 cpukit/libpci/pci_find_dev.c
 create mode 100644 cpukit/libpci/pci_for_each.c
 create mode 100644 cpukit/libpci/pci_for_each_child.c
 create mode 100644 cpukit/libpci/pci_for_each_dev.c
 create mode 100644 cpukit/libpci/pci_get_dev.c
 create mode 100644 cpukit/libpci/pci_irq.c
 create mode 100644 cpukit/libpci/pci_print.c
 create mode 100644 cpukit/libpci/preinstall.am
 create mode 100644 doc/user/libpci.t

diff --git a/cpukit/Makefile.am b/cpukit/Makefile.am
index 9a78587..0364bf1 100644
--- a/cpukit/Makefile.am
+++ b/cpukit/Makefile.am
@@ -9,6 +9,7 @@ SUBDIRS += dev
 SUBDIRS += libcrypt
 SUBDIRS += libcsupport libblock libfs
 SUBDIRS += libnetworking librpc
+SUBDIRS += libpci
 SUBDIRS += libi2c
 SUBDIRS += libmisc
 SUBDIRS += libmd
@@ -95,7 +96,9 @@ endif
 include_rtems_HEADERS += include/rtems/bspIo.h
 include_rtems_HEADERS += include/rtems/userenv.h
 include_rtems_HEADERS += include/rtems/fs.h
+if !LIBPCI
 include_rtems_HEADERS += include/rtems/pci.h
+endif
 include_rtems_HEADERS += include/rtems/concat.h
 include_rtems_HEADERS += include/rtems/status-checks.h
 
diff --git a/cpukit/configure.ac b/cpukit/configure.ac
index 27ffd81..8042c35 100644
--- a/cpukit/configure.ac
+++ b/cpukit/configure.ac
@@ -385,6 +385,17 @@ esac
 AM_CONDITIONAL(LIBDL,[test x"$HAVE_LIBDL" = x"yes"])
 AC_MSG_RESULT([$HAVE_LIBDL])
 
+# Filter libpci to only build for architectures that have support for it
+AC_MSG_CHECKING([whether CPU supports libpci])
+case $RTEMS_CPU in
+  sparc)
+   HAVE_LIBPCI=yes ;;
+  *)
+   HAVE_LIBPCI=no ;;
+esac
+AM_CONDITIONAL(LIBPCI,[test x"$HAVE_LIBPCI" = x"yes"])
+AC_MSG_RESULT([$HAVE_LIBPCI])
+
 RTEMS_AMPOLISH3
 
 # Explicitly list all Makefiles here
@@ -423,6 +434,7 @@ libgnat/Makefile
 libcrypt/Makefile
 libcsupport/Makefile
 libnetworking/Makefile
+libpci/Makefile
 librpc/Makefile
 libmisc/Makefile
 libi2c/Makefile
diff --git a/cpukit/libpci/CHANGES b/cpukit/libpci/CHANGES
new file mode 100644
index 0000000..46064f0
--- /dev/null
+++ b/cpukit/libpci/CHANGES
@@ -0,0 +1,46 @@
+ 2011-03-03, Daniel Hellstrom <daniel at gaisler.com>
+  Added support for ROM BARs at devices and PCI-PCI bridges.
+
+ 2011-02-11, Daniel Hellstrom <daniel at gaisler.com>
+  Split Library into different parts, this enables PCI initialization to be done
+  outside of the PCI Host driver and smaller systems that don't want
+  Configuration Space to be setup.
+    - Access Library (Configuration, Memory and I/O Space read/write routines)
+    - Configuration Libarary
+        A. Auto Config
+        B. Static Config (not implemented yet)
+    - Interrupt Library (shared interrupt support rely on BSP)
+  This file created.
+
+ 2011-02-11, Daniel Hellstrom <daniel at gaisler.com>
+  Changed library to use 16-bit identifiers (pci_dev_t), instead to 3 integers
+  (BUS,SLOT,FUNC), this reduces the footprint.
+
+ 2010-09-29, Kristoffer Glembo <kristoffer at gaisler.com>
+  Fixed I/O BAR size calculation of bridges. Reading/Writing to 0x1C instead of
+  faulty 0x1E.
+
+ 2010-06-10, Daniel Hellstrom <daniel at gaisler.com>
+  Fix in pci_res_insert(), where the above mentioned optimization failed due to
+  bad compare statement. Optimization only affects systems with multiple PCI
+  buses.
+
+ 2010-04-19, Daniel Hellstrom <daniel at gaisler.com>
+  Optimized resource allocation when bridges are present: the resources lists
+  are sorted by boundary instead of size and a reorder aligorithm introduced
+  that move resources into unused areas if possible.
+
+ 2010-04-19, Daniel Hellstrom <daniel at gaisler.com>
+  Fixed autoconf issue when bridges are present
+
+ 2010-02-03, Daniel Hellstrom <daniel at gaisler.com>
+  Fixed initialization problem when first device is a bridge.
+
+ 2010-02-03, Daniel Hellstrom <daniel at gaisler.com>
+  PCI Library rewritten from scratch. Support multiple buses/bridges, print
+  current PCI configuration space setup, BAR assigment sort implementation
+  speeded up drastically (bootup time noticable shorter), interrupt assignment
+  implemented, PCI Host driver extracted from library, support for I/O areas.
+
+
+.... not updated ... lots of more changes
diff --git a/cpukit/libpci/Makefile.am b/cpukit/libpci/Makefile.am
new file mode 100644
index 0000000..fd42a6f
--- /dev/null
+++ b/cpukit/libpci/Makefile.am
@@ -0,0 +1,46 @@
+##
+##  $Id: Makefile.am
+##
+
+include $(top_srcdir)/automake/compile.am
+include $(top_srcdir)/automake/multilib.am
+
+if LIBPCI
+
+EXTRA_DIST=
+
+## PCI Library
+include_HEADERS = pci.h
+include_pcidir = $(includedir)/pci
+include_pci_HEADERS =	pci/access.h pci/cfg.h \
+			pci/cfg_auto.h pci/cfg_static.h \
+			pci/cfg_peripheral.h pci/cfg_read.h \
+			pci/ids.h pci/ids_extra.h pci/irq.h
+
+noinst_LIBRARIES = libpci.a
+
+libpci_a_SOURCES  = pci_access.c
+libpci_a_SOURCES += pci_access_func.c
+libpci_a_SOURCES += pci_access_io.c
+libpci_a_SOURCES += pci_access_mem.c
+libpci_a_SOURCES += pci_access_mem_be.c
+libpci_a_SOURCES += pci_access_mem_le.c
+libpci_a_SOURCES += pci_cfg.c
+libpci_a_SOURCES += pci_cfg_auto.c
+libpci_a_SOURCES += pci_cfg_print_code.c
+libpci_a_SOURCES += pci_cfg_read.c
+libpci_a_SOURCES += pci_cfg_static.c
+libpci_a_SOURCES += pci_cfg_peripheral.c
+libpci_a_SOURCES += pci_find.c
+libpci_a_SOURCES += pci_find_dev.c
+libpci_a_SOURCES += pci_for_each.c
+libpci_a_SOURCES += pci_for_each_dev.c
+libpci_a_SOURCES += pci_for_each_child.c
+libpci_a_SOURCES += pci_get_dev.c
+libpci_a_SOURCES += pci_irq.c
+libpci_a_SOURCES += pci_print.c
+
+endif
+
+include $(srcdir)/preinstall.am
+include $(top_srcdir)/automake/local.am
diff --git a/cpukit/libpci/README b/cpukit/libpci/README
new file mode 100644
index 0000000..334f3a9
--- /dev/null
+++ b/cpukit/libpci/README
@@ -0,0 +1,4 @@
+PCI Library
+
+LIBPCI is documented in the ../../doc directory, see ../../doc/README how
+to build documentation.
diff --git a/cpukit/libpci/pci.h b/cpukit/libpci/pci.h
new file mode 100644
index 0000000..e9955bc
--- /dev/null
+++ b/cpukit/libpci/pci.h
@@ -0,0 +1,375 @@
+/*
+ *
+ *	PCI defines and function prototypes
+ *	Copyright 1994, Drew Eckhardt
+ *	Copyright 1997, 1998 Martin Mares <mj at atrey.karlin.mff.cuni.cz>
+ * 
+ *      New PCI library written from scratch. Defines in this file was reused.
+ *      auto-generated pci_ids.h also reused.
+ *      Copyright 2009, Cobham Gaisler AB
+ *
+ *	For more information, please consult the following manuals (look at
+ *	http://www.pcisig.com/ for how to get them):
+ *
+ *	PCI BIOS Specification
+ *	PCI Local Bus Specification
+ *	PCI to PCI Bridge Specification
+ *	PCI System Design Guide
+ */
+
+#ifndef __PCI_H__
+#define __PCI_H__
+
+#include <pci/ids.h>
+
+/*
+ * Under PCI, each device has 256 bytes of configuration address space,
+ * of which the first 64 bytes are standardized as follows:
+ */
+#define PCI_VENDOR_ID		0x00	/* 16 bits */
+#define PCI_DEVICE_ID		0x02	/* 16 bits */
+#define PCI_COMMAND		0x04	/* 16 bits */
+#define  PCI_COMMAND_IO		0x1	/* Enable response in I/O space */
+#define  PCI_COMMAND_MEMORY	0x2	/* Enable response in Memory space */
+#define  PCI_COMMAND_MASTER	0x4	/* Enable bus mastering */
+#define  PCI_COMMAND_SPECIAL	0x8	/* Enable response to special cycles */
+#define  PCI_COMMAND_INVALIDATE	0x10	/* Use memory write and invalidate */
+#define  PCI_COMMAND_VGA_PALETTE 0x20	/* Enable palette snooping */
+#define  PCI_COMMAND_PARITY	0x40	/* Enable parity checking */
+#define  PCI_COMMAND_WAIT	0x80	/* Enable address/data stepping */
+#define  PCI_COMMAND_SERR	0x100	/* Enable SERR */
+#define  PCI_COMMAND_FAST_BACK	0x200	/* Enable back-to-back writes */
+
+#define PCI_STATUS		0x06	/* 16 bits */
+#define  PCI_STATUS_66MHZ	0x20	/* Support 66 Mhz PCI 2.1 bus */
+#define  PCI_STATUS_UDF		0x40	/* Support User Definable Features */
+
+#define  PCI_STATUS_FAST_BACK	0x80	/* Accept fast-back to back */
+#define  PCI_STATUS_PARITY	0x100	/* Detected parity error */
+#define  PCI_STATUS_DEVSEL_MASK	0x600	/* DEVSEL timing */
+#define  PCI_STATUS_DEVSEL_FAST	0x000
+#define  PCI_STATUS_DEVSEL_MEDIUM 0x200
+#define  PCI_STATUS_DEVSEL_SLOW 0x400
+#define  PCI_STATUS_SIG_TARGET_ABORT 0x800 /* Set on target abort */
+#define  PCI_STATUS_REC_TARGET_ABORT 0x1000 /* Master ack of " */
+#define  PCI_STATUS_REC_MASTER_ABORT 0x2000 /* Set on master abort */
+#define  PCI_STATUS_SIG_SYSTEM_ERROR 0x4000 /* Set when we drive SERR */
+#define  PCI_STATUS_DETECTED_PARITY 0x8000 /* Set on parity error */
+
+#define PCI_CLASS_REVISION	0x08	/* High 24 bits are class, low 8
+					   revision */
+#define PCI_REVISION_ID         0x08    /* Revision ID */
+#define PCI_CLASS_PROG          0x09    /* Reg. Level Programming Interface */
+#define PCI_CLASS_DEVICE        0x0a    /* Device class */
+
+#define PCI_CACHE_LINE_SIZE	0x0c	/* 8 bits */
+#define PCI_LATENCY_TIMER	0x0d	/* 8 bits */
+#define PCI_HEADER_TYPE		0x0e	/* 8 bits */
+#define  PCI_HEADER_TYPE_NORMAL	0
+#define  PCI_HEADER_TYPE_BRIDGE 1
+#define  PCI_HEADER_TYPE_CARDBUS 2
+
+#define PCI_BIST		0x0f	/* 8 bits */
+#define PCI_BIST_CODE_MASK	0x0f	/* Return result */
+#define PCI_BIST_START		0x40	/* 1 to start BIST, 2 secs or less */
+#define PCI_BIST_CAPABLE	0x80	/* 1 if BIST capable */
+
+/*
+ * Base addresses specify locations in memory or I/O space.
+ * Decoded size can be determined by writing a value of
+ * 0xffffffff to the register, and reading it back. Only
+ * 1 bits are decoded.
+ */
+#define PCI_BASE_ADDRESS_0	0x10	/* 32 bits */
+#define PCI_BASE_ADDRESS_1	0x14	/* 32 bits [htype 0,1 only] */
+#define PCI_BASE_ADDRESS_2	0x18	/* 32 bits [htype 0 only] */
+#define PCI_BASE_ADDRESS_3	0x1c	/* 32 bits */
+#define PCI_BASE_ADDRESS_4	0x20	/* 32 bits */
+#define PCI_BASE_ADDRESS_5	0x24	/* 32 bits */
+#define  PCI_BASE_ADDRESS_SPACE	0x01	/* 0 = memory, 1 = I/O */
+#define  PCI_BASE_ADDRESS_SPACE_IO 0x01
+#define  PCI_BASE_ADDRESS_SPACE_MEMORY 0x00
+#define  PCI_BASE_ADDRESS_MEM_TYPE_MASK 0x06
+#define  PCI_BASE_ADDRESS_MEM_TYPE_32	0x00	/* 32 bit address */
+#define  PCI_BASE_ADDRESS_MEM_TYPE_1M	0x02	/* Below 1M */
+#define  PCI_BASE_ADDRESS_MEM_TYPE_64	0x04	/* 64 bit address */
+#define  PCI_BASE_ADDRESS_MEM_PREFETCH	0x08	/* prefetchable? */
+#define  PCI_BASE_ADDRESS_MEM_MASK	(~0x0fUL)
+#define  PCI_BASE_ADDRESS_IO_MASK	(~0x03UL)
+/* bit 1 is reserved if address_space = 1 */
+
+/* Header type 0 (normal devices) */
+#define PCI_CARDBUS_CIS		0x28
+#define PCI_SUBSYSTEM_VENDOR_ID	0x2c
+#define PCI_SUBSYSTEM_ID	0x2e
+#define PCI_ROM_ADDRESS		0x30	/* Bits 31..11 are address, 10..1 reserved */
+#define  PCI_ROM_ADDRESS_ENABLE	0x01
+#define  PCI_ROM_ADDRESS_MASK	(~0x7ffUL)
+
+/* 0x34 Capabilities Pointer (PCI 2.3) */
+#define PCI_CAP_PTR		0x34	/* 8 bits */
+
+/* 0x35-0x3b are reserved */
+#define PCI_INTERRUPT_LINE	0x3c	/* 8 bits */
+#define PCI_INTERRUPT_PIN	0x3d	/* 8 bits */
+#define PCI_MIN_GNT		0x3e	/* 8 bits */
+#define PCI_MAX_LAT		0x3f	/* 8 bits */
+
+/* Header type 1 (PCI-to-PCI bridges) */
+#define PCI_PRIMARY_BUS		0x18	/* Primary bus number */
+#define PCI_SECONDARY_BUS	0x19	/* Secondary bus number */
+#define PCI_SUBORDINATE_BUS	0x1a	/* Highest bus number behind the bridge */
+#define PCI_SEC_LATENCY_TIMER	0x1b	/* Latency timer for secondary interface */
+#define PCI_IO_BASE		0x1c	/* I/O range behind the bridge */
+#define PCI_IO_LIMIT		0x1d
+#define  PCI_IO_RANGE_TYPE_MASK	0x0f	/* I/O bridging type */
+#define  PCI_IO_RANGE_TYPE_16	0x00
+#define  PCI_IO_RANGE_TYPE_32	0x01
+#define  PCI_IO_RANGE_MASK	(~0x0f)
+#define PCI_SEC_STATUS		0x1e	/* Secondary status register, only bit 14 used */
+#define PCI_MEMORY_BASE		0x20	/* Memory range behind */
+#define PCI_MEMORY_LIMIT	0x22
+#define  PCI_MEMORY_RANGE_TYPE_MASK 0x0f
+#define  PCI_MEMORY_RANGE_MASK	(~0x0f)
+#define PCI_PREF_MEMORY_BASE	0x24	/* Prefetchable memory range behind */
+#define PCI_PREF_MEMORY_LIMIT	0x26
+#define  PCI_PREF_RANGE_TYPE_MASK 0x0f
+#define  PCI_PREF_RANGE_TYPE_32	0x00
+#define  PCI_PREF_RANGE_TYPE_64	0x01
+#define  PCI_PREF_RANGE_MASK	(~0x0f)
+#define PCI_PREF_BASE_UPPER32	0x28	/* Upper half of prefetchable memory range */
+#define PCI_PREF_LIMIT_UPPER32	0x2c
+#define PCI_IO_BASE_UPPER16	0x30	/* Upper half of I/O addresses */
+#define PCI_IO_LIMIT_UPPER16	0x32
+/* 0x34-0x3b is reserved */
+#define PCI_ROM_ADDRESS1	0x38	/* Same as PCI_ROM_ADDRESS, but for htype 1 */
+/* 0x3c-0x3d are same as for htype 0 */
+#define PCI_BRIDGE_CONTROL	0x3e
+#define  PCI_BRIDGE_CTL_PARITY	0x01	/* Enable parity detection on secondary interface */
+#define  PCI_BRIDGE_CTL_SERR	0x02	/* The same for SERR forwarding */
+#define  PCI_BRIDGE_CTL_NO_ISA	0x04	/* Disable bridging of ISA ports */
+#define  PCI_BRIDGE_CTL_VGA	0x08	/* Forward VGA addresses */
+#define  PCI_BRIDGE_CTL_MASTER_ABORT 0x20  /* Report master aborts */
+#define  PCI_BRIDGE_CTL_BUS_RESET 0x40	/* Secondary bus reset */
+#define  PCI_BRIDGE_CTL_FAST_BACK 0x80	/* Fast Back2Back enabled on secondary interface */
+
+/* Header type 2 (CardBus bridges) */
+/* 0x14-0x15 reserved */
+#define PCI_CB_SEC_STATUS	0x16	/* Secondary status */
+#define PCI_CB_PRIMARY_BUS	0x18	/* PCI bus number */
+#define PCI_CB_CARD_BUS		0x19	/* CardBus bus number */
+#define PCI_CB_SUBORDINATE_BUS	0x1a	/* Subordinate bus number */
+#define PCI_CB_LATENCY_TIMER	0x1b	/* CardBus latency timer */
+#define PCI_CB_MEMORY_BASE_0	0x1c
+#define PCI_CB_MEMORY_LIMIT_0	0x20
+#define PCI_CB_MEMORY_BASE_1	0x24
+#define PCI_CB_MEMORY_LIMIT_1	0x28
+#define PCI_CB_IO_BASE_0	0x2c
+#define PCI_CB_IO_BASE_0_HI	0x2e
+#define PCI_CB_IO_LIMIT_0	0x30
+#define PCI_CB_IO_LIMIT_0_HI	0x32
+#define PCI_CB_IO_BASE_1	0x34
+#define PCI_CB_IO_BASE_1_HI	0x36
+#define PCI_CB_IO_LIMIT_1	0x38
+#define PCI_CB_IO_LIMIT_1_HI	0x3a
+#define  PCI_CB_IO_RANGE_MASK	(~0x03)
+/* 0x3c-0x3d are same as for htype 0 */
+#define PCI_CB_BRIDGE_CONTROL	0x3e
+#define  PCI_CB_BRIDGE_CTL_PARITY	0x01	/* Similar to standard bridge control register */
+#define  PCI_CB_BRIDGE_CTL_SERR		0x02
+#define  PCI_CB_BRIDGE_CTL_ISA		0x04
+#define  PCI_CB_BRIDGE_CTL_VGA		0x08
+#define  PCI_CB_BRIDGE_CTL_MASTER_ABORT	0x20
+#define  PCI_CB_BRIDGE_CTL_CB_RESET	0x40	/* CardBus reset */
+#define  PCI_CB_BRIDGE_CTL_16BIT_INT	0x80	/* Enable interrupt for 16-bit cards */
+#define  PCI_CB_BRIDGE_CTL_PREFETCH_MEM0 0x100	/* Prefetch enable for both memory regions */
+#define  PCI_CB_BRIDGE_CTL_PREFETCH_MEM1 0x200
+#define  PCI_CB_BRIDGE_CTL_POST_WRITES	0x400
+#define PCI_CB_SUBSYSTEM_VENDOR_ID 0x40
+#define PCI_CB_SUBSYSTEM_ID	0x42
+#define PCI_CB_LEGACY_MODE_BASE	0x44	/* 16-bit PC Card legacy mode base address (ExCa) */
+/* 0x48-0x7f reserved */
+
+/* Device classes and subclasses */
+
+#define PCI_CLASS_NOT_DEFINED		0x0000
+#define PCI_CLASS_NOT_DEFINED_VGA	0x0001
+
+#define PCI_BASE_CLASS_STORAGE		0x01
+#define PCI_CLASS_STORAGE_SCSI		0x0100
+#define PCI_CLASS_STORAGE_IDE		0x0101
+#define PCI_CLASS_STORAGE_FLOPPY	0x0102
+#define PCI_CLASS_STORAGE_IPI		0x0103
+#define PCI_CLASS_STORAGE_RAID		0x0104
+#define PCI_CLASS_STORAGE_OTHER		0x0180
+
+#define PCI_BASE_CLASS_NETWORK		0x02
+#define PCI_CLASS_NETWORK_ETHERNET	0x0200
+#define PCI_CLASS_NETWORK_TOKEN_RING	0x0201
+#define PCI_CLASS_NETWORK_FDDI		0x0202
+#define PCI_CLASS_NETWORK_ATM		0x0203
+#define PCI_CLASS_NETWORK_OTHER		0x0280
+
+#define PCI_BASE_CLASS_DISPLAY		0x03
+#define PCI_CLASS_DISPLAY_VGA		0x0300
+#define PCI_CLASS_DISPLAY_XGA		0x0301
+#define PCI_CLASS_DISPLAY_OTHER		0x0380
+
+#define PCI_BASE_CLASS_MULTIMEDIA	0x04
+#define PCI_CLASS_MULTIMEDIA_VIDEO	0x0400
+#define PCI_CLASS_MULTIMEDIA_AUDIO	0x0401
+#define PCI_CLASS_MULTIMEDIA_OTHER	0x0480
+
+#define PCI_BASE_CLASS_MEMORY		0x05
+#define  PCI_CLASS_MEMORY_RAM		0x0500
+#define  PCI_CLASS_MEMORY_FLASH		0x0501
+#define  PCI_CLASS_MEMORY_OTHER		0x0580
+
+#define PCI_BASE_CLASS_BRIDGE		0x06
+#define  PCI_CLASS_BRIDGE_HOST		0x0600
+#define  PCI_CLASS_BRIDGE_ISA		0x0601
+#define  PCI_CLASS_BRIDGE_EISA		0x0602
+#define  PCI_CLASS_BRIDGE_MC		0x0603
+#define  PCI_CLASS_BRIDGE_PCI		0x0604
+#define  PCI_CLASS_BRIDGE_PCMCIA	0x0605
+#define  PCI_CLASS_BRIDGE_NUBUS		0x0606
+#define  PCI_CLASS_BRIDGE_CARDBUS	0x0607
+#define  PCI_CLASS_BRIDGE_OTHER		0x0680
+
+#define PCI_BASE_CLASS_COMMUNICATION	0x07
+#define PCI_CLASS_COMMUNICATION_SERIAL	0x0700
+#define PCI_CLASS_COMMUNICATION_PARALLEL 0x0701
+#define PCI_CLASS_COMMUNICATION_OTHER	0x0780
+
+#define PCI_BASE_CLASS_SYSTEM		0x08
+#define PCI_CLASS_SYSTEM_PIC		0x0800
+#define PCI_CLASS_SYSTEM_DMA		0x0801
+#define PCI_CLASS_SYSTEM_TIMER		0x0802
+#define PCI_CLASS_SYSTEM_RTC		0x0803
+#define PCI_CLASS_SYSTEM_OTHER		0x0880
+
+#define PCI_BASE_CLASS_INPUT		0x09
+#define PCI_CLASS_INPUT_KEYBOARD	0x0900
+#define PCI_CLASS_INPUT_PEN		0x0901
+#define PCI_CLASS_INPUT_MOUSE		0x0902
+#define PCI_CLASS_INPUT_OTHER		0x0980
+
+#define PCI_BASE_CLASS_DOCKING		0x0a
+#define PCI_CLASS_DOCKING_GENERIC	0x0a00
+#define PCI_CLASS_DOCKING_OTHER		0x0a01
+
+#define PCI_BASE_CLASS_PROCESSOR	0x0b
+#define PCI_CLASS_PROCESSOR_386		0x0b00
+#define PCI_CLASS_PROCESSOR_486		0x0b01
+#define PCI_CLASS_PROCESSOR_PENTIUM	0x0b02
+#define PCI_CLASS_PROCESSOR_ALPHA	0x0b10
+#define PCI_CLASS_PROCESSOR_POWERPC	0x0b20
+#define PCI_CLASS_PROCESSOR_CO		0x0b40
+
+#define PCI_BASE_CLASS_SERIAL		0x0c
+#define PCI_CLASS_SERIAL_FIREWIRE	0x0c00
+#define PCI_CLASS_SERIAL_ACCESS		0x0c01
+#define PCI_CLASS_SERIAL_SSA		0x0c02
+#define PCI_CLASS_SERIAL_USB		0x0c03
+#define PCI_CLASS_SERIAL_FIBER		0x0c04
+
+#define PCI_CLASS_OTHERS		0xff
+
+#define PCI_INVALID_VENDORDEVICEID    0xffffffff
+#define PCI_MULTI_FUNCTION            0x80
+
+#define PCI_MAX_DEVICES			32
+#define PCI_MAX_FUNCTIONS		8
+
+#include <pci/access.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* The PCI Library have the following build time configuration options. It is
+ * up to the BSP header file (bsp.h) to set options properly.
+ *
+ * BSP_PCI_BIG_ENDIAN    - Access inline routines will be for a big-endian PCI
+ *                         bus, if not defined the routines will assume that
+ *                         PCI is as the standard defines: little-endian.
+ *
+ *                         Note that drivers may be run-time configurable,
+ *                         meaning that they may adopt to either big-endian or
+ *                         little-endian PCI bus, the host driver or BSP may
+ *                         detect endianness during run-time.
+ */
+
+/* Error return values */
+enum {
+	PCISTS_ERR         = -1, /* Undefined Error */
+	PCISTS_OK          = 0,
+	PCISTS_EINVAL      = 1, /* Bad input arguments */
+	PCISTS_MSTABRT     = 2, /* CFG space access error (can be ignored) */
+};
+
+/* PCI System type can be used to determine system for drivers. Normally
+ * the system is Host, but the peripheral configuration library also supports
+ * being PCI peripheral not allowed to access configuration space.
+ *
+ * The active configuration Library set this variable.
+ */
+enum {
+	PCI_SYSTEM_NONE = 0,
+	PCI_SYSTEM_HOST = 1,
+	PCI_SYSTEM_PERIPHERAL = 2,
+};
+extern int pci_system_type;
+
+/* PCI Bus Endianness. The PCI specification is little endian, however on some
+ * embedded systems (AT697-LEON2 for example) the PCI bus is defined as big
+ * endian (non-standard) in order to avoid byte-twisting.
+ */
+enum {
+	PCI_LITTLE_ENDIAN = 0,
+	PCI_BIG_ENDIAN = 1,
+};
+extern int pci_endian;
+
+/* Return the number of PCI busses in the system */
+extern int pci_bus_count(void);
+
+/* Scan the PCI bus and print the PCI device/functions/bridges and their
+ * current resources and size to the system console.
+ */
+extern void pci_print(void);
+
+/* Print current configuration of a single PCI device by reading PCI
+ * configuration space
+ */
+extern void pci_print_dev(pci_dev_t dev);
+extern void pci_print_device(int bus, int slot, int function);
+
+/*** PCI Configuration Space direct access routines ***/
+
+/* Function iterates over all PCI buses/devices/functions and calls
+ * func(PCIDEV,arg) for each present device. The iteration is stopped if
+ * func() returns non-zero result the same result is returned. As long
+ * as func() returns zero the function will keep on iterating, when all
+ * devices has been processed the function return zero.
+ *
+ * The function iterates over all devices/functions on all buses by accessing
+ * configuration space directly (PCI RAM data structures not used). This
+ * function is valid to call after PCI buses have been enumrated.
+ */
+extern int pci_for_each(int (*func)(pci_dev_t, void*), void *arg);
+
+/* Get PCI Configuration space BUS|SLOT|FUNC for a device matching PCI
+ * Vendor, Device and instance number 'index'.
+ *
+ * Return Values
+ * -1  pci_find_dev did not find a device matching the criterion.
+ *  0  device was found, *pdev was updated with the device's BUS|SLOT|FUNC
+ */
+extern int pci_find(uint16_t ven, uint16_t dev, int index, pci_dev_t *pdev);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __PCI_H__ */
diff --git a/cpukit/libpci/pci/access.h b/cpukit/libpci/pci/access.h
new file mode 100644
index 0000000..f8365db
--- /dev/null
+++ b/cpukit/libpci/pci/access.h
@@ -0,0 +1,351 @@
+/* Routines to access PCI memory/configuration space and other PCI related
+ * functions the PCI Library provides.
+ *
+ * COPYRIGHT (c) 2010.
+ * Cobham Gaisler AB.
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ */
+
+
+#ifndef __PCI_ACCESS_H__
+#define __PCI_ACCESS_H__
+
+#include <stdint.h>
+#include <libcpu/byteorder.h>
+#include <pci.h>
+
+/* Let BSP configure load/store from PCI */
+#include <bsp.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Identification of a PCI configuration space device (16-bit) */
+typedef uint16_t pci_dev_t;
+/* Create a PCI Configuration Space ID */
+#define PCI_DEV(bus, slot, func) (((bus)<<8) | ((slot)<<3) | (func))
+/* Get Bus of a PCI Configuration Space ID */
+#define PCI_DEV_BUS(dev) (((dev) >> 8) & 0xff)
+/* Get Slot/Device of a PCI Configuration Space ID */
+#define PCI_DEV_SLOT(dev) (((dev) >> 3) & 0x1f)
+/* Get Function of a PCI Configuration Space ID */
+#define PCI_DEV_FUNC(dev) ((dev) & 0x7)
+/* Get Device and Function of a PCI Configuration Space ID */
+#define PCI_DEV_DEVFUNC(dev) ((dev) & 0xff)
+/* Expand Device into argument lists */
+#define PCI_DEV_EXPAND(dev) PCI_DEV_BUS((dev)), PCI_DEV_SLOT((dev)), PCI_DEV_FUNC((dev))
+
+/* Configuration Space Read/Write Operations */
+struct pci_cfg_ops {
+	/* Configuration Space Access and Setup Routines */
+	int (*read8)(pci_dev_t dev, int ofs, uint8_t *data);
+	int (*read16)(pci_dev_t dev, int ofs, uint16_t *data);
+	int (*read32)(pci_dev_t dev, int ofs, uint32_t *data);
+	int (*write8)(pci_dev_t dev, int ofs, uint8_t data);
+	int (*write16)(pci_dev_t dev, int ofs, uint16_t data);
+	int (*write32)(pci_dev_t dev, int ofs, uint32_t data);
+};
+
+/* Read a register over PCI I/O Space, and swap it if necessary (due to 
+ * PCI endianness)
+ */
+struct pci_io_ops {
+	uint8_t (*read8)(uint8_t *adr);
+	uint16_t(*read16)(uint16_t *adr);
+	uint32_t (*read32)(uint32_t *adr);
+	void (*write8)(uint8_t *adr, uint8_t data);
+	void (*write16)(uint16_t *adr, uint16_t data);
+	void (*write32)(uint32_t *adr, uint32_t data);
+};
+
+/* Read a register over PCI Memory Space (non-prefetchable memory), and 
+ * swap it if necessary (due to PCI endianness)
+ */
+struct pci_memreg_ops {
+	uint8_t (*ld8)(uint8_t *adr);
+	void (*st8)(uint8_t *adr, uint8_t data);
+
+	uint16_t(*ld_le16)(uint16_t *adr);
+	void (*st_le16)(uint16_t *adr, uint16_t data);
+	uint16_t(*ld_be16)(uint16_t *adr);
+	void (*st_be16)(uint16_t *adr, uint16_t data);
+
+	uint32_t (*ld_le32)(uint32_t *adr);
+	void (*st_le32)(uint32_t *adr, uint32_t data);
+	uint32_t (*ld_be32)(uint32_t *adr);
+	void (*st_be32)(uint32_t *adr, uint32_t data);
+};
+
+typedef uint8_t (*pci_ld8_t)(uint8_t *adr);
+typedef void (*pci_st8_t)(uint8_t *adr, uint8_t data);
+typedef uint16_t(pci_ld16_t)(uint16_t *adr);
+typedef void (*pci_st16_t)(uint16_t *adr, uint16_t data);
+typedef uint32_t (*pci_ld32_t)(uint32_t *adr);
+typedef void (*pci_st32_t)(uint32_t *adr, uint32_t data);
+
+struct pci_access_drv {
+	/* Configuration */
+	struct pci_cfg_ops cfg;
+
+	/* I/O Access operations */
+	struct pci_io_ops io;
+
+	/* Registers over Memory Access operations. Note that these funcs
+	 * are only for code that need to be compatible with both Big-Endian
+	 * and Little-Endian PCI bus or for some other reason need function
+	 * pointers to access functions. Normally drivers use the inline
+	 * functions for Registers-over-Memory access to avoid extra function
+	 * call.
+	 */
+	struct pci_memreg_ops *memreg;
+
+	/* Translate from PCI address to CPU address (dir=0). Translate
+	 * CPU address to PCI address (dir!=0). The address will can be
+	 * used to perform I/O access or memory access by CPU or PCI DMA
+	 * peripheral.
+	 *
+	 * address    In/Out. CPU address or PCI address.
+	 * type       Access type. 1=I/O, 2=MEMIO, 3=MEM
+	 * dir        Translate direction. 0=PCI-to-CPU, 0!=CPU-to-PCI,
+	 *
+	 * Return Value
+	 *  0   = Success
+	 *  -1  = Requested Address not mapped into other address space
+	 *        i.e. not accessible
+	 */
+	int (*translate)(uint32_t *address, int type, int dir);
+};
+
+/* Access Routines valid after a PCI-Access-Driver has registered */
+extern struct pci_access_drv pci_access_ops;
+
+/* Register PCI Access Driver */
+extern int pci_access_drv_register(struct pci_access_drv *drv);
+
+/* Set/unset bits in command and status register of a PCI device */
+extern void pci_modify_cmdsts(pci_dev_t dev, uint32_t mask, uint32_t val);
+
+/* Enable Memory in command register */
+static inline void pci_mem_enable(pci_dev_t dev)
+{
+	pci_modify_cmdsts(dev, PCI_COMMAND_MEMORY, PCI_COMMAND_MEMORY);
+}
+
+static inline void pci_mem_disable(pci_dev_t dev)
+{
+	pci_modify_cmdsts(dev, PCI_COMMAND_MEMORY, 0);
+}
+
+static inline void pci_io_enable(pci_dev_t dev)
+{
+	pci_modify_cmdsts(dev, PCI_COMMAND_IO, PCI_COMMAND_IO);
+}
+
+static inline void pci_io_disable(pci_dev_t dev)
+{
+	pci_modify_cmdsts(dev, PCI_COMMAND_IO, 0);
+}
+
+static inline void pci_master_enable(pci_dev_t dev)
+{
+	pci_modify_cmdsts(dev, PCI_COMMAND_MASTER, PCI_COMMAND_MASTER);
+}
+
+static inline void pci_master_disable(pci_dev_t dev)
+{
+	pci_modify_cmdsts(dev, PCI_COMMAND_MASTER, 0);
+}
+
+/* Configuration Space Access Read Routines */
+extern int pci_cfg_r8(pci_dev_t dev, int ofs, uint8_t *data);
+extern int pci_cfg_r16(pci_dev_t dev, int ofs, uint16_t *data);
+extern int pci_cfg_r32(pci_dev_t dev, int ofs, uint32_t *data);
+
+/* Configuration Space Access Write Routines */
+extern int pci_cfg_w8(pci_dev_t dev, int ofs, uint8_t data);
+extern int pci_cfg_w16(pci_dev_t dev, int ofs, uint16_t data);
+extern int pci_cfg_w32(pci_dev_t dev, int ofs, uint32_t data);
+
+/* Read a register over PCI I/O Space */
+extern uint8_t pci_io_r8(uint32_t adr);
+extern uint16_t pci_io_r16(uint32_t adr);
+extern uint32_t pci_io_r32(uint32_t adr);
+
+/* Write a register over PCI I/O Space */
+extern void pci_io_w8(uint32_t adr, uint8_t data);
+extern void pci_io_w16(uint32_t adr, uint16_t data);
+extern void pci_io_w32(uint32_t adr, uint32_t data);
+
+/* Translate PCI address into CPU accessible address */
+static inline int pci_pci2cpu(uint32_t *address, int type)
+{
+	return pci_access_ops.translate(address, type, 0);
+}
+
+/* Translate CPU accessible address into PCI address (for DMA) */
+static inline int pci_cpu2pci(uint32_t *address, int type)
+{
+	return pci_access_ops.translate(address, type, 1);
+}
+
+/*** Read/Write a register over PCI Memory Space ***/
+
+static inline uint8_t pci_ld8(volatile uint8_t *addr)
+{
+	return *addr;
+}
+
+static inline void pci_st8(volatile uint8_t *addr, uint8_t val)
+{
+	*addr = val;
+}
+
+#ifdef BSP_PCI_BIG_ENDIAN
+
+/* BSP has decided Big Endian PCI Bus (non-standard) */
+
+static inline uint16_t pci_ld_le16(volatile uint16_t *addr)
+{
+	return ld_be16(addr);
+}
+
+static inline void pci_st_le16(volatile uint16_t *addr, uint16_t val)
+{
+	st_be16(addr, val);
+}
+
+static inline uint32_t pci_ld_le32(volatile uint32_t *addr)
+{
+	return ld_be32(addr);
+}
+
+static inline void pci_st_le32(volatile uint32_t *addr, uint32_t val)
+{
+	st_be32(addr, val);
+}
+
+static inline uint16_t pci_ld_be16(volatile uint16_t *addr)
+{
+	return ld_le16(addr);
+}
+
+static inline void pci_st_be16(volatile uint16_t *addr, uint16_t val)
+{
+	st_le16(addr, val);
+}
+
+static inline uint32_t pci_ld_be32(volatile uint32_t *addr)
+{
+	return ld_le32(addr);
+}
+
+static inline void pci_st_be32(volatile uint32_t *addr, uint32_t val)
+{
+	st_le32(addr, val);
+}
+
+#else
+
+/* Little Endian PCI Bus */
+
+static inline uint16_t pci_ld_le16(volatile uint16_t *addr)
+{
+	return ld_le16(addr);
+}
+
+static inline void pci_st_le16(volatile uint16_t *addr, uint16_t val)
+{
+	st_le16(addr, val);
+}
+
+static inline uint32_t pci_ld_le32(volatile uint32_t *addr)
+{
+	return ld_le32(addr);
+}
+
+static inline void pci_st_le32(volatile uint32_t *addr, uint32_t val)
+{
+	st_le32(addr, val);
+}
+
+static inline uint16_t pci_ld_be16(volatile uint16_t *addr)
+{
+	return ld_be16(addr);
+}
+
+static inline void pci_st_be16(volatile uint16_t *addr, uint16_t val)
+{
+	st_be16(addr, val);
+}
+
+static inline uint32_t pci_ld_be32(volatile uint32_t *addr)
+{
+	return ld_be32(addr);
+}
+
+static inline void pci_st_be32(volatile uint32_t *addr, uint32_t val)
+{
+	st_be32(addr, val);
+}
+
+#endif
+
+/* Registers-over-Memory Space access routines. The routines are not inlined
+ * so it is possible during run-time to select which function implemention
+ * to use. The use of these functions are not recommended since it will have a
+ * performance penalty.
+ *
+ * 8-bit accesses are the same for Little and Big endian PCI buses.
+ */
+uint8_t pci_mem_ld8(uint8_t *adr);
+void pci_mem_st8(uint8_t *adr, uint8_t data);
+/* Registers-over-Memory Space - Generic Big endian PCI bus definitions */
+uint16_t pci_mem_be_ld_le16(uint16_t *adr);
+uint16_t pci_mem_be_ld_be16(uint16_t *adr);
+uint32_t pci_mem_be_ld_le32(uint32_t *adr);
+uint32_t pci_mem_be_ld_be32(uint32_t *adr);
+void pci_mem_be_st_le16(uint16_t *adr, uint16_t data);
+void pci_mem_be_st_be16(uint16_t *adr, uint16_t data);
+void pci_mem_be_st_le32(uint32_t *adr, uint32_t data);
+void pci_mem_be_st_be32(uint32_t *adr, uint32_t data);
+/* Registers-over-Memory Space - Generic Little endian PCI bus definitions */
+uint16_t pci_mem_le_ld_le16(uint16_t *adr);
+uint16_t pci_mem_le_ld_be16(uint16_t *adr);
+uint32_t pci_mem_le_ld_le32(uint32_t *adr);
+uint32_t pci_mem_le_ld_be32(uint32_t *adr);
+void pci_mem_le_st_le16(uint16_t *adr, uint16_t data);
+void pci_mem_le_st_be16(uint16_t *adr, uint16_t data);
+void pci_mem_le_st_le32(uint32_t *adr, uint32_t data);
+void pci_mem_le_st_be32(uint32_t *adr, uint32_t data);
+
+/* Get Read/Write function for accessing a register over PCI Memory Space
+ * (non-inline functions).
+ *
+ * Arguments
+ *  wr             0(Read), 1(Write)
+ *  size           1(Byte), 2(Word), 4(Double Word)
+ *  func           Where function pointer will be stored
+ *  endian         PCI_LITTLE_ENDIAN or PCI_BIG_ENDIAN
+ *  type           1(I/O), 3(REG over MEM), 4(CFG)
+ *
+ * Return
+ *  0              Found function
+ *  others         No such function defined by host driver or BSP
+ */
+extern int pci_access_func(int wr, int size, void **func, int endian, int type);
+
+/* Predefined functions for Host drivers or BSPs that define the 
+ * register-over-memory space functions operations.
+ */
+extern struct pci_memreg_ops pci_mem_le_ops; /* For Little-Endian PCI bus */
+extern struct pci_memreg_ops pci_mem_be_ops; /* For Big-Endian PCI bus */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* !__PCI_ACCESS_H__ */
diff --git a/cpukit/libpci/pci/cfg.h b/cpukit/libpci/pci/cfg.h
new file mode 100644
index 0000000..18c48db
--- /dev/null
+++ b/cpukit/libpci/pci/cfg.h
@@ -0,0 +1,244 @@
+/* PCI Configuration Library, two versions of the library exists:
+ *  - auto configuration (default)
+ *  - static configuration (user defined config)
+ * both versions are defined here.
+ *
+ * COPYRIGHT (c) 2010.
+ * Cobham Gaisler AB.
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ */
+
+
+#ifndef __PCI_CFG_H__
+#define __PCI_CFG_H__
+
+#include <pci.h>
+
+/* PCI Configuration library */
+
+/* Return the number of PCI buses in system */
+extern int pci_bus_count(void);
+
+/* PCI Address assigned to BARs which failed to fit into the PCI Window or
+ * is disabled by any other cause.
+ */
+extern uint32_t pci_invalid_address;
+
+/* PCI Configuration Library of the system */
+enum {
+	PCI_CONFIG_LIB_NONE = 0,
+	PCI_CONFIG_LIB_AUTO = 1,
+	PCI_CONFIG_LIB_STATIC = 2,
+	PCI_CONFIG_LIB_READ = 3,
+	PCI_CONFIG_LIB_PERIPHERAL = 4,
+};
+extern const int pci_config_lib_type;
+
+/* Configuration library function pointers, these are set in <rtems/confdefs.h>
+ * by project configuration or by the BSP. The configuration will pull in the
+ * PCI Library needed and the PCI initialization functions will call these
+ * functions on initialization from the host driver.
+ */
+extern int (*pci_config_lib_init)(void);
+extern void (*pci_config_lib_register)(void *config);
+
+/* Configure PCI devices and bridges, and setup the RAM data structures
+ * describing the PCI devices currently present in the system.
+ *
+ * Returns 0 on success, -1 on failure.
+ */
+extern int pci_config_init(void);
+
+/* Register a config-library specific configuration used by the libarary in
+ * pci_config_init().
+ */
+extern void pci_config_register(void *config);
+
+/* Print current PCI configuration (C-code) to terminal, can be used in
+ * static and peripheral PCI configuration library. The configuration is
+ * taken from the current configuration library setup.
+ */
+extern void pci_cfg_print(void);
+
+struct pci_bus; /* Bridge Device and secondary bus information */
+struct pci_dev; /* Device/function */
+struct pci_res; /* Resource: BAR, ROM or Bridge Window */
+
+/* The Host Bridge and all subdevices (the PCI RAM data structure) */
+extern struct pci_bus pci_hb;
+
+/* Iterate over all PCI devices on a bus (see search options) and call func(),
+ * iteration is stopped if a non-zero value is returned by func().
+ *
+ * The function iterates over the PCI RAM data structure, it is not
+ * available until after all devices have been found and pci_hb is populated,
+ * typically after pci_config_init() is called.
+ *
+ * search options: 0 (no child buses), 1 (depth first, recursive)
+ *
+ * Return Values
+ *  0  All PCI devices were processed, func() returned 0 on every call
+ *  X  func() returned non-zero X value, the search was stopped
+ */
+#define SEARCH_DEPTH 1
+extern int pci_for_each_child(
+	struct pci_bus *bus,
+	int (*func)(struct pci_dev *, void *arg),
+	void *arg,
+	int search);
+
+/* Depth first search of all PCI devices in PCI RAM data structure and call
+ * func(dev, arg), iteration is stopped if a non-zero value is returned by
+ * func().
+ *
+ * The function iterates over the PCI RAM data structure, it is not
+ * available until after all devices have been found and pci_hb is populated,
+ * typically after pci_config_init() is called.
+ *
+ * Return Values
+ *  0  All PCI devices were processed, func() returned 0 on every call
+ *  X  func() returned non-zero X value, the search was stopped
+ */
+extern int pci_for_each_dev(
+	int (*func)(struct pci_dev *, void *arg),
+	void *arg);
+
+/* Get PCI device from RAM device tree for a device matching PCI Vendor, Device
+ * and instance number 'index'.
+ *
+ * Return Values
+ * -1  pci_find_dev did not find a device matching the criterion.
+ *  0  device was found, *ppdev was updated with the PCI device address
+ */
+extern int pci_find_dev(uint16_t ven, uint16_t dev, int index,
+			struct pci_dev **ppdev);
+
+/* Get PCI device from RAM device tree by BUS|SLOT|FUNC.
+ *
+ * Return Values
+ * -1  pci_get_dev did not find a device matching the criterion
+ *  0  device was found, *ppdev was updated with the PCI device address
+ */
+extern int pci_get_dev(pci_dev_t pcidev, struct pci_dev **ppdev);
+
+/* Resource flags */
+#define PCI_RES_IO 1
+#define PCI_RES_MEMIO 2
+#define PCI_RES_MEM_PREFETCH 1
+#define PCI_RES_MEM (PCI_RES_MEMIO | PCI_RES_MEM_PREFETCH)
+#define PCI_RES_TYPE_MASK 0x3
+#define PCI_RES_IO32 0x08
+#define PCI_RES_FAIL 0x10 /* Alloc Failed */
+
+/* BAR Resouces entry */
+struct pci_res {
+	struct pci_res	*next;
+	uint32_t	size;
+	uint32_t	boundary;
+	unsigned char	flags; /* I/O, MEM or MEMIO */
+	unsigned char	bar;
+
+	/* Assigned Resource (PCI address), zero if not assigned */
+	uint32_t	start;
+	uint32_t	end;
+};
+
+/* Get Device from resource pointer */
+#define RES2DEV(res) ((struct pci_dev *) \
+			((void *)res - (res->bar * (sizeof(struct pci_res)))))
+
+/* Device flags */
+#define PCI_DEV_BRIDGE    0x01  /* Device is a Bridge (struct pci_bus) */
+#define PCI_DEV_RES_FAIL  0x02  /* Resource alloction for device BARs failed */
+
+/* Bus Flags */
+#define PCI_BUS_IO        0x01	/* 16-bit I/O address decoding */
+#define PCI_BUS_MEMIO     0x02  /* Bus support non-prefetchable mem (always) */
+#define PCI_BUS_MEM       0x04  /* Bus support prefetchable memory space */
+#define PCI_BUS_IO32      0x08	/* 32-bit I/O address decoding */
+
+#define BRIDGE_RES_COUNT 2 /* Number of BAR resources a bridge can have */
+#define BUS_RES_START BRIDGE_RES_COUNT
+
+/* Bus Resources Array */
+enum {
+	BUS_RES_IO = 0,
+	BUS_RES_MEMIO = 1,
+	BUS_RES_MEM = 2,
+};
+
+/* Device Resource array index meaning */
+enum {
+	/* A Device has up to 6 BARs and an optional ROM BAR */
+	DEV_RES_BAR1 = 0,
+	DEV_RES_BAR2 = 1,
+	DEV_RES_BAR3 = 2,
+	DEV_RES_BAR4 = 3,
+	DEV_RES_BAR5 = 4,
+	DEV_RES_BAR6 = 5,
+	DEV_RES_ROM  = 6,
+
+	/* Bridges have 2 BARs (BAR1 and BAR2) and 3 Windows to secondary bus
+	 * and an optional ROM BAR
+	 */
+	BRIDGE_RES_BAR1 = 0,
+	BRIDGE_RES_BAR2 = 1,
+	BRIDGE_RES_IO = 2,
+	BRIDGE_RES_MEMIO = 3,
+	BRIDGE_RES_MEM = 4,
+	BRIDGE_RES_UNUSED1 = 5,
+	BRIDGE_RES_ROM = 6,
+};
+
+/* Maximum Number of Resources of a device */
+#define DEV_RES_CNT (DEV_RES_ROM + 1)
+
+/* PCI Device (Bus|Slot|Function) description */
+struct pci_dev {
+	struct pci_res	resources[DEV_RES_CNT]; /* must be topmost field */
+	struct pci_dev	*next;
+	struct pci_bus	*bus;
+	pci_dev_t	busdevfun;
+	uint8_t		flags;
+	uint8_t		sysirq;
+	uint16_t	vendor;
+	uint16_t	device;
+	uint16_t	subvendor;
+	uint16_t	subdevice;
+	uint32_t	classrev;
+
+	/* static configuration settings */
+	uint16_t	command;
+};
+
+/* PCI Bus description */
+struct pci_bus {
+	struct pci_dev	dev; /* PCI Bridge */
+	struct pci_dev	*devs; /* Devices on child (secondary) Bus */
+	unsigned int	flags;
+
+	/* Bridge Information */
+	int num;	/* Bus number (0=Root-PCI-bus) */
+	int pri;	/* Primary Bus Number */
+	int sord;	/* Subordinate Buses (Child bus count) */
+
+#if defined(PCI_CFG_AUTO_LIB)
+	/* Resources of devices on bus. USED INTERNALLY IN AUTO-CFG LIBRARY.
+	 *
+	 * BUS_RES_IO    = 0:  I/O resources
+	 * BUS_RES_MEMIO = 1:  Prefetchable memory resources
+	 * BUS_RES_MEM   = 2:  Non-Prefetchable memory resources
+	 */
+	struct pci_res	*busres[3];
+#endif
+};
+
+#include <pci/cfg_auto.h>
+#include <pci/cfg_static.h>
+#include <pci/cfg_read.h>
+#include <pci/cfg_peripheral.h>
+
+#endif
diff --git a/cpukit/libpci/pci/cfg_auto.h b/cpukit/libpci/pci/cfg_auto.h
new file mode 100644
index 0000000..25e7336
--- /dev/null
+++ b/cpukit/libpci/pci/cfg_auto.h
@@ -0,0 +1,59 @@
+/* PCI Auto Configuration Library
+ *
+ * COPYRIGHT (c) 2010.
+ * Cobham Gaisler AB.
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ */
+
+#ifndef __PCI_CFG_AUTO_H__
+#define __PCI_CFG_AUTO_H__
+
+#define CFGOPT_NOSETUP_IRQ 0x1 /* Skip IRQ setup */
+
+/* PCI Memory Layout setup, used by the auto-config library in order to
+ * determine the addresses of PCI BARs and Buses.
+ *
+ * All addresses are in PCI address space, the actual address the CPU access
+ * may be different, and taken care of elsewhere.
+ */
+struct pci_auto_setup {
+	int options;
+
+	/* PCI prefetchable Memory space (OPTIONAL) */
+	uint32_t mem_start;
+	uint32_t mem_size; /* 0 = Use MEMIO space for prefetchable mem BARs */
+
+	/* PCI non-prefetchable Memory */
+	uint32_t memio_start;
+	uint32_t memio_size;
+
+	/* PCI I/O space (OPTIONAL) */
+	uint32_t io_start;
+	uint32_t io_size; /* 0 = No I/O space */
+
+	/* Get System IRQ connected to a PCI line of a PCI device on bus0.
+	 * The return IRQ value zero equals no IRQ (IRQ disabled).
+	 */
+	uint8_t (*irq_map)(pci_dev_t dev, int irq_pin);
+
+	/* IRQ Bridge routing. Returns the interrupt pin (0..3 = A..D) that
+	 * a device is connected to on parent bus.
+	 */
+	int (*irq_route)(pci_dev_t dev, int irq_pin);
+};
+
+/* Do PCI initialization: Enumrate buses, scan buses for devices, assign
+ * I/O MEM and MEMIO resources, assign IRQ and so on.
+ */
+extern int pci_config_auto(void);
+
+/* Register a configuration for the auto library (struct pci_auto_setup *) */
+extern void pci_config_auto_register(void *config);
+
+/* PCI memory map */
+extern struct pci_auto_setup pci_auto_cfg;
+
+#endif
diff --git a/cpukit/libpci/pci/cfg_peripheral.h b/cpukit/libpci/pci/cfg_peripheral.h
new file mode 100644
index 0000000..68f2e24
--- /dev/null
+++ b/cpukit/libpci/pci/cfg_peripheral.h
@@ -0,0 +1,20 @@
+/* PCI Peripheral Configuration Library
+ *
+ * COPYRIGHT (c) 2010.
+ * Cobham Gaisler AB.
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ */
+
+#ifndef __PCI_CFG_PERIPHERAL_H__
+#define __PCI_CFG_PERIPHERAL_H__
+
+/* The user must provide a PCI configuration using the "struct pci_bus pci_hb"
+ * structure. Nothing else than setting pci_system_type and pci_bus_cnt is done
+ * by the peripheral library.
+ */
+extern int pci_config_peripheral(void);
+
+#endif
diff --git a/cpukit/libpci/pci/cfg_read.h b/cpukit/libpci/pci/cfg_read.h
new file mode 100644
index 0000000..af60a4e
--- /dev/null
+++ b/cpukit/libpci/pci/cfg_read.h
@@ -0,0 +1,22 @@
+/* PCI Read Configuration Library. Read current config that bootloader/BIOS
+ * has setup.
+ *
+ * COPYRIGHT (c) 2010.
+ * Cobham Gaisler AB.
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ */
+
+
+#ifndef __PCI_CFG_READ_H__
+#define __PCI_CFG_READ_H__
+
+/* Build PCI device tree in "struct pci_bus pci_hb" according to current setup
+ * in hardware. Devices/buses are created by reading the resource assignments
+ * that the BIOS/bootloader has already setup for us.
+ */
+extern int pci_config_read(void);
+
+#endif
diff --git a/cpukit/libpci/pci/cfg_static.h b/cpukit/libpci/pci/cfg_static.h
new file mode 100644
index 0000000..5633dfc
--- /dev/null
+++ b/cpukit/libpci/pci/cfg_static.h
@@ -0,0 +1,22 @@
+/* Static PCI Auto Configuration Library
+ *
+ * COPYRIGHT (c) 2010.
+ * Cobham Gaisler AB.
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ */
+
+#ifndef __PCI_CFG_STATIC_H__
+#define __PCI_CFG_STATIC_H__
+
+/* This function initializes all buses and device accorind to a user defined
+ * "static" configuration. The configuration can manually created with C
+ * data structures. Or it can be automatically created on a running target
+ * using the pci_cfg_print() routine after the AUTO or READ Configuration
+ * Library has setup the PCI bus
+ */
+extern int pci_config_static(void);
+
+#endif
diff --git a/cpukit/libpci/pci/ids.h b/cpukit/libpci/pci/ids.h
new file mode 100644
index 0000000..2d2592b
--- /dev/null
+++ b/cpukit/libpci/pci/ids.h
@@ -0,0 +1,802 @@
+/* PCI Identifiers - auto generated */
+#ifndef __PCI_IDS_H__
+#define __PCI_IDS_H__
+
+/* Include non-public PCI ids (not auto generated) */
+#include <pci/ids_extra.h>
+
+/* Not a valid ID, used to match any device ID */
+#define PCI_ID_ANY 0xffff
+
+/*
+ * Vendor and card ID's: sort these numerically according to vendor
+ * (and according to card ID within vendor). Send all updates to
+ * <linux-pcisupport at cck.uni-kl.de>.
+ */
+#define PCI_VENDOR_ID_COMPAQ		0x0e11
+#define PCI_DEVICE_ID_COMPAQ_1280	0x3033
+#define PCI_DEVICE_ID_COMPAQ_TRIFLEX	0x4000
+#define PCI_DEVICE_ID_COMPAQ_SMART2P	0xae10
+#define PCI_DEVICE_ID_COMPAQ_NETEL100	0xae32
+#define PCI_DEVICE_ID_COMPAQ_NETEL10	0xae34
+#define PCI_DEVICE_ID_COMPAQ_NETFLEX3I	0xae35
+#define PCI_DEVICE_ID_COMPAQ_NETEL100D	0xae40
+#define PCI_DEVICE_ID_COMPAQ_NETEL100PI	0xae43
+#define PCI_DEVICE_ID_COMPAQ_NETEL100I	0xb011
+#define PCI_DEVICE_ID_COMPAQ_THUNDER	0xf130
+#define PCI_DEVICE_ID_COMPAQ_NETFLEX3B	0xf150
+
+#define PCI_VENDOR_ID_NCR		0x1000
+#define PCI_DEVICE_ID_NCR_53C810	0x0001
+#define PCI_DEVICE_ID_NCR_53C820	0x0002
+#define PCI_DEVICE_ID_NCR_53C825	0x0003
+#define PCI_DEVICE_ID_NCR_53C815	0x0004
+#define PCI_DEVICE_ID_NCR_53C860	0x0006
+#define PCI_DEVICE_ID_NCR_53C896	0x000b
+#define PCI_DEVICE_ID_NCR_53C895	0x000c
+#define PCI_DEVICE_ID_NCR_53C885	0x000d
+#define PCI_DEVICE_ID_NCR_53C875	0x000f
+#define PCI_DEVICE_ID_NCR_53C875J	0x008f
+
+#define PCI_VENDOR_ID_ATI		0x1002
+#define PCI_DEVICE_ID_ATI_68800		0x4158
+#define PCI_DEVICE_ID_ATI_215CT222	0x4354
+#define PCI_DEVICE_ID_ATI_210888CX	0x4358
+#define PCI_DEVICE_ID_ATI_215GB		0x4742
+#define PCI_DEVICE_ID_ATI_215GD		0x4744
+#define PCI_DEVICE_ID_ATI_215GI		0x4749
+#define PCI_DEVICE_ID_ATI_215GP		0x4750
+#define PCI_DEVICE_ID_ATI_215GQ		0x4751
+#define PCI_DEVICE_ID_ATI_215GT		0x4754
+#define PCI_DEVICE_ID_ATI_215GTB	0x4755
+#define PCI_DEVICE_ID_ATI_210888GX	0x4758
+#define PCI_DEVICE_ID_ATI_215LG		0x4c47
+#define PCI_DEVICE_ID_ATI_264LT		0x4c54
+#define PCI_DEVICE_ID_ATI_264VT		0x5654
+
+#define PCI_VENDOR_ID_VLSI		0x1004
+#define PCI_DEVICE_ID_VLSI_82C592	0x0005
+#define PCI_DEVICE_ID_VLSI_82C593	0x0006
+#define PCI_DEVICE_ID_VLSI_82C594	0x0007
+#define PCI_DEVICE_ID_VLSI_82C597	0x0009
+#define PCI_DEVICE_ID_VLSI_82C541	0x000c
+#define PCI_DEVICE_ID_VLSI_82C543	0x000d
+#define PCI_DEVICE_ID_VLSI_82C532	0x0101
+#define PCI_DEVICE_ID_VLSI_82C534	0x0102
+#define PCI_DEVICE_ID_VLSI_82C535	0x0104
+#define PCI_DEVICE_ID_VLSI_82C147	0x0105
+#define PCI_DEVICE_ID_VLSI_VAS96011	0x0702
+
+#define PCI_VENDOR_ID_ADL		0x1005
+#define PCI_DEVICE_ID_ADL_2301		0x2301
+
+#define PCI_VENDOR_ID_NS		0x100b
+#define PCI_DEVICE_ID_NS_87415		0x0002
+#define PCI_DEVICE_ID_NS_87410		0xd001
+
+#define PCI_VENDOR_ID_TSENG		0x100c
+#define PCI_DEVICE_ID_TSENG_W32P_2	0x3202
+#define PCI_DEVICE_ID_TSENG_W32P_b	0x3205
+#define PCI_DEVICE_ID_TSENG_W32P_c	0x3206
+#define PCI_DEVICE_ID_TSENG_W32P_d	0x3207
+#define PCI_DEVICE_ID_TSENG_ET6000	0x3208
+
+#define PCI_VENDOR_ID_WEITEK		0x100e
+#define PCI_DEVICE_ID_WEITEK_P9000	0x9001
+#define PCI_DEVICE_ID_WEITEK_P9100	0x9100
+
+#define PCI_VENDOR_ID_DEC		0x1011
+#define PCI_DEVICE_ID_DEC_BRD		0x0001
+#define PCI_DEVICE_ID_DEC_TULIP		0x0002
+#define PCI_DEVICE_ID_DEC_TGA		0x0004
+#define PCI_DEVICE_ID_DEC_TULIP_FAST	0x0009
+#define PCI_DEVICE_ID_DEC_TGA2		0x000D
+#define PCI_DEVICE_ID_DEC_FDDI		0x000F
+#define PCI_DEVICE_ID_DEC_TULIP_PLUS	0x0014
+#define PCI_DEVICE_ID_DEC_21142		0x0019
+#define PCI_DEVICE_ID_DEC_21052		0x0021
+#define PCI_DEVICE_ID_DEC_21150		0x0022
+#define PCI_DEVICE_ID_DEC_21152		0x0024
+
+#define PCI_VENDOR_ID_CIRRUS		0x1013
+#define PCI_DEVICE_ID_CIRRUS_7548	0x0038
+#define PCI_DEVICE_ID_CIRRUS_5430	0x00a0
+#define PCI_DEVICE_ID_CIRRUS_5434_4	0x00a4
+#define PCI_DEVICE_ID_CIRRUS_5434_8	0x00a8
+#define PCI_DEVICE_ID_CIRRUS_5436	0x00ac
+#define PCI_DEVICE_ID_CIRRUS_5446	0x00b8
+#define PCI_DEVICE_ID_CIRRUS_5480	0x00bc
+#define PCI_DEVICE_ID_CIRRUS_5464	0x00d4
+#define PCI_DEVICE_ID_CIRRUS_5465	0x00d6
+#define PCI_DEVICE_ID_CIRRUS_6729	0x1100
+#define PCI_DEVICE_ID_CIRRUS_6832	0x1110
+#define PCI_DEVICE_ID_CIRRUS_7542	0x1200
+#define PCI_DEVICE_ID_CIRRUS_7543	0x1202
+#define PCI_DEVICE_ID_CIRRUS_7541	0x1204
+
+#define PCI_VENDOR_ID_IBM		0x1014
+#define PCI_DEVICE_ID_IBM_FIRE_CORAL	0x000a
+#define PCI_DEVICE_ID_IBM_TR		0x0018
+#define PCI_DEVICE_ID_IBM_82G2675	0x001d
+#define PCI_DEVICE_ID_IBM_MCA		0x0020
+#define PCI_DEVICE_ID_IBM_82351		0x0022
+#define PCI_DEVICE_ID_IBM_SERVERAID	0x002e
+#define PCI_DEVICE_ID_IBM_TR_WAKE	0x003e
+#define PCI_DEVICE_ID_IBM_MPIC		0x0046
+#define PCI_DEVICE_ID_IBM_3780IDSP	0x007d
+#define PCI_DEVICE_ID_IBM_MPIC_2	0xffff
+
+#define PCI_VENDOR_ID_WD		0x101c
+#define PCI_DEVICE_ID_WD_7197		0x3296
+
+#define PCI_VENDOR_ID_AMD		0x1022
+#define PCI_DEVICE_ID_AMD_LANCE		0x2000
+#define PCI_DEVICE_ID_AMD_SCSI		0x2020
+
+#define PCI_VENDOR_ID_TRIDENT		0x1023
+#define PCI_DEVICE_ID_TRIDENT_9397	0x9397
+#define PCI_DEVICE_ID_TRIDENT_9420	0x9420
+#define PCI_DEVICE_ID_TRIDENT_9440	0x9440
+#define PCI_DEVICE_ID_TRIDENT_9660	0x9660
+#define PCI_DEVICE_ID_TRIDENT_9750	0x9750
+
+#define PCI_VENDOR_ID_AI		0x1025
+#define PCI_DEVICE_ID_AI_M1435		0x1435
+
+#define PCI_VENDOR_ID_MATROX		0x102B
+#define PCI_DEVICE_ID_MATROX_MGA_2	0x0518
+#define PCI_DEVICE_ID_MATROX_MIL	0x0519
+#define PCI_DEVICE_ID_MATROX_MYS	0x051A
+#define PCI_DEVICE_ID_MATROX_MIL_2	0x051b
+#define PCI_DEVICE_ID_MATROX_MIL_2_AGP	0x051f
+#define PCI_DEVICE_ID_MATROX_MGA_IMP	0x0d10
+
+#define PCI_VENDOR_ID_CT		0x102c
+#define PCI_DEVICE_ID_CT_65545		0x00d8
+#define PCI_DEVICE_ID_CT_65548		0x00dc
+#define PCI_DEVICE_ID_CT_65550		0x00e0
+#define PCI_DEVICE_ID_CT_65554		0x00e4
+#define PCI_DEVICE_ID_CT_65555		0x00e5
+
+#define PCI_VENDOR_ID_MIRO		0x1031
+#define PCI_DEVICE_ID_MIRO_36050	0x5601
+
+#define PCI_VENDOR_ID_NEC		0x1033
+#define PCI_DEVICE_ID_NEC_PCX2		0x0046
+
+#define PCI_VENDOR_ID_FD		0x1036
+#define PCI_DEVICE_ID_FD_36C70		0x0000
+
+#define PCI_VENDOR_ID_SI		0x1039
+#define PCI_DEVICE_ID_SI_5591_AGP	0x0001
+#define PCI_DEVICE_ID_SI_6202		0x0002
+#define PCI_DEVICE_ID_SI_503		0x0008
+#define PCI_DEVICE_ID_SI_ACPI		0x0009
+#define PCI_DEVICE_ID_SI_5597_VGA	0x0200
+#define PCI_DEVICE_ID_SI_6205		0x0205
+#define PCI_DEVICE_ID_SI_501		0x0406
+#define PCI_DEVICE_ID_SI_496		0x0496
+#define PCI_DEVICE_ID_SI_601		0x0601
+#define PCI_DEVICE_ID_SI_5107		0x5107
+#define PCI_DEVICE_ID_SI_5511		0x5511
+#define PCI_DEVICE_ID_SI_5513		0x5513
+#define PCI_DEVICE_ID_SI_5571		0x5571
+#define PCI_DEVICE_ID_SI_5591		0x5591
+#define PCI_DEVICE_ID_SI_5597		0x5597
+#define PCI_DEVICE_ID_SI_7001		0x7001
+
+#define PCI_VENDOR_ID_HP		0x103c
+#define PCI_DEVICE_ID_HP_J2585A		0x1030
+#define PCI_DEVICE_ID_HP_J2585B		0x1031
+
+#define PCI_VENDOR_ID_PCTECH		0x1042
+#define PCI_DEVICE_ID_PCTECH_RZ1000	0x1000
+#define PCI_DEVICE_ID_PCTECH_RZ1001	0x1001
+#define PCI_DEVICE_ID_PCTECH_SAMURAI_0	0x3000
+#define PCI_DEVICE_ID_PCTECH_SAMURAI_1	0x3010
+#define PCI_DEVICE_ID_PCTECH_SAMURAI_IDE 0x3020
+
+#define PCI_VENDOR_ID_DPT               0x1044
+#define PCI_DEVICE_ID_DPT               0xa400
+
+#define PCI_VENDOR_ID_OPTI		0x1045
+#define PCI_DEVICE_ID_OPTI_92C178	0xc178
+#define PCI_DEVICE_ID_OPTI_82C557	0xc557
+#define PCI_DEVICE_ID_OPTI_82C558	0xc558
+#define PCI_DEVICE_ID_OPTI_82C621	0xc621
+#define PCI_DEVICE_ID_OPTI_82C700	0xc700
+#define PCI_DEVICE_ID_OPTI_82C701	0xc701
+#define PCI_DEVICE_ID_OPTI_82C814	0xc814
+#define PCI_DEVICE_ID_OPTI_82C822	0xc822
+#define PCI_DEVICE_ID_OPTI_82C825	0xd568
+
+#define PCI_VENDOR_ID_SGS		0x104a
+#define PCI_DEVICE_ID_SGS_2000		0x0008
+#define PCI_DEVICE_ID_SGS_1764		0x0009
+
+#define PCI_VENDOR_ID_BUSLOGIC		      0x104B
+#define PCI_DEVICE_ID_BUSLOGIC_MULTIMASTER_NC 0x0140
+#define PCI_DEVICE_ID_BUSLOGIC_MULTIMASTER    0x1040
+#define PCI_DEVICE_ID_BUSLOGIC_FLASHPOINT     0x8130
+
+#define PCI_VENDOR_ID_TI		0x104c
+#define PCI_DEVICE_ID_TI_TVP4010	0x3d04
+#define PCI_DEVICE_ID_TI_TVP4020	0x3d07
+#define PCI_DEVICE_ID_TI_PCI1130	0xac12
+#define PCI_DEVICE_ID_TI_PCI1031	0xac13
+#define PCI_DEVICE_ID_TI_PCI1131	0xac15
+#define PCI_DEVICE_ID_TI_PCI1250	0xac16
+#define PCI_DEVICE_ID_TI_PCI1220	0xac17
+
+#define PCI_VENDOR_ID_OAK		0x104e
+#define PCI_DEVICE_ID_OAK_OTI107	0x0107
+
+/* Winbond have two vendor IDs! See 0x10ad as well */
+#define PCI_VENDOR_ID_WINBOND2		0x1050
+#define PCI_DEVICE_ID_WINBOND2_89C940	0x0940
+
+#define PCI_VENDOR_ID_MOTOROLA		0x1057
+#define PCI_DEVICE_ID_MOTOROLA_MPC105	0x0001
+#define PCI_DEVICE_ID_MOTOROLA_MPC106	0x0002
+#define PCI_DEVICE_ID_MOTOROLA_RAVEN	0x4801
+
+#define PCI_VENDOR_ID_PROMISE		0x105a
+#define PCI_DEVICE_ID_PROMISE_20246	0x4d33
+#define PCI_DEVICE_ID_PROMISE_5300	0x5300
+
+#define PCI_VENDOR_ID_N9		0x105d
+#define PCI_DEVICE_ID_N9_I128		0x2309
+#define PCI_DEVICE_ID_N9_I128_2		0x2339
+#define PCI_DEVICE_ID_N9_I128_T2R	0x493d
+
+#define PCI_VENDOR_ID_UMC		0x1060
+#define PCI_DEVICE_ID_UMC_UM8673F	0x0101
+#define PCI_DEVICE_ID_UMC_UM8891A	0x0891
+#define PCI_DEVICE_ID_UMC_UM8886BF	0x673a
+#define PCI_DEVICE_ID_UMC_UM8886A	0x886a
+#define PCI_DEVICE_ID_UMC_UM8881F	0x8881
+#define PCI_DEVICE_ID_UMC_UM8886F	0x8886
+#define PCI_DEVICE_ID_UMC_UM9017F	0x9017
+#define PCI_DEVICE_ID_UMC_UM8886N	0xe886
+#define PCI_DEVICE_ID_UMC_UM8891N	0xe891
+
+#define PCI_VENDOR_ID_X			0x1061
+#define PCI_DEVICE_ID_X_AGX016		0x0001
+
+#define PCI_VENDOR_ID_PICOP		0x1066
+#define PCI_DEVICE_ID_PICOP_PT86C52X	0x0001
+#define PCI_DEVICE_ID_PICOP_PT80C524	0x8002
+
+#define PCI_VENDOR_ID_APPLE		0x106b
+#define PCI_DEVICE_ID_APPLE_BANDIT	0x0001
+#define PCI_DEVICE_ID_APPLE_GC		0x0002
+#define PCI_DEVICE_ID_APPLE_HYDRA	0x000e
+
+#define PCI_VENDOR_ID_NEXGEN		0x1074
+#define PCI_DEVICE_ID_NEXGEN_82C501	0x4e78
+
+#define PCI_VENDOR_ID_QLOGIC		0x1077
+#define PCI_DEVICE_ID_QLOGIC_ISP1020	0x1020
+#define PCI_DEVICE_ID_QLOGIC_ISP1022	0x1022
+
+#define PCI_VENDOR_ID_CYRIX		0x1078
+#define PCI_DEVICE_ID_CYRIX_5510	0x0000
+#define PCI_DEVICE_ID_CYRIX_PCI_MASTER	0x0001
+#define PCI_DEVICE_ID_CYRIX_5520	0x0002
+#define PCI_DEVICE_ID_CYRIX_5530_LEGACY	0x0100
+#define PCI_DEVICE_ID_CYRIX_5530_SMI	0x0101
+#define PCI_DEVICE_ID_CYRIX_5530_IDE	0x0102
+#define PCI_DEVICE_ID_CYRIX_5530_AUDIO	0x0103
+#define PCI_DEVICE_ID_CYRIX_5530_VIDEO	0x0104
+
+#define PCI_VENDOR_ID_LEADTEK		0x107d
+#define PCI_DEVICE_ID_LEADTEK_805	0x0000
+
+#define PCI_VENDOR_ID_CONTAQ		0x1080
+#define PCI_DEVICE_ID_CONTAQ_82C599	0x0600
+#define PCI_DEVICE_ID_CONTAQ_82C693	0xc693
+
+#define PCI_VENDOR_ID_FOREX		0x1083
+
+#define PCI_VENDOR_ID_OLICOM		0x108d
+#define PCI_DEVICE_ID_OLICOM_OC3136	0x0001
+#define PCI_DEVICE_ID_OLICOM_OC2315	0x0011
+#define PCI_DEVICE_ID_OLICOM_OC2325	0x0012
+#define PCI_DEVICE_ID_OLICOM_OC2183	0x0013
+#define PCI_DEVICE_ID_OLICOM_OC2326	0x0014
+#define PCI_DEVICE_ID_OLICOM_OC6151	0x0021
+
+#define PCI_VENDOR_ID_SUN		0x108e
+#define PCI_DEVICE_ID_SUN_EBUS		0x1000
+#define PCI_DEVICE_ID_SUN_HAPPYMEAL	0x1001
+#define PCI_DEVICE_ID_SUN_SIMBA		0x5000
+#define PCI_DEVICE_ID_SUN_PBM		0x8000
+#define PCI_DEVICE_ID_SUN_SABRE		0xa000
+
+#define PCI_VENDOR_ID_CMD		0x1095
+#define PCI_DEVICE_ID_CMD_640		0x0640
+#define PCI_DEVICE_ID_CMD_643		0x0643
+#define PCI_DEVICE_ID_CMD_646		0x0646
+#define PCI_DEVICE_ID_CMD_647		0x0647
+#define PCI_DEVICE_ID_CMD_670		0x0670
+
+#define PCI_VENDOR_ID_VISION		0x1098
+#define PCI_DEVICE_ID_VISION_QD8500	0x0001
+#define PCI_DEVICE_ID_VISION_QD8580	0x0002
+
+#define PCI_VENDOR_ID_BROOKTREE		0x109e
+#define PCI_DEVICE_ID_BROOKTREE_848	0x0350
+#define PCI_DEVICE_ID_BROOKTREE_849A	0x0351
+#define PCI_DEVICE_ID_BROOKTREE_8474	0x8474
+
+#define PCI_VENDOR_ID_SIERRA		0x10a8
+#define PCI_DEVICE_ID_SIERRA_STB	0x0000
+
+#define PCI_VENDOR_ID_ACC		0x10aa
+#define PCI_DEVICE_ID_ACC_2056		0x0000
+
+#define PCI_VENDOR_ID_WINBOND		0x10ad
+#define PCI_DEVICE_ID_WINBOND_83769	0x0001
+#define PCI_DEVICE_ID_WINBOND_82C105	0x0105
+#define PCI_DEVICE_ID_WINBOND_83C553	0x0565
+
+#define PCI_VENDOR_ID_DATABOOK		0x10b3
+#define PCI_DEVICE_ID_DATABOOK_87144	0xb106
+
+#define PCI_VENDOR_ID_PLX		0x10b5
+#define PCI_DEVICE_ID_PLX_9050		0x9050
+#define PCI_DEVICE_ID_PLX_9060		0x9060
+#define PCI_DEVICE_ID_PLX_9060ES	0x906E
+#define PCI_DEVICE_ID_PLX_9060SD	0x906D
+#define PCI_DEVICE_ID_PLX_9080		0x9080
+
+#define PCI_VENDOR_ID_MADGE		0x10b6
+#define PCI_DEVICE_ID_MADGE_MK2		0x0002
+#define PCI_DEVICE_ID_MADGE_C155S	0x1001
+
+#define PCI_VENDOR_ID_3COM		0x10b7
+#define PCI_DEVICE_ID_3COM_3C339	0x3390
+#define PCI_DEVICE_ID_3COM_3C590	0x5900
+#define PCI_DEVICE_ID_3COM_3C595TX	0x5950
+#define PCI_DEVICE_ID_3COM_3C595T4	0x5951
+#define PCI_DEVICE_ID_3COM_3C595MII	0x5952
+#define PCI_DEVICE_ID_3COM_3C900TPO	0x9000
+#define PCI_DEVICE_ID_3COM_3C900COMBO	0x9001
+#define PCI_DEVICE_ID_3COM_3C905TX	0x9050
+#define PCI_DEVICE_ID_3COM_3C905T4	0x9051
+#define PCI_DEVICE_ID_3COM_3C905B_TX	0x9055
+
+#define PCI_VENDOR_ID_SMC		0x10b8
+#define PCI_DEVICE_ID_SMC_EPIC100	0x0005
+
+#define PCI_VENDOR_ID_AL		0x10b9
+#define PCI_DEVICE_ID_AL_M1445		0x1445
+#define PCI_DEVICE_ID_AL_M1449		0x1449
+#define PCI_DEVICE_ID_AL_M1451		0x1451
+#define PCI_DEVICE_ID_AL_M1461		0x1461
+#define PCI_DEVICE_ID_AL_M1489		0x1489
+#define PCI_DEVICE_ID_AL_M1511		0x1511
+#define PCI_DEVICE_ID_AL_M1513		0x1513
+#define PCI_DEVICE_ID_AL_M1521		0x1521
+#define PCI_DEVICE_ID_AL_M1523		0x1523
+#define PCI_DEVICE_ID_AL_M1531		0x1531
+#define PCI_DEVICE_ID_AL_M1533		0x1533
+#define PCI_DEVICE_ID_AL_M3307		0x3307
+#define PCI_DEVICE_ID_AL_M4803		0x5215
+#define PCI_DEVICE_ID_AL_M5219		0x5219
+#define PCI_DEVICE_ID_AL_M5229		0x5229
+#define PCI_DEVICE_ID_AL_M5237		0x5237
+#define PCI_DEVICE_ID_AL_M7101		0x7101
+
+#define PCI_VENDOR_ID_MITSUBISHI	0x10ba
+
+#define PCI_VENDOR_ID_SURECOM		0x10bd
+#define PCI_DEVICE_ID_SURECOM_NE34	0x0e34
+
+#define PCI_VENDOR_ID_NEOMAGIC          0x10c8
+#define PCI_DEVICE_ID_NEOMAGIC_MAGICGRAPH_NM2070 0x0001
+#define PCI_DEVICE_ID_NEOMAGIC_MAGICGRAPH_128V 0x0002
+#define PCI_DEVICE_ID_NEOMAGIC_MAGICGRAPH_128ZV 0x0003
+#define PCI_DEVICE_ID_NEOMAGIC_MAGICGRAPH_NM2160 0x0004
+
+#define PCI_VENDOR_ID_ASP		0x10cd
+#define PCI_DEVICE_ID_ASP_ABP940	0x1200
+#define PCI_DEVICE_ID_ASP_ABP940U	0x1300
+#define PCI_DEVICE_ID_ASP_ABP940UW	0x2300
+
+#define PCI_VENDOR_ID_MACRONIX		0x10d9
+#define PCI_DEVICE_ID_MACRONIX_MX98713	0x0512
+#define PCI_DEVICE_ID_MACRONIX_MX987x5	0x0531
+
+#define PCI_VENDOR_ID_CERN		0x10dc
+#define PCI_DEVICE_ID_CERN_SPSB_PMC	0x0001
+#define PCI_DEVICE_ID_CERN_SPSB_PCI	0x0002
+#define PCI_DEVICE_ID_CERN_HIPPI_DST	0x0021
+#define PCI_DEVICE_ID_CERN_HIPPI_SRC	0x0022
+
+#define PCI_VENDOR_ID_NVIDIA		0x10de
+
+#define PCI_VENDOR_ID_IMS		0x10e0
+#define PCI_DEVICE_ID_IMS_8849		0x8849
+
+#define PCI_VENDOR_ID_TEKRAM2		0x10e1
+#define PCI_DEVICE_ID_TEKRAM2_690c	0x690c
+
+#define PCI_VENDOR_ID_TUNDRA		0x10e3
+#define PCI_DEVICE_ID_TUNDRA_CA91C042	0x0000
+
+#define PCI_VENDOR_ID_AMCC		0x10e8
+#define PCI_DEVICE_ID_AMCC_MYRINET	0x8043
+#define PCI_DEVICE_ID_AMCC_PARASTATION	0x8062
+#define PCI_DEVICE_ID_AMCC_S5933	0x807d
+#define PCI_DEVICE_ID_AMCC_S5933_HEPC3	0x809c
+
+#define PCI_VENDOR_ID_INTERG		0x10ea
+#define PCI_DEVICE_ID_INTERG_1680	0x1680
+#define PCI_DEVICE_ID_INTERG_1682	0x1682
+
+#define PCI_VENDOR_ID_REALTEK		0x10ec
+#define PCI_DEVICE_ID_REALTEK_8029	0x8029
+#define PCI_DEVICE_ID_REALTEK_8129	0x8129
+#define PCI_DEVICE_ID_REALTEK_8139	0x8139
+
+#define PCI_VENDOR_ID_TRUEVISION	0x10fa
+#define PCI_DEVICE_ID_TRUEVISION_T1000	0x000c
+
+#define PCI_VENDOR_ID_INIT		0x1101
+#define PCI_DEVICE_ID_INIT_320P		0x9100
+#define PCI_DEVICE_ID_INIT_360P		0x9500
+
+#define PCI_VENDOR_ID_TTI		0x1103
+#define PCI_DEVICE_ID_TTI_HPT343	0x0003
+
+#define PCI_VENDOR_ID_VIA		0x1106
+#define PCI_DEVICE_ID_VIA_82C505	0x0505
+#define PCI_DEVICE_ID_VIA_82C561	0x0561
+#define PCI_DEVICE_ID_VIA_82C586_1	0x0571
+#define PCI_DEVICE_ID_VIA_82C576	0x0576
+#define PCI_DEVICE_ID_VIA_82C585	0x0585
+#define PCI_DEVICE_ID_VIA_82C586_0	0x0586
+#define PCI_DEVICE_ID_VIA_82C595	0x0595
+#define PCI_DEVICE_ID_VIA_82C597_0	0x0597
+#define PCI_DEVICE_ID_VIA_82C926	0x0926
+#define PCI_DEVICE_ID_VIA_82C416	0x1571
+#define PCI_DEVICE_ID_VIA_82C595_97	0x1595
+#define PCI_DEVICE_ID_VIA_82C586_2	0x3038
+#define PCI_DEVICE_ID_VIA_82C586_3	0x3040
+#define PCI_DEVICE_ID_VIA_86C100A	0x6100
+#define PCI_DEVICE_ID_VIA_82C597_1	0x8597
+
+#define PCI_VENDOR_ID_VORTEX		0x1119
+#define PCI_DEVICE_ID_VORTEX_GDT60x0	0x0000
+#define PCI_DEVICE_ID_VORTEX_GDT6000B	0x0001
+#define PCI_DEVICE_ID_VORTEX_GDT6x10	0x0002
+#define PCI_DEVICE_ID_VORTEX_GDT6x20	0x0003
+#define PCI_DEVICE_ID_VORTEX_GDT6530	0x0004
+#define PCI_DEVICE_ID_VORTEX_GDT6550	0x0005
+#define PCI_DEVICE_ID_VORTEX_GDT6x17	0x0006
+#define PCI_DEVICE_ID_VORTEX_GDT6x27	0x0007
+#define PCI_DEVICE_ID_VORTEX_GDT6537	0x0008
+#define PCI_DEVICE_ID_VORTEX_GDT6557	0x0009
+#define PCI_DEVICE_ID_VORTEX_GDT6x15	0x000a
+#define PCI_DEVICE_ID_VORTEX_GDT6x25	0x000b
+#define PCI_DEVICE_ID_VORTEX_GDT6535	0x000c
+#define PCI_DEVICE_ID_VORTEX_GDT6555	0x000d
+#define PCI_DEVICE_ID_VORTEX_GDT6x17RP	0x0100
+#define PCI_DEVICE_ID_VORTEX_GDT6x27RP	0x0101
+#define PCI_DEVICE_ID_VORTEX_GDT6537RP	0x0102
+#define PCI_DEVICE_ID_VORTEX_GDT6557RP	0x0103
+#define PCI_DEVICE_ID_VORTEX_GDT6x11RP	0x0104
+#define PCI_DEVICE_ID_VORTEX_GDT6x21RP	0x0105
+#define PCI_DEVICE_ID_VORTEX_GDT6x17RP1	0x0110
+#define PCI_DEVICE_ID_VORTEX_GDT6x27RP1	0x0111
+#define PCI_DEVICE_ID_VORTEX_GDT6537RP1	0x0112
+#define PCI_DEVICE_ID_VORTEX_GDT6557RP1	0x0113
+#define PCI_DEVICE_ID_VORTEX_GDT6x11RP1	0x0114
+#define PCI_DEVICE_ID_VORTEX_GDT6x21RP1	0x0115
+#define PCI_DEVICE_ID_VORTEX_GDT6x17RP2	0x0120
+#define PCI_DEVICE_ID_VORTEX_GDT6x27RP2	0x0121
+#define PCI_DEVICE_ID_VORTEX_GDT6537RP2	0x0122
+#define PCI_DEVICE_ID_VORTEX_GDT6557RP2	0x0123
+#define PCI_DEVICE_ID_VORTEX_GDT6x11RP2	0x0124
+#define PCI_DEVICE_ID_VORTEX_GDT6x21RP2	0x0125
+
+#define PCI_VENDOR_ID_EF		0x111a
+#define PCI_DEVICE_ID_EF_ATM_FPGA	0x0000
+#define PCI_DEVICE_ID_EF_ATM_ASIC	0x0002
+
+#define PCI_VENDOR_ID_FORE		0x1127
+#define PCI_DEVICE_ID_FORE_PCA200PC	0x0210
+#define PCI_DEVICE_ID_FORE_PCA200E	0x0300
+
+#define PCI_VENDOR_ID_IMAGINGTECH	0x112f
+#define PCI_DEVICE_ID_IMAGINGTECH_ICPCI	0x0000
+
+#define PCI_VENDOR_ID_PHILIPS		0x1131
+#define PCI_DEVICE_ID_PHILIPS_SAA7145	0x7145
+#define PCI_DEVICE_ID_PHILIPS_SAA7146	0x7146
+
+#define PCI_VENDOR_ID_CYCLONE		0x113c
+#define PCI_DEVICE_ID_CYCLONE_SDK	0x0001
+
+#define PCI_VENDOR_ID_ALLIANCE		0x1142
+#define PCI_DEVICE_ID_ALLIANCE_PROMOTIO	0x3210
+#define PCI_DEVICE_ID_ALLIANCE_PROVIDEO	0x6422
+#define PCI_DEVICE_ID_ALLIANCE_AT24	0x6424
+#define PCI_DEVICE_ID_ALLIANCE_AT3D	0x643d
+
+#define PCI_VENDOR_ID_SK		0x1148
+#define PCI_DEVICE_ID_SK_FP		0x4000
+#define PCI_DEVICE_ID_SK_TR		0x4200
+#define PCI_DEVICE_ID_SK_GE		0x4300
+
+#define PCI_VENDOR_ID_VMIC		0x114a
+#define PCI_DEVICE_ID_VMIC_VME		0x7587
+
+#define PCI_VENDOR_ID_DIGI		0x114f
+#define PCI_DEVICE_ID_DIGI_EPC		0x0002
+#define PCI_DEVICE_ID_DIGI_RIGHTSWITCH	0x0003
+#define PCI_DEVICE_ID_DIGI_XEM		0x0004
+#define PCI_DEVICE_ID_DIGI_XR		0x0005
+#define PCI_DEVICE_ID_DIGI_CX		0x0006
+#define PCI_DEVICE_ID_DIGI_XRJ		0x0009
+#define PCI_DEVICE_ID_DIGI_EPCJ		0x000a
+#define PCI_DEVICE_ID_DIGI_XR_920	0x0027
+
+#define PCI_VENDOR_ID_MUTECH		0x1159
+#define PCI_DEVICE_ID_MUTECH_MV1000	0x0001
+
+#define PCI_VENDOR_ID_RENDITION		0x1163
+#define PCI_DEVICE_ID_RENDITION_VERITE	0x0001
+#define PCI_DEVICE_ID_RENDITION_VERITE2100 0x2000
+
+#define PCI_VENDOR_ID_TOSHIBA		0x1179
+#define PCI_DEVICE_ID_TOSHIBA_601	0x0601
+#define PCI_DEVICE_ID_TOSHIBA_TOPIC95	0x060a
+#define PCI_DEVICE_ID_TOSHIBA_TOPIC97	0x060f
+
+#define PCI_VENDOR_ID_RICOH		0x1180
+#define PCI_DEVICE_ID_RICOH_RL5C465	0x0465
+#define PCI_DEVICE_ID_RICOH_RL5C466	0x0466
+#define PCI_DEVICE_ID_RICOH_RL5C475	0x0475
+#define PCI_DEVICE_ID_RICOH_RL5C478	0x0478
+
+#define PCI_VENDOR_ID_ARTOP		0x1191
+#define PCI_DEVICE_ID_ARTOP_ATP8400	0x0004
+#define PCI_DEVICE_ID_ARTOP_ATP850UF	0x0005
+
+#define PCI_VENDOR_ID_ZEITNET		0x1193
+#define PCI_DEVICE_ID_ZEITNET_1221	0x0001
+#define PCI_DEVICE_ID_ZEITNET_1225	0x0002
+
+#define PCI_VENDOR_ID_OMEGA		0x119b
+#define PCI_DEVICE_ID_OMEGA_82C092G	0x1221
+
+#define PCI_VENDOR_ID_LITEON		0x11ad
+#define PCI_DEVICE_ID_LITEON_LNE100TX	0x0002
+
+#define PCI_VENDOR_ID_NP		0x11bc
+#define PCI_DEVICE_ID_NP_PCI_FDDI	0x0001
+
+#define PCI_VENDOR_ID_ATT		0x11c1
+#define PCI_DEVICE_ID_ATT_L56XMF	0x0440
+
+#define PCI_VENDOR_ID_SPECIALIX		0x11cb
+#define PCI_DEVICE_ID_SPECIALIX_IO8	0x2000
+#define PCI_DEVICE_ID_SPECIALIX_XIO	0x4000
+#define PCI_DEVICE_ID_SPECIALIX_RIO	0x8000
+
+#define PCI_VENDOR_ID_AURAVISION	0x11d1
+#define PCI_DEVICE_ID_AURAVISION_VXP524	0x01f7
+
+#define PCI_VENDOR_ID_IKON		0x11d5
+#define PCI_DEVICE_ID_IKON_10115	0x0115
+#define PCI_DEVICE_ID_IKON_10117	0x0117
+
+#define PCI_VENDOR_ID_ZORAN		0x11de
+#define PCI_DEVICE_ID_ZORAN_36057	0x6057
+#define PCI_DEVICE_ID_ZORAN_36120	0x6120
+
+#define PCI_VENDOR_ID_KINETIC		0x11f4
+#define PCI_DEVICE_ID_KINETIC_2915	0x2915
+
+#define PCI_VENDOR_ID_COMPEX		0x11f6
+#define PCI_DEVICE_ID_COMPEX_ENET100VG4	0x0112
+#define PCI_DEVICE_ID_COMPEX_RL2000	0x1401
+
+#define PCI_VENDOR_ID_RP               0x11fe
+#define PCI_DEVICE_ID_RP32INTF         0x0001
+#define PCI_DEVICE_ID_RP8INTF          0x0002
+#define PCI_DEVICE_ID_RP16INTF         0x0003
+#define PCI_DEVICE_ID_RP4QUAD	       0x0004
+#define PCI_DEVICE_ID_RP8OCTA          0x0005
+#define PCI_DEVICE_ID_RP8J	       0x0006
+#define PCI_DEVICE_ID_RPP4	       0x000A
+#define PCI_DEVICE_ID_RPP8	       0x000B
+#define PCI_DEVICE_ID_RP8M	       0x000C
+
+#define PCI_VENDOR_ID_CYCLADES		0x120e
+#define PCI_DEVICE_ID_CYCLOM_Y_Lo	0x0100
+#define PCI_DEVICE_ID_CYCLOM_Y_Hi	0x0101
+#define PCI_DEVICE_ID_CYCLOM_Z_Lo	0x0200
+#define PCI_DEVICE_ID_CYCLOM_Z_Hi	0x0201
+
+#define PCI_VENDOR_ID_ESSENTIAL		0x120f
+#define PCI_DEVICE_ID_ESSENTIAL_ROADRUNNER	0x0001
+
+#define PCI_VENDOR_ID_O2		0x1217
+#define PCI_DEVICE_ID_O2_6729		0x6729
+#define PCI_DEVICE_ID_O2_6730		0x673a
+#define PCI_DEVICE_ID_O2_6832		0x6832
+#define PCI_DEVICE_ID_O2_6836		0x6836
+
+#define PCI_VENDOR_ID_3DFX		0x121a
+#define PCI_DEVICE_ID_3DFX_VOODOO	0x0001
+#define PCI_DEVICE_ID_3DFX_VOODOO2	0x0002
+
+#define PCI_VENDOR_ID_SIGMADES		0x1236
+#define PCI_DEVICE_ID_SIGMADES_6425	0x6401
+
+#define PCI_VENDOR_ID_CCUBE		0x123f
+
+#define PCI_VENDOR_ID_DIPIX		0x1246
+
+#define PCI_VENDOR_ID_STALLION		0x124d
+#define PCI_DEVICE_ID_STALLION_ECHPCI832 0x0000
+#define PCI_DEVICE_ID_STALLION_ECHPCI864 0x0002
+#define PCI_DEVICE_ID_STALLION_EIOPCI	0x0003
+
+#define PCI_VENDOR_ID_OPTIBASE		0x1255
+#define PCI_DEVICE_ID_OPTIBASE_FORGE	0x1110
+#define PCI_DEVICE_ID_OPTIBASE_FUSION	0x1210
+#define PCI_DEVICE_ID_OPTIBASE_VPLEX	0x2110
+#define PCI_DEVICE_ID_OPTIBASE_VPLEXCC	0x2120
+#define PCI_DEVICE_ID_OPTIBASE_VQUEST	0x2130
+
+#define PCI_VENDOR_ID_SATSAGEM		0x1267
+#define PCI_DEVICE_ID_SATSAGEM_PCR2101	0x5352
+#define PCI_DEVICE_ID_SATSAGEM_TELSATTURBO 0x5a4b
+
+#define PCI_VENDOR_ID_HUGHES		0x1273
+#define PCI_DEVICE_ID_HUGHES_DIRECPC	0x0002
+
+#define PCI_VENDOR_ID_ENSONIQ		0x1274
+#define PCI_DEVICE_ID_ENSONIQ_AUDIOPCI	0x5000
+
+#define PCI_VENDOR_ID_ALTEON		0x12ae
+#define PCI_DEVICE_ID_ALTEON_ACENIC	0x0001
+
+#define PCI_VENDOR_ID_PICTUREL		0x12c5
+#define PCI_DEVICE_ID_PICTUREL_PCIVST	0x0081
+
+#define PCI_VENDOR_ID_NVIDIA_SGS	0x12d2
+#define PCI_DEVICE_ID_NVIDIA_SGS_RIVA128 0x0018
+
+#define PCI_VENDOR_ID_CBOARDS		0x1307
+#define PCI_DEVICE_ID_CBOARDS_DAS1602_16 0x0001
+
+#define PCI_VENDOR_ID_SYMPHONY		0x1c1c
+#define PCI_DEVICE_ID_SYMPHONY_101	0x0001
+
+#define PCI_VENDOR_ID_TEKRAM		0x1de1
+#define PCI_DEVICE_ID_TEKRAM_DC290	0xdc29
+
+#define PCI_VENDOR_ID_3DLABS		0x3d3d
+#define PCI_DEVICE_ID_3DLABS_300SX	0x0001
+#define PCI_DEVICE_ID_3DLABS_500TX	0x0002
+#define PCI_DEVICE_ID_3DLABS_DELTA	0x0003
+#define PCI_DEVICE_ID_3DLABS_PERMEDIA	0x0004
+#define PCI_DEVICE_ID_3DLABS_MX		0x0006
+
+#define PCI_VENDOR_ID_AVANCE		0x4005
+#define PCI_DEVICE_ID_AVANCE_ALG2064	0x2064
+#define PCI_DEVICE_ID_AVANCE_2302	0x2302
+
+#define PCI_VENDOR_ID_NETVIN		0x4a14
+#define PCI_DEVICE_ID_NETVIN_NV5000SC	0x5000
+
+#define PCI_VENDOR_ID_S3		0x5333
+#define PCI_DEVICE_ID_S3_PLATO_PXS	0x0551
+#define PCI_DEVICE_ID_S3_ViRGE		0x5631
+#define PCI_DEVICE_ID_S3_TRIO		0x8811
+#define PCI_DEVICE_ID_S3_AURORA64VP	0x8812
+#define PCI_DEVICE_ID_S3_TRIO64UVP	0x8814
+#define PCI_DEVICE_ID_S3_ViRGE_VX	0x883d
+#define PCI_DEVICE_ID_S3_868		0x8880
+#define PCI_DEVICE_ID_S3_928		0x88b0
+#define PCI_DEVICE_ID_S3_864_1		0x88c0
+#define PCI_DEVICE_ID_S3_864_2		0x88c1
+#define PCI_DEVICE_ID_S3_964_1		0x88d0
+#define PCI_DEVICE_ID_S3_964_2		0x88d1
+#define PCI_DEVICE_ID_S3_968		0x88f0
+#define PCI_DEVICE_ID_S3_TRIO64V2	0x8901
+#define PCI_DEVICE_ID_S3_PLATO_PXG	0x8902
+#define PCI_DEVICE_ID_S3_ViRGE_DXGX	0x8a01
+#define PCI_DEVICE_ID_S3_ViRGE_GX2	0x8a10
+#define PCI_DEVICE_ID_S3_ViRGE_MX	0x8c01
+#define PCI_DEVICE_ID_S3_ViRGE_MXP	0x8c02
+#define PCI_DEVICE_ID_S3_ViRGE_MXPMV	0x8c03
+#define PCI_DEVICE_ID_S3_SONICVIBES	0xca00
+
+#define PCI_VENDOR_ID_INTEL		0x8086
+#define PCI_DEVICE_ID_INTEL_82375	0x0482
+#define PCI_DEVICE_ID_INTEL_82424	0x0483
+#define PCI_DEVICE_ID_INTEL_82378	0x0484
+#define PCI_DEVICE_ID_INTEL_82430	0x0486
+#define PCI_DEVICE_ID_INTEL_82434	0x04a3
+#define PCI_DEVICE_ID_INTEL_82092AA_0	0x1221
+#define PCI_DEVICE_ID_INTEL_82092AA_1	0x1222
+#define PCI_DEVICE_ID_INTEL_7116	0x1223
+#define PCI_DEVICE_ID_INTEL_82596	0x1226
+#define PCI_DEVICE_ID_INTEL_82865	0x1227
+#define PCI_DEVICE_ID_INTEL_82557	0x1229
+#define PCI_DEVICE_ID_INTEL_82437	0x122d
+#define PCI_DEVICE_ID_INTEL_82371FB_0	0x122e
+#define PCI_DEVICE_ID_INTEL_82371FB_1	0x1230
+#define PCI_DEVICE_ID_INTEL_82371MX	0x1234
+#define PCI_DEVICE_ID_INTEL_82437MX	0x1235
+#define PCI_DEVICE_ID_INTEL_82441	0x1237
+#define PCI_DEVICE_ID_INTEL_82380FB	0x124b
+#define PCI_DEVICE_ID_INTEL_82439	0x1250
+#define PCI_DEVICE_ID_INTEL_82371SB_0	0x7000
+#define PCI_DEVICE_ID_INTEL_82371SB_1	0x7010
+#define PCI_DEVICE_ID_INTEL_82371SB_2	0x7020
+#define PCI_DEVICE_ID_INTEL_82437VX	0x7030
+#define PCI_DEVICE_ID_INTEL_82439TX	0x7100
+#define PCI_DEVICE_ID_INTEL_82371AB_0	0x7110
+#define PCI_DEVICE_ID_INTEL_82371AB	0x7111
+#define PCI_DEVICE_ID_INTEL_82371AB_2	0x7112
+#define PCI_DEVICE_ID_INTEL_82371AB_3	0x7113
+#define PCI_DEVICE_ID_INTEL_82443LX_0	0x7180
+#define PCI_DEVICE_ID_INTEL_82443LX_1	0x7181
+#define PCI_DEVICE_ID_INTEL_82443BX_0	0x7190
+#define PCI_DEVICE_ID_INTEL_82443BX_1	0x7191
+#define PCI_DEVICE_ID_INTEL_82443BX_2	0x7192
+#define PCI_DEVICE_ID_INTEL_P6		0x84c4
+#define PCI_DEVICE_ID_INTEL_82450GX	0x84c5
+
+#define PCI_VENDOR_ID_KTI		0x8e2e
+#define PCI_DEVICE_ID_KTI_ET32P2	0x3000
+
+#define PCI_VENDOR_ID_ADAPTEC		0x9004
+#define PCI_DEVICE_ID_ADAPTEC_7810	0x1078
+#define PCI_DEVICE_ID_ADAPTEC_7850	0x5078
+#define PCI_DEVICE_ID_ADAPTEC_7855	0x5578
+#define PCI_DEVICE_ID_ADAPTEC_5800	0x5800
+#define PCI_DEVICE_ID_ADAPTEC_1480A	0x6075
+#define PCI_DEVICE_ID_ADAPTEC_7860	0x6078
+#define PCI_DEVICE_ID_ADAPTEC_7861	0x6178
+#define PCI_DEVICE_ID_ADAPTEC_7870	0x7078
+#define PCI_DEVICE_ID_ADAPTEC_7871	0x7178
+#define PCI_DEVICE_ID_ADAPTEC_7872	0x7278
+#define PCI_DEVICE_ID_ADAPTEC_7873	0x7378
+#define PCI_DEVICE_ID_ADAPTEC_7874	0x7478
+#define PCI_DEVICE_ID_ADAPTEC_7895	0x7895
+#define PCI_DEVICE_ID_ADAPTEC_7880	0x8078
+#define PCI_DEVICE_ID_ADAPTEC_7881	0x8178
+#define PCI_DEVICE_ID_ADAPTEC_7882	0x8278
+#define PCI_DEVICE_ID_ADAPTEC_7883	0x8378
+#define PCI_DEVICE_ID_ADAPTEC_7884	0x8478
+#define PCI_DEVICE_ID_ADAPTEC_1030	0x8b78
+
+#define PCI_VENDOR_ID_ADAPTEC2		0x9005
+#define PCI_DEVICE_ID_ADAPTEC2_2940U2	0x0010
+#define PCI_DEVICE_ID_ADAPTEC2_7890	0x001f
+#define PCI_DEVICE_ID_ADAPTEC2_3940U2	0x0050
+#define PCI_DEVICE_ID_ADAPTEC2_7896	0x005f
+
+#define PCI_VENDOR_ID_ATRONICS		0x907f
+#define PCI_DEVICE_ID_ATRONICS_2015	0x2015
+
+#define PCI_VENDOR_ID_HOLTEK		0x9412
+#define PCI_DEVICE_ID_HOLTEK_6565	0x6565
+
+#define PCI_VENDOR_ID_TIGERJET		0xe159
+#define PCI_DEVICE_ID_TIGERJET_300	0x0001
+
+#define PCI_VENDOR_ID_ARK		0xedd8
+#define PCI_DEVICE_ID_ARK_STING		0xa091
+#define PCI_DEVICE_ID_ARK_STINGARK	0xa099
+#define PCI_DEVICE_ID_ARK_2000MT	0xa0a1
+
+#endif /* !__PCI_IDS_H__ */
diff --git a/cpukit/libpci/pci/ids_extra.h b/cpukit/libpci/pci/ids_extra.h
new file mode 100644
index 0000000..ffa18cb
--- /dev/null
+++ b/cpukit/libpci/pci/ids_extra.h
@@ -0,0 +1,19 @@
+/* RTEMS local PCI data base */
+
+/* Only included from pci_ids.h */
+#ifndef __PCI_IDS_H__
+#error pci/ids_extra.h should only be included from pci/ids.h
+#endif
+
+/* Gaisler PCI IDs */
+#define PCIID_VENDOR_GAISLER		0x1AC8
+#define PCIID_VENDOR_GAISLER_OLD	0x16E3
+
+/* Gaisler PCI Devices */
+#define PCIID_DEVICE_GR_RASTA_IO	0x0010	/* GR-RASTA-IO */
+#define PCIID_DEVICE_GR_RASTA_IO_OLD	0x0210	/* old GR-RASTA-IO ID*/
+#define PCIID_DEVICE_GR_RASTA_TMTC	0x0011	/* GR-RASTA-TMTC */
+#define PCIID_DEVICE_GR_RASTA_ADCDAC	0x0014	/* GR-RASTA-ADCDAC */
+#define PCIID_DEVICE_GR_701		0x0701	/* GR-701 */
+#define PCIID_DEVICE_GR_TMTC_1553       0x0198  /* GR-TMTC-1553 */
+#define PCIID_DEVICE_GR_RASTA_SPW_RTR   0x0062  /* GR-RASTA-SPW-ROUTER */
diff --git a/cpukit/libpci/pci/irq.h b/cpukit/libpci/pci/irq.h
new file mode 100644
index 0000000..2dacadf
--- /dev/null
+++ b/cpukit/libpci/pci/irq.h
@@ -0,0 +1,105 @@
+/* PCI IRQ Library
+ *
+ * IRQ handling does not have so much with PCI to do, this library depends
+ * on the BSP to implement shared interrupts.
+ *
+ * COPYRIGHT (c) 2010.
+ * Cobham Gaisler AB.
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ */
+
+#ifndef __PCI_IRQ_H__
+#define __PCI_IRQ_H__
+
+#include <bsp.h>
+
+/* PCI Handler (ISR) called when IRQ is generated by any of the PCI devices
+ * connected to the same PCI IRQ Pin. This is been defined the same way as
+ * rtems_interrupt_handler in order for BSPs to "direct-map" the register
+ * and unregister functions rtems_interrupt_handler_install/remove
+ */
+typedef void (*pci_isr)(void *arg);
+
+/* Get assigned system IRQ to a PCI Device. If no IRQ 0 is returned */
+extern int pci_dev_irq(pci_dev_t dev);
+
+/* Register shared PCI IRQ handler, but does not enable it. The system interrupt
+ * number is read from the PCI board's PCI configuration space header iline
+ * field. The iline field is initialized by the PCI subsystem during start up,
+ * the ipin field is translated into a system IRQ and written to iline. The
+ * board's driver should use the iline field as the irq argument to this
+ * function.
+ *
+ * Arguments
+ *  irq       System IRQ number, normally taken from the PCI configuration area
+ *  isr       Function pointer to the ISR
+ *  arg       Second argument to function isr
+ */
+static inline int pci_interrupt_register(int irq, const char *info,
+						pci_isr isr, void *arg)
+{
+	return BSP_PCI_shared_interrupt_register(irq, info, isr, arg);
+}
+
+/* Unregister previously registered shared PCI IRQ handler
+ *
+ * Arguments
+ *  irq       System IRQ number, normally taken from the PCI configuration area
+ *  isr       Function pointer to the ISR
+ *  arg       Second argument to function isr
+ */
+static inline int pci_interrupt_unregister(int irq, pci_isr isr, void *arg)
+{
+	return BSP_PCI_shared_interrupt_unregister(irq, isr, arg);
+}
+
+/* Enable shared PCI IRQ handler. This function will unmask the interrupt
+ * controller and mark this interrupt handler ready to handle interrupts. Note
+ * that since it is a shared interrupt handler service the interrupt may
+ * already be enabled, however no calls to this specific handler is made
+ * until it is enabled.
+ *
+ * Arguments
+ *  irq       System IRQ number, normally taken from the PCI configuration area
+ *  isr       Function pointer to the ISR
+ *  arg       Second argument to function isr
+ */
+static inline void pci_interrupt_unmask(int irq)
+{
+	BSP_PCI_shared_interrupt_unmask(irq);
+}
+
+/* Disable shared PCI IRQ handler. This function will mask the interrupt
+ * controller and mark this interrupt handler not ready to receive interrupts.
+ * Note that since it is a shared interrupt handler service the interrupt may
+ * still be enabled, however no calls to this specific handler is made
+ * while it is disabled.
+ *
+ * Arguments
+ *  irq       System IRQ number, normally taken from the PCI configuration area
+ *  isr       Function pointer to the ISR
+ *  arg       Second argument to function isr
+ */
+static inline void pci_interrupt_mask(int irq)
+{
+	BSP_PCI_shared_interrupt_mask(irq);
+}
+
+/* Acknowledge the interrupt controller by writing to the interrupt controller.
+ * Note that since it is a shared interrupt handler service, clearing the
+ * interrupt source may affect other ISRs registered to this IRQ.
+ *
+ * Arguments
+ *  irq       System IRQ number, normally taken from the PCI configuration area
+ *  isr       Function pointer to the ISR
+ *  arg       Second argument to function isr
+ */
+static inline void pci_interrupt_clear(int irq)
+{
+	BSP_PCI_shared_interrupt_clear(irq);
+}
+
+#endif /* !__PCI_IRQ_H__ */
diff --git a/cpukit/libpci/pci_access.c b/cpukit/libpci/pci_access.c
new file mode 100644
index 0000000..371c5ef
--- /dev/null
+++ b/cpukit/libpci/pci_access.c
@@ -0,0 +1,74 @@
+/*  PCI Access Library
+ *
+ *  COPYRIGHT (c) 2010.
+ *  Cobham Gaisler AB.
+ *
+ *  The license and distribution terms for this file may be
+ *  found in the file LICENSE in this distribution or at
+ *  http://www.rtems.com/license/LICENSE.
+ */
+
+#include <pci.h>
+#include <pci/access.h>
+
+/* Access Routines valid after a PCI-Access-Driver has registered */
+struct pci_access_drv pci_access_ops = {
+	.cfg = {.read8 = 0},
+};
+
+/* Read a 8-bit register over configuration space */
+int pci_cfg_r8(pci_dev_t dev, int ofs, uint8_t *data)
+{
+	return pci_access_ops.cfg.read8(dev, ofs, data);
+}
+
+/* Read a 16-bit register over configuration space */
+int pci_cfg_r16(pci_dev_t dev, int ofs, uint16_t *data)
+{
+	return pci_access_ops.cfg.read16(dev, ofs, data);
+}
+
+/* Read a 32-bit register over configuration space */
+int pci_cfg_r32(pci_dev_t dev, int ofs, uint32_t *data)
+{
+	return pci_access_ops.cfg.read32(dev, ofs, data);
+}
+
+/* Write a 8-bit register over configuration space */
+int pci_cfg_w8(pci_dev_t dev, int ofs, uint8_t data)
+{
+	return pci_access_ops.cfg.write8(dev, ofs, data);
+}
+
+/* Write a 16-bit register over configuration space */
+int pci_cfg_w16(pci_dev_t dev, int ofs, uint16_t data)
+{
+	return pci_access_ops.cfg.write16(dev, ofs, data);
+}
+
+/* Write a 32-bit register over configuration space */
+int pci_cfg_w32(pci_dev_t dev, int ofs, uint32_t data)
+{
+	return pci_access_ops.cfg.write32(dev, ofs, data);
+}
+
+void pci_modify_cmdsts(pci_dev_t dev, uint32_t mask, uint32_t val)
+{
+	uint32_t data;
+
+	pci_cfg_r32(dev, PCI_COMMAND, &data);
+	data &= ~mask;
+	data |= val;
+	pci_cfg_w32(dev, PCI_COMMAND, data);
+}
+
+/* Register a driver for handling access to PCI */
+int pci_access_drv_register(struct pci_access_drv *drv)
+{
+	if (pci_access_ops.cfg.read8)
+		return -1; /* Already registered a driver.. */
+
+	pci_access_ops = *drv;
+
+	return 0;
+}
diff --git a/cpukit/libpci/pci_access_func.c b/cpukit/libpci/pci_access_func.c
new file mode 100644
index 0000000..d86ccab
--- /dev/null
+++ b/cpukit/libpci/pci_access_func.c
@@ -0,0 +1,73 @@
+/*  PCI Access Library
+ *
+ *  COPYRIGHT (c) 2010.
+ *  Cobham Gaisler AB.
+ *
+ *  The license and distribution terms for this file may be
+ *  found in the file LICENSE in this distribution or at
+ *  http://www.rtems.com/license/LICENSE.
+ */
+
+#include <pci.h>
+
+/* Get PCI I/O or Configuration space access function */
+static int pci_ioc_func(int wr, int size, void **func, void **ops)
+{
+	int ofs;
+
+	ofs = 0;
+	if (wr)
+		ofs += 3;
+	if (size == 4)
+		size = 3;
+	ofs += (size & 0x3) - 1;
+	if (ops[ofs] == NULL)
+		return -1;
+	if (func)
+		*func = ops[ofs];
+	return 0;
+}
+
+/* Get Registers-over-Memory Space access function */
+static int pci_memreg_func(int wr, int size, void **func, int endian)
+{
+	void **ops;
+	int ofs = 0;
+
+	ops = (void **)pci_access_ops.memreg;
+	if (!ops)
+		return -1;
+
+	if (size == 2)
+		ofs += 2;
+	else if (size == 4)
+		ofs += 6;
+
+	if (size != 1 && endian == PCI_BIG_ENDIAN)
+		ofs += 2;
+
+	if (wr)
+		ofs += 1;
+
+	if (ops[ofs] == NULL)
+		return -1;
+	if (func)
+		*func = ops[ofs];
+	return 0;
+}
+
+/* Get function pointer from Host/BSP driver definitions */
+int pci_access_func(int wr, int size, void **func, int endian, int type)
+{
+	switch (type) {
+	default:
+	case 2: /* Memory Space - not implemented */
+		return -1;
+	case 1: /* I/O space */
+		return pci_ioc_func(wr, size, func, (void**)&pci_access_ops.cfg);
+	case 3: /* Registers over Memory space */
+		return pci_memreg_func(wr, size, func, endian);
+	case 4: /* Configuration space */
+		return pci_ioc_func(wr, size, func, (void**)&pci_access_ops.io);
+	}
+}
diff --git a/cpukit/libpci/pci_access_io.c b/cpukit/libpci/pci_access_io.c
new file mode 100644
index 0000000..12e6699
--- /dev/null
+++ b/cpukit/libpci/pci_access_io.c
@@ -0,0 +1,48 @@
+/*  PCI Access Library
+ *
+ *  COPYRIGHT (c) 2010.
+ *  Cobham Gaisler AB.
+ *
+ *  The license and distribution terms for this file may be
+ *  found in the file LICENSE in this distribution or at
+ *  http://www.rtems.com/license/LICENSE.
+ */
+
+#include <pci.h>
+#include <pci/access.h>
+
+/* Read a 8-bit register over PCI I/O Space */
+uint8_t pci_io_r8(uint32_t adr)
+{
+	return pci_access_ops.io.read8((uint8_t *)adr);
+}
+
+/* Read a 16-bit I/O Register */
+uint16_t pci_io_r16(uint32_t adr)
+{
+	return pci_access_ops.io.read16((uint16_t *)adr);
+}
+
+/* Read a 32-bit I/O Register */
+uint32_t pci_io_r32(uint32_t adr)
+{
+	return pci_access_ops.io.read32((uint32_t *)adr);
+}
+
+/* Write a 8-bit I/O Register */
+void pci_io_w8(uint32_t adr, uint8_t data)
+{
+	pci_access_ops.io.write8((uint8_t *)adr, data);
+}
+
+/* Write a 16-bit I/O Register */
+void pci_io_w16(uint32_t adr, uint16_t data)
+{
+	pci_access_ops.io.write16((uint16_t *)adr, data);
+}
+
+/* Write a 32-bit I/O Register */
+void pci_io_w32(uint32_t adr, uint32_t data)
+{
+	pci_access_ops.io.write32((uint32_t *)adr, data);
+}
diff --git a/cpukit/libpci/pci_access_mem.c b/cpukit/libpci/pci_access_mem.c
new file mode 100644
index 0000000..216f83f
--- /dev/null
+++ b/cpukit/libpci/pci_access_mem.c
@@ -0,0 +1,22 @@
+/*  PCI Access Library
+ *  Registers-over-Memory Space - Generic Big/Little endian PCI bus definitions
+ *
+ *  COPYRIGHT (c) 2010.
+ *  Cobham Gaisler AB.
+ *
+ *  The license and distribution terms for this file may be
+ *  found in the file LICENSE in this distribution or at
+ *  http://www.rtems.com/license/LICENSE.
+ */
+
+#include <pci.h>
+
+uint8_t pci_mem_ld8(uint8_t *adr)
+{
+	return *adr;
+}
+
+void pci_mem_st8(uint8_t *adr, uint8_t data)
+{
+	*adr = data;
+}
diff --git a/cpukit/libpci/pci_access_mem_be.c b/cpukit/libpci/pci_access_mem_be.c
new file mode 100644
index 0000000..f05b547
--- /dev/null
+++ b/cpukit/libpci/pci_access_mem_be.c
@@ -0,0 +1,67 @@
+/*  PCI Access Library
+ *  Registers-over-Memory Space - Generic Big endian PCI bus definitions
+ *
+ *  COPYRIGHT (c) 2010.
+ *  Cobham Gaisler AB.
+ *
+ *  The license and distribution terms for this file may be
+ *  found in the file LICENSE in this distribution or at
+ *  http://www.rtems.com/license/LICENSE.
+ */
+
+#include <pci.h>
+
+uint16_t pci_mem_be_ld_le16(uint16_t *adr)
+{
+	return ld_be16(adr);
+}
+
+uint16_t pci_mem_be_ld_be16(uint16_t *adr)
+{
+	return ld_le16(adr);
+}
+
+uint32_t pci_mem_be_ld_le32(uint32_t *adr)
+{
+	return ld_be32(adr);
+}
+
+uint32_t pci_mem_be_ld_be32(uint32_t *adr)
+{
+	return ld_le32(adr);
+}
+
+void pci_mem_be_st_le16(uint16_t *adr, uint16_t data)
+{
+	st_be16(adr, data);
+}
+
+void pci_mem_be_st_be16(uint16_t *adr, uint16_t data)
+{
+	st_le16(adr, data);
+}
+
+void pci_mem_be_st_le32(uint32_t *adr, uint32_t data)
+{
+	st_be32(adr, data);
+}
+
+void pci_mem_be_st_be32(uint32_t *adr, uint32_t data)
+{
+	st_le32(adr, data);
+}
+
+struct pci_memreg_ops pci_mem_be_ops = {
+	.ld8    = pci_mem_ld8,
+	.st8    = pci_mem_st8,
+
+	.ld_le16 = pci_mem_be_ld_le16,
+	.st_le16 = pci_mem_be_st_le16,
+	.ld_be16 = pci_mem_be_ld_be16,
+	.st_be16 = pci_mem_be_st_be16,
+
+	.ld_le32 = pci_mem_be_ld_le32,
+	.st_le32 = pci_mem_be_st_le32,
+	.ld_be32 = pci_mem_be_ld_be32,
+	.st_be32 = pci_mem_be_st_be32,
+};
diff --git a/cpukit/libpci/pci_access_mem_le.c b/cpukit/libpci/pci_access_mem_le.c
new file mode 100644
index 0000000..2746f24
--- /dev/null
+++ b/cpukit/libpci/pci_access_mem_le.c
@@ -0,0 +1,66 @@
+/*  PCI Access Library
+ *  Registers-over-Memory Space - Generic Little endian PCI bus definitions
+ *
+ *  COPYRIGHT (c) 2010.
+ *  Cobham Gaisler AB.
+ *
+ *  The license and distribution terms for this file may be
+ *  found in the file LICENSE in this distribution or at
+ *  http://www.rtems.com/license/LICENSE.
+ */
+
+#include <pci.h>
+
+uint16_t pci_mem_le_ld_le16(uint16_t *adr)
+{
+	return ld_le16(adr);
+}
+
+uint16_t pci_mem_le_ld_be16(uint16_t *adr)
+{
+	return ld_be16(adr);
+}
+
+uint32_t pci_mem_le_ld_le32(uint32_t *adr)
+{
+	return ld_le32(adr);
+}
+
+uint32_t pci_mem_le_ld_be32(uint32_t *adr)
+{
+	return ld_be32(adr);
+}
+
+void pci_mem_le_st_le16(uint16_t *adr, uint16_t data)
+{
+	st_le16(adr, data);
+}
+
+void pci_mem_le_st_be16(uint16_t *adr, uint16_t data)
+{
+	st_be16(adr, data);
+}
+
+void pci_mem_le_st_le32(uint32_t *adr, uint32_t data)
+{
+	st_le32(adr, data);
+}
+
+void pci_mem_le_st_be32(uint32_t *adr, uint32_t data)
+{
+	st_be32(adr, data);
+}
+
+struct pci_memreg_ops pci_mem_le_ops = {
+	.ld8    = pci_mem_ld8,
+	.st8    = pci_mem_st8,
+
+	.ld_le16 = pci_mem_le_ld_le16,
+	.st_le16 = pci_mem_le_st_le16,	
+	.ld_be16 = pci_mem_le_ld_be16,
+	.st_be16 = pci_mem_le_st_be16,
+	.ld_le32 = pci_mem_le_ld_le32,
+	.st_le32 = pci_mem_le_st_le32,
+	.ld_be32 = pci_mem_le_ld_be32,
+	.st_be32 = pci_mem_le_st_be32,
+};
diff --git a/cpukit/libpci/pci_cfg.c b/cpukit/libpci/pci_cfg.c
new file mode 100644
index 0000000..78a1229
--- /dev/null
+++ b/cpukit/libpci/pci_cfg.c
@@ -0,0 +1,55 @@
+/*  PCI Configuration Library
+ *
+ *  COPYRIGHT (c) 2010.
+ *  Cobham Gaisler AB.
+ *
+ *  The license and distribution terms for this file may be
+ *  found in the file LICENSE in this distribution or at
+ *  http://www.rtems.com/license/LICENSE.
+ */
+
+#include <pci/cfg.h>
+
+/* Number of buses. This is set from respective library */
+int pci_bus_cnt = 0;
+
+/* PCI Address assigned to BARs which failed to fit into the PCI Window or
+ * is disabled by any other cause.
+ */
+uint32_t pci_invalid_address = 0;
+
+/* PCI System type. Configuration Library setup this */
+int pci_system_type = PCI_SYSTEM_NONE;
+
+/* PCI Endianness.
+ *
+ * Host driver or BSP must override this be writing here if bus is defined
+ * as non-standard big-endian.
+ */
+int pci_endian = PCI_LITTLE_ENDIAN;
+
+/* Configure PCI devices and bridges, and setup the RAM data structures
+ * describing the PCI devices currently present in the system
+ */
+int pci_config_init(void)
+{
+	if (pci_config_lib_init)
+		return pci_config_lib_init();
+	else
+		return 0;
+}
+
+void pci_config_register(void *config)
+{
+	if (pci_config_lib_register)
+		pci_config_lib_register(config);
+}
+
+/* Return the number of PCI busses available in the system, note that
+ * there are always one bus (bus0) after the PCI library has been
+ * initialized and a driver has been registered.
+ */
+int pci_bus_count(void)
+{
+	return pci_bus_cnt;
+}
diff --git a/cpukit/libpci/pci_cfg_auto.c b/cpukit/libpci/pci_cfg_auto.c
new file mode 100644
index 0000000..548dd90
--- /dev/null
+++ b/cpukit/libpci/pci_cfg_auto.c
@@ -0,0 +1,1014 @@
+/*  PCI (Auto) configuration Library. Setup PCI configuration space and IRQ.
+ *
+ *  COPYRIGHT (c) 2010.
+ *  Cobham Gaisler AB.
+ *
+ *  The license and distribution terms for this file may be
+ *  found in the file LICENSE in this distribution or at
+ *  http://www.rtems.com/license/LICENSE.
+ */
+
+#include <rtems.h>
+#include <stdlib.h>
+#include <rtems/bspIo.h>
+#include <string.h>
+
+/* Configure headers */
+#define PCI_CFG_AUTO_LIB
+
+#include <pci.h>
+#include <pci/access.h>
+#include <pci/cfg.h>
+
+/* Define PCI_INFO_ON_STARTUP to get a listing of configured devices at boot
+ * time
+ */
+#undef PCI_INFO_ON_STARTUP
+
+/* #define DEBUG */
+
+#ifdef DEBUG
+#define DBG(x...) printk(x)
+#else
+#define DBG(x...)
+#endif
+
+/* PCI Library
+ * (For debugging it might be good to use other functions or the driver's
+ *  directly)
+ */
+#define PCI_CFG_R8(dev, args...) pci_cfg_r8(dev, args)
+#define PCI_CFG_R16(dev, args...) pci_cfg_r16(dev, args)
+#define PCI_CFG_R32(dev, args...) pci_cfg_r32(dev, args)
+#define PCI_CFG_W8(dev, args...) pci_cfg_w8(dev, args)
+#define PCI_CFG_W16(dev, args...) pci_cfg_w16(dev, args)
+#define PCI_CFG_W32(dev, args...) pci_cfg_w32(dev, args)
+
+/* Number of PCI buses */
+extern int pci_bus_cnt;
+
+int pci_config_auto_initialized = 0;
+
+/* Configuration setup */
+struct pci_auto_setup pci_auto_cfg;
+
+/* Insert BAR into the sorted resources list. The BARs are sorted on the
+ * BAR size/alignment need.
+ */
+static void pci_res_insert(struct pci_res **root, struct pci_res *res)
+{
+	struct pci_res *curr, *last;
+	unsigned long curr_size_resulting_boundary, size_resulting_boundary;
+	unsigned long boundary, size;
+
+	res->start = 0;
+	res->end = 0;
+	boundary = res->boundary;
+	size = res->size;
+
+	/* Insert the resources depending on the boundary needs
+	 * Normally the boundary=size of the BAR, however when
+	 * PCI bridges are involved the bridge's boundary may be
+	 * smaller that the size due to the fact that a bridge
+	 * may have different-sized BARs behind, the largest BAR
+	 * (also the BAR with the largest boundary) will decide
+	 * the alignment need.
+	 */
+	last = NULL;
+	curr = *root;
+
+	/* Order List after boundary, the boundary is maintained
+	 * when the size is on an equal boundary, normally it is
+	 * but may not be with bridges. So in second hand it is
+	 * sorted after resulting boundary - the boundary after
+	 * the resource.
+	 */
+	while (curr && (curr->boundary >= boundary)) {
+		if (curr->boundary == boundary) {
+			/* Find Resulting boundary of size */
+			size_resulting_boundary = 1;
+			while ((size & size_resulting_boundary) == 0)
+				size_resulting_boundary =
+					size_resulting_boundary << 1;
+
+			/* Find Resulting boundary of curr->size */
+			curr_size_resulting_boundary = 1;
+			while ((curr->size & curr_size_resulting_boundary) == 0)
+				curr_size_resulting_boundary =
+					curr_size_resulting_boundary << 1;
+
+			if (size_resulting_boundary >=
+			    curr_size_resulting_boundary)
+				break;
+		}
+		last = curr;
+		curr = curr->next;
+	}
+
+	if (last == NULL) {
+		/* Insert first in list */
+		res->next = *root;
+		*root = res;
+	} else {
+		last->next = res;
+		res->next = curr;
+	}
+}
+
+#ifdef DEBUG
+void pci_res_list_print(struct pci_res *root)
+{
+	if (root == NULL)
+		return;
+
+	printf("RESOURCE LIST:\n");
+	while (root) {
+		printf(" SIZE: 0x%08x, BOUNDARY: 0x%08x\n", root->size,
+								root->boundary);
+		root = root->next;
+	}
+}
+#endif
+
+/* Reorder a size/alignment ordered resources list. The idea is to
+ * avoid unused due to alignment/size restriction.
+ *
+ * NOTE: The first element is always untouched.
+ * NOTE: If less than three elements in list, nothing will be done
+ *
+ * Normally a BAR has the same alignment requirements as the size of the
+ * BAR. However, when bridges are invloved the alignment need may be smaller
+ * that the size, because a bridge resource consist or multiple BARs.
+ * For example, say that a bridge with a 256Mb and a 16Mb BAR is found, then
+ * the alignment is required to be 256Mb but the size 256+16Mb.
+ *
+ * In order to minimize dead space on the bus, the bounadry ordered list
+ * is reordered, example:
+ *  BUS0
+ *  |	         BUS1
+ *  |------------|
+ *  |            |-- BAR0: SIZE=256Mb, ALIGNMENT=256MB
+ *  |            |-- BAR1: SIZE=16Mb, ALIGNMENT=16MB
+ *  |            |
+ *  |            |
+ *  |            |
+ *  |            |          BUS2 (BAR_BRIDGE1: SIZE=256+16, ALIGNEMENT=256)
+ *  |            |----------|
+ *  |            |          |-- BAR2: SIZE=256Mb, ALIGNMENT=256Mb
+ *  |            |          |-- BAR3: SIZE=16Mb, ALIGNMENT=16MB
+ *
+ * A alignement/boundary ordered list of BUS1 will look like:
+ *	- BAR_BRIDGE1
+ *	- BAR0		  (ALIGMENT NEED 256Mb)
+ *	- BAR1
+ *
+ * However, Between BAR_BRIDGE1 and BAR0 will be a unused hole of 256-16Mb.
+ * We can put BAR1 before BAR0 to avoid the problem.
+ */
+static void pci_res_reorder(struct pci_res *root)
+{
+	struct pci_res *curr, *last, *curr2, *last2;
+	unsigned int start, start_next, hole_size, hole_boundary;
+
+	if (root == NULL)
+		return;
+
+	/* Make up a start address with the boundary of the
+	 * First element.
+	 */
+	start = root->boundary + root->size;
+	last = root;
+	curr = root->next;
+	while (curr) {
+
+		/* Find start address of resource */
+		start_next = (start + (curr->boundary - 1)) &
+					~(curr->boundary - 1);
+
+		/* Find hole size, the unsed space inbetween last resource
+		 *and next */
+		hole_size = start_next - start;
+
+		/* Find Boundary of START */
+		hole_boundary = 1;
+		while ((start & hole_boundary) == 0)
+			hole_boundary = hole_boundary<<1;
+
+		/* Detect dead hole */
+		if (hole_size > 0) {
+			/* Step through list and try to find a resource that
+			 * can fit into hole. Take into account hole start
+			 * boundary and hole size.
+			 */
+			last2 = curr;
+			curr2 = curr->next;
+			while (curr2) {
+				if ((curr2->boundary <= hole_boundary) &&
+					 (curr2->size <= hole_size)) {
+					/* Found matching resource. Move it
+					 * first in the hole. Then rescan, now
+					 * that the hole has changed in
+					 * size/boundary.
+					 */
+					last2->next = curr2->next;
+					curr2->next = curr;
+					last->next = curr2;
+
+					/* New Start address */
+					start_next = (start +
+						     (curr2->boundary - 1)) &
+						     ~(curr2->boundary - 1);
+					/* Since we inserted the resource before
+					 * curr we need to re-evaluate curr one
+					 * more, more resources may fit into the
+					 * shrunken hole.
+					 */
+					curr = curr2;
+					break;
+				}
+				last2 = curr2;
+				curr2 = curr2->next;
+			}
+		}
+
+		/* No hole or nothing fitted into hole. */
+		start = start_next;
+
+		last = curr;
+		curr = curr->next;
+	}
+}
+
+/* Find the total size required in PCI address space needed by a resource list*/
+static unsigned int pci_res_size(struct pci_res *root)
+{
+	struct pci_res *curr;
+	unsigned int size;
+
+	/* Get total size of all resources */
+	size = 0;
+	curr = root;
+	while (curr) {
+		size = (size + (curr->boundary - 1)) & ~(curr->boundary - 1);
+		size += curr->size;
+		curr = curr->next;
+	}
+
+	return size;
+}
+
+#if 0 /* not used for now */
+/* Free a device and secondary bus if device is a bridge */
+static void pci_dev_free(struct pci_dev *dev)
+{
+	struct pci_dev *subdev;
+	struct pci_bus *bus;
+
+	if (dev->flags & PCI_DEV_BRIDGE) {
+		bus = (struct pci_bus *)dev;
+		for (subdev = bus->devs; subdev ; subdev = subdev->next)
+			pci_dev_free(dev);
+	}
+
+	free(dev);
+}
+#endif
+
+static struct pci_dev *pci_dev_create(int isbus)
+{
+	void *ptr;
+	int size;
+
+	if (isbus)
+		size = sizeof(struct pci_bus);
+	else
+		size = sizeof(struct pci_dev);
+
+	ptr = malloc(size);
+	if (!ptr)
+		rtems_fatal_error_occurred(RTEMS_NO_MEMORY);
+	memset(ptr, 0, size);
+	return ptr;
+}
+
+static void pci_find_devs(struct pci_bus *bus)
+{
+	uint32_t id, tmp;
+	uint8_t header;
+	int slot, func, fail;
+	struct pci_dev *dev, **listptr;
+	struct pci_bus *bridge;
+	pci_dev_t pcidev;
+
+	DBG("Scanning bus %d\n", bus->num);
+
+	listptr = &bus->devs;
+	for (slot = 0; slot < PCI_MAX_DEVICES; slot++) {
+
+		/* Slot address */
+		pcidev = PCI_DEV(bus->num, slot, 0);
+
+		for (func = 0; func < PCI_MAX_FUNCTIONS; func++, pcidev++) {
+
+			fail = PCI_CFG_R32(pcidev, PCI_VENDOR_ID, &id);
+			if (fail || id == 0xffffffff || id == 0) {
+				/*
+				 * This slot is empty
+				 */
+				if (func == 0)
+					break;
+				else
+					continue;
+			}
+
+			DBG("Found PCIDEV 0x%x at (bus %x, slot %x, func %x)\n",
+							id, bus, slot, func);
+
+			/* Set command to reset values, it disables bus
+			 * mastering and address responses.
+			 */
+			PCI_CFG_W16(pcidev, PCI_COMMAND, 0);
+
+			/* Clear any already set status bits */
+			PCI_CFG_W16(pcidev, PCI_STATUS, 0xf900);
+
+			/* Set latency timer to 64 */
+			PCI_CFG_W8(pcidev, PCI_LATENCY_TIMER, 64);
+
+			PCI_CFG_R32(pcidev, PCI_CLASS_REVISION, &tmp);
+			tmp >>= 16;
+			dev = pci_dev_create(tmp == PCI_CLASS_BRIDGE_PCI);
+			*listptr = dev;
+			listptr = &dev->next;
+
+			dev->busdevfun = pcidev;
+			dev->bus = bus;
+			PCI_CFG_R16(pcidev, PCI_VENDOR_ID, &dev->vendor);
+			PCI_CFG_R16(pcidev, PCI_DEVICE_ID, &dev->device);
+			PCI_CFG_R32(pcidev, PCI_CLASS_REVISION, &dev->classrev);
+
+			if (tmp == PCI_CLASS_BRIDGE_PCI) {
+				DBG("Found PCI-PCI Bridge 0x%x at "
+				    "(bus %x, slot %x, func %x)\n",
+				    id, bus, slot, func);
+				dev->flags = PCI_DEV_BRIDGE;
+				dev->subvendor = 0;
+				dev->subdevice = 0;
+				bridge = (struct pci_bus *)dev;
+				bridge->num = bus->sord + 1;
+				bridge->pri = bus->num;
+				bridge->sord = bus->sord + 1;
+
+				/* Configure bridge (no support for 64-bit) */
+				PCI_CFG_W32(pcidev, 0x28, 0);
+				PCI_CFG_W32(pcidev, 0x2C, 0);
+				tmp = (64 << 24) | (0xff << 16) |
+				      (bridge->num << 8) | bridge->pri;
+				PCI_CFG_W32(pcidev, PCI_PRIMARY_BUS, tmp);
+
+				/* Scan Secondary Bus */
+				pci_find_devs(bridge);
+
+				/* sord might have been updated */
+				PCI_CFG_W8(pcidev, 0x1a, bridge->sord);
+				bus->sord = bridge->sord;
+
+				DBG("PCI-PCI BRIDGE: Primary %x, Secondary %x, "
+				    "Subordinate %x\n",
+				    bridge->pri, bridge->num, bridge->sord);
+			} else {
+				/* Disable Cardbus CIS Pointer */
+				PCI_CFG_W32(pcidev, PCI_CARDBUS_CIS, 0);
+
+				/* Devices have subsytem device and vendor ID */
+				PCI_CFG_R16(pcidev, PCI_SUBSYSTEM_VENDOR_ID,
+							&dev->subvendor);
+				PCI_CFG_R16(pcidev, PCI_SUBSYSTEM_ID,
+							&dev->subdevice);
+			}
+
+			/* Stop if not a multi-function device */
+			if (func == 0) {
+				pci_cfg_r8(pcidev, PCI_HEADER_TYPE, &header);
+				if ((header & PCI_MULTI_FUNCTION) == 0)
+					break;
+			}
+		}
+	}
+}
+
+static void pci_find_bar(struct pci_dev *dev, int bar)
+{
+	uint32_t size, disable, mask;
+	struct pci_res *res = &dev->resources[bar];
+	pci_dev_t pcidev = dev->busdevfun;
+	int ofs;
+#ifdef DEBUG
+	char *str;
+#define DBG_SET_STR(str, val) str = (val)
+#else
+#define DBG_SET_STR(str, val)
+#endif
+
+	DBG("Bus: %x, Slot: %x, function: %x, bar%d\n",
+		PCI_DEV_EXPAND(pcidev), bar);
+
+	res->bar = bar;
+	if (bar == DEV_RES_ROM) {
+		if (dev->flags & PCI_DEV_BRIDGE)
+			ofs = PCI_ROM_ADDRESS1;
+		else
+			ofs = PCI_ROM_ADDRESS;
+		disable = 0; /* ROM BARs have a unique enable bit per BAR */
+	} else {
+		ofs = PCI_BASE_ADDRESS_0 + (bar << 2);
+		disable = pci_invalid_address;
+	}
+
+	PCI_CFG_W32(pcidev, ofs, 0xffffffff);
+	PCI_CFG_R32(pcidev, ofs, &size);
+	PCI_CFG_W32(pcidev, ofs, disable);
+
+	if (size == 0 || size == 0xffffffff)
+		return;
+	if (bar == DEV_RES_ROM) {
+		mask = PCI_ROM_ADDRESS_MASK;
+		DBG_SET_STR(str, "ROM");
+		if (dev->bus->flags & PCI_BUS_MEM)
+			res->flags = PCI_RES_MEM;
+		else
+			res->flags = PCI_RES_MEMIO;
+	} else if (((size & 0x1) == 0) && (size & 0x6)) {
+		/* unsupported Memory type */
+		PCI_CFG_W32(pcidev, ofs, 0);
+		return;
+	} else {
+		mask = ~0xf;
+		if (size & 0x1) {
+			/* I/O */
+			mask = ~0x3;
+			res->flags = PCI_RES_IO;
+			DBG_SET_STR(str, "I/O");
+			if (size & 0xffff0000)
+				res->flags |= PCI_RES_IO32;
+			/* Limit size of I/O space to 256 byte */
+			size |= 0xffffff00;
+			if ((dev->bus->flags & PCI_BUS_IO) == 0) {
+				res->flags |= PCI_RES_FAIL;
+				dev->flags |= PCI_DEV_RES_FAIL;
+			}
+		} else {
+			/* Memory. We convert Prefetchable Memory BARs to Memory
+			 * BARs in case the Bridge does not support prefetchable
+			 * memory.
+			 */
+			if ((size & 0x8) && (dev->bus->flags & PCI_BUS_MEM)) {
+				/* Prefetchable and Bus supports it */
+				res->flags = PCI_RES_MEM;
+				DBG_SET_STR(str, "MEM");
+			} else {
+				res->flags = PCI_RES_MEMIO;
+				DBG_SET_STR(str, "MEMIO");
+			}
+		}
+	}
+	size &= mask;
+	res->size = ~size + 1;
+	res->boundary = ~size + 1;
+
+	DBG("Bus: %x, Slot: %x, function: %x, %s bar%d size: %x\n",
+		PCI_DEV_EXPAND(pcidev), str, bar, res->size);
+}
+
+static int pci_find_res_dev(struct pci_dev *dev, void *unused)
+{
+	struct pci_bus *bridge;
+	uint32_t tmp;
+	uint16_t tmp16;
+	pci_dev_t pcidev = dev->busdevfun;
+	int i, maxbars;
+
+	if (dev->flags & PCI_DEV_BRIDGE) {
+		/* PCI-PCI Bridge */
+		bridge = (struct pci_bus *)dev;
+
+		/* Only 2 Bridge BARs */
+		maxbars = 2;
+
+		/* Probe Bridge Spaces (MEMIO space always implemented), the
+		 * probe disables all space-decoding at the same time
+		 */
+		PCI_CFG_W32(pcidev, 0x30, 0);
+		PCI_CFG_W16(pcidev, 0x1c, 0x00f0);
+		PCI_CFG_R16(pcidev, 0x1c, &tmp16);
+		if (tmp16 != 0) {
+			bridge->flags |= PCI_BUS_IO;
+			if (tmp16 & 0x1)
+				bridge->flags |= PCI_BUS_IO32;
+		}
+
+		PCI_CFG_W32(pcidev, 0x24, 0x0000ffff);
+		PCI_CFG_R32(pcidev, 0x24, &tmp);
+		if (tmp != 0)
+			bridge->flags |= PCI_BUS_MEM;
+
+		PCI_CFG_W32(pcidev, 0x20, 0x0000ffff);
+		bridge->flags |= PCI_BUS_MEMIO;
+	} else {
+		/* Normal PCI Device as max 6 BARs */
+		maxbars = 6;
+	}
+
+	/* Probe BARs */
+	for (i = 0; i < maxbars; i++)
+		pci_find_bar(dev, i);
+	pci_find_bar(dev, DEV_RES_ROM);
+
+	return 0;
+}
+
+static int pci_add_res_dev(struct pci_dev *dev, void *arg);
+
+static void pci_add_res_bus(struct pci_bus *bus, int type)
+{
+	int tindex = type - 1;
+
+	/* Clear old resources */
+	bus->busres[tindex] = NULL;
+
+	/* Add resources of devices behind bridge if bridge supports
+	 * resource type. If MEM space not supported by bridge, they are
+	 * converted to MEMIO in the process.
+	 */
+	if (!((type == PCI_BUS_IO) && ((bus->flags & PCI_BUS_IO) == 0))) {
+		pci_for_each_child(bus, pci_add_res_dev, (void *)type, 0);
+
+		/* Reorder Bus resources to fit more optimally (avoid dead
+		 * PCI space). Currently they are sorted by boundary and size.
+		 *
+		 * This is especially important when multiple buses (bridges)
+		 * are present.
+		 */
+		pci_res_reorder(bus->busres[tindex]);
+	}
+}
+
+static int pci_add_res_dev(struct pci_dev *dev, void *arg)
+{
+	int tindex, type = (int)arg;
+	struct pci_bus *bridge;
+	struct pci_res *res, *first_busres;
+	int i;
+	uint32_t bbound;
+
+	/* Type index in Bus resource */
+	tindex = type - 1;
+
+	if (dev->flags & PCI_DEV_BRIDGE) {
+		/* PCI-PCI Bridge. Add all sub-bus resources first */
+		bridge = (struct pci_bus *)dev;
+
+		/* Add all child device's resources to this type */
+		pci_add_res_bus(bridge, type);
+
+		/* Propagate the resources from child bus to BAR on
+		 * this bus, by adding a "fake" BAR per type.
+		 */
+		res = &bridge->dev.resources[BUS_RES_START + tindex];
+		res->bar = BUS_RES_START + tindex;
+		res->start = 0;
+		res->end = 0;
+		res->flags = 0; /* mark BAR resource not available */
+		first_busres = bridge->busres[tindex];
+		if (first_busres) {
+			res->flags = type;
+			res->size = pci_res_size(first_busres);
+			res->boundary = first_busres->boundary;
+			if (type == PCI_RES_IO) {
+				bbound = 0x1000; /* Bridge I/O min 4KB */
+			} else {
+				bbound = 0x100000; /* Bridge MEM min 1MB */
+
+				/* Convert MEM to MEMIO if not supported by
+				 * this bridge
+				 */
+				if ((bridge->flags & PCI_BUS_MEM) == 0)
+					res->flags = PCI_RES_MEMIO;
+			}
+			/* Fulfil minimum bridge boundary */
+			if (res->boundary < bbound)
+				res->boundary = bbound;
+			/* Make sure that size is atleast bridge boundary */
+			if (res->size > bbound && (res->size & (bbound-1)))
+				res->size = (res->size | (bbound-1)) + 1;
+		}
+	}
+
+	/* Normal PCI Device as max 6 BARs and a ROM Bar.
+	 * Insert BARs into the sorted resource list.
+	 */
+	for (i = 0; i < DEV_RES_CNT; i++) {
+		res = &dev->resources[i];
+		if ((res->flags & PCI_RES_TYPE_MASK) != type)
+			continue;
+		pci_res_insert(&dev->bus->busres[tindex], res);
+	}
+
+	return 0;
+}
+
+/* Function assumes that base is properly aligned to the requirement of the
+ * largest BAR in the system.
+ */
+static uint32_t pci_alloc_res(struct pci_bus *bus, int type,
+			    uint32_t start, uint32_t end)
+{
+	struct pci_dev *dev;
+	struct pci_res *res, **prev_next;
+	unsigned long starttmp;
+	struct pci_bus *bridge;
+	int removed, sec_type;
+
+	/* The resources are sorted on their size (size and alignment is the
+	 * same)
+	 */
+	prev_next = &bus->busres[type - 1];
+	while ((res = *prev_next) != NULL) {
+
+		dev = RES2DEV(res);
+		removed = 0;
+
+		/* Align start to this reource's need, only needed after
+		 * a bridge resource has been allocated.
+		 */
+		starttmp = (start + (res->boundary-1)) & ~(res->boundary-1);
+
+		if ((starttmp + res->size - 1) > end) {
+			/* Not enough memory available for this resource */
+			printk("PCI[%x:%x:%x]: DEV BAR%d (%d): no resource "
+			       "assigned\n",
+			       PCI_DEV_EXPAND(dev->busdevfun),
+			       res->bar, res->flags & PCI_RES_TYPE_MASK);
+			res->start = res->end = 0;
+
+			/* If this resources is a bridge window to the
+			 * secondary bus, the secondary resources are not
+			 * changed which has the following effect:
+			 *  I/O    :  Will never be assigned
+			 *  MEMIO  :  Will never be assigned
+			 *  MEM    :  Will stay marked as MEM, but bridge window
+			 *            is changed into MEMIO, when the window is
+			 *            assigned a MEMIO address the secondary
+			 *            resources will also be assigned.
+			 */
+
+			if (type == PCI_RES_MEM) {
+				/* Try prefetchable as non-prefetchable mem */
+				res->flags &= ~PCI_RES_MEM_PREFETCH;
+				/* Remove resource from MEM list, ideally we
+				 * should regenerate this list in order to fit
+				 * the comming BARs more optimially...
+				 */
+				*prev_next = res->next;
+				/* We should not update prev_next here since
+				 * we just removed the resource from the list
+				 */
+				removed = 1;
+			} else {
+				res->flags |= PCI_RES_FAIL;
+				dev->flags |= PCI_DEV_RES_FAIL;
+			}
+		} else {
+			start = starttmp;
+
+			res->start = start;
+			res->end = start + res->size;
+
+			/* "Virtual BAR" on a bridge? A bridge resource need all
+			 * its child devices resources allocated
+			 */
+			if ((res->bar != DEV_RES_ROM) &&
+			    (dev->flags & PCI_DEV_BRIDGE) &&
+			    (res->bar >= BUS_RES_START)) {
+				bridge = (struct pci_bus *)dev;
+				/* If MEM bar was changed into a MEMIO the
+				 * secondary MEM resources are still set to MEM,
+				 */
+				if (type == PCI_BUS_MEMIO &&
+				    res->bar == BRIDGE_RES_MEM)
+					sec_type = PCI_RES_MEM;
+				else
+					sec_type = type;
+
+				pci_alloc_res(bridge, sec_type, res->start,
+						res->end);
+			}
+
+			start += res->size;
+		}
+		if (removed == 0)
+			prev_next = &res->next;
+	}
+
+	return start;
+}
+
+static void pci_set_bar(struct pci_dev *dev, int residx)
+{
+	uint32_t tmp;
+	uint16_t tmp16;
+	pci_dev_t pcidev;
+	struct pci_res *res;
+	int is_bridge, ofs;
+
+	res = &dev->resources[residx];
+	pcidev = dev->busdevfun;
+
+	if ((res->flags == 0) || (res->flags & PCI_RES_FAIL))
+		return;
+
+	is_bridge = dev->flags & PCI_DEV_BRIDGE;
+
+	if (res->bar == DEV_RES_ROM) {
+		/* ROM: 32-bit prefetchable memory BAR */
+		if (is_bridge)
+			ofs = PCI_ROM_ADDRESS1;
+		else
+			ofs = PCI_ROM_ADDRESS;
+		PCI_CFG_W32(pcidev, ofs, res->start | PCI_ROM_ADDRESS_ENABLE);
+		DBG("PCI[%x:%x:%x]: ROM BAR: 0x%x-0x%x\n",
+			PCI_DEV_EXPAND(pcidev), res->start, res->end);
+	} else if (is_bridge && (res->bar == BRIDGE_RES_IO)) {
+		/* PCI Bridge I/O BAR */
+		DBG("PCI[%x:%x:%x]: BAR 1C: 0x%x-0x%x\n",
+			PCI_DEV_EXPAND(pcidev), res->start, res->end);
+
+		/* Limit and Base */
+		tmp16 = ((res->end-1) & 0x0000f000) |
+			((res->start & 0x0000f000) >> 8);
+		tmp = ((res->end-1) & 0xffff0000) | (res->start >> 16);
+
+		DBG("PCI[%x:%x:%x]: BRIDGE BAR 0x%x: 0x%08x [0x30: 0x%x]\n",
+			PCI_DEV_EXPAND(pcidev), 0x1C, tmp, tmp2);
+		PCI_CFG_W16(pcidev, 0x1C, tmp16);
+		PCI_CFG_W32(pcidev, 0x30, tmp);
+	} else if (is_bridge && (res->bar >= BRIDGE_RES_MEMIO)) {
+		/* PCI Bridge MEM and MEMIO Space */
+
+		/* Limit and Base */
+		tmp = ((res->end-1) & 0xfff00000) | (res->start >> 16);
+
+		DBG("PCI[%x:%x:%x]: BRIDGE BAR 0x%x: 0x%08x\n",
+			PCI_DEV_EXPAND(pcidev),
+			0x20 + (res->bar-BRIDGE_RES_MEMIO)*4, tmp);
+		PCI_CFG_W32(pcidev, 0x20+(res->bar-BRIDGE_RES_MEMIO)*4, tmp);
+	} else {
+		/* PCI Device */
+		DBG("PCI[%x:%x:%x]: DEV BAR%d: 0x%08x\n",
+			PCI_DEV_EXPAND(pcidev), res->bar, res->start);
+		ofs = PCI_BASE_ADDRESS_0 + res->bar*4;
+		PCI_CFG_W32(pcidev, ofs, res->start);
+	}
+
+	/* Enable Memory or I/O responses */
+	if ((res->flags & PCI_RES_TYPE_MASK) == PCI_RES_IO)
+		pci_io_enable(pcidev);
+	else
+		pci_mem_enable(pcidev);
+
+	/* Enable Master if bridge */
+	if (is_bridge)
+		pci_master_enable(pcidev);
+}
+
+static int pci_set_res_dev(struct pci_dev *dev, void *unused)
+{
+	int i, maxbars;
+
+	if (dev->flags & PCI_DEV_BRIDGE)
+		maxbars = 2 + 3; /* 2 BARs + 3 Bridge-Windows "Virtual BARs" */
+	else
+		maxbars = 6; /* Normal PCI Device as max 6 BARs. */
+
+	/* Set BAR resources with previous allocated values */
+	for (i = 0; i < maxbars; i++)
+		pci_set_bar(dev, i);
+	pci_set_bar(dev, DEV_RES_ROM);
+
+	return 0;
+}
+
+/* Route IRQ through PCI-PCI Bridges */
+static int pci_route_irq(pci_dev_t dev, int irq_pin)
+{
+	int slot_grp;
+
+	if (PCI_DEV_BUS(dev) == 0)
+		return irq_pin;
+
+	slot_grp = PCI_DEV_SLOT(dev) & 0x3;
+
+	return (((irq_pin - 1) + slot_grp) & 0x3) + 1;
+}
+
+/* Put assigned system IRQ into PCI interrupt line information field.
+ * This is to make it possible for drivers to read system IRQ / Vector from
+ * configuration space later on.
+ *
+ * 1. Get Interrupt PIN
+ * 2. Route PIN to host bridge
+ * 3. Get System interrupt number assignment for PIN
+ * 4. Set Interrupt LINE
+ */
+static int pci_set_irq_dev(struct pci_dev *dev, void *cfg)
+{
+	struct pci_auto_setup *autocfg = cfg;
+	uint8_t irq_pin, irq_line, *psysirq;
+	pci_dev_t pcidev;
+
+	psysirq = &dev->sysirq;
+	pcidev = dev->busdevfun;
+	PCI_CFG_R8(pcidev, PCI_INTERRUPT_PIN, &irq_pin);
+
+	/* perform IRQ routing until we reach host bridge */
+	while (dev->bus && irq_pin != 0) {
+		irq_pin = autocfg->irq_route(dev->busdevfun, irq_pin);
+		dev = &dev->bus->dev;
+	}
+
+	/* Get IRQ from PIN on PCI bus0 */
+	if (irq_pin != 0 && autocfg->irq_map)
+		irq_line = autocfg->irq_map(dev->busdevfun, irq_pin);
+	else
+		irq_line = 0;
+
+	*psysirq = irq_line;
+
+	/* Set System Interrupt/Vector for device. 0 means no-IRQ */
+	PCI_CFG_W8(pcidev, PCI_INTERRUPT_LINE, irq_line);
+
+	return 0;
+}
+
+/* This routine assumes that PCI access library has been successfully
+ * initialized. All information about the PCI bus needed is found in
+ * the argument.
+ *
+ * The PCI buses are enumerated as bridges are found, PCI devices are
+ * setup with BARs and IRQs, etc.
+ */
+int pci_config_auto(void)
+{
+	uint32_t end;
+	uint32_t startmemio, startmem, startio;
+	struct pci_auto_setup *autocfg = &pci_auto_cfg;
+#ifdef DEBUG
+	uint32_t endmemio, endmem, endio;
+	uint32_t start;
+#endif
+
+	if (pci_config_auto_initialized == 0)
+		return -1; /* no config given to library */
+
+#ifdef DEBUG
+	DBG("\n--- PCI MEMORY AVAILABLE ---\n");
+	if (autocfg->mem_size) {
+		start = autocfg->mem_start;
+		end = autocfg->mem_start + autocfg->mem_size - 1;
+		DBG(" MEM AVAIL [0x%08x-0x%08x]\n", start, end);
+	} else {
+		/* One big memory space */
+		DBG(" MEM share the space with MEMIO\n");
+	}
+	/* no-prefetchable memory space need separate memory space.
+	 * For example PCI controller maps this region non-cachable.
+	 */
+	start = autocfg->memio_start;
+	end = autocfg->memio_start + autocfg->memio_size - 1;
+	DBG(" MEMIO AVAIL [0x%08x-0x%08x]\n", start, end);
+	if (autocfg->io_size) {
+		start = autocfg->io_start;
+		end = autocfg->io_start + autocfg->io_size - 1;
+		DBG(" I/O AVAIL [0x%08x-0x%08x]\n", start, end);
+	} else {
+		DBG(" I/O Space not available\n");
+	}
+#endif
+
+	/* Init Host-Bridge */
+	memset(&pci_hb, 0, sizeof(pci_hb));
+	pci_hb.dev.flags = PCI_DEV_BRIDGE;
+	if (autocfg->memio_size <= 0)
+		return -1;
+	pci_hb.flags = PCI_BUS_MEMIO;
+	if (autocfg->mem_size)
+		pci_hb.flags |= PCI_BUS_MEM;
+	if (autocfg->io_size)
+		pci_hb.flags |= PCI_BUS_IO;
+
+	/* Find all PCI devices/functions on all buses. The buses will be
+	 * enumrated (assigned a unique PCI Bus ID 0..255).
+	 */
+	DBG("\n--- PCI SCANNING ---\n");
+	pci_find_devs(&pci_hb);
+	pci_bus_cnt = pci_hb.sord + 1;
+	if (pci_hb.devs == NULL)
+		return 0;
+
+	pci_system_type = PCI_SYSTEM_HOST;
+
+	/* Find all resources (MEM/MEMIO/IO BARs) of all devices/functions
+	 * on all buses.
+	 *
+	 * Device resources behind bridges which does not support prefetchable
+	 * memory are already marked as non-prefetchable memory.
+	 * Devices which as I/O resources behind a bridge that do not support
+	 * I/O space are marked DISABLED.
+	 *
+	 * All BARs and Bridge Spaces are disabled after this. Only the ones
+	 * that are allocated an address are initilized later on.
+	 */
+	DBG("\n\n--- PCI RESOURCES ---\n");
+	pci_for_each_dev(pci_find_res_dev, 0);
+
+	/* Add all device's resources to bus and sort them to fit in the PCI
+	 * Window. The device resources are propagated upwards through bridges
+	 * by adding a "virtual" BAR (boundary != BAR size).
+	 *
+	 * We wait with MEMIO (non-prefetchable memory) resources to after MEM
+	 * resources have been allocated, so that MEM resources can be changed
+	 * into MEMIO resources if not enough space.
+	 */
+	pci_add_res_bus(&pci_hb, PCI_RES_IO);
+	pci_add_res_bus(&pci_hb, PCI_RES_MEM);
+
+	/* Start assigning found resource according to the sorted order. */
+
+	/* Allocate resources to I/O areas */
+	if (pci_hb.busres[BUS_RES_IO]) {
+		startio = autocfg->io_start;
+		end = startio + autocfg->io_size;
+#ifdef DEBUG
+		endio =
+#endif
+			pci_alloc_res(&pci_hb, PCI_RES_IO, startio, end);
+	}
+
+	/* Allocate resources to prefetchable memory */
+	if (pci_hb.busres[BUS_RES_MEM]) {
+		startmem = autocfg->mem_start;
+		end = startmem + autocfg->mem_size;
+#ifdef DEBUG
+		endmem =
+#endif
+			pci_alloc_res(&pci_hb, PCI_RES_MEM, startmem, end);
+	}
+
+	/* Add non-prefetchable memory resources and not fitting prefetchable
+	 * memory resources.
+	 *
+	 * Some prefetchable memory resources may not have fitted into PCI
+	 * window. Prefetchable memory can be mapped into non-prefetchable
+	 * memory window. The failing BARs have been marked as MEMIO instead.
+	 */
+	pci_add_res_bus(&pci_hb, PCI_RES_MEMIO);
+
+	/* Allocate resources to non-prefetchable memory */
+	if (pci_hb.busres[BUS_RES_MEMIO]) {
+		startmemio = autocfg->memio_start;
+		end = startmemio + autocfg->memio_size;
+#ifdef DEBUG
+		endmemio =
+#endif
+			pci_alloc_res(&pci_hb, PCI_RES_MEMIO, startmemio, end);
+	}
+
+	DBG("\n--- PCI ALLOCATED SPACE RANGES ---\n");
+	DBG(" MEM NON-PREFETCHABLE: [0x%08x-0x%08x]\n", startmemio, endmemio);
+	DBG(" MEM PREFETCHABLE:	    [0x%08x-0x%08x]\n", startmem, endmem);
+	DBG(" I/O:                  [0x%08x-0x%08x]\n", startio, endio);
+
+	/* Set all allocated BARs and Bridge Windows */
+	pci_for_each_dev(pci_set_res_dev, NULL);
+
+	/* Initialize IRQs of all devices. According to the PCI-PCI bridge
+	 * specification the IRQs are routed differently depending on slot
+	 * number. Drivers can override the default routing if a motherboard
+	 * requires it.
+	 */
+	if ((autocfg->options & CFGOPT_NOSETUP_IRQ) == 0) {
+		if (autocfg->irq_route == NULL) /* use standard irq routing */
+			autocfg->irq_route = pci_route_irq;
+		pci_for_each_dev(pci_set_irq_dev, autocfg);
+	}
+
+	DBG("PCI resource allocation done\n");
+
+	return 0;
+}
+
+void pci_config_auto_register(void *config)
+{
+	pci_config_auto_initialized = 1;
+	memcpy(&pci_auto_cfg, config, sizeof(struct pci_auto_setup));
+}
diff --git a/cpukit/libpci/pci_cfg_peripheral.c b/cpukit/libpci/pci_cfg_peripheral.c
new file mode 100644
index 0000000..d1ba4c9
--- /dev/null
+++ b/cpukit/libpci/pci_cfg_peripheral.c
@@ -0,0 +1,32 @@
+/*  PCI (Peripheral) Configuration Library
+ *
+ *  COPYRIGHT (c) 2011.
+ *  Cobham Gaisler AB.
+ *
+ *  The license and distribution terms for this file may be
+ *  found in the file LICENSE in this distribution or at
+ *  http://www.rtems.com/license/LICENSE.
+ */
+
+/*
+ *
+ *  The Host Bridge bus must be declared by user. It contain the static
+ *  configuration used to setup the devices/functions.
+ */
+
+/* Configure headers */
+#define PCI_CFG_PERIPHERAL_LIB
+
+#include <pci/cfg.h>
+
+/* Number of buses */
+extern int pci_bus_cnt;
+
+/* Assume that user has defined static setup array in pci_hb */
+int pci_config_peripheral(void)
+{
+	pci_bus_cnt = pci_hb.sord + 1;
+	pci_system_type = PCI_SYSTEM_PERIPHERAL;
+
+	return 0;
+}
diff --git a/cpukit/libpci/pci_cfg_print_code.c b/cpukit/libpci/pci_cfg_print_code.c
new file mode 100644
index 0000000..8770c8a
--- /dev/null
+++ b/cpukit/libpci/pci_cfg_print_code.c
@@ -0,0 +1,172 @@
+/* PCI (Static) Configuration Library. PCI Configuration C code console
+ * printout routines that can be used to build a static PCI configuration.
+ *
+ *  COPYRIGHT (c) 2010.
+ *  Cobham Gaisler AB.
+ *
+ *  The license and distribution terms for this file may be
+ *  found in the file LICENSE in this distribution or at
+ *  http://www.rtems.com/license/LICENSE.
+ */
+
+#include <rtems.h>
+#include <stdio.h>
+#include <pci/cfg.h>
+
+int pci_cfg_print_bus(struct pci_bus *bus);
+
+static void get_bus_name(struct pci_bus *bus, char *buf)
+{
+	if (bus->num == 0)
+		strcpy(buf, "pci_hb");
+	else
+		sprintf(buf, "bus%d", bus->num);
+}
+
+static void get_device_name(struct pci_dev *dev, char *buf)
+{
+	char busname[64];
+
+	if (dev->flags & PCI_DEV_BRIDGE) {
+		get_bus_name((struct pci_bus *)dev, busname);
+		sprintf(buf, "%s.dev", busname);
+	} else {
+		sprintf(buf, "dev_%x_%x_%x", PCI_DEV_EXPAND(dev->busdevfun));
+	}
+}
+
+static void pci_cfg_print_resources(struct pci_res *resources, char *prefix)
+{
+	struct pci_res *res;
+	int i;
+
+	for (i = 0; i < DEV_RES_CNT; i++) {
+		res = &resources[i];
+		if (((res->flags & PCI_RES_TYPE_MASK) == 0) ||
+		    ((res->flags & PCI_RES_FAIL) == PCI_RES_FAIL)) {
+			printf("%sPCIRES_EMPTY,\n", prefix);
+			continue;
+		}
+		printf("%s{\n", prefix);
+		printf("%s\t.next = NULL,\n", prefix);
+		printf("%s\t.size = 0x%08lx,\n", prefix, res->size);
+		printf("%s\t.boundary = 0x%08lx,\n", prefix, res->boundary);
+		printf("%s\t.flags = 0x%x,\n", prefix, res->flags);
+		printf("%s\t.bar = %d,\n", prefix, i);
+		printf("%s\t.start = 0x%08lx,\n", prefix, res->start);
+		printf("%s\t.end = 0x%08lx,\n", prefix, res->end);
+		printf("%s},\n", prefix);
+	}
+}
+
+static void pci_cfg_print_device(struct pci_dev *dev, char *prefix)
+{
+	char name[32];
+	char buf[8];
+	printf("%s.resources = {\n", prefix);
+	strcpy(buf, prefix);
+	strcat(buf, "\t");
+	pci_cfg_print_resources(dev->resources, buf);
+	printf("%s},\n", prefix);
+	if (dev->next == NULL) {
+		printf("%s.next = NULL,\n", prefix);
+	} else {
+		get_device_name(dev->next, name);
+		printf("%s.next = &%s,\n", prefix, name);
+	}
+	if (!dev->bus) { /* Host Bridge? */
+		printf("%s.bus = NULL,\n", prefix);
+	} else {
+		get_bus_name(dev->bus, name);
+		printf("%s.bus = &%s,\n", prefix, name);
+	}
+
+	printf("%s.busdevfun = 0x%04x,\n", prefix, dev->busdevfun);
+	printf("%s.flags = 0x%x,\n", prefix, dev->flags);
+	printf("%s.sysirq = %d,\n", prefix, dev->sysirq);
+	printf("%s.vendor = 0x%04x,\n", prefix, dev->vendor);
+	printf("%s.device = 0x%04x,\n", prefix, dev->device);
+	printf("%s.subvendor = 0x%04x,\n", prefix, dev->subvendor);
+	printf("%s.subdevice = 0x%04x,\n", prefix, dev->subdevice);
+	printf("%s.classrev = 0x%08lx,\n", prefix, dev->classrev);
+	printf("%s.command = 0,\n", prefix);
+}
+
+static int pci_cfg_print_dev(struct pci_dev *dev, void *unused)
+{
+	if (dev->flags & PCI_DEV_BRIDGE) {
+		pci_cfg_print_bus((struct pci_bus *)dev);
+	} else {
+		printf("\n\n/* PCI DEV at [%x:%x:%x] */\n",
+			PCI_DEV_EXPAND(dev->busdevfun));
+		printf("static struct pci_dev dev_%x_%x_%x = {\n",
+			PCI_DEV_EXPAND(dev->busdevfun));
+		pci_cfg_print_device(dev, "\t");
+		printf("};\n");
+	}
+	return 0;
+}
+
+int pci_cfg_print_bus(struct pci_bus *bus)
+{
+	char name[32];
+
+	/* Print Bus */
+	printf("\n\n/* PCI BUS %d - Bridge at [%x:%x:%x] */\n\n",
+		bus->num, PCI_DEV_EXPAND(bus->dev.busdevfun));
+	get_bus_name(bus, name);
+	printf("%sstruct pci_bus %s = {\n",
+		bus->num == 0 ? "" : "static ", name);
+	printf("\t.dev = {\n");
+	pci_cfg_print_device(&bus->dev, "\t\t");
+	printf("\t},\n");
+	if (bus->devs == NULL) {
+		printf("\t.devs = NULL,\n");
+	} else {
+		get_device_name(bus->devs, name);
+		printf("\t.devs = &%s,\n", name);
+	}
+	printf("\t.flags = 0x%x,\n", bus->flags);
+	printf("\t.num = %d,\n", bus->num);
+	printf("\t.pri = %d,\n", bus->pri);
+	printf("\t.sord = %d,\n", bus->sord);
+	printf("};\n");
+
+	/* Print all child devices */
+	pci_for_each_child(bus, pci_cfg_print_dev, NULL, 0);
+
+	return 0;
+}
+
+static int pci_cfg_print_forw_dev(struct pci_dev *dev, void *unused)
+{
+	if ((dev->flags & PCI_DEV_BRIDGE) == 0) {
+		printf("static struct pci_dev dev_%x_%x_%x;\n",
+			PCI_DEV_EXPAND(dev->busdevfun));
+	}
+	return 0;
+}
+
+void pci_cfg_print(void)
+{
+	int i;
+
+	printf("\n\n/*** PCI Configuration ***/\n\n");
+	printf("#include <stdlib.h>\n");
+	printf("#define PCI_CFG_STATIC_LIB\n");
+	printf("#include <pci/cfg.h>\n\n");
+	printf("#define PCIRES_EMPTY {0}\n\n");
+
+	/* Forward declaration for all devices / buses */
+	printf("/* FORWARD BUS DECLARATIONS */\n");
+	for (i = 0; i < pci_bus_count(); i++) {
+		if (i == 0)
+			printf("struct pci_bus pci_hb;\n");
+		else
+			printf("static struct pci_bus bus%d;\n", i);
+	}
+	printf("\n/* FORWARD DEVICE DECLARATIONS */\n");
+	pci_for_each_dev(pci_cfg_print_forw_dev, NULL);
+
+	pci_cfg_print_bus(&pci_hb);
+}
diff --git a/cpukit/libpci/pci_cfg_read.c b/cpukit/libpci/pci_cfg_read.c
new file mode 100644
index 0000000..2db465d
--- /dev/null
+++ b/cpukit/libpci/pci_cfg_read.c
@@ -0,0 +1,357 @@
+/*  Read current PCI configuration that bootloader or BIOS has already setup
+ *  and initialize the PCI structures.
+ *
+ *  COPYRIGHT (c) 2010.
+ *  Cobham Gaisler AB.
+ *
+ *  The license and distribution terms for this file may be
+ *  found in the file LICENSE in this distribution or at
+ *  http://www.rtems.com/license/LICENSE.
+ */
+
+#include <rtems.h>
+#include <stdlib.h>
+#include <rtems/bspIo.h>
+#include <pci/cfg.h>
+#include <pci/access.h>
+
+/* PCI Library
+ * (For debugging it might be good to use other functions or the driver's
+ *  directly)
+ */
+#define PCI_CFG_R8(dev, args...) pci_cfg_r8(dev, args)
+#define PCI_CFG_R16(dev, args...) pci_cfg_r16(dev, args)
+#define PCI_CFG_R32(dev, args...) pci_cfg_r32(dev, args)
+#define PCI_CFG_W8(dev, args...) pci_cfg_w8(dev, args)
+#define PCI_CFG_W16(dev, args...) pci_cfg_w16(dev, args)
+#define PCI_CFG_W32(dev, args...) pci_cfg_w32(dev, args)
+
+#ifdef DEBUG
+#define DBG(args...)	printk(args)
+#else
+#define DBG(args...)
+#endif
+
+/* Number of buses */
+extern int pci_bus_cnt;
+
+/* The Host Bridge bus is initialized here */
+extern struct pci_bus pci_hb;
+
+static struct pci_dev *pci_dev_create(int isbus)
+{
+	void *ptr;
+	int size;
+
+	if (isbus)
+		size = sizeof(struct pci_bus);
+	else
+		size = sizeof(struct pci_dev);
+
+	ptr = malloc(size);
+	if (!ptr)
+		rtems_fatal_error_occurred(RTEMS_NO_MEMORY);
+	memset(ptr, 0, size);
+	return ptr;
+}
+
+/* Check if address is accessible from host */
+static int pci_read_addressable(struct pci_dev *dev, struct pci_res *res)
+{
+	struct pci_bus *bus = dev->bus;
+	int type = res->flags & PCI_RES_TYPE_MASK;
+	struct pci_res *range0, *range1;
+
+	if (type == PCI_BUS_IO && (bus->flags & PCI_BUS_IO) == 0)
+		return 0;
+
+	/* Assume that host bridge can access all */
+	if (bus->pri == 0)
+		return 1;
+
+	range1 = NULL;
+	switch (type) {
+	case PCI_RES_IO:
+		range0 = &bus->dev.resources[BRIDGE_RES_IO];
+		break;
+	case PCI_RES_MEM:
+		range1 = &bus->dev.resources[BRIDGE_RES_MEM];
+	default:
+	case PCI_RES_MEMIO:
+		range0 = &bus->dev.resources[BRIDGE_RES_MEMIO];
+		break;
+	}
+	if ((res->start >= range0->start) && (res->end <= range0->end)) {
+		return pci_read_addressable(&bus->dev, range0);
+	} else if (range1 && (res->start >= range1->start) &&
+			(res->end <= range1->end)) {
+		return pci_read_addressable(&bus->dev, range1);
+	}
+
+	return 0;
+}
+
+static void pci_read_bar(struct pci_dev *dev, int bar)
+{
+	uint32_t orig, size, mask;
+	struct pci_res *res = &dev->resources[bar];
+	pci_dev_t pcidev = dev->busdevfun;
+	int ofs;
+#ifdef DEBUG
+	char *str;
+#define DBG_SET_STR(str, val) str = (val)
+#else
+#define DBG_SET_STR(str, val)
+#endif
+
+	DBG("Bus: %x, Slot: %x, function: %x, bar%d\n",
+		PCI_DEV_EXPAND(pcidev), bar);
+
+	res->bar = bar;
+	if (bar == DEV_RES_ROM) {
+		if (dev->flags & PCI_DEV_BRIDGE)
+			ofs = PCI_ROM_ADDRESS1;
+		else
+			ofs = PCI_ROM_ADDRESS;
+	} else {
+		ofs = PCI_BASE_ADDRESS_0 + (bar << 2);
+	}
+
+	PCI_CFG_R32(pcidev, ofs, &orig);
+	PCI_CFG_W32(pcidev, ofs, 0xffffffff);
+	PCI_CFG_R32(pcidev, ofs, &size);
+	PCI_CFG_W32(pcidev, ofs, orig);
+
+	if (size == 0 || size == 0xffffffff)
+		return;
+	if (bar == DEV_RES_ROM) {
+		mask = PCI_ROM_ADDRESS_MASK;
+		DBG_SET_STR(str, "ROM");
+		if (dev->bus->flags & PCI_BUS_MEM)
+			res->flags = PCI_RES_MEM;
+		else
+			res->flags = PCI_RES_MEMIO;
+	} else if (((size & 0x1) == 0) && (size & 0x6)) {
+		/* unsupported Memory type */
+		return;
+	} else {
+		mask = ~0xf;
+		if (size & 0x1) {
+			/* I/O */
+			mask = ~0x3;
+			res->flags = PCI_RES_IO;
+			DBG_SET_STR(str, "I/O");
+			if (size & 0xffff0000)
+				res->flags |= PCI_RES_IO32;
+			/* Limit size of I/O space to 256 byte */
+			size |= 0xffffff00;
+			if ((dev->bus->flags & PCI_BUS_IO) == 0) {
+				res->flags |= PCI_RES_FAIL;
+				dev->flags |= PCI_DEV_RES_FAIL;
+			}
+		} else {
+			/* Memory */
+			if (size & 0x8) {
+				/* Prefetchable */
+				res->flags = PCI_RES_MEM;
+				DBG_SET_STR(str, "MEM");
+			} else {
+				res->flags = PCI_RES_MEMIO;
+				DBG_SET_STR(str, "MEMIO");
+			}
+		}
+	}
+	res->start = orig & mask;
+	size &= mask;
+	res->size = ~size + 1;
+	res->boundary = res->size;
+	res->end = res->start +  res->size;
+
+	DBG("Bus: %x, Slot: %x, function: %x, %s bar%d size: %x\n",
+		PCI_DEV_EXPAND(pcidev), str, bar, res->size);
+
+	/* Check if BAR is addressable by host */
+	if (pci_read_addressable(dev, res) == 0) {
+		/* No matching bridge window contains this BAR */
+		res->flags |= PCI_RES_FAIL;
+		dev->flags |= PCI_DEV_RES_FAIL;
+	}
+}
+
+static void pci_read_devs(struct pci_bus *bus)
+{
+	uint32_t id, tmp;
+	uint16_t tmp16;
+	uint8_t header;
+	int slot, func, fail, i, maxbars, max_sord;
+	struct pci_dev *dev, **listptr;
+	struct pci_bus *bridge;
+	pci_dev_t pcidev;
+	struct pci_res *res;
+
+	DBG("Scanning bus %d\n", bus->num);
+
+	max_sord = bus->num;
+	listptr = &bus->devs;
+	for (slot = 0; slot < PCI_MAX_DEVICES; slot++) {
+
+		/* Slot address */
+		pcidev = PCI_DEV(bus->num, slot, 0);
+
+		for (func = 0; func < PCI_MAX_FUNCTIONS; func++, pcidev++) {
+
+			fail = PCI_CFG_R32(pcidev, PCI_VENDOR_ID, &id);
+			if (fail || id == 0xffffffff || id == 0) {
+				/*
+				 * This slot is empty
+				 */
+				if (func == 0)
+					break;
+				else
+					continue;
+			}
+
+			DBG("Found PCIDEV 0x%x at (bus %x, slot %x, func %x)\n",
+							id, bus, slot, func);
+
+			PCI_CFG_R32(pcidev, PCI_CLASS_REVISION, &tmp);
+			tmp >>= 16;
+			dev = pci_dev_create(tmp == PCI_CLASS_BRIDGE_PCI);
+			*listptr = dev;
+			listptr = &dev->next;
+
+			dev->busdevfun = pcidev;
+			dev->bus = bus;
+			PCI_CFG_R16(pcidev, PCI_VENDOR_ID, &dev->vendor);
+			PCI_CFG_R16(pcidev, PCI_DEVICE_ID, &dev->device);
+			PCI_CFG_R32(pcidev, PCI_CLASS_REVISION, &dev->classrev);
+
+			if (tmp == PCI_CLASS_BRIDGE_PCI) {
+				DBG("Found PCI-PCI Bridge 0x%x at "
+				    "(bus %x, slot %x, func %x)\n",
+				    id, bus, slot, func);
+				dev->flags = PCI_DEV_BRIDGE;
+				bridge = (struct pci_bus *)dev;
+
+				PCI_CFG_R32(pcidev, PCI_PRIMARY_BUS, &tmp);
+				bridge->pri = tmp & 0xff;
+				bridge->num = (tmp >> 8) & 0xff;
+				bridge->sord = (tmp >> 16) & 0xff;
+				if (bridge->sord > max_sord)
+					max_sord = bridge->sord;
+
+				DBG("    Primary %x, Secondary %x, "
+				    "Subordinate %x\n",
+				    bridge->pri, bridge->num, bridge->sord);
+
+				/*** Probe Bridge Spaces ***/
+
+				/* MEMIO Window - always implemented */
+				bridge->flags = PCI_BUS_MEMIO;
+				res = &bridge->dev.resources[BRIDGE_RES_MEMIO];
+				res->flags = PCI_RES_MEMIO;
+				res->bar = BRIDGE_RES_MEMIO;
+				PCI_CFG_R32(pcidev, 0x20, &tmp);
+				res->start = (tmp & 0xfff0) << 16;
+				res->end = 1 + ((tmp & 0xfff00000) | 0xfffff);
+				if (res->end <= res->start) {
+					/* Window disabled */
+					res->end = res->start = 0;
+				}
+				res->size = res->end - res->start;
+
+				/* I/O Window - optional */
+				res = &bridge->dev.resources[BRIDGE_RES_IO];
+				res->bar = BRIDGE_RES_IO;
+				PCI_CFG_R32(pcidev, 0x30, &tmp);
+				PCI_CFG_R16(pcidev, 0x1c, &tmp16);
+				if (tmp != 0 || tmp16 != 0) {
+					bridge->flags |= PCI_BUS_IO;
+					res->flags = PCI_RES_IO;
+					if (tmp16 & 0x1) {
+						bridge->flags |= PCI_BUS_IO32;
+						res->flags |= PCI_RES_IO32;
+					}
+
+					res->start = (tmp & 0xffff) << 16 |
+							(tmp16 & 0xf0) << 8;
+					res->end = 1 + ((tmp & 0xffff0000) |
+							(tmp16 & 0xf000) |
+							0xfff);
+					if (res->end <= res->start) {
+						/* Window disabled */
+						res->end = res->start = 0;
+					}
+					res->size = res->end - res->start;
+				}
+
+				/* MEM Window - optional */
+				res = &bridge->dev.resources[BRIDGE_RES_MEM];
+				res->bar = BRIDGE_RES_MEM;
+				PCI_CFG_R32(pcidev, 0x24, &tmp);
+				if (tmp != 0) {
+					bridge->flags |= PCI_BUS_MEM;
+					res->flags = PCI_RES_MEM;
+					res->start = (tmp & 0xfff0) << 16;
+					res->end = 1 + ((tmp & 0xfff00000) |
+							0xfffff);
+					if (res->end <= res->start) {
+						/* Window disabled */
+						res->end = res->start = 0;
+					}
+					res->size = res->end - res->start;
+				}
+
+				/* Scan Secondary Bus */
+				pci_read_devs(bridge);
+
+				/* Only 2 BARs for Bridges */
+				maxbars = 2;
+			} else {
+				/* Devices have subsytem device and vendor ID */
+				PCI_CFG_R16(pcidev, PCI_SUBSYSTEM_VENDOR_ID,
+							&dev->subvendor);
+				PCI_CFG_R16(pcidev, PCI_SUBSYSTEM_ID,
+							&dev->subdevice);
+
+				/* Normal PCI Device has max 6 BARs */
+				maxbars = 6;
+			}
+
+			/* Probe BARs */
+			for (i = 0; i < maxbars; i++)
+				pci_read_bar(dev, i);
+			pci_read_bar(dev, DEV_RES_ROM);
+
+			/* Get System Interrupt/Vector for device.
+			 * 0 means no-IRQ
+			 */
+			PCI_CFG_R8(pcidev, PCI_INTERRUPT_LINE, &dev->sysirq);
+
+			/* Stop if not a multi-function device */
+			if (func == 0) {
+				pci_cfg_r8(pcidev, PCI_HEADER_TYPE, &header);
+				if ((header & PCI_MULTI_FUNCTION) == 0)
+					break;
+			}
+		}
+	}
+
+	if (bus->num == 0)
+		bus->sord = max_sord;
+}
+
+int pci_config_read(void)
+{
+	pci_system_type = PCI_SYSTEM_HOST;
+
+	/* Find all devices and buses */
+	pci_hb.flags = PCI_BUS_IO|PCI_BUS_MEMIO|PCI_BUS_MEM;
+	pci_hb.dev.flags = PCI_DEV_BRIDGE;
+	pci_read_devs(&pci_hb);
+	pci_bus_cnt = pci_hb.sord + 1;
+	if (pci_hb.devs == NULL)
+		return 0;
+
+	return 0;
+}
diff --git a/cpukit/libpci/pci_cfg_static.c b/cpukit/libpci/pci_cfg_static.c
new file mode 100644
index 0000000..d7d4321
--- /dev/null
+++ b/cpukit/libpci/pci_cfg_static.c
@@ -0,0 +1,157 @@
+/*  PCI (Static) Configuration Library
+ *
+ *  COPYRIGHT (c) 2010.
+ *  Cobham Gaisler AB.
+ *
+ *  The license and distribution terms for this file may be
+ *  found in the file LICENSE in this distribution or at
+ *  http://www.rtems.com/license/LICENSE.
+ */
+ 
+/*
+ * The Host Bridge bus must be declared by user. It contains the static
+ * configuration used to setup the devices/functions.
+ */
+
+/* Configure headers */
+#define PCI_CFG_STATIC_LIB
+
+#include <stdlib.h>
+#include <pci.h>
+#include <pci/access.h>
+#include <pci/cfg.h>
+
+#define PCI_CFG_R8(dev, args...) pci_cfg_r8(dev, args)
+#define PCI_CFG_R16(dev, args...) pci_cfg_r16(dev, args)
+#define PCI_CFG_R32(dev, args...) pci_cfg_r32(dev, args)
+#define PCI_CFG_W8(dev, args...) pci_cfg_w8(dev, args)
+#define PCI_CFG_W16(dev, args...) pci_cfg_w16(dev, args)
+#define PCI_CFG_W32(dev, args...) pci_cfg_w32(dev, args)
+
+/* Number of buses */
+extern int pci_bus_cnt;
+
+/* Enumrate one bus if device is a bridge, and all it's subordinate buses */
+static int pci_init_dev(struct pci_dev *dev, void *unused)
+{
+	uint32_t tmp;
+	uint16_t tmp16, cmd;
+	struct pci_bus *bridge;
+	int maxbars, i, romofs;
+	pci_dev_t pcidev = dev->busdevfun;
+	struct pci_res *res;
+
+	/* Init Device */
+
+	/* Set command to reset values, it disables bus
+	 * mastering and address responses.
+	 */
+	PCI_CFG_W16(pcidev, PCI_COMMAND, 0);
+
+	/* Clear any already set status bits */
+	PCI_CFG_W16(pcidev, PCI_STATUS, 0xf900);
+
+	/* Set latency timer to 64 */
+	PCI_CFG_W8(pcidev, PCI_LATENCY_TIMER, 64);
+
+	/* Set System IRQ of PIN */
+	PCI_CFG_W8(pcidev, PCI_INTERRUPT_LINE, dev->sysirq);
+
+	cmd = dev->command;
+
+	if ((dev->flags & PCI_DEV_BRIDGE) == 0) {
+		/* Disable Cardbus CIS Pointer */
+		PCI_CFG_W32(pcidev, PCI_CARDBUS_CIS, 0);
+
+		romofs = PCI_ROM_ADDRESS;
+		maxbars = 6;
+	} else {
+		/* Init Bridge */
+
+		/* Configure bridge (no support for 64-bit) */
+		PCI_CFG_W32(pcidev, PCI_PREF_BASE_UPPER32, 0);
+		PCI_CFG_W32(pcidev, PCI_PREF_LIMIT_UPPER32, 0);
+
+		bridge = (struct pci_bus *)dev;
+		tmp = (64 << 24) | (bridge->sord << 16) |
+			(bridge->num << 8) | bridge->pri;
+		PCI_CFG_W32(pcidev, PCI_PRIMARY_BUS, tmp);
+
+		/*** Setup I/O Bridge Window ***/
+		res = &dev->resources[BRIDGE_RES_IO];
+		if (res->size > 0) {
+			tmp16 = ((res->end-1) & 0x0000f000) |
+				((res->start & 0x0000f000) >> 8);
+			tmp = ((res->end-1) & 0xffff0000) | (res->start >> 16);
+			cmd |= PCI_COMMAND_IO;
+		} else {
+			tmp16 = 0x00ff;
+			tmp = 0;
+		}
+		/* I/O Limit and Base */
+		PCI_CFG_W16(pcidev, PCI_IO_BASE, tmp16);
+		PCI_CFG_W32(pcidev, PCI_IO_BASE_UPPER16, tmp);
+
+		/*** Setup MEMIO Bridge Window ***/
+		res = &dev->resources[BRIDGE_RES_MEMIO];
+		if (res->size > 0) {
+			tmp = ((res->end-1) & 0xffff0000) |
+				(res->start >> 16);
+			cmd |= PCI_COMMAND_MEMORY;
+		} else {
+			tmp = 0x0000ffff;
+		}
+		/* MEMIO Limit and Base */
+		PCI_CFG_W32(pcidev, PCI_MEMORY_BASE, tmp);
+
+		/*** Setup MEM Bridge Window ***/
+		res = &dev->resources[BRIDGE_RES_MEM];
+		if (res->size > 0) {
+			tmp = ((res->end-1) & 0xffff0000) |
+				(res->start >> 16);
+			cmd |= PCI_COMMAND_MEMORY;
+		} else {
+			tmp = 0x0000ffff;
+		}
+		/* MEM Limit and Base */
+		PCI_CFG_W32(pcidev, PCI_PREF_MEMORY_BASE, tmp);
+		/* 64-bit space not supported */
+		PCI_CFG_W32(pcidev, PCI_PREF_BASE_UPPER32, 0);
+		PCI_CFG_W32(pcidev, PCI_PREF_LIMIT_UPPER32, 0);
+
+		cmd |= PCI_COMMAND_MASTER;
+		romofs = PCI_ROM_ADDRESS1;
+		maxbars = 2;
+	}
+
+	/* Init BARs */
+	for (i = 0; i < maxbars; i++) {
+		res = &dev->resources[i];
+		if (res->flags & PCI_RES_TYPE_MASK) {
+			PCI_CFG_W32(pcidev, PCI_BASE_ADDRESS_0 + 4*i,
+								res->start);
+			if ((res->flags & PCI_RES_TYPE_MASK) == PCI_RES_IO)
+				cmd |= PCI_COMMAND_IO;
+			else
+				cmd |= PCI_COMMAND_MEMORY;
+		}
+	}
+	res = &dev->resources[DEV_RES_ROM];
+	if (res->flags & PCI_RES_TYPE_MASK) {
+		PCI_CFG_W32(pcidev, romofs, res->start|PCI_ROM_ADDRESS_ENABLE);
+		cmd |= PCI_COMMAND_MEMORY;
+	}
+	PCI_CFG_W16(pcidev, PCI_COMMAND, cmd);
+
+	return 0;
+}
+
+/* Assume that user has defined static setup array in pci_hb */
+int pci_config_static(void)
+{
+	pci_bus_cnt = pci_hb.sord + 1;
+	pci_system_type = PCI_SYSTEM_HOST;
+
+	/* Init all PCI devices according to depth-first search algorithm */
+	return pci_for_each_dev(pci_init_dev, NULL);
+}
diff --git a/cpukit/libpci/pci_find.c b/cpukit/libpci/pci_find.c
new file mode 100644
index 0000000..945cb56
--- /dev/null
+++ b/cpukit/libpci/pci_find.c
@@ -0,0 +1,52 @@
+/*  PCI Help function, Find a PCI device by VENDOR/DEVICE ID
+ *
+ *  COPYRIGHT (c) 2010.
+ *  Cobham Gaisler AB.
+ *
+ *  The license and distribution terms for this file may be
+ *  found in the file LICENSE in this distribution or at
+ *  http://www.rtems.com/license/LICENSE.
+ */
+
+#include <pci.h>
+#include <pci/access.h>
+
+struct compare_info {
+	int index;
+	uint16_t vendor;
+	uint16_t device;
+};
+
+static int compare_dev_id(pci_dev_t pcidev, void *arg)
+{
+	struct compare_info *info = arg;
+	uint16_t vid, did;
+
+	pci_cfg_r16(pcidev, PCI_VENDOR_ID, &vid);
+	pci_cfg_r16(pcidev, PCI_DEVICE_ID, &did);
+	if ((vid != info->vendor) || (did != info->device))
+		return 0;
+	if (info->index-- == 0)
+		return pcidev;
+	else
+		return 0;
+}
+
+/* Find a Device in PCI configuration space */
+int pci_find(uint16_t ven, uint16_t dev, int index, pci_dev_t *pdev)
+{
+	struct compare_info info;
+	int result;
+
+	info.index = index;
+	info.vendor = ven;
+	info.device = dev;
+
+	result = pci_for_each(compare_dev_id, &info);
+	if (pdev)
+		*pdev = (pci_dev_t)result;
+	if (result == 0)
+		return -1;
+	else
+		return 0;
+}
diff --git a/cpukit/libpci/pci_find_dev.c b/cpukit/libpci/pci_find_dev.c
new file mode 100644
index 0000000..184d05c
--- /dev/null
+++ b/cpukit/libpci/pci_find_dev.c
@@ -0,0 +1,49 @@
+/*  PCI Help function, Find a PCI device by VENDOR/DEVICE ID
+ *
+ *  COPYRIGHT (c) 2010.
+ *  Cobham Gaisler AB.
+ *
+ *  The license and distribution terms for this file may be
+ *  found in the file LICENSE in this distribution or at
+ *  http://www.rtems.com/license/LICENSE.
+ */
+
+#include <pci.h>
+#include <pci/cfg.h>
+
+struct compare_info {
+	int index;
+	uint16_t vendor;
+	uint16_t device;
+};
+
+static int compare_dev_id(struct pci_dev *dev, void *arg)
+{
+	struct compare_info *info = arg;
+
+	if ((dev->vendor != info->vendor) || (dev->device != info->device))
+		return 0;
+	if (info->index-- == 0)
+		return (int)dev;
+	else
+		return 0;
+}
+
+/* Find a Device in PCI device tree located in RAM */
+int pci_find_dev(uint16_t ven, uint16_t dev, int index, struct pci_dev **ppdev)
+{
+	struct compare_info info;
+	int result;
+
+	info.index = index;
+	info.vendor = ven;
+	info.device = dev;
+
+	result = pci_for_each_dev(compare_dev_id, &info);
+	if (ppdev)
+		*ppdev = (struct pci_dev *)result;
+	if (result == 0)
+		return -1;
+	else
+		return 0;
+}
diff --git a/cpukit/libpci/pci_for_each.c b/cpukit/libpci/pci_for_each.c
new file mode 100644
index 0000000..dc0a9a1
--- /dev/null
+++ b/cpukit/libpci/pci_for_each.c
@@ -0,0 +1,62 @@
+/*  PCI Help Function, iterate over all PCI devices. Find devices by cfg access.
+ *
+ *  COPYRIGHT (c) 2010.
+ *  Cobham Gaisler AB.
+ *
+ *  The license and distribution terms for this file may be
+ *  found in the file LICENSE in this distribution or at
+ *  http://www.rtems.com/license/LICENSE.
+ */
+
+#include <pci.h>
+#include <pci/access.h>
+
+/*#define DEBUG*/
+
+#ifdef DEBUG
+#include <rtems/bspIo.h>
+#define DBG(args...) printk(args)
+#else
+#define DBG(args...)
+#endif
+
+int pci_for_each(int (*func)(pci_dev_t, void*), void *arg)
+{
+	uint32_t id;
+	uint8_t hd;
+	int bus, dev, fun, result, fail;
+	int maxbus = pci_bus_count();
+	pci_dev_t pcidev;
+
+	for (bus = 0; bus < maxbus ; bus++) {
+		for (dev = 0; dev < PCI_MAX_DEVICES; dev++) {
+			pcidev = PCI_DEV(bus, dev, 0);
+
+			for (fun = 0; fun < PCI_MAX_FUNCTIONS; fun++, pcidev++) {
+				fail = pci_cfg_r32(pcidev, PCI_VENDOR_ID, &id);
+				if (fail || (0xffffffff == id) || (0 == id)) {
+					if (fun == 0)
+						break;
+					else
+						continue;
+				}
+
+				DBG("pcibus_for_each: found 0x%08lx at"
+				    " %d/%d/%d\n", id, bus, dev, fun);
+				result = func(pcidev, arg);
+				if (result != 0)
+					return result; /* Stopped */
+
+				/* Stop if not a multi-function device */
+				if (fun == 0) {
+					pci_cfg_r8(pcidev, PCI_HEADER_TYPE,
+							&hd);
+					if ((hd & PCI_MULTI_FUNCTION) == 0)
+						break;
+				}
+			}
+		}
+	}
+
+	return 0; /* scanned all */
+}
diff --git a/cpukit/libpci/pci_for_each_child.c b/cpukit/libpci/pci_for_each_child.c
new file mode 100644
index 0000000..9d08b77
--- /dev/null
+++ b/cpukit/libpci/pci_for_each_child.c
@@ -0,0 +1,41 @@
+/*  PCI Help function, iterate all PCI device children of PCI bus.
+ *
+ *  COPYRIGHT (c) 2010.
+ *  Cobham Gaisler AB.
+ *
+ *  The license and distribution terms for this file may be
+ *  found in the file LICENSE in this distribution or at
+ *  http://www.rtems.com/license/LICENSE.
+ */
+
+#include <pci/cfg.h>
+
+/* Iterate over all PCI devices on a bus (not child buses) and call func(),
+ * iteration is stopped if a non-zero value is returned by func().
+ *
+ * search options: 0 (no child buses), 1 (depth first), 2 (breadth first)
+ */
+int pci_for_each_child(
+	struct pci_bus *bus,
+	int (*func)(struct pci_dev *, void *arg),
+	void *arg,
+	int search)
+{
+	struct pci_dev *dev = bus->devs;
+	int ret;
+
+	while (dev) {
+		ret = func(dev, arg);
+		if (ret)
+			return ret;
+		if (search == SEARCH_DEPTH && (dev->flags & PCI_DEV_BRIDGE)) {
+			ret = pci_for_each_child((struct pci_bus *)dev,
+							func, arg, search);
+			if (ret)
+				return ret;
+		}
+		dev = dev->next;
+	}
+
+	return 0;
+}
diff --git a/cpukit/libpci/pci_for_each_dev.c b/cpukit/libpci/pci_for_each_dev.c
new file mode 100644
index 0000000..c2b3934
--- /dev/null
+++ b/cpukit/libpci/pci_for_each_dev.c
@@ -0,0 +1,18 @@
+/*  PCI Help function, iterate all PCI devices.
+ *
+ *  COPYRIGHT (c) 2010.
+ *  Cobham Gaisler AB.
+ *
+ *  The license and distribution terms for this file may be
+ *  found in the file LICENSE in this distribution or at
+ *  http://www.rtems.com/license/LICENSE.
+ */
+
+#include <pci/cfg.h>
+
+int pci_for_each_dev(
+	int (*func)(struct pci_dev *, void *arg),
+	void *arg)
+{
+	return pci_for_each_child(&pci_hb, func, arg, SEARCH_DEPTH);
+}
diff --git a/cpukit/libpci/pci_get_dev.c b/cpukit/libpci/pci_get_dev.c
new file mode 100644
index 0000000..5e07653
--- /dev/null
+++ b/cpukit/libpci/pci_get_dev.c
@@ -0,0 +1,36 @@
+/*  PCI Help function, Find a PCI device by BUS|SLOT|FUNCTION
+ *
+ *  COPYRIGHT (c) 2010.
+ *  Cobham Gaisler AB.
+ *
+ *  The license and distribution terms for this file may be
+ *  found in the file LICENSE in this distribution or at
+ *  http://www.rtems.com/license/LICENSE.
+ */
+
+#include <pci.h>
+#include <pci/cfg.h>
+
+static int compare_dev_pcidev(struct pci_dev *dev, void *arg)
+{
+	pci_dev_t pcidev = (unsigned)arg;
+
+	if (dev->busdevfun == pcidev)
+		return (int)dev;
+	else
+		return 0;
+}
+
+/* Get a Device in PCI device tree located in RAM by PCI BUS|SLOT|FUNCTION */
+int pci_get_dev(pci_dev_t pcidev, struct pci_dev **ppdev)
+{
+	int result;
+
+	result = pci_for_each_dev(compare_dev_pcidev, (void *)(unsigned)pcidev);
+	if (ppdev)
+		*ppdev = (struct pci_dev *)result;
+	if (result == 0)
+		return -1;
+	else
+		return 0;
+}
diff --git a/cpukit/libpci/pci_irq.c b/cpukit/libpci/pci_irq.c
new file mode 100644
index 0000000..e379852
--- /dev/null
+++ b/cpukit/libpci/pci_irq.c
@@ -0,0 +1,20 @@
+/*  PCI IRQ Library
+ *
+ *  COPYRIGHT (c) 2010.
+ *  Cobham Gaisler AB.
+ *
+ *  The license and distribution terms for this file may be
+ *  found in the file LICENSE in this distribution or at
+ *  http://www.rtems.com/license/LICENSE.
+ */
+
+#include <pci.h>
+#include <pci/access.h>
+#include <pci/irq.h>
+
+int pci_dev_irq(pci_dev_t dev)
+{
+	uint8_t irq_line;
+	pci_cfg_r8(dev, PCI_INTERRUPT_LINE, &irq_line);
+	return irq_line;
+}
diff --git a/cpukit/libpci/pci_print.c b/cpukit/libpci/pci_print.c
new file mode 100644
index 0000000..9c40f1e
--- /dev/null
+++ b/cpukit/libpci/pci_print.c
@@ -0,0 +1,190 @@
+/*  PCI Print Current Configuration To Terminal
+ *
+ *  COPYRIGHT (c) 2010.
+ *  Cobham Gaisler AB.
+ *
+ *  The license and distribution terms for this file may be
+ *  found in the file LICENSE in this distribution or at
+ *  http://www.rtems.com/license/LICENSE.
+ */
+
+#include <stdio.h>
+#include <pci.h>
+#include <pci/access.h>
+
+/* PCI Access Library shortcuts */
+#define PCI_CFG_R8(dev, args...) pci_cfg_r8(dev, args)
+#define PCI_CFG_R16(dev, args...) pci_cfg_r16(dev, args)
+#define PCI_CFG_R32(dev, args...) pci_cfg_r32(dev, args)
+#define PCI_CFG_W8(dev, args...) pci_cfg_w8(dev, args)
+#define PCI_CFG_W16(dev, args...) pci_cfg_w16(dev, args)
+#define PCI_CFG_W32(dev, args...) pci_cfg_w32(dev, args)
+
+void pci_print_dev(pci_dev_t dev)
+{
+	int maxbars, pos, romadrs;
+	uint32_t tmp, tmp2, id;
+	uint16_t irq;
+	uint8_t irq_pin;
+	char *str, *str2;
+	uint32_t base, limit;
+
+	maxbars = 6;
+	romadrs = 0x30;
+	str = "";
+	PCI_CFG_R32(dev, PCI_CLASS_REVISION, &tmp);
+	tmp >>= 16;
+	if (tmp == PCI_CLASS_BRIDGE_PCI) {
+		maxbars = 2;
+		romadrs = 0x38;
+		str = "(BRIDGE)";
+	}
+
+	PCI_CFG_R32(dev, PCI_VENDOR_ID, &id);
+	printf("\nBus %x Slot %x function: %x [0x%x] %s\n",
+		PCI_DEV_EXPAND(dev), dev, str);
+	printf("\tVendor id: 0x%lx, device id: 0x%lx\n",
+		id & 0xffff, id >> 16);
+	if (maxbars == 2) {
+		PCI_CFG_R32(dev, PCI_PRIMARY_BUS, &tmp);
+		printf("\tPrimary: %lx  Secondary: %lx  Subordinate: %lx\n",
+			tmp & 0xff, (tmp >> 8) & 0xff, (tmp >> 16) & 0xff);
+	}
+
+	PCI_CFG_R16(dev, PCI_INTERRUPT_LINE, &irq);
+	irq_pin = irq >> 8;
+	if ((irq_pin > 0) && (irq_pin < 5))
+		printf("\tIRQ INT%c#  LINE: %d\n",
+			(irq_pin - 1) + 'A', (irq & 0xff));
+
+	/* Print standard BARs */
+	for (pos = 0; pos < maxbars; pos++) {
+		PCI_CFG_R32(dev, PCI_BASE_ADDRESS_0 + pos*4, &tmp);
+		PCI_CFG_W32(dev, PCI_BASE_ADDRESS_0 + pos*4, 0xffffffff);
+		PCI_CFG_R32(dev, PCI_BASE_ADDRESS_0 + pos*4, &tmp2);
+		PCI_CFG_W32(dev, PCI_BASE_ADDRESS_0 + pos*4, tmp);
+
+		if (tmp2 != 0 && tmp2 != 0xffffffff && ((tmp2 & 0x1) ||
+		    ((tmp2 & 0x6) == 0))) {
+			uint32_t mask = ~0xf;
+			if ((tmp2 & 0x1) == 1) {
+				/* I/O Bar */
+				mask = ~3;
+				tmp2 = tmp2 | 0xffffff00;
+			}
+			tmp2 &= mask;
+			tmp2 = ~tmp2+1; /* Size of BAR */
+			if (tmp2 < 0x1000) {
+				str = "B";
+			} else if (tmp2 < 0x100000) {
+				str = "kB";
+				tmp2 = tmp2 / 1024;
+			} else {
+				str = "MB";
+				tmp2 = tmp2 / (1024*1024);
+			}
+			printf("\tBAR %d: %lx [%lu%s]\n", pos, tmp, tmp2, str);
+		}
+	}
+
+	/* Print ROM BARs */
+	PCI_CFG_R32(dev, romadrs, &tmp);
+	PCI_CFG_W32(dev, romadrs, 0xffffffff);
+	PCI_CFG_R32(dev, romadrs, &tmp2);
+	PCI_CFG_W32(dev, romadrs, tmp);
+	if (tmp2 & 1) {
+		/* ROM BAR available */
+		tmp2 &= PCI_ROM_ADDRESS_MASK;
+		tmp2 = (~tmp2 + 1); /* Size of BAR */
+		if (tmp2 < 0x1000) {
+			str = "B";
+		} else if (tmp2 < 0x100000) {
+			str = "kB";
+			tmp2 = tmp2 / 1024;
+		} else {
+			str = "MB";
+			tmp2 = tmp2 / (1024*1024);
+		}
+		str2 = tmp & 1 ? "ENABLED" : "DISABLED";
+		printf("\tROM:   %08lx [%lu%s] (%s)\n",
+			tmp, tmp2, str, str2);
+	}
+
+	/* Print Bridge addresses */
+	if (maxbars == 2) {
+		tmp = 0;
+		PCI_CFG_R32(dev, 0x1C, &tmp);
+		if (tmp != 0) {
+			base = (tmp & 0x00f0) << 8;
+			limit = (tmp & 0xf000) | 0xfff;
+			PCI_CFG_R32(dev, 0x30, &tmp);
+			base |= (tmp & 0xffff) << 16;
+			limit |= (tmp & 0xffff0000);
+			str = "ENABLED";
+			if (limit < base)
+				str = "DISABLED";
+			printf("\tI/O:   BASE: 0x%08lx, LIMIT: 0x%08lx (%s)\n",
+				base, limit, str);
+		}
+
+		PCI_CFG_R32(dev, 0x20, &tmp);
+		if (tmp != 0) {
+			base = (tmp & 0xfff0) << 16;
+			limit = (tmp & 0xfff00000) | 0xfffff;
+			str = "ENABLED";
+			if (limit < base)
+				str = "DISABLED";
+			printf("\tMEMIO: BASE: 0x%08lx, LIMIT: 0x%08lx (%s)\n",
+				base, limit, str);
+		}
+
+		PCI_CFG_R32(dev, 0x24, &tmp);
+		if (tmp != 0) {
+			base = (tmp & 0xfff0) << 16;
+			limit = (tmp & 0xfff00000) | 0xfffff;
+			str = "ENABLED";
+			if (limit < base)
+				str = "DISABLED";
+			printf("\tMEM:   BASE: 0x%08lx, LIMIT: 0x%08lx (%s)\n",
+					base, limit, str);
+		}
+	}
+	printf("\n");
+}
+
+void pci_print_device(int bus, int slot, int function)
+{
+	pci_print_dev(PCI_DEV(bus, slot, function));
+}
+
+void pci_print(void)
+{
+    int fail, bus, slot, func;
+    pci_dev_t dev;
+    uint8_t header;
+    uint32_t id;
+
+    printf("\nPCI devices found and configured:\n");
+    for (bus = 0; bus < pci_bus_count(); bus++) {
+        for (slot = 0; slot < PCI_MAX_DEVICES; slot++) {
+            for (func=0; func < PCI_MAX_FUNCTIONS; func++) {
+
+                dev = PCI_DEV(bus, slot, func);
+                fail = PCI_CFG_R32(dev, PCI_VENDOR_ID, &id);
+
+                if (!fail && id != PCI_INVALID_VENDORDEVICEID && id != 0) {
+	               	pci_print_dev(dev);
+
+        	        /* Stop if not a multi-function device */
+                	if (func == 0) {
+	                    PCI_CFG_R8(dev, PCI_HEADER_TYPE, &header);
+        	            if ((header & PCI_MULTI_FUNCTION) == 0)
+                	        break;
+	                }
+		} else if (func == 0)
+			break;
+            }
+        }
+    }
+    printf("\n");
+}
diff --git a/cpukit/libpci/preinstall.am b/cpukit/libpci/preinstall.am
new file mode 100644
index 0000000..b19d288
--- /dev/null
+++ b/cpukit/libpci/preinstall.am
@@ -0,0 +1,66 @@
+## Automatically generated by ampolish3 - Do not edit
+
+if AMPOLISH3
+$(srcdir)/preinstall.am: Makefile.am
+	$(AMPOLISH3) $(srcdir)/Makefile.am > $(srcdir)/preinstall.am
+endif
+
+PREINSTALL_DIRS =
+DISTCLEANFILES = $(PREINSTALL_DIRS)
+
+all-am: $(PREINSTALL_FILES)
+
+PREINSTALL_FILES =
+CLEANFILES = $(PREINSTALL_FILES)
+
+$(PROJECT_INCLUDE)/$(dirstamp):
+	@$(MKDIR_P) $(PROJECT_INCLUDE)
+	@: > $(PROJECT_INCLUDE)/$(dirstamp)
+PREINSTALL_DIRS += $(PROJECT_INCLUDE)/$(dirstamp)
+
+if LIBPCI
+$(PROJECT_INCLUDE)/pci.h: pci.h $(PROJECT_INCLUDE)/$(dirstamp)
+	$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/pci.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/pci.h
+
+$(PROJECT_INCLUDE)/pci/$(dirstamp):
+	@$(MKDIR_P) $(PROJECT_INCLUDE)/pci
+	@: > $(PROJECT_INCLUDE)/pci/$(dirstamp)
+PREINSTALL_DIRS += $(PROJECT_INCLUDE)/pci/$(dirstamp)
+
+$(PROJECT_INCLUDE)/pci/access.h: pci/access.h $(PROJECT_INCLUDE)/pci/$(dirstamp)
+	$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/pci/access.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/pci/access.h
+
+$(PROJECT_INCLUDE)/pci/cfg.h: pci/cfg.h $(PROJECT_INCLUDE)/pci/$(dirstamp)
+	$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/pci/cfg.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/pci/cfg.h
+
+$(PROJECT_INCLUDE)/pci/cfg_auto.h: pci/cfg_auto.h $(PROJECT_INCLUDE)/pci/$(dirstamp)
+	$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/pci/cfg_auto.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/pci/cfg_auto.h
+
+$(PROJECT_INCLUDE)/pci/cfg_static.h: pci/cfg_static.h $(PROJECT_INCLUDE)/pci/$(dirstamp)
+	$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/pci/cfg_static.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/pci/cfg_static.h
+
+$(PROJECT_INCLUDE)/pci/cfg_peripheral.h: pci/cfg_peripheral.h $(PROJECT_INCLUDE)/pci/$(dirstamp)
+	$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/pci/cfg_peripheral.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/pci/cfg_peripheral.h
+
+$(PROJECT_INCLUDE)/pci/cfg_read.h: pci/cfg_read.h $(PROJECT_INCLUDE)/pci/$(dirstamp)
+	$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/pci/cfg_read.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/pci/cfg_read.h
+
+$(PROJECT_INCLUDE)/pci/ids.h: pci/ids.h $(PROJECT_INCLUDE)/pci/$(dirstamp)
+	$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/pci/ids.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/pci/ids.h
+
+$(PROJECT_INCLUDE)/pci/ids_extra.h: pci/ids_extra.h $(PROJECT_INCLUDE)/pci/$(dirstamp)
+	$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/pci/ids_extra.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/pci/ids_extra.h
+
+$(PROJECT_INCLUDE)/pci/irq.h: pci/irq.h $(PROJECT_INCLUDE)/pci/$(dirstamp)
+	$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/pci/irq.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/pci/irq.h
+endif
diff --git a/cpukit/preinstall.am b/cpukit/preinstall.am
index 527142b..b125b2f 100644
--- a/cpukit/preinstall.am
+++ b/cpukit/preinstall.am
@@ -232,10 +232,11 @@ $(PROJECT_INCLUDE)/rtems/fs.h: include/rtems/fs.h $(PROJECT_INCLUDE)/rtems/$(dir
 	$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/fs.h
 PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/fs.h
 
+if !LIBPCI
 $(PROJECT_INCLUDE)/rtems/pci.h: include/rtems/pci.h $(PROJECT_INCLUDE)/rtems/$(dirstamp)
 	$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/pci.h
 PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/pci.h
-
+endif
 $(PROJECT_INCLUDE)/rtems/concat.h: include/rtems/concat.h $(PROJECT_INCLUDE)/rtems/$(dirstamp)
 	$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/concat.h
 PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/concat.h
diff --git a/cpukit/sapi/include/confdefs.h b/cpukit/sapi/include/confdefs.h
index 7d9e3b9..cce961c 100644
--- a/cpukit/sapi/include/confdefs.h
+++ b/cpukit/sapi/include/confdefs.h
@@ -2814,6 +2814,52 @@ const rtems_libio_helper rtems_fs_init_helper =
   #endif
 #endif
 
+/*
+ *  Select PCI Configuration Library
+ */
+#ifdef RTEMS_PCI_CONFIG_LIB
+  #ifdef CONFIGURE_INIT
+    #define PCI_LIB_NONE 0
+    #define PCI_LIB_AUTO 1
+    #define PCI_LIB_STATIC 2
+    #define PCI_LIB_READ 3
+    #define PCI_LIB_PERIPHERAL 4
+    #if CONFIGURE_PCI_LIB == PCI_LIB_AUTO
+      #define PCI_CFG_AUTO_LIB
+      #include <pci/cfg.h>
+      struct pci_bus pci_hb;
+      #define PCI_LIB_INIT pci_config_auto
+      #define PCI_LIB_CONFIG pci_config_auto_register
+    #elif CONFIGURE_PCI_LIB == PCI_LIB_STATIC
+      #define PCI_CFG_STATIC_LIB
+      #include <pci/cfg.h>
+      #define PCI_LIB_INIT pci_config_static
+      #define PCI_LIB_CONFIG NULL
+      /* Let user define PCI configuration (struct pci_bus pci_hb) */
+    #elif CONFIGURE_PCI_LIB == PCI_LIB_READ
+      #define PCI_CFG_READ_LIB
+      #include <pci/cfg.h>
+      #define PCI_LIB_INIT pci_config_read
+      #define PCI_LIB_CONFIG NULL
+      struct pci_bus pci_hb;
+    #elif CONFIGURE_PCI_LIB == PCI_LIB_PERIPHERAL
+      #define PCI_LIB_INIT pci_config_peripheral
+      #define PCI_LIB_CONFIG NULL
+      /* Let user define PCI configuration (struct pci_bus pci_hb) */
+    #elif CONFIGURE_PCI_LIB == PCI_LIB_NONE
+      #define PCI_LIB_INIT NULL
+      #define PCI_LIB_CONFIG NULL
+      /* No PCI Configuration at all, user can use/debug access routines */
+    #else
+      #error NO PCI LIBRARY DEFINED
+    #endif
+
+    const int pci_config_lib_type = CONFIGURE_PCI_LIB;
+    int (*pci_config_lib_init)(void) = PCI_LIB_INIT;
+    void (*pci_config_lib_register)(void *config) = PCI_LIB_CONFIG;
+  #endif
+#endif
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/cpukit/wrapup/Makefile.am b/cpukit/wrapup/Makefile.am
index 6fbddb0..c61ab05 100644
--- a/cpukit/wrapup/Makefile.am
+++ b/cpukit/wrapup/Makefile.am
@@ -65,6 +65,8 @@ TMP_LIBS += ../libmisc/libuuid.a
 
 TMP_LIBS += ../libi2c/libi2c.a
 
+TMP_LIBS += ../libpci/libpci.a
+
 if LIBNETWORKING
 TMP_LIBS += ../libnetworking/libnetworking.a
 TMP_LIBS += ../libnetworking/libc.a
diff --git a/doc/ada_user/Makefile.am b/doc/ada_user/Makefile.am
index ab19e71..f925100 100644
--- a/doc/ada_user/Makefile.am
+++ b/doc/ada_user/Makefile.am
@@ -16,6 +16,7 @@ COMMON_FILES += \
     $(top_builddir)/user/event.texi $(top_builddir)/user/fatal.texi \
     $(top_builddir)/user/glossary.texi $(top_builddir)/user/init.texi \
     $(top_builddir)/user/intr.texi $(top_builddir)/user/io.texi \
+    $(top_builddir)/user/libpci.texi  \
     $(top_builddir)/user/mp.texi $(top_builddir)/user/msg.texi \
     $(top_builddir)/user/overview.texi $(top_builddir)/user/part.texi \
     $(top_builddir)/user/preface.texi $(top_builddir)/user/region.texi \
diff --git a/doc/ada_user/ada_user.texi b/doc/ada_user/ada_user.texi
index 80a0e49..7e39465 100644
--- a/doc/ada_user/ada_user.texi
+++ b/doc/ada_user/ada_user.texi
@@ -108,6 +108,7 @@
 * Configuring a System::
 * Multiprocessing Manager::
 * Symmetric Multiprocessing Services::
+* PCI Library::
 * Stack Bounds Checker::
 * CPU Usage Statistics::
 * Object Services::
@@ -152,6 +153,7 @@
 @include user/conf.texi
 @include user/mp.texi
 @include user/smp.texi
+ at include user/libpci.texi
 @include user/stackchk.texi
 @include user/cpuuse.texi
 @include user/object.texi
diff --git a/doc/develenv/direct.t b/doc/develenv/direct.t
index a512145..9950b69 100644
--- a/doc/develenv/direct.t
+++ b/doc/develenv/direct.t
@@ -448,6 +448,9 @@ TCP/IP stack to RTEMS.
 This directory contains the port of the FreeBSD
 RPC/XDR source to RTEMS.
 
+ at item $@{RTEMS_ROOT@}/cpukit/libpci/
+This directory contains RTEMS PCI Library.
+
 @item $@{RTEMS_ROOT@}/cpukit/posix/
 This directory contains the RTEMS implementation
 of the threading portions of the POSIX API.  
diff --git a/doc/user/Makefile.am b/doc/user/Makefile.am
index cd8b5f3..f17179e 100644
--- a/doc/user/Makefile.am
+++ b/doc/user/Makefile.am
@@ -15,7 +15,7 @@ GENERATED_FILES = overview.texi concepts.texi datatypes.texi init.texi \
     signal.texi part.texi region.texi dpmem.texi io.texi fatal.texi \
     schedule.texi rtmon.texi barrier.texi bsp.texi userext.texi conf.texi \
     mp.texi stackchk.texi cpuuse.texi object.texi chains.texi rbtree.texi \
-    timespec.texi cbs.texi dirstat.texi smp.texi
+    timespec.texi cbs.texi dirstat.texi smp.texi libpci.texi
 
 COMMON_FILES += $(top_srcdir)/common/cpright.texi
 
@@ -166,10 +166,15 @@ mp.texi: mp.t
 smp.texi: smp.t
 	$(BMENU2) -p  "Multiprocessing Manager MULTIPROCESSING_ANNOUNCE - Announce the arrival of a packet"\
 	    -u "Top" \
+	    -n "PCI Library" < $< > $@
+
+libpci.texi: libpci.t
+	$(BMENU2) -p "Symmetric Multiprocessing Services TASK_SET_AFFINITY - Set task processor affinity" \
+	    -u "Top" \
 	    -n "Stack Bounds Checker" < $< > $@
 
 stackchk.texi: stackchk.t
-	$(BMENU2) -p "Symmetric Multiprocessing Services TASK_SET_AFFINITY - Set task processor affinity" \
+	$(BMENU2) -p "PCI Library PCI Shell command" \
 	    -u "Top" \
 	    -n "CPU Usage Statistics" < $< > $@
 
diff --git a/doc/user/c_user.texi b/doc/user/c_user.texi
index 2ff47bf..bdf0cd5 100644
--- a/doc/user/c_user.texi
+++ b/doc/user/c_user.texi
@@ -107,6 +107,7 @@
 * Configuring a System::
 * Multiprocessing Manager::
 * Symmetric Multiprocessing Services::
+* PCI Library::
 * Stack Bounds Checker::
 * CPU Usage Statistics::
 * Object Services::
@@ -152,6 +153,7 @@
 @include conf.texi
 @include mp.texi
 @include smp.texi
+ at include libpci.texi
 @include stackchk.texi
 @include cpuuse.texi
 @include object.texi
diff --git a/doc/user/conf.t b/doc/user/conf.t
index dc10816..0c5ab32 100644
--- a/doc/user/conf.t
+++ b/doc/user/conf.t
@@ -5237,6 +5237,59 @@ uses the Ada run-time.
 None.
 
 @c
+ at c === PCI Library ===
+ at c
+ at section PCI Library
+
+This section defines the system configuration paramters supported
+by @code{rtems/confdefs.h} related to configuring the PCI Library
+for RTEMS.
+
+The PCI Library startup behaviour can be configured in four diffent
+ways depending on how @code{CONFIGURE_PCI_CONFIG_LIB} is defined:
+
+ at itemize @bullet
+ at findex PCI_LIB_AUTO
+ at item @code{PCI_LIB_AUTO} is used to enable the PCI auto configuration
+software. PCI will be automatically probed, PCI buses enumerated, all
+devices and bridges will be initialized using Plug & Play software
+routines. The PCI device tree will be populated based on the PCI devices
+found in the system, PCI devices will be configured by allocating address
+region resources automatically in PCI space according to the BSP or host
+bridge driver set up.
+
+ at findex PCI_LIB_READ
+ at item @code{PCI_LIB_READ} is used to enable the PCI read configuration
+software. The current PCI configuration is read to create the RAM
+representation (the PCI device tree) of the PCI devices present. PCI devices
+are assumed to already have been initialized and PCI buses enumrated, it is
+therefore required that a BIOS or a boot loader has set up configuration space
+prior to booting into RTEMS.
+
+ at findex PCI_LIB_STATIC
+ at item @code{PCI_LIB_STATIC} is used to enable the PCI static configuration
+software. The user provides a PCI tree with information how all PCI devices
+are to be configured at compile time by linking in a custom
+ at code{struct pci_bus pci_hb} tree. The static PCI library will not probe PCI
+for devices, instead it will assume that all devices defined by the user is
+present, it will enumerate the PCI buses and configure all PCI devices in
+static configuration accordingly. Since probe and allocation software is not
+needed the startup is faster, have smaller footprint and does not require
+dynamic memory allocation.
+
+ at findex PCI_LIB_PERIPHERAL
+ at item @code{PCI_LIB_PERIPHERAL} is used to enable the PCI peripheral
+configuration. It is similar to @code{PCI_LIB_STATIC}, but is will never write
+the configuration to the PCI devices since PCI peripherals are not allowed to
+access PCI configuration space.
+
+ at end itemize
+
+Note that selecting PCI_LIB_STATIC or PCI_LIB_PERIPHERAL but not defining
+ at code{pci_hb} will reuslt in link errors. Note also that in these modes
+Plug & Play is not performed.
+
+ at c
 @c === Go Tasks ===
 @c
 @section Go Tasks
diff --git a/doc/user/libpci.t b/doc/user/libpci.t
new file mode 100644
index 0000000..1eaca42
--- /dev/null
+++ b/doc/user/libpci.t
@@ -0,0 +1,409 @@
+ at c
+ at c  COPYRIGHT (c) 2011
+ at c  Aeroflex Gaisler AB
+ at c  All rights reserved.
+ at c
+ at c  $Id: libpci.t,v v.vv xxxx/yy/zz xx:yy:zz ? Exp $
+ at c
+
+ at chapter PCI Library
+
+ at cindex libpci
+
+ at section Introduction
+
+The Peripheral Component Interconnect (PCI) bus is a very common computer
+bus architecture that is found in almost every PC today. The PCI bus is
+normally located at the motherboard where some PCI devices are soldered
+directly onto the PCB and expansion slots allows the user to add custom
+devices easily. There is a wide range of PCI hardware available implementing
+all sorts of interfaces and functions.
+
+This section describes the PCI Library available in RTEMS used to access the
+PCI bus in a portable way across computer architectures supported by RTEMS.
+
+The PCI Library aims to be compatible with PCI 2.3 with a couple of
+limitations, for example there is no support for hot-plugging, 64-bit
+memory space and cardbus bridges.
+
+In order to support different architectures and with small foot-print embedded
+systems in mind the PCI Library offers four different configuration options
+listed below. It is selected during compile time by defining the appropriate
+macros in confdefs.h. It is also possible to enable NONE (No Configuration)
+which can be used for debuging PCI access functions.
+ at itemize @bullet
+ at item Auto Configuration (do Plug & Play)
+ at item Read Configuration (read BIOS or boot loader configuration)
+ at item Static Configuration (write user defined configuration)
+ at item Peripheral Configuration (no access to cfg-space)
+ at end itemize
+
+ at section Background
+
+The PCI bus is constructed in a way where on-board devices and devices
+in expansion slots can be automatically found (probed) and configured
+using Plug & Play completely implemented in software. The bus is set up once
+during boot up. The Plug & Play information can be read and written from
+PCI configuration space. A PCI device is identified in configuration space by
+a unique bus, slot and function number. Each PCI slot can have up to 8
+functions and interface to another PCI sub-bus by implementing a PCI-to-PCI
+bridge according to the PCI Bridge Architecture specification.
+
+Using the unique [bus:slot:func] any device can be configured regardless how PCI
+is currently set up as long as all PCI buses are enumerated correctly. The
+enumration is done during probing, all bridges are given a bus numbers in
+order for the bridges to respond to accesses from both directions. The PCI
+library can assign address ranges to which a PCI device should respond using
+Plug & Play technique or a static user defined configuration. After the
+configuration has been performed the PCI device drivers can find devices by
+the read-only PCI Class type, Vendor ID and Device ID information found in
+configuration space for each device.
+
+In some systems there is a boot loader or BIOS which have already configured
+all PCI devices, but on embedded targets it is quite common that there is no
+BIOS or boot loader, thus RTEMS must configure the PCI bus. Only the PCI host
+may do configuration space access, the host driver or BSP is responsible to
+translate the [bus:slot:func] into a valid PCI configuration space access.
+
+If the target is not a host, but a peripheral, configuration space can not be
+accessed, the peripheral is set up by the host during start up. In complex
+embedded PCI systems the peripheral may need to access other PCI boards than
+then host. In such systems a custom (static) configuration of both the host
+and peripheral may be a convenient solution.
+
+The PCI bus defines four interrupt signals INTA#..INTD#. The interrupt signals
+must be mapped into a system interrupt/vector, it is up to the BSP or host
+driver to know the mapping, however the BIOS or boot loader may use the
+8-bit read/write "Interrupt Line" register to pass the knowledge along to the
+OS.
+
+
+ The PCI standard
+defines and recommends that the backplane route the interupt lines in a
+systematic way, however in 
+
+ at subsection Software Components
+
+The PCI library is located in cpukit/libpci, it consists of different parts:
+ at itemize @bullet
+ at item PCI Host bridge driver interface
+ at item Configuration routines
+ at item Access (Configuration, I/O and Memory space) routines
+ at item Interrupt routines (implemented by BSP)
+ at item Print routines
+ at item Static/peripheral configuration creation
+ at item PCI shell command
+ at end itemize
+
+ at subsection PCI Configuration
+
+During start up the PCI bus must be configured in order for host and peripherals
+to access one another using Memory or I/O accesses and that interrupts are
+properly handled. Three different spaces are defined and mapped separately:
+ at enumerate
+ at item I/O space (IO)
+ at item non-prefetchable Memory space (MEMIO)
+ at item prefetchable Memory space (MEM)
+ at end enumerate
+
+Regions of the same type (I/O or Memory) may not overlap which is guaranteed
+by the software. MEM regions may be mapped into MEMIO regions, but MEMIO
+regions can not be mapped into MEM, for that could lead to prefetching of
+registers. The interrupt pin which a board is driving can be read out from
+PCI configuration space, however it is up to software to know how interrupt
+signals are routed between PCI-to-PCI bridges and how PCI INT[A..D]# pins are
+mapped to system IRQ. In systems where previous software (boot loader or BIOS)
+has already set up this the configuration overwritten or simply read out.
+
+In order to support different configuration methods the following configuration
+libraries are available can selectable by the user:
+ at itemize @bullet
+ at item Auto Configuration (run Plug & Play software)
+ at item Read Configuration (relies on a boot loader or BIOS)
+ at item Static Configuration (write user defined setup, no Plug & Play)
+ at item Peripheral Configuration (user defined setup, no access to configuration space)
+ at end itemize
+
+A host driver can be made to support all three configuration methods, or any
+combination. It may be defined by the BSP which approach is used.
+
+The configuration software is called from the PCI driver (pci_config_init()).
+
+Regardless of configuration method a PCI device tree is created in RAM during
+initialization, the tree can be accessed to find devices and resources without
+accessing configuration space later on. The user is responsible to create the
+device tree at compile time when using the static/peripheral method.
+
+
+ at subsubsection RTEMS Configuration selection
+
+The active configuration method can be selected at compile time in the same
+way as other project parameters by including rtems/confdefs.h and setting
+ at itemize @bullet
+ at item CONFIGURE_INIT
+ at item RTEMS_PCI_CONFIG_LIB
+ at item CONFIGURE_PCI_LIB = PCI_LIB_(AUTO,STATIC,READ,PERIPHERAL)
+ at end itemize
+
+See the RTEMS configuration section how to setup the PCI library.
+
+
+ at subsubsection Auto Configuration
+
+The auto configuration software enumerate PCI buses and initializes all PCI
+devices found using Plug & Play. The auto configuration software requires
+that a configuration setup has been registered by the driver or BSP in order
+to setup the I/O and Memory regions at the correct address ranges. PCI
+interrupt pins can optionally be routed over PCI-to-PCI bridges and mapped
+to a system interrupt number. Resources are sorted by size and required
+alignment, unused "dead" space may be created when PCI bridges are present
+due to the PCI bridge window size does not equal the alignment, to cope with
+that resources are reordered to fit smaller BARs into the dead space to minimize
+the PCI space required. If a BAR or ROM register can not be allocated a PCI
+address region (due to too few resources available) the register will be given
+the value of pci_invalid_address which defaults to 0.
+
+The auto configuration routines support:
+ at itemize @bullet
+ at item PCI 2.3
+ at item Little and big endian PCI bus
+ at item one I/O 16 or 32-bit range (IO)
+ at item memory space (MEMIO)
+ at item prefetchable memory space (MEM), if not present MEM will be mapped into
+      MEMIO
+ at item multiple PCI buses - PCI-to-PCI bridges
+ at item standard BARs, PCI-to-PCI bridge BARs, ROM BARs
+ at item Interrupt routing over bridges
+ at item Interrupt pin to system interrupt mapping
+ at end itemize
+
+Not supported:
+ at itemize @bullet
+ at item hot-pluggable devices
+ at item Cardbus bridges
+ at item 64-bit memory space
+ at item 16-bit and 32-bit I/O address ranges at the same time
+ at end itemize
+
+In PCI 2.3 there may exist I/O BARs that must be located at the low 64kBytes
+address range, in order to support this the host driver or BSP must make sure
+that I/O addresses region is within this region.
+
+
+ at subsubsection Read Configuration
+
+When a BIOS or boot loader already has setup the PCI bus the configuration can
+be read directly from the PCI resource registers and buses are already
+enumerated, this is a much simpler approach than configuring PCI ourselves. The
+PCI device tree is automatically created based on the current configuration and
+devices present. After initialization is done there is no difference between
+the auto or read configuration approaches.
+
+
+ at subsubsection Static Configuration
+
+To support custom configurations and small-footprint PCI systems, the user may
+provide the PCI device tree which contains the current configuration. The
+PCI buses are enumerated and all resources are written to PCI devices during
+initialization. When this approach is selected PCI boards must be located at
+the same slots every time and devices can not be removed or added, Plug & Play
+is not performed. Boards of the same type may of course be exchanged.
+
+The user can create a configuration by calling pci_cfg_print() on a running
+system that has had PCI setup by the auto or read configuration routines, it
+can be called from the PCI shell command. The user must provide the PCI device
+tree named pci_hb.
+
+
+ at subsubsection Peripheral Configuration
+
+On systems where a peripheral PCI device needs to access other PCI devices than
+the host the peripheral configuration approach may be handy. Most PCI devices
+answers on the PCI host's requests and start DMA accesses into the Hosts memory,
+however in some complex systems PCI devices may want to access other devices
+on the same bus or at another PCI bus.
+
+A PCI peripheral is not allowed to do PCI configuration cycles, which means that
+is must either rely on the host to give it the addresses it needs, or that the
+addresses are predefined.
+
+This configuration approach is very similar to the static option, however the
+configuration is never written to PCI bus, instead it is only used for drivers
+to find PCI devices and resources using the same PCI API as for the host
+
+
+ at subsection PCI Access
+
+The PCI access routines are low-level routines provided for drivers,
+configuration software, etc. in order to access different regions in a way
+not dependent upon the host driver, BSP or platform.
+ at itemize @bullet
+ at item PCI configuration space
+ at item PCI I/O space
+ at item Registers over PCI memory space
+ at item Translate PCI address into CPU accessible address and vice verse
+ at end itemize
+
+By using the access routines drivers can be made portable over different
+architectures. The access routines take the architecture endianness into
+consideration and let the host driver or BSP implement I/O space and
+configuration space access.
+
+Some non-standard hardware may also define the PCI bus big-endian, for example
+the LEON2 AT697 PCI host bridge and some LEON3 systems may be configured that
+way. It is up to the BSP to set the appropriate PCI endianness on compile time
+(BSP_PCI_BIG_ENDIAN) in order for inline macros to be correctly defined.
+Another possibility is to use the function pointers defined by the access
+layer to implement drivers that support "run-time endianness detection".
+
+
+ at subsubsection Configuration space
+
+Configuration space is accessed using the routines listed below. The
+pci_dev_t type is used to specify a specific PCI bus, device and function. It
+is up to the host driver or BSP to create a valid access to the requested
+PCI slot. Requests made to slots that is not supported by hardware should
+result in PCISTS_MSTABRT and/or data must be ignored (writes) or 0xffffffff
+is always returned (reads).
+
+ at example
+  /* Configuration Space Access Read Routines */
+  extern int pci_cfg_r8(pci_dev_t dev, int ofs, uint8_t *data);
+  extern int pci_cfg_r16(pci_dev_t dev, int ofs, uint16_t *data);
+  extern int pci_cfg_r32(pci_dev_t dev, int ofs, uint32_t *data);
+
+  /* Configuration Space Access Write Routines */
+  extern int pci_cfg_w8(pci_dev_t dev, int ofs, uint8_t data);
+  extern int pci_cfg_w16(pci_dev_t dev, int ofs, uint16_t data);
+  extern int pci_cfg_w32(pci_dev_t dev, int ofs, uint32_t data);
+ at end example
+
+
+ at subsubsection I/O space
+
+The BSP or driver provide special routines in order to access I/O space. Some
+architectures have a special instruction accessing I/O space, others have it
+mapped into a "PCI I/O window" in the standard address space accessed by the
+CPU. The window size may vary and must be taken into consideration by the
+host driver. The below routines must be used to access I/O space. The address
+given to the functions is not the PCI I/O addresses, the caller must have
+translated PCI I/O addresses (available in the PCI BARs) into a BSP or host
+driver custom address, see @ref{Access functions} how addresses are
+translated.
+
+ at example
+/* Read a register over PCI I/O Space */
+extern uint8_t pci_io_r8(uint32_t adr);
+extern uint16_t pci_io_r16(uint32_t adr);
+extern uint32_t pci_io_r32(uint32_t adr);
+
+/* Write a register over PCI I/O Space */
+extern void pci_io_w8(uint32_t adr, uint8_t data);
+extern void pci_io_w16(uint32_t adr, uint16_t data);
+extern void pci_io_w32(uint32_t adr, uint32_t data);
+ at end example
+
+
+ at subsubsection Registers over Memory space
+
+PCI host bridge hardware normally swap data accesses into the endianness of the
+host architecture in order to lower the load of the CPU, peripherals can do DMA
+without swapping. However, the host controller can not separate a standard
+memory access from a memory access to a register, registers may be mapped into
+memory space. This leads to register content being swapped, which must be
+swapped back. The below routines makes it possible to access registers over PCI
+memory space in a portable way on different architectures, the BSP or
+architecture must provide necessary functions in order to implement this.
+
+ at example
+  static inline uint16_t pci_ld_le16(volatile uint16_t *addr);
+  static inline void pci_st_le16(volatile uint16_t *addr, uint16_t val);
+  static inline uint32_t pci_ld_le32(volatile uint32_t *addr);
+  static inline void pci_st_le32(volatile uint32_t *addr, uint32_t val);
+  static inline uint16_t pci_ld_be16(volatile uint16_t *addr);
+  static inline void pci_st_be16(volatile uint16_t *addr, uint16_t val);
+  static inline uint32_t pci_ld_be32(volatile uint32_t *addr);
+  static inline void pci_st_be32(volatile uint32_t *addr, uint32_t val);
+ at end example
+
+In order to support non-standard big-endian PCI bus the above pci_* functions
+is required, pci_ld_le16 != ld_le16 on big endian PCI buses. 
+
+
+ at subsubsection Access functions
+
+The PCI Access Library can provide device drivers with function pointers
+executing the above Configuration, I/O and Memory space accesses. The
+functions have the same arguments and return values as the as the above
+functions.
+
+The pci_access_func() function defined below can be used to get a function
+pointer of a specific access type.
+
+ at example
+  /* Get Read/Write function for accessing a register over PCI Memory Space
+   * (non-inline functions).
+   *
+   * Arguments
+   *  wr             0(Read), 1(Write)
+   *  size           1(Byte), 2(Word), 4(Double Word)
+   *  func           Where function pointer will be stored
+   *  endian         PCI_LITTLE_ENDIAN or PCI_BIG_ENDIAN
+   *  type           1(I/O), 3(REG over MEM), 4(CFG)
+   *
+   * Return
+   *  0              Found function
+   *  others         No such function defined by host driver or BSP
+   */
+  int pci_access_func(int wr, int size, void **func, int endian, int type);
+ at end example
+
+PCI devices drivers may be written to support run-time detection of endianess,
+this is mosly for debugging or for development systems. When the product is
+finally deployed macros switch to using the inline functions instead which
+have been configured for the correct endianness.
+
+
+ at subsubsection PCI address translation
+
+When PCI addresses, both I/O and memory space, is not mapped 1:1 address
+translation before access is needed. If drivers read the PCI resources directly
+using configuration space routines or in the device tree, the addresses given
+are PCI addresses. The below functions can be used to translate PCI addresses
+into CPU accessible addresses or vise versa, translation may be different for
+different PCI spaces/regions.
+
+ at example
+  /* Translate PCI address into CPU accessible address */
+  static inline int pci_pci2cpu(uint32_t *address, int type);
+
+  /* Translate CPU accessible address into PCI address (for DMA) */
+  static inline int pci_cpu2pci(uint32_t *address, int type);
+ at end example
+
+
+ at subsection PCI Interrupt
+
+The PCI specification defines four different interrupt lines INTA#..INTD#,
+the interrupts are low level sensitive which make it possible to support
+multiple interrupt sources on the same interrupt line. Since the lines are
+level sensitive the interrupt sources must be acknowledged before clearing the
+interrupt contoller, or the interrupt controller must be masked. The BSP must
+provide a routine for clearing/acknowledging the interrupt controller, it is
+up to the interrupt service routine to acknowledge the interrupt source.
+
+The PCI Library relies on the BSP for implementing shared interrupt handling
+through the BSP_PCI_shared_interrupt_* functions/macros, they must be defined
+when including bsp.h.
+
+PCI device drivers may use the pci_interrupt_ routines in order to call the
+BSP specific functions in a platform independent way. The PCI interrupt
+interface has been made similar to the RTEMS IRQ extension so that a BSP can
+use the standard RTEMS interrupt functions directly.
+
+
+ at subsection PCI Shell command
+
+The RTEMS shell have a PCI command 'pci' which makes it possible to read/write
+configuration space, print the current PCI configuration and print out a
+configuration C-file for the static or peripheral library.
-- 
1.7.0.4




More information about the devel mailing list