qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
* [Qemu-devel] [PATCH 0/8] pci core reorg
@ 2012-12-12 13:13 Michael S. Tsirkin
  2012-12-12 13:14 ` [Qemu-devel] [PATCH 1/8] pci: prepare makefiles for pci code reorganization Michael S. Tsirkin
                   ` (9 more replies)
  0 siblings, 10 replies; 19+ messages in thread
From: Michael S. Tsirkin @ 2012-12-12 13:13 UTC (permalink / raw)
  To: qemu-devel

This patchset starts some cleanups of the pci core
by rearranging the code: pci core is split out
from devices into its own directory, pci internals.h
is renamed as it's used externally a lot.

I'd like to merge this quickly to avoid conflicting
with others work.
Plan to send pull request tomorrow, if you have concerns,
speak up soon pls.

Thanks,



Michael S. Tsirkin (8):
  pci: prepare makefiles for pci code reorganization
  MAINTAINERS: add hw/pci/ to list of PCI files
  pci: move pci core code to hw/pci
  pci: update all users to look in pci/
  pci: make external dependencies explicit
  Revert "pci: prepare makefiles for pci code reorganization"
  pci: rename pci_internals.h pci_bus.h
  pci_bus: update comment

 MAINTAINERS              |    1 +
 arch_init.c              |    2 +-
 hw/Makefile.objs         |   10 +-
 hw/ac97.c                |    2 +-
 hw/acpi_ich9.c           |    2 +-
 hw/acpi_piix4.c          |    2 +-
 hw/alpha_sys.h           |    4 +-
 hw/apb_pci.c             |    8 +-
 hw/apic.c                |    2 +-
 hw/bonito.c              |    4 +-
 hw/cirrus_vga.c          |    2 +-
 hw/dec_pci.c             |    8 +-
 hw/e1000.c               |    2 +-
 hw/eepro100.c            |    2 +-
 hw/es1370.c              |    2 +-
 hw/esp-pci.c             |    2 +-
 hw/grackle_pci.c         |    4 +-
 hw/gt64xxx.c             |    4 +-
 hw/hda-audio.c           |    2 +-
 hw/i386/Makefile.objs    |    2 +-
 hw/i82378.c              |    2 +-
 hw/i82801b11.c           |    2 +-
 hw/ich9.h                |    8 +-
 hw/ide.h                 |    2 +-
 hw/ide/ahci.c            |    4 +-
 hw/ide/cmd646.c          |    2 +-
 hw/ide/core.c            |    2 +-
 hw/ide/ich.c             |    4 +-
 hw/ide/pci.c             |    2 +-
 hw/ide/piix.c            |    2 +-
 hw/ide/via.c             |    2 +-
 hw/intel-hda.c           |    4 +-
 hw/ioh3420.c             |    6 +-
 hw/ioh3420.h             |    2 +-
 hw/ivshmem.c             |    4 +-
 hw/kvm/apic.c            |    2 +-
 hw/kvm/pci-assign.c      |    4 +-
 hw/lpc_ich9.c            |    8 +-
 hw/lsi53c895a.c          |    2 +-
 hw/macio.c               |    2 +-
 hw/megasas.c             |    4 +-
 hw/mips_fulong2e.c       |    2 +-
 hw/mips_malta.c          |    2 +-
 hw/msi.c                 |  395 ---------
 hw/msi.h                 |   50 --
 hw/msix.c                |  562 ------------
 hw/msix.h                |   41 -
 hw/ne2000.c              |    2 +-
 hw/openpic.c             |    2 +-
 hw/pc.c                  |    4 +-
 hw/pc_piix.c             |    4 +-
 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_bus.h         |   74 ++
 hw/pci/pci_host.c        |  180 ++++
 hw/pci/pci_host.h        |   62 ++
 hw/pci/pci_ids.h         |  147 ++++
 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_bridge_dev.c      |   12 +-
 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/pcnet-pci.c           |    2 +-
 hw/piix4.c               |    2 +-
 hw/piix_pci.c            |    4 +-
 hw/ppc/Makefile.objs     |    2 +-
 hw/ppc/e500.c            |    2 +-
 hw/ppc440_bamboo.c       |    2 +-
 hw/ppc4xx.h              |    2 +-
 hw/ppc4xx_pci.c          |    4 +-
 hw/ppc_newworld.c        |    2 +-
 hw/ppc_oldworld.c        |    2 +-
 hw/ppc_prep.c            |    4 +-
 hw/ppce500_pci.c         |    4 +-
 hw/prep_pci.c            |    4 +-
 hw/q35.h                 |    4 +-
 hw/qxl.h                 |    2 +-
 hw/r2d.c                 |    2 +-
 hw/realview.c            |    2 +-
 hw/rtl8139.c             |    2 +-
 hw/serial-pci.c          |    2 +-
 hw/sga.c                 |    2 +-
 hw/sh_pci.c              |    4 +-
 hw/shpc.c                |  681 ---------------
 hw/shpc.h                |   48 -
 hw/slotid_cap.c          |   44 -
 hw/slotid_cap.h          |   11 -
 hw/smbus_ich9.c          |    2 +-
 hw/spapr.c               |    4 +-
 hw/spapr_pci.c           |   10 +-
 hw/spapr_pci.h           |    4 +-
 hw/sun4u.c               |    2 +-
 hw/unin_pci.c            |    4 +-
 hw/usb/hcd-ehci-pci.c    |    2 +-
 hw/usb/hcd-ohci.c        |    2 +-
 hw/usb/hcd-uhci.c        |    2 +-
 hw/usb/hcd-xhci.c        |    6 +-
 hw/versatile_pci.c       |    4 +-
 hw/versatilepb.c         |    2 +-
 hw/vfio_pci.c            |    6 +-
 hw/vga-pci.c             |    2 +-
 hw/vga.c                 |    2 +-
 hw/virtio-balloon.h      |    2 +-
 hw/virtio-net.h          |    2 +-
 hw/virtio-pci.c          |    6 +-
 hw/virtio-scsi.h         |    2 +-
 hw/vmware_vga.c          |    2 +-
 hw/vt82c686.c            |    4 +-
 hw/wdt_i6300esb.c        |    2 +-
 hw/xen-host-pci-device.h |    2 +-
 hw/xen_apic.c            |    2 +-
 hw/xen_platform.c        |    2 +-
 hw/xen_pt.c              |    2 +-
 hw/xen_pt.h              |    2 +-
 hw/xio3130_downstream.c  |    6 +-
 hw/xio3130_downstream.h  |    2 +-
 hw/xio3130_upstream.c    |    6 +-
 hw/xio3130_upstream.h    |    2 +-
 kvm-all.c                |    2 +-
 kvm-stub.c               |    2 +-
 monitor.c                |    2 +-
 target-i386/kvm.c        |    2 +-
 xen-all.c                |    2 +-
 162 files changed, 9173 insertions(+), 9176 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_bus.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_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

-- 
MST

^ permalink raw reply	[flat|nested] 19+ messages in thread

* [Qemu-devel] [PATCH 1/8] pci: prepare makefiles for pci code reorganization
  2012-12-12 13:13 [Qemu-devel] [PATCH 0/8] pci core reorg Michael S. Tsirkin
@ 2012-12-12 13:14 ` Michael S. Tsirkin
  2012-12-12 13:14 ` [Qemu-devel] [PATCH 2/8] MAINTAINERS: add hw/pci/ to list of PCI files Michael S. Tsirkin
                   ` (8 subsequent siblings)
  9 siblings, 0 replies; 19+ messages in thread
From: Michael S. Tsirkin @ 2012-12-12 13:14 UTC (permalink / raw)
  To: qemu-devel

To make it easier to move code around without breaking
build at intermedite steps, tweak makefiles
to look in pci/ and hw/ for include files, automatically.
This will be reverted at the end of the reorganization.

Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
---
 Makefile        | 1 +
 Makefile.target | 1 +
 Makefile.user   | 1 +
 hw/pci/hw       | 1 +
 4 files changed, 4 insertions(+)
 create mode 120000 hw/pci/hw

diff --git a/Makefile b/Makefile
index 9ecbcbb..b9a81d1 100644
--- a/Makefile
+++ b/Makefile
@@ -146,6 +146,7 @@ audio/audio.o audio/fmodaudio.o: QEMU_CFLAGS += $(FMOD_CFLAGS)
 QEMU_CFLAGS+=$(CURL_CFLAGS)
 
 QEMU_CFLAGS += -I$(SRC_PATH)/include
+QEMU_CFLAGS+=-I$(SRC_PATH)/hw/pci -I$(SRC_PATH)/hw
 
 ui/cocoa.o: ui/cocoa.m
 
diff --git a/Makefile.target b/Makefile.target
index 8b658c0..e2e8840 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -12,6 +12,7 @@ endif
 QEMU_CFLAGS += -I.. -I$(SRC_PATH)/target-$(TARGET_BASE_ARCH) -DNEED_CPU_H
 
 QEMU_CFLAGS+=-I$(SRC_PATH)/include
+QEMU_CFLAGS+=-I$(SRC_PATH)/hw/pci -I$(SRC_PATH)/hw
 
 ifdef CONFIG_USER_ONLY
 # user emulator name
diff --git a/Makefile.user b/Makefile.user
index 9302d33..045ecd3 100644
--- a/Makefile.user
+++ b/Makefile.user
@@ -11,6 +11,7 @@ $(call set-vpath, $(SRC_PATH))
 QEMU_CFLAGS+=-I..
 QEMU_CFLAGS += -I$(SRC_PATH)/include
 QEMU_CFLAGS += -DCONFIG_USER_ONLY
+QEMU_CFLAGS+=-I$(SRC_PATH)/hw/pci -I$(SRC_PATH)/hw
 
 include $(SRC_PATH)/Makefile.objs
 
diff --git a/hw/pci/hw b/hw/pci/hw
new file mode 120000
index 0000000..945c9b4
--- /dev/null
+++ b/hw/pci/hw
@@ -0,0 +1 @@
+.
\ No newline at end of file
-- 
MST

^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [Qemu-devel] [PATCH 2/8] MAINTAINERS: add hw/pci/ to list of PCI files
  2012-12-12 13:13 [Qemu-devel] [PATCH 0/8] pci core reorg Michael S. Tsirkin
  2012-12-12 13:14 ` [Qemu-devel] [PATCH 1/8] pci: prepare makefiles for pci code reorganization Michael S. Tsirkin
@ 2012-12-12 13:14 ` Michael S. Tsirkin
  2012-12-12 13:14 ` [Qemu-devel] [PATCH 3/8] pci: move pci core code to hw/pci Michael S. Tsirkin
                   ` (7 subsequent siblings)
  9 siblings, 0 replies; 19+ messages in thread
From: Michael S. Tsirkin @ 2012-12-12 13:14 UTC (permalink / raw)
  To: qemu-devel

Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
---
 MAINTAINERS | 1 +
 1 file changed, 1 insertion(+)

diff --git a/MAINTAINERS b/MAINTAINERS
index 2ede20d..c1b16c5 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -490,6 +490,7 @@ F: hw/omap*
 PCI
 M: Michael S. Tsirkin <mst@redhat.com>
 S: Supported
+F: hw/pci/*
 F: hw/pci*
 F: hw/piix*
 
-- 
MST

^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [Qemu-devel] [PATCH 3/8] pci: move pci core code to hw/pci
  2012-12-12 13:13 [Qemu-devel] [PATCH 0/8] pci core reorg Michael S. Tsirkin
  2012-12-12 13:14 ` [Qemu-devel] [PATCH 1/8] pci: prepare makefiles for pci code reorganization Michael S. Tsirkin
  2012-12-12 13:14 ` [Qemu-devel] [PATCH 2/8] MAINTAINERS: add hw/pci/ to list of PCI files Michael S. Tsirkin
@ 2012-12-12 13:14 ` Michael S. Tsirkin
  2012-12-12 19:53   ` Blue Swirl
  2012-12-12 13:14 ` [Qemu-devel] [PATCH 4/8] pci: update all users to look in pci/ Michael S. Tsirkin
                   ` (6 subsequent siblings)
  9 siblings, 1 reply; 19+ messages in thread
From: Michael S. Tsirkin @ 2012-12-12 13:14 UTC (permalink / raw)
  To: qemu-devel

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

Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
---
 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 <mst@redhat.com>
- *
- *  Copyright (c) 2009, Red Hat Inc, Michael S. Tsirkin (mst@redhat.com)
- *
- * 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), "%s@%x",
-                   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 <mst@redhat.com>
+ *
+ *  Copyright (c) 2009, Red Hat Inc, Michael S. Tsirkin (mst@redhat.com)
+ *
+ * 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), "%s@%x",
+                   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 <mj@ucw.cz>
+ *
+ *	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 <mj@ucw.cz>
- *
- *	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

^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [Qemu-devel] [PATCH 4/8] pci: update all users to look in pci/
  2012-12-12 13:13 [Qemu-devel] [PATCH 0/8] pci core reorg Michael S. Tsirkin
                   ` (2 preceding siblings ...)
  2012-12-12 13:14 ` [Qemu-devel] [PATCH 3/8] pci: move pci core code to hw/pci Michael S. Tsirkin
@ 2012-12-12 13:14 ` Michael S. Tsirkin
  2012-12-12 13:14 ` [Qemu-devel] [PATCH 6/8] Revert "pci: prepare makefiles for pci code reorganization" Michael S. Tsirkin
                   ` (5 subsequent siblings)
  9 siblings, 0 replies; 19+ messages in thread
From: Michael S. Tsirkin @ 2012-12-12 13:14 UTC (permalink / raw)
  To: qemu-devel

update all users so we can remove the makefile hack.

Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
---
 arch_init.c              |  2 +-
 hw/ac97.c                |  2 +-
 hw/acpi_ich9.c           |  2 +-
 hw/acpi_piix4.c          |  2 +-
 hw/alpha_sys.h           |  4 ++--
 hw/apb_pci.c             |  8 ++++----
 hw/apic.c                |  2 +-
 hw/bonito.c              |  4 ++--
 hw/cirrus_vga.c          |  2 +-
 hw/dec_pci.c             |  8 ++++----
 hw/e1000.c               |  2 +-
 hw/eepro100.c            |  2 +-
 hw/es1370.c              |  2 +-
 hw/esp-pci.c             |  2 +-
 hw/grackle_pci.c         |  4 ++--
 hw/gt64xxx.c             |  4 ++--
 hw/hda-audio.c           |  2 +-
 hw/i82378.c              |  2 +-
 hw/i82801b11.c           |  2 +-
 hw/ich9.h                |  8 ++++----
 hw/ide.h                 |  2 +-
 hw/ide/ahci.c            |  4 ++--
 hw/ide/cmd646.c          |  2 +-
 hw/ide/core.c            |  2 +-
 hw/ide/ich.c             |  4 ++--
 hw/ide/pci.c             |  2 +-
 hw/ide/piix.c            |  2 +-
 hw/ide/via.c             |  2 +-
 hw/intel-hda.c           |  4 ++--
 hw/ioh3420.c             |  6 +++---
 hw/ioh3420.h             |  2 +-
 hw/ivshmem.c             |  4 ++--
 hw/kvm/apic.c            |  2 +-
 hw/kvm/pci-assign.c      |  4 ++--
 hw/lpc_ich9.c            |  8 ++++----
 hw/lsi53c895a.c          |  2 +-
 hw/macio.c               |  2 +-
 hw/megasas.c             |  4 ++--
 hw/mips_fulong2e.c       |  2 +-
 hw/mips_malta.c          |  2 +-
 hw/ne2000.c              |  2 +-
 hw/openpic.c             |  2 +-
 hw/pc.c                  |  4 ++--
 hw/pc_piix.c             |  4 ++--
 hw/pci_bridge_dev.c      | 12 ++++++------
 hw/pcnet-pci.c           |  2 +-
 hw/piix4.c               |  2 +-
 hw/piix_pci.c            |  4 ++--
 hw/ppc/e500.c            |  2 +-
 hw/ppc440_bamboo.c       |  2 +-
 hw/ppc4xx.h              |  2 +-
 hw/ppc4xx_pci.c          |  4 ++--
 hw/ppc_newworld.c        |  2 +-
 hw/ppc_oldworld.c        |  2 +-
 hw/ppc_prep.c            |  4 ++--
 hw/ppce500_pci.c         |  4 ++--
 hw/prep_pci.c            |  4 ++--
 hw/q35.h                 |  4 ++--
 hw/qxl.h                 |  2 +-
 hw/r2d.c                 |  2 +-
 hw/realview.c            |  2 +-
 hw/rtl8139.c             |  2 +-
 hw/serial-pci.c          |  2 +-
 hw/sga.c                 |  2 +-
 hw/sh_pci.c              |  4 ++--
 hw/smbus_ich9.c          |  2 +-
 hw/spapr.c               |  4 ++--
 hw/spapr_pci.c           | 10 +++++-----
 hw/spapr_pci.h           |  4 ++--
 hw/sun4u.c               |  2 +-
 hw/unin_pci.c            |  4 ++--
 hw/usb/hcd-ehci-pci.c    |  2 +-
 hw/usb/hcd-ohci.c        |  2 +-
 hw/usb/hcd-uhci.c        |  2 +-
 hw/usb/hcd-xhci.c        |  6 +++---
 hw/versatile_pci.c       |  4 ++--
 hw/versatilepb.c         |  2 +-
 hw/vfio_pci.c            |  6 +++---
 hw/vga-pci.c             |  2 +-
 hw/vga.c                 |  2 +-
 hw/virtio-balloon.h      |  2 +-
 hw/virtio-net.h          |  2 +-
 hw/virtio-pci.c          |  6 +++---
 hw/virtio-scsi.h         |  2 +-
 hw/vmware_vga.c          |  2 +-
 hw/vt82c686.c            |  4 ++--
 hw/wdt_i6300esb.c        |  2 +-
 hw/xen-host-pci-device.h |  2 +-
 hw/xen_apic.c            |  2 +-
 hw/xen_platform.c        |  2 +-
 hw/xen_pt.c              |  2 +-
 hw/xen_pt.h              |  2 +-
 hw/xio3130_downstream.c  |  6 +++---
 hw/xio3130_downstream.h  |  2 +-
 hw/xio3130_upstream.c    |  6 +++---
 hw/xio3130_upstream.h    |  2 +-
 kvm-all.c                |  2 +-
 kvm-stub.c               |  2 +-
 monitor.c                |  2 +-
 target-i386/kvm.c        |  2 +-
 xen-all.c                |  2 +-
 101 files changed, 158 insertions(+), 158 deletions(-)

