summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authornjl <njl@FreeBSD.org>2004-02-28 20:39:50 +0000
committernjl <njl@FreeBSD.org>2004-02-28 20:39:50 +0000
commitb81a1a09b72d7d2832f8e0c9ecb3be300cf350cc (patch)
tree0987a15ac5a18c7514ce44375ef9cf3856944d08
parentbdf79178fcecf52d3d625d734187bd4219e5865b (diff)
downloadFreeBSD-src-b81a1a09b72d7d2832f8e0c9ecb3be300cf350cc.zip
FreeBSD-src-b81a1a09b72d7d2832f8e0c9ecb3be300cf350cc.tar.gz
Local change: In the resume path, give up after waiting for a while
for WAK_STS to be set. Some BIOSs never set it.
-rw-r--r--sys/contrib/dev/acpica/hwsleep.c155
1 files changed, 123 insertions, 32 deletions
diff --git a/sys/contrib/dev/acpica/hwsleep.c b/sys/contrib/dev/acpica/hwsleep.c
index 6066752..ca0d057 100644
--- a/sys/contrib/dev/acpica/hwsleep.c
+++ b/sys/contrib/dev/acpica/hwsleep.c
@@ -2,7 +2,7 @@
/******************************************************************************
*
* Name: hwsleep.c - ACPI Hardware Sleep/Wake Interface
- * $Revision: 58 $
+ * $Revision: 65 $
*
*****************************************************************************/
@@ -10,7 +10,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2003, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2004, Intel Corp.
* All rights reserved.
*
* 2. License
@@ -121,6 +121,19 @@
ACPI_MODULE_NAME ("hwsleep")
+#define METHOD_NAME__BFS "\\_BFS"
+#define METHOD_NAME__GTS "\\_GTS"
+#define METHOD_NAME__PTS "\\_PTS"
+#define METHOD_NAME__SST "\\_SI._SST"
+#define METHOD_NAME__WAK "\\_WAK"
+
+#define ACPI_SST_INDICATOR_OFF 0
+#define ACPI_SST_WORKING 1
+#define ACPI_SST_WAKING 2
+#define ACPI_SST_SLEEPING 3
+#define ACPI_SST_SLEEP_CONTEXT 4
+
+
/******************************************************************************
*
* FUNCTION: AcpiSetFirmwareWakingVector
@@ -250,21 +263,44 @@ AcpiEnterSleepStatePrep (
/* Run the _PTS and _GTS methods */
- Status = AcpiEvaluateObject (NULL, "\\_PTS", &ArgList, NULL);
+ Status = AcpiEvaluateObject (NULL, METHOD_NAME__PTS, &ArgList, NULL);
if (ACPI_FAILURE (Status) && Status != AE_NOT_FOUND)
{
return_ACPI_STATUS (Status);
}
- Status = AcpiEvaluateObject (NULL, "\\_GTS", &ArgList, NULL);
+ Status = AcpiEvaluateObject (NULL, METHOD_NAME__GTS, &ArgList, NULL);
if (ACPI_FAILURE (Status) && Status != AE_NOT_FOUND)
{
return_ACPI_STATUS (Status);
}
+ /* Setup the argument to _SST */
+
+ switch (SleepState)
+ {
+ case ACPI_STATE_S0:
+ Arg.Integer.Value = ACPI_SST_WORKING;
+ break;
+
+ case ACPI_STATE_S1:
+ case ACPI_STATE_S2:
+ case ACPI_STATE_S3:
+ Arg.Integer.Value = ACPI_SST_SLEEPING;
+ break;
+
+ case ACPI_STATE_S4:
+ Arg.Integer.Value = ACPI_SST_SLEEP_CONTEXT;
+ break;
+
+ default:
+ Arg.Integer.Value = ACPI_SST_INDICATOR_OFF; /* Default is indicator off */
+ break;
+ }
+
/* Set the system indicators to show the desired sleep state. */
- Status = AcpiEvaluateObject (NULL, "\\_SI._SST", &ArgList, NULL);
+ Status = AcpiEvaluateObject (NULL, METHOD_NAME__SST, &ArgList, NULL);
if (ACPI_FAILURE (Status) && Status != AE_NOT_FOUND)
{
ACPI_REPORT_ERROR (("Method _SST failed, %s\n", AcpiFormatException (Status)));
@@ -339,7 +375,7 @@ AcpiEnterSleepState (
}
}
- Status = AcpiHwDisableNonWakeupGpes();
+ Status = AcpiHwDisableNonWakeupGpes ();
if (ACPI_FAILURE (Status))
{
return_ACPI_STATUS (Status);
@@ -364,6 +400,11 @@ AcpiEnterSleepState (
PM1AControl |= (AcpiGbl_SleepTypeA << SleepTypeRegInfo->BitPosition);
PM1BControl |= (AcpiGbl_SleepTypeB << SleepTypeRegInfo->BitPosition);
+ /*
+ * We 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, PM1AControl);
@@ -408,7 +449,7 @@ AcpiEnterSleepState (
* Wait ten seconds, then try again. This is to get S4/S5 to work on all machines.
*
* We wait so long to allow chipsets that poll this reg very slowly to
- * still read the right value. Ideally, this entire block would go
+ * still read the right value. Ideally, this block would go
* away entirely.
*/
AcpiOsStall (10000000);
@@ -473,12 +514,25 @@ AcpiEnterSleepStateS4bios (
ACPI_FUNCTION_TRACE ("AcpiEnterSleepStateS4bios");
- AcpiSetRegister (ACPI_BITREG_WAKE_STATUS, 1, ACPI_MTX_DO_NOT_LOCK);
- AcpiHwClearAcpiStatus(ACPI_MTX_DO_NOT_LOCK);
+ Status = AcpiSetRegister (ACPI_BITREG_WAKE_STATUS, 1, ACPI_MTX_DO_NOT_LOCK);
+ if (ACPI_FAILURE (Status))
+ {
+ return_ACPI_STATUS (Status);
+ }
- AcpiHwDisableNonWakeupGpes();
+ Status = AcpiHwClearAcpiStatus (ACPI_MTX_DO_NOT_LOCK);
+ if (ACPI_FAILURE (Status))
+ {
+ return_ACPI_STATUS (Status);
+ }
- ACPI_FLUSH_CPU_CACHE();
+ Status = AcpiHwDisableNonWakeupGpes ();
+ if (ACPI_FAILURE (Status))
+ {
+ return_ACPI_STATUS (Status);
+ }
+
+ ACPI_FLUSH_CPU_CACHE ();
Status = AcpiOsWritePort (AcpiGbl_FADT->SmiCmd, (UINT32) AcpiGbl_FADT->S4BiosReq, 8);
@@ -516,31 +570,49 @@ AcpiLeaveSleepState (
ACPI_STATUS Status;
ACPI_BIT_REGISTER_INFO *SleepTypeRegInfo;
ACPI_BIT_REGISTER_INFO *SleepEnableRegInfo;
- UINT32 PM1xControl;
+ UINT32 PM1AControl;
+ UINT32 PM1BControl;
ACPI_FUNCTION_TRACE ("AcpiLeaveSleepState");
- /* Some machines require SLP_TYPE and SLP_EN to be cleared */
- SleepTypeRegInfo = AcpiHwGetBitRegisterInfo (ACPI_BITREG_SLEEP_TYPE_A);
- SleepEnableRegInfo = AcpiHwGetBitRegisterInfo (ACPI_BITREG_SLEEP_ENABLE);
-
- /* Get current value of PM1A control */
-
- Status = AcpiHwRegisterRead (ACPI_MTX_DO_NOT_LOCK,
- ACPI_REGISTER_PM1_CONTROL, &PM1xControl);
+ /*
+ * Set SLP_TYPE and SLP_EN to state S0.
+ * This is unclear from the ACPI Spec, but it is required
+ * by some machines.
+ */
+ Status = AcpiGetSleepTypeData (ACPI_STATE_S0,
+ &AcpiGbl_SleepTypeA, &AcpiGbl_SleepTypeB);
if (ACPI_SUCCESS (Status))
{
- /* Clear SLP_TYP and SLP_EN */
+ SleepTypeRegInfo = AcpiHwGetBitRegisterInfo (ACPI_BITREG_SLEEP_TYPE_A);
+ SleepEnableRegInfo = AcpiHwGetBitRegisterInfo (ACPI_BITREG_SLEEP_ENABLE);
+
+ /* Get current value of PM1A control */
+
+ Status = AcpiHwRegisterRead (ACPI_MTX_DO_NOT_LOCK,
+ ACPI_REGISTER_PM1_CONTROL, &PM1AControl);
+ if (ACPI_SUCCESS (Status))
+ {
+ /* Clear SLP_EN and SLP_TYP fields */
+
+ PM1AControl &= ~(SleepTypeRegInfo->AccessBitMask |
+ SleepEnableRegInfo->AccessBitMask);
+ PM1BControl = PM1AControl;
+
+ /* Insert SLP_TYP bits */
+
+ PM1AControl |= (AcpiGbl_SleepTypeA << SleepTypeRegInfo->BitPosition);
+ PM1BControl |= (AcpiGbl_SleepTypeB << SleepTypeRegInfo->BitPosition);
- PM1xControl &= ~(SleepTypeRegInfo->AccessBitMask |
- SleepEnableRegInfo->AccessBitMask);
+ /* Just ignore any errors */
- AcpiHwRegisterWrite (ACPI_MTX_DO_NOT_LOCK,
- ACPI_REGISTER_PM1A_CONTROL, PM1xControl);
- AcpiHwRegisterWrite (ACPI_MTX_DO_NOT_LOCK,
- ACPI_REGISTER_PM1B_CONTROL, PM1xControl);
+ (void) AcpiHwRegisterWrite (ACPI_MTX_DO_NOT_LOCK,
+ ACPI_REGISTER_PM1A_CONTROL, PM1AControl);
+ (void) AcpiHwRegisterWrite (ACPI_MTX_DO_NOT_LOCK,
+ ACPI_REGISTER_PM1B_CONTROL, PM1BControl);
+ }
}
/* Ensure EnterSleepStatePrep -> EnterSleepState ordering */
@@ -555,21 +627,21 @@ AcpiLeaveSleepState (
/* Ignore any errors from these methods */
- Arg.Integer.Value = 0;
- Status = AcpiEvaluateObject (NULL, "\\_SI._SST", &ArgList, NULL);
+ Arg.Integer.Value = ACPI_SST_WAKING;
+ Status = AcpiEvaluateObject (NULL, METHOD_NAME__SST, &ArgList, NULL);
if (ACPI_FAILURE (Status) && Status != AE_NOT_FOUND)
{
ACPI_REPORT_ERROR (("Method _SST failed, %s\n", AcpiFormatException (Status)));
}
Arg.Integer.Value = SleepState;
- Status = AcpiEvaluateObject (NULL, "\\_BFS", &ArgList, NULL);
+ Status = AcpiEvaluateObject (NULL, METHOD_NAME__BFS, &ArgList, NULL);
if (ACPI_FAILURE (Status) && Status != AE_NOT_FOUND)
{
ACPI_REPORT_ERROR (("Method _BFS failed, %s\n", AcpiFormatException (Status)));
}
- Status = AcpiEvaluateObject (NULL, "\\_WAK", &ArgList, NULL);
+ Status = AcpiEvaluateObject (NULL, METHOD_NAME__WAK, &ArgList, NULL);
if (ACPI_FAILURE (Status) && Status != AE_NOT_FOUND)
{
ACPI_REPORT_ERROR (("Method _WAK failed, %s\n", AcpiFormatException (Status)));
@@ -577,14 +649,33 @@ AcpiLeaveSleepState (
/* _WAK returns stuff - do we want to look at it? */
- Status = AcpiHwEnableNonWakeupGpes();
+ Status = AcpiHwEnableNonWakeupGpes ();
if (ACPI_FAILURE (Status))
{
return_ACPI_STATUS (Status);
}
+ /* Enable power button */
+
+ AcpiSetRegister(AcpiGbl_FixedEventInfo[ACPI_EVENT_POWER_BUTTON].EnableRegisterId,
+ 1, ACPI_MTX_DO_NOT_LOCK);
+ AcpiSetRegister(AcpiGbl_FixedEventInfo[ACPI_EVENT_POWER_BUTTON].StatusRegisterId,
+ 1, ACPI_MTX_DO_NOT_LOCK);
+
/* Enable BM arbitration */
Status = AcpiSetRegister (ACPI_BITREG_ARB_DISABLE, 0, ACPI_MTX_LOCK);
+ if (ACPI_FAILURE (Status))
+ {
+ return_ACPI_STATUS (Status);
+ }
+
+ Arg.Integer.Value = ACPI_SST_WORKING;
+ Status = AcpiEvaluateObject (NULL, METHOD_NAME__SST, &ArgList, NULL);
+ if (ACPI_FAILURE (Status) && Status != AE_NOT_FOUND)
+ {
+ ACPI_REPORT_ERROR (("Method _SST failed, %s\n", AcpiFormatException (Status)));
+ }
+
return_ACPI_STATUS (Status);
}
OpenPOWER on IntegriCloud