aboutsummaryrefslogtreecommitdiff
path: root/source/components/hardware
diff options
context:
space:
mode:
authorJung-uk Kim <jkim@FreeBSD.org>2012-02-16 00:24:10 +0000
committerJung-uk Kim <jkim@FreeBSD.org>2012-02-16 00:24:10 +0000
commit5437485bdb98c4b00f15969e013c454426e9c862 (patch)
tree71526afe7e3c45a4c88ba7b5d8d57d1e469feec2 /source/components/hardware
parent234358d94982312d34c80b868fea481307fb3a48 (diff)
downloadsrc-5437485bdb98c4b00f15969e013c454426e9c862.tar.gz
src-5437485bdb98c4b00f15969e013c454426e9c862.zip
Notes
Diffstat (limited to 'source/components/hardware')
-rw-r--r--source/components/hardware/hwacpi.c209
-rw-r--r--source/components/hardware/hwesleep.c263
-rw-r--r--source/components/hardware/hwgpe.c543
-rw-r--r--source/components/hardware/hwpci.c459
-rw-r--r--source/components/hardware/hwregs.c741
-rw-r--r--source/components/hardware/hwsleep.c384
-rw-r--r--source/components/hardware/hwtimer.c218
-rw-r--r--source/components/hardware/hwvalid.c368
-rw-r--r--source/components/hardware/hwxface.c617
-rw-r--r--source/components/hardware/hwxfsleep.c474
10 files changed, 4276 insertions, 0 deletions
diff --git a/source/components/hardware/hwacpi.c b/source/components/hardware/hwacpi.c
new file mode 100644
index 000000000000..d9f16ef9d767
--- /dev/null
+++ b/source/components/hardware/hwacpi.c
@@ -0,0 +1,209 @@
+
+/******************************************************************************
+ *
+ * Module Name: hwacpi - ACPI Hardware Initialization/Mode Interface
+ *
+ *****************************************************************************/
+
+/*
+ * Copyright (C) 2000 - 2012, Intel Corp.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions, and the following disclaimer,
+ * without modification.
+ * 2. Redistributions in binary form must reproduce at minimum a disclaimer
+ * substantially similar to the "NO WARRANTY" disclaimer below
+ * ("Disclaimer") and any redistribution must be conditioned upon
+ * including a substantially similar Disclaimer requirement for further
+ * binary redistribution.
+ * 3. Neither the names of the above-listed copyright holders nor the names
+ * of any contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * Alternatively, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") version 2 as published by the Free
+ * Software Foundation.
+ *
+ * NO WARRANTY
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGES.
+ */
+
+#define __HWACPI_C__
+
+#include "acpi.h"
+#include "accommon.h"
+
+
+#define _COMPONENT ACPI_HARDWARE
+ ACPI_MODULE_NAME ("hwacpi")
+
+
+#if (!ACPI_REDUCED_HARDWARE) /* Entire module */
+/******************************************************************************
+ *
+ * FUNCTION: AcpiHwSetMode
+ *
+ * PARAMETERS: Mode - SYS_MODE_ACPI or SYS_MODE_LEGACY
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Transitions the system into the requested mode.
+ *
+ ******************************************************************************/
+
+ACPI_STATUS
+AcpiHwSetMode (
+ UINT32 Mode)
+{
+
+ ACPI_STATUS Status;
+ UINT32 Retry;
+
+
+ ACPI_FUNCTION_TRACE (HwSetMode);
+
+ /*
+ * ACPI 2.0 clarified that if SMI_CMD in FADT is zero,
+ * system does not support mode transition.
+ */
+ if (!AcpiGbl_FADT.SmiCommand)
+ {
+ ACPI_ERROR ((AE_INFO, "No SMI_CMD in FADT, mode transition failed"));
+ return_ACPI_STATUS (AE_NO_HARDWARE_RESPONSE);
+ }
+
+ /*
+ * ACPI 2.0 clarified the meaning of ACPI_ENABLE and ACPI_DISABLE
+ * in FADT: If it is zero, enabling or disabling is not supported.
+ * As old systems may have used zero for mode transition,
+ * we make sure both the numbers are zero to determine these
+ * transitions are not supported.
+ */
+ if (!AcpiGbl_FADT.AcpiEnable && !AcpiGbl_FADT.AcpiDisable)
+ {
+ ACPI_ERROR ((AE_INFO,
+ "No ACPI mode transition supported in this system "
+ "(enable/disable both zero)"));
+ return_ACPI_STATUS (AE_OK);
+ }
+
+ switch (Mode)
+ {
+ case ACPI_SYS_MODE_ACPI:
+
+ /* BIOS should have disabled ALL fixed and GP events */
+
+ Status = AcpiHwWritePort (AcpiGbl_FADT.SmiCommand,
+ (UINT32) AcpiGbl_FADT.AcpiEnable, 8);
+ ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Attempting to enable ACPI mode\n"));
+ break;
+
+ case ACPI_SYS_MODE_LEGACY:
+
+ /*
+ * BIOS should clear all fixed status bits and restore fixed event
+ * enable bits to default
+ */
+ Status = AcpiHwWritePort (AcpiGbl_FADT.SmiCommand,
+ (UINT32) AcpiGbl_FADT.AcpiDisable, 8);
+ ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
+ "Attempting to enable Legacy (non-ACPI) mode\n"));
+ break;
+
+ default:
+ return_ACPI_STATUS (AE_BAD_PARAMETER);
+ }
+
+ if (ACPI_FAILURE (Status))
+ {
+ ACPI_EXCEPTION ((AE_INFO, Status,
+ "Could not write ACPI mode change"));
+ return_ACPI_STATUS (Status);
+ }
+
+ /*
+ * Some hardware takes a LONG time to switch modes. Give them 3 sec to
+ * do so, but allow faster systems to proceed more quickly.
+ */
+ Retry = 3000;
+ while (Retry)
+ {
+ if (AcpiHwGetMode() == Mode)
+ {
+ ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Mode %X successfully enabled\n",
+ Mode));
+ return_ACPI_STATUS (AE_OK);
+ }
+ AcpiOsStall(1000);
+ Retry--;
+ }
+
+ ACPI_ERROR ((AE_INFO, "Hardware did not change modes"));
+ return_ACPI_STATUS (AE_NO_HARDWARE_RESPONSE);
+}
+
+
+/*******************************************************************************
+ *
+ * FUNCTION: AcpiHwGetMode
+ *
+ * PARAMETERS: none
+ *
+ * RETURN: SYS_MODE_ACPI or SYS_MODE_LEGACY
+ *
+ * DESCRIPTION: Return current operating state of system. Determined by
+ * querying the SCI_EN bit.
+ *
+ ******************************************************************************/
+
+UINT32
+AcpiHwGetMode (
+ void)
+{
+ ACPI_STATUS Status;
+ UINT32 Value;
+
+
+ ACPI_FUNCTION_TRACE (HwGetMode);
+
+
+ /*
+ * ACPI 2.0 clarified that if SMI_CMD in FADT is zero,
+ * system does not support mode transition.
+ */
+ if (!AcpiGbl_FADT.SmiCommand)
+ {
+ return_UINT32 (ACPI_SYS_MODE_ACPI);
+ }
+
+ Status = AcpiReadBitRegister (ACPI_BITREG_SCI_ENABLE, &Value);
+ if (ACPI_FAILURE (Status))
+ {
+ return_UINT32 (ACPI_SYS_MODE_LEGACY);
+ }
+
+ if (Value)
+ {
+ return_UINT32 (ACPI_SYS_MODE_ACPI);
+ }
+ else
+ {
+ return_UINT32 (ACPI_SYS_MODE_LEGACY);
+ }
+}
+
+#endif /* !ACPI_REDUCED_HARDWARE */
diff --git a/source/components/hardware/hwesleep.c b/source/components/hardware/hwesleep.c
new file mode 100644
index 000000000000..e95647e5cd19
--- /dev/null
+++ b/source/components/hardware/hwesleep.c
@@ -0,0 +1,263 @@
+/******************************************************************************
+ *
+ * Name: hwesleep.c - ACPI Hardware Sleep/Wake Support functions for the
+ * extended FADT-V5 sleep registers.
+ *
+ *****************************************************************************/
+
+/*
+ * Copyright (C) 2000 - 2012, Intel Corp.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions, and the following disclaimer,
+ * without modification.
+ * 2. Redistributions in binary form must reproduce at minimum a disclaimer
+ * substantially similar to the "NO WARRANTY" disclaimer below
+ * ("Disclaimer") and any redistribution must be conditioned upon
+ * including a substantially similar Disclaimer requirement for further
+ * binary redistribution.
+ * 3. Neither the names of the above-listed copyright holders nor the names
+ * of any contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * Alternatively, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") version 2 as published by the Free
+ * Software Foundation.
+ *
+ * NO WARRANTY
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGES.
+ */
+
+#include "acpi.h"
+#include "accommon.h"
+
+#define _COMPONENT ACPI_HARDWARE
+ ACPI_MODULE_NAME ("hwesleep")
+
+
+/*******************************************************************************
+ *
+ * FUNCTION: AcpiHwExecuteSleepMethod
+ *
+ * PARAMETERS: MethodName - Pathname of method to execute
+ * IntegerArgument - Argument to pass to the method
+ *
+ * RETURN: None
+ *
+ * DESCRIPTION: Execute a sleep/wake related method with one integer argument
+ * and no return value.
+ *
+ ******************************************************************************/
+
+void
+AcpiHwExecuteSleepMethod (
+ char *MethodName,
+ UINT32 IntegerArgument)
+{
+ ACPI_OBJECT_LIST ArgList;
+ ACPI_OBJECT Arg;
+ ACPI_STATUS Status;
+
+
+ ACPI_FUNCTION_TRACE (HwExecuteSleepMethod);
+
+
+ /* One argument, IntegerArgument; No return value expected */
+
+ ArgList.Count = 1;
+ ArgList.Pointer = &Arg;
+ Arg.Type = ACPI_TYPE_INTEGER;
+ Arg.Integer.Value = (UINT64) IntegerArgument;
+
+ Status = AcpiEvaluateObject (NULL, MethodName, &ArgList, NULL);
+ if (ACPI_FAILURE (Status) && Status != AE_NOT_FOUND)
+ {
+ ACPI_EXCEPTION ((AE_INFO, Status, "While executing method %s",
+ MethodName));
+ }
+
+ return_VOID;
+}
+
+
+/*******************************************************************************
+ *
+ * FUNCTION: AcpiHwExtendedSleep
+ *
+ * PARAMETERS: SleepState - Which sleep state to enter
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Enter a system sleep state via the extended FADT sleep
+ * registers (V5 FADT).
+ * THIS FUNCTION MUST BE CALLED WITH INTERRUPTS DISABLED
+ *
+ ******************************************************************************/
+
+ACPI_STATUS
+AcpiHwExtendedSleep (
+ UINT8 SleepState)
+{
+ ACPI_STATUS Status;
+ UINT8 SleepTypeValue;
+ UINT64 SleepStatus;
+
+
+ ACPI_FUNCTION_TRACE (HwExtendedSleep);
+
+
+ /* Extended sleep registers must be valid */
+
+ if (!AcpiGbl_FADT.SleepControl.Address ||
+ !AcpiGbl_FADT.SleepStatus.Address)
+ {
+ return_ACPI_STATUS (AE_NOT_EXIST);
+ }
+
+ /* Clear wake status (WAK_STS) */
+
+ Status = AcpiWrite (ACPI_X_WAKE_STATUS, &AcpiGbl_FADT.SleepStatus);
+ if (ACPI_FAILURE (Status))
+ {
+ return_ACPI_STATUS (Status);
+ }
+
+ AcpiGbl_SystemAwakeAndRunning = FALSE;
+
+ /* Execute the _GTS method (Going To Sleep) */
+
+ AcpiHwExecuteSleepMethod (METHOD_NAME__GTS, SleepState);
+
+ /* Flush caches, as per ACPI specification */
+
+ ACPI_FLUSH_CPU_CACHE ();
+
+ /*
+ * Set the SLP_TYP and SLP_EN bits.
+ *
+ * Note: We only use the first value returned by the \_Sx method
+ * (AcpiGbl_SleepTypeA) - As per ACPI specification.
+ */
+ ACPI_DEBUG_PRINT ((ACPI_DB_INIT,
+ "Entering sleep state [S%u]\n", SleepState));
+
+ SleepTypeValue = ((AcpiGbl_SleepTypeA << ACPI_X_SLEEP_TYPE_POSITION) &
+ ACPI_X_SLEEP_TYPE_MASK);
+
+ Status = AcpiWrite ((SleepTypeValue | ACPI_X_SLEEP_ENABLE),
+ &AcpiGbl_FADT.SleepControl);
+ if (ACPI_FAILURE (Status))
+ {
+ return_ACPI_STATUS (Status);
+ }
+
+ /* Wait for transition back to Working State */
+
+ do
+ {
+ Status = AcpiRead (&SleepStatus, &AcpiGbl_FADT.SleepStatus);
+ if (ACPI_FAILURE (Status))
+ {
+ return_ACPI_STATUS (Status);
+ }
+
+ } while (!(((UINT8) SleepStatus) & ACPI_X_WAKE_STATUS));
+
+ return_ACPI_STATUS (AE_OK);
+}
+
+
+/*******************************************************************************
+ *
+ * FUNCTION: AcpiHwExtendedWakePrep
+ *
+ * PARAMETERS: SleepState - Which sleep state we just exited
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Perform first part of OS-independent ACPI cleanup after
+ * a sleep. Called with interrupts ENABLED.
+ *
+ ******************************************************************************/
+
+ACPI_STATUS
+AcpiHwExtendedWakePrep (
+ UINT8 SleepState)
+{
+ ACPI_STATUS Status;
+ UINT8 SleepTypeValue;
+
+
+ ACPI_FUNCTION_TRACE (HwExtendedWakePrep);
+
+
+ Status = AcpiGetSleepTypeData (ACPI_STATE_S0,
+ &AcpiGbl_SleepTypeA, &AcpiGbl_SleepTypeB);
+ if (ACPI_SUCCESS (Status))
+ {
+ SleepTypeValue = ((AcpiGbl_SleepTypeA << ACPI_X_SLEEP_TYPE_POSITION) &
+ ACPI_X_SLEEP_TYPE_MASK);
+
+ (void) AcpiWrite ((SleepTypeValue | ACPI_X_SLEEP_ENABLE),
+ &AcpiGbl_FADT.SleepControl);
+ }
+
+ AcpiHwExecuteSleepMethod (METHOD_NAME__BFS, SleepState);
+ return_ACPI_STATUS (AE_OK);
+}
+
+
+/*******************************************************************************
+ *
+ * FUNCTION: AcpiHwExtendedWake
+ *
+ * PARAMETERS: SleepState - Which sleep state we just exited
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Perform OS-independent ACPI cleanup after a sleep
+ * Called with interrupts ENABLED.
+ *
+ ******************************************************************************/
+
+ACPI_STATUS
+AcpiHwExtendedWake (
+ UINT8 SleepState)
+{
+ ACPI_FUNCTION_TRACE (HwExtendedWake);
+
+
+ /* Ensure EnterSleepStatePrep -> EnterSleepState ordering */
+
+ AcpiGbl_SleepTypeA = ACPI_SLEEP_TYPE_INVALID;
+
+ /* Execute the wake methods */
+
+ AcpiHwExecuteSleepMethod (METHOD_NAME__SST, ACPI_SST_WAKING);
+ AcpiHwExecuteSleepMethod (METHOD_NAME__WAK, SleepState);
+
+ /*
+ * Some BIOS code assumes that WAK_STS will be cleared on resume
+ * and use it to determine whether the system is rebooting or
+ * resuming. Clear WAK_STS for compatibility.
+ */
+ (void) AcpiWrite (ACPI_X_WAKE_STATUS, &AcpiGbl_FADT.SleepStatus);
+ AcpiGbl_SystemAwakeAndRunning = TRUE;
+
+ AcpiHwExecuteSleepMethod (METHOD_NAME__SST, ACPI_SST_WORKING);
+ return_ACPI_STATUS (AE_OK);
+}
diff --git a/source/components/hardware/hwgpe.c b/source/components/hardware/hwgpe.c
new file mode 100644
index 000000000000..c94f17be260e
--- /dev/null
+++ b/source/components/hardware/hwgpe.c
@@ -0,0 +1,543 @@
+
+/******************************************************************************
+ *
+ * Module Name: hwgpe - Low level GPE enable/disable/clear functions
+ *
+ *****************************************************************************/
+
+/*
+ * Copyright (C) 2000 - 2012, Intel Corp.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions, and the following disclaimer,
+ * without modification.
+ * 2. Redistributions in binary form must reproduce at minimum a disclaimer
+ * substantially similar to the "NO WARRANTY" disclaimer below
+ * ("Disclaimer") and any redistribution must be conditioned upon
+ * including a substantially similar Disclaimer requirement for further
+ * binary redistribution.
+ * 3. Neither the names of the above-listed copyright holders nor the names
+ * of any contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * Alternatively, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") version 2 as published by the Free
+ * Software Foundation.
+ *
+ * NO WARRANTY
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGES.
+ */
+
+#include "acpi.h"
+#include "accommon.h"
+#include "acevents.h"
+
+#define _COMPONENT ACPI_HARDWARE
+ ACPI_MODULE_NAME ("hwgpe")
+
+#if (!ACPI_REDUCED_HARDWARE) /* Entire module */
+
+/* Local prototypes */
+
+static ACPI_STATUS
+AcpiHwEnableWakeupGpeBlock (
+ ACPI_GPE_XRUPT_INFO *GpeXruptInfo,
+ ACPI_GPE_BLOCK_INFO *GpeBlock,
+ void *Context);
+
+
+/******************************************************************************
+ *
+ * FUNCTION: AcpiHwGetGpeRegisterBit
+ *
+ * PARAMETERS: GpeEventInfo - Info block for the GPE
+ * GpeRegisterInfo - Info block for the GPE register
+ *
+ * RETURN: Register mask with a one in the GPE bit position
+ *
+ * DESCRIPTION: Compute the register mask for this GPE. One bit is set in the
+ * correct position for the input GPE.
+ *
+ ******************************************************************************/
+
+UINT32
+AcpiHwGetGpeRegisterBit (
+ ACPI_GPE_EVENT_INFO *GpeEventInfo,
+ ACPI_GPE_REGISTER_INFO *GpeRegisterInfo)
+{
+
+ return ((UINT32) 1 <<
+ (GpeEventInfo->GpeNumber - GpeRegisterInfo->BaseGpeNumber));
+}
+
+
+/******************************************************************************
+ *
+ * FUNCTION: AcpiHwLowSetGpe
+ *
+ * PARAMETERS: GpeEventInfo - Info block for the GPE to be disabled
+ * Action - Enable or disable
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Enable or disable a single GPE in the parent enable register.
+ *
+ ******************************************************************************/
+
+ACPI_STATUS
+AcpiHwLowSetGpe (
+ ACPI_GPE_EVENT_INFO *GpeEventInfo,
+ UINT32 Action)
+{
+ ACPI_GPE_REGISTER_INFO *GpeRegisterInfo;
+ ACPI_STATUS Status;
+ UINT32 EnableMask;
+ UINT32 RegisterBit;
+
+
+ ACPI_FUNCTION_ENTRY ();
+
+
+ /* Get the info block for the entire GPE register */
+
+ GpeRegisterInfo = GpeEventInfo->RegisterInfo;
+ if (!GpeRegisterInfo)
+ {
+ return (AE_NOT_EXIST);
+ }
+
+ /* Get current value of the enable register that contains this GPE */
+
+ Status = AcpiHwRead (&EnableMask, &GpeRegisterInfo->EnableAddress);
+ if (ACPI_FAILURE (Status))
+ {
+ return (Status);
+ }
+
+ /* Set or clear just the bit that corresponds to this GPE */
+
+ RegisterBit = AcpiHwGetGpeRegisterBit (GpeEventInfo, GpeRegisterInfo);
+ switch (Action)
+ {
+ case ACPI_GPE_CONDITIONAL_ENABLE:
+
+ /* Only enable if the EnableForRun bit is set */
+
+ if (!(RegisterBit & GpeRegisterInfo->EnableForRun))
+ {
+ return (AE_BAD_PARAMETER);
+ }
+
+ /*lint -fallthrough */
+
+ case ACPI_GPE_ENABLE:
+ ACPI_SET_BIT (EnableMask, RegisterBit);
+ break;
+
+ case ACPI_GPE_DISABLE:
+ ACPI_CLEAR_BIT (EnableMask, RegisterBit);
+ break;
+
+ default:
+ ACPI_ERROR ((AE_INFO, "Invalid GPE Action, %u\n", Action));
+ return (AE_BAD_PARAMETER);
+ }
+
+ /* Write the updated enable mask */
+
+ Status = AcpiHwWrite (EnableMask, &GpeRegisterInfo->EnableAddress);
+ return (Status);
+}
+
+
+/******************************************************************************
+ *
+ * FUNCTION: AcpiHwClearGpe
+ *
+ * PARAMETERS: GpeEventInfo - Info block for the GPE to be cleared
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Clear the status bit for a single GPE.
+ *
+ ******************************************************************************/
+
+ACPI_STATUS
+AcpiHwClearGpe (
+ ACPI_GPE_EVENT_INFO *GpeEventInfo)
+{
+ ACPI_GPE_REGISTER_INFO *GpeRegisterInfo;
+ ACPI_STATUS Status;
+ UINT32 RegisterBit;
+
+
+ ACPI_FUNCTION_ENTRY ();
+
+ /* Get the info block for the entire GPE register */
+
+ GpeRegisterInfo = GpeEventInfo->RegisterInfo;
+ if (!GpeRegisterInfo)
+ {
+ return (AE_NOT_EXIST);
+ }
+
+ /*
+ * Write a one to the appropriate bit in the status register to
+ * clear this GPE.
+ */
+ RegisterBit = AcpiHwGetGpeRegisterBit (GpeEventInfo, GpeRegisterInfo);
+
+ Status = AcpiHwWrite (RegisterBit,
+ &GpeRegisterInfo->StatusAddress);
+
+ return (Status);
+}
+
+
+/******************************************************************************
+ *
+ * FUNCTION: AcpiHwGetGpeStatus
+ *
+ * PARAMETERS: GpeEventInfo - Info block for the GPE to queried
+ * EventStatus - Where the GPE status is returned
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Return the status of a single GPE.
+ *
+ ******************************************************************************/
+
+ACPI_STATUS
+AcpiHwGetGpeStatus (
+ ACPI_GPE_EVENT_INFO *GpeEventInfo,
+ ACPI_EVENT_STATUS *EventStatus)
+{
+ UINT32 InByte;
+ UINT32 RegisterBit;
+ ACPI_GPE_REGISTER_INFO *GpeRegisterInfo;
+ ACPI_EVENT_STATUS LocalEventStatus = 0;
+ ACPI_STATUS Status;
+
+
+ ACPI_FUNCTION_ENTRY ();
+
+
+ if (!EventStatus)
+ {
+ return (AE_BAD_PARAMETER);
+ }
+
+ /* Get the info block for the entire GPE register */
+
+ GpeRegisterInfo = GpeEventInfo->RegisterInfo;
+
+ /* Get the register bitmask for this GPE */
+
+ RegisterBit = AcpiHwGetGpeRegisterBit (GpeEventInfo, GpeRegisterInfo);
+
+ /* GPE currently enabled? (enabled for runtime?) */
+
+ if (RegisterBit & GpeRegisterInfo->EnableForRun)
+ {
+ LocalEventStatus |= ACPI_EVENT_FLAG_ENABLED;
+ }
+
+ /* GPE enabled for wake? */
+
+ if (RegisterBit & GpeRegisterInfo->EnableForWake)
+ {
+ LocalEventStatus |= ACPI_EVENT_FLAG_WAKE_ENABLED;
+ }
+
+ /* GPE currently active (status bit == 1)? */
+
+ Status = AcpiHwRead (&InByte, &GpeRegisterInfo->StatusAddress);
+ if (ACPI_FAILURE (Status))
+ {
+ return (Status);
+ }
+
+ if (RegisterBit & InByte)
+ {
+ LocalEventStatus |= ACPI_EVENT_FLAG_SET;
+ }
+
+ /* Set return value */
+
+ (*EventStatus) = LocalEventStatus;
+ return (AE_OK);
+}
+
+
+/******************************************************************************
+ *
+ * FUNCTION: AcpiHwDisableGpeBlock
+ *
+ * PARAMETERS: GpeXruptInfo - GPE Interrupt info
+ * GpeBlock - Gpe Block info
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Disable all GPEs within a single GPE block
+ *
+ ******************************************************************************/
+
+ACPI_STATUS
+AcpiHwDisableGpeBlock (
+ ACPI_GPE_XRUPT_INFO *GpeXruptInfo,
+ ACPI_GPE_BLOCK_INFO *GpeBlock,
+ void *Context)
+{
+ UINT32 i;
+ ACPI_STATUS Status;
+
+
+ /* Examine each GPE Register within the block */
+
+ for (i = 0; i < GpeBlock->RegisterCount; i++)
+ {
+ /* Disable all GPEs in this register */
+
+ Status = AcpiHwWrite (0x00, &GpeBlock->RegisterInfo[i].EnableAddress);
+ if (ACPI_FAILURE (Status))
+ {
+ return (Status);
+ }
+ }
+
+ return (AE_OK);
+}
+
+
+/******************************************************************************
+ *
+ * FUNCTION: AcpiHwClearGpeBlock
+ *
+ * PARAMETERS: GpeXruptInfo - GPE Interrupt info
+ * GpeBlock - Gpe Block info
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Clear status bits for all GPEs within a single GPE block
+ *
+ ******************************************************************************/
+
+ACPI_STATUS
+AcpiHwClearGpeBlock (
+ ACPI_GPE_XRUPT_INFO *GpeXruptInfo,
+ ACPI_GPE_BLOCK_INFO *GpeBlock,
+ void *Context)
+{
+ UINT32 i;
+ ACPI_STATUS Status;
+
+
+ /* Examine each GPE Register within the block */
+
+ for (i = 0; i < GpeBlock->RegisterCount; i++)
+ {
+ /* Clear status on all GPEs in this register */
+
+ Status = AcpiHwWrite (0xFF, &GpeBlock->RegisterInfo[i].StatusAddress);
+ if (ACPI_FAILURE (Status))
+ {
+ return (Status);
+ }
+ }
+
+ return (AE_OK);
+}
+
+
+/******************************************************************************
+ *
+ * FUNCTION: AcpiHwEnableRuntimeGpeBlock
+ *
+ * PARAMETERS: GpeXruptInfo - GPE Interrupt info
+ * GpeBlock - Gpe Block info
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Enable all "runtime" GPEs within a single GPE block. Includes
+ * combination wake/run GPEs.
+ *
+ ******************************************************************************/
+
+ACPI_STATUS
+AcpiHwEnableRuntimeGpeBlock (
+ ACPI_GPE_XRUPT_INFO *GpeXruptInfo,
+ ACPI_GPE_BLOCK_INFO *GpeBlock,
+ void *Context)
+{
+ UINT32 i;
+ ACPI_STATUS Status;
+
+
+ /* NOTE: assumes that all GPEs are currently disabled */
+
+ /* Examine each GPE Register within the block */
+
+ for (i = 0; i < GpeBlock->RegisterCount; i++)
+ {
+ if (!GpeBlock->RegisterInfo[i].EnableForRun)
+ {
+ continue;
+ }
+
+ /* Enable all "runtime" GPEs in this register */
+
+ Status = AcpiHwWrite (GpeBlock->RegisterInfo[i].EnableForRun,
+ &GpeBlock->RegisterInfo[i].EnableAddress);
+ if (ACPI_FAILURE (Status))
+ {
+ return (Status);
+ }
+ }
+
+ return (AE_OK);
+}
+
+
+/******************************************************************************
+ *
+ * FUNCTION: AcpiHwEnableWakeupGpeBlock
+ *
+ * PARAMETERS: GpeXruptInfo - GPE Interrupt info
+ * GpeBlock - Gpe Block info
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Enable all "wake" GPEs within a single GPE block. Includes
+ * combination wake/run GPEs.
+ *
+ ******************************************************************************/
+
+static ACPI_STATUS
+AcpiHwEnableWakeupGpeBlock (
+ ACPI_GPE_XRUPT_INFO *GpeXruptInfo,
+ ACPI_GPE_BLOCK_INFO *GpeBlock,
+ void *Context)
+{
+ UINT32 i;
+ ACPI_STATUS Status;
+
+
+ /* Examine each GPE Register within the block */
+
+ for (i = 0; i < GpeBlock->RegisterCount; i++)
+ {
+ if (!GpeBlock->RegisterInfo[i].EnableForWake)
+ {
+ continue;
+ }
+
+ /* Enable all "wake" GPEs in this register */
+
+ Status = AcpiHwWrite (GpeBlock->RegisterInfo[i].EnableForWake,
+ &GpeBlock->RegisterInfo[i].EnableAddress);
+ if (ACPI_FAILURE (Status))
+ {
+ return (Status);
+ }
+ }
+
+ return (AE_OK);
+}
+
+
+/******************************************************************************
+ *
+ * FUNCTION: AcpiHwDisableAllGpes
+ *
+ * PARAMETERS: None
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Disable and clear all GPEs in all GPE blocks
+ *
+ ******************************************************************************/
+
+ACPI_STATUS
+AcpiHwDisableAllGpes (
+ void)
+{
+ ACPI_STATUS Status;
+
+
+ ACPI_FUNCTION_TRACE (HwDisableAllGpes);
+
+
+ Status = AcpiEvWalkGpeList (AcpiHwDisableGpeBlock, NULL);
+ Status = AcpiEvWalkGpeList (AcpiHwClearGpeBlock, NULL);
+ return_ACPI_STATUS (Status);
+}
+
+
+/******************************************************************************
+ *
+ * FUNCTION: AcpiHwEnableAllRuntimeGpes
+ *
+ * PARAMETERS: None
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Enable all "runtime" GPEs, in all GPE blocks
+ *
+ ******************************************************************************/
+
+ACPI_STATUS
+AcpiHwEnableAllRuntimeGpes (
+ void)
+{
+ ACPI_STATUS Status;
+
+
+ ACPI_FUNCTION_TRACE (HwEnableAllRuntimeGpes);
+
+
+ Status = AcpiEvWalkGpeList (AcpiHwEnableRuntimeGpeBlock, NULL);
+ return_ACPI_STATUS (Status);
+}
+
+
+/******************************************************************************
+ *
+ * FUNCTION: AcpiHwEnableAllWakeupGpes
+ *
+ * PARAMETERS: None
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Enable all "wakeup" GPEs, in all GPE blocks
+ *
+ ******************************************************************************/
+
+ACPI_STATUS
+AcpiHwEnableAllWakeupGpes (
+ void)
+{
+ ACPI_STATUS Status;
+
+
+ ACPI_FUNCTION_TRACE (HwEnableAllWakeupGpes);
+
+
+ Status = AcpiEvWalkGpeList (AcpiHwEnableWakeupGpeBlock, NULL);
+ return_ACPI_STATUS (Status);
+}
+
+#endif /* !ACPI_REDUCED_HARDWARE */
diff --git a/source/components/hardware/hwpci.c b/source/components/hardware/hwpci.c
new file mode 100644
index 000000000000..065e42d95eb6
--- /dev/null
+++ b/source/components/hardware/hwpci.c
@@ -0,0 +1,459 @@
+/*******************************************************************************
+ *
+ * Module Name: hwpci - Obtain PCI bus, device, and function numbers
+ *
+ ******************************************************************************/
+
+/*
+ * Copyright (C) 2000 - 2012, Intel Corp.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions, and the following disclaimer,
+ * without modification.
+ * 2. Redistributions in binary form must reproduce at minimum a disclaimer
+ * substantially similar to the "NO WARRANTY" disclaimer below
+ * ("Disclaimer") and any redistribution must be conditioned upon
+ * including a substantially similar Disclaimer requirement for further
+ * binary redistribution.
+ * 3. Neither the names of the above-listed copyright holders nor the names
+ * of any contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * Alternatively, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") version 2 as published by the Free
+ * Software Foundation.
+ *
+ * NO WARRANTY
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGES.
+ */
+
+#define __HWPCI_C__
+
+#include "acpi.h"
+#include "accommon.h"
+
+
+#define _COMPONENT ACPI_NAMESPACE
+ ACPI_MODULE_NAME ("hwpci")
+
+
+/* PCI configuration space values */
+
+#define PCI_CFG_HEADER_TYPE_REG 0x0E
+#define PCI_CFG_PRIMARY_BUS_NUMBER_REG 0x18
+#define PCI_CFG_SECONDARY_BUS_NUMBER_REG 0x19
+
+/* PCI header values */
+
+#define PCI_HEADER_TYPE_MASK 0x7F
+#define PCI_TYPE_BRIDGE 0x01
+#define PCI_TYPE_CARDBUS_BRIDGE 0x02
+
+typedef struct acpi_pci_device
+{
+ ACPI_HANDLE Device;
+ struct acpi_pci_device *Next;
+
+} ACPI_PCI_DEVICE;
+
+
+/* Local prototypes */
+
+static ACPI_STATUS
+AcpiHwBuildPciList (
+ ACPI_HANDLE RootPciDevice,
+ ACPI_HANDLE PciRegion,
+ ACPI_PCI_DEVICE **ReturnListHead);
+
+static ACPI_STATUS
+AcpiHwProcessPciList (
+ ACPI_PCI_ID *PciId,
+ ACPI_PCI_DEVICE *ListHead);
+
+static void
+AcpiHwDeletePciList (
+ ACPI_PCI_DEVICE *ListHead);
+
+static ACPI_STATUS
+AcpiHwGetPciDeviceInfo (
+ ACPI_PCI_ID *PciId,
+ ACPI_HANDLE PciDevice,
+ UINT16 *BusNumber,
+ BOOLEAN *IsBridge);
+
+
+/*******************************************************************************
+ *
+ * FUNCTION: AcpiHwDerivePciId
+ *
+ * PARAMETERS: PciId - Initial values for the PCI ID. May be
+ * modified by this function.
+ * RootPciDevice - A handle to a PCI device object. This
+ * object must be a PCI Root Bridge having a
+ * _HID value of either PNP0A03 or PNP0A08
+ * PciRegion - A handle to a PCI configuration space
+ * Operation Region being initialized
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: This function derives a full PCI ID for a PCI device,
+ * consisting of a Segment number, Bus number, Device number,
+ * and function code.
+ *
+ * The PCI hardware dynamically configures PCI bus numbers
+ * depending on the bus topology discovered during system
+ * initialization. This function is invoked during configuration
+ * of a PCI_Config Operation Region in order to (possibly) update
+ * the Bus/Device/Function numbers in the PciId with the actual
+ * values as determined by the hardware and operating system
+ * configuration.
+ *
+ * The PciId parameter is initially populated during the Operation
+ * Region initialization. This function is then called, and is
+ * will make any necessary modifications to the Bus, Device, or
+ * Function number PCI ID subfields as appropriate for the
+ * current hardware and OS configuration.
+ *
+ * NOTE: Created 08/2010. Replaces the previous OSL AcpiOsDerivePciId
+ * interface since this feature is OS-independent. This module
+ * specifically avoids any use of recursion by building a local
+ * temporary device list.
+ *
+ ******************************************************************************/
+
+ACPI_STATUS
+AcpiHwDerivePciId (
+ ACPI_PCI_ID *PciId,
+ ACPI_HANDLE RootPciDevice,
+ ACPI_HANDLE PciRegion)
+{
+ ACPI_STATUS Status;
+ ACPI_PCI_DEVICE *ListHead = NULL;
+
+
+ ACPI_FUNCTION_TRACE (HwDerivePciId);
+
+
+ if (!PciId)
+ {
+ return_ACPI_STATUS (AE_BAD_PARAMETER);
+ }
+
+ /* Build a list of PCI devices, from PciRegion up to RootPciDevice */
+
+ Status = AcpiHwBuildPciList (RootPciDevice, PciRegion, &ListHead);
+ if (ACPI_SUCCESS (Status))
+ {
+ /* Walk the list, updating the PCI device/function/bus numbers */
+
+ Status = AcpiHwProcessPciList (PciId, ListHead);
+ }
+
+ /* Always delete the list */
+
+ AcpiHwDeletePciList (ListHead);
+ return_ACPI_STATUS (Status);
+}
+
+
+/*******************************************************************************
+ *
+ * FUNCTION: AcpiHwBuildPciList
+ *
+ * PARAMETERS: RootPciDevice - A handle to a PCI device object. This
+ * object is guaranteed to be a PCI Root
+ * Bridge having a _HID value of either
+ * PNP0A03 or PNP0A08
+ * PciRegion - A handle to the PCI configuration space
+ * Operation Region
+ * ReturnListHead - Where the PCI device list is returned
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Builds a list of devices from the input PCI region up to the
+ * Root PCI device for this namespace subtree.
+ *
+ ******************************************************************************/
+
+static ACPI_STATUS
+AcpiHwBuildPciList (
+ ACPI_HANDLE RootPciDevice,
+ ACPI_HANDLE PciRegion,
+ ACPI_PCI_DEVICE **ReturnListHead)
+{
+ ACPI_HANDLE CurrentDevice;
+ ACPI_HANDLE ParentDevice;
+ ACPI_STATUS Status;
+ ACPI_PCI_DEVICE *ListElement;
+ ACPI_PCI_DEVICE *ListHead = NULL;
+
+
+ /*
+ * Ascend namespace branch until the RootPciDevice is reached, building
+ * a list of device nodes. Loop will exit when either the PCI device is
+ * found, or the root of the namespace is reached.
+ */
+ CurrentDevice = PciRegion;
+ while (1)
+ {
+ Status = AcpiGetParent (CurrentDevice, &ParentDevice);
+ if (ACPI_FAILURE (Status))
+ {
+ return (Status);
+ }
+
+ /* Finished when we reach the PCI root device (PNP0A03 or PNP0A08) */
+
+ if (ParentDevice == RootPciDevice)
+ {
+ *ReturnListHead = ListHead;
+ return (AE_OK);
+ }
+
+ ListElement = ACPI_ALLOCATE (sizeof (ACPI_PCI_DEVICE));
+ if (!ListElement)
+ {
+ return (AE_NO_MEMORY);
+ }
+
+ /* Put new element at the head of the list */
+
+ ListElement->Next = ListHead;
+ ListElement->Device = ParentDevice;
+ ListHead = ListElement;
+
+ CurrentDevice = ParentDevice;
+ }
+}
+
+
+/*******************************************************************************
+ *
+ * FUNCTION: AcpiHwProcessPciList
+ *
+ * PARAMETERS: PciId - Initial values for the PCI ID. May be
+ * modified by this function.
+ * ListHead - Device list created by
+ * AcpiHwBuildPciList
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Walk downward through the PCI device list, getting the device
+ * info for each, via the PCI configuration space and updating
+ * the PCI ID as necessary. Deletes the list during traversal.
+ *
+ ******************************************************************************/
+
+static ACPI_STATUS
+AcpiHwProcessPciList (
+ ACPI_PCI_ID *PciId,
+ ACPI_PCI_DEVICE *ListHead)
+{
+ ACPI_STATUS Status = AE_OK;
+ ACPI_PCI_DEVICE *Info;
+ UINT16 BusNumber;
+ BOOLEAN IsBridge = TRUE;
+
+
+ ACPI_FUNCTION_NAME (HwProcessPciList);
+
+
+ ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION,
+ "Input PciId: Seg %4.4X Bus %4.4X Dev %4.4X Func %4.4X\n",
+ PciId->Segment, PciId->Bus, PciId->Device, PciId->Function));
+
+ BusNumber = PciId->Bus;
+
+ /*
+ * Descend down the namespace tree, collecting PCI device, function,
+ * and bus numbers. BusNumber is only important for PCI bridges.
+ * Algorithm: As we descend the tree, use the last valid PCI device,
+ * function, and bus numbers that are discovered, and assign them
+ * to the PCI ID for the target device.
+ */
+ Info = ListHead;
+ while (Info)
+ {
+ Status = AcpiHwGetPciDeviceInfo (PciId, Info->Device,
+ &BusNumber, &IsBridge);
+ if (ACPI_FAILURE (Status))
+ {
+ return_ACPI_STATUS (Status);
+ }
+
+ Info = Info->Next;
+ }
+
+ ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION,
+ "Output PciId: Seg %4.4X Bus %4.4X Dev %4.4X Func %4.4X "
+ "Status %X BusNumber %X IsBridge %X\n",
+ PciId->Segment, PciId->Bus, PciId->Device, PciId->Function,
+ Status, BusNumber, IsBridge));
+
+ return_ACPI_STATUS (AE_OK);
+}
+
+
+/*******************************************************************************
+ *
+ * FUNCTION: AcpiHwDeletePciList
+ *
+ * PARAMETERS: ListHead - Device list created by
+ * AcpiHwBuildPciList
+ *
+ * RETURN: None
+ *
+ * DESCRIPTION: Free the entire PCI list.
+ *
+ ******************************************************************************/
+
+static void
+AcpiHwDeletePciList (
+ ACPI_PCI_DEVICE *ListHead)
+{
+ ACPI_PCI_DEVICE *Next;
+ ACPI_PCI_DEVICE *Previous;
+
+
+ Next = ListHead;
+ while (Next)
+ {
+ Previous = Next;
+ Next = Previous->Next;
+ ACPI_FREE (Previous);
+ }
+}
+
+
+/*******************************************************************************
+ *
+ * FUNCTION: AcpiHwGetPciDeviceInfo
+ *
+ * PARAMETERS: PciId - Initial values for the PCI ID. May be
+ * modified by this function.
+ * PciDevice - Handle for the PCI device object
+ * BusNumber - Where a PCI bridge bus number is returned
+ * IsBridge - Return value, indicates if this PCI
+ * device is a PCI bridge
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Get the device info for a single PCI device object. Get the
+ * _ADR (contains PCI device and function numbers), and for PCI
+ * bridge devices, get the bus number from PCI configuration
+ * space.
+ *
+ ******************************************************************************/
+
+static ACPI_STATUS
+AcpiHwGetPciDeviceInfo (
+ ACPI_PCI_ID *PciId,
+ ACPI_HANDLE PciDevice,
+ UINT16 *BusNumber,
+ BOOLEAN *IsBridge)
+{
+ ACPI_STATUS Status;
+ ACPI_OBJECT_TYPE ObjectType;
+ UINT64 ReturnValue;
+ UINT64 PciValue;
+
+
+ /* We only care about objects of type Device */
+
+ Status = AcpiGetType (PciDevice, &ObjectType);
+ if (ACPI_FAILURE (Status))
+ {
+ return (Status);
+ }
+
+ if (ObjectType != ACPI_TYPE_DEVICE)
+ {
+ return (AE_OK);
+ }
+
+ /* We need an _ADR. Ignore device if not present */
+
+ Status = AcpiUtEvaluateNumericObject (METHOD_NAME__ADR,
+ PciDevice, &ReturnValue);
+ if (ACPI_FAILURE (Status))
+ {
+ return (AE_OK);
+ }
+
+ /*
+ * From _ADR, get the PCI Device and Function and
+ * update the PCI ID.
+ */
+ PciId->Device = ACPI_HIWORD (ACPI_LODWORD (ReturnValue));
+ PciId->Function = ACPI_LOWORD (ACPI_LODWORD (ReturnValue));
+
+ /*
+ * If the previous device was a bridge, use the previous
+ * device bus number
+ */
+ if (*IsBridge)
+ {
+ PciId->Bus = *BusNumber;
+ }
+
+ /*
+ * Get the bus numbers from PCI Config space:
+ *
+ * First, get the PCI HeaderType
+ */
+ *IsBridge = FALSE;
+ Status = AcpiOsReadPciConfiguration (PciId,
+ PCI_CFG_HEADER_TYPE_REG, &PciValue, 8);
+ if (ACPI_FAILURE (Status))
+ {
+ return (Status);
+ }
+
+ /* We only care about bridges (1=PciBridge, 2=CardBusBridge) */
+
+ PciValue &= PCI_HEADER_TYPE_MASK;
+
+ if ((PciValue != PCI_TYPE_BRIDGE) &&
+ (PciValue != PCI_TYPE_CARDBUS_BRIDGE))
+ {
+ return (AE_OK);
+ }
+
+ /* Bridge: Get the Primary BusNumber */
+
+ Status = AcpiOsReadPciConfiguration (PciId,
+ PCI_CFG_PRIMARY_BUS_NUMBER_REG, &PciValue, 8);
+ if (ACPI_FAILURE (Status))
+ {
+ return (Status);
+ }
+
+ *IsBridge = TRUE;
+ PciId->Bus = (UINT16) PciValue;
+
+ /* Bridge: Get the Secondary BusNumber */
+
+ Status = AcpiOsReadPciConfiguration (PciId,
+ PCI_CFG_SECONDARY_BUS_NUMBER_REG, &PciValue, 8);
+ if (ACPI_FAILURE (Status))
+ {
+ return (Status);
+ }
+
+ *BusNumber = (UINT16) PciValue;
+ return (AE_OK);
+}
diff --git a/source/components/hardware/hwregs.c b/source/components/hardware/hwregs.c
new file mode 100644
index 000000000000..6d89883179f4
--- /dev/null
+++ b/source/components/hardware/hwregs.c
@@ -0,0 +1,741 @@
+
+/*******************************************************************************
+ *
+ * Module Name: hwregs - Read/write access functions for the various ACPI
+ * control and status registers.
+ *
+ ******************************************************************************/
+
+/*
+ * Copyright (C) 2000 - 2012, Intel Corp.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions, and the following disclaimer,
+ * without modification.
+ * 2. Redistributions in binary form must reproduce at minimum a disclaimer
+ * substantially similar to the "NO WARRANTY" disclaimer below
+ * ("Disclaimer") and any redistribution must be conditioned upon
+ * including a substantially similar Disclaimer requirement for further
+ * binary redistribution.
+ * 3. Neither the names of the above-listed copyright holders nor the names
+ * of any contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * Alternatively, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") version 2 as published by the Free
+ * Software Foundation.
+ *
+ * NO WARRANTY
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGES.
+ */
+
+#define __HWREGS_C__
+
+#include "acpi.h"
+#include "accommon.h"
+#include "acevents.h"
+
+#define _COMPONENT ACPI_HARDWARE
+ ACPI_MODULE_NAME ("hwregs")
+
+
+#if (!ACPI_REDUCED_HARDWARE)
+
+/* Local Prototypes */
+
+static ACPI_STATUS
+AcpiHwReadMultiple (
+ UINT32 *Value,
+ ACPI_GENERIC_ADDRESS *RegisterA,
+ ACPI_GENERIC_ADDRESS *RegisterB);
+
+static ACPI_STATUS
+AcpiHwWriteMultiple (
+ UINT32 Value,
+ ACPI_GENERIC_ADDRESS *RegisterA,
+ ACPI_GENERIC_ADDRESS *RegisterB);
+
+#endif /* !ACPI_REDUCED_HARDWARE */
+
+/******************************************************************************
+ *
+ * FUNCTION: AcpiHwValidateRegister
+ *
+ * PARAMETERS: Reg - GAS register structure
+ * MaxBitWidth - Max BitWidth supported (32 or 64)
+ * Address - Pointer to where the gas->address
+ * is returned
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Validate the contents of a GAS register. Checks the GAS
+ * pointer, Address, SpaceId, BitWidth, and BitOffset.
+ *
+ ******************************************************************************/
+
+ACPI_STATUS
+AcpiHwValidateRegister (
+ ACPI_GENERIC_ADDRESS *Reg,
+ UINT8 MaxBitWidth,
+ UINT64 *Address)
+{
+
+ /* Must have a valid pointer to a GAS structure */
+
+ if (!Reg)
+ {
+ return (AE_BAD_PARAMETER);
+ }
+
+ /*
+ * Copy the target address. This handles possible alignment issues.
+ * Address must not be null. A null address also indicates an optional
+ * ACPI register that is not supported, so no error message.
+ */
+ ACPI_MOVE_64_TO_64 (Address, &Reg->Address);
+ if (!(*Address))
+ {
+ return (AE_BAD_ADDRESS);
+ }
+
+ /* Validate the SpaceID */
+
+ if ((Reg->SpaceId != ACPI_ADR_SPACE_SYSTEM_MEMORY) &&
+ (Reg->SpaceId != ACPI_ADR_SPACE_SYSTEM_IO))
+ {
+ ACPI_ERROR ((AE_INFO,
+ "Unsupported address space: 0x%X", Reg->SpaceId));
+ return (AE_SUPPORT);
+ }
+
+ /* Validate the BitWidth */
+
+ if ((Reg->BitWidth != 8) &&
+ (Reg->BitWidth != 16) &&
+ (Reg->BitWidth != 32) &&
+ (Reg->BitWidth != MaxBitWidth))
+ {
+ ACPI_ERROR ((AE_INFO,
+ "Unsupported register bit width: 0x%X", Reg->BitWidth));
+ return (AE_SUPPORT);
+ }
+
+ /* Validate the BitOffset. Just a warning for now. */
+
+ if (Reg->BitOffset != 0)
+ {
+ ACPI_WARNING ((AE_INFO,
+ "Unsupported register bit offset: 0x%X", Reg->BitOffset));
+ }
+
+ return (AE_OK);
+}
+
+
+/******************************************************************************
+ *
+ * FUNCTION: AcpiHwRead
+ *
+ * PARAMETERS: Value - Where the value is returned
+ * Reg - GAS register structure
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Read from either memory or IO space. This is a 32-bit max
+ * version of AcpiRead, used internally since the overhead of
+ * 64-bit values is not needed.
+ *
+ * LIMITATIONS: <These limitations also apply to AcpiHwWrite>
+ * BitWidth must be exactly 8, 16, or 32.
+ * SpaceID must be SystemMemory or SystemIO.
+ * BitOffset and AccessWidth are currently ignored, as there has
+ * not been a need to implement these.
+ *
+ ******************************************************************************/
+
+ACPI_STATUS
+AcpiHwRead (
+ UINT32 *Value,
+ ACPI_GENERIC_ADDRESS *Reg)
+{
+ UINT64 Address;
+ UINT64 Value64;
+ ACPI_STATUS Status;
+
+
+ ACPI_FUNCTION_NAME (HwRead);
+
+
+ /* Validate contents of the GAS register */
+
+ Status = AcpiHwValidateRegister (Reg, 32, &Address);
+ if (ACPI_FAILURE (Status))
+ {
+ return (Status);
+ }
+
+ /* Initialize entire 32-bit return value to zero */
+
+ *Value = 0;
+
+ /*
+ * Two address spaces supported: Memory or IO. PCI_Config is
+ * not supported here because the GAS structure is insufficient
+ */
+ if (Reg->SpaceId == ACPI_ADR_SPACE_SYSTEM_MEMORY)
+ {
+ Status = AcpiOsReadMemory ((ACPI_PHYSICAL_ADDRESS)
+ Address, &Value64, Reg->BitWidth);
+
+ *Value = (UINT32) Value64;
+ }
+ else /* ACPI_ADR_SPACE_SYSTEM_IO, validated earlier */
+ {
+ Status = AcpiHwReadPort ((ACPI_IO_ADDRESS)
+ Address, Value, Reg->BitWidth);
+ }
+
+ ACPI_DEBUG_PRINT ((ACPI_DB_IO,
+ "Read: %8.8X width %2d from %8.8X%8.8X (%s)\n",
+ *Value, Reg->BitWidth, ACPI_FORMAT_UINT64 (Address),
+ AcpiUtGetRegionName (Reg->SpaceId)));
+
+ return (Status);
+}
+
+
+/******************************************************************************
+ *
+ * FUNCTION: AcpiHwWrite
+ *
+ * PARAMETERS: Value - Value to be written
+ * Reg - GAS register structure
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Write to either memory or IO space. This is a 32-bit max
+ * version of AcpiWrite, used internally since the overhead of
+ * 64-bit values is not needed.
+ *
+ ******************************************************************************/
+
+ACPI_STATUS
+AcpiHwWrite (
+ UINT32 Value,
+ ACPI_GENERIC_ADDRESS *Reg)
+{
+ UINT64 Address;
+ ACPI_STATUS Status;
+
+
+ ACPI_FUNCTION_NAME (HwWrite);
+
+
+ /* Validate contents of the GAS register */
+
+ Status = AcpiHwValidateRegister (Reg, 32, &Address);
+ if (ACPI_FAILURE (Status))
+ {
+ return (Status);
+ }
+
+ /*
+ * Two address spaces supported: Memory or IO. PCI_Config is
+ * not supported here because the GAS structure is insufficient
+ */
+ if (Reg->SpaceId == ACPI_ADR_SPACE_SYSTEM_MEMORY)
+ {
+ Status = AcpiOsWriteMemory ((ACPI_PHYSICAL_ADDRESS)
+ Address, (UINT64) Value, Reg->BitWidth);
+ }
+ else /* ACPI_ADR_SPACE_SYSTEM_IO, validated earlier */
+ {
+ Status = AcpiHwWritePort ((ACPI_IO_ADDRESS)
+ Address, Value, Reg->BitWidth);
+ }
+
+ ACPI_DEBUG_PRINT ((ACPI_DB_IO,
+ "Wrote: %8.8X width %2d to %8.8X%8.8X (%s)\n",
+ Value, Reg->BitWidth, ACPI_FORMAT_UINT64 (Address),
+ AcpiUtGetRegionName (Reg->SpaceId)));
+
+ return (Status);
+}
+
+
+#if (!ACPI_REDUCED_HARDWARE)
+/*******************************************************************************
+ *
+ * FUNCTION: AcpiHwClearAcpiStatus
+ *
+ * PARAMETERS: None
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Clears all fixed and general purpose status bits
+ *
+ ******************************************************************************/
+
+ACPI_STATUS
+AcpiHwClearAcpiStatus (
+ void)
+{
+ ACPI_STATUS Status;
+ ACPI_CPU_FLAGS LockFlags = 0;
+
+
+ ACPI_FUNCTION_TRACE (HwClearAcpiStatus);
+
+
+ ACPI_DEBUG_PRINT ((ACPI_DB_IO, "About to write %04X to %8.8X%8.8X\n",
+ ACPI_BITMASK_ALL_FIXED_STATUS,
+ ACPI_FORMAT_UINT64 (AcpiGbl_XPm1aStatus.Address)));
+
+ LockFlags = AcpiOsAcquireLock (AcpiGbl_HardwareLock);
+
+ /* Clear the fixed events in PM1 A/B */
+
+ Status = AcpiHwRegisterWrite (ACPI_REGISTER_PM1_STATUS,
+ ACPI_BITMASK_ALL_FIXED_STATUS);
+ if (ACPI_FAILURE (Status))
+ {
+ goto UnlockAndExit;
+ }
+
+ /* Clear the GPE Bits in all GPE registers in all GPE blocks */
+
+ Status = AcpiEvWalkGpeList (AcpiHwClearGpeBlock, NULL);
+
+UnlockAndExit:
+ AcpiOsReleaseLock (AcpiGbl_HardwareLock, LockFlags);
+ return_ACPI_STATUS (Status);
+}
+
+
+/*******************************************************************************
+ *
+ * FUNCTION: AcpiHwGetBitRegisterInfo
+ *
+ * PARAMETERS: RegisterId - Index of ACPI Register to access
+ *
+ * RETURN: The bitmask to be used when accessing the register
+ *
+ * DESCRIPTION: Map RegisterId into a register bitmask.
+ *
+ ******************************************************************************/
+
+ACPI_BIT_REGISTER_INFO *
+AcpiHwGetBitRegisterInfo (
+ UINT32 RegisterId)
+{
+ ACPI_FUNCTION_ENTRY ();
+
+
+ if (RegisterId > ACPI_BITREG_MAX)
+ {
+ ACPI_ERROR ((AE_INFO, "Invalid BitRegister ID: 0x%X", RegisterId));
+ return (NULL);
+ }
+
+ return (&AcpiGbl_BitRegisterInfo[RegisterId]);
+}
+
+
+/******************************************************************************
+ *
+ * FUNCTION: AcpiHwWritePm1Control
+ *
+ * PARAMETERS: Pm1aControl - Value to be written to PM1A control
+ * Pm1bControl - Value to be written to PM1B control
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Write the PM1 A/B control registers. These registers are
+ * different than than the PM1 A/B status and enable registers
+ * in that different values can be written to the A/B registers.
+ * Most notably, the SLP_TYP bits can be different, as per the
+ * values returned from the _Sx predefined methods.
+ *
+ ******************************************************************************/
+
+ACPI_STATUS
+AcpiHwWritePm1Control (
+ UINT32 Pm1aControl,
+ UINT32 Pm1bControl)
+{
+ ACPI_STATUS Status;
+
+
+ ACPI_FUNCTION_TRACE (HwWritePm1Control);
+
+
+ Status = AcpiHwWrite (Pm1aControl, &AcpiGbl_FADT.XPm1aControlBlock);
+ if (ACPI_FAILURE (Status))
+ {
+ return_ACPI_STATUS (Status);
+ }
+
+ if (AcpiGbl_FADT.XPm1bControlBlock.Address)
+ {
+ Status = AcpiHwWrite (Pm1bControl, &AcpiGbl_FADT.XPm1bControlBlock);
+ }
+ return_ACPI_STATUS (Status);
+}
+
+
+/******************************************************************************
+ *
+ * FUNCTION: AcpiHwRegisterRead
+ *
+ * PARAMETERS: RegisterId - ACPI Register ID
+ * ReturnValue - Where the register value is returned
+ *
+ * RETURN: Status and the value read.
+ *
+ * DESCRIPTION: Read from the specified ACPI register
+ *
+ ******************************************************************************/
+
+ACPI_STATUS
+AcpiHwRegisterRead (
+ UINT32 RegisterId,
+ UINT32 *ReturnValue)
+{
+ UINT32 Value = 0;
+ ACPI_STATUS Status;
+
+
+ ACPI_FUNCTION_TRACE (HwRegisterRead);
+
+
+ switch (RegisterId)
+ {
+ case ACPI_REGISTER_PM1_STATUS: /* PM1 A/B: 16-bit access each */
+
+ Status = AcpiHwReadMultiple (&Value,
+ &AcpiGbl_XPm1aStatus,
+ &AcpiGbl_XPm1bStatus);
+ break;
+
+
+ case ACPI_REGISTER_PM1_ENABLE: /* PM1 A/B: 16-bit access each */
+
+ Status = AcpiHwReadMultiple (&Value,
+ &AcpiGbl_XPm1aEnable,
+ &AcpiGbl_XPm1bEnable);
+ break;
+
+
+ case ACPI_REGISTER_PM1_CONTROL: /* PM1 A/B: 16-bit access each */
+
+ Status = AcpiHwReadMultiple (&Value,
+ &AcpiGbl_FADT.XPm1aControlBlock,
+ &AcpiGbl_FADT.XPm1bControlBlock);
+
+ /*
+ * Zero the write-only bits. From the ACPI specification, "Hardware
+ * Write-Only Bits": "Upon reads to registers with write-only bits,
+ * software masks out all write-only bits."
+ */
+ Value &= ~ACPI_PM1_CONTROL_WRITEONLY_BITS;
+ break;
+
+
+ case ACPI_REGISTER_PM2_CONTROL: /* 8-bit access */
+
+ Status = AcpiHwRead (&Value, &AcpiGbl_FADT.XPm2ControlBlock);
+ break;
+
+
+ case ACPI_REGISTER_PM_TIMER: /* 32-bit access */
+
+ Status = AcpiHwRead (&Value, &AcpiGbl_FADT.XPmTimerBlock);
+ break;
+
+
+ case ACPI_REGISTER_SMI_COMMAND_BLOCK: /* 8-bit access */
+
+ Status = AcpiHwReadPort (AcpiGbl_FADT.SmiCommand, &Value, 8);
+ break;
+
+
+ default:
+ ACPI_ERROR ((AE_INFO, "Unknown Register ID: 0x%X",
+ RegisterId));
+ Status = AE_BAD_PARAMETER;
+ break;
+ }
+
+ if (ACPI_SUCCESS (Status))
+ {
+ *ReturnValue = Value;
+ }
+
+ return_ACPI_STATUS (Status);
+}
+
+
+/******************************************************************************
+ *
+ * FUNCTION: AcpiHwRegisterWrite
+ *
+ * PARAMETERS: RegisterId - ACPI Register ID
+ * Value - The value to write
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Write to the specified ACPI register
+ *
+ * NOTE: In accordance with the ACPI specification, this function automatically
+ * preserves the value of the following bits, meaning that these bits cannot be
+ * changed via this interface:
+ *
+ * PM1_CONTROL[0] = SCI_EN
+ * PM1_CONTROL[9]
+ * PM1_STATUS[11]
+ *
+ * ACPI References:
+ * 1) Hardware Ignored Bits: When software writes to a register with ignored
+ * bit fields, it preserves the ignored bit fields
+ * 2) SCI_EN: OSPM always preserves this bit position
+ *
+ ******************************************************************************/
+
+ACPI_STATUS
+AcpiHwRegisterWrite (
+ UINT32 RegisterId,
+ UINT32 Value)
+{
+ ACPI_STATUS Status;
+ UINT32 ReadValue;
+
+
+ ACPI_FUNCTION_TRACE (HwRegisterWrite);
+
+
+ switch (RegisterId)
+ {
+ case ACPI_REGISTER_PM1_STATUS: /* PM1 A/B: 16-bit access each */
+ /*
+ * Handle the "ignored" bit in PM1 Status. According to the ACPI
+ * specification, ignored bits are to be preserved when writing.
+ * Normally, this would mean a read/modify/write sequence. However,
+ * preserving a bit in the status register is different. Writing a
+ * one clears the status, and writing a zero preserves the status.
+ * Therefore, we must always write zero to the ignored bit.
+ *
+ * This behavior is clarified in the ACPI 4.0 specification.
+ */
+ Value &= ~ACPI_PM1_STATUS_PRESERVED_BITS;
+
+ Status = AcpiHwWriteMultiple (Value,
+ &AcpiGbl_XPm1aStatus,
+ &AcpiGbl_XPm1bStatus);
+ break;
+
+
+ case ACPI_REGISTER_PM1_ENABLE: /* PM1 A/B: 16-bit access each */
+
+ Status = AcpiHwWriteMultiple (Value,
+ &AcpiGbl_XPm1aEnable,
+ &AcpiGbl_XPm1bEnable);
+ break;
+
+
+ case ACPI_REGISTER_PM1_CONTROL: /* PM1 A/B: 16-bit access each */
+
+ /*
+ * Perform a read first to preserve certain bits (per ACPI spec)
+ * Note: This includes SCI_EN, we never want to change this bit
+ */
+ Status = AcpiHwReadMultiple (&ReadValue,
+ &AcpiGbl_FADT.XPm1aControlBlock,
+ &AcpiGbl_FADT.XPm1bControlBlock);
+ if (ACPI_FAILURE (Status))
+ {
+ goto Exit;
+ }
+
+ /* Insert the bits to be preserved */
+
+ ACPI_INSERT_BITS (Value, ACPI_PM1_CONTROL_PRESERVED_BITS, ReadValue);
+
+ /* Now we can write the data */
+
+ Status = AcpiHwWriteMultiple (Value,
+ &AcpiGbl_FADT.XPm1aControlBlock,
+ &AcpiGbl_FADT.XPm1bControlBlock);
+ break;
+
+
+ case ACPI_REGISTER_PM2_CONTROL: /* 8-bit access */
+
+ /*
+ * For control registers, all reserved bits must be preserved,
+ * as per the ACPI spec.
+ */
+ Status = AcpiHwRead (&ReadValue, &AcpiGbl_FADT.XPm2ControlBlock);
+ if (ACPI_FAILURE (Status))
+ {
+ goto Exit;
+ }
+
+ /* Insert the bits to be preserved */
+
+ ACPI_INSERT_BITS (Value, ACPI_PM2_CONTROL_PRESERVED_BITS, ReadValue);
+
+ Status = AcpiHwWrite (Value, &AcpiGbl_FADT.XPm2ControlBlock);
+ break;
+
+
+ case ACPI_REGISTER_PM_TIMER: /* 32-bit access */
+
+ Status = AcpiHwWrite (Value, &AcpiGbl_FADT.XPmTimerBlock);
+ break;
+
+
+ case ACPI_REGISTER_SMI_COMMAND_BLOCK: /* 8-bit access */
+
+ /* SMI_CMD is currently always in IO space */
+
+ Status = AcpiHwWritePort (AcpiGbl_FADT.SmiCommand, Value, 8);
+ break;
+
+
+ default:
+ ACPI_ERROR ((AE_INFO, "Unknown Register ID: 0x%X",
+ RegisterId));
+ Status = AE_BAD_PARAMETER;
+ break;
+ }
+
+Exit:
+ return_ACPI_STATUS (Status);
+}
+
+
+/******************************************************************************
+ *
+ * FUNCTION: AcpiHwReadMultiple
+ *
+ * PARAMETERS: Value - Where the register value is returned
+ * RegisterA - First ACPI register (required)
+ * RegisterB - Second ACPI register (optional)
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Read from the specified two-part ACPI register (such as PM1 A/B)
+ *
+ ******************************************************************************/
+
+static ACPI_STATUS
+AcpiHwReadMultiple (
+ UINT32 *Value,
+ ACPI_GENERIC_ADDRESS *RegisterA,
+ ACPI_GENERIC_ADDRESS *RegisterB)
+{
+ UINT32 ValueA = 0;
+ UINT32 ValueB = 0;
+ ACPI_STATUS Status;
+
+
+ /* The first register is always required */
+
+ Status = AcpiHwRead (&ValueA, RegisterA);
+ if (ACPI_FAILURE (Status))
+ {
+ return (Status);
+ }
+
+ /* Second register is optional */
+
+ if (RegisterB->Address)
+ {
+ Status = AcpiHwRead (&ValueB, RegisterB);
+ if (ACPI_FAILURE (Status))
+ {
+ return (Status);
+ }
+ }
+
+ /*
+ * OR the two return values together. No shifting or masking is necessary,
+ * because of how the PM1 registers are defined in the ACPI specification:
+ *
+ * "Although the bits can be split between the two register blocks (each
+ * register block has a unique pointer within the FADT), the bit positions
+ * are maintained. The register block with unimplemented bits (that is,
+ * those implemented in the other register block) always returns zeros,
+ * and writes have no side effects"
+ */
+ *Value = (ValueA | ValueB);
+ return (AE_OK);
+}
+
+
+/******************************************************************************
+ *
+ * FUNCTION: AcpiHwWriteMultiple
+ *
+ * PARAMETERS: Value - The value to write
+ * RegisterA - First ACPI register (required)
+ * RegisterB - Second ACPI register (optional)
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Write to the specified two-part ACPI register (such as PM1 A/B)
+ *
+ ******************************************************************************/
+
+static ACPI_STATUS
+AcpiHwWriteMultiple (
+ UINT32 Value,
+ ACPI_GENERIC_ADDRESS *RegisterA,
+ ACPI_GENERIC_ADDRESS *RegisterB)
+{
+ ACPI_STATUS Status;
+
+
+ /* The first register is always required */
+
+ Status = AcpiHwWrite (Value, RegisterA);
+ if (ACPI_FAILURE (Status))
+ {
+ return (Status);
+ }
+
+ /*
+ * Second register is optional
+ *
+ * No bit shifting or clearing is necessary, because of how the PM1
+ * registers are defined in the ACPI specification:
+ *
+ * "Although the bits can be split between the two register blocks (each
+ * register block has a unique pointer within the FADT), the bit positions
+ * are maintained. The register block with unimplemented bits (that is,
+ * those implemented in the other register block) always returns zeros,
+ * and writes have no side effects"
+ */
+ if (RegisterB->Address)
+ {
+ Status = AcpiHwWrite (Value, RegisterB);
+ }
+
+ return (Status);
+}
+
+#endif /* !ACPI_REDUCED_HARDWARE */
diff --git a/source/components/hardware/hwsleep.c b/source/components/hardware/hwsleep.c
new file mode 100644
index 000000000000..0d311435555a
--- /dev/null
+++ b/source/components/hardware/hwsleep.c
@@ -0,0 +1,384 @@
+/******************************************************************************
+ *
+ * Name: hwsleep.c - ACPI Hardware Sleep/Wake Support functions for the
+ * original/legacy sleep/PM registers.
+ *
+ *****************************************************************************/
+
+/*
+ * Copyright (C) 2000 - 2012, Intel Corp.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions, and the following disclaimer,
+ * without modification.
+ * 2. Redistributions in binary form must reproduce at minimum a disclaimer
+ * substantially similar to the "NO WARRANTY" disclaimer below
+ * ("Disclaimer") and any redistribution must be conditioned upon
+ * including a substantially similar Disclaimer requirement for further
+ * binary redistribution.
+ * 3. Neither the names of the above-listed copyright holders nor the names
+ * of any contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * Alternatively, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") version 2 as published by the Free
+ * Software Foundation.
+ *
+ * NO WARRANTY
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGES.
+ */
+
+#include "acpi.h"
+#include "accommon.h"
+
+#define _COMPONENT ACPI_HARDWARE
+ ACPI_MODULE_NAME ("hwsleep")
+
+
+#if (!ACPI_REDUCED_HARDWARE) /* Entire module */
+/*******************************************************************************
+ *
+ * FUNCTION: AcpiHwLegacySleep
+ *
+ * PARAMETERS: SleepState - Which sleep state to enter
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Enter a system sleep state via the legacy FADT PM registers
+ * THIS FUNCTION MUST BE CALLED WITH INTERRUPTS DISABLED
+ *
+ ******************************************************************************/
+
+ACPI_STATUS
+AcpiHwLegacySleep (
+ UINT8 SleepState)
+{
+ ACPI_BIT_REGISTER_INFO *SleepTypeRegInfo;
+ ACPI_BIT_REGISTER_INFO *SleepEnableRegInfo;
+ UINT32 Pm1aControl;
+ UINT32 Pm1bControl;
+ UINT32 InValue;
+ ACPI_STATUS Status;
+
+
+ ACPI_FUNCTION_TRACE (HwLegacySleep);
+
+
+ SleepTypeRegInfo = AcpiHwGetBitRegisterInfo (ACPI_BITREG_SLEEP_TYPE);
+ SleepEnableRegInfo = AcpiHwGetBitRegisterInfo (ACPI_BITREG_SLEEP_ENABLE);
+
+ /* Clear wake status */
+
+ Status = AcpiWriteBitRegister (ACPI_BITREG_WAKE_STATUS, ACPI_CLEAR_STATUS);
+ if (ACPI_FAILURE (Status))
+ {
+ return_ACPI_STATUS (Status);
+ }
+
+ /* Clear all fixed and general purpose status bits */
+
+ Status = AcpiHwClearAcpiStatus ();
+ if (ACPI_FAILURE (Status))
+ {
+ return_ACPI_STATUS (Status);
+ }
+
+ if (SleepState != ACPI_STATE_S5)
+ {
+ /*
+ * Disable BM arbitration. This feature is contained within an
+ * optional register (PM2 Control), so ignore a BAD_ADDRESS
+ * exception.
+ */
+ Status = AcpiWriteBitRegister (ACPI_BITREG_ARB_DISABLE, 1);
+ if (ACPI_FAILURE (Status) && (Status != AE_BAD_ADDRESS))
+ {
+ return_ACPI_STATUS (Status);
+ }
+ }
+
+ /*
+ * 1) Disable/Clear all GPEs
+ * 2) Enable all wakeup GPEs
+ */
+ Status = AcpiHwDisableAllGpes ();
+ if (ACPI_FAILURE (Status))
+ {
+ return_ACPI_STATUS (Status);
+ }
+ AcpiGbl_SystemAwakeAndRunning = FALSE;
+
+ Status = AcpiHwEnableAllWakeupGpes ();
+ if (ACPI_FAILURE (Status))
+ {
+ return_ACPI_STATUS (Status);
+ }
+
+ /* Execute the _GTS method (Going To Sleep) */
+
+ AcpiHwExecuteSleepMethod (METHOD_NAME__GTS, SleepState);
+
+ /* Get current value of PM1A control */
+
+ Status = AcpiHwRegisterRead (ACPI_REGISTER_PM1_CONTROL,
+ &Pm1aControl);
+ if (ACPI_FAILURE (Status))
+ {
+ return_ACPI_STATUS (Status);
+ }
+ ACPI_DEBUG_PRINT ((ACPI_DB_INIT,
+ "Entering sleep state [S%u]\n", SleepState));
+
+ /* Clear the SLP_EN and SLP_TYP fields */
+
+ Pm1aControl &= ~(SleepTypeRegInfo->AccessBitMask |
+ SleepEnableRegInfo->AccessBitMask);
+ Pm1bControl = Pm1aControl;
+
+ /* Insert the SLP_TYP bits */
+
+ 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: write the SLP_TYP data to the PM1 Control registers */
+
+ Status = AcpiHwWritePm1Control (Pm1aControl, Pm1bControl);
+ if (ACPI_FAILURE (Status))
+ {
+ return_ACPI_STATUS (Status);
+ }
+
+ /* Insert the sleep enable (SLP_EN) bit */
+
+ Pm1aControl |= SleepEnableRegInfo->AccessBitMask;
+ Pm1bControl |= SleepEnableRegInfo->AccessBitMask;
+
+ /* Flush caches, as per ACPI specification */
+
+ ACPI_FLUSH_CPU_CACHE ();
+
+ /* Write #2: Write both SLP_TYP + SLP_EN */
+
+ Status = AcpiHwWritePm1Control (Pm1aControl, Pm1bControl);
+ if (ACPI_FAILURE (Status))
+ {
+ return_ACPI_STATUS (Status);
+ }
+
+ if (SleepState > ACPI_STATE_S3)
+ {
+ /*
+ * We wanted to sleep > S3, but it didn't happen (by virtue of the
+ * fact that we are still executing!)
+ *
+ * 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 block would go
+ * away entirely.
+ */
+ AcpiOsStall (10000000);
+
+ Status = AcpiHwRegisterWrite (ACPI_REGISTER_PM1_CONTROL,
+ SleepEnableRegInfo->AccessBitMask);
+ if (ACPI_FAILURE (Status))
+ {
+ return_ACPI_STATUS (Status);
+ }
+ }
+
+ /* Wait for transition back to Working State */
+
+ do
+ {
+ Status = AcpiReadBitRegister (ACPI_BITREG_WAKE_STATUS, &InValue);
+ if (ACPI_FAILURE (Status))
+ {
+ return_ACPI_STATUS (Status);
+ }
+
+ } while (!InValue);
+
+ return_ACPI_STATUS (AE_OK);
+}
+
+
+/*******************************************************************************
+ *
+ * FUNCTION: AcpiHwLegacyWakePrep
+ *
+ * PARAMETERS: SleepState - Which sleep state we just exited
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Perform the first state of OS-independent ACPI cleanup after a
+ * sleep.
+ * Called with interrupts ENABLED.
+ *
+ ******************************************************************************/
+
+ACPI_STATUS
+AcpiHwLegacyWakePrep (
+ UINT8 SleepState)
+{
+ ACPI_STATUS Status;
+ ACPI_BIT_REGISTER_INFO *SleepTypeRegInfo;
+ ACPI_BIT_REGISTER_INFO *SleepEnableRegInfo;
+ UINT32 Pm1aControl;
+ UINT32 Pm1bControl;
+
+
+ ACPI_FUNCTION_TRACE (HwLegacyWakePrep);
+
+ /*
+ * 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))
+ {
+ SleepTypeRegInfo =
+ AcpiHwGetBitRegisterInfo (ACPI_BITREG_SLEEP_TYPE);
+ SleepEnableRegInfo =
+ AcpiHwGetBitRegisterInfo (ACPI_BITREG_SLEEP_ENABLE);
+
+ /* Get current value of PM1A control */
+
+ Status = AcpiHwRegisterRead (ACPI_REGISTER_PM1_CONTROL,
+ &Pm1aControl);
+ if (ACPI_SUCCESS (Status))
+ {
+ /* Clear the SLP_EN and SLP_TYP fields */
+
+ Pm1aControl &= ~(SleepTypeRegInfo->AccessBitMask |
+ SleepEnableRegInfo->AccessBitMask);
+ Pm1bControl = Pm1aControl;
+
+ /* Insert the SLP_TYP bits */
+
+ Pm1aControl |= (AcpiGbl_SleepTypeA <<
+ SleepTypeRegInfo->BitPosition);
+ Pm1bControl |= (AcpiGbl_SleepTypeB <<
+ SleepTypeRegInfo->BitPosition);
+
+ /* Write the control registers and ignore any errors */
+
+ (void) AcpiHwWritePm1Control (Pm1aControl, Pm1bControl);
+ }
+ }
+
+ AcpiHwExecuteSleepMethod (METHOD_NAME__BFS, SleepState);
+ return_ACPI_STATUS (Status);
+}
+
+
+/*******************************************************************************
+ *
+ * FUNCTION: AcpiHwLegacyWake
+ *
+ * PARAMETERS: SleepState - Which sleep state we just exited
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Perform OS-independent ACPI cleanup after a sleep
+ * Called with interrupts ENABLED.
+ *
+ ******************************************************************************/
+
+ACPI_STATUS
+AcpiHwLegacyWake (
+ UINT8 SleepState)
+{
+ ACPI_STATUS Status;
+
+
+ ACPI_FUNCTION_TRACE (HwLegacyWake);
+
+
+ /* Ensure EnterSleepStatePrep -> EnterSleepState ordering */
+
+ AcpiGbl_SleepTypeA = ACPI_SLEEP_TYPE_INVALID;
+ AcpiHwExecuteSleepMethod (METHOD_NAME__SST, ACPI_SST_WAKING);
+
+ /*
+ * GPEs must be enabled before _WAK is called as GPEs
+ * might get fired there
+ *
+ * Restore the GPEs:
+ * 1) Disable/Clear all GPEs
+ * 2) Enable all runtime GPEs
+ */
+ Status = AcpiHwDisableAllGpes ();
+ if (ACPI_FAILURE (Status))
+ {
+ return_ACPI_STATUS (Status);
+ }
+
+ Status = AcpiHwEnableAllRuntimeGpes ();
+ if (ACPI_FAILURE (Status))
+ {
+ return_ACPI_STATUS (Status);
+ }
+
+ /*
+ * Now we can execute _WAK, etc. Some machines require that the GPEs
+ * are enabled before the wake methods are executed.
+ */
+ AcpiHwExecuteSleepMethod (METHOD_NAME__WAK, SleepState);
+
+ /*
+ * Some BIOS code assumes that WAK_STS will be cleared on resume
+ * and use it to determine whether the system is rebooting or
+ * resuming. Clear WAK_STS for compatibility.
+ */
+ (void) AcpiWriteBitRegister (ACPI_BITREG_WAKE_STATUS, ACPI_CLEAR_STATUS);
+ AcpiGbl_SystemAwakeAndRunning = TRUE;
+
+ /* Enable power button */
+
+ (void) AcpiWriteBitRegister(
+ AcpiGbl_FixedEventInfo[ACPI_EVENT_POWER_BUTTON].EnableRegisterId,
+ ACPI_ENABLE_EVENT);
+
+ (void) AcpiWriteBitRegister(
+ AcpiGbl_FixedEventInfo[ACPI_EVENT_POWER_BUTTON].StatusRegisterId,
+ ACPI_CLEAR_STATUS);
+
+ /*
+ * Enable BM arbitration. This feature is contained within an
+ * optional register (PM2 Control), so ignore a BAD_ADDRESS
+ * exception.
+ */
+ Status = AcpiWriteBitRegister (ACPI_BITREG_ARB_DISABLE, 0);
+ if (ACPI_FAILURE (Status) && (Status != AE_BAD_ADDRESS))
+ {
+ return_ACPI_STATUS (Status);
+ }
+
+ AcpiHwExecuteSleepMethod (METHOD_NAME__SST, ACPI_SST_WORKING);
+ return_ACPI_STATUS (Status);
+}
+
+#endif /* !ACPI_REDUCED_HARDWARE */
diff --git a/source/components/hardware/hwtimer.c b/source/components/hardware/hwtimer.c
new file mode 100644
index 000000000000..15dc58f0bffe
--- /dev/null
+++ b/source/components/hardware/hwtimer.c
@@ -0,0 +1,218 @@
+
+/******************************************************************************
+ *
+ * Name: hwtimer.c - ACPI Power Management Timer Interface
+ *
+ *****************************************************************************/
+
+/*
+ * Copyright (C) 2000 - 2012, Intel Corp.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions, and the following disclaimer,
+ * without modification.
+ * 2. Redistributions in binary form must reproduce at minimum a disclaimer
+ * substantially similar to the "NO WARRANTY" disclaimer below
+ * ("Disclaimer") and any redistribution must be conditioned upon
+ * including a substantially similar Disclaimer requirement for further
+ * binary redistribution.
+ * 3. Neither the names of the above-listed copyright holders nor the names
+ * of any contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * Alternatively, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") version 2 as published by the Free
+ * Software Foundation.
+ *
+ * NO WARRANTY
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGES.
+ */
+
+#include "acpi.h"
+#include "accommon.h"
+
+#define _COMPONENT ACPI_HARDWARE
+ ACPI_MODULE_NAME ("hwtimer")
+
+
+#if (!ACPI_REDUCED_HARDWARE) /* Entire module */
+/******************************************************************************
+ *
+ * FUNCTION: AcpiGetTimerResolution
+ *
+ * PARAMETERS: Resolution - Where the resolution is returned
+ *
+ * RETURN: Status and timer resolution
+ *
+ * DESCRIPTION: Obtains resolution of the ACPI PM Timer (24 or 32 bits).
+ *
+ ******************************************************************************/
+
+ACPI_STATUS
+AcpiGetTimerResolution (
+ UINT32 *Resolution)
+{
+ ACPI_FUNCTION_TRACE (AcpiGetTimerResolution);
+
+
+ if (!Resolution)
+ {
+ return_ACPI_STATUS (AE_BAD_PARAMETER);
+ }
+
+ if ((AcpiGbl_FADT.Flags & ACPI_FADT_32BIT_TIMER) == 0)
+ {
+ *Resolution = 24;
+ }
+ else
+ {
+ *Resolution = 32;
+ }
+
+ return_ACPI_STATUS (AE_OK);
+}
+
+ACPI_EXPORT_SYMBOL (AcpiGetTimerResolution)
+
+
+/******************************************************************************
+ *
+ * FUNCTION: AcpiGetTimer
+ *
+ * PARAMETERS: Ticks - Where the timer value is returned
+ *
+ * RETURN: Status and current timer value (ticks)
+ *
+ * DESCRIPTION: Obtains current value of ACPI PM Timer (in ticks).
+ *
+ ******************************************************************************/
+
+ACPI_STATUS
+AcpiGetTimer (
+ UINT32 *Ticks)
+{
+ ACPI_STATUS Status;
+
+
+ ACPI_FUNCTION_TRACE (AcpiGetTimer);
+
+
+ if (!Ticks)
+ {
+ return_ACPI_STATUS (AE_BAD_PARAMETER);
+ }
+
+ Status = AcpiHwRead (Ticks, &AcpiGbl_FADT.XPmTimerBlock);
+
+ return_ACPI_STATUS (Status);
+}
+
+ACPI_EXPORT_SYMBOL (AcpiGetTimer)
+
+
+/******************************************************************************
+ *
+ * FUNCTION: AcpiGetTimerDuration
+ *
+ * PARAMETERS: StartTicks - Starting timestamp
+ * EndTicks - End timestamp
+ * TimeElapsed - Where the elapsed time is returned
+ *
+ * RETURN: Status and TimeElapsed
+ *
+ * DESCRIPTION: Computes the time elapsed (in microseconds) between two
+ * PM Timer time stamps, taking into account the possibility of
+ * rollovers, the timer resolution, and timer frequency.
+ *
+ * The PM Timer's clock ticks at roughly 3.6 times per
+ * _microsecond_, and its clock continues through Cx state
+ * transitions (unlike many CPU timestamp counters) -- making it
+ * a versatile and accurate timer.
+ *
+ * Note that this function accommodates only a single timer
+ * rollover. Thus for 24-bit timers, this function should only
+ * be used for calculating durations less than ~4.6 seconds
+ * (~20 minutes for 32-bit timers) -- calculations below:
+ *
+ * 2**24 Ticks / 3,600,000 Ticks/Sec = 4.66 sec
+ * 2**32 Ticks / 3,600,000 Ticks/Sec = 1193 sec or 19.88 minutes
+ *
+ ******************************************************************************/
+
+ACPI_STATUS
+AcpiGetTimerDuration (
+ UINT32 StartTicks,
+ UINT32 EndTicks,
+ UINT32 *TimeElapsed)
+{
+ ACPI_STATUS Status;
+ UINT32 DeltaTicks;
+ UINT64 Quotient;
+
+
+ ACPI_FUNCTION_TRACE (AcpiGetTimerDuration);
+
+
+ if (!TimeElapsed)
+ {
+ return_ACPI_STATUS (AE_BAD_PARAMETER);
+ }
+
+ /*
+ * Compute Tick Delta:
+ * Handle (max one) timer rollovers on 24-bit versus 32-bit timers.
+ */
+ if (StartTicks < EndTicks)
+ {
+ DeltaTicks = EndTicks - StartTicks;
+ }
+ else if (StartTicks > EndTicks)
+ {
+ if ((AcpiGbl_FADT.Flags & ACPI_FADT_32BIT_TIMER) == 0)
+ {
+ /* 24-bit Timer */
+
+ DeltaTicks = (((0x00FFFFFF - StartTicks) + EndTicks) & 0x00FFFFFF);
+ }
+ else
+ {
+ /* 32-bit Timer */
+
+ DeltaTicks = (0xFFFFFFFF - StartTicks) + EndTicks;
+ }
+ }
+ else /* StartTicks == EndTicks */
+ {
+ *TimeElapsed = 0;
+ return_ACPI_STATUS (AE_OK);
+ }
+
+ /*
+ * Compute Duration (Requires a 64-bit multiply and divide):
+ *
+ * TimeElapsed = (DeltaTicks * 1000000) / PM_TIMER_FREQUENCY;
+ */
+ Status = AcpiUtShortDivide (((UINT64) DeltaTicks) * 1000000,
+ PM_TIMER_FREQUENCY, &Quotient, NULL);
+
+ *TimeElapsed = (UINT32) Quotient;
+ return_ACPI_STATUS (Status);
+}
+
+ACPI_EXPORT_SYMBOL (AcpiGetTimerDuration)
+
+#endif /* !ACPI_REDUCED_HARDWARE */
diff --git a/source/components/hardware/hwvalid.c b/source/components/hardware/hwvalid.c
new file mode 100644
index 000000000000..4462434bbfe6
--- /dev/null
+++ b/source/components/hardware/hwvalid.c
@@ -0,0 +1,368 @@
+
+/******************************************************************************
+ *
+ * Module Name: hwvalid - I/O request validation
+ *
+ *****************************************************************************/
+
+/*
+ * Copyright (C) 2000 - 2012, Intel Corp.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions, and the following disclaimer,
+ * without modification.
+ * 2. Redistributions in binary form must reproduce at minimum a disclaimer
+ * substantially similar to the "NO WARRANTY" disclaimer below
+ * ("Disclaimer") and any redistribution must be conditioned upon
+ * including a substantially similar Disclaimer requirement for further
+ * binary redistribution.
+ * 3. Neither the names of the above-listed copyright holders nor the names
+ * of any contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * Alternatively, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") version 2 as published by the Free
+ * Software Foundation.
+ *
+ * NO WARRANTY
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGES.
+ */
+
+#define __HWVALID_C__
+
+#include "acpi.h"
+#include "accommon.h"
+
+#define _COMPONENT ACPI_HARDWARE
+ ACPI_MODULE_NAME ("hwvalid")
+
+/* Local prototypes */
+
+static ACPI_STATUS
+AcpiHwValidateIoRequest (
+ ACPI_IO_ADDRESS Address,
+ UINT32 BitWidth);
+
+
+/*
+ * Protected I/O ports. Some ports are always illegal, and some are
+ * conditionally illegal. This table must remain ordered by port address.
+ *
+ * The table is used to implement the Microsoft port access rules that
+ * first appeared in Windows XP. Some ports are always illegal, and some
+ * ports are only illegal if the BIOS calls _OSI with a WinXP string or
+ * later (meaning that the BIOS itelf is post-XP.)
+ *
+ * This provides ACPICA with the desired port protections and
+ * Microsoft compatibility.
+ *
+ * Description of port entries:
+ * DMA: DMA controller
+ * PIC0: Programmable Interrupt Controller (8259A)
+ * PIT1: System Timer 1
+ * PIT2: System Timer 2 failsafe
+ * RTC: Real-time clock
+ * CMOS: Extended CMOS
+ * DMA1: DMA 1 page registers
+ * DMA1L: DMA 1 Ch 0 low page
+ * DMA2: DMA 2 page registers
+ * DMA2L: DMA 2 low page refresh
+ * ARBC: Arbitration control
+ * SETUP: Reserved system board setup
+ * POS: POS channel select
+ * PIC1: Cascaded PIC
+ * IDMA: ISA DMA
+ * ELCR: PIC edge/level registers
+ * PCI: PCI configuration space
+ */
+static const ACPI_PORT_INFO AcpiProtectedPorts[] =
+{
+ {"DMA", 0x0000, 0x000F, ACPI_OSI_WIN_XP},
+ {"PIC0", 0x0020, 0x0021, ACPI_ALWAYS_ILLEGAL},
+ {"PIT1", 0x0040, 0x0043, ACPI_OSI_WIN_XP},
+ {"PIT2", 0x0048, 0x004B, ACPI_OSI_WIN_XP},
+ {"RTC", 0x0070, 0x0071, ACPI_OSI_WIN_XP},
+ {"CMOS", 0x0074, 0x0076, ACPI_OSI_WIN_XP},
+ {"DMA1", 0x0081, 0x0083, ACPI_OSI_WIN_XP},
+ {"DMA1L", 0x0087, 0x0087, ACPI_OSI_WIN_XP},
+ {"DMA2", 0x0089, 0x008B, ACPI_OSI_WIN_XP},
+ {"DMA2L", 0x008F, 0x008F, ACPI_OSI_WIN_XP},
+ {"ARBC", 0x0090, 0x0091, ACPI_OSI_WIN_XP},
+ {"SETUP", 0x0093, 0x0094, ACPI_OSI_WIN_XP},
+ {"POS", 0x0096, 0x0097, ACPI_OSI_WIN_XP},
+ {"PIC1", 0x00A0, 0x00A1, ACPI_ALWAYS_ILLEGAL},
+ {"IDMA", 0x00C0, 0x00DF, ACPI_OSI_WIN_XP},
+ {"ELCR", 0x04D0, 0x04D1, ACPI_ALWAYS_ILLEGAL},
+ {"PCI", 0x0CF8, 0x0CFF, ACPI_OSI_WIN_XP}
+};
+
+#define ACPI_PORT_INFO_ENTRIES ACPI_ARRAY_LENGTH (AcpiProtectedPorts)
+
+
+/******************************************************************************
+ *
+ * FUNCTION: AcpiHwValidateIoRequest
+ *
+ * PARAMETERS: Address Address of I/O port/register
+ * BitWidth Number of bits (8,16,32)
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Validates an I/O request (address/length). Certain ports are
+ * always illegal and some ports are only illegal depending on
+ * the requests the BIOS AML code makes to the predefined
+ * _OSI method.
+ *
+ ******************************************************************************/
+
+static ACPI_STATUS
+AcpiHwValidateIoRequest (
+ ACPI_IO_ADDRESS Address,
+ UINT32 BitWidth)
+{
+ UINT32 i;
+ UINT32 ByteWidth;
+ ACPI_IO_ADDRESS LastAddress;
+ const ACPI_PORT_INFO *PortInfo;
+
+
+ ACPI_FUNCTION_TRACE (HwValidateIoRequest);
+
+
+ /* Supported widths are 8/16/32 */
+
+ if ((BitWidth != 8) &&
+ (BitWidth != 16) &&
+ (BitWidth != 32))
+ {
+ ACPI_ERROR ((AE_INFO,
+ "Bad BitWidth parameter: %8.8X", BitWidth));
+ return (AE_BAD_PARAMETER);
+ }
+
+ PortInfo = AcpiProtectedPorts;
+ ByteWidth = ACPI_DIV_8 (BitWidth);
+ LastAddress = Address + ByteWidth - 1;
+
+ ACPI_DEBUG_PRINT ((ACPI_DB_IO, "Address %p LastAddress %p Length %X",
+ ACPI_CAST_PTR (void, Address), ACPI_CAST_PTR (void, LastAddress),
+ ByteWidth));
+
+ /* Maximum 16-bit address in I/O space */
+
+ if (LastAddress > ACPI_UINT16_MAX)
+ {
+ ACPI_ERROR ((AE_INFO,
+ "Illegal I/O port address/length above 64K: %p/0x%X",
+ ACPI_CAST_PTR (void, Address), ByteWidth));
+ return_ACPI_STATUS (AE_LIMIT);
+ }
+
+ /* Exit if requested address is not within the protected port table */
+
+ if (Address > AcpiProtectedPorts[ACPI_PORT_INFO_ENTRIES - 1].End)
+ {
+ return_ACPI_STATUS (AE_OK);
+ }
+
+ /* Check request against the list of protected I/O ports */
+
+ for (i = 0; i < ACPI_PORT_INFO_ENTRIES; i++, PortInfo++)
+ {
+ /*
+ * Check if the requested address range will write to a reserved
+ * port. Four cases to consider:
+ *
+ * 1) Address range is contained completely in the port address range
+ * 2) Address range overlaps port range at the port range start
+ * 3) Address range overlaps port range at the port range end
+ * 4) Address range completely encompasses the port range
+ */
+ if ((Address <= PortInfo->End) && (LastAddress >= PortInfo->Start))
+ {
+ /* Port illegality may depend on the _OSI calls made by the BIOS */
+
+ if (AcpiGbl_OsiData >= PortInfo->OsiDependency)
+ {
+ ACPI_DEBUG_PRINT ((ACPI_DB_IO,
+ "Denied AML access to port 0x%p/%X (%s 0x%.4X-0x%.4X)",
+ ACPI_CAST_PTR (void, Address), ByteWidth, PortInfo->Name,
+ PortInfo->Start, PortInfo->End));
+
+ return_ACPI_STATUS (AE_AML_ILLEGAL_ADDRESS);
+ }
+ }
+
+ /* Finished if address range ends before the end of this port */
+
+ if (LastAddress <= PortInfo->End)
+ {
+ break;
+ }
+ }
+
+ return_ACPI_STATUS (AE_OK);
+}
+
+
+/******************************************************************************
+ *
+ * FUNCTION: AcpiHwReadPort
+ *
+ * PARAMETERS: Address Address of I/O port/register to read
+ * Value Where value is placed
+ * Width Number of bits
+ *
+ * RETURN: Status and value read from port
+ *
+ * DESCRIPTION: Read data from an I/O port or register. This is a front-end
+ * to AcpiOsReadPort that performs validation on both the port
+ * address and the length.
+ *
+ *****************************************************************************/
+
+ACPI_STATUS
+AcpiHwReadPort (
+ ACPI_IO_ADDRESS Address,
+ UINT32 *Value,
+ UINT32 Width)
+{
+ ACPI_STATUS Status;
+ UINT32 OneByte;
+ UINT32 i;
+
+
+ /* Truncate address to 16 bits if requested */
+
+ if (AcpiGbl_TruncateIoAddresses)
+ {
+ Address &= ACPI_UINT16_MAX;
+ }
+
+ /* Validate the entire request and perform the I/O */
+
+ Status = AcpiHwValidateIoRequest (Address, Width);
+ if (ACPI_SUCCESS (Status))
+ {
+ Status = AcpiOsReadPort (Address, Value, Width);
+ return (Status);
+ }
+
+ if (Status != AE_AML_ILLEGAL_ADDRESS)
+ {
+ return (Status);
+ }
+
+ /*
+ * There has been a protection violation within the request. Fall
+ * back to byte granularity port I/O and ignore the failing bytes.
+ * This provides Windows compatibility.
+ */
+ for (i = 0, *Value = 0; i < Width; i += 8)
+ {
+ /* Validate and read one byte */
+
+ if (AcpiHwValidateIoRequest (Address, 8) == AE_OK)
+ {
+ Status = AcpiOsReadPort (Address, &OneByte, 8);
+ if (ACPI_FAILURE (Status))
+ {
+ return (Status);
+ }
+
+ *Value |= (OneByte << i);
+ }
+
+ Address++;
+ }
+
+ return (AE_OK);
+}
+
+
+/******************************************************************************
+ *
+ * FUNCTION: AcpiHwWritePort
+ *
+ * PARAMETERS: Address Address of I/O port/register to write
+ * Value Value to write
+ * Width Number of bits
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Write data to an I/O port or register. This is a front-end
+ * to AcpiOsWritePort that performs validation on both the port
+ * address and the length.
+ *
+ *****************************************************************************/
+
+ACPI_STATUS
+AcpiHwWritePort (
+ ACPI_IO_ADDRESS Address,
+ UINT32 Value,
+ UINT32 Width)
+{
+ ACPI_STATUS Status;
+ UINT32 i;
+
+
+ /* Truncate address to 16 bits if requested */
+
+ if (AcpiGbl_TruncateIoAddresses)
+ {
+ Address &= ACPI_UINT16_MAX;
+ }
+
+ /* Validate the entire request and perform the I/O */
+
+ Status = AcpiHwValidateIoRequest (Address, Width);
+ if (ACPI_SUCCESS (Status))
+ {
+ Status = AcpiOsWritePort (Address, Value, Width);
+ return (Status);
+ }
+
+ if (Status != AE_AML_ILLEGAL_ADDRESS)
+ {
+ return (Status);
+ }
+
+ /*
+ * There has been a protection violation within the request. Fall
+ * back to byte granularity port I/O and ignore the failing bytes.
+ * This provides Windows compatibility.
+ */
+ for (i = 0; i < Width; i += 8)
+ {
+ /* Validate and write one byte */
+
+ if (AcpiHwValidateIoRequest (Address, 8) == AE_OK)
+ {
+ Status = AcpiOsWritePort (Address, (Value >> i) & 0xFF, 8);
+ if (ACPI_FAILURE (Status))
+ {
+ return (Status);
+ }
+ }
+
+ Address++;
+ }
+
+ return (AE_OK);
+}
+
+
diff --git a/source/components/hardware/hwxface.c b/source/components/hardware/hwxface.c
new file mode 100644
index 000000000000..3fec9b566f05
--- /dev/null
+++ b/source/components/hardware/hwxface.c
@@ -0,0 +1,617 @@
+
+/******************************************************************************
+ *
+ * Module Name: hwxface - Public ACPICA hardware interfaces
+ *
+ *****************************************************************************/
+
+/*
+ * Copyright (C) 2000 - 2012, Intel Corp.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions, and the following disclaimer,
+ * without modification.
+ * 2. Redistributions in binary form must reproduce at minimum a disclaimer
+ * substantially similar to the "NO WARRANTY" disclaimer below
+ * ("Disclaimer") and any redistribution must be conditioned upon
+ * including a substantially similar Disclaimer requirement for further
+ * binary redistribution.
+ * 3. Neither the names of the above-listed copyright holders nor the names
+ * of any contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * Alternatively, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") version 2 as published by the Free
+ * Software Foundation.
+ *
+ * NO WARRANTY
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGES.
+ */
+
+#include "acpi.h"
+#include "accommon.h"
+#include "acnamesp.h"
+
+#define _COMPONENT ACPI_HARDWARE
+ ACPI_MODULE_NAME ("hwxface")
+
+
+/******************************************************************************
+ *
+ * FUNCTION: AcpiReset
+ *
+ * PARAMETERS: None
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Set reset register in memory or IO space. Note: Does not
+ * support reset register in PCI config space, this must be
+ * handled separately.
+ *
+ ******************************************************************************/
+
+ACPI_STATUS
+AcpiReset (
+ void)
+{
+ ACPI_GENERIC_ADDRESS *ResetReg;
+ ACPI_STATUS Status;
+
+
+ ACPI_FUNCTION_TRACE (AcpiReset);
+
+
+ ResetReg = &AcpiGbl_FADT.ResetRegister;
+
+ /* Check if the reset register is supported */
+
+ if (!(AcpiGbl_FADT.Flags & ACPI_FADT_RESET_REGISTER) ||
+ !ResetReg->Address)
+ {
+ return_ACPI_STATUS (AE_NOT_EXIST);
+ }
+
+ if (ResetReg->SpaceId == ACPI_ADR_SPACE_SYSTEM_IO)
+ {
+ /*
+ * For I/O space, write directly to the OSL. This bypasses the port
+ * validation mechanism, which may block a valid write to the reset
+ * register.
+ */
+ Status = AcpiOsWritePort ((ACPI_IO_ADDRESS) ResetReg->Address,
+ AcpiGbl_FADT.ResetValue, ResetReg->BitWidth);
+ }
+ else
+ {
+ /* Write the reset value to the reset register */
+
+ Status = AcpiHwWrite (AcpiGbl_FADT.ResetValue, ResetReg);
+ }
+
+ return_ACPI_STATUS (Status);
+}
+
+ACPI_EXPORT_SYMBOL (AcpiReset)
+
+
+/******************************************************************************
+ *
+ * FUNCTION: AcpiRead
+ *
+ * PARAMETERS: Value - Where the value is returned
+ * Reg - GAS register structure
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Read from either memory or IO space.
+ *
+ * LIMITATIONS: <These limitations also apply to AcpiWrite>
+ * BitWidth must be exactly 8, 16, 32, or 64.
+ * SpaceID must be SystemMemory or SystemIO.
+ * BitOffset and AccessWidth are currently ignored, as there has
+ * not been a need to implement these.
+ *
+ ******************************************************************************/
+
+ACPI_STATUS
+AcpiRead (
+ UINT64 *ReturnValue,
+ ACPI_GENERIC_ADDRESS *Reg)
+{
+ UINT32 Value;
+ UINT32 Width;
+ UINT64 Address;
+ ACPI_STATUS Status;
+
+
+ ACPI_FUNCTION_NAME (AcpiRead);
+
+
+ if (!ReturnValue)
+ {
+ return (AE_BAD_PARAMETER);
+ }
+
+ /* Validate contents of the GAS register. Allow 64-bit transfers */
+
+ Status = AcpiHwValidateRegister (Reg, 64, &Address);
+ if (ACPI_FAILURE (Status))
+ {
+ return (Status);
+ }
+
+ /* Initialize entire 64-bit return value to zero */
+
+ *ReturnValue = 0;
+ Value = 0;
+
+ /*
+ * Two address spaces supported: Memory or IO. PCI_Config is
+ * not supported here because the GAS structure is insufficient
+ */
+ if (Reg->SpaceId == ACPI_ADR_SPACE_SYSTEM_MEMORY)
+ {
+ Status = AcpiOsReadMemory ((ACPI_PHYSICAL_ADDRESS)
+ Address, ReturnValue, Reg->BitWidth);
+ if (ACPI_FAILURE (Status))
+ {
+ return (Status);
+ }
+ }
+ else /* ACPI_ADR_SPACE_SYSTEM_IO, validated earlier */
+ {
+ Width = Reg->BitWidth;
+ if (Width == 64)
+ {
+ Width = 32; /* Break into two 32-bit transfers */
+ }
+
+ Status = AcpiHwReadPort ((ACPI_IO_ADDRESS)
+ Address, &Value, Width);
+ if (ACPI_FAILURE (Status))
+ {
+ return (Status);
+ }
+ *ReturnValue = Value;
+
+ if (Reg->BitWidth == 64)
+ {
+ /* Read the top 32 bits */
+
+ Status = AcpiHwReadPort ((ACPI_IO_ADDRESS)
+ (Address + 4), &Value, 32);
+ if (ACPI_FAILURE (Status))
+ {
+ return (Status);
+ }
+ *ReturnValue |= ((UINT64) Value << 32);
+ }
+ }
+
+ ACPI_DEBUG_PRINT ((ACPI_DB_IO,
+ "Read: %8.8X%8.8X width %2d from %8.8X%8.8X (%s)\n",
+ ACPI_FORMAT_UINT64 (*ReturnValue), Reg->BitWidth,
+ ACPI_FORMAT_UINT64 (Address),
+ AcpiUtGetRegionName (Reg->SpaceId)));
+
+ return (Status);
+}
+
+ACPI_EXPORT_SYMBOL (AcpiRead)
+
+
+/******************************************************************************
+ *
+ * FUNCTION: AcpiWrite
+ *
+ * PARAMETERS: Value - Value to be written
+ * Reg - GAS register structure
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Write to either memory or IO space.
+ *
+ ******************************************************************************/
+
+ACPI_STATUS
+AcpiWrite (
+ UINT64 Value,
+ ACPI_GENERIC_ADDRESS *Reg)
+{
+ UINT32 Width;
+ UINT64 Address;
+ ACPI_STATUS Status;
+
+
+ ACPI_FUNCTION_NAME (AcpiWrite);
+
+
+ /* Validate contents of the GAS register. Allow 64-bit transfers */
+
+ Status = AcpiHwValidateRegister (Reg, 64, &Address);
+ if (ACPI_FAILURE (Status))
+ {
+ return (Status);
+ }
+
+ /*
+ * Two address spaces supported: Memory or IO. PCI_Config is
+ * not supported here because the GAS structure is insufficient
+ */
+ if (Reg->SpaceId == ACPI_ADR_SPACE_SYSTEM_MEMORY)
+ {
+ Status = AcpiOsWriteMemory ((ACPI_PHYSICAL_ADDRESS)
+ Address, Value, Reg->BitWidth);
+ if (ACPI_FAILURE (Status))
+ {
+ return (Status);
+ }
+ }
+ else /* ACPI_ADR_SPACE_SYSTEM_IO, validated earlier */
+ {
+ Width = Reg->BitWidth;
+ if (Width == 64)
+ {
+ Width = 32; /* Break into two 32-bit transfers */
+ }
+
+ Status = AcpiHwWritePort ((ACPI_IO_ADDRESS)
+ Address, ACPI_LODWORD (Value), Width);
+ if (ACPI_FAILURE (Status))
+ {
+ return (Status);
+ }
+
+ if (Reg->BitWidth == 64)
+ {
+ Status = AcpiHwWritePort ((ACPI_IO_ADDRESS)
+ (Address + 4), ACPI_HIDWORD (Value), 32);
+ if (ACPI_FAILURE (Status))
+ {
+ return (Status);
+ }
+ }
+ }
+
+ ACPI_DEBUG_PRINT ((ACPI_DB_IO,
+ "Wrote: %8.8X%8.8X width %2d to %8.8X%8.8X (%s)\n",
+ ACPI_FORMAT_UINT64 (Value), Reg->BitWidth,
+ ACPI_FORMAT_UINT64 (Address),
+ AcpiUtGetRegionName (Reg->SpaceId)));
+
+ return (Status);
+}
+
+ACPI_EXPORT_SYMBOL (AcpiWrite)
+
+
+#if (!ACPI_REDUCED_HARDWARE)
+/*******************************************************************************
+ *
+ * FUNCTION: AcpiReadBitRegister
+ *
+ * PARAMETERS: RegisterId - ID of ACPI Bit Register to access
+ * ReturnValue - Value that was read from the register,
+ * normalized to bit position zero.
+ *
+ * RETURN: Status and the value read from the specified Register. Value
+ * returned is normalized to bit0 (is shifted all the way right)
+ *
+ * DESCRIPTION: ACPI BitRegister read function. Does not acquire the HW lock.
+ *
+ * SUPPORTS: Bit fields in PM1 Status, PM1 Enable, PM1 Control, and
+ * PM2 Control.
+ *
+ * Note: The hardware lock is not required when reading the ACPI bit registers
+ * since almost all of them are single bit and it does not matter that
+ * the parent hardware register can be split across two physical
+ * registers. The only multi-bit field is SLP_TYP in the PM1 control
+ * register, but this field does not cross an 8-bit boundary (nor does
+ * it make much sense to actually read this field.)
+ *
+ ******************************************************************************/
+
+ACPI_STATUS
+AcpiReadBitRegister (
+ UINT32 RegisterId,
+ UINT32 *ReturnValue)
+{
+ ACPI_BIT_REGISTER_INFO *BitRegInfo;
+ UINT32 RegisterValue;
+ UINT32 Value;
+ ACPI_STATUS Status;
+
+
+ ACPI_FUNCTION_TRACE_U32 (AcpiReadBitRegister, RegisterId);
+
+
+ /* Get the info structure corresponding to the requested ACPI Register */
+
+ BitRegInfo = AcpiHwGetBitRegisterInfo (RegisterId);
+ if (!BitRegInfo)
+ {
+ return_ACPI_STATUS (AE_BAD_PARAMETER);
+ }
+
+ /* Read the entire parent register */
+
+ Status = AcpiHwRegisterRead (BitRegInfo->ParentRegister,
+ &RegisterValue);
+ if (ACPI_FAILURE (Status))
+ {
+ return_ACPI_STATUS (Status);
+ }
+
+ /* Normalize the value that was read, mask off other bits */
+
+ Value = ((RegisterValue & BitRegInfo->AccessBitMask)
+ >> BitRegInfo->BitPosition);
+
+ ACPI_DEBUG_PRINT ((ACPI_DB_IO,
+ "BitReg %X, ParentReg %X, Actual %8.8X, ReturnValue %8.8X\n",
+ RegisterId, BitRegInfo->ParentRegister, RegisterValue, Value));
+
+ *ReturnValue = Value;
+ return_ACPI_STATUS (AE_OK);
+}
+
+ACPI_EXPORT_SYMBOL (AcpiReadBitRegister)
+
+
+/*******************************************************************************
+ *
+ * FUNCTION: AcpiWriteBitRegister
+ *
+ * PARAMETERS: RegisterId - ID of ACPI Bit Register to access
+ * Value - Value to write to the register, in bit
+ * position zero. The bit is automaticallly
+ * shifted to the correct position.
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: ACPI Bit Register write function. Acquires the hardware lock
+ * since most operations require a read/modify/write sequence.
+ *
+ * SUPPORTS: Bit fields in PM1 Status, PM1 Enable, PM1 Control, and
+ * PM2 Control.
+ *
+ * Note that at this level, the fact that there may be actually two
+ * hardware registers (A and B - and B may not exist) is abstracted.
+ *
+ ******************************************************************************/
+
+ACPI_STATUS
+AcpiWriteBitRegister (
+ UINT32 RegisterId,
+ UINT32 Value)
+{
+ ACPI_BIT_REGISTER_INFO *BitRegInfo;
+ ACPI_CPU_FLAGS LockFlags;
+ UINT32 RegisterValue;
+ ACPI_STATUS Status = AE_OK;
+
+
+ ACPI_FUNCTION_TRACE_U32 (AcpiWriteBitRegister, RegisterId);
+
+
+ /* Get the info structure corresponding to the requested ACPI Register */
+
+ BitRegInfo = AcpiHwGetBitRegisterInfo (RegisterId);
+ if (!BitRegInfo)
+ {
+ return_ACPI_STATUS (AE_BAD_PARAMETER);
+ }
+
+ LockFlags = AcpiOsAcquireLock (AcpiGbl_HardwareLock);
+
+ /*
+ * At this point, we know that the parent register is one of the
+ * following: PM1 Status, PM1 Enable, PM1 Control, or PM2 Control
+ */
+ if (BitRegInfo->ParentRegister != ACPI_REGISTER_PM1_STATUS)
+ {
+ /*
+ * 1) Case for PM1 Enable, PM1 Control, and PM2 Control
+ *
+ * Perform a register read to preserve the bits that we are not
+ * interested in
+ */
+ Status = AcpiHwRegisterRead (BitRegInfo->ParentRegister,
+ &RegisterValue);
+ if (ACPI_FAILURE (Status))
+ {
+ goto UnlockAndExit;
+ }
+
+ /*
+ * Insert the input bit into the value that was just read
+ * and write the register
+ */
+ ACPI_REGISTER_INSERT_VALUE (RegisterValue, BitRegInfo->BitPosition,
+ BitRegInfo->AccessBitMask, Value);
+
+ Status = AcpiHwRegisterWrite (BitRegInfo->ParentRegister,
+ RegisterValue);
+ }
+ else
+ {
+ /*
+ * 2) Case for PM1 Status
+ *
+ * The Status register is different from the rest. Clear an event
+ * by writing 1, writing 0 has no effect. So, the only relevant
+ * information is the single bit we're interested in, all others
+ * should be written as 0 so they will be left unchanged.
+ */
+ RegisterValue = ACPI_REGISTER_PREPARE_BITS (Value,
+ BitRegInfo->BitPosition, BitRegInfo->AccessBitMask);
+
+ /* No need to write the register if value is all zeros */
+
+ if (RegisterValue)
+ {
+ Status = AcpiHwRegisterWrite (ACPI_REGISTER_PM1_STATUS,
+ RegisterValue);
+ }
+ }
+
+ ACPI_DEBUG_PRINT ((ACPI_DB_IO,
+ "BitReg %X, ParentReg %X, Value %8.8X, Actual %8.8X\n",
+ RegisterId, BitRegInfo->ParentRegister, Value, RegisterValue));
+
+
+UnlockAndExit:
+
+ AcpiOsReleaseLock (AcpiGbl_HardwareLock, LockFlags);
+ return_ACPI_STATUS (Status);
+}
+
+ACPI_EXPORT_SYMBOL (AcpiWriteBitRegister)
+
+#endif /* !ACPI_REDUCED_HARDWARE */
+
+
+/*******************************************************************************
+ *
+ * FUNCTION: AcpiGetSleepTypeData
+ *
+ * PARAMETERS: SleepState - Numeric sleep state
+ * *SleepTypeA - Where SLP_TYPa is returned
+ * *SleepTypeB - Where SLP_TYPb is returned
+ *
+ * RETURN: Status - ACPI status
+ *
+ * DESCRIPTION: Obtain the SLP_TYPa and SLP_TYPb values for the requested sleep
+ * state.
+ *
+ ******************************************************************************/
+
+ACPI_STATUS
+AcpiGetSleepTypeData (
+ UINT8 SleepState,
+ UINT8 *SleepTypeA,
+ UINT8 *SleepTypeB)
+{
+ ACPI_STATUS Status = AE_OK;
+ ACPI_EVALUATE_INFO *Info;
+
+
+ ACPI_FUNCTION_TRACE (AcpiGetSleepTypeData);
+
+
+ /* Validate parameters */
+
+ if ((SleepState > ACPI_S_STATES_MAX) ||
+ !SleepTypeA ||
+ !SleepTypeB)
+ {
+ return_ACPI_STATUS (AE_BAD_PARAMETER);
+ }
+
+ /* Allocate the evaluation information block */
+
+ Info = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_EVALUATE_INFO));
+ if (!Info)
+ {
+ return_ACPI_STATUS (AE_NO_MEMORY);
+ }
+
+ Info->Pathname = ACPI_CAST_PTR (char, AcpiGbl_SleepStateNames[SleepState]);
+
+ /* Evaluate the namespace object containing the values for this state */
+
+ Status = AcpiNsEvaluate (Info);
+ if (ACPI_FAILURE (Status))
+ {
+ ACPI_DEBUG_PRINT ((ACPI_DB_EXEC,
+ "%s while evaluating SleepState [%s]\n",
+ AcpiFormatException (Status), Info->Pathname));
+
+ goto Cleanup;
+ }
+
+ /* Must have a return object */
+
+ if (!Info->ReturnObject)
+ {
+ ACPI_ERROR ((AE_INFO, "No Sleep State object returned from [%s]",
+ Info->Pathname));
+ Status = AE_NOT_EXIST;
+ }
+
+ /* It must be of type Package */
+
+ else if (Info->ReturnObject->Common.Type != ACPI_TYPE_PACKAGE)
+ {
+ ACPI_ERROR ((AE_INFO, "Sleep State return object is not a Package"));
+ Status = AE_AML_OPERAND_TYPE;
+ }
+
+ /*
+ * The package must have at least two elements. NOTE (March 2005): This
+ * goes against the current ACPI spec which defines this object as a
+ * package with one encoded DWORD element. However, existing practice
+ * by BIOS vendors seems to be to have 2 or more elements, at least
+ * one per sleep type (A/B).
+ */
+ else if (Info->ReturnObject->Package.Count < 2)
+ {
+ ACPI_ERROR ((AE_INFO,
+ "Sleep State return package does not have at least two elements"));
+ Status = AE_AML_NO_OPERAND;
+ }
+
+ /* The first two elements must both be of type Integer */
+
+ else if (((Info->ReturnObject->Package.Elements[0])->Common.Type
+ != ACPI_TYPE_INTEGER) ||
+ ((Info->ReturnObject->Package.Elements[1])->Common.Type
+ != ACPI_TYPE_INTEGER))
+ {
+ ACPI_ERROR ((AE_INFO,
+ "Sleep State return package elements are not both Integers "
+ "(%s, %s)",
+ AcpiUtGetObjectTypeName (Info->ReturnObject->Package.Elements[0]),
+ AcpiUtGetObjectTypeName (Info->ReturnObject->Package.Elements[1])));
+ Status = AE_AML_OPERAND_TYPE;
+ }
+ else
+ {
+ /* Valid _Sx_ package size, type, and value */
+
+ *SleepTypeA = (UINT8)
+ (Info->ReturnObject->Package.Elements[0])->Integer.Value;
+ *SleepTypeB = (UINT8)
+ (Info->ReturnObject->Package.Elements[1])->Integer.Value;
+ }
+
+ if (ACPI_FAILURE (Status))
+ {
+ ACPI_EXCEPTION ((AE_INFO, Status,
+ "While evaluating SleepState [%s], bad Sleep object %p type %s",
+ Info->Pathname, Info->ReturnObject,
+ AcpiUtGetObjectTypeName (Info->ReturnObject)));
+ }
+
+ AcpiUtRemoveReference (Info->ReturnObject);
+
+Cleanup:
+ ACPI_FREE (Info);
+ return_ACPI_STATUS (Status);
+}
+
+ACPI_EXPORT_SYMBOL (AcpiGetSleepTypeData)
diff --git a/source/components/hardware/hwxfsleep.c b/source/components/hardware/hwxfsleep.c
new file mode 100644
index 000000000000..39bf122a072e
--- /dev/null
+++ b/source/components/hardware/hwxfsleep.c
@@ -0,0 +1,474 @@
+/******************************************************************************
+ *
+ * Name: hwxfsleep.c - ACPI Hardware Sleep/Wake External Interfaces
+ *
+ *****************************************************************************/
+
+/*
+ * Copyright (C) 2000 - 2012, Intel Corp.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions, and the following disclaimer,
+ * without modification.
+ * 2. Redistributions in binary form must reproduce at minimum a disclaimer
+ * substantially similar to the "NO WARRANTY" disclaimer below
+ * ("Disclaimer") and any redistribution must be conditioned upon
+ * including a substantially similar Disclaimer requirement for further
+ * binary redistribution.
+ * 3. Neither the names of the above-listed copyright holders nor the names
+ * of any contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * Alternatively, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") version 2 as published by the Free
+ * Software Foundation.
+ *
+ * NO WARRANTY
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGES.
+ */
+
+#include "acpi.h"
+#include "accommon.h"
+
+#define _COMPONENT ACPI_HARDWARE
+ ACPI_MODULE_NAME ("hwxfsleep")
+
+/* Local prototypes */
+
+static ACPI_STATUS
+AcpiHwSleepDispatch (
+ UINT8 SleepState,
+ UINT32 FunctionId);
+
+/*
+ * Dispatch table used to efficiently branch to the various sleep
+ * functions.
+ */
+#define ACPI_SLEEP_FUNCTION_ID 0
+#define ACPI_WAKE_PREP_FUNCTION_ID 1
+#define ACPI_WAKE_FUNCTION_ID 2
+
+/* Legacy functions are optional, based upon ACPI_REDUCED_HARDWARE */
+
+static ACPI_SLEEP_FUNCTIONS AcpiSleepDispatch[] =
+{
+ {ACPI_HW_OPTIONAL_FUNCTION (AcpiHwLegacySleep), AcpiHwExtendedSleep},
+ {ACPI_HW_OPTIONAL_FUNCTION (AcpiHwLegacyWakePrep), AcpiHwExtendedWakePrep},
+ {ACPI_HW_OPTIONAL_FUNCTION (AcpiHwLegacyWake), AcpiHwExtendedWake}
+};
+
+
+/*
+ * These functions are removed for the ACPI_REDUCED_HARDWARE case:
+ * AcpiSetFirmwareWakingVector
+ * AcpiSetFirmwareWakingVector64
+ * AcpiEnterSleepStateS4bios
+ */
+
+#if (!ACPI_REDUCED_HARDWARE)
+/*******************************************************************************
+ *
+ * FUNCTION: AcpiSetFirmwareWakingVector
+ *
+ * PARAMETERS: PhysicalAddress - 32-bit physical address of ACPI real mode
+ * entry point.
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Sets the 32-bit FirmwareWakingVector field of the FACS
+ *
+ ******************************************************************************/
+
+ACPI_STATUS
+AcpiSetFirmwareWakingVector (
+ UINT32 PhysicalAddress)
+{
+ ACPI_FUNCTION_TRACE (AcpiSetFirmwareWakingVector);
+
+
+ /* Set the 32-bit vector */
+
+ AcpiGbl_FACS->FirmwareWakingVector = PhysicalAddress;
+
+ /* Clear the 64-bit vector if it exists */
+
+ if ((AcpiGbl_FACS->Length > 32) && (AcpiGbl_FACS->Version >= 1))
+ {
+ AcpiGbl_FACS->XFirmwareWakingVector = 0;
+ }
+
+ return_ACPI_STATUS (AE_OK);
+}
+
+ACPI_EXPORT_SYMBOL (AcpiSetFirmwareWakingVector)
+
+
+#if ACPI_MACHINE_WIDTH == 64
+/*******************************************************************************
+ *
+ * FUNCTION: AcpiSetFirmwareWakingVector64
+ *
+ * PARAMETERS: PhysicalAddress - 64-bit physical address of ACPI protected
+ * mode entry point.
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Sets the 64-bit X_FirmwareWakingVector field of the FACS, if
+ * it exists in the table. This function is intended for use with
+ * 64-bit host operating systems.
+ *
+ ******************************************************************************/
+
+ACPI_STATUS
+AcpiSetFirmwareWakingVector64 (
+ UINT64 PhysicalAddress)
+{
+ ACPI_FUNCTION_TRACE (AcpiSetFirmwareWakingVector64);
+
+
+ /* Determine if the 64-bit vector actually exists */
+
+ if ((AcpiGbl_FACS->Length <= 32) || (AcpiGbl_FACS->Version < 1))
+ {
+ return_ACPI_STATUS (AE_NOT_EXIST);
+ }
+
+ /* Clear 32-bit vector, set the 64-bit X_ vector */
+
+ AcpiGbl_FACS->FirmwareWakingVector = 0;
+ AcpiGbl_FACS->XFirmwareWakingVector = PhysicalAddress;
+ return_ACPI_STATUS (AE_OK);
+}
+
+ACPI_EXPORT_SYMBOL (AcpiSetFirmwareWakingVector64)
+#endif
+
+
+/*******************************************************************************
+ *
+ * FUNCTION: AcpiEnterSleepStateS4bios
+ *
+ * PARAMETERS: None
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Perform a S4 bios request.
+ * THIS FUNCTION MUST BE CALLED WITH INTERRUPTS DISABLED
+ *
+ ******************************************************************************/
+
+ACPI_STATUS
+AcpiEnterSleepStateS4bios (
+ void)
+{
+ UINT32 InValue;
+ ACPI_STATUS Status;
+
+
+ ACPI_FUNCTION_TRACE (AcpiEnterSleepStateS4bios);
+
+
+ /* Clear the wake status bit (PM1) */
+
+ Status = AcpiWriteBitRegister (ACPI_BITREG_WAKE_STATUS, ACPI_CLEAR_STATUS);
+ if (ACPI_FAILURE (Status))
+ {
+ return_ACPI_STATUS (Status);
+ }
+
+ Status = AcpiHwClearAcpiStatus ();
+ if (ACPI_FAILURE (Status))
+ {
+ return_ACPI_STATUS (Status);
+ }
+
+ /*
+ * 1) Disable/Clear all GPEs
+ * 2) Enable all wakeup GPEs
+ */
+ Status = AcpiHwDisableAllGpes ();
+ if (ACPI_FAILURE (Status))
+ {
+ return_ACPI_STATUS (Status);
+ }
+ AcpiGbl_SystemAwakeAndRunning = FALSE;
+
+ Status = AcpiHwEnableAllWakeupGpes ();
+ if (ACPI_FAILURE (Status))
+ {
+ return_ACPI_STATUS (Status);
+ }
+
+ ACPI_FLUSH_CPU_CACHE ();
+
+ Status = AcpiHwWritePort (AcpiGbl_FADT.SmiCommand,
+ (UINT32) AcpiGbl_FADT.S4BiosRequest, 8);
+
+ do {
+ AcpiOsStall(1000);
+ Status = AcpiReadBitRegister (ACPI_BITREG_WAKE_STATUS, &InValue);
+ if (ACPI_FAILURE (Status))
+ {
+ return_ACPI_STATUS (Status);
+ }
+ } while (!InValue);
+
+ return_ACPI_STATUS (AE_OK);
+}
+
+ACPI_EXPORT_SYMBOL (AcpiEnterSleepStateS4bios)
+
+#endif /* !ACPI_REDUCED_HARDWARE */
+
+
+/*******************************************************************************
+ *
+ * FUNCTION: AcpiHwSleepDispatch
+ *
+ * PARAMETERS: SleepState - Which sleep state to enter/exit
+ * FunctionId - Sleep, WakePrep, or Wake
+ *
+ * RETURN: Status from the invoked sleep handling function.
+ *
+ * DESCRIPTION: Dispatch a sleep/wake request to the appropriate handling
+ * function.
+ *
+ ******************************************************************************/
+
+static ACPI_STATUS
+AcpiHwSleepDispatch (
+ UINT8 SleepState,
+ UINT32 FunctionId)
+{
+ ACPI_STATUS Status;
+ ACPI_SLEEP_FUNCTIONS *SleepFunctions = &AcpiSleepDispatch[FunctionId];
+
+
+#if (!ACPI_REDUCED_HARDWARE)
+
+ /*
+ * If the Hardware Reduced flag is set (from the FADT), we must
+ * use the extended sleep registers
+ */
+ if (AcpiGbl_ReducedHardware ||
+ AcpiGbl_FADT.SleepControl.Address)
+ {
+ Status = SleepFunctions->ExtendedFunction (SleepState);
+ }
+ else
+ {
+ /* Legacy sleep */
+
+ Status = SleepFunctions->LegacyFunction (SleepState);
+ }
+
+ return (Status);
+
+#else
+ /*
+ * For the case where reduced-hardware-only code is being generated,
+ * we know that only the extended sleep registers are available
+ */
+ Status = SleepFunctions->ExtendedFunction (SleepState);
+ return (Status);
+
+#endif /* !ACPI_REDUCED_HARDWARE */
+}
+
+
+/*******************************************************************************
+ *
+ * FUNCTION: AcpiEnterSleepStatePrep
+ *
+ * PARAMETERS: SleepState - Which sleep state to enter
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Prepare to enter a system sleep state.
+ * This function must execute with interrupts enabled.
+ * We break sleeping into 2 stages so that OSPM can handle
+ * various OS-specific tasks between the two steps.
+ *
+ ******************************************************************************/
+
+ACPI_STATUS
+AcpiEnterSleepStatePrep (
+ UINT8 SleepState)
+{
+ ACPI_STATUS Status;
+ ACPI_OBJECT_LIST ArgList;
+ ACPI_OBJECT Arg;
+ UINT32 SstValue;
+
+
+ ACPI_FUNCTION_TRACE (AcpiEnterSleepStatePrep);
+
+
+ /* _PSW methods could be run here to enable wake-on keyboard, LAN, etc. */
+
+ Status = AcpiGetSleepTypeData (SleepState,
+ &AcpiGbl_SleepTypeA, &AcpiGbl_SleepTypeB);
+ if (ACPI_FAILURE (Status))
+ {
+ return_ACPI_STATUS (Status);
+ }
+
+ /* Execute the _PTS method (Prepare To Sleep) */
+
+ ArgList.Count = 1;
+ ArgList.Pointer = &Arg;
+ Arg.Type = ACPI_TYPE_INTEGER;
+ Arg.Integer.Value = SleepState;
+
+ Status = AcpiEvaluateObject (NULL, METHOD_NAME__PTS, &ArgList, NULL);
+ if (ACPI_FAILURE (Status) && Status != AE_NOT_FOUND)
+ {
+ return_ACPI_STATUS (Status);
+ }
+
+ /* Setup the argument to the _SST method (System STatus) */
+
+ switch (SleepState)
+ {
+ case ACPI_STATE_S0:
+ SstValue = ACPI_SST_WORKING;
+ break;
+
+ case ACPI_STATE_S1:
+ case ACPI_STATE_S2:
+ case ACPI_STATE_S3:
+ SstValue = ACPI_SST_SLEEPING;
+ break;
+
+ case ACPI_STATE_S4:
+ SstValue = ACPI_SST_SLEEP_CONTEXT;
+ break;
+
+ default:
+ SstValue = ACPI_SST_INDICATOR_OFF; /* Default is off */
+ break;
+ }
+
+ /*
+ * Set the system indicators to show the desired sleep state.
+ * _SST is an optional method (return no error if not found)
+ */
+ AcpiHwExecuteSleepMethod (METHOD_NAME__SST, SstValue);
+ return_ACPI_STATUS (AE_OK);
+}
+
+ACPI_EXPORT_SYMBOL (AcpiEnterSleepStatePrep)
+
+
+/*******************************************************************************
+ *
+ * FUNCTION: AcpiEnterSleepState
+ *
+ * PARAMETERS: SleepState - Which sleep state to enter
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Enter a system sleep state
+ * THIS FUNCTION MUST BE CALLED WITH INTERRUPTS DISABLED
+ *
+ ******************************************************************************/
+
+ACPI_STATUS
+AcpiEnterSleepState (
+ UINT8 SleepState)
+{
+ ACPI_STATUS Status;
+
+
+ ACPI_FUNCTION_TRACE (AcpiEnterSleepState);
+
+
+ if ((AcpiGbl_SleepTypeA > ACPI_SLEEP_TYPE_MAX) ||
+ (AcpiGbl_SleepTypeB > ACPI_SLEEP_TYPE_MAX))
+ {
+ ACPI_ERROR ((AE_INFO, "Sleep values out of range: A=0x%X B=0x%X",
+ AcpiGbl_SleepTypeA, AcpiGbl_SleepTypeB));
+ return_ACPI_STATUS (AE_AML_OPERAND_VALUE);
+ }
+
+ Status = AcpiHwSleepDispatch (SleepState, ACPI_SLEEP_FUNCTION_ID);
+ return_ACPI_STATUS (Status);
+}
+
+ACPI_EXPORT_SYMBOL (AcpiEnterSleepState)
+
+
+/*******************************************************************************
+ *
+ * FUNCTION: AcpiLeaveSleepStatePrep
+ *
+ * PARAMETERS: SleepState - Which sleep state we are exiting
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Perform the first state of OS-independent ACPI cleanup after a
+ * sleep. Called with interrupts DISABLED.
+ * We break wake/resume into 2 stages so that OSPM can handle
+ * various OS-specific tasks between the two steps.
+ *
+ ******************************************************************************/
+
+ACPI_STATUS
+AcpiLeaveSleepStatePrep (
+ UINT8 SleepState)
+{
+ ACPI_STATUS Status;
+
+
+ ACPI_FUNCTION_TRACE (AcpiLeaveSleepStatePrep);
+
+
+ Status = AcpiHwSleepDispatch (SleepState, ACPI_WAKE_PREP_FUNCTION_ID);
+ return_ACPI_STATUS (Status);
+}
+
+ACPI_EXPORT_SYMBOL (AcpiLeaveSleepStatePrep)
+
+
+/*******************************************************************************
+ *
+ * FUNCTION: AcpiLeaveSleepState
+ *
+ * PARAMETERS: SleepState - Which sleep state we are exiting
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Perform OS-independent ACPI cleanup after a sleep
+ * Called with interrupts ENABLED.
+ *
+ ******************************************************************************/
+
+ACPI_STATUS
+AcpiLeaveSleepState (
+ UINT8 SleepState)
+{
+ ACPI_STATUS Status;
+
+
+ ACPI_FUNCTION_TRACE (AcpiLeaveSleepState);
+
+
+ Status = AcpiHwSleepDispatch (SleepState, ACPI_WAKE_FUNCTION_ID);
+ return_ACPI_STATUS (Status);
+}
+
+ACPI_EXPORT_SYMBOL (AcpiLeaveSleepState)