All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 0/5] Pegasos2 fixes and audio output support
@ 2023-02-21 18:44 BALATON Zoltan
  2023-02-21 18:44 ` [PATCH 1/5] hw/isa/vt82c686: Implement interrupt routing in via_isa_set_irq BALATON Zoltan
                   ` (5 more replies)
  0 siblings, 6 replies; 40+ messages in thread
From: BALATON Zoltan @ 2023-02-21 18:44 UTC (permalink / raw)
  To: qemu-devel, qemu-ppc
  Cc: Gerd Hoffmann, Daniel Henrique Barboza, Bernhard Beschow, philmd

This series fixes PCI interrupts on the ppc/pegasos2 machine and adds
partial implementation of the via-ac97 sound part enough to get audio
output. I'd like this to be merged for QEMU 8.0.

Regards,
BALATON Zoltan

BALATON Zoltan (5):
  hw/isa/vt82c686: Implement interrupt routing in via_isa_set_irq
  hw/isa/vt82c686: Implement PIRQ pins
  hw/ppc/pegasos2: Fix PCI interrupt routing
  hw/audio/ac97: Split off some definitions to a header
  hw/audio/via-ac97: Basic implementation of audio playback

 hw/audio/ac97.c            |  43 +---
 hw/audio/ac97.h            |  65 ++++++
 hw/audio/trace-events      |   6 +
 hw/audio/via-ac97.c        | 436 ++++++++++++++++++++++++++++++++++++-
 hw/ide/via.c               |   2 +-
 hw/isa/vt82c686.c          |  61 +++++-
 hw/pci-host/mv64361.c      |   4 -
 hw/ppc/pegasos2.c          |  26 ++-
 hw/usb/vt82c686-uhci-pci.c |   5 +-
 include/hw/isa/vt82c686.h  |  39 +++-
 10 files changed, 626 insertions(+), 61 deletions(-)
 create mode 100644 hw/audio/ac97.h

-- 
2.30.7



^ permalink raw reply	[flat|nested] 40+ messages in thread

* [PATCH 1/5] hw/isa/vt82c686: Implement interrupt routing in via_isa_set_irq
  2023-02-21 18:44 [PATCH 0/5] Pegasos2 fixes and audio output support BALATON Zoltan
@ 2023-02-21 18:44 ` BALATON Zoltan
  2023-02-21 18:44 ` [PATCH 2/5] hw/isa/vt82c686: Implement PIRQ pins BALATON Zoltan
                   ` (4 subsequent siblings)
  5 siblings, 0 replies; 40+ messages in thread
From: BALATON Zoltan @ 2023-02-21 18:44 UTC (permalink / raw)
  To: qemu-devel, qemu-ppc
  Cc: Gerd Hoffmann, Daniel Henrique Barboza, Bernhard Beschow, philmd

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 <balaton@eik.bme.hu>
---
 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 level)
         d->config[0x70 + n * 8] &= ~0x80;
     }
 
-    via_isa_set_irq(pci_get_function_0(d), 14 + n, level);
+    via_isa_set_irq(d, VIA_IRQ_IDE0 + n, level);
 }
 
 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 = {
     },
 };
 
-void via_isa_set_irq(PCIDevice *d, int n, int level)
+void via_isa_set_irq(PCIDevice *d, ViaISAIRQSourceBit n, int level)
 {
-    ViaISAState *s = VIA_ISA(d);
-    qemu_set_irq(s->isa_irqs[n], level);
+    ViaISAState *s = VIA_ISA(pci_get_function_0(d));
+    uint8_t isa_irq = 0, max_irq = 15;
+
+    if (n == VIA_IRQ_USB0 && d == PCI_DEVICE(&s->uhci[1])) {
+        n++;
+    }
+    switch (n) {
+    case VIA_IRQ_IDE0:
+        isa_irq = 14;
+        break;
+    case VIA_IRQ_IDE1:
+        isa_irq = 15;
+        break;
+    case VIA_IRQ_USB0:
+    case VIA_IRQ_USB1:
+        max_irq = 14;
+        isa_irq = d->config[PCI_INTERRUPT_LINE];
+        break;
+    }
+
+    if (unlikely(isa_irq > max_irq || isa_irq == 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] |= BIT(n);
+    } else {
+        s->isa_irq_state[isa_irq] &= ~BIT(n);
+    }
+    qemu_set_irq(s->isa_irqs[isa_irq], !!s->isa_irq_state[isa_irq]);
 }
 
 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 = opaque;
-    uint8_t irq = 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);
 }
 
 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"
 
-void via_isa_set_irq(PCIDevice *d, int n, int level);
+typedef enum {
+    VIA_IRQ_IDE0 = 0,
+    VIA_IRQ_IDE1 = 1,
+    VIA_IRQ_USB0 = 2,
+    VIA_IRQ_USB1 = 3,
+} ViaISAIRQSourceBit;
+
+void via_isa_set_irq(PCIDevice *d, ViaISAIRQSourceBit n, int level);
 
 #endif
-- 
2.30.7



^ permalink raw reply related	[flat|nested] 40+ messages in thread

* [PATCH 2/5] hw/isa/vt82c686: Implement PIRQ pins
  2023-02-21 18:44 [PATCH 0/5] Pegasos2 fixes and audio output support BALATON Zoltan
  2023-02-21 18:44 ` [PATCH 1/5] hw/isa/vt82c686: Implement interrupt routing in via_isa_set_irq BALATON Zoltan
@ 2023-02-21 18:44 ` BALATON Zoltan
  2023-02-21 18:44 ` [PATCH 3/5] hw/ppc/pegasos2: Fix PCI interrupt routing BALATON Zoltan
                   ` (3 subsequent siblings)
  5 siblings, 0 replies; 40+ messages in thread
From: BALATON Zoltan @ 2023-02-21 18:44 UTC (permalink / raw)
  To: qemu-devel, qemu-ppc
  Cc: Gerd Hoffmann, Daniel Henrique Barboza, Bernhard Beschow, philmd

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 <balaton@eik.bme.hu>
---
 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 = 14;
         isa_irq = d->config[PCI_INTERRUPT_LINE];
         break;
+    case VIA_IRQ_PIRQA:
+        isa_irq = d->config[0x55] >> 4;
+        break;
+    case VIA_IRQ_PIRQB:
+        isa_irq = d->config[0x56] & 0xf;
+        break;
+    case VIA_IRQ_PIRQC:
+        isa_irq = d->config[0x56] >> 4;
+        break;
+    case VIA_IRQ_PIRQD:
+        isa_irq = d->config[0x57] >> 4;
+        break;
     }
 
     if (unlikely(isa_irq > max_irq || isa_irq == 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]);
 }
 
+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 = opaque;
@@ -648,6 +665,7 @@ static void via_isa_realize(PCIDevice *d, Error **errp)
     int i;
 
     qdev_init_gpio_out(dev, &s->cpu_intr, 1);
+    qdev_init_gpio_in_named(dev, via_isa_pirq, "pirq", PCI_NUM_PINS);
     isa_irq = qemu_allocate_irqs(via_isa_request_i8259_irq, s, 1);
     isa_bus = isa_bus_new(dev, pci_address_space(d), pci_address_space_io(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 = 1,
     VIA_IRQ_USB0 = 2,
     VIA_IRQ_USB1 = 3,
+    VIA_IRQ_PIRQA = 4,
+    VIA_IRQ_PIRQB = 5,
+    VIA_IRQ_PIRQC = 6,
+    VIA_IRQ_PIRQD = 7,
 } ViaISAIRQSourceBit;
 
 void via_isa_set_irq(PCIDevice *d, ViaISAIRQSourceBit n, int level);
-- 
2.30.7



^ permalink raw reply related	[flat|nested] 40+ messages in thread

* [PATCH 3/5] hw/ppc/pegasos2: Fix PCI interrupt routing
  2023-02-21 18:44 [PATCH 0/5] Pegasos2 fixes and audio output support BALATON Zoltan
  2023-02-21 18:44 ` [PATCH 1/5] hw/isa/vt82c686: Implement interrupt routing in via_isa_set_irq BALATON Zoltan
  2023-02-21 18:44 ` [PATCH 2/5] hw/isa/vt82c686: Implement PIRQ pins BALATON Zoltan
@ 2023-02-21 18:44 ` BALATON Zoltan
  2023-02-24 17:04   ` Daniel Henrique Barboza
  2023-02-25 19:34   ` Philippe Mathieu-Daudé
  2023-02-21 18:44 ` [PATCH 4/5] hw/audio/ac97: Split off some definitions to a header BALATON Zoltan
                   ` (2 subsequent siblings)
  5 siblings, 2 replies; 40+ messages in thread
From: BALATON Zoltan @ 2023-02-21 18:44 UTC (permalink / raw)
  To: qemu-devel, qemu-ppc
  Cc: Gerd Hoffmann, Daniel Henrique Barboza, Bernhard Beschow, philmd

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 <balaton@eik.bme.hu>
---
 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 = 0; i < PCI_NUM_PINS; i++) {
-        s->pci[1].irq[i] = qdev_get_gpio_in_named(dev, "gpp", 12 + i);
-    }
 }
 
 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)
     }
 }
 
+static void pegasos2_pci_irq(void *opaque, int n, int level)
+{
+    Pegasos2MachineState *pm = 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 = PEGASOS2_MACHINE(machine);
@@ -107,7 +118,7 @@ static void pegasos2_init(MachineState *machine)
     I2CBus *i2c_bus;
     const char *fwname = machine->firmware ?: PROM_FILENAME;
     char *filename;
-    int sz;
+    int i, sz;
     uint8_t *spd_data;
 
     /* init CPU */
@@ -157,11 +168,18 @@ static void pegasos2_init(MachineState *machine)
     /* Marvell Discovery II system controller */
     pm->mv = DEVICE(sysbus_create_simple(TYPE_MV64361, -1,
                           qdev_get_gpio_in(DEVICE(pm->cpu), PPC6xx_INPUT_INT)));
+    for (i = 0; i < PCI_NUM_PINS; i++) {
+        pm->mv_pirq[i] = qdev_get_gpio_in_named(pm->mv, "gpp", 12 + i);
+    }
     pci_bus = mv64361_get_pci_bus(pm->mv, 1);
+    pci_bus_irqs(pci_bus, pegasos2_pci_irq, pm, PCI_NUM_PINS);
 
     /* VIA VT8231 South Bridge (multifunction PCI device) */
     via = OBJECT(pci_create_simple_multifunction(pci_bus, PCI_DEVFN(12, 0),
                                                  true, TYPE_VT8231_ISA));
+    for (i = 0; i < PCI_NUM_PINS; i++) {
+        pm->via_pirq[i] = 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 *machine, 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);
 
     pegasos2_pci_config_write(pm, 1, (PCI_DEVFN(12, 1) << 8) |
                               PCI_INTERRUPT_LINE, 2, 0x109);
-- 
2.30.7



^ permalink raw reply related	[flat|nested] 40+ messages in thread

* [PATCH 4/5] hw/audio/ac97: Split off some definitions to a header
  2023-02-21 18:44 [PATCH 0/5] Pegasos2 fixes and audio output support BALATON Zoltan
                   ` (2 preceding siblings ...)
  2023-02-21 18:44 ` [PATCH 3/5] hw/ppc/pegasos2: Fix PCI interrupt routing BALATON Zoltan
@ 2023-02-21 18:44 ` BALATON Zoltan
  2023-02-25 19:35   ` Philippe Mathieu-Daudé
  2023-02-21 18:44 ` [PATCH 5/5] hw/audio/via-ac97: Basic implementation of audio playback BALATON Zoltan
  2023-02-22 15:38 ` [PATCH 0/5] Pegasos2 fixes and audio output support Bernhard Beschow
  5 siblings, 1 reply; 40+ messages in thread
From: BALATON Zoltan @ 2023-02-21 18:44 UTC (permalink / raw)
  To: qemu-devel, qemu-ppc
  Cc: Gerd Hoffmann, Daniel Henrique Barboza, Bernhard Beschow, philmd

These can be shared with other AC97 implementations.

Signed-off-by: BALATON Zoltan <balaton@eik.bme.hu>
---
 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                     = 0x00,
-    AC97_Master_Volume_Mute        = 0x02,
-    AC97_Headphone_Volume_Mute     = 0x04,
-    AC97_Master_Volume_Mono_Mute   = 0x06,
-    AC97_Master_Tone_RL            = 0x08,
-    AC97_PC_BEEP_Volume_Mute       = 0x0A,
-    AC97_Phone_Volume_Mute         = 0x0C,
-    AC97_Mic_Volume_Mute           = 0x0E,
-    AC97_Line_In_Volume_Mute       = 0x10,
-    AC97_CD_Volume_Mute            = 0x12,
-    AC97_Video_Volume_Mute         = 0x14,
-    AC97_Aux_Volume_Mute           = 0x16,
-    AC97_PCM_Out_Volume_Mute       = 0x18,
-    AC97_Record_Select             = 0x1A,
-    AC97_Record_Gain_Mute          = 0x1C,
-    AC97_Record_Gain_Mic_Mute      = 0x1E,
-    AC97_General_Purpose           = 0x20,
-    AC97_3D_Control                = 0x22,
-    AC97_AC_97_RESERVED            = 0x24,
-    AC97_Powerdown_Ctrl_Stat       = 0x26,
-    AC97_Extended_Audio_ID         = 0x28,
-    AC97_Extended_Audio_Ctrl_Stat  = 0x2A,
-    AC97_PCM_Front_DAC_Rate        = 0x2C,
-    AC97_PCM_Surround_DAC_Rate     = 0x2E,
-    AC97_PCM_LFE_DAC_Rate          = 0x30,
-    AC97_PCM_LR_ADC_Rate           = 0x32,
-    AC97_MIC_ADC_Rate              = 0x34,
-    AC97_6Ch_Vol_C_LFE_Mute        = 0x36,
-    AC97_6Ch_Vol_L_R_Surround_Mute = 0x38,
-    AC97_Vendor_Reserved           = 0x58,
-    AC97_Sigmatel_Analog           = 0x6c, /* We emulate a Sigmatel codec */
-    AC97_Sigmatel_Dac2Invert       = 0x6e, /* We emulate a Sigmatel codec */
-    AC97_Vendor_ID1                = 0x7c,
-    AC97_Vendor_ID2                = 0x7e
-};
+#include "ac97.h"
 
 #define SOFT_VOLUME
 #define SR_FIFOE 16             /* rwc */
@@ -121,11 +85,6 @@ enum {
 #define BD_IOC (1 << 31)
 #define BD_BUP (1 << 30)
 
-#define EACS_VRA 1
-#define EACS_VRM 8
-
-#define MUTE_SHIFT 15
-
 #define TYPE_AC97 "AC97"
 OBJECT_DECLARE_SIMPLE_TYPE(AC97LinkState, AC97)
 
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                     = 0x00,
+    AC97_Master_Volume_Mute        = 0x02,
+    AC97_Headphone_Volume_Mute     = 0x04,
+    AC97_Master_Volume_Mono_Mute   = 0x06,
+    AC97_Master_Tone_RL            = 0x08,
+    AC97_PC_BEEP_Volume_Mute       = 0x0A,
+    AC97_Phone_Volume_Mute         = 0x0C,
+    AC97_Mic_Volume_Mute           = 0x0E,
+    AC97_Line_In_Volume_Mute       = 0x10,
+    AC97_CD_Volume_Mute            = 0x12,
+    AC97_Video_Volume_Mute         = 0x14,
+    AC97_Aux_Volume_Mute           = 0x16,
+    AC97_PCM_Out_Volume_Mute       = 0x18,
+    AC97_Record_Select             = 0x1A,
+    AC97_Record_Gain_Mute          = 0x1C,
+    AC97_Record_Gain_Mic_Mute      = 0x1E,
+    AC97_General_Purpose           = 0x20,
+    AC97_3D_Control                = 0x22,
+    AC97_AC_97_RESERVED            = 0x24,
+    AC97_Powerdown_Ctrl_Stat       = 0x26,
+    AC97_Extended_Audio_ID         = 0x28,
+    AC97_Extended_Audio_Ctrl_Stat  = 0x2A,
+    AC97_PCM_Front_DAC_Rate        = 0x2C,
+    AC97_PCM_Surround_DAC_Rate     = 0x2E,
+    AC97_PCM_LFE_DAC_Rate          = 0x30,
+    AC97_PCM_LR_ADC_Rate           = 0x32,
+    AC97_MIC_ADC_Rate              = 0x34,
+    AC97_6Ch_Vol_C_LFE_Mute        = 0x36,
+    AC97_6Ch_Vol_L_R_Surround_Mute = 0x38,
+    AC97_Vendor_Reserved           = 0x58,
+    AC97_Sigmatel_Analog           = 0x6c, /* We emulate a Sigmatel codec */
+    AC97_Sigmatel_Dac2Invert       = 0x6e, /* We emulate a Sigmatel codec */
+    AC97_Vendor_ID1                = 0x7c,
+    AC97_Vendor_ID2                = 0x7e
+};
+
+#define EACS_VRA 1
+#define EACS_VRM 8
+
+#define MUTE_SHIFT 15
+
+#endif /* AC97_H */
-- 
2.30.7



^ permalink raw reply related	[flat|nested] 40+ messages in thread

* [PATCH 5/5] hw/audio/via-ac97: Basic implementation of audio playback
  2023-02-21 18:44 [PATCH 0/5] Pegasos2 fixes and audio output support BALATON Zoltan
                   ` (3 preceding siblings ...)
  2023-02-21 18:44 ` [PATCH 4/5] hw/audio/ac97: Split off some definitions to a header BALATON Zoltan
@ 2023-02-21 18:44 ` BALATON Zoltan
  2023-02-23 19:40   ` Volker Rümelin
  2023-02-22 15:38 ` [PATCH 0/5] Pegasos2 fixes and audio output support Bernhard Beschow
  5 siblings, 1 reply; 40+ messages in thread
From: BALATON Zoltan @ 2023-02-21 18:44 UTC (permalink / raw)
  To: qemu-devel, qemu-ppc
  Cc: Gerd Hoffmann, Daniel Henrique Barboza, Bernhard Beschow, philmd,
	vr_qemu

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 <balaton@eik.bme.hu>
---
 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 running) "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=0x%x %c%c%c len=%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.
  */
 
 /*
- * 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.
  */
 
 #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[] = { 8000, 11025, 16000, 22050, 32000, 44100,
+                                  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 = 255 - CODEC_VOL(CODEC_REG(s, AC97_Master_Volume_Mute) >> 8, 0x1f);
+    lvol *= 255 - CODEC_VOL(CODEC_REG(s, AC97_PCM_Out_Volume_Mute) >> 8, 0x1f);
+    lvol /= 255;
+    rvol = 255 - CODEC_VOL(CODEC_REG(s, AC97_Master_Volume_Mute), 0x1f);
+    rvol *= 255 - CODEC_VOL(CODEC_REG(s, AC97_PCM_Out_Volume_Mute), 0x1f);
+    rvol /= 255;
+    mute = CODEC_REG(s, AC97_Master_Volume_Mute) >> MUTE_SHIFT;
+    mute |= 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) = 0x6a90;
+    CODEC_REG(s, AC97_Master_Volume_Mute) = 0x8000;
+    CODEC_REG(s, AC97_Headphone_Volume_Mute) = 0x8000;
+    CODEC_REG(s, AC97_Master_Volume_Mono_Mute) = 0x8000;
+    CODEC_REG(s, AC97_Phone_Volume_Mute) = 0x8008;
+    CODEC_REG(s, AC97_Mic_Volume_Mute) = 0x8008;
+    CODEC_REG(s, AC97_Line_In_Volume_Mute) = 0x8808;
+    CODEC_REG(s, AC97_CD_Volume_Mute) = 0x8808;
+    CODEC_REG(s, AC97_Video_Volume_Mute) = 0x8808;
+    CODEC_REG(s, AC97_Aux_Volume_Mute) = 0x8808;
+    CODEC_REG(s, AC97_PCM_Out_Volume_Mute) = 0x8808;
+    CODEC_REG(s, AC97_Record_Gain_Mute) = 0x8000;
+    CODEC_REG(s, AC97_Powerdown_Ctrl_Stat) = 0x000f;
+    CODEC_REG(s, AC97_Extended_Audio_ID) = 0x0a05;
+    CODEC_REG(s, AC97_Extended_Audio_Ctrl_Stat) = 0x0400;
+    CODEC_REG(s, AC97_PCM_Front_DAC_Rate) = 48000;
+    CODEC_REG(s, AC97_PCM_LR_ADC_Rate) = 48000;
+    /* Sigmatel 9766 (STAC9766) */
+    CODEC_REG(s, AC97_Vendor_ID1) = 0x8384;
+    CODEC_REG(s, AC97_Vendor_ID2) = 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 == AC97_Master_Volume_Mute) {
+            if (val & BIT(13)) {
+                val |= 0x1f00;
+            }
+            if (val & BIT(5)) {
+                val |= 0x1f;
+            }
+        }
+        CODEC_REG(s, addr) = val & 0x9f1f;
+        codec_volume_set_out(s);
+        return;
+    case AC97_Extended_Audio_Ctrl_Stat:
+        CODEC_REG(s, addr) &= ~EACS_VRA;
+        CODEC_REG(s, addr) |= val & EACS_VRA;
+        if (!(val & EACS_VRA)) {
+            CODEC_REG(s, AC97_PCM_Front_DAC_Rate) = 48000;
+            CODEC_REG(s, AC97_PCM_LR_ADC_Rate) = 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 = val;
+
+            for (i = 0; i < ARRAY_SIZE(codec_rates) - 1; i++) {
+                if (rate < codec_rates[i] +
+                    (codec_rates[i + 1] - codec_rates[i]) / 2) {
+                    rate = codec_rates[i];
+                    break;
+                }
+            }
+            if (rate > 48000) {
+                rate = 48000;
+            }
+            CODEC_REG(s, addr) = rate;
+            open_voice_out(s);
+        }
+        return;
+    case AC97_Powerdown_Ctrl_Stat:
+        CODEC_REG(s, addr) = (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", addr);
+        CODEC_REG(s, addr) = val;
+    }
+}
+
+static void fetch_sgd(ViaAC97SGDChannel *c, PCIDevice *d)
+{
+    uint32_t b[2];
+
+    if (c->curr < c->base) {
+        c->curr = c->base;
+    }
+    pci_dma_read(d, c->curr, b, sizeof(b));
+    c->addr = le32_to_cpu(b[0]);
+    c->clen = 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 = opaque;
+    ViaAC97SGDChannel *c = &s->aur;
+    int temp, to_copy, copied;
+    bool stop = false;
+    uint8_t tmpbuf[4096];
+
+    if (c->stat & STAT_PAUSED) {
+        return;
+    }
+    c->stat |= STAT_ACTIVE;
+    while (avail && !stop) {
+        if (!c->clen) {
+            fetch_sgd(c, &s->dev);
+        }
+        temp = MIN(CLEN_LEN(c), avail);
+        while (temp) {
+            to_copy = MIN(temp, sizeof(tmpbuf));
+            pci_dma_read(&s->dev, c->addr, tmpbuf, to_copy);
+            copied = AUD_write(s->vo, tmpbuf, to_copy);
+            if (!copied) {
+                stop = true;
+                break;
+            }
+            temp -= copied;
+            avail -= copied;
+            c->addr += copied;
+            c->clen -= copied;
+        }
+        if (CLEN_LEN(c) == 0) {
+            c->curr += 8;
+            if (CLEN_IS_EOL(c)) {
+                c->stat |= STAT_EOL;
+                if (c->type & CNTL_START) {
+                    c->curr = c->base;
+                    c->stat |= STAT_PAUSED;
+                } else {
+                    c->stat &= ~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 |= STAT_FLAG;
+                c->stat |= STAT_PAUSED;
+                if (c->type & STAT_FLAG) {
+                    via_isa_set_irq(&s->dev, VIA_IRQ_AC97, 1);
+                }
+            }
+            if (CLEN_IS_STOP(c)) {
+                c->stat |= STAT_STOP;
+                c->stat |= STAT_PAUSED;
+            }
+            c->clen = 0;
+            stop = true;
+        }
+    }
+}
+
+static void open_voice_out(ViaAC97State *s)
+{
+    struct audsettings as = {
+        .freq = CODEC_REG(s, AC97_PCM_Front_DAC_Rate),
+        .nchannels = s->aur.type & BIT(4) ? 2 : 1,
+        .fmt = s->aur.type & BIT(5) ? AUDIO_FORMAT_S16 : AUDIO_FORMAT_S8,
+        .endianness = 0,
+    };
+    s->vo = 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 = opaque;
+    uint64_t val = 0;
+
+    switch (addr) {
+    case 0:
+        val = s->aur.stat;
+        if (s->aur.type & CNTL_START) {
+            val |= STAT_TRIG;
+        }
+        break;
+    case 1:
+        val = s->aur.stat & STAT_PAUSED ? BIT(3) : 0;
+        break;
+    case 2:
+        val = s->aur.type;
+        break;
+    case 4:
+        val = s->aur.curr;
+        break;
+    case 0xc:
+        val = CLEN_LEN(&s->aur);
+        break;
+    case 0x80:
+        val = s->ac97_cmd;
+        break;
+    case 0x84:
+        val = s->aur.stat & STAT_FLAG;
+        if (s->aur.stat & STAT_EOL) {
+            val |= BIT(4);
+        }
+        if (s->aur.stat & STAT_STOP) {
+            val |= BIT(8);
+        }
+        if (s->aur.stat & STAT_ACTIVE) {
+            val |= 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 size)
+{
+    ViaAC97State *s = opaque;
+
+    trace_via_ac97_sgd_write(addr, size, val);
+    switch (addr) {
+    case 0:
+        if (val & STAT_STOP) {
+            s->aur.stat &= ~STAT_PAUSED;
+        }
+        if (val & STAT_EOL) {
+            s->aur.stat &= ~(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 &= ~(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 = STAT_ACTIVE;
+        }
+        if (val & CNTL_TERM) {
+            AUD_set_active_out(s->vo, 0);
+            s->aur.stat &= ~(STAT_ACTIVE | STAT_PAUSED);
+            s->aur.clen = 0;
+        }
+        if (val & CNTL_PAUSE) {
+            AUD_set_active_out(s->vo, 0);
+            s->aur.stat &= ~STAT_ACTIVE;
+            s->aur.stat |= STAT_PAUSED;
+        } else if (!(val & CNTL_PAUSE) && (s->aur.stat & STAT_PAUSED)) {
+            AUD_set_active_out(s->vo, 1);
+            s->aur.stat |= STAT_ACTIVE;
+            s->aur.stat &= ~STAT_PAUSED;
+        }
+        break;
+    case 2:
+    {
+        uint32_t oldval = s->aur.type;
+        s->aur.type = val;
+        if ((oldval & 0x30) != (val & 0x30)) {
+            open_voice_out(s);
+        }
+        break;
+    }
+    case 4:
+        s->aur.base = val & ~1ULL;
+        break;
+    case 0x80:
+        if (val >> 30) {
+            /* we only have primary codec */
+            break;
+        }
+        if (val & BIT(23)) { /* read reg */
+            s->ac97_cmd = val & 0xc0ff0000ULL;
+            s->ac97_cmd |= codec_read(s, (val >> 16) & 0x7f);
+            s->ac97_cmd |= BIT(25); /* data valid */
+        } else {
+            s->ac97_cmd = 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 = {
+    .read = sgd_read,
+    .write = sgd_write,
+    .endianness = 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 size)
+{
+    qemu_log_mask(LOG_UNIMP, "%s: 0x%"HWADDR_PRIx" %d <= 0x%"PRIX64"\n",
+                  __func__, addr, size, val);
+}
+
+static const MemoryRegionOps fm_ops = {
+    .read = fm_read,
+    .write = fm_write,
+    .endianness = 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 size)
+{
+    qemu_log_mask(LOG_UNIMP, "%s: 0x%"HWADDR_PRIx" %d <= 0x%"PRIX64"\n",
+                  __func__, addr, size, val);
+}
+
+static const MemoryRegionOps midi_ops = {
+    .read = midi_read,
+    .write = midi_write,
+    .endianness = DEVICE_LITTLE_ENDIAN,
+};
+
+static void via_ac97_reset(DeviceState *dev)
+{
+    ViaAC97State *s = VIA_AC97(dev);
+
+    codec_reset(s);
+}
 
 static void via_ac97_realize(PCIDevice *pci_dev, Error **errp)
 {
+    ViaAC97State *s = VIA_AC97(pci_dev);
+    Object *o = 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);
 }
 
+static void via_ac97_exit(PCIDevice *dev)
+{
+    ViaAC97State *s = VIA_AC97(dev);
+
+    AUD_close_out(&s->card, s->vo);
+    AUD_remove_card(&s->card);
+}
+
+static Property via_ac97_properties[] = {
+    DEFINE_AUDIO_PROPERTIES(ViaAC97State, card),
+    DEFINE_PROP_END_OF_LIST(),
+};
+
 static void via_ac97_class_init(ObjectClass *klass, void *data)
 {
     DeviceClass *dc = DEVICE_CLASS(klass);
     PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
 
     k->realize = via_ac97_realize;
+    k->exit = via_ac97_exit;
     k->vendor_id = PCI_VENDOR_ID_VIA;
     k->device_id = PCI_DEVICE_ID_VIA_AC97;
     k->revision = 0x50;
     k->class_id = PCI_CLASS_MULTIMEDIA_AUDIO;
+    device_class_set_props(dc, via_ac97_properties);
     set_bit(DEVICE_CATEGORY_SOUND, dc->categories);
     dc->desc = "VIA AC97";
+    dc->reset = via_ac97_reset;
     /* Reason: Part of a south bridge chip */
     dc->user_creatable = false;
 }
@@ -41,7 +469,7 @@ static void via_ac97_class_init(ObjectClass *klass, void *data)
 static const TypeInfo via_ac97_info = {
     .name          = TYPE_VIA_AC97,
     .parent        = TYPE_PCI_DEVICE,
-    .instance_size = sizeof(PCIDevice),
+    .instance_size = sizeof(ViaAC97State),
     .class_init    = via_ac97_class_init,
     .interfaces = (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;
 };
 
@@ -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 = 14;
         isa_irq = 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
 
+#include "hw/pci/pci_device.h"
+#include "audio/audio.h"
 
 #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"
 
+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 = 0,
     VIA_IRQ_IDE1 = 1,
@@ -18,6 +43,7 @@ typedef enum {
     VIA_IRQ_PIRQB = 5,
     VIA_IRQ_PIRQC = 6,
     VIA_IRQ_PIRQD = 7,
+    VIA_IRQ_AC97 = 8,
 } ViaISAIRQSourceBit;
 
 void via_isa_set_irq(PCIDevice *d, ViaISAIRQSourceBit n, int level);
-- 
2.30.7



^ permalink raw reply related	[flat|nested] 40+ messages in thread

* Re: [PATCH 0/5] Pegasos2 fixes and audio output support
  2023-02-21 18:44 [PATCH 0/5] Pegasos2 fixes and audio output support BALATON Zoltan
                   ` (4 preceding siblings ...)
  2023-02-21 18:44 ` [PATCH 5/5] hw/audio/via-ac97: Basic implementation of audio playback BALATON Zoltan
@ 2023-02-22 15:38 ` Bernhard Beschow
  2023-02-22 18:56   ` Bernhard Beschow
  5 siblings, 1 reply; 40+ messages in thread
From: Bernhard Beschow @ 2023-02-22 15:38 UTC (permalink / raw)
  To: BALATON Zoltan
  Cc: qemu-devel, qemu-ppc, Gerd Hoffmann, Daniel Henrique Barboza, philmd

[-- Attachment #1: Type: text/plain, Size: 2075 bytes --]

On Tue, Feb 21, 2023 at 7:44 PM BALATON Zoltan <balaton@eik.bme.hu> wrote:

> This series fixes PCI interrupts on the ppc/pegasos2 machine and adds
> partial implementation of the via-ac97 sound part enough to get audio
> output. I'd like this to be merged for QEMU 8.0.
>
> Regards,
> BALATON Zoltan
>
> BALATON Zoltan (5):
>   hw/isa/vt82c686: Implement interrupt routing in via_isa_set_irq
>   hw/isa/vt82c686: Implement PIRQ pins
>   hw/ppc/pegasos2: Fix PCI interrupt routing
>   hw/audio/ac97: Split off some definitions to a header
>   hw/audio/via-ac97: Basic implementation of audio playback
>
>  hw/audio/ac97.c            |  43 +---
>  hw/audio/ac97.h            |  65 ++++++
>  hw/audio/trace-events      |   6 +
>  hw/audio/via-ac97.c        | 436 ++++++++++++++++++++++++++++++++++++-
>  hw/ide/via.c               |   2 +-
>  hw/isa/vt82c686.c          |  61 +++++-
>  hw/pci-host/mv64361.c      |   4 -
>  hw/ppc/pegasos2.c          |  26 ++-
>  hw/usb/vt82c686-uhci-pci.c |   5 +-
>  include/hw/isa/vt82c686.h  |  39 +++-
>  10 files changed, 626 insertions(+), 61 deletions(-)
>  create mode 100644 hw/audio/ac97.h
>
> --
> 2.30.7
>
>
Wow, the MorphOS people paid attention to sound design. Thanks for
presenting it to us, Zoltan!

I've had a closer look at your series and I think it can be simplified:
Patch 2 can be implemented quite straight-forward like I proposed in a
private mail: https://github.com/shentok/qemu/commit/via-priq-routing.
Then, in order to make patch 3 "hw/ppc/pegasos2: Fix PCI interrupt routing"
working, one can expose the PCI interrupts with a single line like you do
in patch 2. With this, patch 1 "hw/isa/vt82c686: Implement interrupt
routing in via_isa_set_irq" isn't needed any longer and can be omitted.

In via-ac97, rather than using via_isa_set_irq(), pci_set_irq() can be used
instead. pci_set_irq() internally takes care of all the ISA interrupt level
tracking patch 1 attempted to address.

I might have further comments but I think it's enough for now.

Thanks again for making via-ac97 work!

Best regards,
Bernhard

[-- Attachment #2: Type: text/html, Size: 2840 bytes --]

^ permalink raw reply	[flat|nested] 40+ messages in thread

* Re: [PATCH 0/5] Pegasos2 fixes and audio output support
  2023-02-22 15:38 ` [PATCH 0/5] Pegasos2 fixes and audio output support Bernhard Beschow
@ 2023-02-22 18:56   ` Bernhard Beschow
  2023-02-22 19:25     ` BALATON Zoltan
  0 siblings, 1 reply; 40+ messages in thread
From: Bernhard Beschow @ 2023-02-22 18:56 UTC (permalink / raw)
  To: BALATON Zoltan
  Cc: qemu-devel, qemu-ppc, Gerd Hoffmann, Daniel Henrique Barboza, philmd

