X-Git-Url: https://git.proxmox.com/?a=blobdiff_plain;f=hw%2Fsysbus.c;h=702fc728f4ca32285af2b2f8b338a95487faed87;hb=6e72a00f909dcd093fbdd1faa2b3c8caa1697a6c;hp=4fab5a41b25e72adee7315107e617ebb1d4d8486;hpb=d8ac46d950451a722fd6b1d5d0768c72bee87d47;p=qemu.git diff --git a/hw/sysbus.c b/hw/sysbus.c index 4fab5a41b..702fc728f 100644 --- a/hw/sysbus.c +++ b/hw/sysbus.c @@ -17,18 +17,26 @@ * License along with this library; if not, see . */ -#include "sysbus.h" -#include "monitor.h" -#include "exec-memory.h" +#include "hw/sysbus.h" +#include "monitor/monitor.h" +#include "exec/address-spaces.h" static void sysbus_dev_print(Monitor *mon, DeviceState *dev, int indent); static char *sysbus_get_fw_dev_path(DeviceState *dev); -struct BusInfo system_bus_info = { - .name = "System", - .size = sizeof(BusState), - .print_dev = sysbus_dev_print, - .get_fw_dev_path = sysbus_get_fw_dev_path, +static void system_bus_class_init(ObjectClass *klass, void *data) +{ + BusClass *k = BUS_CLASS(klass); + + k->print_dev = sysbus_dev_print; + k->get_fw_dev_path = sysbus_get_fw_dev_path; +} + +static const TypeInfo system_bus_info = { + .name = TYPE_SYSTEM_BUS, + .parent = TYPE_BUS, + .instance_size = sizeof(BusState), + .class_init = system_bus_class_init, }; void sysbus_connect_irq(SysBusDevice *dev, int n, qemu_irq irq) @@ -40,7 +48,8 @@ void sysbus_connect_irq(SysBusDevice *dev, int n, qemu_irq irq) } } -void sysbus_mmio_map(SysBusDevice *dev, int n, target_phys_addr_t addr) +static void sysbus_mmio_map_common(SysBusDevice *dev, int n, hwaddr addr, + bool may_overlap, unsigned priority) { assert(n >= 0 && n < dev->num_mmio); @@ -48,31 +57,34 @@ void sysbus_mmio_map(SysBusDevice *dev, int n, target_phys_addr_t addr) /* ??? region already mapped here. */ return; } - if (dev->mmio[n].addr != (target_phys_addr_t)-1) { + if (dev->mmio[n].addr != (hwaddr)-1) { /* Unregister previous mapping. */ - if (dev->mmio[n].memory) { - memory_region_del_subregion(get_system_memory(), - dev->mmio[n].memory); - } else if (dev->mmio[n].unmap) { - dev->mmio[n].unmap(dev, dev->mmio[n].addr); - } else { - cpu_register_physical_memory(dev->mmio[n].addr, dev->mmio[n].size, - IO_MEM_UNASSIGNED); - } + memory_region_del_subregion(get_system_memory(), dev->mmio[n].memory); } dev->mmio[n].addr = addr; - if (dev->mmio[n].memory) { + if (may_overlap) { + memory_region_add_subregion_overlap(get_system_memory(), + addr, + dev->mmio[n].memory, + priority); + } + else { memory_region_add_subregion(get_system_memory(), addr, dev->mmio[n].memory); - } else if (dev->mmio[n].cb) { - dev->mmio[n].cb(dev, addr); - } else { - cpu_register_physical_memory(addr, dev->mmio[n].size, - dev->mmio[n].iofunc); } } +void sysbus_mmio_map(SysBusDevice *dev, int n, hwaddr addr) +{ + sysbus_mmio_map_common(dev, n, addr, false, 0); +} + +void sysbus_mmio_map_overlap(SysBusDevice *dev, int n, hwaddr addr, + unsigned priority) +{ + sysbus_mmio_map_common(dev, n, addr, true, priority); +} /* Request an IRQ source. The actual IRQ object may be populated later. */ void sysbus_init_irq(SysBusDevice *dev, qemu_irq *p) @@ -95,39 +107,13 @@ void sysbus_pass_irq(SysBusDevice *dev, SysBusDevice *target) } } -void sysbus_init_mmio(SysBusDevice *dev, target_phys_addr_t size, - ram_addr_t iofunc) -{ - int n; - - assert(dev->num_mmio < QDEV_MAX_MMIO); - n = dev->num_mmio++; - dev->mmio[n].addr = -1; - dev->mmio[n].size = size; - dev->mmio[n].iofunc = iofunc; -} - -void sysbus_init_mmio_cb2(SysBusDevice *dev, - mmio_mapfunc cb, mmio_mapfunc unmap) -{ - int n; - - assert(dev->num_mmio < QDEV_MAX_MMIO); - n = dev->num_mmio++; - dev->mmio[n].addr = -1; - dev->mmio[n].size = 0; - dev->mmio[n].cb = cb; - dev->mmio[n].unmap = unmap; -} - -void sysbus_init_mmio_region(SysBusDevice *dev, MemoryRegion *memory) +void sysbus_init_mmio(SysBusDevice *dev, MemoryRegion *memory) { int n; assert(dev->num_mmio < QDEV_MAX_MMIO); n = dev->num_mmio++; dev->mmio[n].addr = -1; - dev->mmio[n].size = memory_region_size(memory); dev->mmio[n].memory = memory; } @@ -146,35 +132,16 @@ void sysbus_init_ioports(SysBusDevice *dev, pio_addr_t ioport, pio_addr_t size) } } -static int sysbus_device_init(DeviceState *dev, DeviceInfo *base) +static int sysbus_device_init(DeviceState *dev) { - SysBusDeviceInfo *info = container_of(base, SysBusDeviceInfo, qdev); + SysBusDevice *sd = SYS_BUS_DEVICE(dev); + SysBusDeviceClass *sbc = SYS_BUS_DEVICE_GET_CLASS(sd); - return info->init(sysbus_from_qdev(dev)); -} - -void sysbus_register_withprop(SysBusDeviceInfo *info) -{ - info->qdev.init = sysbus_device_init; - info->qdev.bus_info = &system_bus_info; - - assert(info->qdev.size >= sizeof(SysBusDevice)); - qdev_register(&info->qdev); -} - -void sysbus_register_dev(const char *name, size_t size, sysbus_initfn init) -{ - SysBusDeviceInfo *info; - - info = g_malloc0(sizeof(*info)); - info->qdev.name = g_strdup(name); - info->qdev.size = size; - info->init = init; - sysbus_register_withprop(info); + return sbc->init(sd); } DeviceState *sysbus_create_varargs(const char *name, - target_phys_addr_t addr, ...) + hwaddr addr, ...) { DeviceState *dev; SysBusDevice *s; @@ -183,9 +150,9 @@ DeviceState *sysbus_create_varargs(const char *name, int n; dev = qdev_create(NULL, name); - s = sysbus_from_qdev(dev); + s = SYS_BUS_DEVICE(dev); qdev_init_nofail(dev); - if (addr != (target_phys_addr_t)-1) { + if (addr != (hwaddr)-1) { sysbus_mmio_map(s, 0, addr); } va_start(va, addr); @@ -198,11 +165,12 @@ DeviceState *sysbus_create_varargs(const char *name, sysbus_connect_irq(s, n, irq); n++; } + va_end(va); return dev; } DeviceState *sysbus_try_create_varargs(const char *name, - target_phys_addr_t addr, ...) + hwaddr addr, ...) { DeviceState *dev; SysBusDevice *s; @@ -214,9 +182,9 @@ DeviceState *sysbus_try_create_varargs(const char *name, if (!dev) { return NULL; } - s = sysbus_from_qdev(dev); + s = SYS_BUS_DEVICE(dev); qdev_init_nofail(dev); - if (addr != (target_phys_addr_t)-1) { + if (addr != (hwaddr)-1) { sysbus_mmio_map(s, 0, addr); } va_start(va, addr); @@ -229,24 +197,27 @@ DeviceState *sysbus_try_create_varargs(const char *name, sysbus_connect_irq(s, n, irq); n++; } + va_end(va); return dev; } static void sysbus_dev_print(Monitor *mon, DeviceState *dev, int indent) { - SysBusDevice *s = sysbus_from_qdev(dev); + SysBusDevice *s = SYS_BUS_DEVICE(dev); + hwaddr size; int i; monitor_printf(mon, "%*sirq %d\n", indent, "", s->num_irq); for (i = 0; i < s->num_mmio; i++) { + size = memory_region_size(s->mmio[i].memory); monitor_printf(mon, "%*smmio " TARGET_FMT_plx "/" TARGET_FMT_plx "\n", - indent, "", s->mmio[i].addr, s->mmio[i].size); + indent, "", s->mmio[i].addr, size); } } static char *sysbus_get_fw_dev_path(DeviceState *dev) { - SysBusDevice *s = sysbus_from_qdev(dev); + SysBusDevice *s = SYS_BUS_DEVICE(dev); char path[40]; int off; @@ -259,16 +230,16 @@ static char *sysbus_get_fw_dev_path(DeviceState *dev) snprintf(path + off, sizeof(path) - off, "@i%04x", s->pio[0]); } - return strdup(path); + return g_strdup(path); } -void sysbus_add_memory(SysBusDevice *dev, target_phys_addr_t addr, +void sysbus_add_memory(SysBusDevice *dev, hwaddr addr, MemoryRegion *mem) { memory_region_add_subregion(get_system_memory(), addr, mem); } -void sysbus_add_memory_overlap(SysBusDevice *dev, target_phys_addr_t addr, +void sysbus_add_memory_overlap(SysBusDevice *dev, hwaddr addr, MemoryRegion *mem, unsigned priority) { memory_region_add_subregion_overlap(get_system_memory(), addr, mem, @@ -280,7 +251,7 @@ void sysbus_del_memory(SysBusDevice *dev, MemoryRegion *mem) memory_region_del_subregion(get_system_memory(), mem); } -void sysbus_add_io(SysBusDevice *dev, target_phys_addr_t addr, +void sysbus_add_io(SysBusDevice *dev, hwaddr addr, MemoryRegion *mem) { memory_region_add_subregion(get_system_io(), addr, mem); @@ -290,3 +261,56 @@ void sysbus_del_io(SysBusDevice *dev, MemoryRegion *mem) { memory_region_del_subregion(get_system_io(), mem); } + +MemoryRegion *sysbus_address_space(SysBusDevice *dev) +{ + return get_system_memory(); +} + +static void sysbus_device_class_init(ObjectClass *klass, void *data) +{ + DeviceClass *k = DEVICE_CLASS(klass); + k->init = sysbus_device_init; + k->bus_type = TYPE_SYSTEM_BUS; +} + +static const TypeInfo sysbus_device_type_info = { + .name = TYPE_SYS_BUS_DEVICE, + .parent = TYPE_DEVICE, + .instance_size = sizeof(SysBusDevice), + .abstract = true, + .class_size = sizeof(SysBusDeviceClass), + .class_init = sysbus_device_class_init, +}; + +/* This is a nasty hack to allow passing a NULL bus to qdev_create. */ +static BusState *main_system_bus; + +static void main_system_bus_create(void) +{ + /* assign main_system_bus before qbus_create_inplace() + * in order to make "if (bus != sysbus_get_default())" work */ + main_system_bus = g_malloc0(system_bus_info.instance_size); + qbus_create_inplace(main_system_bus, TYPE_SYSTEM_BUS, NULL, + "main-system-bus"); + OBJECT(main_system_bus)->free = g_free; + object_property_add_child(container_get(qdev_get_machine(), + "/unattached"), + "sysbus", OBJECT(main_system_bus), NULL); +} + +BusState *sysbus_get_default(void) +{ + if (!main_system_bus) { + main_system_bus_create(); + } + return main_system_bus; +} + +static void sysbus_register_types(void) +{ + type_register_static(&system_bus_info); + type_register_static(&sysbus_device_type_info); +} + +type_init(sysbus_register_types)