diff --git a/arch_init.c b/arch_init.c
index e6effe8..e307b23 100644
--- a/arch_init.c
+++ b/arch_init.c
@@ -36,7 +36,7 @@
 #include "arch_init.h"
 #include "audio/audio.h"
 #include "hw/pc.h"
-#include "hw/pci.h"
+#include "hw/pci/pci.h"
 #include "hw/audiodev.h"
 #include "kvm.h"
 #include "migration.h"
diff --git a/hw/ac97.c b/hw/ac97.c
index ce6a1dc..3e659b3 100644
--- a/hw/ac97.c
+++ b/hw/ac97.c
@@ -20,7 +20,7 @@
 #include "hw.h"
 #include "audiodev.h"
 #include "audio/audio.h"
-#include "pci.h"
+#include "pci/pci.h"
 #include "dma.h"
 
 enum {
diff --git a/hw/acpi_ich9.c b/hw/acpi_ich9.c
index 25c9d36..3e01556 100644
--- a/hw/acpi_ich9.c
+++ b/hw/acpi_ich9.c
@@ -25,7 +25,7 @@
  */
 #include "hw.h"
 #include "pc.h"
-#include "pci.h"
+#include "pci/pci.h"
 #include "qemu-timer.h"
 #include "sysemu.h"
 #include "acpi.h"
diff --git a/hw/acpi_piix4.c b/hw/acpi_piix4.c
index 519269a..846f40a 100644
--- a/hw/acpi_piix4.c
+++ b/hw/acpi_piix4.c
@@ -22,7 +22,7 @@
 #include "pc.h"
 #include "apm.h"
 #include "pm_smbus.h"
-#include "pci.h"
+#include "pci/pci.h"
 #include "acpi.h"
 #include "sysemu.h"
 #include "range.h"
diff --git a/hw/alpha_sys.h b/hw/alpha_sys.h
index 7604d09..b1e5258 100644
--- a/hw/alpha_sys.h
+++ b/hw/alpha_sys.h
@@ -3,8 +3,8 @@
 #ifndef HW_ALPHA_H
 #define HW_ALPHA_H 1
 
-#include "pci.h"
-#include "pci_host.h"
+#include "pci/pci.h"
+#include "pci/pci_host.h"
 #include "ide.h"
 #include "net.h"
 #include "pc.h"
diff --git a/hw/apb_pci.c b/hw/apb_pci.c
index 054814f..de594f8 100644
--- a/hw/apb_pci.c
+++ b/hw/apb_pci.c
@@ -27,10 +27,10 @@
    the secondary PCI bridge.  */
 
 #include "sysbus.h"
-#include "pci.h"
-#include "pci_host.h"
-#include "pci_bridge.h"
-#include "pci_internals.h"
+#include "pci/pci.h"
+#include "pci/pci_host.h"
+#include "pci/pci_bridge.h"
+#include "pci/pci_internals.h"
 #include "apb_pci.h"
 #include "sysemu.h"
 #include "exec-memory.h"
diff --git a/hw/apic.c b/hw/apic.c
index f73fc87..d66a476 100644
--- a/hw/apic.c
+++ b/hw/apic.c
@@ -20,7 +20,7 @@
 #include "apic_internal.h"
 #include "apic.h"
 #include "ioapic.h"
-#include "msi.h"
+#include "pci/msi.h"
 #include "host-utils.h"
 #include "trace.h"
 #include "pc.h"
diff --git a/hw/bonito.c b/hw/bonito.c
index 0bf6d4a..a1fc38c 100644
--- a/hw/bonito.c
+++ b/hw/bonito.c
@@ -40,10 +40,10 @@
 #include <assert.h>
 
 #include "hw.h"
-#include "pci.h"
+#include "pci/pci.h"
 #include "pc.h"
 #include "mips.h"
-#include "pci_host.h"
+#include "pci/pci_host.h"
 #include "sysemu.h"
 #include "exec-memory.h"
 
diff --git a/hw/cirrus_vga.c b/hw/cirrus_vga.c
index 9bef96e..2364828 100644
--- a/hw/cirrus_vga.c
+++ b/hw/cirrus_vga.c
@@ -27,7 +27,7 @@
  *   available at http://home.worldonline.dk/~finth/
  */
 #include "hw.h"
-#include "pci.h"
+#include "pci/pci.h"
 #include "console.h"
 #include "vga_int.h"
 #include "loader.h"
diff --git a/hw/dec_pci.c b/hw/dec_pci.c
index c30ade3..a6a7c84 100644
--- a/hw/dec_pci.c
+++ b/hw/dec_pci.c
@@ -25,10 +25,10 @@
 
 #include "dec_pci.h"
 #include "sysbus.h"
-#include "pci.h"
-#include "pci_host.h"
-#include "pci_bridge.h"
-#include "pci_internals.h"
+#include "pci/pci.h"
+#include "pci/pci_host.h"
+#include "pci/pci_bridge.h"
+#include "pci/pci_internals.h"
 
 /* debug DEC */
 //#define DEBUG_DEC
diff --git a/hw/e1000.c b/hw/e1000.c
index cb7e7e8..ecd81d8 100644
--- a/hw/e1000.c
+++ b/hw/e1000.c
@@ -26,7 +26,7 @@
 
 
 #include "hw.h"
-#include "pci.h"
+#include "pci/pci.h"
 #include "net.h"
 #include "net/checksum.h"
 #include "loader.h"
diff --git a/hw/eepro100.c b/hw/eepro100.c
index a189474..992f03a 100644
--- a/hw/eepro100.c
+++ b/hw/eepro100.c
@@ -42,7 +42,7 @@
 
 #include <stddef.h>             /* offsetof */
 #include "hw.h"
-#include "pci.h"
+#include "pci/pci.h"
 #include "net.h"
 #include "eeprom93xx.h"
 #include "sysemu.h"
diff --git a/hw/es1370.c b/hw/es1370.c
index e0c9729..6536578 100644
--- a/hw/es1370.c
+++ b/hw/es1370.c
@@ -29,7 +29,7 @@
 #include "hw.h"
 #include "audiodev.h"
 #include "audio/audio.h"
-#include "pci.h"
+#include "pci/pci.h"
 #include "dma.h"
 
 /* Missing stuff:
diff --git a/hw/esp-pci.c b/hw/esp-pci.c
index d9a8e59..d433473 100644
--- a/hw/esp-pci.c
+++ b/hw/esp-pci.c
@@ -23,7 +23,7 @@
  * THE SOFTWARE.
  */
 
-#include "pci.h"
+#include "pci/pci.h"
 #include "eeprom93xx.h"
 #include "esp.h"
 #include "trace.h"
diff --git a/hw/grackle_pci.c b/hw/grackle_pci.c
index 67da307..9484166 100644
--- a/hw/grackle_pci.c
+++ b/hw/grackle_pci.c
@@ -23,9 +23,9 @@
  * THE SOFTWARE.
  */
 
-#include "pci_host.h"
+#include "pci/pci_host.h"
 #include "ppc_mac.h"
-#include "pci.h"
+#include "pci/pci.h"
 
 /* debug Grackle */
 //#define DEBUG_GRACKLE
diff --git a/hw/gt64xxx.c b/hw/gt64xxx.c
index 95d491d..5aa49c6 100644
--- a/hw/gt64xxx.c
+++ b/hw/gt64xxx.c
@@ -24,8 +24,8 @@
 
 #include "hw.h"
 #include "mips.h"
-#include "pci.h"
-#include "pci_host.h"
+#include "pci/pci.h"
+#include "pci/pci_host.h"
 #include "pc.h"
 #include "exec-memory.h"
 
diff --git a/hw/hda-audio.c b/hw/hda-audio.c
index 36761dd..92a91b5 100644
--- a/hw/hda-audio.c
+++ b/hw/hda-audio.c
@@ -18,7 +18,7 @@
  */
 
 #include "hw.h"
-#include "pci.h"
+#include "pci/pci.h"
 #include "intel-hda.h"
 #include "intel-hda-defs.h"
 #include "audio/audio.h"
diff --git a/hw/i82378.c b/hw/i82378.c
index 99f35d4..c6b0b5e 100644
--- a/hw/i82378.c
+++ b/hw/i82378.c
@@ -17,7 +17,7 @@
  * License along with this library; if not, see <http://www.gnu.org/licenses/>.
  */
 
-#include "pci.h"
+#include "pci/pci.h"
 #include "pc.h"
 #include "i8254.h"
 #include "pcspk.h"
diff --git a/hw/i82801b11.c b/hw/i82801b11.c
index 3d1f996..3dc1000 100644
--- a/hw/i82801b11.c
+++ b/hw/i82801b11.c
@@ -41,7 +41,7 @@
  * License along with this library; if not, see <http://www.gnu.org/licenses/>
  */
 
-#include "pci.h"
+#include "pci/pci.h"
 #include "ich9.h"
 
 
diff --git a/hw/ich9.h b/hw/ich9.h
index de49135..247be94 100644
--- a/hw/ich9.h
+++ b/hw/ich9.h
@@ -8,13 +8,13 @@
 #include "pc.h"
 #include "apm.h"
 #include "ioapic.h"
-#include "pci.h"
-#include "pcie_host.h"
-#include "pci_bridge.h"
+#include "pci/pci.h"
+#include "pci/pcie_host.h"
+#include "pci/pci_bridge.h"
 #include "acpi.h"
 #include "acpi_ich9.h"
 #include "pam.h"
-#include "pci_internals.h"
+#include "pci/pci_internals.h"
 
 void ich9_lpc_set_irq(void *opaque, int irq_num, int level);
 int ich9_lpc_map_irq(PCIDevice *pci_dev, int intx);
diff --git a/hw/ide.h b/hw/ide.h
index add742c..081c710 100644
--- a/hw/ide.h
+++ b/hw/ide.h
@@ -2,7 +2,7 @@
 #define HW_IDE_H
 
 #include "isa.h"
-#include "pci.h"
+#include "pci/pci.h"
 #include "memory.h"
 
 #define MAX_IDE_DEVS	2
diff --git a/hw/ide/ahci.c b/hw/ide/ahci.c
index 67562db..2ea64bd 100644
--- a/hw/ide/ahci.c
+++ b/hw/ide/ahci.c
@@ -22,9 +22,9 @@
  */
 
 #include <hw/hw.h>
-#include <hw/msi.h>
+#include <hw/pci/msi.h>
 #include <hw/pc.h>
-#include <hw/pci.h>
+#include <hw/pci/pci.h>
 #include <hw/sysbus.h>
 
 #include "monitor.h"
diff --git a/hw/ide/cmd646.c b/hw/ide/cmd646.c
index 804db60..88210ea 100644
--- a/hw/ide/cmd646.c
+++ b/hw/ide/cmd646.c
@@ -24,7 +24,7 @@
  */
 #include <hw/hw.h>
 #include <hw/pc.h>
-#include <hw/pci.h>
+#include <hw/pci/pci.h>
 #include <hw/isa.h>
 #include "block.h"
 #include "sysemu.h"
diff --git a/hw/ide/core.c b/hw/ide/core.c
index 8da894f..8ddafbb 100644
--- a/hw/ide/core.c
+++ b/hw/ide/core.c
@@ -24,7 +24,7 @@
  */
 #include <hw/hw.h>
 #include <hw/pc.h>
-#include <hw/pci.h>
+#include <hw/pci/pci.h>
 #include <hw/isa.h>
 #include "qemu-error.h"
 #include "qemu-timer.h"
diff --git a/hw/ide/ich.c b/hw/ide/ich.c
index 272b773..8e1a48e 100644
--- a/hw/ide/ich.c
+++ b/hw/ide/ich.c
@@ -61,9 +61,9 @@
  */
 
 #include <hw/hw.h>
-#include <hw/msi.h>
+#include <hw/pci/msi.h>
 #include <hw/pc.h>
-#include <hw/pci.h>
+#include <hw/pci/pci.h>
 #include <hw/isa.h>
 #include "block.h"
 #include "dma.h"
diff --git a/hw/ide/pci.c b/hw/ide/pci.c
index bcdd70e..23a0e23 100644
--- a/hw/ide/pci.c
+++ b/hw/ide/pci.c
@@ -24,7 +24,7 @@
  */
 #include <hw/hw.h>
 #include <hw/pc.h>
-#include <hw/pci.h>
+#include <hw/pci/pci.h>
 #include <hw/isa.h>
 #include "block.h"
 #include "dma.h"
diff --git a/hw/ide/piix.c b/hw/ide/piix.c
index 9431bad..5cf39cf 100644
--- a/hw/ide/piix.c
+++ b/hw/ide/piix.c
@@ -25,7 +25,7 @@
 
 #include <hw/hw.h>
 #include <hw/pc.h>
-#include <hw/pci.h>
+#include <hw/pci/pci.h>
 #include <hw/isa.h>
 #include "blockdev.h"
 #include "sysemu.h"
diff --git a/hw/ide/via.c b/hw/ide/via.c
index efda173..8b4a24e 100644
--- a/hw/ide/via.c
+++ b/hw/ide/via.c
@@ -25,7 +25,7 @@
  */
 #include <hw/hw.h>
 #include <hw/pc.h>
-#include <hw/pci.h>
+#include <hw/pci/pci.h>
 #include <hw/isa.h>
 #include "block.h"
 #include "sysemu.h"
diff --git a/hw/intel-hda.c b/hw/intel-hda.c
index a68c368..c21bf72 100644
--- a/hw/intel-hda.c
+++ b/hw/intel-hda.c
@@ -18,8 +18,8 @@
  */
 
 #include "hw.h"
-#include "pci.h"
-#include "msi.h"
+#include "pci/pci.h"
+#include "pci/msi.h"
 #include "qemu-timer.h"
 #include "audiodev.h"
 #include "intel-hda.h"
diff --git a/hw/ioh3420.c b/hw/ioh3420.c
index 4d31473..d706e19 100644
--- a/hw/ioh3420.c
+++ b/hw/ioh3420.c
@@ -20,9 +20,9 @@
  * with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
-#include "pci_ids.h"
-#include "msi.h"
-#include "pcie.h"
+#include "pci/pci_ids.h"
+#include "pci/msi.h"
+#include "pci/pcie.h"
 #include "ioh3420.h"
 
 #define PCI_DEVICE_ID_IOH_EPORT         0x3420  /* D0:F0 express mode */
diff --git a/hw/ioh3420.h b/hw/ioh3420.h
index 68c523a..046cf2c 100644
--- a/hw/ioh3420.h
+++ b/hw/ioh3420.h
@@ -1,7 +1,7 @@
 #ifndef QEMU_IOH3420_H
 #define QEMU_IOH3420_H
 
-#include "pcie_port.h"
+#include "pci/pcie_port.h"
 
 PCIESlot *ioh3420_init(PCIBus *bus, int devfn, bool multifunction,
                        const char *bus_name, pci_map_irq_fn map_irq,
diff --git a/hw/ivshmem.c b/hw/ivshmem.c
index f6dbb21..cf64f32 100644
--- a/hw/ivshmem.c
+++ b/hw/ivshmem.c
@@ -18,8 +18,8 @@
  */
 #include "hw.h"
 #include "pc.h"
-#include "pci.h"
-#include "msix.h"
+#include "pci/pci.h"
+#include "pci/msix.h"
 #include "kvm.h"
 #include "migration.h"
 #include "qerror.h"
diff --git a/hw/kvm/apic.c b/hw/kvm/apic.c
index 8b65d51..beb418d 100644
--- a/hw/kvm/apic.c
+++ b/hw/kvm/apic.c
@@ -10,7 +10,7 @@
  * See the COPYING file in the top-level directory.
  */
 #include "hw/apic_internal.h"
-#include "hw/msi.h"
+#include "hw/pci/msi.h"
 #include "kvm.h"
 
 static inline void kvm_apic_set_reg(struct kvm_lapic_state *kapic,
diff --git a/hw/kvm/pci-assign.c b/hw/kvm/pci-assign.c
index e80dad0..4229159 100644
--- a/hw/kvm/pci-assign.c
+++ b/hw/kvm/pci-assign.c
@@ -34,8 +34,8 @@
 #include "monitor.h"
 #include "range.h"
 #include "sysemu.h"
-#include "hw/pci.h"
-#include "hw/msi.h"
+#include "hw/pci/pci.h"
+#include "hw/pci/msi.h"
 #include "kvm_i386.h"
 
 #define MSIX_PAGE_SIZE 0x1000
diff --git a/hw/lpc_ich9.c b/hw/lpc_ich9.c
index f253dbd..23dee88 100644
--- a/hw/lpc_ich9.c
+++ b/hw/lpc_ich9.c
@@ -35,14 +35,14 @@
 #include "pc.h"
 #include "apm.h"
 #include "ioapic.h"
-#include "pci.h"
-#include "pcie_host.h"
-#include "pci_bridge.h"
+#include "pci/pci.h"
+#include "pci/pcie_host.h"
+#include "pci/pci_bridge.h"
 #include "ich9.h"
 #include "acpi.h"
 #include "acpi_ich9.h"
 #include "pam.h"
-#include "pci_internals.h"
+#include "pci/pci_internals.h"
 #include "exec-memory.h"
 
 static int ich9_lpc_sci_irq(ICH9LPCState *lpc);
diff --git a/hw/lsi53c895a.c b/hw/lsi53c895a.c
index 04f2fae..4aac9a0 100644
--- a/hw/lsi53c895a.c
+++ b/hw/lsi53c895a.c
@@ -13,7 +13,7 @@
 #include <assert.h>
 
 #include "hw.h"
-#include "pci.h"
+#include "pci/pci.h"
 #include "scsi.h"
 #include "dma.h"
 
diff --git a/hw/macio.c b/hw/macio.c
index eb15b89..362afdc 100644
--- a/hw/macio.c
+++ b/hw/macio.c
@@ -24,7 +24,7 @@
  */
 #include "hw.h"
 #include "ppc_mac.h"
-#include "pci.h"
+#include "pci/pci.h"
 #include "escc.h"
 
 typedef struct MacIOState
diff --git a/hw/megasas.c b/hw/megasas.c
index 61b6527..f4fbe97 100644
--- a/hw/megasas.c
+++ b/hw/megasas.c
@@ -19,9 +19,9 @@
  */
 
 #include "hw.h"
-#include "pci.h"
+#include "pci/pci.h"
 #include "dma.h"
-#include "msix.h"
+#include "pci/msix.h"
 #include "iov.h"
 #include "scsi.h"
 #include "scsi-defs.h"
diff --git a/hw/mips_fulong2e.c b/hw/mips_fulong2e.c
index 5fcf900..d5cf33b 100644
--- a/hw/mips_fulong2e.c
+++ b/hw/mips_fulong2e.c
@@ -29,7 +29,7 @@
 #include "flash.h"
 #include "mips.h"
 #include "mips_cpudevs.h"
-#include "pci.h"
+#include "pci/pci.h"
 #include "qemu-char.h"
 #include "sysemu.h"
 #include "audio/audio.h"
diff --git a/hw/mips_malta.c b/hw/mips_malta.c
index 4d2464a..571903d 100644
--- a/hw/mips_malta.c
+++ b/hw/mips_malta.c
@@ -33,7 +33,7 @@
 #include "flash.h"
 #include "mips.h"
 #include "mips_cpudevs.h"
-#include "pci.h"
+#include "pci/pci.h"
 #include "qemu-char.h"
 #include "sysemu.h"
 #include "arch_init.h"
diff --git a/hw/ne2000.c b/hw/ne2000.c
index d3dd9a6..fb78e5b 100644
--- a/hw/ne2000.c
+++ b/hw/ne2000.c
@@ -22,7 +22,7 @@
  * THE SOFTWARE.
  */
 #include "hw.h"
-#include "pci.h"
+#include "pci/pci.h"
 #include "net.h"
 #include "ne2000.h"
 #include "loader.h"
diff --git a/hw/openpic.c b/hw/openpic.c
index 8b3784a..4791dc6 100644
--- a/hw/openpic.c
+++ b/hw/openpic.c
@@ -35,7 +35,7 @@
  */
 #include "hw.h"
 #include "ppc_mac.h"
-#include "pci.h"
+#include "pci/pci.h"
 #include "openpic.h"
 
 //#define DEBUG_OPENPIC
diff --git a/hw/pc.c b/hw/pc.c
index 2b5bbbf..77470bc 100644
--- a/hw/pc.c
+++ b/hw/pc.c
@@ -27,7 +27,7 @@
 #include "apic.h"
 #include "fdc.h"
 #include "ide.h"
-#include "pci.h"
+#include "pci/pci.h"
 #include "monitor.h"
 #include "fw_cfg.h"
 #include "hpet_emul.h"
@@ -38,7 +38,7 @@
 #include "mc146818rtc.h"
 #include "i8254.h"
 #include "pcspk.h"
-#include "msi.h"
+#include "pci/msi.h"
 #include "sysbus.h"
 #include "sysemu.h"
 #include "kvm.h"
diff --git a/hw/pc_piix.c b/hw/pc_piix.c
index aa3e7f4..890a1d9 100644
--- a/hw/pc_piix.c
+++ b/hw/pc_piix.c
@@ -27,8 +27,8 @@
 #include "hw.h"
 #include "pc.h"
 #include "apic.h"
-#include "pci.h"
-#include "pci_ids.h"
+#include "pci/pci.h"
+#include "pci/pci_ids.h"
 #include "usb.h"
 #include "net.h"
 #include "boards.h"
diff --git a/hw/pci_bridge_dev.c b/hw/pci_bridge_dev.c
index f706396..5c9fc50 100644
--- a/hw/pci_bridge_dev.c
+++ b/hw/pci_bridge_dev.c
@@ -19,13 +19,13 @@
  * with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
-#include "pci_bridge.h"
-#include "pci_ids.h"
-#include "msi.h"
-#include "shpc.h"
-#include "slotid_cap.h"
+#include "pci/pci_bridge.h"
+#include "pci/pci_ids.h"
+#include "pci/msi.h"
+#include "pci/shpc.h"
+#include "pci/slotid_cap.h"
 #include "memory.h"
-#include "pci_internals.h"
+#include "pci/pci_internals.h"
 
 #define REDHAT_PCI_VENDOR_ID 0x1b36
 #define PCI_BRIDGE_DEV_VENDOR_ID REDHAT_PCI_VENDOR_ID
diff --git a/hw/pcnet-pci.c b/hw/pcnet-pci.c
index 0bf438f..c1abbf8 100644
--- a/hw/pcnet-pci.c
+++ b/hw/pcnet-pci.c
@@ -27,7 +27,7 @@
  * AMD Publication# 19436  Rev:E  Amendment/0  Issue Date: June 2000
  */
 
-#include "pci.h"
+#include "pci/pci.h"
 #include "net.h"
 #include "loader.h"
 #include "qemu-timer.h"
diff --git a/hw/piix4.c b/hw/piix4.c
index ce4eb0d..799ed17 100644
--- a/hw/piix4.c
+++ b/hw/piix4.c
@@ -24,7 +24,7 @@
 
 #include "hw.h"
 #include "pc.h"
-#include "pci.h"
+#include "pci/pci.h"
 #include "isa.h"
 #include "sysbus.h"
 
diff --git a/hw/piix_pci.c b/hw/piix_pci.c
index ba1b3de..b5ea68b 100644
--- a/hw/piix_pci.c
+++ b/hw/piix_pci.c
@@ -24,8 +24,8 @@
 
 #include "hw.h"
 #include "pc.h"
-#include "pci.h"
-#include "pci_host.h"
+#include "pci/pci.h"
+#include "pci/pci_host.h"
 #include "isa.h"
 #include "sysbus.h"
 #include "range.h"
diff --git a/hw/ppc/e500.c b/hw/ppc/e500.c
index 6749fff..f77c488 100644
--- a/hw/ppc/e500.c
+++ b/hw/ppc/e500.c
@@ -20,7 +20,7 @@
 #include "net.h"
 #include "hw/hw.h"
 #include "hw/serial.h"
-#include "hw/pci.h"
+#include "hw/pci/pci.h"
 #include "hw/boards.h"
 #include "sysemu.h"
 #include "kvm.h"
diff --git a/hw/ppc440_bamboo.c b/hw/ppc440_bamboo.c
index cc85607..0b39a81 100644
--- a/hw/ppc440_bamboo.c
+++ b/hw/ppc440_bamboo.c
@@ -15,7 +15,7 @@
 #include "qemu-common.h"
 #include "net.h"
 #include "hw.h"
-#include "pci.h"
+#include "pci/pci.h"
 #include "boards.h"
 #include "kvm.h"
 #include "kvm_ppc.h"
diff --git a/hw/ppc4xx.h b/hw/ppc4xx.h
index d795ced..2b96d47 100644
--- a/hw/ppc4xx.h
+++ b/hw/ppc4xx.h
@@ -25,7 +25,7 @@
 #if !defined(PPC_4XX_H)
 #define PPC_4XX_H
 
-#include "pci.h"
+#include "pci/pci.h"
 
 /* PowerPC 4xx core initialization */
 CPUPPCState *ppc4xx_init (const char *cpu_model,
diff --git a/hw/ppc4xx_pci.c b/hw/ppc4xx_pci.c
index d3ad6a0..3e8af11 100644
--- a/hw/ppc4xx_pci.c
+++ b/hw/ppc4xx_pci.c
@@ -22,8 +22,8 @@
 #include "hw.h"
 #include "ppc.h"
 #include "ppc4xx.h"
-#include "pci.h"
-#include "pci_host.h"
+#include "pci/pci.h"
+#include "pci/pci_host.h"
 #include "exec-memory.h"
 
 #undef DEBUG
diff --git a/hw/ppc_newworld.c b/hw/ppc_newworld.c
index 664747e..c1ff9d7 100644
--- a/hw/ppc_newworld.c
+++ b/hw/ppc_newworld.c
@@ -52,7 +52,7 @@
 #include "adb.h"
 #include "mac_dbdma.h"
 #include "nvram.h"
-#include "pci.h"
+#include "pci/pci.h"
 #include "net.h"
 #include "sysemu.h"
 #include "boards.h"
diff --git a/hw/ppc_oldworld.c b/hw/ppc_oldworld.c
index e8138c0..3bc29c6 100644
--- a/hw/ppc_oldworld.c
+++ b/hw/ppc_oldworld.c
@@ -32,7 +32,7 @@
 #include "sysemu.h"
 #include "net.h"
 #include "isa.h"
-#include "pci.h"
+#include "pci/pci.h"
 #include "boards.h"
 #include "fw_cfg.h"
 #include "escc.h"
diff --git a/hw/ppc_prep.c b/hw/ppc_prep.c
index bf15730..f6ffb59 100644
--- a/hw/ppc_prep.c
+++ b/hw/ppc_prep.c
@@ -29,8 +29,8 @@
 #include "net.h"
 #include "sysemu.h"
 #include "isa.h"
-#include "pci.h"
-#include "pci_host.h"
+#include "pci/pci.h"
+#include "pci/pci_host.h"
 #include "ppc.h"
 #include "boards.h"
 #include "qemu-log.h"
diff --git a/hw/ppce500_pci.c b/hw/ppce500_pci.c
index 2ff7438..39022aa 100644
--- a/hw/ppce500_pci.c
+++ b/hw/ppce500_pci.c
@@ -15,8 +15,8 @@
  */
 
 #include "hw.h"
-#include "pci.h"
-#include "pci_host.h"
+#include "pci/pci.h"
+#include "pci/pci_host.h"
 #include "bswap.h"
 
 #ifdef DEBUG_PCI
diff --git a/hw/prep_pci.c b/hw/prep_pci.c
index 0bc479c..5f22de6 100644
--- a/hw/prep_pci.c
+++ b/hw/prep_pci.c
@@ -23,8 +23,8 @@
  */
 
 #include "hw.h"
-#include "pci.h"
-#include "pci_host.h"
+#include "pci/pci.h"
+#include "pci/pci_host.h"
 #include "pc.h"
 #include "exec-memory.h"
 
diff --git a/hw/q35.h b/hw/q35.h
index e34f7c1..2f951c8 100644
--- a/hw/q35.h
+++ b/hw/q35.h
@@ -29,8 +29,8 @@
 #include "pc.h"
 #include "apm.h"
 #include "apic.h"
-#include "pci.h"
-#include "pcie_host.h"
+#include "pci/pci.h"
+#include "pci/pcie_host.h"
 #include "acpi.h"
 #include "acpi_ich9.h"
 #include "pam.h"
diff --git a/hw/qxl.h b/hw/qxl.h
index e583cfb..41246c7 100644
--- a/hw/qxl.h
+++ b/hw/qxl.h
@@ -2,7 +2,7 @@
 
 #include "console.h"
 #include "hw.h"
-#include "pci.h"
+#include "pci/pci.h"
 #include "vga_int.h"
 #include "qemu-thread.h"
 
diff --git a/hw/r2d.c b/hw/r2d.c
index 66212e9..e18c23b 100644
--- a/hw/r2d.c
+++ b/hw/r2d.c
@@ -29,7 +29,7 @@
 #include "devices.h"
 #include "sysemu.h"
 #include "boards.h"
-#include "pci.h"
+#include "pci/pci.h"
 #include "net.h"
 #include "sh7750_regs.h"
 #include "ide.h"
diff --git a/hw/realview.c b/hw/realview.c
index e789c15..149bb56 100644
--- a/hw/realview.c
+++ b/hw/realview.c
@@ -11,7 +11,7 @@
 #include "arm-misc.h"
 #include "primecell.h"
 #include "devices.h"
-#include "pci.h"
+#include "pci/pci.h"
 #include "net.h"
 #include "sysemu.h"
 #include "boards.h"
diff --git a/hw/rtl8139.c b/hw/rtl8139.c
index e3aa8bf..e294a2a 100644
--- a/hw/rtl8139.c
+++ b/hw/rtl8139.c
@@ -52,7 +52,7 @@
 #include <zlib.h>
 
 #include "hw.h"
-#include "pci.h"
+#include "pci/pci.h"
 #include "dma.h"
 #include "qemu-timer.h"
 #include "net.h"
diff --git a/hw/serial-pci.c b/hw/serial-pci.c
index 95dc5c8..6a2548a 100644
--- a/hw/serial-pci.c
+++ b/hw/serial-pci.c
@@ -26,7 +26,7 @@
 /* see docs/specs/pci-serial.txt */
 
 #include "serial.h"
-#include "pci.h"
+#include "pci/pci.h"
 
 #define PCI_SERIAL_MAX_PORTS 4
 
diff --git a/hw/sga.c b/hw/sga.c
index a666349..5d80efd 100644
--- a/hw/sga.c
+++ b/hw/sga.c
@@ -24,7 +24,7 @@
  * sgabios code originally available at code.google.com/p/sgabios
  *
  */
-#include "pci.h"
+#include "pci/pci.h"
 #include "pc.h"
 #include "loader.h"
 #include "sysemu.h"
diff --git a/hw/sh_pci.c b/hw/sh_pci.c
index fdec71b..9ea08c8 100644
--- a/hw/sh_pci.c
+++ b/hw/sh_pci.c
@@ -23,8 +23,8 @@
  */
 #include "sysbus.h"
 #include "sh.h"
-#include "pci.h"
-#include "pci_host.h"
+#include "pci/pci.h"
+#include "pci/pci_host.h"
 #include "bswap.h"
 #include "exec-memory.h"
 
diff --git a/hw/smbus_ich9.c b/hw/smbus_ich9.c
index 6d31e24..0c52497 100644
--- a/hw/smbus_ich9.c
+++ b/hw/smbus_ich9.c
@@ -27,7 +27,7 @@
 #include "hw.h"
 #include "pc.h"
 #include "pm_smbus.h"
-#include "pci.h"
+#include "pci/pci.h"
 #include "sysemu.h"
 #include "i2c.h"
 #include "smbus.h"
diff --git a/hw/spapr.c b/hw/spapr.c
index ad3f0ea..b0125a8 100644
--- a/hw/spapr.c
+++ b/hw/spapr.c
@@ -41,11 +41,11 @@
 #include "hw/spapr_vio.h"
 #include "hw/spapr_pci.h"
 #include "hw/xics.h"
-#include "hw/msi.h"
+#include "hw/pci/msi.h"
 
 #include "kvm.h"
 #include "kvm_ppc.h"
-#include "pci.h"
+#include "pci/pci.h"
 
 #include "exec-memory.h"
 #include "hw/usb.h"
diff --git a/hw/spapr_pci.c b/hw/spapr_pci.c
index a08ed11..e123866 100644
--- a/hw/spapr_pci.c
+++ b/hw/spapr_pci.c
@@ -23,17 +23,17 @@
  * THE SOFTWARE.
  */
 #include "hw.h"
-#include "pci.h"
-#include "msi.h"
-#include "msix.h"
-#include "pci_host.h"
+#include "pci/pci.h"
+#include "pci/msi.h"
+#include "pci/msix.h"
+#include "pci/pci_host.h"
 #include "hw/spapr.h"
 #include "hw/spapr_pci.h"
 #include "exec-memory.h"
 #include <libfdt.h>
 #include "trace.h"
 
-#include "hw/pci_internals.h"
+#include "hw/pci/pci_internals.h"
 
 /* Copied from the kernel arch/powerpc/platforms/pseries/msi.c */
 #define RTAS_QUERY_FN           0
diff --git a/hw/spapr_pci.h b/hw/spapr_pci.h
index e307ac8..7b26ba1 100644
--- a/hw/spapr_pci.h
+++ b/hw/spapr_pci.h
@@ -23,8 +23,8 @@
 #if !defined(__HW_SPAPR_PCI_H__)
 #define __HW_SPAPR_PCI_H__
 
-#include "hw/pci.h"
-#include "hw/pci_host.h"
+#include "hw/pci/pci.h"
+#include "hw/pci/pci_host.h"
 #include "hw/xics.h"
 
 #define SPAPR_MSIX_MAX_DEVS 32
diff --git a/hw/sun4u.c b/hw/sun4u.c
index b2b51e3..47bcf93 100644
--- a/hw/sun4u.c
+++ b/hw/sun4u.c
@@ -22,7 +22,7 @@
  * THE SOFTWARE.
  */
 #include "hw.h"
-#include "pci.h"
+#include "pci/pci.h"
 #include "apb_pci.h"
 #include "pc.h"
 #include "serial.h"
diff --git a/hw/unin_pci.c b/hw/unin_pci.c
index 9981d94..4675792 100644
--- a/hw/unin_pci.c
+++ b/hw/unin_pci.c
@@ -23,8 +23,8 @@
  */
 #include "hw.h"
 #include "ppc_mac.h"
-#include "pci.h"
-#include "pci_host.h"
+#include "pci/pci.h"
+#include "pci/pci_host.h"
 
 /* debug UniNorth */
 //#define DEBUG_UNIN
diff --git a/hw/usb/hcd-ehci-pci.c b/hw/usb/hcd-ehci-pci.c
index 5887eab..c957c11 100644
--- a/hw/usb/hcd-ehci-pci.c
+++ b/hw/usb/hcd-ehci-pci.c
@@ -16,7 +16,7 @@
  */
 
 #include "hw/usb/hcd-ehci.h"
-#include "hw/pci.h"
+#include "hw/pci/pci.h"
 #include "range.h"
 
 typedef struct EHCIPCIState {
diff --git a/hw/usb/hcd-ohci.c b/hw/usb/hcd-ohci.c
index 64de906..6b7c3dc 100644
--- a/hw/usb/hcd-ohci.c
+++ b/hw/usb/hcd-ohci.c
@@ -29,7 +29,7 @@
 #include "hw/hw.h"
 #include "qemu-timer.h"
 #include "hw/usb.h"
-#include "hw/pci.h"
+#include "hw/pci/pci.h"
 #include "hw/sysbus.h"
 #include "hw/qdev-dma.h"
 
diff --git a/hw/usb/hcd-uhci.c b/hw/usb/hcd-uhci.c
index 8e47803..808b004 100644
--- a/hw/usb/hcd-uhci.c
+++ b/hw/usb/hcd-uhci.c
@@ -27,7 +27,7 @@
  */
 #include "hw/hw.h"
 #include "hw/usb.h"
-#include "hw/pci.h"
+#include "hw/pci/pci.h"
 #include "qemu-timer.h"
 #include "iov.h"
 #include "dma.h"
diff --git a/hw/usb/hcd-xhci.c b/hw/usb/hcd-xhci.c
index 8ef4b07..93117ec 100644
--- a/hw/usb/hcd-xhci.c
+++ b/hw/usb/hcd-xhci.c
@@ -21,9 +21,9 @@
 #include "hw/hw.h"
 #include "qemu-timer.h"
 #include "hw/usb.h"
-#include "hw/pci.h"
-#include "hw/msi.h"
-#include "hw/msix.h"
+#include "hw/pci/pci.h"
+#include "hw/pci/msi.h"
+#include "hw/pci/msix.h"
 #include "trace.h"
 
 //#define DEBUG_XHCI
diff --git a/hw/versatile_pci.c b/hw/versatile_pci.c
index e0c3ee3..7a543b4 100644
--- a/hw/versatile_pci.c
+++ b/hw/versatile_pci.c
@@ -8,8 +8,8 @@
  */
 
 #include "sysbus.h"
-#include "pci.h"
-#include "pci_host.h"
+#include "pci/pci.h"
+#include "pci/pci_host.h"
 #include "exec-memory.h"
 
 typedef struct {
diff --git a/hw/versatilepb.c b/hw/versatilepb.c
index 25e652b..41e39d8 100644
--- a/hw/versatilepb.c
+++ b/hw/versatilepb.c
@@ -12,7 +12,7 @@
 #include "devices.h"
 #include "net.h"
 #include "sysemu.h"
-#include "pci.h"
+#include "pci/pci.h"
 #include "i2c.h"
 #include "boards.h"
 #include "blockdev.h"
diff --git a/hw/vfio_pci.c b/hw/vfio_pci.c
index 7c27834..45d90ab 100644
--- a/hw/vfio_pci.c
+++ b/hw/vfio_pci.c
@@ -31,9 +31,9 @@
 #include "exec-memory.h"
 #include "kvm.h"
 #include "memory.h"
-#include "msi.h"
-#include "msix.h"
-#include "pci.h"
+#include "pci/msi.h"
+#include "pci/msix.h"
+#include "pci/pci.h"
 #include "qemu-common.h"
 #include "qemu-error.h"
 #include "qemu-queue.h"
diff --git a/hw/vga-pci.c b/hw/vga-pci.c
index 947e35c..0cb318e 100644
--- a/hw/vga-pci.c
+++ b/hw/vga-pci.c
@@ -25,7 +25,7 @@
  */
 #include "hw.h"
 #include "console.h"
-#include "pci.h"
+#include "pci/pci.h"
 #include "vga_int.h"
 #include "pixel_ops.h"
 #include "qemu-timer.h"
diff --git a/hw/vga.c b/hw/vga.c
index 2b0200a..6d56f8a 100644
--- a/hw/vga.c
+++ b/hw/vga.c
@@ -25,7 +25,7 @@
 #include "vga.h"
 #include "console.h"
 #include "pc.h"
-#include "pci.h"
+#include "pci/pci.h"
 #include "vga_int.h"
 #include "pixel_ops.h"
 #include "qemu-timer.h"
diff --git a/hw/virtio-balloon.h b/hw/virtio-balloon.h
index 73300dd..b1828f4 100644
--- a/hw/virtio-balloon.h
+++ b/hw/virtio-balloon.h
@@ -16,7 +16,7 @@
 #define _QEMU_VIRTIO_BALLOON_H
 
 #include "virtio.h"
-#include "pci.h"
+#include "pci/pci.h"
 
 /* from Linux's linux/virtio_balloon.h */
 
diff --git a/hw/virtio-net.h b/hw/virtio-net.h
index 36aa463..b13be7c 100644
--- a/hw/virtio-net.h
+++ b/hw/virtio-net.h
@@ -16,7 +16,7 @@
 
 #include "virtio.h"
 #include "net.h"
-#include "pci.h"
+#include "pci/pci.h"
 
 #define ETH_ALEN    6
 
diff --git a/hw/virtio-pci.c b/hw/virtio-pci.c
index 71f4fb5..e9b722d 100644
--- a/hw/virtio-pci.c
+++ b/hw/virtio-pci.c
@@ -22,10 +22,10 @@
 #include "virtio-net.h"
 #include "virtio-serial.h"
 #include "virtio-scsi.h"
-#include "pci.h"
+#include "pci/pci.h"
 #include "qemu-error.h"
-#include "msi.h"
-#include "msix.h"
+#include "pci/msi.h"
+#include "pci/msix.h"
 #include "net.h"
 #include "loader.h"
 #include "kvm.h"
diff --git a/hw/virtio-scsi.h b/hw/virtio-scsi.h
index 91924f6..7d7cba7 100644
--- a/hw/virtio-scsi.h
+++ b/hw/virtio-scsi.h
@@ -16,7 +16,7 @@
 
 #include "virtio.h"
 #include "net.h"
-#include "pci.h"
+#include "pci/pci.h"
 
 /* The ID for virtio_scsi */
 #define VIRTIO_ID_SCSI  8
diff --git a/hw/vmware_vga.c b/hw/vmware_vga.c
index 834588d..333ec8c 100644
--- a/hw/vmware_vga.c
+++ b/hw/vmware_vga.c
@@ -24,7 +24,7 @@
 #include "hw.h"
 #include "loader.h"
 #include "console.h"
-#include "pci.h"
+#include "pci/pci.h"
 
 #undef VERBOSE
 #define HW_RECT_ACCEL
diff --git a/hw/vt82c686.c b/hw/vt82c686.c
index 5d7c00c..620fb75 100644
--- a/hw/vt82c686.c
+++ b/hw/vt82c686.c
@@ -15,7 +15,7 @@
 #include "vt82c686.h"
 #include "i2c.h"
 #include "smbus.h"
-#include "pci.h"
+#include "pci/pci.h"
 #include "isa.h"
 #include "sysbus.h"
 #include "mips.h"
@@ -26,7 +26,7 @@
 #include "qemu-timer.h"
 
 typedef uint32_t pci_addr_t;
-#include "pci_host.h"
+#include "pci/pci_host.h"
 //#define DEBUG_VT82C686B
 
 #ifdef DEBUG_VT82C686B
diff --git a/hw/wdt_i6300esb.c b/hw/wdt_i6300esb.c
index da15c73..1817742 100644
--- a/hw/wdt_i6300esb.c
+++ b/hw/wdt_i6300esb.c
@@ -25,7 +25,7 @@
 #include "qemu-timer.h"
 #include "watchdog.h"
 #include "hw.h"
-#include "pci.h"
+#include "pci/pci.h"
 
 /*#define I6300ESB_DEBUG 1*/
 
diff --git a/hw/xen-host-pci-device.h b/hw/xen-host-pci-device.h
index 0079dac..942b24d 100644
--- a/hw/xen-host-pci-device.h
+++ b/hw/xen-host-pci-device.h
@@ -1,7 +1,7 @@
 #ifndef XEN_HOST_PCI_DEVICE_H
 #define XEN_HOST_PCI_DEVICE_H
 
-#include "pci.h"
+#include "pci/pci.h"
 
 enum {
     XEN_HOST_PCI_REGION_TYPE_IO = 1 << 1,
diff --git a/hw/xen_apic.c b/hw/xen_apic.c
index fc45366..a6632fe 100644
--- a/hw/xen_apic.c
+++ b/hw/xen_apic.c
@@ -10,7 +10,7 @@
  * later. See the COPYING file in the top-level directory.
  */
 #include "hw/apic_internal.h"
-#include "hw/msi.h"
+#include "hw/pci/msi.h"
 #include "xen.h"
 
 static uint64_t xen_apic_mem_read(void *opaque, hwaddr addr,
diff --git a/hw/xen_platform.c b/hw/xen_platform.c
index a54e7a2..10bb560 100644
--- a/hw/xen_platform.c
+++ b/hw/xen_platform.c
@@ -27,7 +27,7 @@
 
 #include "hw.h"
 #include "pc.h"
-#include "pci.h"
+#include "pci/pci.h"
 #include "irq.h"
 #include "xen_common.h"
 #include "net.h"
diff --git a/hw/xen_pt.c b/hw/xen_pt.c
index 7a3846e..c782cdb 100644
--- a/hw/xen_pt.c
+++ b/hw/xen_pt.c
@@ -54,7 +54,7 @@
 
 #include <sys/ioctl.h>
 
-#include "pci.h"
+#include "pci/pci.h"
 #include "xen.h"
 #include "xen_backend.h"
 #include "xen_pt.h"
diff --git a/hw/xen_pt.h b/hw/xen_pt.h
index f15e69a..e349730 100644
--- a/hw/xen_pt.h
+++ b/hw/xen_pt.h
@@ -3,7 +3,7 @@
 
 #include "qemu-common.h"
 #include "xen_common.h"
-#include "pci.h"
+#include "pci/pci.h"
 #include "xen-host-pci-device.h"
 
 void xen_pt_log(const PCIDevice *d, const char *f, ...) GCC_FMT_ATTR(2, 3);
diff --git a/hw/xio3130_downstream.c b/hw/xio3130_downstream.c
index 0d8a5e7..2dcd46b 100644
--- a/hw/xio3130_downstream.c
+++ b/hw/xio3130_downstream.c
@@ -19,9 +19,9 @@
  * with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
-#include "pci_ids.h"
-#include "msi.h"
-#include "pcie.h"
+#include "pci/pci_ids.h"
+#include "pci/msi.h"
+#include "pci/pcie.h"
 #include "xio3130_downstream.h"
 
 #define PCI_DEVICE_ID_TI_XIO3130D       0x8233  /* downstream port */
diff --git a/hw/xio3130_downstream.h b/hw/xio3130_downstream.h
index 010487f..559dff6 100644
--- a/hw/xio3130_downstream.h
+++ b/hw/xio3130_downstream.h
@@ -1,7 +1,7 @@
 #ifndef QEMU_XIO3130_DOWNSTREAM_H
 #define QEMU_XIO3130_DOWNSTREAM_H
 
-#include "pcie_port.h"
+#include "pci/pcie_port.h"
 
 PCIESlot *xio3130_downstream_init(PCIBus *bus, int devfn, bool multifunction,
                                   const char *bus_name, pci_map_irq_fn map_irq,
diff --git a/hw/xio3130_upstream.c b/hw/xio3130_upstream.c
index d46b86c..713caf2 100644
--- a/hw/xio3130_upstream.c
+++ b/hw/xio3130_upstream.c
@@ -19,9 +19,9 @@
  * with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
-#include "pci_ids.h"
-#include "msi.h"
-#include "pcie.h"
+#include "pci/pci_ids.h"
+#include "pci/msi.h"
+#include "pci/pcie.h"
 #include "xio3130_upstream.h"
 
 #define PCI_DEVICE_ID_TI_XIO3130U       0x8232  /* upstream port */
diff --git a/hw/xio3130_upstream.h b/hw/xio3130_upstream.h
index e996997..fa09656 100644
--- a/hw/xio3130_upstream.h
+++ b/hw/xio3130_upstream.h
@@ -1,7 +1,7 @@
 #ifndef QEMU_XIO3130_UPSTREAM_H
 #define QEMU_XIO3130_UPSTREAM_H
 
-#include "pcie_port.h"
+#include "pci/pcie_port.h"
 
 PCIEPort *xio3130_upstream_init(PCIBus *bus, int devfn, bool multifunction,
                                 const char *bus_name, pci_map_irq_fn map_irq,
diff --git a/kvm-all.c b/kvm-all.c
index fb3180d..4bbad86 100644
--- a/kvm-all.c
+++ b/kvm-all.c
@@ -26,7 +26,7 @@
 #include "qemu-config.h"
 #include "sysemu.h"
 #include "hw/hw.h"
-#include "hw/msi.h"
+#include "hw/pci/msi.h"
 #include "gdbstub.h"
 #include "kvm.h"
 #include "bswap.h"
diff --git a/kvm-stub.c b/kvm-stub.c
index a3455e2..d65fd04 100644
--- a/kvm-stub.c
+++ b/kvm-stub.c
@@ -12,7 +12,7 @@
 
 #include "qemu-common.h"
 #include "hw/hw.h"
-#include "hw/msi.h"
+#include "hw/pci/msi.h"
 #include "cpu.h"
 #include "gdbstub.h"
 #include "kvm.h"
diff --git a/monitor.c b/monitor.c
index c0e32d6..a92ab44 100644
--- a/monitor.c
+++ b/monitor.c
@@ -27,7 +27,7 @@
 #include "hw/usb.h"
 #include "hw/pcmcia.h"
 #include "hw/pc.h"
-#include "hw/pci.h"
+#include "hw/pci/pci.h"
 #include "hw/watchdog.h"
 #include "hw/loader.h"
 #include "gdbstub.h"
diff --git a/target-i386/kvm.c b/target-i386/kvm.c
index f669281..0901589 100644
--- a/target-i386/kvm.c
+++ b/target-i386/kvm.c
@@ -31,7 +31,7 @@
 #include "hw/apic.h"
 #include "ioport.h"
 #include "hyperv.h"
-#include "hw/pci.h"
+#include "hw/pci/pci.h"
 
 //#define DEBUG_KVM
 
diff --git a/xen-all.c b/xen-all.c
index 046cc2a..e3a51cc 100644
--- a/xen-all.c
+++ b/xen-all.c
@@ -10,7 +10,7 @@
 
 #include <sys/mman.h>
 
-#include "hw/pci.h"
+#include "hw/pci/pci.h"
 #include "hw/pc.h"
 #include "hw/xen_common.h"
 #include "hw/xen_backend.h"
-- 
MST

^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [Qemu-devel] [PATCH 6/8] Revert "pci: prepare makefiles for pci code reorganization"
  2012-12-12 13:13 [Qemu-devel] [PATCH 0/8] pci core reorg Michael S. Tsirkin
                   ` (3 preceding siblings ...)
  2012-12-12 13:14 ` [Qemu-devel] [PATCH 4/8] pci: update all users to look in pci/ Michael S. Tsirkin
@ 2012-12-12 13:14 ` Michael S. Tsirkin
  2012-12-12 13:14 ` [Qemu-devel] [PATCH 5/8] pci: make external dependencies explicit Michael S. Tsirkin
                   ` (4 subsequent siblings)
  9 siblings, 0 replies; 19+ messages in thread
From: Michael S. Tsirkin @ 2012-12-12 13:14 UTC (permalink / raw)
  To: qemu-devel

This reverts commit 475d67c3bcd6ba9fef917b6e59d96ae69eb1a9b4.

Now that all users have been updated, we don't need the
makefile hack or the softlink anymore.

Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
---
 Makefile        | 1 -
 Makefile.target | 1 -
 Makefile.user   | 1 -
 hw/pci/hw       | 1 -
 4 files changed, 4 deletions(-)
 delete mode 120000 hw/pci/hw

diff --git a/Makefile b/Makefile
index b9a81d1..9ecbcbb 100644
--- a/Makefile
+++ b/Makefile
@@ -146,7 +146,6 @@ audio/audio.o audio/fmodaudio.o: QEMU_CFLAGS += $(FMOD_CFLAGS)
 QEMU_CFLAGS+=$(CURL_CFLAGS)
 
 QEMU_CFLAGS += -I$(SRC_PATH)/include
-QEMU_CFLAGS+=-I$(SRC_PATH)/hw/pci -I$(SRC_PATH)/hw
 
 ui/cocoa.o: ui/cocoa.m
 
diff --git a/Makefile.target b/Makefile.target
index e2e8840..8b658c0 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -12,7 +12,6 @@ endif
 QEMU_CFLAGS += -I.. -I$(SRC_PATH)/target-$(TARGET_BASE_ARCH) -DNEED_CPU_H
 
 QEMU_CFLAGS+=-I$(SRC_PATH)/include
-QEMU_CFLAGS+=-I$(SRC_PATH)/hw/pci -I$(SRC_PATH)/hw
 
 ifdef CONFIG_USER_ONLY
 # user emulator name
diff --git a/Makefile.user b/Makefile.user
index 045ecd3..9302d33 100644
--- a/Makefile.user
+++ b/Makefile.user
@@ -11,7 +11,6 @@ $(call set-vpath, $(SRC_PATH))
 QEMU_CFLAGS+=-I..
 QEMU_CFLAGS += -I$(SRC_PATH)/include
 QEMU_CFLAGS += -DCONFIG_USER_ONLY
-QEMU_CFLAGS+=-I$(SRC_PATH)/hw/pci -I$(SRC_PATH)/hw
 
 include $(SRC_PATH)/Makefile.objs
 
diff --git a/hw/pci/hw b/hw/pci/hw
deleted file mode 120000
index 945c9b4..0000000
--- a/hw/pci/hw
+++ /dev/null
@@ -1 +0,0 @@
-.
\ No newline at end of file
-- 
MST

^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [Qemu-devel] [PATCH 5/8] pci: make external dependencies explicit
  2012-12-12 13:13 [Qemu-devel] [PATCH 0/8] pci core reorg Michael S. Tsirkin
                   ` (4 preceding siblings ...)
  2012-12-12 13:14 ` [Qemu-devel] [PATCH 6/8] Revert "pci: prepare makefiles for pci code reorganization" Michael S. Tsirkin
@ 2012-12-12 13:14 ` Michael S. Tsirkin
  2012-12-12 19:49   ` Blue Swirl
  2012-12-12 13:14 ` [Qemu-devel] [PATCH 7/8] pci: rename pci_internals.h pci_bus.h Michael S. Tsirkin
                   ` (3 subsequent siblings)
  9 siblings, 1 reply; 19+ messages in thread
From: Michael S. Tsirkin @ 2012-12-12 13:14 UTC (permalink / raw)
  To: qemu-devel

Include dependencies from pci core using <> and
the correct path.
Need to check whether they can be minimized, for now,
at least make them explicit.

Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
---
 hw/pci/msix.c        |  4 ++--
 hw/pci/pci-hotplug.c | 20 ++++++++++----------
 hw/pci/pci.c         | 16 ++++++++--------
 hw/pci/pci.h         | 10 +++++-----
 hw/pci/pci_host.h    |  2 +-
 hw/pci/pcie.h        |  2 +-
 hw/pci/pcie_aer.h    |  2 +-
 hw/pci/pcie_host.c   |  4 ++--
 8 files changed, 30 insertions(+), 30 deletions(-)

diff --git a/hw/pci/msix.c b/hw/pci/msix.c
index 136ef09..ec35a5d 100644
--- a/hw/pci/msix.c
+++ b/hw/pci/msix.c
@@ -14,11 +14,11 @@
  * GNU GPL, version 2 or (at your option) any later version.
  */
 
-#include "hw.h"
+#include <hw/hw.h>
 #include "msi.h"
 #include "msix.h"
 #include "pci.h"
-#include "range.h"
+#include <range.h>
 
 #define MSIX_CAP_LENGTH 12
 
diff --git a/hw/pci/pci-hotplug.c b/hw/pci/pci-hotplug.c
index 0ca5546..32ba449 100644
--- a/hw/pci/pci-hotplug.c
+++ b/hw/pci/pci-hotplug.c
@@ -22,17 +22,17 @@
  * THE SOFTWARE.
  */
 
-#include "hw.h"
-#include "boards.h"
+#include <hw/hw.h>
+#include <hw/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"
+#include <net.h>
+#include <hw/pc.h>
+#include <monitor.h>
+#include <hw/scsi.h>
+#include <hw/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,
diff --git a/hw/pci/pci.c b/hw/pci/pci.c
index 97a0cd7..6023ded 100644
--- a/hw/pci/pci.c
+++ b/hw/pci/pci.c
@@ -21,19 +21,19 @@
  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  * THE SOFTWARE.
  */
-#include "hw.h"
+#include <hw/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 <monitor.h>
+#include <net.h>
+#include <sysemu.h>
+#include <hw/loader.h>
+#include <range.h>
+#include <qmp-commands.h>
 #include "msi.h"
 #include "msix.h"
-#include "exec-memory.h"
+#include <exec-memory.h>
 
 //#define DEBUG_PCI
 #ifdef DEBUG_PCI
diff --git a/hw/pci/pci.h b/hw/pci/pci.h
index 4da0c2a..b517995 100644
--- a/hw/pci/pci.h
+++ b/hw/pci/pci.h
@@ -1,14 +1,14 @@
 #ifndef QEMU_PCI_H
 #define QEMU_PCI_H
 
-#include "qemu-common.h"
+#include <qemu-common.h>
 
-#include "qdev.h"
-#include "memory.h"
-#include "dma.h"
+#include <hw/qdev.h>
+#include <memory.h>
+#include <dma.h>
 
 /* PCI includes legacy ISA access.  */
-#include "isa.h"
+#include <hw/isa.h>
 
 #include "pcie.h"
 
diff --git a/hw/pci/pci_host.h b/hw/pci/pci_host.h
index 4b9c300..6dfb38d 100644
--- a/hw/pci/pci_host.h
+++ b/hw/pci/pci_host.h
@@ -28,7 +28,7 @@
 #ifndef PCI_HOST_H
 #define PCI_HOST_H
 
-#include "sysbus.h"
+#include <hw/sysbus.h>
 
 #define TYPE_PCI_HOST_BRIDGE "pci-host-bridge"
 #define PCI_HOST_BRIDGE(obj) \
diff --git a/hw/pci/pcie.h b/hw/pci/pcie.h
index 4889194..cc1f2c5 100644
--- a/hw/pci/pcie.h
+++ b/hw/pci/pcie.h
@@ -21,7 +21,7 @@
 #ifndef QEMU_PCIE_H
 #define QEMU_PCIE_H
 
-#include "hw.h"
+#include <hw/hw.h>
 #include "pci_regs.h"
 #include "pcie_regs.h"
 #include "pcie_aer.h"
diff --git a/hw/pci/pcie_aer.h b/hw/pci/pcie_aer.h
index 7539500..406a736 100644
--- a/hw/pci/pcie_aer.h
+++ b/hw/pci/pcie_aer.h
@@ -21,7 +21,7 @@
 #ifndef QEMU_PCIE_AER_H
 #define QEMU_PCIE_AER_H
 
-#include "hw.h"
+#include <hw/hw.h>
 
 /* definitions which PCIExpressDevice uses */
 
diff --git a/hw/pci/pcie_host.c b/hw/pci/pcie_host.c
index c257fb4..4453cb0 100644
--- a/hw/pci/pcie_host.c
+++ b/hw/pci/pcie_host.c
@@ -19,10 +19,10 @@
  * with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
-#include "hw.h"
+#include <hw/hw.h>
 #include "pci.h"
 #include "pcie_host.h"
-#include "exec-memory.h"
+#include <exec-memory.h>
 
 /*
  * PCI express mmcfig address
-- 
MST

^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [Qemu-devel] [PATCH 7/8] pci: rename pci_internals.h pci_bus.h
  2012-12-12 13:13 [Qemu-devel] [PATCH 0/8] pci core reorg Michael S. Tsirkin
                   ` (5 preceding siblings ...)
  2012-12-12 13:14 ` [Qemu-devel] [PATCH 5/8] pci: make external dependencies explicit Michael S. Tsirkin
@ 2012-12-12 13:14 ` Michael S. Tsirkin
  2012-12-12 19:56   ` Blue Swirl
  2012-12-12 13:14 ` [Qemu-devel] [PATCH 8/8] pci_bus: update comment Michael S. Tsirkin
                   ` (2 subsequent siblings)
  9 siblings, 1 reply; 19+ messages in thread
From: Michael S. Tsirkin @ 2012-12-12 13:14 UTC (permalink / raw)
  To: qemu-devel

There are lots of external users of pci_internals.h,
apparently making it an internal interface only didn't
work out. Let's stop pretending it's an internal header.

Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
---
 hw/apb_pci.c           |  2 +-
 hw/dec_pci.c           |  2 +-
 hw/ich9.h              |  2 +-
 hw/lpc_ich9.c          |  2 +-
 hw/pci/pci.c           |  2 +-
 hw/pci/pci_bridge.c    |  2 +-
 hw/pci/pci_bus.h       | 78 ++++++++++++++++++++++++++++++++++++++++++++++++++
 hw/pci/pci_internals.h | 78 --------------------------------------------------
 hw/pci/pcie.c          |  2 +-
 hw/pci/pcie_aer.c      |  2 +-
 hw/pci/pcie_port.h     |  2 +-
 hw/pci/shpc.c          |  2 +-
 hw/pci_bridge_dev.c    |  2 +-
 hw/spapr_pci.c         |  2 +-
 14 files changed, 90 insertions(+), 90 deletions(-)
 create mode 100644 hw/pci/pci_bus.h
 delete mode 100644 hw/pci/pci_internals.h

diff --git a/hw/apb_pci.c b/hw/apb_pci.c
index de594f8..fb7a07d 100644
--- a/hw/apb_pci.c
+++ b/hw/apb_pci.c
@@ -30,7 +30,7 @@
 #include "pci/pci.h"
 #include "pci/pci_host.h"
 #include "pci/pci_bridge.h"
-#include "pci/pci_internals.h"
+#include "pci/pci_bus.h"
 #include "apb_pci.h"
 #include "sysemu.h"
 #include "exec-memory.h"
diff --git a/hw/dec_pci.c b/hw/dec_pci.c
index a6a7c84..ee3f4ca 100644
--- a/hw/dec_pci.c
+++ b/hw/dec_pci.c
@@ -28,7 +28,7 @@
 #include "pci/pci.h"
 #include "pci/pci_host.h"
 #include "pci/pci_bridge.h"
-#include "pci/pci_internals.h"
+#include "pci/pci_bus.h"
 
 /* debug DEC */
 //#define DEBUG_DEC
diff --git a/hw/ich9.h b/hw/ich9.h
index 247be94..4e7442c 100644
--- a/hw/ich9.h
+++ b/hw/ich9.h
@@ -14,7 +14,7 @@
 #include "acpi.h"
 #include "acpi_ich9.h"
 #include "pam.h"
-#include "pci/pci_internals.h"
+#include "pci/pci_bus.h"
 
 void ich9_lpc_set_irq(void *opaque, int irq_num, int level);
 int ich9_lpc_map_irq(PCIDevice *pci_dev, int intx);
diff --git a/hw/lpc_ich9.c b/hw/lpc_ich9.c
index 23dee88..7bca061 100644
--- a/hw/lpc_ich9.c
+++ b/hw/lpc_ich9.c
@@ -42,7 +42,7 @@
 #include "acpi.h"
 #include "acpi_ich9.h"
 #include "pam.h"
-#include "pci/pci_internals.h"
+#include "pci/pci_bus.h"
 #include "exec-memory.h"
 
 static int ich9_lpc_sci_irq(ICH9LPCState *lpc);
diff --git a/hw/pci/pci.c b/hw/pci/pci.c
index 6023ded..c1a4b32 100644
--- a/hw/pci/pci.c
+++ b/hw/pci/pci.c
@@ -24,7 +24,7 @@
 #include <hw/hw.h>
 #include "pci.h"
 #include "pci_bridge.h"
-#include "pci_internals.h"
+#include "pci_bus.h"
 #include <monitor.h>
 #include <net.h>
 #include <sysemu.h>
diff --git a/hw/pci/pci_bridge.c b/hw/pci/pci_bridge.c
index 4680501..0fb7577 100644
--- a/hw/pci/pci_bridge.c
+++ b/hw/pci/pci_bridge.c
@@ -30,7 +30,7 @@
  */
 
 #include "pci_bridge.h"
-#include "pci_internals.h"
+#include "pci_bus.h"
 #include "range.h"
 
 /* PCI bridge subsystem vendor ID helper functions */
diff --git a/hw/pci/pci_bus.h b/hw/pci/pci_bus.h
new file mode 100644
index 0000000..21d0ce6
--- /dev/null
+++ b/hw/pci/pci_bus.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_internals.h b/hw/pci/pci_internals.h
deleted file mode 100644
index 21d0ce6..0000000
--- a/hw/pci/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/pcie.c b/hw/pci/pcie.c
index 7c92f19..d9c38b5 100644
--- a/hw/pci/pcie.c
+++ b/hw/pci/pcie.c
@@ -23,7 +23,7 @@
 #include "pcie.h"
 #include "msix.h"
 #include "msi.h"
-#include "pci_internals.h"
+#include "pci_bus.h"
 #include "pcie_regs.h"
 #include "range.h"
 
diff --git a/hw/pci/pcie_aer.c b/hw/pci/pcie_aer.c
index b04c164..3c3185c 100644
--- a/hw/pci/pcie_aer.c
+++ b/hw/pci/pcie_aer.c
@@ -25,7 +25,7 @@
 #include "pcie.h"
 #include "msix.h"
 #include "msi.h"
-#include "pci_internals.h"
+#include "pci_bus.h"
 #include "pcie_regs.h"
 
 //#define DEBUG_PCIE
diff --git a/hw/pci/pcie_port.h b/hw/pci/pcie_port.h
index 3709583..36b2241 100644
--- a/hw/pci/pcie_port.h
+++ b/hw/pci/pcie_port.h
@@ -22,7 +22,7 @@
 #define QEMU_PCIE_PORT_H
 
 #include "pci_bridge.h"
-#include "pci_internals.h"
+#include "pci_bus.h"
 
 struct PCIEPort {
     PCIBridge   br;
diff --git a/hw/pci/shpc.c b/hw/pci/shpc.c
index 4597bbd..9297af0 100644
--- a/hw/pci/shpc.c
+++ b/hw/pci/shpc.c
@@ -4,7 +4,7 @@
 #include "range.h"
 #include "shpc.h"
 #include "pci.h"
-#include "pci_internals.h"
+#include "pci_bus.h"
 #include "msi.h"
 
 /* TODO: model power only and disabled slot states. */
diff --git a/hw/pci_bridge_dev.c b/hw/pci_bridge_dev.c
index 5c9fc50..dbb4b3b 100644
--- a/hw/pci_bridge_dev.c
+++ b/hw/pci_bridge_dev.c
@@ -25,7 +25,7 @@
 #include "pci/shpc.h"
 #include "pci/slotid_cap.h"
 #include "memory.h"
-#include "pci/pci_internals.h"
+#include "pci/pci_bus.h"
 
 #define REDHAT_PCI_VENDOR_ID 0x1b36
 #define PCI_BRIDGE_DEV_VENDOR_ID REDHAT_PCI_VENDOR_ID
diff --git a/hw/spapr_pci.c b/hw/spapr_pci.c
index e123866..6b05e5b 100644
--- a/hw/spapr_pci.c
+++ b/hw/spapr_pci.c
@@ -33,7 +33,7 @@
 #include <libfdt.h>
 #include "trace.h"
 
-#include "hw/pci/pci_internals.h"
+#include "hw/pci/pci_bus.h"
 
 /* Copied from the kernel arch/powerpc/platforms/pseries/msi.c */
 #define RTAS_QUERY_FN           0
-- 
MST

^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [Qemu-devel] [PATCH 8/8] pci_bus: update comment
  2012-12-12 13:13 [Qemu-devel] [PATCH 0/8] pci core reorg Michael S. Tsirkin
                   ` (6 preceding siblings ...)
  2012-12-12 13:14 ` [Qemu-devel] [PATCH 7/8] pci: rename pci_internals.h pci_bus.h Michael S. Tsirkin
@ 2012-12-12 13:14 ` Michael S. Tsirkin
  2012-12-12 13:51 ` [Qemu-devel] [PATCH 0/8] pci core reorg Anthony Liguori
  2012-12-12 20:00 ` Blue Swirl
  9 siblings, 0 replies; 19+ messages in thread
From: Michael S. Tsirkin @ 2012-12-12 13:14 UTC (permalink / raw)
  To: qemu-devel

Don't ask everyone to desist from including this header,
simply recommend using accessors.

Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
---
 hw/pci/pci_bus.h | 10 +++-------
 1 file changed, 3 insertions(+), 7 deletions(-)

diff --git a/hw/pci/pci_bus.h b/hw/pci/pci_bus.h
index 21d0ce6..8217f61 100644
--- a/hw/pci/pci_bus.h
+++ b/hw/pci/pci_bus.h
@@ -2,14 +2,10 @@
 #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.
+ * PCI Bus and Bridge datastructures.
  *
- * 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
+ * Do not access the following members directly;
+ * use accessor functions in pci.h, pci_bridge.h
  */
 
 #define TYPE_PCI_BUS "PCI"
-- 
MST

^ permalink raw reply related	[flat|nested] 19+ messages in thread

* Re: [Qemu-devel] [PATCH 0/8] pci core reorg
  2012-12-12 13:13 [Qemu-devel] [PATCH 0/8] pci core reorg Michael S. Tsirkin
                   ` (7 preceding siblings ...)
  2012-12-12 13:14 ` [Qemu-devel] [PATCH 8/8] pci_bus: update comment Michael S. Tsirkin
@ 2012-12-12 13:51 ` Anthony Liguori
  2012-12-12 13:59   ` Paolo Bonzini
  2012-12-12 20:00 ` Blue Swirl
  9 siblings, 1 reply; 19+ messages in thread
From: Anthony Liguori @ 2012-12-12 13:51 UTC (permalink / raw)
  To: Michael S. Tsirkin, qemu-devel; +Cc: Paolo Bonzini

"Michael S. Tsirkin" <mst@redhat.com> writes:

> This patchset starts some cleanups of the pci core
> by rearranging the code: pci core is split out
> from devices into its own directory, pci internals.h
> is renamed as it's used externally a lot.
>
> I'd like to merge this quickly to avoid conflicting
> with others work.
> Plan to send pull request tomorrow, if you have concerns,
> speak up soon pls.

I'd like to see an Ack from Paolo as he's working on a tree-wide file
movement right now..  Don't want to conflict with what he's doing
unnecessarily.

Otherwise, this looks reasonable to me.

Regards,

Anthony Liguori

>
> Thanks,
>
>
>
> Michael S. Tsirkin (8):
>   pci: prepare makefiles for pci code reorganization
>   MAINTAINERS: add hw/pci/ to list of PCI files
>   pci: move pci core code to hw/pci
>   pci: update all users to look in pci/
>   pci: make external dependencies explicit
>   Revert "pci: prepare makefiles for pci code reorganization"
>   pci: rename pci_internals.h pci_bus.h
>   pci_bus: update comment
>
>  MAINTAINERS              |    1 +
>  arch_init.c              |    2 +-
>  hw/Makefile.objs         |   10 +-
>  hw/ac97.c                |    2 +-
>  hw/acpi_ich9.c           |    2 +-
>  hw/acpi_piix4.c          |    2 +-
>  hw/alpha_sys.h           |    4 +-
>  hw/apb_pci.c             |    8 +-
>  hw/apic.c                |    2 +-
>  hw/bonito.c              |    4 +-
>  hw/cirrus_vga.c          |    2 +-
>  hw/dec_pci.c             |    8 +-
>  hw/e1000.c               |    2 +-
>  hw/eepro100.c            |    2 +-
>  hw/es1370.c              |    2 +-
>  hw/esp-pci.c             |    2 +-
>  hw/grackle_pci.c         |    4 +-
>  hw/gt64xxx.c             |    4 +-
>  hw/hda-audio.c           |    2 +-
>  hw/i386/Makefile.objs    |    2 +-
>  hw/i82378.c              |    2 +-
>  hw/i82801b11.c           |    2 +-
>  hw/ich9.h                |    8 +-
>  hw/ide.h                 |    2 +-
>  hw/ide/ahci.c            |    4 +-
>  hw/ide/cmd646.c          |    2 +-
>  hw/ide/core.c            |    2 +-
>  hw/ide/ich.c             |    4 +-
>  hw/ide/pci.c             |    2 +-
>  hw/ide/piix.c            |    2 +-
>  hw/ide/via.c             |    2 +-
>  hw/intel-hda.c           |    4 +-
>  hw/ioh3420.c             |    6 +-
>  hw/ioh3420.h             |    2 +-
>  hw/ivshmem.c             |    4 +-
>  hw/kvm/apic.c            |    2 +-
>  hw/kvm/pci-assign.c      |    4 +-
>  hw/lpc_ich9.c            |    8 +-
>  hw/lsi53c895a.c          |    2 +-
>  hw/macio.c               |    2 +-
>  hw/megasas.c             |    4 +-
>  hw/mips_fulong2e.c       |    2 +-
>  hw/mips_malta.c          |    2 +-
>  hw/msi.c                 |  395 ---------
>  hw/msi.h                 |   50 --
>  hw/msix.c                |  562 ------------
>  hw/msix.h                |   41 -
>  hw/ne2000.c              |    2 +-
>  hw/openpic.c             |    2 +-
>  hw/pc.c                  |    4 +-
>  hw/pc_piix.c             |    4 +-
>  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_bus.h         |   74 ++
>  hw/pci/pci_host.c        |  180 ++++
>  hw/pci/pci_host.h        |   62 ++
>  hw/pci/pci_ids.h         |  147 ++++
>  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_bridge_dev.c      |   12 +-
>  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/pcnet-pci.c           |    2 +-
>  hw/piix4.c               |    2 +-
>  hw/piix_pci.c            |    4 +-
>  hw/ppc/Makefile.objs     |    2 +-
>  hw/ppc/e500.c            |    2 +-
>  hw/ppc440_bamboo.c       |    2 +-
>  hw/ppc4xx.h              |    2 +-
>  hw/ppc4xx_pci.c          |    4 +-
>  hw/ppc_newworld.c        |    2 +-
>  hw/ppc_oldworld.c        |    2 +-
>  hw/ppc_prep.c            |    4 +-
>  hw/ppce500_pci.c         |    4 +-
>  hw/prep_pci.c            |    4 +-
>  hw/q35.h                 |    4 +-
>  hw/qxl.h                 |    2 +-
>  hw/r2d.c                 |    2 +-
>  hw/realview.c            |    2 +-
>  hw/rtl8139.c             |    2 +-
>  hw/serial-pci.c          |    2 +-
>  hw/sga.c                 |    2 +-
>  hw/sh_pci.c              |    4 +-
>  hw/shpc.c                |  681 ---------------
>  hw/shpc.h                |   48 -
>  hw/slotid_cap.c          |   44 -
>  hw/slotid_cap.h          |   11 -
>  hw/smbus_ich9.c          |    2 +-
>  hw/spapr.c               |    4 +-
>  hw/spapr_pci.c           |   10 +-
>  hw/spapr_pci.h           |    4 +-
>  hw/sun4u.c               |    2 +-
>  hw/unin_pci.c            |    4 +-
>  hw/usb/hcd-ehci-pci.c    |    2 +-
>  hw/usb/hcd-ohci.c        |    2 +-
>  hw/usb/hcd-uhci.c        |    2 +-
>  hw/usb/hcd-xhci.c        |    6 +-
>  hw/versatile_pci.c       |    4 +-
>  hw/versatilepb.c         |    2 +-
>  hw/vfio_pci.c            |    6 +-
>  hw/vga-pci.c             |    2 +-
>  hw/vga.c                 |    2 +-
>  hw/virtio-balloon.h      |    2 +-
>  hw/virtio-net.h          |    2 +-
>  hw/virtio-pci.c          |    6 +-
>  hw/virtio-scsi.h         |    2 +-
>  hw/vmware_vga.c          |    2 +-
>  hw/vt82c686.c            |    4 +-
>  hw/wdt_i6300esb.c        |    2 +-
>  hw/xen-host-pci-device.h |    2 +-
>  hw/xen_apic.c            |    2 +-
>  hw/xen_platform.c        |    2 +-
>  hw/xen_pt.c              |    2 +-
>  hw/xen_pt.h              |    2 +-
>  hw/xio3130_downstream.c  |    6 +-
>  hw/xio3130_downstream.h  |    2 +-
>  hw/xio3130_upstream.c    |    6 +-
>  hw/xio3130_upstream.h    |    2 +-
>  kvm-all.c                |    2 +-
>  kvm-stub.c               |    2 +-
>  monitor.c                |    2 +-
>  target-i386/kvm.c        |    2 +-
>  xen-all.c                |    2 +-
>  162 files changed, 9173 insertions(+), 9176 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_bus.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_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
>
> -- 
> MST

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [Qemu-devel] [PATCH 0/8] pci core reorg
  2012-12-12 13:51 ` [Qemu-devel] [PATCH 0/8] pci core reorg Anthony Liguori
@ 2012-12-12 13:59   ` Paolo Bonzini
  0 siblings, 0 replies; 19+ messages in thread
From: Paolo Bonzini @ 2012-12-12 13:59 UTC (permalink / raw)
  To: Anthony Liguori; +Cc: qemu-devel, Michael S. Tsirkin

Il 12/12/2012 14:51, Anthony Liguori ha scritto:
> I'd like to see an Ack from Paolo as he's working on a tree-wide file
> movement right now..  Don't want to conflict with what he's doing
> unnecessarily.
> 
> Otherwise, this looks reasonable to me.

My changes are 99% scripted, so no problem from me.

Alternatively, I can pull from Michael and send a combined pull to you.

Paolo

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [Qemu-devel] [PATCH 5/8] pci: make external dependencies explicit
  2012-12-12 13:14 ` [Qemu-devel] [PATCH 5/8] pci: make external dependencies explicit Michael S. Tsirkin
@ 2012-12-12 19:49   ` Blue Swirl
  2012-12-12 20:53     ` Michael S. Tsirkin
  0 siblings, 1 reply; 19+ messages in thread
From: Blue Swirl @ 2012-12-12 19:49 UTC (permalink / raw)
  To: Michael S. Tsirkin; +Cc: qemu-devel

On Wed, Dec 12, 2012 at 1:14 PM, Michael S. Tsirkin <mst@redhat.com> wrote:
> Include dependencies from pci core using <> and

Nack, the usual convention is to use <> for system headers like
<stdio.h> and "" for local headers.

For example with MSVC the search path for angle brackets does not even
include the local directory:
http://msdn.microsoft.com/en-us/library/36k2cdd4%28v=vs.80%29.aspx

> the correct path.
> Need to check whether they can be minimized, for now,
> at least make them explicit.
>
> Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
> ---
>  hw/pci/msix.c        |  4 ++--
>  hw/pci/pci-hotplug.c | 20 ++++++++++----------
>  hw/pci/pci.c         | 16 ++++++++--------
>  hw/pci/pci.h         | 10 +++++-----
>  hw/pci/pci_host.h    |  2 +-
>  hw/pci/pcie.h        |  2 +-
>  hw/pci/pcie_aer.h    |  2 +-
>  hw/pci/pcie_host.c   |  4 ++--
>  8 files changed, 30 insertions(+), 30 deletions(-)
>
> diff --git a/hw/pci/msix.c b/hw/pci/msix.c
> index 136ef09..ec35a5d 100644
> --- a/hw/pci/msix.c
> +++ b/hw/pci/msix.c
> @@ -14,11 +14,11 @@
>   * GNU GPL, version 2 or (at your option) any later version.
>   */
>
> -#include "hw.h"
> +#include <hw/hw.h>
>  #include "msi.h"
>  #include "msix.h"
>  #include "pci.h"
> -#include "range.h"
> +#include <range.h>
>
>  #define MSIX_CAP_LENGTH 12
>
> diff --git a/hw/pci/pci-hotplug.c b/hw/pci/pci-hotplug.c
> index 0ca5546..32ba449 100644
> --- a/hw/pci/pci-hotplug.c
> +++ b/hw/pci/pci-hotplug.c
> @@ -22,17 +22,17 @@
>   * THE SOFTWARE.
>   */
>
> -#include "hw.h"
> -#include "boards.h"
> +#include <hw/hw.h>
> +#include <hw/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"
> +#include <net.h>
> +#include <hw/pc.h>
> +#include <monitor.h>
> +#include <hw/scsi.h>
> +#include <hw/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,
> diff --git a/hw/pci/pci.c b/hw/pci/pci.c
> index 97a0cd7..6023ded 100644
> --- a/hw/pci/pci.c
> +++ b/hw/pci/pci.c
> @@ -21,19 +21,19 @@
>   * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
>   * THE SOFTWARE.
>   */
> -#include "hw.h"
> +#include <hw/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 <monitor.h>
> +#include <net.h>
> +#include <sysemu.h>
> +#include <hw/loader.h>
> +#include <range.h>
> +#include <qmp-commands.h>
>  #include "msi.h"
>  #include "msix.h"
> -#include "exec-memory.h"
> +#include <exec-memory.h>
>
>  //#define DEBUG_PCI
>  #ifdef DEBUG_PCI
> diff --git a/hw/pci/pci.h b/hw/pci/pci.h
> index 4da0c2a..b517995 100644
> --- a/hw/pci/pci.h
> +++ b/hw/pci/pci.h
> @@ -1,14 +1,14 @@
>  #ifndef QEMU_PCI_H
>  #define QEMU_PCI_H
>
> -#include "qemu-common.h"
> +#include <qemu-common.h>
>
> -#include "qdev.h"
> -#include "memory.h"
> -#include "dma.h"
> +#include <hw/qdev.h>
> +#include <memory.h>
> +#include <dma.h>
>
>  /* PCI includes legacy ISA access.  */
> -#include "isa.h"
> +#include <hw/isa.h>
>
>  #include "pcie.h"
>
> diff --git a/hw/pci/pci_host.h b/hw/pci/pci_host.h
> index 4b9c300..6dfb38d 100644
> --- a/hw/pci/pci_host.h
> +++ b/hw/pci/pci_host.h
> @@ -28,7 +28,7 @@
>  #ifndef PCI_HOST_H
>  #define PCI_HOST_H
>
> -#include "sysbus.h"
> +#include <hw/sysbus.h>
>
>  #define TYPE_PCI_HOST_BRIDGE "pci-host-bridge"
>  #define PCI_HOST_BRIDGE(obj) \
> diff --git a/hw/pci/pcie.h b/hw/pci/pcie.h
> index 4889194..cc1f2c5 100644
> --- a/hw/pci/pcie.h
> +++ b/hw/pci/pcie.h
> @@ -21,7 +21,7 @@
>  #ifndef QEMU_PCIE_H
>  #define QEMU_PCIE_H
>
> -#include "hw.h"
> +#include <hw/hw.h>
>  #include "pci_regs.h"
>  #include "pcie_regs.h"
>  #include "pcie_aer.h"
> diff --git a/hw/pci/pcie_aer.h b/hw/pci/pcie_aer.h
> index 7539500..406a736 100644
> --- a/hw/pci/pcie_aer.h
> +++ b/hw/pci/pcie_aer.h
> @@ -21,7 +21,7 @@
>  #ifndef QEMU_PCIE_AER_H
>  #define QEMU_PCIE_AER_H
>
> -#include "hw.h"
> +#include <hw/hw.h>
>
>  /* definitions which PCIExpressDevice uses */
>
> diff --git a/hw/pci/pcie_host.c b/hw/pci/pcie_host.c
> index c257fb4..4453cb0 100644
> --- a/hw/pci/pcie_host.c
> +++ b/hw/pci/pcie_host.c
> @@ -19,10 +19,10 @@
>   * with this program; if not, see <http://www.gnu.org/licenses/>.
>   */
>
> -#include "hw.h"
> +#include <hw/hw.h>
>  #include "pci.h"
>  #include "pcie_host.h"
> -#include "exec-memory.h"
> +#include <exec-memory.h>
>
>  /*
>   * PCI express mmcfig address
> --
> MST
>
>

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [Qemu-devel] [PATCH 3/8] pci: move pci core code to hw/pci
  2012-12-12 13:14 ` [Qemu-devel] [PATCH 3/8] pci: move pci core code to hw/pci Michael S. Tsirkin
@ 2012-12-12 19:53   ` Blue Swirl
  2012-12-12 20:56     ` Michael S. Tsirkin
  0 siblings, 1 reply; 19+ messages in thread
From: Blue Swirl @ 2012-12-12 19:53 UTC (permalink / raw)
  To: Michael S. Tsirkin; +Cc: qemu-devel

On Wed, Dec 12, 2012 at 1:14 PM, Michael S. Tsirkin <mst@redhat.com> wrote:
> Move files and modify makefiles to pick them at the
> new location.

Please fix coding style before moving.

For easier review, please use git flag -M to detect renames.

>
> Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
> ---
>  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 <mst@redhat.com>
> - *
> - *  Copyright (c) 2009, Red Hat Inc, Michael S. Tsirkin (mst@redhat.com)
> - *
> - * 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), "%s@%x",
> -                   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 <mst@redhat.com>
> + *
> + *  Copyright (c) 2009, Red Hat Inc, Michael S. Tsirkin (mst@redhat.com)
> + *
> + * 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), "%s@%x",
> +                   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 <mj@ucw.cz>
> + *
> + *     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 <mj@ucw.cz>
> - *
> - *     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
>
>

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [Qemu-devel] [PATCH 7/8] pci: rename pci_internals.h pci_bus.h
  2012-12-12 13:14 ` [Qemu-devel] [PATCH 7/8] pci: rename pci_internals.h pci_bus.h Michael S. Tsirkin
@ 2012-12-12 19:56   ` Blue Swirl
  2012-12-12 20:59     ` Michael S. Tsirkin
  0 siblings, 1 reply; 19+ messages in thread
From: Blue Swirl @ 2012-12-12 19:56 UTC (permalink / raw)
  To: Michael S. Tsirkin; +Cc: qemu-devel

On Wed, Dec 12, 2012 at 1:14 PM, Michael S. Tsirkin <mst@redhat.com> wrote:
> There are lots of external users of pci_internals.h,
> apparently making it an internal interface only didn't
> work out. Let's stop pretending it's an internal header.
>
> Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
> ---
>  hw/apb_pci.c           |  2 +-
>  hw/dec_pci.c           |  2 +-
>  hw/ich9.h              |  2 +-
>  hw/lpc_ich9.c          |  2 +-
>  hw/pci/pci.c           |  2 +-
>  hw/pci/pci_bridge.c    |  2 +-
>  hw/pci/pci_bus.h       | 78 ++++++++++++++++++++++++++++++++++++++++++++++++++
>  hw/pci/pci_internals.h | 78 --------------------------------------------------
>  hw/pci/pcie.c          |  2 +-
>  hw/pci/pcie_aer.c      |  2 +-
>  hw/pci/pcie_port.h     |  2 +-
>  hw/pci/shpc.c          |  2 +-
>  hw/pci_bridge_dev.c    |  2 +-
>  hw/spapr_pci.c         |  2 +-
>  14 files changed, 90 insertions(+), 90 deletions(-)
>  create mode 100644 hw/pci/pci_bus.h
>  delete mode 100644 hw/pci/pci_internals.h
>
> diff --git a/hw/apb_pci.c b/hw/apb_pci.c
> index de594f8..fb7a07d 100644
> --- a/hw/apb_pci.c
> +++ b/hw/apb_pci.c
> @@ -30,7 +30,7 @@
>  #include "pci/pci.h"
>  #include "pci/pci_host.h"
>  #include "pci/pci_bridge.h"
> -#include "pci/pci_internals.h"
> +#include "pci/pci_bus.h"
>  #include "apb_pci.h"
>  #include "sysemu.h"
>  #include "exec-memory.h"
> diff --git a/hw/dec_pci.c b/hw/dec_pci.c
> index a6a7c84..ee3f4ca 100644
> --- a/hw/dec_pci.c
> +++ b/hw/dec_pci.c
> @@ -28,7 +28,7 @@
>  #include "pci/pci.h"
>  #include "pci/pci_host.h"
>  #include "pci/pci_bridge.h"
> -#include "pci/pci_internals.h"
> +#include "pci/pci_bus.h"
>
>  /* debug DEC */
>  //#define DEBUG_DEC
> diff --git a/hw/ich9.h b/hw/ich9.h
> index 247be94..4e7442c 100644
> --- a/hw/ich9.h
> +++ b/hw/ich9.h
> @@ -14,7 +14,7 @@
>  #include "acpi.h"
>  #include "acpi_ich9.h"
>  #include "pam.h"
> -#include "pci/pci_internals.h"
> +#include "pci/pci_bus.h"
>
>  void ich9_lpc_set_irq(void *opaque, int irq_num, int level);
>  int ich9_lpc_map_irq(PCIDevice *pci_dev, int intx);
> diff --git a/hw/lpc_ich9.c b/hw/lpc_ich9.c
> index 23dee88..7bca061 100644
> --- a/hw/lpc_ich9.c
> +++ b/hw/lpc_ich9.c
> @@ -42,7 +42,7 @@
>  #include "acpi.h"
>  #include "acpi_ich9.h"
>  #include "pam.h"
> -#include "pci/pci_internals.h"
> +#include "pci/pci_bus.h"
>  #include "exec-memory.h"
>
>  static int ich9_lpc_sci_irq(ICH9LPCState *lpc);
> diff --git a/hw/pci/pci.c b/hw/pci/pci.c
> index 6023ded..c1a4b32 100644
> --- a/hw/pci/pci.c
> +++ b/hw/pci/pci.c
> @@ -24,7 +24,7 @@
>  #include <hw/hw.h>
>  #include "pci.h"
>  #include "pci_bridge.h"
> -#include "pci_internals.h"
> +#include "pci_bus.h"
>  #include <monitor.h>
>  #include <net.h>
>  #include <sysemu.h>
> diff --git a/hw/pci/pci_bridge.c b/hw/pci/pci_bridge.c
> index 4680501..0fb7577 100644
> --- a/hw/pci/pci_bridge.c
> +++ b/hw/pci/pci_bridge.c
> @@ -30,7 +30,7 @@
>   */
>
>  #include "pci_bridge.h"
> -#include "pci_internals.h"
> +#include "pci_bus.h"
>  #include "range.h"
>
>  /* PCI bridge subsystem vendor ID helper functions */
> diff --git a/hw/pci/pci_bus.h b/hw/pci/pci_bus.h
> new file mode 100644
> index 0000000..21d0ce6
> --- /dev/null
> +++ b/hw/pci/pci_bus.h
> @@ -0,0 +1,78 @@
> +#ifndef QEMU_PCI_INTERNALS_H
> +#define QEMU_PCI_INTERNALS_H

This should become QEMU_PCI_BUS_H or something similar.

> +
> +/*
> + * 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_internals.h b/hw/pci/pci_internals.h
> deleted file mode 100644
> index 21d0ce6..0000000
> --- a/hw/pci/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/pcie.c b/hw/pci/pcie.c
> index 7c92f19..d9c38b5 100644
> --- a/hw/pci/pcie.c
> +++ b/hw/pci/pcie.c
> @@ -23,7 +23,7 @@
>  #include "pcie.h"
>  #include "msix.h"
>  #include "msi.h"
> -#include "pci_internals.h"
> +#include "pci_bus.h"
>  #include "pcie_regs.h"
>  #include "range.h"
>
> diff --git a/hw/pci/pcie_aer.c b/hw/pci/pcie_aer.c
> index b04c164..3c3185c 100644
> --- a/hw/pci/pcie_aer.c
> +++ b/hw/pci/pcie_aer.c
> @@ -25,7 +25,7 @@
>  #include "pcie.h"
>  #include "msix.h"
>  #include "msi.h"
> -#include "pci_internals.h"
> +#include "pci_bus.h"
>  #include "pcie_regs.h"
>
>  //#define DEBUG_PCIE
> diff --git a/hw/pci/pcie_port.h b/hw/pci/pcie_port.h
> index 3709583..36b2241 100644
> --- a/hw/pci/pcie_port.h
> +++ b/hw/pci/pcie_port.h
> @@ -22,7 +22,7 @@
>  #define QEMU_PCIE_PORT_H
>
>  #include "pci_bridge.h"
> -#include "pci_internals.h"
> +#include "pci_bus.h"
>
>  struct PCIEPort {
>      PCIBridge   br;
> diff --git a/hw/pci/shpc.c b/hw/pci/shpc.c
> index 4597bbd..9297af0 100644
> --- a/hw/pci/shpc.c
> +++ b/hw/pci/shpc.c
> @@ -4,7 +4,7 @@
>  #include "range.h"
>  #include "shpc.h"
>  #include "pci.h"
> -#include "pci_internals.h"
> +#include "pci_bus.h"
>  #include "msi.h"
>
>  /* TODO: model power only and disabled slot states. */
> diff --git a/hw/pci_bridge_dev.c b/hw/pci_bridge_dev.c
> index 5c9fc50..dbb4b3b 100644
> --- a/hw/pci_bridge_dev.c
> +++ b/hw/pci_bridge_dev.c
> @@ -25,7 +25,7 @@
>  #include "pci/shpc.h"
>  #include "pci/slotid_cap.h"
>  #include "memory.h"
> -#include "pci/pci_internals.h"
> +#include "pci/pci_bus.h"
>
>  #define REDHAT_PCI_VENDOR_ID 0x1b36
>  #define PCI_BRIDGE_DEV_VENDOR_ID REDHAT_PCI_VENDOR_ID
> diff --git a/hw/spapr_pci.c b/hw/spapr_pci.c
> index e123866..6b05e5b 100644
> --- a/hw/spapr_pci.c
> +++ b/hw/spapr_pci.c
> @@ -33,7 +33,7 @@
>  #include <libfdt.h>
>  #include "trace.h"
>
> -#include "hw/pci/pci_internals.h"
> +#include "hw/pci/pci_bus.h"
>
>  /* Copied from the kernel arch/powerpc/platforms/pseries/msi.c */
>  #define RTAS_QUERY_FN           0
> --
> MST
>
>

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [Qemu-devel] [PATCH 0/8] pci core reorg
  2012-12-12 13:13 [Qemu-devel] [PATCH 0/8] pci core reorg Michael S. Tsirkin
                   ` (8 preceding siblings ...)
  2012-12-12 13:51 ` [Qemu-devel] [PATCH 0/8] pci core reorg Anthony Liguori
@ 2012-12-12 20:00 ` Blue Swirl
  2012-12-12 20:58   ` Michael S. Tsirkin
  9 siblings, 1 reply; 19+ messages in thread
From: Blue Swirl @ 2012-12-12 20:00 UTC (permalink / raw)
  To: Michael S. Tsirkin; +Cc: qemu-devel

On Wed, Dec 12, 2012 at 1:13 PM, Michael S. Tsirkin <mst@redhat.com> wrote:
> This patchset starts some cleanups of the pci core
> by rearranging the code: pci core is split out
> from devices into its own directory, pci internals.h
> is renamed as it's used externally a lot.
>
> I'd like to merge this quickly to avoid conflicting
> with others work.
> Plan to send pull request tomorrow, if you have concerns,
> speak up soon pls.

I had a few comments and one nack but otherwise nice cleanup.

>
> Thanks,
>
>
>
> Michael S. Tsirkin (8):
>   pci: prepare makefiles for pci code reorganization
>   MAINTAINERS: add hw/pci/ to list of PCI files
>   pci: move pci core code to hw/pci
>   pci: update all users to look in pci/
>   pci: make external dependencies explicit
>   Revert "pci: prepare makefiles for pci code reorganization"
>   pci: rename pci_internals.h pci_bus.h
>   pci_bus: update comment
>
>  MAINTAINERS              |    1 +
>  arch_init.c              |    2 +-
>  hw/Makefile.objs         |   10 +-
>  hw/ac97.c                |    2 +-
>  hw/acpi_ich9.c           |    2 +-
>  hw/acpi_piix4.c          |    2 +-
>  hw/alpha_sys.h           |    4 +-
>  hw/apb_pci.c             |    8 +-
>  hw/apic.c                |    2 +-
>  hw/bonito.c              |    4 +-
>  hw/cirrus_vga.c          |    2 +-
>  hw/dec_pci.c             |    8 +-
>  hw/e1000.c               |    2 +-
>  hw/eepro100.c            |    2 +-
>  hw/es1370.c              |    2 +-
>  hw/esp-pci.c             |    2 +-
>  hw/grackle_pci.c         |    4 +-
>  hw/gt64xxx.c             |    4 +-
>  hw/hda-audio.c           |    2 +-
>  hw/i386/Makefile.objs    |    2 +-
>  hw/i82378.c              |    2 +-
>  hw/i82801b11.c           |    2 +-
>  hw/ich9.h                |    8 +-
>  hw/ide.h                 |    2 +-
>  hw/ide/ahci.c            |    4 +-
>  hw/ide/cmd646.c          |    2 +-
>  hw/ide/core.c            |    2 +-
>  hw/ide/ich.c             |    4 +-
>  hw/ide/pci.c             |    2 +-
>  hw/ide/piix.c            |    2 +-
>  hw/ide/via.c             |    2 +-
>  hw/intel-hda.c           |    4 +-
>  hw/ioh3420.c             |    6 +-
>  hw/ioh3420.h             |    2 +-
>  hw/ivshmem.c             |    4 +-
>  hw/kvm/apic.c            |    2 +-
>  hw/kvm/pci-assign.c      |    4 +-
>  hw/lpc_ich9.c            |    8 +-
>  hw/lsi53c895a.c          |    2 +-
>  hw/macio.c               |    2 +-
>  hw/megasas.c             |    4 +-
>  hw/mips_fulong2e.c       |    2 +-
>  hw/mips_malta.c          |    2 +-
>  hw/msi.c                 |  395 ---------
>  hw/msi.h                 |   50 --
>  hw/msix.c                |  562 ------------
>  hw/msix.h                |   41 -
>  hw/ne2000.c              |    2 +-
>  hw/openpic.c             |    2 +-
>  hw/pc.c                  |    4 +-
>  hw/pc_piix.c             |    4 +-
>  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_bus.h         |   74 ++
>  hw/pci/pci_host.c        |  180 ++++
>  hw/pci/pci_host.h        |   62 ++
>  hw/pci/pci_ids.h         |  147 ++++
>  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_bridge_dev.c      |   12 +-
>  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/pcnet-pci.c           |    2 +-
>  hw/piix4.c               |    2 +-
>  hw/piix_pci.c            |    4 +-
>  hw/ppc/Makefile.objs     |    2 +-
>  hw/ppc/e500.c            |    2 +-
>  hw/ppc440_bamboo.c       |    2 +-
>  hw/ppc4xx.h              |    2 +-
>  hw/ppc4xx_pci.c          |    4 +-
>  hw/ppc_newworld.c        |    2 +-
>  hw/ppc_oldworld.c        |    2 +-
>  hw/ppc_prep.c            |    4 +-
>  hw/ppce500_pci.c         |    4 +-
>  hw/prep_pci.c            |    4 +-
>  hw/q35.h                 |    4 +-
>  hw/qxl.h                 |    2 +-
>  hw/r2d.c                 |    2 +-
>  hw/realview.c            |    2 +-
>  hw/rtl8139.c             |    2 +-
>  hw/serial-pci.c          |    2 +-
>  hw/sga.c                 |    2 +-
>  hw/sh_pci.c              |    4 +-
>  hw/shpc.c                |  681 ---------------
>  hw/shpc.h                |   48 -
>  hw/slotid_cap.c          |   44 -
>  hw/slotid_cap.h          |   11 -
>  hw/smbus_ich9.c          |    2 +-
>  hw/spapr.c               |    4 +-
>  hw/spapr_pci.c           |   10 +-
>  hw/spapr_pci.h           |    4 +-
>  hw/sun4u.c               |    2 +-
>  hw/unin_pci.c            |    4 +-
>  hw/usb/hcd-ehci-pci.c    |    2 +-
>  hw/usb/hcd-ohci.c        |    2 +-
>  hw/usb/hcd-uhci.c        |    2 +-
>  hw/usb/hcd-xhci.c        |    6 +-
>  hw/versatile_pci.c       |    4 +-
>  hw/versatilepb.c         |    2 +-
>  hw/vfio_pci.c            |    6 +-
>  hw/vga-pci.c             |    2 +-
>  hw/vga.c                 |    2 +-
>  hw/virtio-balloon.h      |    2 +-
>  hw/virtio-net.h          |    2 +-
>  hw/virtio-pci.c          |    6 +-
>  hw/virtio-scsi.h         |    2 +-
>  hw/vmware_vga.c          |    2 +-
>  hw/vt82c686.c            |    4 +-
>  hw/wdt_i6300esb.c        |    2 +-
>  hw/xen-host-pci-device.h |    2 +-
>  hw/xen_apic.c            |    2 +-
>  hw/xen_platform.c        |    2 +-
>  hw/xen_pt.c              |    2 +-
>  hw/xen_pt.h              |    2 +-
>  hw/xio3130_downstream.c  |    6 +-
>  hw/xio3130_downstream.h  |    2 +-
>  hw/xio3130_upstream.c    |    6 +-
>  hw/xio3130_upstream.h    |    2 +-
>  kvm-all.c                |    2 +-
>  kvm-stub.c               |    2 +-
>  monitor.c                |    2 +-
>  target-i386/kvm.c        |    2 +-
>  xen-all.c                |    2 +-
>  162 files changed, 9173 insertions(+), 9176 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_bus.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_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
>
> --
> MST
>

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [Qemu-devel] [PATCH 5/8] pci: make external dependencies explicit
  2012-12-12 19:49   ` Blue Swirl
@ 2012-12-12 20:53     ` Michael S. Tsirkin
  0 siblings, 0 replies; 19+ messages in thread
From: Michael S. Tsirkin @ 2012-12-12 20:53 UTC (permalink / raw)
  To: Blue Swirl; +Cc: qemu-devel

On Wed, Dec 12, 2012 at 07:49:35PM +0000, Blue Swirl wrote:
> On Wed, Dec 12, 2012 at 1:14 PM, Michael S. Tsirkin <mst@redhat.com> wrote:
> > Include dependencies from pci core using <> and
> 
> Nack, the usual convention is to use <> for system headers like
> <stdio.h> and "" for local headers.
> 
> For example with MSVC the search path for angle brackets does not even
> include the local directory:
> http://msdn.microsoft.com/en-us/library/36k2cdd4%28v=vs.80%29.aspx

This convention is non standard:
When hw/pci/pci.h includes hw/hw.h the lookup
that succeeds is not from the current
directory - it's from the -I search path.
So "" simply slows the preprocessor down and
increases chances of picking the wrong header,
for no real benefit.

Oh well another qemu coding style eccentricity.
I'll change them to "".

> > the correct path.
> > Need to check whether they can be minimized, for now,
> > at least make them explicit.
> >
> > Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
> > ---
> >  hw/pci/msix.c        |  4 ++--
> >  hw/pci/pci-hotplug.c | 20 ++++++++++----------
> >  hw/pci/pci.c         | 16 ++++++++--------
> >  hw/pci/pci.h         | 10 +++++-----
> >  hw/pci/pci_host.h    |  2 +-
> >  hw/pci/pcie.h        |  2 +-
> >  hw/pci/pcie_aer.h    |  2 +-
> >  hw/pci/pcie_host.c   |  4 ++--
> >  8 files changed, 30 insertions(+), 30 deletions(-)
> >
> > diff --git a/hw/pci/msix.c b/hw/pci/msix.c
> > index 136ef09..ec35a5d 100644
> > --- a/hw/pci/msix.c
> > +++ b/hw/pci/msix.c
> > @@ -14,11 +14,11 @@
> >   * GNU GPL, version 2 or (at your option) any later version.
> >   */
> >
> > -#include "hw.h"
> > +#include <hw/hw.h>
> >  #include "msi.h"
> >  #include "msix.h"
> >  #include "pci.h"
> > -#include "range.h"
> > +#include <range.h>
> >
> >  #define MSIX_CAP_LENGTH 12
> >
> > diff --git a/hw/pci/pci-hotplug.c b/hw/pci/pci-hotplug.c
> > index 0ca5546..32ba449 100644
> > --- a/hw/pci/pci-hotplug.c
> > +++ b/hw/pci/pci-hotplug.c
> > @@ -22,17 +22,17 @@
> >   * THE SOFTWARE.
> >   */
> >
> > -#include "hw.h"
> > -#include "boards.h"
> > +#include <hw/hw.h>
> > +#include <hw/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"
> > +#include <net.h>
> > +#include <hw/pc.h>
> > +#include <monitor.h>
> > +#include <hw/scsi.h>
> > +#include <hw/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,
> > diff --git a/hw/pci/pci.c b/hw/pci/pci.c
> > index 97a0cd7..6023ded 100644
> > --- a/hw/pci/pci.c
> > +++ b/hw/pci/pci.c
> > @@ -21,19 +21,19 @@
> >   * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
> >   * THE SOFTWARE.
> >   */
> > -#include "hw.h"
> > +#include <hw/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 <monitor.h>
> > +#include <net.h>
> > +#include <sysemu.h>
> > +#include <hw/loader.h>
> > +#include <range.h>
> > +#include <qmp-commands.h>
> >  #include "msi.h"
> >  #include "msix.h"
> > -#include "exec-memory.h"
> > +#include <exec-memory.h>
> >
> >  //#define DEBUG_PCI
> >  #ifdef DEBUG_PCI
> > diff --git a/hw/pci/pci.h b/hw/pci/pci.h
> > index 4da0c2a..b517995 100644
> > --- a/hw/pci/pci.h
> > +++ b/hw/pci/pci.h
> > @@ -1,14 +1,14 @@
> >  #ifndef QEMU_PCI_H
> >  #define QEMU_PCI_H
> >
> > -#include "qemu-common.h"
> > +#include <qemu-common.h>
> >
> > -#include "qdev.h"
> > -#include "memory.h"
> > -#include "dma.h"
> > +#include <hw/qdev.h>
> > +#include <memory.h>
> > +#include <dma.h>
> >
> >  /* PCI includes legacy ISA access.  */
> > -#include "isa.h"
> > +#include <hw/isa.h>
> >
> >  #include "pcie.h"
> >
> > diff --git a/hw/pci/pci_host.h b/hw/pci/pci_host.h
> > index 4b9c300..6dfb38d 100644
> > --- a/hw/pci/pci_host.h
> > +++ b/hw/pci/pci_host.h
> > @@ -28,7 +28,7 @@
> >  #ifndef PCI_HOST_H
> >  #define PCI_HOST_H
> >
> > -#include "sysbus.h"
> > +#include <hw/sysbus.h>
> >
> >  #define TYPE_PCI_HOST_BRIDGE "pci-host-bridge"
> >  #define PCI_HOST_BRIDGE(obj) \
> > diff --git a/hw/pci/pcie.h b/hw/pci/pcie.h
> > index 4889194..cc1f2c5 100644
> > --- a/hw/pci/pcie.h
> > +++ b/hw/pci/pcie.h
> > @@ -21,7 +21,7 @@
> >  #ifndef QEMU_PCIE_H
> >  #define QEMU_PCIE_H
> >
> > -#include "hw.h"
> > +#include <hw/hw.h>
> >  #include "pci_regs.h"
> >  #include "pcie_regs.h"
> >  #include "pcie_aer.h"
> > diff --git a/hw/pci/pcie_aer.h b/hw/pci/pcie_aer.h
> > index 7539500..406a736 100644
> > --- a/hw/pci/pcie_aer.h
> > +++ b/hw/pci/pcie_aer.h
> > @@ -21,7 +21,7 @@
> >  #ifndef QEMU_PCIE_AER_H
> >  #define QEMU_PCIE_AER_H
> >
> > -#include "hw.h"
> > +#include <hw/hw.h>
> >
> >  /* definitions which PCIExpressDevice uses */
> >
> > diff --git a/hw/pci/pcie_host.c b/hw/pci/pcie_host.c
> > index c257fb4..4453cb0 100644
> > --- a/hw/pci/pcie_host.c
> > +++ b/hw/pci/pcie_host.c
> > @@ -19,10 +19,10 @@
> >   * with this program; if not, see <http://www.gnu.org/licenses/>.
> >   */
> >
> > -#include "hw.h"
> > +#include <hw/hw.h>
> >  #include "pci.h"
> >  #include "pcie_host.h"
> > -#include "exec-memory.h"
> > +#include <exec-memory.h>
> >
> >  /*
> >   * PCI express mmcfig address
> > --
> > MST
> >
> >

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [Qemu-devel] [PATCH 3/8] pci: move pci core code to hw/pci
  2012-12-12 19:53   ` Blue Swirl
@ 2012-12-12 20:56     ` Michael S. Tsirkin
  0 siblings, 0 replies; 19+ messages in thread
From: Michael S. Tsirkin @ 2012-12-12 20:56 UTC (permalink / raw)
  To: Blue Swirl; +Cc: qemu-devel

On Wed, Dec 12, 2012 at 07:53:45PM +0000, Blue Swirl wrote:
> On Wed, Dec 12, 2012 at 1:14 PM, Michael S. Tsirkin <mst@redhat.com> wrote:
> > Move files and modify makefiles to pick them at the
> > new location.
> 
> Please fix coding style before moving.

Nah I'll fix it after moving. No reason to mix
multiple changes.

> For easier review, please use git flag -M to detect renames.

I'll note that for future thanks. I don't intend to repost this
huge patchset though - it'll go in through a pull request.

> >
> > Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
> > ---
> >  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 <mst@redhat.com>
> > - *
> > - *  Copyright (c) 2009, Red Hat Inc, Michael S. Tsirkin (mst@redhat.com)
> > - *
> > - * 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), "%s@%x",
> > -                   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 <mst@redhat.com>
> > + *
> > + *  Copyright (c) 2009, Red Hat Inc, Michael S. Tsirkin (mst@redhat.com)
> > + *
> > + * 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), "%s@%x",
> > +                   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 <mj@ucw.cz>
> > + *
> > + *     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 <mj@ucw.cz>
> > - *
> > - *     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
> >
> >

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [Qemu-devel] [PATCH 0/8] pci core reorg
  2012-12-12 20:00 ` Blue Swirl
@ 2012-12-12 20:58   ` Michael S. Tsirkin
  0 siblings, 0 replies; 19+ messages in thread
From: Michael S. Tsirkin @ 2012-12-12 20:58 UTC (permalink / raw)
  To: Blue Swirl; +Cc: qemu-devel

On Wed, Dec 12, 2012 at 08:00:58PM +0000, Blue Swirl wrote:
> On Wed, Dec 12, 2012 at 1:13 PM, Michael S. Tsirkin <mst@redhat.com> wrote:
> > This patchset starts some cleanups of the pci core
> > by rearranging the code: pci core is split out
> > from devices into its own directory, pci internals.h
> > is renamed as it's used externally a lot.
> >
> > I'd like to merge this quickly to avoid conflicting
> > with others work.
> > Plan to send pull request tomorrow, if you have concerns,
> > speak up soon pls.
> 
> I had a few comments and one nack but otherwise nice cleanup.

I haven't seen anything besides the nack, and a suggestion
to fix coding style of existing files which should be
done separately.

> >
> > Thanks,
> >
> >
> >
> > Michael S. Tsirkin (8):
> >   pci: prepare makefiles for pci code reorganization
> >   MAINTAINERS: add hw/pci/ to list of PCI files
> >   pci: move pci core code to hw/pci
> >   pci: update all users to look in pci/
> >   pci: make external dependencies explicit
> >   Revert "pci: prepare makefiles for pci code reorganization"
> >   pci: rename pci_internals.h pci_bus.h
> >   pci_bus: update comment
> >
> >  MAINTAINERS              |    1 +
> >  arch_init.c              |    2 +-
> >  hw/Makefile.objs         |   10 +-
> >  hw/ac97.c                |    2 +-
> >  hw/acpi_ich9.c           |    2 +-
> >  hw/acpi_piix4.c          |    2 +-
> >  hw/alpha_sys.h           |    4 +-
> >  hw/apb_pci.c             |    8 +-
> >  hw/apic.c                |    2 +-
> >  hw/bonito.c              |    4 +-
> >  hw/cirrus_vga.c          |    2 +-
> >  hw/dec_pci.c             |    8 +-
> >  hw/e1000.c               |    2 +-
> >  hw/eepro100.c            |    2 +-
> >  hw/es1370.c              |    2 +-
> >  hw/esp-pci.c             |    2 +-
> >  hw/grackle_pci.c         |    4 +-
> >  hw/gt64xxx.c             |    4 +-
> >  hw/hda-audio.c           |    2 +-
> >  hw/i386/Makefile.objs    |    2 +-
> >  hw/i82378.c              |    2 +-
> >  hw/i82801b11.c           |    2 +-
> >  hw/ich9.h                |    8 +-
> >  hw/ide.h                 |    2 +-
> >  hw/ide/ahci.c            |    4 +-
> >  hw/ide/cmd646.c          |    2 +-
> >  hw/ide/core.c            |    2 +-
> >  hw/ide/ich.c             |    4 +-
> >  hw/ide/pci.c             |    2 +-
> >  hw/ide/piix.c            |    2 +-
> >  hw/ide/via.c             |    2 +-
> >  hw/intel-hda.c           |    4 +-
> >  hw/ioh3420.c             |    6 +-
> >  hw/ioh3420.h             |    2 +-
> >  hw/ivshmem.c             |    4 +-
> >  hw/kvm/apic.c            |    2 +-
> >  hw/kvm/pci-assign.c      |    4 +-
> >  hw/lpc_ich9.c            |    8 +-
> >  hw/lsi53c895a.c          |    2 +-
> >  hw/macio.c               |    2 +-
> >  hw/megasas.c             |    4 +-
> >  hw/mips_fulong2e.c       |    2 +-
> >  hw/mips_malta.c          |    2 +-
> >  hw/msi.c                 |  395 ---------
> >  hw/msi.h                 |   50 --
> >  hw/msix.c                |  562 ------------
> >  hw/msix.h                |   41 -
> >  hw/ne2000.c              |    2 +-
> >  hw/openpic.c             |    2 +-
> >  hw/pc.c                  |    4 +-
> >  hw/pc_piix.c             |    4 +-
> >  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_bus.h         |   74 ++
> >  hw/pci/pci_host.c        |  180 ++++
> >  hw/pci/pci_host.h        |   62 ++
> >  hw/pci/pci_ids.h         |  147 ++++
> >  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_bridge_dev.c      |   12 +-
> >  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/pcnet-pci.c           |    2 +-
> >  hw/piix4.c               |    2 +-
> >  hw/piix_pci.c            |    4 +-
> >  hw/ppc/Makefile.objs     |    2 +-
> >  hw/ppc/e500.c            |    2 +-
> >  hw/ppc440_bamboo.c       |    2 +-
> >  hw/ppc4xx.h              |    2 +-
> >  hw/ppc4xx_pci.c          |    4 +-
> >  hw/ppc_newworld.c        |    2 +-
> >  hw/ppc_oldworld.c        |    2 +-
> >  hw/ppc_prep.c            |    4 +-
> >  hw/ppce500_pci.c         |    4 +-
> >  hw/prep_pci.c            |    4 +-
> >  hw/q35.h                 |    4 +-
> >  hw/qxl.h                 |    2 +-
> >  hw/r2d.c                 |    2 +-
> >  hw/realview.c            |    2 +-
> >  hw/rtl8139.c             |    2 +-
> >  hw/serial-pci.c          |    2 +-
> >  hw/sga.c                 |    2 +-
> >  hw/sh_pci.c              |    4 +-
> >  hw/shpc.c                |  681 ---------------
> >  hw/shpc.h                |   48 -
> >  hw/slotid_cap.c          |   44 -
> >  hw/slotid_cap.h          |   11 -
> >  hw/smbus_ich9.c          |    2 +-
> >  hw/spapr.c               |    4 +-
> >  hw/spapr_pci.c           |   10 +-
> >  hw/spapr_pci.h           |    4 +-
> >  hw/sun4u.c               |    2 +-
> >  hw/unin_pci.c            |    4 +-
> >  hw/usb/hcd-ehci-pci.c    |    2 +-
> >  hw/usb/hcd-ohci.c        |    2 +-
> >  hw/usb/hcd-uhci.c        |    2 +-
> >  hw/usb/hcd-xhci.c        |    6 +-
> >  hw/versatile_pci.c       |    4 +-
> >  hw/versatilepb.c         |    2 +-
> >  hw/vfio_pci.c            |    6 +-
> >  hw/vga-pci.c             |    2 +-
> >  hw/vga.c                 |    2 +-
> >  hw/virtio-balloon.h      |    2 +-
> >  hw/virtio-net.h          |    2 +-
> >  hw/virtio-pci.c          |    6 +-
> >  hw/virtio-scsi.h         |    2 +-
> >  hw/vmware_vga.c          |    2 +-
> >  hw/vt82c686.c            |    4 +-
> >  hw/wdt_i6300esb.c        |    2 +-
> >  hw/xen-host-pci-device.h |    2 +-
> >  hw/xen_apic.c            |    2 +-
> >  hw/xen_platform.c        |    2 +-
> >  hw/xen_pt.c              |    2 +-
> >  hw/xen_pt.h              |    2 +-
> >  hw/xio3130_downstream.c  |    6 +-
> >  hw/xio3130_downstream.h  |    2 +-
> >  hw/xio3130_upstream.c    |    6 +-
> >  hw/xio3130_upstream.h    |    2 +-
> >  kvm-all.c                |    2 +-
> >  kvm-stub.c               |    2 +-
> >  monitor.c                |    2 +-
> >  target-i386/kvm.c        |    2 +-
> >  xen-all.c                |    2 +-
> >  162 files changed, 9173 insertions(+), 9176 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_bus.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_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
> >
> > --
> > MST
> >

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [Qemu-devel] [PATCH 7/8] pci: rename pci_internals.h pci_bus.h
  2012-12-12 19:56   ` Blue Swirl
@ 2012-12-12 20:59     ` Michael S. Tsirkin
  0 siblings, 0 replies; 19+ messages in thread
From: Michael S. Tsirkin @ 2012-12-12 20:59 UTC (permalink / raw)
  To: Blue Swirl; +Cc: qemu-devel

On Wed, Dec 12, 2012 at 07:56:50PM +0000, Blue Swirl wrote:
> On Wed, Dec 12, 2012 at 1:14 PM, Michael S. Tsirkin <mst@redhat.com> wrote:
> > There are lots of external users of pci_internals.h,
> > apparently making it an internal interface only didn't
> > work out. Let's stop pretending it's an internal header.
> >
> > Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
> > ---
> >  hw/apb_pci.c           |  2 +-
> >  hw/dec_pci.c           |  2 +-
> >  hw/ich9.h              |  2 +-
> >  hw/lpc_ich9.c          |  2 +-
> >  hw/pci/pci.c           |  2 +-
> >  hw/pci/pci_bridge.c    |  2 +-
> >  hw/pci/pci_bus.h       | 78 ++++++++++++++++++++++++++++++++++++++++++++++++++
> >  hw/pci/pci_internals.h | 78 --------------------------------------------------
> >  hw/pci/pcie.c          |  2 +-
> >  hw/pci/pcie_aer.c      |  2 +-
> >  hw/pci/pcie_port.h     |  2 +-
> >  hw/pci/shpc.c          |  2 +-
> >  hw/pci_bridge_dev.c    |  2 +-
> >  hw/spapr_pci.c         |  2 +-
> >  14 files changed, 90 insertions(+), 90 deletions(-)
> >  create mode 100644 hw/pci/pci_bus.h
> >  delete mode 100644 hw/pci/pci_internals.h
> >
> > diff --git a/hw/apb_pci.c b/hw/apb_pci.c
> > index de594f8..fb7a07d 100644
> > --- a/hw/apb_pci.c
> > +++ b/hw/apb_pci.c
> > @@ -30,7 +30,7 @@
> >  #include "pci/pci.h"
> >  #include "pci/pci_host.h"
> >  #include "pci/pci_bridge.h"
> > -#include "pci/pci_internals.h"
> > +#include "pci/pci_bus.h"
> >  #include "apb_pci.h"
> >  #include "sysemu.h"
> >  #include "exec-memory.h"
> > diff --git a/hw/dec_pci.c b/hw/dec_pci.c
> > index a6a7c84..ee3f4ca 100644
> > --- a/hw/dec_pci.c
> > +++ b/hw/dec_pci.c
> > @@ -28,7 +28,7 @@
> >  #include "pci/pci.h"
> >  #include "pci/pci_host.h"
> >  #include "pci/pci_bridge.h"
> > -#include "pci/pci_internals.h"
> > +#include "pci/pci_bus.h"
> >
> >  /* debug DEC */
> >  //#define DEBUG_DEC
> > diff --git a/hw/ich9.h b/hw/ich9.h
> > index 247be94..4e7442c 100644
> > --- a/hw/ich9.h
> > +++ b/hw/ich9.h
> > @@ -14,7 +14,7 @@
> >  #include "acpi.h"
> >  #include "acpi_ich9.h"
> >  #include "pam.h"
> > -#include "pci/pci_internals.h"
> > +#include "pci/pci_bus.h"
> >
> >  void ich9_lpc_set_irq(void *opaque, int irq_num, int level);
> >  int ich9_lpc_map_irq(PCIDevice *pci_dev, int intx);
> > diff --git a/hw/lpc_ich9.c b/hw/lpc_ich9.c
> > index 23dee88..7bca061 100644
> > --- a/hw/lpc_ich9.c
> > +++ b/hw/lpc_ich9.c
> > @@ -42,7 +42,7 @@
> >  #include "acpi.h"
> >  #include "acpi_ich9.h"
> >  #include "pam.h"
> > -#include "pci/pci_internals.h"
> > +#include "pci/pci_bus.h"
> >  #include "exec-memory.h"
> >
> >  static int ich9_lpc_sci_irq(ICH9LPCState *lpc);
> > diff --git a/hw/pci/pci.c b/hw/pci/pci.c
> > index 6023ded..c1a4b32 100644
> > --- a/hw/pci/pci.c
> > +++ b/hw/pci/pci.c
> > @@ -24,7 +24,7 @@
> >  #include <hw/hw.h>
> >  #include "pci.h"
> >  #include "pci_bridge.h"
> > -#include "pci_internals.h"
> > +#include "pci_bus.h"
> >  #include <monitor.h>
> >  #include <net.h>
> >  #include <sysemu.h>
> > diff --git a/hw/pci/pci_bridge.c b/hw/pci/pci_bridge.c
> > index 4680501..0fb7577 100644
> > --- a/hw/pci/pci_bridge.c
> > +++ b/hw/pci/pci_bridge.c
> > @@ -30,7 +30,7 @@
> >   */
> >
> >  #include "pci_bridge.h"
> > -#include "pci_internals.h"
> > +#include "pci_bus.h"
> >  #include "range.h"
> >
> >  /* PCI bridge subsystem vendor ID helper functions */
> > diff --git a/hw/pci/pci_bus.h b/hw/pci/pci_bus.h
> > new file mode 100644
> > index 0000000..21d0ce6
> > --- /dev/null
> > +++ b/hw/pci/pci_bus.h
> > @@ -0,0 +1,78 @@
> > +#ifndef QEMU_PCI_INTERNALS_H
> > +#define QEMU_PCI_INTERNALS_H
> 
> This should become QEMU_PCI_BUS_H or something similar.

Good catch, thanks! Will fix in a separate patch though - rename
detection works better if file is moved without changes.

> > +
> > +/*
> > + * 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_internals.h b/hw/pci/pci_internals.h
> > deleted file mode 100644
> > index 21d0ce6..0000000
> > --- a/hw/pci/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/pcie.c b/hw/pci/pcie.c
> > index 7c92f19..d9c38b5 100644
> > --- a/hw/pci/pcie.c
> > +++ b/hw/pci/pcie.c
> > @@ -23,7 +23,7 @@
> >  #include "pcie.h"
> >  #include "msix.h"
> >  #include "msi.h"
> > -#include "pci_internals.h"
> > +#include "pci_bus.h"
> >  #include "pcie_regs.h"
> >  #include "range.h"
> >
> > diff --git a/hw/pci/pcie_aer.c b/hw/pci/pcie_aer.c
> > index b04c164..3c3185c 100644
> > --- a/hw/pci/pcie_aer.c
> > +++ b/hw/pci/pcie_aer.c
> > @@ -25,7 +25,7 @@
> >  #include "pcie.h"
> >  #include "msix.h"
> >  #include "msi.h"
> > -#include "pci_internals.h"
> > +#include "pci_bus.h"
> >  #include "pcie_regs.h"
> >
> >  //#define DEBUG_PCIE
> > diff --git a/hw/pci/pcie_port.h b/hw/pci/pcie_port.h
> > index 3709583..36b2241 100644
> > --- a/hw/pci/pcie_port.h
> > +++ b/hw/pci/pcie_port.h
> > @@ -22,7 +22,7 @@
> >  #define QEMU_PCIE_PORT_H
> >
> >  #include "pci_bridge.h"
> > -#include "pci_internals.h"
> > +#include "pci_bus.h"
> >
> >  struct PCIEPort {
> >      PCIBridge   br;
> > diff --git a/hw/pci/shpc.c b/hw/pci/shpc.c
> > index 4597bbd..9297af0 100644
> > --- a/hw/pci/shpc.c
> > +++ b/hw/pci/shpc.c
> > @@ -4,7 +4,7 @@
> >  #include "range.h"
> >  #include "shpc.h"
> >  #include "pci.h"
> > -#include "pci_internals.h"
> > +#include "pci_bus.h"
> >  #include "msi.h"
> >
> >  /* TODO: model power only and disabled slot states. */
> > diff --git a/hw/pci_bridge_dev.c b/hw/pci_bridge_dev.c
> > index 5c9fc50..dbb4b3b 100644
> > --- a/hw/pci_bridge_dev.c
> > +++ b/hw/pci_bridge_dev.c
> > @@ -25,7 +25,7 @@
> >  #include "pci/shpc.h"
> >  #include "pci/slotid_cap.h"
> >  #include "memory.h"
> > -#include "pci/pci_internals.h"
> > +#include "pci/pci_bus.h"
> >
> >  #define REDHAT_PCI_VENDOR_ID 0x1b36
> >  #define PCI_BRIDGE_DEV_VENDOR_ID REDHAT_PCI_VENDOR_ID
> > diff --git a/hw/spapr_pci.c b/hw/spapr_pci.c
> > index e123866..6b05e5b 100644
> > --- a/hw/spapr_pci.c
> > +++ b/hw/spapr_pci.c
> > @@ -33,7 +33,7 @@
> >  #include <libfdt.h>
> >  #include "trace.h"
> >
> > -#include "hw/pci/pci_internals.h"
> > +#include "hw/pci/pci_bus.h"
> >
> >  /* Copied from the kernel arch/powerpc/platforms/pseries/msi.c */
> >  #define RTAS_QUERY_FN           0
> > --
> > MST
> >
> >

^ permalink raw reply	[flat|nested] 19+ messages in thread

end of thread, other threads:[~2012-12-12 20:56 UTC | newest]

Thread overview: 19+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2012-12-12 13:13 [Qemu-devel] [PATCH 0/8] pci core reorg Michael S. Tsirkin
2012-12-12 13:14 ` [Qemu-devel] [PATCH 1/8] pci: prepare makefiles for pci code reorganization Michael S. Tsirkin
2012-12-12 13:14 ` [Qemu-devel] [PATCH 2/8] MAINTAINERS: add hw/pci/ to list of PCI files Michael S. Tsirkin
2012-12-12 13:14 ` [Qemu-devel] [PATCH 3/8] pci: move pci core code to hw/pci Michael S. Tsirkin
2012-12-12 19:53   ` Blue Swirl
2012-12-12 20:56     ` Michael S. Tsirkin
2012-12-12 13:14 ` [Qemu-devel] [PATCH 4/8] pci: update all users to look in pci/ Michael S. Tsirkin
2012-12-12 13:14 ` [Qemu-devel] [PATCH 6/8] Revert "pci: prepare makefiles for pci code reorganization" Michael S. Tsirkin
2012-12-12 13:14 ` [Qemu-devel] [PATCH 5/8] pci: make external dependencies explicit Michael S. Tsirkin
2012-12-12 19:49   ` Blue Swirl
2012-12-12 20:53     ` Michael S. Tsirkin
2012-12-12 13:14 ` [Qemu-devel] [PATCH 7/8] pci: rename pci_internals.h pci_bus.h Michael S. Tsirkin
2012-12-12 19:56   ` Blue Swirl
2012-12-12 20:59     ` Michael S. Tsirkin
2012-12-12 13:14 ` [Qemu-devel] [PATCH 8/8] pci_bus: update comment Michael S. Tsirkin
2012-12-12 13:51 ` [Qemu-devel] [PATCH 0/8] pci core reorg Anthony Liguori
2012-12-12 13:59   ` Paolo Bonzini
2012-12-12 20:00 ` Blue Swirl
2012-12-12 20:58   ` Michael S. Tsirkin

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).