@@ -3668,9 +3668,13 @@ static void io_commit(MemoryListener *listener)
static void io_region_add(MemoryListener *listener,
MemoryRegionSection *section)
{
- iorange_init(§ion->mr->iorange, &memory_region_iorange_ops,
+ MemoryRegionIORange *mrio = g_new(MemoryRegionIORange, 1);
+
+ mrio->mr = section->mr;
+ mrio->offset = section->offset_within_region;
+ iorange_init(&mrio->iorange, &memory_region_iorange_ops,
section->offset_within_address_space, section->size);
- ioport_register(§ion->mr->iorange);
+ ioport_register(&mrio->iorange);
}
static void io_region_del(MemoryListener *listener,
@@ -52,6 +52,7 @@
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;
@@ -225,6 +226,15 @@ static void ioport_writel_thunk(void *opaque,
uint32_t addr, uint32_t data)
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,
@@ -239,12 +249,17 @@ void ioport_register(IORange *ioport)
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;
@@ -36,6 +36,7 @@ typedef uint32_t pio_addr_t;
/* These should really be in isa.h, but are here to make pc.h happy. */
typedef void (IOPortWriteFunc)(void *opaque, uint32_t address, uint32_t
data);
typedef uint32_t (IOPortReadFunc)(void *opaque, uint32_t address);
+typedef void (IOPortDestructor)(void *opaque);
void ioport_register(IORange *iorange);
int register_ioport_read(pio_addr_t start, int length, int size,
@@ -11,6 +11,7 @@ struct IORangeOps {
uint64_t *data);
void (*write)(IORange *iorange, uint64_t offset, unsigned width,
uint64_t data);
+ void (*destructor)(IORange *iorange);
};
struct IORange {
@@ -382,16 +382,20 @@ static void memory_region_iorange_read(IORange
*iorange,
unsigned width,
uint64_t *data)
{
- MemoryRegion *mr = container_of(iorange, MemoryRegion, iorange);
+ MemoryRegionIORange *mrio
+ = container_of(iorange, MemoryRegionIORange, iorange);
+ MemoryRegion *mr = mrio->mr;
+ offset += mrio->offset;
if (mr->ops->old_portio) {
- const MemoryRegionPortio *mrp = find_portio(mr, offset, width,
false);
+ const MemoryRegionPortio *mrp = find_portio(mr, offset -
mrio->offset,
+ width, false);
*data = ((uint64_t)1 << (width * 8)) - 1;
if (mrp) {
*data = mrp->read(mr->opaque, offset);
} else if (width == 2) {
- mrp = find_portio(mr, offset, 1, false);
+ mrp = find_portio(mr, offset - mrio->offset, 1, false);
assert(mrp);
*data = mrp->read(mr->opaque, offset) |
(mrp->read(mr->opaque, offset + 1) << 8);
@@ -410,15 +414,19 @@ static void memory_region_iorange_write(IORange
*iorange,
unsigned width,
uint64_t data)
{
- MemoryRegion *mr = container_of(iorange, MemoryRegion, iorange);
+ MemoryRegionIORange *mrio
+ = container_of(iorange, MemoryRegionIORange, iorange);
+ MemoryRegion *mr = mrio->mr;
+ offset += mrio->offset;
if (mr->ops->old_portio) {
- const MemoryRegionPortio *mrp = find_portio(mr, offset, width,
true);
+ const MemoryRegionPortio *mrp = find_portio(mr, offset -
mrio->offset,
+ width, true);
if (mrp) {
mrp->write(mr->opaque, offset, data);
} else if (width == 2) {
- mrp = find_portio(mr, offset, 1, false);
+ mrp = find_portio(mr, offset - mrio->offset, 1, false);
assert(mrp);
mrp->write(mr->opaque, offset, data & 0xff);
mrp->write(mr->opaque, offset + 1, data >> 8);
@@ -431,9 +439,15 @@ static void memory_region_iorange_write(IORange
*iorange,
memory_region_write_accessor, mr);
}
+static void memory_region_iorange_destructor(IORange *iorange)
+{
+ g_free(container_of(iorange, MemoryRegionIORange, iorange));
+}
+
const IORangeOps memory_region_iorange_ops = {
.read = memory_region_iorange_read,
.write = memory_region_iorange_write,
+ .destructor = memory_region_iorange_destructor,
};
static AddressSpace address_space_io;
@@ -43,6 +43,14 @@ struct MemoryRegionMmio {
CPUWriteMemoryFunc *write[3];
};
+/* Internal use; thunks between old-style IORange and MemoryRegions. */
+typedef struct MemoryRegionIORange MemoryRegionIORange;
+struct MemoryRegionIORange {
+ IORange iorange;
+ MemoryRegion *mr;
+ target_phys_addr_t offset;
+};
+
/*
* Memory region callbacks
*/
@@ -117,7 +125,6 @@ struct MemoryRegion {
target_phys_addr_t addr;
void (*destructor)(MemoryRegion *mr);
ram_addr_t ram_addr;
- IORange iorange;
bool subpage;
bool terminates;
bool readable;