summaryrefslogtreecommitdiff
path: root/hw/ppce500_pci.c
diff options
context:
space:
mode:
authorAlexander Graf <agraf@suse.de>2010-08-31 00:22:28 +0200
committerAlexander Graf <agraf@suse.de>2011-05-12 00:24:52 +0200
commitbe13cc7a352b74412374a554a15b32b105f6706b (patch)
tree97d7fabe03628667a0939808eb7e08927dc10e74 /hw/ppce500_pci.c
parent5389055a91dd2128279ba6ac6828264465eb19ee (diff)
downloadqemu-be13cc7a352b74412374a554a15b32b105f6706b.tar.gz
qemu-be13cc7a352b74412374a554a15b32b105f6706b.tar.bz2
qemu-be13cc7a352b74412374a554a15b32b105f6706b.zip
PPC: Qdev'ify e500 pci
The e500 PCI controller isn't qdev'ified yet. This leads to severe issues when running with -drive. To be able to use a virtio disk with an e500 VM, let's convert the PCI controller over to qdev. Reviewed-by: Paul Brook <paul@codesourcery.com> Signed-off-by: Alexander Graf <agraf@suse.de>
Diffstat (limited to 'hw/ppce500_pci.c')
-rw-r--r--hw/ppce500_pci.c136
1 files changed, 76 insertions, 60 deletions
diff --git a/hw/ppce500_pci.c b/hw/ppce500_pci.c
index 83a20e4620..069af9691a 100644
--- a/hw/ppce500_pci.c
+++ b/hw/ppce500_pci.c
@@ -15,7 +15,6 @@
*/
#include "hw.h"
-#include "ppce500.h"
#include "pci.h"
#include "pci_host.h"
#include "bswap.h"
@@ -29,7 +28,8 @@
#define PCIE500_CFGADDR 0x0
#define PCIE500_CFGDATA 0x4
#define PCIE500_REG_BASE 0xC00
-#define PCIE500_REG_SIZE (0x1000 - PCIE500_REG_BASE)
+#define PCIE500_ALL_SIZE 0x1000
+#define PCIE500_REG_SIZE (PCIE500_ALL_SIZE - PCIE500_REG_BASE)
#define PPCE500_PCI_CONFIG_ADDR 0x0
#define PPCE500_PCI_CONFIG_DATA 0x4
@@ -73,11 +73,15 @@ struct pci_inbound {
};
struct PPCE500PCIState {
+ PCIHostState pci_state;
struct pci_outbound pob[PPCE500_PCI_NR_POBS];
struct pci_inbound pib[PPCE500_PCI_NR_PIBS];
uint32_t gasket_time;
- PCIHostState pci_state;
- PCIDevice *pci_dev;
+ qemu_irq irq[4];
+ /* mmio maps */
+ int cfgaddr;
+ int cfgdata;
+ int reg;
};
typedef struct PPCE500PCIState PPCE500PCIState;
@@ -250,7 +254,6 @@ static const VMStateDescription vmstate_ppce500_pci = {
.minimum_version_id = 1,
.minimum_version_id_old = 1,
.fields = (VMStateField[]) {
- VMSTATE_PCI_DEVICE_POINTER(pci_dev, PPCE500PCIState),
VMSTATE_STRUCT_ARRAY(pob, PPCE500PCIState, PPCE500_PCI_NR_POBS, 1,
vmstate_pci_outbound, struct pci_outbound),
VMSTATE_STRUCT_ARRAY(pib, PPCE500PCIState, PPCE500_PCI_NR_PIBS, 1,
@@ -260,60 +263,73 @@ static const VMStateDescription vmstate_ppce500_pci = {
}
};
-PCIBus *ppce500_pci_init(qemu_irq pci_irqs[4], target_phys_addr_t registers)
+static void e500_pci_map(SysBusDevice *dev, target_phys_addr_t base)
+{
+ PCIHostState *h = FROM_SYSBUS(PCIHostState, sysbus_from_qdev(dev));
+ PPCE500PCIState *s = DO_UPCAST(PPCE500PCIState, pci_state, h);
+
+ cpu_register_physical_memory(base + PCIE500_CFGADDR, 4, s->cfgaddr);
+ cpu_register_physical_memory(base + PCIE500_CFGDATA, 4, s->cfgdata);
+ cpu_register_physical_memory(base + PCIE500_REG_BASE, PCIE500_REG_SIZE,
+ s->reg);
+}
+
+static int e500_pcihost_initfn(SysBusDevice *dev)
+{
+ PCIHostState *h;
+ PPCE500PCIState *s;
+ PCIBus *b;
+ int i;
+
+ h = FROM_SYSBUS(PCIHostState, sysbus_from_qdev(dev));
+ s = DO_UPCAST(PPCE500PCIState, pci_state, h);
+
+ for (i = 0; i < ARRAY_SIZE(s->irq); i++) {
+ sysbus_init_irq(dev, &s->irq[i]);
+ }
+
+ b = pci_register_bus(&s->pci_state.busdev.qdev, NULL, mpc85xx_pci_set_irq,
+ mpc85xx_pci_map_irq, s->irq, PCI_DEVFN(0x11, 0), 4);
+ s->pci_state.bus = b;
+
+ pci_create_simple(b, 0, "e500-host-bridge");
+
+ s->cfgaddr = pci_host_conf_register_mmio(&s->pci_state, DEVICE_BIG_ENDIAN);
+ s->cfgdata = pci_host_data_register_mmio(&s->pci_state,
+ DEVICE_LITTLE_ENDIAN);
+ s->reg = cpu_register_io_memory(e500_pci_reg_read, e500_pci_reg_write, s,
+ DEVICE_BIG_ENDIAN);
+ sysbus_init_mmio_cb(dev, PCIE500_ALL_SIZE, e500_pci_map);
+
+ return 0;
+}
+
+static int e500_host_bridge_initfn(PCIDevice *dev)
+{
+ pci_config_set_vendor_id(dev->config, PCI_VENDOR_ID_FREESCALE);
+ pci_config_set_device_id(dev->config, PCI_DEVICE_ID_MPC8533E);
+ pci_config_set_class(dev->config, PCI_CLASS_PROCESSOR_POWERPC);
+
+ return 0;
+}
+
+static PCIDeviceInfo e500_host_bridge_info = {
+ .qdev.name = "e500-host-bridge",
+ .qdev.desc = "Host bridge",
+ .qdev.size = sizeof(PCIDevice),
+ .init = e500_host_bridge_initfn,
+};
+
+static SysBusDeviceInfo e500_pcihost_info = {
+ .init = e500_pcihost_initfn,
+ .qdev.name = "e500-pcihost",
+ .qdev.size = sizeof(PPCE500PCIState),
+ .qdev.vmsd = &vmstate_ppce500_pci,
+};
+
+static void e500_pci_register(void)
{
- PPCE500PCIState *controller;
- PCIDevice *d;
- int index;
- static int ppce500_pci_id;
-
- controller = qemu_mallocz(sizeof(PPCE500PCIState));
-
- controller->pci_state.bus = pci_register_bus(NULL, "pci",
- mpc85xx_pci_set_irq,
- mpc85xx_pci_map_irq,
- pci_irqs, PCI_DEVFN(0x11, 0),
- 4);
- d = pci_register_device(controller->pci_state.bus,
- "host bridge", sizeof(PCIDevice),
- 0, NULL, NULL);
-
- pci_config_set_vendor_id(d->config, PCI_VENDOR_ID_FREESCALE);
- pci_config_set_device_id(d->config, PCI_DEVICE_ID_MPC8533E);
- pci_config_set_class(d->config, PCI_CLASS_PROCESSOR_POWERPC);
-
- controller->pci_dev = d;
-
- /* CFGADDR */
- index = pci_host_conf_register_mmio(&controller->pci_state,
- DEVICE_BIG_ENDIAN);
- if (index < 0)
- goto free;
- cpu_register_physical_memory(registers + PCIE500_CFGADDR, 4, index);
-
- /* CFGDATA */
- index = pci_host_data_register_mmio(&controller->pci_state,
- DEVICE_BIG_ENDIAN);
- if (index < 0)
- goto free;
- cpu_register_physical_memory(registers + PCIE500_CFGDATA, 4, index);
-
- index = cpu_register_io_memory(e500_pci_reg_read,
- e500_pci_reg_write, controller,
- DEVICE_NATIVE_ENDIAN);
- if (index < 0)
- goto free;
- cpu_register_physical_memory(registers + PCIE500_REG_BASE,
- PCIE500_REG_SIZE, index);
-
- /* XXX load/save code not tested. */
- vmstate_register(&d->qdev, ppce500_pci_id++, &vmstate_ppce500_pci,
- controller);
-
- return controller->pci_state.bus;
-
-free:
- printf("%s error\n", __func__);
- qemu_free(controller);
- return NULL;
+ sysbus_register_withprop(&e500_pcihost_info);
+ pci_qdev_register(&e500_host_bridge_info);
}
+device_init(e500_pci_register);