diff options
author | Alexander Graf <agraf@suse.de> | 2010-08-31 00:22:28 +0200 |
---|---|---|
committer | Alexander Graf <agraf@suse.de> | 2011-05-12 00:24:52 +0200 |
commit | be13cc7a352b74412374a554a15b32b105f6706b (patch) | |
tree | 97d7fabe03628667a0939808eb7e08927dc10e74 /hw/ppce500_pci.c | |
parent | 5389055a91dd2128279ba6ac6828264465eb19ee (diff) | |
download | qemu-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.c | 136 |
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); |