*/
#include "hw.h"
-#include "ppce500.h"
#include "pci.h"
#include "pci_host.h"
#include "bswap.h"
#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
};
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 */
+ MemoryRegion container;
+ MemoryRegion iomem;
};
typedef struct PPCE500PCIState PPCE500PCIState;
-static uint32_t pci_reg_read4(void *opaque, target_phys_addr_t addr)
+static uint64_t pci_reg_read4(void *opaque, target_phys_addr_t addr,
+ unsigned size)
{
PPCE500PCIState *pci = opaque;
unsigned long win;
uint32_t value = 0;
+ int idx;
win = addr & 0xfe0;
case PPCE500_PCI_OW2:
case PPCE500_PCI_OW3:
case PPCE500_PCI_OW4:
+ idx = (addr >> 5) & 0x7;
switch (addr & 0xC) {
- case PCI_POTAR: value = pci->pob[(addr >> 5) & 0x7].potar; break;
- case PCI_POTEAR: value = pci->pob[(addr >> 5) & 0x7].potear; break;
- case PCI_POWBAR: value = pci->pob[(addr >> 5) & 0x7].powbar; break;
- case PCI_POWAR: value = pci->pob[(addr >> 5) & 0x7].powar; break;
- default: break;
+ case PCI_POTAR:
+ value = pci->pob[idx].potar;
+ break;
+ case PCI_POTEAR:
+ value = pci->pob[idx].potear;
+ break;
+ case PCI_POWBAR:
+ value = pci->pob[idx].powbar;
+ break;
+ case PCI_POWAR:
+ value = pci->pob[idx].powar;
+ break;
+ default:
+ break;
}
break;
case PPCE500_PCI_IW3:
case PPCE500_PCI_IW2:
case PPCE500_PCI_IW1:
+ idx = ((addr >> 5) & 0x3) - 1;
switch (addr & 0xC) {
- case PCI_PITAR: value = pci->pib[(addr >> 5) & 0x3].pitar; break;
- case PCI_PIWBAR: value = pci->pib[(addr >> 5) & 0x3].piwbar; break;
- case PCI_PIWBEAR: value = pci->pib[(addr >> 5) & 0x3].piwbear; break;
- case PCI_PIWAR: value = pci->pib[(addr >> 5) & 0x3].piwar; break;
- default: break;
+ case PCI_PITAR:
+ value = pci->pib[idx].pitar;
+ break;
+ case PCI_PIWBAR:
+ value = pci->pib[idx].piwbar;
+ break;
+ case PCI_PIWBEAR:
+ value = pci->pib[idx].piwbear;
+ break;
+ case PCI_PIWAR:
+ value = pci->pib[idx].piwar;
+ break;
+ default:
+ break;
};
break;
return value;
}
-static CPUReadMemoryFunc * const e500_pci_reg_read[] = {
- &pci_reg_read4,
- &pci_reg_read4,
- &pci_reg_read4,
-};
-
static void pci_reg_write4(void *opaque, target_phys_addr_t addr,
- uint32_t value)
+ uint64_t value, unsigned size)
{
PPCE500PCIState *pci = opaque;
unsigned long win;
+ int idx;
win = addr & 0xfe0;
pci_debug("%s: value:%x -> win:%lx(addr:" TARGET_FMT_plx ")\n",
- __func__, value, win, addr);
+ __func__, (unsigned)value, win, addr);
switch (win) {
case PPCE500_PCI_OW1:
case PPCE500_PCI_OW2:
case PPCE500_PCI_OW3:
case PPCE500_PCI_OW4:
+ idx = (addr >> 5) & 0x7;
switch (addr & 0xC) {
- case PCI_POTAR: pci->pob[(addr >> 5) & 0x7].potar = value; break;
- case PCI_POTEAR: pci->pob[(addr >> 5) & 0x7].potear = value; break;
- case PCI_POWBAR: pci->pob[(addr >> 5) & 0x7].powbar = value; break;
- case PCI_POWAR: pci->pob[(addr >> 5) & 0x7].powar = value; break;
- default: break;
+ case PCI_POTAR:
+ pci->pob[idx].potar = value;
+ break;
+ case PCI_POTEAR:
+ pci->pob[idx].potear = value;
+ break;
+ case PCI_POWBAR:
+ pci->pob[idx].powbar = value;
+ break;
+ case PCI_POWAR:
+ pci->pob[idx].powar = value;
+ break;
+ default:
+ break;
};
break;
case PPCE500_PCI_IW3:
case PPCE500_PCI_IW2:
case PPCE500_PCI_IW1:
+ idx = ((addr >> 5) & 0x3) - 1;
switch (addr & 0xC) {
- case PCI_PITAR: pci->pib[(addr >> 5) & 0x3].pitar = value; break;
- case PCI_PIWBAR: pci->pib[(addr >> 5) & 0x3].piwbar = value; break;
- case PCI_PIWBEAR: pci->pib[(addr >> 5) & 0x3].piwbear = value; break;
- case PCI_PIWAR: pci->pib[(addr >> 5) & 0x3].piwar = value; break;
- default: break;
+ case PCI_PITAR:
+ pci->pib[idx].pitar = value;
+ break;
+ case PCI_PIWBAR:
+ pci->pib[idx].piwbar = value;
+ break;
+ case PCI_PIWBEAR:
+ pci->pib[idx].piwbear = value;
+ break;
+ case PCI_PIWAR:
+ pci->pib[idx].piwar = value;
+ break;
+ default:
+ break;
};
break;
};
}
-static CPUWriteMemoryFunc * const e500_pci_reg_write[] = {
- &pci_reg_write4,
- &pci_reg_write4,
- &pci_reg_write4,
+static const MemoryRegionOps e500_pci_reg_ops = {
+ .read = pci_reg_read4,
+ .write = pci_reg_write4,
+ .endianness = DEVICE_BIG_ENDIAN,
};
static int mpc85xx_pci_map_irq(PCIDevice *pci_dev, int irq_num)
.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,
}
};
-PCIBus *ppce500_pci_init(qemu_irq pci_irqs[4], target_phys_addr_t registers)
+#include "exec-memory.h"
+
+static int e500_pcihost_initfn(SysBusDevice *dev)
+{
+ PCIHostState *h;
+ PPCE500PCIState *s;
+ PCIBus *b;
+ int i;
+ MemoryRegion *address_space_mem = get_system_memory();
+ MemoryRegion *address_space_io = get_system_io();
+
+ 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, address_space_mem,
+ address_space_io, PCI_DEVFN(0x11, 0), 4);
+ s->pci_state.bus = b;
+
+ pci_create_simple(b, 0, "e500-host-bridge");
+
+ memory_region_init(&s->container, "pci-container", PCIE500_ALL_SIZE);
+ memory_region_init_io(&h->conf_mem, &pci_host_conf_be_ops, h,
+ "pci-conf-idx", 4);
+ memory_region_init_io(&h->data_mem, &pci_host_data_le_ops, h,
+ "pci-conf-data", 4);
+ memory_region_init_io(&s->iomem, &e500_pci_reg_ops, s,
+ "pci.reg", PCIE500_REG_SIZE);
+ memory_region_add_subregion(&s->container, PCIE500_CFGADDR, &h->conf_mem);
+ memory_region_add_subregion(&s->container, PCIE500_CFGDATA, &h->data_mem);
+ memory_region_add_subregion(&s->container, PCIE500_REG_BASE, &s->iomem);
+ sysbus_init_mmio(dev, &s->container);
+
+ return 0;
+}
+
+static void e500_host_bridge_class_init(ObjectClass *klass, void *data)
{
- 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;
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
+
+ k->vendor_id = PCI_VENDOR_ID_FREESCALE;
+ k->device_id = PCI_DEVICE_ID_MPC8533E;
+ k->class_id = PCI_CLASS_PROCESSOR_POWERPC;
+ dc->desc = "Host bridge";
}
+
+static TypeInfo e500_host_bridge_info = {
+ .name = "e500-host-bridge",
+ .parent = TYPE_PCI_DEVICE,
+ .instance_size = sizeof(PCIDevice),
+ .class_init = e500_host_bridge_class_init,
+};
+
+static void e500_pcihost_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
+
+ k->init = e500_pcihost_initfn;
+ dc->vmsd = &vmstate_ppce500_pci;
+}
+
+static TypeInfo e500_pcihost_info = {
+ .name = "e500-pcihost",
+ .parent = TYPE_SYS_BUS_DEVICE,
+ .instance_size = sizeof(PPCE500PCIState),
+ .class_init = e500_pcihost_class_init,
+};
+
+static void e500_pci_register_types(void)
+{
+ type_register_static(&e500_pcihost_info);
+ type_register_static(&e500_host_bridge_info);
+}
+
+type_init(e500_pci_register_types)