From 46fd3201cb02d95f42f659121b13cf5e2633db1c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Fri, 16 Apr 2021 18:18:58 +0200 Subject: hw/pci-host: Rename Raven ASIC PCI bridge as raven.c MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The ASIC PCI bridge chipset from Motorola is named 'Raven'. This chipset is used in the PowerPC Reference Platform (PReP), but not restricted to it. Rename it accordingly. Signed-off-by: Philippe Mathieu-Daudé Acked-by: David Gibson Message-Id: <20210417103028.601124-5-f4bug@amsat.org> --- hw/pci-host/Kconfig | 2 +- hw/pci-host/meson.build | 2 +- hw/pci-host/prep.c | 442 ------------------------------------------------ hw/pci-host/raven.c | 442 ++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 444 insertions(+), 444 deletions(-) delete mode 100644 hw/pci-host/prep.c create mode 100644 hw/pci-host/raven.c (limited to 'hw/pci-host') diff --git a/hw/pci-host/Kconfig b/hw/pci-host/Kconfig index 79c20bf28b..84494400b8 100644 --- a/hw/pci-host/Kconfig +++ b/hw/pci-host/Kconfig @@ -6,7 +6,7 @@ config XEN_IGD_PASSTHROUGH default y depends on XEN && PCI_I440FX -config PREP_PCI +config RAVEN_PCI bool select PCI select OR_IRQ diff --git a/hw/pci-host/meson.build b/hw/pci-host/meson.build index 1698d3a192..4c4f39c15c 100644 --- a/hw/pci-host/meson.build +++ b/hw/pci-host/meson.build @@ -13,7 +13,7 @@ pci_ss.add(when: 'CONFIG_REMOTE_PCIHOST', if_true: files('remote.c')) pci_ss.add(when: 'CONFIG_SH_PCI', if_true: files('sh_pci.c')) # PPC devices -pci_ss.add(when: 'CONFIG_PREP_PCI', if_true: files('prep.c')) +pci_ss.add(when: 'CONFIG_RAVEN_PCI', if_true: files('raven.c')) pci_ss.add(when: 'CONFIG_GRACKLE_PCI', if_true: files('grackle.c')) # NewWorld PowerMac pci_ss.add(when: 'CONFIG_UNIN_PCI', if_true: files('uninorth.c')) diff --git a/hw/pci-host/prep.c b/hw/pci-host/prep.c deleted file mode 100644 index 9fef74fc56..0000000000 --- a/hw/pci-host/prep.c +++ /dev/null @@ -1,442 +0,0 @@ -/* - * QEMU PREP PCI host - * - * Copyright (c) 2006 Fabrice Bellard - * Copyright (c) 2011-2013 Andreas Färber - * - * 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 "qemu/osdep.h" -#include "qemu-common.h" -#include "qemu/datadir.h" -#include "qemu/units.h" -#include "qemu/log.h" -#include "qapi/error.h" -#include "hw/pci/pci.h" -#include "hw/pci/pci_bus.h" -#include "hw/pci/pci_host.h" -#include "hw/qdev-properties.h" -#include "migration/vmstate.h" -#include "hw/intc/i8259.h" -#include "hw/irq.h" -#include "hw/loader.h" -#include "hw/or-irq.h" -#include "elf.h" -#include "qom/object.h" - -#define TYPE_RAVEN_PCI_DEVICE "raven" -#define TYPE_RAVEN_PCI_HOST_BRIDGE "raven-pcihost" - -OBJECT_DECLARE_SIMPLE_TYPE(RavenPCIState, RAVEN_PCI_DEVICE) - -struct RavenPCIState { - PCIDevice dev; - - uint32_t elf_machine; - char *bios_name; - MemoryRegion bios; -}; - -typedef struct PRePPCIState PREPPCIState; -DECLARE_INSTANCE_CHECKER(PREPPCIState, RAVEN_PCI_HOST_BRIDGE, - TYPE_RAVEN_PCI_HOST_BRIDGE) - -struct PRePPCIState { - PCIHostState parent_obj; - - qemu_or_irq *or_irq; - qemu_irq pci_irqs[PCI_NUM_PINS]; - PCIBus pci_bus; - AddressSpace pci_io_as; - MemoryRegion pci_io; - MemoryRegion pci_io_non_contiguous; - MemoryRegion pci_memory; - MemoryRegion pci_intack; - MemoryRegion bm; - MemoryRegion bm_ram_alias; - MemoryRegion bm_pci_memory_alias; - AddressSpace bm_as; - RavenPCIState pci_dev; - - int contiguous_map; - bool is_legacy_prep; -}; - -#define BIOS_SIZE (1 * MiB) - -static inline uint32_t raven_pci_io_config(hwaddr addr) -{ - int i; - - for (i = 0; i < 11; i++) { - if ((addr & (1 << (11 + i))) != 0) { - break; - } - } - return (addr & 0x7ff) | (i << 11); -} - -static void raven_pci_io_write(void *opaque, hwaddr addr, - uint64_t val, unsigned int size) -{ - PREPPCIState *s = opaque; - PCIHostState *phb = PCI_HOST_BRIDGE(s); - pci_data_write(phb->bus, raven_pci_io_config(addr), val, size); -} - -static uint64_t raven_pci_io_read(void *opaque, hwaddr addr, - unsigned int size) -{ - PREPPCIState *s = opaque; - PCIHostState *phb = PCI_HOST_BRIDGE(s); - return pci_data_read(phb->bus, raven_pci_io_config(addr), size); -} - -static const MemoryRegionOps raven_pci_io_ops = { - .read = raven_pci_io_read, - .write = raven_pci_io_write, - .endianness = DEVICE_LITTLE_ENDIAN, -}; - -static uint64_t raven_intack_read(void *opaque, hwaddr addr, - unsigned int size) -{ - return pic_read_irq(isa_pic); -} - -static void raven_intack_write(void *opaque, hwaddr addr, - uint64_t data, unsigned size) -{ - qemu_log_mask(LOG_UNIMP, "%s not implemented\n", __func__); -} - -static const MemoryRegionOps raven_intack_ops = { - .read = raven_intack_read, - .write = raven_intack_write, - .valid = { - .max_access_size = 1, - }, -}; - -static inline hwaddr raven_io_address(PREPPCIState *s, - hwaddr addr) -{ - if (s->contiguous_map == 0) { - /* 64 KB contiguous space for IOs */ - addr &= 0xFFFF; - } else { - /* 8 MB non-contiguous space for IOs */ - addr = (addr & 0x1F) | ((addr & 0x007FFF000) >> 7); - } - - /* FIXME: handle endianness switch */ - - return addr; -} - -static uint64_t raven_io_read(void *opaque, hwaddr addr, - unsigned int size) -{ - PREPPCIState *s = opaque; - uint8_t buf[4]; - - addr = raven_io_address(s, addr); - address_space_read(&s->pci_io_as, addr + 0x80000000, - MEMTXATTRS_UNSPECIFIED, buf, size); - - if (size == 1) { - return buf[0]; - } else if (size == 2) { - return lduw_le_p(buf); - } else if (size == 4) { - return ldl_le_p(buf); - } else { - g_assert_not_reached(); - } -} - -static void raven_io_write(void *opaque, hwaddr addr, - uint64_t val, unsigned int size) -{ - PREPPCIState *s = opaque; - uint8_t buf[4]; - - addr = raven_io_address(s, addr); - - if (size == 1) { - buf[0] = val; - } else if (size == 2) { - stw_le_p(buf, val); - } else if (size == 4) { - stl_le_p(buf, val); - } else { - g_assert_not_reached(); - } - - address_space_write(&s->pci_io_as, addr + 0x80000000, - MEMTXATTRS_UNSPECIFIED, buf, size); -} - -static const MemoryRegionOps raven_io_ops = { - .read = raven_io_read, - .write = raven_io_write, - .endianness = DEVICE_LITTLE_ENDIAN, - .impl.max_access_size = 4, - .valid.unaligned = true, -}; - -static int raven_map_irq(PCIDevice *pci_dev, int irq_num) -{ - return (irq_num + (pci_dev->devfn >> 3)) & 1; -} - -static void raven_set_irq(void *opaque, int irq_num, int level) -{ - PREPPCIState *s = opaque; - - qemu_set_irq(s->pci_irqs[irq_num], level); -} - -static AddressSpace *raven_pcihost_set_iommu(PCIBus *bus, void *opaque, - int devfn) -{ - PREPPCIState *s = opaque; - - return &s->bm_as; -} - -static void raven_change_gpio(void *opaque, int n, int level) -{ - PREPPCIState *s = opaque; - - s->contiguous_map = level; -} - -static void raven_pcihost_realizefn(DeviceState *d, Error **errp) -{ - SysBusDevice *dev = SYS_BUS_DEVICE(d); - PCIHostState *h = PCI_HOST_BRIDGE(dev); - PREPPCIState *s = RAVEN_PCI_HOST_BRIDGE(dev); - MemoryRegion *address_space_mem = get_system_memory(); - int i; - - if (s->is_legacy_prep) { - for (i = 0; i < PCI_NUM_PINS; i++) { - sysbus_init_irq(dev, &s->pci_irqs[i]); - } - } else { - /* According to PReP specification section 6.1.6 "System Interrupt - * Assignments", all PCI interrupts are routed via IRQ 15 */ - s->or_irq = OR_IRQ(object_new(TYPE_OR_IRQ)); - object_property_set_int(OBJECT(s->or_irq), "num-lines", PCI_NUM_PINS, - &error_fatal); - qdev_realize(DEVICE(s->or_irq), NULL, &error_fatal); - sysbus_init_irq(dev, &s->or_irq->out_irq); - - for (i = 0; i < PCI_NUM_PINS; i++) { - s->pci_irqs[i] = qdev_get_gpio_in(DEVICE(s->or_irq), i); - } - } - - qdev_init_gpio_in(d, raven_change_gpio, 1); - - pci_bus_irqs(&s->pci_bus, raven_set_irq, raven_map_irq, s, PCI_NUM_PINS); - - memory_region_init_io(&h->conf_mem, OBJECT(h), &pci_host_conf_le_ops, s, - "pci-conf-idx", 4); - memory_region_add_subregion(&s->pci_io, 0xcf8, &h->conf_mem); - - memory_region_init_io(&h->data_mem, OBJECT(h), &pci_host_data_le_ops, s, - "pci-conf-data", 4); - memory_region_add_subregion(&s->pci_io, 0xcfc, &h->data_mem); - - memory_region_init_io(&h->mmcfg, OBJECT(s), &raven_pci_io_ops, s, - "pciio", 0x00400000); - memory_region_add_subregion(address_space_mem, 0x80800000, &h->mmcfg); - - memory_region_init_io(&s->pci_intack, OBJECT(s), &raven_intack_ops, s, - "pci-intack", 1); - memory_region_add_subregion(address_space_mem, 0xbffffff0, &s->pci_intack); - - /* TODO Remove once realize propagates to child devices. */ - qdev_realize(DEVICE(&s->pci_dev), BUS(&s->pci_bus), errp); -} - -static void raven_pcihost_initfn(Object *obj) -{ - PCIHostState *h = PCI_HOST_BRIDGE(obj); - PREPPCIState *s = RAVEN_PCI_HOST_BRIDGE(obj); - MemoryRegion *address_space_mem = get_system_memory(); - DeviceState *pci_dev; - - memory_region_init(&s->pci_io, obj, "pci-io", 0x3f800000); - memory_region_init_io(&s->pci_io_non_contiguous, obj, &raven_io_ops, s, - "pci-io-non-contiguous", 0x00800000); - memory_region_init(&s->pci_memory, obj, "pci-memory", 0x3f000000); - address_space_init(&s->pci_io_as, &s->pci_io, "raven-io"); - - /* CPU address space */ - memory_region_add_subregion(address_space_mem, 0x80000000, &s->pci_io); - memory_region_add_subregion_overlap(address_space_mem, 0x80000000, - &s->pci_io_non_contiguous, 1); - memory_region_add_subregion(address_space_mem, 0xc0000000, &s->pci_memory); - pci_root_bus_new_inplace(&s->pci_bus, sizeof(s->pci_bus), DEVICE(obj), NULL, - &s->pci_memory, &s->pci_io, 0, TYPE_PCI_BUS); - - /* Bus master address space */ - memory_region_init(&s->bm, obj, "bm-raven", 4 * GiB); - memory_region_init_alias(&s->bm_pci_memory_alias, obj, "bm-pci-memory", - &s->pci_memory, 0, - memory_region_size(&s->pci_memory)); - memory_region_init_alias(&s->bm_ram_alias, obj, "bm-system", - get_system_memory(), 0, 0x80000000); - memory_region_add_subregion(&s->bm, 0 , &s->bm_pci_memory_alias); - memory_region_add_subregion(&s->bm, 0x80000000, &s->bm_ram_alias); - address_space_init(&s->bm_as, &s->bm, "raven-bm"); - pci_setup_iommu(&s->pci_bus, raven_pcihost_set_iommu, s); - - h->bus = &s->pci_bus; - - object_initialize(&s->pci_dev, sizeof(s->pci_dev), TYPE_RAVEN_PCI_DEVICE); - pci_dev = DEVICE(&s->pci_dev); - object_property_set_int(OBJECT(&s->pci_dev), "addr", PCI_DEVFN(0, 0), - NULL); - qdev_prop_set_bit(pci_dev, "multifunction", false); -} - -static void raven_realize(PCIDevice *d, Error **errp) -{ - RavenPCIState *s = RAVEN_PCI_DEVICE(d); - char *filename; - int bios_size = -1; - - d->config[0x0C] = 0x08; // cache_line_size - d->config[0x0D] = 0x10; // latency_timer - d->config[0x34] = 0x00; // capabilities_pointer - - memory_region_init_rom_nomigrate(&s->bios, OBJECT(s), "bios", BIOS_SIZE, - &error_fatal); - memory_region_add_subregion(get_system_memory(), (uint32_t)(-BIOS_SIZE), - &s->bios); - if (s->bios_name) { - filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, s->bios_name); - if (filename) { - if (s->elf_machine != EM_NONE) { - bios_size = load_elf(filename, NULL, NULL, NULL, NULL, - NULL, NULL, NULL, 1, s->elf_machine, - 0, 0); - } - if (bios_size < 0) { - bios_size = get_image_size(filename); - if (bios_size > 0 && bios_size <= BIOS_SIZE) { - hwaddr bios_addr; - bios_size = (bios_size + 0xfff) & ~0xfff; - bios_addr = (uint32_t)(-BIOS_SIZE); - bios_size = load_image_targphys(filename, bios_addr, - bios_size); - } - } - } - g_free(filename); - if (bios_size < 0 || bios_size > BIOS_SIZE) { - memory_region_del_subregion(get_system_memory(), &s->bios); - error_setg(errp, "Could not load bios image '%s'", s->bios_name); - return; - } - } - - vmstate_register_ram_global(&s->bios); -} - -static const VMStateDescription vmstate_raven = { - .name = "raven", - .version_id = 0, - .minimum_version_id = 0, - .fields = (VMStateField[]) { - VMSTATE_PCI_DEVICE(dev, RavenPCIState), - VMSTATE_END_OF_LIST() - }, -}; - -static void raven_class_init(ObjectClass *klass, void *data) -{ - PCIDeviceClass *k = PCI_DEVICE_CLASS(klass); - DeviceClass *dc = DEVICE_CLASS(klass); - - k->realize = raven_realize; - k->vendor_id = PCI_VENDOR_ID_MOTOROLA; - k->device_id = PCI_DEVICE_ID_MOTOROLA_RAVEN; - k->revision = 0x00; - k->class_id = PCI_CLASS_BRIDGE_HOST; - dc->desc = "PReP Host Bridge - Motorola Raven"; - dc->vmsd = &vmstate_raven; - /* - * Reason: PCI-facing part of the host bridge, not usable without - * the host-facing part, which can't be device_add'ed, yet. - */ - dc->user_creatable = false; -} - -static const TypeInfo raven_info = { - .name = TYPE_RAVEN_PCI_DEVICE, - .parent = TYPE_PCI_DEVICE, - .instance_size = sizeof(RavenPCIState), - .class_init = raven_class_init, - .interfaces = (InterfaceInfo[]) { - { INTERFACE_CONVENTIONAL_PCI_DEVICE }, - { }, - }, -}; - -static Property raven_pcihost_properties[] = { - DEFINE_PROP_UINT32("elf-machine", PREPPCIState, pci_dev.elf_machine, - EM_NONE), - DEFINE_PROP_STRING("bios-name", PREPPCIState, pci_dev.bios_name), - /* Temporary workaround until legacy prep machine is removed */ - DEFINE_PROP_BOOL("is-legacy-prep", PREPPCIState, is_legacy_prep, - false), - DEFINE_PROP_END_OF_LIST() -}; - -static void raven_pcihost_class_init(ObjectClass *klass, void *data) -{ - DeviceClass *dc = DEVICE_CLASS(klass); - - set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories); - dc->realize = raven_pcihost_realizefn; - device_class_set_props(dc, raven_pcihost_properties); - dc->fw_name = "pci"; -} - -static const TypeInfo raven_pcihost_info = { - .name = TYPE_RAVEN_PCI_HOST_BRIDGE, - .parent = TYPE_PCI_HOST_BRIDGE, - .instance_size = sizeof(PREPPCIState), - .instance_init = raven_pcihost_initfn, - .class_init = raven_pcihost_class_init, -}; - -static void raven_register_types(void) -{ - type_register_static(&raven_pcihost_info); - type_register_static(&raven_info); -} - -type_init(raven_register_types) diff --git a/hw/pci-host/raven.c b/hw/pci-host/raven.c new file mode 100644 index 0000000000..9fef74fc56 --- /dev/null +++ b/hw/pci-host/raven.c @@ -0,0 +1,442 @@ +/* + * QEMU PREP PCI host + * + * Copyright (c) 2006 Fabrice Bellard + * Copyright (c) 2011-2013 Andreas Färber + * + * 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 "qemu/osdep.h" +#include "qemu-common.h" +#include "qemu/datadir.h" +#include "qemu/units.h" +#include "qemu/log.h" +#include "qapi/error.h" +#include "hw/pci/pci.h" +#include "hw/pci/pci_bus.h" +#include "hw/pci/pci_host.h" +#include "hw/qdev-properties.h" +#include "migration/vmstate.h" +#include "hw/intc/i8259.h" +#include "hw/irq.h" +#include "hw/loader.h" +#include "hw/or-irq.h" +#include "elf.h" +#include "qom/object.h" + +#define TYPE_RAVEN_PCI_DEVICE "raven" +#define TYPE_RAVEN_PCI_HOST_BRIDGE "raven-pcihost" + +OBJECT_DECLARE_SIMPLE_TYPE(RavenPCIState, RAVEN_PCI_DEVICE) + +struct RavenPCIState { + PCIDevice dev; + + uint32_t elf_machine; + char *bios_name; + MemoryRegion bios; +}; + +typedef struct PRePPCIState PREPPCIState; +DECLARE_INSTANCE_CHECKER(PREPPCIState, RAVEN_PCI_HOST_BRIDGE, + TYPE_RAVEN_PCI_HOST_BRIDGE) + +struct PRePPCIState { + PCIHostState parent_obj; + + qemu_or_irq *or_irq; + qemu_irq pci_irqs[PCI_NUM_PINS]; + PCIBus pci_bus; + AddressSpace pci_io_as; + MemoryRegion pci_io; + MemoryRegion pci_io_non_contiguous; + MemoryRegion pci_memory; + MemoryRegion pci_intack; + MemoryRegion bm; + MemoryRegion bm_ram_alias; + MemoryRegion bm_pci_memory_alias; + AddressSpace bm_as; + RavenPCIState pci_dev; + + int contiguous_map; + bool is_legacy_prep; +}; + +#define BIOS_SIZE (1 * MiB) + +static inline uint32_t raven_pci_io_config(hwaddr addr) +{ + int i; + + for (i = 0; i < 11; i++) { + if ((addr & (1 << (11 + i))) != 0) { + break; + } + } + return (addr & 0x7ff) | (i << 11); +} + +static void raven_pci_io_write(void *opaque, hwaddr addr, + uint64_t val, unsigned int size) +{ + PREPPCIState *s = opaque; + PCIHostState *phb = PCI_HOST_BRIDGE(s); + pci_data_write(phb->bus, raven_pci_io_config(addr), val, size); +} + +static uint64_t raven_pci_io_read(void *opaque, hwaddr addr, + unsigned int size) +{ + PREPPCIState *s = opaque; + PCIHostState *phb = PCI_HOST_BRIDGE(s); + return pci_data_read(phb->bus, raven_pci_io_config(addr), size); +} + +static const MemoryRegionOps raven_pci_io_ops = { + .read = raven_pci_io_read, + .write = raven_pci_io_write, + .endianness = DEVICE_LITTLE_ENDIAN, +}; + +static uint64_t raven_intack_read(void *opaque, hwaddr addr, + unsigned int size) +{ + return pic_read_irq(isa_pic); +} + +static void raven_intack_write(void *opaque, hwaddr addr, + uint64_t data, unsigned size) +{ + qemu_log_mask(LOG_UNIMP, "%s not implemented\n", __func__); +} + +static const MemoryRegionOps raven_intack_ops = { + .read = raven_intack_read, + .write = raven_intack_write, + .valid = { + .max_access_size = 1, + }, +}; + +static inline hwaddr raven_io_address(PREPPCIState *s, + hwaddr addr) +{ + if (s->contiguous_map == 0) { + /* 64 KB contiguous space for IOs */ + addr &= 0xFFFF; + } else { + /* 8 MB non-contiguous space for IOs */ + addr = (addr & 0x1F) | ((addr & 0x007FFF000) >> 7); + } + + /* FIXME: handle endianness switch */ + + return addr; +} + +static uint64_t raven_io_read(void *opaque, hwaddr addr, + unsigned int size) +{ + PREPPCIState *s = opaque; + uint8_t buf[4]; + + addr = raven_io_address(s, addr); + address_space_read(&s->pci_io_as, addr + 0x80000000, + MEMTXATTRS_UNSPECIFIED, buf, size); + + if (size == 1) { + return buf[0]; + } else if (size == 2) { + return lduw_le_p(buf); + } else if (size == 4) { + return ldl_le_p(buf); + } else { + g_assert_not_reached(); + } +} + +static void raven_io_write(void *opaque, hwaddr addr, + uint64_t val, unsigned int size) +{ + PREPPCIState *s = opaque; + uint8_t buf[4]; + + addr = raven_io_address(s, addr); + + if (size == 1) { + buf[0] = val; + } else if (size == 2) { + stw_le_p(buf, val); + } else if (size == 4) { + stl_le_p(buf, val); + } else { + g_assert_not_reached(); + } + + address_space_write(&s->pci_io_as, addr + 0x80000000, + MEMTXATTRS_UNSPECIFIED, buf, size); +} + +static const MemoryRegionOps raven_io_ops = { + .read = raven_io_read, + .write = raven_io_write, + .endianness = DEVICE_LITTLE_ENDIAN, + .impl.max_access_size = 4, + .valid.unaligned = true, +}; + +static int raven_map_irq(PCIDevice *pci_dev, int irq_num) +{ + return (irq_num + (pci_dev->devfn >> 3)) & 1; +} + +static void raven_set_irq(void *opaque, int irq_num, int level) +{ + PREPPCIState *s = opaque; + + qemu_set_irq(s->pci_irqs[irq_num], level); +} + +static AddressSpace *raven_pcihost_set_iommu(PCIBus *bus, void *opaque, + int devfn) +{ + PREPPCIState *s = opaque; + + return &s->bm_as; +} + +static void raven_change_gpio(void *opaque, int n, int level) +{ + PREPPCIState *s = opaque; + + s->contiguous_map = level; +} + +static void raven_pcihost_realizefn(DeviceState *d, Error **errp) +{ + SysBusDevice *dev = SYS_BUS_DEVICE(d); + PCIHostState *h = PCI_HOST_BRIDGE(dev); + PREPPCIState *s = RAVEN_PCI_HOST_BRIDGE(dev); + MemoryRegion *address_space_mem = get_system_memory(); + int i; + + if (s->is_legacy_prep) { + for (i = 0; i < PCI_NUM_PINS; i++) { + sysbus_init_irq(dev, &s->pci_irqs[i]); + } + } else { + /* According to PReP specification section 6.1.6 "System Interrupt + * Assignments", all PCI interrupts are routed via IRQ 15 */ + s->or_irq = OR_IRQ(object_new(TYPE_OR_IRQ)); + object_property_set_int(OBJECT(s->or_irq), "num-lines", PCI_NUM_PINS, + &error_fatal); + qdev_realize(DEVICE(s->or_irq), NULL, &error_fatal); + sysbus_init_irq(dev, &s->or_irq->out_irq); + + for (i = 0; i < PCI_NUM_PINS; i++) { + s->pci_irqs[i] = qdev_get_gpio_in(DEVICE(s->or_irq), i); + } + } + + qdev_init_gpio_in(d, raven_change_gpio, 1); + + pci_bus_irqs(&s->pci_bus, raven_set_irq, raven_map_irq, s, PCI_NUM_PINS); + + memory_region_init_io(&h->conf_mem, OBJECT(h), &pci_host_conf_le_ops, s, + "pci-conf-idx", 4); + memory_region_add_subregion(&s->pci_io, 0xcf8, &h->conf_mem); + + memory_region_init_io(&h->data_mem, OBJECT(h), &pci_host_data_le_ops, s, + "pci-conf-data", 4); + memory_region_add_subregion(&s->pci_io, 0xcfc, &h->data_mem); + + memory_region_init_io(&h->mmcfg, OBJECT(s), &raven_pci_io_ops, s, + "pciio", 0x00400000); + memory_region_add_subregion(address_space_mem, 0x80800000, &h->mmcfg); + + memory_region_init_io(&s->pci_intack, OBJECT(s), &raven_intack_ops, s, + "pci-intack", 1); + memory_region_add_subregion(address_space_mem, 0xbffffff0, &s->pci_intack); + + /* TODO Remove once realize propagates to child devices. */ + qdev_realize(DEVICE(&s->pci_dev), BUS(&s->pci_bus), errp); +} + +static void raven_pcihost_initfn(Object *obj) +{ + PCIHostState *h = PCI_HOST_BRIDGE(obj); + PREPPCIState *s = RAVEN_PCI_HOST_BRIDGE(obj); + MemoryRegion *address_space_mem = get_system_memory(); + DeviceState *pci_dev; + + memory_region_init(&s->pci_io, obj, "pci-io", 0x3f800000); + memory_region_init_io(&s->pci_io_non_contiguous, obj, &raven_io_ops, s, + "pci-io-non-contiguous", 0x00800000); + memory_region_init(&s->pci_memory, obj, "pci-memory", 0x3f000000); + address_space_init(&s->pci_io_as, &s->pci_io, "raven-io"); + + /* CPU address space */ + memory_region_add_subregion(address_space_mem, 0x80000000, &s->pci_io); + memory_region_add_subregion_overlap(address_space_mem, 0x80000000, + &s->pci_io_non_contiguous, 1); + memory_region_add_subregion(address_space_mem, 0xc0000000, &s->pci_memory); + pci_root_bus_new_inplace(&s->pci_bus, sizeof(s->pci_bus), DEVICE(obj), NULL, + &s->pci_memory, &s->pci_io, 0, TYPE_PCI_BUS); + + /* Bus master address space */ + memory_region_init(&s->bm, obj, "bm-raven", 4 * GiB); + memory_region_init_alias(&s->bm_pci_memory_alias, obj, "bm-pci-memory", + &s->pci_memory, 0, + memory_region_size(&s->pci_memory)); + memory_region_init_alias(&s->bm_ram_alias, obj, "bm-system", + get_system_memory(), 0, 0x80000000); + memory_region_add_subregion(&s->bm, 0 , &s->bm_pci_memory_alias); + memory_region_add_subregion(&s->bm, 0x80000000, &s->bm_ram_alias); + address_space_init(&s->bm_as, &s->bm, "raven-bm"); + pci_setup_iommu(&s->pci_bus, raven_pcihost_set_iommu, s); + + h->bus = &s->pci_bus; + + object_initialize(&s->pci_dev, sizeof(s->pci_dev), TYPE_RAVEN_PCI_DEVICE); + pci_dev = DEVICE(&s->pci_dev); + object_property_set_int(OBJECT(&s->pci_dev), "addr", PCI_DEVFN(0, 0), + NULL); + qdev_prop_set_bit(pci_dev, "multifunction", false); +} + +static void raven_realize(PCIDevice *d, Error **errp) +{ + RavenPCIState *s = RAVEN_PCI_DEVICE(d); + char *filename; + int bios_size = -1; + + d->config[0x0C] = 0x08; // cache_line_size + d->config[0x0D] = 0x10; // latency_timer + d->config[0x34] = 0x00; // capabilities_pointer + + memory_region_init_rom_nomigrate(&s->bios, OBJECT(s), "bios", BIOS_SIZE, + &error_fatal); + memory_region_add_subregion(get_system_memory(), (uint32_t)(-BIOS_SIZE), + &s->bios); + if (s->bios_name) { + filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, s->bios_name); + if (filename) { + if (s->elf_machine != EM_NONE) { + bios_size = load_elf(filename, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, 1, s->elf_machine, + 0, 0); + } + if (bios_size < 0) { + bios_size = get_image_size(filename); + if (bios_size > 0 && bios_size <= BIOS_SIZE) { + hwaddr bios_addr; + bios_size = (bios_size + 0xfff) & ~0xfff; + bios_addr = (uint32_t)(-BIOS_SIZE); + bios_size = load_image_targphys(filename, bios_addr, + bios_size); + } + } + } + g_free(filename); + if (bios_size < 0 || bios_size > BIOS_SIZE) { + memory_region_del_subregion(get_system_memory(), &s->bios); + error_setg(errp, "Could not load bios image '%s'", s->bios_name); + return; + } + } + + vmstate_register_ram_global(&s->bios); +} + +static const VMStateDescription vmstate_raven = { + .name = "raven", + .version_id = 0, + .minimum_version_id = 0, + .fields = (VMStateField[]) { + VMSTATE_PCI_DEVICE(dev, RavenPCIState), + VMSTATE_END_OF_LIST() + }, +}; + +static void raven_class_init(ObjectClass *klass, void *data) +{ + PCIDeviceClass *k = PCI_DEVICE_CLASS(klass); + DeviceClass *dc = DEVICE_CLASS(klass); + + k->realize = raven_realize; + k->vendor_id = PCI_VENDOR_ID_MOTOROLA; + k->device_id = PCI_DEVICE_ID_MOTOROLA_RAVEN; + k->revision = 0x00; + k->class_id = PCI_CLASS_BRIDGE_HOST; + dc->desc = "PReP Host Bridge - Motorola Raven"; + dc->vmsd = &vmstate_raven; + /* + * Reason: PCI-facing part of the host bridge, not usable without + * the host-facing part, which can't be device_add'ed, yet. + */ + dc->user_creatable = false; +} + +static const TypeInfo raven_info = { + .name = TYPE_RAVEN_PCI_DEVICE, + .parent = TYPE_PCI_DEVICE, + .instance_size = sizeof(RavenPCIState), + .class_init = raven_class_init, + .interfaces = (InterfaceInfo[]) { + { INTERFACE_CONVENTIONAL_PCI_DEVICE }, + { }, + }, +}; + +static Property raven_pcihost_properties[] = { + DEFINE_PROP_UINT32("elf-machine", PREPPCIState, pci_dev.elf_machine, + EM_NONE), + DEFINE_PROP_STRING("bios-name", PREPPCIState, pci_dev.bios_name), + /* Temporary workaround until legacy prep machine is removed */ + DEFINE_PROP_BOOL("is-legacy-prep", PREPPCIState, is_legacy_prep, + false), + DEFINE_PROP_END_OF_LIST() +}; + +static void raven_pcihost_class_init(ObjectClass *klass, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(klass); + + set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories); + dc->realize = raven_pcihost_realizefn; + device_class_set_props(dc, raven_pcihost_properties); + dc->fw_name = "pci"; +} + +static const TypeInfo raven_pcihost_info = { + .name = TYPE_RAVEN_PCI_HOST_BRIDGE, + .parent = TYPE_PCI_HOST_BRIDGE, + .instance_size = sizeof(PREPPCIState), + .instance_init = raven_pcihost_initfn, + .class_init = raven_pcihost_class_init, +}; + +static void raven_register_types(void) +{ + type_register_static(&raven_pcihost_info); + type_register_static(&raven_info); +} + +type_init(raven_register_types) -- cgit v1.2.3