From ab5add9a2f0b7d20b29894ce20fc4329ac5d892e Mon Sep 17 00:00:00 2001 From: Matt Borgerson Date: Tue, 2 Jun 2020 20:59:11 -0700 Subject: [PATCH] xbox: Add ACPI GPE0 block and support EXTSMI# --- hw/xbox/acpi_xbox.c | 46 ++++++++++++++++++++++++++++ hw/xbox/acpi_xbox.h | 1 + hw/xbox/xbox_pci.c | 28 +++++++++++------ include/hw/acpi/acpi_dev_interface.h | 3 ++ 4 files changed, 69 insertions(+), 9 deletions(-) diff --git a/hw/xbox/acpi_xbox.c b/hw/xbox/acpi_xbox.c index 22b737259e..4443f99e4f 100644 --- a/hw/xbox/acpi_xbox.c +++ b/hw/xbox/acpi_xbox.c @@ -2,6 +2,7 @@ * Xbox ACPI implementation * * Copyright (c) 2012 espes + * Copyright (c) 2020 Matt Borgerson * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -24,6 +25,7 @@ #include "hw/pci/pci.h" #include "qemu/timer.h" #include "sysemu/sysemu.h" +#include "sysemu/reset.h" #include "hw/acpi/acpi.h" #include "hw/xbox/xbox_pci.h" #include "hw/xbox/acpi_xbox.h" @@ -36,6 +38,8 @@ #endif #define XBOX_PM_BASE_BAR 0 +#define XBOX_PM_GPE_BASE 0x20 +#define XBOX_PM_GPE_LEN 4 #define XBOX_PM_GPIO_BASE 0xC0 #define XBOX_PM_GPIO_LEN 26 @@ -93,6 +97,42 @@ static void xbox_pm_update_sci_fn(ACPIREGS *regs) pm_update_sci(pm); } +static uint64_t xbox_pm_gpe_readb(void *opaque, hwaddr addr, unsigned width) +{ + XBOX_PMRegs *pm = opaque; + return acpi_gpe_ioport_readb(&pm->acpi_regs, addr); +} + +static void xbox_pm_gpe_writeb(void *opaque, hwaddr addr, uint64_t val, + unsigned width) +{ + XBOX_PMRegs *pm = opaque; + acpi_gpe_ioport_writeb(&pm->acpi_regs, addr, val); + acpi_update_sci(&pm->acpi_regs, pm->irq); +} + +static const MemoryRegionOps xbox_pm_gpe_ops = { + .read = xbox_pm_gpe_readb, + .write = xbox_pm_gpe_writeb, + .valid.min_access_size = 1, + .valid.max_access_size = 4, + .impl.min_access_size = 1, + .impl.max_access_size = 1, + .endianness = DEVICE_LITTLE_ENDIAN, +}; + +static void pm_reset(void *opaque) +{ + XBOX_PMRegs *pm = opaque; + + acpi_pm1_evt_reset(&pm->acpi_regs); + acpi_pm1_cnt_reset(&pm->acpi_regs); + acpi_pm_tmr_reset(&pm->acpi_regs); + acpi_gpe_reset(&pm->acpi_regs); + + acpi_update_sci(&pm->acpi_regs, pm->irq); +} + void xbox_pm_init(PCIDevice *dev, XBOX_PMRegs *pm, qemu_irq sci_irq) { memory_region_init(&pm->io, OBJECT(dev), "xbox-pm", 256); @@ -102,10 +142,16 @@ void xbox_pm_init(PCIDevice *dev, XBOX_PMRegs *pm, qemu_irq sci_irq) acpi_pm_tmr_init(&pm->acpi_regs, xbox_pm_update_sci_fn, &pm->io); acpi_pm1_evt_init(&pm->acpi_regs, xbox_pm_update_sci_fn, &pm->io); acpi_pm1_cnt_init(&pm->acpi_regs, &pm->io, true, true, 2); + acpi_gpe_init(&pm->acpi_regs, XBOX_PM_GPE_LEN); + + memory_region_init_io(&pm->io_gpe, OBJECT(dev), &xbox_pm_gpe_ops, pm, + "xbox-pm-gpe0", XBOX_PM_GPE_LEN); + memory_region_add_subregion(&pm->io, XBOX_PM_GPE_BASE, &pm->io_gpe); memory_region_init_io(&pm->io_gpio, OBJECT(dev), &xbox_pm_gpio_ops, pm, "xbox-pm-gpio", XBOX_PM_GPIO_LEN); memory_region_add_subregion(&pm->io, XBOX_PM_GPIO_BASE, &pm->io_gpio); pm->irq = sci_irq; + qemu_register_reset(pm_reset, pm); } diff --git a/hw/xbox/acpi_xbox.h b/hw/xbox/acpi_xbox.h index f84bb81beb..33ba66d033 100644 --- a/hw/xbox/acpi_xbox.h +++ b/hw/xbox/acpi_xbox.h @@ -26,6 +26,7 @@ typedef struct XBOX_PMRegs { ACPIREGS acpi_regs; MemoryRegion io; + MemoryRegion io_gpe; MemoryRegion io_gpio; qemu_irq irq; diff --git a/hw/xbox/xbox_pci.c b/hw/xbox/xbox_pci.c index 724ff3ad6b..67ed44cec3 100644 --- a/hw/xbox/xbox_pci.c +++ b/hw/xbox/xbox_pci.c @@ -2,7 +2,7 @@ * QEMU Xbox PCI buses implementation * * Copyright (c) 2012 espes - * Copyright (c) 2018 Matt Borgerson + * Copyright (c) 2018-2020 Matt Borgerson * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -351,23 +351,32 @@ static const VMStateDescription vmstate_xbox_lpc = { }; #endif +static void xbox_send_gpe(AcpiDeviceIf *adev, AcpiEventStatusBits ev) +{ + XBOX_LPCState *s = XBOX_LPC_DEVICE(adev); + + acpi_send_gpe_event(&s->pm.acpi_regs, s->pm.irq, ev); +} + static void xbox_lpc_class_init(ObjectClass *klass, void *data) { DeviceClass *dc = DEVICE_CLASS(klass); PCIDeviceClass *k = PCI_DEVICE_CLASS(klass); + AcpiDeviceIfClass *adevc = ACPI_DEVICE_IF_CLASS(klass); dc->hotpluggable = false; - k->realize = xbox_lpc_realize; + k->realize = xbox_lpc_realize; //k->config_write = xbox_lpc_config_write; - k->vendor_id = PCI_VENDOR_ID_NVIDIA; - k->device_id = PCI_DEVICE_ID_NVIDIA_NFORCE_LPC; - k->revision = 212; - k->class_id = PCI_CLASS_BRIDGE_ISA; + k->vendor_id = PCI_VENDOR_ID_NVIDIA; + k->device_id = PCI_DEVICE_ID_NVIDIA_NFORCE_LPC; + k->revision = 212; + k->class_id = PCI_CLASS_BRIDGE_ISA; - dc->desc = "nForce LPC Bridge"; + dc->desc = "nForce LPC Bridge"; dc->user_creatable = false; - dc->reset = xbox_lpc_reset; - //dc->vmsd = &vmstate_xbox_lpc; + dc->reset = xbox_lpc_reset; + //dc->vmsd = &vmstate_xbox_lpc; + adevc->send_event = xbox_send_gpe; } static const TypeInfo xbox_lpc_info = { @@ -376,6 +385,7 @@ static const TypeInfo xbox_lpc_info = { .instance_size = sizeof(XBOX_LPCState), .class_init = xbox_lpc_class_init, .interfaces = (InterfaceInfo[]) { + { TYPE_ACPI_DEVICE_IF }, { INTERFACE_CONVENTIONAL_PCI_DEVICE }, { }, }, diff --git a/include/hw/acpi/acpi_dev_interface.h b/include/hw/acpi/acpi_dev_interface.h index a2a12af9b9..8b5e4f9ed3 100644 --- a/include/hw/acpi/acpi_dev_interface.h +++ b/include/hw/acpi/acpi_dev_interface.h @@ -8,6 +8,9 @@ /* These values are part of guest ABI, and can not be changed */ typedef enum { +#ifdef XBOX + ACPI_EXTSMI_STATUS = 2, +#endif ACPI_PCI_HOTPLUG_STATUS = 2, ACPI_CPU_HOTPLUG_STATUS = 4, ACPI_MEMORY_HOTPLUG_STATUS = 8,