summaryrefslogtreecommitdiffstats
path: root/sys
diff options
context:
space:
mode:
authoriwasaki <iwasaki@FreeBSD.org>2001-03-07 15:22:14 +0000
committeriwasaki <iwasaki@FreeBSD.org>2001-03-07 15:22:14 +0000
commit0caeb6f1295e3da8bc213200024581effb320ee9 (patch)
tree6301526779bc355b88dbf3e6fd6fc7a23d72f1f9 /sys
parent7692afa933e49c4db66284c0e902d3113bd8dad3 (diff)
downloadFreeBSD-src-0caeb6f1295e3da8bc213200024581effb320ee9.zip
FreeBSD-src-0caeb6f1295e3da8bc213200024581effb320ee9.tar.gz
Bring our local hack for wakeup back from
sys/contrib/dev/acpica/Subsystem/Hardware/Attic/hwxface.c to the proper location after AcpiEnterSleepState(). - Wait for the WAK_STS bit - Evaluate the _WAK method and check result code
Diffstat (limited to 'sys')
-rw-r--r--sys/dev/acpica/acpi.c88
1 files changed, 88 insertions, 0 deletions
diff --git a/sys/dev/acpica/acpi.c b/sys/dev/acpica/acpi.c
index 77da421..7583acd 100644
--- a/sys/dev/acpica/acpi.c
+++ b/sys/dev/acpica/acpi.c
@@ -765,6 +765,92 @@ acpi_AllocBuffer(int size)
return(buf);
}
+static ACPI_STATUS __inline
+acpi_wakeup(UINT8 state)
+{
+ UINT16 Count;
+ ACPI_STATUS Status;
+ ACPI_OBJECT_LIST Arg_list;
+ ACPI_OBJECT Arg;
+ ACPI_OBJECT Objects[3]; /* package plus 2 number objects */
+ ACPI_BUFFER ReturnBuffer;
+
+ FUNCTION_TRACE_U32(__FUNCTION__, state);
+
+ /* wait for the WAK_STS bit */
+ Count = 0;
+ while (!(AcpiHwRegisterBitAccess(ACPI_READ, ACPI_MTX_LOCK, WAK_STS))) {
+ AcpiOsSleepUsec(1000);
+ /*
+ * Some BIOSes don't set WAK_STS at all,
+ * give up waiting for wakeup if we time out.
+ */
+ if (Count > 1000) {
+ break; /* giving up */
+ }
+ Count++;
+ }
+
+ /*
+ * Evaluate the _WAK method
+ */
+ MEMSET(&Arg_list, 0, sizeof(Arg_list));
+ Arg_list.Count = 1;
+ Arg_list.Pointer = &Arg;
+
+ MEMSET(&Arg, 0, sizeof(Arg));
+ Arg.Type = ACPI_TYPE_INTEGER;
+ Arg.Integer.Value = state;
+
+ /* Set up _WAK result code buffer */
+ MEMSET(Objects, 0, sizeof(Objects));
+ ReturnBuffer.Length = sizeof(Objects);
+ ReturnBuffer.Pointer = Objects;
+
+ AcpiEvaluateObject (NULL, "\\_WAK", &Arg_list, &ReturnBuffer);
+
+ Status = AE_OK;
+ /* Check result code for _WAK */
+ if (Objects[0].Type != ACPI_TYPE_PACKAGE ||
+ Objects[1].Type != ACPI_TYPE_INTEGER ||
+ Objects[2].Type != ACPI_TYPE_INTEGER) {
+ /*
+ * In many BIOSes, _WAK doesn't return a result code.
+ * We don't need to worry about it too much :-).
+ */
+ DEBUG_PRINT (ACPI_INFO,
+ ("acpi_wakeup: _WAK result code is corrupted, "
+ "but should be OK.\n"));
+ } else {
+ /* evaluate status code */
+ switch (Objects[1].Integer.Value) {
+ case 0x00000001:
+ DEBUG_PRINT (ACPI_ERROR,
+ ("acpi_wakeup: Wake was signaled "
+ "but failed due to lack of power.\n"));
+ Status = AE_ERROR;
+ break;
+
+ case 0x00000002:
+ DEBUG_PRINT (ACPI_ERROR,
+ ("acpi_wakeup: Wake was signaled "
+ "but failed due to thermal condition.\n"));
+ Status = AE_ERROR;
+ break;
+ }
+ /* evaluate PSS code */
+ if (Objects[2].Integer.Value == 0) {
+ DEBUG_PRINT (ACPI_ERROR,
+ ("acpi_wakeup: The targeted S-state "
+ "was not entered because of too much current "
+ "being drawn from the power supply.\n"));
+ Status = AE_ERROR;
+ }
+ }
+
+ return_ACPI_STATUS(Status);
+}
+
/*
* Set the system sleep state
*
@@ -804,7 +890,9 @@ acpi_SetSleepState(struct acpi_softc *sc, int state)
status = AcpiEnterSleepState((UINT8)state);
if (status != AE_OK) {
device_printf(sc->acpi_dev, "AcpiEnterSleepState failed - %s\n", acpi_strerror(status));
+ break;
}
+ acpi_wakeup((UINT8)state);
DEVICE_RESUME(root_bus);
sc->acpi_sstate = ACPI_STATE_S0;
acpi_enable_fixed_events(sc);
OpenPOWER on IntegriCloud