From nobody Wed May 15 22:07:36 2024 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=fail(p=none dis=none) header.from=eik.bme.hu Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1677005093147436.38811518396074; Tue, 21 Feb 2023 10:44:53 -0800 (PST) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1pUXcf-0007Qu-0w; Tue, 21 Feb 2023 13:44:17 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1pUXcc-0007PY-D9; Tue, 21 Feb 2023 13:44:14 -0500 Received: from zero.eik.bme.hu ([2001:738:2001:2001::2001]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1pUXcY-0006hS-C4; Tue, 21 Feb 2023 13:44:14 -0500 Received: from zero.eik.bme.hu (blah.eik.bme.hu [152.66.115.182]) by localhost (Postfix) with SMTP id 7E6EB746FCF; Tue, 21 Feb 2023 19:44:02 +0100 (CET) Received: by zero.eik.bme.hu (Postfix, from userid 432) id 548B5746F32; Tue, 21 Feb 2023 19:44:02 +0100 (CET) Message-Id: <8e99d399ce86ca97e4eb7b0afe60e8ca61c9536f.1677004415.git.balaton@eik.bme.hu> In-Reply-To: References: From: BALATON Zoltan Subject: [PATCH 1/5] hw/isa/vt82c686: Implement interrupt routing in via_isa_set_irq MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable To: qemu-devel@nongnu.org, qemu-ppc@nongnu.org Cc: Gerd Hoffmann , Daniel Henrique Barboza , Bernhard Beschow , philmd@redhat.com Date: Tue, 21 Feb 2023 19:44:02 +0100 (CET) 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.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZM-MESSAGEID: 1677005094798100007 Content-Type: text/plain; charset="utf-8" The VIA intergrated south bridge chips combine several functions and allow routing their interrupts to any of the ISA IRQs (also allowing multiple components to share the same ISA IRQ, e.g. pegasos2 firmware configures USB, sound and PCI to use IRQ 9). Currently components call via_isa_set_irq() to directly set the ISA IRQ they are mapped to. Change this that instead of an ISA IRQ number via_isa_set_irq() takes interrupt source and the component that wants to change the IRQ and keeps track of interrupt status of each source separately and does the mapping to ISA IRQ within the ISA bridge to allow different sources to control the same ISA IRQ lines. This patch may not handle cases when the ISA IRQ is also controlled by devices directly, not going through via_isa_set_irq() such as serial, parallel or keyboard but these IRQs being conventionally fixed are not likely for guests to change or share with other devices so this does not cause a problem in practice and limits the complexity of this change to what is needed for the guests we care about. This patch is preliminary for fixing PCI device interrupts on pegasos2. Signed-off-by: BALATON Zoltan --- hw/ide/via.c | 2 +- hw/isa/vt82c686.c | 40 +++++++++++++++++++++++++++++++++++--- hw/usb/vt82c686-uhci-pci.c | 5 +---- include/hw/isa/vt82c686.h | 9 ++++++++- 4 files changed, 47 insertions(+), 9 deletions(-) diff --git a/hw/ide/via.c b/hw/ide/via.c index e1a429405d..c2c182bf1a 100644 --- a/hw/ide/via.c +++ b/hw/ide/via.c @@ -112,7 +112,7 @@ static void via_ide_set_irq(void *opaque, int n, int le= vel) d->config[0x70 + n * 8] &=3D ~0x80; } =20 - via_isa_set_irq(pci_get_function_0(d), 14 + n, level); + via_isa_set_irq(d, VIA_IRQ_IDE0 + n, level); } =20 static void via_ide_reset(DeviceState *dev) diff --git a/hw/isa/vt82c686.c b/hw/isa/vt82c686.c index 3f9bd0c04d..1972063903 100644 --- a/hw/isa/vt82c686.c +++ b/hw/isa/vt82c686.c @@ -549,6 +549,7 @@ struct ViaISAState { PCIDevice dev; qemu_irq cpu_intr; qemu_irq *isa_irqs; + uint16_t isa_irq_state[ISA_NUM_IRQS]; ViaSuperIOState via_sio; RTCState rtc; PCIIDEState ide; @@ -592,10 +593,43 @@ static const TypeInfo via_isa_info =3D { }, }; =20 -void via_isa_set_irq(PCIDevice *d, int n, int level) +void via_isa_set_irq(PCIDevice *d, ViaISAIRQSourceBit n, int level) { - ViaISAState *s =3D VIA_ISA(d); - qemu_set_irq(s->isa_irqs[n], level); + ViaISAState *s =3D VIA_ISA(pci_get_function_0(d)); + uint8_t isa_irq =3D 0, max_irq =3D 15; + + if (n =3D=3D VIA_IRQ_USB0 && d =3D=3D PCI_DEVICE(&s->uhci[1])) { + n++; + } + switch (n) { + case VIA_IRQ_IDE0: + isa_irq =3D 14; + break; + case VIA_IRQ_IDE1: + isa_irq =3D 15; + break; + case VIA_IRQ_USB0: + case VIA_IRQ_USB1: + max_irq =3D 14; + isa_irq =3D d->config[PCI_INTERRUPT_LINE]; + break; + } + + if (unlikely(isa_irq > max_irq || isa_irq =3D=3D 2)) { + qemu_log_mask(LOG_GUEST_ERROR, "Invalid ISA IRQ routing %d for %d", + isa_irq, n); + return; + } + if (!isa_irq) { + return; + } + + if (level) { + s->isa_irq_state[isa_irq] |=3D BIT(n); + } else { + s->isa_irq_state[isa_irq] &=3D ~BIT(n); + } + qemu_set_irq(s->isa_irqs[isa_irq], !!s->isa_irq_state[isa_irq]); } =20 static void via_isa_request_i8259_irq(void *opaque, int irq, int level) diff --git a/hw/usb/vt82c686-uhci-pci.c b/hw/usb/vt82c686-uhci-pci.c index 46a901f56f..2681be3cec 100644 --- a/hw/usb/vt82c686-uhci-pci.c +++ b/hw/usb/vt82c686-uhci-pci.c @@ -6,10 +6,7 @@ static void uhci_isa_set_irq(void *opaque, int irq_num, int level) { UHCIState *s =3D opaque; - uint8_t irq =3D pci_get_byte(s->dev.config + PCI_INTERRUPT_LINE); - if (irq > 0 && irq < 15) { - via_isa_set_irq(pci_get_function_0(&s->dev), irq, level); - } + via_isa_set_irq(&s->dev, VIA_IRQ_USB0, level); } =20 static void usb_uhci_vt82c686b_realize(PCIDevice *dev, Error **errp) diff --git a/include/hw/isa/vt82c686.h b/include/hw/isa/vt82c686.h index e273cd38dc..a0f9f80401 100644 --- a/include/hw/isa/vt82c686.h +++ b/include/hw/isa/vt82c686.h @@ -9,6 +9,13 @@ #define TYPE_VIA_IDE "via-ide" #define TYPE_VIA_MC97 "via-mc97" =20 -void via_isa_set_irq(PCIDevice *d, int n, int level); +typedef enum { + VIA_IRQ_IDE0 =3D 0, + VIA_IRQ_IDE1 =3D 1, + VIA_IRQ_USB0 =3D 2, + VIA_IRQ_USB1 =3D 3, +} ViaISAIRQSourceBit; + +void via_isa_set_irq(PCIDevice *d, ViaISAIRQSourceBit n, int level); =20 #endif --=20 2.30.7 From nobody Wed May 15 22:07:36 2024 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=fail(p=none dis=none) header.from=eik.bme.hu Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1677005108195459.20334050983865; Tue, 21 Feb 2023 10:45:08 -0800 (PST) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1pUXce-0007Qp-Od; Tue, 21 Feb 2023 13:44:16 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1pUXcc-0007PK-DM; Tue, 21 Feb 2023 13:44:14 -0500 Received: from zero.eik.bme.hu ([152.66.115.2]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1pUXcY-0006hW-Bc; Tue, 21 Feb 2023 13:44:13 -0500 Received: from zero.eik.bme.hu (blah.eik.bme.hu [152.66.115.182]) by localhost (Postfix) with SMTP id 7CDAC7470B1; Tue, 21 Feb 2023 19:44:03 +0100 (CET) Received: by zero.eik.bme.hu (Postfix, from userid 432) id 5C7307470B0; Tue, 21 Feb 2023 19:44:03 +0100 (CET) Message-Id: In-Reply-To: References: From: BALATON Zoltan Subject: [PATCH 2/5] hw/isa/vt82c686: Implement PIRQ pins MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable To: qemu-devel@nongnu.org, qemu-ppc@nongnu.org Cc: Gerd Hoffmann , Daniel Henrique Barboza , Bernhard Beschow , philmd@redhat.com Date: Tue, 21 Feb 2023 19:44:03 +0100 (CET) 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=152.66.115.2; envelope-from=balaton@eik.bme.hu; helo=zero.eik.bme.hu X-Spam_score_int: -25 X-Spam_score: -2.6 X-Spam_bar: -- X-Spam_report: (-2.6 / 5.0 requ) BAYES_00=-1.9, RCVD_IN_DNSWL_LOW=-0.7, 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.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZM-MESSAGEID: 1677005109623100001 Content-Type: text/plain; charset="utf-8" The chip has 4 pins (called PIRQA-D in VT82C686B and PINTA-D in VT8231) that are meant to be connected to PCI IRQ lines and allow routing PCI interrupts to the ISA PIC. Add gpio inputs to model these. Signed-off-by: BALATON Zoltan --- hw/isa/vt82c686.c | 18 ++++++++++++++++++ include/hw/isa/vt82c686.h | 4 ++++ 2 files changed, 22 insertions(+) diff --git a/hw/isa/vt82c686.c b/hw/isa/vt82c686.c index 1972063903..f31b2fa7ca 100644 --- a/hw/isa/vt82c686.c +++ b/hw/isa/vt82c686.c @@ -613,6 +613,18 @@ void via_isa_set_irq(PCIDevice *d, ViaISAIRQSourceBit = n, int level) max_irq =3D 14; isa_irq =3D d->config[PCI_INTERRUPT_LINE]; break; + case VIA_IRQ_PIRQA: + isa_irq =3D d->config[0x55] >> 4; + break; + case VIA_IRQ_PIRQB: + isa_irq =3D d->config[0x56] & 0xf; + break; + case VIA_IRQ_PIRQC: + isa_irq =3D d->config[0x56] >> 4; + break; + case VIA_IRQ_PIRQD: + isa_irq =3D d->config[0x57] >> 4; + break; } =20 if (unlikely(isa_irq > max_irq || isa_irq =3D=3D 2)) { @@ -632,6 +644,11 @@ void via_isa_set_irq(PCIDevice *d, ViaISAIRQSourceBit = n, int level) qemu_set_irq(s->isa_irqs[isa_irq], !!s->isa_irq_state[isa_irq]); } =20 +static void via_isa_pirq(void *opaque, int n, int level) +{ + via_isa_set_irq(opaque, VIA_IRQ_PIRQA + n, level); +} + static void via_isa_request_i8259_irq(void *opaque, int irq, int level) { ViaISAState *s =3D opaque; @@ -648,6 +665,7 @@ static void via_isa_realize(PCIDevice *d, Error **errp) int i; =20 qdev_init_gpio_out(dev, &s->cpu_intr, 1); + qdev_init_gpio_in_named(dev, via_isa_pirq, "pirq", PCI_NUM_PINS); isa_irq =3D qemu_allocate_irqs(via_isa_request_i8259_irq, s, 1); isa_bus =3D isa_bus_new(dev, pci_address_space(d), pci_address_space_i= o(d), errp); diff --git a/include/hw/isa/vt82c686.h b/include/hw/isa/vt82c686.h index a0f9f80401..e982c5fe26 100644 --- a/include/hw/isa/vt82c686.h +++ b/include/hw/isa/vt82c686.h @@ -14,6 +14,10 @@ typedef enum { VIA_IRQ_IDE1 =3D 1, VIA_IRQ_USB0 =3D 2, VIA_IRQ_USB1 =3D 3, + VIA_IRQ_PIRQA =3D 4, + VIA_IRQ_PIRQB =3D 5, + VIA_IRQ_PIRQC =3D 6, + VIA_IRQ_PIRQD =3D 7, } ViaISAIRQSourceBit; =20 void via_isa_set_irq(PCIDevice *d, ViaISAIRQSourceBit n, int level); --=20 2.30.7 From nobody Wed May 15 22:07:36 2024 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=fail(p=none dis=none) header.from=eik.bme.hu Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1677005166087825.3044803981159; Tue, 21 Feb 2023 10:46:06 -0800 (PST) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1pUXcg-0007Re-8y; Tue, 21 Feb 2023 13:44:18 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1pUXcc-0007Q3-T2; Tue, 21 Feb 2023 13:44:14 -0500 Received: from zero.eik.bme.hu ([2001:738:2001:2001::2001]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1pUXcZ-0006hY-Cc; Tue, 21 Feb 2023 13:44:14 -0500 Received: from zero.eik.bme.hu (blah.eik.bme.hu [152.66.115.182]) by localhost (Postfix) with SMTP id 8A32A7470B0; Tue, 21 Feb 2023 19:44:04 +0100 (CET) Received: by zero.eik.bme.hu (Postfix, from userid 432) id 654937470AF; Tue, 21 Feb 2023 19:44:04 +0100 (CET) Message-Id: In-Reply-To: References: From: BALATON Zoltan Subject: [PATCH 3/5] hw/ppc/pegasos2: Fix PCI interrupt routing MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable To: qemu-devel@nongnu.org, qemu-ppc@nongnu.org Cc: Gerd Hoffmann , Daniel Henrique Barboza , Bernhard Beschow , philmd@redhat.com Date: Tue, 21 Feb 2023 19:44:04 +0100 (CET) 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.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZM-MESSAGEID: 1677005168036100003 Content-Type: text/plain; charset="utf-8" According to the PegasosII schematics the PCI interrupt lines are connected to both the gpp pins of the Mv64361 north bridge and the PINT pins of the VT8231 south bridge so guests can get interrupts from either of these. So far we only had the MV64361 connections which worked for on board devices but for additional PCI devices (such as network or sound card added with -device) guest OSes expect interrupt from the ISA IRQ 9 where the firmware routes these PCI interrupts in VT8231 ISA bridge. After the previous patches we can now model this and also remove the board specific connection from mv64361. Also configure routing of these lines when using Virtual Open Firmware to match board firmware for guests that expect this. This fixes PCI interrupts on pegasos2 under Linux, MorphOS and AmigaOS. Signed-off-by: BALATON Zoltan Reviewed-by: Daniel Henrique Barboza --- hw/pci-host/mv64361.c | 4 ---- hw/ppc/pegasos2.c | 26 +++++++++++++++++++++++++- 2 files changed, 25 insertions(+), 5 deletions(-) diff --git a/hw/pci-host/mv64361.c b/hw/pci-host/mv64361.c index f43f33fbd9..3d9132f989 100644 --- a/hw/pci-host/mv64361.c +++ b/hw/pci-host/mv64361.c @@ -874,10 +874,6 @@ static void mv64361_realize(DeviceState *dev, Error **= errp) } sysbus_init_irq(SYS_BUS_DEVICE(dev), &s->cpu_irq); qdev_init_gpio_in_named(dev, mv64361_gpp_irq, "gpp", 32); - /* FIXME: PCI IRQ connections may be board specific */ - for (i =3D 0; i < PCI_NUM_PINS; i++) { - s->pci[1].irq[i] =3D qdev_get_gpio_in_named(dev, "gpp", 12 + i); - } } =20 static void mv64361_reset(DeviceState *dev) diff --git a/hw/ppc/pegasos2.c b/hw/ppc/pegasos2.c index a9563f4fb2..4e1476673b 100644 --- a/hw/ppc/pegasos2.c +++ b/hw/ppc/pegasos2.c @@ -74,6 +74,8 @@ struct Pegasos2MachineState { MachineState parent_obj; PowerPCCPU *cpu; DeviceState *mv; + qemu_irq mv_pirq[PCI_NUM_PINS]; + qemu_irq via_pirq[PCI_NUM_PINS]; Vof *vof; void *fdt_blob; uint64_t kernel_addr; @@ -96,6 +98,15 @@ static void pegasos2_cpu_reset(void *opaque) } } =20 +static void pegasos2_pci_irq(void *opaque, int n, int level) +{ + Pegasos2MachineState *pm =3D opaque; + + /* PCI interrupt lines are connected to both MV64361 and VT8231 */ + qemu_set_irq(pm->mv_pirq[n], level); + qemu_set_irq(pm->via_pirq[n], level); +} + static void pegasos2_init(MachineState *machine) { Pegasos2MachineState *pm =3D PEGASOS2_MACHINE(machine); @@ -107,7 +118,7 @@ static void pegasos2_init(MachineState *machine) I2CBus *i2c_bus; const char *fwname =3D machine->firmware ?: PROM_FILENAME; char *filename; - int sz; + int i, sz; uint8_t *spd_data; =20 /* init CPU */ @@ -157,11 +168,18 @@ static void pegasos2_init(MachineState *machine) /* Marvell Discovery II system controller */ pm->mv =3D DEVICE(sysbus_create_simple(TYPE_MV64361, -1, qdev_get_gpio_in(DEVICE(pm->cpu), PPC6xx_INPUT_I= NT))); + for (i =3D 0; i < PCI_NUM_PINS; i++) { + pm->mv_pirq[i] =3D qdev_get_gpio_in_named(pm->mv, "gpp", 12 + i); + } pci_bus =3D mv64361_get_pci_bus(pm->mv, 1); + pci_bus_irqs(pci_bus, pegasos2_pci_irq, pm, PCI_NUM_PINS); =20 /* VIA VT8231 South Bridge (multifunction PCI device) */ via =3D OBJECT(pci_create_simple_multifunction(pci_bus, PCI_DEVFN(12, = 0), true, TYPE_VT8231_ISA)); + for (i =3D 0; i < PCI_NUM_PINS; i++) { + pm->via_pirq[i] =3D qdev_get_gpio_in_named(DEVICE(via), "pirq", i); + } object_property_add_alias(OBJECT(machine), "rtc-time", object_resolve_path_component(via, "rtc"), "date"); @@ -268,6 +286,12 @@ static void pegasos2_machine_reset(MachineState *machi= ne, ShutdownCause reason) PCI_INTERRUPT_LINE, 2, 0x9); pegasos2_pci_config_write(pm, 1, (PCI_DEVFN(12, 0) << 8) | 0x50, 1, 0x2); + pegasos2_pci_config_write(pm, 1, (PCI_DEVFN(12, 0) << 8) | + 0x55, 1, 0x90); + pegasos2_pci_config_write(pm, 1, (PCI_DEVFN(12, 0) << 8) | + 0x56, 1, 0x99); + pegasos2_pci_config_write(pm, 1, (PCI_DEVFN(12, 0) << 8) | + 0x57, 1, 0x90); =20 pegasos2_pci_config_write(pm, 1, (PCI_DEVFN(12, 1) << 8) | PCI_INTERRUPT_LINE, 2, 0x109); --=20 2.30.7 From nobody Wed May 15 22:07:36 2024 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=fail(p=none dis=none) header.from=eik.bme.hu Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1677005108745893.8783212785788; Tue, 21 Feb 2023 10:45:08 -0800 (PST) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1pUXcd-0007Qb-Q7; Tue, 21 Feb 2023 13:44:15 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1pUXcb-0007Ot-H8; Tue, 21 Feb 2023 13:44:13 -0500 Received: from zero.eik.bme.hu ([2001:738:2001:2001::2001]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1pUXcY-0006hj-C7; Tue, 21 Feb 2023 13:44:13 -0500 Received: from zero.eik.bme.hu (blah.eik.bme.hu [152.66.115.182]) by localhost (Postfix) with SMTP id C029B7470B6; Tue, 21 Feb 2023 19:44:05 +0100 (CET) Received: by zero.eik.bme.hu (Postfix, from userid 432) id 6E4B57470AF; Tue, 21 Feb 2023 19:44:05 +0100 (CET) Message-Id: In-Reply-To: References: From: BALATON Zoltan Subject: [PATCH 4/5] hw/audio/ac97: Split off some definitions to a header MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable To: qemu-devel@nongnu.org, qemu-ppc@nongnu.org Cc: Gerd Hoffmann , Daniel Henrique Barboza , Bernhard Beschow , philmd@redhat.com Date: Tue, 21 Feb 2023 19:44:05 +0100 (CET) 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.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZM-MESSAGEID: 1677005109652100003 Content-Type: text/plain; charset="utf-8" These can be shared with other AC97 implementations. Signed-off-by: BALATON Zoltan Reviewed-by: Philippe Mathieu-Daud=C3=A9 --- hw/audio/ac97.c | 43 +------------------------------- hw/audio/ac97.h | 65 +++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 66 insertions(+), 42 deletions(-) create mode 100644 hw/audio/ac97.h diff --git a/hw/audio/ac97.c b/hw/audio/ac97.c index 364cdfa733..b3fb10284c 100644 --- a/hw/audio/ac97.c +++ b/hw/audio/ac97.c @@ -26,43 +26,7 @@ #include "qemu/module.h" #include "sysemu/dma.h" #include "qom/object.h" - -enum { - AC97_Reset =3D 0x00, - AC97_Master_Volume_Mute =3D 0x02, - AC97_Headphone_Volume_Mute =3D 0x04, - AC97_Master_Volume_Mono_Mute =3D 0x06, - AC97_Master_Tone_RL =3D 0x08, - AC97_PC_BEEP_Volume_Mute =3D 0x0A, - AC97_Phone_Volume_Mute =3D 0x0C, - AC97_Mic_Volume_Mute =3D 0x0E, - AC97_Line_In_Volume_Mute =3D 0x10, - AC97_CD_Volume_Mute =3D 0x12, - AC97_Video_Volume_Mute =3D 0x14, - AC97_Aux_Volume_Mute =3D 0x16, - AC97_PCM_Out_Volume_Mute =3D 0x18, - AC97_Record_Select =3D 0x1A, - AC97_Record_Gain_Mute =3D 0x1C, - AC97_Record_Gain_Mic_Mute =3D 0x1E, - AC97_General_Purpose =3D 0x20, - AC97_3D_Control =3D 0x22, - AC97_AC_97_RESERVED =3D 0x24, - AC97_Powerdown_Ctrl_Stat =3D 0x26, - AC97_Extended_Audio_ID =3D 0x28, - AC97_Extended_Audio_Ctrl_Stat =3D 0x2A, - AC97_PCM_Front_DAC_Rate =3D 0x2C, - AC97_PCM_Surround_DAC_Rate =3D 0x2E, - AC97_PCM_LFE_DAC_Rate =3D 0x30, - AC97_PCM_LR_ADC_Rate =3D 0x32, - AC97_MIC_ADC_Rate =3D 0x34, - AC97_6Ch_Vol_C_LFE_Mute =3D 0x36, - AC97_6Ch_Vol_L_R_Surround_Mute =3D 0x38, - AC97_Vendor_Reserved =3D 0x58, - AC97_Sigmatel_Analog =3D 0x6c, /* We emulate a Sigmatel code= c */ - AC97_Sigmatel_Dac2Invert =3D 0x6e, /* We emulate a Sigmatel code= c */ - AC97_Vendor_ID1 =3D 0x7c, - AC97_Vendor_ID2 =3D 0x7e -}; +#include "ac97.h" =20 #define SOFT_VOLUME #define SR_FIFOE 16 /* rwc */ @@ -121,11 +85,6 @@ enum { #define BD_IOC (1 << 31) #define BD_BUP (1 << 30) =20 -#define EACS_VRA 1 -#define EACS_VRM 8 - -#define MUTE_SHIFT 15 - #define TYPE_AC97 "AC97" OBJECT_DECLARE_SIMPLE_TYPE(AC97LinkState, AC97) =20 diff --git a/hw/audio/ac97.h b/hw/audio/ac97.h new file mode 100644 index 0000000000..0358b56ff4 --- /dev/null +++ b/hw/audio/ac97.h @@ -0,0 +1,65 @@ +/* + * Copyright (C) 2006 InnoTek Systemberatung GmbH + * + * This file is part of VirtualBox Open Source Edition (OSE), as + * available from http://www.virtualbox.org. This file is free software; + * you can redistribute it and/or modify it under the terms of the GNU + * General Public License as published by the Free Software Foundation, + * in version 2 as it comes in the "COPYING" file of the VirtualBox OSE + * distribution. VirtualBox OSE is distributed in the hope that it will + * be useful, but WITHOUT ANY WARRANTY of any kind. + * + * If you received this file as part of a commercial VirtualBox + * distribution, then only the terms of your commercial VirtualBox + * license agreement apply instead of the previous paragraph. + * + * Contributions after 2012-01-13 are licensed under the terms of the + * GNU GPL, version 2 or (at your option) any later version. + */ + +#ifndef AC97_H +#define AC97_H + +enum { + AC97_Reset =3D 0x00, + AC97_Master_Volume_Mute =3D 0x02, + AC97_Headphone_Volume_Mute =3D 0x04, + AC97_Master_Volume_Mono_Mute =3D 0x06, + AC97_Master_Tone_RL =3D 0x08, + AC97_PC_BEEP_Volume_Mute =3D 0x0A, + AC97_Phone_Volume_Mute =3D 0x0C, + AC97_Mic_Volume_Mute =3D 0x0E, + AC97_Line_In_Volume_Mute =3D 0x10, + AC97_CD_Volume_Mute =3D 0x12, + AC97_Video_Volume_Mute =3D 0x14, + AC97_Aux_Volume_Mute =3D 0x16, + AC97_PCM_Out_Volume_Mute =3D 0x18, + AC97_Record_Select =3D 0x1A, + AC97_Record_Gain_Mute =3D 0x1C, + AC97_Record_Gain_Mic_Mute =3D 0x1E, + AC97_General_Purpose =3D 0x20, + AC97_3D_Control =3D 0x22, + AC97_AC_97_RESERVED =3D 0x24, + AC97_Powerdown_Ctrl_Stat =3D 0x26, + AC97_Extended_Audio_ID =3D 0x28, + AC97_Extended_Audio_Ctrl_Stat =3D 0x2A, + AC97_PCM_Front_DAC_Rate =3D 0x2C, + AC97_PCM_Surround_DAC_Rate =3D 0x2E, + AC97_PCM_LFE_DAC_Rate =3D 0x30, + AC97_PCM_LR_ADC_Rate =3D 0x32, + AC97_MIC_ADC_Rate =3D 0x34, + AC97_6Ch_Vol_C_LFE_Mute =3D 0x36, + AC97_6Ch_Vol_L_R_Surround_Mute =3D 0x38, + AC97_Vendor_Reserved =3D 0x58, + AC97_Sigmatel_Analog =3D 0x6c, /* We emulate a Sigmatel code= c */ + AC97_Sigmatel_Dac2Invert =3D 0x6e, /* We emulate a Sigmatel code= c */ + AC97_Vendor_ID1 =3D 0x7c, + AC97_Vendor_ID2 =3D 0x7e +}; + +#define EACS_VRA 1 +#define EACS_VRM 8 + +#define MUTE_SHIFT 15 + +#endif /* AC97_H */ --=20 2.30.7 From nobody Wed May 15 22:07:36 2024 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=fail(p=none dis=none) header.from=eik.bme.hu Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 167700509320979.04273998268513; Tue, 21 Feb 2023 10:44:53 -0800 (PST) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1pUXco-0007T4-8X; Tue, 21 Feb 2023 13:44:26 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1pUXce-0007Qv-TX; Tue, 21 Feb 2023 13:44:16 -0500 Received: from zero.eik.bme.hu ([152.66.115.2]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1pUXcc-0006iC-BA; Tue, 21 Feb 2023 13:44:16 -0500 Received: from zero.eik.bme.hu (blah.eik.bme.hu [152.66.115.182]) by localhost (Postfix) with SMTP id B19F97470BC; Tue, 21 Feb 2023 19:44:06 +0100 (CET) Received: by zero.eik.bme.hu (Postfix, from userid 432) id 788FB7470AF; Tue, 21 Feb 2023 19:44:06 +0100 (CET) Message-Id: In-Reply-To: References: From: BALATON Zoltan Subject: [PATCH 5/5] hw/audio/via-ac97: Basic implementation of audio playback MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable To: qemu-devel@nongnu.org, qemu-ppc@nongnu.org Cc: Gerd Hoffmann , Daniel Henrique Barboza , Bernhard Beschow , philmd@redhat.com, vr_qemu@t-online.de Date: Tue, 21 Feb 2023 19:44:06 +0100 (CET) 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=152.66.115.2; envelope-from=balaton@eik.bme.hu; helo=zero.eik.bme.hu X-Spam_score_int: -25 X-Spam_score: -2.6 X-Spam_bar: -- X-Spam_report: (-2.6 / 5.0 requ) BAYES_00=-1.9, RCVD_IN_DNSWL_LOW=-0.7, 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.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZM-MESSAGEID: 1677005094661100005 Content-Type: text/plain; charset="utf-8" This adds basic implementation of the AC'97 sound part used in VIA south bridge chips. Not all features of the device is emulated, only one playback channel is supported but this is enough to get sound output from some guests running on machines using this device such as pegasos2. Signed-off-by: BALATON Zoltan --- hw/audio/trace-events | 6 + hw/audio/via-ac97.c | 436 +++++++++++++++++++++++++++++++++++++- hw/isa/vt82c686.c | 3 +- include/hw/isa/vt82c686.h | 26 +++ 4 files changed, 466 insertions(+), 5 deletions(-) diff --git a/hw/audio/trace-events b/hw/audio/trace-events index e0e71cd9b1..6eccdaa4b5 100644 --- a/hw/audio/trace-events +++ b/hw/audio/trace-events @@ -11,3 +11,9 @@ hda_audio_running(const char *stream, int nr, bool runnin= g) "st %s, nr %d, run % hda_audio_format(const char *stream, int chan, const char *fmt, int freq) = "st %s, %d x %s @ %d Hz" hda_audio_adjust(const char *stream, int pos) "st %s, pos %d" hda_audio_overrun(const char *stream) "st %s" + +#via-ac97.c +via_ac97_codec_write(uint8_t addr, uint16_t val) "0x%x <- 0x%x" +via_ac97_sgd_fetch(uint32_t addr, char stop, char eol, char flag, uint32_t= len) "addr=3D0x%x %c%c%c len=3D%d" +via_ac97_sgd_read(uint64_t addr, unsigned size, uint64_t val) "0x%"PRIx64"= %d -> 0x%"PRIx64 +via_ac97_sgd_write(uint64_t addr, unsigned size, uint64_t val) "0x%"PRIx64= " %d <- 0x%"PRIx64 diff --git a/hw/audio/via-ac97.c b/hw/audio/via-ac97.c index d1a856f63d..cdac5bc14b 100644 --- a/hw/audio/via-ac97.c +++ b/hw/audio/via-ac97.c @@ -1,39 +1,467 @@ /* * VIA south bridges sound support * + * Copyright (c) 2022-2023 BALATON Zoltan + * * This work is licensed under the GNU GPL license version 2 or later. */ =20 /* - * TODO: This is entirely boiler plate just registering empty PCI devices - * with the right ID guests expect, functionality should be added here. + * TODO: This is only a basic implementation of one audio playback channel + * more functionality should be added here. */ =20 #include "qemu/osdep.h" +#include "qemu/log.h" #include "hw/isa/vt82c686.h" -#include "hw/pci/pci_device.h" +#include "ac97.h" +#include "trace.h" + +#define CLEN_IS_EOL(x) ((x)->clen & BIT(31)) +#define CLEN_IS_FLAG(x) ((x)->clen & BIT(30)) +#define CLEN_IS_STOP(x) ((x)->clen & BIT(29)) +#define CLEN_LEN(x) ((x)->clen & 0xfff) + +#define STAT_ACTIVE BIT(7) +#define STAT_PAUSED BIT(6) +#define STAT_TRIG BIT(3) +#define STAT_STOP BIT(2) +#define STAT_EOL BIT(1) +#define STAT_FLAG BIT(0) + +#define CNTL_START BIT(7) +#define CNTL_TERM BIT(6) +#define CNTL_PAUSE BIT(3) + +static void open_voice_out(ViaAC97State *s); + +static uint16_t codec_rates[] =3D { 8000, 11025, 16000, 22050, 32000, 4410= 0, + 48000 }; + +#define CODEC_REG(s, o) ((s)->codec_regs[(o) / 2]) +#define CODEC_VOL(vol, mask) ((255 * ((vol) & mask)) / mask) + +static void codec_volume_set_out(ViaAC97State *s) +{ + int lvol, rvol, mute; + + lvol =3D 255 - CODEC_VOL(CODEC_REG(s, AC97_Master_Volume_Mute) >> 8, 0= x1f); + lvol *=3D 255 - CODEC_VOL(CODEC_REG(s, AC97_PCM_Out_Volume_Mute) >> 8,= 0x1f); + lvol /=3D 255; + rvol =3D 255 - CODEC_VOL(CODEC_REG(s, AC97_Master_Volume_Mute), 0x1f); + rvol *=3D 255 - CODEC_VOL(CODEC_REG(s, AC97_PCM_Out_Volume_Mute), 0x1f= ); + rvol /=3D 255; + mute =3D CODEC_REG(s, AC97_Master_Volume_Mute) >> MUTE_SHIFT; + mute |=3D CODEC_REG(s, AC97_PCM_Out_Volume_Mute) >> MUTE_SHIFT; + AUD_set_volume_out(s->vo, mute, lvol, rvol); +} + +static void codec_reset(ViaAC97State *s) +{ + memset(s->codec_regs, 0, sizeof(s->codec_regs)); + CODEC_REG(s, AC97_Reset) =3D 0x6a90; + CODEC_REG(s, AC97_Master_Volume_Mute) =3D 0x8000; + CODEC_REG(s, AC97_Headphone_Volume_Mute) =3D 0x8000; + CODEC_REG(s, AC97_Master_Volume_Mono_Mute) =3D 0x8000; + CODEC_REG(s, AC97_Phone_Volume_Mute) =3D 0x8008; + CODEC_REG(s, AC97_Mic_Volume_Mute) =3D 0x8008; + CODEC_REG(s, AC97_Line_In_Volume_Mute) =3D 0x8808; + CODEC_REG(s, AC97_CD_Volume_Mute) =3D 0x8808; + CODEC_REG(s, AC97_Video_Volume_Mute) =3D 0x8808; + CODEC_REG(s, AC97_Aux_Volume_Mute) =3D 0x8808; + CODEC_REG(s, AC97_PCM_Out_Volume_Mute) =3D 0x8808; + CODEC_REG(s, AC97_Record_Gain_Mute) =3D 0x8000; + CODEC_REG(s, AC97_Powerdown_Ctrl_Stat) =3D 0x000f; + CODEC_REG(s, AC97_Extended_Audio_ID) =3D 0x0a05; + CODEC_REG(s, AC97_Extended_Audio_Ctrl_Stat) =3D 0x0400; + CODEC_REG(s, AC97_PCM_Front_DAC_Rate) =3D 48000; + CODEC_REG(s, AC97_PCM_LR_ADC_Rate) =3D 48000; + /* Sigmatel 9766 (STAC9766) */ + CODEC_REG(s, AC97_Vendor_ID1) =3D 0x8384; + CODEC_REG(s, AC97_Vendor_ID2) =3D 0x7666; +} + +static uint16_t codec_read(ViaAC97State *s, uint8_t addr) +{ + return CODEC_REG(s, addr); +} + +static void codec_write(ViaAC97State *s, uint8_t addr, uint16_t val) +{ + trace_via_ac97_codec_write(addr, val); + switch (addr) { + case AC97_Reset: + codec_reset(s); + return; + case AC97_Master_Volume_Mute: + case AC97_PCM_Out_Volume_Mute: + if (addr =3D=3D AC97_Master_Volume_Mute) { + if (val & BIT(13)) { + val |=3D 0x1f00; + } + if (val & BIT(5)) { + val |=3D 0x1f; + } + } + CODEC_REG(s, addr) =3D val & 0x9f1f; + codec_volume_set_out(s); + return; + case AC97_Extended_Audio_Ctrl_Stat: + CODEC_REG(s, addr) &=3D ~EACS_VRA; + CODEC_REG(s, addr) |=3D val & EACS_VRA; + if (!(val & EACS_VRA)) { + CODEC_REG(s, AC97_PCM_Front_DAC_Rate) =3D 48000; + CODEC_REG(s, AC97_PCM_LR_ADC_Rate) =3D 48000; + open_voice_out(s); + } + return; + case AC97_PCM_Front_DAC_Rate: + case AC97_PCM_LR_ADC_Rate: + if (CODEC_REG(s, AC97_Extended_Audio_Ctrl_Stat) & EACS_VRA) { + int i; + uint16_t rate =3D val; + + for (i =3D 0; i < ARRAY_SIZE(codec_rates) - 1; i++) { + if (rate < codec_rates[i] + + (codec_rates[i + 1] - codec_rates[i]) / 2) { + rate =3D codec_rates[i]; + break; + } + } + if (rate > 48000) { + rate =3D 48000; + } + CODEC_REG(s, addr) =3D rate; + open_voice_out(s); + } + return; + case AC97_Powerdown_Ctrl_Stat: + CODEC_REG(s, addr) =3D (val & 0xff00) | (CODEC_REG(s, addr) & 0xff= ); + return; + case AC97_Extended_Audio_ID: + case AC97_Vendor_ID1: + case AC97_Vendor_ID2: + /* Read only registers */ + return; + default: + qemu_log_mask(LOG_UNIMP, + "via-ac97: Unimplemented codec register 0x%x\n", add= r); + CODEC_REG(s, addr) =3D val; + } +} + +static void fetch_sgd(ViaAC97SGDChannel *c, PCIDevice *d) +{ + uint32_t b[2]; + + if (c->curr < c->base) { + c->curr =3D c->base; + } + pci_dma_read(d, c->curr, b, sizeof(b)); + c->addr =3D le32_to_cpu(b[0]); + c->clen =3D le32_to_cpu(b[1]); + trace_via_ac97_sgd_fetch(c->addr, CLEN_IS_STOP(c) ? 'S' : '-', + CLEN_IS_EOL(c) ? 'E' : '-', + CLEN_IS_FLAG(c) ? 'F' : '-', CLEN_LEN(c)); +} + +static void out_cb(void *opaque, int avail) +{ + ViaAC97State *s =3D opaque; + ViaAC97SGDChannel *c =3D &s->aur; + int temp, to_copy, copied; + bool stop =3D false; + uint8_t tmpbuf[4096]; + + if (c->stat & STAT_PAUSED) { + return; + } + c->stat |=3D STAT_ACTIVE; + while (avail && !stop) { + if (!c->clen) { + fetch_sgd(c, &s->dev); + } + temp =3D MIN(CLEN_LEN(c), avail); + while (temp) { + to_copy =3D MIN(temp, sizeof(tmpbuf)); + pci_dma_read(&s->dev, c->addr, tmpbuf, to_copy); + copied =3D AUD_write(s->vo, tmpbuf, to_copy); + if (!copied) { + stop =3D true; + break; + } + temp -=3D copied; + avail -=3D copied; + c->addr +=3D copied; + c->clen -=3D copied; + } + if (CLEN_LEN(c) =3D=3D 0) { + c->curr +=3D 8; + if (CLEN_IS_EOL(c)) { + c->stat |=3D STAT_EOL; + if (c->type & CNTL_START) { + c->curr =3D c->base; + c->stat |=3D STAT_PAUSED; + } else { + c->stat &=3D ~STAT_ACTIVE; + AUD_set_active_out(s->vo, 0); + } + if (c->type & STAT_EOL) { + via_isa_set_irq(&s->dev, VIA_IRQ_AC97, 1); + } + } + if (CLEN_IS_FLAG(c)) { + c->stat |=3D STAT_FLAG; + c->stat |=3D STAT_PAUSED; + if (c->type & STAT_FLAG) { + via_isa_set_irq(&s->dev, VIA_IRQ_AC97, 1); + } + } + if (CLEN_IS_STOP(c)) { + c->stat |=3D STAT_STOP; + c->stat |=3D STAT_PAUSED; + } + c->clen =3D 0; + stop =3D true; + } + } +} + +static void open_voice_out(ViaAC97State *s) +{ + struct audsettings as =3D { + .freq =3D CODEC_REG(s, AC97_PCM_Front_DAC_Rate), + .nchannels =3D s->aur.type & BIT(4) ? 2 : 1, + .fmt =3D s->aur.type & BIT(5) ? AUDIO_FORMAT_S16 : AUDIO_FORMAT_S8, + .endianness =3D 0, + }; + s->vo =3D AUD_open_out(&s->card, s->vo, "via-ac97.out", s, out_cb, &as= ); +} + +static uint64_t sgd_read(void *opaque, hwaddr addr, unsigned size) +{ + ViaAC97State *s =3D opaque; + uint64_t val =3D 0; + + switch (addr) { + case 0: + val =3D s->aur.stat; + if (s->aur.type & CNTL_START) { + val |=3D STAT_TRIG; + } + break; + case 1: + val =3D s->aur.stat & STAT_PAUSED ? BIT(3) : 0; + break; + case 2: + val =3D s->aur.type; + break; + case 4: + val =3D s->aur.curr; + break; + case 0xc: + val =3D CLEN_LEN(&s->aur); + break; + case 0x80: + val =3D s->ac97_cmd; + break; + case 0x84: + val =3D s->aur.stat & STAT_FLAG; + if (s->aur.stat & STAT_EOL) { + val |=3D BIT(4); + } + if (s->aur.stat & STAT_STOP) { + val |=3D BIT(8); + } + if (s->aur.stat & STAT_ACTIVE) { + val |=3D BIT(12); + } + break; + default: + qemu_log_mask(LOG_UNIMP, "via-ac97: Unimplemented register read %" + HWADDR_PRIx"\n", addr); + } + trace_via_ac97_sgd_read(addr, size, val); + return val; +} + +static void sgd_write(void *opaque, hwaddr addr, uint64_t val, unsigned si= ze) +{ + ViaAC97State *s =3D opaque; + + trace_via_ac97_sgd_write(addr, size, val); + switch (addr) { + case 0: + if (val & STAT_STOP) { + s->aur.stat &=3D ~STAT_PAUSED; + } + if (val & STAT_EOL) { + s->aur.stat &=3D ~(STAT_EOL | STAT_PAUSED); + if (s->aur.type & STAT_EOL) { + via_isa_set_irq(&s->dev, VIA_IRQ_AC97, 0); + } + } + if (val & STAT_FLAG) { + s->aur.stat &=3D ~(STAT_FLAG | STAT_PAUSED); + if (s->aur.type & STAT_FLAG) { + via_isa_set_irq(&s->dev, VIA_IRQ_AC97, 0); + } + } + break; + case 1: + if (val & CNTL_START) { + AUD_set_active_out(s->vo, 1); + s->aur.stat =3D STAT_ACTIVE; + } + if (val & CNTL_TERM) { + AUD_set_active_out(s->vo, 0); + s->aur.stat &=3D ~(STAT_ACTIVE | STAT_PAUSED); + s->aur.clen =3D 0; + } + if (val & CNTL_PAUSE) { + AUD_set_active_out(s->vo, 0); + s->aur.stat &=3D ~STAT_ACTIVE; + s->aur.stat |=3D STAT_PAUSED; + } else if (!(val & CNTL_PAUSE) && (s->aur.stat & STAT_PAUSED)) { + AUD_set_active_out(s->vo, 1); + s->aur.stat |=3D STAT_ACTIVE; + s->aur.stat &=3D ~STAT_PAUSED; + } + break; + case 2: + { + uint32_t oldval =3D s->aur.type; + s->aur.type =3D val; + if ((oldval & 0x30) !=3D (val & 0x30)) { + open_voice_out(s); + } + break; + } + case 4: + s->aur.base =3D val & ~1ULL; + break; + case 0x80: + if (val >> 30) { + /* we only have primary codec */ + break; + } + if (val & BIT(23)) { /* read reg */ + s->ac97_cmd =3D val & 0xc0ff0000ULL; + s->ac97_cmd |=3D codec_read(s, (val >> 16) & 0x7f); + s->ac97_cmd |=3D BIT(25); /* data valid */ + } else { + s->ac97_cmd =3D val & 0xc0ffffffULL; + codec_write(s, (val >> 16) & 0x7f, val); + } + break; + case 0xc: + case 0x84: + /* Read only */ + break; + default: + qemu_log_mask(LOG_UNIMP, "via-ac97: Unimplemented register write %" + HWADDR_PRIx"\n", addr); + } +} + +static const MemoryRegionOps sgd_ops =3D { + .read =3D sgd_read, + .write =3D sgd_write, + .endianness =3D DEVICE_LITTLE_ENDIAN, +}; + +static uint64_t fm_read(void *opaque, hwaddr addr, unsigned size) +{ + qemu_log_mask(LOG_UNIMP, "%s: 0x%"HWADDR_PRIx" %d\n", __func__, addr, = size); + return 0; +} + +static void fm_write(void *opaque, hwaddr addr, uint64_t val, unsigned siz= e) +{ + qemu_log_mask(LOG_UNIMP, "%s: 0x%"HWADDR_PRIx" %d <=3D 0x%"PRIX64"\n", + __func__, addr, size, val); +} + +static const MemoryRegionOps fm_ops =3D { + .read =3D fm_read, + .write =3D fm_write, + .endianness =3D DEVICE_LITTLE_ENDIAN, +}; + +static uint64_t midi_read(void *opaque, hwaddr addr, unsigned size) +{ + qemu_log_mask(LOG_UNIMP, "%s: 0x%"HWADDR_PRIx" %d\n", __func__, addr, = size); + return 0; +} + +static void midi_write(void *opaque, hwaddr addr, uint64_t val, unsigned s= ize) +{ + qemu_log_mask(LOG_UNIMP, "%s: 0x%"HWADDR_PRIx" %d <=3D 0x%"PRIX64"\n", + __func__, addr, size, val); +} + +static const MemoryRegionOps midi_ops =3D { + .read =3D midi_read, + .write =3D midi_write, + .endianness =3D DEVICE_LITTLE_ENDIAN, +}; + +static void via_ac97_reset(DeviceState *dev) +{ + ViaAC97State *s =3D VIA_AC97(dev); + + codec_reset(s); +} =20 static void via_ac97_realize(PCIDevice *pci_dev, Error **errp) { + ViaAC97State *s =3D VIA_AC97(pci_dev); + Object *o =3D OBJECT(s); + pci_set_word(pci_dev->config + PCI_COMMAND, PCI_COMMAND_INVALIDATE | PCI_COMMAND_PARITY); pci_set_word(pci_dev->config + PCI_STATUS, PCI_STATUS_CAP_LIST | PCI_STATUS_DEVSEL_MEDIUM); pci_set_long(pci_dev->config + PCI_INTERRUPT_PIN, 0x03); + + memory_region_init_io(&s->sgd, o, &sgd_ops, s, "via-ac97.sgd", 256); + pci_register_bar(pci_dev, 0, PCI_BASE_ADDRESS_SPACE_IO, &s->sgd); + memory_region_init_io(&s->fm, o, &fm_ops, s, "via-ac97.fm", 4); + pci_register_bar(pci_dev, 1, PCI_BASE_ADDRESS_SPACE_IO, &s->fm); + memory_region_init_io(&s->midi, o, &midi_ops, s, "via-ac97.midi", 4); + pci_register_bar(pci_dev, 2, PCI_BASE_ADDRESS_SPACE_IO, &s->midi); + + AUD_register_card ("via-ac97", &s->card); } =20 +static void via_ac97_exit(PCIDevice *dev) +{ + ViaAC97State *s =3D VIA_AC97(dev); + + AUD_close_out(&s->card, s->vo); + AUD_remove_card(&s->card); +} + +static Property via_ac97_properties[] =3D { + DEFINE_AUDIO_PROPERTIES(ViaAC97State, card), + DEFINE_PROP_END_OF_LIST(), +}; + static void via_ac97_class_init(ObjectClass *klass, void *data) { DeviceClass *dc =3D DEVICE_CLASS(klass); PCIDeviceClass *k =3D PCI_DEVICE_CLASS(klass); =20 k->realize =3D via_ac97_realize; + k->exit =3D via_ac97_exit; k->vendor_id =3D PCI_VENDOR_ID_VIA; k->device_id =3D PCI_DEVICE_ID_VIA_AC97; k->revision =3D 0x50; k->class_id =3D PCI_CLASS_MULTIMEDIA_AUDIO; + device_class_set_props(dc, via_ac97_properties); set_bit(DEVICE_CATEGORY_SOUND, dc->categories); dc->desc =3D "VIA AC97"; + dc->reset =3D via_ac97_reset; /* Reason: Part of a south bridge chip */ dc->user_creatable =3D false; } @@ -41,7 +469,7 @@ static void via_ac97_class_init(ObjectClass *klass, void= *data) static const TypeInfo via_ac97_info =3D { .name =3D TYPE_VIA_AC97, .parent =3D TYPE_PCI_DEVICE, - .instance_size =3D sizeof(PCIDevice), + .instance_size =3D sizeof(ViaAC97State), .class_init =3D via_ac97_class_init, .interfaces =3D (InterfaceInfo[]) { { INTERFACE_CONVENTIONAL_PCI_DEVICE }, diff --git a/hw/isa/vt82c686.c b/hw/isa/vt82c686.c index f31b2fa7ca..b16620daf8 100644 --- a/hw/isa/vt82c686.c +++ b/hw/isa/vt82c686.c @@ -555,7 +555,7 @@ struct ViaISAState { PCIIDEState ide; UHCIState uhci[2]; ViaPMState pm; - PCIDevice ac97; + ViaAC97State ac97; PCIDevice mc97; }; =20 @@ -610,6 +610,7 @@ void via_isa_set_irq(PCIDevice *d, ViaISAIRQSourceBit n= , int level) break; case VIA_IRQ_USB0: case VIA_IRQ_USB1: + case VIA_IRQ_AC97: max_irq =3D 14; isa_irq =3D d->config[PCI_INTERRUPT_LINE]; break; diff --git a/include/hw/isa/vt82c686.h b/include/hw/isa/vt82c686.h index e982c5fe26..f7258d01df 100644 --- a/include/hw/isa/vt82c686.h +++ b/include/hw/isa/vt82c686.h @@ -1,6 +1,8 @@ #ifndef HW_VT82C686_H #define HW_VT82C686_H =20 +#include "hw/pci/pci_device.h" +#include "audio/audio.h" =20 #define TYPE_VT82C686B_ISA "vt82c686b-isa" #define TYPE_VT82C686B_USB_UHCI "vt82c686b-usb-uhci" @@ -9,6 +11,29 @@ #define TYPE_VIA_IDE "via-ide" #define TYPE_VIA_MC97 "via-mc97" =20 +typedef struct { + uint8_t stat; + uint8_t type; + uint32_t base; + uint32_t curr; + uint32_t addr; + uint32_t clen; +} ViaAC97SGDChannel; + +OBJECT_DECLARE_SIMPLE_TYPE(ViaAC97State, VIA_AC97); + +struct ViaAC97State { + PCIDevice dev; + QEMUSoundCard card; + MemoryRegion sgd; + MemoryRegion fm; + MemoryRegion midi; + SWVoiceOut *vo; + ViaAC97SGDChannel aur; + uint16_t codec_regs[128]; + uint32_t ac97_cmd; +}; + typedef enum { VIA_IRQ_IDE0 =3D 0, VIA_IRQ_IDE1 =3D 1, @@ -18,6 +43,7 @@ typedef enum { VIA_IRQ_PIRQB =3D 5, VIA_IRQ_PIRQC =3D 6, VIA_IRQ_PIRQD =3D 7, + VIA_IRQ_AC97 =3D 8, } ViaISAIRQSourceBit; =20 void via_isa_set_irq(PCIDevice *d, ViaISAIRQSourceBit n, int level); --=20 2.30.7