@@ -39,6 +39,23 @@ void sysbus_connect_irq(SysBusDevice *dev, int n, qemu_irq irq)
}
}
+void sysbus_mmio_unmap(SysBusDevice *dev, int n)
+{
+ assert(n >= 0 && n < dev->num_mmio);
+
+ if (dev->mmio[n].addr == (target_phys_addr_t)-1) {
+ /* region already unmapped */
+ return;
+ }
+ if (dev->mmio[n].cb) {
+ dev->mmio[n].cb(dev, (target_phys_addr_t)-1);
+ } else {
+ cpu_register_physical_memory(dev->mmio[n].addr, dev->mmio[n].size,
+ IO_MEM_UNASSIGNED);
+ }
+ dev->mmio[n].addr = (target_phys_addr_t)-1;
+}
+
void sysbus_mmio_map(SysBusDevice *dev, int n, target_phys_addr_t addr)
{
assert(n >= 0 && n < dev->num_mmio);
@@ -61,6 +78,26 @@ void sysbus_mmio_map(SysBusDevice *dev, int n, target_phys_addr_t addr)
}
}
+void sysbus_mmio_resize(SysBusDevice *dev, int n, target_phys_addr_t newsize)
+{
+ target_phys_addr_t addr;
+ assert(n >= 0 && n < dev->num_mmio);
+
+ if (newsize != dev->mmio[n].size) {
+ addr = dev->mmio[n].addr;
+ if (addr != (target_phys_addr_t)-1) {
+ /* The expected use case is that resizes will only happen
+ * on unmapped regions, but we handle the already-mapped
+ * case by temporarily unmapping and remapping.
+ */
+ sysbus_mmio_unmap(dev, n);
+ }
+ dev->mmio[n].size = newsize;
+ if (addr != (target_phys_addr_t)-1) {
+ sysbus_mmio_map(dev, n, addr);
+ }
+ }
+}
/* Request an IRQ source. The actual IRQ object may be populated later. */
void sysbus_init_irq(SysBusDevice *dev, qemu_irq *p)
@@ -53,6 +53,8 @@ void sysbus_init_ioports(SysBusDevice *dev, pio_addr_t ioport, pio_addr_t size);
void sysbus_connect_irq(SysBusDevice *dev, int n, qemu_irq irq);
void sysbus_mmio_map(SysBusDevice *dev, int n, target_phys_addr_t addr);
+void sysbus_mmio_unmap(SysBusDevice *dev, int n);
+void sysbus_mmio_resize(SysBusDevice *dev, int n, target_phys_addr_t newsize);
/* Legacy helper function for creating devices. */
DeviceState *sysbus_create_varargs(const char *name,