Don't always keep pointer to PIC, but keep only references to required IRQs. Add a PCI host.
Signed-off-by: Hervé Poussineau <hpous...@reactos.org> Avoid adding qemu_irq state by reusing SysBus facilities. This allows to qdev'ify the PCIDevice, too, by banning hardcoded IRQ numbers into pci_prep_init() wrapper. Cc: Michael S. Tsirkin <m...@redhat.com> Cc: Alexander Graf <ag...@suse.de> Signed-off-by: Andreas Färber <andreas.faer...@web.de> --- hw/prep_pci.c | 126 ++++++++++++++++++++++++++++++++++++++++++++------------- 1 files changed, 97 insertions(+), 29 deletions(-) diff --git a/hw/prep_pci.c b/hw/prep_pci.c index f88b825..2554d86 100644 --- a/hw/prep_pci.c +++ b/hw/prep_pci.c @@ -2,6 +2,8 @@ * QEMU PREP PCI host * * Copyright (c) 2006 Fabrice Bellard + * Copyright (c) 2010 Herve Poussineau + * Copyright (c) 2010-2011 Andreas Faerber * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -27,7 +29,14 @@ #include "pci_host.h" #include "prep_pci.h" -typedef PCIHostState PREPPCIState; +typedef struct PREPPCIState { + PCIHostState host_state; +} PREPPCIState; + +typedef struct PRePPCIBusState { + SysBusDevice busdev; + PREPPCIState state; +} PRePPCIBusState; static inline uint32_t PPC_PCIIO_config(target_phys_addr_t addr) { @@ -43,28 +52,28 @@ static inline uint32_t PPC_PCIIO_config(target_phys_addr_t addr) static void PPC_PCIIO_writeb (void *opaque, target_phys_addr_t addr, uint32_t val) { PREPPCIState *s = opaque; - pci_data_write(s->bus, PPC_PCIIO_config(addr), val, 1); + pci_data_write(s->host_state.bus, PPC_PCIIO_config(addr), val, 1); } static void PPC_PCIIO_writew (void *opaque, target_phys_addr_t addr, uint32_t val) { PREPPCIState *s = opaque; val = bswap16(val); - pci_data_write(s->bus, PPC_PCIIO_config(addr), val, 2); + pci_data_write(s->host_state.bus, PPC_PCIIO_config(addr), val, 2); } static void PPC_PCIIO_writel (void *opaque, target_phys_addr_t addr, uint32_t val) { PREPPCIState *s = opaque; val = bswap32(val); - pci_data_write(s->bus, PPC_PCIIO_config(addr), val, 4); + pci_data_write(s->host_state.bus, PPC_PCIIO_config(addr), val, 4); } static uint32_t PPC_PCIIO_readb (void *opaque, target_phys_addr_t addr) { PREPPCIState *s = opaque; uint32_t val; - val = pci_data_read(s->bus, PPC_PCIIO_config(addr), 1); + val = pci_data_read(s->host_state.bus, PPC_PCIIO_config(addr), 1); return val; } @@ -72,7 +81,7 @@ static uint32_t PPC_PCIIO_readw (void *opaque, target_phys_addr_t addr) { PREPPCIState *s = opaque; uint32_t val; - val = pci_data_read(s->bus, PPC_PCIIO_config(addr), 2); + val = pci_data_read(s->host_state.bus, PPC_PCIIO_config(addr), 2); val = bswap16(val); return val; } @@ -81,7 +90,7 @@ static uint32_t PPC_PCIIO_readl (void *opaque, target_phys_addr_t addr) { PREPPCIState *s = opaque; uint32_t val; - val = pci_data_read(s->bus, PPC_PCIIO_config(addr), 4); + val = pci_data_read(s->host_state.bus, PPC_PCIIO_config(addr), 4); val = bswap32(val); return val; } @@ -105,40 +114,99 @@ static int prep_map_irq(PCIDevice *pci_dev, int irq_num) static void prep_set_irq(void *opaque, int irq_num, int level) { - qemu_irq *pic = opaque; + PRePPCIBusState *s = opaque; + SysBusDevice *sysbus = &s->busdev; - qemu_set_irq(pic[(irq_num & 1) ? 11 : 9] , level); + if (sysbus->irqp[irq_num] != NULL) { + qemu_set_irq(*sysbus->irqp[irq_num], level); + } } +static int prep_pci_host_init(PCIDevice *d) +{ + pci_config_set_vendor_id(d->config, PCI_VENDOR_ID_MOTOROLA); + pci_config_set_device_id(d->config, PCI_DEVICE_ID_MOTOROLA_RAVEN); + d->config[0x08] = 0x00; // revision + pci_config_set_class(d->config, PCI_CLASS_BRIDGE_HOST); + d->config[0x0C] = 0x08; // cache_line_size + d->config[0x0D] = 0x10; // latency_timer + d->config[0x34] = 0x00; // capabilities_pointer + + return 0; +} + +/* Motorola Raven */ +static PCIDeviceInfo prep_pci_host_info = { + .qdev.name = "prep-pci", + .qdev.size = sizeof(PCIDevice), + .init = prep_pci_host_init, + .qdev.props = (Property[]) { + DEFINE_PROP_END_OF_LIST() + }, +}; + PCIBus *pci_prep_init(qemu_irq *pic) { - PREPPCIState *s; - PCIDevice *d; - int PPC_io_memory; + DeviceState *dev; + SysBusDevice *sysbus; + + /* PReP PCI bus */ + dev = qdev_create(NULL, "prep-pci"); + sysbus = sysbus_from_qdev(dev); - s = qemu_mallocz(sizeof(PREPPCIState)); - s->bus = pci_register_bus(NULL, "pci", - prep_set_irq, prep_map_irq, pic, 0, 4); + /* Allocate and initialize both IRQs before init */ + sysbus_init_irq(sysbus, &pic[9]); + sysbus_init_irq(sysbus, &pic[11]); - pci_host_conf_register_ioport(0xcf8, s); + qdev_init_nofail(dev); - pci_host_data_register_ioport(0xcfc, s); + sysbus_mmio_map(sysbus, 0, 0x80800000); + + return (PCIBus *)qdev_get_child_bus(dev, "pci"); +} + +static int prep_pci_sysbus_init(SysBusDevice *dev) +{ + PRePPCIBusState *sysbus = FROM_SYSBUS(PRePPCIBusState, dev); + PREPPCIState *s = &sysbus->state; + PCIDevice *d; + int PPC_io_memory; + + /* Allocate two IRQs if necessary and NULL-initialize */ + while (sysbus->busdev.num_irq < 2) { + sysbus_init_irq(&sysbus->busdev, NULL); + } PPC_io_memory = cpu_register_io_memory(PPC_PCIIO_read, PPC_PCIIO_write, s, DEVICE_NATIVE_ENDIAN); - cpu_register_physical_memory(0x80800000, 0x00400000, PPC_io_memory); + sysbus_init_mmio(dev, 0x00400000, PPC_io_memory); - /* PCI host bridge */ - d = pci_register_device(s->bus, "PREP Host Bridge - Motorola Raven", - sizeof(PCIDevice), 0, NULL, NULL); - pci_config_set_vendor_id(d->config, PCI_VENDOR_ID_MOTOROLA); - pci_config_set_device_id(d->config, PCI_DEVICE_ID_MOTOROLA_RAVEN); - d->config[0x08] = 0x00; // revision - pci_config_set_class(d->config, PCI_CLASS_BRIDGE_HOST); - d->config[0x0C] = 0x08; // cache_line_size - d->config[0x0D] = 0x10; // latency_timer - d->config[0x34] = 0x00; // capabilities_pointer + s->host_state.bus = pci_register_bus(&sysbus->busdev.qdev, "pci", + prep_set_irq, + prep_map_irq, sysbus, 0, 2); + + pci_host_conf_register_ioport(0xcf8, &s->host_state); + pci_host_data_register_ioport(0xcfc, &s->host_state); + + d = pci_create_simple(s->host_state.bus, 0, "prep-pci"); + + return 0; +} + +static SysBusDeviceInfo prep_pci_sysbus_info = { + .qdev.name = "prep-pci", + .qdev.size = sizeof(PRePPCIBusState), + .init = prep_pci_sysbus_init, + .qdev.props = (Property[]) { + DEFINE_PROP_END_OF_LIST() + }, +}; - return s->bus; +static void prep_pci_register_devices(void) +{ + sysbus_register_withprop(&prep_pci_sysbus_info); + pci_qdev_register(&prep_pci_host_info); } + +device_init(prep_pci_register_devices) -- 1.7.5.3