From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from eggs.gnu.org ([140.186.70.92]:59250) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1QUHND-0008FB-4p for qemu-devel@nongnu.org; Wed, 08 Jun 2011 07:56:36 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1QUHNB-0002Z9-5T for qemu-devel@nongnu.org; Wed, 08 Jun 2011 07:56:34 -0400 Received: from mnementh.archaic.org.uk ([81.2.115.146]:41608) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1QUHNA-0002Yo-Gh for qemu-devel@nongnu.org; Wed, 08 Jun 2011 07:56:32 -0400 From: Peter Maydell Date: Wed, 8 Jun 2011 12:33:32 +0100 Message-Id: <1307532813-27175-3-git-send-email-peter.maydell@linaro.org> In-Reply-To: <1307532813-27175-1-git-send-email-peter.maydell@linaro.org> References: <1307532813-27175-1-git-send-email-peter.maydell@linaro.org> Subject: [Qemu-devel] [PATCH RFC 2/3] sysbus: Allow sysbus MMIO passthrough List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: qemu-devel@nongnu.org Cc: Markus Armbruster , Anthony Liguori , =?UTF-8?q?Juha=20Riihim=C3=A4ki?= , Paul Brook , patches@linaro.org Add new function sysbus_pass_mmio() to allow a sysbus device to delegate MMIO to another sysbus device. This allows a limited form of composition for sysbus devices. Signed-off-by: Peter Maydell --- hw/sysbus.c | 26 ++++++++++++++++++++++++++ hw/sysbus.h | 3 +++ 2 files changed, 29 insertions(+), 0 deletions(-) diff --git a/hw/sysbus.c b/hw/sysbus.c index 01ebe47..793b0c1 100644 --- a/hw/sysbus.c +++ b/hw/sysbus.c @@ -43,6 +43,10 @@ void sysbus_mmio_unmap(SysBusDevice *dev, int n) { assert(n >= 0 && n < dev->num_mmio); + if (dev->mmio[n].delegate) { + sysbus_mmio_unmap(dev->mmio[n].delegate, dev->mmio[n].delegate_mmio); + return; + } if (dev->mmio[n].addr == (target_phys_addr_t)-1) { /* region already unmapped */ return; @@ -60,6 +64,11 @@ void sysbus_mmio_map(SysBusDevice *dev, int n, target_phys_addr_t addr) { assert(n >= 0 && n < dev->num_mmio); + if (dev->mmio[n].delegate) { + sysbus_mmio_map(dev->mmio[n].delegate, dev->mmio[n].delegate_mmio, + addr); + return; + } if (dev->mmio[n].addr == addr) { /* ??? region already mapped here. */ return; @@ -83,6 +92,11 @@ 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 (dev->mmio[n].delegate) { + sysbus_mmio_resize(dev->mmio[n].delegate, dev->mmio[n].delegate_mmio, + newsize); + return; + } if (newsize != dev->mmio[n].size) { addr = dev->mmio[n].addr; if (addr != (target_phys_addr_t)-1) { @@ -127,6 +141,7 @@ void sysbus_init_mmio(SysBusDevice *dev, target_phys_addr_t size, assert(dev->num_mmio < QDEV_MAX_MMIO); n = dev->num_mmio++; + dev->mmio[n].delegate = 0; dev->mmio[n].addr = -1; dev->mmio[n].size = size; dev->mmio[n].iofunc = iofunc; @@ -139,11 +154,22 @@ void sysbus_init_mmio_cb(SysBusDevice *dev, target_phys_addr_t size, assert(dev->num_mmio < QDEV_MAX_MMIO); n = dev->num_mmio++; + dev->mmio[n].delegate = 0; dev->mmio[n].addr = -1; dev->mmio[n].size = size; dev->mmio[n].cb = cb; } +void sysbus_pass_mmio(SysBusDevice *dev, SysBusDevice *target, int target_mmio) +{ + int n; + + assert(dev->num_mmio < QDEV_MAX_MMIO); + n = dev->num_mmio++; + dev->mmio[n].delegate = target; + dev->mmio[n].delegate_mmio = target_mmio; +} + void sysbus_init_ioports(SysBusDevice *dev, pio_addr_t ioport, pio_addr_t size) { pio_addr_t i; diff --git a/hw/sysbus.h b/hw/sysbus.h index 70e2488..789e4c5 100644 --- a/hw/sysbus.h +++ b/hw/sysbus.h @@ -19,6 +19,8 @@ struct SysBusDevice { qemu_irq *irqp[QDEV_MAX_IRQ]; int num_mmio; struct { + SysBusDevice *delegate; + int delegate_mmio; target_phys_addr_t addr; target_phys_addr_t size; mmio_mapfunc cb; @@ -46,6 +48,7 @@ void sysbus_init_mmio(SysBusDevice *dev, target_phys_addr_t size, ram_addr_t iofunc); void sysbus_init_mmio_cb(SysBusDevice *dev, target_phys_addr_t size, mmio_mapfunc cb); +void sysbus_pass_mmio(SysBusDevice *dev, SysBusDevice *target, int target_mmio); void sysbus_init_irq(SysBusDevice *dev, qemu_irq *p); void sysbus_pass_irq(SysBusDevice *dev, SysBusDevice *target); void sysbus_init_ioports(SysBusDevice *dev, pio_addr_t ioport, pio_addr_t size); -- 1.7.1