From: "Hervé Poussineau" <hpoussin@reactos.org>
To: qemu-devel@nongnu.org
Cc: "Andreas Färber" <andreas.faerber@web.de>,
"Hervé Poussineau" <hpoussin@reactos.org>,
"Gerd Hoffmann" <kraxel@redhat.com>
Subject: [Qemu-devel] [RFC 6/8] isa: use memory regions instead of portio_list_* functions
Date: Sun, 23 Dec 2012 16:32:46 +0100 [thread overview]
Message-ID: <1356276769-7357-7-git-send-email-hpoussin@reactos.org> (raw)
In-Reply-To: <1356276769-7357-1-git-send-email-hpoussin@reactos.org>
Signed-off-by: Hervé Poussineau <hpoussin@reactos.org>
---
hw/isa-bus.c | 127 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++--
hw/isa.h | 2 +-
2 files changed, 125 insertions(+), 4 deletions(-)
diff --git a/hw/isa-bus.c b/hw/isa-bus.c
index 144a88e..d22f432 100644
--- a/hw/isa-bus.c
+++ b/hw/isa-bus.c
@@ -104,19 +104,140 @@ void isa_register_ioport(ISADevice *dev, MemoryRegion *io, uint16_t start)
isa_init_ioport(dev, start);
}
+typedef struct PortioState {
+ const char *name; /* debug purposes */
+ uint16_t start;
+ uint16_t offset;
+ const MemoryRegionPortio *pio_start;
+ void *opaque;
+} PortioState;
+
+static const MemoryRegionPortio *portio_find(const MemoryRegionPortio *mrp,
+ uint64_t offset,
+ unsigned int width, bool write,
+ bool smaller)
+{
+ for (; mrp->size; ++mrp) {
+ if (offset >= mrp->offset && offset < mrp->offset + mrp->len
+ && (width == mrp->size || (smaller && 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 PortioState *s = opaque;
+ const MemoryRegionPortio *mrp;
+
+ addr += s->offset;
+ mrp = portio_find(s->pio_start, addr, size, false, false);
+ if (mrp) {
+ return mrp->read(s->opaque, s->start + addr);
+ } else if (size == 2) {
+ uint64_t data;
+ mrp = portio_find(s->pio_start, addr, 1, false, false);
+ assert(mrp);
+ data = mrp->read(s->opaque, s->start + addr) |
+ (mrp->read(s->opaque, s->start + addr + 1) << 8);
+ return data;
+ }
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: invalid read from 0x%x size=%d",
+ s->name, s->start + (int)addr, size);
+ return -1U;
+}
+
+static void portio_write(void *opaque, hwaddr addr, uint64_t data,
+ unsigned int size)
+{
+ const PortioState *s = opaque;
+ const MemoryRegionPortio *mrp;
+
+ addr += s->offset;
+ mrp = portio_find(s->pio_start, addr, size, true, false);
+ if (mrp) {
+ mrp->write(s->opaque, s->start + addr, data);
+ return;
+ } else if (size == 2) {
+ mrp = portio_find(s->pio_start, addr, 1, true, false);
+ assert(mrp);
+ mrp->write(s->opaque, s->start + addr, data & 0xff);
+ mrp->write(s->opaque, s->start + addr + 1, data >> 8);
+ return;
+ }
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: invalid write to 0x%x size=%d",
+ s->name, s->start + (int)addr, size);
+}
+
+static bool portio_accepts(void *opaque, hwaddr addr, unsigned int size,
+ bool is_write)
+{
+ const PortioState *s = opaque;
+ const MemoryRegionPortio *mrp;
+
+ addr += s->offset;
+ mrp = portio_find(s->pio_start, addr, size, is_write, true);
+ return (mrp != NULL);
+}
+
+const MemoryRegionOps portio_ops = {
+ .read = portio_read,
+ .write = portio_write,
+ .valid.accepts = portio_accepts,
+ .endianness = DEVICE_LITTLE_ENDIAN,
+};
+
+static void isa_register_portio_list_1(ISADevice *dev, uint16_t start,
+ uint16_t offset, uint16_t end,
+ const MemoryRegionPortio *pio_start,
+ void *opaque, const char *name)
+{
+ MemoryRegion *mr = g_new(MemoryRegion, 1);
+ PortioState *s = g_new(PortioState, 1);
+
+ s->name = name;
+ s->start = start;
+ s->offset = offset;
+ s->pio_start = pio_start;
+ s->opaque = opaque;
+ memory_region_init_io(mr, &portio_ops, s, name, end - offset);
+ memory_region_add_subregion(isa_address_space_io(dev),
+ start + offset, mr);
+}
+
void isa_register_portio_list(ISADevice *dev, uint16_t start,
const MemoryRegionPortio *pio_start,
void *opaque, const char *name)
{
- PortioList *piolist = g_new(PortioList, 1);
+ const MemoryRegionPortio *pio, *first;
+ uint16_t end;
/* START is how we should treat DEV, regardless of the actual
contents of the portio array. This is how the old code
actually handled e.g. the FDC device. */
isa_init_ioport(dev, start);
- portio_list_init(piolist, pio_start, opaque, name);
- portio_list_add(piolist, isabus->address_space_io, start);
+ assert(pio_start->size);
+
+ first = pio_start;
+ end = 0;
+ for (pio = pio_start; pio->size; pio++) {
+ assert(pio->offset >= first->offset);
+ if (pio->offset > first->offset + first->len) {
+ isa_register_portio_list_1(dev, start, first->offset, end,
+ pio_start, opaque, name);
+ first = pio;
+ end = 0;
+ }
+ if (pio->offset + pio->len > end) {
+ end = pio->offset + pio->len;
+ }
+ }
+
+ isa_register_portio_list_1(dev, start, first->offset, end,
+ pio_start, opaque, name);
}
static int isa_qdev_init(DeviceState *qdev)
diff --git a/hw/isa.h b/hw/isa.h
index 9d719fa..d44d16d 100644
--- a/hw/isa.h
+++ b/hw/isa.h
@@ -73,7 +73,7 @@ void isa_register_ioport(ISADevice *dev, MemoryRegion *io, uint16_t start);
* @dev: the ISADevice against which these are registered; may be NULL.
* @start: the base I/O port against which the portio->offset is applied.
* @portio: the ports, sorted by offset.
- * @opaque: passed into the old_portio callbacks.
+ * @opaque: passed into the portio callbacks.
* @name: passed into memory_region_init_io.
*/
void isa_register_portio_list(ISADevice *dev, uint16_t start,
--
1.7.10.4
next prev parent reply other threads:[~2012-12-23 15:32 UTC|newest]
Thread overview: 12+ messages / expand[flat|nested] mbox.gz Atom feed top
2012-12-23 15:32 [Qemu-devel] [RFC 0/8] Remove old_portio usage Hervé Poussineau
2012-12-23 15:32 ` [Qemu-devel] [RFC 1/8] pc: disable bochs bios debug ports (do not apply!) Hervé Poussineau
2012-12-23 15:32 ` [Qemu-devel] [RFC 2/8] xen_platform: do not use old_portio-style callbacks Hervé Poussineau
2012-12-23 15:32 ` [Qemu-devel] [RFC 3/8] uhci: " Hervé Poussineau
2013-01-03 14:09 ` Gerd Hoffmann
2012-12-23 15:32 ` [Qemu-devel] [RFC 4/8] acpi-piix4: " Hervé Poussineau
2012-12-23 15:32 ` [Qemu-devel] [RFC 5/8] vga/qxl: do not use portio_list_init/portio_list_add Hervé Poussineau
2012-12-23 15:32 ` Hervé Poussineau [this message]
2012-12-23 15:32 ` [Qemu-devel] [RFC 7/8] ioport: remove now useless portio_list_* functions Hervé Poussineau
2012-12-23 15:32 ` [Qemu-devel] [RFC 8/8] memory: remove old_portio-style callbacks support Hervé Poussineau
2013-01-02 23:32 ` [Qemu-devel] [RFC 0/8] Remove old_portio usage Andreas Färber
2013-01-03 14:05 ` Gerd Hoffmann
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=1356276769-7357-7-git-send-email-hpoussin@reactos.org \
--to=hpoussin@reactos.org \
--cc=andreas.faerber@web.de \
--cc=kraxel@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).