[-- Attachment #1: Type: text/plain, Size: 2448 bytes --]

On Wed, Feb 22, 2023 at 4:38 PM Bernhard Beschow <shentey@gmail.com> wrote:

>
>
> On Tue, Feb 21, 2023 at 7:44 PM BALATON Zoltan <balaton@eik.bme.hu> wrote:
>
>> This series fixes PCI interrupts on the ppc/pegasos2 machine and adds
>> partial implementation of the via-ac97 sound part enough to get audio
>> output. I'd like this to be merged for QEMU 8.0.
>>
>> Regards,
>> BALATON Zoltan
>>
>> BALATON Zoltan (5):
>>   hw/isa/vt82c686: Implement interrupt routing in via_isa_set_irq
>>   hw/isa/vt82c686: Implement PIRQ pins
>>   hw/ppc/pegasos2: Fix PCI interrupt routing
>>   hw/audio/ac97: Split off some definitions to a header
>>   hw/audio/via-ac97: Basic implementation of audio playback
>>
>>  hw/audio/ac97.c            |  43 +---
>>  hw/audio/ac97.h            |  65 ++++++
>>  hw/audio/trace-events      |   6 +
>>  hw/audio/via-ac97.c        | 436 ++++++++++++++++++++++++++++++++++++-
>>  hw/ide/via.c               |   2 +-
>>  hw/isa/vt82c686.c          |  61 +++++-
>>  hw/pci-host/mv64361.c      |   4 -
>>  hw/ppc/pegasos2.c          |  26 ++-
>>  hw/usb/vt82c686-uhci-pci.c |   5 +-
>>  include/hw/isa/vt82c686.h  |  39 +++-
>>  10 files changed, 626 insertions(+), 61 deletions(-)
>>  create mode 100644 hw/audio/ac97.h
>>
>> --
>> 2.30.7
>>
>>
> Wow, the MorphOS people paid attention to sound design. Thanks for
> presenting it to us, Zoltan!
>
> I've had a closer look at your series and I think it can be simplified:
> Patch 2 can be implemented quite straight-forward like I proposed in a
> private mail: https://github.com/shentok/qemu/commit/via-priq-routing.
> Then, in order to make patch 3 "hw/ppc/pegasos2: Fix PCI interrupt routing"
> working, one can expose the PCI interrupts with a single line like you do
> in patch 2. With this, patch 1 "hw/isa/vt82c686: Implement interrupt
> routing in via_isa_set_irq" isn't needed any longer and can be omitted.
>
> In via-ac97, rather than using via_isa_set_irq(), pci_set_irq() can be
> used instead. pci_set_irq() internally takes care of all the ISA interrupt
> level tracking patch 1 attempted to address.
>

Here is a proof of concept branch to demonstrate that the simplification
actually works: https://github.com/shentok/qemu/commits/pegasos2 (Tested
with MorphOS with and without pegasos2.rom).

Best regards,
Bernhard

>
> I might have further comments but I think it's enough for now.
>
> Thanks again for making via-ac97 work!
>
> Best regards,
> Bernhard
>

[-- Attachment #2: Type: text/html, Size: 3784 bytes --]

^ permalink raw reply	[flat|nested] 40+ messages in thread

* Re: [PATCH 0/5] Pegasos2 fixes and audio output support
  2023-02-22 18:56   ` Bernhard Beschow
@ 2023-02-22 19:25     ` BALATON Zoltan
  2023-02-22 20:59       ` Bernhard Beschow
  0 siblings, 1 reply; 40+ messages in thread
From: BALATON Zoltan @ 2023-02-22 19:25 UTC (permalink / raw)
  To: Bernhard Beschow
  Cc: qemu-devel, qemu-ppc, Gerd Hoffmann, Daniel Henrique Barboza, philmd

On Wed, 22 Feb 2023, Bernhard Beschow wrote:
> On Wed, Feb 22, 2023 at 4:38 PM Bernhard Beschow <shentey@gmail.com> wrote:
>> On Tue, Feb 21, 2023 at 7:44 PM BALATON Zoltan <balaton@eik.bme.hu> wrote:
>>> This series fixes PCI interrupts on the ppc/pegasos2 machine and adds
>>> partial implementation of the via-ac97 sound part enough to get audio
>>> output. I'd like this to be merged for QEMU 8.0.
>>>
>>> Regards,
>>> BALATON Zoltan
>>>
>>> BALATON Zoltan (5):
>>>   hw/isa/vt82c686: Implement interrupt routing in via_isa_set_irq
>>>   hw/isa/vt82c686: Implement PIRQ pins
>>>   hw/ppc/pegasos2: Fix PCI interrupt routing
>>>   hw/audio/ac97: Split off some definitions to a header
>>>   hw/audio/via-ac97: Basic implementation of audio playback
>>>
>>>  hw/audio/ac97.c            |  43 +---
>>>  hw/audio/ac97.h            |  65 ++++++
>>>  hw/audio/trace-events      |   6 +
>>>  hw/audio/via-ac97.c        | 436 ++++++++++++++++++++++++++++++++++++-
>>>  hw/ide/via.c               |   2 +-
>>>  hw/isa/vt82c686.c          |  61 +++++-
>>>  hw/pci-host/mv64361.c      |   4 -
>>>  hw/ppc/pegasos2.c          |  26 ++-
>>>  hw/usb/vt82c686-uhci-pci.c |   5 +-
>>>  include/hw/isa/vt82c686.h  |  39 +++-
>>>  10 files changed, 626 insertions(+), 61 deletions(-)
>>>  create mode 100644 hw/audio/ac97.h
>>>
>>> --
>>> 2.30.7
>>>
>>>
>> Wow, the MorphOS people paid attention to sound design. Thanks for
>> presenting it to us, Zoltan!
>>
>> I've had a closer look at your series and I think it can be simplified:
>> Patch 2 can be implemented quite straight-forward like I proposed in a
>> private mail: https://github.com/shentok/qemu/commit/via-priq-routing.
>> Then, in order to make patch 3 "hw/ppc/pegasos2: Fix PCI interrupt routing"
>> working, one can expose the PCI interrupts with a single line like you do
>> in patch 2. With this, patch 1 "hw/isa/vt82c686: Implement interrupt
>> routing in via_isa_set_irq" isn't needed any longer and can be omitted.
>>
>> In via-ac97, rather than using via_isa_set_irq(), pci_set_irq() can be
>> used instead. pci_set_irq() internally takes care of all the ISA interrupt
>> level tracking patch 1 attempted to address.
>>
>
> Here is a proof of concept branch to demonstrate that the simplification
> actually works: https://github.com/shentok/qemu/commits/pegasos2 (Tested
> with MorphOS with and without pegasos2.rom).

Does this only work because both the via-ac97 and the PCI interrupts are 
mapped to the same ISA IRQ and you've only tested sound? The guest could 
configure each device to use a different IRQ, also mapping them so they 
share one ISA interrupt. What happens if multiple devices are mapped to 
IRQ 9 (which is the case on pegasos2 where PCI cards, ac97 and USB all 
share this IRQ) and more than one such device wants to raise an interrupt 
at the same time? If you ack the ac97 interrupt but a PCI network card or 
the USB part still wants to get the CPUs attention the ISA IRQ should 
remain raised until all devices are serviced. I don't see a way to track 
the status of all devices in a single qemu_irq which can only be up or 
down so we need something to store the state of each source. My patch adds 
a state register to each ISA IRQ line for all possible sources which could 
probably be stored once but then for each change of ISA IRQ status all the 
mapped devices should be checked and combined so it's easier to store them 
for each IRQ. Does your approach still work if you play sound, and copy 
something from network to a USB device at the same time? (I'm not sure 
mine does not have remaining bugs but I don't think this can be simplified 
that way but if you can prove it would work I don't mind taking an 
alternative version but I'm not convinced yet.)

Regards,
BALATON Zoltan

>> I might have further comments but I think it's enough for now.
>>
>> Thanks again for making via-ac97 work!
>>
>> Best regards,
>> Bernhard
>>
>


^ permalink raw reply	[flat|nested] 40+ messages in thread

* Re: [PATCH 0/5] Pegasos2 fixes and audio output support
  2023-02-22 19:25     ` BALATON Zoltan
@ 2023-02-22 20:59       ` Bernhard Beschow
  2023-02-22 21:12         ` BALATON Zoltan
  2023-02-22 22:23         ` BALATON Zoltan
  0 siblings, 2 replies; 40+ messages in thread
From: Bernhard Beschow @ 2023-02-22 20:59 UTC (permalink / raw)
  To: BALATON Zoltan
  Cc: qemu-devel, qemu-ppc, Gerd Hoffmann, Daniel Henrique Barboza, philmd

Am 22. Februar 2023 19:25:16 UTC schrieb BALATON Zoltan <balaton@eik.bme.hu>:
>On Wed, 22 Feb 2023, Bernhard Beschow wrote:
>> On Wed, Feb 22, 2023 at 4:38 PM Bernhard Beschow <shentey@gmail.com> wrote:
>>> On Tue, Feb 21, 2023 at 7:44 PM BALATON Zoltan <balaton@eik.bme.hu> wrote:
>>>> This series fixes PCI interrupts on the ppc/pegasos2 machine and adds
>>>> partial implementation of the via-ac97 sound part enough to get audio
>>>> output. I'd like this to be merged for QEMU 8.0.
>>>>
>>>> Regards,
>>>> BALATON Zoltan
>>>>
>>>> BALATON Zoltan (5):
>>>>   hw/isa/vt82c686: Implement interrupt routing in via_isa_set_irq
>>>>   hw/isa/vt82c686: Implement PIRQ pins
>>>>   hw/ppc/pegasos2: Fix PCI interrupt routing
>>>>   hw/audio/ac97: Split off some definitions to a header
>>>>   hw/audio/via-ac97: Basic implementation of audio playback
>>>>
>>>>  hw/audio/ac97.c            |  43 +---
>>>>  hw/audio/ac97.h            |  65 ++++++
>>>>  hw/audio/trace-events      |   6 +
>>>>  hw/audio/via-ac97.c        | 436 ++++++++++++++++++++++++++++++++++++-
>>>>  hw/ide/via.c               |   2 +-
>>>>  hw/isa/vt82c686.c          |  61 +++++-
>>>>  hw/pci-host/mv64361.c      |   4 -
>>>>  hw/ppc/pegasos2.c          |  26 ++-
>>>>  hw/usb/vt82c686-uhci-pci.c |   5 +-
>>>>  include/hw/isa/vt82c686.h  |  39 +++-
>>>>  10 files changed, 626 insertions(+), 61 deletions(-)
>>>>  create mode 100644 hw/audio/ac97.h
>>>>
>>>> --
>>>> 2.30.7
>>>>
>>>>
>>> Wow, the MorphOS people paid attention to sound design. Thanks for
>>> presenting it to us, Zoltan!
>>>
>>> I've had a closer look at your series and I think it can be simplified:
>>> Patch 2 can be implemented quite straight-forward like I proposed in a
>>> private mail: https://github.com/shentok/qemu/commit/via-priq-routing.
>>> Then, in order to make patch 3 "hw/ppc/pegasos2: Fix PCI interrupt routing"
>>> working, one can expose the PCI interrupts with a single line like you do
>>> in patch 2. With this, patch 1 "hw/isa/vt82c686: Implement interrupt
>>> routing in via_isa_set_irq" isn't needed any longer and can be omitted.
>>>
>>> In via-ac97, rather than using via_isa_set_irq(), pci_set_irq() can be
>>> used instead. pci_set_irq() internally takes care of all the ISA interrupt
>>> level tracking patch 1 attempted to address.
>>>
>>
>> Here is a proof of concept branch to demonstrate that the simplification
>> actually works: https://github.com/shentok/qemu/commits/pegasos2 (Tested
>> with MorphOS with and without pegasos2.rom).
>
>Does this only work because both the via-ac97 and the PCI interrupts are mapped to the same ISA IRQ and you've only tested sound? The guest could configure each device to use a different IRQ, also mapping them so they share one ISA interrupt. What happens if multiple devices are mapped to IRQ 9 (which is the case on pegasos2 where PCI cards, ac97 and USB all share this IRQ) and more than one such device wants to raise an interrupt at the same time? If you ack the ac97 interrupt but a PCI network card or the USB part still wants to get the CPUs attention the ISA IRQ should remain raised until all devices are serviced.

pci_bus_get_irq_level(), used in via_isa_set_pci_irq(), should handle
exactly that case very well.

>I don't see a way to track the status of all devices in a single qemu_irq which can only be up or down so we need something to store the state of each source.

pci_set_irq() causes pci_bus_change_irq_level() to be called.
pci_bus_change_irq_level() tracks the sum of all irq levels of all
devices attached to a particular pin in irq_count. Have a look at
pci_bus_change_irq_level() and you will understand better.

>My patch adds a state register to each ISA IRQ line for all possible sources which could probably be stored once but then for each change of ISA IRQ status all the mapped devices should be checked and combined so it's easier to store them for each IRQ. Does your approach still work if you play sound, and copy something from network to a USB device at the same time? (I'm not sure mine does not have remaining bugs but I don't think this can be simplified that way but if you can prove it would work I don't mind taking an alternative version but I'm not convinced yet.)

Well, I can't prove that my approach works but unfortunately I can
prove that both our approaches cause a freeze :/ Try:
1. Start `qemu-system-ppc -M pegasos2 -bios pegasos2.rom -rtc
base=localtime -device ati-vga,guest_hwcursor=true,romfile="" -cdrom
morphos-3.17.iso -device usb-mouse -device usb-kbd`
2. Move the mouse while sound is playing
-> Observe the VM to freeze

So there must be an issue somewhere else...

Best regards,
Bernhard
>
>Regards,
>BALATON Zoltan
>
>>> I might have further comments but I think it's enough for now.
>>>
>>> Thanks again for making via-ac97 work!
>>>
>>> Best regards,
>>> Bernhard
>>>
>>


^ permalink raw reply	[flat|nested] 40+ messages in thread

* Re: [PATCH 0/5] Pegasos2 fixes and audio output support
  2023-02-22 20:59       ` Bernhard Beschow
@ 2023-02-22 21:12         ` BALATON Zoltan
  2023-02-22 22:20           ` Bernhard Beschow
  2023-03-01 13:42           ` Mark Cave-Ayland
  2023-02-22 22:23         ` BALATON Zoltan
  1 sibling, 2 replies; 40+ messages in thread
From: BALATON Zoltan @ 2023-02-22 21:12 UTC (permalink / raw)
  To: Bernhard Beschow
  Cc: qemu-devel, qemu-ppc, Gerd Hoffmann, Daniel Henrique Barboza, philmd

On Wed, 22 Feb 2023, Bernhard Beschow wrote:
> Am 22. Februar 2023 19:25:16 UTC schrieb BALATON Zoltan <balaton@eik.bme.hu>:
>> On Wed, 22 Feb 2023, Bernhard Beschow wrote:
>>> On Wed, Feb 22, 2023 at 4:38 PM Bernhard Beschow <shentey@gmail.com> wrote:
>>>> On Tue, Feb 21, 2023 at 7:44 PM BALATON Zoltan <balaton@eik.bme.hu> wrote:
>>>>> This series fixes PCI interrupts on the ppc/pegasos2 machine and adds
>>>>> partial implementation of the via-ac97 sound part enough to get audio
>>>>> output. I'd like this to be merged for QEMU 8.0.
>>>>>
>>>>> Regards,
>>>>> BALATON Zoltan
>>>>>
>>>>> BALATON Zoltan (5):
>>>>>   hw/isa/vt82c686: Implement interrupt routing in via_isa_set_irq
>>>>>   hw/isa/vt82c686: Implement PIRQ pins
>>>>>   hw/ppc/pegasos2: Fix PCI interrupt routing
>>>>>   hw/audio/ac97: Split off some definitions to a header
>>>>>   hw/audio/via-ac97: Basic implementation of audio playback
>>>>>
>>>>>  hw/audio/ac97.c            |  43 +---
>>>>>  hw/audio/ac97.h            |  65 ++++++
>>>>>  hw/audio/trace-events      |   6 +
>>>>>  hw/audio/via-ac97.c        | 436 ++++++++++++++++++++++++++++++++++++-
>>>>>  hw/ide/via.c               |   2 +-
>>>>>  hw/isa/vt82c686.c          |  61 +++++-
>>>>>  hw/pci-host/mv64361.c      |   4 -
>>>>>  hw/ppc/pegasos2.c          |  26 ++-
>>>>>  hw/usb/vt82c686-uhci-pci.c |   5 +-
>>>>>  include/hw/isa/vt82c686.h  |  39 +++-
>>>>>  10 files changed, 626 insertions(+), 61 deletions(-)
>>>>>  create mode 100644 hw/audio/ac97.h
>>>>>
>>>>> --
>>>>> 2.30.7
>>>>>
>>>>>
>>>> Wow, the MorphOS people paid attention to sound design. Thanks for
>>>> presenting it to us, Zoltan!
>>>>
>>>> I've had a closer look at your series and I think it can be simplified:
>>>> Patch 2 can be implemented quite straight-forward like I proposed in a
>>>> private mail: https://github.com/shentok/qemu/commit/via-priq-routing.
>>>> Then, in order to make patch 3 "hw/ppc/pegasos2: Fix PCI interrupt routing"
>>>> working, one can expose the PCI interrupts with a single line like you do
>>>> in patch 2. With this, patch 1 "hw/isa/vt82c686: Implement interrupt
>>>> routing in via_isa_set_irq" isn't needed any longer and can be omitted.
>>>>
>>>> In via-ac97, rather than using via_isa_set_irq(), pci_set_irq() can be
>>>> used instead. pci_set_irq() internally takes care of all the ISA interrupt
>>>> level tracking patch 1 attempted to address.
>>>>
>>>
>>> Here is a proof of concept branch to demonstrate that the simplification
>>> actually works: https://github.com/shentok/qemu/commits/pegasos2 (Tested
>>> with MorphOS with and without pegasos2.rom).
>>
>> Does this only work because both the via-ac97 and the PCI interrupts are mapped to the same ISA IRQ and you've only tested sound? The guest could configure each device to use a different IRQ, also mapping them so they share one ISA interrupt. What happens if multiple devices are mapped to IRQ 9 (which is the case on pegasos2 where PCI cards, ac97 and USB all share this IRQ) and more than one such device wants to raise an interrupt at the same time? If you ack the ac97 interrupt but a PCI network card or the USB part still wants to get the CPUs attention the ISA IRQ should remain raised until all devices are serviced.
>
> pci_bus_get_irq_level(), used in via_isa_set_pci_irq(), should handle
> exactly that case very well.
>
>> I don't see a way to track the status of all devices in a single qemu_irq which can only be up or down so we need something to store the state of each source.
>
> pci_set_irq() causes pci_bus_change_irq_level() to be called.
> pci_bus_change_irq_level() tracks the sum of all irq levels of all
> devices attached to a particular pin in irq_count. Have a look at
> pci_bus_change_irq_level() and you will understand better.

I'm aware of that, we're using that in sam460ex which connects all PCI 
interrupt lines to a single IRQ and Peter explored and explained it in a 
comment there when that was discovered. First we had a patch with or-irq 
but due to this behaviot that's not needed for PCI interrupts. But the 
VT8132 could change what ISA IRQ you route the sub functions to. It 
happens that on pegasos2 by default all of those are routed to IRQ9 except 
IDE but what if a guest changes ac97 to use a different interrupt? Then 
it's not a PCI interrupt any more so you can't use pci_set_irq in 
via=ac97. There are only 4 PCI INT lines but the VIA components can be 
routed to 13 or 14 ISA IRQs. How do you keep track of that with only the 
PCI bus interrupts? I don't get your approach.

>> My patch adds a state register to each ISA IRQ line for all possible sources which could probably be stored once but then for each change of ISA IRQ status all the mapped devices should be checked and combined so it's easier to store them for each IRQ. Does your approach still work if you play sound, and copy something from network to a USB device at the same time? (I'm not sure mine does not have remaining bugs but I don't think this can be simplified that way but if you can prove it would work I don't mind taking an alternative version but I'm not convinced yet.)
>
> Well, I can't prove that my approach works but unfortunately I can
> prove that both our approaches cause a freeze :/ Try:
> 1. Start `qemu-system-ppc -M pegasos2 -bios pegasos2.rom -rtc
> base=localtime -device ati-vga,guest_hwcursor=true,romfile="" -cdrom
> morphos-3.17.iso -device usb-mouse -device usb-kbd`
> 2. Move the mouse while sound is playing
> -> Observe the VM to freeze
>
> So there must be an issue somewhere else...

I'll have a look later but my patch attempts to handle the USB controller 
interrupts. There may be another bug somewhere in USB emulation though, we 
have similar problem with mac99 with older MacOS guests. Considering that 
USB devices probably did not work at all before this patch it's at least 
still an imptovement. :-)

Regards,
BALATON Zoltan


^ permalink raw reply	[flat|nested] 40+ messages in thread

* Re: [PATCH 0/5] Pegasos2 fixes and audio output support
  2023-02-22 21:12         ` BALATON Zoltan
@ 2023-02-22 22:20           ` Bernhard Beschow
  2023-02-22 23:00             ` BALATON Zoltan
  2023-03-01 13:42           ` Mark Cave-Ayland
  1 sibling, 1 reply; 40+ messages in thread
From: Bernhard Beschow @ 2023-02-22 22:20 UTC (permalink / raw)
  To: BALATON Zoltan
  Cc: qemu-devel, qemu-ppc, Gerd Hoffmann, Daniel Henrique Barboza, philmd



Am 22. Februar 2023 21:12:01 UTC schrieb BALATON Zoltan <balaton@eik.bme.hu>:
>On Wed, 22 Feb 2023, Bernhard Beschow wrote:
>> Am 22. Februar 2023 19:25:16 UTC schrieb BALATON Zoltan <balaton@eik.bme.hu>:
>>> On Wed, 22 Feb 2023, Bernhard Beschow wrote:
>>>> On Wed, Feb 22, 2023 at 4:38 PM Bernhard Beschow <shentey@gmail.com> wrote:
>>>>> On Tue, Feb 21, 2023 at 7:44 PM BALATON Zoltan <balaton@eik.bme.hu> wrote:
>>>>>> This series fixes PCI interrupts on the ppc/pegasos2 machine and adds
>>>>>> partial implementation of the via-ac97 sound part enough to get audio
>>>>>> output. I'd like this to be merged for QEMU 8.0.
>>>>>> 
>>>>>> Regards,
>>>>>> BALATON Zoltan
>>>>>> 
>>>>>> BALATON Zoltan (5):
>>>>>>   hw/isa/vt82c686: Implement interrupt routing in via_isa_set_irq
>>>>>>   hw/isa/vt82c686: Implement PIRQ pins
>>>>>>   hw/ppc/pegasos2: Fix PCI interrupt routing
>>>>>>   hw/audio/ac97: Split off some definitions to a header
>>>>>>   hw/audio/via-ac97: Basic implementation of audio playback
>>>>>> 
>>>>>>  hw/audio/ac97.c            |  43 +---
>>>>>>  hw/audio/ac97.h            |  65 ++++++
>>>>>>  hw/audio/trace-events      |   6 +
>>>>>>  hw/audio/via-ac97.c        | 436 ++++++++++++++++++++++++++++++++++++-
>>>>>>  hw/ide/via.c               |   2 +-
>>>>>>  hw/isa/vt82c686.c          |  61 +++++-
>>>>>>  hw/pci-host/mv64361.c      |   4 -
>>>>>>  hw/ppc/pegasos2.c          |  26 ++-
>>>>>>  hw/usb/vt82c686-uhci-pci.c |   5 +-
>>>>>>  include/hw/isa/vt82c686.h  |  39 +++-
>>>>>>  10 files changed, 626 insertions(+), 61 deletions(-)
>>>>>>  create mode 100644 hw/audio/ac97.h
>>>>>> 
>>>>>> --
>>>>>> 2.30.7
>>>>>> 
>>>>>> 
>>>>> Wow, the MorphOS people paid attention to sound design. Thanks for
>>>>> presenting it to us, Zoltan!
>>>>> 
>>>>> I've had a closer look at your series and I think it can be simplified:
>>>>> Patch 2 can be implemented quite straight-forward like I proposed in a
>>>>> private mail: https://github.com/shentok/qemu/commit/via-priq-routing.
>>>>> Then, in order to make patch 3 "hw/ppc/pegasos2: Fix PCI interrupt routing"
>>>>> working, one can expose the PCI interrupts with a single line like you do
>>>>> in patch 2. With this, patch 1 "hw/isa/vt82c686: Implement interrupt
>>>>> routing in via_isa_set_irq" isn't needed any longer and can be omitted.
>>>>> 
>>>>> In via-ac97, rather than using via_isa_set_irq(), pci_set_irq() can be
>>>>> used instead. pci_set_irq() internally takes care of all the ISA interrupt
>>>>> level tracking patch 1 attempted to address.
>>>>> 
>>>> 
>>>> Here is a proof of concept branch to demonstrate that the simplification
>>>> actually works: https://github.com/shentok/qemu/commits/pegasos2 (Tested
>>>> with MorphOS with and without pegasos2.rom).
>>> 
>>> Does this only work because both the via-ac97 and the PCI interrupts are mapped to the same ISA IRQ and you've only tested sound? The guest could configure each device to use a different IRQ, also mapping them so they share one ISA interrupt. What happens if multiple devices are mapped to IRQ 9 (which is the case on pegasos2 where PCI cards, ac97 and USB all share this IRQ) and more than one such device wants to raise an interrupt at the same time? If you ack the ac97 interrupt but a PCI network card or the USB part still wants to get the CPUs attention the ISA IRQ should remain raised until all devices are serviced.
>> 
>> pci_bus_get_irq_level(), used in via_isa_set_pci_irq(), should handle
>> exactly that case very well.
>> 
>>> I don't see a way to track the status of all devices in a single qemu_irq which can only be up or down so we need something to store the state of each source.
>> 
>> pci_set_irq() causes pci_bus_change_irq_level() to be called.
>> pci_bus_change_irq_level() tracks the sum of all irq levels of all
>> devices attached to a particular pin in irq_count. Have a look at
>> pci_bus_change_irq_level() and you will understand better.
>
>I'm aware of that, we're using that in sam460ex which connects all PCI interrupt lines to a single IRQ and Peter explored and explained it in a comment there when that was discovered. First we had a patch with or-irq but due to this behaviot that's not needed for PCI interrupts. But the VT8132 could change what ISA IRQ you route the sub functions to.

That depends on the sub function if you can do that. And if so, then it depends on whether the function is still in PCI mode (see below).

>It happens that on pegasos2 by default all of those are routed to IRQ9 except IDE

All *PCI* interrupts are routed to IRQ9 while IDE legacy interrupts are routed to the compatible ISA IRQs. Note that the IDE function must only trigger the ISA IRQs if it is in legacy mode while it must only trigger the PCI IRQ in non-legacy mode. See https://www.bswd.com/pciide.pdf for more details on this particular topic.

>but what if a guest changes ac97 to use a different interrupt? Then it's not a PCI interrupt any more so you can't use pci_set_irq in via=ac97.

How would it do that? AFAICS there is no dedicated register to configure which IRQ to use. This means that it can only trigger an interrupt via its PCI intx pin which is subject to the PCI -> ISA IRQ router.

> There are only 4 PCI INT lines but the VIA components can be routed to 13 or 14 ISA IRQs.

Pure PCI components are only able to trigger one of the four PCI intx pins they are *hardwired* to. Each component has only one pin. Which ISA IRQ gets triggered through that pin can be selected from 13 or 14 ISA IRQs as you say by means of the three configuration registers of the PCI -> ISA IRQ router.

>How do you keep track of that with only the PCI bus interrupts?

Devices that operate in ISA mode such as the IDE function shall have their own, dedicated ISA IRQs assigned by the guest. Otherwise this causes a classic interrupt conflict, just like in the olden ISA days. If the function operates in PCI mode, it must not trigger the ISA IRQs, regardless of whether they are assigned or not.

There is also the power management function whose ACPI interrupt (SCI) can be routed by means of a dedicated register. Again, a guest must make sure here to not configure interrupt conflicts.

>I don't get your approach.

I hope that I could help you get a better understanding. The linked .pdf is good and comprehensive reading material.

Best regards,
Bernhard

>
>>> My patch adds a state register to each ISA IRQ line for all possible sources which could probably be stored once but then for each change of ISA IRQ status all the mapped devices should be checked and combined so it's easier to store them for each IRQ. Does your approach still work if you play sound, and copy something from network to a USB device at the same time? (I'm not sure mine does not have remaining bugs but I don't think this can be simplified that way but if you can prove it would work I don't mind taking an alternative version but I'm not convinced yet.)
>> 
>> Well, I can't prove that my approach works but unfortunately I can
>> prove that both our approaches cause a freeze :/ Try:
>> 1. Start `qemu-system-ppc -M pegasos2 -bios pegasos2.rom -rtc
>> base=localtime -device ati-vga,guest_hwcursor=true,romfile="" -cdrom
>> morphos-3.17.iso -device usb-mouse -device usb-kbd`
>> 2. Move the mouse while sound is playing
>> -> Observe the VM to freeze
>> 
>> So there must be an issue somewhere else...
>
>I'll have a look later but my patch attempts to handle the USB controller interrupts. There may be another bug somewhere in USB emulation though, we have similar problem with mac99 with older MacOS guests. Considering that USB devices probably did not work at all before this patch it's at least still an imptovement. :-)
>
>Regards,
>BALATON Zoltan


^ permalink raw reply	[flat|nested] 40+ messages in thread

* Re: [PATCH 0/5] Pegasos2 fixes and audio output support
  2023-02-22 20:59       ` Bernhard Beschow
  2023-02-22 21:12         ` BALATON Zoltan
@ 2023-02-22 22:23         ` BALATON Zoltan
  2023-02-23  0:43           ` BALATON Zoltan
  1 sibling, 1 reply; 40+ messages in thread
From: BALATON Zoltan @ 2023-02-22 22:23 UTC (permalink / raw)
  To: Bernhard Beschow
  Cc: qemu-devel, qemu-ppc, Gerd Hoffmann, Daniel Henrique Barboza, philmd

On Wed, 22 Feb 2023, Bernhard Beschow wrote:
> Am 22. Februar 2023 19:25:16 UTC schrieb BALATON Zoltan <balaton@eik.bme.hu>:
>> On Wed, 22 Feb 2023, Bernhard Beschow wrote:
>>> On Wed, Feb 22, 2023 at 4:38 PM Bernhard Beschow <shentey@gmail.com> wrote:
>>>> On Tue, Feb 21, 2023 at 7:44 PM BALATON Zoltan <balaton@eik.bme.hu> wrote:
>>>>> This series fixes PCI interrupts on the ppc/pegasos2 machine and adds
>>>>> partial implementation of the via-ac97 sound part enough to get audio
>>>>> output. I'd like this to be merged for QEMU 8.0.
>>>>>
>>>>> Regards,
>>>>> BALATON Zoltan
>>>>>
>>>>> BALATON Zoltan (5):
>>>>>   hw/isa/vt82c686: Implement interrupt routing in via_isa_set_irq
>>>>>   hw/isa/vt82c686: Implement PIRQ pins
>>>>>   hw/ppc/pegasos2: Fix PCI interrupt routing
>>>>>   hw/audio/ac97: Split off some definitions to a header
>>>>>   hw/audio/via-ac97: Basic implementation of audio playback
>>>>>
>>>>>  hw/audio/ac97.c            |  43 +---
>>>>>  hw/audio/ac97.h            |  65 ++++++
>>>>>  hw/audio/trace-events      |   6 +
>>>>>  hw/audio/via-ac97.c        | 436 ++++++++++++++++++++++++++++++++++++-
>>>>>  hw/ide/via.c               |   2 +-
>>>>>  hw/isa/vt82c686.c          |  61 +++++-
>>>>>  hw/pci-host/mv64361.c      |   4 -
>>>>>  hw/ppc/pegasos2.c          |  26 ++-
>>>>>  hw/usb/vt82c686-uhci-pci.c |   5 +-
>>>>>  include/hw/isa/vt82c686.h  |  39 +++-
>>>>>  10 files changed, 626 insertions(+), 61 deletions(-)
>>>>>  create mode 100644 hw/audio/ac97.h
>>>>>
>>>>> --
>>>>> 2.30.7
>>>>>
>>>>>
>>>> Wow, the MorphOS people paid attention to sound design. Thanks for
>>>> presenting it to us, Zoltan!
>>>>
>>>> I've had a closer look at your series and I think it can be simplified:
>>>> Patch 2 can be implemented quite straight-forward like I proposed in a
>>>> private mail: https://github.com/shentok/qemu/commit/via-priq-routing.
>>>> Then, in order to make patch 3 "hw/ppc/pegasos2: Fix PCI interrupt routing"
>>>> working, one can expose the PCI interrupts with a single line like you do
>>>> in patch 2. With this, patch 1 "hw/isa/vt82c686: Implement interrupt
>>>> routing in via_isa_set_irq" isn't needed any longer and can be omitted.
>>>>
>>>> In via-ac97, rather than using via_isa_set_irq(), pci_set_irq() can be
>>>> used instead. pci_set_irq() internally takes care of all the ISA interrupt
>>>> level tracking patch 1 attempted to address.
>>>>
>>>
>>> Here is a proof of concept branch to demonstrate that the simplification
>>> actually works: https://github.com/shentok/qemu/commits/pegasos2 (Tested
>>> with MorphOS with and without pegasos2.rom).
>>
>> Does this only work because both the via-ac97 and the PCI interrupts are mapped to the same ISA IRQ and you've only tested sound? The guest could configure each device to use a different IRQ, also mapping them so they share one ISA interrupt. What happens if multiple devices are mapped to IRQ 9 (which is the case on pegasos2 where PCI cards, ac97 and USB all share this IRQ) and more than one such device wants to raise an interrupt at the same time? If you ack the ac97 interrupt but a PCI network card or the USB part still wants to get the CPUs attention the ISA IRQ should remain raised until all devices are serviced.
>
> pci_bus_get_irq_level(), used in via_isa_set_pci_irq(), should handle
> exactly that case very well.
>
>> I don't see a way to track the status of all devices in a single qemu_irq which can only be up or down so we need something to store the state of each source.
>
> pci_set_irq() causes pci_bus_change_irq_level() to be called.
> pci_bus_change_irq_level() tracks the sum of all irq levels of all
> devices attached to a particular pin in irq_count. Have a look at
> pci_bus_change_irq_level() and you will understand better.
>
>> My patch adds a state register to each ISA IRQ line for all possible sources which could probably be stored once but then for each change of ISA IRQ status all the mapped devices should be checked and combined so it's easier to store them for each IRQ. Does your approach still work if you play sound, and copy something from network to a USB device at the same time? (I'm not sure mine does not have remaining bugs but I don't think this can be simplified that way but if you can prove it would work I don't mind taking an alternative version but I'm not convinced yet.)
>
> Well, I can't prove that my approach works but unfortunately I can
> prove that both our approaches cause a freeze :/ Try:
> 1. Start `qemu-system-ppc -M pegasos2 -bios pegasos2.rom -rtc
> base=localtime -device ati-vga,guest_hwcursor=true,romfile="" -cdrom
> morphos-3.17.iso -device usb-mouse -device usb-kbd`
> 2. Move the mouse while sound is playing
> -> Observe the VM to freeze

Not quite sure why but it seems to happen when both the ac97 and USB raise 
the interrupt and the guest driver seems to get confused. Adding some 
debug logging:

diff --git a/hw/isa/vt82c686.c b/hw/isa/vt82c686.c
index b16620daf8..f840e5a8d0 100644
--- a/hw/isa/vt82c686.c
+++ b/hw/isa/vt82c686.c
@@ -636,12 +636,13 @@ void via_isa_set_irq(PCIDevice *d, 
ViaISAIRQSourceBit n, int level)
      if (!isa_irq) {
          return;
      }
-
+if (n > 1) fprintf(stderr, "%s: %d %d %d %x -> ", __func__, n, level, isa_irq, s->isa_irq_state[isa_irq]);
      if (level) {
          s->isa_irq_state[isa_irq] |= BIT(n);
      } else {
          s->isa_irq_state[isa_irq] &= ~BIT(n);
      }
+if (n > 1) fprintf(stderr, "%x\n", s->isa_irq_state[isa_irq]);
      qemu_set_irq(s->isa_irqs[isa_irq], !!s->isa_irq_state[isa_irq]);
  }

I see in the normal case when there's only one interrupt for USB only:

via_isa_set_irq: 2 1 9 0 -> 4
usb_uhci_mmio_readw addr 0x0002, ret 0x0001
usb_uhci_mmio_writew addr 0x0002, val 0x0001
via_isa_set_irq: 2 0 9 4 -> 0

For sound only:

