qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Qemu-devel] [PATCH 3/8] pci: move pci core code to hw/pci


From: Michael S. Tsirkin
Subject: [Qemu-devel] [PATCH 3/8] pci: move pci core code to hw/pci
Date: Wed, 12 Dec 2012 15:14:13 +0200

Move files and modify makefiles to pick them at the
new location.

Signed-off-by: Michael S. Tsirkin <address@hidden>
---
 hw/Makefile.objs       |   10 +-
 hw/i386/Makefile.objs  |    2 +-
 hw/msi.c               |  395 ---------
 hw/msi.h               |   50 --
 hw/msix.c              |  562 -------------
 hw/msix.h              |   41 -
 hw/pci-hotplug.c       |  293 -------
 hw/pci-stub.c          |   47 --
 hw/pci.c               | 2168 ------------------------------------------------
 hw/pci.h               |  684 ---------------
 hw/pci/Makefile.objs   |    6 +
 hw/pci/msi.c           |  395 +++++++++
 hw/pci/msi.h           |   50 ++
 hw/pci/msix.c          |  562 +++++++++++++
 hw/pci/msix.h          |   41 +
 hw/pci/pci-hotplug.c   |  293 +++++++
 hw/pci/pci-stub.c      |   47 ++
 hw/pci/pci.c           | 2168 ++++++++++++++++++++++++++++++++++++++++++++++++
 hw/pci/pci.h           |  684 +++++++++++++++
 hw/pci/pci_bridge.c    |  363 ++++++++
 hw/pci/pci_bridge.h    |   66 ++
 hw/pci/pci_host.c      |  180 ++++
 hw/pci/pci_host.h      |   62 ++
 hw/pci/pci_ids.h       |  147 ++++
 hw/pci/pci_internals.h |   78 ++
 hw/pci/pci_regs.h      |  717 ++++++++++++++++
 hw/pci/pcie.c          |  555 +++++++++++++
 hw/pci/pcie.h          |  142 ++++
 hw/pci/pcie_aer.c      | 1032 +++++++++++++++++++++++
 hw/pci/pcie_aer.h      |  106 +++
 hw/pci/pcie_host.c     |  161 ++++
 hw/pci/pcie_host.h     |   54 ++
 hw/pci/pcie_port.c     |  114 +++
 hw/pci/pcie_port.h     |   51 ++
 hw/pci/pcie_regs.h     |  156 ++++
 hw/pci/shpc.c          |  681 +++++++++++++++
 hw/pci/shpc.h          |   48 ++
 hw/pci/slotid_cap.c    |   44 +
 hw/pci/slotid_cap.h    |   11 +
 hw/pci_bridge.c        |  363 --------
 hw/pci_bridge.h        |   66 --
 hw/pci_host.c          |  180 ----
 hw/pci_host.h          |   62 --
 hw/pci_ids.h           |  147 ----
 hw/pci_internals.h     |   78 --
 hw/pci_regs.h          |  717 ----------------
 hw/pcie.c              |  555 -------------
 hw/pcie.h              |  142 ----
 hw/pcie_aer.c          | 1032 -----------------------
 hw/pcie_aer.h          |  106 ---
 hw/pcie_host.c         |  161 ----
 hw/pcie_host.h         |   54 --
 hw/pcie_port.c         |  114 ---
 hw/pcie_port.h         |   51 --
 hw/pcie_regs.h         |  156 ----
 hw/ppc/Makefile.objs   |    2 +-
 hw/shpc.c              |  681 ---------------
 hw/shpc.h              |   48 --
 hw/slotid_cap.c        |   44 -
 hw/slotid_cap.h        |   11 -
 60 files changed, 9018 insertions(+), 9018 deletions(-)
 delete mode 100644 hw/msi.c
 delete mode 100644 hw/msi.h
 delete mode 100644 hw/msix.c
 delete mode 100644 hw/msix.h
 delete mode 100644 hw/pci-hotplug.c
 delete mode 100644 hw/pci-stub.c
 delete mode 100644 hw/pci.c
 delete mode 100644 hw/pci.h
 create mode 100644 hw/pci/Makefile.objs
 create mode 100644 hw/pci/msi.c
 create mode 100644 hw/pci/msi.h
 create mode 100644 hw/pci/msix.c
 create mode 100644 hw/pci/msix.h
 create mode 100644 hw/pci/pci-hotplug.c
 create mode 100644 hw/pci/pci-stub.c
 create mode 100644 hw/pci/pci.c
 create mode 100644 hw/pci/pci.h
 create mode 100644 hw/pci/pci_bridge.c
 create mode 100644 hw/pci/pci_bridge.h
 create mode 100644 hw/pci/pci_host.c
 create mode 100644 hw/pci/pci_host.h
 create mode 100644 hw/pci/pci_ids.h
 create mode 100644 hw/pci/pci_internals.h
 create mode 100644 hw/pci/pci_regs.h
 create mode 100644 hw/pci/pcie.c
 create mode 100644 hw/pci/pcie.h
 create mode 100644 hw/pci/pcie_aer.c
 create mode 100644 hw/pci/pcie_aer.h
 create mode 100644 hw/pci/pcie_host.c
 create mode 100644 hw/pci/pcie_host.h
 create mode 100644 hw/pci/pcie_port.c
 create mode 100644 hw/pci/pcie_port.h
 create mode 100644 hw/pci/pcie_regs.h
 create mode 100644 hw/pci/shpc.c
 create mode 100644 hw/pci/shpc.h
 create mode 100644 hw/pci/slotid_cap.c
 create mode 100644 hw/pci/slotid_cap.h
 delete mode 100644 hw/pci_bridge.c
 delete mode 100644 hw/pci_bridge.h
 delete mode 100644 hw/pci_host.c
 delete mode 100644 hw/pci_host.h
 delete mode 100644 hw/pci_ids.h
 delete mode 100644 hw/pci_internals.h
 delete mode 100644 hw/pci_regs.h
 delete mode 100644 hw/pcie.c
 delete mode 100644 hw/pcie.h
 delete mode 100644 hw/pcie_aer.c
 delete mode 100644 hw/pcie_aer.h
 delete mode 100644 hw/pcie_host.c
 delete mode 100644 hw/pcie_host.h
 delete mode 100644 hw/pcie_port.c
 delete mode 100644 hw/pcie_port.h
 delete mode 100644 hw/pcie_regs.h
 delete mode 100644 hw/shpc.c
 delete mode 100644 hw/shpc.h
 delete mode 100644 hw/slotid_cap.c
 delete mode 100644 hw/slotid_cap.h

diff --git a/hw/Makefile.objs b/hw/Makefile.objs
index d581d8d..228acd6 100644
--- a/hw/Makefile.objs
+++ b/hw/Makefile.objs
@@ -1,14 +1,10 @@
-common-obj-y = usb/ ide/
+common-obj-y = usb/ ide/ pci/
 common-obj-y += loader.o
 common-obj-$(CONFIG_VIRTIO) += virtio-console.o
 common-obj-$(CONFIG_VIRTIO) += virtio-rng.o
 common-obj-$(CONFIG_VIRTIO_PCI) += virtio-pci.o
 common-obj-y += fw_cfg.o
-common-obj-$(CONFIG_PCI) += pci.o pci_bridge.o pci_bridge_dev.o
-common-obj-$(CONFIG_PCI) += msix.o msi.o
-common-obj-$(CONFIG_PCI) += shpc.o
-common-obj-$(CONFIG_PCI) += slotid_cap.o
-common-obj-$(CONFIG_PCI) += pci_host.o pcie_host.o
+common-obj-$(CONFIG_PCI) += pci_bridge_dev.o
 common-obj-$(CONFIG_PCI) += ioh3420.o xio3130_upstream.o xio3130_downstream.o
 common-obj-$(CONFIG_PCI) += i82801b11.o
 common-obj-y += watchdog.o
@@ -102,8 +98,6 @@ common-obj-$(CONFIG_XGMAC) += xgmac.o
 # PCI watchdog devices
 common-obj-$(CONFIG_PCI) += wdt_i6300esb.o
 
-common-obj-$(CONFIG_PCI) += pcie.o pcie_aer.o pcie_port.o
-
 # PCI network cards
 common-obj-$(CONFIG_NE2000_PCI) += ne2000.o
 common-obj-$(CONFIG_EEPRO100_PCI) += eepro100.o
diff --git a/hw/i386/Makefile.objs b/hw/i386/Makefile.objs
index 0d3f6a8..257f3c1 100644
--- a/hw/i386/Makefile.objs
+++ b/hw/i386/Makefile.objs
@@ -2,7 +2,7 @@ obj-y += mc146818rtc.o pc.o
 obj-y += apic_common.o apic.o kvmvapic.o
 obj-y += sga.o ioapic_common.o ioapic.o piix_pci.o
 obj-y += vmport.o
-obj-y += pci-hotplug.o smbios.o wdt_ib700.o
+obj-y += pci/pci-hotplug.o smbios.o wdt_ib700.o
 obj-y += debugcon.o multiboot.o
 obj-y += pc_piix.o
 obj-y += pc_sysfw.o
diff --git a/hw/msi.c b/hw/msi.c
deleted file mode 100644
index 33037a8..0000000
--- a/hw/msi.c
+++ /dev/null
@@ -1,395 +0,0 @@
-/*
- * msi.c
- *
- * Copyright (c) 2010 Isaku Yamahata <yamahata at valinux co jp>
- *                    VA Linux Systems Japan K.K.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
-
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
-
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, see <http://www.gnu.org/licenses/>.
- */
-
-#include "msi.h"
-#include "range.h"
-
-/* Eventually those constants should go to Linux pci_regs.h */
-#define PCI_MSI_PENDING_32      0x10
-#define PCI_MSI_PENDING_64      0x14
-
-/* PCI_MSI_ADDRESS_LO */
-#define PCI_MSI_ADDRESS_LO_MASK         (~0x3)
-
-/* If we get rid of cap allocator, we won't need those. */
-#define PCI_MSI_32_SIZEOF       0x0a
-#define PCI_MSI_64_SIZEOF       0x0e
-#define PCI_MSI_32M_SIZEOF      0x14
-#define PCI_MSI_64M_SIZEOF      0x18
-
-#define PCI_MSI_VECTORS_MAX     32
-
-/* Flag for interrupt controller to declare MSI/MSI-X support */
-bool msi_supported;
-
-/* If we get rid of cap allocator, we won't need this. */
-static inline uint8_t msi_cap_sizeof(uint16_t flags)
-{
-    switch (flags & (PCI_MSI_FLAGS_MASKBIT | PCI_MSI_FLAGS_64BIT)) {
-    case PCI_MSI_FLAGS_MASKBIT | PCI_MSI_FLAGS_64BIT:
-        return PCI_MSI_64M_SIZEOF;
-    case PCI_MSI_FLAGS_64BIT:
-        return PCI_MSI_64_SIZEOF;
-    case PCI_MSI_FLAGS_MASKBIT:
-        return PCI_MSI_32M_SIZEOF;
-    case 0:
-        return PCI_MSI_32_SIZEOF;
-    default:
-        abort();
-        break;
-    }
-    return 0;
-}
-
-//#define MSI_DEBUG
-
-#ifdef MSI_DEBUG
-# define MSI_DPRINTF(fmt, ...)                                          \
-    fprintf(stderr, "%s:%d " fmt, __func__, __LINE__, ## __VA_ARGS__)
-#else
-# define MSI_DPRINTF(fmt, ...)  do { } while (0)
-#endif
-#define MSI_DEV_PRINTF(dev, fmt, ...)                                   \
-    MSI_DPRINTF("%s:%x " fmt, (dev)->name, (dev)->devfn, ## __VA_ARGS__)
-
-static inline unsigned int msi_nr_vectors(uint16_t flags)
-{
-    return 1U <<
-        ((flags & PCI_MSI_FLAGS_QSIZE) >> (ffs(PCI_MSI_FLAGS_QSIZE) - 1));
-}
-
-static inline uint8_t msi_flags_off(const PCIDevice* dev)
-{
-    return dev->msi_cap + PCI_MSI_FLAGS;
-}
-
-static inline uint8_t msi_address_lo_off(const PCIDevice* dev)
-{
-    return dev->msi_cap + PCI_MSI_ADDRESS_LO;
-}
-
-static inline uint8_t msi_address_hi_off(const PCIDevice* dev)
-{
-    return dev->msi_cap + PCI_MSI_ADDRESS_HI;
-}
-
-static inline uint8_t msi_data_off(const PCIDevice* dev, bool msi64bit)
-{
-    return dev->msi_cap + (msi64bit ? PCI_MSI_DATA_64 : PCI_MSI_DATA_32);
-}
-
-static inline uint8_t msi_mask_off(const PCIDevice* dev, bool msi64bit)
-{
-    return dev->msi_cap + (msi64bit ? PCI_MSI_MASK_64 : PCI_MSI_MASK_32);
-}
-
-static inline uint8_t msi_pending_off(const PCIDevice* dev, bool msi64bit)
-{
-    return dev->msi_cap + (msi64bit ? PCI_MSI_PENDING_64 : PCI_MSI_PENDING_32);
-}
-
-/*
- * Special API for POWER to configure the vectors through
- * a side channel. Should never be used by devices.
- */
-void msi_set_message(PCIDevice *dev, MSIMessage msg)
-{
-    uint16_t flags = pci_get_word(dev->config + msi_flags_off(dev));
-    bool msi64bit = flags & PCI_MSI_FLAGS_64BIT;
-
-    if (msi64bit) {
-        pci_set_quad(dev->config + msi_address_lo_off(dev), msg.address);
-    } else {
-        pci_set_long(dev->config + msi_address_lo_off(dev), msg.address);
-    }
-    pci_set_word(dev->config + msi_data_off(dev, msi64bit), msg.data);
-}
-
-MSIMessage msi_get_message(PCIDevice *dev, unsigned int vector)
-{
-    uint16_t flags = pci_get_word(dev->config + msi_flags_off(dev));
-    bool msi64bit = flags & PCI_MSI_FLAGS_64BIT;
-    unsigned int nr_vectors = msi_nr_vectors(flags);
-    MSIMessage msg;
-
-    assert(vector < nr_vectors);
-
-    if (msi64bit) {
-        msg.address = pci_get_quad(dev->config + msi_address_lo_off(dev));
-    } else {
-        msg.address = pci_get_long(dev->config + msi_address_lo_off(dev));
-    }
-
-    /* upper bit 31:16 is zero */
-    msg.data = pci_get_word(dev->config + msi_data_off(dev, msi64bit));
-    if (nr_vectors > 1) {
-        msg.data &= ~(nr_vectors - 1);
-        msg.data |= vector;
-    }
-
-    return msg;
-}
-
-bool msi_enabled(const PCIDevice *dev)
-{
-    return msi_present(dev) &&
-        (pci_get_word(dev->config + msi_flags_off(dev)) &
-         PCI_MSI_FLAGS_ENABLE);
-}
-
-int msi_init(struct PCIDevice *dev, uint8_t offset,
-             unsigned int nr_vectors, bool msi64bit, bool msi_per_vector_mask)
-{
-    unsigned int vectors_order;
-    uint16_t flags;
-    uint8_t cap_size;
-    int config_offset;
-
-    if (!msi_supported) {
-        return -ENOTSUP;
-    }
-
-    MSI_DEV_PRINTF(dev,
-                   "init offset: 0x%"PRIx8" vector: %"PRId8
-                   " 64bit %d mask %d\n",
-                   offset, nr_vectors, msi64bit, msi_per_vector_mask);
-
-    assert(!(nr_vectors & (nr_vectors - 1)));   /* power of 2 */
-    assert(nr_vectors > 0);
-    assert(nr_vectors <= PCI_MSI_VECTORS_MAX);
-    /* the nr of MSI vectors is up to 32 */
-    vectors_order = ffs(nr_vectors) - 1;
-
-    flags = vectors_order << (ffs(PCI_MSI_FLAGS_QMASK) - 1);
-    if (msi64bit) {
-        flags |= PCI_MSI_FLAGS_64BIT;
-    }
-    if (msi_per_vector_mask) {
-        flags |= PCI_MSI_FLAGS_MASKBIT;
-    }
-
-    cap_size = msi_cap_sizeof(flags);
-    config_offset = pci_add_capability(dev, PCI_CAP_ID_MSI, offset, cap_size);
-    if (config_offset < 0) {
-        return config_offset;
-    }
-
-    dev->msi_cap = config_offset;
-    dev->cap_present |= QEMU_PCI_CAP_MSI;
-
-    pci_set_word(dev->config + msi_flags_off(dev), flags);
-    pci_set_word(dev->wmask + msi_flags_off(dev),
-                 PCI_MSI_FLAGS_QSIZE | PCI_MSI_FLAGS_ENABLE);
-    pci_set_long(dev->wmask + msi_address_lo_off(dev),
-                 PCI_MSI_ADDRESS_LO_MASK);
-    if (msi64bit) {
-        pci_set_long(dev->wmask + msi_address_hi_off(dev), 0xffffffff);
-    }
-    pci_set_word(dev->wmask + msi_data_off(dev, msi64bit), 0xffff);
-
-    if (msi_per_vector_mask) {
-        /* Make mask bits 0 to nr_vectors - 1 writable. */
-        pci_set_long(dev->wmask + msi_mask_off(dev, msi64bit),
-                     0xffffffff >> (PCI_MSI_VECTORS_MAX - nr_vectors));
-    }
-    return config_offset;
-}
-
-void msi_uninit(struct PCIDevice *dev)
-{
-    uint16_t flags;
-    uint8_t cap_size;
-
-    if (!msi_present(dev)) {
-        return;
-    }
-    flags = pci_get_word(dev->config + msi_flags_off(dev));
-    cap_size = msi_cap_sizeof(flags);
-    pci_del_capability(dev, PCI_CAP_ID_MSI, cap_size);
-    dev->cap_present &= ~QEMU_PCI_CAP_MSI;
-
-    MSI_DEV_PRINTF(dev, "uninit\n");
-}
-
-void msi_reset(PCIDevice *dev)
-{
-    uint16_t flags;
-    bool msi64bit;
-
-    if (!msi_present(dev)) {
-        return;
-    }
-
-    flags = pci_get_word(dev->config + msi_flags_off(dev));
-    flags &= ~(PCI_MSI_FLAGS_QSIZE | PCI_MSI_FLAGS_ENABLE);
-    msi64bit = flags & PCI_MSI_FLAGS_64BIT;
-
-    pci_set_word(dev->config + msi_flags_off(dev), flags);
-    pci_set_long(dev->config + msi_address_lo_off(dev), 0);
-    if (msi64bit) {
-        pci_set_long(dev->config + msi_address_hi_off(dev), 0);
-    }
-    pci_set_word(dev->config + msi_data_off(dev, msi64bit), 0);
-    if (flags & PCI_MSI_FLAGS_MASKBIT) {
-        pci_set_long(dev->config + msi_mask_off(dev, msi64bit), 0);
-        pci_set_long(dev->config + msi_pending_off(dev, msi64bit), 0);
-    }
-    MSI_DEV_PRINTF(dev, "reset\n");
-}
-
-static bool msi_is_masked(const PCIDevice *dev, unsigned int vector)
-{
-    uint16_t flags = pci_get_word(dev->config + msi_flags_off(dev));
-    uint32_t mask;
-    assert(vector < PCI_MSI_VECTORS_MAX);
-
-    if (!(flags & PCI_MSI_FLAGS_MASKBIT)) {
-        return false;
-    }
-
-    mask = pci_get_long(dev->config +
-                        msi_mask_off(dev, flags & PCI_MSI_FLAGS_64BIT));
-    return mask & (1U << vector);
-}
-
-void msi_notify(PCIDevice *dev, unsigned int vector)
-{
-    uint16_t flags = pci_get_word(dev->config + msi_flags_off(dev));
-    bool msi64bit = flags & PCI_MSI_FLAGS_64BIT;
-    unsigned int nr_vectors = msi_nr_vectors(flags);
-    MSIMessage msg;
-
-    assert(vector < nr_vectors);
-    if (msi_is_masked(dev, vector)) {
-        assert(flags & PCI_MSI_FLAGS_MASKBIT);
-        pci_long_test_and_set_mask(
-            dev->config + msi_pending_off(dev, msi64bit), 1U << vector);
-        MSI_DEV_PRINTF(dev, "pending vector 0x%x\n", vector);
-        return;
-    }
-
-    msg = msi_get_message(dev, vector);
-
-    MSI_DEV_PRINTF(dev,
-                   "notify vector 0x%x"
-                   " address: 0x%"PRIx64" data: 0x%"PRIx32"\n",
-                   vector, msg.address, msg.data);
-    stl_le_phys(msg.address, msg.data);
-}
-
-/* Normally called by pci_default_write_config(). */
-void msi_write_config(PCIDevice *dev, uint32_t addr, uint32_t val, int len)
-{
-    uint16_t flags = pci_get_word(dev->config + msi_flags_off(dev));
-    bool msi64bit = flags & PCI_MSI_FLAGS_64BIT;
-    bool msi_per_vector_mask = flags & PCI_MSI_FLAGS_MASKBIT;
-    unsigned int nr_vectors;
-    uint8_t log_num_vecs;
-    uint8_t log_max_vecs;
-    unsigned int vector;
-    uint32_t pending;
-
-    if (!msi_present(dev) ||
-        !ranges_overlap(addr, len, dev->msi_cap, msi_cap_sizeof(flags))) {
-        return;
-    }
-
-#ifdef MSI_DEBUG
-    MSI_DEV_PRINTF(dev, "addr 0x%"PRIx32" val 0x%"PRIx32" len %d\n",
-                   addr, val, len);
-    MSI_DEV_PRINTF(dev, "ctrl: 0x%"PRIx16" address: 0x%"PRIx32,
-                   flags,
-                   pci_get_long(dev->config + msi_address_lo_off(dev)));
-    if (msi64bit) {
-        fprintf(stderr, " address-hi: 0x%"PRIx32,
-                pci_get_long(dev->config + msi_address_hi_off(dev)));
-    }
-    fprintf(stderr, " data: 0x%"PRIx16,
-            pci_get_word(dev->config + msi_data_off(dev, msi64bit)));
-    if (flags & PCI_MSI_FLAGS_MASKBIT) {
-        fprintf(stderr, " mask 0x%"PRIx32" pending 0x%"PRIx32,
-                pci_get_long(dev->config + msi_mask_off(dev, msi64bit)),
-                pci_get_long(dev->config + msi_pending_off(dev, msi64bit)));
-    }
-    fprintf(stderr, "\n");
-#endif
-
-    if (!(flags & PCI_MSI_FLAGS_ENABLE)) {
-        return;
-    }
-
-    /*
-     * Now MSI is enabled, clear INTx# interrupts.
-     * the driver is prohibited from writing enable bit to mask
-     * a service request. But the guest OS could do this.
-     * So we just discard the interrupts as moderate fallback.
-     *
-     * 6.8.3.3. Enabling Operation
-     *   While enabled for MSI or MSI-X operation, a function is prohibited
-     *   from using its INTx# pin (if implemented) to request
-     *   service (MSI, MSI-X, and INTx# are mutually exclusive).
-     */
-    pci_device_deassert_intx(dev);
-
-    /*
-     * nr_vectors might be set bigger than capable. So clamp it.
-     * This is not legal by spec, so we can do anything we like,
-     * just don't crash the host
-     */
-    log_num_vecs =
-        (flags & PCI_MSI_FLAGS_QSIZE) >> (ffs(PCI_MSI_FLAGS_QSIZE) - 1);
-    log_max_vecs =
-        (flags & PCI_MSI_FLAGS_QMASK) >> (ffs(PCI_MSI_FLAGS_QMASK) - 1);
-    if (log_num_vecs > log_max_vecs) {
-        flags &= ~PCI_MSI_FLAGS_QSIZE;
-        flags |= log_max_vecs << (ffs(PCI_MSI_FLAGS_QSIZE) - 1);
-        pci_set_word(dev->config + msi_flags_off(dev), flags);
-    }
-
-    if (!msi_per_vector_mask) {
-        /* if per vector masking isn't supported,
-           there is no pending interrupt. */
-        return;
-    }
-
-    nr_vectors = msi_nr_vectors(flags);
-
-    /* This will discard pending interrupts, if any. */
-    pending = pci_get_long(dev->config + msi_pending_off(dev, msi64bit));
-    pending &= 0xffffffff >> (PCI_MSI_VECTORS_MAX - nr_vectors);
-    pci_set_long(dev->config + msi_pending_off(dev, msi64bit), pending);
-
-    /* deliver pending interrupts which are unmasked */
-    for (vector = 0; vector < nr_vectors; ++vector) {
-        if (msi_is_masked(dev, vector) || !(pending & (1U << vector))) {
-            continue;
-        }
-
-        pci_long_test_and_clear_mask(
-            dev->config + msi_pending_off(dev, msi64bit), 1U << vector);
-        msi_notify(dev, vector);
-    }
-}
-
-unsigned int msi_nr_vectors_allocated(const PCIDevice *dev)
-{
-    uint16_t flags = pci_get_word(dev->config + msi_flags_off(dev));
-    return msi_nr_vectors(flags);
-}
diff --git a/hw/msi.h b/hw/msi.h
deleted file mode 100644
index 150b09a..0000000
--- a/hw/msi.h
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * msi.h
- *
- * Copyright (c) 2010 Isaku Yamahata <yamahata at valinux co jp>
- *                    VA Linux Systems Japan K.K.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
-
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
-
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, see <http://www.gnu.org/licenses/>.
- */
-
-#ifndef QEMU_MSI_H
-#define QEMU_MSI_H
-
-#include "qemu-common.h"
-#include "pci.h"
-
-struct MSIMessage {
-    uint64_t address;
-    uint32_t data;
-};
-
-extern bool msi_supported;
-
-void msi_set_message(PCIDevice *dev, MSIMessage msg);
-MSIMessage msi_get_message(PCIDevice *dev, unsigned int vector);
-bool msi_enabled(const PCIDevice *dev);
-int msi_init(struct PCIDevice *dev, uint8_t offset,
-             unsigned int nr_vectors, bool msi64bit, bool msi_per_vector_mask);
-void msi_uninit(struct PCIDevice *dev);
-void msi_reset(PCIDevice *dev);
-void msi_notify(PCIDevice *dev, unsigned int vector);
-void msi_write_config(PCIDevice *dev, uint32_t addr, uint32_t val, int len);
-unsigned int msi_nr_vectors_allocated(const PCIDevice *dev);
-
-static inline bool msi_present(const PCIDevice *dev)
-{
-    return dev->cap_present & QEMU_PCI_CAP_MSI;
-}
-
-#endif /* QEMU_MSI_H */
diff --git a/hw/msix.c b/hw/msix.c
deleted file mode 100644
index 136ef09..0000000
--- a/hw/msix.c
+++ /dev/null
@@ -1,562 +0,0 @@
-/*
- * MSI-X device support
- *
- * This module includes support for MSI-X in pci devices.
- *
- * Author: Michael S. Tsirkin <address@hidden>
- *
- *  Copyright (c) 2009, Red Hat Inc, Michael S. Tsirkin (address@hidden)
- *
- * This work is licensed under the terms of the GNU GPL, version 2.  See
- * the COPYING file in the top-level directory.
- *
- * Contributions after 2012-01-13 are licensed under the terms of the
- * GNU GPL, version 2 or (at your option) any later version.
- */
-
-#include "hw.h"
-#include "msi.h"
-#include "msix.h"
-#include "pci.h"
-#include "range.h"
-
-#define MSIX_CAP_LENGTH 12
-
-/* MSI enable bit and maskall bit are in byte 1 in FLAGS register */
-#define MSIX_CONTROL_OFFSET (PCI_MSIX_FLAGS + 1)
-#define MSIX_ENABLE_MASK (PCI_MSIX_FLAGS_ENABLE >> 8)
-#define MSIX_MASKALL_MASK (PCI_MSIX_FLAGS_MASKALL >> 8)
-
-static MSIMessage msix_get_message(PCIDevice *dev, unsigned vector)
-{
-    uint8_t *table_entry = dev->msix_table + vector * PCI_MSIX_ENTRY_SIZE;
-    MSIMessage msg;
-
-    msg.address = pci_get_quad(table_entry + PCI_MSIX_ENTRY_LOWER_ADDR);
-    msg.data = pci_get_long(table_entry + PCI_MSIX_ENTRY_DATA);
-    return msg;
-}
-
-/*
- * Special API for POWER to configure the vectors through
- * a side channel. Should never be used by devices.
- */
-void msix_set_message(PCIDevice *dev, int vector, struct MSIMessage msg)
-{
-    uint8_t *table_entry = dev->msix_table + vector * PCI_MSIX_ENTRY_SIZE;
-
-    pci_set_quad(table_entry + PCI_MSIX_ENTRY_LOWER_ADDR, msg.address);
-    pci_set_long(table_entry + PCI_MSIX_ENTRY_DATA, msg.data);
-    table_entry[PCI_MSIX_ENTRY_VECTOR_CTRL] &= ~PCI_MSIX_ENTRY_CTRL_MASKBIT;
-}
-
-static uint8_t msix_pending_mask(int vector)
-{
-    return 1 << (vector % 8);
-}
-
-static uint8_t *msix_pending_byte(PCIDevice *dev, int vector)
-{
-    return dev->msix_pba + vector / 8;
-}
-
-static int msix_is_pending(PCIDevice *dev, int vector)
-{
-    return *msix_pending_byte(dev, vector) & msix_pending_mask(vector);
-}
-
-static void msix_set_pending(PCIDevice *dev, int vector)
-{
-    *msix_pending_byte(dev, vector) |= msix_pending_mask(vector);
-}
-
-static void msix_clr_pending(PCIDevice *dev, int vector)
-{
-    *msix_pending_byte(dev, vector) &= ~msix_pending_mask(vector);
-}
-
-static bool msix_vector_masked(PCIDevice *dev, int vector, bool fmask)
-{
-    unsigned offset = vector * PCI_MSIX_ENTRY_SIZE + 
PCI_MSIX_ENTRY_VECTOR_CTRL;
-    return fmask || dev->msix_table[offset] & PCI_MSIX_ENTRY_CTRL_MASKBIT;
-}
-
-static bool msix_is_masked(PCIDevice *dev, int vector)
-{
-    return msix_vector_masked(dev, vector, dev->msix_function_masked);
-}
-
-static void msix_fire_vector_notifier(PCIDevice *dev,
-                                      unsigned int vector, bool is_masked)
-{
-    MSIMessage msg;
-    int ret;
-
-    if (!dev->msix_vector_use_notifier) {
-        return;
-    }
-    if (is_masked) {
-        dev->msix_vector_release_notifier(dev, vector);
-    } else {
-        msg = msix_get_message(dev, vector);
-        ret = dev->msix_vector_use_notifier(dev, vector, msg);
-        assert(ret >= 0);
-    }
-}
-
-static void msix_handle_mask_update(PCIDevice *dev, int vector, bool 
was_masked)
-{
-    bool is_masked = msix_is_masked(dev, vector);
-
-    if (is_masked == was_masked) {
-        return;
-    }
-
-    msix_fire_vector_notifier(dev, vector, is_masked);
-
-    if (!is_masked && msix_is_pending(dev, vector)) {
-        msix_clr_pending(dev, vector);
-        msix_notify(dev, vector);
-    }
-}
-
-static void msix_update_function_masked(PCIDevice *dev)
-{
-    dev->msix_function_masked = !msix_enabled(dev) ||
-        (dev->config[dev->msix_cap + MSIX_CONTROL_OFFSET] & MSIX_MASKALL_MASK);
-}
-
-/* Handle MSI-X capability config write. */
-void msix_write_config(PCIDevice *dev, uint32_t addr,
-                       uint32_t val, int len)
-{
-    unsigned enable_pos = dev->msix_cap + MSIX_CONTROL_OFFSET;
-    int vector;
-    bool was_masked;
-
-    if (!msix_present(dev) || !range_covers_byte(addr, len, enable_pos)) {
-        return;
-    }
-
-    was_masked = dev->msix_function_masked;
-    msix_update_function_masked(dev);
-
-    if (!msix_enabled(dev)) {
-        return;
-    }
-
-    pci_device_deassert_intx(dev);
-
-    if (dev->msix_function_masked == was_masked) {
-        return;
-    }
-
-    for (vector = 0; vector < dev->msix_entries_nr; ++vector) {
-        msix_handle_mask_update(dev, vector,
-                                msix_vector_masked(dev, vector, was_masked));
-    }
-}
-
-static uint64_t msix_table_mmio_read(void *opaque, hwaddr addr,
-                                     unsigned size)
-{
-    PCIDevice *dev = opaque;
-
-    return pci_get_long(dev->msix_table + addr);
-}
-
-static void msix_table_mmio_write(void *opaque, hwaddr addr,
-                                  uint64_t val, unsigned size)
-{
-    PCIDevice *dev = opaque;
-    int vector = addr / PCI_MSIX_ENTRY_SIZE;
-    bool was_masked;
-
-    was_masked = msix_is_masked(dev, vector);
-    pci_set_long(dev->msix_table + addr, val);
-    msix_handle_mask_update(dev, vector, was_masked);
-}
-
-static const MemoryRegionOps msix_table_mmio_ops = {
-    .read = msix_table_mmio_read,
-    .write = msix_table_mmio_write,
-    /* TODO: MSIX should be LITTLE_ENDIAN. */
-    .endianness = DEVICE_NATIVE_ENDIAN,
-    .valid = {
-        .min_access_size = 4,
-        .max_access_size = 4,
-    },
-};
-
-static uint64_t msix_pba_mmio_read(void *opaque, hwaddr addr,
-                                   unsigned size)
-{
-    PCIDevice *dev = opaque;
-
-    return pci_get_long(dev->msix_pba + addr);
-}
-
-static const MemoryRegionOps msix_pba_mmio_ops = {
-    .read = msix_pba_mmio_read,
-    /* TODO: MSIX should be LITTLE_ENDIAN. */
-    .endianness = DEVICE_NATIVE_ENDIAN,
-    .valid = {
-        .min_access_size = 4,
-        .max_access_size = 4,
-    },
-};
-
-static void msix_mask_all(struct PCIDevice *dev, unsigned nentries)
-{
-    int vector;
-
-    for (vector = 0; vector < nentries; ++vector) {
-        unsigned offset =
-            vector * PCI_MSIX_ENTRY_SIZE + PCI_MSIX_ENTRY_VECTOR_CTRL;
-        bool was_masked = msix_is_masked(dev, vector);
-
-        dev->msix_table[offset] |= PCI_MSIX_ENTRY_CTRL_MASKBIT;
-        msix_handle_mask_update(dev, vector, was_masked);
-    }
-}
-
-/* Initialize the MSI-X structures */
-int msix_init(struct PCIDevice *dev, unsigned short nentries,
-              MemoryRegion *table_bar, uint8_t table_bar_nr,
-              unsigned table_offset, MemoryRegion *pba_bar,
-              uint8_t pba_bar_nr, unsigned pba_offset, uint8_t cap_pos)
-{
-    int cap;
-    unsigned table_size, pba_size;
-    uint8_t *config;
-
-    /* Nothing to do if MSI is not supported by interrupt controller */
-    if (!msi_supported) {
-        return -ENOTSUP;
-    }
-
-    if (nentries < 1 || nentries > PCI_MSIX_FLAGS_QSIZE + 1) {
-        return -EINVAL;
-    }
-
-    table_size = nentries * PCI_MSIX_ENTRY_SIZE;
-    pba_size = QEMU_ALIGN_UP(nentries, 64) / 8;
-
-    /* Sanity test: table & pba don't overlap, fit within BARs, min aligned */
-    if ((table_bar_nr == pba_bar_nr &&
-         ranges_overlap(table_offset, table_size, pba_offset, pba_size)) ||
-        table_offset + table_size > memory_region_size(table_bar) ||
-        pba_offset + pba_size > memory_region_size(pba_bar) ||
-        (table_offset | pba_offset) & PCI_MSIX_FLAGS_BIRMASK) {
-        return -EINVAL;
-    }
-
-    cap = pci_add_capability(dev, PCI_CAP_ID_MSIX, cap_pos, MSIX_CAP_LENGTH);
-    if (cap < 0) {
-        return cap;
-    }
-
-    dev->msix_cap = cap;
-    dev->cap_present |= QEMU_PCI_CAP_MSIX;
-    config = dev->config + cap;
-
-    pci_set_word(config + PCI_MSIX_FLAGS, nentries - 1);
-    dev->msix_entries_nr = nentries;
-    dev->msix_function_masked = true;
-
-    pci_set_long(config + PCI_MSIX_TABLE, table_offset | table_bar_nr);
-    pci_set_long(config + PCI_MSIX_PBA, pba_offset | pba_bar_nr);
-
-    /* Make flags bit writable. */
-    dev->wmask[cap + MSIX_CONTROL_OFFSET] |= MSIX_ENABLE_MASK |
-                                             MSIX_MASKALL_MASK;
-
-    dev->msix_table = g_malloc0(table_size);
-    dev->msix_pba = g_malloc0(pba_size);
-    dev->msix_entry_used = g_malloc0(nentries * sizeof *dev->msix_entry_used);
-
-    msix_mask_all(dev, nentries);
-
-    memory_region_init_io(&dev->msix_table_mmio, &msix_table_mmio_ops, dev,
-                          "msix-table", table_size);
-    memory_region_add_subregion(table_bar, table_offset, 
&dev->msix_table_mmio);
-    memory_region_init_io(&dev->msix_pba_mmio, &msix_pba_mmio_ops, dev,
-                          "msix-pba", pba_size);
-    memory_region_add_subregion(pba_bar, pba_offset, &dev->msix_pba_mmio);
-
-    return 0;
-}
-
-int msix_init_exclusive_bar(PCIDevice *dev, unsigned short nentries,
-                            uint8_t bar_nr)
-{
-    int ret;
-    char *name;
-
-    /*
-     * Migration compatibility dictates that this remains a 4k
-     * BAR with the vector table in the lower half and PBA in
-     * the upper half.  Do not use these elsewhere!
-     */
-#define MSIX_EXCLUSIVE_BAR_SIZE 4096
-#define MSIX_EXCLUSIVE_BAR_TABLE_OFFSET 0
-#define MSIX_EXCLUSIVE_BAR_PBA_OFFSET (MSIX_EXCLUSIVE_BAR_SIZE / 2)
-#define MSIX_EXCLUSIVE_CAP_OFFSET 0
-
-    if (nentries * PCI_MSIX_ENTRY_SIZE > MSIX_EXCLUSIVE_BAR_PBA_OFFSET) {
-        return -EINVAL;
-    }
-
-    name = g_strdup_printf("%s-msix", dev->name);
-    memory_region_init(&dev->msix_exclusive_bar, name, 
MSIX_EXCLUSIVE_BAR_SIZE);
-    g_free(name);
-
-    ret = msix_init(dev, nentries, &dev->msix_exclusive_bar, bar_nr,
-                    MSIX_EXCLUSIVE_BAR_TABLE_OFFSET, &dev->msix_exclusive_bar,
-                    bar_nr, MSIX_EXCLUSIVE_BAR_PBA_OFFSET,
-                    MSIX_EXCLUSIVE_CAP_OFFSET);
-    if (ret) {
-        memory_region_destroy(&dev->msix_exclusive_bar);
-        return ret;
-    }
-
-    pci_register_bar(dev, bar_nr, PCI_BASE_ADDRESS_SPACE_MEMORY,
-                     &dev->msix_exclusive_bar);
-
-    return 0;
-}
-
-static void msix_free_irq_entries(PCIDevice *dev)
-{
-    int vector;
-
-    for (vector = 0; vector < dev->msix_entries_nr; ++vector) {
-        dev->msix_entry_used[vector] = 0;
-        msix_clr_pending(dev, vector);
-    }
-}
-
-static void msix_clear_all_vectors(PCIDevice *dev)
-{
-    int vector;
-
-    for (vector = 0; vector < dev->msix_entries_nr; ++vector) {
-        msix_clr_pending(dev, vector);
-    }
-}
-
-/* Clean up resources for the device. */
-void msix_uninit(PCIDevice *dev, MemoryRegion *table_bar, MemoryRegion 
*pba_bar)
-{
-    if (!msix_present(dev)) {
-        return;
-    }
-    pci_del_capability(dev, PCI_CAP_ID_MSIX, MSIX_CAP_LENGTH);
-    dev->msix_cap = 0;
-    msix_free_irq_entries(dev);
-    dev->msix_entries_nr = 0;
-    memory_region_del_subregion(pba_bar, &dev->msix_pba_mmio);
-    memory_region_destroy(&dev->msix_pba_mmio);
-    g_free(dev->msix_pba);
-    dev->msix_pba = NULL;
-    memory_region_del_subregion(table_bar, &dev->msix_table_mmio);
-    memory_region_destroy(&dev->msix_table_mmio);
-    g_free(dev->msix_table);
-    dev->msix_table = NULL;
-    g_free(dev->msix_entry_used);
-    dev->msix_entry_used = NULL;
-    dev->cap_present &= ~QEMU_PCI_CAP_MSIX;
-}
-
-void msix_uninit_exclusive_bar(PCIDevice *dev)
-{
-    if (msix_present(dev)) {
-        msix_uninit(dev, &dev->msix_exclusive_bar, &dev->msix_exclusive_bar);
-        memory_region_destroy(&dev->msix_exclusive_bar);
-    }
-}
-
-void msix_save(PCIDevice *dev, QEMUFile *f)
-{
-    unsigned n = dev->msix_entries_nr;
-
-    if (!msix_present(dev)) {
-        return;
-    }
-
-    qemu_put_buffer(f, dev->msix_table, n * PCI_MSIX_ENTRY_SIZE);
-    qemu_put_buffer(f, dev->msix_pba, (n + 7) / 8);
-}
-
-/* Should be called after restoring the config space. */
-void msix_load(PCIDevice *dev, QEMUFile *f)
-{
-    unsigned n = dev->msix_entries_nr;
-    unsigned int vector;
-
-    if (!msix_present(dev)) {
-        return;
-    }
-
-    msix_clear_all_vectors(dev);
-    qemu_get_buffer(f, dev->msix_table, n * PCI_MSIX_ENTRY_SIZE);
-    qemu_get_buffer(f, dev->msix_pba, (n + 7) / 8);
-    msix_update_function_masked(dev);
-
-    for (vector = 0; vector < n; vector++) {
-        msix_handle_mask_update(dev, vector, true);
-    }
-}
-
-/* Does device support MSI-X? */
-int msix_present(PCIDevice *dev)
-{
-    return dev->cap_present & QEMU_PCI_CAP_MSIX;
-}
-
-/* Is MSI-X enabled? */
-int msix_enabled(PCIDevice *dev)
-{
-    return (dev->cap_present & QEMU_PCI_CAP_MSIX) &&
-        (dev->config[dev->msix_cap + MSIX_CONTROL_OFFSET] &
-         MSIX_ENABLE_MASK);
-}
-
-/* Send an MSI-X message */
-void msix_notify(PCIDevice *dev, unsigned vector)
-{
-    MSIMessage msg;
-
-    if (vector >= dev->msix_entries_nr || !dev->msix_entry_used[vector])
-        return;
-    if (msix_is_masked(dev, vector)) {
-        msix_set_pending(dev, vector);
-        return;
-    }
-
-    msg = msix_get_message(dev, vector);
-
-    stl_le_phys(msg.address, msg.data);
-}
-
-void msix_reset(PCIDevice *dev)
-{
-    if (!msix_present(dev)) {
-        return;
-    }
-    msix_clear_all_vectors(dev);
-    dev->config[dev->msix_cap + MSIX_CONTROL_OFFSET] &=
-           ~dev->wmask[dev->msix_cap + MSIX_CONTROL_OFFSET];
-    memset(dev->msix_table, 0, dev->msix_entries_nr * PCI_MSIX_ENTRY_SIZE);
-    memset(dev->msix_pba, 0, QEMU_ALIGN_UP(dev->msix_entries_nr, 64) / 8);
-    msix_mask_all(dev, dev->msix_entries_nr);
-}
-
-/* PCI spec suggests that devices make it possible for software to configure
- * less vectors than supported by the device, but does not specify a standard
- * mechanism for devices to do so.
- *
- * We support this by asking devices to declare vectors software is going to
- * actually use, and checking this on the notification path. Devices that
- * don't want to follow the spec suggestion can declare all vectors as used. */
-
-/* Mark vector as used. */
-int msix_vector_use(PCIDevice *dev, unsigned vector)
-{
-    if (vector >= dev->msix_entries_nr)
-        return -EINVAL;
-    dev->msix_entry_used[vector]++;
-    return 0;
-}
-
-/* Mark vector as unused. */
-void msix_vector_unuse(PCIDevice *dev, unsigned vector)
-{
-    if (vector >= dev->msix_entries_nr || !dev->msix_entry_used[vector]) {
-        return;
-    }
-    if (--dev->msix_entry_used[vector]) {
-        return;
-    }
-    msix_clr_pending(dev, vector);
-}
-
-void msix_unuse_all_vectors(PCIDevice *dev)
-{
-    if (!msix_present(dev)) {
-        return;
-    }
-    msix_free_irq_entries(dev);
-}
-
-unsigned int msix_nr_vectors_allocated(const PCIDevice *dev)
-{
-    return dev->msix_entries_nr;
-}
-
-static int msix_set_notifier_for_vector(PCIDevice *dev, unsigned int vector)
-{
-    MSIMessage msg;
-
-    if (msix_is_masked(dev, vector)) {
-        return 0;
-    }
-    msg = msix_get_message(dev, vector);
-    return dev->msix_vector_use_notifier(dev, vector, msg);
-}
-
-static void msix_unset_notifier_for_vector(PCIDevice *dev, unsigned int vector)
-{
-    if (msix_is_masked(dev, vector)) {
-        return;
-    }
-    dev->msix_vector_release_notifier(dev, vector);
-}
-
-int msix_set_vector_notifiers(PCIDevice *dev,
-                              MSIVectorUseNotifier use_notifier,
-                              MSIVectorReleaseNotifier release_notifier)
-{
-    int vector, ret;
-
-    assert(use_notifier && release_notifier);
-
-    dev->msix_vector_use_notifier = use_notifier;
-    dev->msix_vector_release_notifier = release_notifier;
-
-    if ((dev->config[dev->msix_cap + MSIX_CONTROL_OFFSET] &
-        (MSIX_ENABLE_MASK | MSIX_MASKALL_MASK)) == MSIX_ENABLE_MASK) {
-        for (vector = 0; vector < dev->msix_entries_nr; vector++) {
-            ret = msix_set_notifier_for_vector(dev, vector);
-            if (ret < 0) {
-                goto undo;
-            }
-        }
-    }
-    return 0;
-
-undo:
-    while (--vector >= 0) {
-        msix_unset_notifier_for_vector(dev, vector);
-    }
-    dev->msix_vector_use_notifier = NULL;
-    dev->msix_vector_release_notifier = NULL;
-    return ret;
-}
-
-void msix_unset_vector_notifiers(PCIDevice *dev)
-{
-    int vector;
-
-    assert(dev->msix_vector_use_notifier &&
-           dev->msix_vector_release_notifier);
-
-    if ((dev->config[dev->msix_cap + MSIX_CONTROL_OFFSET] &
-        (MSIX_ENABLE_MASK | MSIX_MASKALL_MASK)) == MSIX_ENABLE_MASK) {
-        for (vector = 0; vector < dev->msix_entries_nr; vector++) {
-            msix_unset_notifier_for_vector(dev, vector);
-        }
-    }
-    dev->msix_vector_use_notifier = NULL;
-    dev->msix_vector_release_notifier = NULL;
-}
diff --git a/hw/msix.h b/hw/msix.h
deleted file mode 100644
index 15211cb..0000000
--- a/hw/msix.h
+++ /dev/null
@@ -1,41 +0,0 @@
-#ifndef QEMU_MSIX_H
-#define QEMU_MSIX_H
-
-#include "qemu-common.h"
-#include "pci.h"
-
-void msix_set_message(PCIDevice *dev, int vector, MSIMessage msg);
-int msix_init(PCIDevice *dev, unsigned short nentries,
-              MemoryRegion *table_bar, uint8_t table_bar_nr,
-              unsigned table_offset, MemoryRegion *pba_bar,
-              uint8_t pba_bar_nr, unsigned pba_offset, uint8_t cap_pos);
-int msix_init_exclusive_bar(PCIDevice *dev, unsigned short nentries,
-                            uint8_t bar_nr);
-
-void msix_write_config(PCIDevice *dev, uint32_t address, uint32_t val, int 
len);
-
-void msix_uninit(PCIDevice *dev, MemoryRegion *table_bar,
-                 MemoryRegion *pba_bar);
-void msix_uninit_exclusive_bar(PCIDevice *dev);
-
-unsigned int msix_nr_vectors_allocated(const PCIDevice *dev);
-
-void msix_save(PCIDevice *dev, QEMUFile *f);
-void msix_load(PCIDevice *dev, QEMUFile *f);
-
-int msix_enabled(PCIDevice *dev);
-int msix_present(PCIDevice *dev);
-
-int msix_vector_use(PCIDevice *dev, unsigned vector);
-void msix_vector_unuse(PCIDevice *dev, unsigned vector);
-void msix_unuse_all_vectors(PCIDevice *dev);
-
-void msix_notify(PCIDevice *dev, unsigned vector);
-
-void msix_reset(PCIDevice *dev);
-
-int msix_set_vector_notifiers(PCIDevice *dev,
-                              MSIVectorUseNotifier use_notifier,
-                              MSIVectorReleaseNotifier release_notifier);
-void msix_unset_vector_notifiers(PCIDevice *dev);
-#endif
diff --git a/hw/pci-hotplug.c b/hw/pci-hotplug.c
deleted file mode 100644
index 0ca5546..0000000
--- a/hw/pci-hotplug.c
+++ /dev/null
@@ -1,293 +0,0 @@
-/*
- * QEMU PCI hotplug support
- *
- * Copyright (c) 2004 Fabrice Bellard
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to 
deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 
FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- */
-
-#include "hw.h"
-#include "boards.h"
-#include "pci.h"
-#include "net.h"
-#include "pc.h"
-#include "monitor.h"
-#include "scsi.h"
-#include "virtio-blk.h"
-#include "qemu-config.h"
-#include "blockdev.h"
-#include "error.h"
-
-#if defined(TARGET_I386)
-static PCIDevice *qemu_pci_hot_add_nic(Monitor *mon,
-                                       const char *devaddr,
-                                       const char *opts_str)
-{
-    Error *local_err = NULL;
-    QemuOpts *opts;
-    PCIBus *bus;
-    int ret, devfn;
-
-    bus = pci_get_bus_devfn(&devfn, devaddr);
-    if (!bus) {
-        monitor_printf(mon, "Invalid PCI device address %s\n", devaddr);
-        return NULL;
-    }
-    if (!((BusState*)bus)->allow_hotplug) {
-        monitor_printf(mon, "PCI bus doesn't support hotplug\n");
-        return NULL;
-    }
-
-    opts = qemu_opts_parse(qemu_find_opts("net"), opts_str ? opts_str : "", 0);
-    if (!opts) {
-        return NULL;
-    }
-
-    qemu_opt_set(opts, "type", "nic");
-
-    ret = net_client_init(opts, 0, &local_err);
-    if (error_is_set(&local_err)) {
-        qerror_report_err(local_err);
-        error_free(local_err);
-        return NULL;
-    }
-    if (nd_table[ret].devaddr) {
-        monitor_printf(mon, "Parameter addr not supported\n");
-        return NULL;
-    }
-    return pci_nic_init(&nd_table[ret], "rtl8139", devaddr);
-}
-
-static int scsi_hot_add(Monitor *mon, DeviceState *adapter,
-                        DriveInfo *dinfo, int printinfo)
-{
-    SCSIBus *scsibus;
-    SCSIDevice *scsidev;
-
-    scsibus = (SCSIBus *)
-        object_dynamic_cast(OBJECT(QLIST_FIRST(&adapter->child_bus)),
-                            TYPE_SCSI_BUS);
-    if (!scsibus) {
-       error_report("Device is not a SCSI adapter");
-       return -1;
-    }
-
-    /*
-     * drive_init() tries to find a default for dinfo->unit.  Doesn't
-     * work at all for hotplug though as we assign the device to a
-     * specific bus instead of the first bus with spare scsi ids.
-     *
-     * Ditch the calculated value and reload from option string (if
-     * specified).
-     */
-    dinfo->unit = qemu_opt_get_number(dinfo->opts, "unit", -1);
-    dinfo->bus = scsibus->busnr;
-    scsidev = scsi_bus_legacy_add_drive(scsibus, dinfo->bdrv, dinfo->unit,
-                                        false, -1);
-    if (!scsidev) {
-        return -1;
-    }
-    dinfo->unit = scsidev->id;
-
-    if (printinfo)
-        monitor_printf(mon, "OK bus %d, unit %d\n",
-                       scsibus->busnr, scsidev->id);
-    return 0;
-}
-
-int pci_drive_hot_add(Monitor *mon, const QDict *qdict,
-                      DriveInfo *dinfo, int type)
-{
-    int dom, pci_bus;
-    unsigned slot;
-    PCIDevice *dev;
-    const char *pci_addr = qdict_get_str(qdict, "pci_addr");
-
-    switch (type) {
-    case IF_SCSI:
-        if (pci_read_devaddr(mon, pci_addr, &dom, &pci_bus, &slot)) {
-            goto err;
-        }
-        dev = pci_find_device(pci_find_root_bus(dom), pci_bus,
-                              PCI_DEVFN(slot, 0));
-        if (!dev) {
-            monitor_printf(mon, "no pci device with address %s\n", pci_addr);
-            goto err;
-        }
-        if (scsi_hot_add(mon, &dev->qdev, dinfo, 1) != 0) {
-            goto err;
-        }
-        break;
-    default:
-        monitor_printf(mon, "Can't hot-add drive to type %d\n", type);
-        goto err;
-    }
-
-    return 0;
-err:
-    return -1;
-}
-
-static PCIDevice *qemu_pci_hot_add_storage(Monitor *mon,
-                                           const char *devaddr,
-                                           const char *opts)
-{
-    PCIDevice *dev;
-    DriveInfo *dinfo = NULL;
-    int type = -1;
-    char buf[128];
-    PCIBus *bus;
-    int devfn;
-
-    if (get_param_value(buf, sizeof(buf), "if", opts)) {
-        if (!strcmp(buf, "scsi"))
-            type = IF_SCSI;
-        else if (!strcmp(buf, "virtio")) {
-            type = IF_VIRTIO;
-        } else {
-            monitor_printf(mon, "type %s not a hotpluggable PCI device.\n", 
buf);
-            return NULL;
-        }
-    } else {
-        monitor_printf(mon, "no if= specified\n");
-        return NULL;
-    }
-
-    if (get_param_value(buf, sizeof(buf), "file", opts)) {
-        dinfo = add_init_drive(opts);
-        if (!dinfo)
-            return NULL;
-        if (dinfo->devaddr) {
-            monitor_printf(mon, "Parameter addr not supported\n");
-            return NULL;
-        }
-    } else {
-        dinfo = NULL;
-    }
-
-    bus = pci_get_bus_devfn(&devfn, devaddr);
-    if (!bus) {
-        monitor_printf(mon, "Invalid PCI device address %s\n", devaddr);
-        return NULL;
-    }
-    if (!((BusState*)bus)->allow_hotplug) {
-        monitor_printf(mon, "PCI bus doesn't support hotplug\n");
-        return NULL;
-    }
-
-    switch (type) {
-    case IF_SCSI:
-        dev = pci_create(bus, devfn, "lsi53c895a");
-        if (qdev_init(&dev->qdev) < 0)
-            dev = NULL;
-        if (dev && dinfo) {
-            if (scsi_hot_add(mon, &dev->qdev, dinfo, 0) != 0) {
-                qdev_unplug(&dev->qdev, NULL);
-                dev = NULL;
-            }
-        }
-        break;
-    case IF_VIRTIO:
-        if (!dinfo) {
-            monitor_printf(mon, "virtio requires a backing file/device.\n");
-            return NULL;
-        }
-        dev = pci_create(bus, devfn, "virtio-blk-pci");
-        if (qdev_prop_set_drive(&dev->qdev, "drive", dinfo->bdrv) < 0) {
-            qdev_free(&dev->qdev);
-            dev = NULL;
-            break;
-        }
-        if (qdev_init(&dev->qdev) < 0)
-            dev = NULL;
-        break;
-    default:
-        dev = NULL;
-    }
-    return dev;
-}
-
-void pci_device_hot_add(Monitor *mon, const QDict *qdict)
-{
-    PCIDevice *dev = NULL;
-    const char *pci_addr = qdict_get_str(qdict, "pci_addr");
-    const char *type = qdict_get_str(qdict, "type");
-    const char *opts = qdict_get_try_str(qdict, "opts");
-
-    /* strip legacy tag */
-    if (!strncmp(pci_addr, "pci_addr=", 9)) {
-        pci_addr += 9;
-    }
-
-    if (!opts) {
-        opts = "";
-    }
-
-    if (!strcmp(pci_addr, "auto"))
-        pci_addr = NULL;
-
-    if (strcmp(type, "nic") == 0) {
-        dev = qemu_pci_hot_add_nic(mon, pci_addr, opts);
-    } else if (strcmp(type, "storage") == 0) {
-        dev = qemu_pci_hot_add_storage(mon, pci_addr, opts);
-    } else {
-        monitor_printf(mon, "invalid type: %s\n", type);
-    }
-
-    if (dev) {
-        monitor_printf(mon, "OK domain %d, bus %d, slot %d, function %d\n",
-                       pci_find_domain(dev->bus),
-                       pci_bus_num(dev->bus), PCI_SLOT(dev->devfn),
-                       PCI_FUNC(dev->devfn));
-    } else
-        monitor_printf(mon, "failed to add %s\n", opts);
-}
-#endif
-
-static int pci_device_hot_remove(Monitor *mon, const char *pci_addr)
-{
-    PCIDevice *d;
-    int dom, bus;
-    unsigned slot;
-    Error *local_err = NULL;
-
-    if (pci_read_devaddr(mon, pci_addr, &dom, &bus, &slot)) {
-        return -1;
-    }
-
-    d = pci_find_device(pci_find_root_bus(dom), bus, PCI_DEVFN(slot, 0));
-    if (!d) {
-        monitor_printf(mon, "slot %d empty\n", slot);
-        return -1;
-    }
-
-    qdev_unplug(&d->qdev, &local_err);
-    if (error_is_set(&local_err)) {
-        monitor_printf(mon, "%s\n", error_get_pretty(local_err));
-        error_free(local_err);
-        return -1;
-    }
-
-    return 0;
-}
-
-void do_pci_device_hot_remove(Monitor *mon, const QDict *qdict)
-{
-    pci_device_hot_remove(mon, qdict_get_str(qdict, "pci_addr"));
-}
diff --git a/hw/pci-stub.c b/hw/pci-stub.c
deleted file mode 100644
index 134c448..0000000
--- a/hw/pci-stub.c
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * PCI stubs for platforms that don't support pci bus.
- *
- * Copyright (c) 2010 Isaku Yamahata <yamahata at valinux co jp>
- *                    VA Linux Systems Japan K.K.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, see <http://www.gnu.org/licenses/>.
- */
-
-#include "sysemu.h"
-#include "monitor.h"
-#include "pci.h"
-#include "qmp-commands.h"
-
-PciInfoList *qmp_query_pci(Error **errp)
-{
-    error_set(errp, QERR_UNSUPPORTED);
-    return NULL;
-}
-
-static void pci_error_message(Monitor *mon)
-{
-    monitor_printf(mon, "PCI devices not supported\n");
-}
-
-int do_pcie_aer_inject_error(Monitor *mon,
-                             const QDict *qdict, QObject **ret_data)
-{
-    pci_error_message(mon);
-    return -ENOSYS;
-}
-
-void pcie_aer_inject_error_print(Monitor *mon, const QObject *data)
-{
-    pci_error_message(mon);
-}
diff --git a/hw/pci.c b/hw/pci.c
deleted file mode 100644
index 97a0cd7..0000000
--- a/hw/pci.c
+++ /dev/null
@@ -1,2168 +0,0 @@
-/*
- * QEMU PCI bus manager
- *
- * Copyright (c) 2004 Fabrice Bellard
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to 
deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 
FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- */
-#include "hw.h"
-#include "pci.h"
-#include "pci_bridge.h"
-#include "pci_internals.h"
-#include "monitor.h"
-#include "net.h"
-#include "sysemu.h"
-#include "loader.h"
-#include "range.h"
-#include "qmp-commands.h"
-#include "msi.h"
-#include "msix.h"
-#include "exec-memory.h"
-
-//#define DEBUG_PCI
-#ifdef DEBUG_PCI
-# define PCI_DPRINTF(format, ...)       printf(format, ## __VA_ARGS__)
-#else
-# define PCI_DPRINTF(format, ...)       do { } while (0)
-#endif
-
-static void pcibus_dev_print(Monitor *mon, DeviceState *dev, int indent);
-static char *pcibus_get_dev_path(DeviceState *dev);
-static char *pcibus_get_fw_dev_path(DeviceState *dev);
-static int pcibus_reset(BusState *qbus);
-
-static Property pci_props[] = {
-    DEFINE_PROP_PCI_DEVFN("addr", PCIDevice, devfn, -1),
-    DEFINE_PROP_STRING("romfile", PCIDevice, romfile),
-    DEFINE_PROP_UINT32("rombar",  PCIDevice, rom_bar, 1),
-    DEFINE_PROP_BIT("multifunction", PCIDevice, cap_present,
-                    QEMU_PCI_CAP_MULTIFUNCTION_BITNR, false),
-    DEFINE_PROP_BIT("command_serr_enable", PCIDevice, cap_present,
-                    QEMU_PCI_CAP_SERR_BITNR, true),
-    DEFINE_PROP_END_OF_LIST()
-};
-
-static void pci_bus_class_init(ObjectClass *klass, void *data)
-{
-    BusClass *k = BUS_CLASS(klass);
-
-    k->print_dev = pcibus_dev_print;
-    k->get_dev_path = pcibus_get_dev_path;
-    k->get_fw_dev_path = pcibus_get_fw_dev_path;
-    k->reset = pcibus_reset;
-}
-
-static const TypeInfo pci_bus_info = {
-    .name = TYPE_PCI_BUS,
-    .parent = TYPE_BUS,
-    .instance_size = sizeof(PCIBus),
-    .class_init = pci_bus_class_init,
-};
-
-static PCIBus *pci_find_bus_nr(PCIBus *bus, int bus_num);
-static void pci_update_mappings(PCIDevice *d);
-static void pci_set_irq(void *opaque, int irq_num, int level);
-static int pci_add_option_rom(PCIDevice *pdev, bool is_default_rom);
-static void pci_del_option_rom(PCIDevice *pdev);
-
-static uint16_t pci_default_sub_vendor_id = PCI_SUBVENDOR_ID_REDHAT_QUMRANET;
-static uint16_t pci_default_sub_device_id = PCI_SUBDEVICE_ID_QEMU;
-
-struct PCIHostBus {
-    int domain;
-    struct PCIBus *bus;
-    QLIST_ENTRY(PCIHostBus) next;
-};
-static QLIST_HEAD(, PCIHostBus) host_buses;
-
-static const VMStateDescription vmstate_pcibus = {
-    .name = "PCIBUS",
-    .version_id = 1,
-    .minimum_version_id = 1,
-    .minimum_version_id_old = 1,
-    .fields      = (VMStateField []) {
-        VMSTATE_INT32_EQUAL(nirq, PCIBus),
-        VMSTATE_VARRAY_INT32(irq_count, PCIBus, nirq, 0, vmstate_info_int32, 
int32_t),
-        VMSTATE_END_OF_LIST()
-    }
-};
-static int pci_bar(PCIDevice *d, int reg)
-{
-    uint8_t type;
-
-    if (reg != PCI_ROM_SLOT)
-        return PCI_BASE_ADDRESS_0 + reg * 4;
-
-    type = d->config[PCI_HEADER_TYPE] & ~PCI_HEADER_TYPE_MULTI_FUNCTION;
-    return type == PCI_HEADER_TYPE_BRIDGE ? PCI_ROM_ADDRESS1 : PCI_ROM_ADDRESS;
-}
-
-static inline int pci_irq_state(PCIDevice *d, int irq_num)
-{
-       return (d->irq_state >> irq_num) & 0x1;
-}
-
-static inline void pci_set_irq_state(PCIDevice *d, int irq_num, int level)
-{
-       d->irq_state &= ~(0x1 << irq_num);
-       d->irq_state |= level << irq_num;
-}
-
-static void pci_change_irq_level(PCIDevice *pci_dev, int irq_num, int change)
-{
-    PCIBus *bus;
-    for (;;) {
-        bus = pci_dev->bus;
-        irq_num = bus->map_irq(pci_dev, irq_num);
-        if (bus->set_irq)
-            break;
-        pci_dev = bus->parent_dev;
-    }
-    bus->irq_count[irq_num] += change;
-    bus->set_irq(bus->irq_opaque, irq_num, bus->irq_count[irq_num] != 0);
-}
-
-int pci_bus_get_irq_level(PCIBus *bus, int irq_num)
-{
-    assert(irq_num >= 0);
-    assert(irq_num < bus->nirq);
-    return !!bus->irq_count[irq_num];
-}
-
-/* Update interrupt status bit in config space on interrupt
- * state change. */
-static void pci_update_irq_status(PCIDevice *dev)
-{
-    if (dev->irq_state) {
-        dev->config[PCI_STATUS] |= PCI_STATUS_INTERRUPT;
-    } else {
-        dev->config[PCI_STATUS] &= ~PCI_STATUS_INTERRUPT;
-    }
-}
-
-void pci_device_deassert_intx(PCIDevice *dev)
-{
-    int i;
-    for (i = 0; i < PCI_NUM_PINS; ++i) {
-        qemu_set_irq(dev->irq[i], 0);
-    }
-}
-
-/*
- * This function is called on #RST and FLR.
- * FLR if PCI_EXP_DEVCTL_BCR_FLR is set
- */
-void pci_device_reset(PCIDevice *dev)
-{
-    int r;
-
-    qdev_reset_all(&dev->qdev);
-
-    dev->irq_state = 0;
-    pci_update_irq_status(dev);
-    pci_device_deassert_intx(dev);
-    /* Clear all writable bits */
-    pci_word_test_and_clear_mask(dev->config + PCI_COMMAND,
-                                 pci_get_word(dev->wmask + PCI_COMMAND) |
-                                 pci_get_word(dev->w1cmask + PCI_COMMAND));
-    pci_word_test_and_clear_mask(dev->config + PCI_STATUS,
-                                 pci_get_word(dev->wmask + PCI_STATUS) |
-                                 pci_get_word(dev->w1cmask + PCI_STATUS));
-    dev->config[PCI_CACHE_LINE_SIZE] = 0x0;
-    dev->config[PCI_INTERRUPT_LINE] = 0x0;
-    for (r = 0; r < PCI_NUM_REGIONS; ++r) {
-        PCIIORegion *region = &dev->io_regions[r];
-        if (!region->size) {
-            continue;
-        }
-
-        if (!(region->type & PCI_BASE_ADDRESS_SPACE_IO) &&
-            region->type & PCI_BASE_ADDRESS_MEM_TYPE_64) {
-            pci_set_quad(dev->config + pci_bar(dev, r), region->type);
-        } else {
-            pci_set_long(dev->config + pci_bar(dev, r), region->type);
-        }
-    }
-    pci_update_mappings(dev);
-
-    msi_reset(dev);
-    msix_reset(dev);
-}
-
-/*
- * Trigger pci bus reset under a given bus.
- * To be called on RST# assert.
- */
-void pci_bus_reset(PCIBus *bus)
-{
-    int i;
-
-    for (i = 0; i < bus->nirq; i++) {
-        bus->irq_count[i] = 0;
-    }
-    for (i = 0; i < ARRAY_SIZE(bus->devices); ++i) {
-        if (bus->devices[i]) {
-            pci_device_reset(bus->devices[i]);
-        }
-    }
-}
-
-static int pcibus_reset(BusState *qbus)
-{
-    pci_bus_reset(DO_UPCAST(PCIBus, qbus, qbus));
-
-    /* topology traverse is done by pci_bus_reset().
-       Tell qbus/qdev walker not to traverse the tree */
-    return 1;
-}
-
-static void pci_host_bus_register(int domain, PCIBus *bus)
-{
-    struct PCIHostBus *host;
-    host = g_malloc0(sizeof(*host));
-    host->domain = domain;
-    host->bus = bus;
-    QLIST_INSERT_HEAD(&host_buses, host, next);
-}
-
-PCIBus *pci_find_root_bus(int domain)
-{
-    struct PCIHostBus *host;
-
-    QLIST_FOREACH(host, &host_buses, next) {
-        if (host->domain == domain) {
-            return host->bus;
-        }
-    }
-
-    return NULL;
-}
-
-int pci_find_domain(const PCIBus *bus)
-{
-    PCIDevice *d;
-    struct PCIHostBus *host;
-
-    /* obtain root bus */
-    while ((d = bus->parent_dev) != NULL) {
-        bus = d->bus;
-    }
-
-    QLIST_FOREACH(host, &host_buses, next) {
-        if (host->bus == bus) {
-            return host->domain;
-        }
-    }
-
-    abort();    /* should not be reached */
-    return -1;
-}
-
-void pci_bus_new_inplace(PCIBus *bus, DeviceState *parent,
-                         const char *name,
-                         MemoryRegion *address_space_mem,
-                         MemoryRegion *address_space_io,
-                         uint8_t devfn_min)
-{
-    qbus_create_inplace(&bus->qbus, TYPE_PCI_BUS, parent, name);
-    assert(PCI_FUNC(devfn_min) == 0);
-    bus->devfn_min = devfn_min;
-    bus->address_space_mem = address_space_mem;
-    bus->address_space_io = address_space_io;
-
-    /* host bridge */
-    QLIST_INIT(&bus->child);
-    pci_host_bus_register(0, bus); /* for now only pci domain 0 is supported */
-
-    vmstate_register(NULL, -1, &vmstate_pcibus, bus);
-}
-
-PCIBus *pci_bus_new(DeviceState *parent, const char *name,
-                    MemoryRegion *address_space_mem,
-                    MemoryRegion *address_space_io,
-                    uint8_t devfn_min)
-{
-    PCIBus *bus;
-
-    bus = g_malloc0(sizeof(*bus));
-    pci_bus_new_inplace(bus, parent, name, address_space_mem,
-                        address_space_io, devfn_min);
-    OBJECT(bus)->free = g_free;
-    return bus;
-}
-
-void pci_bus_irqs(PCIBus *bus, pci_set_irq_fn set_irq, pci_map_irq_fn map_irq,
-                  void *irq_opaque, int nirq)
-{
-    bus->set_irq = set_irq;
-    bus->map_irq = map_irq;
-    bus->irq_opaque = irq_opaque;
-    bus->nirq = nirq;
-    bus->irq_count = g_malloc0(nirq * sizeof(bus->irq_count[0]));
-}
-
-void pci_bus_hotplug(PCIBus *bus, pci_hotplug_fn hotplug, DeviceState *qdev)
-{
-    bus->qbus.allow_hotplug = 1;
-    bus->hotplug = hotplug;
-    bus->hotplug_qdev = qdev;
-}
-
-PCIBus *pci_register_bus(DeviceState *parent, const char *name,
-                         pci_set_irq_fn set_irq, pci_map_irq_fn map_irq,
-                         void *irq_opaque,
-                         MemoryRegion *address_space_mem,
-                         MemoryRegion *address_space_io,
-                         uint8_t devfn_min, int nirq)
-{
-    PCIBus *bus;
-
-    bus = pci_bus_new(parent, name, address_space_mem,
-                      address_space_io, devfn_min);
-    pci_bus_irqs(bus, set_irq, map_irq, irq_opaque, nirq);
-    return bus;
-}
-
-int pci_bus_num(PCIBus *s)
-{
-    if (!s->parent_dev)
-        return 0;       /* pci host bridge */
-    return s->parent_dev->config[PCI_SECONDARY_BUS];
-}
-
-static int get_pci_config_device(QEMUFile *f, void *pv, size_t size)
-{
-    PCIDevice *s = container_of(pv, PCIDevice, config);
-    uint8_t *config;
-    int i;
-
-    assert(size == pci_config_size(s));
-    config = g_malloc(size);
-
-    qemu_get_buffer(f, config, size);
-    for (i = 0; i < size; ++i) {
-        if ((config[i] ^ s->config[i]) &
-            s->cmask[i] & ~s->wmask[i] & ~s->w1cmask[i]) {
-            g_free(config);
-            return -EINVAL;
-        }
-    }
-    memcpy(s->config, config, size);
-
-    pci_update_mappings(s);
-
-    memory_region_set_enabled(&s->bus_master_enable_region,
-                              pci_get_word(s->config + PCI_COMMAND)
-                              & PCI_COMMAND_MASTER);
-
-    g_free(config);
-    return 0;
-}
-
-/* just put buffer */
-static void put_pci_config_device(QEMUFile *f, void *pv, size_t size)
-{
-    const uint8_t **v = pv;
-    assert(size == pci_config_size(container_of(pv, PCIDevice, config)));
-    qemu_put_buffer(f, *v, size);
-}
-
-static VMStateInfo vmstate_info_pci_config = {
-    .name = "pci config",
-    .get  = get_pci_config_device,
-    .put  = put_pci_config_device,
-};
-
-static int get_pci_irq_state(QEMUFile *f, void *pv, size_t size)
-{
-    PCIDevice *s = container_of(pv, PCIDevice, irq_state);
-    uint32_t irq_state[PCI_NUM_PINS];
-    int i;
-    for (i = 0; i < PCI_NUM_PINS; ++i) {
-        irq_state[i] = qemu_get_be32(f);
-        if (irq_state[i] != 0x1 && irq_state[i] != 0) {
-            fprintf(stderr, "irq state %d: must be 0 or 1.\n",
-                    irq_state[i]);
-            return -EINVAL;
-        }
-    }
-
-    for (i = 0; i < PCI_NUM_PINS; ++i) {
-        pci_set_irq_state(s, i, irq_state[i]);
-    }
-
-    return 0;
-}
-
-static void put_pci_irq_state(QEMUFile *f, void *pv, size_t size)
-{
-    int i;
-    PCIDevice *s = container_of(pv, PCIDevice, irq_state);
-
-    for (i = 0; i < PCI_NUM_PINS; ++i) {
-        qemu_put_be32(f, pci_irq_state(s, i));
-    }
-}
-
-static VMStateInfo vmstate_info_pci_irq_state = {
-    .name = "pci irq state",
-    .get  = get_pci_irq_state,
-    .put  = put_pci_irq_state,
-};
-
-const VMStateDescription vmstate_pci_device = {
-    .name = "PCIDevice",
-    .version_id = 2,
-    .minimum_version_id = 1,
-    .minimum_version_id_old = 1,
-    .fields      = (VMStateField []) {
-        VMSTATE_INT32_LE(version_id, PCIDevice),
-        VMSTATE_BUFFER_UNSAFE_INFO(config, PCIDevice, 0,
-                                   vmstate_info_pci_config,
-                                   PCI_CONFIG_SPACE_SIZE),
-        VMSTATE_BUFFER_UNSAFE_INFO(irq_state, PCIDevice, 2,
-                                  vmstate_info_pci_irq_state,
-                                  PCI_NUM_PINS * sizeof(int32_t)),
-        VMSTATE_END_OF_LIST()
-    }
-};
-
-const VMStateDescription vmstate_pcie_device = {
-    .name = "PCIEDevice",
-    .version_id = 2,
-    .minimum_version_id = 1,
-    .minimum_version_id_old = 1,
-    .fields      = (VMStateField []) {
-        VMSTATE_INT32_LE(version_id, PCIDevice),
-        VMSTATE_BUFFER_UNSAFE_INFO(config, PCIDevice, 0,
-                                   vmstate_info_pci_config,
-                                   PCIE_CONFIG_SPACE_SIZE),
-        VMSTATE_BUFFER_UNSAFE_INFO(irq_state, PCIDevice, 2,
-                                  vmstate_info_pci_irq_state,
-                                  PCI_NUM_PINS * sizeof(int32_t)),
-        VMSTATE_END_OF_LIST()
-    }
-};
-
-static inline const VMStateDescription *pci_get_vmstate(PCIDevice *s)
-{
-    return pci_is_express(s) ? &vmstate_pcie_device : &vmstate_pci_device;
-}
-
-void pci_device_save(PCIDevice *s, QEMUFile *f)
-{
-    /* Clear interrupt status bit: it is implicit
-     * in irq_state which we are saving.
-     * This makes us compatible with old devices
-     * which never set or clear this bit. */
-    s->config[PCI_STATUS] &= ~PCI_STATUS_INTERRUPT;
-    vmstate_save_state(f, pci_get_vmstate(s), s);
-    /* Restore the interrupt status bit. */
-    pci_update_irq_status(s);
-}
-
-int pci_device_load(PCIDevice *s, QEMUFile *f)
-{
-    int ret;
-    ret = vmstate_load_state(f, pci_get_vmstate(s), s, s->version_id);
-    /* Restore the interrupt status bit. */
-    pci_update_irq_status(s);
-    return ret;
-}
-
-static void pci_set_default_subsystem_id(PCIDevice *pci_dev)
-{
-    pci_set_word(pci_dev->config + PCI_SUBSYSTEM_VENDOR_ID,
-                 pci_default_sub_vendor_id);
-    pci_set_word(pci_dev->config + PCI_SUBSYSTEM_ID,
-                 pci_default_sub_device_id);
-}
-
-/*
- * Parse [[<domain>:]<bus>:]<slot>, return -1 on error if funcp == NULL
- *       [[<domain>:]<bus>:]<slot>.<func>, return -1 on error
- */
-static int pci_parse_devaddr(const char *addr, int *domp, int *busp,
-                      unsigned int *slotp, unsigned int *funcp)
-{
-    const char *p;
-    char *e;
-    unsigned long val;
-    unsigned long dom = 0, bus = 0;
-    unsigned int slot = 0;
-    unsigned int func = 0;
-
-    p = addr;
-    val = strtoul(p, &e, 16);
-    if (e == p)
-       return -1;
-    if (*e == ':') {
-       bus = val;
-       p = e + 1;
-       val = strtoul(p, &e, 16);
-       if (e == p)
-           return -1;
-       if (*e == ':') {
-           dom = bus;
-           bus = val;
-           p = e + 1;
-           val = strtoul(p, &e, 16);
-           if (e == p)
-               return -1;
-       }
-    }
-
-    slot = val;
-
-    if (funcp != NULL) {
-        if (*e != '.')
-            return -1;
-
-        p = e + 1;
-        val = strtoul(p, &e, 16);
-        if (e == p)
-            return -1;
-
-        func = val;
-    }
-
-    /* if funcp == NULL func is 0 */
-    if (dom > 0xffff || bus > 0xff || slot > 0x1f || func > 7)
-       return -1;
-
-    if (*e)
-       return -1;
-
-    *domp = dom;
-    *busp = bus;
-    *slotp = slot;
-    if (funcp != NULL)
-        *funcp = func;
-    return 0;
-}
-
-int pci_read_devaddr(Monitor *mon, const char *addr, int *domp, int *busp,
-                     unsigned *slotp)
-{
-    /* strip legacy tag */
-    if (!strncmp(addr, "pci_addr=", 9)) {
-        addr += 9;
-    }
-    if (pci_parse_devaddr(addr, domp, busp, slotp, NULL)) {
-        monitor_printf(mon, "Invalid pci address\n");
-        return -1;
-    }
-    return 0;
-}
-
-PCIBus *pci_get_bus_devfn(int *devfnp, const char *devaddr)
-{
-    int dom, bus;
-    unsigned slot;
-
-    if (!devaddr) {
-        *devfnp = -1;
-        return pci_find_bus_nr(pci_find_root_bus(0), 0);
-    }
-
-    if (pci_parse_devaddr(devaddr, &dom, &bus, &slot, NULL) < 0) {
-        return NULL;
-    }
-
-    *devfnp = PCI_DEVFN(slot, 0);
-    return pci_find_bus_nr(pci_find_root_bus(dom), bus);
-}
-
-static void pci_init_cmask(PCIDevice *dev)
-{
-    pci_set_word(dev->cmask + PCI_VENDOR_ID, 0xffff);
-    pci_set_word(dev->cmask + PCI_DEVICE_ID, 0xffff);
-    dev->cmask[PCI_STATUS] = PCI_STATUS_CAP_LIST;
-    dev->cmask[PCI_REVISION_ID] = 0xff;
-    dev->cmask[PCI_CLASS_PROG] = 0xff;
-    pci_set_word(dev->cmask + PCI_CLASS_DEVICE, 0xffff);
-    dev->cmask[PCI_HEADER_TYPE] = 0xff;
-    dev->cmask[PCI_CAPABILITY_LIST] = 0xff;
-}
-
-static void pci_init_wmask(PCIDevice *dev)
-{
-    int config_size = pci_config_size(dev);
-
-    dev->wmask[PCI_CACHE_LINE_SIZE] = 0xff;
-    dev->wmask[PCI_INTERRUPT_LINE] = 0xff;
-    pci_set_word(dev->wmask + PCI_COMMAND,
-                 PCI_COMMAND_IO | PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER |
-                 PCI_COMMAND_INTX_DISABLE);
-    if (dev->cap_present & QEMU_PCI_CAP_SERR) {
-        pci_word_test_and_set_mask(dev->wmask + PCI_COMMAND, PCI_COMMAND_SERR);
-    }
-
-    memset(dev->wmask + PCI_CONFIG_HEADER_SIZE, 0xff,
-           config_size - PCI_CONFIG_HEADER_SIZE);
-}
-
-static void pci_init_w1cmask(PCIDevice *dev)
-{
-    /*
-     * Note: It's okay to set w1cmask even for readonly bits as
-     * long as their value is hardwired to 0.
-     */
-    pci_set_word(dev->w1cmask + PCI_STATUS,
-                 PCI_STATUS_PARITY | PCI_STATUS_SIG_TARGET_ABORT |
-                 PCI_STATUS_REC_TARGET_ABORT | PCI_STATUS_REC_MASTER_ABORT |
-                 PCI_STATUS_SIG_SYSTEM_ERROR | PCI_STATUS_DETECTED_PARITY);
-}
-
-static void pci_init_mask_bridge(PCIDevice *d)
-{
-    /* PCI_PRIMARY_BUS, PCI_SECONDARY_BUS, PCI_SUBORDINATE_BUS and
-       PCI_SEC_LETENCY_TIMER */
-    memset(d->wmask + PCI_PRIMARY_BUS, 0xff, 4);
-
-    /* base and limit */
-    d->wmask[PCI_IO_BASE] = PCI_IO_RANGE_MASK & 0xff;
-    d->wmask[PCI_IO_LIMIT] = PCI_IO_RANGE_MASK & 0xff;
-    pci_set_word(d->wmask + PCI_MEMORY_BASE,
-                 PCI_MEMORY_RANGE_MASK & 0xffff);
-    pci_set_word(d->wmask + PCI_MEMORY_LIMIT,
-                 PCI_MEMORY_RANGE_MASK & 0xffff);
-    pci_set_word(d->wmask + PCI_PREF_MEMORY_BASE,
-                 PCI_PREF_RANGE_MASK & 0xffff);
-    pci_set_word(d->wmask + PCI_PREF_MEMORY_LIMIT,
-                 PCI_PREF_RANGE_MASK & 0xffff);
-
-    /* PCI_PREF_BASE_UPPER32 and PCI_PREF_LIMIT_UPPER32 */
-    memset(d->wmask + PCI_PREF_BASE_UPPER32, 0xff, 8);
-
-    /* Supported memory and i/o types */
-    d->config[PCI_IO_BASE] |= PCI_IO_RANGE_TYPE_16;
-    d->config[PCI_IO_LIMIT] |= PCI_IO_RANGE_TYPE_16;
-    pci_word_test_and_set_mask(d->config + PCI_PREF_MEMORY_BASE,
-                               PCI_PREF_RANGE_TYPE_64);
-    pci_word_test_and_set_mask(d->config + PCI_PREF_MEMORY_LIMIT,
-                               PCI_PREF_RANGE_TYPE_64);
-
-/* TODO: add this define to pci_regs.h in linux and then in qemu. */
-#define  PCI_BRIDGE_CTL_VGA_16BIT      0x10    /* VGA 16-bit decode */
-#define  PCI_BRIDGE_CTL_DISCARD                0x100   /* Primary discard 
timer */
-#define  PCI_BRIDGE_CTL_SEC_DISCARD    0x200   /* Secondary discard timer */
-#define  PCI_BRIDGE_CTL_DISCARD_STATUS 0x400   /* Discard timer status */
-#define  PCI_BRIDGE_CTL_DISCARD_SERR   0x800   /* Discard timer SERR# enable */
-    pci_set_word(d->wmask + PCI_BRIDGE_CONTROL,
-                 PCI_BRIDGE_CTL_PARITY |
-                 PCI_BRIDGE_CTL_SERR |
-                 PCI_BRIDGE_CTL_ISA |
-                 PCI_BRIDGE_CTL_VGA |
-                 PCI_BRIDGE_CTL_VGA_16BIT |
-                 PCI_BRIDGE_CTL_MASTER_ABORT |
-                 PCI_BRIDGE_CTL_BUS_RESET |
-                 PCI_BRIDGE_CTL_FAST_BACK |
-                 PCI_BRIDGE_CTL_DISCARD |
-                 PCI_BRIDGE_CTL_SEC_DISCARD |
-                 PCI_BRIDGE_CTL_DISCARD_SERR);
-    /* Below does not do anything as we never set this bit, put here for
-     * completeness. */
-    pci_set_word(d->w1cmask + PCI_BRIDGE_CONTROL,
-                 PCI_BRIDGE_CTL_DISCARD_STATUS);
-    d->cmask[PCI_IO_BASE] |= PCI_IO_RANGE_TYPE_MASK;
-    d->cmask[PCI_IO_LIMIT] |= PCI_IO_RANGE_TYPE_MASK;
-    pci_word_test_and_set_mask(d->cmask + PCI_PREF_MEMORY_BASE,
-                               PCI_PREF_RANGE_TYPE_MASK);
-    pci_word_test_and_set_mask(d->cmask + PCI_PREF_MEMORY_LIMIT,
-                               PCI_PREF_RANGE_TYPE_MASK);
-}
-
-static int pci_init_multifunction(PCIBus *bus, PCIDevice *dev)
-{
-    uint8_t slot = PCI_SLOT(dev->devfn);
-    uint8_t func;
-
-    if (dev->cap_present & QEMU_PCI_CAP_MULTIFUNCTION) {
-        dev->config[PCI_HEADER_TYPE] |= PCI_HEADER_TYPE_MULTI_FUNCTION;
-    }
-
-    /*
-     * multifunction bit is interpreted in two ways as follows.
-     *   - all functions must set the bit to 1.
-     *     Example: Intel X53
-     *   - function 0 must set the bit, but the rest function (> 0)
-     *     is allowed to leave the bit to 0.
-     *     Example: PIIX3(also in qemu), PIIX4(also in qemu), ICH10,
-     *
-     * So OS (at least Linux) checks the bit of only function 0,
-     * and doesn't see the bit of function > 0.
-     *
-     * The below check allows both interpretation.
-     */
-    if (PCI_FUNC(dev->devfn)) {
-        PCIDevice *f0 = bus->devices[PCI_DEVFN(slot, 0)];
-        if (f0 && !(f0->cap_present & QEMU_PCI_CAP_MULTIFUNCTION)) {
-            /* function 0 should set multifunction bit */
-            error_report("PCI: single function device can't be populated "
-                         "in function %x.%x", slot, PCI_FUNC(dev->devfn));
-            return -1;
-        }
-        return 0;
-    }
-
-    if (dev->cap_present & QEMU_PCI_CAP_MULTIFUNCTION) {
-        return 0;
-    }
-    /* function 0 indicates single function, so function > 0 must be NULL */
-    for (func = 1; func < PCI_FUNC_MAX; ++func) {
-        if (bus->devices[PCI_DEVFN(slot, func)]) {
-            error_report("PCI: %x.0 indicates single function, "
-                         "but %x.%x is already populated.",
-                         slot, slot, func);
-            return -1;
-        }
-    }
-    return 0;
-}
-
-static void pci_config_alloc(PCIDevice *pci_dev)
-{
-    int config_size = pci_config_size(pci_dev);
-
-    pci_dev->config = g_malloc0(config_size);
-    pci_dev->cmask = g_malloc0(config_size);
-    pci_dev->wmask = g_malloc0(config_size);
-    pci_dev->w1cmask = g_malloc0(config_size);
-    pci_dev->used = g_malloc0(config_size);
-}
-
-static void pci_config_free(PCIDevice *pci_dev)
-{
-    g_free(pci_dev->config);
-    g_free(pci_dev->cmask);
-    g_free(pci_dev->wmask);
-    g_free(pci_dev->w1cmask);
-    g_free(pci_dev->used);
-}
-
-/* -1 for devfn means auto assign */
-static PCIDevice *do_pci_register_device(PCIDevice *pci_dev, PCIBus *bus,
-                                         const char *name, int devfn)
-{
-    PCIDeviceClass *pc = PCI_DEVICE_GET_CLASS(pci_dev);
-    PCIConfigReadFunc *config_read = pc->config_read;
-    PCIConfigWriteFunc *config_write = pc->config_write;
-
-    if (devfn < 0) {
-        for(devfn = bus->devfn_min ; devfn < ARRAY_SIZE(bus->devices);
-            devfn += PCI_FUNC_MAX) {
-            if (!bus->devices[devfn])
-                goto found;
-        }
-        error_report("PCI: no slot/function available for %s, all in use", 
name);
-        return NULL;
-    found: ;
-    } else if (bus->devices[devfn]) {
-        error_report("PCI: slot %d function %d not available for %s, in use by 
%s",
-                     PCI_SLOT(devfn), PCI_FUNC(devfn), name, 
bus->devices[devfn]->name);
-        return NULL;
-    }
-    pci_dev->bus = bus;
-    if (bus->dma_context_fn) {
-        pci_dev->dma = bus->dma_context_fn(bus, bus->dma_context_opaque, 
devfn);
-    } else {
-        /* FIXME: Make dma_context_fn use MemoryRegions instead, so this path 
is
-         * taken unconditionally */
-        /* FIXME: inherit memory region from bus creator */
-        memory_region_init_alias(&pci_dev->bus_master_enable_region, "bus 
master",
-                                 get_system_memory(), 0,
-                                 memory_region_size(get_system_memory()));
-        memory_region_set_enabled(&pci_dev->bus_master_enable_region, false);
-        address_space_init(&pci_dev->bus_master_as, 
&pci_dev->bus_master_enable_region);
-        pci_dev->dma = g_new(DMAContext, 1);
-        dma_context_init(pci_dev->dma, &pci_dev->bus_master_as, NULL, NULL, 
NULL);
-    }
-    pci_dev->devfn = devfn;
-    pstrcpy(pci_dev->name, sizeof(pci_dev->name), name);
-    pci_dev->irq_state = 0;
-    pci_config_alloc(pci_dev);
-
-    pci_config_set_vendor_id(pci_dev->config, pc->vendor_id);
-    pci_config_set_device_id(pci_dev->config, pc->device_id);
-    pci_config_set_revision(pci_dev->config, pc->revision);
-    pci_config_set_class(pci_dev->config, pc->class_id);
-
-    if (!pc->is_bridge) {
-        if (pc->subsystem_vendor_id || pc->subsystem_id) {
-            pci_set_word(pci_dev->config + PCI_SUBSYSTEM_VENDOR_ID,
-                         pc->subsystem_vendor_id);
-            pci_set_word(pci_dev->config + PCI_SUBSYSTEM_ID,
-                         pc->subsystem_id);
-        } else {
-            pci_set_default_subsystem_id(pci_dev);
-        }
-    } else {
-        /* subsystem_vendor_id/subsystem_id are only for header type 0 */
-        assert(!pc->subsystem_vendor_id);
-        assert(!pc->subsystem_id);
-    }
-    pci_init_cmask(pci_dev);
-    pci_init_wmask(pci_dev);
-    pci_init_w1cmask(pci_dev);
-    if (pc->is_bridge) {
-        pci_init_mask_bridge(pci_dev);
-    }
-    if (pci_init_multifunction(bus, pci_dev)) {
-        pci_config_free(pci_dev);
-        return NULL;
-    }
-
-    if (!config_read)
-        config_read = pci_default_read_config;
-    if (!config_write)
-        config_write = pci_default_write_config;
-    pci_dev->config_read = config_read;
-    pci_dev->config_write = config_write;
-    bus->devices[devfn] = pci_dev;
-    pci_dev->irq = qemu_allocate_irqs(pci_set_irq, pci_dev, PCI_NUM_PINS);
-    pci_dev->version_id = 2; /* Current pci device vmstate version */
-    return pci_dev;
-}
-
-static void do_pci_unregister_device(PCIDevice *pci_dev)
-{
-    qemu_free_irqs(pci_dev->irq);
-    pci_dev->bus->devices[pci_dev->devfn] = NULL;
-    pci_config_free(pci_dev);
-
-    if (!pci_dev->bus->dma_context_fn) {
-        address_space_destroy(&pci_dev->bus_master_as);
-        memory_region_destroy(&pci_dev->bus_master_enable_region);
-        g_free(pci_dev->dma);
-        pci_dev->dma = NULL;
-    }
-}
-
-static void pci_unregister_io_regions(PCIDevice *pci_dev)
-{
-    PCIIORegion *r;
-    int i;
-
-    for(i = 0; i < PCI_NUM_REGIONS; i++) {
-        r = &pci_dev->io_regions[i];
-        if (!r->size || r->addr == PCI_BAR_UNMAPPED)
-            continue;
-        memory_region_del_subregion(r->address_space, r->memory);
-    }
-}
-
-static int pci_unregister_device(DeviceState *dev)
-{
-    PCIDevice *pci_dev = PCI_DEVICE(dev);
-    PCIDeviceClass *pc = PCI_DEVICE_GET_CLASS(pci_dev);
-
-    pci_unregister_io_regions(pci_dev);
-    pci_del_option_rom(pci_dev);
-
-    if (pc->exit) {
-        pc->exit(pci_dev);
-    }
-
-    do_pci_unregister_device(pci_dev);
-    return 0;
-}
-
-void pci_register_bar(PCIDevice *pci_dev, int region_num,
-                      uint8_t type, MemoryRegion *memory)
-{
-    PCIIORegion *r;
-    uint32_t addr;
-    uint64_t wmask;
-    pcibus_t size = memory_region_size(memory);
-
-    assert(region_num >= 0);
-    assert(region_num < PCI_NUM_REGIONS);
-    if (size & (size-1)) {
-        fprintf(stderr, "ERROR: PCI region size must be pow2 "
-                    "type=0x%x, size=0x%"FMT_PCIBUS"\n", type, size);
-        exit(1);
-    }
-
-    r = &pci_dev->io_regions[region_num];
-    r->addr = PCI_BAR_UNMAPPED;
-    r->size = size;
-    r->type = type;
-    r->memory = NULL;
-
-    wmask = ~(size - 1);
-    addr = pci_bar(pci_dev, region_num);
-    if (region_num == PCI_ROM_SLOT) {
-        /* ROM enable bit is writable */
-        wmask |= PCI_ROM_ADDRESS_ENABLE;
-    }
-    pci_set_long(pci_dev->config + addr, type);
-    if (!(r->type & PCI_BASE_ADDRESS_SPACE_IO) &&
-        r->type & PCI_BASE_ADDRESS_MEM_TYPE_64) {
-        pci_set_quad(pci_dev->wmask + addr, wmask);
-        pci_set_quad(pci_dev->cmask + addr, ~0ULL);
-    } else {
-        pci_set_long(pci_dev->wmask + addr, wmask & 0xffffffff);
-        pci_set_long(pci_dev->cmask + addr, 0xffffffff);
-    }
-    pci_dev->io_regions[region_num].memory = memory;
-    pci_dev->io_regions[region_num].address_space
-        = type & PCI_BASE_ADDRESS_SPACE_IO
-        ? pci_dev->bus->address_space_io
-        : pci_dev->bus->address_space_mem;
-}
-
-pcibus_t pci_get_bar_addr(PCIDevice *pci_dev, int region_num)
-{
-    return pci_dev->io_regions[region_num].addr;
-}
-
-static pcibus_t pci_bar_address(PCIDevice *d,
-                               int reg, uint8_t type, pcibus_t size)
-{
-    pcibus_t new_addr, last_addr;
-    int bar = pci_bar(d, reg);
-    uint16_t cmd = pci_get_word(d->config + PCI_COMMAND);
-
-    if (type & PCI_BASE_ADDRESS_SPACE_IO) {
-        if (!(cmd & PCI_COMMAND_IO)) {
-            return PCI_BAR_UNMAPPED;
-        }
-        new_addr = pci_get_long(d->config + bar) & ~(size - 1);
-        last_addr = new_addr + size - 1;
-        /* NOTE: we have only 64K ioports on PC */
-        if (last_addr <= new_addr || new_addr == 0 || last_addr > UINT16_MAX) {
-            return PCI_BAR_UNMAPPED;
-        }
-        return new_addr;
-    }
-
-    if (!(cmd & PCI_COMMAND_MEMORY)) {
-        return PCI_BAR_UNMAPPED;
-    }
-    if (type & PCI_BASE_ADDRESS_MEM_TYPE_64) {
-        new_addr = pci_get_quad(d->config + bar);
-    } else {
-        new_addr = pci_get_long(d->config + bar);
-    }
-    /* the ROM slot has a specific enable bit */
-    if (reg == PCI_ROM_SLOT && !(new_addr & PCI_ROM_ADDRESS_ENABLE)) {
-        return PCI_BAR_UNMAPPED;
-    }
-    new_addr &= ~(size - 1);
-    last_addr = new_addr + size - 1;
-    /* NOTE: we do not support wrapping */
-    /* XXX: as we cannot support really dynamic
-       mappings, we handle specific values as invalid
-       mappings. */
-    if (last_addr <= new_addr || new_addr == 0 ||
-        last_addr == PCI_BAR_UNMAPPED) {
-        return PCI_BAR_UNMAPPED;
-    }
-
-    /* Now pcibus_t is 64bit.
-     * Check if 32 bit BAR wraps around explicitly.
-     * Without this, PC ide doesn't work well.
-     * TODO: remove this work around.
-     */
-    if  (!(type & PCI_BASE_ADDRESS_MEM_TYPE_64) && last_addr >= UINT32_MAX) {
-        return PCI_BAR_UNMAPPED;
-    }
-
-    /*
-     * OS is allowed to set BAR beyond its addressable
-     * bits. For example, 32 bit OS can set 64bit bar
-     * to >4G. Check it. TODO: we might need to support
-     * it in the future for e.g. PAE.
-     */
-    if (last_addr >= HWADDR_MAX) {
-        return PCI_BAR_UNMAPPED;
-    }
-
-    return new_addr;
-}
-
-static void pci_update_mappings(PCIDevice *d)
-{
-    PCIIORegion *r;
-    int i;
-    pcibus_t new_addr;
-
-    for(i = 0; i < PCI_NUM_REGIONS; i++) {
-        r = &d->io_regions[i];
-
-        /* this region isn't registered */
-        if (!r->size)
-            continue;
-
-        new_addr = pci_bar_address(d, i, r->type, r->size);
-
-        /* This bar isn't changed */
-        if (new_addr == r->addr)
-            continue;
-
-        /* now do the real mapping */
-        if (r->addr != PCI_BAR_UNMAPPED) {
-            memory_region_del_subregion(r->address_space, r->memory);
-        }
-        r->addr = new_addr;
-        if (r->addr != PCI_BAR_UNMAPPED) {
-            memory_region_add_subregion_overlap(r->address_space,
-                                                r->addr, r->memory, 1);
-        }
-    }
-}
-
-static inline int pci_irq_disabled(PCIDevice *d)
-{
-    return pci_get_word(d->config + PCI_COMMAND) & PCI_COMMAND_INTX_DISABLE;
-}
-
-/* Called after interrupt disabled field update in config space,
- * assert/deassert interrupts if necessary.
- * Gets original interrupt disable bit value (before update). */
-static void pci_update_irq_disabled(PCIDevice *d, int was_irq_disabled)
-{
-    int i, disabled = pci_irq_disabled(d);
-    if (disabled == was_irq_disabled)
-        return;
-    for (i = 0; i < PCI_NUM_PINS; ++i) {
-        int state = pci_irq_state(d, i);
-        pci_change_irq_level(d, i, disabled ? -state : state);
-    }
-}
-
-uint32_t pci_default_read_config(PCIDevice *d,
-                                 uint32_t address, int len)
-{
-    uint32_t val = 0;
-
-    memcpy(&val, d->config + address, len);
-    return le32_to_cpu(val);
-}
-
-void pci_default_write_config(PCIDevice *d, uint32_t addr, uint32_t val, int l)
-{
-    int i, was_irq_disabled = pci_irq_disabled(d);
-
-    for (i = 0; i < l; val >>= 8, ++i) {
-        uint8_t wmask = d->wmask[addr + i];
-        uint8_t w1cmask = d->w1cmask[addr + i];
-        assert(!(wmask & w1cmask));
-        d->config[addr + i] = (d->config[addr + i] & ~wmask) | (val & wmask);
-        d->config[addr + i] &= ~(val & w1cmask); /* W1C: Write 1 to Clear */
-    }
-    if (ranges_overlap(addr, l, PCI_BASE_ADDRESS_0, 24) ||
-        ranges_overlap(addr, l, PCI_ROM_ADDRESS, 4) ||
-        ranges_overlap(addr, l, PCI_ROM_ADDRESS1, 4) ||
-        range_covers_byte(addr, l, PCI_COMMAND))
-        pci_update_mappings(d);
-
-    if (range_covers_byte(addr, l, PCI_COMMAND)) {
-        pci_update_irq_disabled(d, was_irq_disabled);
-        memory_region_set_enabled(&d->bus_master_enable_region,
-                                  pci_get_word(d->config + PCI_COMMAND)
-                                    & PCI_COMMAND_MASTER);
-    }
-
-    msi_write_config(d, addr, val, l);
-    msix_write_config(d, addr, val, l);
-}
-
-/***********************************************************/
-/* generic PCI irq support */
-
-/* 0 <= irq_num <= 3. level must be 0 or 1 */
-static void pci_set_irq(void *opaque, int irq_num, int level)
-{
-    PCIDevice *pci_dev = opaque;
-    int change;
-
-    change = level - pci_irq_state(pci_dev, irq_num);
-    if (!change)
-        return;
-
-    pci_set_irq_state(pci_dev, irq_num, level);
-    pci_update_irq_status(pci_dev);
-    if (pci_irq_disabled(pci_dev))
-        return;
-    pci_change_irq_level(pci_dev, irq_num, change);
-}
-
-/* Special hooks used by device assignment */
-void pci_bus_set_route_irq_fn(PCIBus *bus, pci_route_irq_fn route_intx_to_irq)
-{
-    assert(!bus->parent_dev);
-    bus->route_intx_to_irq = route_intx_to_irq;
-}
-
-PCIINTxRoute pci_device_route_intx_to_irq(PCIDevice *dev, int pin)
-{
-    PCIBus *bus;
-
-    do {
-         bus = dev->bus;
-         pin = bus->map_irq(dev, pin);
-         dev = bus->parent_dev;
-    } while (dev);
-
-    if (!bus->route_intx_to_irq) {
-        error_report("PCI: Bug - unimplemented PCI INTx routing (%s)\n",
-                     object_get_typename(OBJECT(bus->qbus.parent)));
-        return (PCIINTxRoute) { PCI_INTX_DISABLED, -1 };
-    }
-
-    return bus->route_intx_to_irq(bus->irq_opaque, pin);
-}
-
-bool pci_intx_route_changed(PCIINTxRoute *old, PCIINTxRoute *new)
-{
-    return old->mode != new->mode || old->irq != new->irq;
-}
-
-void pci_bus_fire_intx_routing_notifier(PCIBus *bus)
-{
-    PCIDevice *dev;
-    PCIBus *sec;
-    int i;
-
-    for (i = 0; i < ARRAY_SIZE(bus->devices); ++i) {
-        dev = bus->devices[i];
-        if (dev && dev->intx_routing_notifier) {
-            dev->intx_routing_notifier(dev);
-        }
-        QLIST_FOREACH(sec, &bus->child, sibling) {
-            pci_bus_fire_intx_routing_notifier(sec);
-        }
-    }
-}
-
-void pci_device_set_intx_routing_notifier(PCIDevice *dev,
-                                          PCIINTxRoutingNotifier notifier)
-{
-    dev->intx_routing_notifier = notifier;
-}
-
-/*
- * PCI-to-PCI bridge specification
- * 9.1: Interrupt routing. Table 9-1
- *
- * the PCI Express Base Specification, Revision 2.1
- * 2.2.8.1: INTx interrutp signaling - Rules
- *          the Implementation Note
- *          Table 2-20
- */
-/*
- * 0 <= pin <= 3 0 = INTA, 1 = INTB, 2 = INTC, 3 = INTD
- * 0-origin unlike PCI interrupt pin register.
- */
-int pci_swizzle_map_irq_fn(PCIDevice *pci_dev, int pin)
-{
-    return (pin + PCI_SLOT(pci_dev->devfn)) % PCI_NUM_PINS;
-}
-
-/***********************************************************/
-/* monitor info on PCI */
-
-typedef struct {
-    uint16_t class;
-    const char *desc;
-    const char *fw_name;
-    uint16_t fw_ign_bits;
-} pci_class_desc;
-
-static const pci_class_desc pci_class_descriptions[] =
-{
-    { 0x0001, "VGA controller", "display"},
-    { 0x0100, "SCSI controller", "scsi"},
-    { 0x0101, "IDE controller", "ide"},
-    { 0x0102, "Floppy controller", "fdc"},
-    { 0x0103, "IPI controller", "ipi"},
-    { 0x0104, "RAID controller", "raid"},
-    { 0x0106, "SATA controller"},
-    { 0x0107, "SAS controller"},
-    { 0x0180, "Storage controller"},
-    { 0x0200, "Ethernet controller", "ethernet"},
-    { 0x0201, "Token Ring controller", "token-ring"},
-    { 0x0202, "FDDI controller", "fddi"},
-    { 0x0203, "ATM controller", "atm"},
-    { 0x0280, "Network controller"},
-    { 0x0300, "VGA controller", "display", 0x00ff},
-    { 0x0301, "XGA controller"},
-    { 0x0302, "3D controller"},
-    { 0x0380, "Display controller"},
-    { 0x0400, "Video controller", "video"},
-    { 0x0401, "Audio controller", "sound"},
-    { 0x0402, "Phone"},
-    { 0x0403, "Audio controller", "sound"},
-    { 0x0480, "Multimedia controller"},
-    { 0x0500, "RAM controller", "memory"},
-    { 0x0501, "Flash controller", "flash"},
-    { 0x0580, "Memory controller"},
-    { 0x0600, "Host bridge", "host"},
-    { 0x0601, "ISA bridge", "isa"},
-    { 0x0602, "EISA bridge", "eisa"},
-    { 0x0603, "MC bridge", "mca"},
-    { 0x0604, "PCI bridge", "pci"},
-    { 0x0605, "PCMCIA bridge", "pcmcia"},
-    { 0x0606, "NUBUS bridge", "nubus"},
-    { 0x0607, "CARDBUS bridge", "cardbus"},
-    { 0x0608, "RACEWAY bridge"},
-    { 0x0680, "Bridge"},
-    { 0x0700, "Serial port", "serial"},
-    { 0x0701, "Parallel port", "parallel"},
-    { 0x0800, "Interrupt controller", "interrupt-controller"},
-    { 0x0801, "DMA controller", "dma-controller"},
-    { 0x0802, "Timer", "timer"},
-    { 0x0803, "RTC", "rtc"},
-    { 0x0900, "Keyboard", "keyboard"},
-    { 0x0901, "Pen", "pen"},
-    { 0x0902, "Mouse", "mouse"},
-    { 0x0A00, "Dock station", "dock", 0x00ff},
-    { 0x0B00, "i386 cpu", "cpu", 0x00ff},
-    { 0x0c00, "Fireware contorller", "fireware"},
-    { 0x0c01, "Access bus controller", "access-bus"},
-    { 0x0c02, "SSA controller", "ssa"},
-    { 0x0c03, "USB controller", "usb"},
-    { 0x0c04, "Fibre channel controller", "fibre-channel"},
-    { 0x0c05, "SMBus"},
-    { 0, NULL}
-};
-
-static void pci_for_each_device_under_bus(PCIBus *bus,
-                                          void (*fn)(PCIBus *b, PCIDevice *d,
-                                                     void *opaque),
-                                          void *opaque)
-{
-    PCIDevice *d;
-    int devfn;
-
-    for(devfn = 0; devfn < ARRAY_SIZE(bus->devices); devfn++) {
-        d = bus->devices[devfn];
-        if (d) {
-            fn(bus, d, opaque);
-        }
-    }
-}
-
-void pci_for_each_device(PCIBus *bus, int bus_num,
-                         void (*fn)(PCIBus *b, PCIDevice *d, void *opaque),
-                         void *opaque)
-{
-    bus = pci_find_bus_nr(bus, bus_num);
-
-    if (bus) {
-        pci_for_each_device_under_bus(bus, fn, opaque);
-    }
-}
-
-static const pci_class_desc *get_class_desc(int class)
-{
-    const pci_class_desc *desc;
-
-    desc = pci_class_descriptions;
-    while (desc->desc && class != desc->class) {
-        desc++;
-    }
-
-    return desc;
-}
-
-static PciDeviceInfoList *qmp_query_pci_devices(PCIBus *bus, int bus_num);
-
-static PciMemoryRegionList *qmp_query_pci_regions(const PCIDevice *dev)
-{
-    PciMemoryRegionList *head = NULL, *cur_item = NULL;
-    int i;
-
-    for (i = 0; i < PCI_NUM_REGIONS; i++) {
-        const PCIIORegion *r = &dev->io_regions[i];
-        PciMemoryRegionList *region;
-
-        if (!r->size) {
-            continue;
-        }
-
-        region = g_malloc0(sizeof(*region));
-        region->value = g_malloc0(sizeof(*region->value));
-
-        if (r->type & PCI_BASE_ADDRESS_SPACE_IO) {
-            region->value->type = g_strdup("io");
-        } else {
-            region->value->type = g_strdup("memory");
-            region->value->has_prefetch = true;
-            region->value->prefetch = !!(r->type & 
PCI_BASE_ADDRESS_MEM_PREFETCH);
-            region->value->has_mem_type_64 = true;
-            region->value->mem_type_64 = !!(r->type & 
PCI_BASE_ADDRESS_MEM_TYPE_64);
-        }
-
-        region->value->bar = i;
-        region->value->address = r->addr;
-        region->value->size = r->size;
-
-        /* XXX: waiting for the qapi to support GSList */
-        if (!cur_item) {
-            head = cur_item = region;
-        } else {
-            cur_item->next = region;
-            cur_item = region;
-        }
-    }
-
-    return head;
-}
-
-static PciBridgeInfo *qmp_query_pci_bridge(PCIDevice *dev, PCIBus *bus,
-                                           int bus_num)
-{
-    PciBridgeInfo *info;
-
-    info = g_malloc0(sizeof(*info));
-
-    info->bus.number = dev->config[PCI_PRIMARY_BUS];
-    info->bus.secondary = dev->config[PCI_SECONDARY_BUS];
-    info->bus.subordinate = dev->config[PCI_SUBORDINATE_BUS];
-
-    info->bus.io_range = g_malloc0(sizeof(*info->bus.io_range));
-    info->bus.io_range->base = pci_bridge_get_base(dev, 
PCI_BASE_ADDRESS_SPACE_IO);
-    info->bus.io_range->limit = pci_bridge_get_limit(dev, 
PCI_BASE_ADDRESS_SPACE_IO);
-
-    info->bus.memory_range = g_malloc0(sizeof(*info->bus.memory_range));
-    info->bus.memory_range->base = pci_bridge_get_base(dev, 
PCI_BASE_ADDRESS_SPACE_MEMORY);
-    info->bus.memory_range->limit = pci_bridge_get_limit(dev, 
PCI_BASE_ADDRESS_SPACE_MEMORY);
-
-    info->bus.prefetchable_range = 
g_malloc0(sizeof(*info->bus.prefetchable_range));
-    info->bus.prefetchable_range->base = pci_bridge_get_base(dev, 
PCI_BASE_ADDRESS_MEM_PREFETCH);
-    info->bus.prefetchable_range->limit = pci_bridge_get_limit(dev, 
PCI_BASE_ADDRESS_MEM_PREFETCH);
-
-    if (dev->config[PCI_SECONDARY_BUS] != 0) {
-        PCIBus *child_bus = pci_find_bus_nr(bus, 
dev->config[PCI_SECONDARY_BUS]);
-        if (child_bus) {
-            info->has_devices = true;
-            info->devices = qmp_query_pci_devices(child_bus, 
dev->config[PCI_SECONDARY_BUS]);
-        }
-    }
-
-    return info;
-}
-
-static PciDeviceInfo *qmp_query_pci_device(PCIDevice *dev, PCIBus *bus,
-                                           int bus_num)
-{
-    const pci_class_desc *desc;
-    PciDeviceInfo *info;
-    uint8_t type;
-    int class;
-
-    info = g_malloc0(sizeof(*info));
-    info->bus = bus_num;
-    info->slot = PCI_SLOT(dev->devfn);
-    info->function = PCI_FUNC(dev->devfn);
-
-    class = pci_get_word(dev->config + PCI_CLASS_DEVICE);
-    info->class_info.class = class;
-    desc = get_class_desc(class);
-    if (desc->desc) {
-        info->class_info.has_desc = true;
-        info->class_info.desc = g_strdup(desc->desc);
-    }
-
-    info->id.vendor = pci_get_word(dev->config + PCI_VENDOR_ID);
-    info->id.device = pci_get_word(dev->config + PCI_DEVICE_ID);
-    info->regions = qmp_query_pci_regions(dev);
-    info->qdev_id = g_strdup(dev->qdev.id ? dev->qdev.id : "");
-
-    if (dev->config[PCI_INTERRUPT_PIN] != 0) {
-        info->has_irq = true;
-        info->irq = dev->config[PCI_INTERRUPT_LINE];
-    }
-
-    type = dev->config[PCI_HEADER_TYPE] & ~PCI_HEADER_TYPE_MULTI_FUNCTION;
-    if (type == PCI_HEADER_TYPE_BRIDGE) {
-        info->has_pci_bridge = true;
-        info->pci_bridge = qmp_query_pci_bridge(dev, bus, bus_num);
-    }
-
-    return info;
-}
-
-static PciDeviceInfoList *qmp_query_pci_devices(PCIBus *bus, int bus_num)
-{
-    PciDeviceInfoList *info, *head = NULL, *cur_item = NULL;
-    PCIDevice *dev;
-    int devfn;
-
-    for (devfn = 0; devfn < ARRAY_SIZE(bus->devices); devfn++) {
-        dev = bus->devices[devfn];
-        if (dev) {
-            info = g_malloc0(sizeof(*info));
-            info->value = qmp_query_pci_device(dev, bus, bus_num);
-
-            /* XXX: waiting for the qapi to support GSList */
-            if (!cur_item) {
-                head = cur_item = info;
-            } else {
-                cur_item->next = info;
-                cur_item = info;
-            }
-        }
-    }
-
-    return head;
-}
-
-static PciInfo *qmp_query_pci_bus(PCIBus *bus, int bus_num)
-{
-    PciInfo *info = NULL;
-
-    bus = pci_find_bus_nr(bus, bus_num);
-    if (bus) {
-        info = g_malloc0(sizeof(*info));
-        info->bus = bus_num;
-        info->devices = qmp_query_pci_devices(bus, bus_num);
-    }
-
-    return info;
-}
-
-PciInfoList *qmp_query_pci(Error **errp)
-{
-    PciInfoList *info, *head = NULL, *cur_item = NULL;
-    struct PCIHostBus *host;
-
-    QLIST_FOREACH(host, &host_buses, next) {
-        info = g_malloc0(sizeof(*info));
-        info->value = qmp_query_pci_bus(host->bus, 0);
-
-        /* XXX: waiting for the qapi to support GSList */
-        if (!cur_item) {
-            head = cur_item = info;
-        } else {
-            cur_item->next = info;
-            cur_item = info;
-        }
-    }
-
-    return head;
-}
-
-static const char * const pci_nic_models[] = {
-    "ne2k_pci",
-    "i82551",
-    "i82557b",
-    "i82559er",
-    "rtl8139",
-    "e1000",
-    "pcnet",
-    "virtio",
-    NULL
-};
-
-static const char * const pci_nic_names[] = {
-    "ne2k_pci",
-    "i82551",
-    "i82557b",
-    "i82559er",
-    "rtl8139",
-    "e1000",
-    "pcnet",
-    "virtio-net-pci",
-    NULL
-};
-
-/* Initialize a PCI NIC.  */
-/* FIXME callers should check for failure, but don't */
-PCIDevice *pci_nic_init(NICInfo *nd, const char *default_model,
-                        const char *default_devaddr)
-{
-    const char *devaddr = nd->devaddr ? nd->devaddr : default_devaddr;
-    PCIBus *bus;
-    int devfn;
-    PCIDevice *pci_dev;
-    DeviceState *dev;
-    int i;
-
-    i = qemu_find_nic_model(nd, pci_nic_models, default_model);
-    if (i < 0)
-        return NULL;
-
-    bus = pci_get_bus_devfn(&devfn, devaddr);
-    if (!bus) {
-        error_report("Invalid PCI device address %s for device %s",
-                     devaddr, pci_nic_names[i]);
-        return NULL;
-    }
-
-    pci_dev = pci_create(bus, devfn, pci_nic_names[i]);
-    dev = &pci_dev->qdev;
-    qdev_set_nic_properties(dev, nd);
-    if (qdev_init(dev) < 0)
-        return NULL;
-    return pci_dev;
-}
-
-PCIDevice *pci_nic_init_nofail(NICInfo *nd, const char *default_model,
-                               const char *default_devaddr)
-{
-    PCIDevice *res;
-
-    if (qemu_show_nic_models(nd->model, pci_nic_models))
-        exit(0);
-
-    res = pci_nic_init(nd, default_model, default_devaddr);
-    if (!res)
-        exit(1);
-    return res;
-}
-
-PCIDevice *pci_vga_init(PCIBus *bus)
-{
-    switch (vga_interface_type) {
-    case VGA_CIRRUS:
-        return pci_create_simple(bus, -1, "cirrus-vga");
-    case VGA_QXL:
-        return pci_create_simple(bus, -1, "qxl-vga");
-    case VGA_STD:
-        return pci_create_simple(bus, -1, "VGA");
-    case VGA_VMWARE:
-        return pci_create_simple(bus, -1, "vmware-svga");
-    case VGA_NONE:
-    default: /* Other non-PCI types. Checking for unsupported types is already
-                done in vl.c. */
-        return NULL;
-    }
-}
-
-/* Whether a given bus number is in range of the secondary
- * bus of the given bridge device. */
-static bool pci_secondary_bus_in_range(PCIDevice *dev, int bus_num)
-{
-    return !(pci_get_word(dev->config + PCI_BRIDGE_CONTROL) &
-             PCI_BRIDGE_CTL_BUS_RESET) /* Don't walk the bus if it's reset. */ 
&&
-        dev->config[PCI_SECONDARY_BUS] < bus_num &&
-        bus_num <= dev->config[PCI_SUBORDINATE_BUS];
-}
-
-static PCIBus *pci_find_bus_nr(PCIBus *bus, int bus_num)
-{
-    PCIBus *sec;
-
-    if (!bus) {
-        return NULL;
-    }
-
-    if (pci_bus_num(bus) == bus_num) {
-        return bus;
-    }
-
-    /* Consider all bus numbers in range for the host pci bridge. */
-    if (bus->parent_dev &&
-        !pci_secondary_bus_in_range(bus->parent_dev, bus_num)) {
-        return NULL;
-    }
-
-    /* try child bus */
-    for (; bus; bus = sec) {
-        QLIST_FOREACH(sec, &bus->child, sibling) {
-            assert(sec->parent_dev);
-            if (sec->parent_dev->config[PCI_SECONDARY_BUS] == bus_num) {
-                return sec;
-            }
-            if (pci_secondary_bus_in_range(sec->parent_dev, bus_num)) {
-                break;
-            }
-        }
-    }
-
-    return NULL;
-}
-
-PCIDevice *pci_find_device(PCIBus *bus, int bus_num, uint8_t devfn)
-{
-    bus = pci_find_bus_nr(bus, bus_num);
-
-    if (!bus)
-        return NULL;
-
-    return bus->devices[devfn];
-}
-
-static int pci_qdev_init(DeviceState *qdev)
-{
-    PCIDevice *pci_dev = (PCIDevice *)qdev;
-    PCIDeviceClass *pc = PCI_DEVICE_GET_CLASS(pci_dev);
-    PCIBus *bus;
-    int rc;
-    bool is_default_rom;
-
-    /* initialize cap_present for pci_is_express() and pci_config_size() */
-    if (pc->is_express) {
-        pci_dev->cap_present |= QEMU_PCI_CAP_EXPRESS;
-    }
-
-    bus = FROM_QBUS(PCIBus, qdev_get_parent_bus(qdev));
-    pci_dev = do_pci_register_device(pci_dev, bus,
-                                     object_get_typename(OBJECT(qdev)),
-                                     pci_dev->devfn);
-    if (pci_dev == NULL)
-        return -1;
-    if (qdev->hotplugged && pc->no_hotplug) {
-        qerror_report(QERR_DEVICE_NO_HOTPLUG, 
object_get_typename(OBJECT(pci_dev)));
-        do_pci_unregister_device(pci_dev);
-        return -1;
-    }
-    if (pc->init) {
-        rc = pc->init(pci_dev);
-        if (rc != 0) {
-            do_pci_unregister_device(pci_dev);
-            return rc;
-        }
-    }
-
-    /* rom loading */
-    is_default_rom = false;
-    if (pci_dev->romfile == NULL && pc->romfile != NULL) {
-        pci_dev->romfile = g_strdup(pc->romfile);
-        is_default_rom = true;
-    }
-    pci_add_option_rom(pci_dev, is_default_rom);
-
-    if (bus->hotplug) {
-        /* Let buses differentiate between hotplug and when device is
-         * enabled during qemu machine creation. */
-        rc = bus->hotplug(bus->hotplug_qdev, pci_dev,
-                          qdev->hotplugged ? PCI_HOTPLUG_ENABLED:
-                          PCI_COLDPLUG_ENABLED);
-        if (rc != 0) {
-            int r = pci_unregister_device(&pci_dev->qdev);
-            assert(!r);
-            return rc;
-        }
-    }
-    return 0;
-}
-
-static int pci_unplug_device(DeviceState *qdev)
-{
-    PCIDevice *dev = PCI_DEVICE(qdev);
-    PCIDeviceClass *pc = PCI_DEVICE_GET_CLASS(dev);
-
-    if (pc->no_hotplug) {
-        qerror_report(QERR_DEVICE_NO_HOTPLUG, 
object_get_typename(OBJECT(dev)));
-        return -1;
-    }
-    return dev->bus->hotplug(dev->bus->hotplug_qdev, dev,
-                             PCI_HOTPLUG_DISABLED);
-}
-
-PCIDevice *pci_create_multifunction(PCIBus *bus, int devfn, bool multifunction,
-                                    const char *name)
-{
-    DeviceState *dev;
-
-    dev = qdev_create(&bus->qbus, name);
-    qdev_prop_set_int32(dev, "addr", devfn);
-    qdev_prop_set_bit(dev, "multifunction", multifunction);
-    return PCI_DEVICE(dev);
-}
-
-PCIDevice *pci_create_simple_multifunction(PCIBus *bus, int devfn,
-                                           bool multifunction,
-                                           const char *name)
-{
-    PCIDevice *dev = pci_create_multifunction(bus, devfn, multifunction, name);
-    qdev_init_nofail(&dev->qdev);
-    return dev;
-}
-
-PCIDevice *pci_create(PCIBus *bus, int devfn, const char *name)
-{
-    return pci_create_multifunction(bus, devfn, false, name);
-}
-
-PCIDevice *pci_create_simple(PCIBus *bus, int devfn, const char *name)
-{
-    return pci_create_simple_multifunction(bus, devfn, false, name);
-}
-
-static uint8_t pci_find_space(PCIDevice *pdev, uint8_t size)
-{
-    int offset = PCI_CONFIG_HEADER_SIZE;
-    int i;
-    for (i = PCI_CONFIG_HEADER_SIZE; i < PCI_CONFIG_SPACE_SIZE; ++i) {
-        if (pdev->used[i])
-            offset = i + 1;
-        else if (i - offset + 1 == size)
-            return offset;
-    }
-    return 0;
-}
-
-static uint8_t pci_find_capability_list(PCIDevice *pdev, uint8_t cap_id,
-                                        uint8_t *prev_p)
-{
-    uint8_t next, prev;
-
-    if (!(pdev->config[PCI_STATUS] & PCI_STATUS_CAP_LIST))
-        return 0;
-
-    for (prev = PCI_CAPABILITY_LIST; (next = pdev->config[prev]);
-         prev = next + PCI_CAP_LIST_NEXT)
-        if (pdev->config[next + PCI_CAP_LIST_ID] == cap_id)
-            break;
-
-    if (prev_p)
-        *prev_p = prev;
-    return next;
-}
-
-static uint8_t pci_find_capability_at_offset(PCIDevice *pdev, uint8_t offset)
-{
-    uint8_t next, prev, found = 0;
-
-    if (!(pdev->used[offset])) {
-        return 0;
-    }
-
-    assert(pdev->config[PCI_STATUS] & PCI_STATUS_CAP_LIST);
-
-    for (prev = PCI_CAPABILITY_LIST; (next = pdev->config[prev]);
-         prev = next + PCI_CAP_LIST_NEXT) {
-        if (next <= offset && next > found) {
-            found = next;
-        }
-    }
-    return found;
-}
-
-/* Patch the PCI vendor and device ids in a PCI rom image if necessary.
-   This is needed for an option rom which is used for more than one device. */
-static void pci_patch_ids(PCIDevice *pdev, uint8_t *ptr, int size)
-{
-    uint16_t vendor_id;
-    uint16_t device_id;
-    uint16_t rom_vendor_id;
-    uint16_t rom_device_id;
-    uint16_t rom_magic;
-    uint16_t pcir_offset;
-    uint8_t checksum;
-
-    /* Words in rom data are little endian (like in PCI configuration),
-       so they can be read / written with pci_get_word / pci_set_word. */
-
-    /* Only a valid rom will be patched. */
-    rom_magic = pci_get_word(ptr);
-    if (rom_magic != 0xaa55) {
-        PCI_DPRINTF("Bad ROM magic %04x\n", rom_magic);
-        return;
-    }
-    pcir_offset = pci_get_word(ptr + 0x18);
-    if (pcir_offset + 8 >= size || memcmp(ptr + pcir_offset, "PCIR", 4)) {
-        PCI_DPRINTF("Bad PCIR offset 0x%x or signature\n", pcir_offset);
-        return;
-    }
-
-    vendor_id = pci_get_word(pdev->config + PCI_VENDOR_ID);
-    device_id = pci_get_word(pdev->config + PCI_DEVICE_ID);
-    rom_vendor_id = pci_get_word(ptr + pcir_offset + 4);
-    rom_device_id = pci_get_word(ptr + pcir_offset + 6);
-
-    PCI_DPRINTF("%s: ROM id %04x%04x / PCI id %04x%04x\n", pdev->romfile,
-                vendor_id, device_id, rom_vendor_id, rom_device_id);
-
-    checksum = ptr[6];
-
-    if (vendor_id != rom_vendor_id) {
-        /* Patch vendor id and checksum (at offset 6 for etherboot roms). */
-        checksum += (uint8_t)rom_vendor_id + (uint8_t)(rom_vendor_id >> 8);
-        checksum -= (uint8_t)vendor_id + (uint8_t)(vendor_id >> 8);
-        PCI_DPRINTF("ROM checksum %02x / %02x\n", ptr[6], checksum);
-        ptr[6] = checksum;
-        pci_set_word(ptr + pcir_offset + 4, vendor_id);
-    }
-
-    if (device_id != rom_device_id) {
-        /* Patch device id and checksum (at offset 6 for etherboot roms). */
-        checksum += (uint8_t)rom_device_id + (uint8_t)(rom_device_id >> 8);
-        checksum -= (uint8_t)device_id + (uint8_t)(device_id >> 8);
-        PCI_DPRINTF("ROM checksum %02x / %02x\n", ptr[6], checksum);
-        ptr[6] = checksum;
-        pci_set_word(ptr + pcir_offset + 6, device_id);
-    }
-}
-
-/* Add an option rom for the device */
-static int pci_add_option_rom(PCIDevice *pdev, bool is_default_rom)
-{
-    int size;
-    char *path;
-    void *ptr;
-    char name[32];
-    const VMStateDescription *vmsd;
-
-    if (!pdev->romfile)
-        return 0;
-    if (strlen(pdev->romfile) == 0)
-        return 0;
-
-    if (!pdev->rom_bar) {
-        /*
-         * Load rom via fw_cfg instead of creating a rom bar,
-         * for 0.11 compatibility.
-         */
-        int class = pci_get_word(pdev->config + PCI_CLASS_DEVICE);
-        if (class == 0x0300) {
-            rom_add_vga(pdev->romfile);
-        } else {
-            rom_add_option(pdev->romfile, -1);
-        }
-        return 0;
-    }
-
-    path = qemu_find_file(QEMU_FILE_TYPE_BIOS, pdev->romfile);
-    if (path == NULL) {
-        path = g_strdup(pdev->romfile);
-    }
-
-    size = get_image_size(path);
-    if (size < 0) {
-        error_report("%s: failed to find romfile \"%s\"",
-                     __FUNCTION__, pdev->romfile);
-        g_free(path);
-        return -1;
-    }
-    if (size & (size - 1)) {
-        size = 1 << qemu_fls(size);
-    }
-
-    vmsd = qdev_get_vmsd(DEVICE(pdev));
-
-    if (vmsd) {
-        snprintf(name, sizeof(name), "%s.rom", vmsd->name);
-    } else {
-        snprintf(name, sizeof(name), "%s.rom", 
object_get_typename(OBJECT(pdev)));
-    }
-    pdev->has_rom = true;
-    memory_region_init_ram(&pdev->rom, name, size);
-    vmstate_register_ram(&pdev->rom, &pdev->qdev);
-    ptr = memory_region_get_ram_ptr(&pdev->rom);
-    load_image(path, ptr);
-    g_free(path);
-
-    if (is_default_rom) {
-        /* Only the default rom images will be patched (if needed). */
-        pci_patch_ids(pdev, ptr, size);
-    }
-
-    qemu_put_ram_ptr(ptr);
-
-    pci_register_bar(pdev, PCI_ROM_SLOT, 0, &pdev->rom);
-
-    return 0;
-}
-
-static void pci_del_option_rom(PCIDevice *pdev)
-{
-    if (!pdev->has_rom)
-        return;
-
-    vmstate_unregister_ram(&pdev->rom, &pdev->qdev);
-    memory_region_destroy(&pdev->rom);
-    pdev->has_rom = false;
-}
-
-/*
- * if !offset
- * Reserve space and add capability to the linked list in pci config space
- *
- * if offset = 0,
- * Find and reserve space and add capability to the linked list
- * in pci config space */
-int pci_add_capability(PCIDevice *pdev, uint8_t cap_id,
-                       uint8_t offset, uint8_t size)
-{
-    uint8_t *config;
-    int i, overlapping_cap;
-
-    if (!offset) {
-        offset = pci_find_space(pdev, size);
-        if (!offset) {
-            return -ENOSPC;
-        }
-    } else {
-        /* Verify that capabilities don't overlap.  Note: device assignment
-         * depends on this check to verify that the device is not broken.
-         * Should never trigger for emulated devices, but it's helpful
-         * for debugging these. */
-        for (i = offset; i < offset + size; i++) {
-            overlapping_cap = pci_find_capability_at_offset(pdev, i);
-            if (overlapping_cap) {
-                fprintf(stderr, "ERROR: %04x:%02x:%02x.%x "
-                        "Attempt to add PCI capability %x at offset "
-                        "%x overlaps existing capability %x at offset %x\n",
-                        pci_find_domain(pdev->bus), pci_bus_num(pdev->bus),
-                        PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn),
-                        cap_id, offset, overlapping_cap, i);
-                return -EINVAL;
-            }
-        }
-    }
-
-    config = pdev->config + offset;
-    config[PCI_CAP_LIST_ID] = cap_id;
-    config[PCI_CAP_LIST_NEXT] = pdev->config[PCI_CAPABILITY_LIST];
-    pdev->config[PCI_CAPABILITY_LIST] = offset;
-    pdev->config[PCI_STATUS] |= PCI_STATUS_CAP_LIST;
-    memset(pdev->used + offset, 0xFF, QEMU_ALIGN_UP(size, 4));
-    /* Make capability read-only by default */
-    memset(pdev->wmask + offset, 0, size);
-    /* Check capability by default */
-    memset(pdev->cmask + offset, 0xFF, size);
-    return offset;
-}
-
-/* Unlink capability from the pci config space. */
-void pci_del_capability(PCIDevice *pdev, uint8_t cap_id, uint8_t size)
-{
-    uint8_t prev, offset = pci_find_capability_list(pdev, cap_id, &prev);
-    if (!offset)
-        return;
-    pdev->config[prev] = pdev->config[offset + PCI_CAP_LIST_NEXT];
-    /* Make capability writable again */
-    memset(pdev->wmask + offset, 0xff, size);
-    memset(pdev->w1cmask + offset, 0, size);
-    /* Clear cmask as device-specific registers can't be checked */
-    memset(pdev->cmask + offset, 0, size);
-    memset(pdev->used + offset, 0, QEMU_ALIGN_UP(size, 4));
-
-    if (!pdev->config[PCI_CAPABILITY_LIST])
-        pdev->config[PCI_STATUS] &= ~PCI_STATUS_CAP_LIST;
-}
-
-uint8_t pci_find_capability(PCIDevice *pdev, uint8_t cap_id)
-{
-    return pci_find_capability_list(pdev, cap_id, NULL);
-}
-
-static void pcibus_dev_print(Monitor *mon, DeviceState *dev, int indent)
-{
-    PCIDevice *d = (PCIDevice *)dev;
-    const pci_class_desc *desc;
-    char ctxt[64];
-    PCIIORegion *r;
-    int i, class;
-
-    class = pci_get_word(d->config + PCI_CLASS_DEVICE);
-    desc = pci_class_descriptions;
-    while (desc->desc && class != desc->class)
-        desc++;
-    if (desc->desc) {
-        snprintf(ctxt, sizeof(ctxt), "%s", desc->desc);
-    } else {
-        snprintf(ctxt, sizeof(ctxt), "Class %04x", class);
-    }
-
-    monitor_printf(mon, "%*sclass %s, addr %02x:%02x.%x, "
-                   "pci id %04x:%04x (sub %04x:%04x)\n",
-                   indent, "", ctxt, pci_bus_num(d->bus),
-                   PCI_SLOT(d->devfn), PCI_FUNC(d->devfn),
-                   pci_get_word(d->config + PCI_VENDOR_ID),
-                   pci_get_word(d->config + PCI_DEVICE_ID),
-                   pci_get_word(d->config + PCI_SUBSYSTEM_VENDOR_ID),
-                   pci_get_word(d->config + PCI_SUBSYSTEM_ID));
-    for (i = 0; i < PCI_NUM_REGIONS; i++) {
-        r = &d->io_regions[i];
-        if (!r->size)
-            continue;
-        monitor_printf(mon, "%*sbar %d: %s at 0x%"FMT_PCIBUS
-                       " [0x%"FMT_PCIBUS"]\n",
-                       indent, "",
-                       i, r->type & PCI_BASE_ADDRESS_SPACE_IO ? "i/o" : "mem",
-                       r->addr, r->addr + r->size - 1);
-    }
-}
-
-static char *pci_dev_fw_name(DeviceState *dev, char *buf, int len)
-{
-    PCIDevice *d = (PCIDevice *)dev;
-    const char *name = NULL;
-    const pci_class_desc *desc =  pci_class_descriptions;
-    int class = pci_get_word(d->config + PCI_CLASS_DEVICE);
-
-    while (desc->desc &&
-          (class & ~desc->fw_ign_bits) !=
-          (desc->class & ~desc->fw_ign_bits)) {
-        desc++;
-    }
-
-    if (desc->desc) {
-        name = desc->fw_name;
-    }
-
-    if (name) {
-        pstrcpy(buf, len, name);
-    } else {
-        snprintf(buf, len, "pci%04x,%04x",
-                 pci_get_word(d->config + PCI_VENDOR_ID),
-                 pci_get_word(d->config + PCI_DEVICE_ID));
-    }
-
-    return buf;
-}
-
-static char *pcibus_get_fw_dev_path(DeviceState *dev)
-{
-    PCIDevice *d = (PCIDevice *)dev;
-    char path[50], name[33];
-    int off;
-
-    off = snprintf(path, sizeof(path), "address@hidden",
-                   pci_dev_fw_name(dev, name, sizeof name),
-                   PCI_SLOT(d->devfn));
-    if (PCI_FUNC(d->devfn))
-        snprintf(path + off, sizeof(path) + off, ",%x", PCI_FUNC(d->devfn));
-    return g_strdup(path);
-}
-
-static char *pcibus_get_dev_path(DeviceState *dev)
-{
-    PCIDevice *d = container_of(dev, PCIDevice, qdev);
-    PCIDevice *t;
-    int slot_depth;
-    /* Path format: Domain:00:Slot.Function:Slot.Function....:Slot.Function.
-     * 00 is added here to make this format compatible with
-     * domain:Bus:Slot.Func for systems without nested PCI bridges.
-     * Slot.Function list specifies the slot and function numbers for all
-     * devices on the path from root to the specific device. */
-    char domain[] = "DDDD:00";
-    char slot[] = ":SS.F";
-    int domain_len = sizeof domain - 1 /* For '\0' */;
-    int slot_len = sizeof slot - 1 /* For '\0' */;
-    int path_len;
-    char *path, *p;
-    int s;
-
-    /* Calculate # of slots on path between device and root. */;
-    slot_depth = 0;
-    for (t = d; t; t = t->bus->parent_dev) {
-        ++slot_depth;
-    }
-
-    path_len = domain_len + slot_len * slot_depth;
-
-    /* Allocate memory, fill in the terminating null byte. */
-    path = g_malloc(path_len + 1 /* For '\0' */);
-    path[path_len] = '\0';
-
-    /* First field is the domain. */
-    s = snprintf(domain, sizeof domain, "%04x:00", pci_find_domain(d->bus));
-    assert(s == domain_len);
-    memcpy(path, domain, domain_len);
-
-    /* Fill in slot numbers. We walk up from device to root, so need to print
-     * them in the reverse order, last to first. */
-    p = path + path_len;
-    for (t = d; t; t = t->bus->parent_dev) {
-        p -= slot_len;
-        s = snprintf(slot, sizeof slot, ":%02x.%x",
-                     PCI_SLOT(t->devfn), PCI_FUNC(t->devfn));
-        assert(s == slot_len);
-        memcpy(p, slot, slot_len);
-    }
-
-    return path;
-}
-
-static int pci_qdev_find_recursive(PCIBus *bus,
-                                   const char *id, PCIDevice **pdev)
-{
-    DeviceState *qdev = qdev_find_recursive(&bus->qbus, id);
-    if (!qdev) {
-        return -ENODEV;
-    }
-
-    /* roughly check if given qdev is pci device */
-    if (object_dynamic_cast(OBJECT(qdev), TYPE_PCI_DEVICE)) {
-        *pdev = PCI_DEVICE(qdev);
-        return 0;
-    }
-    return -EINVAL;
-}
-
-int pci_qdev_find_device(const char *id, PCIDevice **pdev)
-{
-    struct PCIHostBus *host;
-    int rc = -ENODEV;
-
-    QLIST_FOREACH(host, &host_buses, next) {
-        int tmp = pci_qdev_find_recursive(host->bus, id, pdev);
-        if (!tmp) {
-            rc = 0;
-            break;
-        }
-        if (tmp != -ENODEV) {
-            rc = tmp;
-        }
-    }
-
-    return rc;
-}
-
-MemoryRegion *pci_address_space(PCIDevice *dev)
-{
-    return dev->bus->address_space_mem;
-}
-
-MemoryRegion *pci_address_space_io(PCIDevice *dev)
-{
-    return dev->bus->address_space_io;
-}
-
-static void pci_device_class_init(ObjectClass *klass, void *data)
-{
-    DeviceClass *k = DEVICE_CLASS(klass);
-    k->init = pci_qdev_init;
-    k->unplug = pci_unplug_device;
-    k->exit = pci_unregister_device;
-    k->bus_type = TYPE_PCI_BUS;
-    k->props = pci_props;
-}
-
-void pci_setup_iommu(PCIBus *bus, PCIDMAContextFunc fn, void *opaque)
-{
-    bus->dma_context_fn = fn;
-    bus->dma_context_opaque = opaque;
-}
-
-static TypeInfo pci_device_type_info = {
-    .name = TYPE_PCI_DEVICE,
-    .parent = TYPE_DEVICE,
-    .instance_size = sizeof(PCIDevice),
-    .abstract = true,
-    .class_size = sizeof(PCIDeviceClass),
-    .class_init = pci_device_class_init,
-};
-
-static void pci_register_types(void)
-{
-    type_register_static(&pci_bus_info);
-    type_register_static(&pci_device_type_info);
-}
-
-type_init(pci_register_types)
diff --git a/hw/pci.h b/hw/pci.h
deleted file mode 100644
index 4da0c2a..0000000
--- a/hw/pci.h
+++ /dev/null
@@ -1,684 +0,0 @@
-#ifndef QEMU_PCI_H
-#define QEMU_PCI_H
-
-#include "qemu-common.h"
-
-#include "qdev.h"
-#include "memory.h"
-#include "dma.h"
-
-/* PCI includes legacy ISA access.  */
-#include "isa.h"
-
-#include "pcie.h"
-
-/* PCI bus */
-
-#define PCI_DEVFN(slot, func)   ((((slot) & 0x1f) << 3) | ((func) & 0x07))
-#define PCI_SLOT(devfn)         (((devfn) >> 3) & 0x1f)
-#define PCI_FUNC(devfn)         ((devfn) & 0x07)
-#define PCI_SLOT_MAX            32
-#define PCI_FUNC_MAX            8
-
-/* Class, Vendor and Device IDs from Linux's pci_ids.h */
-#include "pci_ids.h"
-
-/* QEMU-specific Vendor and Device ID definitions */
-
-/* IBM (0x1014) */
-#define PCI_DEVICE_ID_IBM_440GX          0x027f
-#define PCI_DEVICE_ID_IBM_OPENPIC2       0xffff
-
-/* Hitachi (0x1054) */
-#define PCI_VENDOR_ID_HITACHI            0x1054
-#define PCI_DEVICE_ID_HITACHI_SH7751R    0x350e
-
-/* Apple (0x106b) */
-#define PCI_DEVICE_ID_APPLE_343S1201     0x0010
-#define PCI_DEVICE_ID_APPLE_UNI_N_I_PCI  0x001e
-#define PCI_DEVICE_ID_APPLE_UNI_N_PCI    0x001f
-#define PCI_DEVICE_ID_APPLE_UNI_N_KEYL   0x0022
-#define PCI_DEVICE_ID_APPLE_IPID_USB     0x003f
-
-/* Realtek (0x10ec) */
-#define PCI_DEVICE_ID_REALTEK_8029       0x8029
-
-/* Xilinx (0x10ee) */
-#define PCI_DEVICE_ID_XILINX_XC2VP30     0x0300
-
-/* Marvell (0x11ab) */
-#define PCI_DEVICE_ID_MARVELL_GT6412X    0x4620
-
-/* QEMU/Bochs VGA (0x1234) */
-#define PCI_VENDOR_ID_QEMU               0x1234
-#define PCI_DEVICE_ID_QEMU_VGA           0x1111
-
-/* VMWare (0x15ad) */
-#define PCI_VENDOR_ID_VMWARE             0x15ad
-#define PCI_DEVICE_ID_VMWARE_SVGA2       0x0405
-#define PCI_DEVICE_ID_VMWARE_SVGA        0x0710
-#define PCI_DEVICE_ID_VMWARE_NET         0x0720
-#define PCI_DEVICE_ID_VMWARE_SCSI        0x0730
-#define PCI_DEVICE_ID_VMWARE_IDE         0x1729
-
-/* Intel (0x8086) */
-#define PCI_DEVICE_ID_INTEL_82551IT      0x1209
-#define PCI_DEVICE_ID_INTEL_82557        0x1229
-#define PCI_DEVICE_ID_INTEL_82801IR      0x2922
-
-/* Red Hat / Qumranet (for QEMU) -- see pci-ids.txt */
-#define PCI_VENDOR_ID_REDHAT_QUMRANET    0x1af4
-#define PCI_SUBVENDOR_ID_REDHAT_QUMRANET 0x1af4
-#define PCI_SUBDEVICE_ID_QEMU            0x1100
-
-#define PCI_DEVICE_ID_VIRTIO_NET         0x1000
-#define PCI_DEVICE_ID_VIRTIO_BLOCK       0x1001
-#define PCI_DEVICE_ID_VIRTIO_BALLOON     0x1002
-#define PCI_DEVICE_ID_VIRTIO_CONSOLE     0x1003
-#define PCI_DEVICE_ID_VIRTIO_SCSI        0x1004
-#define PCI_DEVICE_ID_VIRTIO_RNG         0x1005
-
-#define FMT_PCIBUS                      PRIx64
-
-typedef void PCIConfigWriteFunc(PCIDevice *pci_dev,
-                                uint32_t address, uint32_t data, int len);
-typedef uint32_t PCIConfigReadFunc(PCIDevice *pci_dev,
-                                   uint32_t address, int len);
-typedef void PCIMapIORegionFunc(PCIDevice *pci_dev, int region_num,
-                                pcibus_t addr, pcibus_t size, int type);
-typedef void PCIUnregisterFunc(PCIDevice *pci_dev);
-
-typedef struct PCIIORegion {
-    pcibus_t addr; /* current PCI mapping address. -1 means not mapped */
-#define PCI_BAR_UNMAPPED (~(pcibus_t)0)
-    pcibus_t size;
-    uint8_t type;
-    MemoryRegion *memory;
-    MemoryRegion *address_space;
-} PCIIORegion;
-
-#define PCI_ROM_SLOT 6
-#define PCI_NUM_REGIONS 7
-
-#include "pci_regs.h"
-
-/* PCI HEADER_TYPE */
-#define  PCI_HEADER_TYPE_MULTI_FUNCTION 0x80
-
-/* Size of the standard PCI config header */
-#define PCI_CONFIG_HEADER_SIZE 0x40
-/* Size of the standard PCI config space */
-#define PCI_CONFIG_SPACE_SIZE 0x100
-/* Size of the standart PCIe config space: 4KB */
-#define PCIE_CONFIG_SPACE_SIZE  0x1000
-
-#define PCI_NUM_PINS 4 /* A-D */
-
-/* Bits in cap_present field. */
-enum {
-    QEMU_PCI_CAP_MSI = 0x1,
-    QEMU_PCI_CAP_MSIX = 0x2,
-    QEMU_PCI_CAP_EXPRESS = 0x4,
-
-    /* multifunction capable device */
-#define QEMU_PCI_CAP_MULTIFUNCTION_BITNR        3
-    QEMU_PCI_CAP_MULTIFUNCTION = (1 << QEMU_PCI_CAP_MULTIFUNCTION_BITNR),
-
-    /* command register SERR bit enabled */
-#define QEMU_PCI_CAP_SERR_BITNR 4
-    QEMU_PCI_CAP_SERR = (1 << QEMU_PCI_CAP_SERR_BITNR),
-    /* Standard hot plug controller. */
-#define QEMU_PCI_SHPC_BITNR 5
-    QEMU_PCI_CAP_SHPC = (1 << QEMU_PCI_SHPC_BITNR),
-#define QEMU_PCI_SLOTID_BITNR 6
-    QEMU_PCI_CAP_SLOTID = (1 << QEMU_PCI_SLOTID_BITNR),
-};
-
-#define TYPE_PCI_DEVICE "pci-device"
-#define PCI_DEVICE(obj) \
-     OBJECT_CHECK(PCIDevice, (obj), TYPE_PCI_DEVICE)
-#define PCI_DEVICE_CLASS(klass) \
-     OBJECT_CLASS_CHECK(PCIDeviceClass, (klass), TYPE_PCI_DEVICE)
-#define PCI_DEVICE_GET_CLASS(obj) \
-     OBJECT_GET_CLASS(PCIDeviceClass, (obj), TYPE_PCI_DEVICE)
-
-typedef struct PCIINTxRoute {
-    enum {
-        PCI_INTX_ENABLED,
-        PCI_INTX_INVERTED,
-        PCI_INTX_DISABLED,
-    } mode;
-    int irq;
-} PCIINTxRoute;
-
-typedef struct PCIDeviceClass {
-    DeviceClass parent_class;
-
-    int (*init)(PCIDevice *dev);
-    PCIUnregisterFunc *exit;
-    PCIConfigReadFunc *config_read;
-    PCIConfigWriteFunc *config_write;
-
-    uint16_t vendor_id;
-    uint16_t device_id;
-    uint8_t revision;
-    uint16_t class_id;
-    uint16_t subsystem_vendor_id;       /* only for header type = 0 */
-    uint16_t subsystem_id;              /* only for header type = 0 */
-
-    /*
-     * pci-to-pci bridge or normal device.
-     * This doesn't mean pci host switch.
-     * When card bus bridge is supported, this would be enhanced.
-     */
-    int is_bridge;
-
-    /* pcie stuff */
-    int is_express;   /* is this device pci express? */
-
-    /* device isn't hot-pluggable */
-    int no_hotplug;
-
-    /* rom bar */
-    const char *romfile;
-} PCIDeviceClass;
-
-typedef void (*PCIINTxRoutingNotifier)(PCIDevice *dev);
-typedef int (*MSIVectorUseNotifier)(PCIDevice *dev, unsigned int vector,
-                                      MSIMessage msg);
-typedef void (*MSIVectorReleaseNotifier)(PCIDevice *dev, unsigned int vector);
-
-struct PCIDevice {
-    DeviceState qdev;
-
-    /* PCI config space */
-    uint8_t *config;
-
-    /* Used to enable config checks on load. Note that writable bits are
-     * never checked even if set in cmask. */
-    uint8_t *cmask;
-
-    /* Used to implement R/W bytes */
-    uint8_t *wmask;
-
-    /* Used to implement RW1C(Write 1 to Clear) bytes */
-    uint8_t *w1cmask;
-
-    /* Used to allocate config space for capabilities. */
-    uint8_t *used;
-
-    /* the following fields are read only */
-    PCIBus *bus;
-    int32_t devfn;
-    char name[64];
-    PCIIORegion io_regions[PCI_NUM_REGIONS];
-    AddressSpace bus_master_as;
-    MemoryRegion bus_master_enable_region;
-    DMAContext *dma;
-
-    /* do not access the following fields */
-    PCIConfigReadFunc *config_read;
-    PCIConfigWriteFunc *config_write;
-
-    /* IRQ objects for the INTA-INTD pins.  */
-    qemu_irq *irq;
-
-    /* Current IRQ levels.  Used internally by the generic PCI code.  */
-    uint8_t irq_state;
-
-    /* Capability bits */
-    uint32_t cap_present;
-
-    /* Offset of MSI-X capability in config space */
-    uint8_t msix_cap;
-
-    /* MSI-X entries */
-    int msix_entries_nr;
-
-    /* Space to store MSIX table & pending bit array */
-    uint8_t *msix_table;
-    uint8_t *msix_pba;
-    /* MemoryRegion container for msix exclusive BAR setup */
-    MemoryRegion msix_exclusive_bar;
-    /* Memory Regions for MSIX table and pending bit entries. */
-    MemoryRegion msix_table_mmio;
-    MemoryRegion msix_pba_mmio;
-    /* Reference-count for entries actually in use by driver. */
-    unsigned *msix_entry_used;
-    /* MSIX function mask set or MSIX disabled */
-    bool msix_function_masked;
-    /* Version id needed for VMState */
-    int32_t version_id;
-
-    /* Offset of MSI capability in config space */
-    uint8_t msi_cap;
-
-    /* PCI Express */
-    PCIExpressDevice exp;
-
-    /* SHPC */
-    SHPCDevice *shpc;
-
-    /* Location of option rom */
-    char *romfile;
-    bool has_rom;
-    MemoryRegion rom;
-    uint32_t rom_bar;
-
-    /* INTx routing notifier */
-    PCIINTxRoutingNotifier intx_routing_notifier;
-
-    /* MSI-X notifiers */
-    MSIVectorUseNotifier msix_vector_use_notifier;
-    MSIVectorReleaseNotifier msix_vector_release_notifier;
-};
-
-void pci_register_bar(PCIDevice *pci_dev, int region_num,
-                      uint8_t attr, MemoryRegion *memory);
-pcibus_t pci_get_bar_addr(PCIDevice *pci_dev, int region_num);
-
-int pci_add_capability(PCIDevice *pdev, uint8_t cap_id,
-                       uint8_t offset, uint8_t size);
-
-void pci_del_capability(PCIDevice *pci_dev, uint8_t cap_id, uint8_t cap_size);
-
-uint8_t pci_find_capability(PCIDevice *pci_dev, uint8_t cap_id);
-
-
-uint32_t pci_default_read_config(PCIDevice *d,
-                                 uint32_t address, int len);
-void pci_default_write_config(PCIDevice *d,
-                              uint32_t address, uint32_t val, int len);
-void pci_device_save(PCIDevice *s, QEMUFile *f);
-int pci_device_load(PCIDevice *s, QEMUFile *f);
-MemoryRegion *pci_address_space(PCIDevice *dev);
-MemoryRegion *pci_address_space_io(PCIDevice *dev);
-
-typedef void (*pci_set_irq_fn)(void *opaque, int irq_num, int level);
-typedef int (*pci_map_irq_fn)(PCIDevice *pci_dev, int irq_num);
-typedef PCIINTxRoute (*pci_route_irq_fn)(void *opaque, int pin);
-
-typedef enum {
-    PCI_HOTPLUG_DISABLED,
-    PCI_HOTPLUG_ENABLED,
-    PCI_COLDPLUG_ENABLED,
-} PCIHotplugState;
-
-typedef int (*pci_hotplug_fn)(DeviceState *qdev, PCIDevice *pci_dev,
-                              PCIHotplugState state);
-void pci_bus_new_inplace(PCIBus *bus, DeviceState *parent,
-                         const char *name,
-                         MemoryRegion *address_space_mem,
-                         MemoryRegion *address_space_io,
-                         uint8_t devfn_min);
-PCIBus *pci_bus_new(DeviceState *parent, const char *name,
-                    MemoryRegion *address_space_mem,
-                    MemoryRegion *address_space_io,
-                    uint8_t devfn_min);
-void pci_bus_irqs(PCIBus *bus, pci_set_irq_fn set_irq, pci_map_irq_fn map_irq,
-                  void *irq_opaque, int nirq);
-int pci_bus_get_irq_level(PCIBus *bus, int irq_num);
-void pci_bus_hotplug(PCIBus *bus, pci_hotplug_fn hotplug, DeviceState *dev);
-/* 0 <= pin <= 3 0 = INTA, 1 = INTB, 2 = INTC, 3 = INTD */
-int pci_swizzle_map_irq_fn(PCIDevice *pci_dev, int pin);
-PCIBus *pci_register_bus(DeviceState *parent, const char *name,
-                         pci_set_irq_fn set_irq, pci_map_irq_fn map_irq,
-                         void *irq_opaque,
-                         MemoryRegion *address_space_mem,
-                         MemoryRegion *address_space_io,
-                         uint8_t devfn_min, int nirq);
-void pci_bus_set_route_irq_fn(PCIBus *, pci_route_irq_fn);
-PCIINTxRoute pci_device_route_intx_to_irq(PCIDevice *dev, int pin);
-bool pci_intx_route_changed(PCIINTxRoute *old, PCIINTxRoute *new);
-void pci_bus_fire_intx_routing_notifier(PCIBus *bus);
-void pci_device_set_intx_routing_notifier(PCIDevice *dev,
-                                          PCIINTxRoutingNotifier notifier);
-void pci_device_reset(PCIDevice *dev);
-void pci_bus_reset(PCIBus *bus);
-
-PCIDevice *pci_nic_init(NICInfo *nd, const char *default_model,
-                        const char *default_devaddr);
-PCIDevice *pci_nic_init_nofail(NICInfo *nd, const char *default_model,
-                               const char *default_devaddr);
-
-PCIDevice *pci_vga_init(PCIBus *bus);
-
-int pci_bus_num(PCIBus *s);
-void pci_for_each_device(PCIBus *bus, int bus_num,
-                         void (*fn)(PCIBus *bus, PCIDevice *d, void *opaque),
-                         void *opaque);
-PCIBus *pci_find_root_bus(int domain);
-int pci_find_domain(const PCIBus *bus);
-PCIDevice *pci_find_device(PCIBus *bus, int bus_num, uint8_t devfn);
-int pci_qdev_find_device(const char *id, PCIDevice **pdev);
-PCIBus *pci_get_bus_devfn(int *devfnp, const char *devaddr);
-
-int pci_read_devaddr(Monitor *mon, const char *addr, int *domp, int *busp,
-                     unsigned *slotp);
-
-void pci_device_deassert_intx(PCIDevice *dev);
-
-typedef DMAContext *(*PCIDMAContextFunc)(PCIBus *, void *, int);
-
-void pci_setup_iommu(PCIBus *bus, PCIDMAContextFunc fn, void *opaque);
-
-static inline void
-pci_set_byte(uint8_t *config, uint8_t val)
-{
-    *config = val;
-}
-
-static inline uint8_t
-pci_get_byte(const uint8_t *config)
-{
-    return *config;
-}
-
-static inline void
-pci_set_word(uint8_t *config, uint16_t val)
-{
-    cpu_to_le16wu((uint16_t *)config, val);
-}
-
-static inline uint16_t
-pci_get_word(const uint8_t *config)
-{
-    return le16_to_cpupu((const uint16_t *)config);
-}
-
-static inline void
-pci_set_long(uint8_t *config, uint32_t val)
-{
-    cpu_to_le32wu((uint32_t *)config, val);
-}
-
-static inline uint32_t
-pci_get_long(const uint8_t *config)
-{
-    return le32_to_cpupu((const uint32_t *)config);
-}
-
-static inline void
-pci_set_quad(uint8_t *config, uint64_t val)
-{
-    cpu_to_le64w((uint64_t *)config, val);
-}
-
-static inline uint64_t
-pci_get_quad(const uint8_t *config)
-{
-    return le64_to_cpup((const uint64_t *)config);
-}
-
-static inline void
-pci_config_set_vendor_id(uint8_t *pci_config, uint16_t val)
-{
-    pci_set_word(&pci_config[PCI_VENDOR_ID], val);
-}
-
-static inline void
-pci_config_set_device_id(uint8_t *pci_config, uint16_t val)
-{
-    pci_set_word(&pci_config[PCI_DEVICE_ID], val);
-}
-
-static inline void
-pci_config_set_revision(uint8_t *pci_config, uint8_t val)
-{
-    pci_set_byte(&pci_config[PCI_REVISION_ID], val);
-}
-
-static inline void
-pci_config_set_class(uint8_t *pci_config, uint16_t val)
-{
-    pci_set_word(&pci_config[PCI_CLASS_DEVICE], val);
-}
-
-static inline void
-pci_config_set_prog_interface(uint8_t *pci_config, uint8_t val)
-{
-    pci_set_byte(&pci_config[PCI_CLASS_PROG], val);
-}
-
-static inline void
-pci_config_set_interrupt_pin(uint8_t *pci_config, uint8_t val)
-{
-    pci_set_byte(&pci_config[PCI_INTERRUPT_PIN], val);
-}
-
-/*
- * helper functions to do bit mask operation on configuration space.
- * Just to set bit, use test-and-set and discard returned value.
- * Just to clear bit, use test-and-clear and discard returned value.
- * NOTE: They aren't atomic.
- */
-static inline uint8_t
-pci_byte_test_and_clear_mask(uint8_t *config, uint8_t mask)
-{
-    uint8_t val = pci_get_byte(config);
-    pci_set_byte(config, val & ~mask);
-    return val & mask;
-}
-
-static inline uint8_t
-pci_byte_test_and_set_mask(uint8_t *config, uint8_t mask)
-{
-    uint8_t val = pci_get_byte(config);
-    pci_set_byte(config, val | mask);
-    return val & mask;
-}
-
-static inline uint16_t
-pci_word_test_and_clear_mask(uint8_t *config, uint16_t mask)
-{
-    uint16_t val = pci_get_word(config);
-    pci_set_word(config, val & ~mask);
-    return val & mask;
-}
-
-static inline uint16_t
-pci_word_test_and_set_mask(uint8_t *config, uint16_t mask)
-{
-    uint16_t val = pci_get_word(config);
-    pci_set_word(config, val | mask);
-    return val & mask;
-}
-
-static inline uint32_t
-pci_long_test_and_clear_mask(uint8_t *config, uint32_t mask)
-{
-    uint32_t val = pci_get_long(config);
-    pci_set_long(config, val & ~mask);
-    return val & mask;
-}
-
-static inline uint32_t
-pci_long_test_and_set_mask(uint8_t *config, uint32_t mask)
-{
-    uint32_t val = pci_get_long(config);
-    pci_set_long(config, val | mask);
-    return val & mask;
-}
-
-static inline uint64_t
-pci_quad_test_and_clear_mask(uint8_t *config, uint64_t mask)
-{
-    uint64_t val = pci_get_quad(config);
-    pci_set_quad(config, val & ~mask);
-    return val & mask;
-}
-
-static inline uint64_t
-pci_quad_test_and_set_mask(uint8_t *config, uint64_t mask)
-{
-    uint64_t val = pci_get_quad(config);
-    pci_set_quad(config, val | mask);
-    return val & mask;
-}
-
-/* Access a register specified by a mask */
-static inline void
-pci_set_byte_by_mask(uint8_t *config, uint8_t mask, uint8_t reg)
-{
-    uint8_t val = pci_get_byte(config);
-    uint8_t rval = reg << (ffs(mask) - 1);
-    pci_set_byte(config, (~mask & val) | (mask & rval));
-}
-
-static inline uint8_t
-pci_get_byte_by_mask(uint8_t *config, uint8_t mask)
-{
-    uint8_t val = pci_get_byte(config);
-    return (val & mask) >> (ffs(mask) - 1);
-}
-
-static inline void
-pci_set_word_by_mask(uint8_t *config, uint16_t mask, uint16_t reg)
-{
-    uint16_t val = pci_get_word(config);
-    uint16_t rval = reg << (ffs(mask) - 1);
-    pci_set_word(config, (~mask & val) | (mask & rval));
-}
-
-static inline uint16_t
-pci_get_word_by_mask(uint8_t *config, uint16_t mask)
-{
-    uint16_t val = pci_get_word(config);
-    return (val & mask) >> (ffs(mask) - 1);
-}
-
-static inline void
-pci_set_long_by_mask(uint8_t *config, uint32_t mask, uint32_t reg)
-{
-    uint32_t val = pci_get_long(config);
-    uint32_t rval = reg << (ffs(mask) - 1);
-    pci_set_long(config, (~mask & val) | (mask & rval));
-}
-
-static inline uint32_t
-pci_get_long_by_mask(uint8_t *config, uint32_t mask)
-{
-    uint32_t val = pci_get_long(config);
-    return (val & mask) >> (ffs(mask) - 1);
-}
-
-static inline void
-pci_set_quad_by_mask(uint8_t *config, uint64_t mask, uint64_t reg)
-{
-    uint64_t val = pci_get_quad(config);
-    uint64_t rval = reg << (ffs(mask) - 1);
-    pci_set_quad(config, (~mask & val) | (mask & rval));
-}
-
-static inline uint64_t
-pci_get_quad_by_mask(uint8_t *config, uint64_t mask)
-{
-    uint64_t val = pci_get_quad(config);
-    return (val & mask) >> (ffs(mask) - 1);
-}
-
-PCIDevice *pci_create_multifunction(PCIBus *bus, int devfn, bool multifunction,
-                                    const char *name);
-PCIDevice *pci_create_simple_multifunction(PCIBus *bus, int devfn,
-                                           bool multifunction,
-                                           const char *name);
-PCIDevice *pci_create(PCIBus *bus, int devfn, const char *name);
-PCIDevice *pci_create_simple(PCIBus *bus, int devfn, const char *name);
-
-static inline int pci_is_express(const PCIDevice *d)
-{
-    return d->cap_present & QEMU_PCI_CAP_EXPRESS;
-}
-
-static inline uint32_t pci_config_size(const PCIDevice *d)
-{
-    return pci_is_express(d) ? PCIE_CONFIG_SPACE_SIZE : PCI_CONFIG_SPACE_SIZE;
-}
-
-/* DMA access functions */
-static inline DMAContext *pci_dma_context(PCIDevice *dev)
-{
-    return dev->dma;
-}
-
-static inline int pci_dma_rw(PCIDevice *dev, dma_addr_t addr,
-                             void *buf, dma_addr_t len, DMADirection dir)
-{
-    dma_memory_rw(pci_dma_context(dev), addr, buf, len, dir);
-    return 0;
-}
-
-static inline int pci_dma_read(PCIDevice *dev, dma_addr_t addr,
-                               void *buf, dma_addr_t len)
-{
-    return pci_dma_rw(dev, addr, buf, len, DMA_DIRECTION_TO_DEVICE);
-}
-
-static inline int pci_dma_write(PCIDevice *dev, dma_addr_t addr,
-                                const void *buf, dma_addr_t len)
-{
-    return pci_dma_rw(dev, addr, (void *) buf, len, DMA_DIRECTION_FROM_DEVICE);
-}
-
-#define PCI_DMA_DEFINE_LDST(_l, _s, _bits)                              \
-    static inline uint##_bits##_t ld##_l##_pci_dma(PCIDevice *dev,      \
-                                                   dma_addr_t addr)     \
-    {                                                                   \
-        return ld##_l##_dma(pci_dma_context(dev), addr);                \
-    }                                                                   \
-    static inline void st##_s##_pci_dma(PCIDevice *dev,                 \
-                                        dma_addr_t addr, uint##_bits##_t val) \
-    {                                                                   \
-        st##_s##_dma(pci_dma_context(dev), addr, val);                  \
-    }
-
-PCI_DMA_DEFINE_LDST(ub, b, 8);
-PCI_DMA_DEFINE_LDST(uw_le, w_le, 16)
-PCI_DMA_DEFINE_LDST(l_le, l_le, 32);
-PCI_DMA_DEFINE_LDST(q_le, q_le, 64);
-PCI_DMA_DEFINE_LDST(uw_be, w_be, 16)
-PCI_DMA_DEFINE_LDST(l_be, l_be, 32);
-PCI_DMA_DEFINE_LDST(q_be, q_be, 64);
-
-#undef PCI_DMA_DEFINE_LDST
-
-static inline void *pci_dma_map(PCIDevice *dev, dma_addr_t addr,
-                                dma_addr_t *plen, DMADirection dir)
-{
-    void *buf;
-
-    buf = dma_memory_map(pci_dma_context(dev), addr, plen, dir);
-    return buf;
-}
-
-static inline void pci_dma_unmap(PCIDevice *dev, void *buffer, dma_addr_t len,
-                                 DMADirection dir, dma_addr_t access_len)
-{
-    dma_memory_unmap(pci_dma_context(dev), buffer, len, dir, access_len);
-}
-
-static inline void pci_dma_sglist_init(QEMUSGList *qsg, PCIDevice *dev,
-                                       int alloc_hint)
-{
-    qemu_sglist_init(qsg, alloc_hint, pci_dma_context(dev));
-}
-
-extern const VMStateDescription vmstate_pci_device;
-
-#define VMSTATE_PCI_DEVICE(_field, _state) {                         \
-    .name       = (stringify(_field)),                               \
-    .size       = sizeof(PCIDevice),                                 \
-    .vmsd       = &vmstate_pci_device,                               \
-    .flags      = VMS_STRUCT,                                        \
-    .offset     = vmstate_offset_value(_state, _field, PCIDevice),   \
-}
-
-#define VMSTATE_PCI_DEVICE_POINTER(_field, _state) {                 \
-    .name       = (stringify(_field)),                               \
-    .size       = sizeof(PCIDevice),                                 \
-    .vmsd       = &vmstate_pci_device,                               \
-    .flags      = VMS_STRUCT|VMS_POINTER,                            \
-    .offset     = vmstate_offset_pointer(_state, _field, PCIDevice), \
-}
-
-#endif
diff --git a/hw/pci/Makefile.objs b/hw/pci/Makefile.objs
new file mode 100644
index 0000000..9d21952
--- /dev/null
+++ b/hw/pci/Makefile.objs
@@ -0,0 +1,6 @@
+common-obj-$(CONFIG_PCI) += pci.o pci_bridge.o
+common-obj-$(CONFIG_PCI) += msix.o msi.o
+common-obj-$(CONFIG_PCI) += shpc.o
+common-obj-$(CONFIG_PCI) += slotid_cap.o
+common-obj-$(CONFIG_PCI) += pci_host.o pcie_host.o
+common-obj-$(CONFIG_PCI) += pcie.o pcie_aer.o pcie_port.o
diff --git a/hw/pci/msi.c b/hw/pci/msi.c
new file mode 100644
index 0000000..33037a8
--- /dev/null
+++ b/hw/pci/msi.c
@@ -0,0 +1,395 @@
+/*
+ * msi.c
+ *
+ * Copyright (c) 2010 Isaku Yamahata <yamahata at valinux co jp>
+ *                    VA Linux Systems Japan K.K.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "msi.h"
+#include "range.h"
+
+/* Eventually those constants should go to Linux pci_regs.h */
+#define PCI_MSI_PENDING_32      0x10
+#define PCI_MSI_PENDING_64      0x14
+
+/* PCI_MSI_ADDRESS_LO */
+#define PCI_MSI_ADDRESS_LO_MASK         (~0x3)
+
+/* If we get rid of cap allocator, we won't need those. */
+#define PCI_MSI_32_SIZEOF       0x0a
+#define PCI_MSI_64_SIZEOF       0x0e
+#define PCI_MSI_32M_SIZEOF      0x14
+#define PCI_MSI_64M_SIZEOF      0x18
+
+#define PCI_MSI_VECTORS_MAX     32
+
+/* Flag for interrupt controller to declare MSI/MSI-X support */
+bool msi_supported;
+
+/* If we get rid of cap allocator, we won't need this. */
+static inline uint8_t msi_cap_sizeof(uint16_t flags)
+{
+    switch (flags & (PCI_MSI_FLAGS_MASKBIT | PCI_MSI_FLAGS_64BIT)) {
+    case PCI_MSI_FLAGS_MASKBIT | PCI_MSI_FLAGS_64BIT:
+        return PCI_MSI_64M_SIZEOF;
+    case PCI_MSI_FLAGS_64BIT:
+        return PCI_MSI_64_SIZEOF;
+    case PCI_MSI_FLAGS_MASKBIT:
+        return PCI_MSI_32M_SIZEOF;
+    case 0:
+        return PCI_MSI_32_SIZEOF;
+    default:
+        abort();
+        break;
+    }
+    return 0;
+}
+
+//#define MSI_DEBUG
+
+#ifdef MSI_DEBUG
+# define MSI_DPRINTF(fmt, ...)                                          \
+    fprintf(stderr, "%s:%d " fmt, __func__, __LINE__, ## __VA_ARGS__)
+#else
+# define MSI_DPRINTF(fmt, ...)  do { } while (0)
+#endif
+#define MSI_DEV_PRINTF(dev, fmt, ...)                                   \
+    MSI_DPRINTF("%s:%x " fmt, (dev)->name, (dev)->devfn, ## __VA_ARGS__)
+
+static inline unsigned int msi_nr_vectors(uint16_t flags)
+{
+    return 1U <<
+        ((flags & PCI_MSI_FLAGS_QSIZE) >> (ffs(PCI_MSI_FLAGS_QSIZE) - 1));
+}
+
+static inline uint8_t msi_flags_off(const PCIDevice* dev)
+{
+    return dev->msi_cap + PCI_MSI_FLAGS;
+}
+
+static inline uint8_t msi_address_lo_off(const PCIDevice* dev)
+{
+    return dev->msi_cap + PCI_MSI_ADDRESS_LO;
+}
+
+static inline uint8_t msi_address_hi_off(const PCIDevice* dev)
+{
+    return dev->msi_cap + PCI_MSI_ADDRESS_HI;
+}
+
+static inline uint8_t msi_data_off(const PCIDevice* dev, bool msi64bit)
+{
+    return dev->msi_cap + (msi64bit ? PCI_MSI_DATA_64 : PCI_MSI_DATA_32);
+}
+
+static inline uint8_t msi_mask_off(const PCIDevice* dev, bool msi64bit)
+{
+    return dev->msi_cap + (msi64bit ? PCI_MSI_MASK_64 : PCI_MSI_MASK_32);
+}
+
+static inline uint8_t msi_pending_off(const PCIDevice* dev, bool msi64bit)
+{
+    return dev->msi_cap + (msi64bit ? PCI_MSI_PENDING_64 : PCI_MSI_PENDING_32);
+}
+
+/*
+ * Special API for POWER to configure the vectors through
+ * a side channel. Should never be used by devices.
+ */
+void msi_set_message(PCIDevice *dev, MSIMessage msg)
+{
+    uint16_t flags = pci_get_word(dev->config + msi_flags_off(dev));
+    bool msi64bit = flags & PCI_MSI_FLAGS_64BIT;
+
+    if (msi64bit) {
+        pci_set_quad(dev->config + msi_address_lo_off(dev), msg.address);
+    } else {
+        pci_set_long(dev->config + msi_address_lo_off(dev), msg.address);
+    }
+    pci_set_word(dev->config + msi_data_off(dev, msi64bit), msg.data);
+}
+
+MSIMessage msi_get_message(PCIDevice *dev, unsigned int vector)
+{
+    uint16_t flags = pci_get_word(dev->config + msi_flags_off(dev));
+    bool msi64bit = flags & PCI_MSI_FLAGS_64BIT;
+    unsigned int nr_vectors = msi_nr_vectors(flags);
+    MSIMessage msg;
+
+    assert(vector < nr_vectors);
+
+    if (msi64bit) {
+        msg.address = pci_get_quad(dev->config + msi_address_lo_off(dev));
+    } else {
+        msg.address = pci_get_long(dev->config + msi_address_lo_off(dev));
+    }
+
+    /* upper bit 31:16 is zero */
+    msg.data = pci_get_word(dev->config + msi_data_off(dev, msi64bit));
+    if (nr_vectors > 1) {
+        msg.data &= ~(nr_vectors - 1);
+        msg.data |= vector;
+    }
+
+    return msg;
+}
+
+bool msi_enabled(const PCIDevice *dev)
+{
+    return msi_present(dev) &&
+        (pci_get_word(dev->config + msi_flags_off(dev)) &
+         PCI_MSI_FLAGS_ENABLE);
+}
+
+int msi_init(struct PCIDevice *dev, uint8_t offset,
+             unsigned int nr_vectors, bool msi64bit, bool msi_per_vector_mask)
+{
+    unsigned int vectors_order;
+    uint16_t flags;
+    uint8_t cap_size;
+    int config_offset;
+
+    if (!msi_supported) {
+        return -ENOTSUP;
+    }
+
+    MSI_DEV_PRINTF(dev,
+                   "init offset: 0x%"PRIx8" vector: %"PRId8
+                   " 64bit %d mask %d\n",
+                   offset, nr_vectors, msi64bit, msi_per_vector_mask);
+
+    assert(!(nr_vectors & (nr_vectors - 1)));   /* power of 2 */
+    assert(nr_vectors > 0);
+    assert(nr_vectors <= PCI_MSI_VECTORS_MAX);
+    /* the nr of MSI vectors is up to 32 */
+    vectors_order = ffs(nr_vectors) - 1;
+
+    flags = vectors_order << (ffs(PCI_MSI_FLAGS_QMASK) - 1);
+    if (msi64bit) {
+        flags |= PCI_MSI_FLAGS_64BIT;
+    }
+    if (msi_per_vector_mask) {
+        flags |= PCI_MSI_FLAGS_MASKBIT;
+    }
+
+    cap_size = msi_cap_sizeof(flags);
+    config_offset = pci_add_capability(dev, PCI_CAP_ID_MSI, offset, cap_size);
+    if (config_offset < 0) {
+        return config_offset;
+    }
+
+    dev->msi_cap = config_offset;
+    dev->cap_present |= QEMU_PCI_CAP_MSI;
+
+    pci_set_word(dev->config + msi_flags_off(dev), flags);
+    pci_set_word(dev->wmask + msi_flags_off(dev),
+                 PCI_MSI_FLAGS_QSIZE | PCI_MSI_FLAGS_ENABLE);
+    pci_set_long(dev->wmask + msi_address_lo_off(dev),
+                 PCI_MSI_ADDRESS_LO_MASK);
+    if (msi64bit) {
+        pci_set_long(dev->wmask + msi_address_hi_off(dev), 0xffffffff);
+    }
+    pci_set_word(dev->wmask + msi_data_off(dev, msi64bit), 0xffff);
+
+    if (msi_per_vector_mask) {
+        /* Make mask bits 0 to nr_vectors - 1 writable. */
+        pci_set_long(dev->wmask + msi_mask_off(dev, msi64bit),
+                     0xffffffff >> (PCI_MSI_VECTORS_MAX - nr_vectors));
+    }
+    return config_offset;
+}
+
+void msi_uninit(struct PCIDevice *dev)
+{
+    uint16_t flags;
+    uint8_t cap_size;
+
+    if (!msi_present(dev)) {
+        return;
+    }
+    flags = pci_get_word(dev->config + msi_flags_off(dev));
+    cap_size = msi_cap_sizeof(flags);
+    pci_del_capability(dev, PCI_CAP_ID_MSI, cap_size);
+    dev->cap_present &= ~QEMU_PCI_CAP_MSI;
+
+    MSI_DEV_PRINTF(dev, "uninit\n");
+}
+
+void msi_reset(PCIDevice *dev)
+{
+    uint16_t flags;
+    bool msi64bit;
+
+    if (!msi_present(dev)) {
+        return;
+    }
+
+    flags = pci_get_word(dev->config + msi_flags_off(dev));
+    flags &= ~(PCI_MSI_FLAGS_QSIZE | PCI_MSI_FLAGS_ENABLE);
+    msi64bit = flags & PCI_MSI_FLAGS_64BIT;
+
+    pci_set_word(dev->config + msi_flags_off(dev), flags);
+    pci_set_long(dev->config + msi_address_lo_off(dev), 0);
+    if (msi64bit) {
+        pci_set_long(dev->config + msi_address_hi_off(dev), 0);
+    }
+    pci_set_word(dev->config + msi_data_off(dev, msi64bit), 0);
+    if (flags & PCI_MSI_FLAGS_MASKBIT) {
+        pci_set_long(dev->config + msi_mask_off(dev, msi64bit), 0);
+        pci_set_long(dev->config + msi_pending_off(dev, msi64bit), 0);
+    }
+    MSI_DEV_PRINTF(dev, "reset\n");
+}
+
+static bool msi_is_masked(const PCIDevice *dev, unsigned int vector)
+{
+    uint16_t flags = pci_get_word(dev->config + msi_flags_off(dev));
+    uint32_t mask;
+    assert(vector < PCI_MSI_VECTORS_MAX);
+
+    if (!(flags & PCI_MSI_FLAGS_MASKBIT)) {
+        return false;
+    }
+
+    mask = pci_get_long(dev->config +
+                        msi_mask_off(dev, flags & PCI_MSI_FLAGS_64BIT));
+    return mask & (1U << vector);
+}
+
+void msi_notify(PCIDevice *dev, unsigned int vector)
+{
+    uint16_t flags = pci_get_word(dev->config + msi_flags_off(dev));
+    bool msi64bit = flags & PCI_MSI_FLAGS_64BIT;
+    unsigned int nr_vectors = msi_nr_vectors(flags);
+    MSIMessage msg;
+
+    assert(vector < nr_vectors);
+    if (msi_is_masked(dev, vector)) {
+        assert(flags & PCI_MSI_FLAGS_MASKBIT);
+        pci_long_test_and_set_mask(
+            dev->config + msi_pending_off(dev, msi64bit), 1U << vector);
+        MSI_DEV_PRINTF(dev, "pending vector 0x%x\n", vector);
+        return;
+    }
+
+    msg = msi_get_message(dev, vector);
+
+    MSI_DEV_PRINTF(dev,
+                   "notify vector 0x%x"
+                   " address: 0x%"PRIx64" data: 0x%"PRIx32"\n",
+                   vector, msg.address, msg.data);
+    stl_le_phys(msg.address, msg.data);
+}
+
+/* Normally called by pci_default_write_config(). */
+void msi_write_config(PCIDevice *dev, uint32_t addr, uint32_t val, int len)
+{
+    uint16_t flags = pci_get_word(dev->config + msi_flags_off(dev));
+    bool msi64bit = flags & PCI_MSI_FLAGS_64BIT;
+    bool msi_per_vector_mask = flags & PCI_MSI_FLAGS_MASKBIT;
+    unsigned int nr_vectors;
+    uint8_t log_num_vecs;
+    uint8_t log_max_vecs;
+    unsigned int vector;
+    uint32_t pending;
+
+    if (!msi_present(dev) ||
+        !ranges_overlap(addr, len, dev->msi_cap, msi_cap_sizeof(flags))) {
+        return;
+    }
+
+#ifdef MSI_DEBUG
+    MSI_DEV_PRINTF(dev, "addr 0x%"PRIx32" val 0x%"PRIx32" len %d\n",
+                   addr, val, len);
+    MSI_DEV_PRINTF(dev, "ctrl: 0x%"PRIx16" address: 0x%"PRIx32,
+                   flags,
+                   pci_get_long(dev->config + msi_address_lo_off(dev)));
+    if (msi64bit) {
+        fprintf(stderr, " address-hi: 0x%"PRIx32,
+                pci_get_long(dev->config + msi_address_hi_off(dev)));
+    }
+    fprintf(stderr, " data: 0x%"PRIx16,
+            pci_get_word(dev->config + msi_data_off(dev, msi64bit)));
+    if (flags & PCI_MSI_FLAGS_MASKBIT) {
+        fprintf(stderr, " mask 0x%"PRIx32" pending 0x%"PRIx32,
+                pci_get_long(dev->config + msi_mask_off(dev, msi64bit)),
+                pci_get_long(dev->config + msi_pending_off(dev, msi64bit)));
+    }
+    fprintf(stderr, "\n");
+#endif
+
+    if (!(flags & PCI_MSI_FLAGS_ENABLE)) {
+        return;
+    }
+
+    /*
+     * Now MSI is enabled, clear INTx# interrupts.
+     * the driver is prohibited from writing enable bit to mask
+     * a service request. But the guest OS could do this.
+     * So we just discard the interrupts as moderate fallback.
+     *
+     * 6.8.3.3. Enabling Operation
+     *   While enabled for MSI or MSI-X operation, a function is prohibited
+     *   from using its INTx# pin (if implemented) to request
+     *   service (MSI, MSI-X, and INTx# are mutually exclusive).
+     */
+    pci_device_deassert_intx(dev);
+
+    /*
+     * nr_vectors might be set bigger than capable. So clamp it.
+     * This is not legal by spec, so we can do anything we like,
+     * just don't crash the host
+     */
+    log_num_vecs =
+        (flags & PCI_MSI_FLAGS_QSIZE) >> (ffs(PCI_MSI_FLAGS_QSIZE) - 1);
+    log_max_vecs =
+        (flags & PCI_MSI_FLAGS_QMASK) >> (ffs(PCI_MSI_FLAGS_QMASK) - 1);
+    if (log_num_vecs > log_max_vecs) {
+        flags &= ~PCI_MSI_FLAGS_QSIZE;
+        flags |= log_max_vecs << (ffs(PCI_MSI_FLAGS_QSIZE) - 1);
+        pci_set_word(dev->config + msi_flags_off(dev), flags);
+    }
+
+    if (!msi_per_vector_mask) {
+        /* if per vector masking isn't supported,
+           there is no pending interrupt. */
+        return;
+    }
+
+    nr_vectors = msi_nr_vectors(flags);
+
+    /* This will discard pending interrupts, if any. */
+    pending = pci_get_long(dev->config + msi_pending_off(dev, msi64bit));
+    pending &= 0xffffffff >> (PCI_MSI_VECTORS_MAX - nr_vectors);
+    pci_set_long(dev->config + msi_pending_off(dev, msi64bit), pending);
+
+    /* deliver pending interrupts which are unmasked */
+    for (vector = 0; vector < nr_vectors; ++vector) {
+        if (msi_is_masked(dev, vector) || !(pending & (1U << vector))) {
+            continue;
+        }
+
+        pci_long_test_and_clear_mask(
+            dev->config + msi_pending_off(dev, msi64bit), 1U << vector);
+        msi_notify(dev, vector);
+    }
+}
+
+unsigned int msi_nr_vectors_allocated(const PCIDevice *dev)
+{
+    uint16_t flags = pci_get_word(dev->config + msi_flags_off(dev));
+    return msi_nr_vectors(flags);
+}
diff --git a/hw/pci/msi.h b/hw/pci/msi.h
new file mode 100644
index 0000000..150b09a
--- /dev/null
+++ b/hw/pci/msi.h
@@ -0,0 +1,50 @@
+/*
+ * msi.h
+ *
+ * Copyright (c) 2010 Isaku Yamahata <yamahata at valinux co jp>
+ *                    VA Linux Systems Japan K.K.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef QEMU_MSI_H
+#define QEMU_MSI_H
+
+#include "qemu-common.h"
+#include "pci.h"
+
+struct MSIMessage {
+    uint64_t address;
+    uint32_t data;
+};
+
+extern bool msi_supported;
+
+void msi_set_message(PCIDevice *dev, MSIMessage msg);
+MSIMessage msi_get_message(PCIDevice *dev, unsigned int vector);
+bool msi_enabled(const PCIDevice *dev);
+int msi_init(struct PCIDevice *dev, uint8_t offset,
+             unsigned int nr_vectors, bool msi64bit, bool msi_per_vector_mask);
+void msi_uninit(struct PCIDevice *dev);
+void msi_reset(PCIDevice *dev);
+void msi_notify(PCIDevice *dev, unsigned int vector);
+void msi_write_config(PCIDevice *dev, uint32_t addr, uint32_t val, int len);
+unsigned int msi_nr_vectors_allocated(const PCIDevice *dev);
+
+static inline bool msi_present(const PCIDevice *dev)
+{
+    return dev->cap_present & QEMU_PCI_CAP_MSI;
+}
+
+#endif /* QEMU_MSI_H */
diff --git a/hw/pci/msix.c b/hw/pci/msix.c
new file mode 100644
index 0000000..136ef09
--- /dev/null
+++ b/hw/pci/msix.c
@@ -0,0 +1,562 @@
+/*
+ * MSI-X device support
+ *
+ * This module includes support for MSI-X in pci devices.
+ *
+ * Author: Michael S. Tsirkin <address@hidden>
+ *
+ *  Copyright (c) 2009, Red Hat Inc, Michael S. Tsirkin (address@hidden)
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2.  See
+ * the COPYING file in the top-level directory.
+ *
+ * Contributions after 2012-01-13 are licensed under the terms of the
+ * GNU GPL, version 2 or (at your option) any later version.
+ */
+
+#include "hw.h"
+#include "msi.h"
+#include "msix.h"
+#include "pci.h"
+#include "range.h"
+
+#define MSIX_CAP_LENGTH 12
+
+/* MSI enable bit and maskall bit are in byte 1 in FLAGS register */
+#define MSIX_CONTROL_OFFSET (PCI_MSIX_FLAGS + 1)
+#define MSIX_ENABLE_MASK (PCI_MSIX_FLAGS_ENABLE >> 8)
+#define MSIX_MASKALL_MASK (PCI_MSIX_FLAGS_MASKALL >> 8)
+
+static MSIMessage msix_get_message(PCIDevice *dev, unsigned vector)
+{
+    uint8_t *table_entry = dev->msix_table + vector * PCI_MSIX_ENTRY_SIZE;
+    MSIMessage msg;
+
+    msg.address = pci_get_quad(table_entry + PCI_MSIX_ENTRY_LOWER_ADDR);
+    msg.data = pci_get_long(table_entry + PCI_MSIX_ENTRY_DATA);
+    return msg;
+}
+
+/*
+ * Special API for POWER to configure the vectors through
+ * a side channel. Should never be used by devices.
+ */
+void msix_set_message(PCIDevice *dev, int vector, struct MSIMessage msg)
+{
+    uint8_t *table_entry = dev->msix_table + vector * PCI_MSIX_ENTRY_SIZE;
+
+    pci_set_quad(table_entry + PCI_MSIX_ENTRY_LOWER_ADDR, msg.address);
+    pci_set_long(table_entry + PCI_MSIX_ENTRY_DATA, msg.data);
+    table_entry[PCI_MSIX_ENTRY_VECTOR_CTRL] &= ~PCI_MSIX_ENTRY_CTRL_MASKBIT;
+}
+
+static uint8_t msix_pending_mask(int vector)
+{
+    return 1 << (vector % 8);
+}
+
+static uint8_t *msix_pending_byte(PCIDevice *dev, int vector)
+{
+    return dev->msix_pba + vector / 8;
+}
+
+static int msix_is_pending(PCIDevice *dev, int vector)
+{
+    return *msix_pending_byte(dev, vector) & msix_pending_mask(vector);
+}
+
+static void msix_set_pending(PCIDevice *dev, int vector)
+{
+    *msix_pending_byte(dev, vector) |= msix_pending_mask(vector);
+}
+
+static void msix_clr_pending(PCIDevice *dev, int vector)
+{
+    *msix_pending_byte(dev, vector) &= ~msix_pending_mask(vector);
+}
+
+static bool msix_vector_masked(PCIDevice *dev, int vector, bool fmask)
+{
+    unsigned offset = vector * PCI_MSIX_ENTRY_SIZE + 
PCI_MSIX_ENTRY_VECTOR_CTRL;
+    return fmask || dev->msix_table[offset] & PCI_MSIX_ENTRY_CTRL_MASKBIT;
+}
+
+static bool msix_is_masked(PCIDevice *dev, int vector)
+{
+    return msix_vector_masked(dev, vector, dev->msix_function_masked);
+}
+
+static void msix_fire_vector_notifier(PCIDevice *dev,
+                                      unsigned int vector, bool is_masked)
+{
+    MSIMessage msg;
+    int ret;
+
+    if (!dev->msix_vector_use_notifier) {
+        return;
+    }
+    if (is_masked) {
+        dev->msix_vector_release_notifier(dev, vector);
+    } else {
+        msg = msix_get_message(dev, vector);
+        ret = dev->msix_vector_use_notifier(dev, vector, msg);
+        assert(ret >= 0);
+    }
+}
+
+static void msix_handle_mask_update(PCIDevice *dev, int vector, bool 
was_masked)
+{
+    bool is_masked = msix_is_masked(dev, vector);
+
+    if (is_masked == was_masked) {
+        return;
+    }
+
+    msix_fire_vector_notifier(dev, vector, is_masked);
+
+    if (!is_masked && msix_is_pending(dev, vector)) {
+        msix_clr_pending(dev, vector);
+        msix_notify(dev, vector);
+    }
+}
+
+static void msix_update_function_masked(PCIDevice *dev)
+{
+    dev->msix_function_masked = !msix_enabled(dev) ||
+        (dev->config[dev->msix_cap + MSIX_CONTROL_OFFSET] & MSIX_MASKALL_MASK);
+}
+
+/* Handle MSI-X capability config write. */
+void msix_write_config(PCIDevice *dev, uint32_t addr,
+                       uint32_t val, int len)
+{
+    unsigned enable_pos = dev->msix_cap + MSIX_CONTROL_OFFSET;
+    int vector;
+    bool was_masked;
+
+    if (!msix_present(dev) || !range_covers_byte(addr, len, enable_pos)) {
+        return;
+    }
+
+    was_masked = dev->msix_function_masked;
+    msix_update_function_masked(dev);
+
+    if (!msix_enabled(dev)) {
+        return;
+    }
+
+    pci_device_deassert_intx(dev);
+
+    if (dev->msix_function_masked == was_masked) {
+        return;
+    }
+
+    for (vector = 0; vector < dev->msix_entries_nr; ++vector) {
+        msix_handle_mask_update(dev, vector,
+                                msix_vector_masked(dev, vector, was_masked));
+    }
+}
+
+static uint64_t msix_table_mmio_read(void *opaque, hwaddr addr,
+                                     unsigned size)
+{
+    PCIDevice *dev = opaque;
+
+    return pci_get_long(dev->msix_table + addr);
+}
+
+static void msix_table_mmio_write(void *opaque, hwaddr addr,
+                                  uint64_t val, unsigned size)
+{
+    PCIDevice *dev = opaque;
+    int vector = addr / PCI_MSIX_ENTRY_SIZE;
+    bool was_masked;
+
+    was_masked = msix_is_masked(dev, vector);
+    pci_set_long(dev->msix_table + addr, val);
+    msix_handle_mask_update(dev, vector, was_masked);
+}
+
+static const MemoryRegionOps msix_table_mmio_ops = {
+    .read = msix_table_mmio_read,
+    .write = msix_table_mmio_write,
+    /* TODO: MSIX should be LITTLE_ENDIAN. */
+    .endianness = DEVICE_NATIVE_ENDIAN,
+    .valid = {
+        .min_access_size = 4,
+        .max_access_size = 4,
+    },
+};
+
+static uint64_t msix_pba_mmio_read(void *opaque, hwaddr addr,
+                                   unsigned size)
+{
+    PCIDevice *dev = opaque;
+
+    return pci_get_long(dev->msix_pba + addr);
+}
+
+static const MemoryRegionOps msix_pba_mmio_ops = {
+    .read = msix_pba_mmio_read,
+    /* TODO: MSIX should be LITTLE_ENDIAN. */
+    .endianness = DEVICE_NATIVE_ENDIAN,
+    .valid = {
+        .min_access_size = 4,
+        .max_access_size = 4,
+    },
+};
+
+static void msix_mask_all(struct PCIDevice *dev, unsigned nentries)
+{
+    int vector;
+
+    for (vector = 0; vector < nentries; ++vector) {
+        unsigned offset =
+            vector * PCI_MSIX_ENTRY_SIZE + PCI_MSIX_ENTRY_VECTOR_CTRL;
+        bool was_masked = msix_is_masked(dev, vector);
+
+        dev->msix_table[offset] |= PCI_MSIX_ENTRY_CTRL_MASKBIT;
+        msix_handle_mask_update(dev, vector, was_masked);
+    }
+}
+
+/* Initialize the MSI-X structures */
+int msix_init(struct PCIDevice *dev, unsigned short nentries,
+              MemoryRegion *table_bar, uint8_t table_bar_nr,
+              unsigned table_offset, MemoryRegion *pba_bar,
+              uint8_t pba_bar_nr, unsigned pba_offset, uint8_t cap_pos)
+{
+    int cap;
+    unsigned table_size, pba_size;
+    uint8_t *config;
+
+    /* Nothing to do if MSI is not supported by interrupt controller */
+    if (!msi_supported) {
+        return -ENOTSUP;
+    }
+
+    if (nentries < 1 || nentries > PCI_MSIX_FLAGS_QSIZE + 1) {
+        return -EINVAL;
+    }
+
+    table_size = nentries * PCI_MSIX_ENTRY_SIZE;
+    pba_size = QEMU_ALIGN_UP(nentries, 64) / 8;
+
+    /* Sanity test: table & pba don't overlap, fit within BARs, min aligned */
+    if ((table_bar_nr == pba_bar_nr &&
+         ranges_overlap(table_offset, table_size, pba_offset, pba_size)) ||
+        table_offset + table_size > memory_region_size(table_bar) ||
+        pba_offset + pba_size > memory_region_size(pba_bar) ||
+        (table_offset | pba_offset) & PCI_MSIX_FLAGS_BIRMASK) {
+        return -EINVAL;
+    }
+
+    cap = pci_add_capability(dev, PCI_CAP_ID_MSIX, cap_pos, MSIX_CAP_LENGTH);
+    if (cap < 0) {
+        return cap;
+    }
+
+    dev->msix_cap = cap;
+    dev->cap_present |= QEMU_PCI_CAP_MSIX;
+    config = dev->config + cap;
+
+    pci_set_word(config + PCI_MSIX_FLAGS, nentries - 1);
+    dev->msix_entries_nr = nentries;
+    dev->msix_function_masked = true;
+
+    pci_set_long(config + PCI_MSIX_TABLE, table_offset | table_bar_nr);
+    pci_set_long(config + PCI_MSIX_PBA, pba_offset | pba_bar_nr);
+
+    /* Make flags bit writable. */
+    dev->wmask[cap + MSIX_CONTROL_OFFSET] |= MSIX_ENABLE_MASK |
+                                             MSIX_MASKALL_MASK;
+
+    dev->msix_table = g_malloc0(table_size);
+    dev->msix_pba = g_malloc0(pba_size);
+    dev->msix_entry_used = g_malloc0(nentries * sizeof *dev->msix_entry_used);
+
+    msix_mask_all(dev, nentries);
+
+    memory_region_init_io(&dev->msix_table_mmio, &msix_table_mmio_ops, dev,
+                          "msix-table", table_size);
+    memory_region_add_subregion(table_bar, table_offset, 
&dev->msix_table_mmio);
+    memory_region_init_io(&dev->msix_pba_mmio, &msix_pba_mmio_ops, dev,
+                          "msix-pba", pba_size);
+    memory_region_add_subregion(pba_bar, pba_offset, &dev->msix_pba_mmio);
+
+    return 0;
+}
+
+int msix_init_exclusive_bar(PCIDevice *dev, unsigned short nentries,
+                            uint8_t bar_nr)
+{
+    int ret;
+    char *name;
+
+    /*
+     * Migration compatibility dictates that this remains a 4k
+     * BAR with the vector table in the lower half and PBA in
+     * the upper half.  Do not use these elsewhere!
+     */
+#define MSIX_EXCLUSIVE_BAR_SIZE 4096
+#define MSIX_EXCLUSIVE_BAR_TABLE_OFFSET 0
+#define MSIX_EXCLUSIVE_BAR_PBA_OFFSET (MSIX_EXCLUSIVE_BAR_SIZE / 2)
+#define MSIX_EXCLUSIVE_CAP_OFFSET 0
+
+    if (nentries * PCI_MSIX_ENTRY_SIZE > MSIX_EXCLUSIVE_BAR_PBA_OFFSET) {
+        return -EINVAL;
+    }
+
+    name = g_strdup_printf("%s-msix", dev->name);
+    memory_region_init(&dev->msix_exclusive_bar, name, 
MSIX_EXCLUSIVE_BAR_SIZE);
+    g_free(name);
+
+    ret = msix_init(dev, nentries, &dev->msix_exclusive_bar, bar_nr,
+                    MSIX_EXCLUSIVE_BAR_TABLE_OFFSET, &dev->msix_exclusive_bar,
+                    bar_nr, MSIX_EXCLUSIVE_BAR_PBA_OFFSET,
+                    MSIX_EXCLUSIVE_CAP_OFFSET);
+    if (ret) {
+        memory_region_destroy(&dev->msix_exclusive_bar);
+        return ret;
+    }
+
+    pci_register_bar(dev, bar_nr, PCI_BASE_ADDRESS_SPACE_MEMORY,
+                     &dev->msix_exclusive_bar);
+
+    return 0;
+}
+
+static void msix_free_irq_entries(PCIDevice *dev)
+{
+    int vector;
+
+    for (vector = 0; vector < dev->msix_entries_nr; ++vector) {
+        dev->msix_entry_used[vector] = 0;
+        msix_clr_pending(dev, vector);
+    }
+}
+
+static void msix_clear_all_vectors(PCIDevice *dev)
+{
+    int vector;
+
+    for (vector = 0; vector < dev->msix_entries_nr; ++vector) {
+        msix_clr_pending(dev, vector);
+    }
+}
+
+/* Clean up resources for the device. */
+void msix_uninit(PCIDevice *dev, MemoryRegion *table_bar, MemoryRegion 
*pba_bar)
+{
+    if (!msix_present(dev)) {
+        return;
+    }
+    pci_del_capability(dev, PCI_CAP_ID_MSIX, MSIX_CAP_LENGTH);
+    dev->msix_cap = 0;
+    msix_free_irq_entries(dev);
+    dev->msix_entries_nr = 0;
+    memory_region_del_subregion(pba_bar, &dev->msix_pba_mmio);
+    memory_region_destroy(&dev->msix_pba_mmio);
+    g_free(dev->msix_pba);
+    dev->msix_pba = NULL;
+    memory_region_del_subregion(table_bar, &dev->msix_table_mmio);
+    memory_region_destroy(&dev->msix_table_mmio);
+    g_free(dev->msix_table);
+    dev->msix_table = NULL;
+    g_free(dev->msix_entry_used);
+    dev->msix_entry_used = NULL;
+    dev->cap_present &= ~QEMU_PCI_CAP_MSIX;
+}
+
+void msix_uninit_exclusive_bar(PCIDevice *dev)
+{
+    if (msix_present(dev)) {
+        msix_uninit(dev, &dev->msix_exclusive_bar, &dev->msix_exclusive_bar);
+        memory_region_destroy(&dev->msix_exclusive_bar);
+    }
+}
+
+void msix_save(PCIDevice *dev, QEMUFile *f)
+{
+    unsigned n = dev->msix_entries_nr;
+
+    if (!msix_present(dev)) {
+        return;
+    }
+
+    qemu_put_buffer(f, dev->msix_table, n * PCI_MSIX_ENTRY_SIZE);
+    qemu_put_buffer(f, dev->msix_pba, (n + 7) / 8);
+}
+
+/* Should be called after restoring the config space. */
+void msix_load(PCIDevice *dev, QEMUFile *f)
+{
+    unsigned n = dev->msix_entries_nr;
+    unsigned int vector;
+
+    if (!msix_present(dev)) {
+        return;
+    }
+
+    msix_clear_all_vectors(dev);
+    qemu_get_buffer(f, dev->msix_table, n * PCI_MSIX_ENTRY_SIZE);
+    qemu_get_buffer(f, dev->msix_pba, (n + 7) / 8);
+    msix_update_function_masked(dev);
+
+    for (vector = 0; vector < n; vector++) {
+        msix_handle_mask_update(dev, vector, true);
+    }
+}
+
+/* Does device support MSI-X? */
+int msix_present(PCIDevice *dev)
+{
+    return dev->cap_present & QEMU_PCI_CAP_MSIX;
+}
+
+/* Is MSI-X enabled? */
+int msix_enabled(PCIDevice *dev)
+{
+    return (dev->cap_present & QEMU_PCI_CAP_MSIX) &&
+        (dev->config[dev->msix_cap + MSIX_CONTROL_OFFSET] &
+         MSIX_ENABLE_MASK);
+}
+
+/* Send an MSI-X message */
+void msix_notify(PCIDevice *dev, unsigned vector)
+{
+    MSIMessage msg;
+
+    if (vector >= dev->msix_entries_nr || !dev->msix_entry_used[vector])
+        return;
+    if (msix_is_masked(dev, vector)) {
+        msix_set_pending(dev, vector);
+        return;
+    }
+
+    msg = msix_get_message(dev, vector);
+
+    stl_le_phys(msg.address, msg.data);
+}
+
+void msix_reset(PCIDevice *dev)
+{
+    if (!msix_present(dev)) {
+        return;
+    }
+    msix_clear_all_vectors(dev);
+    dev->config[dev->msix_cap + MSIX_CONTROL_OFFSET] &=
+           ~dev->wmask[dev->msix_cap + MSIX_CONTROL_OFFSET];
+    memset(dev->msix_table, 0, dev->msix_entries_nr * PCI_MSIX_ENTRY_SIZE);
+    memset(dev->msix_pba, 0, QEMU_ALIGN_UP(dev->msix_entries_nr, 64) / 8);
+    msix_mask_all(dev, dev->msix_entries_nr);
+}
+
+/* PCI spec suggests that devices make it possible for software to configure
+ * less vectors than supported by the device, but does not specify a standard
+ * mechanism for devices to do so.
+ *
+ * We support this by asking devices to declare vectors software is going to
+ * actually use, and checking this on the notification path. Devices that
+ * don't want to follow the spec suggestion can declare all vectors as used. */
+
+/* Mark vector as used. */
+int msix_vector_use(PCIDevice *dev, unsigned vector)
+{
+    if (vector >= dev->msix_entries_nr)
+        return -EINVAL;
+    dev->msix_entry_used[vector]++;
+    return 0;
+}
+
+/* Mark vector as unused. */
+void msix_vector_unuse(PCIDevice *dev, unsigned vector)
+{
+    if (vector >= dev->msix_entries_nr || !dev->msix_entry_used[vector]) {
+        return;
+    }
+    if (--dev->msix_entry_used[vector]) {
+        return;
+    }
+    msix_clr_pending(dev, vector);
+}
+
+void msix_unuse_all_vectors(PCIDevice *dev)
+{
+    if (!msix_present(dev)) {
+        return;
+    }
+    msix_free_irq_entries(dev);
+}
+
+unsigned int msix_nr_vectors_allocated(const PCIDevice *dev)
+{
+    return dev->msix_entries_nr;
+}
+
+static int msix_set_notifier_for_vector(PCIDevice *dev, unsigned int vector)
+{
+    MSIMessage msg;
+
+    if (msix_is_masked(dev, vector)) {
+        return 0;
+    }
+    msg = msix_get_message(dev, vector);
+    return dev->msix_vector_use_notifier(dev, vector, msg);
+}
+
+static void msix_unset_notifier_for_vector(PCIDevice *dev, unsigned int vector)
+{
+    if (msix_is_masked(dev, vector)) {
+        return;
+    }
+    dev->msix_vector_release_notifier(dev, vector);
+}
+
+int msix_set_vector_notifiers(PCIDevice *dev,
+                              MSIVectorUseNotifier use_notifier,
+                              MSIVectorReleaseNotifier release_notifier)
+{
+    int vector, ret;
+
+    assert(use_notifier && release_notifier);
+
+    dev->msix_vector_use_notifier = use_notifier;
+    dev->msix_vector_release_notifier = release_notifier;
+
+    if ((dev->config[dev->msix_cap + MSIX_CONTROL_OFFSET] &
+        (MSIX_ENABLE_MASK | MSIX_MASKALL_MASK)) == MSIX_ENABLE_MASK) {
+        for (vector = 0; vector < dev->msix_entries_nr; vector++) {
+            ret = msix_set_notifier_for_vector(dev, vector);
+            if (ret < 0) {
+                goto undo;
+            }
+        }
+    }
+    return 0;
+
+undo:
+    while (--vector >= 0) {
+        msix_unset_notifier_for_vector(dev, vector);
+    }
+    dev->msix_vector_use_notifier = NULL;
+    dev->msix_vector_release_notifier = NULL;
+    return ret;
+}
+
+void msix_unset_vector_notifiers(PCIDevice *dev)
+{
+    int vector;
+
+    assert(dev->msix_vector_use_notifier &&
+           dev->msix_vector_release_notifier);
+
+    if ((dev->config[dev->msix_cap + MSIX_CONTROL_OFFSET] &
+        (MSIX_ENABLE_MASK | MSIX_MASKALL_MASK)) == MSIX_ENABLE_MASK) {
+        for (vector = 0; vector < dev->msix_entries_nr; vector++) {
+            msix_unset_notifier_for_vector(dev, vector);
+        }
+    }
+    dev->msix_vector_use_notifier = NULL;
+    dev->msix_vector_release_notifier = NULL;
+}
diff --git a/hw/pci/msix.h b/hw/pci/msix.h
new file mode 100644
index 0000000..15211cb
--- /dev/null
+++ b/hw/pci/msix.h
@@ -0,0 +1,41 @@
+#ifndef QEMU_MSIX_H
+#define QEMU_MSIX_H
+
+#include "qemu-common.h"
+#include "pci.h"
+
+void msix_set_message(PCIDevice *dev, int vector, MSIMessage msg);
+int msix_init(PCIDevice *dev, unsigned short nentries,
+              MemoryRegion *table_bar, uint8_t table_bar_nr,
+              unsigned table_offset, MemoryRegion *pba_bar,
+              uint8_t pba_bar_nr, unsigned pba_offset, uint8_t cap_pos);
+int msix_init_exclusive_bar(PCIDevice *dev, unsigned short nentries,
+                            uint8_t bar_nr);
+
+void msix_write_config(PCIDevice *dev, uint32_t address, uint32_t val, int 
len);
+
+void msix_uninit(PCIDevice *dev, MemoryRegion *table_bar,
+                 MemoryRegion *pba_bar);
+void msix_uninit_exclusive_bar(PCIDevice *dev);
+
+unsigned int msix_nr_vectors_allocated(const PCIDevice *dev);
+
+void msix_save(PCIDevice *dev, QEMUFile *f);
+void msix_load(PCIDevice *dev, QEMUFile *f);
+
+int msix_enabled(PCIDevice *dev);
+int msix_present(PCIDevice *dev);
+
+int msix_vector_use(PCIDevice *dev, unsigned vector);
+void msix_vector_unuse(PCIDevice *dev, unsigned vector);
+void msix_unuse_all_vectors(PCIDevice *dev);
+
+void msix_notify(PCIDevice *dev, unsigned vector);
+
+void msix_reset(PCIDevice *dev);
+
+int msix_set_vector_notifiers(PCIDevice *dev,
+                              MSIVectorUseNotifier use_notifier,
+                              MSIVectorReleaseNotifier release_notifier);
+void msix_unset_vector_notifiers(PCIDevice *dev);
+#endif
diff --git a/hw/pci/pci-hotplug.c b/hw/pci/pci-hotplug.c
new file mode 100644
index 0000000..0ca5546
--- /dev/null
+++ b/hw/pci/pci-hotplug.c
@@ -0,0 +1,293 @@
+/*
+ * QEMU PCI hotplug support
+ *
+ * Copyright (c) 2004 Fabrice Bellard
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to 
deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 
FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "hw.h"
+#include "boards.h"
+#include "pci.h"
+#include "net.h"
+#include "pc.h"
+#include "monitor.h"
+#include "scsi.h"
+#include "virtio-blk.h"
+#include "qemu-config.h"
+#include "blockdev.h"
+#include "error.h"
+
+#if defined(TARGET_I386)
+static PCIDevice *qemu_pci_hot_add_nic(Monitor *mon,
+                                       const char *devaddr,
+                                       const char *opts_str)
+{
+    Error *local_err = NULL;
+    QemuOpts *opts;
+    PCIBus *bus;
+    int ret, devfn;
+
+    bus = pci_get_bus_devfn(&devfn, devaddr);
+    if (!bus) {
+        monitor_printf(mon, "Invalid PCI device address %s\n", devaddr);
+        return NULL;
+    }
+    if (!((BusState*)bus)->allow_hotplug) {
+        monitor_printf(mon, "PCI bus doesn't support hotplug\n");
+        return NULL;
+    }
+
+    opts = qemu_opts_parse(qemu_find_opts("net"), opts_str ? opts_str : "", 0);
+    if (!opts) {
+        return NULL;
+    }
+
+    qemu_opt_set(opts, "type", "nic");
+
+    ret = net_client_init(opts, 0, &local_err);
+    if (error_is_set(&local_err)) {
+        qerror_report_err(local_err);
+        error_free(local_err);
+        return NULL;
+    }
+    if (nd_table[ret].devaddr) {
+        monitor_printf(mon, "Parameter addr not supported\n");
+        return NULL;
+    }
+    return pci_nic_init(&nd_table[ret], "rtl8139", devaddr);
+}
+
+static int scsi_hot_add(Monitor *mon, DeviceState *adapter,
+                        DriveInfo *dinfo, int printinfo)
+{
+    SCSIBus *scsibus;
+    SCSIDevice *scsidev;
+
+    scsibus = (SCSIBus *)
+        object_dynamic_cast(OBJECT(QLIST_FIRST(&adapter->child_bus)),
+                            TYPE_SCSI_BUS);
+    if (!scsibus) {
+       error_report("Device is not a SCSI adapter");
+       return -1;
+    }
+
+    /*
+     * drive_init() tries to find a default for dinfo->unit.  Doesn't
+     * work at all for hotplug though as we assign the device to a
+     * specific bus instead of the first bus with spare scsi ids.
+     *
+     * Ditch the calculated value and reload from option string (if
+     * specified).
+     */
+    dinfo->unit = qemu_opt_get_number(dinfo->opts, "unit", -1);
+    dinfo->bus = scsibus->busnr;
+    scsidev = scsi_bus_legacy_add_drive(scsibus, dinfo->bdrv, dinfo->unit,
+                                        false, -1);
+    if (!scsidev) {
+        return -1;
+    }
+    dinfo->unit = scsidev->id;
+
+    if (printinfo)
+        monitor_printf(mon, "OK bus %d, unit %d\n",
+                       scsibus->busnr, scsidev->id);
+    return 0;
+}
+
+int pci_drive_hot_add(Monitor *mon, const QDict *qdict,
+                      DriveInfo *dinfo, int type)
+{
+    int dom, pci_bus;
+    unsigned slot;
+    PCIDevice *dev;
+    const char *pci_addr = qdict_get_str(qdict, "pci_addr");
+
+    switch (type) {
+    case IF_SCSI:
+        if (pci_read_devaddr(mon, pci_addr, &dom, &pci_bus, &slot)) {
+            goto err;
+        }
+        dev = pci_find_device(pci_find_root_bus(dom), pci_bus,
+                              PCI_DEVFN(slot, 0));
+        if (!dev) {
+            monitor_printf(mon, "no pci device with address %s\n", pci_addr);
+            goto err;
+        }
+        if (scsi_hot_add(mon, &dev->qdev, dinfo, 1) != 0) {
+            goto err;
+        }
+        break;
+    default:
+        monitor_printf(mon, "Can't hot-add drive to type %d\n", type);
+        goto err;
+    }
+
+    return 0;
+err:
+    return -1;
+}
+
+static PCIDevice *qemu_pci_hot_add_storage(Monitor *mon,
+                                           const char *devaddr,
+                                           const char *opts)
+{
+    PCIDevice *dev;
+    DriveInfo *dinfo = NULL;
+    int type = -1;
+    char buf[128];
+    PCIBus *bus;
+    int devfn;
+
+    if (get_param_value(buf, sizeof(buf), "if", opts)) {
+        if (!strcmp(buf, "scsi"))
+            type = IF_SCSI;
+        else if (!strcmp(buf, "virtio")) {
+            type = IF_VIRTIO;
+        } else {
+            monitor_printf(mon, "type %s not a hotpluggable PCI device.\n", 
buf);
+            return NULL;
+        }
+    } else {
+        monitor_printf(mon, "no if= specified\n");
+        return NULL;
+    }
+
+    if (get_param_value(buf, sizeof(buf), "file", opts)) {
+        dinfo = add_init_drive(opts);
+        if (!dinfo)
+            return NULL;
+        if (dinfo->devaddr) {
+            monitor_printf(mon, "Parameter addr not supported\n");
+            return NULL;
+        }
+    } else {
+        dinfo = NULL;
+    }
+
+    bus = pci_get_bus_devfn(&devfn, devaddr);
+    if (!bus) {
+        monitor_printf(mon, "Invalid PCI device address %s\n", devaddr);
+        return NULL;
+    }
+    if (!((BusState*)bus)->allow_hotplug) {
+        monitor_printf(mon, "PCI bus doesn't support hotplug\n");
+        return NULL;
+    }
+
+    switch (type) {
+    case IF_SCSI:
+        dev = pci_create(bus, devfn, "lsi53c895a");
+        if (qdev_init(&dev->qdev) < 0)
+            dev = NULL;
+        if (dev && dinfo) {
+            if (scsi_hot_add(mon, &dev->qdev, dinfo, 0) != 0) {
+                qdev_unplug(&dev->qdev, NULL);
+                dev = NULL;
+            }
+        }
+        break;
+    case IF_VIRTIO:
+        if (!dinfo) {
+            monitor_printf(mon, "virtio requires a backing file/device.\n");
+            return NULL;
+        }
+        dev = pci_create(bus, devfn, "virtio-blk-pci");
+        if (qdev_prop_set_drive(&dev->qdev, "drive", dinfo->bdrv) < 0) {
+            qdev_free(&dev->qdev);
+            dev = NULL;
+            break;
+        }
+        if (qdev_init(&dev->qdev) < 0)
+            dev = NULL;
+        break;
+    default:
+        dev = NULL;
+    }
+    return dev;
+}
+
+void pci_device_hot_add(Monitor *mon, const QDict *qdict)
+{
+    PCIDevice *dev = NULL;
+    const char *pci_addr = qdict_get_str(qdict, "pci_addr");
+    const char *type = qdict_get_str(qdict, "type");
+    const char *opts = qdict_get_try_str(qdict, "opts");
+
+    /* strip legacy tag */
+    if (!strncmp(pci_addr, "pci_addr=", 9)) {
+        pci_addr += 9;
+    }
+
+    if (!opts) {
+        opts = "";
+    }
+
+    if (!strcmp(pci_addr, "auto"))
+        pci_addr = NULL;
+
+    if (strcmp(type, "nic") == 0) {
+        dev = qemu_pci_hot_add_nic(mon, pci_addr, opts);
+    } else if (strcmp(type, "storage") == 0) {
+        dev = qemu_pci_hot_add_storage(mon, pci_addr, opts);
+    } else {
+        monitor_printf(mon, "invalid type: %s\n", type);
+    }
+
+    if (dev) {
+        monitor_printf(mon, "OK domain %d, bus %d, slot %d, function %d\n",
+                       pci_find_domain(dev->bus),
+                       pci_bus_num(dev->bus), PCI_SLOT(dev->devfn),
+                       PCI_FUNC(dev->devfn));
+    } else
+        monitor_printf(mon, "failed to add %s\n", opts);
+}
+#endif
+
+static int pci_device_hot_remove(Monitor *mon, const char *pci_addr)
+{
+    PCIDevice *d;
+    int dom, bus;
+    unsigned slot;
+    Error *local_err = NULL;
+
+    if (pci_read_devaddr(mon, pci_addr, &dom, &bus, &slot)) {
+        return -1;
+    }
+
+    d = pci_find_device(pci_find_root_bus(dom), bus, PCI_DEVFN(slot, 0));
+    if (!d) {
+        monitor_printf(mon, "slot %d empty\n", slot);
+        return -1;
+    }
+
+    qdev_unplug(&d->qdev, &local_err);
+    if (error_is_set(&local_err)) {
+        monitor_printf(mon, "%s\n", error_get_pretty(local_err));
+        error_free(local_err);
+        return -1;
+    }
+
+    return 0;
+}
+
+void do_pci_device_hot_remove(Monitor *mon, const QDict *qdict)
+{
+    pci_device_hot_remove(mon, qdict_get_str(qdict, "pci_addr"));
+}
diff --git a/hw/pci/pci-stub.c b/hw/pci/pci-stub.c
new file mode 100644
index 0000000..134c448
--- /dev/null
+++ b/hw/pci/pci-stub.c
@@ -0,0 +1,47 @@
+/*
+ * PCI stubs for platforms that don't support pci bus.
+ *
+ * Copyright (c) 2010 Isaku Yamahata <yamahata at valinux co jp>
+ *                    VA Linux Systems Japan K.K.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "sysemu.h"
+#include "monitor.h"
+#include "pci.h"
+#include "qmp-commands.h"
+
+PciInfoList *qmp_query_pci(Error **errp)
+{
+    error_set(errp, QERR_UNSUPPORTED);
+    return NULL;
+}
+
+static void pci_error_message(Monitor *mon)
+{
+    monitor_printf(mon, "PCI devices not supported\n");
+}
+
+int do_pcie_aer_inject_error(Monitor *mon,
+                             const QDict *qdict, QObject **ret_data)
+{
+    pci_error_message(mon);
+    return -ENOSYS;
+}
+
+void pcie_aer_inject_error_print(Monitor *mon, const QObject *data)
+{
+    pci_error_message(mon);
+}
diff --git a/hw/pci/pci.c b/hw/pci/pci.c
new file mode 100644
index 0000000..97a0cd7
--- /dev/null
+++ b/hw/pci/pci.c
@@ -0,0 +1,2168 @@
+/*
+ * QEMU PCI bus manager
+ *
+ * Copyright (c) 2004 Fabrice Bellard
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to 
deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 
FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+#include "hw.h"
+#include "pci.h"
+#include "pci_bridge.h"
+#include "pci_internals.h"
+#include "monitor.h"
+#include "net.h"
+#include "sysemu.h"
+#include "loader.h"
+#include "range.h"
+#include "qmp-commands.h"
+#include "msi.h"
+#include "msix.h"
+#include "exec-memory.h"
+
+//#define DEBUG_PCI
+#ifdef DEBUG_PCI
+# define PCI_DPRINTF(format, ...)       printf(format, ## __VA_ARGS__)
+#else
+# define PCI_DPRINTF(format, ...)       do { } while (0)
+#endif
+
+static void pcibus_dev_print(Monitor *mon, DeviceState *dev, int indent);
+static char *pcibus_get_dev_path(DeviceState *dev);
+static char *pcibus_get_fw_dev_path(DeviceState *dev);
+static int pcibus_reset(BusState *qbus);
+
+static Property pci_props[] = {
+    DEFINE_PROP_PCI_DEVFN("addr", PCIDevice, devfn, -1),
+    DEFINE_PROP_STRING("romfile", PCIDevice, romfile),
+    DEFINE_PROP_UINT32("rombar",  PCIDevice, rom_bar, 1),
+    DEFINE_PROP_BIT("multifunction", PCIDevice, cap_present,
+                    QEMU_PCI_CAP_MULTIFUNCTION_BITNR, false),
+    DEFINE_PROP_BIT("command_serr_enable", PCIDevice, cap_present,
+                    QEMU_PCI_CAP_SERR_BITNR, true),
+    DEFINE_PROP_END_OF_LIST()
+};
+
+static void pci_bus_class_init(ObjectClass *klass, void *data)
+{
+    BusClass *k = BUS_CLASS(klass);
+
+    k->print_dev = pcibus_dev_print;
+    k->get_dev_path = pcibus_get_dev_path;
+    k->get_fw_dev_path = pcibus_get_fw_dev_path;
+    k->reset = pcibus_reset;
+}
+
+static const TypeInfo pci_bus_info = {
+    .name = TYPE_PCI_BUS,
+    .parent = TYPE_BUS,
+    .instance_size = sizeof(PCIBus),
+    .class_init = pci_bus_class_init,
+};
+
+static PCIBus *pci_find_bus_nr(PCIBus *bus, int bus_num);
+static void pci_update_mappings(PCIDevice *d);
+static void pci_set_irq(void *opaque, int irq_num, int level);
+static int pci_add_option_rom(PCIDevice *pdev, bool is_default_rom);
+static void pci_del_option_rom(PCIDevice *pdev);
+
+static uint16_t pci_default_sub_vendor_id = PCI_SUBVENDOR_ID_REDHAT_QUMRANET;
+static uint16_t pci_default_sub_device_id = PCI_SUBDEVICE_ID_QEMU;
+
+struct PCIHostBus {
+    int domain;
+    struct PCIBus *bus;
+    QLIST_ENTRY(PCIHostBus) next;
+};
+static QLIST_HEAD(, PCIHostBus) host_buses;
+
+static const VMStateDescription vmstate_pcibus = {
+    .name = "PCIBUS",
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .minimum_version_id_old = 1,
+    .fields      = (VMStateField []) {
+        VMSTATE_INT32_EQUAL(nirq, PCIBus),
+        VMSTATE_VARRAY_INT32(irq_count, PCIBus, nirq, 0, vmstate_info_int32, 
int32_t),
+        VMSTATE_END_OF_LIST()
+    }
+};
+static int pci_bar(PCIDevice *d, int reg)
+{
+    uint8_t type;
+
+    if (reg != PCI_ROM_SLOT)
+        return PCI_BASE_ADDRESS_0 + reg * 4;
+
+    type = d->config[PCI_HEADER_TYPE] & ~PCI_HEADER_TYPE_MULTI_FUNCTION;
+    return type == PCI_HEADER_TYPE_BRIDGE ? PCI_ROM_ADDRESS1 : PCI_ROM_ADDRESS;
+}
+
+static inline int pci_irq_state(PCIDevice *d, int irq_num)
+{
+       return (d->irq_state >> irq_num) & 0x1;
+}
+
+static inline void pci_set_irq_state(PCIDevice *d, int irq_num, int level)
+{
+       d->irq_state &= ~(0x1 << irq_num);
+       d->irq_state |= level << irq_num;
+}
+
+static void pci_change_irq_level(PCIDevice *pci_dev, int irq_num, int change)
+{
+    PCIBus *bus;
+    for (;;) {
+        bus = pci_dev->bus;
+        irq_num = bus->map_irq(pci_dev, irq_num);
+        if (bus->set_irq)
+            break;
+        pci_dev = bus->parent_dev;
+    }
+    bus->irq_count[irq_num] += change;
+    bus->set_irq(bus->irq_opaque, irq_num, bus->irq_count[irq_num] != 0);
+}
+
+int pci_bus_get_irq_level(PCIBus *bus, int irq_num)
+{
+    assert(irq_num >= 0);
+    assert(irq_num < bus->nirq);
+    return !!bus->irq_count[irq_num];
+}
+
+/* Update interrupt status bit in config space on interrupt
+ * state change. */
+static void pci_update_irq_status(PCIDevice *dev)
+{
+    if (dev->irq_state) {
+        dev->config[PCI_STATUS] |= PCI_STATUS_INTERRUPT;
+    } else {
+        dev->config[PCI_STATUS] &= ~PCI_STATUS_INTERRUPT;
+    }
+}
+
+void pci_device_deassert_intx(PCIDevice *dev)
+{
+    int i;
+    for (i = 0; i < PCI_NUM_PINS; ++i) {
+        qemu_set_irq(dev->irq[i], 0);
+    }
+}
+
+/*
+ * This function is called on #RST and FLR.
+ * FLR if PCI_EXP_DEVCTL_BCR_FLR is set
+ */
+void pci_device_reset(PCIDevice *dev)
+{
+    int r;
+
+    qdev_reset_all(&dev->qdev);
+
+    dev->irq_state = 0;
+    pci_update_irq_status(dev);
+    pci_device_deassert_intx(dev);
+    /* Clear all writable bits */
+    pci_word_test_and_clear_mask(dev->config + PCI_COMMAND,
+                                 pci_get_word(dev->wmask + PCI_COMMAND) |
+                                 pci_get_word(dev->w1cmask + PCI_COMMAND));
+    pci_word_test_and_clear_mask(dev->config + PCI_STATUS,
+                                 pci_get_word(dev->wmask + PCI_STATUS) |
+                                 pci_get_word(dev->w1cmask + PCI_STATUS));
+    dev->config[PCI_CACHE_LINE_SIZE] = 0x0;
+    dev->config[PCI_INTERRUPT_LINE] = 0x0;
+    for (r = 0; r < PCI_NUM_REGIONS; ++r) {
+        PCIIORegion *region = &dev->io_regions[r];
+        if (!region->size) {
+            continue;
+        }
+
+        if (!(region->type & PCI_BASE_ADDRESS_SPACE_IO) &&
+            region->type & PCI_BASE_ADDRESS_MEM_TYPE_64) {
+            pci_set_quad(dev->config + pci_bar(dev, r), region->type);
+        } else {
+            pci_set_long(dev->config + pci_bar(dev, r), region->type);
+        }
+    }
+    pci_update_mappings(dev);
+
+    msi_reset(dev);
+    msix_reset(dev);
+}
+
+/*
+ * Trigger pci bus reset under a given bus.
+ * To be called on RST# assert.
+ */
+void pci_bus_reset(PCIBus *bus)
+{
+    int i;
+
+    for (i = 0; i < bus->nirq; i++) {
+        bus->irq_count[i] = 0;
+    }
+    for (i = 0; i < ARRAY_SIZE(bus->devices); ++i) {
+        if (bus->devices[i]) {
+            pci_device_reset(bus->devices[i]);
+        }
+    }
+}
+
+static int pcibus_reset(BusState *qbus)
+{
+    pci_bus_reset(DO_UPCAST(PCIBus, qbus, qbus));
+
+    /* topology traverse is done by pci_bus_reset().
+       Tell qbus/qdev walker not to traverse the tree */
+    return 1;
+}
+
+static void pci_host_bus_register(int domain, PCIBus *bus)
+{
+    struct PCIHostBus *host;
+    host = g_malloc0(sizeof(*host));
+    host->domain = domain;
+    host->bus = bus;
+    QLIST_INSERT_HEAD(&host_buses, host, next);
+}
+
+PCIBus *pci_find_root_bus(int domain)
+{
+    struct PCIHostBus *host;
+
+    QLIST_FOREACH(host, &host_buses, next) {
+        if (host->domain == domain) {
+            return host->bus;
+        }
+    }
+
+    return NULL;
+}
+
+int pci_find_domain(const PCIBus *bus)
+{
+    PCIDevice *d;
+    struct PCIHostBus *host;
+
+    /* obtain root bus */
+    while ((d = bus->parent_dev) != NULL) {
+        bus = d->bus;
+    }
+
+    QLIST_FOREACH(host, &host_buses, next) {
+        if (host->bus == bus) {
+            return host->domain;
+        }
+    }
+
+    abort();    /* should not be reached */
+    return -1;
+}
+
+void pci_bus_new_inplace(PCIBus *bus, DeviceState *parent,
+                         const char *name,
+                         MemoryRegion *address_space_mem,
+                         MemoryRegion *address_space_io,
+                         uint8_t devfn_min)
+{
+    qbus_create_inplace(&bus->qbus, TYPE_PCI_BUS, parent, name);
+    assert(PCI_FUNC(devfn_min) == 0);
+    bus->devfn_min = devfn_min;
+    bus->address_space_mem = address_space_mem;
+    bus->address_space_io = address_space_io;
+
+    /* host bridge */
+    QLIST_INIT(&bus->child);
+    pci_host_bus_register(0, bus); /* for now only pci domain 0 is supported */
+
+    vmstate_register(NULL, -1, &vmstate_pcibus, bus);
+}
+
+PCIBus *pci_bus_new(DeviceState *parent, const char *name,
+                    MemoryRegion *address_space_mem,
+                    MemoryRegion *address_space_io,
+                    uint8_t devfn_min)
+{
+    PCIBus *bus;
+
+    bus = g_malloc0(sizeof(*bus));
+    pci_bus_new_inplace(bus, parent, name, address_space_mem,
+                        address_space_io, devfn_min);
+    OBJECT(bus)->free = g_free;
+    return bus;
+}
+
+void pci_bus_irqs(PCIBus *bus, pci_set_irq_fn set_irq, pci_map_irq_fn map_irq,
+                  void *irq_opaque, int nirq)
+{
+    bus->set_irq = set_irq;
+    bus->map_irq = map_irq;
+    bus->irq_opaque = irq_opaque;
+    bus->nirq = nirq;
+    bus->irq_count = g_malloc0(nirq * sizeof(bus->irq_count[0]));
+}
+
+void pci_bus_hotplug(PCIBus *bus, pci_hotplug_fn hotplug, DeviceState *qdev)
+{
+    bus->qbus.allow_hotplug = 1;
+    bus->hotplug = hotplug;
+    bus->hotplug_qdev = qdev;
+}
+
+PCIBus *pci_register_bus(DeviceState *parent, const char *name,
+                         pci_set_irq_fn set_irq, pci_map_irq_fn map_irq,
+                         void *irq_opaque,
+                         MemoryRegion *address_space_mem,
+                         MemoryRegion *address_space_io,
+                         uint8_t devfn_min, int nirq)
+{
+    PCIBus *bus;
+
+    bus = pci_bus_new(parent, name, address_space_mem,
+                      address_space_io, devfn_min);
+    pci_bus_irqs(bus, set_irq, map_irq, irq_opaque, nirq);
+    return bus;
+}
+
+int pci_bus_num(PCIBus *s)
+{
+    if (!s->parent_dev)
+        return 0;       /* pci host bridge */
+    return s->parent_dev->config[PCI_SECONDARY_BUS];
+}
+
+static int get_pci_config_device(QEMUFile *f, void *pv, size_t size)
+{
+    PCIDevice *s = container_of(pv, PCIDevice, config);
+    uint8_t *config;
+    int i;
+
+    assert(size == pci_config_size(s));
+    config = g_malloc(size);
+
+    qemu_get_buffer(f, config, size);
+    for (i = 0; i < size; ++i) {
+        if ((config[i] ^ s->config[i]) &
+            s->cmask[i] & ~s->wmask[i] & ~s->w1cmask[i]) {
+            g_free(config);
+            return -EINVAL;
+        }
+    }
+    memcpy(s->config, config, size);
+
+    pci_update_mappings(s);
+
+    memory_region_set_enabled(&s->bus_master_enable_region,
+                              pci_get_word(s->config + PCI_COMMAND)
+                              & PCI_COMMAND_MASTER);
+
+    g_free(config);
+    return 0;
+}
+
+/* just put buffer */
+static void put_pci_config_device(QEMUFile *f, void *pv, size_t size)
+{
+    const uint8_t **v = pv;
+    assert(size == pci_config_size(container_of(pv, PCIDevice, config)));
+    qemu_put_buffer(f, *v, size);
+}
+
+static VMStateInfo vmstate_info_pci_config = {
+    .name = "pci config",
+    .get  = get_pci_config_device,
+    .put  = put_pci_config_device,
+};
+
+static int get_pci_irq_state(QEMUFile *f, void *pv, size_t size)
+{
+    PCIDevice *s = container_of(pv, PCIDevice, irq_state);
+    uint32_t irq_state[PCI_NUM_PINS];
+    int i;
+    for (i = 0; i < PCI_NUM_PINS; ++i) {
+        irq_state[i] = qemu_get_be32(f);
+        if (irq_state[i] != 0x1 && irq_state[i] != 0) {
+            fprintf(stderr, "irq state %d: must be 0 or 1.\n",
+                    irq_state[i]);
+            return -EINVAL;
+        }
+    }
+
+    for (i = 0; i < PCI_NUM_PINS; ++i) {
+        pci_set_irq_state(s, i, irq_state[i]);
+    }
+
+    return 0;
+}
+
+static void put_pci_irq_state(QEMUFile *f, void *pv, size_t size)
+{
+    int i;
+    PCIDevice *s = container_of(pv, PCIDevice, irq_state);
+
+    for (i = 0; i < PCI_NUM_PINS; ++i) {
+        qemu_put_be32(f, pci_irq_state(s, i));
+    }
+}
+
+static VMStateInfo vmstate_info_pci_irq_state = {
+    .name = "pci irq state",
+    .get  = get_pci_irq_state,
+    .put  = put_pci_irq_state,
+};
+
+const VMStateDescription vmstate_pci_device = {
+    .name = "PCIDevice",
+    .version_id = 2,
+    .minimum_version_id = 1,
+    .minimum_version_id_old = 1,
+    .fields      = (VMStateField []) {
+        VMSTATE_INT32_LE(version_id, PCIDevice),
+        VMSTATE_BUFFER_UNSAFE_INFO(config, PCIDevice, 0,
+                                   vmstate_info_pci_config,
+                                   PCI_CONFIG_SPACE_SIZE),
+        VMSTATE_BUFFER_UNSAFE_INFO(irq_state, PCIDevice, 2,
+                                  vmstate_info_pci_irq_state,
+                                  PCI_NUM_PINS * sizeof(int32_t)),
+        VMSTATE_END_OF_LIST()
+    }
+};
+
+const VMStateDescription vmstate_pcie_device = {
+    .name = "PCIEDevice",
+    .version_id = 2,
+    .minimum_version_id = 1,
+    .minimum_version_id_old = 1,
+    .fields      = (VMStateField []) {
+        VMSTATE_INT32_LE(version_id, PCIDevice),
+        VMSTATE_BUFFER_UNSAFE_INFO(config, PCIDevice, 0,
+                                   vmstate_info_pci_config,
+                                   PCIE_CONFIG_SPACE_SIZE),
+        VMSTATE_BUFFER_UNSAFE_INFO(irq_state, PCIDevice, 2,
+                                  vmstate_info_pci_irq_state,
+                                  PCI_NUM_PINS * sizeof(int32_t)),
+        VMSTATE_END_OF_LIST()
+    }
+};
+
+static inline const VMStateDescription *pci_get_vmstate(PCIDevice *s)
+{
+    return pci_is_express(s) ? &vmstate_pcie_device : &vmstate_pci_device;
+}
+
+void pci_device_save(PCIDevice *s, QEMUFile *f)
+{
+    /* Clear interrupt status bit: it is implicit
+     * in irq_state which we are saving.
+     * This makes us compatible with old devices
+     * which never set or clear this bit. */
+    s->config[PCI_STATUS] &= ~PCI_STATUS_INTERRUPT;
+    vmstate_save_state(f, pci_get_vmstate(s), s);
+    /* Restore the interrupt status bit. */
+    pci_update_irq_status(s);
+}
+
+int pci_device_load(PCIDevice *s, QEMUFile *f)
+{
+    int ret;
+    ret = vmstate_load_state(f, pci_get_vmstate(s), s, s->version_id);
+    /* Restore the interrupt status bit. */
+    pci_update_irq_status(s);
+    return ret;
+}
+
+static void pci_set_default_subsystem_id(PCIDevice *pci_dev)
+{
+    pci_set_word(pci_dev->config + PCI_SUBSYSTEM_VENDOR_ID,
+                 pci_default_sub_vendor_id);
+    pci_set_word(pci_dev->config + PCI_SUBSYSTEM_ID,
+                 pci_default_sub_device_id);
+}
+
+/*
+ * Parse [[<domain>:]<bus>:]<slot>, return -1 on error if funcp == NULL
+ *       [[<domain>:]<bus>:]<slot>.<func>, return -1 on error
+ */
+static int pci_parse_devaddr(const char *addr, int *domp, int *busp,
+                      unsigned int *slotp, unsigned int *funcp)
+{
+    const char *p;
+    char *e;
+    unsigned long val;
+    unsigned long dom = 0, bus = 0;
+    unsigned int slot = 0;
+    unsigned int func = 0;
+
+    p = addr;
+    val = strtoul(p, &e, 16);
+    if (e == p)
+       return -1;
+    if (*e == ':') {
+       bus = val;
+       p = e + 1;
+       val = strtoul(p, &e, 16);
+       if (e == p)
+           return -1;
+       if (*e == ':') {
+           dom = bus;
+           bus = val;
+           p = e + 1;
+           val = strtoul(p, &e, 16);
+           if (e == p)
+               return -1;
+       }
+    }
+
+    slot = val;
+
+    if (funcp != NULL) {
+        if (*e != '.')
+            return -1;
+
+        p = e + 1;
+        val = strtoul(p, &e, 16);
+        if (e == p)
+            return -1;
+
+        func = val;
+    }
+
+    /* if funcp == NULL func is 0 */
+    if (dom > 0xffff || bus > 0xff || slot > 0x1f || func > 7)
+       return -1;
+
+    if (*e)
+       return -1;
+
+    *domp = dom;
+    *busp = bus;
+    *slotp = slot;
+    if (funcp != NULL)
+        *funcp = func;
+    return 0;
+}
+
+int pci_read_devaddr(Monitor *mon, const char *addr, int *domp, int *busp,
+                     unsigned *slotp)
+{
+    /* strip legacy tag */
+    if (!strncmp(addr, "pci_addr=", 9)) {
+        addr += 9;
+    }
+    if (pci_parse_devaddr(addr, domp, busp, slotp, NULL)) {
+        monitor_printf(mon, "Invalid pci address\n");
+        return -1;
+    }
+    return 0;
+}
+
+PCIBus *pci_get_bus_devfn(int *devfnp, const char *devaddr)
+{
+    int dom, bus;
+    unsigned slot;
+
+    if (!devaddr) {
+        *devfnp = -1;
+        return pci_find_bus_nr(pci_find_root_bus(0), 0);
+    }
+
+    if (pci_parse_devaddr(devaddr, &dom, &bus, &slot, NULL) < 0) {
+        return NULL;
+    }
+
+    *devfnp = PCI_DEVFN(slot, 0);
+    return pci_find_bus_nr(pci_find_root_bus(dom), bus);
+}
+
+static void pci_init_cmask(PCIDevice *dev)
+{
+    pci_set_word(dev->cmask + PCI_VENDOR_ID, 0xffff);
+    pci_set_word(dev->cmask + PCI_DEVICE_ID, 0xffff);
+    dev->cmask[PCI_STATUS] = PCI_STATUS_CAP_LIST;
+    dev->cmask[PCI_REVISION_ID] = 0xff;
+    dev->cmask[PCI_CLASS_PROG] = 0xff;
+    pci_set_word(dev->cmask + PCI_CLASS_DEVICE, 0xffff);
+    dev->cmask[PCI_HEADER_TYPE] = 0xff;
+    dev->cmask[PCI_CAPABILITY_LIST] = 0xff;
+}
+
+static void pci_init_wmask(PCIDevice *dev)
+{
+    int config_size = pci_config_size(dev);
+
+    dev->wmask[PCI_CACHE_LINE_SIZE] = 0xff;
+    dev->wmask[PCI_INTERRUPT_LINE] = 0xff;
+    pci_set_word(dev->wmask + PCI_COMMAND,
+                 PCI_COMMAND_IO | PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER |
+                 PCI_COMMAND_INTX_DISABLE);
+    if (dev->cap_present & QEMU_PCI_CAP_SERR) {
+        pci_word_test_and_set_mask(dev->wmask + PCI_COMMAND, PCI_COMMAND_SERR);
+    }
+
+    memset(dev->wmask + PCI_CONFIG_HEADER_SIZE, 0xff,
+           config_size - PCI_CONFIG_HEADER_SIZE);
+}
+
+static void pci_init_w1cmask(PCIDevice *dev)
+{
+    /*
+     * Note: It's okay to set w1cmask even for readonly bits as
+     * long as their value is hardwired to 0.
+     */
+    pci_set_word(dev->w1cmask + PCI_STATUS,
+                 PCI_STATUS_PARITY | PCI_STATUS_SIG_TARGET_ABORT |
+                 PCI_STATUS_REC_TARGET_ABORT | PCI_STATUS_REC_MASTER_ABORT |
+                 PCI_STATUS_SIG_SYSTEM_ERROR | PCI_STATUS_DETECTED_PARITY);
+}
+
+static void pci_init_mask_bridge(PCIDevice *d)
+{
+    /* PCI_PRIMARY_BUS, PCI_SECONDARY_BUS, PCI_SUBORDINATE_BUS and
+       PCI_SEC_LETENCY_TIMER */
+    memset(d->wmask + PCI_PRIMARY_BUS, 0xff, 4);
+
+    /* base and limit */
+    d->wmask[PCI_IO_BASE] = PCI_IO_RANGE_MASK & 0xff;
+    d->wmask[PCI_IO_LIMIT] = PCI_IO_RANGE_MASK & 0xff;
+    pci_set_word(d->wmask + PCI_MEMORY_BASE,
+                 PCI_MEMORY_RANGE_MASK & 0xffff);
+    pci_set_word(d->wmask + PCI_MEMORY_LIMIT,
+                 PCI_MEMORY_RANGE_MASK & 0xffff);
+    pci_set_word(d->wmask + PCI_PREF_MEMORY_BASE,
+                 PCI_PREF_RANGE_MASK & 0xffff);
+    pci_set_word(d->wmask + PCI_PREF_MEMORY_LIMIT,
+                 PCI_PREF_RANGE_MASK & 0xffff);
+
+    /* PCI_PREF_BASE_UPPER32 and PCI_PREF_LIMIT_UPPER32 */
+    memset(d->wmask + PCI_PREF_BASE_UPPER32, 0xff, 8);
+
+    /* Supported memory and i/o types */
+    d->config[PCI_IO_BASE] |= PCI_IO_RANGE_TYPE_16;
+    d->config[PCI_IO_LIMIT] |= PCI_IO_RANGE_TYPE_16;
+    pci_word_test_and_set_mask(d->config + PCI_PREF_MEMORY_BASE,
+                               PCI_PREF_RANGE_TYPE_64);
+    pci_word_test_and_set_mask(d->config + PCI_PREF_MEMORY_LIMIT,
+                               PCI_PREF_RANGE_TYPE_64);
+
+/* TODO: add this define to pci_regs.h in linux and then in qemu. */
+#define  PCI_BRIDGE_CTL_VGA_16BIT      0x10    /* VGA 16-bit decode */
+#define  PCI_BRIDGE_CTL_DISCARD                0x100   /* Primary discard 
timer */
+#define  PCI_BRIDGE_CTL_SEC_DISCARD    0x200   /* Secondary discard timer */
+#define  PCI_BRIDGE_CTL_DISCARD_STATUS 0x400   /* Discard timer status */
+#define  PCI_BRIDGE_CTL_DISCARD_SERR   0x800   /* Discard timer SERR# enable */
+    pci_set_word(d->wmask + PCI_BRIDGE_CONTROL,
+                 PCI_BRIDGE_CTL_PARITY |
+                 PCI_BRIDGE_CTL_SERR |
+                 PCI_BRIDGE_CTL_ISA |
+                 PCI_BRIDGE_CTL_VGA |
+                 PCI_BRIDGE_CTL_VGA_16BIT |
+                 PCI_BRIDGE_CTL_MASTER_ABORT |
+                 PCI_BRIDGE_CTL_BUS_RESET |
+                 PCI_BRIDGE_CTL_FAST_BACK |
+                 PCI_BRIDGE_CTL_DISCARD |
+                 PCI_BRIDGE_CTL_SEC_DISCARD |
+                 PCI_BRIDGE_CTL_DISCARD_SERR);
+    /* Below does not do anything as we never set this bit, put here for
+     * completeness. */
+    pci_set_word(d->w1cmask + PCI_BRIDGE_CONTROL,
+                 PCI_BRIDGE_CTL_DISCARD_STATUS);
+    d->cmask[PCI_IO_BASE] |= PCI_IO_RANGE_TYPE_MASK;
+    d->cmask[PCI_IO_LIMIT] |= PCI_IO_RANGE_TYPE_MASK;
+    pci_word_test_and_set_mask(d->cmask + PCI_PREF_MEMORY_BASE,
+                               PCI_PREF_RANGE_TYPE_MASK);
+    pci_word_test_and_set_mask(d->cmask + PCI_PREF_MEMORY_LIMIT,
+                               PCI_PREF_RANGE_TYPE_MASK);
+}
+
+static int pci_init_multifunction(PCIBus *bus, PCIDevice *dev)
+{
+    uint8_t slot = PCI_SLOT(dev->devfn);
+    uint8_t func;
+
+    if (dev->cap_present & QEMU_PCI_CAP_MULTIFUNCTION) {
+        dev->config[PCI_HEADER_TYPE] |= PCI_HEADER_TYPE_MULTI_FUNCTION;
+    }
+
+    /*
+     * multifunction bit is interpreted in two ways as follows.
+     *   - all functions must set the bit to 1.
+     *     Example: Intel X53
+     *   - function 0 must set the bit, but the rest function (> 0)
+     *     is allowed to leave the bit to 0.
+     *     Example: PIIX3(also in qemu), PIIX4(also in qemu), ICH10,
+     *
+     * So OS (at least Linux) checks the bit of only function 0,
+     * and doesn't see the bit of function > 0.
+     *
+     * The below check allows both interpretation.
+     */
+    if (PCI_FUNC(dev->devfn)) {
+        PCIDevice *f0 = bus->devices[PCI_DEVFN(slot, 0)];
+        if (f0 && !(f0->cap_present & QEMU_PCI_CAP_MULTIFUNCTION)) {
+            /* function 0 should set multifunction bit */
+            error_report("PCI: single function device can't be populated "
+                         "in function %x.%x", slot, PCI_FUNC(dev->devfn));
+            return -1;
+        }
+        return 0;
+    }
+
+    if (dev->cap_present & QEMU_PCI_CAP_MULTIFUNCTION) {
+        return 0;
+    }
+    /* function 0 indicates single function, so function > 0 must be NULL */
+    for (func = 1; func < PCI_FUNC_MAX; ++func) {
+        if (bus->devices[PCI_DEVFN(slot, func)]) {
+            error_report("PCI: %x.0 indicates single function, "
+                         "but %x.%x is already populated.",
+                         slot, slot, func);
+            return -1;
+        }
+    }
+    return 0;
+}
+
+static void pci_config_alloc(PCIDevice *pci_dev)
+{
+    int config_size = pci_config_size(pci_dev);
+
+    pci_dev->config = g_malloc0(config_size);
+    pci_dev->cmask = g_malloc0(config_size);
+    pci_dev->wmask = g_malloc0(config_size);
+    pci_dev->w1cmask = g_malloc0(config_size);
+    pci_dev->used = g_malloc0(config_size);
+}
+
+static void pci_config_free(PCIDevice *pci_dev)
+{
+    g_free(pci_dev->config);
+    g_free(pci_dev->cmask);
+    g_free(pci_dev->wmask);
+    g_free(pci_dev->w1cmask);
+    g_free(pci_dev->used);
+}
+
+/* -1 for devfn means auto assign */
+static PCIDevice *do_pci_register_device(PCIDevice *pci_dev, PCIBus *bus,
+                                         const char *name, int devfn)
+{
+    PCIDeviceClass *pc = PCI_DEVICE_GET_CLASS(pci_dev);
+    PCIConfigReadFunc *config_read = pc->config_read;
+    PCIConfigWriteFunc *config_write = pc->config_write;
+
+    if (devfn < 0) {
+        for(devfn = bus->devfn_min ; devfn < ARRAY_SIZE(bus->devices);
+            devfn += PCI_FUNC_MAX) {
+            if (!bus->devices[devfn])
+                goto found;
+        }
+        error_report("PCI: no slot/function available for %s, all in use", 
name);
+        return NULL;
+    found: ;
+    } else if (bus->devices[devfn]) {
+        error_report("PCI: slot %d function %d not available for %s, in use by 
%s",
+                     PCI_SLOT(devfn), PCI_FUNC(devfn), name, 
bus->devices[devfn]->name);
+        return NULL;
+    }
+    pci_dev->bus = bus;
+    if (bus->dma_context_fn) {
+        pci_dev->dma = bus->dma_context_fn(bus, bus->dma_context_opaque, 
devfn);
+    } else {
+        /* FIXME: Make dma_context_fn use MemoryRegions instead, so this path 
is
+         * taken unconditionally */
+        /* FIXME: inherit memory region from bus creator */
+        memory_region_init_alias(&pci_dev->bus_master_enable_region, "bus 
master",
+                                 get_system_memory(), 0,
+                                 memory_region_size(get_system_memory()));
+        memory_region_set_enabled(&pci_dev->bus_master_enable_region, false);
+        address_space_init(&pci_dev->bus_master_as, 
&pci_dev->bus_master_enable_region);
+        pci_dev->dma = g_new(DMAContext, 1);
+        dma_context_init(pci_dev->dma, &pci_dev->bus_master_as, NULL, NULL, 
NULL);
+    }
+    pci_dev->devfn = devfn;
+    pstrcpy(pci_dev->name, sizeof(pci_dev->name), name);
+    pci_dev->irq_state = 0;
+    pci_config_alloc(pci_dev);
+
+    pci_config_set_vendor_id(pci_dev->config, pc->vendor_id);
+    pci_config_set_device_id(pci_dev->config, pc->device_id);
+    pci_config_set_revision(pci_dev->config, pc->revision);
+    pci_config_set_class(pci_dev->config, pc->class_id);
+
+    if (!pc->is_bridge) {
+        if (pc->subsystem_vendor_id || pc->subsystem_id) {
+            pci_set_word(pci_dev->config + PCI_SUBSYSTEM_VENDOR_ID,
+                         pc->subsystem_vendor_id);
+            pci_set_word(pci_dev->config + PCI_SUBSYSTEM_ID,
+                         pc->subsystem_id);
+        } else {
+            pci_set_default_subsystem_id(pci_dev);
+        }
+    } else {
+        /* subsystem_vendor_id/subsystem_id are only for header type 0 */
+        assert(!pc->subsystem_vendor_id);
+        assert(!pc->subsystem_id);
+    }
+    pci_init_cmask(pci_dev);
+    pci_init_wmask(pci_dev);
+    pci_init_w1cmask(pci_dev);
+    if (pc->is_bridge) {
+        pci_init_mask_bridge(pci_dev);
+    }
+    if (pci_init_multifunction(bus, pci_dev)) {
+        pci_config_free(pci_dev);
+        return NULL;
+    }
+
+    if (!config_read)
+        config_read = pci_default_read_config;
+    if (!config_write)
+        config_write = pci_default_write_config;
+    pci_dev->config_read = config_read;
+    pci_dev->config_write = config_write;
+    bus->devices[devfn] = pci_dev;
+    pci_dev->irq = qemu_allocate_irqs(pci_set_irq, pci_dev, PCI_NUM_PINS);
+    pci_dev->version_id = 2; /* Current pci device vmstate version */
+    return pci_dev;
+}
+
+static void do_pci_unregister_device(PCIDevice *pci_dev)
+{
+    qemu_free_irqs(pci_dev->irq);
+    pci_dev->bus->devices[pci_dev->devfn] = NULL;
+    pci_config_free(pci_dev);
+
+    if (!pci_dev->bus->dma_context_fn) {
+        address_space_destroy(&pci_dev->bus_master_as);
+        memory_region_destroy(&pci_dev->bus_master_enable_region);
+        g_free(pci_dev->dma);
+        pci_dev->dma = NULL;
+    }
+}
+
+static void pci_unregister_io_regions(PCIDevice *pci_dev)
+{
+    PCIIORegion *r;
+    int i;
+
+    for(i = 0; i < PCI_NUM_REGIONS; i++) {
+        r = &pci_dev->io_regions[i];
+        if (!r->size || r->addr == PCI_BAR_UNMAPPED)
+            continue;
+        memory_region_del_subregion(r->address_space, r->memory);
+    }
+}
+
+static int pci_unregister_device(DeviceState *dev)
+{
+    PCIDevice *pci_dev = PCI_DEVICE(dev);
+    PCIDeviceClass *pc = PCI_DEVICE_GET_CLASS(pci_dev);
+
+    pci_unregister_io_regions(pci_dev);
+    pci_del_option_rom(pci_dev);
+
+    if (pc->exit) {
+        pc->exit(pci_dev);
+    }
+
+    do_pci_unregister_device(pci_dev);
+    return 0;
+}
+
+void pci_register_bar(PCIDevice *pci_dev, int region_num,
+                      uint8_t type, MemoryRegion *memory)
+{
+    PCIIORegion *r;
+    uint32_t addr;
+    uint64_t wmask;
+    pcibus_t size = memory_region_size(memory);
+
+    assert(region_num >= 0);
+    assert(region_num < PCI_NUM_REGIONS);
+    if (size & (size-1)) {
+        fprintf(stderr, "ERROR: PCI region size must be pow2 "
+                    "type=0x%x, size=0x%"FMT_PCIBUS"\n", type, size);
+        exit(1);
+    }
+
+    r = &pci_dev->io_regions[region_num];
+    r->addr = PCI_BAR_UNMAPPED;
+    r->size = size;
+    r->type = type;
+    r->memory = NULL;
+
+    wmask = ~(size - 1);
+    addr = pci_bar(pci_dev, region_num);
+    if (region_num == PCI_ROM_SLOT) {
+        /* ROM enable bit is writable */
+        wmask |= PCI_ROM_ADDRESS_ENABLE;
+    }
+    pci_set_long(pci_dev->config + addr, type);
+    if (!(r->type & PCI_BASE_ADDRESS_SPACE_IO) &&
+        r->type & PCI_BASE_ADDRESS_MEM_TYPE_64) {
+        pci_set_quad(pci_dev->wmask + addr, wmask);
+        pci_set_quad(pci_dev->cmask + addr, ~0ULL);
+    } else {
+        pci_set_long(pci_dev->wmask + addr, wmask & 0xffffffff);
+        pci_set_long(pci_dev->cmask + addr, 0xffffffff);
+    }
+    pci_dev->io_regions[region_num].memory = memory;
+    pci_dev->io_regions[region_num].address_space
+        = type & PCI_BASE_ADDRESS_SPACE_IO
+        ? pci_dev->bus->address_space_io
+        : pci_dev->bus->address_space_mem;
+}
+
+pcibus_t pci_get_bar_addr(PCIDevice *pci_dev, int region_num)
+{
+    return pci_dev->io_regions[region_num].addr;
+}
+
+static pcibus_t pci_bar_address(PCIDevice *d,
+                               int reg, uint8_t type, pcibus_t size)
+{
+    pcibus_t new_addr, last_addr;
+    int bar = pci_bar(d, reg);
+    uint16_t cmd = pci_get_word(d->config + PCI_COMMAND);
+
+    if (type & PCI_BASE_ADDRESS_SPACE_IO) {
+        if (!(cmd & PCI_COMMAND_IO)) {
+            return PCI_BAR_UNMAPPED;
+        }
+        new_addr = pci_get_long(d->config + bar) & ~(size - 1);
+        last_addr = new_addr + size - 1;
+        /* NOTE: we have only 64K ioports on PC */
+        if (last_addr <= new_addr || new_addr == 0 || last_addr > UINT16_MAX) {
+            return PCI_BAR_UNMAPPED;
+        }
+        return new_addr;
+    }
+
+    if (!(cmd & PCI_COMMAND_MEMORY)) {
+        return PCI_BAR_UNMAPPED;
+    }
+    if (type & PCI_BASE_ADDRESS_MEM_TYPE_64) {
+        new_addr = pci_get_quad(d->config + bar);
+    } else {
+        new_addr = pci_get_long(d->config + bar);
+    }
+    /* the ROM slot has a specific enable bit */
+    if (reg == PCI_ROM_SLOT && !(new_addr & PCI_ROM_ADDRESS_ENABLE)) {
+        return PCI_BAR_UNMAPPED;
+    }
+    new_addr &= ~(size - 1);
+    last_addr = new_addr + size - 1;
+    /* NOTE: we do not support wrapping */
+    /* XXX: as we cannot support really dynamic
+       mappings, we handle specific values as invalid
+       mappings. */
+    if (last_addr <= new_addr || new_addr == 0 ||
+        last_addr == PCI_BAR_UNMAPPED) {
+        return PCI_BAR_UNMAPPED;
+    }
+
+    /* Now pcibus_t is 64bit.
+     * Check if 32 bit BAR wraps around explicitly.
+     * Without this, PC ide doesn't work well.
+     * TODO: remove this work around.
+     */
+    if  (!(type & PCI_BASE_ADDRESS_MEM_TYPE_64) && last_addr >= UINT32_MAX) {
+        return PCI_BAR_UNMAPPED;
+    }
+
+    /*
+     * OS is allowed to set BAR beyond its addressable
+     * bits. For example, 32 bit OS can set 64bit bar
+     * to >4G. Check it. TODO: we might need to support
+     * it in the future for e.g. PAE.
+     */
+    if (last_addr >= HWADDR_MAX) {
+        return PCI_BAR_UNMAPPED;
+    }
+
+    return new_addr;
+}
+
+static void pci_update_mappings(PCIDevice *d)
+{
+    PCIIORegion *r;
+    int i;
+    pcibus_t new_addr;
+
+    for(i = 0; i < PCI_NUM_REGIONS; i++) {
+        r = &d->io_regions[i];
+
+        /* this region isn't registered */
+        if (!r->size)
+            continue;
+
+        new_addr = pci_bar_address(d, i, r->type, r->size);
+
+        /* This bar isn't changed */
+        if (new_addr == r->addr)
+            continue;
+
+        /* now do the real mapping */
+        if (r->addr != PCI_BAR_UNMAPPED) {
+            memory_region_del_subregion(r->address_space, r->memory);
+        }
+        r->addr = new_addr;
+        if (r->addr != PCI_BAR_UNMAPPED) {
+            memory_region_add_subregion_overlap(r->address_space,
+                                                r->addr, r->memory, 1);
+        }
+    }
+}
+
+static inline int pci_irq_disabled(PCIDevice *d)
+{
+    return pci_get_word(d->config + PCI_COMMAND) & PCI_COMMAND_INTX_DISABLE;
+}
+
+/* Called after interrupt disabled field update in config space,
+ * assert/deassert interrupts if necessary.
+ * Gets original interrupt disable bit value (before update). */
+static void pci_update_irq_disabled(PCIDevice *d, int was_irq_disabled)
+{
+    int i, disabled = pci_irq_disabled(d);
+    if (disabled == was_irq_disabled)
+        return;
+    for (i = 0; i < PCI_NUM_PINS; ++i) {
+        int state = pci_irq_state(d, i);
+        pci_change_irq_level(d, i, disabled ? -state : state);
+    }
+}
+
+uint32_t pci_default_read_config(PCIDevice *d,
+                                 uint32_t address, int len)
+{
+    uint32_t val = 0;
+
+    memcpy(&val, d->config + address, len);
+    return le32_to_cpu(val);
+}
+
+void pci_default_write_config(PCIDevice *d, uint32_t addr, uint32_t val, int l)
+{
+    int i, was_irq_disabled = pci_irq_disabled(d);
+
+    for (i = 0; i < l; val >>= 8, ++i) {
+        uint8_t wmask = d->wmask[addr + i];
+        uint8_t w1cmask = d->w1cmask[addr + i];
+        assert(!(wmask & w1cmask));
+        d->config[addr + i] = (d->config[addr + i] & ~wmask) | (val & wmask);
+        d->config[addr + i] &= ~(val & w1cmask); /* W1C: Write 1 to Clear */
+    }
+    if (ranges_overlap(addr, l, PCI_BASE_ADDRESS_0, 24) ||
+        ranges_overlap(addr, l, PCI_ROM_ADDRESS, 4) ||
+        ranges_overlap(addr, l, PCI_ROM_ADDRESS1, 4) ||
+        range_covers_byte(addr, l, PCI_COMMAND))
+        pci_update_mappings(d);
+
+    if (range_covers_byte(addr, l, PCI_COMMAND)) {
+        pci_update_irq_disabled(d, was_irq_disabled);
+        memory_region_set_enabled(&d->bus_master_enable_region,
+                                  pci_get_word(d->config + PCI_COMMAND)
+                                    & PCI_COMMAND_MASTER);
+    }
+
+    msi_write_config(d, addr, val, l);
+    msix_write_config(d, addr, val, l);
+}
+
+/***********************************************************/
+/* generic PCI irq support */
+
+/* 0 <= irq_num <= 3. level must be 0 or 1 */
+static void pci_set_irq(void *opaque, int irq_num, int level)
+{
+    PCIDevice *pci_dev = opaque;
+    int change;
+
+    change = level - pci_irq_state(pci_dev, irq_num);
+    if (!change)
+        return;
+
+    pci_set_irq_state(pci_dev, irq_num, level);
+    pci_update_irq_status(pci_dev);
+    if (pci_irq_disabled(pci_dev))
+        return;
+    pci_change_irq_level(pci_dev, irq_num, change);
+}
+
+/* Special hooks used by device assignment */
+void pci_bus_set_route_irq_fn(PCIBus *bus, pci_route_irq_fn route_intx_to_irq)
+{
+    assert(!bus->parent_dev);
+    bus->route_intx_to_irq = route_intx_to_irq;
+}
+
+PCIINTxRoute pci_device_route_intx_to_irq(PCIDevice *dev, int pin)
+{
+    PCIBus *bus;
+
+    do {
+         bus = dev->bus;
+         pin = bus->map_irq(dev, pin);
+         dev = bus->parent_dev;
+    } while (dev);
+
+    if (!bus->route_intx_to_irq) {
+        error_report("PCI: Bug - unimplemented PCI INTx routing (%s)\n",
+                     object_get_typename(OBJECT(bus->qbus.parent)));
+        return (PCIINTxRoute) { PCI_INTX_DISABLED, -1 };
+    }
+
+    return bus->route_intx_to_irq(bus->irq_opaque, pin);
+}
+
+bool pci_intx_route_changed(PCIINTxRoute *old, PCIINTxRoute *new)
+{
+    return old->mode != new->mode || old->irq != new->irq;
+}
+
+void pci_bus_fire_intx_routing_notifier(PCIBus *bus)
+{
+    PCIDevice *dev;
+    PCIBus *sec;
+    int i;
+
+    for (i = 0; i < ARRAY_SIZE(bus->devices); ++i) {
+        dev = bus->devices[i];
+        if (dev && dev->intx_routing_notifier) {
+            dev->intx_routing_notifier(dev);
+        }
+        QLIST_FOREACH(sec, &bus->child, sibling) {
+            pci_bus_fire_intx_routing_notifier(sec);
+        }
+    }
+}
+
+void pci_device_set_intx_routing_notifier(PCIDevice *dev,
+                                          PCIINTxRoutingNotifier notifier)
+{
+    dev->intx_routing_notifier = notifier;
+}
+
+/*
+ * PCI-to-PCI bridge specification
+ * 9.1: Interrupt routing. Table 9-1
+ *
+ * the PCI Express Base Specification, Revision 2.1
+ * 2.2.8.1: INTx interrutp signaling - Rules
+ *          the Implementation Note
+ *          Table 2-20
+ */
+/*
+ * 0 <= pin <= 3 0 = INTA, 1 = INTB, 2 = INTC, 3 = INTD
+ * 0-origin unlike PCI interrupt pin register.
+ */
+int pci_swizzle_map_irq_fn(PCIDevice *pci_dev, int pin)
+{
+    return (pin + PCI_SLOT(pci_dev->devfn)) % PCI_NUM_PINS;
+}
+
+/***********************************************************/
+/* monitor info on PCI */
+
+typedef struct {
+    uint16_t class;
+    const char *desc;
+    const char *fw_name;
+    uint16_t fw_ign_bits;
+} pci_class_desc;
+
+static const pci_class_desc pci_class_descriptions[] =
+{
+    { 0x0001, "VGA controller", "display"},
+    { 0x0100, "SCSI controller", "scsi"},
+    { 0x0101, "IDE controller", "ide"},
+    { 0x0102, "Floppy controller", "fdc"},
+    { 0x0103, "IPI controller", "ipi"},
+    { 0x0104, "RAID controller", "raid"},
+    { 0x0106, "SATA controller"},
+    { 0x0107, "SAS controller"},
+    { 0x0180, "Storage controller"},
+    { 0x0200, "Ethernet controller", "ethernet"},
+    { 0x0201, "Token Ring controller", "token-ring"},
+    { 0x0202, "FDDI controller", "fddi"},
+    { 0x0203, "ATM controller", "atm"},
+    { 0x0280, "Network controller"},
+    { 0x0300, "VGA controller", "display", 0x00ff},
+    { 0x0301, "XGA controller"},
+    { 0x0302, "3D controller"},
+    { 0x0380, "Display controller"},
+    { 0x0400, "Video controller", "video"},
+    { 0x0401, "Audio controller", "sound"},
+    { 0x0402, "Phone"},
+    { 0x0403, "Audio controller", "sound"},
+    { 0x0480, "Multimedia controller"},
+    { 0x0500, "RAM controller", "memory"},
+    { 0x0501, "Flash controller", "flash"},
+    { 0x0580, "Memory controller"},
+    { 0x0600, "Host bridge", "host"},
+    { 0x0601, "ISA bridge", "isa"},
+    { 0x0602, "EISA bridge", "eisa"},
+    { 0x0603, "MC bridge", "mca"},
+    { 0x0604, "PCI bridge", "pci"},
+    { 0x0605, "PCMCIA bridge", "pcmcia"},
+    { 0x0606, "NUBUS bridge", "nubus"},
+    { 0x0607, "CARDBUS bridge", "cardbus"},
+    { 0x0608, "RACEWAY bridge"},
+    { 0x0680, "Bridge"},
+    { 0x0700, "Serial port", "serial"},
+    { 0x0701, "Parallel port", "parallel"},
+    { 0x0800, "Interrupt controller", "interrupt-controller"},
+    { 0x0801, "DMA controller", "dma-controller"},
+    { 0x0802, "Timer", "timer"},
+    { 0x0803, "RTC", "rtc"},
+    { 0x0900, "Keyboard", "keyboard"},
+    { 0x0901, "Pen", "pen"},
+    { 0x0902, "Mouse", "mouse"},
+    { 0x0A00, "Dock station", "dock", 0x00ff},
+    { 0x0B00, "i386 cpu", "cpu", 0x00ff},
+    { 0x0c00, "Fireware contorller", "fireware"},
+    { 0x0c01, "Access bus controller", "access-bus"},
+    { 0x0c02, "SSA controller", "ssa"},
+    { 0x0c03, "USB controller", "usb"},
+    { 0x0c04, "Fibre channel controller", "fibre-channel"},
+    { 0x0c05, "SMBus"},
+    { 0, NULL}
+};
+
+static void pci_for_each_device_under_bus(PCIBus *bus,
+                                          void (*fn)(PCIBus *b, PCIDevice *d,
+                                                     void *opaque),
+                                          void *opaque)
+{
+    PCIDevice *d;
+    int devfn;
+
+    for(devfn = 0; devfn < ARRAY_SIZE(bus->devices); devfn++) {
+        d = bus->devices[devfn];
+        if (d) {
+            fn(bus, d, opaque);
+        }
+    }
+}
+
+void pci_for_each_device(PCIBus *bus, int bus_num,
+                         void (*fn)(PCIBus *b, PCIDevice *d, void *opaque),
+                         void *opaque)
+{
+    bus = pci_find_bus_nr(bus, bus_num);
+
+    if (bus) {
+        pci_for_each_device_under_bus(bus, fn, opaque);
+    }
+}
+
+static const pci_class_desc *get_class_desc(int class)
+{
+    const pci_class_desc *desc;
+
+    desc = pci_class_descriptions;
+    while (desc->desc && class != desc->class) {
+        desc++;
+    }
+
+    return desc;
+}
+
+static PciDeviceInfoList *qmp_query_pci_devices(PCIBus *bus, int bus_num);
+
+static PciMemoryRegionList *qmp_query_pci_regions(const PCIDevice *dev)
+{
+    PciMemoryRegionList *head = NULL, *cur_item = NULL;
+    int i;
+
+    for (i = 0; i < PCI_NUM_REGIONS; i++) {
+        const PCIIORegion *r = &dev->io_regions[i];
+        PciMemoryRegionList *region;
+
+        if (!r->size) {
+            continue;
+        }
+
+        region = g_malloc0(sizeof(*region));
+        region->value = g_malloc0(sizeof(*region->value));
+
+        if (r->type & PCI_BASE_ADDRESS_SPACE_IO) {
+            region->value->type = g_strdup("io");
+        } else {
+            region->value->type = g_strdup("memory");
+            region->value->has_prefetch = true;
+            region->value->prefetch = !!(r->type & 
PCI_BASE_ADDRESS_MEM_PREFETCH);
+            region->value->has_mem_type_64 = true;
+            region->value->mem_type_64 = !!(r->type & 
PCI_BASE_ADDRESS_MEM_TYPE_64);
+        }
+
+        region->value->bar = i;
+        region->value->address = r->addr;
+        region->value->size = r->size;
+
+        /* XXX: waiting for the qapi to support GSList */
+        if (!cur_item) {
+            head = cur_item = region;
+        } else {
+            cur_item->next = region;
+            cur_item = region;
+        }
+    }
+
+    return head;
+}
+
+static PciBridgeInfo *qmp_query_pci_bridge(PCIDevice *dev, PCIBus *bus,
+                                           int bus_num)
+{
+    PciBridgeInfo *info;
+
+    info = g_malloc0(sizeof(*info));
+
+    info->bus.number = dev->config[PCI_PRIMARY_BUS];
+    info->bus.secondary = dev->config[PCI_SECONDARY_BUS];
+    info->bus.subordinate = dev->config[PCI_SUBORDINATE_BUS];
+
+    info->bus.io_range = g_malloc0(sizeof(*info->bus.io_range));
+    info->bus.io_range->base = pci_bridge_get_base(dev, 
PCI_BASE_ADDRESS_SPACE_IO);
+    info->bus.io_range->limit = pci_bridge_get_limit(dev, 
PCI_BASE_ADDRESS_SPACE_IO);
+
+    info->bus.memory_range = g_malloc0(sizeof(*info->bus.memory_range));
+    info->bus.memory_range->base = pci_bridge_get_base(dev, 
PCI_BASE_ADDRESS_SPACE_MEMORY);
+    info->bus.memory_range->limit = pci_bridge_get_limit(dev, 
PCI_BASE_ADDRESS_SPACE_MEMORY);
+
+    info->bus.prefetchable_range = 
g_malloc0(sizeof(*info->bus.prefetchable_range));
+    info->bus.prefetchable_range->base = pci_bridge_get_base(dev, 
PCI_BASE_ADDRESS_MEM_PREFETCH);
+    info->bus.prefetchable_range->limit = pci_bridge_get_limit(dev, 
PCI_BASE_ADDRESS_MEM_PREFETCH);
+
+    if (dev->config[PCI_SECONDARY_BUS] != 0) {
+        PCIBus *child_bus = pci_find_bus_nr(bus, 
dev->config[PCI_SECONDARY_BUS]);
+        if (child_bus) {
+            info->has_devices = true;
+            info->devices = qmp_query_pci_devices(child_bus, 
dev->config[PCI_SECONDARY_BUS]);
+        }
+    }
+
+    return info;
+}
+
+static PciDeviceInfo *qmp_query_pci_device(PCIDevice *dev, PCIBus *bus,
+                                           int bus_num)
+{
+    const pci_class_desc *desc;
+    PciDeviceInfo *info;
+    uint8_t type;
+    int class;
+
+    info = g_malloc0(sizeof(*info));
+    info->bus = bus_num;
+    info->slot = PCI_SLOT(dev->devfn);
+    info->function = PCI_FUNC(dev->devfn);
+
+    class = pci_get_word(dev->config + PCI_CLASS_DEVICE);
+    info->class_info.class = class;
+    desc = get_class_desc(class);
+    if (desc->desc) {
+        info->class_info.has_desc = true;
+        info->class_info.desc = g_strdup(desc->desc);
+    }
+
+    info->id.vendor = pci_get_word(dev->config + PCI_VENDOR_ID);
+    info->id.device = pci_get_word(dev->config + PCI_DEVICE_ID);
+    info->regions = qmp_query_pci_regions(dev);
+    info->qdev_id = g_strdup(dev->qdev.id ? dev->qdev.id : "");
+
+    if (dev->config[PCI_INTERRUPT_PIN] != 0) {
+        info->has_irq = true;
+        info->irq = dev->config[PCI_INTERRUPT_LINE];
+    }
+
+    type = dev->config[PCI_HEADER_TYPE] & ~PCI_HEADER_TYPE_MULTI_FUNCTION;
+    if (type == PCI_HEADER_TYPE_BRIDGE) {
+        info->has_pci_bridge = true;
+        info->pci_bridge = qmp_query_pci_bridge(dev, bus, bus_num);
+    }
+
+    return info;
+}
+
+static PciDeviceInfoList *qmp_query_pci_devices(PCIBus *bus, int bus_num)
+{
+    PciDeviceInfoList *info, *head = NULL, *cur_item = NULL;
+    PCIDevice *dev;
+    int devfn;
+
+    for (devfn = 0; devfn < ARRAY_SIZE(bus->devices); devfn++) {
+        dev = bus->devices[devfn];
+        if (dev) {
+            info = g_malloc0(sizeof(*info));
+            info->value = qmp_query_pci_device(dev, bus, bus_num);
+
+            /* XXX: waiting for the qapi to support GSList */
+            if (!cur_item) {
+                head = cur_item = info;
+            } else {
+                cur_item->next = info;
+                cur_item = info;
+            }
+        }
+    }
+
+    return head;
+}
+
+static PciInfo *qmp_query_pci_bus(PCIBus *bus, int bus_num)
+{
+    PciInfo *info = NULL;
+
+    bus = pci_find_bus_nr(bus, bus_num);
+    if (bus) {
+        info = g_malloc0(sizeof(*info));
+        info->bus = bus_num;
+        info->devices = qmp_query_pci_devices(bus, bus_num);
+    }
+
+    return info;
+}
+
+PciInfoList *qmp_query_pci(Error **errp)
+{
+    PciInfoList *info, *head = NULL, *cur_item = NULL;
+    struct PCIHostBus *host;
+
+    QLIST_FOREACH(host, &host_buses, next) {
+        info = g_malloc0(sizeof(*info));
+        info->value = qmp_query_pci_bus(host->bus, 0);
+
+        /* XXX: waiting for the qapi to support GSList */
+        if (!cur_item) {
+            head = cur_item = info;
+        } else {
+            cur_item->next = info;
+            cur_item = info;
+        }
+    }
+
+    return head;
+}
+
+static const char * const pci_nic_models[] = {
+    "ne2k_pci",
+    "i82551",
+    "i82557b",
+    "i82559er",
+    "rtl8139",
+    "e1000",
+    "pcnet",
+    "virtio",
+    NULL
+};
+
+static const char * const pci_nic_names[] = {
+    "ne2k_pci",
+    "i82551",
+    "i82557b",
+    "i82559er",
+    "rtl8139",
+    "e1000",
+    "pcnet",
+    "virtio-net-pci",
+    NULL
+};
+
+/* Initialize a PCI NIC.  */
+/* FIXME callers should check for failure, but don't */
+PCIDevice *pci_nic_init(NICInfo *nd, const char *default_model,
+                        const char *default_devaddr)
+{
+    const char *devaddr = nd->devaddr ? nd->devaddr : default_devaddr;
+    PCIBus *bus;
+    int devfn;
+    PCIDevice *pci_dev;
+    DeviceState *dev;
+    int i;
+
+    i = qemu_find_nic_model(nd, pci_nic_models, default_model);
+    if (i < 0)
+        return NULL;
+
+    bus = pci_get_bus_devfn(&devfn, devaddr);
+    if (!bus) {
+        error_report("Invalid PCI device address %s for device %s",
+                     devaddr, pci_nic_names[i]);
+        return NULL;
+    }
+
+    pci_dev = pci_create(bus, devfn, pci_nic_names[i]);
+    dev = &pci_dev->qdev;
+    qdev_set_nic_properties(dev, nd);
+    if (qdev_init(dev) < 0)
+        return NULL;
+    return pci_dev;
+}
+
+PCIDevice *pci_nic_init_nofail(NICInfo *nd, const char *default_model,
+                               const char *default_devaddr)
+{
+    PCIDevice *res;
+
+    if (qemu_show_nic_models(nd->model, pci_nic_models))
+        exit(0);
+
+    res = pci_nic_init(nd, default_model, default_devaddr);
+    if (!res)
+        exit(1);
+    return res;
+}
+
+PCIDevice *pci_vga_init(PCIBus *bus)
+{
+    switch (vga_interface_type) {
+    case VGA_CIRRUS:
+        return pci_create_simple(bus, -1, "cirrus-vga");
+    case VGA_QXL:
+        return pci_create_simple(bus, -1, "qxl-vga");
+    case VGA_STD:
+        return pci_create_simple(bus, -1, "VGA");
+    case VGA_VMWARE:
+        return pci_create_simple(bus, -1, "vmware-svga");
+    case VGA_NONE:
+    default: /* Other non-PCI types. Checking for unsupported types is already
+                done in vl.c. */
+        return NULL;
+    }
+}
+
+/* Whether a given bus number is in range of the secondary
+ * bus of the given bridge device. */
+static bool pci_secondary_bus_in_range(PCIDevice *dev, int bus_num)
+{
+    return !(pci_get_word(dev->config + PCI_BRIDGE_CONTROL) &
+             PCI_BRIDGE_CTL_BUS_RESET) /* Don't walk the bus if it's reset. */ 
&&
+        dev->config[PCI_SECONDARY_BUS] < bus_num &&
+        bus_num <= dev->config[PCI_SUBORDINATE_BUS];
+}
+
+static PCIBus *pci_find_bus_nr(PCIBus *bus, int bus_num)
+{
+    PCIBus *sec;
+
+    if (!bus) {
+        return NULL;
+    }
+
+    if (pci_bus_num(bus) == bus_num) {
+        return bus;
+    }
+
+    /* Consider all bus numbers in range for the host pci bridge. */
+    if (bus->parent_dev &&
+        !pci_secondary_bus_in_range(bus->parent_dev, bus_num)) {
+        return NULL;
+    }
+
+    /* try child bus */
+    for (; bus; bus = sec) {
+        QLIST_FOREACH(sec, &bus->child, sibling) {
+            assert(sec->parent_dev);
+            if (sec->parent_dev->config[PCI_SECONDARY_BUS] == bus_num) {
+                return sec;
+            }
+            if (pci_secondary_bus_in_range(sec->parent_dev, bus_num)) {
+                break;
+            }
+        }
+    }
+
+    return NULL;
+}
+
+PCIDevice *pci_find_device(PCIBus *bus, int bus_num, uint8_t devfn)
+{
+    bus = pci_find_bus_nr(bus, bus_num);
+
+    if (!bus)
+        return NULL;
+
+    return bus->devices[devfn];
+}
+
+static int pci_qdev_init(DeviceState *qdev)
+{
+    PCIDevice *pci_dev = (PCIDevice *)qdev;
+    PCIDeviceClass *pc = PCI_DEVICE_GET_CLASS(pci_dev);
+    PCIBus *bus;
+    int rc;
+    bool is_default_rom;
+
+    /* initialize cap_present for pci_is_express() and pci_config_size() */
+    if (pc->is_express) {
+        pci_dev->cap_present |= QEMU_PCI_CAP_EXPRESS;
+    }
+
+    bus = FROM_QBUS(PCIBus, qdev_get_parent_bus(qdev));
+    pci_dev = do_pci_register_device(pci_dev, bus,
+                                     object_get_typename(OBJECT(qdev)),
+                                     pci_dev->devfn);
+    if (pci_dev == NULL)
+        return -1;
+    if (qdev->hotplugged && pc->no_hotplug) {
+        qerror_report(QERR_DEVICE_NO_HOTPLUG, 
object_get_typename(OBJECT(pci_dev)));
+        do_pci_unregister_device(pci_dev);
+        return -1;
+    }
+    if (pc->init) {
+        rc = pc->init(pci_dev);
+        if (rc != 0) {
+            do_pci_unregister_device(pci_dev);
+            return rc;
+        }
+    }
+
+    /* rom loading */
+    is_default_rom = false;
+    if (pci_dev->romfile == NULL && pc->romfile != NULL) {
+        pci_dev->romfile = g_strdup(pc->romfile);
+        is_default_rom = true;
+    }
+    pci_add_option_rom(pci_dev, is_default_rom);
+
+    if (bus->hotplug) {
+        /* Let buses differentiate between hotplug and when device is
+         * enabled during qemu machine creation. */
+        rc = bus->hotplug(bus->hotplug_qdev, pci_dev,
+                          qdev->hotplugged ? PCI_HOTPLUG_ENABLED:
+                          PCI_COLDPLUG_ENABLED);
+        if (rc != 0) {
+            int r = pci_unregister_device(&pci_dev->qdev);
+            assert(!r);
+            return rc;
+        }
+    }
+    return 0;
+}
+
+static int pci_unplug_device(DeviceState *qdev)
+{
+    PCIDevice *dev = PCI_DEVICE(qdev);
+    PCIDeviceClass *pc = PCI_DEVICE_GET_CLASS(dev);
+
+    if (pc->no_hotplug) {
+        qerror_report(QERR_DEVICE_NO_HOTPLUG, 
object_get_typename(OBJECT(dev)));
+        return -1;
+    }
+    return dev->bus->hotplug(dev->bus->hotplug_qdev, dev,
+                             PCI_HOTPLUG_DISABLED);
+}
+
+PCIDevice *pci_create_multifunction(PCIBus *bus, int devfn, bool multifunction,
+                                    const char *name)
+{
+    DeviceState *dev;
+
+    dev = qdev_create(&bus->qbus, name);
+    qdev_prop_set_int32(dev, "addr", devfn);
+    qdev_prop_set_bit(dev, "multifunction", multifunction);
+    return PCI_DEVICE(dev);
+}
+
+PCIDevice *pci_create_simple_multifunction(PCIBus *bus, int devfn,
+                                           bool multifunction,
+                                           const char *name)
+{
+    PCIDevice *dev = pci_create_multifunction(bus, devfn, multifunction, name);
+    qdev_init_nofail(&dev->qdev);
+    return dev;
+}
+
+PCIDevice *pci_create(PCIBus *bus, int devfn, const char *name)
+{
+    return pci_create_multifunction(bus, devfn, false, name);
+}
+
+PCIDevice *pci_create_simple(PCIBus *bus, int devfn, const char *name)
+{
+    return pci_create_simple_multifunction(bus, devfn, false, name);
+}
+
+static uint8_t pci_find_space(PCIDevice *pdev, uint8_t size)
+{
+    int offset = PCI_CONFIG_HEADER_SIZE;
+    int i;
+    for (i = PCI_CONFIG_HEADER_SIZE; i < PCI_CONFIG_SPACE_SIZE; ++i) {
+        if (pdev->used[i])
+            offset = i + 1;
+        else if (i - offset + 1 == size)
+            return offset;
+    }
+    return 0;
+}
+
+static uint8_t pci_find_capability_list(PCIDevice *pdev, uint8_t cap_id,
+                                        uint8_t *prev_p)
+{
+    uint8_t next, prev;
+
+    if (!(pdev->config[PCI_STATUS] & PCI_STATUS_CAP_LIST))
+        return 0;
+
+    for (prev = PCI_CAPABILITY_LIST; (next = pdev->config[prev]);
+         prev = next + PCI_CAP_LIST_NEXT)
+        if (pdev->config[next + PCI_CAP_LIST_ID] == cap_id)
+            break;
+
+    if (prev_p)
+        *prev_p = prev;
+    return next;
+}
+
+static uint8_t pci_find_capability_at_offset(PCIDevice *pdev, uint8_t offset)
+{
+    uint8_t next, prev, found = 0;
+
+    if (!(pdev->used[offset])) {
+        return 0;
+    }
+
+    assert(pdev->config[PCI_STATUS] & PCI_STATUS_CAP_LIST);
+
+    for (prev = PCI_CAPABILITY_LIST; (next = pdev->config[prev]);
+         prev = next + PCI_CAP_LIST_NEXT) {
+        if (next <= offset && next > found) {
+            found = next;
+        }
+    }
+    return found;
+}
+
+/* Patch the PCI vendor and device ids in a PCI rom image if necessary.
+   This is needed for an option rom which is used for more than one device. */
+static void pci_patch_ids(PCIDevice *pdev, uint8_t *ptr, int size)
+{
+    uint16_t vendor_id;
+    uint16_t device_id;
+    uint16_t rom_vendor_id;
+    uint16_t rom_device_id;
+    uint16_t rom_magic;
+    uint16_t pcir_offset;
+    uint8_t checksum;
+
+    /* Words in rom data are little endian (like in PCI configuration),
+       so they can be read / written with pci_get_word / pci_set_word. */
+
+    /* Only a valid rom will be patched. */
+    rom_magic = pci_get_word(ptr);
+    if (rom_magic != 0xaa55) {
+        PCI_DPRINTF("Bad ROM magic %04x\n", rom_magic);
+        return;
+    }
+    pcir_offset = pci_get_word(ptr + 0x18);
+    if (pcir_offset + 8 >= size || memcmp(ptr + pcir_offset, "PCIR", 4)) {
+        PCI_DPRINTF("Bad PCIR offset 0x%x or signature\n", pcir_offset);
+        return;
+    }
+
+    vendor_id = pci_get_word(pdev->config + PCI_VENDOR_ID);
+    device_id = pci_get_word(pdev->config + PCI_DEVICE_ID);
+    rom_vendor_id = pci_get_word(ptr + pcir_offset + 4);
+    rom_device_id = pci_get_word(ptr + pcir_offset + 6);
+
+    PCI_DPRINTF("%s: ROM id %04x%04x / PCI id %04x%04x\n", pdev->romfile,
+                vendor_id, device_id, rom_vendor_id, rom_device_id);
+
+    checksum = ptr[6];
+
+    if (vendor_id != rom_vendor_id) {
+        /* Patch vendor id and checksum (at offset 6 for etherboot roms). */
+        checksum += (uint8_t)rom_vendor_id + (uint8_t)(rom_vendor_id >> 8);
+        checksum -= (uint8_t)vendor_id + (uint8_t)(vendor_id >> 8);
+        PCI_DPRINTF("ROM checksum %02x / %02x\n", ptr[6], checksum);
+        ptr[6] = checksum;
+        pci_set_word(ptr + pcir_offset + 4, vendor_id);
+    }
+
+    if (device_id != rom_device_id) {
+        /* Patch device id and checksum (at offset 6 for etherboot roms). */
+        checksum += (uint8_t)rom_device_id + (uint8_t)(rom_device_id >> 8);
+        checksum -= (uint8_t)device_id + (uint8_t)(device_id >> 8);
+        PCI_DPRINTF("ROM checksum %02x / %02x\n", ptr[6], checksum);
+        ptr[6] = checksum;
+        pci_set_word(ptr + pcir_offset + 6, device_id);
+    }
+}
+
+/* Add an option rom for the device */
+static int pci_add_option_rom(PCIDevice *pdev, bool is_default_rom)
+{
+    int size;
+    char *path;
+    void *ptr;
+    char name[32];
+    const VMStateDescription *vmsd;
+
+    if (!pdev->romfile)
+        return 0;
+    if (strlen(pdev->romfile) == 0)
+        return 0;
+
+    if (!pdev->rom_bar) {
+        /*
+         * Load rom via fw_cfg instead of creating a rom bar,
+         * for 0.11 compatibility.
+         */
+        int class = pci_get_word(pdev->config + PCI_CLASS_DEVICE);
+        if (class == 0x0300) {
+            rom_add_vga(pdev->romfile);
+        } else {
+            rom_add_option(pdev->romfile, -1);
+        }
+        return 0;
+    }
+
+    path = qemu_find_file(QEMU_FILE_TYPE_BIOS, pdev->romfile);
+    if (path == NULL) {
+        path = g_strdup(pdev->romfile);
+    }
+
+    size = get_image_size(path);
+    if (size < 0) {
+        error_report("%s: failed to find romfile \"%s\"",
+                     __FUNCTION__, pdev->romfile);
+        g_free(path);
+        return -1;
+    }
+    if (size & (size - 1)) {
+        size = 1 << qemu_fls(size);
+    }
+
+    vmsd = qdev_get_vmsd(DEVICE(pdev));
+
+    if (vmsd) {
+        snprintf(name, sizeof(name), "%s.rom", vmsd->name);
+    } else {
+        snprintf(name, sizeof(name), "%s.rom", 
object_get_typename(OBJECT(pdev)));
+    }
+    pdev->has_rom = true;
+    memory_region_init_ram(&pdev->rom, name, size);
+    vmstate_register_ram(&pdev->rom, &pdev->qdev);
+    ptr = memory_region_get_ram_ptr(&pdev->rom);
+    load_image(path, ptr);
+    g_free(path);
+
+    if (is_default_rom) {
+        /* Only the default rom images will be patched (if needed). */
+        pci_patch_ids(pdev, ptr, size);
+    }
+
+    qemu_put_ram_ptr(ptr);
+
+    pci_register_bar(pdev, PCI_ROM_SLOT, 0, &pdev->rom);
+
+    return 0;
+}
+
+static void pci_del_option_rom(PCIDevice *pdev)
+{
+    if (!pdev->has_rom)
+        return;
+
+    vmstate_unregister_ram(&pdev->rom, &pdev->qdev);
+    memory_region_destroy(&pdev->rom);
+    pdev->has_rom = false;
+}
+
+/*
+ * if !offset
+ * Reserve space and add capability to the linked list in pci config space
+ *
+ * if offset = 0,
+ * Find and reserve space and add capability to the linked list
+ * in pci config space */
+int pci_add_capability(PCIDevice *pdev, uint8_t cap_id,
+                       uint8_t offset, uint8_t size)
+{
+    uint8_t *config;
+    int i, overlapping_cap;
+
+    if (!offset) {
+        offset = pci_find_space(pdev, size);
+        if (!offset) {
+            return -ENOSPC;
+        }
+    } else {
+        /* Verify that capabilities don't overlap.  Note: device assignment
+         * depends on this check to verify that the device is not broken.
+         * Should never trigger for emulated devices, but it's helpful
+         * for debugging these. */
+        for (i = offset; i < offset + size; i++) {
+            overlapping_cap = pci_find_capability_at_offset(pdev, i);
+            if (overlapping_cap) {
+                fprintf(stderr, "ERROR: %04x:%02x:%02x.%x "
+                        "Attempt to add PCI capability %x at offset "
+                        "%x overlaps existing capability %x at offset %x\n",
+                        pci_find_domain(pdev->bus), pci_bus_num(pdev->bus),
+                        PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn),
+                        cap_id, offset, overlapping_cap, i);
+                return -EINVAL;
+            }
+        }
+    }
+
+    config = pdev->config + offset;
+    config[PCI_CAP_LIST_ID] = cap_id;
+    config[PCI_CAP_LIST_NEXT] = pdev->config[PCI_CAPABILITY_LIST];
+    pdev->config[PCI_CAPABILITY_LIST] = offset;
+    pdev->config[PCI_STATUS] |= PCI_STATUS_CAP_LIST;
+    memset(pdev->used + offset, 0xFF, QEMU_ALIGN_UP(size, 4));
+    /* Make capability read-only by default */
+    memset(pdev->wmask + offset, 0, size);
+    /* Check capability by default */
+    memset(pdev->cmask + offset, 0xFF, size);
+    return offset;
+}
+
+/* Unlink capability from the pci config space. */
+void pci_del_capability(PCIDevice *pdev, uint8_t cap_id, uint8_t size)
+{
+    uint8_t prev, offset = pci_find_capability_list(pdev, cap_id, &prev);
+    if (!offset)
+        return;
+    pdev->config[prev] = pdev->config[offset + PCI_CAP_LIST_NEXT];
+    /* Make capability writable again */
+    memset(pdev->wmask + offset, 0xff, size);
+    memset(pdev->w1cmask + offset, 0, size);
+    /* Clear cmask as device-specific registers can't be checked */
+    memset(pdev->cmask + offset, 0, size);
+    memset(pdev->used + offset, 0, QEMU_ALIGN_UP(size, 4));
+
+    if (!pdev->config[PCI_CAPABILITY_LIST])
+        pdev->config[PCI_STATUS] &= ~PCI_STATUS_CAP_LIST;
+}
+
+uint8_t pci_find_capability(PCIDevice *pdev, uint8_t cap_id)
+{
+    return pci_find_capability_list(pdev, cap_id, NULL);
+}
+
+static void pcibus_dev_print(Monitor *mon, DeviceState *dev, int indent)
+{
+    PCIDevice *d = (PCIDevice *)dev;
+    const pci_class_desc *desc;
+    char ctxt[64];
+    PCIIORegion *r;
+    int i, class;
+
+    class = pci_get_word(d->config + PCI_CLASS_DEVICE);
+    desc = pci_class_descriptions;
+    while (desc->desc && class != desc->class)
+        desc++;
+    if (desc->desc) {
+        snprintf(ctxt, sizeof(ctxt), "%s", desc->desc);
+    } else {
+        snprintf(ctxt, sizeof(ctxt), "Class %04x", class);
+    }
+
+    monitor_printf(mon, "%*sclass %s, addr %02x:%02x.%x, "
+                   "pci id %04x:%04x (sub %04x:%04x)\n",
+                   indent, "", ctxt, pci_bus_num(d->bus),
+                   PCI_SLOT(d->devfn), PCI_FUNC(d->devfn),
+                   pci_get_word(d->config + PCI_VENDOR_ID),
+                   pci_get_word(d->config + PCI_DEVICE_ID),
+                   pci_get_word(d->config + PCI_SUBSYSTEM_VENDOR_ID),
+                   pci_get_word(d->config + PCI_SUBSYSTEM_ID));
+    for (i = 0; i < PCI_NUM_REGIONS; i++) {
+        r = &d->io_regions[i];
+        if (!r->size)
+            continue;
+        monitor_printf(mon, "%*sbar %d: %s at 0x%"FMT_PCIBUS
+                       " [0x%"FMT_PCIBUS"]\n",
+                       indent, "",
+                       i, r->type & PCI_BASE_ADDRESS_SPACE_IO ? "i/o" : "mem",
+                       r->addr, r->addr + r->size - 1);
+    }
+}
+
+static char *pci_dev_fw_name(DeviceState *dev, char *buf, int len)
+{
+    PCIDevice *d = (PCIDevice *)dev;
+    const char *name = NULL;
+    const pci_class_desc *desc =  pci_class_descriptions;
+    int class = pci_get_word(d->config + PCI_CLASS_DEVICE);
+
+    while (desc->desc &&
+          (class & ~desc->fw_ign_bits) !=
+          (desc->class & ~desc->fw_ign_bits)) {
+        desc++;
+    }
+
+    if (desc->desc) {
+        name = desc->fw_name;
+    }
+
+    if (name) {
+        pstrcpy(buf, len, name);
+    } else {
+        snprintf(buf, len, "pci%04x,%04x",
+                 pci_get_word(d->config + PCI_VENDOR_ID),
+                 pci_get_word(d->config + PCI_DEVICE_ID));
+    }
+
+    return buf;
+}
+
+static char *pcibus_get_fw_dev_path(DeviceState *dev)
+{
+    PCIDevice *d = (PCIDevice *)dev;
+    char path[50], name[33];
+    int off;
+
+    off = snprintf(path, sizeof(path), "address@hidden",
+                   pci_dev_fw_name(dev, name, sizeof name),
+                   PCI_SLOT(d->devfn));
+    if (PCI_FUNC(d->devfn))
+        snprintf(path + off, sizeof(path) + off, ",%x", PCI_FUNC(d->devfn));
+    return g_strdup(path);
+}
+
+static char *pcibus_get_dev_path(DeviceState *dev)
+{
+    PCIDevice *d = container_of(dev, PCIDevice, qdev);
+    PCIDevice *t;
+    int slot_depth;
+    /* Path format: Domain:00:Slot.Function:Slot.Function....:Slot.Function.
+     * 00 is added here to make this format compatible with
+     * domain:Bus:Slot.Func for systems without nested PCI bridges.
+     * Slot.Function list specifies the slot and function numbers for all
+     * devices on the path from root to the specific device. */
+    char domain[] = "DDDD:00";
+    char slot[] = ":SS.F";
+    int domain_len = sizeof domain - 1 /* For '\0' */;
+    int slot_len = sizeof slot - 1 /* For '\0' */;
+    int path_len;
+    char *path, *p;
+    int s;
+
+    /* Calculate # of slots on path between device and root. */;
+    slot_depth = 0;
+    for (t = d; t; t = t->bus->parent_dev) {
+        ++slot_depth;
+    }
+
+    path_len = domain_len + slot_len * slot_depth;
+
+    /* Allocate memory, fill in the terminating null byte. */
+    path = g_malloc(path_len + 1 /* For '\0' */);
+    path[path_len] = '\0';
+
+    /* First field is the domain. */
+    s = snprintf(domain, sizeof domain, "%04x:00", pci_find_domain(d->bus));
+    assert(s == domain_len);
+    memcpy(path, domain, domain_len);
+
+    /* Fill in slot numbers. We walk up from device to root, so need to print
+     * them in the reverse order, last to first. */
+    p = path + path_len;
+    for (t = d; t; t = t->bus->parent_dev) {
+        p -= slot_len;
+        s = snprintf(slot, sizeof slot, ":%02x.%x",
+                     PCI_SLOT(t->devfn), PCI_FUNC(t->devfn));
+        assert(s == slot_len);
+        memcpy(p, slot, slot_len);
+    }
+
+    return path;
+}
+
+static int pci_qdev_find_recursive(PCIBus *bus,
+                                   const char *id, PCIDevice **pdev)
+{
+    DeviceState *qdev = qdev_find_recursive(&bus->qbus, id);
+    if (!qdev) {
+        return -ENODEV;
+    }
+
+    /* roughly check if given qdev is pci device */
+    if (object_dynamic_cast(OBJECT(qdev), TYPE_PCI_DEVICE)) {
+        *pdev = PCI_DEVICE(qdev);
+        return 0;
+    }
+    return -EINVAL;
+}
+
+int pci_qdev_find_device(const char *id, PCIDevice **pdev)
+{
+    struct PCIHostBus *host;
+    int rc = -ENODEV;
+
+    QLIST_FOREACH(host, &host_buses, next) {
+        int tmp = pci_qdev_find_recursive(host->bus, id, pdev);
+        if (!tmp) {
+            rc = 0;
+            break;
+        }
+        if (tmp != -ENODEV) {
+            rc = tmp;
+        }
+    }
+
+    return rc;
+}
+
+MemoryRegion *pci_address_space(PCIDevice *dev)
+{
+    return dev->bus->address_space_mem;
+}
+
+MemoryRegion *pci_address_space_io(PCIDevice *dev)
+{
+    return dev->bus->address_space_io;
+}
+
+static void pci_device_class_init(ObjectClass *klass, void *data)
+{
+    DeviceClass *k = DEVICE_CLASS(klass);
+    k->init = pci_qdev_init;
+    k->unplug = pci_unplug_device;
+    k->exit = pci_unregister_device;
+    k->bus_type = TYPE_PCI_BUS;
+    k->props = pci_props;
+}
+
+void pci_setup_iommu(PCIBus *bus, PCIDMAContextFunc fn, void *opaque)
+{
+    bus->dma_context_fn = fn;
+    bus->dma_context_opaque = opaque;
+}
+
+static TypeInfo pci_device_type_info = {
+    .name = TYPE_PCI_DEVICE,
+    .parent = TYPE_DEVICE,
+    .instance_size = sizeof(PCIDevice),
+    .abstract = true,
+    .class_size = sizeof(PCIDeviceClass),
+    .class_init = pci_device_class_init,
+};
+
+static void pci_register_types(void)
+{
+    type_register_static(&pci_bus_info);
+    type_register_static(&pci_device_type_info);
+}
+
+type_init(pci_register_types)
diff --git a/hw/pci/pci.h b/hw/pci/pci.h
new file mode 100644
index 0000000..4da0c2a
--- /dev/null
+++ b/hw/pci/pci.h
@@ -0,0 +1,684 @@
+#ifndef QEMU_PCI_H
+#define QEMU_PCI_H
+
+#include "qemu-common.h"
+
+#include "qdev.h"
+#include "memory.h"
+#include "dma.h"
+
+/* PCI includes legacy ISA access.  */
+#include "isa.h"
+
+#include "pcie.h"
+
+/* PCI bus */
+
+#define PCI_DEVFN(slot, func)   ((((slot) & 0x1f) << 3) | ((func) & 0x07))
+#define PCI_SLOT(devfn)         (((devfn) >> 3) & 0x1f)
+#define PCI_FUNC(devfn)         ((devfn) & 0x07)
+#define PCI_SLOT_MAX            32
+#define PCI_FUNC_MAX            8
+
+/* Class, Vendor and Device IDs from Linux's pci_ids.h */
+#include "pci_ids.h"
+
+/* QEMU-specific Vendor and Device ID definitions */
+
+/* IBM (0x1014) */
+#define PCI_DEVICE_ID_IBM_440GX          0x027f
+#define PCI_DEVICE_ID_IBM_OPENPIC2       0xffff
+
+/* Hitachi (0x1054) */
+#define PCI_VENDOR_ID_HITACHI            0x1054
+#define PCI_DEVICE_ID_HITACHI_SH7751R    0x350e
+
+/* Apple (0x106b) */
+#define PCI_DEVICE_ID_APPLE_343S1201     0x0010
+#define PCI_DEVICE_ID_APPLE_UNI_N_I_PCI  0x001e
+#define PCI_DEVICE_ID_APPLE_UNI_N_PCI    0x001f
+#define PCI_DEVICE_ID_APPLE_UNI_N_KEYL   0x0022
+#define PCI_DEVICE_ID_APPLE_IPID_USB     0x003f
+
+/* Realtek (0x10ec) */
+#define PCI_DEVICE_ID_REALTEK_8029       0x8029
+
+/* Xilinx (0x10ee) */
+#define PCI_DEVICE_ID_XILINX_XC2VP30     0x0300
+
+/* Marvell (0x11ab) */
+#define PCI_DEVICE_ID_MARVELL_GT6412X    0x4620
+
+/* QEMU/Bochs VGA (0x1234) */
+#define PCI_VENDOR_ID_QEMU               0x1234
+#define PCI_DEVICE_ID_QEMU_VGA           0x1111
+
+/* VMWare (0x15ad) */
+#define PCI_VENDOR_ID_VMWARE             0x15ad
+#define PCI_DEVICE_ID_VMWARE_SVGA2       0x0405
+#define PCI_DEVICE_ID_VMWARE_SVGA        0x0710
+#define PCI_DEVICE_ID_VMWARE_NET         0x0720
+#define PCI_DEVICE_ID_VMWARE_SCSI        0x0730
+#define PCI_DEVICE_ID_VMWARE_IDE         0x1729
+
+/* Intel (0x8086) */
+#define PCI_DEVICE_ID_INTEL_82551IT      0x1209
+#define PCI_DEVICE_ID_INTEL_82557        0x1229
+#define PCI_DEVICE_ID_INTEL_82801IR      0x2922
+
+/* Red Hat / Qumranet (for QEMU) -- see pci-ids.txt */
+#define PCI_VENDOR_ID_REDHAT_QUMRANET    0x1af4
+#define PCI_SUBVENDOR_ID_REDHAT_QUMRANET 0x1af4
+#define PCI_SUBDEVICE_ID_QEMU            0x1100
+
+#define PCI_DEVICE_ID_VIRTIO_NET         0x1000
+#define PCI_DEVICE_ID_VIRTIO_BLOCK       0x1001
+#define PCI_DEVICE_ID_VIRTIO_BALLOON     0x1002
+#define PCI_DEVICE_ID_VIRTIO_CONSOLE     0x1003
+#define PCI_DEVICE_ID_VIRTIO_SCSI        0x1004
+#define PCI_DEVICE_ID_VIRTIO_RNG         0x1005
+
+#define FMT_PCIBUS                      PRIx64
+
+typedef void PCIConfigWriteFunc(PCIDevice *pci_dev,
+                                uint32_t address, uint32_t data, int len);
+typedef uint32_t PCIConfigReadFunc(PCIDevice *pci_dev,
+                                   uint32_t address, int len);
+typedef void PCIMapIORegionFunc(PCIDevice *pci_dev, int region_num,
+                                pcibus_t addr, pcibus_t size, int type);
+typedef void PCIUnregisterFunc(PCIDevice *pci_dev);
+
+typedef struct PCIIORegion {
+    pcibus_t addr; /* current PCI mapping address. -1 means not mapped */
+#define PCI_BAR_UNMAPPED (~(pcibus_t)0)
+    pcibus_t size;
+    uint8_t type;
+    MemoryRegion *memory;
+    MemoryRegion *address_space;
+} PCIIORegion;
+
+#define PCI_ROM_SLOT 6
+#define PCI_NUM_REGIONS 7
+
+#include "pci_regs.h"
+
+/* PCI HEADER_TYPE */
+#define  PCI_HEADER_TYPE_MULTI_FUNCTION 0x80
+
+/* Size of the standard PCI config header */
+#define PCI_CONFIG_HEADER_SIZE 0x40
+/* Size of the standard PCI config space */
+#define PCI_CONFIG_SPACE_SIZE 0x100
+/* Size of the standart PCIe config space: 4KB */
+#define PCIE_CONFIG_SPACE_SIZE  0x1000
+
+#define PCI_NUM_PINS 4 /* A-D */
+
+/* Bits in cap_present field. */
+enum {
+    QEMU_PCI_CAP_MSI = 0x1,
+    QEMU_PCI_CAP_MSIX = 0x2,
+    QEMU_PCI_CAP_EXPRESS = 0x4,
+
+    /* multifunction capable device */
+#define QEMU_PCI_CAP_MULTIFUNCTION_BITNR        3
+    QEMU_PCI_CAP_MULTIFUNCTION = (1 << QEMU_PCI_CAP_MULTIFUNCTION_BITNR),
+
+    /* command register SERR bit enabled */
+#define QEMU_PCI_CAP_SERR_BITNR 4
+    QEMU_PCI_CAP_SERR = (1 << QEMU_PCI_CAP_SERR_BITNR),
+    /* Standard hot plug controller. */
+#define QEMU_PCI_SHPC_BITNR 5
+    QEMU_PCI_CAP_SHPC = (1 << QEMU_PCI_SHPC_BITNR),
+#define QEMU_PCI_SLOTID_BITNR 6
+    QEMU_PCI_CAP_SLOTID = (1 << QEMU_PCI_SLOTID_BITNR),
+};
+
+#define TYPE_PCI_DEVICE "pci-device"
+#define PCI_DEVICE(obj) \
+     OBJECT_CHECK(PCIDevice, (obj), TYPE_PCI_DEVICE)
+#define PCI_DEVICE_CLASS(klass) \
+     OBJECT_CLASS_CHECK(PCIDeviceClass, (klass), TYPE_PCI_DEVICE)
+#define PCI_DEVICE_GET_CLASS(obj) \
+     OBJECT_GET_CLASS(PCIDeviceClass, (obj), TYPE_PCI_DEVICE)
+
+typedef struct PCIINTxRoute {
+    enum {
+        PCI_INTX_ENABLED,
+        PCI_INTX_INVERTED,
+        PCI_INTX_DISABLED,
+    } mode;
+    int irq;
+} PCIINTxRoute;
+
+typedef struct PCIDeviceClass {
+    DeviceClass parent_class;
+
+    int (*init)(PCIDevice *dev);
+    PCIUnregisterFunc *exit;
+    PCIConfigReadFunc *config_read;
+    PCIConfigWriteFunc *config_write;
+
+    uint16_t vendor_id;
+    uint16_t device_id;
+    uint8_t revision;
+    uint16_t class_id;
+    uint16_t subsystem_vendor_id;       /* only for header type = 0 */
+    uint16_t subsystem_id;              /* only for header type = 0 */
+
+    /*
+     * pci-to-pci bridge or normal device.
+     * This doesn't mean pci host switch.
+     * When card bus bridge is supported, this would be enhanced.
+     */
+    int is_bridge;
+
+    /* pcie stuff */
+    int is_express;   /* is this device pci express? */
+
+    /* device isn't hot-pluggable */
+    int no_hotplug;
+
+    /* rom bar */
+    const char *romfile;
+} PCIDeviceClass;
+
+typedef void (*PCIINTxRoutingNotifier)(PCIDevice *dev);
+typedef int (*MSIVectorUseNotifier)(PCIDevice *dev, unsigned int vector,
+                                      MSIMessage msg);
+typedef void (*MSIVectorReleaseNotifier)(PCIDevice *dev, unsigned int vector);
+
+struct PCIDevice {
+    DeviceState qdev;
+
+    /* PCI config space */
+    uint8_t *config;
+
+    /* Used to enable config checks on load. Note that writable bits are
+     * never checked even if set in cmask. */
+    uint8_t *cmask;
+
+    /* Used to implement R/W bytes */
+    uint8_t *wmask;
+
+    /* Used to implement RW1C(Write 1 to Clear) bytes */
+    uint8_t *w1cmask;
+
+    /* Used to allocate config space for capabilities. */
+    uint8_t *used;
+
+    /* the following fields are read only */
+    PCIBus *bus;
+    int32_t devfn;
+    char name[64];
+    PCIIORegion io_regions[PCI_NUM_REGIONS];
+    AddressSpace bus_master_as;
+    MemoryRegion bus_master_enable_region;
+    DMAContext *dma;
+
+    /* do not access the following fields */
+    PCIConfigReadFunc *config_read;
+    PCIConfigWriteFunc *config_write;
+
+    /* IRQ objects for the INTA-INTD pins.  */
+    qemu_irq *irq;
+
+    /* Current IRQ levels.  Used internally by the generic PCI code.  */
+    uint8_t irq_state;
+
+    /* Capability bits */
+    uint32_t cap_present;
+
+    /* Offset of MSI-X capability in config space */
+    uint8_t msix_cap;
+
+    /* MSI-X entries */
+    int msix_entries_nr;
+
+    /* Space to store MSIX table & pending bit array */
+    uint8_t *msix_table;
+    uint8_t *msix_pba;
+    /* MemoryRegion container for msix exclusive BAR setup */
+    MemoryRegion msix_exclusive_bar;
+    /* Memory Regions for MSIX table and pending bit entries. */
+    MemoryRegion msix_table_mmio;
+    MemoryRegion msix_pba_mmio;
+    /* Reference-count for entries actually in use by driver. */
+    unsigned *msix_entry_used;
+    /* MSIX function mask set or MSIX disabled */
+    bool msix_function_masked;
+    /* Version id needed for VMState */
+    int32_t version_id;
+
+    /* Offset of MSI capability in config space */
+    uint8_t msi_cap;
+
+    /* PCI Express */
+    PCIExpressDevice exp;
+
+    /* SHPC */
+    SHPCDevice *shpc;
+
+    /* Location of option rom */
+    char *romfile;
+    bool has_rom;
+    MemoryRegion rom;
+    uint32_t rom_bar;
+
+    /* INTx routing notifier */
+    PCIINTxRoutingNotifier intx_routing_notifier;
+
+    /* MSI-X notifiers */
+    MSIVectorUseNotifier msix_vector_use_notifier;
+    MSIVectorReleaseNotifier msix_vector_release_notifier;
+};
+
+void pci_register_bar(PCIDevice *pci_dev, int region_num,
+                      uint8_t attr, MemoryRegion *memory);
+pcibus_t pci_get_bar_addr(PCIDevice *pci_dev, int region_num);
+
+int pci_add_capability(PCIDevice *pdev, uint8_t cap_id,
+                       uint8_t offset, uint8_t size);
+
+void pci_del_capability(PCIDevice *pci_dev, uint8_t cap_id, uint8_t cap_size);
+
+uint8_t pci_find_capability(PCIDevice *pci_dev, uint8_t cap_id);
+
+
+uint32_t pci_default_read_config(PCIDevice *d,
+                                 uint32_t address, int len);
+void pci_default_write_config(PCIDevice *d,
+                              uint32_t address, uint32_t val, int len);
+void pci_device_save(PCIDevice *s, QEMUFile *f);
+int pci_device_load(PCIDevice *s, QEMUFile *f);
+MemoryRegion *pci_address_space(PCIDevice *dev);
+MemoryRegion *pci_address_space_io(PCIDevice *dev);
+
+typedef void (*pci_set_irq_fn)(void *opaque, int irq_num, int level);
+typedef int (*pci_map_irq_fn)(PCIDevice *pci_dev, int irq_num);
+typedef PCIINTxRoute (*pci_route_irq_fn)(void *opaque, int pin);
+
+typedef enum {
+    PCI_HOTPLUG_DISABLED,
+    PCI_HOTPLUG_ENABLED,
+    PCI_COLDPLUG_ENABLED,
+} PCIHotplugState;
+
+typedef int (*pci_hotplug_fn)(DeviceState *qdev, PCIDevice *pci_dev,
+                              PCIHotplugState state);
+void pci_bus_new_inplace(PCIBus *bus, DeviceState *parent,
+                         const char *name,
+                         MemoryRegion *address_space_mem,
+                         MemoryRegion *address_space_io,
+                         uint8_t devfn_min);
+PCIBus *pci_bus_new(DeviceState *parent, const char *name,
+                    MemoryRegion *address_space_mem,
+                    MemoryRegion *address_space_io,
+                    uint8_t devfn_min);
+void pci_bus_irqs(PCIBus *bus, pci_set_irq_fn set_irq, pci_map_irq_fn map_irq,
+                  void *irq_opaque, int nirq);
+int pci_bus_get_irq_level(PCIBus *bus, int irq_num);
+void pci_bus_hotplug(PCIBus *bus, pci_hotplug_fn hotplug, DeviceState *dev);
+/* 0 <= pin <= 3 0 = INTA, 1 = INTB, 2 = INTC, 3 = INTD */
+int pci_swizzle_map_irq_fn(PCIDevice *pci_dev, int pin);
+PCIBus *pci_register_bus(DeviceState *parent, const char *name,
+                         pci_set_irq_fn set_irq, pci_map_irq_fn map_irq,
+                         void *irq_opaque,
+                         MemoryRegion *address_space_mem,
+                         MemoryRegion *address_space_io,
+                         uint8_t devfn_min, int nirq);
+void pci_bus_set_route_irq_fn(PCIBus *, pci_route_irq_fn);
+PCIINTxRoute pci_device_route_intx_to_irq(PCIDevice *dev, int pin);
+bool pci_intx_route_changed(PCIINTxRoute *old, PCIINTxRoute *new);
+void pci_bus_fire_intx_routing_notifier(PCIBus *bus);
+void pci_device_set_intx_routing_notifier(PCIDevice *dev,
+                                          PCIINTxRoutingNotifier notifier);
+void pci_device_reset(PCIDevice *dev);
+void pci_bus_reset(PCIBus *bus);
+
+PCIDevice *pci_nic_init(NICInfo *nd, const char *default_model,
+                        const char *default_devaddr);
+PCIDevice *pci_nic_init_nofail(NICInfo *nd, const char *default_model,
+                               const char *default_devaddr);
+
+PCIDevice *pci_vga_init(PCIBus *bus);
+
+int pci_bus_num(PCIBus *s);
+void pci_for_each_device(PCIBus *bus, int bus_num,
+                         void (*fn)(PCIBus *bus, PCIDevice *d, void *opaque),
+                         void *opaque);
+PCIBus *pci_find_root_bus(int domain);
+int pci_find_domain(const PCIBus *bus);
+PCIDevice *pci_find_device(PCIBus *bus, int bus_num, uint8_t devfn);
+int pci_qdev_find_device(const char *id, PCIDevice **pdev);
+PCIBus *pci_get_bus_devfn(int *devfnp, const char *devaddr);
+
+int pci_read_devaddr(Monitor *mon, const char *addr, int *domp, int *busp,
+                     unsigned *slotp);
+
+void pci_device_deassert_intx(PCIDevice *dev);
+
+typedef DMAContext *(*PCIDMAContextFunc)(PCIBus *, void *, int);
+
+void pci_setup_iommu(PCIBus *bus, PCIDMAContextFunc fn, void *opaque);
+
+static inline void
+pci_set_byte(uint8_t *config, uint8_t val)
+{
+    *config = val;
+}
+
+static inline uint8_t
+pci_get_byte(const uint8_t *config)
+{
+    return *config;
+}
+
+static inline void
+pci_set_word(uint8_t *config, uint16_t val)
+{
+    cpu_to_le16wu((uint16_t *)config, val);
+}
+
+static inline uint16_t
+pci_get_word(const uint8_t *config)
+{
+    return le16_to_cpupu((const uint16_t *)config);
+}
+
+static inline void
+pci_set_long(uint8_t *config, uint32_t val)
+{
+    cpu_to_le32wu((uint32_t *)config, val);
+}
+
+static inline uint32_t
+pci_get_long(const uint8_t *config)
+{
+    return le32_to_cpupu((const uint32_t *)config);
+}
+
+static inline void
+pci_set_quad(uint8_t *config, uint64_t val)
+{
+    cpu_to_le64w((uint64_t *)config, val);
+}
+
+static inline uint64_t
+pci_get_quad(const uint8_t *config)
+{
+    return le64_to_cpup((const uint64_t *)config);
+}
+
+static inline void
+pci_config_set_vendor_id(uint8_t *pci_config, uint16_t val)
+{
+    pci_set_word(&pci_config[PCI_VENDOR_ID], val);
+}
+
+static inline void
+pci_config_set_device_id(uint8_t *pci_config, uint16_t val)
+{
+    pci_set_word(&pci_config[PCI_DEVICE_ID], val);
+}
+
+static inline void
+pci_config_set_revision(uint8_t *pci_config, uint8_t val)
+{
+    pci_set_byte(&pci_config[PCI_REVISION_ID], val);
+}
+
+static inline void
+pci_config_set_class(uint8_t *pci_config, uint16_t val)
+{
+    pci_set_word(&pci_config[PCI_CLASS_DEVICE], val);
+}
+
+static inline void
+pci_config_set_prog_interface(uint8_t *pci_config, uint8_t val)
+{
+    pci_set_byte(&pci_config[PCI_CLASS_PROG], val);
+}
+
+static inline void
+pci_config_set_interrupt_pin(uint8_t *pci_config, uint8_t val)
+{
+    pci_set_byte(&pci_config[PCI_INTERRUPT_PIN], val);
+}
+
+/*
+ * helper functions to do bit mask operation on configuration space.
+ * Just to set bit, use test-and-set and discard returned value.
+ * Just to clear bit, use test-and-clear and discard returned value.
+ * NOTE: They aren't atomic.
+ */
+static inline uint8_t
+pci_byte_test_and_clear_mask(uint8_t *config, uint8_t mask)
+{
+    uint8_t val = pci_get_byte(config);
+    pci_set_byte(config, val & ~mask);
+    return val & mask;
+}
+
+static inline uint8_t
+pci_byte_test_and_set_mask(uint8_t *config, uint8_t mask)
+{
+    uint8_t val = pci_get_byte(config);
+    pci_set_byte(config, val | mask);
+    return val & mask;
+}
+
+static inline uint16_t
+pci_word_test_and_clear_mask(uint8_t *config, uint16_t mask)
+{
+    uint16_t val = pci_get_word(config);
+    pci_set_word(config, val & ~mask);
+    return val & mask;
+}
+
+static inline uint16_t
+pci_word_test_and_set_mask(uint8_t *config, uint16_t mask)
+{
+    uint16_t val = pci_get_word(config);
+    pci_set_word(config, val | mask);
+    return val & mask;
+}
+
+static inline uint32_t
+pci_long_test_and_clear_mask(uint8_t *config, uint32_t mask)
+{
+    uint32_t val = pci_get_long(config);
+    pci_set_long(config, val & ~mask);
+    return val & mask;
+}
+
+static inline uint32_t
+pci_long_test_and_set_mask(uint8_t *config, uint32_t mask)
+{
+    uint32_t val = pci_get_long(config);
+    pci_set_long(config, val | mask);
+    return val & mask;
+}
+
+static inline uint64_t
+pci_quad_test_and_clear_mask(uint8_t *config, uint64_t mask)
+{
+    uint64_t val = pci_get_quad(config);
+    pci_set_quad(config, val & ~mask);
+    return val & mask;
+}
+
+static inline uint64_t
+pci_quad_test_and_set_mask(uint8_t *config, uint64_t mask)
+{
+    uint64_t val = pci_get_quad(config);
+    pci_set_quad(config, val | mask);
+    return val & mask;
+}
+
+/* Access a register specified by a mask */
+static inline void
+pci_set_byte_by_mask(uint8_t *config, uint8_t mask, uint8_t reg)
+{
+    uint8_t val = pci_get_byte(config);
+    uint8_t rval = reg << (ffs(mask) - 1);
+    pci_set_byte(config, (~mask & val) | (mask & rval));
+}
+
+static inline uint8_t
+pci_get_byte_by_mask(uint8_t *config, uint8_t mask)
+{
+    uint8_t val = pci_get_byte(config);
+    return (val & mask) >> (ffs(mask) - 1);
+}
+
+static inline void
+pci_set_word_by_mask(uint8_t *config, uint16_t mask, uint16_t reg)
+{
+    uint16_t val = pci_get_word(config);
+    uint16_t rval = reg << (ffs(mask) - 1);
+    pci_set_word(config, (~mask & val) | (mask & rval));
+}
+
+static inline uint16_t
+pci_get_word_by_mask(uint8_t *config, uint16_t mask)
+{
+    uint16_t val = pci_get_word(config);
+    return (val & mask) >> (ffs(mask) - 1);
+}
+
+static inline void
+pci_set_long_by_mask(uint8_t *config, uint32_t mask, uint32_t reg)
+{
+    uint32_t val = pci_get_long(config);
+    uint32_t rval = reg << (ffs(mask) - 1);
+    pci_set_long(config, (~mask & val) | (mask & rval));
+}
+
+static inline uint32_t
+pci_get_long_by_mask(uint8_t *config, uint32_t mask)
+{
+    uint32_t val = pci_get_long(config);
+    return (val & mask) >> (ffs(mask) - 1);
+}
+
+static inline void
+pci_set_quad_by_mask(uint8_t *config, uint64_t mask, uint64_t reg)
+{
+    uint64_t val = pci_get_quad(config);
+    uint64_t rval = reg << (ffs(mask) - 1);
+    pci_set_quad(config, (~mask & val) | (mask & rval));
+}
+
+static inline uint64_t
+pci_get_quad_by_mask(uint8_t *config, uint64_t mask)
+{
+    uint64_t val = pci_get_quad(config);
+    return (val & mask) >> (ffs(mask) - 1);
+}
+
+PCIDevice *pci_create_multifunction(PCIBus *bus, int devfn, bool multifunction,
+                                    const char *name);
+PCIDevice *pci_create_simple_multifunction(PCIBus *bus, int devfn,
+                                           bool multifunction,
+                                           const char *name);
+PCIDevice *pci_create(PCIBus *bus, int devfn, const char *name);
+PCIDevice *pci_create_simple(PCIBus *bus, int devfn, const char *name);
+
+static inline int pci_is_express(const PCIDevice *d)
+{
+    return d->cap_present & QEMU_PCI_CAP_EXPRESS;
+}
+
+static inline uint32_t pci_config_size(const PCIDevice *d)
+{
+    return pci_is_express(d) ? PCIE_CONFIG_SPACE_SIZE : PCI_CONFIG_SPACE_SIZE;
+}
+
+/* DMA access functions */
+static inline DMAContext *pci_dma_context(PCIDevice *dev)
+{
+    return dev->dma;
+}
+
+static inline int pci_dma_rw(PCIDevice *dev, dma_addr_t addr,
+                             void *buf, dma_addr_t len, DMADirection dir)
+{
+    dma_memory_rw(pci_dma_context(dev), addr, buf, len, dir);
+    return 0;
+}
+
+static inline int pci_dma_read(PCIDevice *dev, dma_addr_t addr,
+                               void *buf, dma_addr_t len)
+{
+    return pci_dma_rw(dev, addr, buf, len, DMA_DIRECTION_TO_DEVICE);
+}
+
+static inline int pci_dma_write(PCIDevice *dev, dma_addr_t addr,
+                                const void *buf, dma_addr_t len)
+{
+    return pci_dma_rw(dev, addr, (void *) buf, len, DMA_DIRECTION_FROM_DEVICE);
+}
+
+#define PCI_DMA_DEFINE_LDST(_l, _s, _bits)                              \
+    static inline uint##_bits##_t ld##_l##_pci_dma(PCIDevice *dev,      \
+                                                   dma_addr_t addr)     \
+    {                                                                   \
+        return ld##_l##_dma(pci_dma_context(dev), addr);                \
+    }                                                                   \
+    static inline void st##_s##_pci_dma(PCIDevice *dev,                 \
+                                        dma_addr_t addr, uint##_bits##_t val) \
+    {                                                                   \
+        st##_s##_dma(pci_dma_context(dev), addr, val);                  \
+    }
+
+PCI_DMA_DEFINE_LDST(ub, b, 8);
+PCI_DMA_DEFINE_LDST(uw_le, w_le, 16)
+PCI_DMA_DEFINE_LDST(l_le, l_le, 32);
+PCI_DMA_DEFINE_LDST(q_le, q_le, 64);
+PCI_DMA_DEFINE_LDST(uw_be, w_be, 16)
+PCI_DMA_DEFINE_LDST(l_be, l_be, 32);
+PCI_DMA_DEFINE_LDST(q_be, q_be, 64);
+
+#undef PCI_DMA_DEFINE_LDST
+
+static inline void *pci_dma_map(PCIDevice *dev, dma_addr_t addr,
+                                dma_addr_t *plen, DMADirection dir)
+{
+    void *buf;
+
+    buf = dma_memory_map(pci_dma_context(dev), addr, plen, dir);
+    return buf;
+}
+
+static inline void pci_dma_unmap(PCIDevice *dev, void *buffer, dma_addr_t len,
+                                 DMADirection dir, dma_addr_t access_len)
+{
+    dma_memory_unmap(pci_dma_context(dev), buffer, len, dir, access_len);
+}
+
+static inline void pci_dma_sglist_init(QEMUSGList *qsg, PCIDevice *dev,
+                                       int alloc_hint)
+{
+    qemu_sglist_init(qsg, alloc_hint, pci_dma_context(dev));
+}
+
+extern const VMStateDescription vmstate_pci_device;
+
+#define VMSTATE_PCI_DEVICE(_field, _state) {                         \
+    .name       = (stringify(_field)),                               \
+    .size       = sizeof(PCIDevice),                                 \
+    .vmsd       = &vmstate_pci_device,                               \
+    .flags      = VMS_STRUCT,                                        \
+    .offset     = vmstate_offset_value(_state, _field, PCIDevice),   \
+}
+
+#define VMSTATE_PCI_DEVICE_POINTER(_field, _state) {                 \
+    .name       = (stringify(_field)),                               \
+    .size       = sizeof(PCIDevice),                                 \
+    .vmsd       = &vmstate_pci_device,                               \
+    .flags      = VMS_STRUCT|VMS_POINTER,                            \
+    .offset     = vmstate_offset_pointer(_state, _field, PCIDevice), \
+}
+
+#endif
diff --git a/hw/pci/pci_bridge.c b/hw/pci/pci_bridge.c
new file mode 100644
index 0000000..4680501
--- /dev/null
+++ b/hw/pci/pci_bridge.c
@@ -0,0 +1,363 @@
+/*
+ * QEMU PCI bus manager
+ *
+ * Copyright (c) 2004 Fabrice Bellard
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to dea
+
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM
+
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+/*
+ * split out from pci.c
+ * Copyright (c) 2010 Isaku Yamahata <yamahata at valinux co jp>
+ *                    VA Linux Systems Japan K.K.
+ */
+
+#include "pci_bridge.h"
+#include "pci_internals.h"
+#include "range.h"
+
+/* PCI bridge subsystem vendor ID helper functions */
+#define PCI_SSVID_SIZEOF        8
+#define PCI_SSVID_SVID          4
+#define PCI_SSVID_SSID          6
+
+int pci_bridge_ssvid_init(PCIDevice *dev, uint8_t offset,
+                          uint16_t svid, uint16_t ssid)
+{
+    int pos;
+    pos = pci_add_capability(dev, PCI_CAP_ID_SSVID, offset, PCI_SSVID_SIZEOF);
+    if (pos < 0) {
+        return pos;
+    }
+
+    pci_set_word(dev->config + pos + PCI_SSVID_SVID, svid);
+    pci_set_word(dev->config + pos + PCI_SSVID_SSID, ssid);
+    return pos;
+}
+
+/* Accessor function to get parent bridge device from pci bus. */
+PCIDevice *pci_bridge_get_device(PCIBus *bus)
+{
+    return bus->parent_dev;
+}
+
+/* Accessor function to get secondary bus from pci-to-pci bridge device */
+PCIBus *pci_bridge_get_sec_bus(PCIBridge *br)
+{
+    return &br->sec_bus;
+}
+
+static uint32_t pci_config_get_io_base(const PCIDevice *d,
+                                       uint32_t base, uint32_t base_upper16)
+{
+    uint32_t val;
+
+    val = ((uint32_t)d->config[base] & PCI_IO_RANGE_MASK) << 8;
+    if (d->config[base] & PCI_IO_RANGE_TYPE_32) {
+        val |= (uint32_t)pci_get_word(d->config + base_upper16) << 16;
+    }
+    return val;
+}
+
+static pcibus_t pci_config_get_memory_base(const PCIDevice *d, uint32_t base)
+{
+    return ((pcibus_t)pci_get_word(d->config + base) & PCI_MEMORY_RANGE_MASK)
+        << 16;
+}
+
+static pcibus_t pci_config_get_pref_base(const PCIDevice *d,
+                                         uint32_t base, uint32_t upper)
+{
+    pcibus_t tmp;
+    pcibus_t val;
+
+    tmp = (pcibus_t)pci_get_word(d->config + base);
+    val = (tmp & PCI_PREF_RANGE_MASK) << 16;
+    if (tmp & PCI_PREF_RANGE_TYPE_64) {
+        val |= (pcibus_t)pci_get_long(d->config + upper) << 32;
+    }
+    return val;
+}
+
+/* accessor function to get bridge filtering base address */
+pcibus_t pci_bridge_get_base(const PCIDevice *bridge, uint8_t type)
+{
+    pcibus_t base;
+    if (type & PCI_BASE_ADDRESS_SPACE_IO) {
+        base = pci_config_get_io_base(bridge,
+                                      PCI_IO_BASE, PCI_IO_BASE_UPPER16);
+    } else {
+        if (type & PCI_BASE_ADDRESS_MEM_PREFETCH) {
+            base = pci_config_get_pref_base(
+                bridge, PCI_PREF_MEMORY_BASE, PCI_PREF_BASE_UPPER32);
+        } else {
+            base = pci_config_get_memory_base(bridge, PCI_MEMORY_BASE);
+        }
+    }
+
+    return base;
+}
+
+/* accessor funciton to get bridge filtering limit */
+pcibus_t pci_bridge_get_limit(const PCIDevice *bridge, uint8_t type)
+{
+    pcibus_t limit;
+    if (type & PCI_BASE_ADDRESS_SPACE_IO) {
+        limit = pci_config_get_io_base(bridge,
+                                      PCI_IO_LIMIT, PCI_IO_LIMIT_UPPER16);
+        limit |= 0xfff;         /* PCI bridge spec 3.2.5.6. */
+    } else {
+        if (type & PCI_BASE_ADDRESS_MEM_PREFETCH) {
+            limit = pci_config_get_pref_base(
+                bridge, PCI_PREF_MEMORY_LIMIT, PCI_PREF_LIMIT_UPPER32);
+        } else {
+            limit = pci_config_get_memory_base(bridge, PCI_MEMORY_LIMIT);
+        }
+        limit |= 0xfffff;       /* PCI bridge spec 3.2.5.{1, 8}. */
+    }
+    return limit;
+}
+
+static void pci_bridge_init_alias(PCIBridge *bridge, MemoryRegion *alias,
+                                  uint8_t type, const char *name,
+                                  MemoryRegion *space,
+                                  MemoryRegion *parent_space,
+                                  bool enabled)
+{
+    pcibus_t base = pci_bridge_get_base(&bridge->dev, type);
+    pcibus_t limit = pci_bridge_get_limit(&bridge->dev, type);
+    /* TODO: this doesn't handle base = 0 limit = 2^64 - 1 correctly.
+     * Apparently no way to do this with existing memory APIs. */
+    pcibus_t size = enabled && limit >= base ? limit + 1 - base : 0;
+
+    memory_region_init_alias(alias, name, space, base, size);
+    memory_region_add_subregion_overlap(parent_space, base, alias, 1);
+}
+
+static PCIBridgeWindows *pci_bridge_region_init(PCIBridge *br)
+{
+    PCIBus *parent = br->dev.bus;
+    PCIBridgeWindows *w = g_new(PCIBridgeWindows, 1);
+    uint16_t cmd = pci_get_word(br->dev.config + PCI_COMMAND);
+
+    pci_bridge_init_alias(br, &w->alias_pref_mem,
+                          PCI_BASE_ADDRESS_MEM_PREFETCH,
+                          "pci_bridge_pref_mem",
+                          &br->address_space_mem,
+                          parent->address_space_mem,
+                          cmd & PCI_COMMAND_MEMORY);
+    pci_bridge_init_alias(br, &w->alias_mem,
+                          PCI_BASE_ADDRESS_SPACE_MEMORY,
+                          "pci_bridge_mem",
+                          &br->address_space_mem,
+                          parent->address_space_mem,
+                          cmd & PCI_COMMAND_MEMORY);
+    pci_bridge_init_alias(br, &w->alias_io,
+                          PCI_BASE_ADDRESS_SPACE_IO,
+                          "pci_bridge_io",
+                          &br->address_space_io,
+                          parent->address_space_io,
+                          cmd & PCI_COMMAND_IO);
+   /* TODO: optinal VGA and VGA palette snooping support. */
+
+    return w;
+}
+
+static void pci_bridge_region_del(PCIBridge *br, PCIBridgeWindows *w)
+{
+    PCIBus *parent = br->dev.bus;
+
+    memory_region_del_subregion(parent->address_space_io, &w->alias_io);
+    memory_region_del_subregion(parent->address_space_mem, &w->alias_mem);
+    memory_region_del_subregion(parent->address_space_mem, &w->alias_pref_mem);
+}
+
+static void pci_bridge_region_cleanup(PCIBridge *br, PCIBridgeWindows *w)
+{
+    memory_region_destroy(&w->alias_io);
+    memory_region_destroy(&w->alias_mem);
+    memory_region_destroy(&w->alias_pref_mem);
+    g_free(w);
+}
+
+static void pci_bridge_update_mappings(PCIBridge *br)
+{
+    PCIBridgeWindows *w = br->windows;
+
+    /* Make updates atomic to: handle the case of one VCPU updating the bridge
+     * while another accesses an unaffected region. */
+    memory_region_transaction_begin();
+    pci_bridge_region_del(br, br->windows);
+    br->windows = pci_bridge_region_init(br);
+    memory_region_transaction_commit();
+    pci_bridge_region_cleanup(br, w);
+}
+
+/* default write_config function for PCI-to-PCI bridge */
+void pci_bridge_write_config(PCIDevice *d,
+                             uint32_t address, uint32_t val, int len)
+{
+    PCIBridge *s = container_of(d, PCIBridge, dev);
+    uint16_t oldctl = pci_get_word(d->config + PCI_BRIDGE_CONTROL);
+    uint16_t newctl;
+
+    pci_default_write_config(d, address, val, len);
+
+    if (ranges_overlap(address, len, PCI_COMMAND, 2) ||
+
+        /* io base/limit */
+        ranges_overlap(address, len, PCI_IO_BASE, 2) ||
+
+        /* memory base/limit, prefetchable base/limit and
+           io base/limit upper 16 */
+        ranges_overlap(address, len, PCI_MEMORY_BASE, 20)) {
+        pci_bridge_update_mappings(s);
+    }
+
+    newctl = pci_get_word(d->config + PCI_BRIDGE_CONTROL);
+    if (~oldctl & newctl & PCI_BRIDGE_CTL_BUS_RESET) {
+        /* Trigger hot reset on 0->1 transition. */
+        pci_bus_reset(&s->sec_bus);
+    }
+}
+
+void pci_bridge_disable_base_limit(PCIDevice *dev)
+{
+    uint8_t *conf = dev->config;
+
+    pci_byte_test_and_set_mask(conf + PCI_IO_BASE,
+                               PCI_IO_RANGE_MASK & 0xff);
+    pci_byte_test_and_clear_mask(conf + PCI_IO_LIMIT,
+                                 PCI_IO_RANGE_MASK & 0xff);
+    pci_word_test_and_set_mask(conf + PCI_MEMORY_BASE,
+                               PCI_MEMORY_RANGE_MASK & 0xffff);
+    pci_word_test_and_clear_mask(conf + PCI_MEMORY_LIMIT,
+                                 PCI_MEMORY_RANGE_MASK & 0xffff);
+    pci_word_test_and_set_mask(conf + PCI_PREF_MEMORY_BASE,
+                               PCI_PREF_RANGE_MASK & 0xffff);
+    pci_word_test_and_clear_mask(conf + PCI_PREF_MEMORY_LIMIT,
+                                 PCI_PREF_RANGE_MASK & 0xffff);
+    pci_set_long(conf + PCI_PREF_BASE_UPPER32, 0);
+    pci_set_long(conf + PCI_PREF_LIMIT_UPPER32, 0);
+}
+
+/* reset bridge specific configuration registers */
+void pci_bridge_reset(DeviceState *qdev)
+{
+    PCIDevice *dev = PCI_DEVICE(qdev);
+    uint8_t *conf = dev->config;
+
+    conf[PCI_PRIMARY_BUS] = 0;
+    conf[PCI_SECONDARY_BUS] = 0;
+    conf[PCI_SUBORDINATE_BUS] = 0;
+    conf[PCI_SEC_LATENCY_TIMER] = 0;
+
+    /*
+     * the default values for base/limit registers aren't specified
+     * in the PCI-to-PCI-bridge spec. So we don't thouch them here.
+     * Each implementation can override it.
+     * typical implementation does
+     * zero base/limit registers or
+     * disable forwarding: pci_bridge_disable_base_limit()
+     * If disable forwarding is wanted, call pci_bridge_disable_base_limit()
+     * after this function.
+     */
+    pci_byte_test_and_clear_mask(conf + PCI_IO_BASE,
+                                 PCI_IO_RANGE_MASK & 0xff);
+    pci_byte_test_and_clear_mask(conf + PCI_IO_LIMIT,
+                                 PCI_IO_RANGE_MASK & 0xff);
+    pci_word_test_and_clear_mask(conf + PCI_MEMORY_BASE,
+                                 PCI_MEMORY_RANGE_MASK & 0xffff);
+    pci_word_test_and_clear_mask(conf + PCI_MEMORY_LIMIT,
+                                 PCI_MEMORY_RANGE_MASK & 0xffff);
+    pci_word_test_and_clear_mask(conf + PCI_PREF_MEMORY_BASE,
+                                 PCI_PREF_RANGE_MASK & 0xffff);
+    pci_word_test_and_clear_mask(conf + PCI_PREF_MEMORY_LIMIT,
+                                 PCI_PREF_RANGE_MASK & 0xffff);
+    pci_set_long(conf + PCI_PREF_BASE_UPPER32, 0);
+    pci_set_long(conf + PCI_PREF_LIMIT_UPPER32, 0);
+
+    pci_set_word(conf + PCI_BRIDGE_CONTROL, 0);
+}
+
+/* default qdev initialization function for PCI-to-PCI bridge */
+int pci_bridge_initfn(PCIDevice *dev)
+{
+    PCIBus *parent = dev->bus;
+    PCIBridge *br = DO_UPCAST(PCIBridge, dev, dev);
+    PCIBus *sec_bus = &br->sec_bus;
+
+    pci_word_test_and_set_mask(dev->config + PCI_STATUS,
+                               PCI_STATUS_66MHZ | PCI_STATUS_FAST_BACK);
+    pci_config_set_class(dev->config, PCI_CLASS_BRIDGE_PCI);
+    dev->config[PCI_HEADER_TYPE] =
+        (dev->config[PCI_HEADER_TYPE] & PCI_HEADER_TYPE_MULTI_FUNCTION) |
+        PCI_HEADER_TYPE_BRIDGE;
+    pci_set_word(dev->config + PCI_SEC_STATUS,
+                 PCI_STATUS_66MHZ | PCI_STATUS_FAST_BACK);
+
+    /*
+     * If we don't specify the name, the bus will be addressed as <id>.0, where
+     * id is the device id.
+     * Since PCI Bridge devices have a single bus each, we don't need the 
index:
+     * let users address the bus using the device name.
+     */
+    if (!br->bus_name && dev->qdev.id && *dev->qdev.id) {
+           br->bus_name = dev->qdev.id;
+    }
+
+    qbus_create_inplace(&sec_bus->qbus, TYPE_PCI_BUS, &dev->qdev,
+                        br->bus_name);
+    sec_bus->parent_dev = dev;
+    sec_bus->map_irq = br->map_irq;
+    sec_bus->address_space_mem = &br->address_space_mem;
+    memory_region_init(&br->address_space_mem, "pci_bridge_pci", INT64_MAX);
+    sec_bus->address_space_io = &br->address_space_io;
+    memory_region_init(&br->address_space_io, "pci_bridge_io", 65536);
+    br->windows = pci_bridge_region_init(br);
+    QLIST_INIT(&sec_bus->child);
+    QLIST_INSERT_HEAD(&parent->child, sec_bus, sibling);
+    return 0;
+}
+
+/* default qdev clean up function for PCI-to-PCI bridge */
+void pci_bridge_exitfn(PCIDevice *pci_dev)
+{
+    PCIBridge *s = DO_UPCAST(PCIBridge, dev, pci_dev);
+    assert(QLIST_EMPTY(&s->sec_bus.child));
+    QLIST_REMOVE(&s->sec_bus, sibling);
+    pci_bridge_region_del(s, s->windows);
+    pci_bridge_region_cleanup(s, s->windows);
+    memory_region_destroy(&s->address_space_mem);
+    memory_region_destroy(&s->address_space_io);
+    /* qbus_free() is called automatically by qdev_free() */
+}
+
+/*
+ * before qdev initialization(qdev_init()), this function sets bus_name and
+ * map_irq callback which are necessry for pci_bridge_initfn() to
+ * initialize bus.
+ */
+void pci_bridge_map_irq(PCIBridge *br, const char* bus_name,
+                        pci_map_irq_fn map_irq)
+{
+    br->map_irq = map_irq;
+    br->bus_name = bus_name;
+}
diff --git a/hw/pci/pci_bridge.h b/hw/pci/pci_bridge.h
new file mode 100644
index 0000000..a00accc
--- /dev/null
+++ b/hw/pci/pci_bridge.h
@@ -0,0 +1,66 @@
+/*
+ * QEMU PCI bridge
+ *
+ * Copyright (c) 2004 Fabrice Bellard
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ * split out pci bus specific stuff from pci.[hc] to pci_bridge.[hc]
+ * Copyright (c) 2009 Isaku Yamahata <yamahata at valinux co jp>
+ *                    VA Linux Systems Japan K.K.
+ *
+ */
+
+#ifndef QEMU_PCI_BRIDGE_H
+#define QEMU_PCI_BRIDGE_H
+
+#include "pci.h"
+
+int pci_bridge_ssvid_init(PCIDevice *dev, uint8_t offset,
+                          uint16_t svid, uint16_t ssid);
+
+PCIDevice *pci_bridge_get_device(PCIBus *bus);
+PCIBus *pci_bridge_get_sec_bus(PCIBridge *br);
+
+pcibus_t pci_bridge_get_base(const PCIDevice *bridge, uint8_t type);
+pcibus_t pci_bridge_get_limit(const PCIDevice *bridge, uint8_t type);
+
+void pci_bridge_write_config(PCIDevice *d,
+                             uint32_t address, uint32_t val, int len);
+void pci_bridge_disable_base_limit(PCIDevice *dev);
+void pci_bridge_reset_reg(PCIDevice *dev);
+void pci_bridge_reset(DeviceState *qdev);
+
+int pci_bridge_initfn(PCIDevice *pci_dev);
+void pci_bridge_exitfn(PCIDevice *pci_dev);
+
+
+/*
+ * before qdev initialization(qdev_init()), this function sets bus_name and
+ * map_irq callback which are necessry for pci_bridge_initfn() to
+ * initialize bus.
+ */
+void pci_bridge_map_irq(PCIBridge *br, const char* bus_name,
+                        pci_map_irq_fn map_irq);
+
+#endif  /* QEMU_PCI_BRIDGE_H */
+/*
+ * Local variables:
+ *  c-indent-level: 4
+ *  c-basic-offset: 4
+ *  tab-width: 8
+ *  indent-tab-mode: nil
+ * End:
+ */
diff --git a/hw/pci/pci_host.c b/hw/pci/pci_host.c
new file mode 100644
index 0000000..68e328c
--- /dev/null
+++ b/hw/pci/pci_host.c
@@ -0,0 +1,180 @@
+/*
+ * pci_host.c
+ *
+ * Copyright (c) 2009 Isaku Yamahata <yamahata at valinux co jp>
+ *                    VA Linux Systems Japan K.K.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "pci.h"
+#include "pci_host.h"
+
+/* debug PCI */
+//#define DEBUG_PCI
+
+#ifdef DEBUG_PCI
+#define PCI_DPRINTF(fmt, ...) \
+do { printf("pci_host_data: " fmt , ## __VA_ARGS__); } while (0)
+#else
+#define PCI_DPRINTF(fmt, ...)
+#endif
+
+/*
+ * PCI address
+ * bit 16 - 24: bus number
+ * bit  8 - 15: devfun number
+ * bit  0 -  7: offset in configuration space of a given pci device
+ */
+
+/* the helper functio to get a PCIDeice* for a given pci address */
+static inline PCIDevice *pci_dev_find_by_addr(PCIBus *bus, uint32_t addr)
+{
+    uint8_t bus_num = addr >> 16;
+    uint8_t devfn = addr >> 8;
+
+    return pci_find_device(bus, bus_num, devfn);
+}
+
+void pci_host_config_write_common(PCIDevice *pci_dev, uint32_t addr,
+                                  uint32_t limit, uint32_t val, uint32_t len)
+{
+    assert(len <= 4);
+    pci_dev->config_write(pci_dev, addr, val, MIN(len, limit - addr));
+}
+
+uint32_t pci_host_config_read_common(PCIDevice *pci_dev, uint32_t addr,
+                                     uint32_t limit, uint32_t len)
+{
+    assert(len <= 4);
+    return pci_dev->config_read(pci_dev, addr, MIN(len, limit - addr));
+}
+
+void pci_data_write(PCIBus *s, uint32_t addr, uint32_t val, int len)
+{
+    PCIDevice *pci_dev = pci_dev_find_by_addr(s, addr);
+    uint32_t config_addr = addr & (PCI_CONFIG_SPACE_SIZE - 1);
+
+    if (!pci_dev) {
+        return;
+    }
+
+    PCI_DPRINTF("%s: %s: addr=%02" PRIx32 " val=%08" PRIx32 " len=%d\n",
+                __func__, pci_dev->name, config_addr, val, len);
+    pci_host_config_write_common(pci_dev, config_addr, PCI_CONFIG_SPACE_SIZE,
+                                 val, len);
+}
+
+uint32_t pci_data_read(PCIBus *s, uint32_t addr, int len)
+{
+    PCIDevice *pci_dev = pci_dev_find_by_addr(s, addr);
+    uint32_t config_addr = addr & (PCI_CONFIG_SPACE_SIZE - 1);
+    uint32_t val;
+
+    if (!pci_dev) {
+        return ~0x0;
+    }
+
+    val = pci_host_config_read_common(pci_dev, config_addr,
+                                      PCI_CONFIG_SPACE_SIZE, len);
+    PCI_DPRINTF("%s: %s: addr=%02"PRIx32" val=%08"PRIx32" len=%d\n",
+                __func__, pci_dev->name, config_addr, val, len);
+
+    return val;
+}
+
+static void pci_host_config_write(void *opaque, hwaddr addr,
+                                  uint64_t val, unsigned len)
+{
+    PCIHostState *s = opaque;
+
+    PCI_DPRINTF("%s addr " TARGET_FMT_plx " len %d val %"PRIx64"\n",
+                __func__, addr, len, val);
+    if (addr != 0 || len != 4) {
+        return;
+    }
+    s->config_reg = val;
+}
+
+static uint64_t pci_host_config_read(void *opaque, hwaddr addr,
+                                     unsigned len)
+{
+    PCIHostState *s = opaque;
+    uint32_t val = s->config_reg;
+
+    PCI_DPRINTF("%s addr " TARGET_FMT_plx " len %d val %"PRIx32"\n",
+                __func__, addr, len, val);
+    return val;
+}
+
+static void pci_host_data_write(void *opaque, hwaddr addr,
+                                uint64_t val, unsigned len)
+{
+    PCIHostState *s = opaque;
+    PCI_DPRINTF("write addr " TARGET_FMT_plx " len %d val %x\n",
+                addr, len, (unsigned)val);
+    if (s->config_reg & (1u << 31))
+        pci_data_write(s->bus, s->config_reg | (addr & 3), val, len);
+}
+
+static uint64_t pci_host_data_read(void *opaque,
+                                   hwaddr addr, unsigned len)
+{
+    PCIHostState *s = opaque;
+    uint32_t val;
+    if (!(s->config_reg & (1 << 31)))
+        return 0xffffffff;
+    val = pci_data_read(s->bus, s->config_reg | (addr & 3), len);
+    PCI_DPRINTF("read addr " TARGET_FMT_plx " len %d val %x\n",
+                addr, len, val);
+    return val;
+}
+
+const MemoryRegionOps pci_host_conf_le_ops = {
+    .read = pci_host_config_read,
+    .write = pci_host_config_write,
+    .endianness = DEVICE_LITTLE_ENDIAN,
+};
+
+const MemoryRegionOps pci_host_conf_be_ops = {
+    .read = pci_host_config_read,
+    .write = pci_host_config_write,
+    .endianness = DEVICE_BIG_ENDIAN,
+};
+
+const MemoryRegionOps pci_host_data_le_ops = {
+    .read = pci_host_data_read,
+    .write = pci_host_data_write,
+    .endianness = DEVICE_LITTLE_ENDIAN,
+};
+
+const MemoryRegionOps pci_host_data_be_ops = {
+    .read = pci_host_data_read,
+    .write = pci_host_data_write,
+    .endianness = DEVICE_BIG_ENDIAN,
+};
+
+static const TypeInfo pci_host_type_info = {
+    .name = TYPE_PCI_HOST_BRIDGE,
+    .parent = TYPE_SYS_BUS_DEVICE,
+    .abstract = true,
+    .instance_size = sizeof(PCIHostState),
+};
+
+static void pci_host_register_types(void)
+{
+    type_register_static(&pci_host_type_info);
+}
+
+type_init(pci_host_register_types)
diff --git a/hw/pci/pci_host.h b/hw/pci/pci_host.h
new file mode 100644
index 0000000..4b9c300
--- /dev/null
+++ b/hw/pci/pci_host.h
@@ -0,0 +1,62 @@
+/*
+ * QEMU Common PCI Host bridge configuration data space access routines.
+ *
+ * Copyright (c) 2006 Fabrice Bellard
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to 
deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 
FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+/* Worker routines for a PCI host controller that uses an {address,data}
+   register pair to access PCI configuration space.  */
+
+#ifndef PCI_HOST_H
+#define PCI_HOST_H
+
+#include "sysbus.h"
+
+#define TYPE_PCI_HOST_BRIDGE "pci-host-bridge"
+#define PCI_HOST_BRIDGE(obj) \
+    OBJECT_CHECK(PCIHostState, (obj), TYPE_PCI_HOST_BRIDGE)
+
+struct PCIHostState {
+    SysBusDevice busdev;
+
+    MemoryRegion conf_mem;
+    MemoryRegion data_mem;
+    MemoryRegion mmcfg;
+    MemoryRegion *address_space;
+    uint32_t config_reg;
+    PCIBus *bus;
+};
+
+/* common internal helpers for PCI/PCIe hosts, cut off overflows */
+void pci_host_config_write_common(PCIDevice *pci_dev, uint32_t addr,
+                                  uint32_t limit, uint32_t val, uint32_t len);
+uint32_t pci_host_config_read_common(PCIDevice *pci_dev, uint32_t addr,
+                                     uint32_t limit, uint32_t len);
+
+void pci_data_write(PCIBus *s, uint32_t addr, uint32_t val, int len);
+uint32_t pci_data_read(PCIBus *s, uint32_t addr, int len);
+
+extern const MemoryRegionOps pci_host_conf_le_ops;
+extern const MemoryRegionOps pci_host_conf_be_ops;
+extern const MemoryRegionOps pci_host_data_le_ops;
+extern const MemoryRegionOps pci_host_data_be_ops;
+
+#endif /* PCI_HOST_H */
diff --git a/hw/pci/pci_ids.h b/hw/pci/pci_ids.h
new file mode 100644
index 0000000..5df7245
--- /dev/null
+++ b/hw/pci/pci_ids.h
@@ -0,0 +1,147 @@
+/*
+ *      PCI Class, Vendor and Device IDs
+ *
+ *      Please keep sorted.
+ *
+ *      Abbreviated version of linux/pci_ids.h
+ *
+ *      QEMU-specific definitions belong in pci.h
+ */
+
+/* Device classes and subclasses */
+
+#define PCI_BASE_CLASS_STORAGE           0x01
+#define PCI_BASE_CLASS_NETWORK           0x02
+
+#define PCI_CLASS_STORAGE_SCSI           0x0100
+#define PCI_CLASS_STORAGE_IDE            0x0101
+#define PCI_CLASS_STORAGE_RAID           0x0104
+#define PCI_CLASS_STORAGE_SATA           0x0106
+#define PCI_CLASS_STORAGE_OTHER          0x0180
+
+#define PCI_CLASS_NETWORK_ETHERNET       0x0200
+
+#define PCI_CLASS_DISPLAY_VGA            0x0300
+#define PCI_CLASS_DISPLAY_OTHER          0x0380
+
+#define PCI_CLASS_MULTIMEDIA_AUDIO       0x0401
+
+#define PCI_CLASS_MEMORY_RAM             0x0500
+
+#define PCI_CLASS_SYSTEM_OTHER           0x0880
+
+#define PCI_CLASS_SERIAL_USB             0x0c03
+#define PCI_CLASS_SERIAL_SMBUS           0x0c05
+
+#define PCI_CLASS_BRIDGE_HOST            0x0600
+#define PCI_CLASS_BRIDGE_ISA             0x0601
+#define PCI_CLASS_BRIDGE_PCI             0x0604
+#define PCI_CLASS_BRDIGE_PCI_INF_SUB     0x01
+#define PCI_CLASS_BRIDGE_OTHER           0x0680
+
+#define PCI_CLASS_COMMUNICATION_SERIAL   0x0700
+#define PCI_CLASS_COMMUNICATION_OTHER    0x0780
+
+#define PCI_CLASS_PROCESSOR_CO           0x0b40
+#define PCI_CLASS_PROCESSOR_POWERPC      0x0b20
+
+#define PCI_CLASS_OTHERS                 0xff
+
+/* Vendors and devices.  Sort key: vendor first, device next. */
+
+#define PCI_VENDOR_ID_LSI_LOGIC          0x1000
+#define PCI_DEVICE_ID_LSI_53C895A        0x0012
+#define PCI_DEVICE_ID_LSI_SAS1078        0x0060
+
+#define PCI_VENDOR_ID_DEC                0x1011
+#define PCI_DEVICE_ID_DEC_21154          0x0026
+
+#define PCI_VENDOR_ID_CIRRUS             0x1013
+
+#define PCI_VENDOR_ID_IBM                0x1014
+
+#define PCI_VENDOR_ID_AMD                0x1022
+#define PCI_DEVICE_ID_AMD_LANCE          0x2000
+#define PCI_DEVICE_ID_AMD_SCSI           0x2020
+
+#define PCI_VENDOR_ID_TI                 0x104c
+
+#define PCI_VENDOR_ID_MOTOROLA           0x1057
+#define PCI_DEVICE_ID_MOTOROLA_MPC106    0x0002
+#define PCI_DEVICE_ID_MOTOROLA_RAVEN     0x4801
+
+#define PCI_VENDOR_ID_APPLE              0x106b
+#define PCI_DEVICE_ID_APPLE_UNI_N_AGP    0x0020
+#define PCI_DEVICE_ID_APPLE_U3_AGP       0x004b
+
+#define PCI_VENDOR_ID_SUN                0x108e
+#define PCI_DEVICE_ID_SUN_EBUS           0x1000
+#define PCI_DEVICE_ID_SUN_SIMBA          0x5000
+#define PCI_DEVICE_ID_SUN_SABRE          0xa000
+
+#define PCI_VENDOR_ID_CMD                0x1095
+#define PCI_DEVICE_ID_CMD_646            0x0646
+
+#define PCI_VENDOR_ID_REALTEK            0x10ec
+#define PCI_DEVICE_ID_REALTEK_8139       0x8139
+
+#define PCI_VENDOR_ID_XILINX             0x10ee
+
+#define PCI_VENDOR_ID_VIA                0x1106
+#define PCI_DEVICE_ID_VIA_ISA_BRIDGE     0x0686
+#define PCI_DEVICE_ID_VIA_IDE            0x0571
+#define PCI_DEVICE_ID_VIA_UHCI           0x3038
+#define PCI_DEVICE_ID_VIA_ACPI           0x3057
+#define PCI_DEVICE_ID_VIA_AC97           0x3058
+#define PCI_DEVICE_ID_VIA_MC97           0x3068
+
+#define PCI_VENDOR_ID_MARVELL            0x11ab
+
+#define PCI_VENDOR_ID_ENSONIQ            0x1274
+#define PCI_DEVICE_ID_ENSONIQ_ES1370     0x5000
+
+#define PCI_VENDOR_ID_FREESCALE          0x1957
+#define PCI_DEVICE_ID_MPC8533E           0x0030
+
+#define PCI_VENDOR_ID_INTEL              0x8086
+#define PCI_DEVICE_ID_INTEL_82378        0x0484
+#define PCI_DEVICE_ID_INTEL_82441        0x1237
+#define PCI_DEVICE_ID_INTEL_82801AA_5    0x2415
+#define PCI_DEVICE_ID_INTEL_82801BA_11   0x244e
+#define PCI_DEVICE_ID_INTEL_82801D       0x24CD
+#define PCI_DEVICE_ID_INTEL_ESB_9        0x25ab
+#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_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_ICH9_0       0x2910
+#define PCI_DEVICE_ID_INTEL_ICH9_1       0x2917
+#define PCI_DEVICE_ID_INTEL_ICH9_2       0x2912
+#define PCI_DEVICE_ID_INTEL_ICH9_3       0x2913
+#define PCI_DEVICE_ID_INTEL_ICH9_4       0x2914
+#define PCI_DEVICE_ID_INTEL_ICH9_5       0x2919
+#define PCI_DEVICE_ID_INTEL_ICH9_6       0x2930
+#define PCI_DEVICE_ID_INTEL_ICH9_7       0x2916
+#define PCI_DEVICE_ID_INTEL_ICH9_8       0x2918
+
+#define PCI_DEVICE_ID_INTEL_82801I_UHCI1 0x2934
+#define PCI_DEVICE_ID_INTEL_82801I_UHCI2 0x2935
+#define PCI_DEVICE_ID_INTEL_82801I_UHCI3 0x2936
+#define PCI_DEVICE_ID_INTEL_82801I_UHCI4 0x2937
+#define PCI_DEVICE_ID_INTEL_82801I_UHCI5 0x2938
+#define PCI_DEVICE_ID_INTEL_82801I_UHCI6 0x2939
+#define PCI_DEVICE_ID_INTEL_82801I_EHCI1 0x293a
+#define PCI_DEVICE_ID_INTEL_82801I_EHCI2 0x293c
+#define PCI_DEVICE_ID_INTEL_82599_SFP_VF 0x10ed
+
+#define PCI_DEVICE_ID_INTEL_Q35_MCH      0x29c0
+
+#define PCI_VENDOR_ID_XEN               0x5853
+#define PCI_DEVICE_ID_XEN_PLATFORM      0x0001
+
+#define PCI_VENDOR_ID_NEC                0x1033
+#define PCI_DEVICE_ID_NEC_UPD720200      0x0194
diff --git a/hw/pci/pci_internals.h b/hw/pci/pci_internals.h
new file mode 100644
index 0000000..21d0ce6
--- /dev/null
+++ b/hw/pci/pci_internals.h
@@ -0,0 +1,78 @@
+#ifndef QEMU_PCI_INTERNALS_H
+#define QEMU_PCI_INTERNALS_H
+
+/*
+ * This header files is private to pci.c and pci_bridge.c
+ * So following structures are opaque to others and shouldn't be
+ * accessed.
+ *
+ * For pci-to-pci bridge needs to include this header file to embed
+ * PCIBridge in its structure or to get sizeof(PCIBridge),
+ * However, they shouldn't access those following members directly.
+ * Use accessor function in pci.h, pci_bridge.h
+ */
+
+#define TYPE_PCI_BUS "PCI"
+#define PCI_BUS(obj) OBJECT_CHECK(PCIBus, (obj), TYPE_PCI_BUS)
+
+struct PCIBus {
+    BusState qbus;
+    PCIDMAContextFunc dma_context_fn;
+    void *dma_context_opaque;
+    uint8_t devfn_min;
+    pci_set_irq_fn set_irq;
+    pci_map_irq_fn map_irq;
+    pci_route_irq_fn route_intx_to_irq;
+    pci_hotplug_fn hotplug;
+    DeviceState *hotplug_qdev;
+    void *irq_opaque;
+    PCIDevice *devices[PCI_SLOT_MAX * PCI_FUNC_MAX];
+    PCIDevice *parent_dev;
+    MemoryRegion *address_space_mem;
+    MemoryRegion *address_space_io;
+
+    QLIST_HEAD(, PCIBus) child; /* this will be replaced by qdev later */
+    QLIST_ENTRY(PCIBus) sibling;/* this will be replaced by qdev later */
+
+    /* The bus IRQ state is the logical OR of the connected devices.
+       Keep a count of the number of devices with raised IRQs.  */
+    int nirq;
+    int *irq_count;
+};
+
+typedef struct PCIBridgeWindows PCIBridgeWindows;
+
+/*
+ * Aliases for each of the address space windows that the bridge
+ * can forward. Mapped into the bridge's parent's address space,
+ * as subregions.
+ */
+struct PCIBridgeWindows {
+    MemoryRegion alias_pref_mem;
+    MemoryRegion alias_mem;
+    MemoryRegion alias_io;
+};
+
+struct PCIBridge {
+    PCIDevice dev;
+
+    /* private member */
+    PCIBus sec_bus;
+    /*
+     * Memory regions for the bridge's address spaces.  These regions are not
+     * directly added to system_memory/system_io or its descendants.
+     * Bridge's secondary bus points to these, so that devices
+     * under the bridge see these regions as its address spaces.
+     * The regions are as large as the entire address space -
+     * they don't take into account any windows.
+     */
+    MemoryRegion address_space_mem;
+    MemoryRegion address_space_io;
+
+    PCIBridgeWindows *windows;
+
+    pci_map_irq_fn map_irq;
+    const char *bus_name;
+};
+
+#endif /* QEMU_PCI_INTERNALS_H */
diff --git a/hw/pci/pci_regs.h b/hw/pci/pci_regs.h
new file mode 100644
index 0000000..56a404b
--- /dev/null
+++ b/hw/pci/pci_regs.h
@@ -0,0 +1,717 @@
+/*
+ *     pci_regs.h
+ *
+ *     PCI standard defines
+ *     Copyright 1994, Drew Eckhardt
+ *     Copyright 1997--1999 Martin Mares <address@hidden>
+ *
+ *     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
+ *
+ *     For hypertransport information, please consult the following manuals
+ *     from http://www.hypertransport.org
+ *
+ *     The Hypertransport I/O Link Specification
+ */
+
+#ifndef LINUX_PCI_REGS_H
+#define LINUX_PCI_REGS_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_COMMAND_INTX_DISABLE 0x400 /* INTx Emulation Disable */
+
+#define PCI_STATUS             0x06    /* 16 bits */
+#define  PCI_STATUS_INTERRUPT  0x08    /* Interrupt status */
+#define  PCI_STATUS_CAP_LIST   0x10    /* Support Capability List */
+#define  PCI_STATUS_66MHZ      0x20    /* Support 66 Mhz PCI 2.1 bus */
+#define  PCI_STATUS_UDF                0x40    /* Support User Definable 
Features [obsolete] */
+#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 [obsolete] */
+#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)
+
+#define PCI_CAPABILITY_LIST    0x34    /* Offset of first capability list 
entry */
+
+/* 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        0x0fUL  /* I/O bridging type */
+#define  PCI_IO_RANGE_TYPE_16  0x00
+#define  PCI_IO_RANGE_TYPE_32  0x01
+#define  PCI_IO_RANGE_MASK     (~0x0fUL)
+#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 0x0fUL
+#define  PCI_MEMORY_RANGE_MASK (~0x0fUL)
+#define PCI_PREF_MEMORY_BASE   0x24    /* Prefetchable memory range behind */
+#define PCI_PREF_MEMORY_LIMIT  0x26
+#define  PCI_PREF_RANGE_TYPE_MASK 0x0fUL
+#define  PCI_PREF_RANGE_TYPE_32        0x00
+#define  PCI_PREF_RANGE_TYPE_64        0x01
+#define  PCI_PREF_RANGE_MASK   (~0x0fUL)
+#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 same as for htype 0 */
+/* 0x35-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_ISA    0x04    /* Enable ISA mode */
+#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) */
+#define PCI_CB_CAPABILITY_LIST 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  (~0x03UL)
+/* 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 */
+
+/* Capability lists */
+
+#define PCI_CAP_LIST_ID                0       /* Capability ID */
+#define  PCI_CAP_ID_PM         0x01    /* Power Management */
+#define  PCI_CAP_ID_AGP                0x02    /* Accelerated Graphics Port */
+#define  PCI_CAP_ID_VPD                0x03    /* Vital Product Data */
+#define  PCI_CAP_ID_SLOTID     0x04    /* Slot Identification */
+#define  PCI_CAP_ID_MSI                0x05    /* Message Signalled Interrupts 
*/
+#define  PCI_CAP_ID_CHSWP      0x06    /* CompactPCI HotSwap */
+#define  PCI_CAP_ID_PCIX       0x07    /* PCI-X */
+#define  PCI_CAP_ID_HT         0x08    /* HyperTransport */
+#define  PCI_CAP_ID_VNDR       0x09    /* Vendor specific */
+#define  PCI_CAP_ID_DBG                0x0A    /* Debug port */
+#define  PCI_CAP_ID_CCRC       0x0B    /* CompactPCI Central Resource Control 
*/
+#define  PCI_CAP_ID_SHPC       0x0C    /* PCI Standard Hot-Plug Controller */
+#define  PCI_CAP_ID_SSVID      0x0D    /* Bridge subsystem vendor/device ID */
+#define  PCI_CAP_ID_AGP3       0x0E    /* AGP Target PCI-PCI bridge */
+#define  PCI_CAP_ID_EXP        0x10    /* PCI Express */
+#define  PCI_CAP_ID_MSIX       0x11    /* MSI-X */
+#define  PCI_CAP_ID_SATA       0x12    /* Serial ATA */
+#define  PCI_CAP_ID_AF         0x13    /* PCI Advanced Features */
+#define PCI_CAP_LIST_NEXT      1       /* Next capability in the list */
+#define PCI_CAP_FLAGS          2       /* Capability defined flags (16 bits) */
+#define PCI_CAP_SIZEOF         4
+
+/* Power Management Registers */
+
+#define PCI_PM_PMC             2       /* PM Capabilities Register */
+#define  PCI_PM_CAP_VER_MASK   0x0007  /* Version */
+#define  PCI_PM_CAP_PME_CLOCK  0x0008  /* PME clock required */
+#define  PCI_PM_CAP_RESERVED    0x0010  /* Reserved field */
+#define  PCI_PM_CAP_DSI                0x0020  /* Device specific 
initialization */
+#define  PCI_PM_CAP_AUX_POWER  0x01C0  /* Auxiliary power support mask */
+#define  PCI_PM_CAP_D1         0x0200  /* D1 power state support */
+#define  PCI_PM_CAP_D2         0x0400  /* D2 power state support */
+#define  PCI_PM_CAP_PME                0x0800  /* PME pin supported */
+#define  PCI_PM_CAP_PME_MASK   0xF800  /* PME Mask of all supported states */
+#define  PCI_PM_CAP_PME_D0     0x0800  /* PME# from D0 */
+#define  PCI_PM_CAP_PME_D1     0x1000  /* PME# from D1 */
+#define  PCI_PM_CAP_PME_D2     0x2000  /* PME# from D2 */
+#define  PCI_PM_CAP_PME_D3     0x4000  /* PME# from D3 (hot) */
+#define  PCI_PM_CAP_PME_D3cold 0x8000  /* PME# from D3 (cold) */
+#define  PCI_PM_CAP_PME_SHIFT  11      /* Start of the PME Mask in PMC */
+#define PCI_PM_CTRL            4       /* PM control and status register */
+#define  PCI_PM_CTRL_STATE_MASK        0x0003  /* Current power state (D0 to 
D3) */
+#define  PCI_PM_CTRL_NO_SOFT_RESET     0x0008  /* No reset for D3hot->D0 */
+#define  PCI_PM_CTRL_PME_ENABLE        0x0100  /* PME pin enable */
+#define  PCI_PM_CTRL_DATA_SEL_MASK     0x1e00  /* Data select (??) */
+#define  PCI_PM_CTRL_DATA_SCALE_MASK   0x6000  /* Data scale (??) */
+#define  PCI_PM_CTRL_PME_STATUS        0x8000  /* PME pin status */
+#define PCI_PM_PPB_EXTENSIONS  6       /* PPB support extensions (??) */
+#define  PCI_PM_PPB_B2_B3      0x40    /* Stop clock when in D3hot (??) */
+#define  PCI_PM_BPCC_ENABLE    0x80    /* Bus power/clock control enable (??) 
*/
+#define PCI_PM_DATA_REGISTER   7       /* (??) */
+#define PCI_PM_SIZEOF          8
+
+/* AGP registers */
+
+#define PCI_AGP_VERSION                2       /* BCD version number */
+#define PCI_AGP_RFU            3       /* Rest of capability flags */
+#define PCI_AGP_STATUS         4       /* Status register */
+#define  PCI_AGP_STATUS_RQ_MASK        0xff000000      /* Maximum number of 
requests - 1 */
+#define  PCI_AGP_STATUS_SBA    0x0200  /* Sideband addressing supported */
+#define  PCI_AGP_STATUS_64BIT  0x0020  /* 64-bit addressing supported */
+#define  PCI_AGP_STATUS_FW     0x0010  /* FW transfers supported */
+#define  PCI_AGP_STATUS_RATE4  0x0004  /* 4x transfer rate supported */
+#define  PCI_AGP_STATUS_RATE2  0x0002  /* 2x transfer rate supported */
+#define  PCI_AGP_STATUS_RATE1  0x0001  /* 1x transfer rate supported */
+#define PCI_AGP_COMMAND                8       /* Control register */
+#define  PCI_AGP_COMMAND_RQ_MASK 0xff000000  /* Master: Maximum number of 
requests */
+#define  PCI_AGP_COMMAND_SBA   0x0200  /* Sideband addressing enabled */
+#define  PCI_AGP_COMMAND_AGP   0x0100  /* Allow processing of AGP transactions 
*/
+#define  PCI_AGP_COMMAND_64BIT 0x0020  /* Allow processing of 64-bit addresses 
*/
+#define  PCI_AGP_COMMAND_FW    0x0010  /* Force FW transfers */
+#define  PCI_AGP_COMMAND_RATE4 0x0004  /* Use 4x rate */
+#define  PCI_AGP_COMMAND_RATE2 0x0002  /* Use 2x rate */
+#define  PCI_AGP_COMMAND_RATE1 0x0001  /* Use 1x rate */
+#define PCI_AGP_SIZEOF         12
+
+/* Vital Product Data */
+
+#define PCI_VPD_ADDR           2       /* Address to access (15 bits!) */
+#define  PCI_VPD_ADDR_MASK     0x7fff  /* Address mask */
+#define  PCI_VPD_ADDR_F                0x8000  /* Write 0, 1 indicates 
completion */
+#define PCI_VPD_DATA           4       /* 32-bits of data returned here */
+
+/* Slot Identification */
+
+#define PCI_SID_ESR            2       /* Expansion Slot Register */
+#define  PCI_SID_ESR_NSLOTS    0x1f    /* Number of expansion slots available 
*/
+#define  PCI_SID_ESR_FIC       0x20    /* First In Chassis Flag */
+#define PCI_SID_CHASSIS_NR     3       /* Chassis Number */
+
+/* Message Signalled Interrupts registers */
+
+#define PCI_MSI_FLAGS          2       /* Various flags */
+#define  PCI_MSI_FLAGS_64BIT   0x80    /* 64-bit addresses allowed */
+#define  PCI_MSI_FLAGS_QSIZE   0x70    /* Message queue size configured */
+#define  PCI_MSI_FLAGS_QMASK   0x0e    /* Maximum queue size available */
+#define  PCI_MSI_FLAGS_ENABLE  0x01    /* MSI feature enabled */
+#define  PCI_MSI_FLAGS_MASKBIT 0x100   /* 64-bit mask bits allowed */
+#define PCI_MSI_RFU            3       /* Rest of capability flags */
+#define PCI_MSI_ADDRESS_LO     4       /* Lower 32 bits */
+#define PCI_MSI_ADDRESS_HI     8       /* Upper 32 bits (if 
PCI_MSI_FLAGS_64BIT set) */
+#define PCI_MSI_DATA_32                8       /* 16 bits of data for 32-bit 
devices */
+#define PCI_MSI_MASK_32                12      /* Mask bits register for 
32-bit devices */
+#define PCI_MSI_DATA_64                12      /* 16 bits of data for 64-bit 
devices */
+#define PCI_MSI_MASK_64                16      /* Mask bits register for 
64-bit devices */
+
+/* MSI-X registers */
+#define PCI_MSIX_FLAGS         2
+#define  PCI_MSIX_FLAGS_QSIZE  0x7FF
+#define  PCI_MSIX_FLAGS_ENABLE (1 << 15)
+#define  PCI_MSIX_FLAGS_MASKALL        (1 << 14)
+#define PCI_MSIX_TABLE         4
+#define PCI_MSIX_PBA           8
+#define  PCI_MSIX_FLAGS_BIRMASK        (7 << 0)
+
+/* MSI-X entry's format */
+#define PCI_MSIX_ENTRY_SIZE            16
+#define  PCI_MSIX_ENTRY_LOWER_ADDR     0
+#define  PCI_MSIX_ENTRY_UPPER_ADDR     4
+#define  PCI_MSIX_ENTRY_DATA           8
+#define  PCI_MSIX_ENTRY_VECTOR_CTRL    12
+#define   PCI_MSIX_ENTRY_CTRL_MASKBIT  1
+
+/* CompactPCI Hotswap Register */
+
+#define PCI_CHSWP_CSR          2       /* Control and Status Register */
+#define  PCI_CHSWP_DHA         0x01    /* Device Hiding Arm */
+#define  PCI_CHSWP_EIM         0x02    /* ENUM# Signal Mask */
+#define  PCI_CHSWP_PIE         0x04    /* Pending Insert or Extract */
+#define  PCI_CHSWP_LOO         0x08    /* LED On / Off */
+#define  PCI_CHSWP_PI          0x30    /* Programming Interface */
+#define  PCI_CHSWP_EXT         0x40    /* ENUM# status - extraction */
+#define  PCI_CHSWP_INS         0x80    /* ENUM# status - insertion */
+
+/* PCI Advanced Feature registers */
+
+#define PCI_AF_LENGTH          2
+#define PCI_AF_CAP             3
+#define  PCI_AF_CAP_TP         0x01
+#define  PCI_AF_CAP_FLR                0x02
+#define PCI_AF_CTRL            4
+#define  PCI_AF_CTRL_FLR       0x01
+#define PCI_AF_STATUS          5
+#define  PCI_AF_STATUS_TP      0x01
+
+/* PCI-X registers */
+
+#define PCI_X_CMD              2       /* Modes & Features */
+#define  PCI_X_CMD_DPERR_E     0x0001  /* Data Parity Error Recovery Enable */
+#define  PCI_X_CMD_ERO         0x0002  /* Enable Relaxed Ordering */
+#define  PCI_X_CMD_READ_512    0x0000  /* 512 byte maximum read byte count */
+#define  PCI_X_CMD_READ_1K     0x0004  /* 1Kbyte maximum read byte count */
+#define  PCI_X_CMD_READ_2K     0x0008  /* 2Kbyte maximum read byte count */
+#define  PCI_X_CMD_READ_4K     0x000c  /* 4Kbyte maximum read byte count */
+#define  PCI_X_CMD_MAX_READ    0x000c  /* Max Memory Read Byte Count */
+                               /* Max # of outstanding split transactions */
+#define  PCI_X_CMD_SPLIT_1     0x0000  /* Max 1 */
+#define  PCI_X_CMD_SPLIT_2     0x0010  /* Max 2 */
+#define  PCI_X_CMD_SPLIT_3     0x0020  /* Max 3 */
+#define  PCI_X_CMD_SPLIT_4     0x0030  /* Max 4 */
+#define  PCI_X_CMD_SPLIT_8     0x0040  /* Max 8 */
+#define  PCI_X_CMD_SPLIT_12    0x0050  /* Max 12 */
+#define  PCI_X_CMD_SPLIT_16    0x0060  /* Max 16 */
+#define  PCI_X_CMD_SPLIT_32    0x0070  /* Max 32 */
+#define  PCI_X_CMD_MAX_SPLIT   0x0070  /* Max Outstanding Split Transactions */
+#define  PCI_X_CMD_VERSION(x)  (((x) >> 12) & 3) /* Version */
+#define PCI_X_STATUS           4       /* PCI-X capabilities */
+#define  PCI_X_STATUS_DEVFN    0x000000ff      /* A copy of devfn */
+#define  PCI_X_STATUS_BUS      0x0000ff00      /* A copy of bus nr */
+#define  PCI_X_STATUS_64BIT    0x00010000      /* 64-bit device */
+#define  PCI_X_STATUS_133MHZ   0x00020000      /* 133 MHz capable */
+#define  PCI_X_STATUS_SPL_DISC 0x00040000      /* Split Completion Discarded */
+#define  PCI_X_STATUS_UNX_SPL  0x00080000      /* Unexpected Split Completion 
*/
+#define  PCI_X_STATUS_COMPLEX  0x00100000      /* Device Complexity */
+#define  PCI_X_STATUS_MAX_READ 0x00600000      /* Designed Max Memory Read 
Count */
+#define  PCI_X_STATUS_MAX_SPLIT        0x03800000      /* Designed Max 
Outstanding Split Transactions */
+#define  PCI_X_STATUS_MAX_CUM  0x1c000000      /* Designed Max Cumulative Read 
Size */
+#define  PCI_X_STATUS_SPL_ERR  0x20000000      /* Rcvd Split Completion Error 
Msg */
+#define  PCI_X_STATUS_266MHZ   0x40000000      /* 266 MHz capable */
+#define  PCI_X_STATUS_533MHZ   0x80000000      /* 533 MHz capable */
+
+/* PCI Bridge Subsystem ID registers */
+
+#define PCI_SSVID_VENDOR_ID     4      /* PCI-Bridge subsystem vendor id 
register */
+#define PCI_SSVID_DEVICE_ID     6      /* PCI-Bridge subsystem device id 
register */
+
+/* PCI Express capability registers */
+
+#define PCI_EXP_FLAGS          2       /* Capabilities register */
+#define PCI_EXP_FLAGS_VERS     0x000f  /* Capability version */
+#define PCI_EXP_FLAGS_TYPE     0x00f0  /* Device/Port type */
+#define  PCI_EXP_TYPE_ENDPOINT 0x0     /* Express Endpoint */
+#define  PCI_EXP_TYPE_LEG_END  0x1     /* Legacy Endpoint */
+#define  PCI_EXP_TYPE_ROOT_PORT 0x4    /* Root Port */
+#define  PCI_EXP_TYPE_UPSTREAM 0x5     /* Upstream Port */
+#define  PCI_EXP_TYPE_DOWNSTREAM 0x6   /* Downstream Port */
+#define  PCI_EXP_TYPE_PCI_BRIDGE 0x7   /* PCI/PCI-X Bridge */
+#define  PCI_EXP_TYPE_PCIE_BRIDGE 0x8   /* PCI/PCI-X to PCIE Bridge */
+#define  PCI_EXP_TYPE_RC_END   0x9     /* Root Complex Integrated Endpoint */
+#define  PCI_EXP_TYPE_RC_EC     0xa     /* Root Complex Event Collector */
+#define PCI_EXP_FLAGS_SLOT     0x0100  /* Slot implemented */
+#define PCI_EXP_FLAGS_IRQ      0x3e00  /* Interrupt message number */
+#define PCI_EXP_DEVCAP         4       /* Device capabilities */
+#define  PCI_EXP_DEVCAP_PAYLOAD        0x07    /* Max_Payload_Size */
+#define  PCI_EXP_DEVCAP_PHANTOM        0x18    /* Phantom functions */
+#define  PCI_EXP_DEVCAP_EXT_TAG        0x20    /* Extended tags */
+#define  PCI_EXP_DEVCAP_L0S    0x1c0   /* L0s Acceptable Latency */
+#define  PCI_EXP_DEVCAP_L1     0xe00   /* L1 Acceptable Latency */
+#define  PCI_EXP_DEVCAP_ATN_BUT        0x1000  /* Attention Button Present */
+#define  PCI_EXP_DEVCAP_ATN_IND        0x2000  /* Attention Indicator Present 
*/
+#define  PCI_EXP_DEVCAP_PWR_IND        0x4000  /* Power Indicator Present */
+#define  PCI_EXP_DEVCAP_RBER   0x8000  /* Role-Based Error Reporting */
+#define  PCI_EXP_DEVCAP_PWR_VAL        0x3fc0000 /* Slot Power Limit Value */
+#define  PCI_EXP_DEVCAP_PWR_SCL        0xc000000 /* Slot Power Limit Scale */
+#define  PCI_EXP_DEVCAP_FLR     0x10000000 /* Function Level Reset */
+#define PCI_EXP_DEVCTL         8       /* Device Control */
+#define  PCI_EXP_DEVCTL_CERE   0x0001  /* Correctable Error Reporting En. */
+#define  PCI_EXP_DEVCTL_NFERE  0x0002  /* Non-Fatal Error Reporting Enable */
+#define  PCI_EXP_DEVCTL_FERE   0x0004  /* Fatal Error Reporting Enable */
+#define  PCI_EXP_DEVCTL_URRE   0x0008  /* Unsupported Request Reporting En. */
+#define  PCI_EXP_DEVCTL_RELAX_EN 0x0010 /* Enable relaxed ordering */
+#define  PCI_EXP_DEVCTL_PAYLOAD        0x00e0  /* Max_Payload_Size */
+#define  PCI_EXP_DEVCTL_EXT_TAG        0x0100  /* Extended Tag Field Enable */
+#define  PCI_EXP_DEVCTL_PHANTOM        0x0200  /* Phantom Functions Enable */
+#define  PCI_EXP_DEVCTL_AUX_PME        0x0400  /* Auxiliary Power PM Enable */
+#define  PCI_EXP_DEVCTL_NOSNOOP_EN 0x0800  /* Enable No Snoop */
+#define  PCI_EXP_DEVCTL_READRQ 0x7000  /* Max_Read_Request_Size */
+#define  PCI_EXP_DEVCTL_BCR_FLR 0x8000  /* Bridge Configuration Retry / FLR */
+#define PCI_EXP_DEVSTA         10      /* Device Status */
+#define  PCI_EXP_DEVSTA_CED    0x01    /* Correctable Error Detected */
+#define  PCI_EXP_DEVSTA_NFED   0x02    /* Non-Fatal Error Detected */
+#define  PCI_EXP_DEVSTA_FED    0x04    /* Fatal Error Detected */
+#define  PCI_EXP_DEVSTA_URD    0x08    /* Unsupported Request Detected */
+#define  PCI_EXP_DEVSTA_AUXPD  0x10    /* AUX Power Detected */
+#define  PCI_EXP_DEVSTA_TRPND  0x20    /* Transactions Pending */
+#define PCI_EXP_LNKCAP         12      /* Link Capabilities */
+#define  PCI_EXP_LNKCAP_SLS    0x0000000f /* Supported Link Speeds */
+#define  PCI_EXP_LNKCAP_MLW    0x000003f0 /* Maximum Link Width */
+#define  PCI_EXP_LNKCAP_ASPMS  0x00000c00 /* ASPM Support */
+#define  PCI_EXP_LNKCAP_L0SEL  0x00007000 /* L0s Exit Latency */
+#define  PCI_EXP_LNKCAP_L1EL   0x00038000 /* L1 Exit Latency */
+#define  PCI_EXP_LNKCAP_CLKPM  0x00040000 /* L1 Clock Power Management */
+#define  PCI_EXP_LNKCAP_SDERC  0x00080000 /* Surprise Down Error Reporting 
Capable */
+#define  PCI_EXP_LNKCAP_DLLLARC        0x00100000 /* Data Link Layer Link 
Active Reporting Capable */
+#define  PCI_EXP_LNKCAP_LBNC   0x00200000 /* Link Bandwidth Notification 
Capability */
+#define  PCI_EXP_LNKCAP_PN     0xff000000 /* Port Number */
+#define PCI_EXP_LNKCTL         16      /* Link Control */
+#define  PCI_EXP_LNKCTL_ASPMC  0x0003  /* ASPM Control */
+#define  PCI_EXP_LNKCTL_RCB    0x0008  /* Read Completion Boundary */
+#define  PCI_EXP_LNKCTL_LD     0x0010  /* Link Disable */
+#define  PCI_EXP_LNKCTL_RL     0x0020  /* Retrain Link */
+#define  PCI_EXP_LNKCTL_CCC    0x0040  /* Common Clock Configuration */
+#define  PCI_EXP_LNKCTL_ES     0x0080  /* Extended Synch */
+#define  PCI_EXP_LNKCTL_CLKREQ_EN 0x100        /* Enable clkreq */
+#define  PCI_EXP_LNKCTL_HAWD   0x0200  /* Hardware Autonomous Width Disable */
+#define  PCI_EXP_LNKCTL_LBMIE  0x0400  /* Link Bandwidth Management Interrupt 
Enable */
+#define  PCI_EXP_LNKCTL_LABIE  0x0800  /* Lnk Autonomous Bandwidth Interrupt 
Enable */
+#define PCI_EXP_LNKSTA         18      /* Link Status */
+#define  PCI_EXP_LNKSTA_CLS    0x000f  /* Current Link Speed */
+#define  PCI_EXP_LNKSTA_CLS_2_5GB 0x01 /* Current Link Speed 2.5GT/s */
+#define  PCI_EXP_LNKSTA_CLS_5_0GB 0x02 /* Current Link Speed 5.0GT/s */
+#define  PCI_EXP_LNKSTA_NLW    0x03f0  /* Nogotiated Link Width */
+#define  PCI_EXP_LNKSTA_NLW_SHIFT 4    /* start of NLW mask in link status */
+#define  PCI_EXP_LNKSTA_LT     0x0800  /* Link Training */
+#define  PCI_EXP_LNKSTA_SLC    0x1000  /* Slot Clock Configuration */
+#define  PCI_EXP_LNKSTA_DLLLA  0x2000  /* Data Link Layer Link Active */
+#define  PCI_EXP_LNKSTA_LBMS   0x4000  /* Link Bandwidth Management Status */
+#define  PCI_EXP_LNKSTA_LABS   0x8000  /* Link Autonomous Bandwidth Status */
+#define PCI_EXP_SLTCAP         20      /* Slot Capabilities */
+#define  PCI_EXP_SLTCAP_ABP    0x00000001 /* Attention Button Present */
+#define  PCI_EXP_SLTCAP_PCP    0x00000002 /* Power Controller Present */
+#define  PCI_EXP_SLTCAP_MRLSP  0x00000004 /* MRL Sensor Present */
+#define  PCI_EXP_SLTCAP_AIP    0x00000008 /* Attention Indicator Present */
+#define  PCI_EXP_SLTCAP_PIP    0x00000010 /* Power Indicator Present */
+#define  PCI_EXP_SLTCAP_HPS    0x00000020 /* Hot-Plug Surprise */
+#define  PCI_EXP_SLTCAP_HPC    0x00000040 /* Hot-Plug Capable */
+#define  PCI_EXP_SLTCAP_SPLV   0x00007f80 /* Slot Power Limit Value */
+#define  PCI_EXP_SLTCAP_SPLS   0x00018000 /* Slot Power Limit Scale */
+#define  PCI_EXP_SLTCAP_EIP    0x00020000 /* Electromechanical Interlock 
Present */
+#define  PCI_EXP_SLTCAP_NCCS   0x00040000 /* No Command Completed Support */
+#define  PCI_EXP_SLTCAP_PSN    0xfff80000 /* Physical Slot Number */
+#define PCI_EXP_SLTCTL         24      /* Slot Control */
+#define  PCI_EXP_SLTCTL_ABPE   0x0001  /* Attention Button Pressed Enable */
+#define  PCI_EXP_SLTCTL_PFDE   0x0002  /* Power Fault Detected Enable */
+#define  PCI_EXP_SLTCTL_MRLSCE 0x0004  /* MRL Sensor Changed Enable */
+#define  PCI_EXP_SLTCTL_PDCE   0x0008  /* Presence Detect Changed Enable */
+#define  PCI_EXP_SLTCTL_CCIE   0x0010  /* Command Completed Interrupt Enable */
+#define  PCI_EXP_SLTCTL_HPIE   0x0020  /* Hot-Plug Interrupt Enable */
+#define  PCI_EXP_SLTCTL_AIC    0x00c0  /* Attention Indicator Control */
+#define  PCI_EXP_SLTCTL_PIC    0x0300  /* Power Indicator Control */
+#define  PCI_EXP_SLTCTL_PCC    0x0400  /* Power Controller Control */
+#define  PCI_EXP_SLTCTL_EIC    0x0800  /* Electromechanical Interlock Control 
*/
+#define  PCI_EXP_SLTCTL_DLLSCE 0x1000  /* Data Link Layer State Changed Enable 
*/
+#define PCI_EXP_SLTSTA         26      /* Slot Status */
+#define  PCI_EXP_SLTSTA_ABP    0x0001  /* Attention Button Pressed */
+#define  PCI_EXP_SLTSTA_PFD    0x0002  /* Power Fault Detected */
+#define  PCI_EXP_SLTSTA_MRLSC  0x0004  /* MRL Sensor Changed */
+#define  PCI_EXP_SLTSTA_PDC    0x0008  /* Presence Detect Changed */
+#define  PCI_EXP_SLTSTA_CC     0x0010  /* Command Completed */
+#define  PCI_EXP_SLTSTA_MRLSS  0x0020  /* MRL Sensor State */
+#define  PCI_EXP_SLTSTA_PDS    0x0040  /* Presence Detect State */
+#define  PCI_EXP_SLTSTA_EIS    0x0080  /* Electromechanical Interlock Status */
+#define  PCI_EXP_SLTSTA_DLLSC  0x0100  /* Data Link Layer State Changed */
+#define PCI_EXP_RTCTL          28      /* Root Control */
+#define  PCI_EXP_RTCTL_SECEE   0x01    /* System Error on Correctable Error */
+#define  PCI_EXP_RTCTL_SENFEE  0x02    /* System Error on Non-Fatal Error */
+#define  PCI_EXP_RTCTL_SEFEE   0x04    /* System Error on Fatal Error */
+#define  PCI_EXP_RTCTL_PMEIE   0x08    /* PME Interrupt Enable */
+#define  PCI_EXP_RTCTL_CRSSVE  0x10    /* CRS Software Visibility Enable */
+#define PCI_EXP_RTCAP          30      /* Root Capabilities */
+#define PCI_EXP_RTSTA          32      /* Root Status */
+#define PCI_EXP_RTSTA_PME      0x10000 /* PME status */
+#define PCI_EXP_RTSTA_PENDING  0x20000 /* PME pending */
+#define PCI_EXP_DEVCAP2                36      /* Device Capabilities 2 */
+#define  PCI_EXP_DEVCAP2_ARI   0x20    /* Alternative Routing-ID */
+#define  PCI_EXP_DEVCAP2_LTR   0x800   /* Latency tolerance reporting */
+#define  PCI_EXP_OBFF_MASK     0xc0000 /* OBFF support mechanism */
+#define  PCI_EXP_OBFF_MSG      0x40000 /* New message signaling */
+#define  PCI_EXP_OBFF_WAKE     0x80000 /* Re-use WAKE# for OBFF */
+#define PCI_EXP_DEVCTL2                40      /* Device Control 2 */
+#define  PCI_EXP_DEVCTL2_ARI   0x20    /* Alternative Routing-ID */
+#define  PCI_EXP_IDO_REQ_EN    0x100   /* ID-based ordering request enable */
+#define  PCI_EXP_IDO_CMP_EN    0x200   /* ID-based ordering completion enable 
*/
+#define  PCI_EXP_LTR_EN                0x400   /* Latency tolerance reporting 
*/
+#define  PCI_EXP_OBFF_MSGA_EN  0x2000  /* OBFF enable with Message type A */
+#define  PCI_EXP_OBFF_MSGB_EN  0x4000  /* OBFF enable with Message type B */
+#define  PCI_EXP_OBFF_WAKE_EN  0x6000  /* OBFF using WAKE# signaling */
+#define PCI_EXP_LNKCTL2                48      /* Link Control 2 */
+#define PCI_EXP_SLTCTL2                56      /* Slot Control 2 */
+
+/* Extended Capabilities (PCI-X 2.0 and Express) */
+#define PCI_EXT_CAP_ID(header)         (header & 0x0000ffff)
+#define PCI_EXT_CAP_VER(header)                ((header >> 16) & 0xf)
+#define PCI_EXT_CAP_NEXT(header)       ((header >> 20) & 0xffc)
+
+#define PCI_EXT_CAP_ID_ERR     1
+#define PCI_EXT_CAP_ID_VC      2
+#define PCI_EXT_CAP_ID_DSN     3
+#define PCI_EXT_CAP_ID_PWR     4
+#define PCI_EXT_CAP_ID_VNDR    11
+#define PCI_EXT_CAP_ID_ACS     13
+#define PCI_EXT_CAP_ID_ARI     14
+#define PCI_EXT_CAP_ID_ATS     15
+#define PCI_EXT_CAP_ID_SRIOV   16
+#define PCI_EXT_CAP_ID_LTR     24
+
+/* Advanced Error Reporting */
+#define PCI_ERR_UNCOR_STATUS   4       /* Uncorrectable Error Status */
+#define  PCI_ERR_UNC_TRAIN     0x00000001      /* Training */
+#define  PCI_ERR_UNC_DLP       0x00000010      /* Data Link Protocol */
+#define  PCI_ERR_UNC_POISON_TLP        0x00001000      /* Poisoned TLP */
+#define  PCI_ERR_UNC_FCP       0x00002000      /* Flow Control Protocol */
+#define  PCI_ERR_UNC_COMP_TIME 0x00004000      /* Completion Timeout */
+#define  PCI_ERR_UNC_COMP_ABORT        0x00008000      /* Completer Abort */
+#define  PCI_ERR_UNC_UNX_COMP  0x00010000      /* Unexpected Completion */
+#define  PCI_ERR_UNC_RX_OVER   0x00020000      /* Receiver Overflow */
+#define  PCI_ERR_UNC_MALF_TLP  0x00040000      /* Malformed TLP */
+#define  PCI_ERR_UNC_ECRC      0x00080000      /* ECRC Error Status */
+#define  PCI_ERR_UNC_UNSUP     0x00100000      /* Unsupported Request */
+#define PCI_ERR_UNCOR_MASK     8       /* Uncorrectable Error Mask */
+       /* Same bits as above */
+#define PCI_ERR_UNCOR_SEVER    12      /* Uncorrectable Error Severity */
+       /* Same bits as above */
+#define PCI_ERR_COR_STATUS     16      /* Correctable Error Status */
+#define  PCI_ERR_COR_RCVR      0x00000001      /* Receiver Error Status */
+#define  PCI_ERR_COR_BAD_TLP   0x00000040      /* Bad TLP Status */
+#define  PCI_ERR_COR_BAD_DLLP  0x00000080      /* Bad DLLP Status */
+#define  PCI_ERR_COR_REP_ROLL  0x00000100      /* REPLAY_NUM Rollover */
+#define  PCI_ERR_COR_REP_TIMER 0x00001000      /* Replay Timer Timeout */
+#define PCI_ERR_COR_MASK       20      /* Correctable Error Mask */
+       /* Same bits as above */
+#define PCI_ERR_CAP            24      /* Advanced Error Capabilities */
+#define  PCI_ERR_CAP_FEP(x)    ((x) & 31)      /* First Error Pointer */
+#define  PCI_ERR_CAP_ECRC_GENC 0x00000020      /* ECRC Generation Capable */
+#define  PCI_ERR_CAP_ECRC_GENE 0x00000040      /* ECRC Generation Enable */
+#define  PCI_ERR_CAP_ECRC_CHKC 0x00000080      /* ECRC Check Capable */
+#define  PCI_ERR_CAP_ECRC_CHKE 0x00000100      /* ECRC Check Enable */
+#define PCI_ERR_HEADER_LOG     28      /* Header Log Register (16 bytes) */
+#define PCI_ERR_ROOT_COMMAND   44      /* Root Error Command */
+/* Correctable Err Reporting Enable */
+#define PCI_ERR_ROOT_CMD_COR_EN                0x00000001
+/* Non-fatal Err Reporting Enable */
+#define PCI_ERR_ROOT_CMD_NONFATAL_EN   0x00000002
+/* Fatal Err Reporting Enable */
+#define PCI_ERR_ROOT_CMD_FATAL_EN      0x00000004
+#define PCI_ERR_ROOT_STATUS    48
+#define PCI_ERR_ROOT_COR_RCV           0x00000001      /* ERR_COR Received */
+/* Multi ERR_COR Received */
+#define PCI_ERR_ROOT_MULTI_COR_RCV     0x00000002
+/* ERR_FATAL/NONFATAL Recevied */
+#define PCI_ERR_ROOT_UNCOR_RCV         0x00000004
+/* Multi ERR_FATAL/NONFATAL Recevied */
+#define PCI_ERR_ROOT_MULTI_UNCOR_RCV   0x00000008
+#define PCI_ERR_ROOT_FIRST_FATAL       0x00000010      /* First Fatal */
+#define PCI_ERR_ROOT_NONFATAL_RCV      0x00000020      /* Non-Fatal Received */
+#define PCI_ERR_ROOT_FATAL_RCV         0x00000040      /* Fatal Received */
+#define PCI_ERR_ROOT_ERR_SRC   52      /* Error Source Identification */
+
+/* Virtual Channel */
+#define PCI_VC_PORT_REG1       4
+#define PCI_VC_PORT_REG2       8
+#define PCI_VC_PORT_CTRL       12
+#define PCI_VC_PORT_STATUS     14
+#define PCI_VC_RES_CAP         16
+#define PCI_VC_RES_CTRL                20
+#define PCI_VC_RES_STATUS      26
+
+/* Power Budgeting */
+#define PCI_PWR_DSR            4       /* Data Select Register */
+#define PCI_PWR_DATA           8       /* Data Register */
+#define  PCI_PWR_DATA_BASE(x)  ((x) & 0xff)        /* Base Power */
+#define  PCI_PWR_DATA_SCALE(x) (((x) >> 8) & 3)    /* Data Scale */
+#define  PCI_PWR_DATA_PM_SUB(x)        (((x) >> 10) & 7)   /* PM Sub State */
+#define  PCI_PWR_DATA_PM_STATE(x) (((x) >> 13) & 3) /* PM State */
+#define  PCI_PWR_DATA_TYPE(x)  (((x) >> 15) & 7)   /* Type */
+#define  PCI_PWR_DATA_RAIL(x)  (((x) >> 18) & 7)   /* Power Rail */
+#define PCI_PWR_CAP            12      /* Capability */
+#define  PCI_PWR_CAP_BUDGET(x) ((x) & 1)       /* Included in system budget */
+
+/*
+ * Hypertransport sub capability types
+ *
+ * Unfortunately there are both 3 bit and 5 bit capability types defined
+ * in the HT spec, catering for that is a little messy. You probably don't
+ * want to use these directly, just use pci_find_ht_capability() and it
+ * will do the right thing for you.
+ */
+#define HT_3BIT_CAP_MASK       0xE0
+#define HT_CAPTYPE_SLAVE       0x00    /* Slave/Primary link configuration */
+#define HT_CAPTYPE_HOST                0x20    /* Host/Secondary link 
configuration */
+
+#define HT_5BIT_CAP_MASK       0xF8
+#define HT_CAPTYPE_IRQ         0x80    /* IRQ Configuration */
+#define HT_CAPTYPE_REMAPPING_40        0xA0    /* 40 bit address remapping */
+#define HT_CAPTYPE_REMAPPING_64 0xA2   /* 64 bit address remapping */
+#define HT_CAPTYPE_UNITID_CLUMP        0x90    /* Unit ID clumping */
+#define HT_CAPTYPE_EXTCONF     0x98    /* Extended Configuration Space Access 
*/
+#define HT_CAPTYPE_MSI_MAPPING 0xA8    /* MSI Mapping Capability */
+#define  HT_MSI_FLAGS          0x02            /* Offset to flags */
+#define  HT_MSI_FLAGS_ENABLE   0x1             /* Mapping enable */
+#define  HT_MSI_FLAGS_FIXED    0x2             /* Fixed mapping only */
+#define  HT_MSI_FIXED_ADDR     0x00000000FEE00000ULL   /* Fixed addr */
+#define  HT_MSI_ADDR_LO                0x04            /* Offset to low addr 
bits */
+#define  HT_MSI_ADDR_LO_MASK   0xFFF00000      /* Low address bit mask */
+#define  HT_MSI_ADDR_HI                0x08            /* Offset to high addr 
bits */
+#define HT_CAPTYPE_DIRECT_ROUTE        0xB0    /* Direct routing configuration 
*/
+#define HT_CAPTYPE_VCSET       0xB8    /* Virtual Channel configuration */
+#define HT_CAPTYPE_ERROR_RETRY 0xC0    /* Retry on error configuration */
+#define HT_CAPTYPE_GEN3                0xD0    /* Generation 3 hypertransport 
configuration */
+#define HT_CAPTYPE_PM          0xE0    /* Hypertransport powermanagement 
configuration */
+
+/* Alternative Routing-ID Interpretation */
+#define PCI_ARI_CAP            0x04    /* ARI Capability Register */
+#define  PCI_ARI_CAP_MFVC      0x0001  /* MFVC Function Groups Capability */
+#define  PCI_ARI_CAP_ACS       0x0002  /* ACS Function Groups Capability */
+#define  PCI_ARI_CAP_NFN(x)    (((x) >> 8) & 0xff) /* Next Function Number */
+#define PCI_ARI_CTRL           0x06    /* ARI Control Register */
+#define  PCI_ARI_CTRL_MFVC     0x0001  /* MFVC Function Groups Enable */
+#define  PCI_ARI_CTRL_ACS      0x0002  /* ACS Function Groups Enable */
+#define  PCI_ARI_CTRL_FG(x)    (((x) >> 4) & 7) /* Function Group */
+
+/* Address Translation Service */
+#define PCI_ATS_CAP            0x04    /* ATS Capability Register */
+#define  PCI_ATS_CAP_QDEP(x)   ((x) & 0x1f)    /* Invalidate Queue Depth */
+#define  PCI_ATS_MAX_QDEP      32      /* Max Invalidate Queue Depth */
+#define PCI_ATS_CTRL           0x06    /* ATS Control Register */
+#define  PCI_ATS_CTRL_ENABLE   0x8000  /* ATS Enable */
+#define  PCI_ATS_CTRL_STU(x)   ((x) & 0x1f)    /* Smallest Translation Unit */
+#define  PCI_ATS_MIN_STU       12      /* shift of minimum STU block */
+
+/* Single Root I/O Virtualization */
+#define PCI_SRIOV_CAP          0x04    /* SR-IOV Capabilities */
+#define  PCI_SRIOV_CAP_VFM     0x01    /* VF Migration Capable */
+#define  PCI_SRIOV_CAP_INTR(x) ((x) >> 21) /* Interrupt Message Number */
+#define PCI_SRIOV_CTRL         0x08    /* SR-IOV Control */
+#define  PCI_SRIOV_CTRL_VFE    0x01    /* VF Enable */
+#define  PCI_SRIOV_CTRL_VFM    0x02    /* VF Migration Enable */
+#define  PCI_SRIOV_CTRL_INTR   0x04    /* VF Migration Interrupt Enable */
+#define  PCI_SRIOV_CTRL_MSE    0x08    /* VF Memory Space Enable */
+#define  PCI_SRIOV_CTRL_ARI    0x10    /* ARI Capable Hierarchy */
+#define PCI_SRIOV_STATUS       0x0a    /* SR-IOV Status */
+#define  PCI_SRIOV_STATUS_VFM  0x01    /* VF Migration Status */
+#define PCI_SRIOV_INITIAL_VF   0x0c    /* Initial VFs */
+#define PCI_SRIOV_TOTAL_VF     0x0e    /* Total VFs */
+#define PCI_SRIOV_NUM_VF       0x10    /* Number of VFs */
+#define PCI_SRIOV_FUNC_LINK    0x12    /* Function Dependency Link */
+#define PCI_SRIOV_VF_OFFSET    0x14    /* First VF Offset */
+#define PCI_SRIOV_VF_STRIDE    0x16    /* Following VF Stride */
+#define PCI_SRIOV_VF_DID       0x1a    /* VF Device ID */
+#define PCI_SRIOV_SUP_PGSIZE   0x1c    /* Supported Page Sizes */
+#define PCI_SRIOV_SYS_PGSIZE   0x20    /* System Page Size */
+#define PCI_SRIOV_BAR          0x24    /* VF BAR0 */
+#define  PCI_SRIOV_NUM_BARS    6       /* Number of VF BARs */
+#define PCI_SRIOV_VFM          0x3c    /* VF Migration State Array Offset*/
+#define  PCI_SRIOV_VFM_BIR(x)  ((x) & 7)       /* State BIR */
+#define  PCI_SRIOV_VFM_OFFSET(x) ((x) & ~7)    /* State Offset */
+#define  PCI_SRIOV_VFM_UA      0x0     /* Inactive.Unavailable */
+#define  PCI_SRIOV_VFM_MI      0x1     /* Dormant.MigrateIn */
+#define  PCI_SRIOV_VFM_MO      0x2     /* Active.MigrateOut */
+#define  PCI_SRIOV_VFM_AV      0x3     /* Active.Available */
+
+#define PCI_LTR_MAX_SNOOP_LAT  0x4
+#define PCI_LTR_MAX_NOSNOOP_LAT        0x6
+#define  PCI_LTR_VALUE_MASK    0x000003ff
+#define  PCI_LTR_SCALE_MASK    0x00001c00
+#define  PCI_LTR_SCALE_SHIFT   10
+
+/* Access Control Service */
+#define PCI_ACS_CAP            0x04    /* ACS Capability Register */
+#define  PCI_ACS_SV            0x01    /* Source Validation */
+#define  PCI_ACS_TB            0x02    /* Translation Blocking */
+#define  PCI_ACS_RR            0x04    /* P2P Request Redirect */
+#define  PCI_ACS_CR            0x08    /* P2P Completion Redirect */
+#define  PCI_ACS_UF            0x10    /* Upstream Forwarding */
+#define  PCI_ACS_EC            0x20    /* P2P Egress Control */
+#define  PCI_ACS_DT            0x40    /* Direct Translated P2P */
+#define PCI_ACS_CTRL           0x06    /* ACS Control Register */
+#define PCI_ACS_EGRESS_CTL_V   0x08    /* ACS Egress Control Vector */
+
+#endif /* LINUX_PCI_REGS_H */
diff --git a/hw/pci/pcie.c b/hw/pci/pcie.c
new file mode 100644
index 0000000..7c92f19
--- /dev/null
+++ b/hw/pci/pcie.c
@@ -0,0 +1,555 @@
+/*
+ * pcie.c
+ *
+ * Copyright (c) 2010 Isaku Yamahata <yamahata at valinux co jp>
+ *                    VA Linux Systems Japan K.K.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "qemu-common.h"
+#include "pci_bridge.h"
+#include "pcie.h"
+#include "msix.h"
+#include "msi.h"
+#include "pci_internals.h"
+#include "pcie_regs.h"
+#include "range.h"
+
+//#define DEBUG_PCIE
+#ifdef DEBUG_PCIE
+# define PCIE_DPRINTF(fmt, ...)                                         \
+    fprintf(stderr, "%s:%d " fmt, __func__, __LINE__, ## __VA_ARGS__)
+#else
+# define PCIE_DPRINTF(fmt, ...) do {} while (0)
+#endif
+#define PCIE_DEV_PRINTF(dev, fmt, ...)                                  \
+    PCIE_DPRINTF("%s:%x "fmt, (dev)->name, (dev)->devfn, ## __VA_ARGS__)
+
+
+/***************************************************************************
+ * pci express capability helper functions
+ */
+int pcie_cap_init(PCIDevice *dev, uint8_t offset, uint8_t type, uint8_t port)
+{
+    int pos;
+    uint8_t *exp_cap;
+
+    assert(pci_is_express(dev));
+
+    pos = pci_add_capability(dev, PCI_CAP_ID_EXP, offset,
+                                 PCI_EXP_VER2_SIZEOF);
+    if (pos < 0) {
+        return pos;
+    }
+    dev->exp.exp_cap = pos;
+    exp_cap = dev->config + pos;
+
+    /* capability register
+       interrupt message number defaults to 0 */
+    pci_set_word(exp_cap + PCI_EXP_FLAGS,
+                 ((type << PCI_EXP_FLAGS_TYPE_SHIFT) & PCI_EXP_FLAGS_TYPE) |
+                 PCI_EXP_FLAGS_VER2);
+
+    /* device capability register
+     * table 7-12:
+     * roll based error reporting bit must be set by all
+     * Functions conforming to the ECN, PCI Express Base
+     * Specification, Revision 1.1., or subsequent PCI Express Base
+     * Specification revisions.
+     */
+    pci_set_long(exp_cap + PCI_EXP_DEVCAP, PCI_EXP_DEVCAP_RBER);
+
+    pci_set_long(exp_cap + PCI_EXP_LNKCAP,
+                 (port << PCI_EXP_LNKCAP_PN_SHIFT) |
+                 PCI_EXP_LNKCAP_ASPMS_0S |
+                 PCI_EXP_LNK_MLW_1 |
+                 PCI_EXP_LNK_LS_25);
+
+    pci_set_word(exp_cap + PCI_EXP_LNKSTA,
+                 PCI_EXP_LNK_MLW_1 | PCI_EXP_LNK_LS_25);
+
+    pci_set_long(exp_cap + PCI_EXP_DEVCAP2,
+                 PCI_EXP_DEVCAP2_EFF | PCI_EXP_DEVCAP2_EETLPP);
+
+    pci_set_word(dev->wmask + pos, PCI_EXP_DEVCTL2_EETLPPB);
+    return pos;
+}
+
+void pcie_cap_exit(PCIDevice *dev)
+{
+    pci_del_capability(dev, PCI_CAP_ID_EXP, PCI_EXP_VER2_SIZEOF);
+}
+
+uint8_t pcie_cap_get_type(const PCIDevice *dev)
+{
+    uint32_t pos = dev->exp.exp_cap;
+    assert(pos > 0);
+    return (pci_get_word(dev->config + pos + PCI_EXP_FLAGS) &
+            PCI_EXP_FLAGS_TYPE) >> PCI_EXP_FLAGS_TYPE_SHIFT;
+}
+
+/* MSI/MSI-X */
+/* pci express interrupt message number */
+/* 7.8.2 PCI Express Capabilities Register: Interrupt Message Number */
+void pcie_cap_flags_set_vector(PCIDevice *dev, uint8_t vector)
+{
+    uint8_t *exp_cap = dev->config + dev->exp.exp_cap;
+    assert(vector < 32);
+    pci_word_test_and_clear_mask(exp_cap + PCI_EXP_FLAGS, PCI_EXP_FLAGS_IRQ);
+    pci_word_test_and_set_mask(exp_cap + PCI_EXP_FLAGS,
+                               vector << PCI_EXP_FLAGS_IRQ_SHIFT);
+}
+
+uint8_t pcie_cap_flags_get_vector(PCIDevice *dev)
+{
+    return (pci_get_word(dev->config + dev->exp.exp_cap + PCI_EXP_FLAGS) &
+            PCI_EXP_FLAGS_IRQ) >> PCI_EXP_FLAGS_IRQ_SHIFT;
+}
+
+void pcie_cap_deverr_init(PCIDevice *dev)
+{
+    uint32_t pos = dev->exp.exp_cap;
+    pci_long_test_and_set_mask(dev->config + pos + PCI_EXP_DEVCAP,
+                               PCI_EXP_DEVCAP_RBER);
+    pci_long_test_and_set_mask(dev->wmask + pos + PCI_EXP_DEVCTL,
+                               PCI_EXP_DEVCTL_CERE | PCI_EXP_DEVCTL_NFERE |
+                               PCI_EXP_DEVCTL_FERE | PCI_EXP_DEVCTL_URRE);
+    pci_long_test_and_set_mask(dev->w1cmask + pos + PCI_EXP_DEVSTA,
+                               PCI_EXP_DEVSTA_CED | PCI_EXP_DEVSTA_NFED |
+                               PCI_EXP_DEVSTA_URD | PCI_EXP_DEVSTA_URD);
+}
+
+void pcie_cap_deverr_reset(PCIDevice *dev)
+{
+    uint8_t *devctl = dev->config + dev->exp.exp_cap + PCI_EXP_DEVCTL;
+    pci_long_test_and_clear_mask(devctl,
+                                 PCI_EXP_DEVCTL_CERE | PCI_EXP_DEVCTL_NFERE |
+                                 PCI_EXP_DEVCTL_FERE | PCI_EXP_DEVCTL_URRE);
+}
+
+static void hotplug_event_update_event_status(PCIDevice *dev)
+{
+    uint32_t pos = dev->exp.exp_cap;
+    uint8_t *exp_cap = dev->config + pos;
+    uint16_t sltctl = pci_get_word(exp_cap + PCI_EXP_SLTCTL);
+    uint16_t sltsta = pci_get_word(exp_cap + PCI_EXP_SLTSTA);
+
+    dev->exp.hpev_notified = (sltctl & PCI_EXP_SLTCTL_HPIE) &&
+        (sltsta & sltctl & PCI_EXP_HP_EV_SUPPORTED);
+}
+
+static void hotplug_event_notify(PCIDevice *dev)
+{
+    bool prev = dev->exp.hpev_notified;
+
+    hotplug_event_update_event_status(dev);
+
+    if (prev == dev->exp.hpev_notified) {
+        return;
+    }
+
+    /* Note: the logic above does not take into account whether interrupts
+     * are masked. The result is that interrupt will be sent when it is
+     * subsequently unmasked. This appears to be legal: Section 6.7.3.4:
+     * The Port may optionally send an MSI when there are hot-plug events that
+     * occur while interrupt generation is disabled, and interrupt generation 
is
+     * subsequently enabled. */
+    if (msix_enabled(dev)) {
+        msix_notify(dev, pcie_cap_flags_get_vector(dev));
+    } else if (msi_enabled(dev)) {
+        msi_notify(dev, pcie_cap_flags_get_vector(dev));
+    } else {
+        qemu_set_irq(dev->irq[dev->exp.hpev_intx], dev->exp.hpev_notified);
+    }
+}
+
+static void hotplug_event_clear(PCIDevice *dev)
+{
+    hotplug_event_update_event_status(dev);
+    if (!msix_enabled(dev) && !msi_enabled(dev) && !dev->exp.hpev_notified) {
+        qemu_set_irq(dev->irq[dev->exp.hpev_intx], 0);
+    }
+}
+
+/*
+ * A PCI Express Hot-Plug Event has occurred, so update slot status register
+ * and notify OS of the event if necessary.
+ *
+ * 6.7.3 PCI Express Hot-Plug Events
+ * 6.7.3.4 Software Notification of Hot-Plug Events
+ */
+static void pcie_cap_slot_event(PCIDevice *dev, PCIExpressHotPlugEvent event)
+{
+    /* Minor optimization: if nothing changed - no event is needed. */
+    if (pci_word_test_and_set_mask(dev->config + dev->exp.exp_cap +
+                                   PCI_EXP_SLTSTA, event)) {
+        return;
+    }
+    hotplug_event_notify(dev);
+}
+
+static int pcie_cap_slot_hotplug(DeviceState *qdev,
+                                 PCIDevice *pci_dev, PCIHotplugState state)
+{
+    PCIDevice *d = PCI_DEVICE(qdev);
+    uint8_t *exp_cap = d->config + d->exp.exp_cap;
+    uint16_t sltsta = pci_get_word(exp_cap + PCI_EXP_SLTSTA);
+
+    /* Don't send event when device is enabled during qemu machine creation:
+     * it is present on boot, no hotplug event is necessary. We do send an
+     * event when the device is disabled later. */
+    if (state == PCI_COLDPLUG_ENABLED) {
+        pci_word_test_and_set_mask(exp_cap + PCI_EXP_SLTSTA,
+                                   PCI_EXP_SLTSTA_PDS);
+        return 0;
+    }
+
+    PCIE_DEV_PRINTF(pci_dev, "hotplug state: %d\n", state);
+    if (sltsta & PCI_EXP_SLTSTA_EIS) {
+        /* the slot is electromechanically locked.
+         * This error is propagated up to qdev and then to HMP/QMP.
+         */
+        return -EBUSY;
+    }
+
+    /* TODO: multifunction hot-plug.
+     * Right now, only a device of function = 0 is allowed to be
+     * hot plugged/unplugged.
+     */
+    assert(PCI_FUNC(pci_dev->devfn) == 0);
+
+    if (state == PCI_HOTPLUG_ENABLED) {
+        pci_word_test_and_set_mask(exp_cap + PCI_EXP_SLTSTA,
+                                   PCI_EXP_SLTSTA_PDS);
+        pcie_cap_slot_event(d, PCI_EXP_HP_EV_PDC);
+    } else {
+        qdev_free(&pci_dev->qdev);
+        pci_word_test_and_clear_mask(exp_cap + PCI_EXP_SLTSTA,
+                                     PCI_EXP_SLTSTA_PDS);
+        pcie_cap_slot_event(d, PCI_EXP_HP_EV_PDC);
+    }
+    return 0;
+}
+
+/* pci express slot for pci express root/downstream port
+   PCI express capability slot registers */
+void pcie_cap_slot_init(PCIDevice *dev, uint16_t slot)
+{
+    uint32_t pos = dev->exp.exp_cap;
+
+    pci_word_test_and_set_mask(dev->config + pos + PCI_EXP_FLAGS,
+                               PCI_EXP_FLAGS_SLOT);
+
+    pci_long_test_and_clear_mask(dev->config + pos + PCI_EXP_SLTCAP,
+                                 ~PCI_EXP_SLTCAP_PSN);
+    pci_long_test_and_set_mask(dev->config + pos + PCI_EXP_SLTCAP,
+                               (slot << PCI_EXP_SLTCAP_PSN_SHIFT) |
+                               PCI_EXP_SLTCAP_EIP |
+                               PCI_EXP_SLTCAP_HPS |
+                               PCI_EXP_SLTCAP_HPC |
+                               PCI_EXP_SLTCAP_PIP |
+                               PCI_EXP_SLTCAP_AIP |
+                               PCI_EXP_SLTCAP_ABP);
+
+    pci_word_test_and_clear_mask(dev->config + pos + PCI_EXP_SLTCTL,
+                                 PCI_EXP_SLTCTL_PIC |
+                                 PCI_EXP_SLTCTL_AIC);
+    pci_word_test_and_set_mask(dev->config + pos + PCI_EXP_SLTCTL,
+                               PCI_EXP_SLTCTL_PIC_OFF |
+                               PCI_EXP_SLTCTL_AIC_OFF);
+    pci_word_test_and_set_mask(dev->wmask + pos + PCI_EXP_SLTCTL,
+                               PCI_EXP_SLTCTL_PIC |
+                               PCI_EXP_SLTCTL_AIC |
+                               PCI_EXP_SLTCTL_HPIE |
+                               PCI_EXP_SLTCTL_CCIE |
+                               PCI_EXP_SLTCTL_PDCE |
+                               PCI_EXP_SLTCTL_ABPE);
+    /* Although reading PCI_EXP_SLTCTL_EIC returns always 0,
+     * make the bit writable here in order to detect 1b is written.
+     * pcie_cap_slot_write_config() test-and-clear the bit, so
+     * this bit always returns 0 to the guest.
+     */
+    pci_word_test_and_set_mask(dev->wmask + pos + PCI_EXP_SLTCTL,
+                               PCI_EXP_SLTCTL_EIC);
+
+    pci_word_test_and_set_mask(dev->w1cmask + pos + PCI_EXP_SLTSTA,
+                               PCI_EXP_HP_EV_SUPPORTED);
+
+    dev->exp.hpev_notified = false;
+
+    pci_bus_hotplug(pci_bridge_get_sec_bus(DO_UPCAST(PCIBridge, dev, dev)),
+                    pcie_cap_slot_hotplug, &dev->qdev);
+}
+
+void pcie_cap_slot_reset(PCIDevice *dev)
+{
+    uint8_t *exp_cap = dev->config + dev->exp.exp_cap;
+
+    PCIE_DEV_PRINTF(dev, "reset\n");
+
+    pci_word_test_and_clear_mask(exp_cap + PCI_EXP_SLTCTL,
+                                 PCI_EXP_SLTCTL_EIC |
+                                 PCI_EXP_SLTCTL_PIC |
+                                 PCI_EXP_SLTCTL_AIC |
+                                 PCI_EXP_SLTCTL_HPIE |
+                                 PCI_EXP_SLTCTL_CCIE |
+                                 PCI_EXP_SLTCTL_PDCE |
+                                 PCI_EXP_SLTCTL_ABPE);
+    pci_word_test_and_set_mask(exp_cap + PCI_EXP_SLTCTL,
+                               PCI_EXP_SLTCTL_PIC_OFF |
+                               PCI_EXP_SLTCTL_AIC_OFF);
+
+    pci_word_test_and_clear_mask(exp_cap + PCI_EXP_SLTSTA,
+                                 PCI_EXP_SLTSTA_EIS |/* on reset,
+                                                        the lock is released */
+                                 PCI_EXP_SLTSTA_CC |
+                                 PCI_EXP_SLTSTA_PDC |
+                                 PCI_EXP_SLTSTA_ABP);
+
+    hotplug_event_update_event_status(dev);
+}
+
+void pcie_cap_slot_write_config(PCIDevice *dev,
+                                uint32_t addr, uint32_t val, int len)
+{
+    uint32_t pos = dev->exp.exp_cap;
+    uint8_t *exp_cap = dev->config + pos;
+    uint16_t sltsta = pci_get_word(exp_cap + PCI_EXP_SLTSTA);
+
+    if (ranges_overlap(addr, len, pos + PCI_EXP_SLTSTA, 2)) {
+        hotplug_event_clear(dev);
+    }
+
+    if (!ranges_overlap(addr, len, pos + PCI_EXP_SLTCTL, 2)) {
+        return;
+    }
+
+    if (pci_word_test_and_clear_mask(exp_cap + PCI_EXP_SLTCTL,
+                                     PCI_EXP_SLTCTL_EIC)) {
+        sltsta ^= PCI_EXP_SLTSTA_EIS; /* toggle PCI_EXP_SLTSTA_EIS bit */
+        pci_set_word(exp_cap + PCI_EXP_SLTSTA, sltsta);
+        PCIE_DEV_PRINTF(dev, "PCI_EXP_SLTCTL_EIC: "
+                        "sltsta -> 0x%02"PRIx16"\n",
+                        sltsta);
+    }
+
+    hotplug_event_notify(dev);
+
+    /* 
+     * 6.7.3.2 Command Completed Events
+     *
+     * Software issues a command to a hot-plug capable Downstream Port by
+     * issuing a write transaction that targets any portion of the Port’s Slot
+     * Control register. A single write to the Slot Control register is
+     * considered to be a single command, even if the write affects more than
+     * one field in the Slot Control register. In response to this transaction,
+     * the Port must carry out the requested actions and then set the
+     * associated status field for the command completed event. */
+
+    /* Real hardware might take a while to complete requested command because
+     * physical movement would be involved like locking the electromechanical
+     * lock.  However in our case, command is completed instantaneously above,
+     * so send a command completion event right now.
+     */
+    pcie_cap_slot_event(dev, PCI_EXP_HP_EV_CCI);
+}
+
+int pcie_cap_slot_post_load(void *opaque, int version_id)
+{
+    PCIDevice *dev = opaque;
+    hotplug_event_update_event_status(dev);
+    return 0;
+}
+
+void pcie_cap_slot_push_attention_button(PCIDevice *dev)
+{
+    pcie_cap_slot_event(dev, PCI_EXP_HP_EV_ABP);
+}
+
+/* root control/capabilities/status. PME isn't emulated for now */
+void pcie_cap_root_init(PCIDevice *dev)
+{
+    pci_set_word(dev->wmask + dev->exp.exp_cap + PCI_EXP_RTCTL,
+                 PCI_EXP_RTCTL_SECEE | PCI_EXP_RTCTL_SENFEE |
+                 PCI_EXP_RTCTL_SEFEE);
+}
+
+void pcie_cap_root_reset(PCIDevice *dev)
+{
+    pci_set_word(dev->config + dev->exp.exp_cap + PCI_EXP_RTCTL, 0);
+}
+
+/* function level reset(FLR) */
+void pcie_cap_flr_init(PCIDevice *dev)
+{
+    pci_long_test_and_set_mask(dev->config + dev->exp.exp_cap + PCI_EXP_DEVCAP,
+                               PCI_EXP_DEVCAP_FLR);
+
+    /* Although reading BCR_FLR returns always 0,
+     * the bit is made writable here in order to detect the 1b is written
+     * pcie_cap_flr_write_config() test-and-clear the bit, so
+     * this bit always returns 0 to the guest.
+     */
+    pci_word_test_and_set_mask(dev->wmask + dev->exp.exp_cap + PCI_EXP_DEVCTL,
+                               PCI_EXP_DEVCTL_BCR_FLR);
+}
+
+void pcie_cap_flr_write_config(PCIDevice *dev,
+                               uint32_t addr, uint32_t val, int len)
+{
+    uint8_t *devctl = dev->config + dev->exp.exp_cap + PCI_EXP_DEVCTL;
+    if (pci_get_word(devctl) & PCI_EXP_DEVCTL_BCR_FLR) {
+        /* Clear PCI_EXP_DEVCTL_BCR_FLR after invoking the reset handler
+           so the handler can detect FLR by looking at this bit. */
+        pci_device_reset(dev);
+        pci_word_test_and_clear_mask(devctl, PCI_EXP_DEVCTL_BCR_FLR);
+    }
+}
+
+/* Alternative Routing-ID Interpretation (ARI) */
+/* ari forwarding support for down stream port */
+void pcie_cap_ari_init(PCIDevice *dev)
+{
+    uint32_t pos = dev->exp.exp_cap;
+    pci_long_test_and_set_mask(dev->config + pos + PCI_EXP_DEVCAP2,
+                               PCI_EXP_DEVCAP2_ARI);
+    pci_long_test_and_set_mask(dev->wmask + pos + PCI_EXP_DEVCTL2,
+                               PCI_EXP_DEVCTL2_ARI);
+}
+
+void pcie_cap_ari_reset(PCIDevice *dev)
+{
+    uint8_t *devctl2 = dev->config + dev->exp.exp_cap + PCI_EXP_DEVCTL2;
+    pci_long_test_and_clear_mask(devctl2, PCI_EXP_DEVCTL2_ARI);
+}
+
+bool pcie_cap_is_ari_enabled(const PCIDevice *dev)
+{
+    if (!pci_is_express(dev)) {
+        return false;
+    }
+    if (!dev->exp.exp_cap) {
+        return false;
+    }
+
+    return pci_get_long(dev->config + dev->exp.exp_cap + PCI_EXP_DEVCTL2) &
+        PCI_EXP_DEVCTL2_ARI;
+}
+
+/**************************************************************************
+ * pci express extended capability allocation functions
+ * uint16_t ext_cap_id (16 bit)
+ * uint8_t cap_ver (4 bit)
+ * uint16_t cap_offset (12 bit)
+ * uint16_t ext_cap_size
+ */
+
+static uint16_t pcie_find_capability_list(PCIDevice *dev, uint16_t cap_id,
+                                          uint16_t *prev_p)
+{
+    uint16_t prev = 0;
+    uint16_t next;
+    uint32_t header = pci_get_long(dev->config + PCI_CONFIG_SPACE_SIZE);
+
+    if (!header) {
+        /* no extended capability */
+        next = 0;
+        goto out;
+    }
+    for (next = PCI_CONFIG_SPACE_SIZE; next;
+         prev = next, next = PCI_EXT_CAP_NEXT(header)) {
+
+        assert(next >= PCI_CONFIG_SPACE_SIZE);
+        assert(next <= PCIE_CONFIG_SPACE_SIZE - 8);
+
+        header = pci_get_long(dev->config + next);
+        if (PCI_EXT_CAP_ID(header) == cap_id) {
+            break;
+        }
+    }
+
+out:
+    if (prev_p) {
+        *prev_p = prev;
+    }
+    return next;
+}
+
+uint16_t pcie_find_capability(PCIDevice *dev, uint16_t cap_id)
+{
+    return pcie_find_capability_list(dev, cap_id, NULL);
+}
+
+static void pcie_ext_cap_set_next(PCIDevice *dev, uint16_t pos, uint16_t next)
+{
+    uint16_t header = pci_get_long(dev->config + pos);
+    assert(!(next & (PCI_EXT_CAP_ALIGN - 1)));
+    header = (header & ~PCI_EXT_CAP_NEXT_MASK) |
+        ((next << PCI_EXT_CAP_NEXT_SHIFT) & PCI_EXT_CAP_NEXT_MASK);
+    pci_set_long(dev->config + pos, header);
+}
+
+/*
+ * caller must supply valid (offset, size) * such that the range shouldn't
+ * overlap with other capability or other registers.
+ * This function doesn't check it.
+ */
+void pcie_add_capability(PCIDevice *dev,
+                         uint16_t cap_id, uint8_t cap_ver,
+                         uint16_t offset, uint16_t size)
+{
+    uint32_t header;
+    uint16_t next;
+
+    assert(offset >= PCI_CONFIG_SPACE_SIZE);
+    assert(offset < offset + size);
+    assert(offset + size < PCIE_CONFIG_SPACE_SIZE);
+    assert(size >= 8);
+    assert(pci_is_express(dev));
+
+    if (offset == PCI_CONFIG_SPACE_SIZE) {
+        header = pci_get_long(dev->config + offset);
+        next = PCI_EXT_CAP_NEXT(header);
+    } else {
+        uint16_t prev;
+
+        /* 0 is reserved cap id. use internally to find the last capability
+           in the linked list */
+        next = pcie_find_capability_list(dev, 0, &prev);
+
+        assert(prev >= PCI_CONFIG_SPACE_SIZE);
+        assert(next == 0);
+        pcie_ext_cap_set_next(dev, prev, offset);
+    }
+    pci_set_long(dev->config + offset, PCI_EXT_CAP(cap_id, cap_ver, next));
+
+    /* Make capability read-only by default */
+    memset(dev->wmask + offset, 0, size);
+    memset(dev->w1cmask + offset, 0, size);
+    /* Check capability by default */
+    memset(dev->cmask + offset, 0xFF, size);
+}
+
+/**************************************************************************
+ * pci express extended capability helper functions
+ */
+
+/* ARI */
+void pcie_ari_init(PCIDevice *dev, uint16_t offset, uint16_t nextfn)
+{
+    pcie_add_capability(dev, PCI_EXT_CAP_ID_ARI, PCI_ARI_VER,
+                        offset, PCI_ARI_SIZEOF);
+    pci_set_long(dev->config + offset + PCI_ARI_CAP, PCI_ARI_CAP_NFN(nextfn));
+}
diff --git a/hw/pci/pcie.h b/hw/pci/pcie.h
new file mode 100644
index 0000000..4889194
--- /dev/null
+++ b/hw/pci/pcie.h
@@ -0,0 +1,142 @@
+/*
+ * pcie.h
+ *
+ * Copyright (c) 2010 Isaku Yamahata <yamahata at valinux co jp>
+ *                    VA Linux Systems Japan K.K.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef QEMU_PCIE_H
+#define QEMU_PCIE_H
+
+#include "hw.h"
+#include "pci_regs.h"
+#include "pcie_regs.h"
+#include "pcie_aer.h"
+
+typedef enum {
+    /* for attention and power indicator */
+    PCI_EXP_HP_IND_RESERVED     = PCI_EXP_SLTCTL_IND_RESERVED,
+    PCI_EXP_HP_IND_ON           = PCI_EXP_SLTCTL_IND_ON,
+    PCI_EXP_HP_IND_BLINK        = PCI_EXP_SLTCTL_IND_BLINK,
+    PCI_EXP_HP_IND_OFF          = PCI_EXP_SLTCTL_IND_OFF,
+} PCIExpressIndicator;
+
+typedef enum {
+    /* these bits must match the bits in Slot Control/Status registers.
+     * PCI_EXP_HP_EV_xxx = PCI_EXP_SLTCTL_xxxE = PCI_EXP_SLTSTA_xxx
+     *
+     * Not all the bits of slot control register match with the ones of
+     * slot status. Not some bits of slot status register is used to
+     * show status, not to report event occurrence.
+     * So such bits must be masked out when checking the software
+     * notification condition.
+     */
+    PCI_EXP_HP_EV_ABP           = PCI_EXP_SLTCTL_ABPE,
+                                        /* attention button pressed */
+    PCI_EXP_HP_EV_PDC           = PCI_EXP_SLTCTL_PDCE,
+                                        /* presence detect changed */
+    PCI_EXP_HP_EV_CCI           = PCI_EXP_SLTCTL_CCIE,
+                                        /* command completed */
+
+    PCI_EXP_HP_EV_SUPPORTED     = PCI_EXP_HP_EV_ABP |
+                                  PCI_EXP_HP_EV_PDC |
+                                  PCI_EXP_HP_EV_CCI,
+                                                /* supported event mask  */
+
+    /* events not listed aren't supported */
+} PCIExpressHotPlugEvent;
+
+struct PCIExpressDevice {
+    /* Offset of express capability in config space */
+    uint8_t exp_cap;
+
+    /* SLOT */
+    unsigned int hpev_intx;     /* INTx for hot plug event (0-3:INT[A-D]#)
+                                 * default is 0 = INTA#
+                                 * If the chip wants to use other interrupt
+                                 * line, initialize this member with the
+                                 * desired number.
+                                 * If the chip dynamically changes this member,
+                                 * also initialize it when loaded as
+                                 * appropreately.
+                                 */
+    bool hpev_notified; /* Logical AND of conditions for hot plug event.
+                         Following 6.7.3.4:
+                         Software Notification of Hot-Plug Events, an interrupt
+                         is sent whenever the logical and of these conditions
+                         transitions from false to true. */
+
+    /* AER */
+    uint16_t aer_cap;
+    PCIEAERLog aer_log;
+    unsigned int aer_intx;      /* INTx for error reporting
+                                 * default is 0 = INTA#
+                                 * If the chip wants to use other interrupt
+                                 * line, initialize this member with the
+                                 * desired number.
+                                 * If the chip dynamically changes this member,
+                                 * also initialize it when loaded as
+                                 * appropreately.
+                                 */
+};
+
+/* PCI express capability helper functions */
+int pcie_cap_init(PCIDevice *dev, uint8_t offset, uint8_t type, uint8_t port);
+void pcie_cap_exit(PCIDevice *dev);
+uint8_t pcie_cap_get_type(const PCIDevice *dev);
+void pcie_cap_flags_set_vector(PCIDevice *dev, uint8_t vector);
+uint8_t pcie_cap_flags_get_vector(PCIDevice *dev);
+
+void pcie_cap_deverr_init(PCIDevice *dev);
+void pcie_cap_deverr_reset(PCIDevice *dev);
+
+void pcie_cap_slot_init(PCIDevice *dev, uint16_t slot);
+void pcie_cap_slot_reset(PCIDevice *dev);
+void pcie_cap_slot_write_config(PCIDevice *dev,
+                                uint32_t addr, uint32_t val, int len);
+int pcie_cap_slot_post_load(void *opaque, int version_id);
+void pcie_cap_slot_push_attention_button(PCIDevice *dev);
+
+void pcie_cap_root_init(PCIDevice *dev);
+void pcie_cap_root_reset(PCIDevice *dev);
+
+void pcie_cap_flr_init(PCIDevice *dev);
+void pcie_cap_flr_write_config(PCIDevice *dev,
+                           uint32_t addr, uint32_t val, int len);
+
+void pcie_cap_ari_init(PCIDevice *dev);
+void pcie_cap_ari_reset(PCIDevice *dev);
+bool pcie_cap_is_ari_enabled(const PCIDevice *dev);
+
+/* PCI express extended capability helper functions */
+uint16_t pcie_find_capability(PCIDevice *dev, uint16_t cap_id);
+void pcie_add_capability(PCIDevice *dev,
+                         uint16_t cap_id, uint8_t cap_ver,
+                         uint16_t offset, uint16_t size);
+
+void pcie_ari_init(PCIDevice *dev, uint16_t offset, uint16_t nextfn);
+
+extern const VMStateDescription vmstate_pcie_device;
+
+#define VMSTATE_PCIE_DEVICE(_field, _state) {                        \
+    .name       = (stringify(_field)),                               \
+    .size       = sizeof(PCIDevice),                                 \
+    .vmsd       = &vmstate_pcie_device,                              \
+    .flags      = VMS_STRUCT,                                        \
+    .offset     = vmstate_offset_value(_state, _field, PCIDevice),   \
+}
+
+#endif /* QEMU_PCIE_H */
diff --git a/hw/pci/pcie_aer.c b/hw/pci/pcie_aer.c
new file mode 100644
index 0000000..b04c164
--- /dev/null
+++ b/hw/pci/pcie_aer.c
@@ -0,0 +1,1032 @@
+/*
+ * pcie_aer.c
+ *
+ * Copyright (c) 2010 Isaku Yamahata <yamahata at valinux co jp>
+ *                    VA Linux Systems Japan K.K.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "sysemu.h"
+#include "qemu-objects.h"
+#include "monitor.h"
+#include "pci_bridge.h"
+#include "pcie.h"
+#include "msix.h"
+#include "msi.h"
+#include "pci_internals.h"
+#include "pcie_regs.h"
+
+//#define DEBUG_PCIE
+#ifdef DEBUG_PCIE
+# define PCIE_DPRINTF(fmt, ...)                                         \
+    fprintf(stderr, "%s:%d " fmt, __func__, __LINE__, ## __VA_ARGS__)
+#else
+# define PCIE_DPRINTF(fmt, ...) do {} while (0)
+#endif
+#define PCIE_DEV_PRINTF(dev, fmt, ...)                                  \
+    PCIE_DPRINTF("%s:%x "fmt, (dev)->name, (dev)->devfn, ## __VA_ARGS__)
+
+#define PCI_ERR_SRC_COR_OFFS    0
+#define PCI_ERR_SRC_UNCOR_OFFS  2
+
+/* From 6.2.7 Error Listing and Rules. Table 6-2, 6-3 and 6-4 */
+static uint32_t pcie_aer_uncor_default_severity(uint32_t status)
+{
+    switch (status) {
+    case PCI_ERR_UNC_INTN:
+    case PCI_ERR_UNC_DLP:
+    case PCI_ERR_UNC_SDN:
+    case PCI_ERR_UNC_RX_OVER:
+    case PCI_ERR_UNC_FCP:
+    case PCI_ERR_UNC_MALF_TLP:
+        return PCI_ERR_ROOT_CMD_FATAL_EN;
+    case PCI_ERR_UNC_POISON_TLP:
+    case PCI_ERR_UNC_ECRC:
+    case PCI_ERR_UNC_UNSUP:
+    case PCI_ERR_UNC_COMP_TIME:
+    case PCI_ERR_UNC_COMP_ABORT:
+    case PCI_ERR_UNC_UNX_COMP:
+    case PCI_ERR_UNC_ACSV:
+    case PCI_ERR_UNC_MCBTLP:
+    case PCI_ERR_UNC_ATOP_EBLOCKED:
+    case PCI_ERR_UNC_TLP_PRF_BLOCKED:
+        return PCI_ERR_ROOT_CMD_NONFATAL_EN;
+    default:
+        abort();
+        break;
+    }
+    return PCI_ERR_ROOT_CMD_FATAL_EN;
+}
+
+static int aer_log_add_err(PCIEAERLog *aer_log, const PCIEAERErr *err)
+{
+    if (aer_log->log_num == aer_log->log_max) {
+        return -1;
+    }
+    memcpy(&aer_log->log[aer_log->log_num], err, sizeof *err);
+    aer_log->log_num++;
+    return 0;
+}
+
+static void aer_log_del_err(PCIEAERLog *aer_log, PCIEAERErr *err)
+{
+    assert(aer_log->log_num);
+    *err = aer_log->log[0];
+    aer_log->log_num--;
+    memmove(&aer_log->log[0], &aer_log->log[1],
+            aer_log->log_num * sizeof *err);
+}
+
+static void aer_log_clear_all_err(PCIEAERLog *aer_log)
+{
+    aer_log->log_num = 0;
+}
+
+int pcie_aer_init(PCIDevice *dev, uint16_t offset)
+{
+    PCIExpressDevice *exp;
+
+    pcie_add_capability(dev, PCI_EXT_CAP_ID_ERR, PCI_ERR_VER,
+                        offset, PCI_ERR_SIZEOF);
+    exp = &dev->exp;
+    exp->aer_cap = offset;
+
+    /* log_max is property */
+    if (dev->exp.aer_log.log_max == PCIE_AER_LOG_MAX_UNSET) {
+        dev->exp.aer_log.log_max = PCIE_AER_LOG_MAX_DEFAULT;
+    }
+    /* clip down the value to avoid unreasobale memory usage */
+    if (dev->exp.aer_log.log_max > PCIE_AER_LOG_MAX_LIMIT) {
+        return -EINVAL;
+    }
+    dev->exp.aer_log.log = g_malloc0(sizeof dev->exp.aer_log.log[0] *
+                                        dev->exp.aer_log.log_max);
+
+    pci_set_long(dev->w1cmask + offset + PCI_ERR_UNCOR_STATUS,
+                 PCI_ERR_UNC_SUPPORTED);
+
+    pci_set_long(dev->config + offset + PCI_ERR_UNCOR_SEVER,
+                 PCI_ERR_UNC_SEVERITY_DEFAULT);
+    pci_set_long(dev->wmask + offset + PCI_ERR_UNCOR_SEVER,
+                 PCI_ERR_UNC_SUPPORTED);
+
+    pci_long_test_and_set_mask(dev->w1cmask + offset + PCI_ERR_COR_STATUS,
+                               PCI_ERR_COR_STATUS);
+
+    pci_set_long(dev->config + offset + PCI_ERR_COR_MASK,
+                 PCI_ERR_COR_MASK_DEFAULT);
+    pci_set_long(dev->wmask + offset + PCI_ERR_COR_MASK,
+                 PCI_ERR_COR_SUPPORTED);
+
+    /* capabilities and control. multiple header logging is supported */
+    if (dev->exp.aer_log.log_max > 0) {
+        pci_set_long(dev->config + offset + PCI_ERR_CAP,
+                     PCI_ERR_CAP_ECRC_GENC | PCI_ERR_CAP_ECRC_CHKC |
+                     PCI_ERR_CAP_MHRC);
+        pci_set_long(dev->wmask + offset + PCI_ERR_CAP,
+                     PCI_ERR_CAP_ECRC_GENE | PCI_ERR_CAP_ECRC_CHKE |
+                     PCI_ERR_CAP_MHRE);
+    } else {
+        pci_set_long(dev->config + offset + PCI_ERR_CAP,
+                     PCI_ERR_CAP_ECRC_GENC | PCI_ERR_CAP_ECRC_CHKC);
+        pci_set_long(dev->wmask + offset + PCI_ERR_CAP,
+                     PCI_ERR_CAP_ECRC_GENE | PCI_ERR_CAP_ECRC_CHKE);
+    }
+
+    switch (pcie_cap_get_type(dev)) {
+    case PCI_EXP_TYPE_ROOT_PORT:
+        /* this case will be set by pcie_aer_root_init() */
+        /* fallthrough */
+    case PCI_EXP_TYPE_DOWNSTREAM:
+    case PCI_EXP_TYPE_UPSTREAM:
+        pci_word_test_and_set_mask(dev->wmask + PCI_BRIDGE_CONTROL,
+                                   PCI_BRIDGE_CTL_SERR);
+        pci_long_test_and_set_mask(dev->w1cmask + PCI_STATUS,
+                                   PCI_SEC_STATUS_RCV_SYSTEM_ERROR);
+        break;
+    default:
+        /* nothing */
+        break;
+    }
+    return 0;
+}
+
+void pcie_aer_exit(PCIDevice *dev)
+{
+    g_free(dev->exp.aer_log.log);
+}
+
+static void pcie_aer_update_uncor_status(PCIDevice *dev)
+{
+    uint8_t *aer_cap = dev->config + dev->exp.aer_cap;
+    PCIEAERLog *aer_log = &dev->exp.aer_log;
+
+    uint16_t i;
+    for (i = 0; i < aer_log->log_num; i++) {
+        pci_long_test_and_set_mask(aer_cap + PCI_ERR_UNCOR_STATUS,
+                                   dev->exp.aer_log.log[i].status);
+    }
+}
+
+/*
+ * return value:
+ * true: error message needs to be sent up
+ * false: error message is masked
+ *
+ * 6.2.6 Error Message Control
+ * Figure 6-3
+ * all pci express devices part
+ */
+static bool
+pcie_aer_msg_alldev(PCIDevice *dev, const PCIEAERMsg *msg)
+{
+    if (!(pcie_aer_msg_is_uncor(msg) &&
+          (pci_get_word(dev->config + PCI_COMMAND) & PCI_COMMAND_SERR))) {
+        return false;
+    }
+
+    /* Signaled System Error
+     *
+     * 7.5.1.1 Command register
+     * Bit 8 SERR# Enable
+     *
+     * When Set, this bit enables reporting of Non-fatal and Fatal
+     * errors detected by the Function to the Root Complex. Note that
+     * errors are reported if enabled either through this bit or through
+     * the PCI Express specific bits in the Device Control register (see
+     * Section 7.8.4).
+     */
+    pci_word_test_and_set_mask(dev->config + PCI_STATUS,
+                               PCI_STATUS_SIG_SYSTEM_ERROR);
+
+    if (!(msg->severity &
+          pci_get_word(dev->config + dev->exp.exp_cap + PCI_EXP_DEVCTL))) {
+        return false;
+    }
+
+    /* send up error message */
+    return true;
+}
+
+/*
+ * return value:
+ * true: error message is sent up
+ * false: error message is masked
+ *
+ * 6.2.6 Error Message Control
+ * Figure 6-3
+ * virtual pci bridge part
+ */
+static bool pcie_aer_msg_vbridge(PCIDevice *dev, const PCIEAERMsg *msg)
+{
+    uint16_t bridge_control = pci_get_word(dev->config + PCI_BRIDGE_CONTROL);
+
+    if (pcie_aer_msg_is_uncor(msg)) {
+        /* Received System Error */
+        pci_word_test_and_set_mask(dev->config + PCI_SEC_STATUS,
+                                   PCI_SEC_STATUS_RCV_SYSTEM_ERROR);
+    }
+
+    if (!(bridge_control & PCI_BRIDGE_CTL_SERR)) {
+        return false;
+    }
+    return true;
+}
+
+void pcie_aer_root_set_vector(PCIDevice *dev, unsigned int vector)
+{
+    uint8_t *aer_cap = dev->config + dev->exp.aer_cap;
+    assert(vector < PCI_ERR_ROOT_IRQ_MAX);
+    pci_long_test_and_clear_mask(aer_cap + PCI_ERR_ROOT_STATUS,
+                                 PCI_ERR_ROOT_IRQ);
+    pci_long_test_and_set_mask(aer_cap + PCI_ERR_ROOT_STATUS,
+                               vector << PCI_ERR_ROOT_IRQ_SHIFT);
+}
+
+static unsigned int pcie_aer_root_get_vector(PCIDevice *dev)
+{
+    uint8_t *aer_cap = dev->config + dev->exp.aer_cap;
+    uint32_t root_status = pci_get_long(aer_cap + PCI_ERR_ROOT_STATUS);
+    return (root_status & PCI_ERR_ROOT_IRQ) >> PCI_ERR_ROOT_IRQ_SHIFT;
+}
+
+/* Given a status register, get corresponding bits in the command register */
+static uint32_t pcie_aer_status_to_cmd(uint32_t status)
+{
+    uint32_t cmd = 0;
+    if (status & PCI_ERR_ROOT_COR_RCV) {
+        cmd |= PCI_ERR_ROOT_CMD_COR_EN;
+    }
+    if (status & PCI_ERR_ROOT_NONFATAL_RCV) {
+        cmd |= PCI_ERR_ROOT_CMD_NONFATAL_EN;
+    }
+    if (status & PCI_ERR_ROOT_FATAL_RCV) {
+        cmd |= PCI_ERR_ROOT_CMD_FATAL_EN;
+    }
+    return cmd;
+}
+
+static void pcie_aer_root_notify(PCIDevice *dev)
+{
+    if (msix_enabled(dev)) {
+        msix_notify(dev, pcie_aer_root_get_vector(dev));
+    } else if (msi_enabled(dev)) {
+        msi_notify(dev, pcie_aer_root_get_vector(dev));
+    } else {
+        qemu_set_irq(dev->irq[dev->exp.aer_intx], 1);
+    }
+}
+
+/*
+ * 6.2.6 Error Message Control
+ * Figure 6-3
+ * root port part
+ */
+static void pcie_aer_msg_root_port(PCIDevice *dev, const PCIEAERMsg *msg)
+{
+    uint16_t cmd;
+    uint8_t *aer_cap;
+    uint32_t root_cmd;
+    uint32_t root_status, prev_status;
+
+    cmd = pci_get_word(dev->config + PCI_COMMAND);
+    aer_cap = dev->config + dev->exp.aer_cap;
+    root_cmd = pci_get_long(aer_cap + PCI_ERR_ROOT_COMMAND);
+    prev_status = root_status = pci_get_long(aer_cap + PCI_ERR_ROOT_STATUS);
+
+    if (cmd & PCI_COMMAND_SERR) {
+        /* System Error.
+         *
+         * The way to report System Error is platform specific and
+         * it isn't implemented in qemu right now.
+         * So just discard the error for now.
+         * OS which cares of aer would receive errors via
+         * native aer mechanims, so this wouldn't matter.
+         */
+    }
+
+    /* Errro Message Received: Root Error Status register */
+    switch (msg->severity) {
+    case PCI_ERR_ROOT_CMD_COR_EN:
+        if (root_status & PCI_ERR_ROOT_COR_RCV) {
+            root_status |= PCI_ERR_ROOT_MULTI_COR_RCV;
+        } else {
+            pci_set_word(aer_cap + PCI_ERR_ROOT_ERR_SRC + PCI_ERR_SRC_COR_OFFS,
+                         msg->source_id);
+        }
+        root_status |= PCI_ERR_ROOT_COR_RCV;
+        break;
+    case PCI_ERR_ROOT_CMD_NONFATAL_EN:
+        root_status |= PCI_ERR_ROOT_NONFATAL_RCV;
+        break;
+    case PCI_ERR_ROOT_CMD_FATAL_EN:
+        if (!(root_status & PCI_ERR_ROOT_UNCOR_RCV)) {
+            root_status |= PCI_ERR_ROOT_FIRST_FATAL;
+        }
+        root_status |= PCI_ERR_ROOT_FATAL_RCV;
+        break;
+    default:
+        abort();
+        break;
+    }
+    if (pcie_aer_msg_is_uncor(msg)) {
+        if (root_status & PCI_ERR_ROOT_UNCOR_RCV) {
+            root_status |= PCI_ERR_ROOT_MULTI_UNCOR_RCV;
+        } else {
+            pci_set_word(aer_cap + PCI_ERR_ROOT_ERR_SRC +
+                         PCI_ERR_SRC_UNCOR_OFFS, msg->source_id);
+        }
+        root_status |= PCI_ERR_ROOT_UNCOR_RCV;
+    }
+    pci_set_long(aer_cap + PCI_ERR_ROOT_STATUS, root_status);
+
+    /* 6.2.4.1.2 Interrupt Generation */
+    /* All the above did was set some bits in the status register.
+     * Specifically these that match message severity.
+     * The below code relies on this fact. */
+    if (!(root_cmd & msg->severity) ||
+        (pcie_aer_status_to_cmd(prev_status) & root_cmd)) {
+        /* Condition is not being set or was already true so nothing to do. */
+        return;
+    }
+
+    pcie_aer_root_notify(dev);
+}
+
+/*
+ * 6.2.6 Error Message Control Figure 6-3
+ *
+ * Walk up the bus tree from the device, propagate the error message.
+ */
+static void pcie_aer_msg(PCIDevice *dev, const PCIEAERMsg *msg)
+{
+    uint8_t type;
+
+    while (dev) {
+        if (!pci_is_express(dev)) {
+            /* just ignore it */
+            /* TODO: Shouldn't we set PCI_STATUS_SIG_SYSTEM_ERROR?
+             * Consider e.g. a PCI bridge above a PCI Express device. */
+            return;
+        }
+
+        type = pcie_cap_get_type(dev);
+        if ((type == PCI_EXP_TYPE_ROOT_PORT ||
+            type == PCI_EXP_TYPE_UPSTREAM ||
+            type == PCI_EXP_TYPE_DOWNSTREAM) &&
+            !pcie_aer_msg_vbridge(dev, msg)) {
+                return;
+        }
+        if (!pcie_aer_msg_alldev(dev, msg)) {
+            return;
+        }
+        if (type == PCI_EXP_TYPE_ROOT_PORT) {
+            pcie_aer_msg_root_port(dev, msg);
+            /* Root port can notify system itself,
+               or send the error message to root complex event collector. */
+            /*
+             * if root port is associated with an event collector,
+             * return the root complex event collector here.
+             * For now root complex event collector isn't supported.
+             */
+            return;
+        }
+        dev = pci_bridge_get_device(dev->bus);
+    }
+}
+
+static void pcie_aer_update_log(PCIDevice *dev, const PCIEAERErr *err)
+{
+    uint8_t *aer_cap = dev->config + dev->exp.aer_cap;
+    uint8_t first_bit = ffs(err->status) - 1;
+    uint32_t errcap = pci_get_long(aer_cap + PCI_ERR_CAP);
+    int i;
+
+    assert(err->status);
+    assert(!(err->status & (err->status - 1)));
+
+    errcap &= ~(PCI_ERR_CAP_FEP_MASK | PCI_ERR_CAP_TLP);
+    errcap |= PCI_ERR_CAP_FEP(first_bit);
+
+    if (err->flags & PCIE_AER_ERR_HEADER_VALID) {
+        for (i = 0; i < ARRAY_SIZE(err->header); ++i) {
+            /* 7.10.8 Header Log Register */
+            uint8_t *header_log =
+                aer_cap + PCI_ERR_HEADER_LOG + i * sizeof err->header[0];
+            cpu_to_be32wu((uint32_t*)header_log, err->header[i]);
+        }
+    } else {
+        assert(!(err->flags & PCIE_AER_ERR_TLP_PREFIX_PRESENT));
+        memset(aer_cap + PCI_ERR_HEADER_LOG, 0, PCI_ERR_HEADER_LOG_SIZE);
+    }
+
+    if ((err->flags & PCIE_AER_ERR_TLP_PREFIX_PRESENT) &&
+        (pci_get_long(dev->config + dev->exp.exp_cap + PCI_EXP_DEVCTL2) &
+         PCI_EXP_DEVCAP2_EETLPP)) {
+        for (i = 0; i < ARRAY_SIZE(err->prefix); ++i) {
+            /* 7.10.12 tlp prefix log register */
+            uint8_t *prefix_log =
+                aer_cap + PCI_ERR_TLP_PREFIX_LOG + i * sizeof err->prefix[0];
+            cpu_to_be32wu((uint32_t*)prefix_log, err->prefix[i]);
+        }
+        errcap |= PCI_ERR_CAP_TLP;
+    } else {
+        memset(aer_cap + PCI_ERR_TLP_PREFIX_LOG, 0,
+               PCI_ERR_TLP_PREFIX_LOG_SIZE);
+    }
+    pci_set_long(aer_cap + PCI_ERR_CAP, errcap);
+}
+
+static void pcie_aer_clear_log(PCIDevice *dev)
+{
+    uint8_t *aer_cap = dev->config + dev->exp.aer_cap;
+
+    pci_long_test_and_clear_mask(aer_cap + PCI_ERR_CAP,
+                                 PCI_ERR_CAP_FEP_MASK | PCI_ERR_CAP_TLP);
+
+    memset(aer_cap + PCI_ERR_HEADER_LOG, 0, PCI_ERR_HEADER_LOG_SIZE);
+    memset(aer_cap + PCI_ERR_TLP_PREFIX_LOG, 0, PCI_ERR_TLP_PREFIX_LOG_SIZE);
+}
+
+static void pcie_aer_clear_error(PCIDevice *dev)
+{
+    uint8_t *aer_cap = dev->config + dev->exp.aer_cap;
+    uint32_t errcap = pci_get_long(aer_cap + PCI_ERR_CAP);
+    PCIEAERLog *aer_log = &dev->exp.aer_log;
+    PCIEAERErr err;
+
+    if (!(errcap & PCI_ERR_CAP_MHRE) || !aer_log->log_num) {
+        pcie_aer_clear_log(dev);
+        return;
+    }
+
+    /*
+     * If more errors are queued, set corresponding bits in uncorrectable
+     * error status.
+     * We emulate uncorrectable error status register as W1CS.
+     * So set bit in uncorrectable error status here again for multiple
+     * error recording support.
+     *
+     * 6.2.4.2 Multiple Error Handling(Advanced Error Reporting Capability)
+     */
+    pcie_aer_update_uncor_status(dev);
+
+    aer_log_del_err(aer_log, &err);
+    pcie_aer_update_log(dev, &err);
+}
+
+static int pcie_aer_record_error(PCIDevice *dev,
+                                 const PCIEAERErr *err)
+{
+    uint8_t *aer_cap = dev->config + dev->exp.aer_cap;
+    uint32_t errcap = pci_get_long(aer_cap + PCI_ERR_CAP);
+    int fep = PCI_ERR_CAP_FEP(errcap);
+
+    assert(err->status);
+    assert(!(err->status & (err->status - 1)));
+
+    if (errcap & PCI_ERR_CAP_MHRE &&
+        (pci_get_long(aer_cap + PCI_ERR_UNCOR_STATUS) & (1U << fep))) {
+        /*  Not first error. queue error */
+        if (aer_log_add_err(&dev->exp.aer_log, err) < 0) {
+            /* overflow */
+            return -1;
+        }
+        return 0;
+    }
+
+    pcie_aer_update_log(dev, err);
+    return 0;
+}
+
+typedef struct PCIEAERInject {
+    PCIDevice *dev;
+    uint8_t *aer_cap;
+    const PCIEAERErr *err;
+    uint16_t devctl;
+    uint16_t devsta;
+    uint32_t error_status;
+    bool unsupported_request;
+    bool log_overflow;
+    PCIEAERMsg msg;
+} PCIEAERInject;
+
+static bool pcie_aer_inject_cor_error(PCIEAERInject *inj,
+                                      uint32_t uncor_status,
+                                      bool is_advisory_nonfatal)
+{
+    PCIDevice *dev = inj->dev;
+
+    inj->devsta |= PCI_EXP_DEVSTA_CED;
+    if (inj->unsupported_request) {
+        inj->devsta |= PCI_EXP_DEVSTA_URD;
+    }
+    pci_set_word(dev->config + dev->exp.exp_cap + PCI_EXP_DEVSTA, inj->devsta);
+
+    if (inj->aer_cap) {
+        uint32_t mask;
+        pci_long_test_and_set_mask(inj->aer_cap + PCI_ERR_COR_STATUS,
+                                   inj->error_status);
+        mask = pci_get_long(inj->aer_cap + PCI_ERR_COR_MASK);
+        if (mask & inj->error_status) {
+            return false;
+        }
+        if (is_advisory_nonfatal) {
+            uint32_t uncor_mask =
+                pci_get_long(inj->aer_cap + PCI_ERR_UNCOR_MASK);
+            if (!(uncor_mask & uncor_status)) {
+                inj->log_overflow = !!pcie_aer_record_error(dev, inj->err);
+            }
+            pci_long_test_and_set_mask(inj->aer_cap + PCI_ERR_UNCOR_STATUS,
+                                       uncor_status);
+        }
+    }
+
+    if (inj->unsupported_request && !(inj->devctl & PCI_EXP_DEVCTL_URRE)) {
+        return false;
+    }
+    if (!(inj->devctl & PCI_EXP_DEVCTL_CERE)) {
+        return false;
+    }
+
+    inj->msg.severity = PCI_ERR_ROOT_CMD_COR_EN;
+    return true;
+}
+
+static bool pcie_aer_inject_uncor_error(PCIEAERInject *inj, bool is_fatal)
+{
+    PCIDevice *dev = inj->dev;
+    uint16_t cmd;
+
+    if (is_fatal) {
+        inj->devsta |= PCI_EXP_DEVSTA_FED;
+    } else {
+        inj->devsta |= PCI_EXP_DEVSTA_NFED;
+    }
+    if (inj->unsupported_request) {
+        inj->devsta |= PCI_EXP_DEVSTA_URD;
+    }
+    pci_set_long(dev->config + dev->exp.exp_cap + PCI_EXP_DEVSTA, inj->devsta);
+
+    if (inj->aer_cap) {
+        uint32_t mask = pci_get_long(inj->aer_cap + PCI_ERR_UNCOR_MASK);
+        if (mask & inj->error_status) {
+            pci_long_test_and_set_mask(inj->aer_cap + PCI_ERR_UNCOR_STATUS,
+                                       inj->error_status);
+            return false;
+        }
+
+        inj->log_overflow = !!pcie_aer_record_error(dev, inj->err);
+        pci_long_test_and_set_mask(inj->aer_cap + PCI_ERR_UNCOR_STATUS,
+                                   inj->error_status);
+    }
+
+    cmd = pci_get_word(dev->config + PCI_COMMAND);
+    if (inj->unsupported_request &&
+        !(inj->devctl & PCI_EXP_DEVCTL_URRE) && !(cmd & PCI_COMMAND_SERR)) {
+        return false;
+    }
+    if (is_fatal) {
+        if (!((cmd & PCI_COMMAND_SERR) ||
+              (inj->devctl & PCI_EXP_DEVCTL_FERE))) {
+            return false;
+        }
+        inj->msg.severity = PCI_ERR_ROOT_CMD_FATAL_EN;
+    } else {
+        if (!((cmd & PCI_COMMAND_SERR) ||
+              (inj->devctl & PCI_EXP_DEVCTL_NFERE))) {
+            return false;
+        }
+        inj->msg.severity = PCI_ERR_ROOT_CMD_NONFATAL_EN;
+    }
+    return true;
+}
+
+/*
+ * non-Function specific error must be recorded in all functions.
+ * It is the responsibility of the caller of this function.
+ * It is also caller's responsibility to determine which function should
+ * report the rerror.
+ *
+ * 6.2.4 Error Logging
+ * 6.2.5 Sqeunce of Device Error Signaling and Logging Operations
+ * table 6-2: Flowchard Showing Sequence of Device Error Signaling and Logging
+ *            Operations
+ */
+int pcie_aer_inject_error(PCIDevice *dev, const PCIEAERErr *err)
+{
+    uint8_t *aer_cap = NULL;
+    uint16_t devctl = 0;
+    uint16_t devsta = 0;
+    uint32_t error_status = err->status;
+    PCIEAERInject inj;
+
+    if (!pci_is_express(dev)) {
+        return -ENOSYS;
+    }
+
+    if (err->flags & PCIE_AER_ERR_IS_CORRECTABLE) {
+        error_status &= PCI_ERR_COR_SUPPORTED;
+    } else {
+        error_status &= PCI_ERR_UNC_SUPPORTED;
+    }
+
+    /* invalid status bit. one and only one bit must be set */
+    if (!error_status || (error_status & (error_status - 1))) {
+        return -EINVAL;
+    }
+
+    if (dev->exp.aer_cap) {
+        uint8_t *exp_cap = dev->config + dev->exp.exp_cap;
+        aer_cap = dev->config + dev->exp.aer_cap;
+        devctl = pci_get_long(exp_cap + PCI_EXP_DEVCTL);
+        devsta = pci_get_long(exp_cap + PCI_EXP_DEVSTA);
+    }
+
+    inj.dev = dev;
+    inj.aer_cap = aer_cap;
+    inj.err = err;
+    inj.devctl = devctl;
+    inj.devsta = devsta;
+    inj.error_status = error_status;
+    inj.unsupported_request = !(err->flags & PCIE_AER_ERR_IS_CORRECTABLE) &&
+        err->status == PCI_ERR_UNC_UNSUP;
+    inj.log_overflow = false;
+
+    if (err->flags & PCIE_AER_ERR_IS_CORRECTABLE) {
+        if (!pcie_aer_inject_cor_error(&inj, 0, false)) {
+            return 0;
+        }
+    } else {
+        bool is_fatal =
+            pcie_aer_uncor_default_severity(error_status) ==
+            PCI_ERR_ROOT_CMD_FATAL_EN;
+        if (aer_cap) {
+            is_fatal =
+                error_status & pci_get_long(aer_cap + PCI_ERR_UNCOR_SEVER);
+        }
+        if (!is_fatal && (err->flags & PCIE_AER_ERR_MAYBE_ADVISORY)) {
+            inj.error_status = PCI_ERR_COR_ADV_NONFATAL;
+            if (!pcie_aer_inject_cor_error(&inj, error_status, true)) {
+                return 0;
+            }
+        } else {
+            if (!pcie_aer_inject_uncor_error(&inj, is_fatal)) {
+                return 0;
+            }
+        }
+    }
+
+    /* send up error message */
+    inj.msg.source_id = err->source_id;
+    pcie_aer_msg(dev, &inj.msg);
+
+    if (inj.log_overflow) {
+        PCIEAERErr header_log_overflow = {
+            .status = PCI_ERR_COR_HL_OVERFLOW,
+            .flags = PCIE_AER_ERR_IS_CORRECTABLE,
+        };
+        int ret = pcie_aer_inject_error(dev, &header_log_overflow);
+        assert(!ret);
+    }
+    return 0;
+}
+
+void pcie_aer_write_config(PCIDevice *dev,
+                           uint32_t addr, uint32_t val, int len)
+{
+    uint8_t *aer_cap = dev->config + dev->exp.aer_cap;
+    uint32_t errcap = pci_get_long(aer_cap + PCI_ERR_CAP);
+    uint32_t first_error = 1U << PCI_ERR_CAP_FEP(errcap);
+    uint32_t uncorsta = pci_get_long(aer_cap + PCI_ERR_UNCOR_STATUS);
+
+    /* uncorrectable error */
+    if (!(uncorsta & first_error)) {
+        /* the bit that corresponds to the first error is cleared */
+        pcie_aer_clear_error(dev);
+    } else if (errcap & PCI_ERR_CAP_MHRE) {
+        /* When PCI_ERR_CAP_MHRE is enabled and the first error isn't cleared
+         * nothing should happen. So we have to revert the modification to
+         * the register.
+         */
+        pcie_aer_update_uncor_status(dev);
+    } else {
+        /* capability & control
+         * PCI_ERR_CAP_MHRE might be cleared, so clear of header log.
+         */
+        aer_log_clear_all_err(&dev->exp.aer_log);
+    }
+}
+
+void pcie_aer_root_init(PCIDevice *dev)
+{
+    uint16_t pos = dev->exp.aer_cap;
+
+    pci_set_long(dev->wmask + pos + PCI_ERR_ROOT_COMMAND,
+                 PCI_ERR_ROOT_CMD_EN_MASK);
+    pci_set_long(dev->w1cmask + pos + PCI_ERR_ROOT_STATUS,
+                 PCI_ERR_ROOT_STATUS_REPORT_MASK);
+    /* PCI_ERR_ROOT_IRQ is RO but devices change it using a
+     * device-specific method.
+     */
+    pci_set_long(dev->cmask + pos + PCI_ERR_ROOT_STATUS,
+                 ~PCI_ERR_ROOT_IRQ);
+}
+
+void pcie_aer_root_reset(PCIDevice *dev)
+{
+    uint8_t* aer_cap = dev->config + dev->exp.aer_cap;
+
+    pci_set_long(aer_cap + PCI_ERR_ROOT_COMMAND, 0);
+
+    /*
+     * Advanced Error Interrupt Message Number in Root Error Status Register
+     * must be updated by chip dependent code because it's chip dependent
+     * which number is used.
+     */
+}
+
+void pcie_aer_root_write_config(PCIDevice *dev,
+                                uint32_t addr, uint32_t val, int len,
+                                uint32_t root_cmd_prev)
+{
+    uint8_t *aer_cap = dev->config + dev->exp.aer_cap;
+    uint32_t root_status = pci_get_long(aer_cap + PCI_ERR_ROOT_STATUS);
+    uint32_t enabled_cmd = pcie_aer_status_to_cmd(root_status);
+    uint32_t root_cmd = pci_get_long(aer_cap + PCI_ERR_ROOT_COMMAND);
+    /* 6.2.4.1.2 Interrupt Generation */
+    if (!msix_enabled(dev) && !msi_enabled(dev)) {
+        qemu_set_irq(dev->irq[dev->exp.aer_intx], !!(root_cmd & enabled_cmd));
+        return;
+    }
+
+    if ((root_cmd_prev & enabled_cmd) || !(root_cmd & enabled_cmd)) {
+        /* Send MSI on transition from false to true. */
+        return;
+    }
+
+    pcie_aer_root_notify(dev);
+}
+
+static const VMStateDescription vmstate_pcie_aer_err = {
+    .name = "PCIE_AER_ERROR",
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .minimum_version_id_old = 1,
+    .fields     = (VMStateField[]) {
+        VMSTATE_UINT32(status, PCIEAERErr),
+        VMSTATE_UINT16(source_id, PCIEAERErr),
+        VMSTATE_UINT16(flags, PCIEAERErr),
+        VMSTATE_UINT32_ARRAY(header, PCIEAERErr, 4),
+        VMSTATE_UINT32_ARRAY(prefix, PCIEAERErr, 4),
+        VMSTATE_END_OF_LIST()
+    }
+};
+
+const VMStateDescription vmstate_pcie_aer_log = {
+    .name = "PCIE_AER_ERROR_LOG",
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .minimum_version_id_old = 1,
+    .fields     = (VMStateField[]) {
+        VMSTATE_UINT16(log_num, PCIEAERLog),
+        VMSTATE_UINT16(log_max, PCIEAERLog),
+        VMSTATE_STRUCT_VARRAY_POINTER_UINT16(log, PCIEAERLog, log_num,
+                              vmstate_pcie_aer_err, PCIEAERErr),
+        VMSTATE_END_OF_LIST()
+    }
+};
+
+void pcie_aer_inject_error_print(Monitor *mon, const QObject *data)
+{
+    QDict *qdict;
+    int devfn;
+    assert(qobject_type(data) == QTYPE_QDICT);
+    qdict = qobject_to_qdict(data);
+
+    devfn = (int)qdict_get_int(qdict, "devfn");
+    monitor_printf(mon, "OK id: %s domain: %x, bus: %x devfn: %x.%x\n",
+                   qdict_get_str(qdict, "id"),
+                   (int) qdict_get_int(qdict, "domain"),
+                   (int) qdict_get_int(qdict, "bus"),
+                   PCI_SLOT(devfn), PCI_FUNC(devfn));
+}
+
+typedef struct PCIEAERErrorName {
+    const char *name;
+    uint32_t val;
+    bool correctable;
+} PCIEAERErrorName;
+
+/*
+ * AER error name -> value conversion table
+ * This naming scheme is same to linux aer-injection tool.
+ */
+static const struct PCIEAERErrorName pcie_aer_error_list[] = {
+    {
+        .name = "TRAIN",
+        .val = PCI_ERR_UNC_TRAIN,
+        .correctable = false,
+    }, {
+        .name = "DLP",
+        .val = PCI_ERR_UNC_DLP,
+        .correctable = false,
+    }, {
+        .name = "SDN",
+        .val = PCI_ERR_UNC_SDN,
+        .correctable = false,
+    }, {
+        .name = "POISON_TLP",
+        .val = PCI_ERR_UNC_POISON_TLP,
+        .correctable = false,
+    }, {
+        .name = "FCP",
+        .val = PCI_ERR_UNC_FCP,
+        .correctable = false,
+    }, {
+        .name = "COMP_TIME",
+        .val = PCI_ERR_UNC_COMP_TIME,
+        .correctable = false,
+    }, {
+        .name = "COMP_ABORT",
+        .val = PCI_ERR_UNC_COMP_ABORT,
+        .correctable = false,
+    }, {
+        .name = "UNX_COMP",
+        .val = PCI_ERR_UNC_UNX_COMP,
+        .correctable = false,
+    }, {
+        .name = "RX_OVER",
+        .val = PCI_ERR_UNC_RX_OVER,
+        .correctable = false,
+    }, {
+        .name = "MALF_TLP",
+        .val = PCI_ERR_UNC_MALF_TLP,
+        .correctable = false,
+    }, {
+        .name = "ECRC",
+        .val = PCI_ERR_UNC_ECRC,
+        .correctable = false,
+    }, {
+        .name = "UNSUP",
+        .val = PCI_ERR_UNC_UNSUP,
+        .correctable = false,
+    }, {
+        .name = "ACSV",
+        .val = PCI_ERR_UNC_ACSV,
+        .correctable = false,
+    }, {
+        .name = "INTN",
+        .val = PCI_ERR_UNC_INTN,
+        .correctable = false,
+    }, {
+        .name = "MCBTLP",
+        .val = PCI_ERR_UNC_MCBTLP,
+        .correctable = false,
+    }, {
+        .name = "ATOP_EBLOCKED",
+        .val = PCI_ERR_UNC_ATOP_EBLOCKED,
+        .correctable = false,
+    }, {
+        .name = "TLP_PRF_BLOCKED",
+        .val = PCI_ERR_UNC_TLP_PRF_BLOCKED,
+        .correctable = false,
+    }, {
+        .name = "RCVR",
+        .val = PCI_ERR_COR_RCVR,
+        .correctable = true,
+    }, {
+        .name = "BAD_TLP",
+        .val = PCI_ERR_COR_BAD_TLP,
+        .correctable = true,
+    }, {
+        .name = "BAD_DLLP",
+        .val = PCI_ERR_COR_BAD_DLLP,
+        .correctable = true,
+    }, {
+        .name = "REP_ROLL",
+        .val = PCI_ERR_COR_REP_ROLL,
+        .correctable = true,
+    }, {
+        .name = "REP_TIMER",
+        .val = PCI_ERR_COR_REP_TIMER,
+        .correctable = true,
+    }, {
+        .name = "ADV_NONFATAL",
+        .val = PCI_ERR_COR_ADV_NONFATAL,
+        .correctable = true,
+    }, {
+        .name = "INTERNAL",
+        .val = PCI_ERR_COR_INTERNAL,
+        .correctable = true,
+    }, {
+        .name = "HL_OVERFLOW",
+        .val = PCI_ERR_COR_HL_OVERFLOW,
+        .correctable = true,
+    },
+};
+
+static int pcie_aer_parse_error_string(const char *error_name,
+                                       uint32_t *status, bool *correctable)
+{
+    int i;
+
+    for (i = 0; i < ARRAY_SIZE(pcie_aer_error_list); i++) {
+        const  PCIEAERErrorName *e = &pcie_aer_error_list[i];
+        if (strcmp(error_name, e->name)) {
+            continue;
+        }
+
+        *status = e->val;
+        *correctable = e->correctable;
+        return 0;
+    }
+    return -EINVAL;
+}
+
+int do_pcie_aer_inject_error(Monitor *mon,
+                             const QDict *qdict, QObject **ret_data)
+{
+    const char *id = qdict_get_str(qdict, "id");
+    const char *error_name;
+    uint32_t error_status;
+    bool correctable;
+    PCIDevice *dev;
+    PCIEAERErr err;
+    int ret;
+
+    ret = pci_qdev_find_device(id, &dev);
+    if (ret < 0) {
+        monitor_printf(mon,
+                       "id or pci device path is invalid or device not "
+                       "found. %s\n", id);
+        return ret;
+    }
+    if (!pci_is_express(dev)) {
+        monitor_printf(mon, "the device doesn't support pci express. %s\n",
+                       id);
+        return -ENOSYS;
+    }
+
+    error_name = qdict_get_str(qdict, "error_status");
+    if (pcie_aer_parse_error_string(error_name, &error_status, &correctable)) {
+        char *e = NULL;
+        error_status = strtoul(error_name, &e, 0);
+        correctable = qdict_get_try_bool(qdict, "correctable", 0);
+        if (!e || *e != '\0') {
+            monitor_printf(mon, "invalid error status value. \"%s\"",
+                           error_name);
+            return -EINVAL;
+        }
+    }
+    err.status = error_status;
+    err.source_id = (pci_bus_num(dev->bus) << 8) | dev->devfn;
+
+    err.flags = 0;
+    if (correctable) {
+        err.flags |= PCIE_AER_ERR_IS_CORRECTABLE;
+    }
+    if (qdict_get_try_bool(qdict, "advisory_non_fatal", 0)) {
+        err.flags |= PCIE_AER_ERR_MAYBE_ADVISORY;
+    }
+    if (qdict_haskey(qdict, "header0")) {
+        err.flags |= PCIE_AER_ERR_HEADER_VALID;
+    }
+    if (qdict_haskey(qdict, "prefix0")) {
+        err.flags |= PCIE_AER_ERR_TLP_PREFIX_PRESENT;
+    }
+
+    err.header[0] = qdict_get_try_int(qdict, "header0", 0);
+    err.header[1] = qdict_get_try_int(qdict, "header1", 0);
+    err.header[2] = qdict_get_try_int(qdict, "header2", 0);
+    err.header[3] = qdict_get_try_int(qdict, "header3", 0);
+
+    err.prefix[0] = qdict_get_try_int(qdict, "prefix0", 0);
+    err.prefix[1] = qdict_get_try_int(qdict, "prefix1", 0);
+    err.prefix[2] = qdict_get_try_int(qdict, "prefix2", 0);
+    err.prefix[3] = qdict_get_try_int(qdict, "prefix3", 0);
+
+    ret = pcie_aer_inject_error(dev, &err);
+    *ret_data = qobject_from_jsonf("{'id': %s, "
+                                   "'domain': %d, 'bus': %d, 'devfn': %d, "
+                                   "'ret': %d}",
+                                   id,
+                                   pci_find_domain(dev->bus),
+                                   pci_bus_num(dev->bus), dev->devfn,
+                                   ret);
+    assert(*ret_data);
+
+    return 0;
+}
diff --git a/hw/pci/pcie_aer.h b/hw/pci/pcie_aer.h
new file mode 100644
index 0000000..7539500
--- /dev/null
+++ b/hw/pci/pcie_aer.h
@@ -0,0 +1,106 @@
+/*
+ * pcie_aer.h
+ *
+ * Copyright (c) 2010 Isaku Yamahata <yamahata at valinux co jp>
+ *                    VA Linux Systems Japan K.K.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef QEMU_PCIE_AER_H
+#define QEMU_PCIE_AER_H
+
+#include "hw.h"
+
+/* definitions which PCIExpressDevice uses */
+
+/* AER log */
+struct PCIEAERLog {
+    /* This structure is saved/loaded.
+       So explicitly size them instead of unsigned int */
+
+    /* the number of currently recorded log in log member */
+    uint16_t log_num;
+
+    /*
+     * The maximum number of the log. Errors can be logged up to this.
+     *
+     * This is configurable property.
+     * The specified value will be clipped down to PCIE_AER_LOG_MAX_LIMIT
+     * to avoid unreasonable memory usage.
+     * I bet that 128 log size would be big enough, otherwise too many errors
+     * for system to function normaly. But could consecutive errors occur?
+     */
+#define PCIE_AER_LOG_MAX_DEFAULT        8
+#define PCIE_AER_LOG_MAX_LIMIT          128
+#define PCIE_AER_LOG_MAX_UNSET          0xffff
+    uint16_t log_max;
+
+    /* Error log. log_max-sized array */
+    PCIEAERErr *log;
+};
+
+/* aer error message: error signaling message has only error sevirity and
+   source id. See 2.2.8.3 error signaling messages */
+struct PCIEAERMsg {
+    /*
+     * PCI_ERR_ROOT_CMD_{COR, NONFATAL, FATAL}_EN
+     * = PCI_EXP_DEVCTL_{CERE, NFERE, FERE}
+     */
+    uint32_t severity;
+
+    uint16_t source_id; /* bdf */
+};
+
+static inline bool
+pcie_aer_msg_is_uncor(const PCIEAERMsg *msg)
+{
+    return msg->severity == PCI_ERR_ROOT_CMD_NONFATAL_EN ||
+        msg->severity == PCI_ERR_ROOT_CMD_FATAL_EN;
+}
+
+/* error */
+struct PCIEAERErr {
+    uint32_t status;    /* error status bits */
+    uint16_t source_id; /* bdf */
+
+#define PCIE_AER_ERR_IS_CORRECTABLE     0x1     /* correctable/uncorrectable */
+#define PCIE_AER_ERR_MAYBE_ADVISORY     0x2     /* maybe advisory non-fatal */
+#define PCIE_AER_ERR_HEADER_VALID       0x4     /* TLP header is logged */
+#define PCIE_AER_ERR_TLP_PREFIX_PRESENT 0x8     /* TLP Prefix is logged */
+    uint16_t flags;
+
+    uint32_t header[4]; /* TLP header */
+    uint32_t prefix[4]; /* TLP header prefix */
+};
+
+extern const VMStateDescription vmstate_pcie_aer_log;
+
+int pcie_aer_init(PCIDevice *dev, uint16_t offset);
+void pcie_aer_exit(PCIDevice *dev);
+void pcie_aer_write_config(PCIDevice *dev,
+                           uint32_t addr, uint32_t val, int len);
+
+/* aer root port */
+void pcie_aer_root_set_vector(PCIDevice *dev, unsigned int vector);
+void pcie_aer_root_init(PCIDevice *dev);
+void pcie_aer_root_reset(PCIDevice *dev);
+void pcie_aer_root_write_config(PCIDevice *dev,
+                                uint32_t addr, uint32_t val, int len,
+                                uint32_t root_cmd_prev);
+
+/* error injection */
+int pcie_aer_inject_error(PCIDevice *dev, const PCIEAERErr *err);
+
+#endif /* QEMU_PCIE_AER_H */
diff --git a/hw/pci/pcie_host.c b/hw/pci/pcie_host.c
new file mode 100644
index 0000000..c257fb4
--- /dev/null
+++ b/hw/pci/pcie_host.c
@@ -0,0 +1,161 @@
+/*
+ * pcie_host.c
+ * utility functions for pci express host bridge.
+ *
+ * Copyright (c) 2009 Isaku Yamahata <yamahata at valinux co jp>
+ *                    VA Linux Systems Japan K.K.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "hw.h"
+#include "pci.h"
+#include "pcie_host.h"
+#include "exec-memory.h"
+
+/*
+ * PCI express mmcfig address
+ * bit 20 - 28: bus number
+ * bit 15 - 19: device number
+ * bit 12 - 14: function number
+ * bit  0 - 11: offset in configuration space of a given device
+ */
+#define PCIE_MMCFG_SIZE_MAX             (1ULL << 28)
+#define PCIE_MMCFG_SIZE_MIN             (1ULL << 20)
+#define PCIE_MMCFG_BUS_BIT              20
+#define PCIE_MMCFG_BUS_MASK             0x1ff
+#define PCIE_MMCFG_DEVFN_BIT            12
+#define PCIE_MMCFG_DEVFN_MASK           0xff
+#define PCIE_MMCFG_CONFOFFSET_MASK      0xfff
+#define PCIE_MMCFG_BUS(addr)            (((addr) >> PCIE_MMCFG_BUS_BIT) & \
+                                         PCIE_MMCFG_BUS_MASK)
+#define PCIE_MMCFG_DEVFN(addr)          (((addr) >> PCIE_MMCFG_DEVFN_BIT) & \
+                                         PCIE_MMCFG_DEVFN_MASK)
+#define PCIE_MMCFG_CONFOFFSET(addr)     ((addr) & PCIE_MMCFG_CONFOFFSET_MASK)
+
+
+/* a helper function to get a PCIDevice for a given mmconfig address */
+static inline PCIDevice *pcie_dev_find_by_mmcfg_addr(PCIBus *s,
+                                                     uint32_t mmcfg_addr)
+{
+    return pci_find_device(s, PCIE_MMCFG_BUS(mmcfg_addr),
+                           PCIE_MMCFG_DEVFN(mmcfg_addr));
+}
+
+static void pcie_mmcfg_data_write(void *opaque, hwaddr mmcfg_addr,
+                                  uint64_t val, unsigned len)
+{
+    PCIExpressHost *e = opaque;
+    PCIBus *s = e->pci.bus;
+    PCIDevice *pci_dev = pcie_dev_find_by_mmcfg_addr(s, mmcfg_addr);
+    uint32_t addr;
+    uint32_t limit;
+
+    if (!pci_dev) {
+        return;
+    }
+    addr = PCIE_MMCFG_CONFOFFSET(mmcfg_addr);
+    limit = pci_config_size(pci_dev);
+    if (limit <= addr) {
+        /* conventional pci device can be behind pcie-to-pci bridge.
+           256 <= addr < 4K has no effects. */
+        return;
+    }
+    pci_host_config_write_common(pci_dev, addr, limit, val, len);
+}
+
+static uint64_t pcie_mmcfg_data_read(void *opaque,
+                                     hwaddr mmcfg_addr,
+                                     unsigned len)
+{
+    PCIExpressHost *e = opaque;
+    PCIBus *s = e->pci.bus;
+    PCIDevice *pci_dev = pcie_dev_find_by_mmcfg_addr(s, mmcfg_addr);
+    uint32_t addr;
+    uint32_t limit;
+
+    if (!pci_dev) {
+        return ~0x0;
+    }
+    addr = PCIE_MMCFG_CONFOFFSET(mmcfg_addr);
+    limit = pci_config_size(pci_dev);
+    if (limit <= addr) {
+        /* conventional pci device can be behind pcie-to-pci bridge.
+           256 <= addr < 4K has no effects. */
+        return ~0x0;
+    }
+    return pci_host_config_read_common(pci_dev, addr, limit, len);
+}
+
+static const MemoryRegionOps pcie_mmcfg_ops = {
+    .read = pcie_mmcfg_data_read,
+    .write = pcie_mmcfg_data_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+};
+
+/* pcie_host::base_addr == PCIE_BASE_ADDR_UNMAPPED when it isn't mapped. */
+#define PCIE_BASE_ADDR_UNMAPPED  ((hwaddr)-1ULL)
+
+int pcie_host_init(PCIExpressHost *e)
+{
+    e->base_addr = PCIE_BASE_ADDR_UNMAPPED;
+
+    return 0;
+}
+
+void pcie_host_mmcfg_unmap(PCIExpressHost *e)
+{
+    if (e->base_addr != PCIE_BASE_ADDR_UNMAPPED) {
+        memory_region_del_subregion(get_system_memory(), &e->mmio);
+        memory_region_destroy(&e->mmio);
+        e->base_addr = PCIE_BASE_ADDR_UNMAPPED;
+    }
+}
+
+void pcie_host_mmcfg_map(PCIExpressHost *e, hwaddr addr,
+                         uint32_t size)
+{
+    assert(!(size & (size - 1)));       /* power of 2 */
+    assert(size >= PCIE_MMCFG_SIZE_MIN);
+    assert(size <= PCIE_MMCFG_SIZE_MAX);
+    e->size = size;
+    memory_region_init_io(&e->mmio, &pcie_mmcfg_ops, e, "pcie-mmcfg", e->size);
+    e->base_addr = addr;
+    memory_region_add_subregion(get_system_memory(), e->base_addr, &e->mmio);
+}
+
+void pcie_host_mmcfg_update(PCIExpressHost *e,
+                            int enable,
+                            hwaddr addr,
+                            uint32_t size)
+{
+    pcie_host_mmcfg_unmap(e);
+    if (enable) {
+        pcie_host_mmcfg_map(e, addr, size);
+    }
+}
+
+static const TypeInfo pcie_host_type_info = {
+    .name = TYPE_PCIE_HOST_BRIDGE,
+    .parent = TYPE_PCI_HOST_BRIDGE,
+    .abstract = true,
+    .instance_size = sizeof(PCIExpressHost),
+};
+
+static void pcie_host_register_types(void)
+{
+    type_register_static(&pcie_host_type_info);
+}
+
+type_init(pcie_host_register_types)
diff --git a/hw/pci/pcie_host.h b/hw/pci/pcie_host.h
new file mode 100644
index 0000000..3921935
--- /dev/null
+++ b/hw/pci/pcie_host.h
@@ -0,0 +1,54 @@
+/*
+ * pcie_host.h
+ *
+ * Copyright (c) 2009 Isaku Yamahata <yamahata at valinux co jp>
+ *                    VA Linux Systems Japan K.K.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef PCIE_HOST_H
+#define PCIE_HOST_H
+
+#include "pci_host.h"
+#include "memory.h"
+
+#define TYPE_PCIE_HOST_BRIDGE "pcie-host-bridge"
+#define PCIE_HOST_BRIDGE(obj) \
+    OBJECT_CHECK(PCIExpressHost, (obj), TYPE_PCIE_HOST_BRIDGE)
+
+struct PCIExpressHost {
+    PCIHostState pci;
+
+    /* express part */
+
+    /* base address where MMCONFIG area is mapped. */
+    hwaddr  base_addr;
+
+    /* the size of MMCONFIG area. It's host bridge dependent */
+    hwaddr  size;
+
+    /* MMCONFIG mmio area */
+    MemoryRegion mmio;
+};
+
+int pcie_host_init(PCIExpressHost *e);
+void pcie_host_mmcfg_unmap(PCIExpressHost *e);
+void pcie_host_mmcfg_map(PCIExpressHost *e, hwaddr addr, uint32_t size);
+void pcie_host_mmcfg_update(PCIExpressHost *e,
+                            int enable,
+                            hwaddr addr,
+                            uint32_t size);
+
+#endif /* PCIE_HOST_H */
diff --git a/hw/pci/pcie_port.c b/hw/pci/pcie_port.c
new file mode 100644
index 0000000..d6350e5
--- /dev/null
+++ b/hw/pci/pcie_port.c
@@ -0,0 +1,114 @@
+/*
+ * pcie_port.c
+ *
+ * Copyright (c) 2010 Isaku Yamahata <yamahata at valinux co jp>
+ *                    VA Linux Systems Japan K.K.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "pcie_port.h"
+
+void pcie_port_init_reg(PCIDevice *d)
+{
+    /* Unlike pci bridge,
+       66MHz and fast back to back don't apply to pci express port. */
+    pci_set_word(d->config + PCI_STATUS, 0);
+    pci_set_word(d->config + PCI_SEC_STATUS, 0);
+
+    /* Unlike conventional pci bridge, some bits are hardwired to 0. */
+    pci_set_word(d->wmask + PCI_BRIDGE_CONTROL,
+                 PCI_BRIDGE_CTL_PARITY |
+                 PCI_BRIDGE_CTL_ISA |
+                 PCI_BRIDGE_CTL_VGA |
+                 PCI_BRIDGE_CTL_SERR |
+                 PCI_BRIDGE_CTL_BUS_RESET);
+}
+
+/**************************************************************************
+ * (chassis number, pcie physical slot number) -> pcie slot conversion
+ */
+struct PCIEChassis {
+    uint8_t     number;
+
+    QLIST_HEAD(, PCIESlot) slots;
+    QLIST_ENTRY(PCIEChassis) next;
+};
+
+static QLIST_HEAD(, PCIEChassis) chassis = QLIST_HEAD_INITIALIZER(chassis);
+
+static struct PCIEChassis *pcie_chassis_find(uint8_t chassis_number)
+{
+    struct PCIEChassis *c;
+    QLIST_FOREACH(c, &chassis, next) {
+        if (c->number == chassis_number) {
+            break;
+        }
+    }
+    return c;
+}
+
+void pcie_chassis_create(uint8_t chassis_number)
+{
+    struct PCIEChassis *c;
+    c = pcie_chassis_find(chassis_number);
+    if (c) {
+        return;
+    }
+    c = g_malloc0(sizeof(*c));
+    c->number = chassis_number;
+    QLIST_INIT(&c->slots);
+    QLIST_INSERT_HEAD(&chassis, c, next);
+}
+
+static PCIESlot *pcie_chassis_find_slot_with_chassis(struct PCIEChassis *c,
+                                                     uint8_t slot)
+{
+    PCIESlot *s;
+    QLIST_FOREACH(s, &c->slots, next) {
+        if (s->slot == slot) {
+            break;
+        }
+    }
+    return s;
+}
+
+PCIESlot *pcie_chassis_find_slot(uint8_t chassis_number, uint16_t slot)
+{
+    struct PCIEChassis *c;
+    c = pcie_chassis_find(chassis_number);
+    if (!c) {
+        return NULL;
+    }
+    return pcie_chassis_find_slot_with_chassis(c, slot);
+}
+
+int pcie_chassis_add_slot(struct PCIESlot *slot)
+{
+    struct PCIEChassis *c;
+    c = pcie_chassis_find(slot->chassis);
+    if (!c) {
+        return -ENODEV;
+    }
+    if (pcie_chassis_find_slot_with_chassis(c, slot->slot)) {
+        return -EBUSY;
+    }
+    QLIST_INSERT_HEAD(&c->slots, slot, next);
+    return 0;
+}
+
+void pcie_chassis_del_slot(PCIESlot *s)
+{
+    QLIST_REMOVE(s, next);
+}
diff --git a/hw/pci/pcie_port.h b/hw/pci/pcie_port.h
new file mode 100644
index 0000000..3709583
--- /dev/null
+++ b/hw/pci/pcie_port.h
@@ -0,0 +1,51 @@
+/*
+ * pcie_port.h
+ *
+ * Copyright (c) 2010 Isaku Yamahata <yamahata at valinux co jp>
+ *                    VA Linux Systems Japan K.K.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef QEMU_PCIE_PORT_H
+#define QEMU_PCIE_PORT_H
+
+#include "pci_bridge.h"
+#include "pci_internals.h"
+
+struct PCIEPort {
+    PCIBridge   br;
+
+    /* pci express switch port */
+    uint8_t     port;
+};
+
+void pcie_port_init_reg(PCIDevice *d);
+
+struct PCIESlot {
+    PCIEPort    port;
+
+    /* pci express switch port with slot */
+    uint8_t     chassis;
+    uint16_t    slot;
+    QLIST_ENTRY(PCIESlot) next;
+};
+
+void pcie_chassis_create(uint8_t chassis_number);
+void pcie_main_chassis_create(void);
+PCIESlot *pcie_chassis_find_slot(uint8_t chassis, uint16_t slot);
+int pcie_chassis_add_slot(struct PCIESlot *slot);
+void pcie_chassis_del_slot(PCIESlot *s);
+
+#endif /* QEMU_PCIE_PORT_H */
diff --git a/hw/pci/pcie_regs.h b/hw/pci/pcie_regs.h
new file mode 100644
index 0000000..4d123d9
--- /dev/null
+++ b/hw/pci/pcie_regs.h
@@ -0,0 +1,156 @@
+/*
+ * constants for pcie configurations space from pci express spec.
+ *
+ * TODO:
+ * Those constants and macros should go to Linux pci_regs.h
+ * Once they're merged, they will go away.
+ */
+#ifndef QEMU_PCIE_REGS_H
+#define QEMU_PCIE_REGS_H
+
+
+/* express capability */
+
+#define PCI_EXP_VER2_SIZEOF             0x3c /* express capability of ver. 2 */
+#define PCI_EXT_CAP_VER_SHIFT           16
+#define PCI_EXT_CAP_NEXT_SHIFT          20
+#define PCI_EXT_CAP_NEXT_MASK           (0xffc << PCI_EXT_CAP_NEXT_SHIFT)
+
+#define PCI_EXT_CAP(id, ver, next)                                      \
+    ((id) |                                                             \
+     ((ver) << PCI_EXT_CAP_VER_SHIFT) |                                 \
+     ((next) << PCI_EXT_CAP_NEXT_SHIFT))
+
+#define PCI_EXT_CAP_ALIGN               4
+#define PCI_EXT_CAP_ALIGNUP(x)                                  \
+    (((x) + PCI_EXT_CAP_ALIGN - 1) & ~(PCI_EXT_CAP_ALIGN - 1))
+
+/* PCI_EXP_FLAGS */
+#define PCI_EXP_FLAGS_VER2              2 /* for now, supports only ver. 2 */
+#define PCI_EXP_FLAGS_IRQ_SHIFT         (ffs(PCI_EXP_FLAGS_IRQ) - 1)
+#define PCI_EXP_FLAGS_TYPE_SHIFT        (ffs(PCI_EXP_FLAGS_TYPE) - 1)
+
+
+/* PCI_EXP_LINK{CAP, STA} */
+/* link speed */
+#define PCI_EXP_LNK_LS_25               1
+
+#define PCI_EXP_LNK_MLW_SHIFT           (ffs(PCI_EXP_LNKCAP_MLW) - 1)
+#define PCI_EXP_LNK_MLW_1               (1 << PCI_EXP_LNK_MLW_SHIFT)
+
+/* PCI_EXP_LINKCAP */
+#define PCI_EXP_LNKCAP_ASPMS_SHIFT      (ffs(PCI_EXP_LNKCAP_ASPMS) - 1)
+#define PCI_EXP_LNKCAP_ASPMS_0S         (1 << PCI_EXP_LNKCAP_ASPMS_SHIFT)
+
+#define PCI_EXP_LNKCAP_PN_SHIFT         (ffs(PCI_EXP_LNKCAP_PN) - 1)
+
+#define PCI_EXP_SLTCAP_PSN_SHIFT        (ffs(PCI_EXP_SLTCAP_PSN) - 1)
+
+#define PCI_EXP_SLTCTL_IND_RESERVED     0x0
+#define PCI_EXP_SLTCTL_IND_ON           0x1
+#define PCI_EXP_SLTCTL_IND_BLINK        0x2
+#define PCI_EXP_SLTCTL_IND_OFF          0x3
+#define PCI_EXP_SLTCTL_AIC_SHIFT        (ffs(PCI_EXP_SLTCTL_AIC) - 1)
+#define PCI_EXP_SLTCTL_AIC_OFF                          \
+    (PCI_EXP_SLTCTL_IND_OFF << PCI_EXP_SLTCTL_AIC_SHIFT)
+
+#define PCI_EXP_SLTCTL_PIC_SHIFT        (ffs(PCI_EXP_SLTCTL_PIC) - 1)
+#define PCI_EXP_SLTCTL_PIC_OFF                          \
+    (PCI_EXP_SLTCTL_IND_OFF << PCI_EXP_SLTCTL_PIC_SHIFT)
+
+#define PCI_EXP_SLTCTL_SUPPORTED        \
+            (PCI_EXP_SLTCTL_ABPE |      \
+             PCI_EXP_SLTCTL_PDCE |      \
+             PCI_EXP_SLTCTL_CCIE |      \
+             PCI_EXP_SLTCTL_HPIE |      \
+             PCI_EXP_SLTCTL_AIC |       \
+             PCI_EXP_SLTCTL_PCC |       \
+             PCI_EXP_SLTCTL_EIC)
+
+#define PCI_EXP_DEVCAP2_EFF             0x100000
+#define PCI_EXP_DEVCAP2_EETLPP          0x200000
+
+#define PCI_EXP_DEVCTL2_EETLPPB         0x80
+
+/* ARI */
+#define PCI_ARI_VER                     1
+#define PCI_ARI_SIZEOF                  8
+
+/* AER */
+#define PCI_ERR_VER                     2
+#define PCI_ERR_SIZEOF                  0x48
+
+#define PCI_ERR_UNC_SDN                 0x00000020      /* surprise down */
+#define PCI_ERR_UNC_ACSV                0x00200000      /* ACS Violation */
+#define PCI_ERR_UNC_INTN                0x00400000      /* Internal Error */
+#define PCI_ERR_UNC_MCBTLP              0x00800000      /* MC Blcoked TLP */
+#define PCI_ERR_UNC_ATOP_EBLOCKED       0x01000000      /* atomic op egress 
blocked */
+#define PCI_ERR_UNC_TLP_PRF_BLOCKED     0x02000000      /* TLP Prefix Blocked 
*/
+#define PCI_ERR_COR_ADV_NONFATAL        0x00002000      /* Advisory Non-Fatal 
*/
+#define PCI_ERR_COR_INTERNAL            0x00004000      /* Corrected Internal 
*/
+#define PCI_ERR_COR_HL_OVERFLOW         0x00008000      /* Header Long 
Overflow */
+#define PCI_ERR_CAP_FEP_MASK            0x0000001f
+#define PCI_ERR_CAP_MHRC                0x00000200
+#define PCI_ERR_CAP_MHRE                0x00000400
+#define PCI_ERR_CAP_TLP                 0x00000800
+
+#define PCI_ERR_HEADER_LOG_SIZE         16
+#define PCI_ERR_TLP_PREFIX_LOG          0x38
+#define PCI_ERR_TLP_PREFIX_LOG_SIZE     16
+
+#define PCI_SEC_STATUS_RCV_SYSTEM_ERROR         0x4000
+
+/* aer root error command/status */
+#define PCI_ERR_ROOT_CMD_EN_MASK        (PCI_ERR_ROOT_CMD_COR_EN |      \
+                                         PCI_ERR_ROOT_CMD_NONFATAL_EN | \
+                                         PCI_ERR_ROOT_CMD_FATAL_EN)
+
+#define PCI_ERR_ROOT_IRQ_MAX            32
+#define PCI_ERR_ROOT_IRQ                0xf8000000
+#define PCI_ERR_ROOT_IRQ_SHIFT          (ffs(PCI_ERR_ROOT_IRQ) - 1)
+#define PCI_ERR_ROOT_STATUS_REPORT_MASK (PCI_ERR_ROOT_COR_RCV |         \
+                                         PCI_ERR_ROOT_MULTI_COR_RCV |   \
+                                         PCI_ERR_ROOT_UNCOR_RCV |       \
+                                         PCI_ERR_ROOT_MULTI_UNCOR_RCV | \
+                                         PCI_ERR_ROOT_FIRST_FATAL |     \
+                                         PCI_ERR_ROOT_NONFATAL_RCV |    \
+                                         PCI_ERR_ROOT_FATAL_RCV)
+
+#define PCI_ERR_UNC_SUPPORTED           (PCI_ERR_UNC_DLP |              \
+                                         PCI_ERR_UNC_SDN |              \
+                                         PCI_ERR_UNC_POISON_TLP |       \
+                                         PCI_ERR_UNC_FCP |              \
+                                         PCI_ERR_UNC_COMP_TIME |        \
+                                         PCI_ERR_UNC_COMP_ABORT |       \
+                                         PCI_ERR_UNC_UNX_COMP |         \
+                                         PCI_ERR_UNC_RX_OVER |          \
+                                         PCI_ERR_UNC_MALF_TLP |         \
+                                         PCI_ERR_UNC_ECRC |             \
+                                         PCI_ERR_UNC_UNSUP |            \
+                                         PCI_ERR_UNC_ACSV |             \
+                                         PCI_ERR_UNC_INTN |             \
+                                         PCI_ERR_UNC_MCBTLP |           \
+                                         PCI_ERR_UNC_ATOP_EBLOCKED |    \
+                                         PCI_ERR_UNC_TLP_PRF_BLOCKED)
+
+#define PCI_ERR_UNC_SEVERITY_DEFAULT    (PCI_ERR_UNC_DLP |              \
+                                         PCI_ERR_UNC_SDN |              \
+                                         PCI_ERR_UNC_FCP |              \
+                                         PCI_ERR_UNC_RX_OVER |          \
+                                         PCI_ERR_UNC_MALF_TLP |         \
+                                         PCI_ERR_UNC_INTN)
+
+#define PCI_ERR_COR_SUPPORTED           (PCI_ERR_COR_RCVR |             \
+                                         PCI_ERR_COR_BAD_TLP |          \
+                                         PCI_ERR_COR_BAD_DLLP |         \
+                                         PCI_ERR_COR_REP_ROLL |         \
+                                         PCI_ERR_COR_REP_TIMER |        \
+                                         PCI_ERR_COR_ADV_NONFATAL |     \
+                                         PCI_ERR_COR_INTERNAL |         \
+                                         PCI_ERR_COR_HL_OVERFLOW)
+
+#define PCI_ERR_COR_MASK_DEFAULT        (PCI_ERR_COR_ADV_NONFATAL |     \
+                                         PCI_ERR_COR_INTERNAL |         \
+                                         PCI_ERR_COR_HL_OVERFLOW)
+
+#endif /* QEMU_PCIE_REGS_H */
diff --git a/hw/pci/shpc.c b/hw/pci/shpc.c
new file mode 100644
index 0000000..4597bbd
--- /dev/null
+++ b/hw/pci/shpc.c
@@ -0,0 +1,681 @@
+#include <strings.h>
+#include <stdint.h>
+#include "range.h"
+#include "range.h"
+#include "shpc.h"
+#include "pci.h"
+#include "pci_internals.h"
+#include "msi.h"
+
+/* TODO: model power only and disabled slot states. */
+/* TODO: handle SERR and wakeups */
+/* TODO: consider enabling 66MHz support */
+
+/* TODO: remove fully only on state DISABLED and LED off.
+ * track state to properly record this. */
+
+/* SHPC Working Register Set */
+#define SHPC_BASE_OFFSET  0x00 /* 4 bytes */
+#define SHPC_SLOTS_33     0x04 /* 4 bytes. Also encodes PCI-X slots. */
+#define SHPC_SLOTS_66     0x08 /* 4 bytes. */
+#define SHPC_NSLOTS       0x0C /* 1 byte */
+#define SHPC_FIRST_DEV    0x0D /* 1 byte */
+#define SHPC_PHYS_SLOT    0x0E /* 2 byte */
+#define SHPC_PHYS_NUM_MAX 0x7ff
+#define SHPC_PHYS_NUM_UP  0x2000
+#define SHPC_PHYS_MRL     0x4000
+#define SHPC_PHYS_BUTTON  0x8000
+#define SHPC_SEC_BUS      0x10 /* 2 bytes */
+#define SHPC_SEC_BUS_33   0x0
+#define SHPC_SEC_BUS_66   0x1 /* Unused */
+#define SHPC_SEC_BUS_MASK 0x7
+#define SHPC_MSI_CTL      0x12 /* 1 byte */
+#define SHPC_PROG_IFC     0x13 /* 1 byte */
+#define SHPC_PROG_IFC_1_0 0x1
+#define SHPC_CMD_CODE     0x14 /* 1 byte */
+#define SHPC_CMD_TRGT     0x15 /* 1 byte */
+#define SHPC_CMD_TRGT_MIN 0x1
+#define SHPC_CMD_TRGT_MAX 0x1f
+#define SHPC_CMD_STATUS   0x16 /* 2 bytes */
+#define SHPC_CMD_STATUS_BUSY          0x1
+#define SHPC_CMD_STATUS_MRL_OPEN      0x2
+#define SHPC_CMD_STATUS_INVALID_CMD   0x4
+#define SHPC_CMD_STATUS_INVALID_MODE  0x8
+#define SHPC_INT_LOCATOR  0x18 /* 4 bytes */
+#define SHPC_INT_COMMAND  0x1
+#define SHPC_SERR_LOCATOR 0x1C /* 4 bytes */
+#define SHPC_SERR_INT     0x20 /* 4 bytes */
+#define SHPC_INT_DIS      0x1
+#define SHPC_SERR_DIS     0x2
+#define SHPC_CMD_INT_DIS  0x4
+#define SHPC_ARB_SERR_DIS 0x8
+#define SHPC_CMD_DETECTED 0x10000
+#define SHPC_ARB_DETECTED 0x20000
+ /* 4 bytes * slot # (start from 0) */
+#define SHPC_SLOT_REG(s)         (0x24 + (s) * 4)
+ /* 2 bytes */
+#define SHPC_SLOT_STATUS(s)       (0x0 + SHPC_SLOT_REG(s))
+
+/* Same slot state masks are used for command and status registers */
+#define SHPC_SLOT_STATE_MASK     0x03
+#define SHPC_SLOT_STATE_SHIFT \
+    (ffs(SHPC_SLOT_STATE_MASK) - 1)
+
+#define SHPC_STATE_NO       0x0
+#define SHPC_STATE_PWRONLY  0x1
+#define SHPC_STATE_ENABLED  0x2
+#define SHPC_STATE_DISABLED 0x3
+
+#define SHPC_SLOT_PWR_LED_MASK   0xC
+#define SHPC_SLOT_PWR_LED_SHIFT \
+    (ffs(SHPC_SLOT_PWR_LED_MASK) - 1)
+#define SHPC_SLOT_ATTN_LED_MASK  0x30
+#define SHPC_SLOT_ATTN_LED_SHIFT \
+    (ffs(SHPC_SLOT_ATTN_LED_MASK) - 1)
+
+#define SHPC_LED_NO     0x0
+#define SHPC_LED_ON     0x1
+#define SHPC_LED_BLINK  0x2
+#define SHPC_LED_OFF    0x3
+
+#define SHPC_SLOT_STATUS_PWR_FAULT      0x40
+#define SHPC_SLOT_STATUS_BUTTON         0x80
+#define SHPC_SLOT_STATUS_MRL_OPEN       0x100
+#define SHPC_SLOT_STATUS_66             0x200
+#define SHPC_SLOT_STATUS_PRSNT_MASK     0xC00
+#define SHPC_SLOT_STATUS_PRSNT_EMPTY    0x3
+#define SHPC_SLOT_STATUS_PRSNT_25W      0x1
+#define SHPC_SLOT_STATUS_PRSNT_15W      0x2
+#define SHPC_SLOT_STATUS_PRSNT_7_5W     0x0
+
+#define SHPC_SLOT_STATUS_PRSNT_PCIX     0x3000
+
+
+ /* 1 byte */
+#define SHPC_SLOT_EVENT_LATCH(s)        (0x2 + SHPC_SLOT_REG(s))
+ /* 1 byte */
+#define SHPC_SLOT_EVENT_SERR_INT_DIS(d, s) (0x3 + SHPC_SLOT_REG(s))
+#define SHPC_SLOT_EVENT_PRESENCE        0x01
+#define SHPC_SLOT_EVENT_ISOLATED_FAULT  0x02
+#define SHPC_SLOT_EVENT_BUTTON          0x04
+#define SHPC_SLOT_EVENT_MRL             0x08
+#define SHPC_SLOT_EVENT_CONNECTED_FAULT 0x10
+/* Bits below are used for Serr/Int disable only */
+#define SHPC_SLOT_EVENT_MRL_SERR_DIS    0x20
+#define SHPC_SLOT_EVENT_CONNECTED_FAULT_SERR_DIS 0x40
+
+#define SHPC_MIN_SLOTS        1
+#define SHPC_MAX_SLOTS        31
+#define SHPC_SIZEOF(d)    SHPC_SLOT_REG((d)->shpc->nslots)
+
+/* SHPC Slot identifiers */
+
+/* Hotplug supported at 31 slots out of the total 32.  We reserve slot 0,
+   and give the rest of them physical *and* pci numbers starting from 1, so
+   they match logical numbers.  Note: this means that multiple slots must have
+   different chassis number values, to make chassis+physical slot unique.
+   TODO: make this configurable? */
+#define SHPC_IDX_TO_LOGICAL(slot) ((slot) + 1)
+#define SHPC_LOGICAL_TO_IDX(target) ((target) - 1)
+#define SHPC_IDX_TO_PCI(slot) ((slot) + 1)
+#define SHPC_PCI_TO_IDX(pci_slot) ((pci_slot) - 1)
+#define SHPC_IDX_TO_PHYSICAL(slot) ((slot) + 1)
+
+static int roundup_pow_of_two(int x)
+{
+    x |= (x >> 1);
+    x |= (x >> 2);
+    x |= (x >> 4);
+    x |= (x >> 8);
+    x |= (x >> 16);
+    return x + 1;
+}
+
+static uint16_t shpc_get_status(SHPCDevice *shpc, int slot, uint16_t msk)
+{
+    uint8_t *status = shpc->config + SHPC_SLOT_STATUS(slot);
+    return (pci_get_word(status) & msk) >> (ffs(msk) - 1);
+}
+
+static void shpc_set_status(SHPCDevice *shpc,
+                            int slot, uint8_t value, uint16_t msk)
+{
+    uint8_t *status = shpc->config + SHPC_SLOT_STATUS(slot);
+    pci_word_test_and_clear_mask(status, msk);
+    pci_word_test_and_set_mask(status, value << (ffs(msk) - 1));
+}
+
+static void shpc_interrupt_update(PCIDevice *d)
+{
+    SHPCDevice *shpc = d->shpc;
+    int slot;
+    int level = 0;
+    uint32_t serr_int;
+    uint32_t int_locator = 0;
+
+    /* Update interrupt locator register */
+    for (slot = 0; slot < shpc->nslots; ++slot) {
+        uint8_t event = shpc->config[SHPC_SLOT_EVENT_LATCH(slot)];
+        uint8_t disable = shpc->config[SHPC_SLOT_EVENT_SERR_INT_DIS(d, slot)];
+        uint32_t mask = 1 << SHPC_IDX_TO_LOGICAL(slot);
+        if (event & ~disable) {
+            int_locator |= mask;
+        }
+    }
+    serr_int = pci_get_long(shpc->config + SHPC_SERR_INT);
+    if ((serr_int & SHPC_CMD_DETECTED) && !(serr_int & SHPC_CMD_INT_DIS)) {
+        int_locator |= SHPC_INT_COMMAND;
+    }
+    pci_set_long(shpc->config + SHPC_INT_LOCATOR, int_locator);
+    level = (!(serr_int & SHPC_INT_DIS) && int_locator) ? 1 : 0;
+    if (msi_enabled(d) && shpc->msi_requested != level)
+        msi_notify(d, 0);
+    else
+        qemu_set_irq(d->irq[0], level);
+    shpc->msi_requested = level;
+}
+
+static void shpc_set_sec_bus_speed(SHPCDevice *shpc, uint8_t speed)
+{
+    switch (speed) {
+    case SHPC_SEC_BUS_33:
+        shpc->config[SHPC_SEC_BUS] &= ~SHPC_SEC_BUS_MASK;
+        shpc->config[SHPC_SEC_BUS] |= speed;
+        break;
+    default:
+        pci_word_test_and_set_mask(shpc->config + SHPC_CMD_STATUS,
+                                   SHPC_CMD_STATUS_INVALID_MODE);
+    }
+}
+
+void shpc_reset(PCIDevice *d)
+{
+    SHPCDevice *shpc = d->shpc;
+    int nslots = shpc->nslots;
+    int i;
+    memset(shpc->config, 0, SHPC_SIZEOF(d));
+    pci_set_byte(shpc->config + SHPC_NSLOTS, nslots);
+    pci_set_long(shpc->config + SHPC_SLOTS_33, nslots);
+    pci_set_long(shpc->config + SHPC_SLOTS_66, 0);
+    pci_set_byte(shpc->config + SHPC_FIRST_DEV, SHPC_IDX_TO_PCI(0));
+    pci_set_word(shpc->config + SHPC_PHYS_SLOT,
+                 SHPC_IDX_TO_PHYSICAL(0) |
+                 SHPC_PHYS_NUM_UP |
+                 SHPC_PHYS_MRL |
+                 SHPC_PHYS_BUTTON);
+    pci_set_long(shpc->config + SHPC_SERR_INT, SHPC_INT_DIS |
+                 SHPC_SERR_DIS |
+                 SHPC_CMD_INT_DIS |
+                 SHPC_ARB_SERR_DIS);
+    pci_set_byte(shpc->config + SHPC_PROG_IFC, SHPC_PROG_IFC_1_0);
+    pci_set_word(shpc->config + SHPC_SEC_BUS, SHPC_SEC_BUS_33);
+    for (i = 0; i < shpc->nslots; ++i) {
+        pci_set_byte(shpc->config + SHPC_SLOT_EVENT_SERR_INT_DIS(d, i),
+                     SHPC_SLOT_EVENT_PRESENCE |
+                     SHPC_SLOT_EVENT_ISOLATED_FAULT |
+                     SHPC_SLOT_EVENT_BUTTON |
+                     SHPC_SLOT_EVENT_MRL |
+                     SHPC_SLOT_EVENT_CONNECTED_FAULT |
+                     SHPC_SLOT_EVENT_MRL_SERR_DIS |
+                     SHPC_SLOT_EVENT_CONNECTED_FAULT_SERR_DIS);
+        if (shpc->sec_bus->devices[PCI_DEVFN(SHPC_IDX_TO_PCI(i), 0)]) {
+            shpc_set_status(shpc, i, SHPC_STATE_ENABLED, SHPC_SLOT_STATE_MASK);
+            shpc_set_status(shpc, i, 0, SHPC_SLOT_STATUS_MRL_OPEN);
+            shpc_set_status(shpc, i, SHPC_SLOT_STATUS_PRSNT_7_5W,
+                            SHPC_SLOT_STATUS_PRSNT_MASK);
+            shpc_set_status(shpc, i, SHPC_LED_ON, SHPC_SLOT_PWR_LED_MASK);
+        } else {
+            shpc_set_status(shpc, i, SHPC_STATE_DISABLED, 
SHPC_SLOT_STATE_MASK);
+            shpc_set_status(shpc, i, 1, SHPC_SLOT_STATUS_MRL_OPEN);
+            shpc_set_status(shpc, i, SHPC_SLOT_STATUS_PRSNT_EMPTY,
+                            SHPC_SLOT_STATUS_PRSNT_MASK);
+            shpc_set_status(shpc, i, SHPC_LED_OFF, SHPC_SLOT_PWR_LED_MASK);
+        }
+        shpc_set_status(shpc, i, 0, SHPC_SLOT_STATUS_66);
+    }
+    shpc_set_sec_bus_speed(shpc, SHPC_SEC_BUS_33);
+    shpc->msi_requested = 0;
+    shpc_interrupt_update(d);
+}
+
+static void shpc_invalid_command(SHPCDevice *shpc)
+{
+    pci_word_test_and_set_mask(shpc->config + SHPC_CMD_STATUS,
+                               SHPC_CMD_STATUS_INVALID_CMD);
+}
+
+static void shpc_free_devices_in_slot(SHPCDevice *shpc, int slot)
+{
+    int devfn;
+    int pci_slot = SHPC_IDX_TO_PCI(slot);
+    for (devfn = PCI_DEVFN(pci_slot, 0);
+         devfn <= PCI_DEVFN(pci_slot, PCI_FUNC_MAX - 1);
+         ++devfn) {
+        PCIDevice *affected_dev = shpc->sec_bus->devices[devfn];
+        if (affected_dev) {
+            qdev_free(&affected_dev->qdev);
+        }
+    }
+}
+
+static void shpc_slot_command(SHPCDevice *shpc, uint8_t target,
+                              uint8_t state, uint8_t power, uint8_t attn)
+{
+    uint8_t current_state;
+    int slot = SHPC_LOGICAL_TO_IDX(target);
+    if (target < SHPC_CMD_TRGT_MIN || slot >= shpc->nslots) {
+        shpc_invalid_command(shpc);
+        return;
+    }
+    current_state = shpc_get_status(shpc, slot, SHPC_SLOT_STATE_MASK);
+    if (current_state == SHPC_STATE_ENABLED && state == SHPC_STATE_PWRONLY) {
+        shpc_invalid_command(shpc);
+        return;
+    }
+
+    switch (power) {
+    case SHPC_LED_NO:
+        break;
+    default:
+        /* TODO: send event to monitor */
+        shpc_set_status(shpc, slot, power, SHPC_SLOT_PWR_LED_MASK);
+    }
+    switch (attn) {
+    case SHPC_LED_NO:
+        break;
+    default:
+        /* TODO: send event to monitor */
+        shpc_set_status(shpc, slot, attn, SHPC_SLOT_ATTN_LED_MASK);
+    }
+
+    if ((current_state == SHPC_STATE_DISABLED && state == SHPC_STATE_PWRONLY) 
||
+        (current_state == SHPC_STATE_DISABLED && state == SHPC_STATE_ENABLED)) 
{
+        shpc_set_status(shpc, slot, state, SHPC_SLOT_STATE_MASK);
+    } else if ((current_state == SHPC_STATE_ENABLED ||
+                current_state == SHPC_STATE_PWRONLY) &&
+               state == SHPC_STATE_DISABLED) {
+        shpc_set_status(shpc, slot, state, SHPC_SLOT_STATE_MASK);
+        power = shpc_get_status(shpc, slot, SHPC_SLOT_PWR_LED_MASK);
+        /* TODO: track what monitor requested. */
+        /* Look at LED to figure out whether it's ok to remove the device. */
+        if (power == SHPC_LED_OFF) {
+            shpc_free_devices_in_slot(shpc, slot);
+            shpc_set_status(shpc, slot, 1, SHPC_SLOT_STATUS_MRL_OPEN);
+            shpc_set_status(shpc, slot, SHPC_SLOT_STATUS_PRSNT_EMPTY,
+                            SHPC_SLOT_STATUS_PRSNT_MASK);
+            shpc->config[SHPC_SLOT_EVENT_LATCH(slot)] |=
+                SHPC_SLOT_EVENT_BUTTON |
+                SHPC_SLOT_EVENT_MRL |
+                SHPC_SLOT_EVENT_PRESENCE;
+        }
+    }
+}
+
+static void shpc_command(SHPCDevice *shpc)
+{
+    uint8_t code = pci_get_byte(shpc->config + SHPC_CMD_CODE);
+    uint8_t speed;
+    uint8_t target;
+    uint8_t attn;
+    uint8_t power;
+    uint8_t state;
+    int i;
+
+    /* Clear status from the previous command. */
+    pci_word_test_and_clear_mask(shpc->config + SHPC_CMD_STATUS,
+                                 SHPC_CMD_STATUS_BUSY |
+                                 SHPC_CMD_STATUS_MRL_OPEN |
+                                 SHPC_CMD_STATUS_INVALID_CMD |
+                                 SHPC_CMD_STATUS_INVALID_MODE);
+    switch (code) {
+    case 0x00 ... 0x3f:
+        target = shpc->config[SHPC_CMD_TRGT] & SHPC_CMD_TRGT_MAX;
+        state = (code & SHPC_SLOT_STATE_MASK) >> SHPC_SLOT_STATE_SHIFT;
+        power = (code & SHPC_SLOT_PWR_LED_MASK) >> SHPC_SLOT_PWR_LED_SHIFT;
+        attn = (code & SHPC_SLOT_ATTN_LED_MASK) >> SHPC_SLOT_ATTN_LED_SHIFT;
+        shpc_slot_command(shpc, target, state, power, attn);
+        break;
+    case 0x40 ... 0x47:
+        speed = code & SHPC_SEC_BUS_MASK;
+        shpc_set_sec_bus_speed(shpc, speed);
+        break;
+    case 0x48:
+        /* Power only all slots */
+        /* first verify no slots are enabled */
+        for (i = 0; i < shpc->nslots; ++i) {
+            state = shpc_get_status(shpc, i, SHPC_SLOT_STATE_MASK);
+            if (state == SHPC_STATE_ENABLED) {
+                shpc_invalid_command(shpc);
+                goto done;
+            }
+        }
+        for (i = 0; i < shpc->nslots; ++i) {
+            if (!(shpc_get_status(shpc, i, SHPC_SLOT_STATUS_MRL_OPEN))) {
+                shpc_slot_command(shpc, i + SHPC_CMD_TRGT_MIN,
+                                  SHPC_STATE_PWRONLY, SHPC_LED_ON, 
SHPC_LED_NO);
+            } else {
+                shpc_slot_command(shpc, i + SHPC_CMD_TRGT_MIN,
+                                  SHPC_STATE_NO, SHPC_LED_OFF, SHPC_LED_NO);
+            }
+        }
+        break;
+    case 0x49:
+        /* Enable all slots */
+        /* TODO: Spec says this shall fail if some are already enabled.
+         * This doesn't make sense - why not? a spec bug? */
+        for (i = 0; i < shpc->nslots; ++i) {
+            state = shpc_get_status(shpc, i, SHPC_SLOT_STATE_MASK);
+            if (state == SHPC_STATE_ENABLED) {
+                shpc_invalid_command(shpc);
+                goto done;
+            }
+        }
+        for (i = 0; i < shpc->nslots; ++i) {
+            if (!(shpc_get_status(shpc, i, SHPC_SLOT_STATUS_MRL_OPEN))) {
+                shpc_slot_command(shpc, i + SHPC_CMD_TRGT_MIN,
+                                  SHPC_STATE_ENABLED, SHPC_LED_ON, 
SHPC_LED_NO);
+            } else {
+                shpc_slot_command(shpc, i + SHPC_CMD_TRGT_MIN,
+                                  SHPC_STATE_NO, SHPC_LED_OFF, SHPC_LED_NO);
+            }
+        }
+        break;
+    default:
+        shpc_invalid_command(shpc);
+        break;
+    }
+done:
+    pci_long_test_and_set_mask(shpc->config + SHPC_SERR_INT, 
SHPC_CMD_DETECTED);
+}
+
+static void shpc_write(PCIDevice *d, unsigned addr, uint64_t val, int l)
+{
+    SHPCDevice *shpc = d->shpc;
+    int i;
+    if (addr >= SHPC_SIZEOF(d)) {
+        return;
+    }
+    l = MIN(l, SHPC_SIZEOF(d) - addr);
+
+    /* TODO: code duplicated from pci.c */
+    for (i = 0; i < l; val >>= 8, ++i) {
+        unsigned a = addr + i;
+        uint8_t wmask = shpc->wmask[a];
+        uint8_t w1cmask = shpc->w1cmask[a];
+        assert(!(wmask & w1cmask));
+        shpc->config[a] = (shpc->config[a] & ~wmask) | (val & wmask);
+        shpc->config[a] &= ~(val & w1cmask); /* W1C: Write 1 to Clear */
+    }
+    if (ranges_overlap(addr, l, SHPC_CMD_CODE, 2)) {
+        shpc_command(shpc);
+    }
+    shpc_interrupt_update(d);
+}
+
+static uint64_t shpc_read(PCIDevice *d, unsigned addr, int l)
+{
+    uint64_t val = 0x0;
+    if (addr >= SHPC_SIZEOF(d)) {
+        return val;
+    }
+    l = MIN(l, SHPC_SIZEOF(d) - addr);
+    memcpy(&val, d->shpc->config + addr, l);
+    return val;
+}
+
+/* SHPC Bridge Capability */
+#define SHPC_CAP_LENGTH 0x08
+#define SHPC_CAP_DWORD_SELECT 0x2 /* 1 byte */
+#define SHPC_CAP_CxP 0x3 /* 1 byte: CSP, CIP */
+#define SHPC_CAP_DWORD_DATA 0x4 /* 4 bytes */
+#define SHPC_CAP_CSP_MASK 0x4
+#define SHPC_CAP_CIP_MASK 0x8
+
+static uint8_t shpc_cap_dword(PCIDevice *d)
+{
+    return pci_get_byte(d->config + d->shpc->cap + SHPC_CAP_DWORD_SELECT);
+}
+
+/* Update dword data capability register */
+static void shpc_cap_update_dword(PCIDevice *d)
+{
+    unsigned data;
+    data = shpc_read(d, shpc_cap_dword(d) * 4, 4);
+    pci_set_long(d->config  + d->shpc->cap + SHPC_CAP_DWORD_DATA, data);
+}
+
+/* Add SHPC capability to the config space for the device. */
+static int shpc_cap_add_config(PCIDevice *d)
+{
+    uint8_t *config;
+    int config_offset;
+    config_offset = pci_add_capability(d, PCI_CAP_ID_SHPC,
+                                       0, SHPC_CAP_LENGTH);
+    if (config_offset < 0) {
+        return config_offset;
+    }
+    config = d->config + config_offset;
+
+    pci_set_byte(config + SHPC_CAP_DWORD_SELECT, 0);
+    pci_set_byte(config + SHPC_CAP_CxP, 0);
+    pci_set_long(config + SHPC_CAP_DWORD_DATA, 0);
+    d->shpc->cap = config_offset;
+    /* Make dword select and data writeable. */
+    pci_set_byte(d->wmask + config_offset + SHPC_CAP_DWORD_SELECT, 0xff);
+    pci_set_long(d->wmask + config_offset + SHPC_CAP_DWORD_DATA, 0xffffffff);
+    return 0;
+}
+
+static uint64_t shpc_mmio_read(void *opaque, hwaddr addr,
+                               unsigned size)
+{
+    return shpc_read(opaque, addr, size);
+}
+
+static void shpc_mmio_write(void *opaque, hwaddr addr,
+                            uint64_t val, unsigned size)
+{
+    shpc_write(opaque, addr, val, size);
+}
+
+static const MemoryRegionOps shpc_mmio_ops = {
+    .read = shpc_mmio_read,
+    .write = shpc_mmio_write,
+    .endianness = DEVICE_LITTLE_ENDIAN,
+    .valid = {
+        /* SHPC ECN requires dword accesses, but the original 1.0 spec doesn't.
+         * It's easier to suppport all sizes than worry about it. */
+        .min_access_size = 1,
+        .max_access_size = 4,
+    },
+};
+
+static int shpc_device_hotplug(DeviceState *qdev, PCIDevice *affected_dev,
+                               PCIHotplugState hotplug_state)
+{
+    int pci_slot = PCI_SLOT(affected_dev->devfn);
+    uint8_t state;
+    uint8_t led;
+    PCIDevice *d = DO_UPCAST(PCIDevice, qdev, qdev);
+    SHPCDevice *shpc = d->shpc;
+    int slot = SHPC_PCI_TO_IDX(pci_slot);
+    if (pci_slot < SHPC_IDX_TO_PCI(0) || slot >= shpc->nslots) {
+        error_report("Unsupported PCI slot %d for standard hotplug "
+                     "controller. Valid slots are between %d and %d.",
+                     pci_slot, SHPC_IDX_TO_PCI(0),
+                     SHPC_IDX_TO_PCI(shpc->nslots) - 1);
+        return -1;
+    }
+    /* Don't send event when device is enabled during qemu machine creation:
+     * it is present on boot, no hotplug event is necessary. We do send an
+     * event when the device is disabled later. */
+    if (hotplug_state == PCI_COLDPLUG_ENABLED) {
+        shpc_set_status(shpc, slot, 0, SHPC_SLOT_STATUS_MRL_OPEN);
+        shpc_set_status(shpc, slot, SHPC_SLOT_STATUS_PRSNT_7_5W,
+                        SHPC_SLOT_STATUS_PRSNT_MASK);
+        return 0;
+    }
+    if (hotplug_state == PCI_HOTPLUG_DISABLED) {
+        shpc->config[SHPC_SLOT_EVENT_LATCH(slot)] |= SHPC_SLOT_EVENT_BUTTON;
+        state = shpc_get_status(shpc, slot, SHPC_SLOT_STATE_MASK);
+        led = shpc_get_status(shpc, slot, SHPC_SLOT_PWR_LED_MASK);
+        if (state == SHPC_STATE_DISABLED && led == SHPC_LED_OFF) {
+            shpc_free_devices_in_slot(shpc, slot);
+            shpc_set_status(shpc, slot, 1, SHPC_SLOT_STATUS_MRL_OPEN);
+            shpc_set_status(shpc, slot, SHPC_SLOT_STATUS_PRSNT_EMPTY,
+                            SHPC_SLOT_STATUS_PRSNT_MASK);
+            shpc->config[SHPC_SLOT_EVENT_LATCH(slot)] |=
+                SHPC_SLOT_EVENT_MRL |
+                SHPC_SLOT_EVENT_PRESENCE;
+        }
+    } else {
+        /* This could be a cancellation of the previous removal.
+         * We check MRL state to figure out. */
+        if (shpc_get_status(shpc, slot, SHPC_SLOT_STATUS_MRL_OPEN)) {
+            shpc_set_status(shpc, slot, 0, SHPC_SLOT_STATUS_MRL_OPEN);
+            shpc_set_status(shpc, slot, SHPC_SLOT_STATUS_PRSNT_7_5W,
+                            SHPC_SLOT_STATUS_PRSNT_MASK);
+            shpc->config[SHPC_SLOT_EVENT_LATCH(slot)] |=
+                SHPC_SLOT_EVENT_BUTTON |
+                SHPC_SLOT_EVENT_MRL |
+                SHPC_SLOT_EVENT_PRESENCE;
+        } else {
+            /* Press attention button to cancel removal */
+            shpc->config[SHPC_SLOT_EVENT_LATCH(slot)] |=
+                SHPC_SLOT_EVENT_BUTTON;
+        }
+    }
+    shpc_set_status(shpc, slot, 0, SHPC_SLOT_STATUS_66);
+    shpc_interrupt_update(d);
+    return 0;
+}
+
+/* Initialize the SHPC structure in bridge's BAR. */
+int shpc_init(PCIDevice *d, PCIBus *sec_bus, MemoryRegion *bar, unsigned 
offset)
+{
+    int i, ret;
+    int nslots = SHPC_MAX_SLOTS; /* TODO: qdev property? */
+    SHPCDevice *shpc = d->shpc = g_malloc0(sizeof(*d->shpc));
+    shpc->sec_bus = sec_bus;
+    ret = shpc_cap_add_config(d);
+    if (ret) {
+        g_free(d->shpc);
+        return ret;
+    }
+    if (nslots < SHPC_MIN_SLOTS) {
+        return 0;
+    }
+    if (nslots > SHPC_MAX_SLOTS ||
+        SHPC_IDX_TO_PCI(nslots) > PCI_SLOT_MAX) {
+        /* TODO: report an error mesage that makes sense. */
+        return -EINVAL;
+    }
+    shpc->nslots = nslots;
+    shpc->config = g_malloc0(SHPC_SIZEOF(d));
+    shpc->cmask = g_malloc0(SHPC_SIZEOF(d));
+    shpc->wmask = g_malloc0(SHPC_SIZEOF(d));
+    shpc->w1cmask = g_malloc0(SHPC_SIZEOF(d));
+
+    shpc_reset(d);
+
+    pci_set_long(shpc->config + SHPC_BASE_OFFSET, offset);
+
+    pci_set_byte(shpc->wmask + SHPC_CMD_CODE, 0xff);
+    pci_set_byte(shpc->wmask + SHPC_CMD_TRGT, SHPC_CMD_TRGT_MAX);
+    pci_set_byte(shpc->wmask + SHPC_CMD_TRGT, SHPC_CMD_TRGT_MAX);
+    pci_set_long(shpc->wmask + SHPC_SERR_INT,
+                 SHPC_INT_DIS |
+                 SHPC_SERR_DIS |
+                 SHPC_CMD_INT_DIS |
+                 SHPC_ARB_SERR_DIS);
+    pci_set_long(shpc->w1cmask + SHPC_SERR_INT,
+                 SHPC_CMD_DETECTED |
+                 SHPC_ARB_DETECTED);
+    for (i = 0; i < nslots; ++i) {
+        pci_set_byte(shpc->wmask +
+                     SHPC_SLOT_EVENT_SERR_INT_DIS(d, i),
+                     SHPC_SLOT_EVENT_PRESENCE |
+                     SHPC_SLOT_EVENT_ISOLATED_FAULT |
+                     SHPC_SLOT_EVENT_BUTTON |
+                     SHPC_SLOT_EVENT_MRL |
+                     SHPC_SLOT_EVENT_CONNECTED_FAULT |
+                     SHPC_SLOT_EVENT_MRL_SERR_DIS |
+                     SHPC_SLOT_EVENT_CONNECTED_FAULT_SERR_DIS);
+        pci_set_byte(shpc->w1cmask +
+                     SHPC_SLOT_EVENT_LATCH(i),
+                     SHPC_SLOT_EVENT_PRESENCE |
+                     SHPC_SLOT_EVENT_ISOLATED_FAULT |
+                     SHPC_SLOT_EVENT_BUTTON |
+                     SHPC_SLOT_EVENT_MRL |
+                     SHPC_SLOT_EVENT_CONNECTED_FAULT);
+    }
+
+    /* TODO: init cmask */
+    memory_region_init_io(&shpc->mmio, &shpc_mmio_ops, d, "shpc-mmio",
+                          SHPC_SIZEOF(d));
+    shpc_cap_update_dword(d);
+    memory_region_add_subregion(bar, offset, &shpc->mmio);
+    pci_bus_hotplug(sec_bus, shpc_device_hotplug, &d->qdev);
+
+    d->cap_present |= QEMU_PCI_CAP_SHPC;
+    return 0;
+}
+
+int shpc_bar_size(PCIDevice *d)
+{
+    return roundup_pow_of_two(SHPC_SLOT_REG(SHPC_MAX_SLOTS));
+}
+
+void shpc_cleanup(PCIDevice *d, MemoryRegion *bar)
+{
+    SHPCDevice *shpc = d->shpc;
+    d->cap_present &= ~QEMU_PCI_CAP_SHPC;
+    memory_region_del_subregion(bar, &shpc->mmio);
+    /* TODO: cleanup config space changes? */
+    g_free(shpc->config);
+    g_free(shpc->cmask);
+    g_free(shpc->wmask);
+    g_free(shpc->w1cmask);
+    memory_region_destroy(&shpc->mmio);
+    g_free(shpc);
+}
+
+void shpc_cap_write_config(PCIDevice *d, uint32_t addr, uint32_t val, int l)
+{
+    if (!ranges_overlap(addr, l, d->shpc->cap, SHPC_CAP_LENGTH)) {
+        return;
+    }
+    if (ranges_overlap(addr, l, d->shpc->cap + SHPC_CAP_DWORD_DATA, 4)) {
+        unsigned dword_data;
+        dword_data = pci_get_long(d->shpc->config + d->shpc->cap
+                                  + SHPC_CAP_DWORD_DATA);
+        shpc_write(d, shpc_cap_dword(d) * 4, dword_data, 4);
+    }
+    /* Update cap dword data in case guest is going to read it. */
+    shpc_cap_update_dword(d);
+}
+
+static void shpc_save(QEMUFile *f, void *pv, size_t size)
+{
+    PCIDevice *d = container_of(pv, PCIDevice, shpc);
+    qemu_put_buffer(f, d->shpc->config, SHPC_SIZEOF(d));
+}
+
+static int shpc_load(QEMUFile *f, void *pv, size_t size)
+{
+    PCIDevice *d = container_of(pv, PCIDevice, shpc);
+    int ret = qemu_get_buffer(f, d->shpc->config, SHPC_SIZEOF(d));
+    if (ret != SHPC_SIZEOF(d)) {
+        return -EINVAL;
+    }
+    /* Make sure we don't lose notifications. An extra interrupt is harmless. 
*/
+    d->shpc->msi_requested = 0;
+    shpc_interrupt_update(d);
+    return 0;
+}
+
+VMStateInfo shpc_vmstate_info = {
+    .name = "shpc",
+    .get  = shpc_load,
+    .put  = shpc_save,
+};
diff --git a/hw/pci/shpc.h b/hw/pci/shpc.h
new file mode 100644
index 0000000..130b71d
--- /dev/null
+++ b/hw/pci/shpc.h
@@ -0,0 +1,48 @@
+#ifndef SHPC_H
+#define SHPC_H
+
+#include "qemu-common.h"
+#include "memory.h"
+#include "vmstate.h"
+
+struct SHPCDevice {
+    /* Capability offset in device's config space */
+    int cap;
+
+    /* # of hot-pluggable slots */
+    int nslots;
+
+    /* SHPC WRS: working register set */
+    uint8_t *config;
+
+    /* Used to enable checks on load. Note that writable bits are
+     * never checked even if set in cmask. */
+    uint8_t *cmask;
+
+    /* Used to implement R/W bytes */
+    uint8_t *wmask;
+
+    /* Used to implement RW1C(Write 1 to Clear) bytes */
+    uint8_t *w1cmask;
+
+    /* MMIO for the SHPC BAR */
+    MemoryRegion mmio;
+
+    /* Bus controlled by this SHPC */
+    PCIBus *sec_bus;
+
+    /* MSI already requested for this event */
+    int msi_requested;
+};
+
+void shpc_reset(PCIDevice *d);
+int shpc_bar_size(PCIDevice *dev);
+int shpc_init(PCIDevice *dev, PCIBus *sec_bus, MemoryRegion *bar, unsigned 
off);
+void shpc_cleanup(PCIDevice *dev, MemoryRegion *bar);
+void shpc_cap_write_config(PCIDevice *d, uint32_t addr, uint32_t val, int len);
+
+extern VMStateInfo shpc_vmstate_info;
+#define SHPC_VMSTATE(_field, _type) \
+    VMSTATE_BUFFER_UNSAFE_INFO(_field, _type, 0, shpc_vmstate_info, 0)
+
+#endif
diff --git a/hw/pci/slotid_cap.c b/hw/pci/slotid_cap.c
new file mode 100644
index 0000000..0106452
--- /dev/null
+++ b/hw/pci/slotid_cap.c
@@ -0,0 +1,44 @@
+#include "slotid_cap.h"
+#include "pci.h"
+
+#define SLOTID_CAP_LENGTH 4
+#define SLOTID_NSLOTS_SHIFT (ffs(PCI_SID_ESR_NSLOTS) - 1)
+
+int slotid_cap_init(PCIDevice *d, int nslots,
+                    uint8_t chassis,
+                    unsigned offset)
+{
+    int cap;
+    if (!chassis) {
+        error_report("Bridge chassis not specified. Each bridge is required "
+                     "to be assigned a unique chassis id > 0.");
+        return -EINVAL;
+    }
+    if (nslots < 0 || nslots > (PCI_SID_ESR_NSLOTS >> SLOTID_NSLOTS_SHIFT)) {
+        /* TODO: error report? */
+        return -EINVAL;
+    }
+
+    cap = pci_add_capability(d, PCI_CAP_ID_SLOTID, offset, SLOTID_CAP_LENGTH);
+    if (cap < 0) {
+        return cap;
+    }
+    /* We make each chassis unique, this way each bridge is First in Chassis */
+    d->config[cap + PCI_SID_ESR] = PCI_SID_ESR_FIC |
+        (nslots << SLOTID_NSLOTS_SHIFT);
+    d->cmask[cap + PCI_SID_ESR] = 0xff;
+    d->config[cap + PCI_SID_CHASSIS_NR] = chassis;
+    /* Note: Chassis number register is non-volatile,
+       so we don't reset it. */
+    /* TODO: store in eeprom? */
+    d->wmask[cap + PCI_SID_CHASSIS_NR] = 0xff;
+
+    d->cap_present |= QEMU_PCI_CAP_SLOTID;
+    return 0;
+}
+
+void slotid_cap_cleanup(PCIDevice *d)
+{
+    /* TODO: cleanup config space? */
+    d->cap_present &= ~QEMU_PCI_CAP_SLOTID;
+}
diff --git a/hw/pci/slotid_cap.h b/hw/pci/slotid_cap.h
new file mode 100644
index 0000000..70db047
--- /dev/null
+++ b/hw/pci/slotid_cap.h
@@ -0,0 +1,11 @@
+#ifndef PCI_SLOTID_CAP_H
+#define PCI_SLOTID_CAP_H
+
+#include "qemu-common.h"
+
+int slotid_cap_init(PCIDevice *dev, int nslots,
+                    uint8_t chassis,
+                    unsigned offset);
+void slotid_cap_cleanup(PCIDevice *dev);
+
+#endif
diff --git a/hw/pci_bridge.c b/hw/pci_bridge.c
deleted file mode 100644
index 4680501..0000000
--- a/hw/pci_bridge.c
+++ /dev/null
@@ -1,363 +0,0 @@
-/*
- * QEMU PCI bus manager
- *
- * Copyright (c) 2004 Fabrice Bellard
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to dea
-
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM
-
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- */
-/*
- * split out from pci.c
- * Copyright (c) 2010 Isaku Yamahata <yamahata at valinux co jp>
- *                    VA Linux Systems Japan K.K.
- */
-
-#include "pci_bridge.h"
-#include "pci_internals.h"
-#include "range.h"
-
-/* PCI bridge subsystem vendor ID helper functions */
-#define PCI_SSVID_SIZEOF        8
-#define PCI_SSVID_SVID          4
-#define PCI_SSVID_SSID          6
-
-int pci_bridge_ssvid_init(PCIDevice *dev, uint8_t offset,
-                          uint16_t svid, uint16_t ssid)
-{
-    int pos;
-    pos = pci_add_capability(dev, PCI_CAP_ID_SSVID, offset, PCI_SSVID_SIZEOF);
-    if (pos < 0) {
-        return pos;
-    }
-
-    pci_set_word(dev->config + pos + PCI_SSVID_SVID, svid);
-    pci_set_word(dev->config + pos + PCI_SSVID_SSID, ssid);
-    return pos;
-}
-
-/* Accessor function to get parent bridge device from pci bus. */
-PCIDevice *pci_bridge_get_device(PCIBus *bus)
-{
-    return bus->parent_dev;
-}
-
-/* Accessor function to get secondary bus from pci-to-pci bridge device */
-PCIBus *pci_bridge_get_sec_bus(PCIBridge *br)
-{
-    return &br->sec_bus;
-}
-
-static uint32_t pci_config_get_io_base(const PCIDevice *d,
-                                       uint32_t base, uint32_t base_upper16)
-{
-    uint32_t val;
-
-    val = ((uint32_t)d->config[base] & PCI_IO_RANGE_MASK) << 8;
-    if (d->config[base] & PCI_IO_RANGE_TYPE_32) {
-        val |= (uint32_t)pci_get_word(d->config + base_upper16) << 16;
-    }
-    return val;
-}
-
-static pcibus_t pci_config_get_memory_base(const PCIDevice *d, uint32_t base)
-{
-    return ((pcibus_t)pci_get_word(d->config + base) & PCI_MEMORY_RANGE_MASK)
-        << 16;
-}
-
-static pcibus_t pci_config_get_pref_base(const PCIDevice *d,
-                                         uint32_t base, uint32_t upper)
-{
-    pcibus_t tmp;
-    pcibus_t val;
-
-    tmp = (pcibus_t)pci_get_word(d->config + base);
-    val = (tmp & PCI_PREF_RANGE_MASK) << 16;
-    if (tmp & PCI_PREF_RANGE_TYPE_64) {
-        val |= (pcibus_t)pci_get_long(d->config + upper) << 32;
-    }
-    return val;
-}
-
-/* accessor function to get bridge filtering base address */
-pcibus_t pci_bridge_get_base(const PCIDevice *bridge, uint8_t type)
-{
-    pcibus_t base;
-    if (type & PCI_BASE_ADDRESS_SPACE_IO) {
-        base = pci_config_get_io_base(bridge,
-                                      PCI_IO_BASE, PCI_IO_BASE_UPPER16);
-    } else {
-        if (type & PCI_BASE_ADDRESS_MEM_PREFETCH) {
-            base = pci_config_get_pref_base(
-                bridge, PCI_PREF_MEMORY_BASE, PCI_PREF_BASE_UPPER32);
-        } else {
-            base = pci_config_get_memory_base(bridge, PCI_MEMORY_BASE);
-        }
-    }
-
-    return base;
-}
-
-/* accessor funciton to get bridge filtering limit */
-pcibus_t pci_bridge_get_limit(const PCIDevice *bridge, uint8_t type)
-{
-    pcibus_t limit;
-    if (type & PCI_BASE_ADDRESS_SPACE_IO) {
-        limit = pci_config_get_io_base(bridge,
-                                      PCI_IO_LIMIT, PCI_IO_LIMIT_UPPER16);
-        limit |= 0xfff;         /* PCI bridge spec 3.2.5.6. */
-    } else {
-        if (type & PCI_BASE_ADDRESS_MEM_PREFETCH) {
-            limit = pci_config_get_pref_base(
-                bridge, PCI_PREF_MEMORY_LIMIT, PCI_PREF_LIMIT_UPPER32);
-        } else {
-            limit = pci_config_get_memory_base(bridge, PCI_MEMORY_LIMIT);
-        }
-        limit |= 0xfffff;       /* PCI bridge spec 3.2.5.{1, 8}. */
-    }
-    return limit;
-}
-
-static void pci_bridge_init_alias(PCIBridge *bridge, MemoryRegion *alias,
-                                  uint8_t type, const char *name,
-                                  MemoryRegion *space,
-                                  MemoryRegion *parent_space,
-                                  bool enabled)
-{
-    pcibus_t base = pci_bridge_get_base(&bridge->dev, type);
-    pcibus_t limit = pci_bridge_get_limit(&bridge->dev, type);
-    /* TODO: this doesn't handle base = 0 limit = 2^64 - 1 correctly.
-     * Apparently no way to do this with existing memory APIs. */
-    pcibus_t size = enabled && limit >= base ? limit + 1 - base : 0;
-
-    memory_region_init_alias(alias, name, space, base, size);
-    memory_region_add_subregion_overlap(parent_space, base, alias, 1);
-}
-
-static PCIBridgeWindows *pci_bridge_region_init(PCIBridge *br)
-{
-    PCIBus *parent = br->dev.bus;
-    PCIBridgeWindows *w = g_new(PCIBridgeWindows, 1);
-    uint16_t cmd = pci_get_word(br->dev.config + PCI_COMMAND);
-
-    pci_bridge_init_alias(br, &w->alias_pref_mem,
-                          PCI_BASE_ADDRESS_MEM_PREFETCH,
-                          "pci_bridge_pref_mem",
-                          &br->address_space_mem,
-                          parent->address_space_mem,
-                          cmd & PCI_COMMAND_MEMORY);
-    pci_bridge_init_alias(br, &w->alias_mem,
-                          PCI_BASE_ADDRESS_SPACE_MEMORY,
-                          "pci_bridge_mem",
-                          &br->address_space_mem,
-                          parent->address_space_mem,
-                          cmd & PCI_COMMAND_MEMORY);
-    pci_bridge_init_alias(br, &w->alias_io,
-                          PCI_BASE_ADDRESS_SPACE_IO,
-                          "pci_bridge_io",
-                          &br->address_space_io,
-                          parent->address_space_io,
-                          cmd & PCI_COMMAND_IO);
-   /* TODO: optinal VGA and VGA palette snooping support. */
-
-    return w;
-}
-
-static void pci_bridge_region_del(PCIBridge *br, PCIBridgeWindows *w)
-{
-    PCIBus *parent = br->dev.bus;
-
-    memory_region_del_subregion(parent->address_space_io, &w->alias_io);
-    memory_region_del_subregion(parent->address_space_mem, &w->alias_mem);
-    memory_region_del_subregion(parent->address_space_mem, &w->alias_pref_mem);
-}
-
-static void pci_bridge_region_cleanup(PCIBridge *br, PCIBridgeWindows *w)
-{
-    memory_region_destroy(&w->alias_io);
-    memory_region_destroy(&w->alias_mem);
-    memory_region_destroy(&w->alias_pref_mem);
-    g_free(w);
-}
-
-static void pci_bridge_update_mappings(PCIBridge *br)
-{
-    PCIBridgeWindows *w = br->windows;
-
-    /* Make updates atomic to: handle the case of one VCPU updating the bridge
-     * while another accesses an unaffected region. */
-    memory_region_transaction_begin();
-    pci_bridge_region_del(br, br->windows);
-    br->windows = pci_bridge_region_init(br);
-    memory_region_transaction_commit();
-    pci_bridge_region_cleanup(br, w);
-}
-
-/* default write_config function for PCI-to-PCI bridge */
-void pci_bridge_write_config(PCIDevice *d,
-                             uint32_t address, uint32_t val, int len)
-{
-    PCIBridge *s = container_of(d, PCIBridge, dev);
-    uint16_t oldctl = pci_get_word(d->config + PCI_BRIDGE_CONTROL);
-    uint16_t newctl;
-
-    pci_default_write_config(d, address, val, len);
-
-    if (ranges_overlap(address, len, PCI_COMMAND, 2) ||
-
-        /* io base/limit */
-        ranges_overlap(address, len, PCI_IO_BASE, 2) ||
-
-        /* memory base/limit, prefetchable base/limit and
-           io base/limit upper 16 */
-        ranges_overlap(address, len, PCI_MEMORY_BASE, 20)) {
-        pci_bridge_update_mappings(s);
-    }
-
-    newctl = pci_get_word(d->config + PCI_BRIDGE_CONTROL);
-    if (~oldctl & newctl & PCI_BRIDGE_CTL_BUS_RESET) {
-        /* Trigger hot reset on 0->1 transition. */
-        pci_bus_reset(&s->sec_bus);
-    }
-}
-
-void pci_bridge_disable_base_limit(PCIDevice *dev)
-{
-    uint8_t *conf = dev->config;
-
-    pci_byte_test_and_set_mask(conf + PCI_IO_BASE,
-                               PCI_IO_RANGE_MASK & 0xff);
-    pci_byte_test_and_clear_mask(conf + PCI_IO_LIMIT,
-                                 PCI_IO_RANGE_MASK & 0xff);
-    pci_word_test_and_set_mask(conf + PCI_MEMORY_BASE,
-                               PCI_MEMORY_RANGE_MASK & 0xffff);
-    pci_word_test_and_clear_mask(conf + PCI_MEMORY_LIMIT,
-                                 PCI_MEMORY_RANGE_MASK & 0xffff);
-    pci_word_test_and_set_mask(conf + PCI_PREF_MEMORY_BASE,
-                               PCI_PREF_RANGE_MASK & 0xffff);
-    pci_word_test_and_clear_mask(conf + PCI_PREF_MEMORY_LIMIT,
-                                 PCI_PREF_RANGE_MASK & 0xffff);
-    pci_set_long(conf + PCI_PREF_BASE_UPPER32, 0);
-    pci_set_long(conf + PCI_PREF_LIMIT_UPPER32, 0);
-}
-
-/* reset bridge specific configuration registers */
-void pci_bridge_reset(DeviceState *qdev)
-{
-    PCIDevice *dev = PCI_DEVICE(qdev);
-    uint8_t *conf = dev->config;
-
-    conf[PCI_PRIMARY_BUS] = 0;
-    conf[PCI_SECONDARY_BUS] = 0;
-    conf[PCI_SUBORDINATE_BUS] = 0;
-    conf[PCI_SEC_LATENCY_TIMER] = 0;
-
-    /*
-     * the default values for base/limit registers aren't specified
-     * in the PCI-to-PCI-bridge spec. So we don't thouch them here.
-     * Each implementation can override it.
-     * typical implementation does
-     * zero base/limit registers or
-     * disable forwarding: pci_bridge_disable_base_limit()
-     * If disable forwarding is wanted, call pci_bridge_disable_base_limit()
-     * after this function.
-     */
-    pci_byte_test_and_clear_mask(conf + PCI_IO_BASE,
-                                 PCI_IO_RANGE_MASK & 0xff);
-    pci_byte_test_and_clear_mask(conf + PCI_IO_LIMIT,
-                                 PCI_IO_RANGE_MASK & 0xff);
-    pci_word_test_and_clear_mask(conf + PCI_MEMORY_BASE,
-                                 PCI_MEMORY_RANGE_MASK & 0xffff);
-    pci_word_test_and_clear_mask(conf + PCI_MEMORY_LIMIT,
-                                 PCI_MEMORY_RANGE_MASK & 0xffff);
-    pci_word_test_and_clear_mask(conf + PCI_PREF_MEMORY_BASE,
-                                 PCI_PREF_RANGE_MASK & 0xffff);
-    pci_word_test_and_clear_mask(conf + PCI_PREF_MEMORY_LIMIT,
-                                 PCI_PREF_RANGE_MASK & 0xffff);
-    pci_set_long(conf + PCI_PREF_BASE_UPPER32, 0);
-    pci_set_long(conf + PCI_PREF_LIMIT_UPPER32, 0);
-
-    pci_set_word(conf + PCI_BRIDGE_CONTROL, 0);
-}
-
-/* default qdev initialization function for PCI-to-PCI bridge */
-int pci_bridge_initfn(PCIDevice *dev)
-{
-    PCIBus *parent = dev->bus;
-    PCIBridge *br = DO_UPCAST(PCIBridge, dev, dev);
-    PCIBus *sec_bus = &br->sec_bus;
-
-    pci_word_test_and_set_mask(dev->config + PCI_STATUS,
-                               PCI_STATUS_66MHZ | PCI_STATUS_FAST_BACK);
-    pci_config_set_class(dev->config, PCI_CLASS_BRIDGE_PCI);
-    dev->config[PCI_HEADER_TYPE] =
-        (dev->config[PCI_HEADER_TYPE] & PCI_HEADER_TYPE_MULTI_FUNCTION) |
-        PCI_HEADER_TYPE_BRIDGE;
-    pci_set_word(dev->config + PCI_SEC_STATUS,
-                 PCI_STATUS_66MHZ | PCI_STATUS_FAST_BACK);
-
-    /*
-     * If we don't specify the name, the bus will be addressed as <id>.0, where
-     * id is the device id.
-     * Since PCI Bridge devices have a single bus each, we don't need the 
index:
-     * let users address the bus using the device name.
-     */
-    if (!br->bus_name && dev->qdev.id && *dev->qdev.id) {
-           br->bus_name = dev->qdev.id;
-    }
-
-    qbus_create_inplace(&sec_bus->qbus, TYPE_PCI_BUS, &dev->qdev,
-                        br->bus_name);
-    sec_bus->parent_dev = dev;
-    sec_bus->map_irq = br->map_irq;
-    sec_bus->address_space_mem = &br->address_space_mem;
-    memory_region_init(&br->address_space_mem, "pci_bridge_pci", INT64_MAX);
-    sec_bus->address_space_io = &br->address_space_io;
-    memory_region_init(&br->address_space_io, "pci_bridge_io", 65536);
-    br->windows = pci_bridge_region_init(br);
-    QLIST_INIT(&sec_bus->child);
-    QLIST_INSERT_HEAD(&parent->child, sec_bus, sibling);
-    return 0;
-}
-
-/* default qdev clean up function for PCI-to-PCI bridge */
-void pci_bridge_exitfn(PCIDevice *pci_dev)
-{
-    PCIBridge *s = DO_UPCAST(PCIBridge, dev, pci_dev);
-    assert(QLIST_EMPTY(&s->sec_bus.child));
-    QLIST_REMOVE(&s->sec_bus, sibling);
-    pci_bridge_region_del(s, s->windows);
-    pci_bridge_region_cleanup(s, s->windows);
-    memory_region_destroy(&s->address_space_mem);
-    memory_region_destroy(&s->address_space_io);
-    /* qbus_free() is called automatically by qdev_free() */
-}
-
-/*
- * before qdev initialization(qdev_init()), this function sets bus_name and
- * map_irq callback which are necessry for pci_bridge_initfn() to
- * initialize bus.
- */
-void pci_bridge_map_irq(PCIBridge *br, const char* bus_name,
-                        pci_map_irq_fn map_irq)
-{
-    br->map_irq = map_irq;
-    br->bus_name = bus_name;
-}
diff --git a/hw/pci_bridge.h b/hw/pci_bridge.h
deleted file mode 100644
index a00accc..0000000
--- a/hw/pci_bridge.h
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
- * QEMU PCI bridge
- *
- * Copyright (c) 2004 Fabrice Bellard
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- *
- * split out pci bus specific stuff from pci.[hc] to pci_bridge.[hc]
- * Copyright (c) 2009 Isaku Yamahata <yamahata at valinux co jp>
- *                    VA Linux Systems Japan K.K.
- *
- */
-
-#ifndef QEMU_PCI_BRIDGE_H
-#define QEMU_PCI_BRIDGE_H
-
-#include "pci.h"
-
-int pci_bridge_ssvid_init(PCIDevice *dev, uint8_t offset,
-                          uint16_t svid, uint16_t ssid);
-
-PCIDevice *pci_bridge_get_device(PCIBus *bus);
-PCIBus *pci_bridge_get_sec_bus(PCIBridge *br);
-
-pcibus_t pci_bridge_get_base(const PCIDevice *bridge, uint8_t type);
-pcibus_t pci_bridge_get_limit(const PCIDevice *bridge, uint8_t type);
-
-void pci_bridge_write_config(PCIDevice *d,
-                             uint32_t address, uint32_t val, int len);
-void pci_bridge_disable_base_limit(PCIDevice *dev);
-void pci_bridge_reset_reg(PCIDevice *dev);
-void pci_bridge_reset(DeviceState *qdev);
-
-int pci_bridge_initfn(PCIDevice *pci_dev);
-void pci_bridge_exitfn(PCIDevice *pci_dev);
-
-
-/*
- * before qdev initialization(qdev_init()), this function sets bus_name and
- * map_irq callback which are necessry for pci_bridge_initfn() to
- * initialize bus.
- */
-void pci_bridge_map_irq(PCIBridge *br, const char* bus_name,
-                        pci_map_irq_fn map_irq);
-
-#endif  /* QEMU_PCI_BRIDGE_H */
-/*
- * Local variables:
- *  c-indent-level: 4
- *  c-basic-offset: 4
- *  tab-width: 8
- *  indent-tab-mode: nil
- * End:
- */
diff --git a/hw/pci_host.c b/hw/pci_host.c
deleted file mode 100644
index 68e328c..0000000
--- a/hw/pci_host.c
+++ /dev/null
@@ -1,180 +0,0 @@
-/*
- * pci_host.c
- *
- * Copyright (c) 2009 Isaku Yamahata <yamahata at valinux co jp>
- *                    VA Linux Systems Japan K.K.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
-
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
-
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, see <http://www.gnu.org/licenses/>.
- */
-
-#include "pci.h"
-#include "pci_host.h"
-
-/* debug PCI */
-//#define DEBUG_PCI
-
-#ifdef DEBUG_PCI
-#define PCI_DPRINTF(fmt, ...) \
-do { printf("pci_host_data: " fmt , ## __VA_ARGS__); } while (0)
-#else
-#define PCI_DPRINTF(fmt, ...)
-#endif
-
-/*
- * PCI address
- * bit 16 - 24: bus number
- * bit  8 - 15: devfun number
- * bit  0 -  7: offset in configuration space of a given pci device
- */
-
-/* the helper functio to get a PCIDeice* for a given pci address */
-static inline PCIDevice *pci_dev_find_by_addr(PCIBus *bus, uint32_t addr)
-{
-    uint8_t bus_num = addr >> 16;
-    uint8_t devfn = addr >> 8;
-
-    return pci_find_device(bus, bus_num, devfn);
-}
-
-void pci_host_config_write_common(PCIDevice *pci_dev, uint32_t addr,
-                                  uint32_t limit, uint32_t val, uint32_t len)
-{
-    assert(len <= 4);
-    pci_dev->config_write(pci_dev, addr, val, MIN(len, limit - addr));
-}
-
-uint32_t pci_host_config_read_common(PCIDevice *pci_dev, uint32_t addr,
-                                     uint32_t limit, uint32_t len)
-{
-    assert(len <= 4);
-    return pci_dev->config_read(pci_dev, addr, MIN(len, limit - addr));
-}
-
-void pci_data_write(PCIBus *s, uint32_t addr, uint32_t val, int len)
-{
-    PCIDevice *pci_dev = pci_dev_find_by_addr(s, addr);
-    uint32_t config_addr = addr & (PCI_CONFIG_SPACE_SIZE - 1);
-
-    if (!pci_dev) {
-        return;
-    }
-
-    PCI_DPRINTF("%s: %s: addr=%02" PRIx32 " val=%08" PRIx32 " len=%d\n",
-                __func__, pci_dev->name, config_addr, val, len);
-    pci_host_config_write_common(pci_dev, config_addr, PCI_CONFIG_SPACE_SIZE,
-                                 val, len);
-}
-
-uint32_t pci_data_read(PCIBus *s, uint32_t addr, int len)
-{
-    PCIDevice *pci_dev = pci_dev_find_by_addr(s, addr);
-    uint32_t config_addr = addr & (PCI_CONFIG_SPACE_SIZE - 1);
-    uint32_t val;
-
-    if (!pci_dev) {
-        return ~0x0;
-    }
-
-    val = pci_host_config_read_common(pci_dev, config_addr,
-                                      PCI_CONFIG_SPACE_SIZE, len);
-    PCI_DPRINTF("%s: %s: addr=%02"PRIx32" val=%08"PRIx32" len=%d\n",
-                __func__, pci_dev->name, config_addr, val, len);
-
-    return val;
-}
-
-static void pci_host_config_write(void *opaque, hwaddr addr,
-                                  uint64_t val, unsigned len)
-{
-    PCIHostState *s = opaque;
-
-    PCI_DPRINTF("%s addr " TARGET_FMT_plx " len %d val %"PRIx64"\n",
-                __func__, addr, len, val);
-    if (addr != 0 || len != 4) {
-        return;
-    }
-    s->config_reg = val;
-}
-
-static uint64_t pci_host_config_read(void *opaque, hwaddr addr,
-                                     unsigned len)
-{
-    PCIHostState *s = opaque;
-    uint32_t val = s->config_reg;
-
-    PCI_DPRINTF("%s addr " TARGET_FMT_plx " len %d val %"PRIx32"\n",
-                __func__, addr, len, val);
-    return val;
-}
-
-static void pci_host_data_write(void *opaque, hwaddr addr,
-                                uint64_t val, unsigned len)
-{
-    PCIHostState *s = opaque;
-    PCI_DPRINTF("write addr " TARGET_FMT_plx " len %d val %x\n",
-                addr, len, (unsigned)val);
-    if (s->config_reg & (1u << 31))
-        pci_data_write(s->bus, s->config_reg | (addr & 3), val, len);
-}
-
-static uint64_t pci_host_data_read(void *opaque,
-                                   hwaddr addr, unsigned len)
-{
-    PCIHostState *s = opaque;
-    uint32_t val;
-    if (!(s->config_reg & (1 << 31)))
-        return 0xffffffff;
-    val = pci_data_read(s->bus, s->config_reg | (addr & 3), len);
-    PCI_DPRINTF("read addr " TARGET_FMT_plx " len %d val %x\n",
-                addr, len, val);
-    return val;
-}
-
-const MemoryRegionOps pci_host_conf_le_ops = {
-    .read = pci_host_config_read,
-    .write = pci_host_config_write,
-    .endianness = DEVICE_LITTLE_ENDIAN,
-};
-
-const MemoryRegionOps pci_host_conf_be_ops = {
-    .read = pci_host_config_read,
-    .write = pci_host_config_write,
-    .endianness = DEVICE_BIG_ENDIAN,
-};
-
-const MemoryRegionOps pci_host_data_le_ops = {
-    .read = pci_host_data_read,
-    .write = pci_host_data_write,
-    .endianness = DEVICE_LITTLE_ENDIAN,
-};
-
-const MemoryRegionOps pci_host_data_be_ops = {
-    .read = pci_host_data_read,
-    .write = pci_host_data_write,
-    .endianness = DEVICE_BIG_ENDIAN,
-};
-
-static const TypeInfo pci_host_type_info = {
-    .name = TYPE_PCI_HOST_BRIDGE,
-    .parent = TYPE_SYS_BUS_DEVICE,
-    .abstract = true,
-    .instance_size = sizeof(PCIHostState),
-};
-
-static void pci_host_register_types(void)
-{
-    type_register_static(&pci_host_type_info);
-}
-
-type_init(pci_host_register_types)
diff --git a/hw/pci_host.h b/hw/pci_host.h
deleted file mode 100644
index 4b9c300..0000000
--- a/hw/pci_host.h
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * QEMU Common PCI Host bridge configuration data space access routines.
- *
- * Copyright (c) 2006 Fabrice Bellard
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to 
deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 
FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- */
-
-/* Worker routines for a PCI host controller that uses an {address,data}
-   register pair to access PCI configuration space.  */
-
-#ifndef PCI_HOST_H
-#define PCI_HOST_H
-
-#include "sysbus.h"
-
-#define TYPE_PCI_HOST_BRIDGE "pci-host-bridge"
-#define PCI_HOST_BRIDGE(obj) \
-    OBJECT_CHECK(PCIHostState, (obj), TYPE_PCI_HOST_BRIDGE)
-
-struct PCIHostState {
-    SysBusDevice busdev;
-
-    MemoryRegion conf_mem;
-    MemoryRegion data_mem;
-    MemoryRegion mmcfg;
-    MemoryRegion *address_space;
-    uint32_t config_reg;
-    PCIBus *bus;
-};
-
-/* common internal helpers for PCI/PCIe hosts, cut off overflows */
-void pci_host_config_write_common(PCIDevice *pci_dev, uint32_t addr,
-                                  uint32_t limit, uint32_t val, uint32_t len);
-uint32_t pci_host_config_read_common(PCIDevice *pci_dev, uint32_t addr,
-                                     uint32_t limit, uint32_t len);
-
-void pci_data_write(PCIBus *s, uint32_t addr, uint32_t val, int len);
-uint32_t pci_data_read(PCIBus *s, uint32_t addr, int len);
-
-extern const MemoryRegionOps pci_host_conf_le_ops;
-extern const MemoryRegionOps pci_host_conf_be_ops;
-extern const MemoryRegionOps pci_host_data_le_ops;
-extern const MemoryRegionOps pci_host_data_be_ops;
-
-#endif /* PCI_HOST_H */
diff --git a/hw/pci_ids.h b/hw/pci_ids.h
deleted file mode 100644
index 5df7245..0000000
--- a/hw/pci_ids.h
+++ /dev/null
@@ -1,147 +0,0 @@
-/*
- *      PCI Class, Vendor and Device IDs
- *
- *      Please keep sorted.
- *
- *      Abbreviated version of linux/pci_ids.h
- *
- *      QEMU-specific definitions belong in pci.h
- */
-
-/* Device classes and subclasses */
-
-#define PCI_BASE_CLASS_STORAGE           0x01
-#define PCI_BASE_CLASS_NETWORK           0x02
-
-#define PCI_CLASS_STORAGE_SCSI           0x0100
-#define PCI_CLASS_STORAGE_IDE            0x0101
-#define PCI_CLASS_STORAGE_RAID           0x0104
-#define PCI_CLASS_STORAGE_SATA           0x0106
-#define PCI_CLASS_STORAGE_OTHER          0x0180
-
-#define PCI_CLASS_NETWORK_ETHERNET       0x0200
-
-#define PCI_CLASS_DISPLAY_VGA            0x0300
-#define PCI_CLASS_DISPLAY_OTHER          0x0380
-
-#define PCI_CLASS_MULTIMEDIA_AUDIO       0x0401
-
-#define PCI_CLASS_MEMORY_RAM             0x0500
-
-#define PCI_CLASS_SYSTEM_OTHER           0x0880
-
-#define PCI_CLASS_SERIAL_USB             0x0c03
-#define PCI_CLASS_SERIAL_SMBUS           0x0c05
-
-#define PCI_CLASS_BRIDGE_HOST            0x0600
-#define PCI_CLASS_BRIDGE_ISA             0x0601
-#define PCI_CLASS_BRIDGE_PCI             0x0604
-#define PCI_CLASS_BRDIGE_PCI_INF_SUB     0x01
-#define PCI_CLASS_BRIDGE_OTHER           0x0680
-
-#define PCI_CLASS_COMMUNICATION_SERIAL   0x0700
-#define PCI_CLASS_COMMUNICATION_OTHER    0x0780
-
-#define PCI_CLASS_PROCESSOR_CO           0x0b40
-#define PCI_CLASS_PROCESSOR_POWERPC      0x0b20
-
-#define PCI_CLASS_OTHERS                 0xff
-
-/* Vendors and devices.  Sort key: vendor first, device next. */
-
-#define PCI_VENDOR_ID_LSI_LOGIC          0x1000
-#define PCI_DEVICE_ID_LSI_53C895A        0x0012
-#define PCI_DEVICE_ID_LSI_SAS1078        0x0060
-
-#define PCI_VENDOR_ID_DEC                0x1011
-#define PCI_DEVICE_ID_DEC_21154          0x0026
-
-#define PCI_VENDOR_ID_CIRRUS             0x1013
-
-#define PCI_VENDOR_ID_IBM                0x1014
-
-#define PCI_VENDOR_ID_AMD                0x1022
-#define PCI_DEVICE_ID_AMD_LANCE          0x2000
-#define PCI_DEVICE_ID_AMD_SCSI           0x2020
-
-#define PCI_VENDOR_ID_TI                 0x104c
-
-#define PCI_VENDOR_ID_MOTOROLA           0x1057
-#define PCI_DEVICE_ID_MOTOROLA_MPC106    0x0002
-#define PCI_DEVICE_ID_MOTOROLA_RAVEN     0x4801
-
-#define PCI_VENDOR_ID_APPLE              0x106b
-#define PCI_DEVICE_ID_APPLE_UNI_N_AGP    0x0020
-#define PCI_DEVICE_ID_APPLE_U3_AGP       0x004b
-
-#define PCI_VENDOR_ID_SUN                0x108e
-#define PCI_DEVICE_ID_SUN_EBUS           0x1000
-#define PCI_DEVICE_ID_SUN_SIMBA          0x5000
-#define PCI_DEVICE_ID_SUN_SABRE          0xa000
-
-#define PCI_VENDOR_ID_CMD                0x1095
-#define PCI_DEVICE_ID_CMD_646            0x0646
-
-#define PCI_VENDOR_ID_REALTEK            0x10ec
-#define PCI_DEVICE_ID_REALTEK_8139       0x8139
-
-#define PCI_VENDOR_ID_XILINX             0x10ee
-
-#define PCI_VENDOR_ID_VIA                0x1106
-#define PCI_DEVICE_ID_VIA_ISA_BRIDGE     0x0686
-#define PCI_DEVICE_ID_VIA_IDE            0x0571
-#define PCI_DEVICE_ID_VIA_UHCI           0x3038
-#define PCI_DEVICE_ID_VIA_ACPI           0x3057
-#define PCI_DEVICE_ID_VIA_AC97           0x3058
-#define PCI_DEVICE_ID_VIA_MC97           0x3068
-
-#define PCI_VENDOR_ID_MARVELL            0x11ab
-
-#define PCI_VENDOR_ID_ENSONIQ            0x1274
-#define PCI_DEVICE_ID_ENSONIQ_ES1370     0x5000
-
-#define PCI_VENDOR_ID_FREESCALE          0x1957
-#define PCI_DEVICE_ID_MPC8533E           0x0030
-
-#define PCI_VENDOR_ID_INTEL              0x8086
-#define PCI_DEVICE_ID_INTEL_82378        0x0484
-#define PCI_DEVICE_ID_INTEL_82441        0x1237
-#define PCI_DEVICE_ID_INTEL_82801AA_5    0x2415
-#define PCI_DEVICE_ID_INTEL_82801BA_11   0x244e
-#define PCI_DEVICE_ID_INTEL_82801D       0x24CD
-#define PCI_DEVICE_ID_INTEL_ESB_9        0x25ab
-#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_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_ICH9_0       0x2910
-#define PCI_DEVICE_ID_INTEL_ICH9_1       0x2917
-#define PCI_DEVICE_ID_INTEL_ICH9_2       0x2912
-#define PCI_DEVICE_ID_INTEL_ICH9_3       0x2913
-#define PCI_DEVICE_ID_INTEL_ICH9_4       0x2914
-#define PCI_DEVICE_ID_INTEL_ICH9_5       0x2919
-#define PCI_DEVICE_ID_INTEL_ICH9_6       0x2930
-#define PCI_DEVICE_ID_INTEL_ICH9_7       0x2916
-#define PCI_DEVICE_ID_INTEL_ICH9_8       0x2918
-
-#define PCI_DEVICE_ID_INTEL_82801I_UHCI1 0x2934
-#define PCI_DEVICE_ID_INTEL_82801I_UHCI2 0x2935
-#define PCI_DEVICE_ID_INTEL_82801I_UHCI3 0x2936
-#define PCI_DEVICE_ID_INTEL_82801I_UHCI4 0x2937
-#define PCI_DEVICE_ID_INTEL_82801I_UHCI5 0x2938
-#define PCI_DEVICE_ID_INTEL_82801I_UHCI6 0x2939
-#define PCI_DEVICE_ID_INTEL_82801I_EHCI1 0x293a
-#define PCI_DEVICE_ID_INTEL_82801I_EHCI2 0x293c
-#define PCI_DEVICE_ID_INTEL_82599_SFP_VF 0x10ed
-
-#define PCI_DEVICE_ID_INTEL_Q35_MCH      0x29c0
-
-#define PCI_VENDOR_ID_XEN               0x5853
-#define PCI_DEVICE_ID_XEN_PLATFORM      0x0001
-
-#define PCI_VENDOR_ID_NEC                0x1033
-#define PCI_DEVICE_ID_NEC_UPD720200      0x0194
diff --git a/hw/pci_internals.h b/hw/pci_internals.h
deleted file mode 100644
index 21d0ce6..0000000
--- a/hw/pci_internals.h
+++ /dev/null
@@ -1,78 +0,0 @@
-#ifndef QEMU_PCI_INTERNALS_H
-#define QEMU_PCI_INTERNALS_H
-
-/*
- * This header files is private to pci.c and pci_bridge.c
- * So following structures are opaque to others and shouldn't be
- * accessed.
- *
- * For pci-to-pci bridge needs to include this header file to embed
- * PCIBridge in its structure or to get sizeof(PCIBridge),
- * However, they shouldn't access those following members directly.
- * Use accessor function in pci.h, pci_bridge.h
- */
-
-#define TYPE_PCI_BUS "PCI"
-#define PCI_BUS(obj) OBJECT_CHECK(PCIBus, (obj), TYPE_PCI_BUS)
-
-struct PCIBus {
-    BusState qbus;
-    PCIDMAContextFunc dma_context_fn;
-    void *dma_context_opaque;
-    uint8_t devfn_min;
-    pci_set_irq_fn set_irq;
-    pci_map_irq_fn map_irq;
-    pci_route_irq_fn route_intx_to_irq;
-    pci_hotplug_fn hotplug;
-    DeviceState *hotplug_qdev;
-    void *irq_opaque;
-    PCIDevice *devices[PCI_SLOT_MAX * PCI_FUNC_MAX];
-    PCIDevice *parent_dev;
-    MemoryRegion *address_space_mem;
-    MemoryRegion *address_space_io;
-
-    QLIST_HEAD(, PCIBus) child; /* this will be replaced by qdev later */
-    QLIST_ENTRY(PCIBus) sibling;/* this will be replaced by qdev later */
-
-    /* The bus IRQ state is the logical OR of the connected devices.
-       Keep a count of the number of devices with raised IRQs.  */
-    int nirq;
-    int *irq_count;
-};
-
-typedef struct PCIBridgeWindows PCIBridgeWindows;
-
-/*
- * Aliases for each of the address space windows that the bridge
- * can forward. Mapped into the bridge's parent's address space,
- * as subregions.
- */
-struct PCIBridgeWindows {
-    MemoryRegion alias_pref_mem;
-    MemoryRegion alias_mem;
-    MemoryRegion alias_io;
-};
-
-struct PCIBridge {
-    PCIDevice dev;
-
-    /* private member */
-    PCIBus sec_bus;
-    /*
-     * Memory regions for the bridge's address spaces.  These regions are not
-     * directly added to system_memory/system_io or its descendants.
-     * Bridge's secondary bus points to these, so that devices
-     * under the bridge see these regions as its address spaces.
-     * The regions are as large as the entire address space -
-     * they don't take into account any windows.
-     */
-    MemoryRegion address_space_mem;
-    MemoryRegion address_space_io;
-
-    PCIBridgeWindows *windows;
-
-    pci_map_irq_fn map_irq;
-    const char *bus_name;
-};
-
-#endif /* QEMU_PCI_INTERNALS_H */
diff --git a/hw/pci_regs.h b/hw/pci_regs.h
deleted file mode 100644
index 56a404b..0000000
--- a/hw/pci_regs.h
+++ /dev/null
@@ -1,717 +0,0 @@
-/*
- *     pci_regs.h
- *
- *     PCI standard defines
- *     Copyright 1994, Drew Eckhardt
- *     Copyright 1997--1999 Martin Mares <address@hidden>
- *
- *     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
- *
- *     For hypertransport information, please consult the following manuals
- *     from http://www.hypertransport.org
- *
- *     The Hypertransport I/O Link Specification
- */
-
-#ifndef LINUX_PCI_REGS_H
-#define LINUX_PCI_REGS_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_COMMAND_INTX_DISABLE 0x400 /* INTx Emulation Disable */
-
-#define PCI_STATUS             0x06    /* 16 bits */
-#define  PCI_STATUS_INTERRUPT  0x08    /* Interrupt status */
-#define  PCI_STATUS_CAP_LIST   0x10    /* Support Capability List */
-#define  PCI_STATUS_66MHZ      0x20    /* Support 66 Mhz PCI 2.1 bus */
-#define  PCI_STATUS_UDF                0x40    /* Support User Definable 
Features [obsolete] */
-#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 [obsolete] */
-#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)
-
-#define PCI_CAPABILITY_LIST    0x34    /* Offset of first capability list 
entry */
-
-/* 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        0x0fUL  /* I/O bridging type */
-#define  PCI_IO_RANGE_TYPE_16  0x00
-#define  PCI_IO_RANGE_TYPE_32  0x01
-#define  PCI_IO_RANGE_MASK     (~0x0fUL)
-#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 0x0fUL
-#define  PCI_MEMORY_RANGE_MASK (~0x0fUL)
-#define PCI_PREF_MEMORY_BASE   0x24    /* Prefetchable memory range behind */
-#define PCI_PREF_MEMORY_LIMIT  0x26
-#define  PCI_PREF_RANGE_TYPE_MASK 0x0fUL
-#define  PCI_PREF_RANGE_TYPE_32        0x00
-#define  PCI_PREF_RANGE_TYPE_64        0x01
-#define  PCI_PREF_RANGE_MASK   (~0x0fUL)
-#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 same as for htype 0 */
-/* 0x35-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_ISA    0x04    /* Enable ISA mode */
-#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) */
-#define PCI_CB_CAPABILITY_LIST 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  (~0x03UL)
-/* 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 */
-
-/* Capability lists */
-
-#define PCI_CAP_LIST_ID                0       /* Capability ID */
-#define  PCI_CAP_ID_PM         0x01    /* Power Management */
-#define  PCI_CAP_ID_AGP                0x02    /* Accelerated Graphics Port */
-#define  PCI_CAP_ID_VPD                0x03    /* Vital Product Data */
-#define  PCI_CAP_ID_SLOTID     0x04    /* Slot Identification */
-#define  PCI_CAP_ID_MSI                0x05    /* Message Signalled Interrupts 
*/
-#define  PCI_CAP_ID_CHSWP      0x06    /* CompactPCI HotSwap */
-#define  PCI_CAP_ID_PCIX       0x07    /* PCI-X */
-#define  PCI_CAP_ID_HT         0x08    /* HyperTransport */
-#define  PCI_CAP_ID_VNDR       0x09    /* Vendor specific */
-#define  PCI_CAP_ID_DBG                0x0A    /* Debug port */
-#define  PCI_CAP_ID_CCRC       0x0B    /* CompactPCI Central Resource Control 
*/
-#define  PCI_CAP_ID_SHPC       0x0C    /* PCI Standard Hot-Plug Controller */
-#define  PCI_CAP_ID_SSVID      0x0D    /* Bridge subsystem vendor/device ID */
-#define  PCI_CAP_ID_AGP3       0x0E    /* AGP Target PCI-PCI bridge */
-#define  PCI_CAP_ID_EXP        0x10    /* PCI Express */
-#define  PCI_CAP_ID_MSIX       0x11    /* MSI-X */
-#define  PCI_CAP_ID_SATA       0x12    /* Serial ATA */
-#define  PCI_CAP_ID_AF         0x13    /* PCI Advanced Features */
-#define PCI_CAP_LIST_NEXT      1       /* Next capability in the list */
-#define PCI_CAP_FLAGS          2       /* Capability defined flags (16 bits) */
-#define PCI_CAP_SIZEOF         4
-
-/* Power Management Registers */
-
-#define PCI_PM_PMC             2       /* PM Capabilities Register */
-#define  PCI_PM_CAP_VER_MASK   0x0007  /* Version */
-#define  PCI_PM_CAP_PME_CLOCK  0x0008  /* PME clock required */
-#define  PCI_PM_CAP_RESERVED    0x0010  /* Reserved field */
-#define  PCI_PM_CAP_DSI                0x0020  /* Device specific 
initialization */
-#define  PCI_PM_CAP_AUX_POWER  0x01C0  /* Auxiliary power support mask */
-#define  PCI_PM_CAP_D1         0x0200  /* D1 power state support */
-#define  PCI_PM_CAP_D2         0x0400  /* D2 power state support */
-#define  PCI_PM_CAP_PME                0x0800  /* PME pin supported */
-#define  PCI_PM_CAP_PME_MASK   0xF800  /* PME Mask of all supported states */
-#define  PCI_PM_CAP_PME_D0     0x0800  /* PME# from D0 */
-#define  PCI_PM_CAP_PME_D1     0x1000  /* PME# from D1 */
-#define  PCI_PM_CAP_PME_D2     0x2000  /* PME# from D2 */
-#define  PCI_PM_CAP_PME_D3     0x4000  /* PME# from D3 (hot) */
-#define  PCI_PM_CAP_PME_D3cold 0x8000  /* PME# from D3 (cold) */
-#define  PCI_PM_CAP_PME_SHIFT  11      /* Start of the PME Mask in PMC */
-#define PCI_PM_CTRL            4       /* PM control and status register */
-#define  PCI_PM_CTRL_STATE_MASK        0x0003  /* Current power state (D0 to 
D3) */
-#define  PCI_PM_CTRL_NO_SOFT_RESET     0x0008  /* No reset for D3hot->D0 */
-#define  PCI_PM_CTRL_PME_ENABLE        0x0100  /* PME pin enable */
-#define  PCI_PM_CTRL_DATA_SEL_MASK     0x1e00  /* Data select (??) */
-#define  PCI_PM_CTRL_DATA_SCALE_MASK   0x6000  /* Data scale (??) */
-#define  PCI_PM_CTRL_PME_STATUS        0x8000  /* PME pin status */
-#define PCI_PM_PPB_EXTENSIONS  6       /* PPB support extensions (??) */
-#define  PCI_PM_PPB_B2_B3      0x40    /* Stop clock when in D3hot (??) */
-#define  PCI_PM_BPCC_ENABLE    0x80    /* Bus power/clock control enable (??) 
*/
-#define PCI_PM_DATA_REGISTER   7       /* (??) */
-#define PCI_PM_SIZEOF          8
-
-/* AGP registers */
-
-#define PCI_AGP_VERSION                2       /* BCD version number */
-#define PCI_AGP_RFU            3       /* Rest of capability flags */
-#define PCI_AGP_STATUS         4       /* Status register */
-#define  PCI_AGP_STATUS_RQ_MASK        0xff000000      /* Maximum number of 
requests - 1 */
-#define  PCI_AGP_STATUS_SBA    0x0200  /* Sideband addressing supported */
-#define  PCI_AGP_STATUS_64BIT  0x0020  /* 64-bit addressing supported */
-#define  PCI_AGP_STATUS_FW     0x0010  /* FW transfers supported */
-#define  PCI_AGP_STATUS_RATE4  0x0004  /* 4x transfer rate supported */
-#define  PCI_AGP_STATUS_RATE2  0x0002  /* 2x transfer rate supported */
-#define  PCI_AGP_STATUS_RATE1  0x0001  /* 1x transfer rate supported */
-#define PCI_AGP_COMMAND                8       /* Control register */
-#define  PCI_AGP_COMMAND_RQ_MASK 0xff000000  /* Master: Maximum number of 
requests */
-#define  PCI_AGP_COMMAND_SBA   0x0200  /* Sideband addressing enabled */
-#define  PCI_AGP_COMMAND_AGP   0x0100  /* Allow processing of AGP transactions 
*/
-#define  PCI_AGP_COMMAND_64BIT 0x0020  /* Allow processing of 64-bit addresses 
*/
-#define  PCI_AGP_COMMAND_FW    0x0010  /* Force FW transfers */
-#define  PCI_AGP_COMMAND_RATE4 0x0004  /* Use 4x rate */
-#define  PCI_AGP_COMMAND_RATE2 0x0002  /* Use 2x rate */
-#define  PCI_AGP_COMMAND_RATE1 0x0001  /* Use 1x rate */
-#define PCI_AGP_SIZEOF         12
-
-/* Vital Product Data */
-
-#define PCI_VPD_ADDR           2       /* Address to access (15 bits!) */
-#define  PCI_VPD_ADDR_MASK     0x7fff  /* Address mask */
-#define  PCI_VPD_ADDR_F                0x8000  /* Write 0, 1 indicates 
completion */
-#define PCI_VPD_DATA           4       /* 32-bits of data returned here */
-
-/* Slot Identification */
-
-#define PCI_SID_ESR            2       /* Expansion Slot Register */
-#define  PCI_SID_ESR_NSLOTS    0x1f    /* Number of expansion slots available 
*/
-#define  PCI_SID_ESR_FIC       0x20    /* First In Chassis Flag */
-#define PCI_SID_CHASSIS_NR     3       /* Chassis Number */
-
-/* Message Signalled Interrupts registers */
-
-#define PCI_MSI_FLAGS          2       /* Various flags */
-#define  PCI_MSI_FLAGS_64BIT   0x80    /* 64-bit addresses allowed */
-#define  PCI_MSI_FLAGS_QSIZE   0x70    /* Message queue size configured */
-#define  PCI_MSI_FLAGS_QMASK   0x0e    /* Maximum queue size available */
-#define  PCI_MSI_FLAGS_ENABLE  0x01    /* MSI feature enabled */
-#define  PCI_MSI_FLAGS_MASKBIT 0x100   /* 64-bit mask bits allowed */
-#define PCI_MSI_RFU            3       /* Rest of capability flags */
-#define PCI_MSI_ADDRESS_LO     4       /* Lower 32 bits */
-#define PCI_MSI_ADDRESS_HI     8       /* Upper 32 bits (if 
PCI_MSI_FLAGS_64BIT set) */
-#define PCI_MSI_DATA_32                8       /* 16 bits of data for 32-bit 
devices */
-#define PCI_MSI_MASK_32                12      /* Mask bits register for 
32-bit devices */
-#define PCI_MSI_DATA_64                12      /* 16 bits of data for 64-bit 
devices */
-#define PCI_MSI_MASK_64                16      /* Mask bits register for 
64-bit devices */
-
-/* MSI-X registers */
-#define PCI_MSIX_FLAGS         2
-#define  PCI_MSIX_FLAGS_QSIZE  0x7FF
-#define  PCI_MSIX_FLAGS_ENABLE (1 << 15)
-#define  PCI_MSIX_FLAGS_MASKALL        (1 << 14)
-#define PCI_MSIX_TABLE         4
-#define PCI_MSIX_PBA           8
-#define  PCI_MSIX_FLAGS_BIRMASK        (7 << 0)
-
-/* MSI-X entry's format */
-#define PCI_MSIX_ENTRY_SIZE            16
-#define  PCI_MSIX_ENTRY_LOWER_ADDR     0
-#define  PCI_MSIX_ENTRY_UPPER_ADDR     4
-#define  PCI_MSIX_ENTRY_DATA           8
-#define  PCI_MSIX_ENTRY_VECTOR_CTRL    12
-#define   PCI_MSIX_ENTRY_CTRL_MASKBIT  1
-
-/* CompactPCI Hotswap Register */
-
-#define PCI_CHSWP_CSR          2       /* Control and Status Register */
-#define  PCI_CHSWP_DHA         0x01    /* Device Hiding Arm */
-#define  PCI_CHSWP_EIM         0x02    /* ENUM# Signal Mask */
-#define  PCI_CHSWP_PIE         0x04    /* Pending Insert or Extract */
-#define  PCI_CHSWP_LOO         0x08    /* LED On / Off */
-#define  PCI_CHSWP_PI          0x30    /* Programming Interface */
-#define  PCI_CHSWP_EXT         0x40    /* ENUM# status - extraction */
-#define  PCI_CHSWP_INS         0x80    /* ENUM# status - insertion */
-
-/* PCI Advanced Feature registers */
-
-#define PCI_AF_LENGTH          2
-#define PCI_AF_CAP             3
-#define  PCI_AF_CAP_TP         0x01
-#define  PCI_AF_CAP_FLR                0x02
-#define PCI_AF_CTRL            4
-#define  PCI_AF_CTRL_FLR       0x01
-#define PCI_AF_STATUS          5
-#define  PCI_AF_STATUS_TP      0x01
-
-/* PCI-X registers */
-
-#define PCI_X_CMD              2       /* Modes & Features */
-#define  PCI_X_CMD_DPERR_E     0x0001  /* Data Parity Error Recovery Enable */
-#define  PCI_X_CMD_ERO         0x0002  /* Enable Relaxed Ordering */
-#define  PCI_X_CMD_READ_512    0x0000  /* 512 byte maximum read byte count */
-#define  PCI_X_CMD_READ_1K     0x0004  /* 1Kbyte maximum read byte count */
-#define  PCI_X_CMD_READ_2K     0x0008  /* 2Kbyte maximum read byte count */
-#define  PCI_X_CMD_READ_4K     0x000c  /* 4Kbyte maximum read byte count */
-#define  PCI_X_CMD_MAX_READ    0x000c  /* Max Memory Read Byte Count */
-                               /* Max # of outstanding split transactions */
-#define  PCI_X_CMD_SPLIT_1     0x0000  /* Max 1 */
-#define  PCI_X_CMD_SPLIT_2     0x0010  /* Max 2 */
-#define  PCI_X_CMD_SPLIT_3     0x0020  /* Max 3 */
-#define  PCI_X_CMD_SPLIT_4     0x0030  /* Max 4 */
-#define  PCI_X_CMD_SPLIT_8     0x0040  /* Max 8 */
-#define  PCI_X_CMD_SPLIT_12    0x0050  /* Max 12 */
-#define  PCI_X_CMD_SPLIT_16    0x0060  /* Max 16 */
-#define  PCI_X_CMD_SPLIT_32    0x0070  /* Max 32 */
-#define  PCI_X_CMD_MAX_SPLIT   0x0070  /* Max Outstanding Split Transactions */
-#define  PCI_X_CMD_VERSION(x)  (((x) >> 12) & 3) /* Version */
-#define PCI_X_STATUS           4       /* PCI-X capabilities */
-#define  PCI_X_STATUS_DEVFN    0x000000ff      /* A copy of devfn */
-#define  PCI_X_STATUS_BUS      0x0000ff00      /* A copy of bus nr */
-#define  PCI_X_STATUS_64BIT    0x00010000      /* 64-bit device */
-#define  PCI_X_STATUS_133MHZ   0x00020000      /* 133 MHz capable */
-#define  PCI_X_STATUS_SPL_DISC 0x00040000      /* Split Completion Discarded */
-#define  PCI_X_STATUS_UNX_SPL  0x00080000      /* Unexpected Split Completion 
*/
-#define  PCI_X_STATUS_COMPLEX  0x00100000      /* Device Complexity */
-#define  PCI_X_STATUS_MAX_READ 0x00600000      /* Designed Max Memory Read 
Count */
-#define  PCI_X_STATUS_MAX_SPLIT        0x03800000      /* Designed Max 
Outstanding Split Transactions */
-#define  PCI_X_STATUS_MAX_CUM  0x1c000000      /* Designed Max Cumulative Read 
Size */
-#define  PCI_X_STATUS_SPL_ERR  0x20000000      /* Rcvd Split Completion Error 
Msg */
-#define  PCI_X_STATUS_266MHZ   0x40000000      /* 266 MHz capable */
-#define  PCI_X_STATUS_533MHZ   0x80000000      /* 533 MHz capable */
-
-/* PCI Bridge Subsystem ID registers */
-
-#define PCI_SSVID_VENDOR_ID     4      /* PCI-Bridge subsystem vendor id 
register */
-#define PCI_SSVID_DEVICE_ID     6      /* PCI-Bridge subsystem device id 
register */
-
-/* PCI Express capability registers */
-
-#define PCI_EXP_FLAGS          2       /* Capabilities register */
-#define PCI_EXP_FLAGS_VERS     0x000f  /* Capability version */
-#define PCI_EXP_FLAGS_TYPE     0x00f0  /* Device/Port type */
-#define  PCI_EXP_TYPE_ENDPOINT 0x0     /* Express Endpoint */
-#define  PCI_EXP_TYPE_LEG_END  0x1     /* Legacy Endpoint */
-#define  PCI_EXP_TYPE_ROOT_PORT 0x4    /* Root Port */
-#define  PCI_EXP_TYPE_UPSTREAM 0x5     /* Upstream Port */
-#define  PCI_EXP_TYPE_DOWNSTREAM 0x6   /* Downstream Port */
-#define  PCI_EXP_TYPE_PCI_BRIDGE 0x7   /* PCI/PCI-X Bridge */
-#define  PCI_EXP_TYPE_PCIE_BRIDGE 0x8   /* PCI/PCI-X to PCIE Bridge */
-#define  PCI_EXP_TYPE_RC_END   0x9     /* Root Complex Integrated Endpoint */
-#define  PCI_EXP_TYPE_RC_EC     0xa     /* Root Complex Event Collector */
-#define PCI_EXP_FLAGS_SLOT     0x0100  /* Slot implemented */
-#define PCI_EXP_FLAGS_IRQ      0x3e00  /* Interrupt message number */
-#define PCI_EXP_DEVCAP         4       /* Device capabilities */
-#define  PCI_EXP_DEVCAP_PAYLOAD        0x07    /* Max_Payload_Size */
-#define  PCI_EXP_DEVCAP_PHANTOM        0x18    /* Phantom functions */
-#define  PCI_EXP_DEVCAP_EXT_TAG        0x20    /* Extended tags */
-#define  PCI_EXP_DEVCAP_L0S    0x1c0   /* L0s Acceptable Latency */
-#define  PCI_EXP_DEVCAP_L1     0xe00   /* L1 Acceptable Latency */
-#define  PCI_EXP_DEVCAP_ATN_BUT        0x1000  /* Attention Button Present */
-#define  PCI_EXP_DEVCAP_ATN_IND        0x2000  /* Attention Indicator Present 
*/
-#define  PCI_EXP_DEVCAP_PWR_IND        0x4000  /* Power Indicator Present */
-#define  PCI_EXP_DEVCAP_RBER   0x8000  /* Role-Based Error Reporting */
-#define  PCI_EXP_DEVCAP_PWR_VAL        0x3fc0000 /* Slot Power Limit Value */
-#define  PCI_EXP_DEVCAP_PWR_SCL        0xc000000 /* Slot Power Limit Scale */
-#define  PCI_EXP_DEVCAP_FLR     0x10000000 /* Function Level Reset */
-#define PCI_EXP_DEVCTL         8       /* Device Control */
-#define  PCI_EXP_DEVCTL_CERE   0x0001  /* Correctable Error Reporting En. */
-#define  PCI_EXP_DEVCTL_NFERE  0x0002  /* Non-Fatal Error Reporting Enable */
-#define  PCI_EXP_DEVCTL_FERE   0x0004  /* Fatal Error Reporting Enable */
-#define  PCI_EXP_DEVCTL_URRE   0x0008  /* Unsupported Request Reporting En. */
-#define  PCI_EXP_DEVCTL_RELAX_EN 0x0010 /* Enable relaxed ordering */
-#define  PCI_EXP_DEVCTL_PAYLOAD        0x00e0  /* Max_Payload_Size */
-#define  PCI_EXP_DEVCTL_EXT_TAG        0x0100  /* Extended Tag Field Enable */
-#define  PCI_EXP_DEVCTL_PHANTOM        0x0200  /* Phantom Functions Enable */
-#define  PCI_EXP_DEVCTL_AUX_PME        0x0400  /* Auxiliary Power PM Enable */
-#define  PCI_EXP_DEVCTL_NOSNOOP_EN 0x0800  /* Enable No Snoop */
-#define  PCI_EXP_DEVCTL_READRQ 0x7000  /* Max_Read_Request_Size */
-#define  PCI_EXP_DEVCTL_BCR_FLR 0x8000  /* Bridge Configuration Retry / FLR */
-#define PCI_EXP_DEVSTA         10      /* Device Status */
-#define  PCI_EXP_DEVSTA_CED    0x01    /* Correctable Error Detected */
-#define  PCI_EXP_DEVSTA_NFED   0x02    /* Non-Fatal Error Detected */
-#define  PCI_EXP_DEVSTA_FED    0x04    /* Fatal Error Detected */
-#define  PCI_EXP_DEVSTA_URD    0x08    /* Unsupported Request Detected */
-#define  PCI_EXP_DEVSTA_AUXPD  0x10    /* AUX Power Detected */
-#define  PCI_EXP_DEVSTA_TRPND  0x20    /* Transactions Pending */
-#define PCI_EXP_LNKCAP         12      /* Link Capabilities */
-#define  PCI_EXP_LNKCAP_SLS    0x0000000f /* Supported Link Speeds */
-#define  PCI_EXP_LNKCAP_MLW    0x000003f0 /* Maximum Link Width */
-#define  PCI_EXP_LNKCAP_ASPMS  0x00000c00 /* ASPM Support */
-#define  PCI_EXP_LNKCAP_L0SEL  0x00007000 /* L0s Exit Latency */
-#define  PCI_EXP_LNKCAP_L1EL   0x00038000 /* L1 Exit Latency */
-#define  PCI_EXP_LNKCAP_CLKPM  0x00040000 /* L1 Clock Power Management */
-#define  PCI_EXP_LNKCAP_SDERC  0x00080000 /* Surprise Down Error Reporting 
Capable */
-#define  PCI_EXP_LNKCAP_DLLLARC        0x00100000 /* Data Link Layer Link 
Active Reporting Capable */
-#define  PCI_EXP_LNKCAP_LBNC   0x00200000 /* Link Bandwidth Notification 
Capability */
-#define  PCI_EXP_LNKCAP_PN     0xff000000 /* Port Number */
-#define PCI_EXP_LNKCTL         16      /* Link Control */
-#define  PCI_EXP_LNKCTL_ASPMC  0x0003  /* ASPM Control */
-#define  PCI_EXP_LNKCTL_RCB    0x0008  /* Read Completion Boundary */
-#define  PCI_EXP_LNKCTL_LD     0x0010  /* Link Disable */
-#define  PCI_EXP_LNKCTL_RL     0x0020  /* Retrain Link */
-#define  PCI_EXP_LNKCTL_CCC    0x0040  /* Common Clock Configuration */
-#define  PCI_EXP_LNKCTL_ES     0x0080  /* Extended Synch */
-#define  PCI_EXP_LNKCTL_CLKREQ_EN 0x100        /* Enable clkreq */
-#define  PCI_EXP_LNKCTL_HAWD   0x0200  /* Hardware Autonomous Width Disable */
-#define  PCI_EXP_LNKCTL_LBMIE  0x0400  /* Link Bandwidth Management Interrupt 
Enable */
-#define  PCI_EXP_LNKCTL_LABIE  0x0800  /* Lnk Autonomous Bandwidth Interrupt 
Enable */
-#define PCI_EXP_LNKSTA         18      /* Link Status */
-#define  PCI_EXP_LNKSTA_CLS    0x000f  /* Current Link Speed */
-#define  PCI_EXP_LNKSTA_CLS_2_5GB 0x01 /* Current Link Speed 2.5GT/s */
-#define  PCI_EXP_LNKSTA_CLS_5_0GB 0x02 /* Current Link Speed 5.0GT/s */
-#define  PCI_EXP_LNKSTA_NLW    0x03f0  /* Nogotiated Link Width */
-#define  PCI_EXP_LNKSTA_NLW_SHIFT 4    /* start of NLW mask in link status */
-#define  PCI_EXP_LNKSTA_LT     0x0800  /* Link Training */
-#define  PCI_EXP_LNKSTA_SLC    0x1000  /* Slot Clock Configuration */
-#define  PCI_EXP_LNKSTA_DLLLA  0x2000  /* Data Link Layer Link Active */
-#define  PCI_EXP_LNKSTA_LBMS   0x4000  /* Link Bandwidth Management Status */
-#define  PCI_EXP_LNKSTA_LABS   0x8000  /* Link Autonomous Bandwidth Status */
-#define PCI_EXP_SLTCAP         20      /* Slot Capabilities */
-#define  PCI_EXP_SLTCAP_ABP    0x00000001 /* Attention Button Present */
-#define  PCI_EXP_SLTCAP_PCP    0x00000002 /* Power Controller Present */
-#define  PCI_EXP_SLTCAP_MRLSP  0x00000004 /* MRL Sensor Present */
-#define  PCI_EXP_SLTCAP_AIP    0x00000008 /* Attention Indicator Present */
-#define  PCI_EXP_SLTCAP_PIP    0x00000010 /* Power Indicator Present */
-#define  PCI_EXP_SLTCAP_HPS    0x00000020 /* Hot-Plug Surprise */
-#define  PCI_EXP_SLTCAP_HPC    0x00000040 /* Hot-Plug Capable */
-#define  PCI_EXP_SLTCAP_SPLV   0x00007f80 /* Slot Power Limit Value */
-#define  PCI_EXP_SLTCAP_SPLS   0x00018000 /* Slot Power Limit Scale */
-#define  PCI_EXP_SLTCAP_EIP    0x00020000 /* Electromechanical Interlock 
Present */
-#define  PCI_EXP_SLTCAP_NCCS   0x00040000 /* No Command Completed Support */
-#define  PCI_EXP_SLTCAP_PSN    0xfff80000 /* Physical Slot Number */
-#define PCI_EXP_SLTCTL         24      /* Slot Control */
-#define  PCI_EXP_SLTCTL_ABPE   0x0001  /* Attention Button Pressed Enable */
-#define  PCI_EXP_SLTCTL_PFDE   0x0002  /* Power Fault Detected Enable */
-#define  PCI_EXP_SLTCTL_MRLSCE 0x0004  /* MRL Sensor Changed Enable */
-#define  PCI_EXP_SLTCTL_PDCE   0x0008  /* Presence Detect Changed Enable */
-#define  PCI_EXP_SLTCTL_CCIE   0x0010  /* Command Completed Interrupt Enable */
-#define  PCI_EXP_SLTCTL_HPIE   0x0020  /* Hot-Plug Interrupt Enable */
-#define  PCI_EXP_SLTCTL_AIC    0x00c0  /* Attention Indicator Control */
-#define  PCI_EXP_SLTCTL_PIC    0x0300  /* Power Indicator Control */
-#define  PCI_EXP_SLTCTL_PCC    0x0400  /* Power Controller Control */
-#define  PCI_EXP_SLTCTL_EIC    0x0800  /* Electromechanical Interlock Control 
*/
-#define  PCI_EXP_SLTCTL_DLLSCE 0x1000  /* Data Link Layer State Changed Enable 
*/
-#define PCI_EXP_SLTSTA         26      /* Slot Status */
-#define  PCI_EXP_SLTSTA_ABP    0x0001  /* Attention Button Pressed */
-#define  PCI_EXP_SLTSTA_PFD    0x0002  /* Power Fault Detected */
-#define  PCI_EXP_SLTSTA_MRLSC  0x0004  /* MRL Sensor Changed */
-#define  PCI_EXP_SLTSTA_PDC    0x0008  /* Presence Detect Changed */
-#define  PCI_EXP_SLTSTA_CC     0x0010  /* Command Completed */
-#define  PCI_EXP_SLTSTA_MRLSS  0x0020  /* MRL Sensor State */
-#define  PCI_EXP_SLTSTA_PDS    0x0040  /* Presence Detect State */
-#define  PCI_EXP_SLTSTA_EIS    0x0080  /* Electromechanical Interlock Status */
-#define  PCI_EXP_SLTSTA_DLLSC  0x0100  /* Data Link Layer State Changed */
-#define PCI_EXP_RTCTL          28      /* Root Control */
-#define  PCI_EXP_RTCTL_SECEE   0x01    /* System Error on Correctable Error */
-#define  PCI_EXP_RTCTL_SENFEE  0x02    /* System Error on Non-Fatal Error */
-#define  PCI_EXP_RTCTL_SEFEE   0x04    /* System Error on Fatal Error */
-#define  PCI_EXP_RTCTL_PMEIE   0x08    /* PME Interrupt Enable */
-#define  PCI_EXP_RTCTL_CRSSVE  0x10    /* CRS Software Visibility Enable */
-#define PCI_EXP_RTCAP          30      /* Root Capabilities */
-#define PCI_EXP_RTSTA          32      /* Root Status */
-#define PCI_EXP_RTSTA_PME      0x10000 /* PME status */
-#define PCI_EXP_RTSTA_PENDING  0x20000 /* PME pending */
-#define PCI_EXP_DEVCAP2                36      /* Device Capabilities 2 */
-#define  PCI_EXP_DEVCAP2_ARI   0x20    /* Alternative Routing-ID */
-#define  PCI_EXP_DEVCAP2_LTR   0x800   /* Latency tolerance reporting */
-#define  PCI_EXP_OBFF_MASK     0xc0000 /* OBFF support mechanism */
-#define  PCI_EXP_OBFF_MSG      0x40000 /* New message signaling */
-#define  PCI_EXP_OBFF_WAKE     0x80000 /* Re-use WAKE# for OBFF */
-#define PCI_EXP_DEVCTL2                40      /* Device Control 2 */
-#define  PCI_EXP_DEVCTL2_ARI   0x20    /* Alternative Routing-ID */
-#define  PCI_EXP_IDO_REQ_EN    0x100   /* ID-based ordering request enable */
-#define  PCI_EXP_IDO_CMP_EN    0x200   /* ID-based ordering completion enable 
*/
-#define  PCI_EXP_LTR_EN                0x400   /* Latency tolerance reporting 
*/
-#define  PCI_EXP_OBFF_MSGA_EN  0x2000  /* OBFF enable with Message type A */
-#define  PCI_EXP_OBFF_MSGB_EN  0x4000  /* OBFF enable with Message type B */
-#define  PCI_EXP_OBFF_WAKE_EN  0x6000  /* OBFF using WAKE# signaling */
-#define PCI_EXP_LNKCTL2                48      /* Link Control 2 */
-#define PCI_EXP_SLTCTL2                56      /* Slot Control 2 */
-
-/* Extended Capabilities (PCI-X 2.0 and Express) */
-#define PCI_EXT_CAP_ID(header)         (header & 0x0000ffff)
-#define PCI_EXT_CAP_VER(header)                ((header >> 16) & 0xf)
-#define PCI_EXT_CAP_NEXT(header)       ((header >> 20) & 0xffc)
-
-#define PCI_EXT_CAP_ID_ERR     1
-#define PCI_EXT_CAP_ID_VC      2
-#define PCI_EXT_CAP_ID_DSN     3
-#define PCI_EXT_CAP_ID_PWR     4
-#define PCI_EXT_CAP_ID_VNDR    11
-#define PCI_EXT_CAP_ID_ACS     13
-#define PCI_EXT_CAP_ID_ARI     14
-#define PCI_EXT_CAP_ID_ATS     15
-#define PCI_EXT_CAP_ID_SRIOV   16
-#define PCI_EXT_CAP_ID_LTR     24
-
-/* Advanced Error Reporting */
-#define PCI_ERR_UNCOR_STATUS   4       /* Uncorrectable Error Status */
-#define  PCI_ERR_UNC_TRAIN     0x00000001      /* Training */
-#define  PCI_ERR_UNC_DLP       0x00000010      /* Data Link Protocol */
-#define  PCI_ERR_UNC_POISON_TLP        0x00001000      /* Poisoned TLP */
-#define  PCI_ERR_UNC_FCP       0x00002000      /* Flow Control Protocol */
-#define  PCI_ERR_UNC_COMP_TIME 0x00004000      /* Completion Timeout */
-#define  PCI_ERR_UNC_COMP_ABORT        0x00008000      /* Completer Abort */
-#define  PCI_ERR_UNC_UNX_COMP  0x00010000      /* Unexpected Completion */
-#define  PCI_ERR_UNC_RX_OVER   0x00020000      /* Receiver Overflow */
-#define  PCI_ERR_UNC_MALF_TLP  0x00040000      /* Malformed TLP */
-#define  PCI_ERR_UNC_ECRC      0x00080000      /* ECRC Error Status */
-#define  PCI_ERR_UNC_UNSUP     0x00100000      /* Unsupported Request */
-#define PCI_ERR_UNCOR_MASK     8       /* Uncorrectable Error Mask */
-       /* Same bits as above */
-#define PCI_ERR_UNCOR_SEVER    12      /* Uncorrectable Error Severity */
-       /* Same bits as above */
-#define PCI_ERR_COR_STATUS     16      /* Correctable Error Status */
-#define  PCI_ERR_COR_RCVR      0x00000001      /* Receiver Error Status */
-#define  PCI_ERR_COR_BAD_TLP   0x00000040      /* Bad TLP Status */
-#define  PCI_ERR_COR_BAD_DLLP  0x00000080      /* Bad DLLP Status */
-#define  PCI_ERR_COR_REP_ROLL  0x00000100      /* REPLAY_NUM Rollover */
-#define  PCI_ERR_COR_REP_TIMER 0x00001000      /* Replay Timer Timeout */
-#define PCI_ERR_COR_MASK       20      /* Correctable Error Mask */
-       /* Same bits as above */
-#define PCI_ERR_CAP            24      /* Advanced Error Capabilities */
-#define  PCI_ERR_CAP_FEP(x)    ((x) & 31)      /* First Error Pointer */
-#define  PCI_ERR_CAP_ECRC_GENC 0x00000020      /* ECRC Generation Capable */
-#define  PCI_ERR_CAP_ECRC_GENE 0x00000040      /* ECRC Generation Enable */
-#define  PCI_ERR_CAP_ECRC_CHKC 0x00000080      /* ECRC Check Capable */
-#define  PCI_ERR_CAP_ECRC_CHKE 0x00000100      /* ECRC Check Enable */
-#define PCI_ERR_HEADER_LOG     28      /* Header Log Register (16 bytes) */
-#define PCI_ERR_ROOT_COMMAND   44      /* Root Error Command */
-/* Correctable Err Reporting Enable */
-#define PCI_ERR_ROOT_CMD_COR_EN                0x00000001
-/* Non-fatal Err Reporting Enable */
-#define PCI_ERR_ROOT_CMD_NONFATAL_EN   0x00000002
-/* Fatal Err Reporting Enable */
-#define PCI_ERR_ROOT_CMD_FATAL_EN      0x00000004
-#define PCI_ERR_ROOT_STATUS    48
-#define PCI_ERR_ROOT_COR_RCV           0x00000001      /* ERR_COR Received */
-/* Multi ERR_COR Received */
-#define PCI_ERR_ROOT_MULTI_COR_RCV     0x00000002
-/* ERR_FATAL/NONFATAL Recevied */
-#define PCI_ERR_ROOT_UNCOR_RCV         0x00000004
-/* Multi ERR_FATAL/NONFATAL Recevied */
-#define PCI_ERR_ROOT_MULTI_UNCOR_RCV   0x00000008
-#define PCI_ERR_ROOT_FIRST_FATAL       0x00000010      /* First Fatal */
-#define PCI_ERR_ROOT_NONFATAL_RCV      0x00000020      /* Non-Fatal Received */
-#define PCI_ERR_ROOT_FATAL_RCV         0x00000040      /* Fatal Received */
-#define PCI_ERR_ROOT_ERR_SRC   52      /* Error Source Identification */
-
-/* Virtual Channel */
-#define PCI_VC_PORT_REG1       4
-#define PCI_VC_PORT_REG2       8
-#define PCI_VC_PORT_CTRL       12
-#define PCI_VC_PORT_STATUS     14
-#define PCI_VC_RES_CAP         16
-#define PCI_VC_RES_CTRL                20
-#define PCI_VC_RES_STATUS      26
-
-/* Power Budgeting */
-#define PCI_PWR_DSR            4       /* Data Select Register */
-#define PCI_PWR_DATA           8       /* Data Register */
-#define  PCI_PWR_DATA_BASE(x)  ((x) & 0xff)        /* Base Power */
-#define  PCI_PWR_DATA_SCALE(x) (((x) >> 8) & 3)    /* Data Scale */
-#define  PCI_PWR_DATA_PM_SUB(x)        (((x) >> 10) & 7)   /* PM Sub State */
-#define  PCI_PWR_DATA_PM_STATE(x) (((x) >> 13) & 3) /* PM State */
-#define  PCI_PWR_DATA_TYPE(x)  (((x) >> 15) & 7)   /* Type */
-#define  PCI_PWR_DATA_RAIL(x)  (((x) >> 18) & 7)   /* Power Rail */
-#define PCI_PWR_CAP            12      /* Capability */
-#define  PCI_PWR_CAP_BUDGET(x) ((x) & 1)       /* Included in system budget */
-
-/*
- * Hypertransport sub capability types
- *
- * Unfortunately there are both 3 bit and 5 bit capability types defined
- * in the HT spec, catering for that is a little messy. You probably don't
- * want to use these directly, just use pci_find_ht_capability() and it
- * will do the right thing for you.
- */
-#define HT_3BIT_CAP_MASK       0xE0
-#define HT_CAPTYPE_SLAVE       0x00    /* Slave/Primary link configuration */
-#define HT_CAPTYPE_HOST                0x20    /* Host/Secondary link 
configuration */
-
-#define HT_5BIT_CAP_MASK       0xF8
-#define HT_CAPTYPE_IRQ         0x80    /* IRQ Configuration */
-#define HT_CAPTYPE_REMAPPING_40        0xA0    /* 40 bit address remapping */
-#define HT_CAPTYPE_REMAPPING_64 0xA2   /* 64 bit address remapping */
-#define HT_CAPTYPE_UNITID_CLUMP        0x90    /* Unit ID clumping */
-#define HT_CAPTYPE_EXTCONF     0x98    /* Extended Configuration Space Access 
*/
-#define HT_CAPTYPE_MSI_MAPPING 0xA8    /* MSI Mapping Capability */
-#define  HT_MSI_FLAGS          0x02            /* Offset to flags */
-#define  HT_MSI_FLAGS_ENABLE   0x1             /* Mapping enable */
-#define  HT_MSI_FLAGS_FIXED    0x2             /* Fixed mapping only */
-#define  HT_MSI_FIXED_ADDR     0x00000000FEE00000ULL   /* Fixed addr */
-#define  HT_MSI_ADDR_LO                0x04            /* Offset to low addr 
bits */
-#define  HT_MSI_ADDR_LO_MASK   0xFFF00000      /* Low address bit mask */
-#define  HT_MSI_ADDR_HI                0x08            /* Offset to high addr 
bits */
-#define HT_CAPTYPE_DIRECT_ROUTE        0xB0    /* Direct routing configuration 
*/
-#define HT_CAPTYPE_VCSET       0xB8    /* Virtual Channel configuration */
-#define HT_CAPTYPE_ERROR_RETRY 0xC0    /* Retry on error configuration */
-#define HT_CAPTYPE_GEN3                0xD0    /* Generation 3 hypertransport 
configuration */
-#define HT_CAPTYPE_PM          0xE0    /* Hypertransport powermanagement 
configuration */
-
-/* Alternative Routing-ID Interpretation */
-#define PCI_ARI_CAP            0x04    /* ARI Capability Register */
-#define  PCI_ARI_CAP_MFVC      0x0001  /* MFVC Function Groups Capability */
-#define  PCI_ARI_CAP_ACS       0x0002  /* ACS Function Groups Capability */
-#define  PCI_ARI_CAP_NFN(x)    (((x) >> 8) & 0xff) /* Next Function Number */
-#define PCI_ARI_CTRL           0x06    /* ARI Control Register */
-#define  PCI_ARI_CTRL_MFVC     0x0001  /* MFVC Function Groups Enable */
-#define  PCI_ARI_CTRL_ACS      0x0002  /* ACS Function Groups Enable */
-#define  PCI_ARI_CTRL_FG(x)    (((x) >> 4) & 7) /* Function Group */
-
-/* Address Translation Service */
-#define PCI_ATS_CAP            0x04    /* ATS Capability Register */
-#define  PCI_ATS_CAP_QDEP(x)   ((x) & 0x1f)    /* Invalidate Queue Depth */
-#define  PCI_ATS_MAX_QDEP      32      /* Max Invalidate Queue Depth */
-#define PCI_ATS_CTRL           0x06    /* ATS Control Register */
-#define  PCI_ATS_CTRL_ENABLE   0x8000  /* ATS Enable */
-#define  PCI_ATS_CTRL_STU(x)   ((x) & 0x1f)    /* Smallest Translation Unit */
-#define  PCI_ATS_MIN_STU       12      /* shift of minimum STU block */
-
-/* Single Root I/O Virtualization */
-#define PCI_SRIOV_CAP          0x04    /* SR-IOV Capabilities */
-#define  PCI_SRIOV_CAP_VFM     0x01    /* VF Migration Capable */
-#define  PCI_SRIOV_CAP_INTR(x) ((x) >> 21) /* Interrupt Message Number */
-#define PCI_SRIOV_CTRL         0x08    /* SR-IOV Control */
-#define  PCI_SRIOV_CTRL_VFE    0x01    /* VF Enable */
-#define  PCI_SRIOV_CTRL_VFM    0x02    /* VF Migration Enable */
-#define  PCI_SRIOV_CTRL_INTR   0x04    /* VF Migration Interrupt Enable */
-#define  PCI_SRIOV_CTRL_MSE    0x08    /* VF Memory Space Enable */
-#define  PCI_SRIOV_CTRL_ARI    0x10    /* ARI Capable Hierarchy */
-#define PCI_SRIOV_STATUS       0x0a    /* SR-IOV Status */
-#define  PCI_SRIOV_STATUS_VFM  0x01    /* VF Migration Status */
-#define PCI_SRIOV_INITIAL_VF   0x0c    /* Initial VFs */
-#define PCI_SRIOV_TOTAL_VF     0x0e    /* Total VFs */
-#define PCI_SRIOV_NUM_VF       0x10    /* Number of VFs */
-#define PCI_SRIOV_FUNC_LINK    0x12    /* Function Dependency Link */
-#define PCI_SRIOV_VF_OFFSET    0x14    /* First VF Offset */
-#define PCI_SRIOV_VF_STRIDE    0x16    /* Following VF Stride */
-#define PCI_SRIOV_VF_DID       0x1a    /* VF Device ID */
-#define PCI_SRIOV_SUP_PGSIZE   0x1c    /* Supported Page Sizes */
-#define PCI_SRIOV_SYS_PGSIZE   0x20    /* System Page Size */
-#define PCI_SRIOV_BAR          0x24    /* VF BAR0 */
-#define  PCI_SRIOV_NUM_BARS    6       /* Number of VF BARs */
-#define PCI_SRIOV_VFM          0x3c    /* VF Migration State Array Offset*/
-#define  PCI_SRIOV_VFM_BIR(x)  ((x) & 7)       /* State BIR */
-#define  PCI_SRIOV_VFM_OFFSET(x) ((x) & ~7)    /* State Offset */
-#define  PCI_SRIOV_VFM_UA      0x0     /* Inactive.Unavailable */
-#define  PCI_SRIOV_VFM_MI      0x1     /* Dormant.MigrateIn */
-#define  PCI_SRIOV_VFM_MO      0x2     /* Active.MigrateOut */
-#define  PCI_SRIOV_VFM_AV      0x3     /* Active.Available */
-
-#define PCI_LTR_MAX_SNOOP_LAT  0x4
-#define PCI_LTR_MAX_NOSNOOP_LAT        0x6
-#define  PCI_LTR_VALUE_MASK    0x000003ff
-#define  PCI_LTR_SCALE_MASK    0x00001c00
-#define  PCI_LTR_SCALE_SHIFT   10
-
-/* Access Control Service */
-#define PCI_ACS_CAP            0x04    /* ACS Capability Register */
-#define  PCI_ACS_SV            0x01    /* Source Validation */
-#define  PCI_ACS_TB            0x02    /* Translation Blocking */
-#define  PCI_ACS_RR            0x04    /* P2P Request Redirect */
-#define  PCI_ACS_CR            0x08    /* P2P Completion Redirect */
-#define  PCI_ACS_UF            0x10    /* Upstream Forwarding */
-#define  PCI_ACS_EC            0x20    /* P2P Egress Control */
-#define  PCI_ACS_DT            0x40    /* Direct Translated P2P */
-#define PCI_ACS_CTRL           0x06    /* ACS Control Register */
-#define PCI_ACS_EGRESS_CTL_V   0x08    /* ACS Egress Control Vector */
-
-#endif /* LINUX_PCI_REGS_H */
diff --git a/hw/pcie.c b/hw/pcie.c
deleted file mode 100644
index 7c92f19..0000000
--- a/hw/pcie.c
+++ /dev/null
@@ -1,555 +0,0 @@
-/*
- * pcie.c
- *
- * Copyright (c) 2010 Isaku Yamahata <yamahata at valinux co jp>
- *                    VA Linux Systems Japan K.K.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, see <http://www.gnu.org/licenses/>.
- */
-
-#include "qemu-common.h"
-#include "pci_bridge.h"
-#include "pcie.h"
-#include "msix.h"
-#include "msi.h"
-#include "pci_internals.h"
-#include "pcie_regs.h"
-#include "range.h"
-
-//#define DEBUG_PCIE
-#ifdef DEBUG_PCIE
-# define PCIE_DPRINTF(fmt, ...)                                         \
-    fprintf(stderr, "%s:%d " fmt, __func__, __LINE__, ## __VA_ARGS__)
-#else
-# define PCIE_DPRINTF(fmt, ...) do {} while (0)
-#endif
-#define PCIE_DEV_PRINTF(dev, fmt, ...)                                  \
-    PCIE_DPRINTF("%s:%x "fmt, (dev)->name, (dev)->devfn, ## __VA_ARGS__)
-
-
-/***************************************************************************
- * pci express capability helper functions
- */
-int pcie_cap_init(PCIDevice *dev, uint8_t offset, uint8_t type, uint8_t port)
-{
-    int pos;
-    uint8_t *exp_cap;
-
-    assert(pci_is_express(dev));
-
-    pos = pci_add_capability(dev, PCI_CAP_ID_EXP, offset,
-                                 PCI_EXP_VER2_SIZEOF);
-    if (pos < 0) {
-        return pos;
-    }
-    dev->exp.exp_cap = pos;
-    exp_cap = dev->config + pos;
-
-    /* capability register
-       interrupt message number defaults to 0 */
-    pci_set_word(exp_cap + PCI_EXP_FLAGS,
-                 ((type << PCI_EXP_FLAGS_TYPE_SHIFT) & PCI_EXP_FLAGS_TYPE) |
-                 PCI_EXP_FLAGS_VER2);
-
-    /* device capability register
-     * table 7-12:
-     * roll based error reporting bit must be set by all
-     * Functions conforming to the ECN, PCI Express Base
-     * Specification, Revision 1.1., or subsequent PCI Express Base
-     * Specification revisions.
-     */
-    pci_set_long(exp_cap + PCI_EXP_DEVCAP, PCI_EXP_DEVCAP_RBER);
-
-    pci_set_long(exp_cap + PCI_EXP_LNKCAP,
-                 (port << PCI_EXP_LNKCAP_PN_SHIFT) |
-                 PCI_EXP_LNKCAP_ASPMS_0S |
-                 PCI_EXP_LNK_MLW_1 |
-                 PCI_EXP_LNK_LS_25);
-
-    pci_set_word(exp_cap + PCI_EXP_LNKSTA,
-                 PCI_EXP_LNK_MLW_1 | PCI_EXP_LNK_LS_25);
-
-    pci_set_long(exp_cap + PCI_EXP_DEVCAP2,
-                 PCI_EXP_DEVCAP2_EFF | PCI_EXP_DEVCAP2_EETLPP);
-
-    pci_set_word(dev->wmask + pos, PCI_EXP_DEVCTL2_EETLPPB);
-    return pos;
-}
-
-void pcie_cap_exit(PCIDevice *dev)
-{
-    pci_del_capability(dev, PCI_CAP_ID_EXP, PCI_EXP_VER2_SIZEOF);
-}
-
-uint8_t pcie_cap_get_type(const PCIDevice *dev)
-{
-    uint32_t pos = dev->exp.exp_cap;
-    assert(pos > 0);
-    return (pci_get_word(dev->config + pos + PCI_EXP_FLAGS) &
-            PCI_EXP_FLAGS_TYPE) >> PCI_EXP_FLAGS_TYPE_SHIFT;
-}
-
-/* MSI/MSI-X */
-/* pci express interrupt message number */
-/* 7.8.2 PCI Express Capabilities Register: Interrupt Message Number */
-void pcie_cap_flags_set_vector(PCIDevice *dev, uint8_t vector)
-{
-    uint8_t *exp_cap = dev->config + dev->exp.exp_cap;
-    assert(vector < 32);
-    pci_word_test_and_clear_mask(exp_cap + PCI_EXP_FLAGS, PCI_EXP_FLAGS_IRQ);
-    pci_word_test_and_set_mask(exp_cap + PCI_EXP_FLAGS,
-                               vector << PCI_EXP_FLAGS_IRQ_SHIFT);
-}
-
-uint8_t pcie_cap_flags_get_vector(PCIDevice *dev)
-{
-    return (pci_get_word(dev->config + dev->exp.exp_cap + PCI_EXP_FLAGS) &
-            PCI_EXP_FLAGS_IRQ) >> PCI_EXP_FLAGS_IRQ_SHIFT;
-}
-
-void pcie_cap_deverr_init(PCIDevice *dev)
-{
-    uint32_t pos = dev->exp.exp_cap;
-    pci_long_test_and_set_mask(dev->config + pos + PCI_EXP_DEVCAP,
-                               PCI_EXP_DEVCAP_RBER);
-    pci_long_test_and_set_mask(dev->wmask + pos + PCI_EXP_DEVCTL,
-                               PCI_EXP_DEVCTL_CERE | PCI_EXP_DEVCTL_NFERE |
-                               PCI_EXP_DEVCTL_FERE | PCI_EXP_DEVCTL_URRE);
-    pci_long_test_and_set_mask(dev->w1cmask + pos + PCI_EXP_DEVSTA,
-                               PCI_EXP_DEVSTA_CED | PCI_EXP_DEVSTA_NFED |
-                               PCI_EXP_DEVSTA_URD | PCI_EXP_DEVSTA_URD);
-}
-
-void pcie_cap_deverr_reset(PCIDevice *dev)
-{
-    uint8_t *devctl = dev->config + dev->exp.exp_cap + PCI_EXP_DEVCTL;
-    pci_long_test_and_clear_mask(devctl,
-                                 PCI_EXP_DEVCTL_CERE | PCI_EXP_DEVCTL_NFERE |
-                                 PCI_EXP_DEVCTL_FERE | PCI_EXP_DEVCTL_URRE);
-}
-
-static void hotplug_event_update_event_status(PCIDevice *dev)
-{
-    uint32_t pos = dev->exp.exp_cap;
-    uint8_t *exp_cap = dev->config + pos;
-    uint16_t sltctl = pci_get_word(exp_cap + PCI_EXP_SLTCTL);
-    uint16_t sltsta = pci_get_word(exp_cap + PCI_EXP_SLTSTA);
-
-    dev->exp.hpev_notified = (sltctl & PCI_EXP_SLTCTL_HPIE) &&
-        (sltsta & sltctl & PCI_EXP_HP_EV_SUPPORTED);
-}
-
-static void hotplug_event_notify(PCIDevice *dev)
-{
-    bool prev = dev->exp.hpev_notified;
-
-    hotplug_event_update_event_status(dev);
-
-    if (prev == dev->exp.hpev_notified) {
-        return;
-    }
-
-    /* Note: the logic above does not take into account whether interrupts
-     * are masked. The result is that interrupt will be sent when it is
-     * subsequently unmasked. This appears to be legal: Section 6.7.3.4:
-     * The Port may optionally send an MSI when there are hot-plug events that
-     * occur while interrupt generation is disabled, and interrupt generation 
is
-     * subsequently enabled. */
-    if (msix_enabled(dev)) {
-        msix_notify(dev, pcie_cap_flags_get_vector(dev));
-    } else if (msi_enabled(dev)) {
-        msi_notify(dev, pcie_cap_flags_get_vector(dev));
-    } else {
-        qemu_set_irq(dev->irq[dev->exp.hpev_intx], dev->exp.hpev_notified);
-    }
-}
-
-static void hotplug_event_clear(PCIDevice *dev)
-{
-    hotplug_event_update_event_status(dev);
-    if (!msix_enabled(dev) && !msi_enabled(dev) && !dev->exp.hpev_notified) {
-        qemu_set_irq(dev->irq[dev->exp.hpev_intx], 0);
-    }
-}
-
-/*
- * A PCI Express Hot-Plug Event has occurred, so update slot status register
- * and notify OS of the event if necessary.
- *
- * 6.7.3 PCI Express Hot-Plug Events
- * 6.7.3.4 Software Notification of Hot-Plug Events
- */
-static void pcie_cap_slot_event(PCIDevice *dev, PCIExpressHotPlugEvent event)
-{
-    /* Minor optimization: if nothing changed - no event is needed. */
-    if (pci_word_test_and_set_mask(dev->config + dev->exp.exp_cap +
-                                   PCI_EXP_SLTSTA, event)) {
-        return;
-    }
-    hotplug_event_notify(dev);
-}
-
-static int pcie_cap_slot_hotplug(DeviceState *qdev,
-                                 PCIDevice *pci_dev, PCIHotplugState state)
-{
-    PCIDevice *d = PCI_DEVICE(qdev);
-    uint8_t *exp_cap = d->config + d->exp.exp_cap;
-    uint16_t sltsta = pci_get_word(exp_cap + PCI_EXP_SLTSTA);
-
-    /* Don't send event when device is enabled during qemu machine creation:
-     * it is present on boot, no hotplug event is necessary. We do send an
-     * event when the device is disabled later. */
-    if (state == PCI_COLDPLUG_ENABLED) {
-        pci_word_test_and_set_mask(exp_cap + PCI_EXP_SLTSTA,
-                                   PCI_EXP_SLTSTA_PDS);
-        return 0;
-    }
-
-    PCIE_DEV_PRINTF(pci_dev, "hotplug state: %d\n", state);
-    if (sltsta & PCI_EXP_SLTSTA_EIS) {
-        /* the slot is electromechanically locked.
-         * This error is propagated up to qdev and then to HMP/QMP.
-         */
-        return -EBUSY;
-    }
-
-    /* TODO: multifunction hot-plug.
-     * Right now, only a device of function = 0 is allowed to be
-     * hot plugged/unplugged.
-     */
-    assert(PCI_FUNC(pci_dev->devfn) == 0);
-
-    if (state == PCI_HOTPLUG_ENABLED) {
-        pci_word_test_and_set_mask(exp_cap + PCI_EXP_SLTSTA,
-                                   PCI_EXP_SLTSTA_PDS);
-        pcie_cap_slot_event(d, PCI_EXP_HP_EV_PDC);
-    } else {
-        qdev_free(&pci_dev->qdev);
-        pci_word_test_and_clear_mask(exp_cap + PCI_EXP_SLTSTA,
-                                     PCI_EXP_SLTSTA_PDS);
-        pcie_cap_slot_event(d, PCI_EXP_HP_EV_PDC);
-    }
-    return 0;
-}
-
-/* pci express slot for pci express root/downstream port
-   PCI express capability slot registers */
-void pcie_cap_slot_init(PCIDevice *dev, uint16_t slot)
-{
-    uint32_t pos = dev->exp.exp_cap;
-
-    pci_word_test_and_set_mask(dev->config + pos + PCI_EXP_FLAGS,
-                               PCI_EXP_FLAGS_SLOT);
-
-    pci_long_test_and_clear_mask(dev->config + pos + PCI_EXP_SLTCAP,
-                                 ~PCI_EXP_SLTCAP_PSN);
-    pci_long_test_and_set_mask(dev->config + pos + PCI_EXP_SLTCAP,
-                               (slot << PCI_EXP_SLTCAP_PSN_SHIFT) |
-                               PCI_EXP_SLTCAP_EIP |
-                               PCI_EXP_SLTCAP_HPS |
-                               PCI_EXP_SLTCAP_HPC |
-                               PCI_EXP_SLTCAP_PIP |
-                               PCI_EXP_SLTCAP_AIP |
-                               PCI_EXP_SLTCAP_ABP);
-
-    pci_word_test_and_clear_mask(dev->config + pos + PCI_EXP_SLTCTL,
-                                 PCI_EXP_SLTCTL_PIC |
-                                 PCI_EXP_SLTCTL_AIC);
-    pci_word_test_and_set_mask(dev->config + pos + PCI_EXP_SLTCTL,
-                               PCI_EXP_SLTCTL_PIC_OFF |
-                               PCI_EXP_SLTCTL_AIC_OFF);
-    pci_word_test_and_set_mask(dev->wmask + pos + PCI_EXP_SLTCTL,
-                               PCI_EXP_SLTCTL_PIC |
-                               PCI_EXP_SLTCTL_AIC |
-                               PCI_EXP_SLTCTL_HPIE |
-                               PCI_EXP_SLTCTL_CCIE |
-                               PCI_EXP_SLTCTL_PDCE |
-                               PCI_EXP_SLTCTL_ABPE);
-    /* Although reading PCI_EXP_SLTCTL_EIC returns always 0,
-     * make the bit writable here in order to detect 1b is written.
-     * pcie_cap_slot_write_config() test-and-clear the bit, so
-     * this bit always returns 0 to the guest.
-     */
-    pci_word_test_and_set_mask(dev->wmask + pos + PCI_EXP_SLTCTL,
-                               PCI_EXP_SLTCTL_EIC);
-
-    pci_word_test_and_set_mask(dev->w1cmask + pos + PCI_EXP_SLTSTA,
-                               PCI_EXP_HP_EV_SUPPORTED);
-
-    dev->exp.hpev_notified = false;
-
-    pci_bus_hotplug(pci_bridge_get_sec_bus(DO_UPCAST(PCIBridge, dev, dev)),
-                    pcie_cap_slot_hotplug, &dev->qdev);
-}
-
-void pcie_cap_slot_reset(PCIDevice *dev)
-{
-    uint8_t *exp_cap = dev->config + dev->exp.exp_cap;
-
-    PCIE_DEV_PRINTF(dev, "reset\n");
-
-    pci_word_test_and_clear_mask(exp_cap + PCI_EXP_SLTCTL,
-                                 PCI_EXP_SLTCTL_EIC |
-                                 PCI_EXP_SLTCTL_PIC |
-                                 PCI_EXP_SLTCTL_AIC |
-                                 PCI_EXP_SLTCTL_HPIE |
-                                 PCI_EXP_SLTCTL_CCIE |
-                                 PCI_EXP_SLTCTL_PDCE |
-                                 PCI_EXP_SLTCTL_ABPE);
-    pci_word_test_and_set_mask(exp_cap + PCI_EXP_SLTCTL,
-                               PCI_EXP_SLTCTL_PIC_OFF |
-                               PCI_EXP_SLTCTL_AIC_OFF);
-
-    pci_word_test_and_clear_mask(exp_cap + PCI_EXP_SLTSTA,
-                                 PCI_EXP_SLTSTA_EIS |/* on reset,
-                                                        the lock is released */
-                                 PCI_EXP_SLTSTA_CC |
-                                 PCI_EXP_SLTSTA_PDC |
-                                 PCI_EXP_SLTSTA_ABP);
-
-    hotplug_event_update_event_status(dev);
-}
-
-void pcie_cap_slot_write_config(PCIDevice *dev,
-                                uint32_t addr, uint32_t val, int len)
-{
-    uint32_t pos = dev->exp.exp_cap;
-    uint8_t *exp_cap = dev->config + pos;
-    uint16_t sltsta = pci_get_word(exp_cap + PCI_EXP_SLTSTA);
-
-    if (ranges_overlap(addr, len, pos + PCI_EXP_SLTSTA, 2)) {
-        hotplug_event_clear(dev);
-    }
-
-    if (!ranges_overlap(addr, len, pos + PCI_EXP_SLTCTL, 2)) {
-        return;
-    }
-
-    if (pci_word_test_and_clear_mask(exp_cap + PCI_EXP_SLTCTL,
-                                     PCI_EXP_SLTCTL_EIC)) {
-        sltsta ^= PCI_EXP_SLTSTA_EIS; /* toggle PCI_EXP_SLTSTA_EIS bit */
-        pci_set_word(exp_cap + PCI_EXP_SLTSTA, sltsta);
-        PCIE_DEV_PRINTF(dev, "PCI_EXP_SLTCTL_EIC: "
-                        "sltsta -> 0x%02"PRIx16"\n",
-                        sltsta);
-    }
-
-    hotplug_event_notify(dev);
-
-    /* 
-     * 6.7.3.2 Command Completed Events
-     *
-     * Software issues a command to a hot-plug capable Downstream Port by
-     * issuing a write transaction that targets any portion of the Port’s Slot
-     * Control register. A single write to the Slot Control register is
-     * considered to be a single command, even if the write affects more than
-     * one field in the Slot Control register. In response to this transaction,
-     * the Port must carry out the requested actions and then set the
-     * associated status field for the command completed event. */
-
-    /* Real hardware might take a while to complete requested command because
-     * physical movement would be involved like locking the electromechanical
-     * lock.  However in our case, command is completed instantaneously above,
-     * so send a command completion event right now.
-     */
-    pcie_cap_slot_event(dev, PCI_EXP_HP_EV_CCI);
-}
-
-int pcie_cap_slot_post_load(void *opaque, int version_id)
-{
-    PCIDevice *dev = opaque;
-    hotplug_event_update_event_status(dev);
-    return 0;
-}
-
-void pcie_cap_slot_push_attention_button(PCIDevice *dev)
-{
-    pcie_cap_slot_event(dev, PCI_EXP_HP_EV_ABP);
-}
-
-/* root control/capabilities/status. PME isn't emulated for now */
-void pcie_cap_root_init(PCIDevice *dev)
-{
-    pci_set_word(dev->wmask + dev->exp.exp_cap + PCI_EXP_RTCTL,
-                 PCI_EXP_RTCTL_SECEE | PCI_EXP_RTCTL_SENFEE |
-                 PCI_EXP_RTCTL_SEFEE);
-}
-
-void pcie_cap_root_reset(PCIDevice *dev)
-{
-    pci_set_word(dev->config + dev->exp.exp_cap + PCI_EXP_RTCTL, 0);
-}
-
-/* function level reset(FLR) */
-void pcie_cap_flr_init(PCIDevice *dev)
-{
-    pci_long_test_and_set_mask(dev->config + dev->exp.exp_cap + PCI_EXP_DEVCAP,
-                               PCI_EXP_DEVCAP_FLR);
-
-    /* Although reading BCR_FLR returns always 0,
-     * the bit is made writable here in order to detect the 1b is written
-     * pcie_cap_flr_write_config() test-and-clear the bit, so
-     * this bit always returns 0 to the guest.
-     */
-    pci_word_test_and_set_mask(dev->wmask + dev->exp.exp_cap + PCI_EXP_DEVCTL,
-                               PCI_EXP_DEVCTL_BCR_FLR);
-}
-
-void pcie_cap_flr_write_config(PCIDevice *dev,
-                               uint32_t addr, uint32_t val, int len)
-{
-    uint8_t *devctl = dev->config + dev->exp.exp_cap + PCI_EXP_DEVCTL;
-    if (pci_get_word(devctl) & PCI_EXP_DEVCTL_BCR_FLR) {
-        /* Clear PCI_EXP_DEVCTL_BCR_FLR after invoking the reset handler
-           so the handler can detect FLR by looking at this bit. */
-        pci_device_reset(dev);
-        pci_word_test_and_clear_mask(devctl, PCI_EXP_DEVCTL_BCR_FLR);
-    }
-}
-
-/* Alternative Routing-ID Interpretation (ARI) */
-/* ari forwarding support for down stream port */
-void pcie_cap_ari_init(PCIDevice *dev)
-{
-    uint32_t pos = dev->exp.exp_cap;
-    pci_long_test_and_set_mask(dev->config + pos + PCI_EXP_DEVCAP2,
-                               PCI_EXP_DEVCAP2_ARI);
-    pci_long_test_and_set_mask(dev->wmask + pos + PCI_EXP_DEVCTL2,
-                               PCI_EXP_DEVCTL2_ARI);
-}
-
-void pcie_cap_ari_reset(PCIDevice *dev)
-{
-    uint8_t *devctl2 = dev->config + dev->exp.exp_cap + PCI_EXP_DEVCTL2;
-    pci_long_test_and_clear_mask(devctl2, PCI_EXP_DEVCTL2_ARI);
-}
-
-bool pcie_cap_is_ari_enabled(const PCIDevice *dev)
-{
-    if (!pci_is_express(dev)) {
-        return false;
-    }
-    if (!dev->exp.exp_cap) {
-        return false;
-    }
-
-    return pci_get_long(dev->config + dev->exp.exp_cap + PCI_EXP_DEVCTL2) &
-        PCI_EXP_DEVCTL2_ARI;
-}
-
-/**************************************************************************
- * pci express extended capability allocation functions
- * uint16_t ext_cap_id (16 bit)
- * uint8_t cap_ver (4 bit)
- * uint16_t cap_offset (12 bit)
- * uint16_t ext_cap_size
- */
-
-static uint16_t pcie_find_capability_list(PCIDevice *dev, uint16_t cap_id,
-                                          uint16_t *prev_p)
-{
-    uint16_t prev = 0;
-    uint16_t next;
-    uint32_t header = pci_get_long(dev->config + PCI_CONFIG_SPACE_SIZE);
-
-    if (!header) {
-        /* no extended capability */
-        next = 0;
-        goto out;
-    }
-    for (next = PCI_CONFIG_SPACE_SIZE; next;
-         prev = next, next = PCI_EXT_CAP_NEXT(header)) {
-
-        assert(next >= PCI_CONFIG_SPACE_SIZE);
-        assert(next <= PCIE_CONFIG_SPACE_SIZE - 8);
-
-        header = pci_get_long(dev->config + next);
-        if (PCI_EXT_CAP_ID(header) == cap_id) {
-            break;
-        }
-    }
-
-out:
-    if (prev_p) {
-        *prev_p = prev;
-    }
-    return next;
-}
-
-uint16_t pcie_find_capability(PCIDevice *dev, uint16_t cap_id)
-{
-    return pcie_find_capability_list(dev, cap_id, NULL);
-}
-
-static void pcie_ext_cap_set_next(PCIDevice *dev, uint16_t pos, uint16_t next)
-{
-    uint16_t header = pci_get_long(dev->config + pos);
-    assert(!(next & (PCI_EXT_CAP_ALIGN - 1)));
-    header = (header & ~PCI_EXT_CAP_NEXT_MASK) |
-        ((next << PCI_EXT_CAP_NEXT_SHIFT) & PCI_EXT_CAP_NEXT_MASK);
-    pci_set_long(dev->config + pos, header);
-}
-
-/*
- * caller must supply valid (offset, size) * such that the range shouldn't
- * overlap with other capability or other registers.
- * This function doesn't check it.
- */
-void pcie_add_capability(PCIDevice *dev,
-                         uint16_t cap_id, uint8_t cap_ver,
-                         uint16_t offset, uint16_t size)
-{
-    uint32_t header;
-    uint16_t next;
-
-    assert(offset >= PCI_CONFIG_SPACE_SIZE);
-    assert(offset < offset + size);
-    assert(offset + size < PCIE_CONFIG_SPACE_SIZE);
-    assert(size >= 8);
-    assert(pci_is_express(dev));
-
-    if (offset == PCI_CONFIG_SPACE_SIZE) {
-        header = pci_get_long(dev->config + offset);
-        next = PCI_EXT_CAP_NEXT(header);
-    } else {
-        uint16_t prev;
-
-        /* 0 is reserved cap id. use internally to find the last capability
-           in the linked list */
-        next = pcie_find_capability_list(dev, 0, &prev);
-
-        assert(prev >= PCI_CONFIG_SPACE_SIZE);
-        assert(next == 0);
-        pcie_ext_cap_set_next(dev, prev, offset);
-    }
-    pci_set_long(dev->config + offset, PCI_EXT_CAP(cap_id, cap_ver, next));
-
-    /* Make capability read-only by default */
-    memset(dev->wmask + offset, 0, size);
-    memset(dev->w1cmask + offset, 0, size);
-    /* Check capability by default */
-    memset(dev->cmask + offset, 0xFF, size);
-}
-
-/**************************************************************************
- * pci express extended capability helper functions
- */
-
-/* ARI */
-void pcie_ari_init(PCIDevice *dev, uint16_t offset, uint16_t nextfn)
-{
-    pcie_add_capability(dev, PCI_EXT_CAP_ID_ARI, PCI_ARI_VER,
-                        offset, PCI_ARI_SIZEOF);
-    pci_set_long(dev->config + offset + PCI_ARI_CAP, PCI_ARI_CAP_NFN(nextfn));
-}
diff --git a/hw/pcie.h b/hw/pcie.h
deleted file mode 100644
index 4889194..0000000
--- a/hw/pcie.h
+++ /dev/null
@@ -1,142 +0,0 @@
-/*
- * pcie.h
- *
- * Copyright (c) 2010 Isaku Yamahata <yamahata at valinux co jp>
- *                    VA Linux Systems Japan K.K.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, see <http://www.gnu.org/licenses/>.
- */
-
-#ifndef QEMU_PCIE_H
-#define QEMU_PCIE_H
-
-#include "hw.h"
-#include "pci_regs.h"
-#include "pcie_regs.h"
-#include "pcie_aer.h"
-
-typedef enum {
-    /* for attention and power indicator */
-    PCI_EXP_HP_IND_RESERVED     = PCI_EXP_SLTCTL_IND_RESERVED,
-    PCI_EXP_HP_IND_ON           = PCI_EXP_SLTCTL_IND_ON,
-    PCI_EXP_HP_IND_BLINK        = PCI_EXP_SLTCTL_IND_BLINK,
-    PCI_EXP_HP_IND_OFF          = PCI_EXP_SLTCTL_IND_OFF,
-} PCIExpressIndicator;
-
-typedef enum {
-    /* these bits must match the bits in Slot Control/Status registers.
-     * PCI_EXP_HP_EV_xxx = PCI_EXP_SLTCTL_xxxE = PCI_EXP_SLTSTA_xxx
-     *
-     * Not all the bits of slot control register match with the ones of
-     * slot status. Not some bits of slot status register is used to
-     * show status, not to report event occurrence.
-     * So such bits must be masked out when checking the software
-     * notification condition.
-     */
-    PCI_EXP_HP_EV_ABP           = PCI_EXP_SLTCTL_ABPE,
-                                        /* attention button pressed */
-    PCI_EXP_HP_EV_PDC           = PCI_EXP_SLTCTL_PDCE,
-                                        /* presence detect changed */
-    PCI_EXP_HP_EV_CCI           = PCI_EXP_SLTCTL_CCIE,
-                                        /* command completed */
-
-    PCI_EXP_HP_EV_SUPPORTED     = PCI_EXP_HP_EV_ABP |
-                                  PCI_EXP_HP_EV_PDC |
-                                  PCI_EXP_HP_EV_CCI,
-                                                /* supported event mask  */
-
-    /* events not listed aren't supported */
-} PCIExpressHotPlugEvent;
-
-struct PCIExpressDevice {
-    /* Offset of express capability in config space */
-    uint8_t exp_cap;
-
-    /* SLOT */
-    unsigned int hpev_intx;     /* INTx for hot plug event (0-3:INT[A-D]#)
-                                 * default is 0 = INTA#
-                                 * If the chip wants to use other interrupt
-                                 * line, initialize this member with the
-                                 * desired number.
-                                 * If the chip dynamically changes this member,
-                                 * also initialize it when loaded as
-                                 * appropreately.
-                                 */
-    bool hpev_notified; /* Logical AND of conditions for hot plug event.
-                         Following 6.7.3.4:
-                         Software Notification of Hot-Plug Events, an interrupt
-                         is sent whenever the logical and of these conditions
-                         transitions from false to true. */
-
-    /* AER */
-    uint16_t aer_cap;
-    PCIEAERLog aer_log;
-    unsigned int aer_intx;      /* INTx for error reporting
-                                 * default is 0 = INTA#
-                                 * If the chip wants to use other interrupt
-                                 * line, initialize this member with the
-                                 * desired number.
-                                 * If the chip dynamically changes this member,
-                                 * also initialize it when loaded as
-                                 * appropreately.
-                                 */
-};
-
-/* PCI express capability helper functions */
-int pcie_cap_init(PCIDevice *dev, uint8_t offset, uint8_t type, uint8_t port);
-void pcie_cap_exit(PCIDevice *dev);
-uint8_t pcie_cap_get_type(const PCIDevice *dev);
-void pcie_cap_flags_set_vector(PCIDevice *dev, uint8_t vector);
-uint8_t pcie_cap_flags_get_vector(PCIDevice *dev);
-
-void pcie_cap_deverr_init(PCIDevice *dev);
-void pcie_cap_deverr_reset(PCIDevice *dev);
-
-void pcie_cap_slot_init(PCIDevice *dev, uint16_t slot);
-void pcie_cap_slot_reset(PCIDevice *dev);
-void pcie_cap_slot_write_config(PCIDevice *dev,
-                                uint32_t addr, uint32_t val, int len);
-int pcie_cap_slot_post_load(void *opaque, int version_id);
-void pcie_cap_slot_push_attention_button(PCIDevice *dev);
-
-void pcie_cap_root_init(PCIDevice *dev);
-void pcie_cap_root_reset(PCIDevice *dev);
-
-void pcie_cap_flr_init(PCIDevice *dev);
-void pcie_cap_flr_write_config(PCIDevice *dev,
-                           uint32_t addr, uint32_t val, int len);
-
-void pcie_cap_ari_init(PCIDevice *dev);
-void pcie_cap_ari_reset(PCIDevice *dev);
-bool pcie_cap_is_ari_enabled(const PCIDevice *dev);
-
-/* PCI express extended capability helper functions */
-uint16_t pcie_find_capability(PCIDevice *dev, uint16_t cap_id);
-void pcie_add_capability(PCIDevice *dev,
-                         uint16_t cap_id, uint8_t cap_ver,
-                         uint16_t offset, uint16_t size);
-
-void pcie_ari_init(PCIDevice *dev, uint16_t offset, uint16_t nextfn);
-
-extern const VMStateDescription vmstate_pcie_device;
-
-#define VMSTATE_PCIE_DEVICE(_field, _state) {                        \
-    .name       = (stringify(_field)),                               \
-    .size       = sizeof(PCIDevice),                                 \
-    .vmsd       = &vmstate_pcie_device,                              \
-    .flags      = VMS_STRUCT,                                        \
-    .offset     = vmstate_offset_value(_state, _field, PCIDevice),   \
-}
-
-#endif /* QEMU_PCIE_H */
diff --git a/hw/pcie_aer.c b/hw/pcie_aer.c
deleted file mode 100644
index b04c164..0000000
--- a/hw/pcie_aer.c
+++ /dev/null
@@ -1,1032 +0,0 @@
-/*
- * pcie_aer.c
- *
- * Copyright (c) 2010 Isaku Yamahata <yamahata at valinux co jp>
- *                    VA Linux Systems Japan K.K.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, see <http://www.gnu.org/licenses/>.
- */
-
-#include "sysemu.h"
-#include "qemu-objects.h"
-#include "monitor.h"
-#include "pci_bridge.h"
-#include "pcie.h"
-#include "msix.h"
-#include "msi.h"
-#include "pci_internals.h"
-#include "pcie_regs.h"
-
-//#define DEBUG_PCIE
-#ifdef DEBUG_PCIE
-# define PCIE_DPRINTF(fmt, ...)                                         \
-    fprintf(stderr, "%s:%d " fmt, __func__, __LINE__, ## __VA_ARGS__)
-#else
-# define PCIE_DPRINTF(fmt, ...) do {} while (0)
-#endif
-#define PCIE_DEV_PRINTF(dev, fmt, ...)                                  \
-    PCIE_DPRINTF("%s:%x "fmt, (dev)->name, (dev)->devfn, ## __VA_ARGS__)
-
-#define PCI_ERR_SRC_COR_OFFS    0
-#define PCI_ERR_SRC_UNCOR_OFFS  2
-
-/* From 6.2.7 Error Listing and Rules. Table 6-2, 6-3 and 6-4 */
-static uint32_t pcie_aer_uncor_default_severity(uint32_t status)
-{
-    switch (status) {
-    case PCI_ERR_UNC_INTN:
-    case PCI_ERR_UNC_DLP:
-    case PCI_ERR_UNC_SDN:
-    case PCI_ERR_UNC_RX_OVER:
-    case PCI_ERR_UNC_FCP:
-    case PCI_ERR_UNC_MALF_TLP:
-        return PCI_ERR_ROOT_CMD_FATAL_EN;
-    case PCI_ERR_UNC_POISON_TLP:
-    case PCI_ERR_UNC_ECRC:
-    case PCI_ERR_UNC_UNSUP:
-    case PCI_ERR_UNC_COMP_TIME:
-    case PCI_ERR_UNC_COMP_ABORT:
-    case PCI_ERR_UNC_UNX_COMP:
-    case PCI_ERR_UNC_ACSV:
-    case PCI_ERR_UNC_MCBTLP:
-    case PCI_ERR_UNC_ATOP_EBLOCKED:
-    case PCI_ERR_UNC_TLP_PRF_BLOCKED:
-        return PCI_ERR_ROOT_CMD_NONFATAL_EN;
-    default:
-        abort();
-        break;
-    }
-    return PCI_ERR_ROOT_CMD_FATAL_EN;
-}
-
-static int aer_log_add_err(PCIEAERLog *aer_log, const PCIEAERErr *err)
-{
-    if (aer_log->log_num == aer_log->log_max) {
-        return -1;
-    }
-    memcpy(&aer_log->log[aer_log->log_num], err, sizeof *err);
-    aer_log->log_num++;
-    return 0;
-}
-
-static void aer_log_del_err(PCIEAERLog *aer_log, PCIEAERErr *err)
-{
-    assert(aer_log->log_num);
-    *err = aer_log->log[0];
-    aer_log->log_num--;
-    memmove(&aer_log->log[0], &aer_log->log[1],
-            aer_log->log_num * sizeof *err);
-}
-
-static void aer_log_clear_all_err(PCIEAERLog *aer_log)
-{
-    aer_log->log_num = 0;
-}
-
-int pcie_aer_init(PCIDevice *dev, uint16_t offset)
-{
-    PCIExpressDevice *exp;
-
-    pcie_add_capability(dev, PCI_EXT_CAP_ID_ERR, PCI_ERR_VER,
-                        offset, PCI_ERR_SIZEOF);
-    exp = &dev->exp;
-    exp->aer_cap = offset;
-
-    /* log_max is property */
-    if (dev->exp.aer_log.log_max == PCIE_AER_LOG_MAX_UNSET) {
-        dev->exp.aer_log.log_max = PCIE_AER_LOG_MAX_DEFAULT;
-    }
-    /* clip down the value to avoid unreasobale memory usage */
-    if (dev->exp.aer_log.log_max > PCIE_AER_LOG_MAX_LIMIT) {
-        return -EINVAL;
-    }
-    dev->exp.aer_log.log = g_malloc0(sizeof dev->exp.aer_log.log[0] *
-                                        dev->exp.aer_log.log_max);
-
-    pci_set_long(dev->w1cmask + offset + PCI_ERR_UNCOR_STATUS,
-                 PCI_ERR_UNC_SUPPORTED);
-
-    pci_set_long(dev->config + offset + PCI_ERR_UNCOR_SEVER,
-                 PCI_ERR_UNC_SEVERITY_DEFAULT);
-    pci_set_long(dev->wmask + offset + PCI_ERR_UNCOR_SEVER,
-                 PCI_ERR_UNC_SUPPORTED);
-
-    pci_long_test_and_set_mask(dev->w1cmask + offset + PCI_ERR_COR_STATUS,
-                               PCI_ERR_COR_STATUS);
-
-    pci_set_long(dev->config + offset + PCI_ERR_COR_MASK,
-                 PCI_ERR_COR_MASK_DEFAULT);
-    pci_set_long(dev->wmask + offset + PCI_ERR_COR_MASK,
-                 PCI_ERR_COR_SUPPORTED);
-
-    /* capabilities and control. multiple header logging is supported */
-    if (dev->exp.aer_log.log_max > 0) {
-        pci_set_long(dev->config + offset + PCI_ERR_CAP,
-                     PCI_ERR_CAP_ECRC_GENC | PCI_ERR_CAP_ECRC_CHKC |
-                     PCI_ERR_CAP_MHRC);
-        pci_set_long(dev->wmask + offset + PCI_ERR_CAP,
-                     PCI_ERR_CAP_ECRC_GENE | PCI_ERR_CAP_ECRC_CHKE |
-                     PCI_ERR_CAP_MHRE);
-    } else {
-        pci_set_long(dev->config + offset + PCI_ERR_CAP,
-                     PCI_ERR_CAP_ECRC_GENC | PCI_ERR_CAP_ECRC_CHKC);
-        pci_set_long(dev->wmask + offset + PCI_ERR_CAP,
-                     PCI_ERR_CAP_ECRC_GENE | PCI_ERR_CAP_ECRC_CHKE);
-    }
-
-    switch (pcie_cap_get_type(dev)) {
-    case PCI_EXP_TYPE_ROOT_PORT:
-        /* this case will be set by pcie_aer_root_init() */
-        /* fallthrough */
-    case PCI_EXP_TYPE_DOWNSTREAM:
-    case PCI_EXP_TYPE_UPSTREAM:
-        pci_word_test_and_set_mask(dev->wmask + PCI_BRIDGE_CONTROL,
-                                   PCI_BRIDGE_CTL_SERR);
-        pci_long_test_and_set_mask(dev->w1cmask + PCI_STATUS,
-                                   PCI_SEC_STATUS_RCV_SYSTEM_ERROR);
-        break;
-    default:
-        /* nothing */
-        break;
-    }
-    return 0;
-}
-
-void pcie_aer_exit(PCIDevice *dev)
-{
-    g_free(dev->exp.aer_log.log);
-}
-
-static void pcie_aer_update_uncor_status(PCIDevice *dev)
-{
-    uint8_t *aer_cap = dev->config + dev->exp.aer_cap;
-    PCIEAERLog *aer_log = &dev->exp.aer_log;
-
-    uint16_t i;
-    for (i = 0; i < aer_log->log_num; i++) {
-        pci_long_test_and_set_mask(aer_cap + PCI_ERR_UNCOR_STATUS,
-                                   dev->exp.aer_log.log[i].status);
-    }
-}
-
-/*
- * return value:
- * true: error message needs to be sent up
- * false: error message is masked
- *
- * 6.2.6 Error Message Control
- * Figure 6-3
- * all pci express devices part
- */
-static bool
-pcie_aer_msg_alldev(PCIDevice *dev, const PCIEAERMsg *msg)
-{
-    if (!(pcie_aer_msg_is_uncor(msg) &&
-          (pci_get_word(dev->config + PCI_COMMAND) & PCI_COMMAND_SERR))) {
-        return false;
-    }
-
-    /* Signaled System Error
-     *
-     * 7.5.1.1 Command register
-     * Bit 8 SERR# Enable
-     *
-     * When Set, this bit enables reporting of Non-fatal and Fatal
-     * errors detected by the Function to the Root Complex. Note that
-     * errors are reported if enabled either through this bit or through
-     * the PCI Express specific bits in the Device Control register (see
-     * Section 7.8.4).
-     */
-    pci_word_test_and_set_mask(dev->config + PCI_STATUS,
-                               PCI_STATUS_SIG_SYSTEM_ERROR);
-
-    if (!(msg->severity &
-          pci_get_word(dev->config + dev->exp.exp_cap + PCI_EXP_DEVCTL))) {
-        return false;
-    }
-
-    /* send up error message */
-    return true;
-}
-
-/*
- * return value:
- * true: error message is sent up
- * false: error message is masked
- *
- * 6.2.6 Error Message Control
- * Figure 6-3
- * virtual pci bridge part
- */
-static bool pcie_aer_msg_vbridge(PCIDevice *dev, const PCIEAERMsg *msg)
-{
-    uint16_t bridge_control = pci_get_word(dev->config + PCI_BRIDGE_CONTROL);
-
-    if (pcie_aer_msg_is_uncor(msg)) {
-        /* Received System Error */
-        pci_word_test_and_set_mask(dev->config + PCI_SEC_STATUS,
-                                   PCI_SEC_STATUS_RCV_SYSTEM_ERROR);
-    }
-
-    if (!(bridge_control & PCI_BRIDGE_CTL_SERR)) {
-        return false;
-    }
-    return true;
-}
-
-void pcie_aer_root_set_vector(PCIDevice *dev, unsigned int vector)
-{
-    uint8_t *aer_cap = dev->config + dev->exp.aer_cap;
-    assert(vector < PCI_ERR_ROOT_IRQ_MAX);
-    pci_long_test_and_clear_mask(aer_cap + PCI_ERR_ROOT_STATUS,
-                                 PCI_ERR_ROOT_IRQ);
-    pci_long_test_and_set_mask(aer_cap + PCI_ERR_ROOT_STATUS,
-                               vector << PCI_ERR_ROOT_IRQ_SHIFT);
-}
-
-static unsigned int pcie_aer_root_get_vector(PCIDevice *dev)
-{
-    uint8_t *aer_cap = dev->config + dev->exp.aer_cap;
-    uint32_t root_status = pci_get_long(aer_cap + PCI_ERR_ROOT_STATUS);
-    return (root_status & PCI_ERR_ROOT_IRQ) >> PCI_ERR_ROOT_IRQ_SHIFT;
-}
-
-/* Given a status register, get corresponding bits in the command register */
-static uint32_t pcie_aer_status_to_cmd(uint32_t status)
-{
-    uint32_t cmd = 0;
-    if (status & PCI_ERR_ROOT_COR_RCV) {
-        cmd |= PCI_ERR_ROOT_CMD_COR_EN;
-    }
-    if (status & PCI_ERR_ROOT_NONFATAL_RCV) {
-        cmd |= PCI_ERR_ROOT_CMD_NONFATAL_EN;
-    }
-    if (status & PCI_ERR_ROOT_FATAL_RCV) {
-        cmd |= PCI_ERR_ROOT_CMD_FATAL_EN;
-    }
-    return cmd;
-}
-
-static void pcie_aer_root_notify(PCIDevice *dev)
-{
-    if (msix_enabled(dev)) {
-        msix_notify(dev, pcie_aer_root_get_vector(dev));
-    } else if (msi_enabled(dev)) {
-        msi_notify(dev, pcie_aer_root_get_vector(dev));
-    } else {
-        qemu_set_irq(dev->irq[dev->exp.aer_intx], 1);
-    }
-}
-
-/*
- * 6.2.6 Error Message Control
- * Figure 6-3
- * root port part
- */
-static void pcie_aer_msg_root_port(PCIDevice *dev, const PCIEAERMsg *msg)
-{
-    uint16_t cmd;
-    uint8_t *aer_cap;
-    uint32_t root_cmd;
-    uint32_t root_status, prev_status;
-
-    cmd = pci_get_word(dev->config + PCI_COMMAND);
-    aer_cap = dev->config + dev->exp.aer_cap;
-    root_cmd = pci_get_long(aer_cap + PCI_ERR_ROOT_COMMAND);
-    prev_status = root_status = pci_get_long(aer_cap + PCI_ERR_ROOT_STATUS);
-
-    if (cmd & PCI_COMMAND_SERR) {
-        /* System Error.
-         *
-         * The way to report System Error is platform specific and
-         * it isn't implemented in qemu right now.
-         * So just discard the error for now.
-         * OS which cares of aer would receive errors via
-         * native aer mechanims, so this wouldn't matter.
-         */
-    }
-
-    /* Errro Message Received: Root Error Status register */
-    switch (msg->severity) {
-    case PCI_ERR_ROOT_CMD_COR_EN:
-        if (root_status & PCI_ERR_ROOT_COR_RCV) {
-            root_status |= PCI_ERR_ROOT_MULTI_COR_RCV;
-        } else {
-            pci_set_word(aer_cap + PCI_ERR_ROOT_ERR_SRC + PCI_ERR_SRC_COR_OFFS,
-                         msg->source_id);
-        }
-        root_status |= PCI_ERR_ROOT_COR_RCV;
-        break;
-    case PCI_ERR_ROOT_CMD_NONFATAL_EN:
-        root_status |= PCI_ERR_ROOT_NONFATAL_RCV;
-        break;
-    case PCI_ERR_ROOT_CMD_FATAL_EN:
-        if (!(root_status & PCI_ERR_ROOT_UNCOR_RCV)) {
-            root_status |= PCI_ERR_ROOT_FIRST_FATAL;
-        }
-        root_status |= PCI_ERR_ROOT_FATAL_RCV;
-        break;
-    default:
-        abort();
-        break;
-    }
-    if (pcie_aer_msg_is_uncor(msg)) {
-        if (root_status & PCI_ERR_ROOT_UNCOR_RCV) {
-            root_status |= PCI_ERR_ROOT_MULTI_UNCOR_RCV;
-        } else {
-            pci_set_word(aer_cap + PCI_ERR_ROOT_ERR_SRC +
-                         PCI_ERR_SRC_UNCOR_OFFS, msg->source_id);
-        }
-        root_status |= PCI_ERR_ROOT_UNCOR_RCV;
-    }
-    pci_set_long(aer_cap + PCI_ERR_ROOT_STATUS, root_status);
-
-    /* 6.2.4.1.2 Interrupt Generation */
-    /* All the above did was set some bits in the status register.
-     * Specifically these that match message severity.
-     * The below code relies on this fact. */
-    if (!(root_cmd & msg->severity) ||
-        (pcie_aer_status_to_cmd(prev_status) & root_cmd)) {
-        /* Condition is not being set or was already true so nothing to do. */
-        return;
-    }
-
-    pcie_aer_root_notify(dev);
-}
-
-/*
- * 6.2.6 Error Message Control Figure 6-3
- *
- * Walk up the bus tree from the device, propagate the error message.
- */
-static void pcie_aer_msg(PCIDevice *dev, const PCIEAERMsg *msg)
-{
-    uint8_t type;
-
-    while (dev) {
-        if (!pci_is_express(dev)) {
-            /* just ignore it */
-            /* TODO: Shouldn't we set PCI_STATUS_SIG_SYSTEM_ERROR?
-             * Consider e.g. a PCI bridge above a PCI Express device. */
-            return;
-        }
-
-        type = pcie_cap_get_type(dev);
-        if ((type == PCI_EXP_TYPE_ROOT_PORT ||
-            type == PCI_EXP_TYPE_UPSTREAM ||
-            type == PCI_EXP_TYPE_DOWNSTREAM) &&
-            !pcie_aer_msg_vbridge(dev, msg)) {
-                return;
-        }
-        if (!pcie_aer_msg_alldev(dev, msg)) {
-            return;
-        }
-        if (type == PCI_EXP_TYPE_ROOT_PORT) {
-            pcie_aer_msg_root_port(dev, msg);
-            /* Root port can notify system itself,
-               or send the error message to root complex event collector. */
-            /*
-             * if root port is associated with an event collector,
-             * return the root complex event collector here.
-             * For now root complex event collector isn't supported.
-             */
-            return;
-        }
-        dev = pci_bridge_get_device(dev->bus);
-    }
-}
-
-static void pcie_aer_update_log(PCIDevice *dev, const PCIEAERErr *err)
-{
-    uint8_t *aer_cap = dev->config + dev->exp.aer_cap;
-    uint8_t first_bit = ffs(err->status) - 1;
-    uint32_t errcap = pci_get_long(aer_cap + PCI_ERR_CAP);
-    int i;
-
-    assert(err->status);
-    assert(!(err->status & (err->status - 1)));
-
-    errcap &= ~(PCI_ERR_CAP_FEP_MASK | PCI_ERR_CAP_TLP);
-    errcap |= PCI_ERR_CAP_FEP(first_bit);
-
-    if (err->flags & PCIE_AER_ERR_HEADER_VALID) {
-        for (i = 0; i < ARRAY_SIZE(err->header); ++i) {
-            /* 7.10.8 Header Log Register */
-            uint8_t *header_log =
-                aer_cap + PCI_ERR_HEADER_LOG + i * sizeof err->header[0];
-            cpu_to_be32wu((uint32_t*)header_log, err->header[i]);
-        }
-    } else {
-        assert(!(err->flags & PCIE_AER_ERR_TLP_PREFIX_PRESENT));
-        memset(aer_cap + PCI_ERR_HEADER_LOG, 0, PCI_ERR_HEADER_LOG_SIZE);
-    }
-
-    if ((err->flags & PCIE_AER_ERR_TLP_PREFIX_PRESENT) &&
-        (pci_get_long(dev->config + dev->exp.exp_cap + PCI_EXP_DEVCTL2) &
-         PCI_EXP_DEVCAP2_EETLPP)) {
-        for (i = 0; i < ARRAY_SIZE(err->prefix); ++i) {
-            /* 7.10.12 tlp prefix log register */
-            uint8_t *prefix_log =
-                aer_cap + PCI_ERR_TLP_PREFIX_LOG + i * sizeof err->prefix[0];
-            cpu_to_be32wu((uint32_t*)prefix_log, err->prefix[i]);
-        }
-        errcap |= PCI_ERR_CAP_TLP;
-    } else {
-        memset(aer_cap + PCI_ERR_TLP_PREFIX_LOG, 0,
-               PCI_ERR_TLP_PREFIX_LOG_SIZE);
-    }
-    pci_set_long(aer_cap + PCI_ERR_CAP, errcap);
-}
-
-static void pcie_aer_clear_log(PCIDevice *dev)
-{
-    uint8_t *aer_cap = dev->config + dev->exp.aer_cap;
-
-    pci_long_test_and_clear_mask(aer_cap + PCI_ERR_CAP,
-                                 PCI_ERR_CAP_FEP_MASK | PCI_ERR_CAP_TLP);
-
-    memset(aer_cap + PCI_ERR_HEADER_LOG, 0, PCI_ERR_HEADER_LOG_SIZE);
-    memset(aer_cap + PCI_ERR_TLP_PREFIX_LOG, 0, PCI_ERR_TLP_PREFIX_LOG_SIZE);
-}
-
-static void pcie_aer_clear_error(PCIDevice *dev)
-{
-    uint8_t *aer_cap = dev->config + dev->exp.aer_cap;
-    uint32_t errcap = pci_get_long(aer_cap + PCI_ERR_CAP);
-    PCIEAERLog *aer_log = &dev->exp.aer_log;
-    PCIEAERErr err;
-
-    if (!(errcap & PCI_ERR_CAP_MHRE) || !aer_log->log_num) {
-        pcie_aer_clear_log(dev);
-        return;
-    }
-
-    /*
-     * If more errors are queued, set corresponding bits in uncorrectable
-     * error status.
-     * We emulate uncorrectable error status register as W1CS.
-     * So set bit in uncorrectable error status here again for multiple
-     * error recording support.
-     *
-     * 6.2.4.2 Multiple Error Handling(Advanced Error Reporting Capability)
-     */
-    pcie_aer_update_uncor_status(dev);
-
-    aer_log_del_err(aer_log, &err);
-    pcie_aer_update_log(dev, &err);
-}
-
-static int pcie_aer_record_error(PCIDevice *dev,
-                                 const PCIEAERErr *err)
-{
-    uint8_t *aer_cap = dev->config + dev->exp.aer_cap;
-    uint32_t errcap = pci_get_long(aer_cap + PCI_ERR_CAP);
-    int fep = PCI_ERR_CAP_FEP(errcap);
-
-    assert(err->status);
-    assert(!(err->status & (err->status - 1)));
-
-    if (errcap & PCI_ERR_CAP_MHRE &&
-        (pci_get_long(aer_cap + PCI_ERR_UNCOR_STATUS) & (1U << fep))) {
-        /*  Not first error. queue error */
-        if (aer_log_add_err(&dev->exp.aer_log, err) < 0) {
-            /* overflow */
-            return -1;
-        }
-        return 0;
-    }
-
-    pcie_aer_update_log(dev, err);
-    return 0;
-}
-
-typedef struct PCIEAERInject {
-    PCIDevice *dev;
-    uint8_t *aer_cap;
-    const PCIEAERErr *err;
-    uint16_t devctl;
-    uint16_t devsta;
-    uint32_t error_status;
-    bool unsupported_request;
-    bool log_overflow;
-    PCIEAERMsg msg;
-} PCIEAERInject;
-
-static bool pcie_aer_inject_cor_error(PCIEAERInject *inj,
-                                      uint32_t uncor_status,
-                                      bool is_advisory_nonfatal)
-{
-    PCIDevice *dev = inj->dev;
-
-    inj->devsta |= PCI_EXP_DEVSTA_CED;
-    if (inj->unsupported_request) {
-        inj->devsta |= PCI_EXP_DEVSTA_URD;
-    }
-    pci_set_word(dev->config + dev->exp.exp_cap + PCI_EXP_DEVSTA, inj->devsta);
-
-    if (inj->aer_cap) {
-        uint32_t mask;
-        pci_long_test_and_set_mask(inj->aer_cap + PCI_ERR_COR_STATUS,
-                                   inj->error_status);
-        mask = pci_get_long(inj->aer_cap + PCI_ERR_COR_MASK);
-        if (mask & inj->error_status) {
-            return false;
-        }
-        if (is_advisory_nonfatal) {
-            uint32_t uncor_mask =
-                pci_get_long(inj->aer_cap + PCI_ERR_UNCOR_MASK);
-            if (!(uncor_mask & uncor_status)) {
-                inj->log_overflow = !!pcie_aer_record_error(dev, inj->err);
-            }
-            pci_long_test_and_set_mask(inj->aer_cap + PCI_ERR_UNCOR_STATUS,
-                                       uncor_status);
-        }
-    }
-
-    if (inj->unsupported_request && !(inj->devctl & PCI_EXP_DEVCTL_URRE)) {
-        return false;
-    }
-    if (!(inj->devctl & PCI_EXP_DEVCTL_CERE)) {
-        return false;
-    }
-
-    inj->msg.severity = PCI_ERR_ROOT_CMD_COR_EN;
-    return true;
-}
-
-static bool pcie_aer_inject_uncor_error(PCIEAERInject *inj, bool is_fatal)
-{
-    PCIDevice *dev = inj->dev;
-    uint16_t cmd;
-
-    if (is_fatal) {
-        inj->devsta |= PCI_EXP_DEVSTA_FED;
-    } else {
-        inj->devsta |= PCI_EXP_DEVSTA_NFED;
-    }
-    if (inj->unsupported_request) {
-        inj->devsta |= PCI_EXP_DEVSTA_URD;
-    }
-    pci_set_long(dev->config + dev->exp.exp_cap + PCI_EXP_DEVSTA, inj->devsta);
-
-    if (inj->aer_cap) {
-        uint32_t mask = pci_get_long(inj->aer_cap + PCI_ERR_UNCOR_MASK);
-        if (mask & inj->error_status) {
-            pci_long_test_and_set_mask(inj->aer_cap + PCI_ERR_UNCOR_STATUS,
-                                       inj->error_status);
-            return false;
-        }
-
-        inj->log_overflow = !!pcie_aer_record_error(dev, inj->err);
-        pci_long_test_and_set_mask(inj->aer_cap + PCI_ERR_UNCOR_STATUS,
-                                   inj->error_status);
-    }
-
-    cmd = pci_get_word(dev->config + PCI_COMMAND);
-    if (inj->unsupported_request &&
-        !(inj->devctl & PCI_EXP_DEVCTL_URRE) && !(cmd & PCI_COMMAND_SERR)) {
-        return false;
-    }
-    if (is_fatal) {
-        if (!((cmd & PCI_COMMAND_SERR) ||
-              (inj->devctl & PCI_EXP_DEVCTL_FERE))) {
-            return false;
-        }
-        inj->msg.severity = PCI_ERR_ROOT_CMD_FATAL_EN;
-    } else {
-        if (!((cmd & PCI_COMMAND_SERR) ||
-              (inj->devctl & PCI_EXP_DEVCTL_NFERE))) {
-            return false;
-        }
-        inj->msg.severity = PCI_ERR_ROOT_CMD_NONFATAL_EN;
-    }
-    return true;
-}
-
-/*
- * non-Function specific error must be recorded in all functions.
- * It is the responsibility of the caller of this function.
- * It is also caller's responsibility to determine which function should
- * report the rerror.
- *
- * 6.2.4 Error Logging
- * 6.2.5 Sqeunce of Device Error Signaling and Logging Operations
- * table 6-2: Flowchard Showing Sequence of Device Error Signaling and Logging
- *            Operations
- */
-int pcie_aer_inject_error(PCIDevice *dev, const PCIEAERErr *err)
-{
-    uint8_t *aer_cap = NULL;
-    uint16_t devctl = 0;
-    uint16_t devsta = 0;
-    uint32_t error_status = err->status;
-    PCIEAERInject inj;
-
-    if (!pci_is_express(dev)) {
-        return -ENOSYS;
-    }
-
-    if (err->flags & PCIE_AER_ERR_IS_CORRECTABLE) {
-        error_status &= PCI_ERR_COR_SUPPORTED;
-    } else {
-        error_status &= PCI_ERR_UNC_SUPPORTED;
-    }
-
-    /* invalid status bit. one and only one bit must be set */
-    if (!error_status || (error_status & (error_status - 1))) {
-        return -EINVAL;
-    }
-
-    if (dev->exp.aer_cap) {
-        uint8_t *exp_cap = dev->config + dev->exp.exp_cap;
-        aer_cap = dev->config + dev->exp.aer_cap;
-        devctl = pci_get_long(exp_cap + PCI_EXP_DEVCTL);
-        devsta = pci_get_long(exp_cap + PCI_EXP_DEVSTA);
-    }
-
-    inj.dev = dev;
-    inj.aer_cap = aer_cap;
-    inj.err = err;
-    inj.devctl = devctl;
-    inj.devsta = devsta;
-    inj.error_status = error_status;
-    inj.unsupported_request = !(err->flags & PCIE_AER_ERR_IS_CORRECTABLE) &&
-        err->status == PCI_ERR_UNC_UNSUP;
-    inj.log_overflow = false;
-
-    if (err->flags & PCIE_AER_ERR_IS_CORRECTABLE) {
-        if (!pcie_aer_inject_cor_error(&inj, 0, false)) {
-            return 0;
-        }
-    } else {
-        bool is_fatal =
-            pcie_aer_uncor_default_severity(error_status) ==
-            PCI_ERR_ROOT_CMD_FATAL_EN;
-        if (aer_cap) {
-            is_fatal =
-                error_status & pci_get_long(aer_cap + PCI_ERR_UNCOR_SEVER);
-        }
-        if (!is_fatal && (err->flags & PCIE_AER_ERR_MAYBE_ADVISORY)) {
-            inj.error_status = PCI_ERR_COR_ADV_NONFATAL;
-            if (!pcie_aer_inject_cor_error(&inj, error_status, true)) {
-                return 0;
-            }
-        } else {
-            if (!pcie_aer_inject_uncor_error(&inj, is_fatal)) {
-                return 0;
-            }
-        }
-    }
-
-    /* send up error message */
-    inj.msg.source_id = err->source_id;
-    pcie_aer_msg(dev, &inj.msg);
-
-    if (inj.log_overflow) {
-        PCIEAERErr header_log_overflow = {
-            .status = PCI_ERR_COR_HL_OVERFLOW,
-            .flags = PCIE_AER_ERR_IS_CORRECTABLE,
-        };
-        int ret = pcie_aer_inject_error(dev, &header_log_overflow);
-        assert(!ret);
-    }
-    return 0;
-}
-
-void pcie_aer_write_config(PCIDevice *dev,
-                           uint32_t addr, uint32_t val, int len)
-{
-    uint8_t *aer_cap = dev->config + dev->exp.aer_cap;
-    uint32_t errcap = pci_get_long(aer_cap + PCI_ERR_CAP);
-    uint32_t first_error = 1U << PCI_ERR_CAP_FEP(errcap);
-    uint32_t uncorsta = pci_get_long(aer_cap + PCI_ERR_UNCOR_STATUS);
-
-    /* uncorrectable error */
-    if (!(uncorsta & first_error)) {
-        /* the bit that corresponds to the first error is cleared */
-        pcie_aer_clear_error(dev);
-    } else if (errcap & PCI_ERR_CAP_MHRE) {
-        /* When PCI_ERR_CAP_MHRE is enabled and the first error isn't cleared
-         * nothing should happen. So we have to revert the modification to
-         * the register.
-         */
-        pcie_aer_update_uncor_status(dev);
-    } else {
-        /* capability & control
-         * PCI_ERR_CAP_MHRE might be cleared, so clear of header log.
-         */
-        aer_log_clear_all_err(&dev->exp.aer_log);
-    }
-}
-
-void pcie_aer_root_init(PCIDevice *dev)
-{
-    uint16_t pos = dev->exp.aer_cap;
-
-    pci_set_long(dev->wmask + pos + PCI_ERR_ROOT_COMMAND,
-                 PCI_ERR_ROOT_CMD_EN_MASK);
-    pci_set_long(dev->w1cmask + pos + PCI_ERR_ROOT_STATUS,
-                 PCI_ERR_ROOT_STATUS_REPORT_MASK);
-    /* PCI_ERR_ROOT_IRQ is RO but devices change it using a
-     * device-specific method.
-     */
-    pci_set_long(dev->cmask + pos + PCI_ERR_ROOT_STATUS,
-                 ~PCI_ERR_ROOT_IRQ);
-}
-
-void pcie_aer_root_reset(PCIDevice *dev)
-{
-    uint8_t* aer_cap = dev->config + dev->exp.aer_cap;
-
-    pci_set_long(aer_cap + PCI_ERR_ROOT_COMMAND, 0);
-
-    /*
-     * Advanced Error Interrupt Message Number in Root Error Status Register
-     * must be updated by chip dependent code because it's chip dependent
-     * which number is used.
-     */
-}
-
-void pcie_aer_root_write_config(PCIDevice *dev,
-                                uint32_t addr, uint32_t val, int len,
-                                uint32_t root_cmd_prev)
-{
-    uint8_t *aer_cap = dev->config + dev->exp.aer_cap;
-    uint32_t root_status = pci_get_long(aer_cap + PCI_ERR_ROOT_STATUS);
-    uint32_t enabled_cmd = pcie_aer_status_to_cmd(root_status);
-    uint32_t root_cmd = pci_get_long(aer_cap + PCI_ERR_ROOT_COMMAND);
-    /* 6.2.4.1.2 Interrupt Generation */
-    if (!msix_enabled(dev) && !msi_enabled(dev)) {
-        qemu_set_irq(dev->irq[dev->exp.aer_intx], !!(root_cmd & enabled_cmd));
-        return;
-    }
-
-    if ((root_cmd_prev & enabled_cmd) || !(root_cmd & enabled_cmd)) {
-        /* Send MSI on transition from false to true. */
-        return;
-    }
-
-    pcie_aer_root_notify(dev);
-}
-
-static const VMStateDescription vmstate_pcie_aer_err = {
-    .name = "PCIE_AER_ERROR",
-    .version_id = 1,
-    .minimum_version_id = 1,
-    .minimum_version_id_old = 1,
-    .fields     = (VMStateField[]) {
-        VMSTATE_UINT32(status, PCIEAERErr),
-        VMSTATE_UINT16(source_id, PCIEAERErr),
-        VMSTATE_UINT16(flags, PCIEAERErr),
-        VMSTATE_UINT32_ARRAY(header, PCIEAERErr, 4),
-        VMSTATE_UINT32_ARRAY(prefix, PCIEAERErr, 4),
-        VMSTATE_END_OF_LIST()
-    }
-};
-
-const VMStateDescription vmstate_pcie_aer_log = {
-    .name = "PCIE_AER_ERROR_LOG",
-    .version_id = 1,
-    .minimum_version_id = 1,
-    .minimum_version_id_old = 1,
-    .fields     = (VMStateField[]) {
-        VMSTATE_UINT16(log_num, PCIEAERLog),
-        VMSTATE_UINT16(log_max, PCIEAERLog),
-        VMSTATE_STRUCT_VARRAY_POINTER_UINT16(log, PCIEAERLog, log_num,
-                              vmstate_pcie_aer_err, PCIEAERErr),
-        VMSTATE_END_OF_LIST()
-    }
-};
-
-void pcie_aer_inject_error_print(Monitor *mon, const QObject *data)
-{
-    QDict *qdict;
-    int devfn;
-    assert(qobject_type(data) == QTYPE_QDICT);
-    qdict = qobject_to_qdict(data);
-
-    devfn = (int)qdict_get_int(qdict, "devfn");
-    monitor_printf(mon, "OK id: %s domain: %x, bus: %x devfn: %x.%x\n",
-                   qdict_get_str(qdict, "id"),
-                   (int) qdict_get_int(qdict, "domain"),
-                   (int) qdict_get_int(qdict, "bus"),
-                   PCI_SLOT(devfn), PCI_FUNC(devfn));
-}
-
-typedef struct PCIEAERErrorName {
-    const char *name;
-    uint32_t val;
-    bool correctable;
-} PCIEAERErrorName;
-
-/*
- * AER error name -> value conversion table
- * This naming scheme is same to linux aer-injection tool.
- */
-static const struct PCIEAERErrorName pcie_aer_error_list[] = {
-    {
-        .name = "TRAIN",
-        .val = PCI_ERR_UNC_TRAIN,
-        .correctable = false,
-    }, {
-        .name = "DLP",
-        .val = PCI_ERR_UNC_DLP,
-        .correctable = false,
-    }, {
-        .name = "SDN",
-        .val = PCI_ERR_UNC_SDN,
-        .correctable = false,
-    }, {
-        .name = "POISON_TLP",
-        .val = PCI_ERR_UNC_POISON_TLP,
-        .correctable = false,
-    }, {
-        .name = "FCP",
-        .val = PCI_ERR_UNC_FCP,
-        .correctable = false,
-    }, {
-        .name = "COMP_TIME",
-        .val = PCI_ERR_UNC_COMP_TIME,
-        .correctable = false,
-    }, {
-        .name = "COMP_ABORT",
-        .val = PCI_ERR_UNC_COMP_ABORT,
-        .correctable = false,
-    }, {
-        .name = "UNX_COMP",
-        .val = PCI_ERR_UNC_UNX_COMP,
-        .correctable = false,
-    }, {
-        .name = "RX_OVER",
-        .val = PCI_ERR_UNC_RX_OVER,
-        .correctable = false,
-    }, {
-        .name = "MALF_TLP",
-        .val = PCI_ERR_UNC_MALF_TLP,
-        .correctable = false,
-    }, {
-        .name = "ECRC",
-        .val = PCI_ERR_UNC_ECRC,
-        .correctable = false,
-    }, {
-        .name = "UNSUP",
-        .val = PCI_ERR_UNC_UNSUP,
-        .correctable = false,
-    }, {
-        .name = "ACSV",
-        .val = PCI_ERR_UNC_ACSV,
-        .correctable = false,
-    }, {
-        .name = "INTN",
-        .val = PCI_ERR_UNC_INTN,
-        .correctable = false,
-    }, {
-        .name = "MCBTLP",
-        .val = PCI_ERR_UNC_MCBTLP,
-        .correctable = false,
-    }, {
-        .name = "ATOP_EBLOCKED",
-        .val = PCI_ERR_UNC_ATOP_EBLOCKED,
-        .correctable = false,
-    }, {
-        .name = "TLP_PRF_BLOCKED",
-        .val = PCI_ERR_UNC_TLP_PRF_BLOCKED,
-        .correctable = false,
-    }, {
-        .name = "RCVR",
-        .val = PCI_ERR_COR_RCVR,
-        .correctable = true,
-    }, {
-        .name = "BAD_TLP",
-        .val = PCI_ERR_COR_BAD_TLP,
-        .correctable = true,
-    }, {
-        .name = "BAD_DLLP",
-        .val = PCI_ERR_COR_BAD_DLLP,
-        .correctable = true,
-    }, {
-        .name = "REP_ROLL",
-        .val = PCI_ERR_COR_REP_ROLL,
-        .correctable = true,
-    }, {
-        .name = "REP_TIMER",
-        .val = PCI_ERR_COR_REP_TIMER,
-        .correctable = true,
-    }, {
-        .name = "ADV_NONFATAL",
-        .val = PCI_ERR_COR_ADV_NONFATAL,
-        .correctable = true,
-    }, {
-        .name = "INTERNAL",
-        .val = PCI_ERR_COR_INTERNAL,
-        .correctable = true,
-    }, {
-        .name = "HL_OVERFLOW",
-        .val = PCI_ERR_COR_HL_OVERFLOW,
-        .correctable = true,
-    },
-};
-
-static int pcie_aer_parse_error_string(const char *error_name,
-                                       uint32_t *status, bool *correctable)
-{
-    int i;
-
-    for (i = 0; i < ARRAY_SIZE(pcie_aer_error_list); i++) {
-        const  PCIEAERErrorName *e = &pcie_aer_error_list[i];
-        if (strcmp(error_name, e->name)) {
-            continue;
-        }
-
-        *status = e->val;
-        *correctable = e->correctable;
-        return 0;
-    }
-    return -EINVAL;
-}
-
-int do_pcie_aer_inject_error(Monitor *mon,
-                             const QDict *qdict, QObject **ret_data)
-{
-    const char *id = qdict_get_str(qdict, "id");
-    const char *error_name;
-    uint32_t error_status;
-    bool correctable;
-    PCIDevice *dev;
-    PCIEAERErr err;
-    int ret;
-
-    ret = pci_qdev_find_device(id, &dev);
-    if (ret < 0) {
-        monitor_printf(mon,
-                       "id or pci device path is invalid or device not "
-                       "found. %s\n", id);
-        return ret;
-    }
-    if (!pci_is_express(dev)) {
-        monitor_printf(mon, "the device doesn't support pci express. %s\n",
-                       id);
-        return -ENOSYS;
-    }
-
-    error_name = qdict_get_str(qdict, "error_status");
-    if (pcie_aer_parse_error_string(error_name, &error_status, &correctable)) {
-        char *e = NULL;
-        error_status = strtoul(error_name, &e, 0);
-        correctable = qdict_get_try_bool(qdict, "correctable", 0);
-        if (!e || *e != '\0') {
-            monitor_printf(mon, "invalid error status value. \"%s\"",
-                           error_name);
-            return -EINVAL;
-        }
-    }
-    err.status = error_status;
-    err.source_id = (pci_bus_num(dev->bus) << 8) | dev->devfn;
-
-    err.flags = 0;
-    if (correctable) {
-        err.flags |= PCIE_AER_ERR_IS_CORRECTABLE;
-    }
-    if (qdict_get_try_bool(qdict, "advisory_non_fatal", 0)) {
-        err.flags |= PCIE_AER_ERR_MAYBE_ADVISORY;
-    }
-    if (qdict_haskey(qdict, "header0")) {
-        err.flags |= PCIE_AER_ERR_HEADER_VALID;
-    }
-    if (qdict_haskey(qdict, "prefix0")) {
-        err.flags |= PCIE_AER_ERR_TLP_PREFIX_PRESENT;
-    }
-
-    err.header[0] = qdict_get_try_int(qdict, "header0", 0);
-    err.header[1] = qdict_get_try_int(qdict, "header1", 0);
-    err.header[2] = qdict_get_try_int(qdict, "header2", 0);
-    err.header[3] = qdict_get_try_int(qdict, "header3", 0);
-
-    err.prefix[0] = qdict_get_try_int(qdict, "prefix0", 0);
-    err.prefix[1] = qdict_get_try_int(qdict, "prefix1", 0);
-    err.prefix[2] = qdict_get_try_int(qdict, "prefix2", 0);
-    err.prefix[3] = qdict_get_try_int(qdict, "prefix3", 0);
-
-    ret = pcie_aer_inject_error(dev, &err);
-    *ret_data = qobject_from_jsonf("{'id': %s, "
-                                   "'domain': %d, 'bus': %d, 'devfn': %d, "
-                                   "'ret': %d}",
-                                   id,
-                                   pci_find_domain(dev->bus),
-                                   pci_bus_num(dev->bus), dev->devfn,
-                                   ret);
-    assert(*ret_data);
-
-    return 0;
-}
diff --git a/hw/pcie_aer.h b/hw/pcie_aer.h
deleted file mode 100644
index 7539500..0000000
--- a/hw/pcie_aer.h
+++ /dev/null
@@ -1,106 +0,0 @@
-/*
- * pcie_aer.h
- *
- * Copyright (c) 2010 Isaku Yamahata <yamahata at valinux co jp>
- *                    VA Linux Systems Japan K.K.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, see <http://www.gnu.org/licenses/>.
- */
-
-#ifndef QEMU_PCIE_AER_H
-#define QEMU_PCIE_AER_H
-
-#include "hw.h"
-
-/* definitions which PCIExpressDevice uses */
-
-/* AER log */
-struct PCIEAERLog {
-    /* This structure is saved/loaded.
-       So explicitly size them instead of unsigned int */
-
-    /* the number of currently recorded log in log member */
-    uint16_t log_num;
-
-    /*
-     * The maximum number of the log. Errors can be logged up to this.
-     *
-     * This is configurable property.
-     * The specified value will be clipped down to PCIE_AER_LOG_MAX_LIMIT
-     * to avoid unreasonable memory usage.
-     * I bet that 128 log size would be big enough, otherwise too many errors
-     * for system to function normaly. But could consecutive errors occur?
-     */
-#define PCIE_AER_LOG_MAX_DEFAULT        8
-#define PCIE_AER_LOG_MAX_LIMIT          128
-#define PCIE_AER_LOG_MAX_UNSET          0xffff
-    uint16_t log_max;
-
-    /* Error log. log_max-sized array */
-    PCIEAERErr *log;
-};
-
-/* aer error message: error signaling message has only error sevirity and
-   source id. See 2.2.8.3 error signaling messages */
-struct PCIEAERMsg {
-    /*
-     * PCI_ERR_ROOT_CMD_{COR, NONFATAL, FATAL}_EN
-     * = PCI_EXP_DEVCTL_{CERE, NFERE, FERE}
-     */
-    uint32_t severity;
-
-    uint16_t source_id; /* bdf */
-};
-
-static inline bool
-pcie_aer_msg_is_uncor(const PCIEAERMsg *msg)
-{
-    return msg->severity == PCI_ERR_ROOT_CMD_NONFATAL_EN ||
-        msg->severity == PCI_ERR_ROOT_CMD_FATAL_EN;
-}
-
-/* error */
-struct PCIEAERErr {
-    uint32_t status;    /* error status bits */
-    uint16_t source_id; /* bdf */
-
-#define PCIE_AER_ERR_IS_CORRECTABLE     0x1     /* correctable/uncorrectable */
-#define PCIE_AER_ERR_MAYBE_ADVISORY     0x2     /* maybe advisory non-fatal */
-#define PCIE_AER_ERR_HEADER_VALID       0x4     /* TLP header is logged */
-#define PCIE_AER_ERR_TLP_PREFIX_PRESENT 0x8     /* TLP Prefix is logged */
-    uint16_t flags;
-
-    uint32_t header[4]; /* TLP header */
-    uint32_t prefix[4]; /* TLP header prefix */
-};
-
-extern const VMStateDescription vmstate_pcie_aer_log;
-
-int pcie_aer_init(PCIDevice *dev, uint16_t offset);
-void pcie_aer_exit(PCIDevice *dev);
-void pcie_aer_write_config(PCIDevice *dev,
-                           uint32_t addr, uint32_t val, int len);
-
-/* aer root port */
-void pcie_aer_root_set_vector(PCIDevice *dev, unsigned int vector);
-void pcie_aer_root_init(PCIDevice *dev);
-void pcie_aer_root_reset(PCIDevice *dev);
-void pcie_aer_root_write_config(PCIDevice *dev,
-                                uint32_t addr, uint32_t val, int len,
-                                uint32_t root_cmd_prev);
-
-/* error injection */
-int pcie_aer_inject_error(PCIDevice *dev, const PCIEAERErr *err);
-
-#endif /* QEMU_PCIE_AER_H */
diff --git a/hw/pcie_host.c b/hw/pcie_host.c
deleted file mode 100644
index c257fb4..0000000
--- a/hw/pcie_host.c
+++ /dev/null
@@ -1,161 +0,0 @@
-/*
- * pcie_host.c
- * utility functions for pci express host bridge.
- *
- * Copyright (c) 2009 Isaku Yamahata <yamahata at valinux co jp>
- *                    VA Linux Systems Japan K.K.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
-
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
-
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, see <http://www.gnu.org/licenses/>.
- */
-
-#include "hw.h"
-#include "pci.h"
-#include "pcie_host.h"
-#include "exec-memory.h"
-
-/*
- * PCI express mmcfig address
- * bit 20 - 28: bus number
- * bit 15 - 19: device number
- * bit 12 - 14: function number
- * bit  0 - 11: offset in configuration space of a given device
- */
-#define PCIE_MMCFG_SIZE_MAX             (1ULL << 28)
-#define PCIE_MMCFG_SIZE_MIN             (1ULL << 20)
-#define PCIE_MMCFG_BUS_BIT              20
-#define PCIE_MMCFG_BUS_MASK             0x1ff
-#define PCIE_MMCFG_DEVFN_BIT            12
-#define PCIE_MMCFG_DEVFN_MASK           0xff
-#define PCIE_MMCFG_CONFOFFSET_MASK      0xfff
-#define PCIE_MMCFG_BUS(addr)            (((addr) >> PCIE_MMCFG_BUS_BIT) & \
-                                         PCIE_MMCFG_BUS_MASK)
-#define PCIE_MMCFG_DEVFN(addr)          (((addr) >> PCIE_MMCFG_DEVFN_BIT) & \
-                                         PCIE_MMCFG_DEVFN_MASK)
-#define PCIE_MMCFG_CONFOFFSET(addr)     ((addr) & PCIE_MMCFG_CONFOFFSET_MASK)
-
-
-/* a helper function to get a PCIDevice for a given mmconfig address */
-static inline PCIDevice *pcie_dev_find_by_mmcfg_addr(PCIBus *s,
-                                                     uint32_t mmcfg_addr)
-{
-    return pci_find_device(s, PCIE_MMCFG_BUS(mmcfg_addr),
-                           PCIE_MMCFG_DEVFN(mmcfg_addr));
-}
-
-static void pcie_mmcfg_data_write(void *opaque, hwaddr mmcfg_addr,
-                                  uint64_t val, unsigned len)
-{
-    PCIExpressHost *e = opaque;
-    PCIBus *s = e->pci.bus;
-    PCIDevice *pci_dev = pcie_dev_find_by_mmcfg_addr(s, mmcfg_addr);
-    uint32_t addr;
-    uint32_t limit;
-
-    if (!pci_dev) {
-        return;
-    }
-    addr = PCIE_MMCFG_CONFOFFSET(mmcfg_addr);
-    limit = pci_config_size(pci_dev);
-    if (limit <= addr) {
-        /* conventional pci device can be behind pcie-to-pci bridge.
-           256 <= addr < 4K has no effects. */
-        return;
-    }
-    pci_host_config_write_common(pci_dev, addr, limit, val, len);
-}
-
-static uint64_t pcie_mmcfg_data_read(void *opaque,
-                                     hwaddr mmcfg_addr,
-                                     unsigned len)
-{
-    PCIExpressHost *e = opaque;
-    PCIBus *s = e->pci.bus;
-    PCIDevice *pci_dev = pcie_dev_find_by_mmcfg_addr(s, mmcfg_addr);
-    uint32_t addr;
-    uint32_t limit;
-
-    if (!pci_dev) {
-        return ~0x0;
-    }
-    addr = PCIE_MMCFG_CONFOFFSET(mmcfg_addr);
-    limit = pci_config_size(pci_dev);
-    if (limit <= addr) {
-        /* conventional pci device can be behind pcie-to-pci bridge.
-           256 <= addr < 4K has no effects. */
-        return ~0x0;
-    }
-    return pci_host_config_read_common(pci_dev, addr, limit, len);
-}
-
-static const MemoryRegionOps pcie_mmcfg_ops = {
-    .read = pcie_mmcfg_data_read,
-    .write = pcie_mmcfg_data_write,
-    .endianness = DEVICE_NATIVE_ENDIAN,
-};
-
-/* pcie_host::base_addr == PCIE_BASE_ADDR_UNMAPPED when it isn't mapped. */
-#define PCIE_BASE_ADDR_UNMAPPED  ((hwaddr)-1ULL)
-
-int pcie_host_init(PCIExpressHost *e)
-{
-    e->base_addr = PCIE_BASE_ADDR_UNMAPPED;
-
-    return 0;
-}
-
-void pcie_host_mmcfg_unmap(PCIExpressHost *e)
-{
-    if (e->base_addr != PCIE_BASE_ADDR_UNMAPPED) {
-        memory_region_del_subregion(get_system_memory(), &e->mmio);
-        memory_region_destroy(&e->mmio);
-        e->base_addr = PCIE_BASE_ADDR_UNMAPPED;
-    }
-}
-
-void pcie_host_mmcfg_map(PCIExpressHost *e, hwaddr addr,
-                         uint32_t size)
-{
-    assert(!(size & (size - 1)));       /* power of 2 */
-    assert(size >= PCIE_MMCFG_SIZE_MIN);
-    assert(size <= PCIE_MMCFG_SIZE_MAX);
-    e->size = size;
-    memory_region_init_io(&e->mmio, &pcie_mmcfg_ops, e, "pcie-mmcfg", e->size);
-    e->base_addr = addr;
-    memory_region_add_subregion(get_system_memory(), e->base_addr, &e->mmio);
-}
-
-void pcie_host_mmcfg_update(PCIExpressHost *e,
-                            int enable,
-                            hwaddr addr,
-                            uint32_t size)
-{
-    pcie_host_mmcfg_unmap(e);
-    if (enable) {
-        pcie_host_mmcfg_map(e, addr, size);
-    }
-}
-
-static const TypeInfo pcie_host_type_info = {
-    .name = TYPE_PCIE_HOST_BRIDGE,
-    .parent = TYPE_PCI_HOST_BRIDGE,
-    .abstract = true,
-    .instance_size = sizeof(PCIExpressHost),
-};
-
-static void pcie_host_register_types(void)
-{
-    type_register_static(&pcie_host_type_info);
-}
-
-type_init(pcie_host_register_types)
diff --git a/hw/pcie_host.h b/hw/pcie_host.h
deleted file mode 100644
index 3921935..0000000
--- a/hw/pcie_host.h
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * pcie_host.h
- *
- * Copyright (c) 2009 Isaku Yamahata <yamahata at valinux co jp>
- *                    VA Linux Systems Japan K.K.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
-
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
-
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, see <http://www.gnu.org/licenses/>.
- */
-
-#ifndef PCIE_HOST_H
-#define PCIE_HOST_H
-
-#include "pci_host.h"
-#include "memory.h"
-
-#define TYPE_PCIE_HOST_BRIDGE "pcie-host-bridge"
-#define PCIE_HOST_BRIDGE(obj) \
-    OBJECT_CHECK(PCIExpressHost, (obj), TYPE_PCIE_HOST_BRIDGE)
-
-struct PCIExpressHost {
-    PCIHostState pci;
-
-    /* express part */
-
-    /* base address where MMCONFIG area is mapped. */
-    hwaddr  base_addr;
-
-    /* the size of MMCONFIG area. It's host bridge dependent */
-    hwaddr  size;
-
-    /* MMCONFIG mmio area */
-    MemoryRegion mmio;
-};
-
-int pcie_host_init(PCIExpressHost *e);
-void pcie_host_mmcfg_unmap(PCIExpressHost *e);
-void pcie_host_mmcfg_map(PCIExpressHost *e, hwaddr addr, uint32_t size);
-void pcie_host_mmcfg_update(PCIExpressHost *e,
-                            int enable,
-                            hwaddr addr,
-                            uint32_t size);
-
-#endif /* PCIE_HOST_H */
diff --git a/hw/pcie_port.c b/hw/pcie_port.c
deleted file mode 100644
index d6350e5..0000000
--- a/hw/pcie_port.c
+++ /dev/null
@@ -1,114 +0,0 @@
-/*
- * pcie_port.c
- *
- * Copyright (c) 2010 Isaku Yamahata <yamahata at valinux co jp>
- *                    VA Linux Systems Japan K.K.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, see <http://www.gnu.org/licenses/>.
- */
-
-#include "pcie_port.h"
-
-void pcie_port_init_reg(PCIDevice *d)
-{
-    /* Unlike pci bridge,
-       66MHz and fast back to back don't apply to pci express port. */
-    pci_set_word(d->config + PCI_STATUS, 0);
-    pci_set_word(d->config + PCI_SEC_STATUS, 0);
-
-    /* Unlike conventional pci bridge, some bits are hardwired to 0. */
-    pci_set_word(d->wmask + PCI_BRIDGE_CONTROL,
-                 PCI_BRIDGE_CTL_PARITY |
-                 PCI_BRIDGE_CTL_ISA |
-                 PCI_BRIDGE_CTL_VGA |
-                 PCI_BRIDGE_CTL_SERR |
-                 PCI_BRIDGE_CTL_BUS_RESET);
-}
-
-/**************************************************************************
- * (chassis number, pcie physical slot number) -> pcie slot conversion
- */
-struct PCIEChassis {
-    uint8_t     number;
-
-    QLIST_HEAD(, PCIESlot) slots;
-    QLIST_ENTRY(PCIEChassis) next;
-};
-
-static QLIST_HEAD(, PCIEChassis) chassis = QLIST_HEAD_INITIALIZER(chassis);
-
-static struct PCIEChassis *pcie_chassis_find(uint8_t chassis_number)
-{
-    struct PCIEChassis *c;
-    QLIST_FOREACH(c, &chassis, next) {
-        if (c->number == chassis_number) {
-            break;
-        }
-    }
-    return c;
-}
-
-void pcie_chassis_create(uint8_t chassis_number)
-{
-    struct PCIEChassis *c;
-    c = pcie_chassis_find(chassis_number);
-    if (c) {
-        return;
-    }
-    c = g_malloc0(sizeof(*c));
-    c->number = chassis_number;
-    QLIST_INIT(&c->slots);
-    QLIST_INSERT_HEAD(&chassis, c, next);
-}
-
-static PCIESlot *pcie_chassis_find_slot_with_chassis(struct PCIEChassis *c,
-                                                     uint8_t slot)
-{
-    PCIESlot *s;
-    QLIST_FOREACH(s, &c->slots, next) {
-        if (s->slot == slot) {
-            break;
-        }
-    }
-    return s;
-}
-
-PCIESlot *pcie_chassis_find_slot(uint8_t chassis_number, uint16_t slot)
-{
-    struct PCIEChassis *c;
-    c = pcie_chassis_find(chassis_number);
-    if (!c) {
-        return NULL;
-    }
-    return pcie_chassis_find_slot_with_chassis(c, slot);
-}
-
-int pcie_chassis_add_slot(struct PCIESlot *slot)
-{
-    struct PCIEChassis *c;
-    c = pcie_chassis_find(slot->chassis);
-    if (!c) {
-        return -ENODEV;
-    }
-    if (pcie_chassis_find_slot_with_chassis(c, slot->slot)) {
-        return -EBUSY;
-    }
-    QLIST_INSERT_HEAD(&c->slots, slot, next);
-    return 0;
-}
-
-void pcie_chassis_del_slot(PCIESlot *s)
-{
-    QLIST_REMOVE(s, next);
-}
diff --git a/hw/pcie_port.h b/hw/pcie_port.h
deleted file mode 100644
index 3709583..0000000
--- a/hw/pcie_port.h
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * pcie_port.h
- *
- * Copyright (c) 2010 Isaku Yamahata <yamahata at valinux co jp>
- *                    VA Linux Systems Japan K.K.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, see <http://www.gnu.org/licenses/>.
- */
-
-#ifndef QEMU_PCIE_PORT_H
-#define QEMU_PCIE_PORT_H
-
-#include "pci_bridge.h"
-#include "pci_internals.h"
-
-struct PCIEPort {
-    PCIBridge   br;
-
-    /* pci express switch port */
-    uint8_t     port;
-};
-
-void pcie_port_init_reg(PCIDevice *d);
-
-struct PCIESlot {
-    PCIEPort    port;
-
-    /* pci express switch port with slot */
-    uint8_t     chassis;
-    uint16_t    slot;
-    QLIST_ENTRY(PCIESlot) next;
-};
-
-void pcie_chassis_create(uint8_t chassis_number);
-void pcie_main_chassis_create(void);
-PCIESlot *pcie_chassis_find_slot(uint8_t chassis, uint16_t slot);
-int pcie_chassis_add_slot(struct PCIESlot *slot);
-void pcie_chassis_del_slot(PCIESlot *s);
-
-#endif /* QEMU_PCIE_PORT_H */
diff --git a/hw/pcie_regs.h b/hw/pcie_regs.h
deleted file mode 100644
index 4d123d9..0000000
--- a/hw/pcie_regs.h
+++ /dev/null
@@ -1,156 +0,0 @@
-/*
- * constants for pcie configurations space from pci express spec.
- *
- * TODO:
- * Those constants and macros should go to Linux pci_regs.h
- * Once they're merged, they will go away.
- */
-#ifndef QEMU_PCIE_REGS_H
-#define QEMU_PCIE_REGS_H
-
-
-/* express capability */
-
-#define PCI_EXP_VER2_SIZEOF             0x3c /* express capability of ver. 2 */
-#define PCI_EXT_CAP_VER_SHIFT           16
-#define PCI_EXT_CAP_NEXT_SHIFT          20
-#define PCI_EXT_CAP_NEXT_MASK           (0xffc << PCI_EXT_CAP_NEXT_SHIFT)
-
-#define PCI_EXT_CAP(id, ver, next)                                      \
-    ((id) |                                                             \
-     ((ver) << PCI_EXT_CAP_VER_SHIFT) |                                 \
-     ((next) << PCI_EXT_CAP_NEXT_SHIFT))
-
-#define PCI_EXT_CAP_ALIGN               4
-#define PCI_EXT_CAP_ALIGNUP(x)                                  \
-    (((x) + PCI_EXT_CAP_ALIGN - 1) & ~(PCI_EXT_CAP_ALIGN - 1))
-
-/* PCI_EXP_FLAGS */
-#define PCI_EXP_FLAGS_VER2              2 /* for now, supports only ver. 2 */
-#define PCI_EXP_FLAGS_IRQ_SHIFT         (ffs(PCI_EXP_FLAGS_IRQ) - 1)
-#define PCI_EXP_FLAGS_TYPE_SHIFT        (ffs(PCI_EXP_FLAGS_TYPE) - 1)
-
-
-/* PCI_EXP_LINK{CAP, STA} */
-/* link speed */
-#define PCI_EXP_LNK_LS_25               1
-
-#define PCI_EXP_LNK_MLW_SHIFT           (ffs(PCI_EXP_LNKCAP_MLW) - 1)
-#define PCI_EXP_LNK_MLW_1               (1 << PCI_EXP_LNK_MLW_SHIFT)
-
-/* PCI_EXP_LINKCAP */
-#define PCI_EXP_LNKCAP_ASPMS_SHIFT      (ffs(PCI_EXP_LNKCAP_ASPMS) - 1)
-#define PCI_EXP_LNKCAP_ASPMS_0S         (1 << PCI_EXP_LNKCAP_ASPMS_SHIFT)
-
-#define PCI_EXP_LNKCAP_PN_SHIFT         (ffs(PCI_EXP_LNKCAP_PN) - 1)
-
-#define PCI_EXP_SLTCAP_PSN_SHIFT        (ffs(PCI_EXP_SLTCAP_PSN) - 1)
-
-#define PCI_EXP_SLTCTL_IND_RESERVED     0x0
-#define PCI_EXP_SLTCTL_IND_ON           0x1
-#define PCI_EXP_SLTCTL_IND_BLINK        0x2
-#define PCI_EXP_SLTCTL_IND_OFF          0x3
-#define PCI_EXP_SLTCTL_AIC_SHIFT        (ffs(PCI_EXP_SLTCTL_AIC) - 1)
-#define PCI_EXP_SLTCTL_AIC_OFF                          \
-    (PCI_EXP_SLTCTL_IND_OFF << PCI_EXP_SLTCTL_AIC_SHIFT)
-
-#define PCI_EXP_SLTCTL_PIC_SHIFT        (ffs(PCI_EXP_SLTCTL_PIC) - 1)
-#define PCI_EXP_SLTCTL_PIC_OFF                          \
-    (PCI_EXP_SLTCTL_IND_OFF << PCI_EXP_SLTCTL_PIC_SHIFT)
-
-#define PCI_EXP_SLTCTL_SUPPORTED        \
-            (PCI_EXP_SLTCTL_ABPE |      \
-             PCI_EXP_SLTCTL_PDCE |      \
-             PCI_EXP_SLTCTL_CCIE |      \
-             PCI_EXP_SLTCTL_HPIE |      \
-             PCI_EXP_SLTCTL_AIC |       \
-             PCI_EXP_SLTCTL_PCC |       \
-             PCI_EXP_SLTCTL_EIC)
-
-#define PCI_EXP_DEVCAP2_EFF             0x100000
-#define PCI_EXP_DEVCAP2_EETLPP          0x200000
-
-#define PCI_EXP_DEVCTL2_EETLPPB         0x80
-
-/* ARI */
-#define PCI_ARI_VER                     1
-#define PCI_ARI_SIZEOF                  8
-
-/* AER */
-#define PCI_ERR_VER                     2
-#define PCI_ERR_SIZEOF                  0x48
-
-#define PCI_ERR_UNC_SDN                 0x00000020      /* surprise down */
-#define PCI_ERR_UNC_ACSV                0x00200000      /* ACS Violation */
-#define PCI_ERR_UNC_INTN                0x00400000      /* Internal Error */
-#define PCI_ERR_UNC_MCBTLP              0x00800000      /* MC Blcoked TLP */
-#define PCI_ERR_UNC_ATOP_EBLOCKED       0x01000000      /* atomic op egress 
blocked */
-#define PCI_ERR_UNC_TLP_PRF_BLOCKED     0x02000000      /* TLP Prefix Blocked 
*/
-#define PCI_ERR_COR_ADV_NONFATAL        0x00002000      /* Advisory Non-Fatal 
*/
-#define PCI_ERR_COR_INTERNAL            0x00004000      /* Corrected Internal 
*/
-#define PCI_ERR_COR_HL_OVERFLOW         0x00008000      /* Header Long 
Overflow */
-#define PCI_ERR_CAP_FEP_MASK            0x0000001f
-#define PCI_ERR_CAP_MHRC                0x00000200
-#define PCI_ERR_CAP_MHRE                0x00000400
-#define PCI_ERR_CAP_TLP                 0x00000800
-
-#define PCI_ERR_HEADER_LOG_SIZE         16
-#define PCI_ERR_TLP_PREFIX_LOG          0x38
-#define PCI_ERR_TLP_PREFIX_LOG_SIZE     16
-
-#define PCI_SEC_STATUS_RCV_SYSTEM_ERROR         0x4000
-
-/* aer root error command/status */
-#define PCI_ERR_ROOT_CMD_EN_MASK        (PCI_ERR_ROOT_CMD_COR_EN |      \
-                                         PCI_ERR_ROOT_CMD_NONFATAL_EN | \
-                                         PCI_ERR_ROOT_CMD_FATAL_EN)
-
-#define PCI_ERR_ROOT_IRQ_MAX            32
-#define PCI_ERR_ROOT_IRQ                0xf8000000
-#define PCI_ERR_ROOT_IRQ_SHIFT          (ffs(PCI_ERR_ROOT_IRQ) - 1)
-#define PCI_ERR_ROOT_STATUS_REPORT_MASK (PCI_ERR_ROOT_COR_RCV |         \
-                                         PCI_ERR_ROOT_MULTI_COR_RCV |   \
-                                         PCI_ERR_ROOT_UNCOR_RCV |       \
-                                         PCI_ERR_ROOT_MULTI_UNCOR_RCV | \
-                                         PCI_ERR_ROOT_FIRST_FATAL |     \
-                                         PCI_ERR_ROOT_NONFATAL_RCV |    \
-                                         PCI_ERR_ROOT_FATAL_RCV)
-
-#define PCI_ERR_UNC_SUPPORTED           (PCI_ERR_UNC_DLP |              \
-                                         PCI_ERR_UNC_SDN |              \
-                                         PCI_ERR_UNC_POISON_TLP |       \
-                                         PCI_ERR_UNC_FCP |              \
-                                         PCI_ERR_UNC_COMP_TIME |        \
-                                         PCI_ERR_UNC_COMP_ABORT |       \
-                                         PCI_ERR_UNC_UNX_COMP |         \
-                                         PCI_ERR_UNC_RX_OVER |          \
-                                         PCI_ERR_UNC_MALF_TLP |         \
-                                         PCI_ERR_UNC_ECRC |             \
-                                         PCI_ERR_UNC_UNSUP |            \
-                                         PCI_ERR_UNC_ACSV |             \
-                                         PCI_ERR_UNC_INTN |             \
-                                         PCI_ERR_UNC_MCBTLP |           \
-                                         PCI_ERR_UNC_ATOP_EBLOCKED |    \
-                                         PCI_ERR_UNC_TLP_PRF_BLOCKED)
-
-#define PCI_ERR_UNC_SEVERITY_DEFAULT    (PCI_ERR_UNC_DLP |              \
-                                         PCI_ERR_UNC_SDN |              \
-                                         PCI_ERR_UNC_FCP |              \
-                                         PCI_ERR_UNC_RX_OVER |          \
-                                         PCI_ERR_UNC_MALF_TLP |         \
-                                         PCI_ERR_UNC_INTN)
-
-#define PCI_ERR_COR_SUPPORTED           (PCI_ERR_COR_RCVR |             \
-                                         PCI_ERR_COR_BAD_TLP |          \
-                                         PCI_ERR_COR_BAD_DLLP |         \
-                                         PCI_ERR_COR_REP_ROLL |         \
-                                         PCI_ERR_COR_REP_TIMER |        \
-                                         PCI_ERR_COR_ADV_NONFATAL |     \
-                                         PCI_ERR_COR_INTERNAL |         \
-                                         PCI_ERR_COR_HL_OVERFLOW)
-
-#define PCI_ERR_COR_MASK_DEFAULT        (PCI_ERR_COR_ADV_NONFATAL |     \
-                                         PCI_ERR_COR_INTERNAL |         \
-                                         PCI_ERR_COR_HL_OVERFLOW)
-
-#endif /* QEMU_PCIE_REGS_H */
diff --git a/hw/ppc/Makefile.objs b/hw/ppc/Makefile.objs
index 8fe2123..cb7cf8f 100644
--- a/hw/ppc/Makefile.objs
+++ b/hw/ppc/Makefile.objs
@@ -10,7 +10,7 @@ obj-y += ppc_newworld.o
 # IBM pSeries (sPAPR)
 obj-$(CONFIG_PSERIES) += spapr.o spapr_hcall.o spapr_rtas.o spapr_vio.o
 obj-$(CONFIG_PSERIES) += xics.o spapr_vty.o spapr_llan.o spapr_vscsi.o
-obj-$(CONFIG_PSERIES) += spapr_pci.o pci-hotplug.o spapr_iommu.o
+obj-$(CONFIG_PSERIES) += spapr_pci.o pci/pci-hotplug.o spapr_iommu.o
 obj-$(CONFIG_PSERIES) += spapr_events.o
 # PowerPC 4xx boards
 obj-y += ppc4xx_devs.o ppc4xx_pci.o ppc405_uc.o ppc405_boards.o
diff --git a/hw/shpc.c b/hw/shpc.c
deleted file mode 100644
index 4597bbd..0000000
--- a/hw/shpc.c
+++ /dev/null
@@ -1,681 +0,0 @@
-#include <strings.h>
-#include <stdint.h>
-#include "range.h"
-#include "range.h"
-#include "shpc.h"
-#include "pci.h"
-#include "pci_internals.h"
-#include "msi.h"
-
-/* TODO: model power only and disabled slot states. */
-/* TODO: handle SERR and wakeups */
-/* TODO: consider enabling 66MHz support */
-
-/* TODO: remove fully only on state DISABLED and LED off.
- * track state to properly record this. */
-
-/* SHPC Working Register Set */
-#define SHPC_BASE_OFFSET  0x00 /* 4 bytes */
-#define SHPC_SLOTS_33     0x04 /* 4 bytes. Also encodes PCI-X slots. */
-#define SHPC_SLOTS_66     0x08 /* 4 bytes. */
-#define SHPC_NSLOTS       0x0C /* 1 byte */
-#define SHPC_FIRST_DEV    0x0D /* 1 byte */
-#define SHPC_PHYS_SLOT    0x0E /* 2 byte */
-#define SHPC_PHYS_NUM_MAX 0x7ff
-#define SHPC_PHYS_NUM_UP  0x2000
-#define SHPC_PHYS_MRL     0x4000
-#define SHPC_PHYS_BUTTON  0x8000
-#define SHPC_SEC_BUS      0x10 /* 2 bytes */
-#define SHPC_SEC_BUS_33   0x0
-#define SHPC_SEC_BUS_66   0x1 /* Unused */
-#define SHPC_SEC_BUS_MASK 0x7
-#define SHPC_MSI_CTL      0x12 /* 1 byte */
-#define SHPC_PROG_IFC     0x13 /* 1 byte */
-#define SHPC_PROG_IFC_1_0 0x1
-#define SHPC_CMD_CODE     0x14 /* 1 byte */
-#define SHPC_CMD_TRGT     0x15 /* 1 byte */
-#define SHPC_CMD_TRGT_MIN 0x1
-#define SHPC_CMD_TRGT_MAX 0x1f
-#define SHPC_CMD_STATUS   0x16 /* 2 bytes */
-#define SHPC_CMD_STATUS_BUSY          0x1
-#define SHPC_CMD_STATUS_MRL_OPEN      0x2
-#define SHPC_CMD_STATUS_INVALID_CMD   0x4
-#define SHPC_CMD_STATUS_INVALID_MODE  0x8
-#define SHPC_INT_LOCATOR  0x18 /* 4 bytes */
-#define SHPC_INT_COMMAND  0x1
-#define SHPC_SERR_LOCATOR 0x1C /* 4 bytes */
-#define SHPC_SERR_INT     0x20 /* 4 bytes */
-#define SHPC_INT_DIS      0x1
-#define SHPC_SERR_DIS     0x2
-#define SHPC_CMD_INT_DIS  0x4
-#define SHPC_ARB_SERR_DIS 0x8
-#define SHPC_CMD_DETECTED 0x10000
-#define SHPC_ARB_DETECTED 0x20000
- /* 4 bytes * slot # (start from 0) */
-#define SHPC_SLOT_REG(s)         (0x24 + (s) * 4)
- /* 2 bytes */
-#define SHPC_SLOT_STATUS(s)       (0x0 + SHPC_SLOT_REG(s))
-
-/* Same slot state masks are used for command and status registers */
-#define SHPC_SLOT_STATE_MASK     0x03
-#define SHPC_SLOT_STATE_SHIFT \
-    (ffs(SHPC_SLOT_STATE_MASK) - 1)
-
-#define SHPC_STATE_NO       0x0
-#define SHPC_STATE_PWRONLY  0x1
-#define SHPC_STATE_ENABLED  0x2
-#define SHPC_STATE_DISABLED 0x3
-
-#define SHPC_SLOT_PWR_LED_MASK   0xC
-#define SHPC_SLOT_PWR_LED_SHIFT \
-    (ffs(SHPC_SLOT_PWR_LED_MASK) - 1)
-#define SHPC_SLOT_ATTN_LED_MASK  0x30
-#define SHPC_SLOT_ATTN_LED_SHIFT \
-    (ffs(SHPC_SLOT_ATTN_LED_MASK) - 1)
-
-#define SHPC_LED_NO     0x0
-#define SHPC_LED_ON     0x1
-#define SHPC_LED_BLINK  0x2
-#define SHPC_LED_OFF    0x3
-
-#define SHPC_SLOT_STATUS_PWR_FAULT      0x40
-#define SHPC_SLOT_STATUS_BUTTON         0x80
-#define SHPC_SLOT_STATUS_MRL_OPEN       0x100
-#define SHPC_SLOT_STATUS_66             0x200
-#define SHPC_SLOT_STATUS_PRSNT_MASK     0xC00
-#define SHPC_SLOT_STATUS_PRSNT_EMPTY    0x3
-#define SHPC_SLOT_STATUS_PRSNT_25W      0x1
-#define SHPC_SLOT_STATUS_PRSNT_15W      0x2
-#define SHPC_SLOT_STATUS_PRSNT_7_5W     0x0
-
-#define SHPC_SLOT_STATUS_PRSNT_PCIX     0x3000
-
-
- /* 1 byte */
-#define SHPC_SLOT_EVENT_LATCH(s)        (0x2 + SHPC_SLOT_REG(s))
- /* 1 byte */
-#define SHPC_SLOT_EVENT_SERR_INT_DIS(d, s) (0x3 + SHPC_SLOT_REG(s))
-#define SHPC_SLOT_EVENT_PRESENCE        0x01
-#define SHPC_SLOT_EVENT_ISOLATED_FAULT  0x02
-#define SHPC_SLOT_EVENT_BUTTON          0x04
-#define SHPC_SLOT_EVENT_MRL             0x08
-#define SHPC_SLOT_EVENT_CONNECTED_FAULT 0x10
-/* Bits below are used for Serr/Int disable only */
-#define SHPC_SLOT_EVENT_MRL_SERR_DIS    0x20
-#define SHPC_SLOT_EVENT_CONNECTED_FAULT_SERR_DIS 0x40
-
-#define SHPC_MIN_SLOTS        1
-#define SHPC_MAX_SLOTS        31
-#define SHPC_SIZEOF(d)    SHPC_SLOT_REG((d)->shpc->nslots)
-
-/* SHPC Slot identifiers */
-
-/* Hotplug supported at 31 slots out of the total 32.  We reserve slot 0,
-   and give the rest of them physical *and* pci numbers starting from 1, so
-   they match logical numbers.  Note: this means that multiple slots must have
-   different chassis number values, to make chassis+physical slot unique.
-   TODO: make this configurable? */
-#define SHPC_IDX_TO_LOGICAL(slot) ((slot) + 1)
-#define SHPC_LOGICAL_TO_IDX(target) ((target) - 1)
-#define SHPC_IDX_TO_PCI(slot) ((slot) + 1)
-#define SHPC_PCI_TO_IDX(pci_slot) ((pci_slot) - 1)
-#define SHPC_IDX_TO_PHYSICAL(slot) ((slot) + 1)
-
-static int roundup_pow_of_two(int x)
-{
-    x |= (x >> 1);
-    x |= (x >> 2);
-    x |= (x >> 4);
-    x |= (x >> 8);
-    x |= (x >> 16);
-    return x + 1;
-}
-
-static uint16_t shpc_get_status(SHPCDevice *shpc, int slot, uint16_t msk)
-{
-    uint8_t *status = shpc->config + SHPC_SLOT_STATUS(slot);
-    return (pci_get_word(status) & msk) >> (ffs(msk) - 1);
-}
-
-static void shpc_set_status(SHPCDevice *shpc,
-                            int slot, uint8_t value, uint16_t msk)
-{
-    uint8_t *status = shpc->config + SHPC_SLOT_STATUS(slot);
-    pci_word_test_and_clear_mask(status, msk);
-    pci_word_test_and_set_mask(status, value << (ffs(msk) - 1));
-}
-
-static void shpc_interrupt_update(PCIDevice *d)
-{
-    SHPCDevice *shpc = d->shpc;
-    int slot;
-    int level = 0;
-    uint32_t serr_int;
-    uint32_t int_locator = 0;
-
-    /* Update interrupt locator register */
-    for (slot = 0; slot < shpc->nslots; ++slot) {
-        uint8_t event = shpc->config[SHPC_SLOT_EVENT_LATCH(slot)];
-        uint8_t disable = shpc->config[SHPC_SLOT_EVENT_SERR_INT_DIS(d, slot)];
-        uint32_t mask = 1 << SHPC_IDX_TO_LOGICAL(slot);
-        if (event & ~disable) {
-            int_locator |= mask;
-        }
-    }
-    serr_int = pci_get_long(shpc->config + SHPC_SERR_INT);
-    if ((serr_int & SHPC_CMD_DETECTED) && !(serr_int & SHPC_CMD_INT_DIS)) {
-        int_locator |= SHPC_INT_COMMAND;
-    }
-    pci_set_long(shpc->config + SHPC_INT_LOCATOR, int_locator);
-    level = (!(serr_int & SHPC_INT_DIS) && int_locator) ? 1 : 0;
-    if (msi_enabled(d) && shpc->msi_requested != level)
-        msi_notify(d, 0);
-    else
-        qemu_set_irq(d->irq[0], level);
-    shpc->msi_requested = level;
-}
-
-static void shpc_set_sec_bus_speed(SHPCDevice *shpc, uint8_t speed)
-{
-    switch (speed) {
-    case SHPC_SEC_BUS_33:
-        shpc->config[SHPC_SEC_BUS] &= ~SHPC_SEC_BUS_MASK;
-        shpc->config[SHPC_SEC_BUS] |= speed;
-        break;
-    default:
-        pci_word_test_and_set_mask(shpc->config + SHPC_CMD_STATUS,
-                                   SHPC_CMD_STATUS_INVALID_MODE);
-    }
-}
-
-void shpc_reset(PCIDevice *d)
-{
-    SHPCDevice *shpc = d->shpc;
-    int nslots = shpc->nslots;
-    int i;
-    memset(shpc->config, 0, SHPC_SIZEOF(d));
-    pci_set_byte(shpc->config + SHPC_NSLOTS, nslots);
-    pci_set_long(shpc->config + SHPC_SLOTS_33, nslots);
-    pci_set_long(shpc->config + SHPC_SLOTS_66, 0);
-    pci_set_byte(shpc->config + SHPC_FIRST_DEV, SHPC_IDX_TO_PCI(0));
-    pci_set_word(shpc->config + SHPC_PHYS_SLOT,
-                 SHPC_IDX_TO_PHYSICAL(0) |
-                 SHPC_PHYS_NUM_UP |
-                 SHPC_PHYS_MRL |
-                 SHPC_PHYS_BUTTON);
-    pci_set_long(shpc->config + SHPC_SERR_INT, SHPC_INT_DIS |
-                 SHPC_SERR_DIS |
-                 SHPC_CMD_INT_DIS |
-                 SHPC_ARB_SERR_DIS);
-    pci_set_byte(shpc->config + SHPC_PROG_IFC, SHPC_PROG_IFC_1_0);
-    pci_set_word(shpc->config + SHPC_SEC_BUS, SHPC_SEC_BUS_33);
-    for (i = 0; i < shpc->nslots; ++i) {
-        pci_set_byte(shpc->config + SHPC_SLOT_EVENT_SERR_INT_DIS(d, i),
-                     SHPC_SLOT_EVENT_PRESENCE |
-                     SHPC_SLOT_EVENT_ISOLATED_FAULT |
-                     SHPC_SLOT_EVENT_BUTTON |
-                     SHPC_SLOT_EVENT_MRL |
-                     SHPC_SLOT_EVENT_CONNECTED_FAULT |
-                     SHPC_SLOT_EVENT_MRL_SERR_DIS |
-                     SHPC_SLOT_EVENT_CONNECTED_FAULT_SERR_DIS);
-        if (shpc->sec_bus->devices[PCI_DEVFN(SHPC_IDX_TO_PCI(i), 0)]) {
-            shpc_set_status(shpc, i, SHPC_STATE_ENABLED, SHPC_SLOT_STATE_MASK);
-            shpc_set_status(shpc, i, 0, SHPC_SLOT_STATUS_MRL_OPEN);
-            shpc_set_status(shpc, i, SHPC_SLOT_STATUS_PRSNT_7_5W,
-                            SHPC_SLOT_STATUS_PRSNT_MASK);
-            shpc_set_status(shpc, i, SHPC_LED_ON, SHPC_SLOT_PWR_LED_MASK);
-        } else {
-            shpc_set_status(shpc, i, SHPC_STATE_DISABLED, 
SHPC_SLOT_STATE_MASK);
-            shpc_set_status(shpc, i, 1, SHPC_SLOT_STATUS_MRL_OPEN);
-            shpc_set_status(shpc, i, SHPC_SLOT_STATUS_PRSNT_EMPTY,
-                            SHPC_SLOT_STATUS_PRSNT_MASK);
-            shpc_set_status(shpc, i, SHPC_LED_OFF, SHPC_SLOT_PWR_LED_MASK);
-        }
-        shpc_set_status(shpc, i, 0, SHPC_SLOT_STATUS_66);
-    }
-    shpc_set_sec_bus_speed(shpc, SHPC_SEC_BUS_33);
-    shpc->msi_requested = 0;
-    shpc_interrupt_update(d);
-}
-
-static void shpc_invalid_command(SHPCDevice *shpc)
-{
-    pci_word_test_and_set_mask(shpc->config + SHPC_CMD_STATUS,
-                               SHPC_CMD_STATUS_INVALID_CMD);
-}
-
-static void shpc_free_devices_in_slot(SHPCDevice *shpc, int slot)
-{
-    int devfn;
-    int pci_slot = SHPC_IDX_TO_PCI(slot);
-    for (devfn = PCI_DEVFN(pci_slot, 0);
-         devfn <= PCI_DEVFN(pci_slot, PCI_FUNC_MAX - 1);
-         ++devfn) {
-        PCIDevice *affected_dev = shpc->sec_bus->devices[devfn];
-        if (affected_dev) {
-            qdev_free(&affected_dev->qdev);
-        }
-    }
-}
-
-static void shpc_slot_command(SHPCDevice *shpc, uint8_t target,
-                              uint8_t state, uint8_t power, uint8_t attn)
-{
-    uint8_t current_state;
-    int slot = SHPC_LOGICAL_TO_IDX(target);
-    if (target < SHPC_CMD_TRGT_MIN || slot >= shpc->nslots) {
-        shpc_invalid_command(shpc);
-        return;
-    }
-    current_state = shpc_get_status(shpc, slot, SHPC_SLOT_STATE_MASK);
-    if (current_state == SHPC_STATE_ENABLED && state == SHPC_STATE_PWRONLY) {
-        shpc_invalid_command(shpc);
-        return;
-    }
-
-    switch (power) {
-    case SHPC_LED_NO:
-        break;
-    default:
-        /* TODO: send event to monitor */
-        shpc_set_status(shpc, slot, power, SHPC_SLOT_PWR_LED_MASK);
-    }
-    switch (attn) {
-    case SHPC_LED_NO:
-        break;
-    default:
-        /* TODO: send event to monitor */
-        shpc_set_status(shpc, slot, attn, SHPC_SLOT_ATTN_LED_MASK);
-    }
-
-    if ((current_state == SHPC_STATE_DISABLED && state == SHPC_STATE_PWRONLY) 
||
-        (current_state == SHPC_STATE_DISABLED && state == SHPC_STATE_ENABLED)) 
{
-        shpc_set_status(shpc, slot, state, SHPC_SLOT_STATE_MASK);
-    } else if ((current_state == SHPC_STATE_ENABLED ||
-                current_state == SHPC_STATE_PWRONLY) &&
-               state == SHPC_STATE_DISABLED) {
-        shpc_set_status(shpc, slot, state, SHPC_SLOT_STATE_MASK);
-        power = shpc_get_status(shpc, slot, SHPC_SLOT_PWR_LED_MASK);
-        /* TODO: track what monitor requested. */
-        /* Look at LED to figure out whether it's ok to remove the device. */
-        if (power == SHPC_LED_OFF) {
-            shpc_free_devices_in_slot(shpc, slot);
-            shpc_set_status(shpc, slot, 1, SHPC_SLOT_STATUS_MRL_OPEN);
-            shpc_set_status(shpc, slot, SHPC_SLOT_STATUS_PRSNT_EMPTY,
-                            SHPC_SLOT_STATUS_PRSNT_MASK);
-            shpc->config[SHPC_SLOT_EVENT_LATCH(slot)] |=
-                SHPC_SLOT_EVENT_BUTTON |
-                SHPC_SLOT_EVENT_MRL |
-                SHPC_SLOT_EVENT_PRESENCE;
-        }
-    }
-}
-
-static void shpc_command(SHPCDevice *shpc)
-{
-    uint8_t code = pci_get_byte(shpc->config + SHPC_CMD_CODE);
-    uint8_t speed;
-    uint8_t target;
-    uint8_t attn;
-    uint8_t power;
-    uint8_t state;
-    int i;
-
-    /* Clear status from the previous command. */
-    pci_word_test_and_clear_mask(shpc->config + SHPC_CMD_STATUS,
-                                 SHPC_CMD_STATUS_BUSY |
-                                 SHPC_CMD_STATUS_MRL_OPEN |
-                                 SHPC_CMD_STATUS_INVALID_CMD |
-                                 SHPC_CMD_STATUS_INVALID_MODE);
-    switch (code) {
-    case 0x00 ... 0x3f:
-        target = shpc->config[SHPC_CMD_TRGT] & SHPC_CMD_TRGT_MAX;
-        state = (code & SHPC_SLOT_STATE_MASK) >> SHPC_SLOT_STATE_SHIFT;
-        power = (code & SHPC_SLOT_PWR_LED_MASK) >> SHPC_SLOT_PWR_LED_SHIFT;
-        attn = (code & SHPC_SLOT_ATTN_LED_MASK) >> SHPC_SLOT_ATTN_LED_SHIFT;
-        shpc_slot_command(shpc, target, state, power, attn);
-        break;
-    case 0x40 ... 0x47:
-        speed = code & SHPC_SEC_BUS_MASK;
-        shpc_set_sec_bus_speed(shpc, speed);
-        break;
-    case 0x48:
-        /* Power only all slots */
-        /* first verify no slots are enabled */
-        for (i = 0; i < shpc->nslots; ++i) {
-            state = shpc_get_status(shpc, i, SHPC_SLOT_STATE_MASK);
-            if (state == SHPC_STATE_ENABLED) {
-                shpc_invalid_command(shpc);
-                goto done;
-            }
-        }
-        for (i = 0; i < shpc->nslots; ++i) {
-            if (!(shpc_get_status(shpc, i, SHPC_SLOT_STATUS_MRL_OPEN))) {
-                shpc_slot_command(shpc, i + SHPC_CMD_TRGT_MIN,
-                                  SHPC_STATE_PWRONLY, SHPC_LED_ON, 
SHPC_LED_NO);
-            } else {
-                shpc_slot_command(shpc, i + SHPC_CMD_TRGT_MIN,
-                                  SHPC_STATE_NO, SHPC_LED_OFF, SHPC_LED_NO);
-            }
-        }
-        break;
-    case 0x49:
-        /* Enable all slots */
-        /* TODO: Spec says this shall fail if some are already enabled.
-         * This doesn't make sense - why not? a spec bug? */
-        for (i = 0; i < shpc->nslots; ++i) {
-            state = shpc_get_status(shpc, i, SHPC_SLOT_STATE_MASK);
-            if (state == SHPC_STATE_ENABLED) {
-                shpc_invalid_command(shpc);
-                goto done;
-            }
-        }
-        for (i = 0; i < shpc->nslots; ++i) {
-            if (!(shpc_get_status(shpc, i, SHPC_SLOT_STATUS_MRL_OPEN))) {
-                shpc_slot_command(shpc, i + SHPC_CMD_TRGT_MIN,
-                                  SHPC_STATE_ENABLED, SHPC_LED_ON, 
SHPC_LED_NO);
-            } else {
-                shpc_slot_command(shpc, i + SHPC_CMD_TRGT_MIN,
-                                  SHPC_STATE_NO, SHPC_LED_OFF, SHPC_LED_NO);
-            }
-        }
-        break;
-    default:
-        shpc_invalid_command(shpc);
-        break;
-    }
-done:
-    pci_long_test_and_set_mask(shpc->config + SHPC_SERR_INT, 
SHPC_CMD_DETECTED);
-}
-
-static void shpc_write(PCIDevice *d, unsigned addr, uint64_t val, int l)
-{
-    SHPCDevice *shpc = d->shpc;
-    int i;
-    if (addr >= SHPC_SIZEOF(d)) {
-        return;
-    }
-    l = MIN(l, SHPC_SIZEOF(d) - addr);
-
-    /* TODO: code duplicated from pci.c */
-    for (i = 0; i < l; val >>= 8, ++i) {
-        unsigned a = addr + i;
-        uint8_t wmask = shpc->wmask[a];
-        uint8_t w1cmask = shpc->w1cmask[a];
-        assert(!(wmask & w1cmask));
-        shpc->config[a] = (shpc->config[a] & ~wmask) | (val & wmask);
-        shpc->config[a] &= ~(val & w1cmask); /* W1C: Write 1 to Clear */
-    }
-    if (ranges_overlap(addr, l, SHPC_CMD_CODE, 2)) {
-        shpc_command(shpc);
-    }
-    shpc_interrupt_update(d);
-}
-
-static uint64_t shpc_read(PCIDevice *d, unsigned addr, int l)
-{
-    uint64_t val = 0x0;
-    if (addr >= SHPC_SIZEOF(d)) {
-        return val;
-    }
-    l = MIN(l, SHPC_SIZEOF(d) - addr);
-    memcpy(&val, d->shpc->config + addr, l);
-    return val;
-}
-
-/* SHPC Bridge Capability */
-#define SHPC_CAP_LENGTH 0x08
-#define SHPC_CAP_DWORD_SELECT 0x2 /* 1 byte */
-#define SHPC_CAP_CxP 0x3 /* 1 byte: CSP, CIP */
-#define SHPC_CAP_DWORD_DATA 0x4 /* 4 bytes */
-#define SHPC_CAP_CSP_MASK 0x4
-#define SHPC_CAP_CIP_MASK 0x8
-
-static uint8_t shpc_cap_dword(PCIDevice *d)
-{
-    return pci_get_byte(d->config + d->shpc->cap + SHPC_CAP_DWORD_SELECT);
-}
-
-/* Update dword data capability register */
-static void shpc_cap_update_dword(PCIDevice *d)
-{
-    unsigned data;
-    data = shpc_read(d, shpc_cap_dword(d) * 4, 4);
-    pci_set_long(d->config  + d->shpc->cap + SHPC_CAP_DWORD_DATA, data);
-}
-
-/* Add SHPC capability to the config space for the device. */
-static int shpc_cap_add_config(PCIDevice *d)
-{
-    uint8_t *config;
-    int config_offset;
-    config_offset = pci_add_capability(d, PCI_CAP_ID_SHPC,
-                                       0, SHPC_CAP_LENGTH);
-    if (config_offset < 0) {
-        return config_offset;
-    }
-    config = d->config + config_offset;
-
-    pci_set_byte(config + SHPC_CAP_DWORD_SELECT, 0);
-    pci_set_byte(config + SHPC_CAP_CxP, 0);
-    pci_set_long(config + SHPC_CAP_DWORD_DATA, 0);
-    d->shpc->cap = config_offset;
-    /* Make dword select and data writeable. */
-    pci_set_byte(d->wmask + config_offset + SHPC_CAP_DWORD_SELECT, 0xff);
-    pci_set_long(d->wmask + config_offset + SHPC_CAP_DWORD_DATA, 0xffffffff);
-    return 0;
-}
-
-static uint64_t shpc_mmio_read(void *opaque, hwaddr addr,
-                               unsigned size)
-{
-    return shpc_read(opaque, addr, size);
-}
-
-static void shpc_mmio_write(void *opaque, hwaddr addr,
-                            uint64_t val, unsigned size)
-{
-    shpc_write(opaque, addr, val, size);
-}
-
-static const MemoryRegionOps shpc_mmio_ops = {
-    .read = shpc_mmio_read,
-    .write = shpc_mmio_write,
-    .endianness = DEVICE_LITTLE_ENDIAN,
-    .valid = {
-        /* SHPC ECN requires dword accesses, but the original 1.0 spec doesn't.
-         * It's easier to suppport all sizes than worry about it. */
-        .min_access_size = 1,
-        .max_access_size = 4,
-    },
-};
-
-static int shpc_device_hotplug(DeviceState *qdev, PCIDevice *affected_dev,
-                               PCIHotplugState hotplug_state)
-{
-    int pci_slot = PCI_SLOT(affected_dev->devfn);
-    uint8_t state;
-    uint8_t led;
-    PCIDevice *d = DO_UPCAST(PCIDevice, qdev, qdev);
-    SHPCDevice *shpc = d->shpc;
-    int slot = SHPC_PCI_TO_IDX(pci_slot);
-    if (pci_slot < SHPC_IDX_TO_PCI(0) || slot >= shpc->nslots) {
-        error_report("Unsupported PCI slot %d for standard hotplug "
-                     "controller. Valid slots are between %d and %d.",
-                     pci_slot, SHPC_IDX_TO_PCI(0),
-                     SHPC_IDX_TO_PCI(shpc->nslots) - 1);
-        return -1;
-    }
-    /* Don't send event when device is enabled during qemu machine creation:
-     * it is present on boot, no hotplug event is necessary. We do send an
-     * event when the device is disabled later. */
-    if (hotplug_state == PCI_COLDPLUG_ENABLED) {
-        shpc_set_status(shpc, slot, 0, SHPC_SLOT_STATUS_MRL_OPEN);
-        shpc_set_status(shpc, slot, SHPC_SLOT_STATUS_PRSNT_7_5W,
-                        SHPC_SLOT_STATUS_PRSNT_MASK);
-        return 0;
-    }
-    if (hotplug_state == PCI_HOTPLUG_DISABLED) {
-        shpc->config[SHPC_SLOT_EVENT_LATCH(slot)] |= SHPC_SLOT_EVENT_BUTTON;
-        state = shpc_get_status(shpc, slot, SHPC_SLOT_STATE_MASK);
-        led = shpc_get_status(shpc, slot, SHPC_SLOT_PWR_LED_MASK);
-        if (state == SHPC_STATE_DISABLED && led == SHPC_LED_OFF) {
-            shpc_free_devices_in_slot(shpc, slot);
-            shpc_set_status(shpc, slot, 1, SHPC_SLOT_STATUS_MRL_OPEN);
-            shpc_set_status(shpc, slot, SHPC_SLOT_STATUS_PRSNT_EMPTY,
-                            SHPC_SLOT_STATUS_PRSNT_MASK);
-            shpc->config[SHPC_SLOT_EVENT_LATCH(slot)] |=
-                SHPC_SLOT_EVENT_MRL |
-                SHPC_SLOT_EVENT_PRESENCE;
-        }
-    } else {
-        /* This could be a cancellation of the previous removal.
-         * We check MRL state to figure out. */
-        if (shpc_get_status(shpc, slot, SHPC_SLOT_STATUS_MRL_OPEN)) {
-            shpc_set_status(shpc, slot, 0, SHPC_SLOT_STATUS_MRL_OPEN);
-            shpc_set_status(shpc, slot, SHPC_SLOT_STATUS_PRSNT_7_5W,
-                            SHPC_SLOT_STATUS_PRSNT_MASK);
-            shpc->config[SHPC_SLOT_EVENT_LATCH(slot)] |=
-                SHPC_SLOT_EVENT_BUTTON |
-                SHPC_SLOT_EVENT_MRL |
-                SHPC_SLOT_EVENT_PRESENCE;
-        } else {
-            /* Press attention button to cancel removal */
-            shpc->config[SHPC_SLOT_EVENT_LATCH(slot)] |=
-                SHPC_SLOT_EVENT_BUTTON;
-        }
-    }
-    shpc_set_status(shpc, slot, 0, SHPC_SLOT_STATUS_66);
-    shpc_interrupt_update(d);
-    return 0;
-}
-
-/* Initialize the SHPC structure in bridge's BAR. */
-int shpc_init(PCIDevice *d, PCIBus *sec_bus, MemoryRegion *bar, unsigned 
offset)
-{
-    int i, ret;
-    int nslots = SHPC_MAX_SLOTS; /* TODO: qdev property? */
-    SHPCDevice *shpc = d->shpc = g_malloc0(sizeof(*d->shpc));
-    shpc->sec_bus = sec_bus;
-    ret = shpc_cap_add_config(d);
-    if (ret) {
-        g_free(d->shpc);
-        return ret;
-    }
-    if (nslots < SHPC_MIN_SLOTS) {
-        return 0;
-    }
-    if (nslots > SHPC_MAX_SLOTS ||
-        SHPC_IDX_TO_PCI(nslots) > PCI_SLOT_MAX) {
-        /* TODO: report an error mesage that makes sense. */
-        return -EINVAL;
-    }
-    shpc->nslots = nslots;
-    shpc->config = g_malloc0(SHPC_SIZEOF(d));
-    shpc->cmask = g_malloc0(SHPC_SIZEOF(d));
-    shpc->wmask = g_malloc0(SHPC_SIZEOF(d));
-    shpc->w1cmask = g_malloc0(SHPC_SIZEOF(d));
-
-    shpc_reset(d);
-
-    pci_set_long(shpc->config + SHPC_BASE_OFFSET, offset);
-
-    pci_set_byte(shpc->wmask + SHPC_CMD_CODE, 0xff);
-    pci_set_byte(shpc->wmask + SHPC_CMD_TRGT, SHPC_CMD_TRGT_MAX);
-    pci_set_byte(shpc->wmask + SHPC_CMD_TRGT, SHPC_CMD_TRGT_MAX);
-    pci_set_long(shpc->wmask + SHPC_SERR_INT,
-                 SHPC_INT_DIS |
-                 SHPC_SERR_DIS |
-                 SHPC_CMD_INT_DIS |
-                 SHPC_ARB_SERR_DIS);
-    pci_set_long(shpc->w1cmask + SHPC_SERR_INT,
-                 SHPC_CMD_DETECTED |
-                 SHPC_ARB_DETECTED);
-    for (i = 0; i < nslots; ++i) {
-        pci_set_byte(shpc->wmask +
-                     SHPC_SLOT_EVENT_SERR_INT_DIS(d, i),
-                     SHPC_SLOT_EVENT_PRESENCE |
-                     SHPC_SLOT_EVENT_ISOLATED_FAULT |
-                     SHPC_SLOT_EVENT_BUTTON |
-                     SHPC_SLOT_EVENT_MRL |
-                     SHPC_SLOT_EVENT_CONNECTED_FAULT |
-                     SHPC_SLOT_EVENT_MRL_SERR_DIS |
-                     SHPC_SLOT_EVENT_CONNECTED_FAULT_SERR_DIS);
-        pci_set_byte(shpc->w1cmask +
-                     SHPC_SLOT_EVENT_LATCH(i),
-                     SHPC_SLOT_EVENT_PRESENCE |
-                     SHPC_SLOT_EVENT_ISOLATED_FAULT |
-                     SHPC_SLOT_EVENT_BUTTON |
-                     SHPC_SLOT_EVENT_MRL |
-                     SHPC_SLOT_EVENT_CONNECTED_FAULT);
-    }
-
-    /* TODO: init cmask */
-    memory_region_init_io(&shpc->mmio, &shpc_mmio_ops, d, "shpc-mmio",
-                          SHPC_SIZEOF(d));
-    shpc_cap_update_dword(d);
-    memory_region_add_subregion(bar, offset, &shpc->mmio);
-    pci_bus_hotplug(sec_bus, shpc_device_hotplug, &d->qdev);
-
-    d->cap_present |= QEMU_PCI_CAP_SHPC;
-    return 0;
-}
-
-int shpc_bar_size(PCIDevice *d)
-{
-    return roundup_pow_of_two(SHPC_SLOT_REG(SHPC_MAX_SLOTS));
-}
-
-void shpc_cleanup(PCIDevice *d, MemoryRegion *bar)
-{
-    SHPCDevice *shpc = d->shpc;
-    d->cap_present &= ~QEMU_PCI_CAP_SHPC;
-    memory_region_del_subregion(bar, &shpc->mmio);
-    /* TODO: cleanup config space changes? */
-    g_free(shpc->config);
-    g_free(shpc->cmask);
-    g_free(shpc->wmask);
-    g_free(shpc->w1cmask);
-    memory_region_destroy(&shpc->mmio);
-    g_free(shpc);
-}
-
-void shpc_cap_write_config(PCIDevice *d, uint32_t addr, uint32_t val, int l)
-{
-    if (!ranges_overlap(addr, l, d->shpc->cap, SHPC_CAP_LENGTH)) {
-        return;
-    }
-    if (ranges_overlap(addr, l, d->shpc->cap + SHPC_CAP_DWORD_DATA, 4)) {
-        unsigned dword_data;
-        dword_data = pci_get_long(d->shpc->config + d->shpc->cap
-                                  + SHPC_CAP_DWORD_DATA);
-        shpc_write(d, shpc_cap_dword(d) * 4, dword_data, 4);
-    }
-    /* Update cap dword data in case guest is going to read it. */
-    shpc_cap_update_dword(d);
-}
-
-static void shpc_save(QEMUFile *f, void *pv, size_t size)
-{
-    PCIDevice *d = container_of(pv, PCIDevice, shpc);
-    qemu_put_buffer(f, d->shpc->config, SHPC_SIZEOF(d));
-}
-
-static int shpc_load(QEMUFile *f, void *pv, size_t size)
-{
-    PCIDevice *d = container_of(pv, PCIDevice, shpc);
-    int ret = qemu_get_buffer(f, d->shpc->config, SHPC_SIZEOF(d));
-    if (ret != SHPC_SIZEOF(d)) {
-        return -EINVAL;
-    }
-    /* Make sure we don't lose notifications. An extra interrupt is harmless. 
*/
-    d->shpc->msi_requested = 0;
-    shpc_interrupt_update(d);
-    return 0;
-}
-
-VMStateInfo shpc_vmstate_info = {
-    .name = "shpc",
-    .get  = shpc_load,
-    .put  = shpc_save,
-};
diff --git a/hw/shpc.h b/hw/shpc.h
deleted file mode 100644
index 130b71d..0000000
--- a/hw/shpc.h
+++ /dev/null
@@ -1,48 +0,0 @@
-#ifndef SHPC_H
-#define SHPC_H
-
-#include "qemu-common.h"
-#include "memory.h"
-#include "vmstate.h"
-
-struct SHPCDevice {
-    /* Capability offset in device's config space */
-    int cap;
-
-    /* # of hot-pluggable slots */
-    int nslots;
-
-    /* SHPC WRS: working register set */
-    uint8_t *config;
-
-    /* Used to enable checks on load. Note that writable bits are
-     * never checked even if set in cmask. */
-    uint8_t *cmask;
-
-    /* Used to implement R/W bytes */
-    uint8_t *wmask;
-
-    /* Used to implement RW1C(Write 1 to Clear) bytes */
-    uint8_t *w1cmask;
-
-    /* MMIO for the SHPC BAR */
-    MemoryRegion mmio;
-
-    /* Bus controlled by this SHPC */
-    PCIBus *sec_bus;
-
-    /* MSI already requested for this event */
-    int msi_requested;
-};
-
-void shpc_reset(PCIDevice *d);
-int shpc_bar_size(PCIDevice *dev);
-int shpc_init(PCIDevice *dev, PCIBus *sec_bus, MemoryRegion *bar, unsigned 
off);
-void shpc_cleanup(PCIDevice *dev, MemoryRegion *bar);
-void shpc_cap_write_config(PCIDevice *d, uint32_t addr, uint32_t val, int len);
-
-extern VMStateInfo shpc_vmstate_info;
-#define SHPC_VMSTATE(_field, _type) \
-    VMSTATE_BUFFER_UNSAFE_INFO(_field, _type, 0, shpc_vmstate_info, 0)
-
-#endif
diff --git a/hw/slotid_cap.c b/hw/slotid_cap.c
deleted file mode 100644
index 0106452..0000000
--- a/hw/slotid_cap.c
+++ /dev/null
@@ -1,44 +0,0 @@
-#include "slotid_cap.h"
-#include "pci.h"
-
-#define SLOTID_CAP_LENGTH 4
-#define SLOTID_NSLOTS_SHIFT (ffs(PCI_SID_ESR_NSLOTS) - 1)
-
-int slotid_cap_init(PCIDevice *d, int nslots,
-                    uint8_t chassis,
-                    unsigned offset)
-{
-    int cap;
-    if (!chassis) {
-        error_report("Bridge chassis not specified. Each bridge is required "
-                     "to be assigned a unique chassis id > 0.");
-        return -EINVAL;
-    }
-    if (nslots < 0 || nslots > (PCI_SID_ESR_NSLOTS >> SLOTID_NSLOTS_SHIFT)) {
-        /* TODO: error report? */
-        return -EINVAL;
-    }
-
-    cap = pci_add_capability(d, PCI_CAP_ID_SLOTID, offset, SLOTID_CAP_LENGTH);
-    if (cap < 0) {
-        return cap;
-    }
-    /* We make each chassis unique, this way each bridge is First in Chassis */
-    d->config[cap + PCI_SID_ESR] = PCI_SID_ESR_FIC |
-        (nslots << SLOTID_NSLOTS_SHIFT);
-    d->cmask[cap + PCI_SID_ESR] = 0xff;
-    d->config[cap + PCI_SID_CHASSIS_NR] = chassis;
-    /* Note: Chassis number register is non-volatile,
-       so we don't reset it. */
-    /* TODO: store in eeprom? */
-    d->wmask[cap + PCI_SID_CHASSIS_NR] = 0xff;
-
-    d->cap_present |= QEMU_PCI_CAP_SLOTID;
-    return 0;
-}
-
-void slotid_cap_cleanup(PCIDevice *d)
-{
-    /* TODO: cleanup config space? */
-    d->cap_present &= ~QEMU_PCI_CAP_SLOTID;
-}
diff --git a/hw/slotid_cap.h b/hw/slotid_cap.h
deleted file mode 100644
index 70db047..0000000
--- a/hw/slotid_cap.h
+++ /dev/null
@@ -1,11 +0,0 @@
-#ifndef PCI_SLOTID_CAP_H
-#define PCI_SLOTID_CAP_H
-
-#include "qemu-common.h"
-
-int slotid_cap_init(PCIDevice *dev, int nslots,
-                    uint8_t chassis,
-                    unsigned offset);
-void slotid_cap_cleanup(PCIDevice *dev);
-
-#endif
-- 
MST




reply via email to

[Prev in Thread] Current Thread [Next in Thread]