All of lore.kernel.org
 help / color / mirror / Atom feed
From: Helge Deller <deller@kernel.org>
To: qemu-devel@nongnu.org
Cc: Richard Henderson <richard.henderson@linaro.org>,
	Paolo Bonzini <pbonzini@redhat.com>,
	"Michael S. Tsirkin" <mst@redhat.com>,
	qemu-block@nongnu.org, John Snow <jsnow@redhat.com>,
	Helge Deller <deller@gmx.de>, "Denis V. Lunev" <den@openvz.org>,
	Abizer Lokhandwala <abizerlokhandwalastd10@gmail.com>
Subject: [PULL 2/7] hw/isa/pc87560: Add main isa code for NS 87560 SuperIO chip
Date: Fri, 18 Sep 2026 18:38:23 +0200	[thread overview]
Message-ID: <20260918163829.2917-3-deller@kernel.org> (raw)
In-Reply-To: <20260918163829.2917-1-deller@kernel.org>

From: Abizer Lokhandwala <abizerlokhandwalastd10@gmail.com>

Add emulation of the core components (PCI function 1 aka I/O
Peripherals) of the National Semiconductor SuperIO chip which was
commonly used in HP PA-RISC B- and C-class workstations. This includes
the PIC interrupt controller, the floppy controller, serial and parallel
ports.

Signed-off-by: Abizer Lokhandwala <abizerlokhandwalastd10@gmail.com>
Signed-off-by: Helge Deller <deller@gmx.de>
---
 MAINTAINERS              |   2 +
 hw/isa/Kconfig           |  11 +
 hw/isa/pc87560.c         | 510 +++++++++++++++++++++++++++++++++++++++
 include/hw/isa/pc87560.h |  96 ++++++++
 4 files changed, 619 insertions(+)
 create mode 100644 hw/isa/pc87560.c
 create mode 100644 include/hw/isa/pc87560.h

diff --git a/MAINTAINERS b/MAINTAINERS
index e9b68c51f1..e3b1e80ad6 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -1355,6 +1355,8 @@ F: include/hw/pci-host/dino.h
 F: pc-bios/hppa-firmware.img
 F: roms/seabios-hppa/
 F: tests/functional/hppa/
+F: hw/isa/pc87560.c
+F: include/hw/isa/pc87560.h
 
 Hexagon Machines
 ----------------
diff --git a/hw/isa/Kconfig b/hw/isa/Kconfig
index 73c6470805..23d327e88c 100644
--- a/hw/isa/Kconfig
+++ b/hw/isa/Kconfig
@@ -67,6 +67,17 @@ config SMC37C669
     bool
     select ISA_SUPERIO
 
+config PC87560
+    bool
+    default y if PCI_DEVICES
+    depends on PCI
+    depends on HPPA
+    select ISA_BUS
+    select FDC_ISA
+    select SERIAL_ISA
+    select IDE_PCI
+    select USB_OHCI
+
 config LPC_ICH9
     bool
     # For historical reasons, SuperIO devices are created in the board