via_ac97_sgd_fetch addr=0x43b70bc --F len=3528
via_isa_set_irq: 8 1 9 0 -> 100
usb_uhci_mmio_readw addr 0x0002, ret 0x0000
usb_uhci_mmio_readw addr 0x0002, ret 0x0000
via_ac97_sgd_read 0x0 1 -> 0xc9
via_ac97_sgd_write 0x0 1 <- 0x1
via_isa_set_irq: 8 0 9 100 -> 0
via_ac97_sgd_read 0x4 4 -> 0x439cbe8
via_ac97_sgd_fetch addr=0x43c70bc -E- len=3528
via_isa_set_irq: 8 1 9 0 -> 100
via_ac97_sgd_read 0x4 4 -> 0x439cbe0
via_ac97_sgd_read 0x4 4 -> 0x439cbe0
via_ac97_sgd_read 0x10 1 -> 0x0
usb_uhci_mmio_readw addr 0x0002, ret 0x0000
usb_uhci_mmio_readw addr 0x0002, ret 0x0000
via_ac97_sgd_read 0x0 1 -> 0xca
via_ac97_sgd_write 0x0 1 <- 0x2
via_isa_set_irq: 8 0 9 100 -> 0
via_ac97_sgd_read 0x4 4 -> 0x439cbe0

but it stops acking irqs when both are raised or it seems USB IRQ is 
raised while it's in the guest IRQ handler:

via_ac97_sgd_fetch addr=0x43c70bc -E- len=3528
via_isa_set_irq: 8 1 9 0 -> 100
usb_uhci_mmio_readw addr 0x0002, ret 0x0000
usb_uhci_mmio_readw addr 0x0002, ret 0x0000
via_isa_set_irq: 2 1 9 100 -> 104
via_ac97_sgd_read 0x0 1 -> 0xca
via_ac97_sgd_write 0x0 1 <- 0x2
via_isa_set_irq: 8 0 9 104 -> 4
via_ac97_sgd_read 0x4 4 -> 0x439cbe0
via_ac97_sgd_fetch addr=0x43b70bc --F len=3528
via_isa_set_irq: 8 1 9 4 -> 104
via_ac97_sgd_read 0x4 4 -> 0x439cbe8
via_ac97_sgd_read 0x4 4 -> 0x439cbe8
via_ac97_sgd_read 0x10 1 -> 0x0
usb_uhci_mmio_readw addr 0x0006, ret 0x06bf
usb_uhci_mmio_readw addr 0x0010, ret 0x0085
usb_uhci_mmio_writew addr 0x0010, val 0x0085
usb_uhci_mmio_readw addr 0x0012, ret 0x0085
usb_uhci_mmio_writew addr 0x0012, val 0x0085
usb_uhci_mmio_readw addr 0x0006, ret 0x06b7
usb_uhci_mmio_readw addr 0x0010, ret 0x0080
usb_uhci_mmio_writew addr 0x0010, val 0x0080
usb_uhci_mmio_readw addr 0x0012, ret 0x0080
usb_uhci_mmio_writew addr 0x0012, val 0x0080
usb_uhci_mmio_readw addr 0x0006, ret 0x0759
usb_uhci_mmio_readw addr 0x0010, ret 0x0085
usb_uhci_mmio_writew addr 0x0010, val 0x0085
usb_uhci_mmio_readw addr 0x0012, ret 0x0085
usb_uhci_mmio_writew addr 0x0012, val 0x0085
usb_uhci_mmio_readw addr 0x0006, ret 0x0752
usb_uhci_mmio_readw addr 0x0010, ret 0x0080
usb_uhci_mmio_writew addr 0x0010, val 0x0080
usb_uhci_mmio_readw addr 0x0012, ret 0x0080
usb_uhci_mmio_writew addr 0x0012, val 0x0080
via_isa_set_irq: 2 1 9 104 -> 104
usb_uhci_mmio_readw addr 0x0006, ret 0x07f1
usb_uhci_mmio_readw addr 0x0010, ret 0x0085
usb_uhci_mmio_writew addr 0x0010, val 0x0085
usb_uhci_mmio_readw addr 0x0012, ret 0x0085
usb_uhci_mmio_writew addr 0x0012, val 0x0085
usb_uhci_mmio_readw addr 0x0006, ret 0x07e9

It seems to not notice the USB interrupt any more after that although 
sound playback stops but mouse still moves but otherwise does not work. 
I'm not sure this is not a guest bug as it seems an interrupt handler 
should disable interrupts to not get interrupted. Could this be reproduced 
with Linux? I'd still go wit this patch series for 8.0 because the default 
case works and this was also tested with two PCI cards on AmigaOS4 which 
works not while it did not work at all before so this could be debugged 
and fixed later but adding this series makes the machine generally usable 
at least without USB devices. With -d unimp I also get these logs when 
booting MorphOS:

ok boot cd boot.img
ISO-9660 filesystem:  System-ID: "MORPHOS"  Volume-ID: "MorphOSBoot"
Root dir: "" flags=0x2 extent=0x20 size=0x1800
31.127| Memory used before SYS_Init: 9MB
i8259: level sensitive irq not supported
i8259: level sensitive irq not supported

Could it be the PIC emulation should be fixed for this?

Regards,
BALATON Zoltan


^ permalink raw reply related	[flat|nested] 40+ messages in thread

* Re: [PATCH 0/5] Pegasos2 fixes and audio output support
  2023-02-22 22:20           ` Bernhard Beschow
@ 2023-02-22 23:00             ` BALATON Zoltan
  2023-02-23  9:13               ` Bernhard Beschow
  0 siblings, 1 reply; 40+ messages in thread
From: BALATON Zoltan @ 2023-02-22 23:00 UTC (permalink / raw)
  To: Bernhard Beschow
  Cc: qemu-devel, qemu-ppc, Gerd Hoffmann, Daniel Henrique Barboza, philmd

On Wed, 22 Feb 2023, Bernhard Beschow wrote:
> Am 22. Februar 2023 21:12:01 UTC schrieb BALATON Zoltan <balaton@eik.bme.hu>:
>> On Wed, 22 Feb 2023, Bernhard Beschow wrote:
>>> Am 22. Februar 2023 19:25:16 UTC schrieb BALATON Zoltan <balaton@eik.bme.hu>:
>>>> On Wed, 22 Feb 2023, Bernhard Beschow wrote:
>>>>> On Wed, Feb 22, 2023 at 4:38 PM Bernhard Beschow <shentey@gmail.com> wrote:
>>>>>> I've had a closer look at your series and I think it can be simplified:
>>>>>> Patch 2 can be implemented quite straight-forward like I proposed in a
>>>>>> private mail: https://github.com/shentok/qemu/commit/via-priq-routing.
>>>>>> Then, in order to make patch 3 "hw/ppc/pegasos2: Fix PCI interrupt routing"
>>>>>> working, one can expose the PCI interrupts with a single line like you do
>>>>>> in patch 2. With this, patch 1 "hw/isa/vt82c686: Implement interrupt
>>>>>> routing in via_isa_set_irq" isn't needed any longer and can be omitted.
>>>>>>
>>>>>> In via-ac97, rather than using via_isa_set_irq(), pci_set_irq() can be
>>>>>> used instead. pci_set_irq() internally takes care of all the ISA interrupt
>>>>>> level tracking patch 1 attempted to address.
>>>>>>
>>>>>
>>>>> Here is a proof of concept branch to demonstrate that the simplification
>>>>> actually works: https://github.com/shentok/qemu/commits/pegasos2 (Tested
>>>>> with MorphOS with and without pegasos2.rom).
>>>>
>>>> Does this only work because both the via-ac97 and the PCI interrupts are mapped to the same ISA IRQ and you've only tested sound? The guest could configure each device to use a different IRQ, also mapping them so they share one ISA interrupt. What happens if multiple devices are mapped to IRQ 9 (which is the case on pegasos2 where PCI cards, ac97 and USB all share this IRQ) and more than one such device wants to raise an interrupt at the same time? If you ack the ac97 interrupt but a PCI network card or the USB part still wants to get the CPUs attention the ISA IRQ should remain raised until all devices are serviced.
>>>
>>> pci_bus_get_irq_level(), used in via_isa_set_pci_irq(), should handle
>>> exactly that case very well.
>>>
>>>> I don't see a way to track the status of all devices in a single qemu_irq which can only be up or down so we need something to store the state of each source.
>>>
>>> pci_set_irq() causes pci_bus_change_irq_level() to be called.
>>> pci_bus_change_irq_level() tracks the sum of all irq levels of all
>>> devices attached to a particular pin in irq_count. Have a look at
>>> pci_bus_change_irq_level() and you will understand better.
>>
>> I'm aware of that, we're using that in sam460ex which connects all PCI 
>> interrupt lines to a single IRQ and Peter explored and explained it in 
>> a comment there when that was discovered. First we had a patch with 
>> or-irq but due to this behaviot that's not needed for PCI interrupts. 
>> But the VT8132 could change what ISA IRQ you route the sub functions 
>> to.
>
> That depends on the sub function if you can do that. And if so, then it 
> depends on whether the function is still in PCI mode (see below).
>
>> It happens that on pegasos2 by default all of those are routed to IRQ9 except IDE
>
> All *PCI* interrupts are routed to IRQ9 while IDE legacy interrupts are 
> routed to the compatible ISA IRQs. Note that the IDE function must only 
> trigger the ISA IRQs if it is in legacy mode while it must only trigger 
> the PCI IRQ in non-legacy mode. See https://www.bswd.com/pciide.pdf for 
> more details on this particular topic.

The docs say so but based on what guests that work on real hardware do it 
does not work that way. Look up previous discussion on this on the list 
from around the time Mark changed via-ide about 4-5 years ago. That series 
was a result of his review of my proposed changes and gave resuled in an 
alternative appdroach. On pegasos2 (and probably also on fuloong2e based 
on same later findings, see patches to that, I can try to find these later 
if you can't find them) via-ide *always* uses IRQ 14/15 and the native 
mode only switches register addresses from legacy io ports to PCI io space 
so you can set it in with BAR regs but the IRQs don't change despite what 
the docs say. There are some hacks in Linux kernel and other guests to 
account for this but the comments for the reason are wrong in Linux, they 
say IDE is always in legacy mode but in fact if has a half-native mode 
which is what I called it where io addresses are set with BARs but IRQs 
are still the legacy ISA ones. You can find some references in previous 
discussion. Probably searching for via-ide half-native mode might find it.

>> but what if a guest changes ac97 to use a different interrupt? Then 
>> it's not a PCI interrupt any more so you can't use pci_set_irq in 
>> via=ac97.
>
> How would it do that? AFAICS there is no dedicated register to configure 
> which IRQ to use. This means that it can only trigger an interrupt via 
> its PCI intx pin which is subject to the PCI -> ISA IRQ router.

The VIA functions can use their PCI_INTERRUPT_LINE (0x3c) registers to set 
their ISA IRQ according to the docs (and unlike IDE in other functions 
like USB and sound this probably also works) and the PIRQA-D pins can be 
mapped to ISA IRQs by the 0x55-0x57 config registers of the isa bridge 
(function0). This is what I implemented in via_isa_set_irq() in this 
series.

>> There are only 4 PCI INT lines but the VIA components can be routed to 13 or 14 ISA IRQs.
>
> Pure PCI components are only able to trigger one of the four PCI intx 
> pins they are *hardwired* to.

This is true for PCI cards which can only use the 4 pins the slot they are 
in is wired to. These come in through the PIRQA-D pins and they are routed 
with the funstion 0 0x55-0x57 config registers. But I'm not sure about the 
internal functions.

> Each component has only one pin. Which ISA 
> IRQ gets triggered through that pin can be selected from 13 or 14 ISA 
> IRQs as you say by means of the three configuration registers of the PCI 
> -> ISA IRQ router.

So you say that internal functions are also wired to the same 4 lines like 
normal PCI cards? Then how can you route them to different interrupts 
setting their config reg 0x3c independent of function0 0x55-0x57 regs?

>> How do you keep track of that with only the PCI bus interrupts?
>
> Devices that operate in ISA mode such as the IDE function shall have 
> their own, dedicated ISA IRQs assigned by the guest. Otherwise this 
> causes a classic interrupt conflict, just like in the olden ISA days. If 
> the function operates in PCI mode, it must not trigger the ISA IRQs, 
> regardless of whether they are assigned or not.

This does not match with guests which clearly expect to get ISA IRQ9 for 
PCI cards and USB and sound which is where these are routed within the VIA 
bridge as the firmware programs it.

> There is also the power management function whose ACPI interrupt (SCI) 
> can be routed by means of a dedicated register. Again, a guest must make 
> sure here to not configure interrupt conflicts.
>
>> I don't get your approach.
>
> I hope that I could help you get a better understanding. The linked .pdf 
> is good and comprehensive reading material.

I'm not sure the via-ide confirms to that doc but it's also not any more a 
problem with via-ide now. That was discussed to death back then and 
"fixed" to work for the cases we want it to work with. We probably never 
agreed on how this really works but at least what we ended up with works 
with guests that run on real hardware. I'm OK with also making these cases 
work that we want now such as network and sound card under AmigaOS and 
sound under MorphOS (as long as you don't use USB) on pegasos2. This 
series does that so unless it breaks something that worked before I 
condider this moving forward and we can always improve adn fix it later. 
I'm not saying I'm not interested in your improvements just that let's 
that not hold this back now as we can fix and improve it later but 
otherwise users will have to wait until September to be able to use it. I 
know a few who want this and getting this out as it is would allow more 
people to test it and report problems so unless there are clearly wrong 
parts I'm OK with less than perfect but working solution as long as it's 
not too messy.

Regards,
BALATON Zoltan


^ permalink raw reply	[flat|nested] 40+ messages in thread

* Re: [PATCH 0/5] Pegasos2 fixes and audio output support
  2023-02-22 22:23         ` BALATON Zoltan
@ 2023-02-23  0:43           ` BALATON Zoltan
  2023-03-01 13:47             ` Mark Cave-Ayland
  0 siblings, 1 reply; 40+ messages in thread
From: BALATON Zoltan @ 2023-02-23  0:43 UTC (permalink / raw)
  To: Bernhard Beschow
  Cc: qemu-devel, qemu-ppc, Gerd Hoffmann, Daniel Henrique Barboza, philmd

On Wed, 22 Feb 2023, BALATON Zoltan wrote:
> On Wed, 22 Feb 2023, Bernhard Beschow wrote:
>> Am 22. Februar 2023 19:25:16 UTC schrieb BALATON Zoltan 
>> <balaton@eik.bme.hu>:
>>> On Wed, 22 Feb 2023, Bernhard Beschow wrote:
>>>> On Wed, Feb 22, 2023 at 4:38 PM Bernhard Beschow <shentey@gmail.com> 
>>>> wrote:
>>>>> On Tue, Feb 21, 2023 at 7:44 PM BALATON Zoltan <balaton@eik.bme.hu> 
>>>>> wrote:
>>>>>> This series fixes PCI interrupts on the ppc/pegasos2 machine and adds
>>>>>> partial implementation of the via-ac97 sound part enough to get audio
>>>>>> output. I'd like this to be merged for QEMU 8.0.
>>>>>> 
>>>>>> Regards,
>>>>>> BALATON Zoltan
>>>>>> 
>>>>>> BALATON Zoltan (5):
>>>>>>   hw/isa/vt82c686: Implement interrupt routing in via_isa_set_irq
>>>>>>   hw/isa/vt82c686: Implement PIRQ pins
>>>>>>   hw/ppc/pegasos2: Fix PCI interrupt routing
>>>>>>   hw/audio/ac97: Split off some definitions to a header
>>>>>>   hw/audio/via-ac97: Basic implementation of audio playback
>>>>>>
>>>>>>  hw/audio/ac97.c            |  43 +---
>>>>>>  hw/audio/ac97.h            |  65 ++++++
>>>>>>  hw/audio/trace-events      |   6 +
>>>>>>  hw/audio/via-ac97.c        | 436 ++++++++++++++++++++++++++++++++++++-
>>>>>>  hw/ide/via.c               |   2 +-
>>>>>>  hw/isa/vt82c686.c          |  61 +++++-
>>>>>>  hw/pci-host/mv64361.c      |   4 -
>>>>>>  hw/ppc/pegasos2.c          |  26 ++-
>>>>>>  hw/usb/vt82c686-uhci-pci.c |   5 +-
>>>>>>  include/hw/isa/vt82c686.h  |  39 +++-
>>>>>>  10 files changed, 626 insertions(+), 61 deletions(-)
>>>>>>  create mode 100644 hw/audio/ac97.h
>>>>>> 
>>>>>> --
>>>>>> 2.30.7
>>>>>> 
>>>>>> 
>>>>> Wow, the MorphOS people paid attention to sound design. Thanks for
>>>>> presenting it to us, Zoltan!
>>>>> 
>>>>> I've had a closer look at your series and I think it can be simplified:
>>>>> Patch 2 can be implemented quite straight-forward like I proposed in a
>>>>> private mail: https://github.com/shentok/qemu/commit/via-priq-routing.
>>>>> Then, in order to make patch 3 "hw/ppc/pegasos2: Fix PCI interrupt 
>>>>> routing"
>>>>> working, one can expose the PCI interrupts with a single line like you 
>>>>> do
>>>>> in patch 2. With this, patch 1 "hw/isa/vt82c686: Implement interrupt
>>>>> routing in via_isa_set_irq" isn't needed any longer and can be omitted.
>>>>> 
>>>>> In via-ac97, rather than using via_isa_set_irq(), pci_set_irq() can be
>>>>> used instead. pci_set_irq() internally takes care of all the ISA 
>>>>> interrupt
>>>>> level tracking patch 1 attempted to address.
>>>>> 
>>>> 
>>>> Here is a proof of concept branch to demonstrate that the simplification
>>>> actually works: https://github.com/shentok/qemu/commits/pegasos2 (Tested
>>>> with MorphOS with and without pegasos2.rom).
>>> 
>>> Does this only work because both the via-ac97 and the PCI interrupts are 
>>> mapped to the same ISA IRQ and you've only tested sound? The guest could 
>>> configure each device to use a different IRQ, also mapping them so they 
>>> share one ISA interrupt. What happens if multiple devices are mapped to 
>>> IRQ 9 (which is the case on pegasos2 where PCI cards, ac97 and USB all 
>>> share this IRQ) and more than one such device wants to raise an interrupt 
>>> at the same time? If you ack the ac97 interrupt but a PCI network card or 
>>> the USB part still wants to get the CPUs attention the ISA IRQ should 
>>> remain raised until all devices are serviced.
>> 
>> pci_bus_get_irq_level(), used in via_isa_set_pci_irq(), should handle
>> exactly that case very well.
>> 
>>> I don't see a way to track the status of all devices in a single qemu_irq 
>>> which can only be up or down so we need something to store the state of 
>>> each source.
>> 
>> pci_set_irq() causes pci_bus_change_irq_level() to be called.
>> pci_bus_change_irq_level() tracks the sum of all irq levels of all
>> devices attached to a particular pin in irq_count. Have a look at
>> pci_bus_change_irq_level() and you will understand better.
>> 
>>> My patch adds a state register to each ISA IRQ line for all possible 
>>> sources which could probably be stored once but then for each change of 
>>> ISA IRQ status all the mapped devices should be checked and combined so 
>>> it's easier to store them for each IRQ. Does your approach still work if 
>>> you play sound, and copy something from network to a USB device at the 
>>> same time? (I'm not sure mine does not have remaining bugs but I don't 
>>> think this can be simplified that way but if you can prove it would work I 
>>> don't mind taking an alternative version but I'm not convinced yet.)
>> 
>> Well, I can't prove that my approach works but unfortunately I can
>> prove that both our approaches cause a freeze :/ Try:
>> 1. Start `qemu-system-ppc -M pegasos2 -bios pegasos2.rom -rtc
>> base=localtime -device ati-vga,guest_hwcursor=true,romfile="" -cdrom
>> morphos-3.17.iso -device usb-mouse -device usb-kbd`
>> 2. Move the mouse while sound is playing
>> -> Observe the VM to freeze
>
> Not quite sure why but it seems to happen when both the ac97 and USB raise 
> the interrupt and the guest driver seems to get confused. Adding some debug 
> logging:
>
> diff --git a/hw/isa/vt82c686.c b/hw/isa/vt82c686.c
> index b16620daf8..f840e5a8d0 100644
> --- a/hw/isa/vt82c686.c
> +++ b/hw/isa/vt82c686.c
> @@ -636,12 +636,13 @@ void via_isa_set_irq(PCIDevice *d, ViaISAIRQSourceBit 
> n, int level)
>     if (!isa_irq) {
>         return;
>     }
> -
> +if (n > 1) fprintf(stderr, "%s: %d %d %d %x -> ", __func__, n, level, 
> isa_irq, s->isa_irq_state[isa_irq]);
>     if (level) {
>         s->isa_irq_state[isa_irq] |= BIT(n);
>     } else {
>         s->isa_irq_state[isa_irq] &= ~BIT(n);
>     }
> +if (n > 1) fprintf(stderr, "%x\n", s->isa_irq_state[isa_irq]);
>     qemu_set_irq(s->isa_irqs[isa_irq], !!s->isa_irq_state[isa_irq]);
> }
>
> I see in the normal case when there's only one interrupt for USB only:
>
> via_isa_set_irq: 2 1 9 0 -> 4
> usb_uhci_mmio_readw addr 0x0002, ret 0x0001
> usb_uhci_mmio_writew addr 0x0002, val 0x0001
> via_isa_set_irq: 2 0 9 4 -> 0
>
> For sound only:
>
> via_ac97_sgd_fetch addr=0x43b70bc --F len=3528
> via_isa_set_irq: 8 1 9 0 -> 100
> usb_uhci_mmio_readw addr 0x0002, ret 0x0000
> usb_uhci_mmio_readw addr 0x0002, ret 0x0000
> via_ac97_sgd_read 0x0 1 -> 0xc9
> via_ac97_sgd_write 0x0 1 <- 0x1
> via_isa_set_irq: 8 0 9 100 -> 0
> via_ac97_sgd_read 0x4 4 -> 0x439cbe8
> via_ac97_sgd_fetch addr=0x43c70bc -E- len=3528
> via_isa_set_irq: 8 1 9 0 -> 100
> via_ac97_sgd_read 0x4 4 -> 0x439cbe0
> via_ac97_sgd_read 0x4 4 -> 0x439cbe0
> via_ac97_sgd_read 0x10 1 -> 0x0
> usb_uhci_mmio_readw addr 0x0002, ret 0x0000
> usb_uhci_mmio_readw addr 0x0002, ret 0x0000
> via_ac97_sgd_read 0x0 1 -> 0xca
> via_ac97_sgd_write 0x0 1 <- 0x2
> via_isa_set_irq: 8 0 9 100 -> 0
> via_ac97_sgd_read 0x4 4 -> 0x439cbe0
>
> but it stops acking irqs when both are raised or it seems USB IRQ is raised 
> while it's in the guest IRQ handler:
>
> via_ac97_sgd_fetch addr=0x43c70bc -E- len=3528
> via_isa_set_irq: 8 1 9 0 -> 100
> usb_uhci_mmio_readw addr 0x0002, ret 0x0000
> usb_uhci_mmio_readw addr 0x0002, ret 0x0000
> via_isa_set_irq: 2 1 9 100 -> 104
> via_ac97_sgd_read 0x0 1 -> 0xca
> via_ac97_sgd_write 0x0 1 <- 0x2
> via_isa_set_irq: 8 0 9 104 -> 4
> via_ac97_sgd_read 0x4 4 -> 0x439cbe0
> via_ac97_sgd_fetch addr=0x43b70bc --F len=3528
> via_isa_set_irq: 8 1 9 4 -> 104
> via_ac97_sgd_read 0x4 4 -> 0x439cbe8
> via_ac97_sgd_read 0x4 4 -> 0x439cbe8
> via_ac97_sgd_read 0x10 1 -> 0x0
> usb_uhci_mmio_readw addr 0x0006, ret 0x06bf
> usb_uhci_mmio_readw addr 0x0010, ret 0x0085
> usb_uhci_mmio_writew addr 0x0010, val 0x0085
> usb_uhci_mmio_readw addr 0x0012, ret 0x0085
> usb_uhci_mmio_writew addr 0x0012, val 0x0085
> usb_uhci_mmio_readw addr 0x0006, ret 0x06b7
> usb_uhci_mmio_readw addr 0x0010, ret 0x0080
> usb_uhci_mmio_writew addr 0x0010, val 0x0080
> usb_uhci_mmio_readw addr 0x0012, ret 0x0080
> usb_uhci_mmio_writew addr 0x0012, val 0x0080
> usb_uhci_mmio_readw addr 0x0006, ret 0x0759
> usb_uhci_mmio_readw addr 0x0010, ret 0x0085
> usb_uhci_mmio_writew addr 0x0010, val 0x0085
> usb_uhci_mmio_readw addr 0x0012, ret 0x0085
> usb_uhci_mmio_writew addr 0x0012, val 0x0085
> usb_uhci_mmio_readw addr 0x0006, ret 0x0752
> usb_uhci_mmio_readw addr 0x0010, ret 0x0080
> usb_uhci_mmio_writew addr 0x0010, val 0x0080
> usb_uhci_mmio_readw addr 0x0012, ret 0x0080
> usb_uhci_mmio_writew addr 0x0012, val 0x0080
> via_isa_set_irq: 2 1 9 104 -> 104
> usb_uhci_mmio_readw addr 0x0006, ret 0x07f1
> usb_uhci_mmio_readw addr 0x0010, ret 0x0085
> usb_uhci_mmio_writew addr 0x0010, val 0x0085
> usb_uhci_mmio_readw addr 0x0012, ret 0x0085
> usb_uhci_mmio_writew addr 0x0012, val 0x0085
> usb_uhci_mmio_readw addr 0x0006, ret 0x07e9
>
> It seems to not notice the USB interrupt any more after that although sound 
> playback stops but mouse still moves but otherwise does not work. I'm not 
> sure this is not a guest bug as it seems an interrupt handler should disable 
> interrupts to not get interrupted. Could this be reproduced with Linux? I'd 
> still go wit this patch series for 8.0 because the default case works and 
> this was also tested with two PCI cards on AmigaOS4 which works not while it 
> did not work at all before so this could be debugged and fixed later but 
> adding this series makes the machine generally usable at least without USB 
> devices. With -d unimp I also get these logs when booting MorphOS:
>
> ok boot cd boot.img
> ISO-9660 filesystem:  System-ID: "MORPHOS"  Volume-ID: "MorphOSBoot"
> Root dir: "" flags=0x2 extent=0x20 size=0x1800
> 31.127| Memory used before SYS_Init: 9MB
> i8259: level sensitive irq not supported
> i8259: level sensitive irq not supported
>
> Could it be the PIC emulation should be fixed for this?

After thinking about that more I think this is the reason and this patch 
just uncovered a defficiency in the PIC model. I would not care much it 
this was only sound vs. USB but it's also sound vs. PCI cards e.g. network 
so until that's fixed in i8259 I can hack around that here like this:

diff --git a/hw/isa/vt82c686.c b/hw/isa/vt82c686.c
index b16620daf8..a6cf55a632 100644
--- a/hw/isa/vt82c686.c
+++ b/hw/isa/vt82c686.c
@@ -597,6 +597,7 @@ void via_isa_set_irq(PCIDevice *d, ViaISAIRQSourceBit n, int level)
 {
     ViaISAState *s = VIA_ISA(pci_get_function_0(d));
     uint8_t isa_irq = 0, max_irq = 15;
+    int old_level;

     if (n == VIA_IRQ_USB0 && d == PCI_DEVICE(&s->uhci[1])) {
         n++;
@@ -637,11 +638,16 @@ void via_isa_set_irq(PCIDevice *d, ViaISAIRQSourceBit n, int level)
         return;
     }

+    old_level = !!s->isa_irq_state[isa_irq];
     if (level) {
         s->isa_irq_state[isa_irq] |= BIT(n);
     } else {
         s->isa_irq_state[isa_irq] &= ~BIT(n);
     }
+    if (old_level && !!s->isa_irq_state[isa_irq]) {
+        /* Only needed because i8259 model does not support level sensitive */
+        qemu_set_irq(s->isa_irqs[isa_irq], 0);
+    }
     qemu_set_irq(s->isa_irqs[isa_irq], !!s->isa_irq_state[isa_irq]);
 }

Unless somebody has a better idea I'll go with this for a v2 and let this 
be cleaned up sometimes in the future when sombody gets around to improve 
the PIC model.

Regards,
BALATON Zoltan



^ permalink raw reply related	[flat|nested] 40+ messages in thread

* Re: [PATCH 0/5] Pegasos2 fixes and audio output support
  2023-02-22 23:00             ` BALATON Zoltan
@ 2023-02-23  9:13               ` Bernhard Beschow
  2023-02-23 12:33                 ` BALATON Zoltan
  2023-03-01 13:49                 ` Mark Cave-Ayland
  0 siblings, 2 replies; 40+ messages in thread
From: Bernhard Beschow @ 2023-02-23  9:13 UTC (permalink / raw)
  To: BALATON Zoltan
  Cc: qemu-devel, qemu-ppc, Gerd Hoffmann, Daniel Henrique Barboza, philmd



Am 22. Februar 2023 23:00:02 UTC schrieb BALATON Zoltan <balaton@eik.bme.hu>:
>On Wed, 22 Feb 2023, Bernhard Beschow wrote:
>> Am 22. Februar 2023 21:12:01 UTC schrieb BALATON Zoltan <balaton@eik.bme.hu>:
>>> On Wed, 22 Feb 2023, Bernhard Beschow wrote:
>>>> Am 22. Februar 2023 19:25:16 UTC schrieb BALATON Zoltan <balaton@eik.bme.hu>:
>>>>> On Wed, 22 Feb 2023, Bernhard Beschow wrote:
>>>>>> On Wed, Feb 22, 2023 at 4:38 PM Bernhard Beschow <shentey@gmail.com> wrote:
>>>>>>> I've had a closer look at your series and I think it can be simplified:
>>>>>>> Patch 2 can be implemented quite straight-forward like I proposed in a
>>>>>>> private mail: https://github.com/shentok/qemu/commit/via-priq-routing.
>>>>>>> Then, in order to make patch 3 "hw/ppc/pegasos2: Fix PCI interrupt routing"
>>>>>>> working, one can expose the PCI interrupts with a single line like you do
>>>>>>> in patch 2. With this, patch 1 "hw/isa/vt82c686: Implement interrupt
>>>>>>> routing in via_isa_set_irq" isn't needed any longer and can be omitted.
>>>>>>> 
>>>>>>> In via-ac97, rather than using via_isa_set_irq(), pci_set_irq() can be
>>>>>>> used instead. pci_set_irq() internally takes care of all the ISA interrupt
>>>>>>> level tracking patch 1 attempted to address.
>>>>>>> 
>>>>>> 
>>>>>> Here is a proof of concept branch to demonstrate that the simplification
>>>>>> actually works: https://github.com/shentok/qemu/commits/pegasos2 (Tested
>>>>>> with MorphOS with and without pegasos2.rom).
>>>>> 
>>>>> Does this only work because both the via-ac97 and the PCI interrupts are mapped to the same ISA IRQ and you've only tested sound? The guest could configure each device to use a different IRQ, also mapping them so they share one ISA interrupt. What happens if multiple devices are mapped to IRQ 9 (which is the case on pegasos2 where PCI cards, ac97 and USB all share this IRQ) and more than one such device wants to raise an interrupt at the same time? If you ack the ac97 interrupt but a PCI network card or the USB part still wants to get the CPUs attention the ISA IRQ should remain raised until all devices are serviced.
>>>> 
>>>> pci_bus_get_irq_level(), used in via_isa_set_pci_irq(), should handle
>>>> exactly that case very well.
>>>> 
>>>>> I don't see a way to track the status of all devices in a single qemu_irq which can only be up or down so we need something to store the state of each source.
>>>> 
>>>> pci_set_irq() causes pci_bus_change_irq_level() to be called.
>>>> pci_bus_change_irq_level() tracks the sum of all irq levels of all
>>>> devices attached to a particular pin in irq_count. Have a look at
>>>> pci_bus_change_irq_level() and you will understand better.
>>> 
>>> I'm aware of that, we're using that in sam460ex which connects all PCI interrupt lines to a single IRQ and Peter explored and explained it in a comment there when that was discovered. First we had a patch with or-irq but due to this behaviot that's not needed for PCI interrupts. But the VT8132 could change what ISA IRQ you route the sub functions to.
>> 
>> That depends on the sub function if you can do that. And if so, then it depends on whether the function is still in PCI mode (see below).
>> 
>>> It happens that on pegasos2 by default all of those are routed to IRQ9 except IDE
>> 
>> All *PCI* interrupts are routed to IRQ9 while IDE legacy interrupts are routed to the compatible ISA IRQs. Note that the IDE function must only trigger the ISA IRQs if it is in legacy mode while it must only trigger the PCI IRQ in non-legacy mode. See https://www.bswd.com/pciide.pdf for more details on this particular topic.
>
>The docs say so but based on what guests that work on real hardware do it does not work that way. Look up previous discussion on this on the list from around the time Mark changed via-ide about 4-5 years ago. That series was a result of his review of my proposed changes and gave resuled in an alternative appdroach. On pegasos2 (and probably also on fuloong2e based on same later findings, see patches to that, I can try to find these later if you can't find them) via-ide *always* uses IRQ 14/15 and the native mode only switches register addresses from legacy io ports to PCI io space so you can set it in with BAR regs but the IRQs don't change despite what the docs say. There are some hacks in Linux kernel and other guests to account for this but the comments for the reason are wrong in Linux, they say IDE is always in legacy mode but in fact if has a half-native mode which is what I called it where io addresses are set with BARs but IRQs are still the legacy ISA ones. You can find some references in previous discussion. Probably searching for via-ide half-native mode might find it.
>
>>> but what if a guest changes ac97 to use a different interrupt? Then it's not a PCI interrupt any more so you can't use pci_set_irq in via=ac97.
>> 
>> How would it do that? AFAICS there is no dedicated register to configure which IRQ to use. This means that it can only trigger an interrupt via its PCI intx pin which is subject to the PCI -> ISA IRQ router.
>
>The VIA functions can use their PCI_INTERRUPT_LINE (0x3c) registers to set their ISA IRQ according to the docs (and unlike IDE in other functions like USB and sound this probably also works) and the PIRQA-D pins can be mapped to ISA IRQs by the 0x55-0x57 config registers of the isa bridge (function0). This is what I implemented in via_isa_set_irq() in this series.
>
>>> There are only 4 PCI INT lines but the VIA components can be routed to 13 or 14 ISA IRQs.
>> 
>> Pure PCI components are only able to trigger one of the four PCI intx pins they are *hardwired* to.
>
>This is true for PCI cards which can only use the 4 pins the slot they are in is wired to. These come in through the PIRQA-D pins and they are routed with the funstion 0 0x55-0x57 config registers. But I'm not sure about the internal functions.
>
>> Each component has only one pin. Which ISA IRQ gets triggered through that pin can be selected from 13 or 14 ISA IRQs as you say by means of the three configuration registers of the PCI -> ISA IRQ router.
>
>So you say that internal functions are also wired to the same 4 lines like normal PCI cards?

Yes.

> Then how can you route them to different interrupts setting their config reg 0x3c independent of function0 0x55-0x57 regs?

0x3c isn't supposed to be interpretet by hardware, and in general hardware can't: 0x3c is standardized for every PCI function which includes standalone PCI devices in particular. Standalone PCI devices don't have access to an IRQ router. So if they don't, how could they possibly configure the IRQ they are triggering?

0x3c is only information to the OS (populated by the BIOS). It merily indicates that the PCI device needs attention when the IRQ configured in 0x3c is raised. See comment 4 in https://community.osr.com/discussion/30399/read-only-pci-interrupt-line-register for another explanation.

Even though the south bridge contains an interrupt router doesn't mean that its PCI functions can configure their IRQ through their 0x3c registers. That would change the semantics of standardized PCI registers which is surely not permitted by the standard. Instead, the PCI IRQs are configured through the device-specific 0x55-0x57 regs.

I see that 0x3c is also used for the USB functions. They used to trigger the raw ISA IRQs before your series which seems wrong. I think 0x3c usage needs to be cleaned up in the VIA model. Otherwise this will likely cause problems elsewhere.

>
>>> How do you keep track of that with only the PCI bus interrupts?
>> 
>> Devices that operate in ISA mode such as the IDE function shall have their own, dedicated ISA IRQs assigned by the guest. Otherwise this causes a classic interrupt conflict, just like in the olden ISA days. If the function operates in PCI mode, it must not trigger the ISA IRQs, regardless of whether they are assigned or not.
>
>This does not match with guests which clearly expect to get ISA IRQ9 for PCI cards and USB and sound which is where these are routed within the VIA bridge as the firmware programs it.

What I meant was that a component able to operate in native/legacy/mixed mode such as IDE must not use both PCI and legacy ISA interrupts at the same time. Multiple PCI functions may of course share interrupts.

>
>> There is also the power management function whose ACPI interrupt (SCI) can be routed by means of a dedicated register. Again, a guest must make sure here to not configure interrupt conflicts.
>> 
>>> I don't get your approach.
>> 
>> I hope that I could help you get a better understanding. The linked .pdf is good and comprehensive reading material.
>
>I'm not sure the via-ide confirms to that doc but it's also not any more a problem with via-ide now. That was discussed to death back then and "fixed" to work for the cases we want it to work with. We probably never agreed on how this really works but at least what we ended up with works with guests that run on real hardware. I'm OK with also making these cases work that we want now such as network and sound card under AmigaOS and sound under MorphOS (as long as you don't use USB) on pegasos2. This series does that so unless it breaks something that worked before I condider this moving forward and we can always improve adn fix it later. I'm not saying I'm not interested in your improvements just that let's that not hold this back now as we can fix and improve it later but otherwise users will have to wait until September to be able to use it. I know a few who want this and getting this out as it is would allow more people to test it and report problems so unless there are clearly wrong parts I'm OK with less than perfect but working solution as long as it's not too messy.

