From: "Hervé Poussineau" <hpoussin@reactos.org>
To: qemu-devel@nongnu.org
Cc: "Paolo Bonzini" <pbonzini@redhat.com>,
"Hervé Poussineau" <hpoussin@reactos.org>
Subject: [Qemu-devel] [PATCH v2 3/8] ioport: register memory regions for I/O port lists
Date: Sun, 9 Jun 2013 01:44:01 +0800 [thread overview]
Message-ID: <1370713446-9460-4-git-send-email-hpoussin@reactos.org> (raw)
In-Reply-To: <1370713446-9460-1-git-send-email-hpoussin@reactos.org>
As I/O ports are now memory regions, they can be seen in 'info qtree'.
This also removes the last use of MemoryRegionOps.old_portio field.
Some of the code has been extracted from memory.c
Signed-off-by: Hervé Poussineau <hpoussin@reactos.org>
---
include/exec/ioport.h | 3 +-
ioport.c | 132 +++++++++++++++++++++++++++++++++++++++----------
2 files changed, 107 insertions(+), 28 deletions(-)
diff --git a/include/exec/ioport.h b/include/exec/ioport.h
index fc28350..398fe14 100644
--- a/include/exec/ioport.h
+++ b/include/exec/ioport.h
@@ -55,13 +55,14 @@ uint32_t cpu_inl(pio_addr_t addr);
struct MemoryRegion;
struct MemoryRegionPortio;
+struct PortioListState;
typedef struct PortioList {
const struct MemoryRegionPortio *ports;
struct MemoryRegion *address_space;
unsigned nr;
struct MemoryRegion **regions;
- struct MemoryRegion **aliases;
+ struct PortioListState **states;
void *opaque;
const char *name;
} PortioList;
diff --git a/ioport.c b/ioport.c
index a0ac2a0..d26d3e1 100644
--- a/ioport.c
+++ b/ioport.c
@@ -28,6 +28,7 @@
#include "exec/ioport.h"
#include "trace.h"
#include "exec/memory.h"
+#include "qemu/host-utils.h"
/***********************************************************/
/* IO Port */
@@ -330,6 +331,12 @@ uint32_t cpu_inl(pio_addr_t addr)
return val;
}
+typedef struct PortioListState {
+ const MemoryRegionPortio *portio;
+ uint32_t offset;
+ void *opaque;
+} PortioListState;
+
void portio_list_init(PortioList *piolist,
const MemoryRegionPortio *callbacks,
void *opaque, const char *name)
@@ -343,16 +350,95 @@ void portio_list_init(PortioList *piolist,
piolist->ports = callbacks;
piolist->nr = 0;
piolist->regions = g_new0(MemoryRegion *, n);
- piolist->aliases = g_new0(MemoryRegion *, n);
+ piolist->states = g_new0(PortioListState *, n);
piolist->address_space = NULL;
piolist->opaque = opaque;
piolist->name = name;
}
+static const MemoryRegionPortio *portio_find(const MemoryRegionPortio *mrp,
+ uint64_t offset,
+ unsigned int width, bool write)
+{
+ for (; mrp->size; ++mrp) {
+ if (offset >= mrp->offset && offset < mrp->offset + mrp->len
+ && width == mrp->size
+ && (write ? (bool)mrp->write : (bool)mrp->read)) {
+ return mrp;
+ }
+ }
+ return NULL;
+}
+
+static uint64_t portio_read(void *opaque, hwaddr addr, unsigned int size)
+{
+ const PortioListState *s = opaque;
+ const MemoryRegionPortio *mrp;
+ uint16_t data;
+
+ addr += s->portio->offset;
+ mrp = portio_find(s->portio, addr, size, false);
+ if (!mrp && size == 2) {
+ mrp = portio_find(s->portio, addr, 1, false);
+ assert(mrp);
+ data = mrp->read(s->opaque, addr) |
+ (mrp->read(s->opaque, addr + 1) << 8);
+ return data;
+ }
+ assert(mrp);
+ return mrp->read(s->opaque, addr);
+}
+
+static void portio_write(void *opaque, hwaddr addr, uint64_t data,
+ unsigned int size)
+{
+ const PortioListState *s = opaque;
+ const MemoryRegionPortio *mrp;
+
+ addr += s->offset;
+ mrp = portio_find(s->portio, addr, size, true);
+ if (!mrp && size == 2) {
+ mrp = portio_find(s->portio, addr, 1, true);
+ assert(mrp);
+ mrp->write(s->opaque, addr, data & 0xff);
+ mrp->write(s->opaque, addr + 1, data >> 8);
+ return;
+ }
+ assert(mrp);
+ mrp->write(s->opaque, addr, data);
+}
+
+static bool portio_accepts(void *opaque, hwaddr addr, unsigned int size,
+ bool is_write)
+{
+ const PortioListState *s = opaque;
+ const MemoryRegionPortio *mrp;
+
+ addr += s->offset;
+ mrp = portio_find(s->portio, addr, size, is_write);
+ if (!mrp && size == 2) {
+ mrp = portio_find(s->portio, addr, 1, is_write);
+ }
+ if (!mrp) {
+ LOG_UNUSED_IOPORT("unused %s%c: port=0x%04" HWADDR_PRIx "\n",
+ is_write ? "out" : "in",
+ size == 1 ? 'b' : size == 2 ? 'w' : 'l',
+ addr);
+ }
+ return mrp;
+}
+
+const MemoryRegionOps portio_ops = {
+ .endianness = DEVICE_LITTLE_ENDIAN,
+ .read = portio_read,
+ .write = portio_write,
+ .valid.accepts = portio_accepts,
+};
+
void portio_list_destroy(PortioList *piolist)
{
g_free(piolist->regions);
- g_free(piolist->aliases);
+ g_free(piolist->states);
}
static void portio_list_add_1(PortioList *piolist,
@@ -361,8 +447,8 @@ static void portio_list_add_1(PortioList *piolist,
unsigned off_low, unsigned off_high)
{
MemoryRegionPortio *pio;
- MemoryRegionOps *ops;
- MemoryRegion *region, *alias;
+ MemoryRegion *region = g_new(MemoryRegion, 1);
+ PortioListState *s = g_new(PortioListState, 1);
unsigned i;
/* Copy the sub-list and null-terminate it. */
@@ -370,28 +456,20 @@ static void portio_list_add_1(PortioList *piolist,
memcpy(pio, pio_init, sizeof(MemoryRegionPortio) * count);
memset(pio + count, 0, sizeof(MemoryRegionPortio));
- /* Adjust the offsets to all be zero-based for the region. */
+ /* Adjust the offsets to all be address-based for the region. */
for (i = 0; i < count; ++i) {
- pio[i].offset -= off_low;
+ pio[i].offset += start;
}
- ops = g_new0(MemoryRegionOps, 1);
- 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,
- INT64_MAX);
- memory_region_init_alias(alias, piolist->name,
- region, start + off_low, off_high - off_low);
+ s->offset = start + off_low;
+ s->portio = pio;
+ s->opaque = piolist->opaque;
+ memory_region_init_io(region, &portio_ops, s, piolist->name,
+ off_high - off_low);
memory_region_add_subregion(piolist->address_space,
- start + off_low, alias);
+ s->offset, region);
piolist->regions[piolist->nr] = region;
- piolist->aliases[piolist->nr] = alias;
+ piolist->states[piolist->nr] = s;
++piolist->nr;
}
@@ -434,19 +512,19 @@ void portio_list_add(PortioList *piolist,
void portio_list_del(PortioList *piolist)
{
- MemoryRegion *mr, *alias;
+ MemoryRegion *mr;
+ PortioListState *s;
unsigned i;
for (i = 0; i < piolist->nr; ++i) {
mr = piolist->regions[i];
- alias = piolist->aliases[i];
- memory_region_del_subregion(piolist->address_space, alias);
- memory_region_destroy(alias);
+ s = piolist->states[i];
+ memory_region_del_subregion(piolist->address_space, mr);
memory_region_destroy(mr);
g_free((MemoryRegionOps *)mr->ops);
g_free(mr);
- g_free(alias);
+ g_free(s);
piolist->regions[i] = NULL;
- piolist->aliases[i] = NULL;
+ piolist->states[i] = NULL;
}
}
--
1.7.10.4
next prev parent reply other threads:[~2013-06-08 17:43 UTC|newest]
Thread overview: 16+ messages / expand[flat|nested] mbox.gz Atom feed top
2013-06-08 17:43 [Qemu-devel] [PATCH v2 0/8] memory: remove old_portio usage Hervé Poussineau
2013-06-08 17:43 ` [Qemu-devel] [PATCH v2 1/8] isa: fix documentation of isa_register_portio_list Hervé Poussineau
2013-06-08 17:44 ` [Qemu-devel] [PATCH v2 2/8] memory: handle old_portio accesses in MMIO path Hervé Poussineau
2013-06-08 17:44 ` Hervé Poussineau [this message]
2013-06-08 17:44 ` [Qemu-devel] [PATCH v2 4/8] memory: remove code dealing with old_portio Hervé Poussineau
2013-06-08 17:44 ` [Qemu-devel] [PATCH v2 5/8] ioport: reimplement cpu_in/cpu_out using address_space_rw Hervé Poussineau
2013-06-08 17:44 ` [Qemu-devel] [PATCH v2 6/8] ppc: simplify access to PReP I/O region Hervé Poussineau
2013-06-08 17:44 ` [Qemu-devel] [PATCH v2 7/8] PPC: pseries: Remove hack for PIO window Hervé Poussineau
2013-06-08 17:44 ` [Qemu-devel] [PATCH v2 8/8] isa_mmio: simplify access to system I/O region Hervé Poussineau
2013-06-16 18:20 ` [Qemu-devel] [PATCH v2 0/8] memory: remove old_portio usage Hervé Poussineau
2013-06-17 7:32 ` Paolo Bonzini
2013-06-17 7:43 ` Jan Kiszka
2013-06-17 20:39 ` Hervé Poussineau
2013-06-18 14:38 ` Jan Kiszka
2013-06-18 18:09 ` Hervé Poussineau
2013-06-21 18:11 ` Jan Kiszka
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1370713446-9460-4-git-send-email-hpoussin@reactos.org \
--to=hpoussin@reactos.org \
--cc=pbonzini@redhat.com \
--cc=qemu-devel@nongnu.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).