* splitted out ioport related stuffs from vl.c.
*/
-#include "ioport.h"
+#include "exec/ioport.h"
#include "trace.h"
-#include "memory.h"
+#include "exec/memory.h"
/***********************************************************/
/* IO Port */
static void *ioport_opaque[MAX_IOPORTS];
static IOPortReadFunc *ioport_read_table[3][MAX_IOPORTS];
static IOPortWriteFunc *ioport_write_table[3][MAX_IOPORTS];
+static IOPortDestructor *ioport_destructor_table[MAX_IOPORTS];
static IOPortReadFunc default_ioport_readb, default_ioport_readw, default_ioport_readl;
static IOPortWriteFunc default_ioport_writeb, default_ioport_writew, default_ioport_writel;
ioport->ops->write(ioport, addr - ioport->base, 4, data);
}
+static void iorange_destructor_thunk(void *opaque)
+{
+ IORange *iorange = opaque;
+
+ if (iorange->ops->destructor) {
+ iorange->ops->destructor(iorange);
+ }
+}
+
void ioport_register(IORange *ioport)
{
register_ioport_read(ioport->base, ioport->len, 1,
ioport_writew_thunk, ioport);
register_ioport_write(ioport->base, ioport->len, 4,
ioport_writel_thunk, ioport);
+ ioport_destructor_table[ioport->base] = iorange_destructor_thunk;
}
void isa_unassign_ioport(pio_addr_t start, int length)
{
int i;
+ if (ioport_destructor_table[start]) {
+ ioport_destructor_table[start](ioport_opaque[start]);
+ ioport_destructor_table[start] = NULL;
+ }
for(i = start; i < start + length; i++) {
ioport_read_table[0][i] = NULL;
ioport_read_table[1][i] = NULL;
piolist->ports = callbacks;
piolist->nr = 0;
piolist->regions = g_new0(MemoryRegion *, n);
+ piolist->aliases = g_new0(MemoryRegion *, n);
piolist->address_space = NULL;
piolist->opaque = opaque;
piolist->name = name;
void portio_list_destroy(PortioList *piolist)
{
g_free(piolist->regions);
+ g_free(piolist->aliases);
}
static void portio_list_add_1(PortioList *piolist,
{
MemoryRegionPortio *pio;
MemoryRegionOps *ops;
- MemoryRegion *region;
+ MemoryRegion *region, *alias;
unsigned i;
/* Copy the sub-list and null-terminate it. */
ops->old_portio = pio;
region = g_new(MemoryRegion, 1);
+ alias = g_new(MemoryRegion, 1);
+ /*
+ * Use an alias so that the callback is called with an absolute address,
+ * rather than an offset relative to to start + off_low.
+ */
memory_region_init_io(region, ops, piolist->opaque, piolist->name,
- off_high - off_low);
- memory_region_set_offset(region, start + off_low);
+ INT64_MAX);
+ memory_region_init_alias(alias, piolist->name,
+ region, start + off_low, off_high - off_low);
memory_region_add_subregion(piolist->address_space,
- start + off_low, region);
- piolist->regions[piolist->nr++] = region;
+ start + off_low, alias);
+ piolist->regions[piolist->nr] = region;
+ piolist->aliases[piolist->nr] = alias;
+ ++piolist->nr;
}
void portio_list_add(PortioList *piolist,
void portio_list_del(PortioList *piolist)
{
- MemoryRegion *mr;
+ MemoryRegion *mr, *alias;
unsigned i;
for (i = 0; i < piolist->nr; ++i) {
mr = piolist->regions[i];
- memory_region_del_subregion(piolist->address_space, mr);
+ alias = piolist->aliases[i];
+ memory_region_del_subregion(piolist->address_space, alias);
+ memory_region_destroy(alias);
memory_region_destroy(mr);
g_free((MemoryRegionOps *)mr->ops);
g_free(mr);
+ g_free(alias);
piolist->regions[i] = NULL;
+ piolist->aliases[i] = NULL;
}
}