diff options
author | Gerd Hoffmann <kraxel@redhat.com> | 2013-07-25 09:47:18 +0200 |
---|---|---|
committer | Gerd Hoffmann <kraxel@redhat.com> | 2013-08-08 11:14:42 +0200 |
commit | 5b63109242042372c1d6c3d23602e980f1c9637b (patch) | |
tree | 6bcfe70dc92b54dbc8cc223d975adeeee585dcba /src | |
parent | d4c2e01b8fe519d53244cd709ec145f7afaf1801 (diff) | |
download | seabios-hppa-5b63109242042372c1d6c3d23602e980f1c9637b.zip seabios-hppa-5b63109242042372c1d6c3d23602e980f1c9637b.tar.gz seabios-hppa-5b63109242042372c1d6c3d23602e980f1c9637b.tar.bz2 |
apm: fix shutdown
Qemu commit 9ee59f3 removed the bochs bios apm interface emulation at
port 0x8900. That broke poweroff via APM. Fix it by powering off the
machine using the acpi pm control register.
Old code is left in, so seabios wil try both poweroff methods. Cleaning
that eventually up is left for another patch, after checking it isn't
needed. Qemu never implemented "Standby" and "Suspend", only
"Shutdown", so it looks like there might be non-qemu use cases (bochs
probably).
Easiest way to test this is the syslinux poweroff module; modern linux
distros usually have CONFIG_APM turned off.
Reported-by: Sebastian Herbszt <herbszt@gmx.de>
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
Diffstat (limited to 'src')
-rw-r--r-- | src/acpi.c | 5 | ||||
-rw-r--r-- | src/acpi.h | 1 | ||||
-rw-r--r-- | src/apm.c | 5 | ||||
-rw-r--r-- | src/pciinit.c | 3 |
4 files changed, 14 insertions, 0 deletions
@@ -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); + 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 @@ -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) */ @@ -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 6d7f8fa..5259853 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 #define PCI_DEVICE_MEM_MIN 0x1000 #define PCI_BRIDGE_IO_MIN 0x1000 @@ -191,6 +192,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); } @@ -235,6 +237,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); } |