qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
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

  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).