diff --git a/hw/isa/pc87560.c b/hw/isa/pc87560.c
new file mode 100644
index 0000000000..c13c54deb2
--- /dev/null
+++ b/hw/isa/pc87560.c
@@ -0,0 +1,510 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * NS PC87560 SuperI/O — ISA emulation
+ *
+ * Copyright (c) 2026 Abizer abizerlokhandwalastd10@gmail.com
+ */
+#include "qemu/osdep.h"
+#include "hw/pci/pci.h"
+#include "hw/pci/pci_device.h"
+#include "qapi/error.h"
+#include "qemu/log.h"
+#include "migration/vmstate.h"
+#include "qemu/module.h"
+#include "hw/core/irq.h"
+#include "hw/core/qdev-properties.h"
+#include "hw/core/qdev-properties-system.h"
+#include "hw/char/serial.h"
+#include "hw/char/parallel.h"
+#include "hw/block/fdc-internal.h"
+#include "hw/isa/pc87560.h"
+
+static uint64_t pc87560_pp_read(void *opaque, hwaddr addr, unsigned size)
+{
+    ParallelState *s = opaque;
+    switch (addr) {
+    case 0: return s->datar;
+    case 1: return s->status;
+    case 2: return s->control;
+    default:
+        qemu_log_mask(LOG_UNIMP,
+                      "pc87560-pp: read  offset 0x%" HWADDR_PRIx "\n", addr);
+        return 0xFF;
+    }
+}
+
+static int pic_highest_priority(int priority_base, uint8_t mask)
+{
+    int i;
+    for (i = 1; i <= 8; i++) {
+        int irq = (priority_base + i) & 7;
+        if (mask & (1 << irq)) {
+            return irq;
+        }
+    }
+    return -1;
+}
+
+static void pic_update_irq(PC87560SuperioState *s)
+{
+    int base = s->pic.priority_base;
+    int first_irr = pic_highest_priority(base, s->pic.irr & ~s->pic.imr);
+    int first_isr = pic_highest_priority(base, s->pic.isr);
+    int pending = 0;
+
+    if (first_irr != -1) {
+        if (first_isr == -1) {
+            pending = 1;
+        } else if (first_irr != first_isr) {
+            int irr_lvl = (first_irr - s->pic.priority_base - 1) & 7;
+            int isr_lvl = (first_isr - s->pic.priority_base - 1) & 7;
+            if (irr_lvl < isr_lvl) {
+                pending = 1;
+            }
+        }
+    }
+
+    if (pending != s->pic.irq_level) {
+        s->pic.irq_level = pending;
+        qemu_set_irq(s->parent_irq, pending);
+    }
+}
+
+static uint64_t pic1_read(void *opaque, hwaddr addr, unsigned size)
+{
+    PC87560SuperioState *s = opaque;
+    if (addr == 0) {
+        if (s->pic.poll_mode) {
+            s->pic.poll_mode = false;
+            uint8_t pending_mask = s->pic.irr & ~s->pic.imr;
+            int irq = pic_highest_priority(s->pic.priority_base, pending_mask);
+            if (irq == -1) {
+                pic_update_irq(s);
+                return 0x00;
+            }
+            s->pic.isr |= (1 << irq);
+            pic_update_irq(s);
+            return 0x80 | irq;
+        }
+        return s->pic.read_isr ? s->pic.isr : s->pic.irr;
+    }
+    return s->pic.imr;
+}
+
+static void pic1_write(void *opaque, hwaddr addr, uint64_t val, unsigned size)
+{
+    PC87560SuperioState *s = opaque;
+    uint8_t v = (uint8_t)val;
+
+    if (addr == 1) {
+        if (s->pic.init_phase > 0) {
+            if (s->pic.init_phase == 3) {
+                s->pic.init_phase = 0;
+            } else {
+                s->pic.init_phase++;
+            }
+        } else {
+            s->pic.imr = v;
+            pic_update_irq(s);
+        }
+        return;
+    }
+
+    if (v & 0x10) {
+        s->pic.init_phase = 1;
+        s->pic.imr = 0xFF;
+        s->pic.irr = 0;
+        s->pic.isr = 0;
+        s->pic.poll_mode = false;
+        s->pic.priority_base = 7;
+    } else if (v & 0x08) {
+        if (v & 0x04) {
+            s->pic.poll_mode = true;
+        }
+        if (v & 0x02) {
+            s->pic.read_isr = (v & 0x01);
+        }
+    } else {
+        uint8_t cmd = (v >> 5) & 0x07;
+        uint8_t irq = v & 0x07;
+        switch (cmd) {
+        case 1:
+        case 5: {
+            int serviced = pic_highest_priority(s->pic.priority_base,
+                                                 s->pic.isr);
+            if (serviced != -1) {
+                s->pic.isr &= ~(1 << serviced);
+                if (cmd == 5) {
+                    s->pic.priority_base = serviced;
+                }
+            }
+            break;
+        }
+        case 3:
+        case 7:
+            s->pic.isr &= ~(1 << irq);
+            if (cmd == 7) {
+                s->pic.priority_base = irq;
+            }
+            break;
+        case 6:
+            s->pic.priority_base = irq;
+            break;
+        }
+        pic_update_irq(s);
+    }
+}
+
+static const MemoryRegionOps pc87560_pic1_ops = {
+    .read  = pic1_read,
+    .write = pic1_write,
+    .endianness = DEVICE_LITTLE_ENDIAN,
+    .valid.min_access_size = 1,
+    .valid.max_access_size = 1,
+};
+
+static void pc87560_pic_irq_in(void *opaque, int irq_n, int level)
+{
+    PC87560SuperioState *s = opaque;
+    if (level) {
+        s->pic.irr |=  (1 << irq_n);
+    } else {
+        s->pic.irr &= ~(1 << irq_n);
+    }
+    pic_update_irq(s);
+}
+
+
+static void pc87560_pp_write(void *opaque, hwaddr addr, uint64_t val,
+                             unsigned size)
+{
+    ParallelState *s = opaque;
+    switch (addr) {
+    case 0:
+        s->dataw = (uint8_t)val;
+        if (qemu_chr_fe_backend_connected(&s->chr)) {
+            unsigned char ch = (uint8_t)val;
+            qemu_chr_fe_write_all(&s->chr, &ch, 1);
+        }
+        break;
+    case 2:
+        s->control = (uint8_t)(val & 0x1F);
+        if (!(s->control & 0x10)) {
+            qemu_irq_lower(s->irq);
+        }
+        break;
+    default:
+        qemu_log_mask(LOG_UNIMP,
+            "pc87560-pp: write offset 0x%" HWADDR_PRIx "\n", addr);
+    }
+}
+static const MemoryRegionOps pc87560_pp_ops = {
+    .read  = pc87560_pp_read,
+    .write = pc87560_pp_write,
+    .endianness = DEVICE_LITTLE_ENDIAN,
+    .valid.min_access_size = 1,
+    .valid.max_access_size = 1,
+};
+
+/*
+ * Some features on the chip are disabled by default. If a guest
+ * reads or writes one of those registers, respond via this stub
+ * instead of faulting.
+ */
+static uint64_t pc87560_stub_read(void *opaque, hwaddr addr, unsigned size)
+{
+    qemu_log_mask(LOG_UNIMP,
+                  "pc87560-superio: stub read  0x%" HWADDR_PRIx "\n", addr);
+    return 0xFF;
+}
+static void pc87560_stub_write(void *opaque, hwaddr addr, uint64_t val,
+                               unsigned size)
+{
+    qemu_log_mask(LOG_UNIMP,
+                  "pc87560-superio: stub write 0x%" HWADDR_PRIx
+                  " = 0x%" PRIx64 "\n", addr, val);
+}
+
+static const MemoryRegionOps pc87560_stub_ops = {
+    .read = pc87560_stub_read,
+    .write = pc87560_stub_write,
+    .endianness = DEVICE_LITTLE_ENDIAN,
+};
+
+
+static uint64_t pc87560_fdc_read(void *opaque, hwaddr addr, unsigned size)
+{
+    return fdctrl_read(opaque, (uint32_t)addr);
+}
+
+static void pc87560_fdc_write(void *opaque, hwaddr addr, uint64_t val,
+                              unsigned size)
+{
+    fdctrl_write(opaque, (uint32_t)addr, (uint32_t)val);
+}
+
+static const MemoryRegionOps pc87560_fdc_ops = {
+    .read  = pc87560_fdc_read,
+    .write = pc87560_fdc_write,
+    .endianness = DEVICE_LITTLE_ENDIAN,
+    .valid.min_access_size = 1,
+    .valid.max_access_size = 1,
+};
+
+static void pc87560_map_region(PC87560SuperioState *s, MemoryRegion *mr,
+                               bool *mapped, hwaddr base)
+{
+    MemoryRegion *io = pci_address_space_io(PCI_DEVICE(s));
+    if (*mapped) {
+        memory_region_del_subregion(io, mr);
+        *mapped = false;
+    }
+    if (base) {
+        memory_region_add_subregion(io, base, mr);
+        *mapped = true;
+    }
+}
+
+static void pc87560_apply_funcen(PC87560SuperioState *s)
+{
+    PCIDevice *pci = PCI_DEVICE(s);
+    uint16_t en = pci_get_word(pci->config + REG_FUNCEN);
+
+    pc87560_map_region(s, &s->fdc_io, &s->fdc_mapped, (en & FUNCEN_FDC)
+            ? (pci_get_long(pci->config + REG_FDCBAR) & ~(hwaddr)0x7) : 0);
+
+    pc87560_map_region(s, &s->sp1_io, &s->sp1_mapped, (en & FUNCEN_SP1)
+            ? (pci_get_long(pci->config + REG_SP1BAR) & ~(hwaddr)0x7) : 0);
+
+    pc87560_map_region(s, &s->sp2_io, &s->sp2_mapped, (en & FUNCEN_SP2)
+            ? (pci_get_long(pci->config + REG_SP2BAR) & ~(hwaddr)0x7) : 0);
+
+    pc87560_map_region(s, &s->pp_io, &s->pp_mapped,   (en & FUNCEN_PP)
+            ? (pci_get_long(pci->config + REG_PPBAR) & ~(hwaddr)0x7) : 0);
+
+    pc87560_map_region(s, &s->kbc_io, &s->kbc_mapped, (en & FUNCEN_KBC)
+            ? (pci_get_long(pci->config + REG_KBCBAR) & ~(hwaddr)0x7) : 0);
+}
+
+static void pc87560_superio_config_write(PCIDevice *pci,
+                                         uint32_t addr, uint32_t val, int len)
+{
+    PC87560SuperioState *s = PC87560_Superio(pci);
+    uint16_t funcen;
+
+    pci_default_write_config(pci, addr, val, len);
+    funcen = pci_get_word(pci->config + REG_FUNCEN);
+
+    if (ranges_overlap(addr, len, REG_FUNCEN, 2)) {
+        pc87560_apply_funcen(s);
+    }
+
+    if (ranges_overlap(addr, len, REG_FDCBAR, 4)) {
+        if (funcen & FUNCEN_FDC) {
+            pc87560_map_region(s, &s->fdc_io, &s->fdc_mapped,
+               pci_get_long(pci->config + REG_FDCBAR) & ~(hwaddr)0x7);
+        }
+    }
+
+    if (ranges_overlap(addr, len, REG_SP1BAR, 4)) {
+        if (funcen & FUNCEN_SP1) {
+            pc87560_map_region(s, &s->sp1_io, &s->sp1_mapped,
+               pci_get_long(pci->config + REG_SP1BAR) & ~(hwaddr)0x7);
+        }
+    }
+
+    if (ranges_overlap(addr, len, REG_SP2BAR, 4)) {
+        if (funcen & FUNCEN_SP2) {
+            pc87560_map_region(s, &s->sp2_io, &s->sp2_mapped,
+               pci_get_long(pci->config + REG_SP2BAR) & ~(hwaddr)0x7);
+        }
+    }
+
+    if (ranges_overlap(addr, len, REG_PPBAR, 4)) {
+        if (funcen & FUNCEN_PP) {
+            pc87560_map_region(s, &s->pp_io, &s->pp_mapped,
+               pci_get_long(pci->config + REG_PPBAR) & ~(hwaddr)0x7);
+        }
+    }
+
+    if (ranges_overlap(addr, len, REG_KBCBAR, 4)) {
+        if (funcen & FUNCEN_KBC) {
+            pc87560_map_region(s, &s->kbc_io, &s->kbc_mapped,
+               pci_get_long(pci->config + REG_KBCBAR) & ~(hwaddr)0x7);
+        }
+    }
+
+    if (ranges_overlap(addr, len, REG_ACPIBAR, 4)) {
+        uint32_t ab = pci_get_long(pci->config + REG_ACPIBAR);
+        pc87560_map_region(s, &s->acpi_io, &s->acpi_mapped,
+                           (ab & 1) ? (ab & ~(hwaddr)0x1F) : 0);
+    }
+
+    if (ranges_overlap(addr, len, REG_PMBAR, 4)) {
+        uint32_t pb = pci_get_long(pci->config + REG_PMBAR);
+        pc87560_map_region(s, &s->pm_io, &s->pm_mapped,
+                           (pb & 1) ? (pb & ~(hwaddr)0xFF) : 0);
+    }
+
+    if (ranges_overlap(addr, len, REG_RSVD_CFG, 1)) {
+        if ((pci->config[REG_RSVD_CFG] & 0x0F) != 0x01) {
+            qemu_log_mask(LOG_GUEST_ERROR,
+                  "pc87560-superio: offset 0x7E bits[3:0] must be 0x01\n");
+        }
+    }
+}
+
+static void pc87560_superio_realize(PCIDevice *pci, Error **errp)
+{
+    PC87560SuperioState *s = PC87560_Superio(pci);
+    MemoryRegion   *io = pci_address_space_io(pci);
+
+    pci_set_word(pci->config + REG_FUNCEN,  FUNCEN_DEFAULT);
+    pci->config[REG_RSVD_CFG]   = 0x01;
+    pci->config[REG_DMA_ROUTE1] = 0x67;
+    pci->config[REG_PPDID]      = 0x10;
+
+    pci_set_long(pci->config + REG_KBCBAR,  0x00000060); /* not usable */
+    pci_set_long(pci->config + REG_ACPIBAR, 0x00004001);
+    pci_set_long(pci->config + REG_PMBAR,   0xFFFFFF01);
+    pci_set_long(pci->config + REG_FDCBAR,  0x000003F0); /* not usable */
+    pci_set_long(pci->config + REG_SP1BAR,  0x000003F8);
+    pci_set_long(pci->config + REG_SP2BAR,  0x000002F8);
+    pci_set_long(pci->config + REG_PPBAR,   0x00000378);
+
+
+    pci_set_long(pci->wmask + REG_KBCBAR,  0xFFFFFFF8); /* not usable */
+    pci_set_long(pci->wmask + REG_ACPIBAR, 0xFFFFFFE1);
+    pci_set_long(pci->wmask + REG_PMBAR,   0xFFFFFF01);
+    pci_set_long(pci->wmask + REG_FDCBAR,  0xFFFFFFF8); /* not usable */
+    pci_set_long(pci->wmask + REG_SP1BAR,  0xFFFFFFF8);
+    pci_set_long(pci->wmask + REG_SP2BAR,  0xFFFFFFF8);
+    pci_set_long(pci->wmask + REG_PPBAR,   0xFFFFFFF8);
+
+    pci->config[PCI_INTERRUPT_PIN] = 0x01;
+
+    qdev_init_gpio_out_named(DEVICE(pci), &s->parent_irq, "pic-out", 1);
+    qdev_init_gpio_in_named(DEVICE(pci), pc87560_pic_irq_in, "pic-irq", 8);
+
+    memory_region_init_io(&s->pic1_io, OBJECT(s), &pc87560_pic1_ops,
+                          s, "pc87560-pic1", 2);
+    memory_region_add_subregion(io, IC_PIC1, &s->pic1_io);
+
+    s->serial[0].irq = qemu_allocate_irq(pc87560_pic_irq_in, s, 3);
+    if (!qdev_realize(DEVICE(&s->serial[0]), NULL, errp)) {
+        return;
+    }
+    memory_region_init_io(&s->sp1_io, OBJECT(s), &serial_io_ops,
+                          &s->serial[0], "pc87560-sp1", 8);
+    memory_region_add_subregion(io, 0x3F8, &s->sp1_io);
+    s->sp1_mapped = true;
+
+    s->serial[1].irq = qemu_allocate_irq(pc87560_pic_irq_in, s, 4);
+    if (!qdev_realize(DEVICE(&s->serial[1]), NULL, errp)) {
+        return;
+    }
+    memory_region_init_io(&s->sp2_io, OBJECT(s), &serial_io_ops,
+                          &s->serial[1], "pc87560-sp2", 8);
+    memory_region_add_subregion(io, 0x2F8, &s->sp2_io);
+    s->sp2_mapped = true;
+
+    s->pp.irq        = qemu_allocate_irq(pc87560_pic_irq_in, s, 5);
+    memory_region_init_io(&s->pp_io, OBJECT(s), &pc87560_pp_ops,
+                          &s->pp, "pc87560-pp", 8);
+    memory_region_add_subregion(io, 0x378, &s->pp_io);
+    s->pp_mapped = true;
+    s->pic.irq_level = -1;
+    s->pic.priority_base = 7;
+    s->fdc.irq       = qemu_allocate_irq(pc87560_pic_irq_in, s, 6);
+    s->fdc.dma_chann = -1;
+    s->fdc.dma       = NULL;
+    s->fdc.fallback  = FLOPPY_DRIVE_TYPE_144;
+    fdctrl_realize_common(DEVICE(pci), &s->fdc, errp);
+    if (*errp) {
+        return;
+    }
+    memory_region_init_io(&s->fdc_io, OBJECT(s), &pc87560_fdc_ops,
+                          &s->fdc, "pc87560-fdc", 8);
+    memory_region_add_subregion(io, 0x3F0, &s->fdc_io);
+    s->fdc_mapped = true;
+
+    memory_region_init_io(&s->kbc_io, OBJECT(s), &pc87560_stub_ops,
+                          s, "pc87560-kbc", 8);
+    memory_region_add_subregion(io, 0x60, &s->kbc_io);
+    s->kbc_mapped = true;
+
+    memory_region_init_io(&s->acpi_io, OBJECT(s), &pc87560_stub_ops,
+                          s, "pc87560-acpi", 32);
+    memory_region_add_subregion(io, 0x4000, &s->acpi_io);
+    s->acpi_mapped = true;
+
+    memory_region_init_io(&s->pm_io, OBJECT(s), &pc87560_stub_ops,
+                          s, "pc87560-pm", 256);
+}
+
+static void pc87560_superio_instance_init(Object *obj)
+{
+    PC87560SuperioState *s = PC87560_Superio(obj);
+
+    object_initialize_child(obj, "serial[*]", &s->serial[0], TYPE_SERIAL);
+    object_initialize_child(obj, "serial[*]", &s->serial[1], TYPE_SERIAL);
+}
+
+static const VMStateDescription vmstate_pc87560_superio = {
+    .name               = "pc87560-superio",
+    .version_id         = 1,
+    .minimum_version_id = 1,
+    .fields = (const VMStateField[]) {
+        VMSTATE_PCI_DEVICE(parent_obj, PC87560SuperioState),
+        VMSTATE_STRUCT_ARRAY(serial, PC87560SuperioState, 2, 0,
+                             vmstate_serial, SerialState),
+        VMSTATE_STRUCT(fdc, PC87560SuperioState, 0, vmstate_fdc, FDCtrl),
+        VMSTATE_END_OF_LIST()
+    },
+};
+
+static const Property pc87560_superio_properties[] = {
+    DEFINE_PROP_CHR("serial0",  PC87560SuperioState, serial[0].chr),
+    DEFINE_PROP_CHR("serial1",  PC87560SuperioState, serial[1].chr),
+    DEFINE_PROP_CHR("parallel", PC87560SuperioState, pp.chr),
+};
+
+static void pc87560_superio_class_init(ObjectClass *oc, const void *data)
+{
+    DeviceClass    *dc = DEVICE_CLASS(oc);
+    PCIDeviceClass *k  = PCI_DEVICE_CLASS(oc);
+
+    k->realize       = pc87560_superio_realize;
+    k->config_write  = pc87560_superio_config_write;
+    k->vendor_id     = PCI_VENDOR_ID_NS;
+    k->device_id     = PCI_DEVICE_ID_NS_87560_LIO;
+    k->class_id      = 0x0680;
+    k->revision      = 0x01;
+    k->subsystem_vendor_id = PCI_VENDOR_ID_HP;
+    k->subsystem_id  = 0x10A7;
+
+    dc->desc           = "NS PC87560 SuperI/O Function 1 (I/O Peripherals)";
+    dc->vmsd           = &vmstate_pc87560_superio;
+    dc->user_creatable = false;
+    device_class_set_props(dc, pc87560_superio_properties);
+    set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories);
+}
+
+static const TypeInfo pc87560_superio_info = {
+    .name          = TYPE_PC87560_Superio,
+    .parent        = TYPE_PCI_DEVICE,
+    .instance_size = sizeof(PC87560SuperioState),
+    .instance_init = pc87560_superio_instance_init,
+    .class_init    = pc87560_superio_class_init,
+    .interfaces    = (InterfaceInfo[]) {
+        { INTERFACE_CONVENTIONAL_PCI_DEVICE },
+        { },
+    },
+};
+
+static void pc87560_superio_register_types(void)
+{
+    type_register_static(&pc87560_superio_info);
+}
+
+type_init(pc87560_superio_register_types)
diff --git a/include/hw/isa/pc87560.h b/include/hw/isa/pc87560.h
new file mode 100644
index 0000000000..72e317cc7b
--- /dev/null
+++ b/include/hw/isa/pc87560.h
@@ -0,0 +1,96 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+#ifndef HW_ISA_PC87560_H
+#define HW_ISA_PC87560_H
+
+#define TYPE_PC87560_Superio  "pc87560-superio"
+OBJECT_DECLARE_SIMPLE_TYPE(PC87560SuperioState, PC87560_Superio)
+
+#define REG_FXBAR0      0x40
+#define REG_FXBAR1      0x44
+#define REG_FXBAR2      0x48
+#define REG_DDMA_BAR    0x4C
+#define REG_FIR_BAR     0x50
+#define REG_SYSCFG      0x58
+#define REG_FUNCEN      0x5A
+#define REG_SIOCFG      0x5C
+#define REG_SPECFEN     0x5D
+#define REG_PPDID       0x5E
+#define REG_PPMODE      0x5F
+#define REG_DMA_ROUTE4  0x61
+#define REG_ROMCFG      0x62
+#define REG_DMA_ROUTE1  0x63
+#define REG_DMA_ROUTE2  0x64
+#define REG_DMA_ROUTE3  0x65
+#define REG_DMA_CHAN    0x66
+#define REG_IRQ_TRIG    0x67
+#define REG_IRQ_ROUTE1  0x69
+#define REG_ARBCTL      0x72
+#define REG_FX_MASK2    0x74
+#define REG_FX_TIMING   0x76
+#define REG_FXCTL       0x78
+#define REG_GPIO_CFG    0x79
+#define REG_GPIO_DIR    0x7A
+#define REG_SIRQ_CTL    0x7B
+#define REG_SIRQ_EN     0x7C
+#define REG_RSVD_CFG    0x7E
+#define REG_AUDIOCS_EN  0x7F
+#define REG_FXMEM_CTL1  0x80
+#define REG_KBCBAR      0x84
+#define REG_ACPIBAR     0x88
+#define REG_PMBAR       0x8C
+#define REG_FDCBAR      0x90
+#define REG_SP1BAR      0x94
+#define REG_SP2BAR      0x98
+#define REG_PPBAR       0x9C
+#define REG_TEST_CTL    0xFF
+
+#define FUNCEN_FDC  (1 << 0)
+#define FUNCEN_SP1  (1 << 1)
+#define FUNCEN_SP2  (1 << 3)
+#define FUNCEN_PP   (1 << 5)
+#define FUNCEN_KBC  (1 << 13)
+
+#define FUNCEN_DEFAULT  0xFFBF
+
+#define IC_PIC1  0x20
+
+typedef struct {
+    uint8_t imr;       /* interrupt mask register (OCW1) */
+    uint8_t irr;       /* interrupt request register    */
+    uint8_t isr;       /* in-service register           */
+    bool    poll_mode; /* OCW3 POLL bit set             */
+    bool    read_isr;  /* OCW3: true=ISR, false=IRR     */
+    int     init_phase;/* 0=normal, 1-3=ICW2/3/4 expected */
+    int     priority_base;
+    int     irq_level;
+} Pic8259;
+
+struct PC87560SuperioState {
+    PCIDevice parent_obj;
+
+    qemu_irq parent_irq;
+
+    SerialState   serial[2];
+    ParallelState pp;
+    FDCtrl        fdc;
+
+    MemoryRegion fdc_io;
+    MemoryRegion sp1_io;
+    MemoryRegion sp2_io;
+    MemoryRegion pp_io;
+    MemoryRegion kbc_io;
+    MemoryRegion acpi_io;
+    MemoryRegion pm_io;
+    MemoryRegion pic1_io;
+
+    bool fdc_mapped;
+    bool sp1_mapped;
+    bool sp2_mapped;
+    bool pp_mapped;
+    bool kbc_mapped;
+    bool acpi_mapped;
+    bool pm_mapped;
+    Pic8259 pic;
+};
+
+#endif
-- 
2.54.0



  parent reply	other threads:[~2026-09-18 16:41 UTC|newest]

