From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from eggs.gnu.org ([208.118.235.92]:34600) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1TmnXY-0008MJ-SF for qemu-devel@nongnu.org; Sun, 23 Dec 2012 10:32:42 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1TmnXS-0007St-0j for qemu-devel@nongnu.org; Sun, 23 Dec 2012 10:32:36 -0500 Received: from smtp1-g21.free.fr ([2a01:e0c:1:1599::10]:43613) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1TmnXR-0007So-FK for qemu-devel@nongnu.org; Sun, 23 Dec 2012 10:32:29 -0500 From: =?UTF-8?q?Herv=C3=A9=20Poussineau?= Date: Sun, 23 Dec 2012 16:32:46 +0100 Message-Id: <1356276769-7357-7-git-send-email-hpoussin@reactos.org> In-Reply-To: <1356276769-7357-1-git-send-email-hpoussin@reactos.org> References: <1356276769-7357-1-git-send-email-hpoussin@reactos.org> MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: quoted-printable Subject: [Qemu-devel] [RFC 6/8] isa: use memory regions instead of portio_list_* functions List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: qemu-devel@nongnu.org Cc: =?UTF-8?q?Andreas=20F=C3=A4rber?= , =?UTF-8?q?Herv=C3=A9=20Poussineau?= , Gerd Hoffmann Signed-off-by: Herv=C3=A9 Poussineau --- 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, MemoryReg= ion *io, uint16_t start) isa_init_ioport(dev, start); } =20 +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 *m= rp, + uint64_t offset, + unsigned int width, bool wr= ite, + bool smaller) +{ + for (; mrp->size; ++mrp) { + if (offset >=3D mrp->offset && offset < mrp->offset + mrp->len + && (width =3D=3D 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 =3D opaque; + const MemoryRegionPortio *mrp; + + addr +=3D s->offset; + mrp =3D portio_find(s->pio_start, addr, size, false, false); + if (mrp) { + return mrp->read(s->opaque, s->start + addr); + } else if (size =3D=3D 2) { + uint64_t data; + mrp =3D portio_find(s->pio_start, addr, 1, false, false); + assert(mrp); + data =3D 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=3D%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 =3D opaque; + const MemoryRegionPortio *mrp; + + addr +=3D s->offset; + mrp =3D portio_find(s->pio_start, addr, size, true, false); + if (mrp) { + mrp->write(s->opaque, s->start + addr, data); + return; + } else if (size =3D=3D 2) { + mrp =3D 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=3D%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 =3D opaque; + const MemoryRegionPortio *mrp; + + addr +=3D s->offset; + mrp =3D portio_find(s->pio_start, addr, size, is_write, true); + return (mrp !=3D NULL); +} + +const MemoryRegionOps portio_ops =3D { + .read =3D portio_read, + .write =3D portio_write, + .valid.accepts =3D portio_accepts, + .endianness =3D DEVICE_LITTLE_ENDIAN, +}; + +static void isa_register_portio_list_1(ISADevice *dev, uint16_t start, + uint16_t offset, uint16_t end, + const MemoryRegionPortio *pio_sta= rt, + void *opaque, const char *name) +{ + MemoryRegion *mr =3D g_new(MemoryRegion, 1); + PortioState *s =3D g_new(PortioState, 1); + + s->name =3D name; + s->start =3D start; + s->offset =3D offset; + s->pio_start =3D pio_start; + s->opaque =3D 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 =3D g_new(PortioList, 1); + const MemoryRegionPortio *pio, *first; + uint16_t end; =20 /* 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); =20 - portio_list_init(piolist, pio_start, opaque, name); - portio_list_add(piolist, isabus->address_space_io, start); + assert(pio_start->size); + + first =3D pio_start; + end =3D 0; + for (pio =3D pio_start; pio->size; pio++) { + assert(pio->offset >=3D first->offset); + if (pio->offset > first->offset + first->len) { + isa_register_portio_list_1(dev, start, first->offset, end, + pio_start, opaque, name); + first =3D pio; + end =3D 0; + } + if (pio->offset + pio->len > end) { + end =3D pio->offset + pio->len; + } + } + + isa_register_portio_list_1(dev, start, first->offset, end, + pio_start, opaque, name); } =20 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, --=20 1.7.10.4