Module Name: src Committed By: cegger Date: Thu Jun 18 11:14:14 UTC 2009
Modified Files: src/sys/arch/xen/xen [jym-xensuspend]: xen_acpi_machdep.c Log Message: implement ACPI S3 support for Dom0. ok jym@ To generate a diff of this commit: cvs rdiff -u -r1.4 -r1.4.24.1 src/sys/arch/xen/xen/xen_acpi_machdep.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sys/arch/xen/xen/xen_acpi_machdep.c diff -u src/sys/arch/xen/xen/xen_acpi_machdep.c:1.4 src/sys/arch/xen/xen/xen_acpi_machdep.c:1.4.24.1 --- src/sys/arch/xen/xen/xen_acpi_machdep.c:1.4 Sun Feb 17 14:03:16 2008 +++ src/sys/arch/xen/xen/xen_acpi_machdep.c Thu Jun 18 11:14:14 2009 @@ -1,18 +1,122 @@ -/* $NetBSD: xen_acpi_machdep.c,v 1.4 2008/02/17 14:03:16 bouyer Exp $ */ +/* $NetBSD: xen_acpi_machdep.c,v 1.4.24.1 2009/06/18 11:14:14 cegger Exp $ */ #include "acpi.h" #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: xen_acpi_machdep.c,v 1.4 2008/02/17 14:03:16 bouyer Exp $"); +__KERNEL_RCSID(0, "$NetBSD: xen_acpi_machdep.c,v 1.4.24.1 2009/06/18 11:14:14 cegger Exp $"); #include <dev/acpi/acpica.h> #include <dev/acpi/acpivar.h> #define ACPI_MACHDEP_PRIVATE #include <machine/acpi_machdep.h> +#include <xen/xen3-public/version.h> + +static int +xen_dom0_sleepenter(int sleep_state, int pm1a_control, int pm1b_control) +{ + struct xen_platform_op op = { + .cmd = XENPF_enter_acpi_sleep, + .interface_version = XENPF_INTERFACE_VERSION, + .u = { + .enter_acpi_sleep = { + .pm1a_cnt_val = pm1a_control, + .pm1b_cnt_val = pm1b_control, + .sleep_state = sleep_state, + }, + }, + }; + + return HYPERVISOR_platform_op(&op); +} + +static ACPI_STATUS +acpi_md_get_pm1controls(uint32_t *pm1a_control, uint32_t *pm1b_control) +{ + ACPI_STATUS status = 0; + uint32_t pm1a, pm1b; + struct acpi_bit_register_info *sleep_type_reg_info; + struct acpi_bit_register_info *sleep_enable_reg_info; + + *pm1a_control = *pm1b_control = 0; + + sleep_type_reg_info = + AcpiHwGetBitRegisterInfo(ACPI_BITREG_SLEEP_TYPE_A); + sleep_enable_reg_info = + AcpiHwGetBitRegisterInfo(ACPI_BITREG_SLEEP_ENABLE); + + status = AcpiHwRegisterRead(ACPI_MTX_DO_NOT_LOCK, + ACPI_REGISTER_PM1_CONTROL, &pm1a); + if (ACPI_FAILURE(status)) + return status; + + /* Clear SLP_EN and SLP_TYP fields */ + pm1a &= ~(sleep_type_reg_info->AccessBitMask | + sleep_enable_reg_info->AccessBitMask); + pm1b = pm1a; + + /* Insert SLP_TYP bits */ + pm1a |= (AcpiGbl_SleepTypeA << sleep_type_reg_info->BitPosition); + pm1b |= (AcpiGbl_SleepTypeB << sleep_type_reg_info->BitPosition); + + /* Split the writes of SLP_TYP and SLP_EN to workaround + * poorly implemented hardware + */ + + /* Write #1: fill in SLP_TYP data */ + status = AcpiHwRegisterWrite(ACPI_MTX_DO_NOT_LOCK, + ACPI_REGISTER_PM1A_CONTROL, + pm1a); + if (ACPI_FAILURE(status)) + return status; + + status = AcpiHwRegisterWrite(ACPI_MTX_DO_NOT_LOCK, + ACPI_REGISTER_PM1B_CONTROL, + pm1b); + if (ACPI_FAILURE(status)) + return status; + + /* Insert SLP_ENABLE bit */ + + pm1a |= sleep_enable_reg_info->AccessBitMask; + pm1b |= sleep_enable_reg_info->AccessBitMask; + + ACPI_FLUSH_CPU_CACHE(); + + *pm1a_control = pm1a; + *pm1b_control = pm1b; + + return status; +} int acpi_md_sleep(int state) { - printf("acpi: sleep not implemented\n"); - return (-1); + int error; + ACPI_STATUS status; + uint32_t pm1a_control, pm1b_control; + uint32_t xen_version, xen_vermajor, xen_verminor; + + xen_version = HYPERVISOR_xen_version(XENVER_version, NULL); + xen_vermajor = (xen_version & 0xffff0000) >> 16; + xen_verminor = (xen_version & 0x0000ffff); + + /* Xen version check. We require Xen 3.x */ + KASSERT(xen_vermajor >= 3); + + /* Xen 3.2 and older have no s3 support. */ + if (xen_verminor < 3) { + printf("xenacpi: Xen 3.2 and older have no S3 support.\n"); + return -1; + } + + status = acpi_md_get_pm1controls(&pm1a_control, &pm1b_control); + if (ACPI_FAILURE(status)) { + printf("xenacpi: can't enter sleep mode. acpi error %i\n", + status); + return -1; + } + + error = xen_dom0_sleepenter(state, pm1a_control, pm1b_control); + + return error; }