All of lore.kernel.org
 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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.