From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from [140.186.70.92] (port=47627 helo=eggs.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1PAPCy-0000Lb-SY for qemu-devel@nongnu.org; Mon, 25 Oct 2010 11:43:38 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1PAPCx-0005xn-8z for qemu-devel@nongnu.org; Mon, 25 Oct 2010 11:43:36 -0400 Received: from mx1.redhat.com ([209.132.183.28]:17368) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1PAPCx-0005xU-1O for qemu-devel@nongnu.org; Mon, 25 Oct 2010 11:43:35 -0400 From: Avi Kivity Date: Mon, 25 Oct 2010 17:43:29 +0200 Message-Id: <1288021410-10372-2-git-send-email-avi@redhat.com> In-Reply-To: <1288021410-10372-1-git-send-email-avi@redhat.com> References: <1288021410-10372-1-git-send-email-avi@redhat.com> Subject: [Qemu-devel] [PATCH v2 1/2] Type-safe ioport callbacks List-Id: qemu-devel.nongnu.org List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: Anthony Liguori , qemu-devel@nongnu.org Cc: kvm@vger.kernel.org The current ioport callbacks are not type-safe, in that they accept an "opaque" pointer as an argument whose type must match the argument to the registration function; this is not checked by the compiler. This patch adds an alternative that is type-safe. Instead of an opaque argument, both registation and the callback use a new IOPort type. The callback then uses container_of() to access its main structures. Currently the old and new methods exist side by side; once the old way is gone, we can also save a bunch of memory since the new method requires one pointer per ioport instead of 6. Acked-by: Anthony Liguori Signed-off-by: Avi Kivity --- ioport.c | 64 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ioport.h | 16 +++++++++++++++ 2 files changed, 80 insertions(+), 0 deletions(-) diff --git a/ioport.c b/ioport.c index ec3dc65..b9e74b8 100644 --- a/ioport.c +++ b/ioport.c @@ -174,6 +174,70 @@ int register_ioport_write(pio_addr_t start, int length, int size, return 0; } +static uint32_t ioport_readb_thunk(void *opaque, uint32_t addr) +{ + IOPort *ioport = opaque; + + return ioport->ops->readb(ioport, addr); +} + +static uint32_t ioport_readw_thunk(void *opaque, uint32_t addr) +{ + IOPort *ioport = opaque; + + return ioport->ops->readw(ioport, addr); +} + +static uint32_t ioport_readl_thunk(void *opaque, uint32_t addr) +{ + IOPort *ioport = opaque; + + return ioport->ops->readl(ioport, addr); +} + +static void ioport_writeb_thunk(void *opaque, uint32_t addr, uint32_t data) +{ + IOPort *ioport = opaque; + + ioport->ops->writeb(ioport, addr, data); +} + +static void ioport_writew_thunk(void *opaque, uint32_t addr, uint32_t data) +{ + IOPort *ioport = opaque; + + ioport->ops->writew(ioport, addr, data); +} + +static void ioport_writel_thunk(void *opaque, uint32_t addr, uint32_t data) +{ + IOPort *ioport = opaque; + + ioport->ops->writel(ioport, addr, data); +} + +void ioport_register(IOPort *ioport, pio_addr_t start, pio_addr_t length) +{ + if (ioport->ops->readb) { + register_ioport_read(start, length, 1, ioport_readb_thunk, ioport); + } + if (ioport->ops->readw) { + register_ioport_read(start, length, 2, ioport_readw_thunk, ioport); + } + if (ioport->ops->readl) { + register_ioport_read(start, length, 4, ioport_readl_thunk, ioport); + } + if (ioport->ops->writeb) { + register_ioport_write(start, length, 1, ioport_writeb_thunk, ioport); + } + if (ioport->ops->writew) { + register_ioport_write(start, length, 2, ioport_writew_thunk, ioport); + } + if (ioport->ops->writel) { + register_ioport_write(start, length, 4, ioport_writel_thunk, ioport); + } +} + void isa_unassign_ioport(pio_addr_t start, int length) { int i; diff --git a/ioport.h b/ioport.h index 3d3c8a3..6a7742b 100644 --- a/ioport.h +++ b/ioport.h @@ -36,6 +36,22 @@ typedef uint32_t pio_addr_t; typedef void (IOPortWriteFunc)(void *opaque, uint32_t address, uint32_t data); typedef uint32_t (IOPortReadFunc)(void *opaque, uint32_t address); +struct IOPort; + +typedef struct IOPortOps { + uint32_t (*readb)(struct IOPort *ioport, pio_addr_t addr); + uint32_t (*readw)(struct IOPort *ioport, pio_addr_t addr); + uint32_t (*readl)(struct IOPort *ioport, pio_addr_t addr); + void (*writeb)(struct IOPort *ioport, pio_addr_t addr, uint32_t data); + void (*writew)(struct IOPort *ioport, pio_addr_t addr, uint32_t data); + void (*writel)(struct IOPort *ioport, pio_addr_t addr, uint32_t data); +} IOPortOps; + +typedef struct IOPort { + const IOPortOps *ops; +} IOPort; + +void ioport_register(IOPort *ioport, pio_addr_t start, pio_addr_t length); int register_ioport_read(pio_addr_t start, int length, int size, IOPortReadFunc *func, void *opaque); int register_ioport_write(pio_addr_t start, int length, int size, -- 1.7.3.1