From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from eggs.gnu.org ([140.186.70.92]:54288) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1RAOcl-0004pq-Ox for qemu-devel@nongnu.org; Sun, 02 Oct 2011 12:10:45 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1RAOck-00084O-33 for qemu-devel@nongnu.org; Sun, 02 Oct 2011 12:10:43 -0400 Received: from smtp5-g21.free.fr ([212.27.42.5]:45608) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1RAOcj-00083H-9N for qemu-devel@nongnu.org; Sun, 02 Oct 2011 12:10:41 -0400 From: =?UTF-8?q?Herv=C3=A9=20Poussineau?= Date: Sun, 2 Oct 2011 18:10:14 +0200 Message-Id: <1317571828-9059-3-git-send-email-hpoussin@reactos.org> In-Reply-To: <1317571828-9059-1-git-send-email-hpoussin@reactos.org> References: <1317571828-9059-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] [PATCH v3 02/16] isa: rework ISA bus internals, and add ISA bus ops structure List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: qemu-devel@nongnu.org Cc: =?UTF-8?q?Herv=C3=A9=20Poussineau?= This allows future implementations of real pci-isa bridges Signed-off-by: Herv=C3=A9 Poussineau --- Makefile.objs | 2 +- hw/isa-bridge.c | 85 +++++++++++++++++++++++++++++++++++++++++++++++++= + hw/isa-bus.c | 93 ++++++++++++++++++++++++++++++++++++-------------= ------ hw/isa.h | 18 ++++++++++- qemu-common.h | 1 + 5 files changed, 165 insertions(+), 34 deletions(-) create mode 100644 hw/isa-bridge.c diff --git a/Makefile.objs b/Makefile.objs index 8d23fbb..bab4b3f 100644 --- a/Makefile.objs +++ b/Makefile.objs @@ -276,7 +276,7 @@ hw-obj-$(CONFIG_AHCI) +=3D ide/ich.o hw-obj-$(CONFIG_LSI_SCSI_PCI) +=3D lsi53c895a.o hw-obj-$(CONFIG_ESP) +=3D esp.o =20 -hw-obj-y +=3D dma-helpers.o sysbus.o isa-bus.o +hw-obj-y +=3D dma-helpers.o sysbus.o isa-bus.o isa-bridge.o hw-obj-y +=3D qdev-addr.o =20 # VGA diff --git a/hw/isa-bridge.c b/hw/isa-bridge.c new file mode 100644 index 0000000..6f51701 --- /dev/null +++ b/hw/isa-bridge.c @@ -0,0 +1,85 @@ +/* + * Simple ISA bus bridge + * + * Copyright (c) 2011 Herve Poussineau + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see . + */ + +#include "isa.h" +#include "sysbus.h" + +typedef struct { + SysBusDevice busdev; + ISABus bus; + qemu_irq *irqs; + MemoryRegion *io_space; +} ISABridgeSysBusState; + +static void isabus_bridge_set_irqs(ISABus *bus, qemu_irq *irqs) +{ + ISABridgeSysBusState *s =3D container_of(bus, ISABridgeSysBusState, = bus); + s->irqs =3D irqs; +} + +static qemu_irq isabus_bridge_get_irq(ISABus *bus, int isairq) +{ + ISABridgeSysBusState *s =3D container_of(bus, ISABridgeSysBusState, = bus); + if (!s->irqs || isairq < 0 || isairq > 15) { + hw_error("isa irq %d invalid", isairq); + } + return s->irqs[isairq]; +} + +static void isa_bridge_set_io_space(ISABus *bus, MemoryRegion* io_space) +{ + ISABridgeSysBusState *s =3D container_of(bus, ISABridgeSysBusState, = bus); + s->io_space =3D io_space; +} + +static MemoryRegion *isa_bridge_get_io_space(ISABus *bus) +{ + ISABridgeSysBusState *s =3D container_of(bus, ISABridgeSysBusState, = bus); + return s->io_space; +} + +static ISABusOps isabus_bridge_ops =3D { + .set_irqs =3D isabus_bridge_set_irqs, + .get_irq =3D isabus_bridge_get_irq, + .set_io_space =3D isa_bridge_set_io_space, + .get_io_space =3D isa_bridge_get_io_space, +}; + +static int isabus_bridge_init(SysBusDevice *dev) +{ + ISABridgeSysBusState *isa =3D FROM_SYSBUS(ISABridgeSysBusState, dev)= ; + isa_bus_new(&isa->bus, &isabus_bridge_ops, &dev->qdev); + return 0; +} + +static SysBusDeviceInfo isabus_bridge_info =3D { + .init =3D isabus_bridge_init, + .qdev.name =3D "isabus-bridge", + .qdev.fw_name =3D "isa", + .qdev.size =3D sizeof(ISABridgeSysBusState), + .qdev.no_user =3D 1, +}; + +static void isabus_bridge_register_devices(void) +{ + sysbus_register_withprop(&isabus_bridge_info); +} + +device_init(isabus_bridge_register_devices) + diff --git a/hw/isa-bus.c b/hw/isa-bus.c index ad225c6..f8b5dcb 100644 --- a/hw/isa-bus.c +++ b/hw/isa-bus.c @@ -22,13 +22,10 @@ #include "isa.h" #include "exec-memory.h" =20 -struct ISABus { - BusState qbus; - MemoryRegion *address_space_io; - qemu_irq *irqs; -}; static ISABus *isabus; target_phys_addr_t isa_mem_base =3D 0; +static qemu_irq *isa_bus_default_irqs; +static MemoryRegion *isa_bus_io_space; =20 static void isabus_dev_print(Monitor *mon, DeviceState *dev, int indent)= ; static char *isabus_get_fw_dev_path(DeviceState *dev); @@ -40,6 +37,36 @@ static struct BusInfo isa_bus_info =3D { .get_fw_dev_path =3D isabus_get_fw_dev_path, }; =20 +static void isa_bus_default_set_irqs(ISABus *bus, qemu_irq *irqs) +{ + isa_bus_default_irqs =3D irqs; +} + +static qemu_irq isa_bus_default_get_irq(ISABus *bus, int isairq) +{ + if (isairq < 0 || isairq > 15) { + hw_error("isa irq %d invalid", isairq); + } + return isa_bus_default_irqs[isairq]; +} + +static void isa_bus_default_set_io_space(ISABus *bus, MemoryRegion *io_s= pace) +{ + isa_bus_io_space =3D io_space; +} + +static MemoryRegion *isa_bus_default_get_io_space(ISABus *bus) +{ + return isa_bus_io_space; +} + +static ISABusOps isa_bus_default_ops =3D { + .set_irqs =3D isa_bus_default_set_irqs, + .get_irq =3D isa_bus_default_get_irq, + .set_io_space =3D isa_bus_default_set_io_space, + .get_io_space =3D isa_bus_default_get_io_space, +}; + ISABus *isa_bus_bridge_init(DeviceState *dev, MemoryRegion *address_spac= e_io) { if (isabus) { @@ -49,16 +76,32 @@ ISABus *isa_bus_bridge_init(DeviceState *dev, MemoryR= egion *address_space_io) if (NULL =3D=3D dev) { dev =3D qdev_create(NULL, "isabus-bridge"); qdev_init_nofail(dev); + } else { + isabus =3D FROM_QBUS(ISABus, qbus_create(&isa_bus_info, dev, NUL= L)); + isabus->ops =3D &isa_bus_default_ops; } =20 - isabus =3D FROM_QBUS(ISABus, qbus_create(&isa_bus_info, dev, NULL)); - isabus->address_space_io =3D address_space_io; + isabus->ops->set_io_space(isabus, address_space_io); + return isabus; } =20 +void isa_bus_new(ISABus *bus, ISABusOps *ops, DeviceState *host) +{ + if (isabus) { + hw_error("Can't create a second ISA bus"); + } + qbus_create_inplace(&bus->qbus, &isa_bus_info, host, NULL); + bus->ops =3D ops; + isabus =3D bus; +} + void isa_bus_irqs(qemu_irq *irqs) { - isabus->irqs =3D irqs; + if (!isabus || !isabus->ops->set_irqs) { + hw_error("Tried to set isa irqs with no isa bus present."); + } + isabus->ops->set_irqs(isabus, irqs); } =20 /* @@ -69,10 +112,10 @@ void isa_bus_irqs(qemu_irq *irqs) */ qemu_irq isa_get_irq(int isairq) { - if (isairq < 0 || isairq > 15) { - hw_error("isa irq %d invalid", isairq); + if (!isabus || !isabus->ops->get_irq) { + hw_error("ISA bus invalid"); } - return isabus->irqs[isairq]; + return isabus->ops->get_irq(isabus, isairq); } =20 void isa_init_irq(ISADevice *dev, qemu_irq *p, int isairq) @@ -110,7 +153,13 @@ void isa_init_ioport(ISADevice *dev, uint16_t ioport= ) =20 void isa_register_ioport(ISADevice *dev, MemoryRegion *io, uint16_t star= t) { - memory_region_add_subregion(isabus->address_space_io, start, io); + ISABus *bus =3D isabus; + + if (!bus || !bus->ops->get_io_space) { + hw_error("Tried to register I/O port with no isa bus present."); + } + + memory_region_add_subregion(bus->ops->get_io_space(bus), start, io); if (dev !=3D NULL) { assert(dev->nio < ARRAY_SIZE(dev->io)); dev->io[dev->nio++] =3D io; @@ -182,25 +231,6 @@ static void isabus_dev_print(Monitor *mon, DeviceSta= te *dev, int indent) } } =20 -static int isabus_bridge_init(SysBusDevice *dev) -{ - /* nothing */ - return 0; -} - -static SysBusDeviceInfo isabus_bridge_info =3D { - .init =3D isabus_bridge_init, - .qdev.name =3D "isabus-bridge", - .qdev.fw_name =3D "isa", - .qdev.size =3D sizeof(SysBusDevice), - .qdev.no_user =3D 1, -}; - -static void isabus_register_devices(void) -{ - sysbus_register_withprop(&isabus_bridge_info); -} - static char *isabus_get_fw_dev_path(DeviceState *dev) { ISADevice *d =3D (ISADevice*)dev; @@ -220,4 +250,3 @@ MemoryRegion *isa_address_space(ISADevice *dev) return get_system_memory(); } =20 -device_init(isabus_register_devices) diff --git a/hw/isa.h b/hw/isa.h index d2b3cba..3437199 100644 --- a/hw/isa.h +++ b/hw/isa.h @@ -7,7 +7,7 @@ #include "memory.h" #include "qdev.h" =20 -typedef struct ISABus ISABus; +typedef struct ISABusOps ISABusOps; typedef struct ISADevice ISADevice; typedef struct ISADeviceInfo ISADeviceInfo; =20 @@ -27,7 +27,23 @@ struct ISADeviceInfo { isa_qdev_initfn init; }; =20 +/* isa-bus.c */ + +struct ISABus { + BusState qbus; + ISABusOps *ops; +}; + +struct ISABusOps { + void (*set_irqs)(ISABus *bus, qemu_irq *irqs); + qemu_irq (*get_irq)(ISABus *bus, int isairq); + void (*set_io_space)(ISABus *bus, MemoryRegion *address_space); + MemoryRegion *(*get_io_space)(ISABus *bus); +}; + ISABus *isa_bus_bridge_init(DeviceState *dev, MemoryRegion *address_spac= e_io); + +void isa_bus_new(ISABus *bus, ISABusOps *ops, DeviceState *host); void isa_bus_irqs(qemu_irq *irqs); qemu_irq isa_get_irq(int isairq); void isa_init_irq(ISADevice *dev, qemu_irq *p, int isairq); diff --git a/qemu-common.h b/qemu-common.h index 5e87bdf..e3a470d 100644 --- a/qemu-common.h +++ b/qemu-common.h @@ -243,6 +243,7 @@ typedef struct VLANClientState VLANClientState; typedef struct i2c_bus i2c_bus; typedef struct i2c_slave i2c_slave; typedef struct SMBusDevice SMBusDevice; +typedef struct ISABus ISABus; typedef struct PCIHostState PCIHostState; typedef struct PCIExpressHost PCIExpressHost; typedef struct PCIBus PCIBus; --=20 1.7.6.3