Skip to content

Commit

Permalink
Type-safe ioport callbacks
Browse files Browse the repository at this point in the history
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 <[email protected]>
Signed-off-by: Avi Kivity <[email protected]>
Signed-off-by: Anthony Liguori <[email protected]>
  • Loading branch information
avikivity authored and Anthony Liguori committed Nov 21, 2010
1 parent 94b0b5f commit acd1c81
Show file tree
Hide file tree
Showing 3 changed files with 96 additions and 0 deletions.
64 changes: 64 additions & 0 deletions ioport.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
{
IORange *ioport = opaque;
uint64_t data;

ioport->ops->read(ioport, addr - ioport->base, 1, &data);
return data;
}

static uint32_t ioport_readw_thunk(void *opaque, uint32_t addr)
{
IORange *ioport = opaque;
uint64_t data;

ioport->ops->read(ioport, addr - ioport->base, 2, &data);
return data;
}

static uint32_t ioport_readl_thunk(void *opaque, uint32_t addr)
{
IORange *ioport = opaque;
uint64_t data;

ioport->ops->read(ioport, addr - ioport->base, 4, &data);
return data;
}

static void ioport_writeb_thunk(void *opaque, uint32_t addr, uint32_t data)
{
IORange *ioport = opaque;

ioport->ops->write(ioport, addr - ioport->base, 1, data);
}

static void ioport_writew_thunk(void *opaque, uint32_t addr, uint32_t data)
{
IORange *ioport = opaque;

ioport->ops->write(ioport, addr - ioport->base, 2, data);
}

static void ioport_writel_thunk(void *opaque, uint32_t addr, uint32_t data)
{
IORange *ioport = opaque;

ioport->ops->write(ioport, addr - ioport->base, 4, data);
}

void ioport_register(IORange *ioport)
{
register_ioport_read(ioport->base, ioport->len, 1,
ioport_readb_thunk, ioport);
register_ioport_read(ioport->base, ioport->len, 2,
ioport_readw_thunk, ioport);
register_ioport_read(ioport->base, ioport->len, 4,
ioport_readl_thunk, ioport);
register_ioport_write(ioport->base, ioport->len, 1,
ioport_writeb_thunk, ioport);
register_ioport_write(ioport->base, ioport->len, 2,
ioport_writew_thunk, ioport);
register_ioport_write(ioport->base, ioport->len, 4,
ioport_writel_thunk, ioport);
}

void isa_unassign_ioport(pio_addr_t start, int length)
{
int i;
Expand Down
2 changes: 2 additions & 0 deletions ioport.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
#define IOPORT_H

#include "qemu-common.h"
#include "iorange.h"

typedef uint32_t pio_addr_t;
#define FMT_pioaddr PRIx32
Expand All @@ -36,6 +37,7 @@ 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);

void ioport_register(IORange *iorange);
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,
Expand Down
30 changes: 30 additions & 0 deletions iorange.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
#ifndef IORANGE_H
#define IORANGE_H

#include <stdint.h>

typedef struct IORange IORange;
typedef struct IORangeOps IORangeOps;

struct IORangeOps {
void (*read)(IORange *iorange, uint64_t offset, unsigned width,
uint64_t *data);
void (*write)(IORange *iorange, uint64_t offset, unsigned width,
uint64_t data);
};

struct IORange {
const IORangeOps *ops;
uint64_t base;
uint64_t len;
};

static inline void iorange_init(IORange *iorange, const IORangeOps *ops,
uint64_t base, uint64_t len)
{
iorange->ops = ops;
iorange->base = base;
iorange->len = len;
}

#endif

0 comments on commit acd1c81

Please sign in to comment.