Patch 1 really seems like duplicating PCI code that already exists in QEMU. This is not needed and we should avoid that.

Moreover, usage of the IRQ line register (0x3c) for interrupt routing should be switched to using the 0x55-0x57 regs to be PCI compliant.

Thanks to your great work to make via-ac97 work we can confirm that both IRQ routing implementations basically work for now. Let's work out a solution that relies on existing code, sticks to the standard and hopefully works for i386 and MIPS, too.

Best regards,
Bernhard

>
>Regards,
>BALATON Zoltan


^ permalink raw reply	[flat|nested] 40+ messages in thread

* Re: [PATCH 0/5] Pegasos2 fixes and audio output support
  2023-02-23  9:13               ` Bernhard Beschow
@ 2023-02-23 12:33                 ` BALATON Zoltan
  2023-02-23 13:17                   ` Bernhard Beschow
  2023-03-01 13:49                 ` Mark Cave-Ayland
  1 sibling, 1 reply; 40+ messages in thread
From: BALATON Zoltan @ 2023-02-23 12:33 UTC (permalink / raw)
  To: Bernhard Beschow
  Cc: qemu-devel, qemu-ppc, Gerd Hoffmann, Daniel Henrique Barboza, philmd

[-- Attachment #1: Type: text/plain, Size: 15789 bytes --]

On Thu, 23 Feb 2023, Bernhard Beschow wrote:
> Am 22. Februar 2023 23:00:02 UTC schrieb BALATON Zoltan <balaton@eik.bme.hu>:
>> On Wed, 22 Feb 2023, Bernhard Beschow wrote:
>>> Am 22. Februar 2023 21:12:01 UTC schrieb BALATON Zoltan <balaton@eik.bme.hu>:
>>>> On Wed, 22 Feb 2023, Bernhard Beschow wrote:
>>>>> Am 22. Februar 2023 19:25:16 UTC schrieb BALATON Zoltan <balaton@eik.bme.hu>:
>>>>>> On Wed, 22 Feb 2023, Bernhard Beschow wrote:
>>>>>>> On Wed, Feb 22, 2023 at 4:38 PM Bernhard Beschow <shentey@gmail.com> wrote:
>>>>>>>> I've had a closer look at your series and I think it can be simplified:
>>>>>>>> Patch 2 can be implemented quite straight-forward like I proposed in a
>>>>>>>> private mail: https://github.com/shentok/qemu/commit/via-priq-routing.
>>>>>>>> Then, in order to make patch 3 "hw/ppc/pegasos2: Fix PCI interrupt routing"
>>>>>>>> working, one can expose the PCI interrupts with a single line like you do
>>>>>>>> in patch 2. With this, patch 1 "hw/isa/vt82c686: Implement interrupt
>>>>>>>> routing in via_isa_set_irq" isn't needed any longer and can be omitted.
>>>>>>>>
>>>>>>>> In via-ac97, rather than using via_isa_set_irq(), pci_set_irq() can be
>>>>>>>> used instead. pci_set_irq() internally takes care of all the ISA interrupt
>>>>>>>> level tracking patch 1 attempted to address.
>>>>>>>>
>>>>>>>
>>>>>>> Here is a proof of concept branch to demonstrate that the simplification
>>>>>>> actually works: https://github.com/shentok/qemu/commits/pegasos2 (Tested
>>>>>>> with MorphOS with and without pegasos2.rom).
>>>>>>
>>>>>> Does this only work because both the via-ac97 and the PCI interrupts are mapped to the same ISA IRQ and you've only tested sound? The guest could configure each device to use a different IRQ, also mapping them so they share one ISA interrupt. What happens if multiple devices are mapped to IRQ 9 (which is the case on pegasos2 where PCI cards, ac97 and USB all share this IRQ) and more than one such device wants to raise an interrupt at the same time? If you ack the ac97 interrupt but a PCI network card or the USB part still wants to get the CPUs attention the ISA IRQ should remain raised until all devices are serviced.
>>>>>
>>>>> pci_bus_get_irq_level(), used in via_isa_set_pci_irq(), should handle
>>>>> exactly that case very well.
>>>>>
>>>>>> I don't see a way to track the status of all devices in a single qemu_irq which can only be up or down so we need something to store the state of each source.
>>>>>
>>>>> pci_set_irq() causes pci_bus_change_irq_level() to be called.
>>>>> pci_bus_change_irq_level() tracks the sum of all irq levels of all
>>>>> devices attached to a particular pin in irq_count. Have a look at
>>>>> pci_bus_change_irq_level() and you will understand better.
>>>>
>>>> I'm aware of that, we're using that in sam460ex which connects all PCI interrupt lines to a single IRQ and Peter explored and explained it in a comment there when that was discovered. First we had a patch with or-irq but due to this behaviot that's not needed for PCI interrupts. But the VT8132 could change what ISA IRQ you route the sub functions to.
>>>
>>> That depends on the sub function if you can do that. And if so, then it depends on whether the function is still in PCI mode (see below).
>>>
>>>> It happens that on pegasos2 by default all of those are routed to IRQ9 except IDE
>>>
>>> All *PCI* interrupts are routed to IRQ9 while IDE legacy interrupts are routed to the compatible ISA IRQs. Note that the IDE function must only trigger the ISA IRQs if it is in legacy mode while it must only trigger the PCI IRQ in non-legacy mode. See https://www.bswd.com/pciide.pdf for more details on this particular topic.
>>
>> The docs say so but based on what guests that work on real hardware do it does not work that way. Look up previous discussion on this on the list from around the time Mark changed via-ide about 4-5 years ago. That series was a result of his review of my proposed changes and gave resuled in an alternative appdroach. On pegasos2 (and probably also on fuloong2e based on same later findings, see patches to that, I can try to find these later if you can't find them) via-ide *always* uses IRQ 14/15 and the native mode only switches register addresses from legacy io ports to PCI io space so you can set it in with BAR regs but the IRQs don't change despite what the docs say. There are some hacks in Linux kernel and other guests to account for this but the comments for the reason are wrong in Linux, they say IDE is always in legacy mode but in fact if has a half-native mode which is what I called it where io addresses are set with BARs but IRQs are still the legacy ISA ones. You can find s
 ome references in previous discussion. Probably searching for via-ide half-native mode might find it.
>>
>>>> but what if a guest changes ac97 to use a different interrupt? Then it's not a PCI interrupt any more so you can't use pci_set_irq in via=ac97.
>>>
>>> How would it do that? AFAICS there is no dedicated register to configure which IRQ to use. This means that it can only trigger an interrupt via its PCI intx pin which is subject to the PCI -> ISA IRQ router.
>>
>> The VIA functions can use their PCI_INTERRUPT_LINE (0x3c) registers to set their ISA IRQ according to the docs (and unlike IDE in other functions like USB and sound this probably also works) and the PIRQA-D pins can be mapped to ISA IRQs by the 0x55-0x57 config registers of the isa bridge (function0). This is what I implemented in via_isa_set_irq() in this series.
>>
>>>> There are only 4 PCI INT lines but the VIA components can be routed to 13 or 14 ISA IRQs.
>>>
>>> Pure PCI components are only able to trigger one of the four PCI intx pins they are *hardwired* to.
>>
>> This is true for PCI cards which can only use the 4 pins the slot they are in is wired to. These come in through the PIRQA-D pins and they are routed with the funstion 0 0x55-0x57 config registers. But I'm not sure about the internal functions.
>>
>>> Each component has only one pin. Which ISA IRQ gets triggered through that pin can be selected from 13 or 14 ISA IRQs as you say by means of the three configuration registers of the PCI -> ISA IRQ router.
>>
>> So you say that internal functions are also wired to the same 4 lines like normal PCI cards?
>
> Yes.
>
>> Then how can you route them to different interrupts setting their config reg 0x3c independent of function0 0x55-0x57 regs?
>
> 0x3c isn't supposed to be interpretet by hardware, and in general 
> hardware can't: 0x3c is standardized for every PCI function which 
> includes standalone PCI devices in particular. Standalone PCI devices 
> don't have access to an IRQ router. So if they don't, how could they 
> possibly configure the IRQ they are triggering?
>
> 0x3c is only information to the OS (populated by the BIOS). It merily 
> indicates that the PCI device needs attention when the IRQ configured in 
> 0x3c is raised. See comment 4 in 
> https://community.osr.com/discussion/30399/read-only-pci-interrupt-line-register 
> for another explanation.

But we're not talking about notmal PCI devices attached to a PCI slot here 
but internal functions of the VIA southbridges which are internally 
connected in some way inside the chip. You (and also Mark before, check 
the previous discussion on via-ide half-native mode) seem to want to 
assume these functions are normal PCI devices and force them in that model 
but that does not match with what the VIA datasheet says and what guests 
running on these behave so I don't think we want to (or can) assume these 
internal functions are normal PCI devices.

> Even though the south bridge contains an interrupt router doesn't mean 
> that its PCI functions can configure their IRQ through their 0x3c 
> registers. That would change the semantics of standardized PCI registers 
> which is surely not permitted by the standard. Instead, the PCI IRQs are 
> configured through the device-specific 0x55-0x57 regs.

But the datasheets (both 686B and 8231) say so and guests do expect IRQ 9 
when the config reg of the AC97 and USB functions are set to that by the 
firmware. The 0x55-0x57 regs on function0 only configures the routing of 
the PIRQA-D pins which are external inputs to the chip while internal 
functions are routed by their 0x3c reg. At least that's how I understand 
the docs and how all the guests I've looked at seem to work. So I think 
this VIA device does not fully confirm to PCI standard with respect to its 
internal functions that are instead kind of mixed ISA/PCI things, probably 
for compatibility with contemporary OS drivers or trying to fit former ISA 
hardware to the then new PCI bus. These chips are from the 90's when these 
were new and maybe not that standardised or not everybody did everything 
in a standard way.

> I see that 0x3c is also used for the USB functions. They used to trigger 
> the raw ISA IRQs before your series which seems wrong. I think 0x3c 
> usage needs to be cleaned up in the VIA model. Otherwise this will 
> likely cause problems elsewhere.

Again, don't look at papers that this VIA chip might not follow. If 
anything, look at its datasheet and guests running on it for reference. 
The guests expect ISA IRQs as set in 0x3c of internal functions so these 
functions are not regular PCI devices. They are part of the chip and 
behave how the chip docs say which may not be fully match a normal PCI 
card. I think your proposed clesn up to make these functions PCI devices 
would break it becuase then you can't properly route IRQs the way the 
datasheet says. That's why I think this series is needed.

>>>> How do you keep track of that with only the PCI bus interrupts?
>>>
>>> Devices that operate in ISA mode such as the IDE function shall have 
>>> their own, dedicated ISA IRQs assigned by the guest. Otherwise this 
>>> causes a classic interrupt conflict, just like in the olden ISA days. 
>>> If the function operates in PCI mode, it must not trigger the ISA 
>>> IRQs, regardless of whether they are assigned or not.
>>
>> This does not match with guests which clearly expect to get ISA IRQ9 
>> for PCI cards and USB and sound which is where these are routed within 
>> the VIA bridge as the firmware programs it.
>
> What I meant was that a component able to operate in native/legacy/mixed 
> mode such as IDE must not use both PCI and legacy ISA interrupts at the 
> same time. Multiple PCI functions may of course share interrupts.

The IDE part is even more complicated than other functions because of its 
"half-native" mode which is not quite what the datasheet suggests yet 
still both pegasos2 and fuloong2e guests seem to assume it works that way 
and we model it so now. So I think our model is correct we just doesn't 
model the startup state in legacy mode which is then immediately switched 
to native mode by the firmware anyway so we only model that, but a quirk 
in real hardware seems to be that contrary to the docs the IRQs are still 
tied to the legasy 14/15 even when in native mode and the full native mode 
IRQ routing via 0x3c is not implemented. The pegasos2 firmware sets the 
ide function to native mode and sets 0x3c to 9 but then guests still 
expect to get IRQs via 14/15. This is what the Linux kernel fixes up in 
the device tree for it's drivers to work, MorphOS just knows and does not 
care about the 0x3c setting yet it excpects to be able to set io addresses 
with BARs so it assumes native mode with legacy IRQs. This was what we 
were discussing long ago and now looks like we're back to that again just 
with you instead of Mark.

>>> There is also the power management function whose ACPI interrupt (SCI) 
>>> can be routed by means of a dedicated register. Again, a guest must 
>>> make sure here to not configure interrupt conflicts.
>>>
>>>> I don't get your approach.
>>>
>>> I hope that I could help you get a better understanding. The linked 
>>> .pdf is good and comprehensive reading material.
>>
>> I'm not sure the via-ide confirms to that doc but it's also not any 
>> more a problem with via-ide now. That was discussed to death back then 
>> and "fixed" to work for the cases we want it to work with. We probably 
>> never agreed on how this really works but at least what we ended up 
>> with works with guests that run on real hardware. I'm OK with also 
>> making these cases work that we want now such as network and sound card 
>> under AmigaOS and sound under MorphOS (as long as you don't use USB) on 
>> pegasos2. This series does that so unless it breaks something that 
>> worked before I condider this moving forward and we can always improve 
>> adn fix it later. I'm not saying I'm not interested in your 
>> improvements just that let's that not hold this back now as we can fix 
>> and improve it later but otherwise users will have to wait until 
>> September to be able to use it. I know a few who want this and getting 
>> this out as it is would allow more people to test it and report 
>> problems so unless there are clearly wrong parts I'm OK with less than 
>> perfect but working solution as long as it's not too messy.
>
> Patch 1 really seems like duplicating PCI code that already exists in 
> QEMU. This is not needed and we should avoid that.
>
> Moreover, usage of the IRQ line register (0x3c) for interrupt routing 
> should be switched to using the 0x55-0x57 regs to be PCI compliant.

That would not work because then guests were not able to separately 
configure IRQs for PCI interrupt lines and internal functions which is 
what the datasheet says should be possible. The internal functions' IRQs 
are not affeceted by 0x55-0x57 but routed by different registers. I think 
your series only work because pegasos2 firmware progeams everything to 
IRQ9 but if a guest decided to change that and route e.g. USB somewhere 
else then it would break. My series models that a bit better but may still 
break if a guest routes a function to an IRQ also controlled by some ISA 
device (like serial or ps2 keyboard) which are currently done within 
QEMU's ISA model so I can't easily channel those IRQs through the 
via-isa.for proper routing but it's unliikely guests would want to do that 
so in practice my series should work. We may duplicate PCI IRQ routing 
here but this chip does that and more so we need to implement it as it 
handles more than the 4 PCI interrupts so that implementation is not 
enough to handle all sources this chip has. This isn't a complex piece of 
code though so having a similar implementation is not a problem IMO.

> Thanks to your great work to make via-ac97 work we can confirm that both 
> IRQ routing implementations basically work for now. Let's work out a 
> solution that relies on existing code, sticks to the standard and 
> hopefully works for i386 and MIPS, too.

I'm still not convinced your implementation is correct so I would atick to 
my series with that, that this could be improved and changed in the future 
in follow up series but I don't want that to hold this back now. So unless 
there's a good reason against taking this series now (like it breaking 
something) I'd like this to be merged for 8.0. I could go with your 
version which might work too as long as guests share IRQ of internal 
functions with PCI interrupts but I don't think that's correct and I think 
my series better models the actual hardware and more clearly separates 
components. whereas your proposal reuses code from PCI that's not quite 
adequate for the job it's supposed to do. So I think in this case that 
should not be reused here. The VIA chip is more complex than a simple PCI 
IRQ router, that's just a part of its IRQ routing. It handles more sources 
than just the 4 PCI interrupt lines.

Regards,
BALATON Zoltan

^ permalink raw reply	[flat|nested] 40+ messages in thread

* Re: [PATCH 0/5] Pegasos2 fixes and audio output support
  2023-02-23 12:33                 ` BALATON Zoltan
@ 2023-02-23 13:17                   ` Bernhard Beschow
  2023-02-23 14:23                     ` BALATON Zoltan
  0 siblings, 1 reply; 40+ messages in thread
From: Bernhard Beschow @ 2023-02-23 13:17 UTC (permalink / raw)
  To: BALATON Zoltan
  Cc: qemu-devel, qemu-ppc, Gerd Hoffmann, Daniel Henrique Barboza,
	philmd, Mark Cave-Ayland

[-- Attachment #1: Type: text/plain, Size: 16902 bytes --]

On Thu, Feb 23, 2023 at 1:34 PM BALATON Zoltan <balaton@eik.bme.hu> wrote:

> On Thu, 23 Feb 2023, Bernhard Beschow wrote:
> > Am 22. Februar 2023 23:00:02 UTC schrieb BALATON Zoltan <
> balaton@eik.bme.hu>:
> >> On Wed, 22 Feb 2023, Bernhard Beschow wrote:
> >>> Am 22. Februar 2023 21:12:01 UTC schrieb BALATON Zoltan <
> balaton@eik.bme.hu>:
> >>>> On Wed, 22 Feb 2023, Bernhard Beschow wrote:
> >>>>> Am 22. Februar 2023 19:25:16 UTC schrieb BALATON Zoltan <
> balaton@eik.bme.hu>:
> >>>>>> On Wed, 22 Feb 2023, Bernhard Beschow wrote:
> >>>>>>> On Wed, Feb 22, 2023 at 4:38 PM Bernhard Beschow <
> shentey@gmail.com> wrote:
> >>>>>>>> I've had a closer look at your series and I think it can be
> simplified:
> >>>>>>>> Patch 2 can be implemented quite straight-forward like I proposed
> in a
> >>>>>>>> private mail:
> https://github.com/shentok/qemu/commit/via-priq-routing.
> >>>>>>>> Then, in order to make patch 3 "hw/ppc/pegasos2: Fix PCI
> interrupt routing"
> >>>>>>>> working, one can expose the PCI interrupts with a single line
> like you do
> >>>>>>>> in patch 2. With this, patch 1 "hw/isa/vt82c686: Implement
> interrupt
> >>>>>>>> routing in via_isa_set_irq" isn't needed any longer and can be
> omitted.
> >>>>>>>>
> >>>>>>>> In via-ac97, rather than using via_isa_set_irq(), pci_set_irq()
> can be
> >>>>>>>> used instead. pci_set_irq() internally takes care of all the ISA
> interrupt
> >>>>>>>> level tracking patch 1 attempted to address.
> >>>>>>>>
> >>>>>>>
> >>>>>>> Here is a proof of concept branch to demonstrate that the
> simplification
> >>>>>>> actually works: https://github.com/shentok/qemu/commits/pegasos2
> (Tested
> >>>>>>> with MorphOS with and without pegasos2.rom).
> >>>>>>
> >>>>>> Does this only work because both the via-ac97 and the PCI
> interrupts are mapped to the same ISA IRQ and you've only tested sound? The
> guest could configure each device to use a different IRQ, also mapping them
> so they share one ISA interrupt. What happens if multiple devices are
> mapped to IRQ 9 (which is the case on pegasos2 where PCI cards, ac97 and
> USB all share this IRQ) and more than one such device wants to raise an
> interrupt at the same time? If you ack the ac97 interrupt but a PCI network
> card or the USB part still wants to get the CPUs attention the ISA IRQ
> should remain raised until all devices are serviced.
> >>>>>
> >>>>> pci_bus_get_irq_level(), used in via_isa_set_pci_irq(), should handle
> >>>>> exactly that case very well.
> >>>>>
> >>>>>> I don't see a way to track the status of all devices in a single
> qemu_irq which can only be up or down so we need something to store the
> state of each source.
> >>>>>
> >>>>> pci_set_irq() causes pci_bus_change_irq_level() to be called.
> >>>>> pci_bus_change_irq_level() tracks the sum of all irq levels of all
> >>>>> devices attached to a particular pin in irq_count. Have a look at
> >>>>> pci_bus_change_irq_level() and you will understand better.
> >>>>
> >>>> I'm aware of that, we're using that in sam460ex which connects all
> PCI interrupt lines to a single IRQ and Peter explored and explained it in
> a comment there when that was discovered. First we had a patch with or-irq
> but due to this behaviot that's not needed for PCI interrupts. But the
> VT8132 could change what ISA IRQ you route the sub functions to.
> >>>
> >>> That depends on the sub function if you can do that. And if so, then
> it depends on whether the function is still in PCI mode (see below).
> >>>
> >>>> It happens that on pegasos2 by default all of those are routed to
> IRQ9 except IDE
> >>>
> >>> All *PCI* interrupts are routed to IRQ9 while IDE legacy interrupts
> are routed to the compatible ISA IRQs. Note that the IDE function must only
> trigger the ISA IRQs if it is in legacy mode while it must only trigger the
> PCI IRQ in non-legacy mode. See https://www.bswd.com/pciide.pdf for more
> details on this particular topic.
> >>
> >> The docs say so but based on what guests that work on real hardware do
> it does not work that way. Look up previous discussion on this on the list
> from around the time Mark changed via-ide about 4-5 years ago. That series
> was a result of his review of my proposed changes and gave resuled in an
> alternative appdroach. On pegasos2 (and probably also on fuloong2e based on
> same later findings, see patches to that, I can try to find these later if
> you can't find them) via-ide *always* uses IRQ 14/15 and the native mode
> only switches register addresses from legacy io ports to PCI io space so
> you can set it in with BAR regs but the IRQs don't change despite what the
> docs say. There are some hacks in Linux kernel and other guests to account
> for this but the comments for the reason are wrong in Linux, they say IDE
> is always in legacy mode but in fact if has a half-native mode which is
> what I called it where io addresses are set with BARs but IRQs are still
> the legacy ISA ones. You can find s
>  ome references in previous discussion. Probably searching for via-ide
> half-native mode might find it.
> >>
> >>>> but what if a guest changes ac97 to use a different interrupt? Then
> it's not a PCI interrupt any more so you can't use pci_set_irq in via=ac97.
> >>>
> >>> How would it do that? AFAICS there is no dedicated register to
> configure which IRQ to use. This means that it can only trigger an
> interrupt via its PCI intx pin which is subject to the PCI -> ISA IRQ
> router.
> >>
> >> The VIA functions can use their PCI_INTERRUPT_LINE (0x3c) registers to
> set their ISA IRQ according to the docs (and unlike IDE in other functions
> like USB and sound this probably also works) and the PIRQA-D pins can be
> mapped to ISA IRQs by the 0x55-0x57 config registers of the isa bridge
> (function0). This is what I implemented in via_isa_set_irq() in this series.
> >>
> >>>> There are only 4 PCI INT lines but the VIA components can be routed
> to 13 or 14 ISA IRQs.
> >>>
> >>> Pure PCI components are only able to trigger one of the four PCI intx
> pins they are *hardwired* to.
> >>
> >> This is true for PCI cards which can only use the 4 pins the slot they
> are in is wired to. These come in through the PIRQA-D pins and they are
> routed with the funstion 0 0x55-0x57 config registers. But I'm not sure
> about the internal functions.
> >>
> >>> Each component has only one pin. Which ISA IRQ gets triggered through
> that pin can be selected from 13 or 14 ISA IRQs as you say by means of the
> three configuration registers of the PCI -> ISA IRQ router.
> >>
> >> So you say that internal functions are also wired to the same 4 lines
> like normal PCI cards?
> >
> > Yes.
> >
> >> Then how can you route them to different interrupts setting their
> config reg 0x3c independent of function0 0x55-0x57 regs?
> >
> > 0x3c isn't supposed to be interpretet by hardware, and in general
> > hardware can't: 0x3c is standardized for every PCI function which
> > includes standalone PCI devices in particular. Standalone PCI devices
> > don't have access to an IRQ router. So if they don't, how could they
> > possibly configure the IRQ they are triggering?
> >
> > 0x3c is only information to the OS (populated by the BIOS). It merily
> > indicates that the PCI device needs attention when the IRQ configured in
> > 0x3c is raised. See comment 4 in
> >
> https://community.osr.com/discussion/30399/read-only-pci-interrupt-line-register
> > for another explanation.
>
> But we're not talking about notmal PCI devices attached to a PCI slot here
> but internal functions of the VIA southbridges which are internally
> connected in some way inside the chip. You (and also Mark before, check
> the previous discussion on via-ide half-native mode) seem to want to
> assume these functions are normal PCI devices and force them in that model
> but that does not match with what the VIA datasheet says and what guests
> running on these behave so I don't think we want to (or can) assume these
> internal functions are normal PCI devices.
>
> > Even though the south bridge contains an interrupt router doesn't mean
> > that its PCI functions can configure their IRQ through their 0x3c
> > registers. That would change the semantics of standardized PCI registers
> > which is surely not permitted by the standard. Instead, the PCI IRQs are
> > configured through the device-specific 0x55-0x57 regs.
>
> But the datasheets (both 686B and 8231) say so and guests do expect IRQ 9
> when the config reg of the AC97 and USB functions are set to that by the
> firmware. The 0x55-0x57 regs on function0 only configures the routing of
> the PIRQA-D pins which are external inputs to the chip while internal
> functions are routed by their 0x3c reg. At least that's how I understand
> the docs and how all the guests I've looked at seem to work. So I think
> this VIA device does not fully confirm to PCI standard with respect to its
> internal functions that are instead kind of mixed ISA/PCI things, probably
> for compatibility with contemporary OS drivers or trying to fit former ISA
> hardware to the then new PCI bus. These chips are from the 90's when these
> were new and maybe not that standardised or not everybody did everything
> in a standard way.
>
> > I see that 0x3c is also used for the USB functions. They used to trigger
> > the raw ISA IRQs before your series which seems wrong. I think 0x3c
> > usage needs to be cleaned up in the VIA model. Otherwise this will
> > likely cause problems elsewhere.
>
> Again, don't look at papers that this VIA chip might not follow. If
> anything, look at its datasheet and guests running on it for reference.
> The guests expect ISA IRQs as set in 0x3c of internal functions so these
> functions are not regular PCI devices. They are part of the chip and
> behave how the chip docs say which may not be fully match a normal PCI
> card. I think your proposed clesn up to make these functions PCI devices
> would break it becuase then you can't properly route IRQs the way the
> datasheet says. That's why I think this series is needed.
>
> >>>> How do you keep track of that with only the PCI bus interrupts?
> >>>
> >>> Devices that operate in ISA mode such as the IDE function shall have
> >>> their own, dedicated ISA IRQs assigned by the guest. Otherwise this
> >>> causes a classic interrupt conflict, just like in the olden ISA days.
> >>> If the function operates in PCI mode, it must not trigger the ISA
> >>> IRQs, regardless of whether they are assigned or not.
> >>
> >> This does not match with guests which clearly expect to get ISA IRQ9
> >> for PCI cards and USB and sound which is where these are routed within
> >> the VIA bridge as the firmware programs it.
> >
> > What I meant was that a component able to operate in native/legacy/mixed
> > mode such as IDE must not use both PCI and legacy ISA interrupts at the
> > same time. Multiple PCI functions may of course share interrupts.
>
> The IDE part is even more complicated than other functions because of its
> "half-native" mode which is not quite what the datasheet suggests yet
> still both pegasos2 and fuloong2e guests seem to assume it works that way
> and we model it so now. So I think our model is correct we just doesn't
> model the startup state in legacy mode which is then immediately switched
> to native mode by the firmware anyway so we only model that, but a quirk
> in real hardware seems to be that contrary to the docs the IRQs are still
> tied to the legasy 14/15 even when in native mode and the full native mode
> IRQ routing via 0x3c is not implemented. The pegasos2 firmware sets the
> ide function to native mode and sets 0x3c to 9 but then guests still
> expect to get IRQs via 14/15. This is what the Linux kernel fixes up in
> the device tree for it's drivers to work, MorphOS just knows and does not
> care about the 0x3c setting yet it excpects to be able to set io addresses
> with BARs so it assumes native mode with legacy IRQs. This was what we
> were discussing long ago and now looks like we're back to that again just
> with you instead of Mark.
>
> >>> There is also the power management function whose ACPI interrupt (SCI)
> >>> can be routed by means of a dedicated register. Again, a guest must
> >>> make sure here to not configure interrupt conflicts.
> >>>
> >>>> I don't get your approach.
> >>>
> >>> I hope that I could help you get a better understanding. The linked
> >>> .pdf is good and comprehensive reading material.
> >>
> >> I'm not sure the via-ide confirms to that doc but it's also not any
> >> more a problem with via-ide now. That was discussed to death back then
> >> and "fixed" to work for the cases we want it to work with. We probably
> >> never agreed on how this really works but at least what we ended up
> >> with works with guests that run on real hardware. I'm OK with also
> >> making these cases work that we want now such as network and sound card
> >> under AmigaOS and sound under MorphOS (as long as you don't use USB) on
> >> pegasos2. This series does that so unless it breaks something that
> >> worked before I condider this moving forward and we can always improve
> >> adn fix it later. I'm not saying I'm not interested in your
> >> improvements just that let's that not hold this back now as we can fix
> >> and improve it later but otherwise users will have to wait until
> >> September to be able to use it. I know a few who want this and getting
> >> this out as it is would allow more people to test it and report
> >> problems so unless there are clearly wrong parts I'm OK with less than
> >> perfect but working solution as long as it's not too messy.
> >
> > Patch 1 really seems like duplicating PCI code that already exists in
> > QEMU. This is not needed and we should avoid that.
> >
> > Moreover, usage of the IRQ line register (0x3c) for interrupt routing
> > should be switched to using the 0x55-0x57 regs to be PCI compliant.
>
> That would not work because then guests were not able to separately
> configure IRQs for PCI interrupt lines and internal functions which is
> what the datasheet says should be possible. The internal functions' IRQs
> are not affeceted by 0x55-0x57 but routed by different registers.


How do you know?

I think
> your series only work because pegasos2 firmware progeams everything to
> IRQ9 but if a guest decided to change that and route e.g. USB somewhere
> else then it would break. My series models that a bit better but may still
> break if a guest routes a function to an IRQ also controlled by some ISA
> device (like serial or ps2 keyboard) which are currently done within
> QEMU's ISA model so I can't easily channel those IRQs through the
> via-isa.for proper routing but it's unliikely guests would want to do that
> so in practice my series should work. We may duplicate PCI IRQ routing
> here but this chip does that and more so we need to implement it as it
> handles more than the 4 PCI interrupts so that implementation is not
> enough to handle all sources this chip has. This isn't a complex piece of
> code though so having a similar implementation is not a problem IMO.
>
> > Thanks to your great work to make via-ac97 work we can confirm that both
> > IRQ routing implementations basically work for now. Let's work out a
> > solution that relies on existing code, sticks to the standard and
> > hopefully works for i386 and MIPS, too.
>
> I'm still not convinced your implementation is correct


It seems that Mark (cc'd), I, the commenter in
https://community.osr.com/discussion/30399/read-only-pci-interrupt-line-register
and the PCI specification agree that the 0x3c regs aren't supposed to be
interpreted by hardware. I've provided a working example with no functional
downsides to the 0x3c approach. I've provided the PCI-IDE reading material
that Mark suggested for reading in
https://lore.kernel.org/qemu-devel/b38987d5-5530-ecd9-2fd2-3a57e1a611dd@ilande.co.uk/
. I'm running out of ideas now on how to proceed.

Best regards,
Bernhard


> so I would atick to
> my series with that, that this could be improved and changed in the future
> in follow up series but I don't want that to hold this back now. So unless
> there's a good reason against taking this series now (like it breaking
> something) I'd like this to be merged for 8.0. I could go with your
> version which might work too as long as guests share IRQ of internal
> functions with PCI interrupts but I don't think that's correct and I think
> my series better models the actual hardware and more clearly separates
> components. whereas your proposal reuses code from PCI that's not quite
> adequate for the job it's supposed to do. So I think in this case that
> should not be reused here. The VIA chip is more complex than a simple PCI
> IRQ router, that's just a part of its IRQ routing. It handles more sources
> than just the 4 PCI interrupt lines.
>
> Regards,
> BALATON Zoltan

[-- Attachment #2: Type: text/html, Size: 20645 bytes --]

^ permalink raw reply	[flat|nested] 40+ messages in thread

* Re: [PATCH 0/5] Pegasos2 fixes and audio output support
  2023-02-23 13:17                   ` Bernhard Beschow
@ 2023-02-23 14:23                     ` BALATON Zoltan
  2023-02-23 20:28                       ` Bernhard Beschow
  0 siblings, 1 reply; 40+ messages in thread
From: BALATON Zoltan @ 2023-02-23 14:23 UTC (permalink / raw)
  To: Bernhard Beschow
  Cc: qemu-devel, qemu-ppc, Gerd Hoffmann, Daniel Henrique Barboza,
	philmd, Mark Cave-Ayland

On Thu, 23 Feb 2023, Bernhard Beschow wrote:
> On Thu, Feb 23, 2023 at 1:34 PM BALATON Zoltan <balaton@eik.bme.hu> wrote:
>>>>>> I don't get your approach.
>>>>>
>>>>> I hope that I could help you get a better understanding. The linked
>>>>> .pdf is good and comprehensive reading material.
>>>>
>>>> I'm not sure the via-ide confirms to that doc but it's also not any
>>>> more a problem with via-ide now. That was discussed to death back then
>>>> and "fixed" to work for the cases we want it to work with. We probably
>>>> never agreed on how this really works but at least what we ended up
>>>> with works with guests that run on real hardware. I'm OK with also
>>>> making these cases work that we want now such as network and sound card
>>>> under AmigaOS and sound under MorphOS (as long as you don't use USB) on
>>>> pegasos2. This series does that so unless it breaks something that
>>>> worked before I condider this moving forward and we can always improve
>>>> adn fix it later. I'm not saying I'm not interested in your
>>>> improvements just that let's that not hold this back now as we can fix
>>>> and improve it later but otherwise users will have to wait until
>>>> September to be able to use it. I know a few who want this and getting
>>>> this out as it is would allow more people to test it and report
>>>> problems so unless there are clearly wrong parts I'm OK with less than
>>>> perfect but working solution as long as it's not too messy.
>>>
>>> Patch 1 really seems like duplicating PCI code that already exists in
>>> QEMU. This is not needed and we should avoid that.
>>>
>>> Moreover, usage of the IRQ line register (0x3c) for interrupt routing
>>> should be switched to using the 0x55-0x57 regs to be PCI compliant.
>>
>> That would not work because then guests were not able to separately
>> configure IRQs for PCI interrupt lines and internal functions which is
>> what the datasheet says should be possible. The internal functions' IRQs
>> are not affeceted by 0x55-0x57 but routed by different registers.
>
> How do you know?

The datasheet says so. It says that 0x55-0x57 are controlling what ISA 
interrupts the PIRQA-D pins should raise while internal functions are 
documented to have 0x3c register to select what ISA IRQ they use. It's not 
said internal functions would use PCI interrupts that are separate and 
connected to the PIRQ pins.

> I think
>> your series only work because pegasos2 firmware progeams everything to
>> IRQ9 but if a guest decided to change that and route e.g. USB somewhere
>> else then it would break. My series models that a bit better but may still
>> break if a guest routes a function to an IRQ also controlled by some ISA
>> device (like serial or ps2 keyboard) which are currently done within
>> QEMU's ISA model so I can't easily channel those IRQs through the
>> via-isa.for proper routing but it's unliikely guests would want to do that
>> so in practice my series should work. We may duplicate PCI IRQ routing
>> here but this chip does that and more so we need to implement it as it
>> handles more than the 4 PCI interrupts so that implementation is not
>> enough to handle all sources this chip has. This isn't a complex piece of
>> code though so having a similar implementation is not a problem IMO.
>>
>>> Thanks to your great work to make via-ac97 work we can confirm that both
>>> IRQ routing implementations basically work for now. Let's work out a
>>> solution that relies on existing code, sticks to the standard and
>>> hopefully works for i386 and MIPS, too.
>>
>> I'm still not convinced your implementation is correct
>
>
> It seems that Mark (cc'd), I, the commenter in
> https://community.osr.com/discussion/30399/read-only-pci-interrupt-line-register
> and the PCI specification agree that the 0x3c regs aren't supposed to be
> interpreted by hardware.

You could still all be wrong if the PCI spec does not apply to the 
internal functions of the VIA chip which is just an assumption you made 
but the docs and experience never proved that so I don't believe that's a 
valid assumption. According to the datasheet internal functions' 
interrupts are routed independently from PCI interrupts which is what I've 
tried to model.

> I've provided a working example with no functional
> downsides to the 0x3c approach. I've provided the PCI-IDE reading material
> that Mark suggested for reading in
> https://lore.kernel.org/qemu-devel/b38987d5-5530-ecd9-2fd2-3a57e1a611dd@ilande.co.uk/
> . I'm running out of ideas now on how to proceed.

Please submit an alternative series that we can test and if it works with 
the guests that I want to run like mine we can take that instead even if I 
believe your way is wrong. I don't care about who's right as long as it 
works. But make sure it gets in for 8.0 as I do care that it should work 
in the next release.

Regards,
BALATON Zoltan


^ permalink raw reply	[flat|nested] 40+ messages in thread

* Re: [PATCH 5/5] hw/audio/via-ac97: Basic implementation of audio playback
  2023-02-21 18:44 ` [PATCH 5/5] hw/audio/via-ac97: Basic implementation of audio playback BALATON Zoltan
@ 2023-02-23 19:40   ` Volker Rümelin
  2023-02-24  9:53     ` Bernhard Beschow
  0 siblings, 1 reply; 40+ messages in thread
From: Volker Rümelin @ 2023-02-23 19:40 UTC (permalink / raw)
  To: BALATON Zoltan, qemu-devel, qemu-ppc
  Cc: Gerd Hoffmann, Daniel Henrique Barboza, Bernhard Beschow, philmd

Am 21.02.23 um 19:44 schrieb BALATON Zoltan:
> 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 <balaton@eik.bme.hu>
> ---
>   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 running) "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=0x%x %c%c%c len=%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.
>    */
>   
>   /*
> - * 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.
>    */
>   
>   #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)

Hi,

the CLEN_LEN mask is 0xffffff instead of 0xfff. The SGD Table Base Count 
has 24 bits.

With best regards,
Volker

> +
> +#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[] = { 8000, 11025, 16000, 22050, 32000, 44100,
> +                                  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 = 255 - CODEC_VOL(CODEC_REG(s, AC97_Master_Volume_Mute) >> 8, 0x1f);
> +    lvol *= 255 - CODEC_VOL(CODEC_REG(s, AC97_PCM_Out_Volume_Mute) >> 8, 0x1f);
> +    lvol /= 255;
> +    rvol = 255 - CODEC_VOL(CODEC_REG(s, AC97_Master_Volume_Mute), 0x1f);
> +    rvol *= 255 - CODEC_VOL(CODEC_REG(s, AC97_PCM_Out_Volume_Mute), 0x1f);
> +    rvol /= 255;
> +    mute = CODEC_REG(s, AC97_Master_Volume_Mute) >> MUTE_SHIFT;
> +    mute |= 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) = 0x6a90;
> +    CODEC_REG(s, AC97_Master_Volume_Mute) = 0x8000;
> +    CODEC_REG(s, AC97_Headphone_Volume_Mute) = 0x8000;
> +    CODEC_REG(s, AC97_Master_Volume_Mono_Mute) = 0x8000;
> +    CODEC_REG(s, AC97_Phone_Volume_Mute) = 0x8008;
> +    CODEC_REG(s, AC97_Mic_Volume_Mute) = 0x8008;
> +    CODEC_REG(s, AC97_Line_In_Volume_Mute) = 0x8808;
> +    CODEC_REG(s, AC97_CD_Volume_Mute) = 0x8808;
> +    CODEC_REG(s, AC97_Video_Volume_Mute) = 0x8808;
> +    CODEC_REG(s, AC97_Aux_Volume_Mute) = 0x8808;
> +    CODEC_REG(s, AC97_PCM_Out_Volume_Mute) = 0x8808;
> +    CODEC_REG(s, AC97_Record_Gain_Mute) = 0x8000;
> +    CODEC_REG(s, AC97_Powerdown_Ctrl_Stat) = 0x000f;
> +    CODEC_REG(s, AC97_Extended_Audio_ID) = 0x0a05;
> +    CODEC_REG(s, AC97_Extended_Audio_Ctrl_Stat) = 0x0400;
> +    CODEC_REG(s, AC97_PCM_Front_DAC_Rate) = 48000;
> +    CODEC_REG(s, AC97_PCM_LR_ADC_Rate) = 48000;
> +    /* Sigmatel 9766 (STAC9766) */
> +    CODEC_REG(s, AC97_Vendor_ID1) = 0x8384;
> +    CODEC_REG(s, AC97_Vendor_ID2) = 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 == AC97_Master_Volume_Mute) {
> +            if (val & BIT(13)) {
> +                val |= 0x1f00;
> +            }
> +            if (val & BIT(5)) {
> +                val |= 0x1f;
> +            }
> +        }
> +        CODEC_REG(s, addr) = val & 0x9f1f;
> +        codec_volume_set_out(s);
> +        return;
> +    case AC97_Extended_Audio_Ctrl_Stat:
> +        CODEC_REG(s, addr) &= ~EACS_VRA;
> +        CODEC_REG(s, addr) |= val & EACS_VRA;
> +        if (!(val & EACS_VRA)) {
> +            CODEC_REG(s, AC97_PCM_Front_DAC_Rate) = 48000;
> +            CODEC_REG(s, AC97_PCM_LR_ADC_Rate) = 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 = val;
> +
> +            for (i = 0; i < ARRAY_SIZE(codec_rates) - 1; i++) {
> +                if (rate < codec_rates[i] +
> +                    (codec_rates[i + 1] - codec_rates[i]) / 2) {
> +                    rate = codec_rates[i];
> +                    break;
> +                }
> +            }
> +            if (rate > 48000) {
> +                rate = 48000;
> +            }
> +            CODEC_REG(s, addr) = rate;
> +            open_voice_out(s);
> +        }
> +        return;
> +    case AC97_Powerdown_Ctrl_Stat:
> +        CODEC_REG(s, addr) = (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", addr);
> +        CODEC_REG(s, addr) = val;
> +    }
> +}
> +
> +static void fetch_sgd(ViaAC97SGDChannel *c, PCIDevice *d)
> +{
> +    uint32_t b[2];
> +
> +    if (c->curr < c->base) {
> +        c->curr = c->base;
> +    }
> +    pci_dma_read(d, c->curr, b, sizeof(b));
> +    c->addr = le32_to_cpu(b[0]);
> +    c->clen = 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 = opaque;
> +    ViaAC97SGDChannel *c = &s->aur;
> +    int temp, to_copy, copied;
> +    bool stop = false;
> +    uint8_t tmpbuf[4096];
> +
> +    if (c->stat & STAT_PAUSED) {
> +        return;
> +    }
> +    c->stat |= STAT_ACTIVE;
> +    while (avail && !stop) {
> +        if (!c->clen) {
> +            fetch_sgd(c, &s->dev);
> +        }
> +        temp = MIN(CLEN_LEN(c), avail);
> +        while (temp) {
> +            to_copy = MIN(temp, sizeof(tmpbuf));
> +            pci_dma_read(&s->dev, c->addr, tmpbuf, to_copy);
> +            copied = AUD_write(s->vo, tmpbuf, to_copy);
> +            if (!copied) {
> +                stop = true;
> +                break;
> +            }
> +            temp -= copied;
> +            avail -= copied;
> +            c->addr += copied;
> +            c->clen -= copied;
> +        }
> +        if (CLEN_LEN(c) == 0) {
> +            c->curr += 8;
> +            if (CLEN_IS_EOL(c)) {
> +                c->stat |= STAT_EOL;
> +                if (c->type & CNTL_START) {
> +                    c->curr = c->base;
> +                    c->stat |= STAT_PAUSED;
> +                } else {
> +                    c->stat &= ~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 |= STAT_FLAG;
> +                c->stat |= STAT_PAUSED;
> +                if (c->type & STAT_FLAG) {
> +                    via_isa_set_irq(&s->dev, VIA_IRQ_AC97, 1);
> +                }
> +            }
> +            if (CLEN_IS_STOP(c)) {
> +                c->stat |= STAT_STOP;
> +                c->stat |= STAT_PAUSED;
> +            }
> +            c->clen = 0;
> +            stop = true;
> +        }
> +    }
> +}
> +
> +static void open_voice_out(ViaAC97State *s)
> +{
> +    struct audsettings as = {
> +        .freq = CODEC_REG(s, AC97_PCM_Front_DAC_Rate),
> +        .nchannels = s->aur.type & BIT(4) ? 2 : 1,
> +        .fmt = s->aur.type & BIT(5) ? AUDIO_FORMAT_S16 : AUDIO_FORMAT_S8,
> +        .endianness = 0,
> +    };
> +    s->vo = 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 = opaque;
> +    uint64_t val = 0;
> +
> +    switch (addr) {
> +    case 0:
> +        val = s->aur.stat;
> +        if (s->aur.type & CNTL_START) {
> +            val |= STAT_TRIG;
> +        }
> +        break;
> +    case 1:
> +        val = s->aur.stat & STAT_PAUSED ? BIT(3) : 0;
> +        break;
> +    case 2:
> +        val = s->aur.type;
> +        break;
> +    case 4:
> +        val = s->aur.curr;
> +        break;
> +    case 0xc:
> +        val = CLEN_LEN(&s->aur);
> +        break;
> +    case 0x80:
> +        val = s->ac97_cmd;
> +        break;
> +    case 0x84:
> +        val = s->aur.stat & STAT_FLAG;
> +        if (s->aur.stat & STAT_EOL) {
> +            val |= BIT(4);
> +        }
> +        if (s->aur.stat & STAT_STOP) {
> +            val |= BIT(8);
> +        }
> +        if (s->aur.stat & STAT_ACTIVE) {
> +            val |= 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 size)
> +{
> +    ViaAC97State *s = opaque;
> +
> +    trace_via_ac97_sgd_write(addr, size, val);
> +    switch (addr) {
> +    case 0:
> +        if (val & STAT_STOP) {
> +            s->aur.stat &= ~STAT_PAUSED;
> +        }
> +        if (val & STAT_EOL) {
> +            s->aur.stat &= ~(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 &= ~(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 = STAT_ACTIVE;
> +        }
> +        if (val & CNTL_TERM) {
> +            AUD_set_active_out(s->vo, 0);
> +            s->aur.stat &= ~(STAT_ACTIVE | STAT_PAUSED);
> +            s->aur.clen = 0;
> +        }
> +        if (val & CNTL_PAUSE) {
> +            AUD_set_active_out(s->vo, 0);
> +            s->aur.stat &= ~STAT_ACTIVE;
> +            s->aur.stat |= STAT_PAUSED;
> +        } else if (!(val & CNTL_PAUSE) && (s->aur.stat & STAT_PAUSED)) {
> +            AUD_set_active_out(s->vo, 1);
> +            s->aur.stat |= STAT_ACTIVE;
> +            s->aur.stat &= ~STAT_PAUSED;
> +        }
> +        break;
> +    case 2:
> +    {
> +        uint32_t oldval = s->aur.type;
> +        s->aur.type = val;
> +        if ((oldval & 0x30) != (val & 0x30)) {
> +            open_voice_out(s);
> +        }
> +        break;
> +    }
> +    case 4:
> +        s->aur.base = val & ~1ULL;
> +        break;
> +    case 0x80:
> +        if (val >> 30) {
> +            /* we only have primary codec */
> +            break;
> +        }
> +        if (val & BIT(23)) { /* read reg */
> +            s->ac97_cmd = val & 0xc0ff0000ULL;
> +            s->ac97_cmd |= codec_read(s, (val >> 16) & 0x7f);
> +            s->ac97_cmd |= BIT(25); /* data valid */
> +        } else {
> +            s->ac97_cmd = 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 = {
> +    .read = sgd_read,
> +    .write = sgd_write,
> +    .endianness = 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 size)
> +{
> +    qemu_log_mask(LOG_UNIMP, "%s: 0x%"HWADDR_PRIx" %d <= 0x%"PRIX64"\n",
> +                  __func__, addr, size, val);
> +}
> +
> +static const MemoryRegionOps fm_ops = {
> +    .read = fm_read,
> +    .write = fm_write,
> +    .endianness = 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 size)
> +{
> +    qemu_log_mask(LOG_UNIMP, "%s: 0x%"HWADDR_PRIx" %d <= 0x%"PRIX64"\n",
> +                  __func__, addr, size, val);
> +}
> +
> +static const MemoryRegionOps midi_ops = {
> +    .read = midi_read,
> +    .write = midi_write,
> +    .endianness = DEVICE_LITTLE_ENDIAN,
> +};
> +
> +static void via_ac97_reset(DeviceState *dev)
> +{
> +    ViaAC97State *s = VIA_AC97(dev);
> +
> +    codec_reset(s);
> +}
>   
>   static void via_ac97_realize(PCIDevice *pci_dev, Error **errp)
>   {
> +    ViaAC97State *s = VIA_AC97(pci_dev);
> +    Object *o = 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);
>   }
>   
> +static void via_ac97_exit(PCIDevice *dev)
> +{
> +    ViaAC97State *s = VIA_AC97(dev);
> +
> +    AUD_close_out(&s->card, s->vo);
> +    AUD_remove_card(&s->card);
> +}
> +
> +static Property via_ac97_properties[] = {
> +    DEFINE_AUDIO_PROPERTIES(ViaAC97State, card),
> +    DEFINE_PROP_END_OF_LIST(),
> +};
> +
>   static void via_ac97_class_init(ObjectClass *klass, void *data)
>   {
>       DeviceClass *dc = DEVICE_CLASS(klass);
>       PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
>   
>       k->realize = via_ac97_realize;
> +    k->exit = via_ac97_exit;
>       k->vendor_id = PCI_VENDOR_ID_VIA;
>       k->device_id = PCI_DEVICE_ID_VIA_AC97;
>       k->revision = 0x50;
>       k->class_id = PCI_CLASS_MULTIMEDIA_AUDIO;
> +    device_class_set_props(dc, via_ac97_properties);
>       set_bit(DEVICE_CATEGORY_SOUND, dc->categories);
>       dc->desc = "VIA AC97";
> +    dc->reset = via_ac97_reset;
>       /* Reason: Part of a south bridge chip */
>       dc->user_creatable = false;
>   }
> @@ -41,7 +469,7 @@ static void via_ac97_class_init(ObjectClass *klass, void *data)
>   static const TypeInfo via_ac97_info = {
>       .name          = TYPE_VIA_AC97,
>       .parent        = TYPE_PCI_DEVICE,
> -    .instance_size = sizeof(PCIDevice),
> +    .instance_size = sizeof(ViaAC97State),
>       .class_init    = via_ac97_class_init,
>       .interfaces = (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;
>   };
>   
> @@ -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 = 14;
>           isa_irq = 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
>   
> +#include "hw/pci/pci_device.h"
> +#include "audio/audio.h"
>   
>   #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"
>   
> +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 = 0,
>       VIA_IRQ_IDE1 = 1,
> @@ -18,6 +43,7 @@ typedef enum {
>       VIA_IRQ_PIRQB = 5,
>       VIA_IRQ_PIRQC = 6,
>       VIA_IRQ_PIRQD = 7,
> +    VIA_IRQ_AC97 = 8,
>   } ViaISAIRQSourceBit;
>   
>   void via_isa_set_irq(PCIDevice *d, ViaISAIRQSourceBit n, int level);



^ permalink raw reply	[flat|nested] 40+ messages in thread

* Re: [PATCH 0/5] Pegasos2 fixes and audio output support
  2023-02-23 14:23                     ` BALATON Zoltan
@ 2023-02-23 20:28                       ` Bernhard Beschow
  0 siblings, 0 replies; 40+ messages in thread
From: Bernhard Beschow @ 2023-02-23 20:28 UTC (permalink / raw)
  To: BALATON Zoltan
  Cc: qemu-devel, qemu-ppc, Gerd Hoffmann, Daniel Henrique Barboza,
	philmd, Mark Cave-Ayland

[-- Attachment #1: Type: text/plain, Size: 5322 bytes --]

On Thu, Feb 23, 2023 at 3:23 PM BALATON Zoltan <balaton@eik.bme.hu> wrote:

> On Thu, 23 Feb 2023, Bernhard Beschow wrote:
> > On Thu, Feb 23, 2023 at 1:34 PM BALATON Zoltan <balaton@eik.bme.hu>
> wrote:
> >>>>>> I don't get your approach.
> >>>>>
> >>>>> I hope that I could help you get a better understanding. The linked
> >>>>> .pdf is good and comprehensive reading material.
> >>>>
> >>>> I'm not sure the via-ide confirms to that doc but it's also not any
> >>>> more a problem with via-ide now. That was discussed to death back then
> >>>> and "fixed" to work for the cases we want it to work with. We probably
> >>>> never agreed on how this really works but at least what we ended up
> >>>> with works with guests that run on real hardware. I'm OK with also
> >>>> making these cases work that we want now such as network and sound
> card
> >>>> under AmigaOS and sound under MorphOS (as long as you don't use USB)
> on
> >>>> pegasos2. This series does that so unless it breaks something that
> >>>> worked before I condider this moving forward and we can always improve
> >>>> adn fix it later. I'm not saying I'm not interested in your
> >>>> improvements just that let's that not hold this back now as we can fix
> >>>> and improve it later but otherwise users will have to wait until
> >>>> September to be able to use it. I know a few who want this and getting
> >>>> this out as it is would allow more people to test it and report
> >>>> problems so unless there are clearly wrong parts I'm OK with less than
> >>>> perfect but working solution as long as it's not too messy.
> >>>
> >>> Patch 1 really seems like duplicating PCI code that already exists in
> >>> QEMU. This is not needed and we should avoid that.
> >>>
> >>> Moreover, usage of the IRQ line register (0x3c) for interrupt routing
> >>> should be switched to using the 0x55-0x57 regs to be PCI compliant.
> >>
> >> That would not work because then guests were not able to separately
> >> configure IRQs for PCI interrupt lines and internal functions which is
> >> what the datasheet says should be possible. The internal functions' IRQs
> >> are not affeceted by 0x55-0x57 but routed by different registers.
> >
> > How do you know?
>
> The datasheet says so. It says that 0x55-0x57 are controlling what ISA
> interrupts the PIRQA-D pins should raise while internal functions are
> documented to have 0x3c register to select what ISA IRQ they use. It's not
> said internal functions would use PCI interrupts that are separate and
> connected to the PIRQ pins.
>
> > I think
> >> your series only work because pegasos2 firmware progeams everything to
> >> IRQ9 but if a guest decided to change that and route e.g. USB somewhere
> >> else then it would break. My series models that a bit better but may
> still
> >> break if a guest routes a function to an IRQ also controlled by some ISA
> >> device (like serial or ps2 keyboard) which are currently done within
> >> QEMU's ISA model so I can't easily channel those IRQs through the
> >> via-isa.for proper routing but it's unliikely guests would want to do
> that
> >> so in practice my series should work. We may duplicate PCI IRQ routing
> >> here but this chip does that and more so we need to implement it as it
> >> handles more than the 4 PCI interrupts so that implementation is not
> >> enough to handle all sources this chip has. This isn't a complex piece
> of
> >> code though so having a similar implementation is not a problem IMO.
> >>
> >>> Thanks to your great work to make via-ac97 work we can confirm that
> both
> >>> IRQ routing implementations basically work for now. Let's work out a
> >>> solution that relies on existing code, sticks to the standard and
> >>> hopefully works for i386 and MIPS, too.
> >>
> >> I'm still not convinced your implementation is correct
> >
> >
> > It seems that Mark (cc'd), I, the commenter in
> >
> https://community.osr.com/discussion/30399/read-only-pci-interrupt-line-register
> > and the PCI specification agree that the 0x3c regs aren't supposed to be
> > interpreted by hardware.
>
> You could still all be wrong if the PCI spec does not apply to the
> internal functions of the VIA chip which is just an assumption you made
> but the docs and experience never proved that so I don't believe that's a
> valid assumption. According to the datasheet internal functions'
> interrupts are routed independently from PCI interrupts which is what I've
> tried to model.
>
> > I've provided a working example with no functional
> > downsides to the 0x3c approach. I've provided the PCI-IDE reading
> material
> > that Mark suggested for reading in
> >
> https://lore.kernel.org/qemu-devel/b38987d5-5530-ecd9-2fd2-3a57e1a611dd@ilande.co.uk/
> > . I'm running out of ideas now on how to proceed.
>
> Please submit an alternative series that we can test and if it works with
> the guests that I want to run like mine we can take that instead even if I
> believe your way is wrong. I don't care about who's right as long as it
> works. But make sure it gets in for 8.0 as I do care that it should work
> in the next release.
>

Here we go:
https://lore.kernel.org/qemu-devel/20230223202053.117050-1-shentey@gmail.com/

Please submit further iterations when audio changes are needed.

Best regards,
Bernhard

>
> Regards,
> BALATON Zoltan
>

[-- Attachment #2: Type: text/html, Size: 7179 bytes --]

^ permalink raw reply	[flat|nested] 40+ messages in thread

* Re: [PATCH 5/5] hw/audio/via-ac97: Basic implementation of audio playback
  2023-02-23 19:40   ` Volker Rümelin
@ 2023-02-24  9:53     ` Bernhard Beschow
  2023-02-24 12:26       ` BALATON Zoltan
  2023-02-24 13:05       ` BALATON Zoltan
  0 siblings, 2 replies; 40+ messages in thread
From: Bernhard Beschow @ 2023-02-24  9:53 UTC (permalink / raw)
  To: Volker Rümelin, BALATON Zoltan, qemu-devel, qemu-ppc
  Cc: Gerd Hoffmann, Daniel Henrique Barboza, philmd



Am 23. Februar 2023 19:40:03 UTC schrieb "Volker Rümelin" <vr_qemu@t-online.de>:
>Am 21.02.23 um 19:44 schrieb BALATON Zoltan:
>> 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 <balaton@eik.bme.hu>
>> ---
>>   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 running) "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=0x%x %c%c%c len=%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.
>>    */
>>     /*
>> - * 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.
>>    */
>>     #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)
>
>Hi,
>
>the CLEN_LEN mask is 0xffffff instead of 0xfff. The SGD Table Base Count has 24 bits.

This fixes sound for a x86 Linux guest on my pc-via branch.

Best regards,
Bernhard

>
>With best regards,
>Volker
>
>> +
>> +#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[] = { 8000, 11025, 16000, 22050, 32000, 44100,
>> +                                  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 = 255 - CODEC_VOL(CODEC_REG(s, AC97_Master_Volume_Mute) >> 8, 0x1f);
>> +    lvol *= 255 - CODEC_VOL(CODEC_REG(s, AC97_PCM_Out_Volume_Mute) >> 8, 0x1f);
>> +    lvol /= 255;
>> +    rvol = 255 - CODEC_VOL(CODEC_REG(s, AC97_Master_Volume_Mute), 0x1f);
>> +    rvol *= 255 - CODEC_VOL(CODEC_REG(s, AC97_PCM_Out_Volume_Mute), 0x1f);
>> +    rvol /= 255;
>> +    mute = CODEC_REG(s, AC97_Master_Volume_Mute) >> MUTE_SHIFT;
>> +    mute |= 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) = 0x6a90;
>> +    CODEC_REG(s, AC97_Master_Volume_Mute) = 0x8000;
>> +    CODEC_REG(s, AC97_Headphone_Volume_Mute) = 0x8000;
>> +    CODEC_REG(s, AC97_Master_Volume_Mono_Mute) = 0x8000;
>> +    CODEC_REG(s, AC97_Phone_Volume_Mute) = 0x8008;
>> +    CODEC_REG(s, AC97_Mic_Volume_Mute) = 0x8008;
>> +    CODEC_REG(s, AC97_Line_In_Volume_Mute) = 0x8808;
>> +    CODEC_REG(s, AC97_CD_Volume_Mute) = 0x8808;
>> +    CODEC_REG(s, AC97_Video_Volume_Mute) = 0x8808;
>> +    CODEC_REG(s, AC97_Aux_Volume_Mute) = 0x8808;
>> +    CODEC_REG(s, AC97_PCM_Out_Volume_Mute) = 0x8808;
>> +    CODEC_REG(s, AC97_Record_Gain_Mute) = 0x8000;
>> +    CODEC_REG(s, AC97_Powerdown_Ctrl_Stat) = 0x000f;
>> +    CODEC_REG(s, AC97_Extended_Audio_ID) = 0x0a05;
>> +    CODEC_REG(s, AC97_Extended_Audio_Ctrl_Stat) = 0x0400;
>> +    CODEC_REG(s, AC97_PCM_Front_DAC_Rate) = 48000;
>> +    CODEC_REG(s, AC97_PCM_LR_ADC_Rate) = 48000;
>> +    /* Sigmatel 9766 (STAC9766) */
>> +    CODEC_REG(s, AC97_Vendor_ID1) = 0x8384;
>> +    CODEC_REG(s, AC97_Vendor_ID2) = 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 == AC97_Master_Volume_Mute) {
>> +            if (val & BIT(13)) {
>> +                val |= 0x1f00;
>> +            }
>> +            if (val & BIT(5)) {
>> +                val |= 0x1f;
>> +            }
>> +        }
>> +        CODEC_REG(s, addr) = val & 0x9f1f;
>> +        codec_volume_set_out(s);
>> +        return;
>> +    case AC97_Extended_Audio_Ctrl_Stat:
>> +        CODEC_REG(s, addr) &= ~EACS_VRA;
>> +        CODEC_REG(s, addr) |= val & EACS_VRA;
>> +        if (!(val & EACS_VRA)) {
>> +            CODEC_REG(s, AC97_PCM_Front_DAC_Rate) = 48000;
>> +            CODEC_REG(s, AC97_PCM_LR_ADC_Rate) = 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 = val;
>> +
>> +            for (i = 0; i < ARRAY_SIZE(codec_rates) - 1; i++) {
>> +                if (rate < codec_rates[i] +
>> +                    (codec_rates[i + 1] - codec_rates[i]) / 2) {
>> +                    rate = codec_rates[i];
>> +                    break;
>> +                }
>> +            }
>> +            if (rate > 48000) {
>> +                rate = 48000;
>> +            }
>> +            CODEC_REG(s, addr) = rate;
>> +            open_voice_out(s);
>> +        }
>> +        return;
>> +    case AC97_Powerdown_Ctrl_Stat:
>> +        CODEC_REG(s, addr) = (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", addr);
>> +        CODEC_REG(s, addr) = val;
>> +    }
>> +}
>> +
>> +static void fetch_sgd(ViaAC97SGDChannel *c, PCIDevice *d)
>> +{
>> +    uint32_t b[2];
>> +
>> +    if (c->curr < c->base) {
>> +        c->curr = c->base;
>> +    }
>> +    pci_dma_read(d, c->curr, b, sizeof(b));
>> +    c->addr = le32_to_cpu(b[0]);
>> +    c->clen = 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 = opaque;
>> +    ViaAC97SGDChannel *c = &s->aur;
>> +    int temp, to_copy, copied;
>> +    bool stop = false;
>> +    uint8_t tmpbuf[4096];
>> +
>> +    if (c->stat & STAT_PAUSED) {
>> +        return;
>> +    }
>> +    c->stat |= STAT_ACTIVE;
>> +    while (avail && !stop) {
>> +        if (!c->clen) {
>> +            fetch_sgd(c, &s->dev);
>> +        }
>> +        temp = MIN(CLEN_LEN(c), avail);
>> +        while (temp) {
>> +            to_copy = MIN(temp, sizeof(tmpbuf));
>> +            pci_dma_read(&s->dev, c->addr, tmpbuf, to_copy);
>> +            copied = AUD_write(s->vo, tmpbuf, to_copy);
>> +            if (!copied) {
>> +                stop = true;
>> +                break;
>> +            }
>> +            temp -= copied;
>> +            avail -= copied;
>> +            c->addr += copied;
>> +            c->clen -= copied;
>> +        }
>> +        if (CLEN_LEN(c) == 0) {
>> +            c->curr += 8;
>> +            if (CLEN_IS_EOL(c)) {
>> +                c->stat |= STAT_EOL;
>> +                if (c->type & CNTL_START) {
>> +                    c->curr = c->base;
>> +                    c->stat |= STAT_PAUSED;
>> +                } else {
>> +                    c->stat &= ~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 |= STAT_FLAG;
>> +                c->stat |= STAT_PAUSED;
>> +                if (c->type & STAT_FLAG) {
>> +                    via_isa_set_irq(&s->dev, VIA_IRQ_AC97, 1);
>> +                }
>> +            }
>> +            if (CLEN_IS_STOP(c)) {
>> +                c->stat |= STAT_STOP;
>> +                c->stat |= STAT_PAUSED;
>> +            }
>> +            c->clen = 0;
>> +            stop = true;
>> +        }
>> +    }
>> +}
>> +
>> +static void open_voice_out(ViaAC97State *s)
>> +{
>> +    struct audsettings as = {
>> +        .freq = CODEC_REG(s, AC97_PCM_Front_DAC_Rate),
>> +        .nchannels = s->aur.type & BIT(4) ? 2 : 1,
>> +        .fmt = s->aur.type & BIT(5) ? AUDIO_FORMAT_S16 : AUDIO_FORMAT_S8,
>> +        .endianness = 0,
>> +    };
>> +    s->vo = 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 = opaque;
>> +    uint64_t val = 0;
>> +
>> +    switch (addr) {
>> +    case 0:
>> +        val = s->aur.stat;
>> +        if (s->aur.type & CNTL_START) {
>> +            val |= STAT_TRIG;
>> +        }
>> +        break;
>> +    case 1:
>> +        val = s->aur.stat & STAT_PAUSED ? BIT(3) : 0;
>> +        break;
>> +    case 2:
>> +        val = s->aur.type;
>> +        break;
>> +    case 4:
>> +        val = s->aur.curr;
>> +        break;
>> +    case 0xc:
>> +        val = CLEN_LEN(&s->aur);
>> +        break;
>> +    case 0x80:
>> +        val = s->ac97_cmd;
>> +        break;
>> +    case 0x84:
>> +        val = s->aur.stat & STAT_FLAG;
>> +        if (s->aur.stat & STAT_EOL) {
>> +            val |= BIT(4);
>> +        }
>> +        if (s->aur.stat & STAT_STOP) {
>> +            val |= BIT(8);
>> +        }
>> +        if (s->aur.stat & STAT_ACTIVE) {
>> +            val |= 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 size)
>> +{
>> +    ViaAC97State *s = opaque;
>> +
>> +    trace_via_ac97_sgd_write(addr, size, val);
>> +    switch (addr) {
>> +    case 0:
>> +        if (val & STAT_STOP) {
>> +            s->aur.stat &= ~STAT_PAUSED;
>> +        }
>> +        if (val & STAT_EOL) {
>> +            s->aur.stat &= ~(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 &= ~(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 = STAT_ACTIVE;
>> +        }
>> +        if (val & CNTL_TERM) {
>> +            AUD_set_active_out(s->vo, 0);
>> +            s->aur.stat &= ~(STAT_ACTIVE | STAT_PAUSED);
>> +            s->aur.clen = 0;
>> +        }
>> +        if (val & CNTL_PAUSE) {
>> +            AUD_set_active_out(s->vo, 0);
>> +            s->aur.stat &= ~STAT_ACTIVE;
>> +            s->aur.stat |= STAT_PAUSED;
>> +        } else if (!(val & CNTL_PAUSE) && (s->aur.stat & STAT_PAUSED)) {
>> +            AUD_set_active_out(s->vo, 1);
>> +            s->aur.stat |= STAT_ACTIVE;
>> +            s->aur.stat &= ~STAT_PAUSED;
>> +        }
>> +        break;
>> +    case 2:
>> +    {
>> +        uint32_t oldval = s->aur.type;
>> +        s->aur.type = val;
>> +        if ((oldval & 0x30) != (val & 0x30)) {
>> +            open_voice_out(s);
>> +        }
>> +        break;
>> +    }
>> +    case 4:
>> +        s->aur.base = val & ~1ULL;
>> +        break;
>> +    case 0x80:
>> +        if (val >> 30) {
>> +            /* we only have primary codec */
>> +            break;
>> +        }
>> +        if (val & BIT(23)) { /* read reg */
>> +            s->ac97_cmd = val & 0xc0ff0000ULL;
>> +            s->ac97_cmd |= codec_read(s, (val >> 16) & 0x7f);
>> +            s->ac97_cmd |= BIT(25); /* data valid */
>> +        } else {
>> +            s->ac97_cmd = 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 = {
>> +    .read = sgd_read,
>> +    .write = sgd_write,
>> +    .endianness = 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 size)
>> +{
>> +    qemu_log_mask(LOG_UNIMP, "%s: 0x%"HWADDR_PRIx" %d <= 0x%"PRIX64"\n",
>> +                  __func__, addr, size, val);
>> +}
>> +
>> +static const MemoryRegionOps fm_ops = {
>> +    .read = fm_read,
>> +    .write = fm_write,
>> +    .endianness = 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 size)
>> +{
>> +    qemu_log_mask(LOG_UNIMP, "%s: 0x%"HWADDR_PRIx" %d <= 0x%"PRIX64"\n",
>> +                  __func__, addr, size, val);
>> +}
>> +
>> +static const MemoryRegionOps midi_ops = {
>> +    .read = midi_read,
>> +    .write = midi_write,
>> +    .endianness = DEVICE_LITTLE_ENDIAN,
>> +};
>> +
>> +static void via_ac97_reset(DeviceState *dev)
>> +{
>> +    ViaAC97State *s = VIA_AC97(dev);
>> +
>> +    codec_reset(s);
>> +}
>>     static void via_ac97_realize(PCIDevice *pci_dev, Error **errp)
>>   {
>> +    ViaAC97State *s = VIA_AC97(pci_dev);
>> +    Object *o = 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);
>>   }
>>   +static void via_ac97_exit(PCIDevice *dev)
>> +{
>> +    ViaAC97State *s = VIA_AC97(dev);
>> +
>> +    AUD_close_out(&s->card, s->vo);
>> +    AUD_remove_card(&s->card);
>> +}
>> +
>> +static Property via_ac97_properties[] = {
>> +    DEFINE_AUDIO_PROPERTIES(ViaAC97State, card),
>> +    DEFINE_PROP_END_OF_LIST(),
>> +};
>> +
>>   static void via_ac97_class_init(ObjectClass *klass, void *data)
>>   {
>>       DeviceClass *dc = DEVICE_CLASS(klass);
>>       PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
>>         k->realize = via_ac97_realize;
>> +    k->exit = via_ac97_exit;
>>       k->vendor_id = PCI_VENDOR_ID_VIA;
>>       k->device_id = PCI_DEVICE_ID_VIA_AC97;
>>       k->revision = 0x50;
>>       k->class_id = PCI_CLASS_MULTIMEDIA_AUDIO;
>> +    device_class_set_props(dc, via_ac97_properties);
>>       set_bit(DEVICE_CATEGORY_SOUND, dc->categories);
>>       dc->desc = "VIA AC97";
>> +    dc->reset = via_ac97_reset;
>>       /* Reason: Part of a south bridge chip */
>>       dc->user_creatable = false;
>>   }
>> @@ -41,7 +469,7 @@ static void via_ac97_class_init(ObjectClass *klass, void *data)
>>   static const TypeInfo via_ac97_info = {
>>       .name          = TYPE_VIA_AC97,
>>       .parent        = TYPE_PCI_DEVICE,
>> -    .instance_size = sizeof(PCIDevice),
>> +    .instance_size = sizeof(ViaAC97State),
>>       .class_init    = via_ac97_class_init,
>>       .interfaces = (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;
>>   };
>>   @@ -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 = 14;
>>           isa_irq = 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
>>   +#include "hw/pci/pci_device.h"
>> +#include "audio/audio.h"
>>     #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"
>>   +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 = 0,
>>       VIA_IRQ_IDE1 = 1,
>> @@ -18,6 +43,7 @@ typedef enum {
>>       VIA_IRQ_PIRQB = 5,
>>       VIA_IRQ_PIRQC = 6,
>>       VIA_IRQ_PIRQD = 7,
>> +    VIA_IRQ_AC97 = 8,
>>   } ViaISAIRQSourceBit;
>>     void via_isa_set_irq(PCIDevice *d, ViaISAIRQSourceBit n, int level);
>


^ permalink raw reply	[flat|nested] 40+ messages in thread

* Re: [PATCH 5/5] hw/audio/via-ac97: Basic implementation of audio playback
  2023-02-24  9:53     ` Bernhard Beschow
@ 2023-02-24 12:26       ` BALATON Zoltan
  2023-02-24 13:05       ` BALATON Zoltan
  1 sibling, 0 replies; 40+ messages in thread
From: BALATON Zoltan @ 2023-02-24 12:26 UTC (permalink / raw)
  To: Bernhard Beschow
  Cc: Volker Rümelin, qemu-devel, qemu-ppc, Gerd Hoffmann,
	Daniel Henrique Barboza, philmd

[-- Attachment #1: Type: text/plain, Size: 3179 bytes --]

On Fri, 24 Feb 2023, Bernhard Beschow wrote:
> Am 23. Februar 2023 19:40:03 UTC schrieb "Volker Rümelin" <vr_qemu@t-online.de>:
>> Am 21.02.23 um 19:44 schrieb BALATON Zoltan:
>>> 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 <balaton@eik.bme.hu>
>>> ---
>>>   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 running) "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=0x%x %c%c%c len=%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.
>>>    */
>>>     /*
>>> - * 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.
>>>    */
>>>     #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)
>>
>> Hi,
>>
>> the CLEN_LEN mask is 0xffffff instead of 0xfff. The SGD Table Base Count has 24 bits.
>
> This fixes sound for a x86 Linux guest on my pc-via branch.

Thanks, will be in next version. Not sure where have I lost that, maybe 
accidenatlly deleted part of the constant on a rebase and did not notice.
Bernhard does that mean you give a Tested-by for this patch?

Regards,
BALATON Zoltan

^ permalink raw reply	[flat|nested] 40+ messages in thread

* Re: [PATCH 5/5] hw/audio/via-ac97: Basic implementation of audio playback
  2023-02-24  9:53     ` Bernhard Beschow
  2023-02-24 12:26       ` BALATON Zoltan
@ 2023-02-24 13:05       ` BALATON Zoltan
  2023-02-24 17:14         ` Daniel Henrique Barboza
  1 sibling, 1 reply; 40+ messages in thread
From: BALATON Zoltan @ 2023-02-24 13:05 UTC (permalink / raw)
  To: Bernhard Beschow
  Cc: Volker Rümelin, qemu-devel, qemu-ppc, Gerd Hoffmann,
	Daniel Henrique Barboza, philmd, Peter Maydell

Just for some motivation, this is what we want to make possible for more 
people with QEMU 8.0: https://youtu.be/YY9RExl4VDI

This would need at least my SM502 patches and fixing the IRQ routing in 
the VT8231 (this test was with my series for that, I'll ask testing 
Bernhard's version the same way once I get it and rebase my patches on 
it). AmigaOS can use ES1370 so the via-ac97 patches are not that important 
now but the other patches would be needed. I hope users won't have to wait 
until September to try this.

While AmigaOS runs on sam460ex now, that versiion is much slower due to 
the limited PPC440 that doesn't have AltiVec and also due to some issues 
on the real platform it has to do more synchronisation which slows it 
down. The pegasos2 version runs much better and has a better chance to get 
it to work with KVM on PPC host so this would be a big improvement even if 
there would be more bugs to fix in upcoming releases but we'll never find 
those unless people can start using it and report them. More people are 
interested but less are able to compile and test from git repos and depend 
on binary distros instead.

Regards,
BALATON Zoltan


^ permalink raw reply	[flat|nested] 40+ messages in thread

* Re: [PATCH 3/5] hw/ppc/pegasos2: Fix PCI interrupt routing
  2023-02-21 18:44 ` [PATCH 3/5] hw/ppc/pegasos2: Fix PCI interrupt routing BALATON Zoltan
@ 2023-02-24 17:04   ` Daniel Henrique Barboza
  2023-02-25 19:34   ` Philippe Mathieu-Daudé
  1 sibling, 0 replies; 40+ messages in thread
From: Daniel Henrique Barboza @ 2023-02-24 17:04 UTC (permalink / raw)
  To: BALATON Zoltan, qemu-devel, qemu-ppc
  Cc: Gerd Hoffmann, Bernhard Beschow, philmd



On 2/21/23 15:44, BALATON Zoltan wrote:
> 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 <balaton@eik.bme.hu>
> ---

Reviewed-by: Daniel Henrique Barboza <danielhb413@gmail.com>

>   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 = 0; i < PCI_NUM_PINS; i++) {
> -        s->pci[1].irq[i] = qdev_get_gpio_in_named(dev, "gpp", 12 + i);
> -    }
>   }
>   
>   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)
>       }
>   }
>   
> +static void pegasos2_pci_irq(void *opaque, int n, int level)
> +{
> +    Pegasos2MachineState *pm = 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 = PEGASOS2_MACHINE(machine);
> @@ -107,7 +118,7 @@ static void pegasos2_init(MachineState *machine)
>       I2CBus *i2c_bus;
>       const char *fwname = machine->firmware ?: PROM_FILENAME;
>       char *filename;
> -    int sz;
> +    int i, sz;
>       uint8_t *spd_data;
>   
>       /* init CPU */
> @@ -157,11 +168,18 @@ static void pegasos2_init(MachineState *machine)
>       /* Marvell Discovery II system controller */
>       pm->mv = DEVICE(sysbus_create_simple(TYPE_MV64361, -1,
>                             qdev_get_gpio_in(DEVICE(pm->cpu), PPC6xx_INPUT_INT)));
> +    for (i = 0; i < PCI_NUM_PINS; i++) {
> +        pm->mv_pirq[i] = qdev_get_gpio_in_named(pm->mv, "gpp", 12 + i);
> +    }
>       pci_bus = mv64361_get_pci_bus(pm->mv, 1);
> +    pci_bus_irqs(pci_bus, pegasos2_pci_irq, pm, PCI_NUM_PINS);
>   
>       /* VIA VT8231 South Bridge (multifunction PCI device) */
>       via = OBJECT(pci_create_simple_multifunction(pci_bus, PCI_DEVFN(12, 0),
>                                                    true, TYPE_VT8231_ISA));
> +    for (i = 0; i < PCI_NUM_PINS; i++) {
> +        pm->via_pirq[i] = 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 *machine, 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);
>   
>       pegasos2_pci_config_write(pm, 1, (PCI_DEVFN(12, 1) << 8) |
>                                 PCI_INTERRUPT_LINE, 2, 0x109);


^ permalink raw reply	[flat|nested] 40+ messages in thread

* Re: [PATCH 5/5] hw/audio/via-ac97: Basic implementation of audio playback
  2023-02-24 13:05       ` BALATON Zoltan
@ 2023-02-24 17:14         ` Daniel Henrique Barboza
  2023-02-24 21:08           ` BALATON Zoltan
  0 siblings, 1 reply; 40+ messages in thread
From: Daniel Henrique Barboza @ 2023-02-24 17:14 UTC (permalink / raw)
  To: BALATON Zoltan, Bernhard Beschow
  Cc: Volker Rümelin, qemu-devel, qemu-ppc, Gerd Hoffmann, philmd,
	Peter Maydell



On 2/24/23 10:05, BALATON Zoltan wrote:
> Just for some motivation, this is what we want to make possible for more people with QEMU 8.0: https://youtu.be/YY9RExl4VDI

That's neat!

> 
> This would need at least my SM502 patches and fixing the IRQ routing in the VT8231 (this test was with my series for that, I'll ask testing Bernhard's version the same way once I get it and rebase my patches on it). AmigaOS can use ES1370 so the via-ac97 patches are not that important now but the other patches would be needed. I hope users won't have to wait until September to try this.

If you're referring to "hw/display/sm501: Implement more 2D raster operations" then it's already
queued in ppc-next. In fact I believe you can re-send it with this series, with my r-b, and whoever
gets to send the PR can send everything at once.

If either Gerd of Phil wants to pick these up I have already acked the pegasos2 changes.

If you want me to get this via qemu-ppc bear in mind that I need to send the PR March 7th
at the latest.


Thanks,


Daniel

> 
> While AmigaOS runs on sam460ex now, that versiion is much slower due to the limited PPC440 that doesn't have AltiVec and also due to some issues on the real platform it has to do more synchronisation which slows it down. The pegasos2 version runs much better and has a better chance to get it to work with KVM on PPC host so this would be a big improvement even if there would be more bugs to fix in upcoming releases but we'll never find those unless people can start using it and report them. More people are interested but less are able to compile and test from git repos and depend on binary distros instead.
> 
> Regards,
> BALATON Zoltan


^ permalink raw reply	[flat|nested] 40+ messages in thread

* Re: [PATCH 5/5] hw/audio/via-ac97: Basic implementation of audio playback
  2023-02-24 17:14         ` Daniel Henrique Barboza
@ 2023-02-24 21:08           ` BALATON Zoltan
  2023-02-25  8:58             ` Daniel Henrique Barboza
  0 siblings, 1 reply; 40+ messages in thread
From: BALATON Zoltan @ 2023-02-24 21:08 UTC (permalink / raw)
  To: Daniel Henrique Barboza
  Cc: Bernhard Beschow, Volker Rümelin, qemu-devel, qemu-ppc,
	Gerd Hoffmann, philmd, Peter Maydell

On Fri, 24 Feb 2023, Daniel Henrique Barboza wrote:
> On 2/24/23 10:05, BALATON Zoltan wrote:
>> Just for some motivation, this is what we want to make possible for more 
>> people with QEMU 8.0: https://youtu.be/YY9RExl4VDI
>
> That's neat!
>
>> 
>> This would need at least my SM502 patches and fixing the IRQ routing in the 
>> VT8231 (this test was with my series for that, I'll ask testing Bernhard's 
>> version the same way once I get it and rebase my patches on it). AmigaOS 
>> can use ES1370 so the via-ac97 patches are not that important now but the 
>> other patches would be needed. I hope users won't have to wait until 
>> September to try this.
>
> If you're referring to "hw/display/sm501: Implement more 2D raster 
> operations" then it's already
> queued in ppc-next.

That one and another I've sent yesterday that adds fallbacks for pixman 
routines.

> In fact I believe you can re-send it with this series, 
> with my r-b, and whoever
> gets to send the PR can send everything at once.

OK I'll collect all the patches in one series and submit it early next 
week. Hopefully we can test over the weekend and address any comments by 
the freeze.

> If either Gerd of Phil wants to pick these up I have already acked the 
> pegasos2 changes.
>
> If you want me to get this via qemu-ppc bear in mind that I need to send the 
> PR March 7th
> at the latest.

I'm aware of that, although if we get more CI outage which stops pulls 
maybe we should consider 1-2 week extension, but I'm planning accordingly 
and if there won't be unexpected delays (e.g. new late reviews asking for 
extensive changes) this should be ready a week before the freeze. I think 
we can do one or two more versions/

Regards,
BALATON Zoltan


^ permalink raw reply	[flat|nested] 40+ messages in thread

* Re: [PATCH 5/5] hw/audio/via-ac97: Basic implementation of audio playback
  2023-02-24 21:08           ` BALATON Zoltan
@ 2023-02-25  8:58             ` Daniel Henrique Barboza
  0 siblings, 0 replies; 40+ messages in thread
From: Daniel Henrique Barboza @ 2023-02-25  8:58 UTC (permalink / raw)
  To: BALATON Zoltan
  Cc: Bernhard Beschow, Volker Rümelin, qemu-devel, qemu-ppc,
	Gerd Hoffmann, philmd, Peter Maydell



On 2/24/23 18:08, BALATON Zoltan wrote:
> On Fri, 24 Feb 2023, Daniel Henrique Barboza wrote:
>> On 2/24/23 10:05, BALATON Zoltan wrote:
>>> Just for some motivation, this is what we want to make possible for more people with QEMU 8.0: https://youtu.be/YY9RExl4VDI
>>
>> That's neat!
>>
>>>
>>> This would need at least my SM502 patches and fixing the IRQ routing in the VT8231 (this test was with my series for that, I'll ask testing Bernhard's version the same way once I get it and rebase my patches on it). AmigaOS can use ES1370 so the via-ac97 patches are not that important now but the other patches would be needed. I hope users won't have to wait until September to try this.
>>
>> If you're referring to "hw/display/sm501: Implement more 2D raster operations" then it's already
>> queued in ppc-next.
> 
> That one and another I've sent yesterday that adds fallbacks for pixman routines.
> 
>> In fact I believe you can re-send it with this series, with my r-b, and whoever
>> gets to send the PR can send everything at once.
> 
> OK I'll collect all the patches in one series and submit it early next week. Hopefully we can test over the weekend and address any comments by the freeze.

Yes please.

> 
>> If either Gerd of Phil wants to pick these up I have already acked the pegasos2 changes.
>>
>> If you want me to get this via qemu-ppc bear in mind that I need to send the PR March 7th
>> at the latest.
> 
> I'm aware of that, although if we get more CI outage which stops pulls maybe we should consider 1-2 week extension, but I'm planning accordingly and if there won't be unexpected delays (e.g. new late reviews asking for extensive changes) this should be ready a week before the freeze. I think we can do one or two more versions/

It's no possible to predict this kind of unexpected delay, yes. But in the end the
maintainer is here to mediate these situations. If the patches have acks and the
maintainer considered it worth pushing, then this late review must be so good that
it convinces the maintainer to drop the patches from the PR (and from the release,
in this case).

It can happen, sure, but it's not a given. Specially considering that we have a good
code freeze window to fix any bugs that we might have left behind during the development
cycle.


Thanks,


Daniel

> 
> Regards,
> BALATON Zoltan


^ permalink raw reply	[flat|nested] 40+ messages in thread

* Re: [PATCH 3/5] hw/ppc/pegasos2: Fix PCI interrupt routing
  2023-02-21 18:44 ` [PATCH 3/5] hw/ppc/pegasos2: Fix PCI interrupt routing BALATON Zoltan
  2023-02-24 17:04   ` Daniel Henrique Barboza
@ 2023-02-25 19:34   ` Philippe Mathieu-Daudé
  2023-02-25 20:19     ` BALATON Zoltan
  2023-02-26 22:22     ` BALATON Zoltan
  1 sibling, 2 replies; 40+ messages in thread
From: Philippe Mathieu-Daudé @ 2023-02-25 19:34 UTC (permalink / raw)
  To: BALATON Zoltan, qemu-devel, qemu-ppc
  Cc: Gerd Hoffmann, Daniel Henrique Barboza, Bernhard Beschow, philmd

On 21/2/23 19:44, BALATON Zoltan wrote:
> 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 <balaton@eik.bme.hu>
> ---
>   hw/pci-host/mv64361.c |  4 ----
>   hw/ppc/pegasos2.c     | 26 +++++++++++++++++++++++++-
>   2 files changed, 25 insertions(+), 5 deletions(-)


> +static void pegasos2_pci_irq(void *opaque, int n, int level)
> +{
> +    Pegasos2MachineState *pm = 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);
> +}

See TYPE_SPLIT_IRQ.


^ permalink raw reply	[flat|nested] 40+ messages in thread

* Re: [PATCH 4/5] hw/audio/ac97: Split off some definitions to a header
  2023-02-21 18:44 ` [PATCH 4/5] hw/audio/ac97: Split off some definitions to a header BALATON Zoltan
@ 2023-02-25 19:35   ` Philippe Mathieu-Daudé
  2023-02-26 22:17     ` BALATON Zoltan
  0 siblings, 1 reply; 40+ messages in thread
From: Philippe Mathieu-Daudé @ 2023-02-25 19:35 UTC (permalink / raw)
  To: BALATON Zoltan, qemu-devel, qemu-ppc
  Cc: Gerd Hoffmann, Daniel Henrique Barboza, Bernhard Beschow, philmd

On 21/2/23 19:44, BALATON Zoltan wrote:
> These can be shared with other AC97 implementations.
> 
> Signed-off-by: BALATON Zoltan <balaton@eik.bme.hu>
> ---
>   hw/audio/ac97.c | 43 +-------------------------------
>   hw/audio/ac97.h | 65 +++++++++++++++++++++++++++++++++++++++++++++++++
>   2 files changed, 66 insertions(+), 42 deletions(-)
>   create mode 100644 hw/audio/ac97.h

Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>



^ permalink raw reply	[flat|nested] 40+ messages in thread

* Re: [PATCH 3/5] hw/ppc/pegasos2: Fix PCI interrupt routing
  2023-02-25 19:34   ` Philippe Mathieu-Daudé
@ 2023-02-25 20:19     ` BALATON Zoltan
  2023-02-26 22:22     ` BALATON Zoltan
  1 sibling, 0 replies; 40+ messages in thread
From: BALATON Zoltan @ 2023-02-25 20:19 UTC (permalink / raw)
  To: Philippe Mathieu-Daudé
  Cc: qemu-devel, qemu-ppc, Gerd Hoffmann, Daniel Henrique Barboza,
	Bernhard Beschow, philmd

[-- Attachment #1: Type: text/plain, Size: 1615 bytes --]

On Sat, 25 Feb 2023, Philippe Mathieu-Daudé wrote:
> On 21/2/23 19:44, BALATON Zoltan wrote:
>> 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 <balaton@eik.bme.hu>
>> ---
>>   hw/pci-host/mv64361.c |  4 ----
>>   hw/ppc/pegasos2.c     | 26 +++++++++++++++++++++++++-
>>   2 files changed, 25 insertions(+), 5 deletions(-)
>
>
>> +static void pegasos2_pci_irq(void *opaque, int n, int level)
>> +{
>> +    Pegasos2MachineState *pm = 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);
>> +}
>
> See TYPE_SPLIT_IRQ.

I remembered there was something like that somewhere but could not find 
it. Thanks, I'll check if that's simpler here.

Regards,
BALATON Zoltan

^ permalink raw reply	[flat|nested] 40+ messages in thread

* Re: [PATCH 4/5] hw/audio/ac97: Split off some definitions to a header
  2023-02-25 19:35   ` Philippe Mathieu-Daudé
@ 2023-02-26 22:17     ` BALATON Zoltan
  0 siblings, 0 replies; 40+ messages in thread
From: BALATON Zoltan @ 2023-02-26 22:17 UTC (permalink / raw)
  To: Philippe Mathieu-Daudé
  Cc: qemu-devel, qemu-ppc, Gerd Hoffmann, Daniel Henrique Barboza,
	Bernhard Beschow, philmd

[-- Attachment #1: Type: text/plain, Size: 566 bytes --]

On Sat, 25 Feb 2023, Philippe Mathieu-Daudé wrote:
> On 21/2/23 19:44, BALATON Zoltan wrote:
>> These can be shared with other AC97 implementations.
>> 
>> Signed-off-by: BALATON Zoltan <balaton@eik.bme.hu>
>> ---
>>   hw/audio/ac97.c | 43 +-------------------------------
>>   hw/audio/ac97.h | 65 +++++++++++++++++++++++++++++++++++++++++++++++++
>>   2 files changed, 66 insertions(+), 42 deletions(-)
>>   create mode 100644 hw/audio/ac97.h
>
> Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>

Sorry missed this one, I'll add to next version if needed.

^ permalink raw reply	[flat|nested] 40+ messages in thread

* Re: [PATCH 3/5] hw/ppc/pegasos2: Fix PCI interrupt routing
  2023-02-25 19:34   ` Philippe Mathieu-Daudé
  2023-02-25 20:19     ` BALATON Zoltan
@ 2023-02-26 22:22     ` BALATON Zoltan
  1 sibling, 0 replies; 40+ messages in thread
From: BALATON Zoltan @ 2023-02-26 22:22 UTC (permalink / raw)
  To: Philippe Mathieu-Daudé
  Cc: qemu-devel, qemu-ppc, Gerd Hoffmann, Daniel Henrique Barboza,
	Bernhard Beschow

[-- Attachment #1: Type: text/plain, Size: 1976 bytes --]

On Sat, 25 Feb 2023, Philippe Mathieu-Daudé wrote:
> On 21/2/23 19:44, BALATON Zoltan wrote:
>> 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 <balaton@eik.bme.hu>
>> ---
>>   hw/pci-host/mv64361.c |  4 ----
>>   hw/ppc/pegasos2.c     | 26 +++++++++++++++++++++++++-
>>   2 files changed, 25 insertions(+), 5 deletions(-)
>
>
>> +static void pegasos2_pci_irq(void *opaque, int n, int level)
>> +{
>> +    Pegasos2MachineState *pm = 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);
>> +}
>
> See TYPE_SPLIT_IRQ.

I've checked it but instead of storing 8 qemi_irqs in machine state we 
would end up storing additional 2 DeviceStates and had to use cryptic 
qemu_gpio and qdev commands to achieve the same in a much more convoluted 
and longer way. So I concluded that if you have to split an irq into more 
than two or have variable number of destinations then split-irq would be 
useful but it's an overkill for this simple case so I'd stay with the 
simple solution that's easy to understand.

Regards,
BALATON Zoltan

^ permalink raw reply	[flat|nested] 40+ messages in thread

* Re: [PATCH 0/5] Pegasos2 fixes and audio output support
  2023-02-22 21:12         ` BALATON Zoltan
  2023-02-22 22:20           ` Bernhard Beschow
@ 2023-03-01 13:42           ` Mark Cave-Ayland
  2023-03-01 19:21             ` BALATON Zoltan
  1 sibling, 1 reply; 40+ messages in thread
From: Mark Cave-Ayland @ 2023-03-01 13:42 UTC (permalink / raw)
  To: BALATON Zoltan, Bernhard Beschow
  Cc: qemu-devel, qemu-ppc, Gerd Hoffmann, Daniel Henrique Barboza, philmd

On 22/02/2023 21:12, BALATON Zoltan wrote:

> On Wed, 22 Feb 2023, Bernhard Beschow wrote:
>> Am 22. Februar 2023 19:25:16 UTC schrieb BALATON Zoltan <balaton@eik.bme.hu>:
>>> On Wed, 22 Feb 2023, Bernhard Beschow wrote:
>>>> On Wed, Feb 22, 2023 at 4:38 PM Bernhard Beschow <shentey@gmail.com> wrote:
>>>>> On Tue, Feb 21, 2023 at 7:44 PM BALATON Zoltan <balaton@eik.bme.hu> wrote:
>>>>>> This series fixes PCI interrupts on the ppc/pegasos2 machine and adds
>>>>>> partial implementation of the via-ac97 sound part enough to get audio
>>>>>> output. I'd like this to be merged for QEMU 8.0.
>>>>>>
>>>>>> Regards,
>>>>>> BALATON Zoltan
>>>>>>
>>>>>> BALATON Zoltan (5):
>>>>>>   hw/isa/vt82c686: Implement interrupt routing in via_isa_set_irq
>>>>>>   hw/isa/vt82c686: Implement PIRQ pins
>>>>>>   hw/ppc/pegasos2: Fix PCI interrupt routing
>>>>>>   hw/audio/ac97: Split off some definitions to a header
>>>>>>   hw/audio/via-ac97: Basic implementation of audio playback
>>>>>>
>>>>>>  hw/audio/ac97.c            |  43 +---
>>>>>>  hw/audio/ac97.h            |  65 ++++++
>>>>>>  hw/audio/trace-events      |   6 +
>>>>>>  hw/audio/via-ac97.c        | 436 ++++++++++++++++++++++++++++++++++++-
>>>>>>  hw/ide/via.c               |   2 +-
>>>>>>  hw/isa/vt82c686.c          |  61 +++++-
>>>>>>  hw/pci-host/mv64361.c      |   4 -
>>>>>>  hw/ppc/pegasos2.c          |  26 ++-
>>>>>>  hw/usb/vt82c686-uhci-pci.c |   5 +-
>>>>>>  include/hw/isa/vt82c686.h  |  39 +++-
>>>>>>  10 files changed, 626 insertions(+), 61 deletions(-)
>>>>>>  create mode 100644 hw/audio/ac97.h
>>>>>>
>>>>>> -- 
>>>>>> 2.30.7
>>>>>>
>>>>>>
>>>>> Wow, the MorphOS people paid attention to sound design. Thanks for
>>>>> presenting it to us, Zoltan!
>>>>>
>>>>> I've had a closer look at your series and I think it can be simplified:
>>>>> Patch 2 can be implemented quite straight-forward like I proposed in a
>>>>> private mail: https://github.com/shentok/qemu/commit/via-priq-routing.
>>>>> Then, in order to make patch 3 "hw/ppc/pegasos2: Fix PCI interrupt routing"
>>>>> working, one can expose the PCI interrupts with a single line like you do
>>>>> in patch 2. With this, patch 1 "hw/isa/vt82c686: Implement interrupt
>>>>> routing in via_isa_set_irq" isn't needed any longer and can be omitted.
>>>>>
>>>>> In via-ac97, rather than using via_isa_set_irq(), pci_set_irq() can be
>>>>> used instead. pci_set_irq() internally takes care of all the ISA interrupt
>>>>> level tracking patch 1 attempted to address.
>>>>>
>>>>
>>>> Here is a proof of concept branch to demonstrate that the simplification
>>>> actually works: https://github.com/shentok/qemu/commits/pegasos2 (Tested
>>>> with MorphOS with and without pegasos2.rom).
>>>
>>> Does this only work because both the via-ac97 and the PCI interrupts are mapped to 
>>> the same ISA IRQ and you've only tested sound? The guest could configure each 
>>> device to use a different IRQ, also mapping them so they share one ISA interrupt. 
>>> What happens if multiple devices are mapped to IRQ 9 (which is the case on 
>>> pegasos2 where PCI cards, ac97 and USB all share this IRQ) and more than one such 
>>> device wants to raise an interrupt at the same time? If you ack the ac97 interrupt 
>>> but a PCI network card or the USB part still wants to get the CPUs attention the 
>>> ISA IRQ should remain raised until all devices are serviced.
>>
>> pci_bus_get_irq_level(), used in via_isa_set_pci_irq(), should handle
>> exactly that case very well.
>>
>>> I don't see a way to track the status of all devices in a single qemu_irq which 
>>> can only be up or down so we need something to store the state of each source.
>>
>> pci_set_irq() causes pci_bus_change_irq_level() to be called.
>> pci_bus_change_irq_level() tracks the sum of all irq levels of all
>> devices attached to a particular pin in irq_count. Have a look at
>> pci_bus_change_irq_level() and you will understand better.
> 
> I'm aware of that, we're using that in sam460ex which connects all PCI interrupt 
> lines to a single IRQ and Peter explored and explained it in a comment there when 
> that was discovered. First we had a patch with or-irq but due to this behaviot that's 
> not needed for PCI interrupts. But the VT8132 could change what ISA IRQ you route the 
> sub functions to. It happens that on pegasos2 by default all of those are routed to 
> IRQ9 except IDE but what if a guest changes ac97 to use a different interrupt? Then 
> it's not a PCI interrupt any more so you can't use pci_set_irq in via=ac97. There are 
> only 4 PCI INT lines but the VIA components can be routed to 13 or 14 ISA IRQs. How 
> do you keep track of that with only the PCI bus interrupts? I don't get your approach.

It's up to the OS to setup the IRQ routing as required, so if the guest wants to 
route via an ISA IRQ then there should be a register to control this, much in the 
same way that legacy mode can be enabled for some PCI IDE controllers.

>>> My patch adds a state register to each ISA IRQ line for all possible sources which 
>>> could probably be stored once but then for each change of ISA IRQ status all the 
>>> mapped devices should be checked and combined so it's easier to store them for 
>>> each IRQ. Does your approach still work if you play sound, and copy something from 
>>> network to a USB device at the same time? (I'm not sure mine does not have 
>>> remaining bugs but I don't think this can be simplified that way but if you can 
>>> prove it would work I don't mind taking an alternative version but I'm not 
>>> convinced yet.)

This doesn't sound right at all: at least on old PCs an ISA card was wired to one or 
more IRQ lines, and it wasn't possible to share them. If you find you're sharing the 
same ISQ IRQ then it's likely something is wrong with the IRQ routing.

>> Well, I can't prove that my approach works but unfortunately I can
>> prove that both our approaches cause a freeze :/ Try:
>> 1. Start `qemu-system-ppc -M pegasos2 -bios pegasos2.rom -rtc
>> base=localtime -device ati-vga,guest_hwcursor=true,romfile="" -cdrom
>> morphos-3.17.iso -device usb-mouse -device usb-kbd`
>> 2. Move the mouse while sound is playing
>> -> Observe the VM to freeze
>>
>> So there must be an issue somewhere else...
> 
> I'll have a look later but my patch attempts to handle the USB controller interrupts. 
> There may be another bug somewhere in USB emulation though, we have similar problem 
> with mac99 with older MacOS guests. Considering that USB devices probably did not 
> work at all before this patch it's at least still an imptovement. :-)
> 
> Regards,
> BALATON Zoltan


ATB,

Mark.


^ permalink raw reply	[flat|nested] 40+ messages in thread

* Re: [PATCH 0/5] Pegasos2 fixes and audio output support
  2023-02-23  0:43           ` BALATON Zoltan
@ 2023-03-01 13:47             ` Mark Cave-Ayland
  0 siblings, 0 replies; 40+ messages in thread
From: Mark Cave-Ayland @ 2023-03-01 13:47 UTC (permalink / raw)
  To: BALATON Zoltan, Bernhard Beschow
  Cc: qemu-devel, qemu-ppc, Gerd Hoffmann, Daniel Henrique Barboza, philmd

On 23/02/2023 00:43, BALATON Zoltan wrote:

> On Wed, 22 Feb 2023, BALATON Zoltan wrote:
>> On Wed, 22 Feb 2023, Bernhard Beschow wrote:
>>> Am 22. Februar 2023 19:25:16 UTC schrieb BALATON Zoltan
>>> <balaton@eik.bme.hu>:
>>>> On Wed, 22 Feb 2023, Bernhard Beschow wrote:
>>>>> On Wed, Feb 22, 2023 at 4:38 PM Bernhard Beschow <shentey@gmail.com>
>>>>> wrote:
>>>>>> On Tue, Feb 21, 2023 at 7:44 PM BALATON Zoltan <balaton@eik.bme.hu>
>>>>>> wrote:
>>>>>>> This series fixes PCI interrupts on the ppc/pegasos2 machine and adds
>>>>>>> partial implementation of the via-ac97 sound part enough to get audio
>>>>>>> output. I'd like this to be merged for QEMU 8.0.
>>>>>>>
>>>>>>> Regards,
>>>>>>> BALATON Zoltan
>>>>>>>
>>>>>>> BALATON Zoltan (5):
>>>>>>>    hw/isa/vt82c686: Implement interrupt routing in via_isa_set_irq
>>>>>>>    hw/isa/vt82c686: Implement PIRQ pins
>>>>>>>    hw/ppc/pegasos2: Fix PCI interrupt routing
>>>>>>>    hw/audio/ac97: Split off some definitions to a header
>>>>>>>    hw/audio/via-ac97: Basic implementation of audio playback
>>>>>>>
>>>>>>>   hw/audio/ac97.c            |  43 +---
>>>>>>>   hw/audio/ac97.h            |  65 ++++++
>>>>>>>   hw/audio/trace-events      |   6 +
>>>>>>>   hw/audio/via-ac97.c        | 436 ++++++++++++++++++++++++++++++++++++-
>>>>>>>   hw/ide/via.c               |   2 +-
>>>>>>>   hw/isa/vt82c686.c          |  61 +++++-
>>>>>>>   hw/pci-host/mv64361.c      |   4 -
>>>>>>>   hw/ppc/pegasos2.c          |  26 ++-
>>>>>>>   hw/usb/vt82c686-uhci-pci.c |   5 +-
>>>>>>>   include/hw/isa/vt82c686.h  |  39 +++-
>>>>>>>   10 files changed, 626 insertions(+), 61 deletions(-)
>>>>>>>   create mode 100644 hw/audio/ac97.h
>>>>>>>
>>>>>>> --
>>>>>>> 2.30.7
>>>>>>>
>>>>>>>
>>>>>> Wow, the MorphOS people paid attention to sound design. Thanks for
>>>>>> presenting it to us, Zoltan!
>>>>>>
>>>>>> I've had a closer look at your series and I think it can be simplified:
>>>>>> Patch 2 can be implemented quite straight-forward like I proposed in a
>>>>>> private mail: https://github.com/shentok/qemu/commit/via-priq-routing.
>>>>>> Then, in order to make patch 3 "hw/ppc/pegasos2: Fix PCI interrupt
>>>>>> routing"
>>>>>> working, one can expose the PCI interrupts with a single line like you
>>>>>> do
>>>>>> in patch 2. With this, patch 1 "hw/isa/vt82c686: Implement interrupt
>>>>>> routing in via_isa_set_irq" isn't needed any longer and can be omitted.
>>>>>>
>>>>>> In via-ac97, rather than using via_isa_set_irq(), pci_set_irq() can be
>>>>>> used instead. pci_set_irq() internally takes care of all the ISA
>>>>>> interrupt
>>>>>> level tracking patch 1 attempted to address.
>>>>>>
>>>>>
>>>>> Here is a proof of concept branch to demonstrate that the simplification
>>>>> actually works: https://github.com/shentok/qemu/commits/pegasos2 (Tested
>>>>> with MorphOS with and without pegasos2.rom).
>>>>
>>>> Does this only work because both the via-ac97 and the PCI interrupts are
>>>> mapped to the same ISA IRQ and you've only tested sound? The guest could
>>>> configure each device to use a different IRQ, also mapping them so they
>>>> share one ISA interrupt. What happens if multiple devices are mapped to
>>>> IRQ 9 (which is the case on pegasos2 where PCI cards, ac97 and USB all
>>>> share this IRQ) and more than one such device wants to raise an interrupt
>>>> at the same time? If you ack the ac97 interrupt but a PCI network card or
>>>> the USB part still wants to get the CPUs attention the ISA IRQ should
>>>> remain raised until all devices are serviced.
>>>
>>> pci_bus_get_irq_level(), used in via_isa_set_pci_irq(), should handle
>>> exactly that case very well.
>>>
>>>> I don't see a way to track the status of all devices in a single qemu_irq
>>>> which can only be up or down so we need something to store the state of
>>>> each source.
>>>
>>> pci_set_irq() causes pci_bus_change_irq_level() to be called.
>>> pci_bus_change_irq_level() tracks the sum of all irq levels of all
>>> devices attached to a particular pin in irq_count. Have a look at
>>> pci_bus_change_irq_level() and you will understand better.
>>>
>>>> My patch adds a state register to each ISA IRQ line for all possible
>>>> sources which could probably be stored once but then for each change of
>>>> ISA IRQ status all the mapped devices should be checked and combined so
>>>> it's easier to store them for each IRQ. Does your approach still work if
>>>> you play sound, and copy something from network to a USB device at the
>>>> same time? (I'm not sure mine does not have remaining bugs but I don't
>>>> think this can be simplified that way but if you can prove it would work I
>>>> don't mind taking an alternative version but I'm not convinced yet.)
>>>
>>> Well, I can't prove that my approach works but unfortunately I can
>>> prove that both our approaches cause a freeze :/ Try:
>>> 1. Start `qemu-system-ppc -M pegasos2 -bios pegasos2.rom -rtc
>>> base=localtime -device ati-vga,guest_hwcursor=true,romfile="" -cdrom
>>> morphos-3.17.iso -device usb-mouse -device usb-kbd`
>>> 2. Move the mouse while sound is playing
>>> -> Observe the VM to freeze
>>
>> Not quite sure why but it seems to happen when both the ac97 and USB raise
>> the interrupt and the guest driver seems to get confused. Adding some debug
>> logging:
>>
>> diff --git a/hw/isa/vt82c686.c b/hw/isa/vt82c686.c
>> index b16620daf8..f840e5a8d0 100644
>> --- a/hw/isa/vt82c686.c
>> +++ b/hw/isa/vt82c686.c
>> @@ -636,12 +636,13 @@ void via_isa_set_irq(PCIDevice *d, ViaISAIRQSourceBit
>> n, int level)
>>      if (!isa_irq) {
>>          return;
>>      }
>> -
>> +if (n > 1) fprintf(stderr, "%s: %d %d %d %x -> ", __func__, n, level,
>> isa_irq, s->isa_irq_state[isa_irq]);
>>      if (level) {
>>          s->isa_irq_state[isa_irq] |= BIT(n);
>>      } else {
>>          s->isa_irq_state[isa_irq] &= ~BIT(n);
>>      }
>> +if (n > 1) fprintf(stderr, "%x\n", s->isa_irq_state[isa_irq]);
>>      qemu_set_irq(s->isa_irqs[isa_irq], !!s->isa_irq_state[isa_irq]);
>> }
>>
>> I see in the normal case when there's only one interrupt for USB only:
>>
>> via_isa_set_irq: 2 1 9 0 -> 4
>> usb_uhci_mmio_readw addr 0x0002, ret 0x0001
>> usb_uhci_mmio_writew addr 0x0002, val 0x0001
>> via_isa_set_irq: 2 0 9 4 -> 0
>>
>> For sound only:
>>
>> via_ac97_sgd_fetch addr=0x43b70bc --F len=3528
>> via_isa_set_irq: 8 1 9 0 -> 100
>> usb_uhci_mmio_readw addr 0x0002, ret 0x0000
>> usb_uhci_mmio_readw addr 0x0002, ret 0x0000
>> via_ac97_sgd_read 0x0 1 -> 0xc9
>> via_ac97_sgd_write 0x0 1 <- 0x1
>> via_isa_set_irq: 8 0 9 100 -> 0
>> via_ac97_sgd_read 0x4 4 -> 0x439cbe8
>> via_ac97_sgd_fetch addr=0x43c70bc -E- len=3528
>> via_isa_set_irq: 8 1 9 0 -> 100
>> via_ac97_sgd_read 0x4 4 -> 0x439cbe0
>> via_ac97_sgd_read 0x4 4 -> 0x439cbe0
>> via_ac97_sgd_read 0x10 1 -> 0x0
>> usb_uhci_mmio_readw addr 0x0002, ret 0x0000
>> usb_uhci_mmio_readw addr 0x0002, ret 0x0000
>> via_ac97_sgd_read 0x0 1 -> 0xca
>> via_ac97_sgd_write 0x0 1 <- 0x2
>> via_isa_set_irq: 8 0 9 100 -> 0
>> via_ac97_sgd_read 0x4 4 -> 0x439cbe0
>>
>> but it stops acking irqs when both are raised or it seems USB IRQ is raised
>> while it's in the guest IRQ handler:
>>
>> via_ac97_sgd_fetch addr=0x43c70bc -E- len=3528
>> via_isa_set_irq: 8 1 9 0 -> 100
>> usb_uhci_mmio_readw addr 0x0002, ret 0x0000
>> usb_uhci_mmio_readw addr 0x0002, ret 0x0000
>> via_isa_set_irq: 2 1 9 100 -> 104
>> via_ac97_sgd_read 0x0 1 -> 0xca
>> via_ac97_sgd_write 0x0 1 <- 0x2
>> via_isa_set_irq: 8 0 9 104 -> 4
>> via_ac97_sgd_read 0x4 4 -> 0x439cbe0
>> via_ac97_sgd_fetch addr=0x43b70bc --F len=3528
>> via_isa_set_irq: 8 1 9 4 -> 104
>> via_ac97_sgd_read 0x4 4 -> 0x439cbe8
>> via_ac97_sgd_read 0x4 4 -> 0x439cbe8
>> via_ac97_sgd_read 0x10 1 -> 0x0
>> usb_uhci_mmio_readw addr 0x0006, ret 0x06bf
>> usb_uhci_mmio_readw addr 0x0010, ret 0x0085
>> usb_uhci_mmio_writew addr 0x0010, val 0x0085
>> usb_uhci_mmio_readw addr 0x0012, ret 0x0085
>> usb_uhci_mmio_writew addr 0x0012, val 0x0085
>> usb_uhci_mmio_readw addr 0x0006, ret 0x06b7
>> usb_uhci_mmio_readw addr 0x0010, ret 0x0080
>> usb_uhci_mmio_writew addr 0x0010, val 0x0080
>> usb_uhci_mmio_readw addr 0x0012, ret 0x0080
>> usb_uhci_mmio_writew addr 0x0012, val 0x0080
>> usb_uhci_mmio_readw addr 0x0006, ret 0x0759
>> usb_uhci_mmio_readw addr 0x0010, ret 0x0085
>> usb_uhci_mmio_writew addr 0x0010, val 0x0085
>> usb_uhci_mmio_readw addr 0x0012, ret 0x0085
>> usb_uhci_mmio_writew addr 0x0012, val 0x0085
>> usb_uhci_mmio_readw addr 0x0006, ret 0x0752
>> usb_uhci_mmio_readw addr 0x0010, ret 0x0080
>> usb_uhci_mmio_writew addr 0x0010, val 0x0080
>> usb_uhci_mmio_readw addr 0x0012, ret 0x0080
>> usb_uhci_mmio_writew addr 0x0012, val 0x0080
>> via_isa_set_irq: 2 1 9 104 -> 104
>> usb_uhci_mmio_readw addr 0x0006, ret 0x07f1
>> usb_uhci_mmio_readw addr 0x0010, ret 0x0085
>> usb_uhci_mmio_writew addr 0x0010, val 0x0085
>> usb_uhci_mmio_readw addr 0x0012, ret 0x0085
>> usb_uhci_mmio_writew addr 0x0012, val 0x0085
>> usb_uhci_mmio_readw addr 0x0006, ret 0x07e9
>>
>> It seems to not notice the USB interrupt any more after that although sound
>> playback stops but mouse still moves but otherwise does not work. I'm not
>> sure this is not a guest bug as it seems an interrupt handler should disable
>> interrupts to not get interrupted. Could this be reproduced with Linux? I'd
>> still go wit this patch series for 8.0 because the default case works and
>> this was also tested with two PCI cards on AmigaOS4 which works not while it
>> did not work at all before so this could be debugged and fixed later but
>> adding this series makes the machine generally usable at least without USB
>> devices. With -d unimp I also get these logs when booting MorphOS:
>>
>> ok boot cd boot.img
>> ISO-9660 filesystem:  System-ID: "MORPHOS"  Volume-ID: "MorphOSBoot"
>> Root dir: "" flags=0x2 extent=0x20 size=0x1800
>> 31.127| Memory used before SYS_Init: 9MB
>> i8259: level sensitive irq not supported
>> i8259: level sensitive irq not supported
>>
>> Could it be the PIC emulation should be fixed for this?
> 
> After thinking about that more I think this is the reason and this patch
> just uncovered a defficiency in the PIC model. I would not care much it
> this was only sound vs. USB but it's also sound vs. PCI cards e.g. network
> so until that's fixed in i8259 I can hack around that here like this:
> 
> diff --git a/hw/isa/vt82c686.c b/hw/isa/vt82c686.c
> index b16620daf8..a6cf55a632 100644
> --- a/hw/isa/vt82c686.c
> +++ b/hw/isa/vt82c686.c
> @@ -597,6 +597,7 @@ void via_isa_set_irq(PCIDevice *d, ViaISAIRQSourceBit n, int level)
>   {
>       ViaISAState *s = VIA_ISA(pci_get_function_0(d));
>       uint8_t isa_irq = 0, max_irq = 15;
> +    int old_level;
> 
>       if (n == VIA_IRQ_USB0 && d == PCI_DEVICE(&s->uhci[1])) {
>           n++;
> @@ -637,11 +638,16 @@ void via_isa_set_irq(PCIDevice *d, ViaISAIRQSourceBit n, int level)
>           return;
>       }
> 
> +    old_level = !!s->isa_irq_state[isa_irq];
>       if (level) {
>           s->isa_irq_state[isa_irq] |= BIT(n);
>       } else {
>           s->isa_irq_state[isa_irq] &= ~BIT(n);
>       }
> +    if (old_level && !!s->isa_irq_state[isa_irq]) {
> +        /* Only needed because i8259 model does not support level sensitive */
> +        qemu_set_irq(s->isa_irqs[isa_irq], 0);
> +    }
>       qemu_set_irq(s->isa_irqs[isa_irq], !!s->isa_irq_state[isa_irq]);
>   }
> 
> Unless somebody has a better idea I'll go with this for a v2 and let this
> be cleaned up sometimes in the future when sombody gets around to improve
> the PIC model.

This still doesn't seem right: if this were required for ISA IRQs then it would also 
be needed for 8259-based PICs, otherwise the various PC models would continually hang 
in the same way. Again this suggests that multiple devices are sharing an ISA IRQ 
which is likely incorrect.


ATB,

Mark.


^ permalink raw reply	[flat|nested] 40+ messages in thread

* Re: [PATCH 0/5] Pegasos2 fixes and audio output support
  2023-02-23  9:13               ` Bernhard Beschow
  2023-02-23 12:33                 ` BALATON Zoltan
@ 2023-03-01 13:49                 ` Mark Cave-Ayland
  2023-03-01 19:24                   ` BALATON Zoltan
  1 sibling, 1 reply; 40+ messages in thread
From: Mark Cave-Ayland @ 2023-03-01 13:49 UTC (permalink / raw)
  To: Bernhard Beschow, BALATON Zoltan
  Cc: qemu-devel, qemu-ppc, Gerd Hoffmann, Daniel Henrique Barboza, philmd

On 23/02/2023 09:13, Bernhard Beschow wrote:

> Am 22. Februar 2023 23:00:02 UTC schrieb BALATON Zoltan <balaton@eik.bme.hu>:
>> On Wed, 22 Feb 2023, Bernhard Beschow wrote:
>>> Am 22. Februar 2023 21:12:01 UTC schrieb BALATON Zoltan <balaton@eik.bme.hu>:
>>>> On Wed, 22 Feb 2023, Bernhard Beschow wrote:
>>>>> Am 22. Februar 2023 19:25:16 UTC schrieb BALATON Zoltan <balaton@eik.bme.hu>:
>>>>>> On Wed, 22 Feb 2023, Bernhard Beschow wrote:
>>>>>>> On Wed, Feb 22, 2023 at 4:38 PM Bernhard Beschow <shentey@gmail.com> wrote:
>>>>>>>> I've had a closer look at your series and I think it can be simplified:
>>>>>>>> Patch 2 can be implemented quite straight-forward like I proposed in a
>>>>>>>> private mail: https://github.com/shentok/qemu/commit/via-priq-routing.
>>>>>>>> Then, in order to make patch 3 "hw/ppc/pegasos2: Fix PCI interrupt routing"
>>>>>>>> working, one can expose the PCI interrupts with a single line like you do
>>>>>>>> in patch 2. With this, patch 1 "hw/isa/vt82c686: Implement interrupt
>>>>>>>> routing in via_isa_set_irq" isn't needed any longer and can be omitted.
>>>>>>>>
>>>>>>>> In via-ac97, rather than using via_isa_set_irq(), pci_set_irq() can be
>>>>>>>> used instead. pci_set_irq() internally takes care of all the ISA interrupt
>>>>>>>> level tracking patch 1 attempted to address.
>>>>>>>>
>>>>>>>
>>>>>>> Here is a proof of concept branch to demonstrate that the simplification
>>>>>>> actually works: https://github.com/shentok/qemu/commits/pegasos2 (Tested
>>>>>>> with MorphOS with and without pegasos2.rom).
>>>>>>
>>>>>> Does this only work because both the via-ac97 and the PCI interrupts are mapped to the same ISA IRQ and you've only tested sound? The guest could configure each device to use a different IRQ, also mapping them so they share one ISA interrupt. What happens if multiple devices are mapped to IRQ 9 (which is the case on pegasos2 where PCI cards, ac97 and USB all share this IRQ) and more than one such device wants to raise an interrupt at the same time? If you ack the ac97 interrupt but a PCI network card or the USB part still wants to get the CPUs attention the ISA IRQ should remain raised until all devices are serviced.
>>>>>
>>>>> pci_bus_get_irq_level(), used in via_isa_set_pci_irq(), should handle
>>>>> exactly that case very well.
>>>>>
>>>>>> I don't see a way to track the status of all devices in a single qemu_irq which can only be up or down so we need something to store the state of each source.
>>>>>
>>>>> pci_set_irq() causes pci_bus_change_irq_level() to be called.
>>>>> pci_bus_change_irq_level() tracks the sum of all irq levels of all
>>>>> devices attached to a particular pin in irq_count. Have a look at
>>>>> pci_bus_change_irq_level() and you will understand better.
>>>>
>>>> I'm aware of that, we're using that in sam460ex which connects all PCI interrupt lines to a single IRQ and Peter explored and explained it in a comment there when that was discovered. First we had a patch with or-irq but due to this behaviot that's not needed for PCI interrupts. But the VT8132 could change what ISA IRQ you route the sub functions to.
>>>
>>> That depends on the sub function if you can do that. And if so, then it depends on whether the function is still in PCI mode (see below).
>>>
>>>> It happens that on pegasos2 by default all of those are routed to IRQ9 except IDE
>>>
>>> All *PCI* interrupts are routed to IRQ9 while IDE legacy interrupts are routed to the compatible ISA IRQs. Note that the IDE function must only trigger the ISA IRQs if it is in legacy mode while it must only trigger the PCI IRQ in non-legacy mode. See https://www.bswd.com/pciide.pdf for more details on this particular topic.
>>
>> The docs say so but based on what guests that work on real hardware do it does not work that way. Look up previous discussion on this on the list from around the time Mark changed via-ide about 4-5 years ago. That series was a result of his review of my proposed changes and gave resuled in an alternative appdroach. On pegasos2 (and probably also on fuloong2e based on same later findings, see patches to that, I can try to find these later if you can't find them) via-ide *always* uses IRQ 14/15 and the native mode only switches register addresses from legacy io ports to PCI io space so you can set it in with BAR regs but the IRQs don't change despite what the docs say. There are some hacks in Linux kernel and other guests to account for this but the comments for the reason are wrong in Linux, they say IDE is always in legacy mode but in fact if has a half-native mode which is what I called it where io addresses are set with BARs but IRQs are still the legacy ISA ones. You can find some references in previous discussion. Probably searching for via-ide half-native mode might find it.
>>
>>>> but what if a guest changes ac97 to use a different interrupt? Then it's not a PCI interrupt any more so you can't use pci_set_irq in via=ac97.
>>>
>>> How would it do that? AFAICS there is no dedicated register to configure which IRQ to use. This means that it can only trigger an interrupt via its PCI intx pin which is subject to the PCI -> ISA IRQ router.
>>
>> The VIA functions can use their PCI_INTERRUPT_LINE (0x3c) registers to set their ISA IRQ according to the docs (and unlike IDE in other functions like USB and sound this probably also works) and the PIRQA-D pins can be mapped to ISA IRQs by the 0x55-0x57 config registers of the isa bridge (function0). This is what I implemented in via_isa_set_irq() in this series.
>>
>>>> There are only 4 PCI INT lines but the VIA components can be routed to 13 or 14 ISA IRQs.
>>>
>>> Pure PCI components are only able to trigger one of the four PCI intx pins they are *hardwired* to.
>>
>> This is true for PCI cards which can only use the 4 pins the slot they are in is wired to. These come in through the PIRQA-D pins and they are routed with the funstion 0 0x55-0x57 config registers. But I'm not sure about the internal functions.
>>
>>> Each component has only one pin. Which ISA IRQ gets triggered through that pin can be selected from 13 or 14 ISA IRQs as you say by means of the three configuration registers of the PCI -> ISA IRQ router.
>>
>> So you say that internal functions are also wired to the same 4 lines like normal PCI cards?
> 
> Yes.
> 
>> Then how can you route them to different interrupts setting their config reg 0x3c independent of function0 0x55-0x57 regs?
> 
> 0x3c isn't supposed to be interpretet by hardware, and in general hardware can't: 0x3c is standardized for every PCI function which includes standalone PCI devices in particular. Standalone PCI devices don't have access to an IRQ router. So if they don't, how could they possibly configure the IRQ they are triggering?
> 
> 0x3c is only information to the OS (populated by the BIOS). It merily indicates that the PCI device needs attention when the IRQ configured in 0x3c is raised. See comment 4 in https://community.osr.com/discussion/30399/read-only-pci-interrupt-line-register for another explanation.
> 
> Even though the south bridge contains an interrupt router doesn't mean that its PCI functions can configure their IRQ through their 0x3c registers. That would change the semantics of standardized PCI registers which is surely not permitted by the standard. Instead, the PCI IRQs are configured through the device-specific 0x55-0x57 regs.
> 
> I see that 0x3c is also used for the USB functions. They used to trigger the raw ISA IRQs before your series which seems wrong. I think 0x3c usage needs to be cleaned up in the VIA model. Otherwise this will likely cause problems elsewhere.
> 
>>
>>>> How do you keep track of that with only the PCI bus interrupts?
>>>
>>> Devices that operate in ISA mode such as the IDE function shall have their own, dedicated ISA IRQs assigned by the guest. Otherwise this causes a classic interrupt conflict, just like in the olden ISA days. If the function operates in PCI mode, it must not trigger the ISA IRQs, regardless of whether they are assigned or not.
>>
>> This does not match with guests which clearly expect to get ISA IRQ9 for PCI cards and USB and sound which is where these are routed within the VIA bridge as the firmware programs it.
> 
> What I meant was that a component able to operate in native/legacy/mixed mode such as IDE must not use both PCI and legacy ISA interrupts at the same time. Multiple PCI functions may of course share interrupts.
> 
>>
>>> There is also the power management function whose ACPI interrupt (SCI) can be routed by means of a dedicated register. Again, a guest must make sure here to not configure interrupt conflicts.
>>>
>>>> I don't get your approach.
>>>
>>> I hope that I could help you get a better understanding. The linked .pdf is good and comprehensive reading material.
>>
>> I'm not sure the via-ide confirms to that doc but it's also not any more a problem with via-ide now. That was discussed to death back then and "fixed" to work for the cases we want it to work with. We probably never agreed on how this really works but at least what we ended up with works with guests that run on real hardware. I'm OK with also making these cases work that we want now such as network and sound card under AmigaOS and sound under MorphOS (as long as you don't use USB) on pegasos2. This series does that so unless it breaks something that worked before I condider this moving forward and we can always improve adn fix it later. I'm not saying I'm not interested in your improvements just that let's that not hold this back now as we can fix and improve it later but otherwise users will have to wait until September to be able to use it. I know a few who want this and getting this out as it is would allow more people to test it and report problems so unless there are clearly wrong parts I'm OK with less than perfect but working solution as long as it's not too messy.
> 
> Patch 1 really seems like duplicating PCI code that already exists in QEMU. This is not needed and we should avoid that.
> 
> Moreover, usage of the IRQ line register (0x3c) for interrupt routing should be switched to using the 0x55-0x57 regs to be PCI compliant.
> 
> Thanks to your great work to make via-ac97 work we can confirm that both IRQ routing implementations basically work for now. Let's work out a solution that relies on existing code, sticks to the standard and hopefully works for i386 and MIPS, too.

FWIW this analysis seems correct to me based upon my experience with older PCs and 
reading the various specifications.


ATB,

Mark.

^ permalink raw reply	[flat|nested] 40+ messages in thread

* Re: [PATCH 0/5] Pegasos2 fixes and audio output support
  2023-03-01 13:42           ` Mark Cave-Ayland
@ 2023-03-01 19:21             ` BALATON Zoltan
  0 siblings, 0 replies; 40+ messages in thread
From: BALATON Zoltan @ 2023-03-01 19:21 UTC (permalink / raw)
  To: Mark Cave-Ayland
  Cc: Bernhard Beschow, qemu-devel, qemu-ppc, Gerd Hoffmann,
	Daniel Henrique Barboza, philmd

[-- Attachment #1: Type: text/plain, Size: 10911 bytes --]

On Wed, 1 Mar 2023, Mark Cave-Ayland wrote:
> On 22/02/2023 21:12, BALATON Zoltan wrote:
>> On Wed, 22 Feb 2023, Bernhard Beschow wrote:
>>> Am 22. Februar 2023 19:25:16 UTC schrieb BALATON Zoltan 
>>> <balaton@eik.bme.hu>:
>>>> On Wed, 22 Feb 2023, Bernhard Beschow wrote:
>>>>> On Wed, Feb 22, 2023 at 4:38 PM Bernhard Beschow <shentey@gmail.com> 
>>>>> wrote:
>>>>>> On Tue, Feb 21, 2023 at 7:44 PM BALATON Zoltan <balaton@eik.bme.hu> 
>>>>>> wrote:
>>>>>>> This series fixes PCI interrupts on the ppc/pegasos2 machine and adds
>>>>>>> partial implementation of the via-ac97 sound part enough to get audio
>>>>>>> output. I'd like this to be merged for QEMU 8.0.
>>>>>>> 
>>>>>>> Regards,
>>>>>>> BALATON Zoltan
>>>>>>> 
>>>>>>> BALATON Zoltan (5):
>>>>>>>   hw/isa/vt82c686: Implement interrupt routing in via_isa_set_irq
>>>>>>>   hw/isa/vt82c686: Implement PIRQ pins
>>>>>>>   hw/ppc/pegasos2: Fix PCI interrupt routing
>>>>>>>   hw/audio/ac97: Split off some definitions to a header
>>>>>>>   hw/audio/via-ac97: Basic implementation of audio playback
>>>>>>> 
>>>>>>>  hw/audio/ac97.c            |  43 +---
>>>>>>>  hw/audio/ac97.h            |  65 ++++++
>>>>>>>  hw/audio/trace-events      |   6 +
>>>>>>>  hw/audio/via-ac97.c        | 436 
>>>>>>> ++++++++++++++++++++++++++++++++++++-
>>>>>>>  hw/ide/via.c               |   2 +-
>>>>>>>  hw/isa/vt82c686.c          |  61 +++++-
>>>>>>>  hw/pci-host/mv64361.c      |   4 -
>>>>>>>  hw/ppc/pegasos2.c          |  26 ++-
>>>>>>>  hw/usb/vt82c686-uhci-pci.c |   5 +-
>>>>>>>  include/hw/isa/vt82c686.h  |  39 +++-
>>>>>>>  10 files changed, 626 insertions(+), 61 deletions(-)
>>>>>>>  create mode 100644 hw/audio/ac97.h
>>>>>>> 
>>>>>>> -- 
>>>>>>> 2.30.7
>>>>>>> 
>>>>>>> 
>>>>>> Wow, the MorphOS people paid attention to sound design. Thanks for
>>>>>> presenting it to us, Zoltan!
>>>>>> 
>>>>>> I've had a closer look at your series and I think it can be simplified:
>>>>>> Patch 2 can be implemented quite straight-forward like I proposed in a
>>>>>> private mail: https://github.com/shentok/qemu/commit/via-priq-routing.
>>>>>> Then, in order to make patch 3 "hw/ppc/pegasos2: Fix PCI interrupt 
>>>>>> routing"
>>>>>> working, one can expose the PCI interrupts with a single line like you 
>>>>>> do
>>>>>> in patch 2. With this, patch 1 "hw/isa/vt82c686: Implement interrupt
>>>>>> routing in via_isa_set_irq" isn't needed any longer and can be omitted.
>>>>>> 
>>>>>> In via-ac97, rather than using via_isa_set_irq(), pci_set_irq() can be
>>>>>> used instead. pci_set_irq() internally takes care of all the ISA 
>>>>>> interrupt
>>>>>> level tracking patch 1 attempted to address.
>>>>>> 
>>>>> 
>>>>> Here is a proof of concept branch to demonstrate that the simplification
>>>>> actually works: https://github.com/shentok/qemu/commits/pegasos2 (Tested
>>>>> with MorphOS with and without pegasos2.rom).
>>>> 
>>>> Does this only work because both the via-ac97 and the PCI interrupts are 
>>>> mapped to the same ISA IRQ and you've only tested sound? The guest could 
>>>> configure each device to use a different IRQ, also mapping them so they 
>>>> share one ISA interrupt. What happens if multiple devices are mapped to 
>>>> IRQ 9 (which is the case on pegasos2 where PCI cards, ac97 and USB all 
>>>> share this IRQ) and more than one such device wants to raise an interrupt 
>>>> at the same time? If you ack the ac97 interrupt but a PCI network card or 
>>>> the USB part still wants to get the CPUs attention the ISA IRQ should 
>>>> remain raised until all devices are serviced.
>>> 
>>> pci_bus_get_irq_level(), used in via_isa_set_pci_irq(), should handle
>>> exactly that case very well.
>>> 
>>>> I don't see a way to track the status of all devices in a single qemu_irq 
>>>> which can only be up or down so we need something to store the state of 
>>>> each source.
>>> 
>>> pci_set_irq() causes pci_bus_change_irq_level() to be called.
>>> pci_bus_change_irq_level() tracks the sum of all irq levels of all
>>> devices attached to a particular pin in irq_count. Have a look at
>>> pci_bus_change_irq_level() and you will understand better.
>> 
>> I'm aware of that, we're using that in sam460ex which connects all PCI 
>> interrupt lines to a single IRQ and Peter explored and explained it in a 
>> comment there when that was discovered. First we had a patch with or-irq 
>> but due to this behaviot that's not needed for PCI interrupts. But the 
>> VT8132 could change what ISA IRQ you route the sub functions to. It happens 
>> that on pegasos2 by default all of those are routed to IRQ9 except IDE but 
>> what if a guest changes ac97 to use a different interrupt? Then it's not a 
>> PCI interrupt any more so you can't use pci_set_irq in via=ac97. There are 
>> only 4 PCI INT lines but the VIA components can be routed to 13 or 14 ISA 
>> IRQs. How do you keep track of that with only the PCI bus interrupts? I 
>> don't get your approach.
>
> It's up to the OS to setup the IRQ routing as required, so if the guest wants 
> to route via an ISA IRQ then there should be a register to control this, much 
> in the same way that legacy mode can be enabled for some PCI IDE controllers.

The VT82C686B and VT8231 datasheets document PCI config reg 0x3c to do 
that which is what I implemented in the first version but then Bernhard 
said this does not confirm to PCI standard spec so let's model these 
internal functions of the VIA chip as PCI devices and only map the PCI 
interrupts with the other registers called PnP IRQ routing in the ISA 
bridge function for mapping PIRQ/PINT pins. This IMO isn't correctly 
modeling the chip as documented in the datasheet but may still work as 
long as guests program everything to share IRQ 9 which is what the 
pegasos2 firmware does and guests seem to not change it but deal with it 
one way or another (MorphOS using level sensitive mode of the ISA PICs, 
Linux and AmigaOS without that). So we can get away with this and make our 
model simpler until we find a guest that actually need the more fine 
grained control the chip appears to have. So after some debate and testing 
it still works with the guests I cate about I went with this simpification 
in the latest version, noting the above in the commit message.

>>>> My patch adds a state register to each ISA IRQ line for all possible 
>>>> sources which could probably be stored once but then for each change of 
>>>> ISA IRQ status all the mapped devices should be checked and combined so 
>>>> it's easier to store them for each IRQ. Does your approach still work if 
>>>> you play sound, and copy something from network to a USB device at the 
>>>> same time? (I'm not sure mine does not have remaining bugs but I don't 
>>>> think this can be simplified that way but if you can prove it would work 
>>>> I don't mind taking an alternative version but I'm not convinced yet.)
>
> This doesn't sound right at all: at least on old PCs an ISA card was wired to 
> one or more IRQ lines, and it wasn't possible to share them. If you find 
> you're sharing the same ISQ IRQ then it's likely something is wrong with the 
> IRQ routing.

The fimrmware definitely writes 9 to 0x3c config regs of all internal 
devices (including IDE which despite of that still uses IRQ 14/15 as we 
have found before) and also writes 9 to 0x55-57 which map the PIRQ or PINT 
(these are called differently in 686B and VT8231) which are connected to 
PCI interrupts as seen on an obscure part of the schematics that I've 
missed first. You can see this with -trace enable="pci*" and guests work 
accordingly: logs from Linux and BSD on real hardware I've found on-line 
all list USB and other parts using IRQ 9 and also PCI cards started 
working after this series with AmigaOS which previously expecting 
interrupt 9 for these bit did not get it because of the missing 
connection to PINT pins.

I think your and Bernhard's assumption that internal functions of these 
VIA cups are PCI devices is wrong. There are multiple proofs for that:

- The datasheet documents regs to work differently than PCI spec
- The sound part ignores PCI bus master bit yet still can DMA (documented 
in datasheet and evidenced by AmigaOS driver which works on real hardware)
- The IDE part is still using ISA IRQs even in native mode (this one is 
also contrary to the datasheet not just the PCI spec but this was 
confirmed before and seems to also be the case on fuloong2e so probably 
true for all VIA chips)

So I think assuming these must work as normal PCI devices is clearly not 
what the datasheet says and likely not how real chip works so I'd rather 
believe the datasheet and what guests do than a PCI standard that may be 
later than this chip and nothing said the chip must confirm to it but you 
still want to assume that strongly.

Yet due to the way guests use it, sharing the same interrupt for all PCI 
lines and all internal functions we can still model it that way and thus 
make the model simpler (albeit conceptually wrong). I can accept if you 
want it to be simpler but I can't accept it's really how the chip works. 
But then this debate is theoretical, as long as guests work I'm OK with 
that so just took Bernhard's patches and I really hope now you won't come 
up with a 3rd way you think this should be done instead which would be 
really late now. This was tested first with my patches then with 
Bernhard's approach and now is being tested with the current state after 
rebase. We may have time for only one more iteration left but I really 
don't want to break it with extensive changes at this point. There's 
always an oportunity to improve things later so my main goal now is to let 
people be able to use these guests on pegasos2 as soon as possible. For 
AmigaOS pegasos2 would really help as it's a lot faster than sam460ex and 
may also allow KVM to work but for that this needs to get out then we can 
improve it in future versions.

Regards,
BALATON Zoltan

>>> Well, I can't prove that my approach works but unfortunately I can
>>> prove that both our approaches cause a freeze :/ Try:
>>> 1. Start `qemu-system-ppc -M pegasos2 -bios pegasos2.rom -rtc
>>> base=localtime -device ati-vga,guest_hwcursor=true,romfile="" -cdrom
>>> morphos-3.17.iso -device usb-mouse -device usb-kbd`
>>> 2. Move the mouse while sound is playing
>>> -> Observe the VM to freeze
>>> 
>>> So there must be an issue somewhere else...
>> 
>> I'll have a look later but my patch attempts to handle the USB controller 
>> interrupts. There may be another bug somewhere in USB emulation though, we 
>> have similar problem with mac99 with older MacOS guests. Considering that 
>> USB devices probably did not work at all before this patch it's at least 
>> still an imptovement. :-)
>> 
>> Regards,
>> BALATON Zoltan
>
>
> ATB,
>
> Mark.
>
>

^ permalink raw reply	[flat|nested] 40+ messages in thread

* Re: [PATCH 0/5] Pegasos2 fixes and audio output support
  2023-03-01 13:49                 ` Mark Cave-Ayland
@ 2023-03-01 19:24                   ` BALATON Zoltan
  2023-03-01 20:53                     ` Bernhard Beschow
  0 siblings, 1 reply; 40+ messages in thread
From: BALATON Zoltan @ 2023-03-01 19:24 UTC (permalink / raw)
  To: Mark Cave-Ayland
  Cc: Bernhard Beschow, qemu-devel, qemu-ppc, Gerd Hoffmann,
	Daniel Henrique Barboza, philmd

On Wed, 1 Mar 2023, Mark Cave-Ayland wrote:
> On 23/02/2023 09:13, Bernhard Beschow wrote:
>> Am 22. Februar 2023 23:00:02 UTC schrieb BALATON Zoltan 
>> <balaton@eik.bme.hu>:
>>> On Wed, 22 Feb 2023, Bernhard Beschow wrote:
>>>> Am 22. Februar 2023 21:12:01 UTC schrieb BALATON Zoltan 
>>>> <balaton@eik.bme.hu>:
>>>>> On Wed, 22 Feb 2023, Bernhard Beschow wrote:
>>>>>> Am 22. Februar 2023 19:25:16 UTC schrieb BALATON Zoltan 
>>>>>> <balaton@eik.bme.hu>:
>>>>>>> On Wed, 22 Feb 2023, Bernhard Beschow wrote:
>>>>>>>> On Wed, Feb 22, 2023 at 4:38 PM Bernhard Beschow <shentey@gmail.com> 
>>>>>>>> wrote:
>>>>>>>>> I've had a closer look at your series and I think it can be 
>>>>>>>>> simplified:
>>>>>>>>> Patch 2 can be implemented quite straight-forward like I proposed in 
>>>>>>>>> a
>>>>>>>>> private mail: 
>>>>>>>>> https://github.com/shentok/qemu/commit/via-priq-routing.
>>>>>>>>> Then, in order to make patch 3 "hw/ppc/pegasos2: Fix PCI interrupt 
>>>>>>>>> routing"
>>>>>>>>> working, one can expose the PCI interrupts with a single line like 
>>>>>>>>> you do
>>>>>>>>> in patch 2. With this, patch 1 "hw/isa/vt82c686: Implement interrupt
>>>>>>>>> routing in via_isa_set_irq" isn't needed any longer and can be 
>>>>>>>>> omitted.
>>>>>>>>> 
>>>>>>>>> In via-ac97, rather than using via_isa_set_irq(), pci_set_irq() can 
>>>>>>>>> be
>>>>>>>>> used instead. pci_set_irq() internally takes care of all the ISA 
>>>>>>>>> interrupt
>>>>>>>>> level tracking patch 1 attempted to address.
>>>>>>>>> 
>>>>>>>> 
>>>>>>>> Here is a proof of concept branch to demonstrate that the 
>>>>>>>> simplification
>>>>>>>> actually works: https://github.com/shentok/qemu/commits/pegasos2 
>>>>>>>> (Tested
>>>>>>>> with MorphOS with and without pegasos2.rom).
>>>>>>> 
>>>>>>> Does this only work because both the via-ac97 and the PCI interrupts 
>>>>>>> are mapped to the same ISA IRQ and you've only tested sound? The guest 
>>>>>>> could configure each device to use a different IRQ, also mapping them 
>>>>>>> so they share one ISA interrupt. What happens if multiple devices are 
>>>>>>> mapped to IRQ 9 (which is the case on pegasos2 where PCI cards, ac97 
>>>>>>> and USB all share this IRQ) and more than one such device wants to 
>>>>>>> raise an interrupt at the same time? If you ack the ac97 interrupt but 
>>>>>>> a PCI network card or the USB part still wants to get the CPUs 
>>>>>>> attention the ISA IRQ should remain raised until all devices are 
>>>>>>> serviced.
>>>>>> 
>>>>>> pci_bus_get_irq_level(), used in via_isa_set_pci_irq(), should handle
>>>>>> exactly that case very well.
>>>>>> 
>>>>>>> I don't see a way to track the status of all devices in a single 
>>>>>>> qemu_irq which can only be up or down so we need something to store 
>>>>>>> the state of each source.
>>>>>> 
>>>>>> pci_set_irq() causes pci_bus_change_irq_level() to be called.
>>>>>> pci_bus_change_irq_level() tracks the sum of all irq levels of all
>>>>>> devices attached to a particular pin in irq_count. Have a look at
>>>>>> pci_bus_change_irq_level() and you will understand better.
>>>>> 
>>>>> I'm aware of that, we're using that in sam460ex which connects all PCI 
>>>>> interrupt lines to a single IRQ and Peter explored and explained it in a 
>>>>> comment there when that was discovered. First we had a patch with or-irq 
>>>>> but due to this behaviot that's not needed for PCI interrupts. But the 
>>>>> VT8132 could change what ISA IRQ you route the sub functions to.
>>>> 
>>>> That depends on the sub function if you can do that. And if so, then it 
>>>> depends on whether the function is still in PCI mode (see below).
>>>> 
>>>>> It happens that on pegasos2 by default all of those are routed to IRQ9 
>>>>> except IDE
>>>> 
>>>> All *PCI* interrupts are routed to IRQ9 while IDE legacy interrupts are 
>>>> routed to the compatible ISA IRQs. Note that the IDE function must only 
>>>> trigger the ISA IRQs if it is in legacy mode while it must only trigger 
>>>> the PCI IRQ in non-legacy mode. See https://www.bswd.com/pciide.pdf for 
>>>> more details on this particular topic.
>>> 
>>> The docs say so but based on what guests that work on real hardware do it 
>>> does not work that way. Look up previous discussion on this on the list 
>>> from around the time Mark changed via-ide about 4-5 years ago. That series 
>>> was a result of his review of my proposed changes and gave resuled in an 
>>> alternative appdroach. On pegasos2 (and probably also on fuloong2e based 
>>> on same later findings, see patches to that, I can try to find these later 
>>> if you can't find them) via-ide *always* uses IRQ 14/15 and the native 
>>> mode only switches register addresses from legacy io ports to PCI io space 
>>> so you can set it in with BAR regs but the IRQs don't change despite what 
>>> the docs say. There are some hacks in Linux kernel and other guests to 
>>> account for this but the comments for the reason are wrong in Linux, they 
>>> say IDE is always in legacy mode but in fact if has a half-native mode 
>>> which is what I called it where io addresses are set with BARs but IRQs 
>>> are still the legacy ISA ones. You can find some references in previous 
>>> discussion. Probably searching for via-ide half-native mode might find it.
>>> 
>>>>> but what if a guest changes ac97 to use a different interrupt? Then it's 
>>>>> not a PCI interrupt any more so you can't use pci_set_irq in via=ac97.
>>>> 
>>>> How would it do that? AFAICS there is no dedicated register to configure 
>>>> which IRQ to use. This means that it can only trigger an interrupt via 
>>>> its PCI intx pin which is subject to the PCI -> ISA IRQ router.
>>> 
>>> The VIA functions can use their PCI_INTERRUPT_LINE (0x3c) registers to set 
>>> their ISA IRQ according to the docs (and unlike IDE in other functions 
>>> like USB and sound this probably also works) and the PIRQA-D pins can be 
>>> mapped to ISA IRQs by the 0x55-0x57 config registers of the isa bridge 
>>> (function0). This is what I implemented in via_isa_set_irq() in this 
>>> series.
>>> 
>>>>> There are only 4 PCI INT lines but the VIA components can be routed to 
>>>>> 13 or 14 ISA IRQs.
>>>> 
>>>> Pure PCI components are only able to trigger one of the four PCI intx 
>>>> pins they are *hardwired* to.
>>> 
>>> This is true for PCI cards which can only use the 4 pins the slot they are 
>>> in is wired to. These come in through the PIRQA-D pins and they are routed 
>>> with the funstion 0 0x55-0x57 config registers. But I'm not sure about the 
>>> internal functions.
>>> 
>>>> Each component has only one pin. Which ISA IRQ gets triggered through 
>>>> that pin can be selected from 13 or 14 ISA IRQs as you say by means of 
>>>> the three configuration registers of the PCI -> ISA IRQ router.
>>> 
>>> So you say that internal functions are also wired to the same 4 lines like 
>>> normal PCI cards?
>> 
>> Yes.
>> 
>>> Then how can you route them to different interrupts setting their config 
>>> reg 0x3c independent of function0 0x55-0x57 regs?
>> 
>> 0x3c isn't supposed to be interpretet by hardware, and in general hardware 
>> can't: 0x3c is standardized for every PCI function which includes 
>> standalone PCI devices in particular. Standalone PCI devices don't have 
>> access to an IRQ router. So if they don't, how could they possibly 
>> configure the IRQ they are triggering?
>> 
>> 0x3c is only information to the OS (populated by the BIOS). It merily 
>> indicates that the PCI device needs attention when the IRQ configured in 
>> 0x3c is raised. See comment 4 in 
>> https://community.osr.com/discussion/30399/read-only-pci-interrupt-line-register 
>> for another explanation.
>> 
>> Even though the south bridge contains an interrupt router doesn't mean that 
>> its PCI functions can configure their IRQ through their 0x3c registers. 
>> That would change the semantics of standardized PCI registers which is 
>> surely not permitted by the standard. Instead, the PCI IRQs are configured 
>> through the device-specific 0x55-0x57 regs.
>> 
>> I see that 0x3c is also used for the USB functions. They used to trigger 
>> the raw ISA IRQs before your series which seems wrong. I think 0x3c usage 
>> needs to be cleaned up in the VIA model. Otherwise this will likely cause 
>> problems elsewhere.
>> 
>>> 
>>>>> How do you keep track of that with only the PCI bus interrupts?
>>>> 
>>>> Devices that operate in ISA mode such as the IDE function shall have 
>>>> their own, dedicated ISA IRQs assigned by the guest. Otherwise this 
>>>> causes a classic interrupt conflict, just like in the olden ISA days. If 
>>>> the function operates in PCI mode, it must not trigger the ISA IRQs, 
>>>> regardless of whether they are assigned or not.
>>> 
>>> This does not match with guests which clearly expect to get ISA IRQ9 for 
>>> PCI cards and USB and sound which is where these are routed within the VIA 
>>> bridge as the firmware programs it.
>> 
>> What I meant was that a component able to operate in native/legacy/mixed 
>> mode such as IDE must not use both PCI and legacy ISA interrupts at the 
>> same time. Multiple PCI functions may of course share interrupts.
>> 
>>> 
>>>> There is also the power management function whose ACPI interrupt (SCI) 
>>>> can be routed by means of a dedicated register. Again, a guest must make 
>>>> sure here to not configure interrupt conflicts.
>>>> 
>>>>> I don't get your approach.
>>>> 
>>>> I hope that I could help you get a better understanding. The linked .pdf 
>>>> is good and comprehensive reading material.
>>> 
>>> I'm not sure the via-ide confirms to that doc but it's also not any more a 
>>> problem with via-ide now. That was discussed to death back then and 
>>> "fixed" to work for the cases we want it to work with. We probably never 
>>> agreed on how this really works but at least what we ended up with works 
>>> with guests that run on real hardware. I'm OK with also making these cases 
>>> work that we want now such as network and sound card under AmigaOS and 
>>> sound under MorphOS (as long as you don't use USB) on pegasos2. This 
>>> series does that so unless it breaks something that worked before I 
>>> condider this moving forward and we can always improve adn fix it later. 
>>> I'm not saying I'm not interested in your improvements just that let's 
>>> that not hold this back now as we can fix and improve it later but 
>>> otherwise users will have to wait until September to be able to use it. I 
>>> know a few who want this and getting this out as it is would allow more 
>>> people to test it and report problems so unless there are clearly wrong 
>>> parts I'm OK with less than perfect but working solution as long as it's 
>>> not too messy.
>> 
>> Patch 1 really seems like duplicating PCI code that already exists in QEMU. 
>> This is not needed and we should avoid that.
>> 
>> Moreover, usage of the IRQ line register (0x3c) for interrupt routing 
>> should be switched to using the 0x55-0x57 regs to be PCI compliant.
>> 
>> Thanks to your great work to make via-ac97 work we can confirm that both 
>> IRQ routing implementations basically work for now. Let's work out a 
>> solution that relies on existing code, sticks to the standard and hopefully 
>> works for i386 and MIPS, too.
>
> FWIW this analysis seems correct to me based upon my experience with older 
> PCs and reading the various specifications.

Have you read the VT82C686B and VT8231 spces which this is about? Other 
specs may not apply to these chips, they should confirm to their own docs. 
(But sometimes they may even fail to do that like in case of the IDE part.)

Regards,
BALATON Zoltan


^ permalink raw reply	[flat|nested] 40+ messages in thread

* Re: [PATCH 0/5] Pegasos2 fixes and audio output support
  2023-03-01 19:24                   ` BALATON Zoltan
@ 2023-03-01 20:53                     ` Bernhard Beschow
  2023-03-01 21:05                       ` BALATON Zoltan
  0 siblings, 1 reply; 40+ messages in thread
From: Bernhard Beschow @ 2023-03-01 20:53 UTC (permalink / raw)
  To: BALATON Zoltan, Mark Cave-Ayland
  Cc: qemu-devel, qemu-ppc, Gerd Hoffmann, Daniel Henrique Barboza, philmd



Am 1. März 2023 19:24:20 UTC schrieb BALATON Zoltan <balaton@eik.bme.hu>:
>On Wed, 1 Mar 2023, Mark Cave-Ayland wrote:
>> On 23/02/2023 09:13, Bernhard Beschow wrote:
>>> Am 22. Februar 2023 23:00:02 UTC schrieb BALATON Zoltan <balaton@eik.bme.hu>:
>>>> On Wed, 22 Feb 2023, Bernhard Beschow wrote:
>>>>> Am 22. Februar 2023 21:12:01 UTC schrieb BALATON Zoltan <balaton@eik.bme.hu>:
>>>>>> On Wed, 22 Feb 2023, Bernhard Beschow wrote:
>>>>>>> Am 22. Februar 2023 19:25:16 UTC schrieb BALATON Zoltan <balaton@eik.bme.hu>:
>>>>>>>> On Wed, 22 Feb 2023, Bernhard Beschow wrote:
>>>>>>>>> On Wed, Feb 22, 2023 at 4:38 PM Bernhard Beschow <shentey@gmail.com> wrote:
>>>>>>>>>> I've had a closer look at your series and I think it can be simplified:
>>>>>>>>>> Patch 2 can be implemented quite straight-forward like I proposed in a
>>>>>>>>>> private mail: https://github.com/shentok/qemu/commit/via-priq-routing.
>>>>>>>>>> Then, in order to make patch 3 "hw/ppc/pegasos2: Fix PCI interrupt routing"
>>>>>>>>>> working, one can expose the PCI interrupts with a single line like you do
>>>>>>>>>> in patch 2. With this, patch 1 "hw/isa/vt82c686: Implement interrupt
>>>>>>>>>> routing in via_isa_set_irq" isn't needed any longer and can be omitted.
>>>>>>>>>> 
>>>>>>>>>> In via-ac97, rather than using via_isa_set_irq(), pci_set_irq() can be
>>>>>>>>>> used instead. pci_set_irq() internally takes care of all the ISA interrupt
>>>>>>>>>> level tracking patch 1 attempted to address.
>>>>>>>>>> 
>>>>>>>>> 
>>>>>>>>> Here is a proof of concept branch to demonstrate that the simplification
>>>>>>>>> actually works: https://github.com/shentok/qemu/commits/pegasos2 (Tested
>>>>>>>>> with MorphOS with and without pegasos2.rom).
>>>>>>>> 
>>>>>>>> Does this only work because both the via-ac97 and the PCI interrupts are mapped to the same ISA IRQ and you've only tested sound? The guest could configure each device to use a different IRQ, also mapping them so they share one ISA interrupt. What happens if multiple devices are mapped to IRQ 9 (which is the case on pegasos2 where PCI cards, ac97 and USB all share this IRQ) and more than one such device wants to raise an interrupt at the same time? If you ack the ac97 interrupt but a PCI network card or the USB part still wants to get the CPUs attention the ISA IRQ should remain raised until all devices are serviced.
>>>>>>> 
>>>>>>> pci_bus_get_irq_level(), used in via_isa_set_pci_irq(), should handle
>>>>>>> exactly that case very well.
>>>>>>> 
>>>>>>>> I don't see a way to track the status of all devices in a single qemu_irq which can only be up or down so we need something to store the state of each source.
>>>>>>> 
>>>>>>> pci_set_irq() causes pci_bus_change_irq_level() to be called.
>>>>>>> pci_bus_change_irq_level() tracks the sum of all irq levels of all
>>>>>>> devices attached to a particular pin in irq_count. Have a look at
>>>>>>> pci_bus_change_irq_level() and you will understand better.
>>>>>> 
>>>>>> I'm aware of that, we're using that in sam460ex which connects all PCI interrupt lines to a single IRQ and Peter explored and explained it in a comment there when that was discovered. First we had a patch with or-irq but due to this behaviot that's not needed for PCI interrupts. But the VT8132 could change what ISA IRQ you route the sub functions to.
>>>>> 
>>>>> That depends on the sub function if you can do that. And if so, then it depends on whether the function is still in PCI mode (see below).
>>>>> 
>>>>>> It happens that on pegasos2 by default all of those are routed to IRQ9 except IDE
>>>>> 
>>>>> All *PCI* interrupts are routed to IRQ9 while IDE legacy interrupts are routed to the compatible ISA IRQs. Note that the IDE function must only trigger the ISA IRQs if it is in legacy mode while it must only trigger the PCI IRQ in non-legacy mode. See https://www.bswd.com/pciide.pdf for more details on this particular topic.
>>>> 
>>>> The docs say so but based on what guests that work on real hardware do it does not work that way. Look up previous discussion on this on the list from around the time Mark changed via-ide about 4-5 years ago. That series was a result of his review of my proposed changes and gave resuled in an alternative appdroach. On pegasos2 (and probably also on fuloong2e based on same later findings, see patches to that, I can try to find these later if you can't find them) via-ide *always* uses IRQ 14/15 and the native mode only switches register addresses from legacy io ports to PCI io space so you can set it in with BAR regs but the IRQs don't change despite what the docs say. There are some hacks in Linux kernel and other guests to account for this but the comments for the reason are wrong in Linux, they say IDE is always in legacy mode but in fact if has a half-native mode which is what I called it where io addresses are set with BARs but IRQs are still the legacy ISA ones. You can find some references in previous discussion. Probably searching for via-ide half-native mode might find it.
>>>> 
>>>>>> but what if a guest changes ac97 to use a different interrupt? Then it's not a PCI interrupt any more so you can't use pci_set_irq in via=ac97.
>>>>> 
>>>>> How would it do that? AFAICS there is no dedicated register to configure which IRQ to use. This means that it can only trigger an interrupt via its PCI intx pin which is subject to the PCI -> ISA IRQ router.
>>>> 
>>>> The VIA functions can use their PCI_INTERRUPT_LINE (0x3c) registers to set their ISA IRQ according to the docs (and unlike IDE in other functions like USB and sound this probably also works) and the PIRQA-D pins can be mapped to ISA IRQs by the 0x55-0x57 config registers of the isa bridge (function0). This is what I implemented in via_isa_set_irq() in this series.
>>>> 
>>>>>> There are only 4 PCI INT lines but the VIA components can be routed to 13 or 14 ISA IRQs.
>>>>> 
>>>>> Pure PCI components are only able to trigger one of the four PCI intx pins they are *hardwired* to.
>>>> 
>>>> This is true for PCI cards which can only use the 4 pins the slot they are in is wired to. These come in through the PIRQA-D pins and they are routed with the funstion 0 0x55-0x57 config registers. But I'm not sure about the internal functions.
>>>> 
>>>>> Each component has only one pin. Which ISA IRQ gets triggered through that pin can be selected from 13 or 14 ISA IRQs as you say by means of the three configuration registers of the PCI -> ISA IRQ router.
>>>> 
>>>> So you say that internal functions are also wired to the same 4 lines like normal PCI cards?
>>> 
>>> Yes.
>>> 
>>>> Then how can you route them to different interrupts setting their config reg 0x3c independent of function0 0x55-0x57 regs?
>>> 
>>> 0x3c isn't supposed to be interpretet by hardware, and in general hardware can't: 0x3c is standardized for every PCI function which includes standalone PCI devices in particular. Standalone PCI devices don't have access to an IRQ router. So if they don't, how could they possibly configure the IRQ they are triggering?
>>> 
>>> 0x3c is only information to the OS (populated by the BIOS). It merily indicates that the PCI device needs attention when the IRQ configured in 0x3c is raised. See comment 4 in https://community.osr.com/discussion/30399/read-only-pci-interrupt-line-register for another explanation.
>>> 
>>> Even though the south bridge contains an interrupt router doesn't mean that its PCI functions can configure their IRQ through their 0x3c registers. That would change the semantics of standardized PCI registers which is surely not permitted by the standard. Instead, the PCI IRQs are configured through the device-specific 0x55-0x57 regs.
>>> 
>>> I see that 0x3c is also used for the USB functions. They used to trigger the raw ISA IRQs before your series which seems wrong. I think 0x3c usage needs to be cleaned up in the VIA model. Otherwise this will likely cause problems elsewhere.
>>> 
>>>> 
>>>>>> How do you keep track of that with only the PCI bus interrupts?
>>>>> 
>>>>> Devices that operate in ISA mode such as the IDE function shall have their own, dedicated ISA IRQs assigned by the guest. Otherwise this causes a classic interrupt conflict, just like in the olden ISA days. If the function operates in PCI mode, it must not trigger the ISA IRQs, regardless of whether they are assigned or not.
>>>> 
>>>> This does not match with guests which clearly expect to get ISA IRQ9 for PCI cards and USB and sound which is where these are routed within the VIA bridge as the firmware programs it.
>>> 
>>> What I meant was that a component able to operate in native/legacy/mixed mode such as IDE must not use both PCI and legacy ISA interrupts at the same time. Multiple PCI functions may of course share interrupts.
>>> 
>>>> 
>>>>> There is also the power management function whose ACPI interrupt (SCI) can be routed by means of a dedicated register. Again, a guest must make sure here to not configure interrupt conflicts.
>>>>> 
>>>>>> I don't get your approach.
>>>>> 
>>>>> I hope that I could help you get a better understanding. The linked .pdf is good and comprehensive reading material.
>>>> 
>>>> I'm not sure the via-ide confirms to that doc but it's also not any more a problem with via-ide now. That was discussed to death back then and "fixed" to work for the cases we want it to work with. We probably never agreed on how this really works but at least what we ended up with works with guests that run on real hardware. I'm OK with also making these cases work that we want now such as network and sound card under AmigaOS and sound under MorphOS (as long as you don't use USB) on pegasos2. This series does that so unless it breaks something that worked before I condider this moving forward and we can always improve adn fix it later. I'm not saying I'm not interested in your improvements just that let's that not hold this back now as we can fix and improve it later but otherwise users will have to wait until September to be able to use it. I know a few who want this and getting this out as it is would allow more people to test it and report problems so unless there are clearly wrong parts I'm OK with less than perfect but working solution as long as it's not too messy.
>>> 
>>> Patch 1 really seems like duplicating PCI code that already exists in QEMU. This is not needed and we should avoid that.
>>> 
>>> Moreover, usage of the IRQ line register (0x3c) for interrupt routing should be switched to using the 0x55-0x57 regs to be PCI compliant.
>>> 
>>> Thanks to your great work to make via-ac97 work we can confirm that both IRQ routing implementations basically work for now. Let's work out a solution that relies on existing code, sticks to the standard and hopefully works for i386 and MIPS, too.
>> 
>> FWIW this analysis seems correct to me based upon my experience with older PCs and reading the various specifications.
>
>Have you read the VT82C686B and VT8231 spces which this is about?

Yes, I did.

For the USB function it specifies the interrupt line register (offset 0x3c) as follows:

  7-4 Reserved........................................always reads 0
  3-0 USB Interrupt Routing........................default = 16h

However, 0x16 doesn't fit into four bits. Not even 16 (decimal) would fit because the biggest representable value is 15, i.e. 0xf.

This makes me wonder if the datasheet is a reliable source describing these regiserts in the first place.

Best regards,
Bernhard

> Other specs may not apply to these chips, they should confirm to their own docs. (But sometimes they may even fail to do that like in case of the IDE part.)
>
>Regards,
>BALATON Zoltan


^ permalink raw reply	[flat|nested] 40+ messages in thread

* Re: [PATCH 0/5] Pegasos2 fixes and audio output support
  2023-03-01 20:53                     ` Bernhard Beschow
@ 2023-03-01 21:05                       ` BALATON Zoltan
  0 siblings, 0 replies; 40+ messages in thread
From: BALATON Zoltan @ 2023-03-01 21:05 UTC (permalink / raw)
  To: Bernhard Beschow
  Cc: Mark Cave-Ayland, qemu-devel, qemu-ppc, Gerd Hoffmann,
	Daniel Henrique Barboza, philmd

[-- Attachment #1: Type: text/plain, Size: 12215 bytes --]

On Wed, 1 Mar 2023, Bernhard Beschow wrote:
> Am 1. März 2023 19:24:20 UTC schrieb BALATON Zoltan <balaton@eik.bme.hu>:
>> On Wed, 1 Mar 2023, Mark Cave-Ayland wrote:
>>> On 23/02/2023 09:13, Bernhard Beschow wrote:
>>>> Am 22. Februar 2023 23:00:02 UTC schrieb BALATON Zoltan <balaton@eik.bme.hu>:
>>>>> On Wed, 22 Feb 2023, Bernhard Beschow wrote:
>>>>>> Am 22. Februar 2023 21:12:01 UTC schrieb BALATON Zoltan <balaton@eik.bme.hu>:
>>>>>>> On Wed, 22 Feb 2023, Bernhard Beschow wrote:
>>>>>>>> Am 22. Februar 2023 19:25:16 UTC schrieb BALATON Zoltan <balaton@eik.bme.hu>:
>>>>>>>>> On Wed, 22 Feb 2023, Bernhard Beschow wrote:
>>>>>>>>>> On Wed, Feb 22, 2023 at 4:38 PM Bernhard Beschow <shentey@gmail.com> wrote:
>>>>>>>>>>> I've had a closer look at your series and I think it can be simplified:
>>>>>>>>>>> Patch 2 can be implemented quite straight-forward like I proposed in a
>>>>>>>>>>> private mail: https://github.com/shentok/qemu/commit/via-priq-routing.
>>>>>>>>>>> Then, in order to make patch 3 "hw/ppc/pegasos2: Fix PCI interrupt routing"
>>>>>>>>>>> working, one can expose the PCI interrupts with a single line like you do
>>>>>>>>>>> in patch 2. With this, patch 1 "hw/isa/vt82c686: Implement interrupt
>>>>>>>>>>> routing in via_isa_set_irq" isn't needed any longer and can be omitted.
>>>>>>>>>>>
>>>>>>>>>>> In via-ac97, rather than using via_isa_set_irq(), pci_set_irq() can be
>>>>>>>>>>> used instead. pci_set_irq() internally takes care of all the ISA interrupt
>>>>>>>>>>> level tracking patch 1 attempted to address.
>>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> Here is a proof of concept branch to demonstrate that the simplification
>>>>>>>>>> actually works: https://github.com/shentok/qemu/commits/pegasos2 (Tested
>>>>>>>>>> with MorphOS with and without pegasos2.rom).
>>>>>>>>>
>>>>>>>>> Does this only work because both the via-ac97 and the PCI interrupts are mapped to the same ISA IRQ and you've only tested sound? The guest could configure each device to use a different IRQ, also mapping them so they share one ISA interrupt. What happens if multiple devices are mapped to IRQ 9 (which is the case on pegasos2 where PCI cards, ac97 and USB all share this IRQ) and more than one such device wants to raise an interrupt at the same time? If you ack the ac97 interrupt but a PCI network card or the USB part still wants to get the CPUs attention the ISA IRQ should remain raised until all devices are serviced.
>>>>>>>>
>>>>>>>> pci_bus_get_irq_level(), used in via_isa_set_pci_irq(), should handle
>>>>>>>> exactly that case very well.
>>>>>>>>
>>>>>>>>> I don't see a way to track the status of all devices in a single qemu_irq which can only be up or down so we need something to store the state of each source.
>>>>>>>>
>>>>>>>> pci_set_irq() causes pci_bus_change_irq_level() to be called.
>>>>>>>> pci_bus_change_irq_level() tracks the sum of all irq levels of all
>>>>>>>> devices attached to a particular pin in irq_count. Have a look at
>>>>>>>> pci_bus_change_irq_level() and you will understand better.
>>>>>>>
>>>>>>> I'm aware of that, we're using that in sam460ex which connects all PCI interrupt lines to a single IRQ and Peter explored and explained it in a comment there when that was discovered. First we had a patch with or-irq but due to this behaviot that's not needed for PCI interrupts. But the VT8132 could change what ISA IRQ you route the sub functions to.
>>>>>>
>>>>>> That depends on the sub function if you can do that. And if so, then it depends on whether the function is still in PCI mode (see below).
>>>>>>
>>>>>>> It happens that on pegasos2 by default all of those are routed to IRQ9 except IDE
>>>>>>
>>>>>> All *PCI* interrupts are routed to IRQ9 while IDE legacy interrupts are routed to the compatible ISA IRQs. Note that the IDE function must only trigger the ISA IRQs if it is in legacy mode while it must only trigger the PCI IRQ in non-legacy mode. See https://www.bswd.com/pciide.pdf for more details on this particular topic.
>>>>>
>>>>> The docs say so but based on what guests that work on real hardware do it does not work that way. Look up previous discussion on this on the list from around the time Mark changed via-ide about 4-5 years ago. That series was a result of his review of my proposed changes and gave resuled in an alternative appdroach. On pegasos2 (and probably also on fuloong2e based on same later findings, see patches to that, I can try to find these later if you can't find them) via-ide *always* uses IRQ 14/15 and the native mode only switches register addresses from legacy io ports to PCI io space so you can set it in with BAR regs but the IRQs don't change despite what the docs say. There are some hacks in Linux kernel and other guests to account for this but the comments for the reason are wrong in Linux, they say IDE is always in legacy mode but in fact if has a half-native mode which is what I called it where io addresses are set with BARs but IRQs are still the legacy ISA ones. You can fin
 d some references in previous discussion. Probably searching for via-ide half-native mode might find it.
>>>>>
>>>>>>> but what if a guest changes ac97 to use a different interrupt? Then it's not a PCI interrupt any more so you can't use pci_set_irq in via=ac97.
>>>>>>
>>>>>> How would it do that? AFAICS there is no dedicated register to configure which IRQ to use. This means that it can only trigger an interrupt via its PCI intx pin which is subject to the PCI -> ISA IRQ router.
>>>>>
>>>>> The VIA functions can use their PCI_INTERRUPT_LINE (0x3c) registers to set their ISA IRQ according to the docs (and unlike IDE in other functions like USB and sound this probably also works) and the PIRQA-D pins can be mapped to ISA IRQs by the 0x55-0x57 config registers of the isa bridge (function0). This is what I implemented in via_isa_set_irq() in this series.
>>>>>
>>>>>>> There are only 4 PCI INT lines but the VIA components can be routed to 13 or 14 ISA IRQs.
>>>>>>
>>>>>> Pure PCI components are only able to trigger one of the four PCI intx pins they are *hardwired* to.
>>>>>
>>>>> This is true for PCI cards which can only use the 4 pins the slot they are in is wired to. These come in through the PIRQA-D pins and they are routed with the funstion 0 0x55-0x57 config registers. But I'm not sure about the internal functions.
>>>>>
>>>>>> Each component has only one pin. Which ISA IRQ gets triggered through that pin can be selected from 13 or 14 ISA IRQs as you say by means of the three configuration registers of the PCI -> ISA IRQ router.
>>>>>
>>>>> So you say that internal functions are also wired to the same 4 lines like normal PCI cards?
>>>>
>>>> Yes.
>>>>
>>>>> Then how can you route them to different interrupts setting their config reg 0x3c independent of function0 0x55-0x57 regs?
>>>>
>>>> 0x3c isn't supposed to be interpretet by hardware, and in general hardware can't: 0x3c is standardized for every PCI function which includes standalone PCI devices in particular. Standalone PCI devices don't have access to an IRQ router. So if they don't, how could they possibly configure the IRQ they are triggering?
>>>>
>>>> 0x3c is only information to the OS (populated by the BIOS). It merily indicates that the PCI device needs attention when the IRQ configured in 0x3c is raised. See comment 4 in https://community.osr.com/discussion/30399/read-only-pci-interrupt-line-register for another explanation.
>>>>
>>>> Even though the south bridge contains an interrupt router doesn't mean that its PCI functions can configure their IRQ through their 0x3c registers. That would change the semantics of standardized PCI registers which is surely not permitted by the standard. Instead, the PCI IRQs are configured through the device-specific 0x55-0x57 regs.
>>>>
>>>> I see that 0x3c is also used for the USB functions. They used to trigger the raw ISA IRQs before your series which seems wrong. I think 0x3c usage needs to be cleaned up in the VIA model. Otherwise this will likely cause problems elsewhere.
>>>>
>>>>>
>>>>>>> How do you keep track of that with only the PCI bus interrupts?
>>>>>>
>>>>>> Devices that operate in ISA mode such as the IDE function shall have their own, dedicated ISA IRQs assigned by the guest. Otherwise this causes a classic interrupt conflict, just like in the olden ISA days. If the function operates in PCI mode, it must not trigger the ISA IRQs, regardless of whether they are assigned or not.
>>>>>
>>>>> This does not match with guests which clearly expect to get ISA IRQ9 for PCI cards and USB and sound which is where these are routed within the VIA bridge as the firmware programs it.
>>>>
>>>> What I meant was that a component able to operate in native/legacy/mixed mode such as IDE must not use both PCI and legacy ISA interrupts at the same time. Multiple PCI functions may of course share interrupts.
>>>>
>>>>>
>>>>>> There is also the power management function whose ACPI interrupt (SCI) can be routed by means of a dedicated register. Again, a guest must make sure here to not configure interrupt conflicts.
>>>>>>
>>>>>>> I don't get your approach.
>>>>>>
>>>>>> I hope that I could help you get a better understanding. The linked .pdf is good and comprehensive reading material.
>>>>>
>>>>> I'm not sure the via-ide confirms to that doc but it's also not any more a problem with via-ide now. That was discussed to death back then and "fixed" to work for the cases we want it to work with. We probably never agreed on how this really works but at least what we ended up with works with guests that run on real hardware. I'm OK with also making these cases work that we want now such as network and sound card under AmigaOS and sound under MorphOS (as long as you don't use USB) on pegasos2. This series does that so unless it breaks something that worked before I condider this moving forward and we can always improve adn fix it later. I'm not saying I'm not interested in your improvements just that let's that not hold this back now as we can fix and improve it later but otherwise users will have to wait until September to be able to use it. I know a few who want this and getting this out as it is would allow more people to test it and report problems so unless there are clear
 ly wrong parts I'm OK with less than perfect but working solution as long as it's not too messy.
>>>>
>>>> Patch 1 really seems like duplicating PCI code that already exists in QEMU. This is not needed and we should avoid that.
>>>>
>>>> Moreover, usage of the IRQ line register (0x3c) for interrupt routing should be switched to using the 0x55-0x57 regs to be PCI compliant.
>>>>
>>>> Thanks to your great work to make via-ac97 work we can confirm that both IRQ routing implementations basically work for now. Let's work out a solution that relies on existing code, sticks to the standard and hopefully works for i386 and MIPS, too.
>>>
>>> FWIW this analysis seems correct to me based upon my experience with older PCs and reading the various specifications.
>>
>> Have you read the VT82C686B and VT8231 spces which this is about?
>
> Yes, I did.
>
> For the USB function it specifies the interrupt line register (offset 0x3c) as follows:
>
>  7-4 Reserved........................................always reads 0
>  3-0 USB Interrupt Routing........................default = 16h
>
> However, 0x16 doesn't fit into four bits. Not even 16 (decimal) would fit because the biggest representable value is 15, i.e. 0xf.
>
> This makes me wonder if the datasheet is a reliable source describing these regiserts in the first place.

It may clearly have errors but maybe still more likely to describe the 
actual chip than a PCI standard which may not even existed yet at the time 
this chip was produced. This is a part from the 90's I think when PCI was 
pretty new. Also firmware and guests appear to work the way the datasheet 
describes (except IDE which seems to have its IRQs tied to ISA ones 
irrespective or 0x3c reg (but there's some other reg in ISA func along PnP 
IRQ regs that also talks about IDE so that may also have something to do 
with it). But since it works now I'm less courious to find out what's 
behind it.

Regards,
BALATON Zoltan

^ permalink raw reply	[flat|nested] 40+ messages in thread

end of thread, other threads:[~2023-03-01 21:06 UTC | newest]

Thread overview: 40+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-02-21 18:44 [PATCH 0/5] Pegasos2 fixes and audio output support BALATON Zoltan
2023-02-21 18:44 ` [PATCH 1/5] hw/isa/vt82c686: Implement interrupt routing in via_isa_set_irq BALATON Zoltan
2023-02-21 18:44 ` [PATCH 2/5] hw/isa/vt82c686: Implement PIRQ pins BALATON Zoltan
2023-02-21 18:44 ` [PATCH 3/5] hw/ppc/pegasos2: Fix PCI interrupt routing BALATON Zoltan
2023-02-24 17:04   ` Daniel Henrique Barboza
2023-02-25 19:34   ` Philippe Mathieu-Daudé
2023-02-25 20:19     ` BALATON Zoltan
2023-02-26 22:22     ` BALATON Zoltan
2023-02-21 18:44 ` [PATCH 4/5] hw/audio/ac97: Split off some definitions to a header BALATON Zoltan
2023-02-25 19:35   ` Philippe Mathieu-Daudé
2023-02-26 22:17     ` BALATON Zoltan
2023-02-21 18:44 ` [PATCH 5/5] hw/audio/via-ac97: Basic implementation of audio playback BALATON Zoltan
2023-02-23 19:40   ` Volker Rümelin
2023-02-24  9:53     ` Bernhard Beschow
2023-02-24 12:26       ` BALATON Zoltan
2023-02-24 13:05       ` BALATON Zoltan
2023-02-24 17:14         ` Daniel Henrique Barboza
2023-02-24 21:08           ` BALATON Zoltan
2023-02-25  8:58             ` Daniel Henrique Barboza
2023-02-22 15:38 ` [PATCH 0/5] Pegasos2 fixes and audio output support Bernhard Beschow
2023-02-22 18:56   ` Bernhard Beschow
2023-02-22 19:25     ` BALATON Zoltan
2023-02-22 20:59       ` Bernhard Beschow
2023-02-22 21:12         ` BALATON Zoltan
2023-02-22 22:20           ` Bernhard Beschow
2023-02-22 23:00             ` BALATON Zoltan
2023-02-23  9:13               ` Bernhard Beschow
2023-02-23 12:33                 ` BALATON Zoltan
2023-02-23 13:17                   ` Bernhard Beschow
2023-02-23 14:23                     ` BALATON Zoltan
2023-02-23 20:28                       ` Bernhard Beschow
2023-03-01 13:49                 ` Mark Cave-Ayland
2023-03-01 19:24                   ` BALATON Zoltan
2023-03-01 20:53                     ` Bernhard Beschow
2023-03-01 21:05                       ` BALATON Zoltan
2023-03-01 13:42           ` Mark Cave-Ayland
2023-03-01 19:21             ` BALATON Zoltan
2023-02-22 22:23         ` BALATON Zoltan
2023-02-23  0:43           ` BALATON Zoltan
2023-03-01 13:47             ` Mark Cave-Ayland

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.