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. Signed-off-by: Avi Kivity <a...@redhat.com> --- ioport.c | 64 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ioport.h | 16 +++++++++++++++ 2 files changed, 80 insertions(+), 0 deletions(-) diff --git a/ioport.c b/ioport.c index ec3dc65..47eafc3 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; + + return ioport->ops->writeb(ioport, addr, data); +} + +static void ioport_writew_thunk(void *opaque, uint32_t addr, uint32_t data) +{ + IOPort *ioport = opaque; + + return ioport->ops->writew(ioport, addr, data); +} + +static void ioport_writel_thunk(void *opaque, uint32_t addr, uint32_t data) +{ + IOPort *ioport = opaque; + + return 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..8036e59 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 { + 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