summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDaniel Hellstrom <daniel@gaisler.com>2011-11-28 10:11:10 +0100
committerDaniel Hellstrom <daniel@gaisler.com>2015-04-17 01:10:15 +0200
commita31845f7f9b4770cf9ddd8b6820641d2f4f4c1da (patch)
tree0d7f215ec45d7c4cf6f1293af72ece2fbde1ddc3
parentleon3,ngmp: simplify cpucounter initialization (diff)
downloadrtems-a31845f7f9b4770cf9ddd8b6820641d2f4f4c1da.tar.bz2
LIBPCI: added PCI layer to cpukit/libpci
-rw-r--r--cpukit/Makefile.am3
-rw-r--r--cpukit/configure.ac12
-rw-r--r--cpukit/libpci/CHANGES46
-rw-r--r--cpukit/libpci/Makefile.am46
-rw-r--r--cpukit/libpci/README4
-rw-r--r--cpukit/libpci/pci.h375
-rw-r--r--cpukit/libpci/pci/access.h351
-rw-r--r--cpukit/libpci/pci/cfg.h244
-rw-r--r--cpukit/libpci/pci/cfg_auto.h59
-rw-r--r--cpukit/libpci/pci/cfg_peripheral.h20
-rw-r--r--cpukit/libpci/pci/cfg_read.h22
-rw-r--r--cpukit/libpci/pci/cfg_static.h22
-rw-r--r--cpukit/libpci/pci/ids.h802
-rw-r--r--cpukit/libpci/pci/ids_extra.h19
-rw-r--r--cpukit/libpci/pci/irq.h105
-rw-r--r--cpukit/libpci/pci_access.c74
-rw-r--r--cpukit/libpci/pci_access_func.c73
-rw-r--r--cpukit/libpci/pci_access_io.c48
-rw-r--r--cpukit/libpci/pci_access_mem.c22
-rw-r--r--cpukit/libpci/pci_access_mem_be.c67
-rw-r--r--cpukit/libpci/pci_access_mem_le.c66
-rw-r--r--cpukit/libpci/pci_cfg.c55
-rw-r--r--cpukit/libpci/pci_cfg_auto.c1014
-rw-r--r--cpukit/libpci/pci_cfg_peripheral.c32
-rw-r--r--cpukit/libpci/pci_cfg_print_code.c172
-rw-r--r--cpukit/libpci/pci_cfg_read.c357
-rw-r--r--cpukit/libpci/pci_cfg_static.c157
-rw-r--r--cpukit/libpci/pci_find.c52
-rw-r--r--cpukit/libpci/pci_find_dev.c49
-rw-r--r--cpukit/libpci/pci_for_each.c62
-rw-r--r--cpukit/libpci/pci_for_each_child.c41
-rw-r--r--cpukit/libpci/pci_for_each_dev.c18
-rw-r--r--cpukit/libpci/pci_get_dev.c36
-rw-r--r--cpukit/libpci/pci_irq.c20
-rw-r--r--cpukit/libpci/pci_print.c190
-rw-r--r--cpukit/libpci/preinstall.am66
-rw-r--r--cpukit/preinstall.am3
-rw-r--r--cpukit/sapi/include/confdefs.h46
-rw-r--r--cpukit/wrapup/Makefile.am2
-rw-r--r--doc/ada_user/Makefile.am1
-rw-r--r--doc/ada_user/ada_user.texi2
-rw-r--r--doc/develenv/direct.t3
-rw-r--r--doc/user/Makefile.am9
-rw-r--r--doc/user/c_user.texi2
-rw-r--r--doc/user/conf.t53
-rw-r--r--doc/user/libpci.t409
46 files changed, 5328 insertions, 3 deletions
diff --git a/cpukit/Makefile.am b/cpukit/Makefile.am
index 7df116ce07..d68f0576d2 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 00580824a0..d04ce87efd 100644
--- a/cpukit/configure.ac
+++ b/cpukit/configure.ac
@@ -410,6 +410,17 @@ esac
AM_CONDITIONAL(SHA,[test x"$HAVE_SHA" = x"yes"])
AC_MSG_RESULT([$HAVE_SHA])
+# 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
@@ -448,6 +459,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 0000000000..46064f0faa
--- /dev/null
+++ b/cpukit/libpci/CHANGES
@@ -0,0 +1,46 @@
+ 2011-03-03, Daniel Hellstrom <daniel@gaisler.com>
+ Added support for ROM BARs at devices and PCI-PCI bridges.
+
+ 2011-02-11, Daniel Hellstrom <daniel@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@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@gaisler.com>
+ Fixed I/O BAR size calculation of bridges. Reading/Writing to 0x1C instead of
+ faulty 0x1E.
+
+ 2010-06-10, Daniel Hellstrom <daniel@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@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@gaisler.com>
+ Fixed autoconf issue when bridges are present
+
+ 2010-02-03, Daniel Hellstrom <daniel@gaisler.com>
+ Fixed initialization problem when first device is a bridge.
+
+ 2010-02-03, Daniel Hellstrom <daniel@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 0000000000..fd42a6fdcf
--- /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 0000000000..334f3a9271
--- /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 0000000000..e9955bc6a2
--- /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@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 0000000000..f8365db604
--- /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 0000000000..18c48db5c2
--- /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 0000000000..25e733640c
--- /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 0000000000..68f2e24e2f
--- /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 0000000000..af60a4e5e3
--- /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 0000000000..5633dfcdb5
--- /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 0000000000..2d2592bc03
--- /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@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 0000000000..ffa18cb271
--- /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 0000000000..2dacadf4c4
--- /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 0000000000..371c5ef24e
--- /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 0000000000..d86ccab357
--- /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 0000000000..12e6699c65
--- /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 0000000000..216f83fe90
--- /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 0000000000..f05b547e1c
--- /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 0000000000..2746f24a4f
--- /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 0000000000..78a1229f29
--- /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 0000000000..548dd90185
--- /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 0000000000..d1ba4c93a6
--- /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 0000000000..8770c8a717
--- /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 0000000000..2db465db2c
--- /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 0000000000..d7d43211d8
--- /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 0000000000..945cb56ea9
--- /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 0000000000..184d05cb67
--- /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 0000000000..dc0a9a16f1
--- /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 0000000000..9d08b77051
--- /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 0000000000..c2b3934fdc
--- /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 0000000000..5e07653e6c
--- /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 0000000000..e379852c8b
--- /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 0000000000..9c40f1e437
--- /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 0000000000..b19d28830f
--- /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 40273bb71d..640a17a335 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 d1a5229c5b..daeda0be3c 100644
--- a/cpukit/sapi/include/confdefs.h
+++ b/cpukit/sapi/include/confdefs.h
@@ -3480,6 +3480,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 c45bf28648..5dc23a6a32 100644
--- a/cpukit/wrapup/Makefile.am
+++ b/cpukit/wrapup/Makefile.am
@@ -66,6 +66,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 ab19e71643..f925100682 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 da5836c6ad..006dfd5967 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::
@@ -153,6 +154,7 @@
@include user/conf.texi
@include user/mp.texi
@include user/smp.texi
+@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 a512145840..9950b69274 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.
+@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 cd8b5f3f4d..f17179e416 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 2ff47bf54b..bdf0cd574e 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
+@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 fe714b42d4..ae2d9668ea 100644
--- a/doc/user/conf.t
+++ b/doc/user/conf.t
@@ -5273,6 +5273,59 @@ uses the Ada run-time.
None.
@c
+@c === PCI Library ===
+@c
+@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:
+
+@itemize @bullet
+@findex PCI_LIB_AUTO
+@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.
+
+@findex PCI_LIB_READ
+@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.
+
+@findex PCI_LIB_STATIC
+@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
+@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.
+
+@findex PCI_LIB_PERIPHERAL
+@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.
+
+@end itemize
+
+Note that selecting PCI_LIB_STATIC or PCI_LIB_PERIPHERAL but not defining
+@code{pci_hb} will reuslt in link errors. Note also that in these modes
+Plug & Play is not performed.
+
+@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 0000000000..1eaca42018
--- /dev/null
+++ b/doc/user/libpci.t
@@ -0,0 +1,409 @@
+@c
+@c COPYRIGHT (c) 2011
+@c Aeroflex Gaisler AB
+@c All rights reserved.
+@c
+@c $Id: libpci.t,v v.vv xxxx/yy/zz xx:yy:zz ? Exp $
+@c
+
+@chapter PCI Library
+
+@cindex libpci
+
+@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.
+@itemize @bullet
+@item Auto Configuration (do Plug & Play)
+@item Read Configuration (read BIOS or boot loader configuration)
+@item Static Configuration (write user defined configuration)
+@item Peripheral Configuration (no access to cfg-space)
+@end itemize
+
+@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
+
+@subsection Software Components
+
+The PCI library is located in cpukit/libpci, it consists of different parts:
+@itemize @bullet
+@item PCI Host bridge driver interface
+@item Configuration routines
+@item Access (Configuration, I/O and Memory space) routines
+@item Interrupt routines (implemented by BSP)
+@item Print routines
+@item Static/peripheral configuration creation
+@item PCI shell command
+@end itemize
+
+@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:
+@enumerate
+@item I/O space (IO)
+@item non-prefetchable Memory space (MEMIO)
+@item prefetchable Memory space (MEM)
+@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:
+@itemize @bullet
+@item Auto Configuration (run Plug & Play software)
+@item Read Configuration (relies on a boot loader or BIOS)
+@item Static Configuration (write user defined setup, no Plug & Play)
+@item Peripheral Configuration (user defined setup, no access to configuration space)
+@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.
+
+
+@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
+@itemize @bullet
+@item CONFIGURE_INIT
+@item RTEMS_PCI_CONFIG_LIB
+@item CONFIGURE_PCI_LIB = PCI_LIB_(AUTO,STATIC,READ,PERIPHERAL)
+@end itemize
+
+See the RTEMS configuration section how to setup the PCI library.
+
+
+@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:
+@itemize @bullet
+@item PCI 2.3
+@item Little and big endian PCI bus
+@item one I/O 16 or 32-bit range (IO)
+@item memory space (MEMIO)
+@item prefetchable memory space (MEM), if not present MEM will be mapped into
+ MEMIO
+@item multiple PCI buses - PCI-to-PCI bridges
+@item standard BARs, PCI-to-PCI bridge BARs, ROM BARs
+@item Interrupt routing over bridges
+@item Interrupt pin to system interrupt mapping
+@end itemize
+
+Not supported:
+@itemize @bullet
+@item hot-pluggable devices
+@item Cardbus bridges
+@item 64-bit memory space
+@item 16-bit and 32-bit I/O address ranges at the same time
+@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.
+
+
+@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.
+
+
+@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.
+
+
+@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
+
+
+@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.
+@itemize @bullet
+@item PCI configuration space
+@item PCI I/O space
+@item Registers over PCI memory space
+@item Translate PCI address into CPU accessible address and vice verse
+@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".
+
+
+@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).
+
+@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);
+@end example
+
+
+@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.
+
+@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);
+@end example
+
+
+@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.
+
+@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);
+@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.
+
+
+@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.
+
+@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);
+@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.
+
+
+@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.
+
+@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);
+@end example
+
+
+@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.
+
+
+@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.