On Tuesday, October 15, 2019, Philippe Mathieu-Daudé <phi...@redhat.com>
wrote:

> From: Philippe Mathieu-Daudé <f4...@amsat.org>
>
> Move all the PIIX3 functions to a new file: hw/isa/piix3.c.
>
> Signed-off-by: Philippe Mathieu-Daudé <phi...@redhat.com>
> ---
> Checkpatch warning:
>
>  ERROR: spaces required around that '*' (ctx:VxV)
>  #312: FILE: hw/isa/piix3.c:248:
>  +    .subsections = (const VMStateDescription*[]) {
>                                               ^
> ---
>  MAINTAINERS                   |   1 +
>  hw/i386/Kconfig               |   1 +
>  hw/isa/Kconfig                |   4 +
>  hw/isa/Makefile.objs          |   1 +
>  hw/isa/piix3.c                | 399 +++++++++++++++++++++++++++++++++
>  hw/pci-host/Kconfig           |   1 -
>  hw/pci-host/piix.c            | 402 ----------------------------------
>  include/hw/southbridge/piix.h |  36 +++
>  8 files changed, 442 insertions(+), 403 deletions(-)
>  create mode 100644 hw/isa/piix3.c
>
>

Reviewed-by: Aleksandar Markovic <amarko...@wavecomp.com>


> diff --git a/MAINTAINERS b/MAINTAINERS
> index adf059a164..4845f47d93 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -1231,6 +1231,7 @@ F: hw/pci-host/pam.c
>  F: include/hw/pci-host/i440fx.h
>  F: include/hw/pci-host/q35.h
>  F: include/hw/pci-host/pam.h
> +F: hw/isa/piix3.c
>  F: hw/isa/lpc_ich9.c
>  F: hw/i2c/smbus_ich9.c
>  F: hw/acpi/piix4.c
> diff --git a/hw/i386/Kconfig b/hw/i386/Kconfig
> index c5c9d4900e..589d75e26a 100644
> --- a/hw/i386/Kconfig
> +++ b/hw/i386/Kconfig
> @@ -61,6 +61,7 @@ config I440FX
>      select PC_ACPI
>      select ACPI_SMBUS
>      select PCI_PIIX
> +    select PIIX3
>      select IDE_PIIX
>      select DIMM
>      select SMBIOS
> diff --git a/hw/isa/Kconfig b/hw/isa/Kconfig
> index 98a289957e..8a38813cc1 100644
> --- a/hw/isa/Kconfig
> +++ b/hw/isa/Kconfig
> @@ -29,6 +29,10 @@ config PC87312
>      select FDC
>      select IDE_ISA
>
> +config PIIX3
> +    bool
> +    select ISA_BUS
> +
>  config PIIX4
>      bool
>      # For historical reasons, SuperIO devices are created in the board
> diff --git a/hw/isa/Makefile.objs b/hw/isa/Makefile.objs
> index ff97485504..8e73960a75 100644
> --- a/hw/isa/Makefile.objs
> +++ b/hw/isa/Makefile.objs
> @@ -3,6 +3,7 @@ common-obj-$(CONFIG_ISA_SUPERIO) += isa-superio.o
>  common-obj-$(CONFIG_APM) += apm.o
>  common-obj-$(CONFIG_I82378) += i82378.o
>  common-obj-$(CONFIG_PC87312) += pc87312.o
> +common-obj-$(CONFIG_PIIX3) += piix3.o
>  common-obj-$(CONFIG_PIIX4) += piix4.o
>  common-obj-$(CONFIG_VT82C686) += vt82c686.o
>  common-obj-$(CONFIG_SMC37C669) += smc37c669-superio.o
> diff --git a/hw/isa/piix3.c b/hw/isa/piix3.c
> new file mode 100644
> index 0000000000..05146447ef
> --- /dev/null
> +++ b/hw/isa/piix3.c
> @@ -0,0 +1,399 @@
> +/*
> + * QEMU PIIX PCI ISA Bridge Emulation
> + *
> + * Copyright (c) 2006 Fabrice Bellard
> + *
> + * Permission is hereby granted, free of charge, to any person obtaining
> a copy
> + * of this software and associated documentation files (the "Software"),
> to deal
> + * in the Software without restriction, including without limitation the
> rights
> + * to use, copy, modify, merge, publish, distribute, sublicense, and/or
> sell
> + * copies of the Software, and to permit persons to whom the Software is
> + * furnished to do so, subject to the following conditions:
> + *
> + * The above copyright notice and this permission notice shall be
> included in
> + * all copies or substantial portions of the Software.
> + *
> + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
> EXPRESS OR
> + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
> MERCHANTABILITY,
> + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
> + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
> OTHER
> + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
> ARISING FROM,
> + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
> IN
> + * THE SOFTWARE.
> + */
> +
> +#include "qemu/osdep.h"
> +#include "qemu/range.h"
> +#include "hw/southbridge/piix.h"
> +#include "hw/irq.h"
> +#include "hw/isa/isa.h"
> +#include "hw/xen/xen.h"
> +#include "sysemu/sysemu.h"
> +#include "sysemu/reset.h"
> +#include "sysemu/runstate.h"
> +#include "migration/vmstate.h"
> +
> +#define XEN_PIIX_NUM_PIRQS      128ULL
> +
> +#define TYPE_PIIX3_PCI_DEVICE "pci-piix3"
> +#define PIIX3_PCI_DEVICE(obj) \
> +    OBJECT_CHECK(PIIX3State, (obj), TYPE_PIIX3_PCI_DEVICE)
> +
> +#define TYPE_PIIX3_DEVICE "PIIX3"
> +#define TYPE_PIIX3_XEN_DEVICE "PIIX3-xen"
> +
> +static void piix3_set_irq_pic(PIIX3State *piix3, int pic_irq)
> +{
> +    qemu_set_irq(piix3->pic[pic_irq],
> +                 !!(piix3->pic_levels &
> +                    (((1ULL << PIIX_NUM_PIRQS) - 1) <<
> +                     (pic_irq * PIIX_NUM_PIRQS))));
> +}
> +
> +static void piix3_set_irq_level_internal(PIIX3State *piix3, int pirq,
> int level)
> +{
> +    int pic_irq;
> +    uint64_t mask;
> +
> +    pic_irq = piix3->dev.config[PIIX_PIRQCA + pirq];
> +    if (pic_irq >= PIIX_NUM_PIC_IRQS) {
> +        return;
> +    }
> +
> +    mask = 1ULL << ((pic_irq * PIIX_NUM_PIRQS) + pirq);
> +    piix3->pic_levels &= ~mask;
> +    piix3->pic_levels |= mask * !!level;
> +}
> +
> +static void piix3_set_irq_level(PIIX3State *piix3, int pirq, int level)
> +{
> +    int pic_irq;
> +
> +    pic_irq = piix3->dev.config[PIIX_PIRQCA + pirq];
> +    if (pic_irq >= PIIX_NUM_PIC_IRQS) {
> +        return;
> +    }
> +
> +    piix3_set_irq_level_internal(piix3, pirq, level);
> +
> +    piix3_set_irq_pic(piix3, pic_irq);
> +}
> +
> +static void piix3_set_irq(void *opaque, int pirq, int level)
> +{
> +    PIIX3State *piix3 = opaque;
> +    piix3_set_irq_level(piix3, pirq, level);
> +}
> +
> +static PCIINTxRoute piix3_route_intx_pin_to_irq(void *opaque, int pin)
> +{
> +    PIIX3State *piix3 = opaque;
> +    int irq = piix3->dev.config[PIIX_PIRQCA + pin];
> +    PCIINTxRoute route;
> +
> +    if (irq < PIIX_NUM_PIC_IRQS) {
> +        route.mode = PCI_INTX_ENABLED;
> +        route.irq = irq;
> +    } else {
> +        route.mode = PCI_INTX_DISABLED;
> +        route.irq = -1;
> +    }
> +    return route;
> +}
> +
> +/* irq routing is changed. so rebuild bitmap */
> +static void piix3_update_irq_levels(PIIX3State *piix3)
> +{
> +    PCIBus *bus = pci_get_bus(&piix3->dev);
> +    int pirq;
> +
> +    piix3->pic_levels = 0;
> +    for (pirq = 0; pirq < PIIX_NUM_PIRQS; pirq++) {
> +        piix3_set_irq_level(piix3, pirq, pci_bus_get_irq_level(bus,
> pirq));
> +    }
> +}
> +
> +static void piix3_write_config(PCIDevice *dev,
> +                               uint32_t address, uint32_t val, int len)
> +{
> +    pci_default_write_config(dev, address, val, len);
> +    if (ranges_overlap(address, len, PIIX_PIRQCA, 4)) {
> +        PIIX3State *piix3 = PIIX3_PCI_DEVICE(dev);
> +        int pic_irq;
> +
> +        pci_bus_fire_intx_routing_notifier(pci_get_bus(&piix3->dev));
> +        piix3_update_irq_levels(piix3);
> +        for (pic_irq = 0; pic_irq < PIIX_NUM_PIC_IRQS; pic_irq++) {
> +            piix3_set_irq_pic(piix3, pic_irq);
> +        }
> +    }
> +}
> +
> +static void piix3_write_config_xen(PCIDevice *dev,
> +                                   uint32_t address, uint32_t val, int
> len)
> +{
> +    xen_piix_pci_write_config_client(address, val, len);
> +    piix3_write_config(dev, address, val, len);
> +}
> +
> +static void piix3_reset(void *opaque)
> +{
> +    PIIX3State *d = opaque;
> +    uint8_t *pci_conf = d->dev.config;
> +
> +    pci_conf[0x04] = 0x07; /* master, memory and I/O */
> +    pci_conf[0x05] = 0x00;
> +    pci_conf[0x06] = 0x00;
> +    pci_conf[0x07] = 0x02; /* PCI_status_devsel_medium */
> +    pci_conf[0x4c] = 0x4d;
> +    pci_conf[0x4e] = 0x03;
> +    pci_conf[0x4f] = 0x00;
> +    pci_conf[0x60] = 0x80;
> +    pci_conf[0x61] = 0x80;
> +    pci_conf[0x62] = 0x80;
> +    pci_conf[0x63] = 0x80;
> +    pci_conf[0x69] = 0x02;
> +    pci_conf[0x70] = 0x80;
> +    pci_conf[0x76] = 0x0c;
> +    pci_conf[0x77] = 0x0c;
> +    pci_conf[0x78] = 0x02;
> +    pci_conf[0x79] = 0x00;
> +    pci_conf[0x80] = 0x00;
> +    pci_conf[0x82] = 0x00;
> +    pci_conf[0xa0] = 0x08;
> +    pci_conf[0xa2] = 0x00;
> +    pci_conf[0xa3] = 0x00;
> +    pci_conf[0xa4] = 0x00;
> +    pci_conf[0xa5] = 0x00;
> +    pci_conf[0xa6] = 0x00;
> +    pci_conf[0xa7] = 0x00;
> +    pci_conf[0xa8] = 0x0f;
> +    pci_conf[0xaa] = 0x00;
> +    pci_conf[0xab] = 0x00;
> +    pci_conf[0xac] = 0x00;
> +    pci_conf[0xae] = 0x00;
> +
> +    d->pic_levels = 0;
> +    d->rcr = 0;
> +}
> +
> +static int piix3_post_load(void *opaque, int version_id)
> +{
> +    PIIX3State *piix3 = opaque;
> +    int pirq;
> +
> +    /*
> +     * Because the i8259 has not been deserialized yet, qemu_irq_raise
> +     * might bring the system to a different state than the saved one;
> +     * for example, the interrupt could be masked but the i8259 would
> +     * not know that yet and would trigger an interrupt in the CPU.
> +     *
> +     * Here, we update irq levels without raising the interrupt.
> +     * Interrupt state will be deserialized separately through the i8259.
> +     */
> +    piix3->pic_levels = 0;
> +    for (pirq = 0; pirq < PIIX_NUM_PIRQS; pirq++) {
> +        piix3_set_irq_level_internal(piix3, pirq,
> +            pci_bus_get_irq_level(pci_get_bus(&piix3->dev), pirq));
> +    }
> +    return 0;
> +}
> +
> +static int piix3_pre_save(void *opaque)
> +{
> +    int i;
> +    PIIX3State *piix3 = opaque;
> +
> +    for (i = 0; i < ARRAY_SIZE(piix3->pci_irq_levels_vmstate); i++) {
> +        piix3->pci_irq_levels_vmstate[i] =
> +            pci_bus_get_irq_level(pci_get_bus(&piix3->dev), i);
> +    }
> +
> +    return 0;
> +}
> +
> +static bool piix3_rcr_needed(void *opaque)
> +{
> +    PIIX3State *piix3 = opaque;
> +
> +    return (piix3->rcr != 0);
> +}
> +
> +static const VMStateDescription vmstate_piix3_rcr = {
> +    .name = "PIIX3/rcr",
> +    .version_id = 1,
> +    .minimum_version_id = 1,
> +    .needed = piix3_rcr_needed,
> +    .fields = (VMStateField[]) {
> +        VMSTATE_UINT8(rcr, PIIX3State),
> +        VMSTATE_END_OF_LIST()
> +    }
> +};
> +
> +static const VMStateDescription vmstate_piix3 = {
> +    .name = "PIIX3",
> +    .version_id = 3,
> +    .minimum_version_id = 2,
> +    .post_load = piix3_post_load,
> +    .pre_save = piix3_pre_save,
> +    .fields = (VMStateField[]) {
> +        VMSTATE_PCI_DEVICE(dev, PIIX3State),
> +        VMSTATE_INT32_ARRAY_V(pci_irq_levels_vmstate, PIIX3State,
> +                              PIIX_NUM_PIRQS, 3),
> +        VMSTATE_END_OF_LIST()
> +    },
> +    .subsections = (const VMStateDescription*[]) {
> +        &vmstate_piix3_rcr,
> +        NULL
> +    }
> +};
> +
> +
> +static void rcr_write(void *opaque, hwaddr addr, uint64_t val, unsigned
> len)
> +{
> +    PIIX3State *d = opaque;
> +
> +    if (val & 4) {
> +        qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET);
> +        return;
> +    }
> +    d->rcr = val & 2; /* keep System Reset type only */
> +}
> +
> +static uint64_t rcr_read(void *opaque, hwaddr addr, unsigned len)
> +{
> +    PIIX3State *d = opaque;
> +
> +    return d->rcr;
> +}
> +
> +static const MemoryRegionOps rcr_ops = {
> +    .read = rcr_read,
> +    .write = rcr_write,
> +    .endianness = DEVICE_LITTLE_ENDIAN
> +};
> +
> +static void piix3_realize(PCIDevice *dev, Error **errp)
> +{
> +    PIIX3State *d = PIIX3_PCI_DEVICE(dev);
> +
> +    if (!isa_bus_new(DEVICE(d), get_system_memory(),
> +                     pci_address_space_io(dev), errp)) {
> +        return;
> +    }
> +
> +    memory_region_init_io(&d->rcr_mem, OBJECT(dev), &rcr_ops, d,
> +                          "piix3-reset-control", 1);
> +    memory_region_add_subregion_overlap(pci_address_space_io(dev),
> RCR_IOPORT,
> +                                        &d->rcr_mem, 1);
> +
> +    qemu_register_reset(piix3_reset, d);
> +}
> +
> +static void pci_piix3_class_init(ObjectClass *klass, void *data)
> +{
> +    DeviceClass *dc = DEVICE_CLASS(klass);
> +    PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
> +
> +    dc->desc        = "ISA bridge";
> +    dc->vmsd        = &vmstate_piix3;
> +    dc->hotpluggable   = false;
> +    k->realize      = piix3_realize;
> +    k->vendor_id    = PCI_VENDOR_ID_INTEL;
> +    /* 82371SB PIIX3 PCI-to-ISA bridge (Step A1) */
> +    k->device_id    = PCI_DEVICE_ID_INTEL_82371SB_0;
> +    k->class_id     = PCI_CLASS_BRIDGE_ISA;
> +    /*
> +     * Reason: part of PIIX3 southbridge, needs to be wired up by
> +     * pc_piix.c's pc_init1()
> +     */
> +    dc->user_creatable = false;
> +}
> +
> +static const TypeInfo piix3_pci_type_info = {
> +    .name = TYPE_PIIX3_PCI_DEVICE,
> +    .parent = TYPE_PCI_DEVICE,
> +    .instance_size = sizeof(PIIX3State),
> +    .abstract = true,
> +    .class_init = pci_piix3_class_init,
> +    .interfaces = (InterfaceInfo[]) {
> +        { INTERFACE_CONVENTIONAL_PCI_DEVICE },
> +        { },
> +    },
> +};
> +
> +static void piix3_class_init(ObjectClass *klass, void *data)
> +{
> +    PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
> +
> +    k->config_write = piix3_write_config;
> +}
> +
> +static const TypeInfo piix3_info = {
> +    .name          = TYPE_PIIX3_DEVICE,
> +    .parent        = TYPE_PIIX3_PCI_DEVICE,
> +    .class_init    = piix3_class_init,
> +};
> +
> +static void piix3_xen_class_init(ObjectClass *klass, void *data)
> +{
> +    PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
> +
> +    k->config_write = piix3_write_config_xen;
> +};
> +
> +static const TypeInfo piix3_xen_info = {
> +    .name          = TYPE_PIIX3_XEN_DEVICE,
> +    .parent        = TYPE_PIIX3_PCI_DEVICE,
> +    .class_init    = piix3_xen_class_init,
> +};
> +
> +static void piix3_register_types(void)
> +{
> +    type_register_static(&piix3_pci_type_info);
> +    type_register_static(&piix3_info);
> +    type_register_static(&piix3_xen_info);
> +}
> +
> +type_init(piix3_register_types)
> +
> +/*
> + * Return the global irq number corresponding to a given device irq
> + * pin. We could also use the bus number to have a more precise mapping.
> + */
> +static int pci_slot_get_pirq(PCIDevice *pci_dev, int pci_intx)
> +{
> +    int slot_addend;
> +    slot_addend = (pci_dev->devfn >> 3) - 1;
> +    return (pci_intx + slot_addend) & 3;
> +}
> +
> +PIIX3State *piix3_create(PCIBus *pci_bus, ISABus **isa_bus)
> +{
> +    PIIX3State *piix3;
> +    PCIDevice *pci_dev;
> +
> +    /*
> +     * Xen supports additional interrupt routes from the PCI devices to
> +     * the IOAPIC: the four pins of each PCI device on the bus are also
> +     * connected to the IOAPIC directly.
> +     * These additional routes can be discovered through ACPI.
> +     */
> +    if (xen_enabled()) {
> +        pci_dev = pci_create_simple_multifunction(pci_bus, -1, true,
> +                                                  TYPE_PIIX3_XEN_DEVICE);
> +        piix3 = PIIX3_PCI_DEVICE(pci_dev);
> +        pci_bus_irqs(pci_bus, xen_piix3_set_irq, xen_pci_slot_get_pirq,
> +                     piix3, XEN_PIIX_NUM_PIRQS);
> +    } else {
> +        pci_dev = pci_create_simple_multifunction(pci_bus, -1, true,
> +                                                  TYPE_PIIX3_DEVICE);
> +        piix3 = PIIX3_PCI_DEVICE(pci_dev);
> +        pci_bus_irqs(pci_bus, piix3_set_irq, pci_slot_get_pirq,
> +                     piix3, PIIX_NUM_PIRQS);
> +        pci_bus_set_route_irq_fn(pci_bus, piix3_route_intx_pin_to_irq);
> +    }
> +    *isa_bus = ISA_BUS(qdev_get_child_bus(DEVICE(piix3), "isa.0"));
> +
> +    return piix3;
> +}
> diff --git a/hw/pci-host/Kconfig b/hw/pci-host/Kconfig
> index 1edc1a31d4..397043b289 100644
> --- a/hw/pci-host/Kconfig
> +++ b/hw/pci-host/Kconfig
> @@ -32,7 +32,6 @@ config PCI_PIIX
>      bool
>      select PCI
>      select PAM
> -    select ISA_BUS
>
>  config PCI_EXPRESS_Q35
>      bool
> diff --git a/hw/pci-host/piix.c b/hw/pci-host/piix.c
> index 61f91ff561..79ecd58a2b 100644
> --- a/hw/pci-host/piix.c
> +++ b/hw/pci-host/piix.c
> @@ -24,22 +24,15 @@
>
>  #include "qemu/osdep.h"
>  #include "hw/i386/pc.h"
> -#include "hw/irq.h"
>  #include "hw/pci/pci.h"
>  #include "hw/pci/pci_host.h"
>  #include "hw/pci-host/i440fx.h"
>  #include "hw/southbridge/piix.h"
>  #include "hw/qdev-properties.h"
> -#include "hw/isa/isa.h"
>  #include "hw/sysbus.h"
>  #include "qapi/error.h"
> -#include "qemu/range.h"
> -#include "hw/xen/xen.h"
>  #include "migration/vmstate.h"
>  #include "hw/pci-host/pam.h"
> -#include "sysemu/reset.h"
> -#include "sysemu/runstate.h"
> -#include "hw/i386/ioapic.h"
>  #include "qapi/visitor.h"
>  #include "qemu/error-report.h"
>
> @@ -59,49 +52,9 @@ typedef struct I440FXState {
>      uint32_t short_root_bus;
>  } I440FXState;
>
> -#define PIIX_NUM_PIC_IRQS       16      /* i8259 * 2 */
> -#define PIIX_NUM_PIRQS          4ULL    /* PIRQ[A-D] */
> -#define XEN_PIIX_NUM_PIRQS      128ULL
> -
> -typedef struct PIIX3State {
> -    PCIDevice dev;
> -
> -    /*
> -     * bitmap to track pic levels.
> -     * The pic level is the logical OR of all the PCI irqs mapped to it
> -     * So one PIC level is tracked by PIIX_NUM_PIRQS bits.
> -     *
> -     * PIRQ is mapped to PIC pins, we track it by
> -     * PIIX_NUM_PIRQS * PIIX_NUM_PIC_IRQS = 64 bits with
> -     * pic_irq * PIIX_NUM_PIRQS + pirq
> -     */
> -#if PIIX_NUM_PIC_IRQS * PIIX_NUM_PIRQS > 64
> -#error "unable to encode pic state in 64bit in pic_levels."
> -#endif
> -    uint64_t pic_levels;
> -
> -    qemu_irq *pic;
> -
> -    /* This member isn't used. Just for save/load compatibility */
> -    int32_t pci_irq_levels_vmstate[PIIX_NUM_PIRQS];
> -
> -    /* Reset Control Register contents */
> -    uint8_t rcr;
> -
> -    /* IO memory region for Reset Control Register (RCR_IOPORT) */
> -    MemoryRegion rcr_mem;
> -} PIIX3State;
> -
> -#define TYPE_PIIX3_PCI_DEVICE "pci-piix3"
> -#define PIIX3_PCI_DEVICE(obj) \
> -    OBJECT_CHECK(PIIX3State, (obj), TYPE_PIIX3_PCI_DEVICE)
> -
>  #define I440FX_PCI_DEVICE(obj) \
>      OBJECT_CHECK(PCII440FXState, (obj), TYPE_I440FX_PCI_DEVICE)
>
> -#define TYPE_PIIX3_DEVICE "PIIX3"
> -#define TYPE_PIIX3_XEN_DEVICE "PIIX3-xen"
> -
>  struct PCII440FXState {
>      /*< private >*/
>      PCIDevice parent_obj;
> @@ -128,22 +81,6 @@ struct PCII440FXState {
>   */
>  #define I440FX_COREBOOT_RAM_SIZE 0x57
>
> -static void piix3_set_irq(void *opaque, int pirq, int level);
> -static PCIINTxRoute piix3_route_intx_pin_to_irq(void *opaque, int
> pci_intx);
> -static void piix3_write_config_xen(PCIDevice *dev,
> -                               uint32_t address, uint32_t val, int len);
> -
> -/*
> - * Return the global irq number corresponding to a given device irq
> - * pin. We could also use the bus number to have a more precise mapping.
> - */
> -static int pci_slot_get_pirq(PCIDevice *pci_dev, int pci_intx)
> -{
> -    int slot_addend;
> -    slot_addend = (pci_dev->devfn >> 3) - 1;
> -    return (pci_intx + slot_addend) & 3;
> -}
> -
>  static void i440fx_update_memory_mappings(PCII440FXState *d)
>  {
>      int i;
> @@ -333,36 +270,6 @@ static void i440fx_realize(PCIDevice *dev, Error
> **errp)
>      }
>  }
>
> -static PIIX3State *piix3_create(PCIBus *pci_bus, ISABus **isa_bus)
> -{
> -    PIIX3State *piix3;
> -    PCIDevice *pci_dev;
> -
> -    /*
> -     * Xen supports additional interrupt routes from the PCI devices to
> -     * the IOAPIC: the four pins of each PCI device on the bus are also
> -     * connected to the IOAPIC directly.
> -     * These additional routes can be discovered through ACPI.
> -     */
> -    if (xen_enabled()) {
> -        pci_dev = pci_create_simple_multifunction(pci_bus, -1, true,
> -                                                  TYPE_PIIX3_XEN_DEVICE);
> -        piix3 = PIIX3_PCI_DEVICE(pci_dev);
> -        pci_bus_irqs(pci_bus, xen_piix3_set_irq, xen_pci_slot_get_pirq,
> -                     piix3, XEN_PIIX_NUM_PIRQS);
> -    } else {
> -        pci_dev = pci_create_simple_multifunction(pci_bus, -1, true,
> -                                                  TYPE_PIIX3_DEVICE);
> -        piix3 = PIIX3_PCI_DEVICE(pci_dev);
> -        pci_bus_irqs(pci_bus, piix3_set_irq, pci_slot_get_pirq,
> -                     piix3, PIIX_NUM_PIRQS);
> -        pci_bus_set_route_irq_fn(pci_bus, piix3_route_intx_pin_to_irq);
> -    }
> -    *isa_bus = ISA_BUS(qdev_get_child_bus(DEVICE(piix3), "isa.0"));
> -
> -    return piix3;
> -}
> -
>  PCIBus *i440fx_init(const char *host_type, const char *pci_type,
>                      PCII440FXState **pi440fx_state,
>                      int *piix3_devfn,
> @@ -455,312 +362,6 @@ PCIBus *find_i440fx(void)
>      return s ? s->bus : NULL;
>  }
>
> -/* PIIX3 PCI to ISA bridge */
> -static void piix3_set_irq_pic(PIIX3State *piix3, int pic_irq)
> -{
> -    qemu_set_irq(piix3->pic[pic_irq],
> -                 !!(piix3->pic_levels &
> -                    (((1ULL << PIIX_NUM_PIRQS) - 1) <<
> -                     (pic_irq * PIIX_NUM_PIRQS))));
> -}
> -
> -static void piix3_set_irq_level_internal(PIIX3State *piix3, int pirq,
> int level)
> -{
> -    int pic_irq;
> -    uint64_t mask;
> -
> -    pic_irq = piix3->dev.config[PIIX_PIRQCA + pirq];
> -    if (pic_irq >= PIIX_NUM_PIC_IRQS) {
> -        return;
> -    }
> -
> -    mask = 1ULL << ((pic_irq * PIIX_NUM_PIRQS) + pirq);
> -    piix3->pic_levels &= ~mask;
> -    piix3->pic_levels |= mask * !!level;
> -}
> -
> -static void piix3_set_irq_level(PIIX3State *piix3, int pirq, int level)
> -{
> -    int pic_irq;
> -
> -    pic_irq = piix3->dev.config[PIIX_PIRQCA + pirq];
> -    if (pic_irq >= PIIX_NUM_PIC_IRQS) {
> -        return;
> -    }
> -
> -    piix3_set_irq_level_internal(piix3, pirq, level);
> -
> -    piix3_set_irq_pic(piix3, pic_irq);
> -}
> -
> -static void piix3_set_irq(void *opaque, int pirq, int level)
> -{
> -    PIIX3State *piix3 = opaque;
> -    piix3_set_irq_level(piix3, pirq, level);
> -}
> -
> -static PCIINTxRoute piix3_route_intx_pin_to_irq(void *opaque, int pin)
> -{
> -    PIIX3State *piix3 = opaque;
> -    int irq = piix3->dev.config[PIIX_PIRQCA + pin];
> -    PCIINTxRoute route;
> -
> -    if (irq < PIIX_NUM_PIC_IRQS) {
> -        route.mode = PCI_INTX_ENABLED;
> -        route.irq = irq;
> -    } else {
> -        route.mode = PCI_INTX_DISABLED;
> -        route.irq = -1;
> -    }
> -    return route;
> -}
> -
> -/* irq routing is changed. so rebuild bitmap */
> -static void piix3_update_irq_levels(PIIX3State *piix3)
> -{
> -    PCIBus *bus = pci_get_bus(&piix3->dev);
> -    int pirq;
> -
> -    piix3->pic_levels = 0;
> -    for (pirq = 0; pirq < PIIX_NUM_PIRQS; pirq++) {
> -        piix3_set_irq_level(piix3, pirq, pci_bus_get_irq_level(bus,
> pirq));
> -    }
> -}
> -
> -static void piix3_write_config(PCIDevice *dev,
> -                               uint32_t address, uint32_t val, int len)
> -{
> -    pci_default_write_config(dev, address, val, len);
> -    if (ranges_overlap(address, len, PIIX_PIRQCA, 4)) {
> -        PIIX3State *piix3 = PIIX3_PCI_DEVICE(dev);
> -        int pic_irq;
> -
> -        pci_bus_fire_intx_routing_notifier(pci_get_bus(&piix3->dev));
> -        piix3_update_irq_levels(piix3);
> -        for (pic_irq = 0; pic_irq < PIIX_NUM_PIC_IRQS; pic_irq++) {
> -            piix3_set_irq_pic(piix3, pic_irq);
> -        }
> -    }
> -}
> -
> -static void piix3_write_config_xen(PCIDevice *dev,
> -                               uint32_t address, uint32_t val, int len)
> -{
> -    xen_piix_pci_write_config_client(address, val, len);
> -    piix3_write_config(dev, address, val, len);
> -}
> -
> -static void piix3_reset(void *opaque)
> -{
> -    PIIX3State *d = opaque;
> -    uint8_t *pci_conf = d->dev.config;
> -
> -    pci_conf[0x04] = 0x07; /* master, memory and I/O */
> -    pci_conf[0x05] = 0x00;
> -    pci_conf[0x06] = 0x00;
> -    pci_conf[0x07] = 0x02; /* PCI_status_devsel_medium */
> -    pci_conf[0x4c] = 0x4d;
> -    pci_conf[0x4e] = 0x03;
> -    pci_conf[0x4f] = 0x00;
> -    pci_conf[0x60] = 0x80;
> -    pci_conf[0x61] = 0x80;
> -    pci_conf[0x62] = 0x80;
> -    pci_conf[0x63] = 0x80;
> -    pci_conf[0x69] = 0x02;
> -    pci_conf[0x70] = 0x80;
> -    pci_conf[0x76] = 0x0c;
> -    pci_conf[0x77] = 0x0c;
> -    pci_conf[0x78] = 0x02;
> -    pci_conf[0x79] = 0x00;
> -    pci_conf[0x80] = 0x00;
> -    pci_conf[0x82] = 0x00;
> -    pci_conf[0xa0] = 0x08;
> -    pci_conf[0xa2] = 0x00;
> -    pci_conf[0xa3] = 0x00;
> -    pci_conf[0xa4] = 0x00;
> -    pci_conf[0xa5] = 0x00;
> -    pci_conf[0xa6] = 0x00;
> -    pci_conf[0xa7] = 0x00;
> -    pci_conf[0xa8] = 0x0f;
> -    pci_conf[0xaa] = 0x00;
> -    pci_conf[0xab] = 0x00;
> -    pci_conf[0xac] = 0x00;
> -    pci_conf[0xae] = 0x00;
> -
> -    d->pic_levels = 0;
> -    d->rcr = 0;
> -}
> -
> -static int piix3_post_load(void *opaque, int version_id)
> -{
> -    PIIX3State *piix3 = opaque;
> -    int pirq;
> -
> -    /* Because the i8259 has not been deserialized yet, qemu_irq_raise
> -     * might bring the system to a different state than the saved one;
> -     * for example, the interrupt could be masked but the i8259 would
> -     * not know that yet and would trigger an interrupt in the CPU.
> -     *
> -     * Here, we update irq levels without raising the interrupt.
> -     * Interrupt state will be deserialized separately through the i8259.
> -     */
> -    piix3->pic_levels = 0;
> -    for (pirq = 0; pirq < PIIX_NUM_PIRQS; pirq++) {
> -        piix3_set_irq_level_internal(piix3, pirq,
> -            pci_bus_get_irq_level(pci_get_bus(&piix3->dev), pirq));
> -    }
> -    return 0;
> -}
> -
> -static int piix3_pre_save(void *opaque)
> -{
> -    int i;
> -    PIIX3State *piix3 = opaque;
> -
> -    for (i = 0; i < ARRAY_SIZE(piix3->pci_irq_levels_vmstate); i++) {
> -        piix3->pci_irq_levels_vmstate[i] =
> -            pci_bus_get_irq_level(pci_get_bus(&piix3->dev), i);
> -    }
> -
> -    return 0;
> -}
> -
> -static bool piix3_rcr_needed(void *opaque)
> -{
> -    PIIX3State *piix3 = opaque;
> -
> -    return (piix3->rcr != 0);
> -}
> -
> -static const VMStateDescription vmstate_piix3_rcr = {
> -    .name = "PIIX3/rcr",
> -    .version_id = 1,
> -    .minimum_version_id = 1,
> -    .needed = piix3_rcr_needed,
> -    .fields = (VMStateField[]) {
> -        VMSTATE_UINT8(rcr, PIIX3State),
> -        VMSTATE_END_OF_LIST()
> -    }
> -};
> -
> -static const VMStateDescription vmstate_piix3 = {
> -    .name = "PIIX3",
> -    .version_id = 3,
> -    .minimum_version_id = 2,
> -    .post_load = piix3_post_load,
> -    .pre_save = piix3_pre_save,
> -    .fields = (VMStateField[]) {
> -        VMSTATE_PCI_DEVICE(dev, PIIX3State),
> -        VMSTATE_INT32_ARRAY_V(pci_irq_levels_vmstate, PIIX3State,
> -                              PIIX_NUM_PIRQS, 3),
> -        VMSTATE_END_OF_LIST()
> -    },
> -    .subsections = (const VMStateDescription*[]) {
> -        &vmstate_piix3_rcr,
> -        NULL
> -    }
> -};
> -
> -
> -static void rcr_write(void *opaque, hwaddr addr, uint64_t val, unsigned
> len)
> -{
> -    PIIX3State *d = opaque;
> -
> -    if (val & 4) {
> -        qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET);
> -        return;
> -    }
> -    d->rcr = val & 2; /* keep System Reset type only */
> -}
> -
> -static uint64_t rcr_read(void *opaque, hwaddr addr, unsigned len)
> -{
> -    PIIX3State *d = opaque;
> -
> -    return d->rcr;
> -}
> -
> -static const MemoryRegionOps rcr_ops = {
> -    .read = rcr_read,
> -    .write = rcr_write,
> -    .endianness = DEVICE_LITTLE_ENDIAN
> -};
> -
> -static void piix3_realize(PCIDevice *dev, Error **errp)
> -{
> -    PIIX3State *d = PIIX3_PCI_DEVICE(dev);
> -
> -    if (!isa_bus_new(DEVICE(d), get_system_memory(),
> -                     pci_address_space_io(dev), errp)) {
> -        return;
> -    }
> -
> -    memory_region_init_io(&d->rcr_mem, OBJECT(dev), &rcr_ops, d,
> -                          "piix3-reset-control", 1);
> -    memory_region_add_subregion_overlap(pci_address_space_io(dev),
> RCR_IOPORT,
> -                                        &d->rcr_mem, 1);
> -
> -    qemu_register_reset(piix3_reset, d);
> -}
> -
> -static void pci_piix3_class_init(ObjectClass *klass, void *data)
> -{
> -    DeviceClass *dc = DEVICE_CLASS(klass);
> -    PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
> -
> -    dc->desc        = "ISA bridge";
> -    dc->vmsd        = &vmstate_piix3;
> -    dc->hotpluggable   = false;
> -    k->realize      = piix3_realize;
> -    k->vendor_id    = PCI_VENDOR_ID_INTEL;
> -    /* 82371SB PIIX3 PCI-to-ISA bridge (Step A1) */
> -    k->device_id    = PCI_DEVICE_ID_INTEL_82371SB_0;
> -    k->class_id     = PCI_CLASS_BRIDGE_ISA;
> -    /*
> -     * Reason: part of PIIX3 southbridge, needs to be wired up by
> -     * pc_piix.c's pc_init1()
> -     */
> -    dc->user_creatable = false;
> -}
> -
> -static const TypeInfo piix3_pci_type_info = {
> -    .name = TYPE_PIIX3_PCI_DEVICE,
> -    .parent = TYPE_PCI_DEVICE,
> -    .instance_size = sizeof(PIIX3State),
> -    .abstract = true,
> -    .class_init = pci_piix3_class_init,
> -    .interfaces = (InterfaceInfo[]) {
> -        { INTERFACE_CONVENTIONAL_PCI_DEVICE },
> -        { },
> -    },
> -};
> -
> -static void piix3_class_init(ObjectClass *klass, void *data)
> -{
> -    PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
> -
> -    k->config_write = piix3_write_config;
> -}
> -
> -static const TypeInfo piix3_info = {
> -    .name          = TYPE_PIIX3_DEVICE,
> -    .parent        = TYPE_PIIX3_PCI_DEVICE,
> -    .class_init    = piix3_class_init,
> -};
> -
> -static void piix3_xen_class_init(ObjectClass *klass, void *data)
> -{
> -    PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
> -
> -    k->config_write = piix3_write_config_xen;
> -};
> -
> -static const TypeInfo piix3_xen_info = {
> -    .name          = TYPE_PIIX3_XEN_DEVICE,
> -    .parent        = TYPE_PIIX3_PCI_DEVICE,
> -    .class_init    = piix3_xen_class_init,
> -};
> -
>  static void i440fx_class_init(ObjectClass *klass, void *data)
>  {
>      DeviceClass *dc = DEVICE_CLASS(klass);
> @@ -922,9 +523,6 @@ static void i440fx_register_types(void)
>  {
>      type_register_static(&i440fx_info);
>      type_register_static(&igd_passthrough_i440fx_info);
> -    type_register_static(&piix3_pci_type_info);
> -    type_register_static(&piix3_info);
> -    type_register_static(&piix3_xen_info);
>      type_register_static(&i440fx_pcihost_info);
>  }
>
> diff --git a/include/hw/southbridge/piix.h b/include/hw/southbridge/piix.h
> index 9c92c37a4d..324a3a99fc 100644
> --- a/include/hw/southbridge/piix.h
> +++ b/include/hw/southbridge/piix.h
> @@ -12,6 +12,8 @@
>  #ifndef HW_SOUTHBRIDGE_PIIX_H
>  #define HW_SOUTHBRIDGE_PIIX_H
>
> +#include "hw/pci/pci.h"
> +
>  #define TYPE_PIIX4_PM "PIIX4_PM"
>
>  I2CBus *piix4_pm_init(PCIBus *bus, int devfn, uint32_t smb_io_base,
> @@ -30,8 +32,42 @@ I2CBus *piix4_pm_init(PCIBus *bus, int devfn, uint32_t
> smb_io_base,
>   */
>  #define RCR_IOPORT 0xcf9
>
> +#define PIIX_NUM_PIC_IRQS       16      /* i8259 * 2 */
> +#define PIIX_NUM_PIRQS          4ULL    /* PIRQ[A-D] */
> +
> +typedef struct PIIXState {
> +    PCIDevice dev;
> +
> +    /*
> +     * bitmap to track pic levels.
> +     * The pic level is the logical OR of all the PCI irqs mapped to it
> +     * So one PIC level is tracked by PIIX_NUM_PIRQS bits.
> +     *
> +     * PIRQ is mapped to PIC pins, we track it by
> +     * PIIX_NUM_PIRQS * PIIX_NUM_PIC_IRQS = 64 bits with
> +     * pic_irq * PIIX_NUM_PIRQS + pirq
> +     */
> +#if PIIX_NUM_PIC_IRQS * PIIX_NUM_PIRQS > 64
> +#error "unable to encode pic state in 64bit in pic_levels."
> +#endif
> +    uint64_t pic_levels;
> +
> +    qemu_irq *pic;
> +
> +    /* This member isn't used. Just for save/load compatibility */
> +    int32_t pci_irq_levels_vmstate[PIIX_NUM_PIRQS];
> +
> +    /* Reset Control Register contents */
> +    uint8_t rcr;
> +
> +    /* IO memory region for Reset Control Register (RCR_IOPORT) */
> +    MemoryRegion rcr_mem;
> +} PIIX3State;
> +
>  extern PCIDevice *piix4_dev;
>
> +PIIX3State *piix3_create(PCIBus *pci_bus, ISABus **isa_bus);
> +
>  DeviceState *piix4_create(PCIBus *pci_bus, ISABus **isa_bus,
>                            I2CBus **smbus, size_t ide_buses);
>
> --
> 2.21.0
>
>
>
_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel

Reply via email to