From nobody Tue Nov 18 10:39:17 2025 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass(p=none dis=none) header.from=nongnu.org ARC-Seal: i=1; a=rsa-sha256; t=1609586654; cv=none; d=zohomail.com; s=zohoarc; b=bOJbppyEtxTCyoql9Pgk29HkrkNmyy/0QYZDOF1g+wlzUUHTaXaFdPk0oCAU6Q2e3ipuwU8wv6pjqO4rNPoisJUgm9nUjvXiz0FmTElYZW7BLB7wR1zHH+zs4mNFwWGH6OlcbvKxUGdWn+Iw7lMRRjQRHlGarLg4MnQ9WLLnr/U= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1609586654; h=Content-Type:Content-Transfer-Encoding:Cc:Date:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:Reply-To:References:Sender:Subject:To; bh=w8eRFA9pXTKv6O4hvSscpOs6i2piaXeA+ZVHp7dBkO8=; b=lUMRQRmwsLvP0OhvS2l4cLKwqANgKddD0pyccSahgt2AInIzN02amFKAgs3qEOhIWmLubE64fO+xuXIrEAqzK7ZZu0KjlActj8woJBFRPXf8hHVA9ViH5ONFB+kebqPlFyXAYlDzgyBK2a8yugKID1UyLLe2NM738TlR3l8u7jk= ARC-Authentication-Results: i=1; mx.zohomail.com; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass header.from= (p=none dis=none) header.from= Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1609586654938614.8499713626954; Sat, 2 Jan 2021 03:24:14 -0800 (PST) Received: from localhost ([::1]:46794 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1kvf13-0004cb-Ru for importer@patchew.org; Sat, 02 Jan 2021 06:24:13 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]:33248) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1kveqy-0000uQ-7v for qemu-devel@nongnu.org; Sat, 02 Jan 2021 06:13:48 -0500 Received: from zero.eik.bme.hu ([2001:738:2001:2001::2001]:56514) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1kveqr-000792-Uv for qemu-devel@nongnu.org; Sat, 02 Jan 2021 06:13:48 -0500 Received: from zero.eik.bme.hu (blah.eik.bme.hu [152.66.115.182]) by localhost (Postfix) with SMTP id 00E0A747610; Sat, 2 Jan 2021 12:13:32 +0100 (CET) Received: by zero.eik.bme.hu (Postfix, from userid 432) id 33B01747636; Sat, 2 Jan 2021 12:13:30 +0100 (CET) Message-Id: In-Reply-To: References: Subject: [PATCH 21/24] vt82c686: Implement control of serial port io ranges via config regs Date: Sat, 02 Jan 2021 11:43:35 +0100 MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable To: qemu-devel@nongnu.org X-Spam-Probability: 8% Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: pass client-ip=2001:738:2001:2001::2001; envelope-from=balaton@eik.bme.hu; helo=zero.eik.bme.hu X-Spam_score_int: -18 X-Spam_score: -1.9 X-Spam_bar: - X-Spam_report: (-1.9 / 5.0 requ) BAYES_00=-1.9, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Huacai Chen , f4bug@amsat.org Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" Reply-to: BALATON Zoltan From: BALATON Zoltan via Content-Type: text/plain; charset="utf-8" In VIA super south bridge the io ranges of superio components (parallel and serial ports and FDC) can be controlled by superio config registers to set their base address and enable/disable them. This is not easy to implement in QEMU because ISA emulation is only designed to set io base address once on creating the device and io ranges are registered at creation and cannot easily be disabled or moved later. In this patch we hack around that but only for serial ports because those have a single io range at port base that's relatively easy to handle and it's what guests actually use and set address different than the default. We do not attempt to handle controlling the parallel and FDC regions because those have multiple io ranges so handling them would be messy and guests either don't change their deafult or don't care. We could even get away with disabling and not emulating them, but since they are already there, this patch leaves them mapped at their default address just in case this could be useful for a guest in the future. Signed-off-by: BALATON Zoltan --- hw/isa/vt82c686.c | 84 +++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 82 insertions(+), 2 deletions(-) diff --git a/hw/isa/vt82c686.c b/hw/isa/vt82c686.c index 1a876a1fbf..26db1a18e2 100644 --- a/hw/isa/vt82c686.c +++ b/hw/isa/vt82c686.c @@ -252,8 +252,24 @@ static const TypeInfo vt8231_pm_info =3D { typedef struct SuperIOConfig { uint8_t regs[0x100]; MemoryRegion io; + ISASuperIODevice *superio; + MemoryRegion *serial_io[SUPERIO_MAX_SERIAL_PORTS]; } SuperIOConfig; =20 +static MemoryRegion *find_subregion(ISADevice *d, MemoryRegion *parent, + int offs) +{ + MemoryRegion *subregion, *mr =3D NULL; + + QTAILQ_FOREACH(subregion, &parent->subregions, subregions_link) { + if (subregion->addr =3D=3D offs) { + mr =3D subregion; + break; + } + } + return mr; +} + static void superio_cfg_write(void *opaque, hwaddr addr, uint64_t data, unsigned size) { @@ -279,7 +295,53 @@ static void superio_cfg_write(void *opaque, hwaddr add= r, uint64_t data, case 0xfd ... 0xff: /* ignore write to read only registers */ return; - /* case 0xe6 ... 0xe8: Should set base port of parallel and serial */ + case 0xe2: + { + data &=3D 0x1f; + if (data & BIT(2)) { /* Serial port 1 enable */ + ISADevice *dev =3D sc->superio->serial[0]; + if (!memory_region_is_mapped(sc->serial_io[0])) { + memory_region_add_subregion(isa_address_space_io(dev), + dev->ioport_id, sc->serial_io[= 0]); + } + } else { + MemoryRegion *io =3D isa_address_space_io(sc->superio->serial[= 0]); + if (memory_region_is_mapped(sc->serial_io[0])) { + memory_region_del_subregion(io, sc->serial_io[0]); + } + } + if (data & BIT(3)) { /* Serial port 2 enable */ + ISADevice *dev =3D sc->superio->serial[1]; + if (!memory_region_is_mapped(sc->serial_io[1])) { + memory_region_add_subregion(isa_address_space_io(dev), + dev->ioport_id, sc->serial_io[= 1]); + } + } else { + MemoryRegion *io =3D isa_address_space_io(sc->superio->serial[= 1]); + if (memory_region_is_mapped(sc->serial_io[1])) { + memory_region_del_subregion(io, sc->serial_io[1]); + } + } + break; + } + case 0xe7: /* Serial port 1 io base address */ + { + data &=3D 0xfe; + sc->superio->serial[0]->ioport_id =3D data << 2; + if (memory_region_is_mapped(sc->serial_io[0])) { + memory_region_set_address(sc->serial_io[0], data << 2); + } + break; + } + case 0xe8: /* Serial port 2 io base address */ + { + data &=3D 0xfe; + sc->superio->serial[1]->ioport_id =3D data << 2; + if (memory_region_is_mapped(sc->serial_io[1])) { + memory_region_set_address(sc->serial_io[1], data << 2); + } + break; + } default: qemu_log_mask(LOG_UNIMP, "via_superio_cfg: unimplemented register 0x%x\n", id= x); @@ -385,6 +447,7 @@ static void vt82c686b_realize(PCIDevice *d, Error **err= p) DeviceState *dev =3D DEVICE(d); ISABus *isa_bus; qemu_irq *isa_irq; + ISASuperIOClass *ic; int i; =20 qdev_init_gpio_out(dev, &s->cpu_intr, 1); @@ -394,7 +457,9 @@ static void vt82c686b_realize(PCIDevice *d, Error **err= p) isa_bus_irqs(isa_bus, i8259_init(isa_bus, *isa_irq)); i8254_pit_init(isa_bus, 0x40, 0, NULL); i8257_dma_init(isa_bus, 0); - isa_create_simple(isa_bus, TYPE_VT82C686B_SUPERIO); + s->superio_cfg.superio =3D ISA_SUPERIO(isa_create_simple(isa_bus, + TYPE_VT82C686B_SUPER= IO)); + ic =3D ISA_SUPERIO_GET_CLASS(s->superio_cfg.superio); mc146818_rtc_init(isa_bus, 2000, NULL); =20 for (i =3D 0; i < PCI_CONFIG_HEADER_SIZE; i++) { @@ -412,6 +477,21 @@ static void vt82c686b_realize(PCIDevice *d, Error **er= rp) */ memory_region_add_subregion(isa_bus->address_space_io, 0x3f0, &s->superio_cfg.io); + + /* Grab io regions of serial devices so we can control them */ + for (i =3D 0; i < ic->serial.count; i++) { + ISADevice *sd =3D s->superio_cfg.superio->serial[i]; + MemoryRegion *io =3D isa_address_space_io(sd); + MemoryRegion *mr =3D find_subregion(sd, io, sd->ioport_id); + if (!mr) { + error_setg(errp, "Could not get io region for serial %d", i); + return; + } + s->superio_cfg.serial_io[i] =3D mr; + if (memory_region_is_mapped(mr)) { + memory_region_del_subregion(io, mr); + } + } } =20 static void via_class_init(ObjectClass *klass, void *data) --=20 2.21.3