Thread overview: 11+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-09-18 16:38 [PULL 0/7] Superio hppa patches Helge Deller
2026-09-18 16:38 ` [PULL 1/7] hw/pci/pci_ids: Add PCI vendor ID and IDs for NS chips Helge Deller
2026-09-18 16:38 ` Helge Deller [this message]
2026-09-21  9:51   ` [PULL 2/7] hw/isa/pc87560: Add main isa code for NS 87560 SuperIO chip Philippe Mathieu-Daudé
2026-09-21 10:17     ` Daniel P. Berrangé
2026-09-18 16:38 ` [PULL 3/7] hw/ide/pc87560-ide: Add IDE emulation of " Helge Deller
2026-09-18 16:38 ` [PULL 4/7] hw/usb/hcd-ohci: Add big endian and consistency check support Helge Deller
2026-09-18 16:38 ` [PULL 5/7] hw/usb/pc87560-ohci: Add USB OHCI emulation of NS 87560 SuperIO chip Helge Deller
2026-09-18 16:38 ` [PULL 6/7] hw/pc87560: Wire up " Helge Deller
2026-09-18 16:38 ` [PULL 7/7] hw/hppa: Add NS 87560 SuperIO chip to HP C3700 machine Helge Deller
2026-09-19  0:27 ` [PULL 0/7] Superio hppa patches Richard Henderson

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20260918163829.2917-3-deller@kernel.org \
    --to=deller@kernel.org \
    --cc=abizerlokhandwalastd10@gmail.com \
    --cc=deller@gmx.de \
    --cc=den@openvz.org \
    --cc=jsnow@redhat.com \
    --cc=mst@redhat.com \
    --cc=pbonzini@redhat.com \
    --cc=qemu-block@nongnu.org \
    --cc=qemu-devel@nongnu.org \
    --cc=richard.henderson@linaro.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
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.