aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/acpi.c5
-rw-r--r--src/acpi.h1
-rw-r--r--src/apm.c5
-rw-r--r--src/pciinit.c3
4 files changed, 14 insertions, 0 deletions
diff --git a/src/acpi.c b/src/acpi.c
index 3699898..1994838 100644
--- a/src/acpi.c
+++ b/src/acpi.c
@@ -18,6 +18,8 @@
#include "acpi-dsdt.hex"
+u32 acpi_pm1a_cnt VARFSEG;
+
static void
build_header(struct acpi_table_header *h, u32 sig, int len, u8 rev)
{
@@ -730,9 +732,12 @@ find_acpi_features(void)
if (!fadt)
return;
u32 pm_tmr = le32_to_cpu(fadt->pm_tmr_blk);
+ u32 pm1a_cnt = le32_to_cpu(fadt->pm1a_cnt_blk);
dprintf(4, "pm_tmr_blk=%x\n", pm_tmr);
if (pm_tmr)
pmtimer_setup(pm_tmr, 3579);
+ if (pm1a_cnt)
+ acpi_pm1a_cnt = pm1a_cnt;
// Theoretically we should check the 'reset_reg_sup' flag, but Windows
// doesn't and thus nobody seems to *set* it. If the table is large enough
diff --git a/src/acpi.h b/src/acpi.h
index 5d1e104..f0d24d4 100644
--- a/src/acpi.h
+++ b/src/acpi.h
@@ -36,6 +36,7 @@ struct rsdp_descriptor { /* Root System Descriptor Pointer */
};
extern struct rsdp_descriptor *RsdpAddr;
+extern u32 acpi_pm1a_cnt;
/* Table structure from Linux kernel (the ACPI tables are under the
BSD license) */
diff --git a/src/apm.c b/src/apm.c
index b2eac6d..de6bd99 100644
--- a/src/apm.c
+++ b/src/apm.c
@@ -12,6 +12,7 @@
#include "config.h" // CONFIG_*
#include "biosvar.h" // GET_GLOBAL
#include "paravirt.h" // runningOnQEMU
+#include "acpi.h" // acpi_pm_ctl
static void
out_str(const char *str_cs)
@@ -108,7 +109,11 @@ handle_155306(struct bregs *regs)
void
apm_shutdown(void)
{
+ u16 pm1a_cnt = GET_GLOBAL(acpi_pm1a_cnt);
+
irq_disable();
+ if (pm1a_cnt)
+ outw(0x2000, pm1a_cnt);
out_str("Shutdown");
for (;;)
hlt();
diff --git a/src/pciinit.c b/src/pciinit.c
index 8370b96..0c6b0cb 100644
--- a/src/pciinit.c
+++ b/src/pciinit.c
@@ -15,6 +15,7 @@
#include "paravirt.h" // RamSize
#include "dev-q35.h" // Q35_HOST_BRIDGE_PCIEXBAR_ADDR
#include "list.h" // struct hlist_node
+#include "acpi.h" // acpi_pm1a_cnt
/* PM Timer ticks per second (HZ) */
#define PM_TIMER_FREQUENCY 3579545
@@ -194,6 +195,7 @@ void mch_isa_bridge_setup(struct pci_device *dev, void *arg)
/* acpi enable, SCI: IRQ9 000b = irq9*/
pci_config_writeb(bdf, ICH9_LPC_ACPI_CTRL, ICH9_LPC_ACPI_CTRL_ACPI_EN);
+ acpi_pm1a_cnt = PORT_ACPI_PM_BASE + 0x04;
pmtimer_setup(PORT_ACPI_PM_BASE + 0x08, PM_TIMER_FREQUENCY / 1000);
}
@@ -238,6 +240,7 @@ static void piix4_pm_setup(struct pci_device *pci, void *arg)
pci_config_writel(bdf, 0x90, PORT_SMB_BASE | 1);
pci_config_writeb(bdf, 0xd2, 0x09); /* enable SMBus io space */
+ acpi_pm1a_cnt = PORT_ACPI_PM_BASE + 0x04;
pmtimer_setup(PORT_ACPI_PM_BASE + 0x08, PM_TIMER_FREQUENCY / 1000);
}