Back to home page

Quest Cross Reference

 
 

    


Warning, cross-references for /kernel/drivers/acpica/hwsleep.c need to be fixed.

0001 
0002 /******************************************************************************
0003  *
0004  * Name: hwsleep.c - ACPI Hardware Sleep/Wake Interface
0005  *
0006  *****************************************************************************/
0007 
0008 /******************************************************************************
0009  *
0010  * 1. Copyright Notice
0011  *
0012  * Some or all of this work - Copyright (c) 1999 - 2009, Intel Corp.
0013  * All rights reserved.
0014  *
0015  * 2. License
0016  *
0017  * 2.1. This is your license from Intel Corp. under its intellectual property
0018  * rights.  You may have additional license terms from the party that provided
0019  * you this software, covering your right to use that party's intellectual
0020  * property rights.
0021  *
0022  * 2.2. Intel grants, free of charge, to any person ("Licensee") obtaining a
0023  * copy of the source code appearing in this file ("Covered Code") an
0024  * irrevocable, perpetual, worldwide license under Intel's copyrights in the
0025  * base code distributed originally by Intel ("Original Intel Code") to copy,
0026  * make derivatives, distribute, use and display any portion of the Covered
0027  * Code in any form, with the right to sublicense such rights; and
0028  *
0029  * 2.3. Intel grants Licensee a non-exclusive and non-transferable patent
0030  * license (with the right to sublicense), under only those claims of Intel
0031  * patents that are infringed by the Original Intel Code, to make, use, sell,
0032  * offer to sell, and import the Covered Code and derivative works thereof
0033  * solely to the minimum extent necessary to exercise the above copyright
0034  * license, and in no event shall the patent license extend to any additions
0035  * to or modifications of the Original Intel Code.  No other license or right
0036  * is granted directly or by implication, estoppel or otherwise;
0037  *
0038  * The above copyright and patent license is granted only if the following
0039  * conditions are met:
0040  *
0041  * 3. Conditions
0042  *
0043  * 3.1. Redistribution of Source with Rights to Further Distribute Source.
0044  * Redistribution of source code of any substantial portion of the Covered
0045  * Code or modification with rights to further distribute source must include
0046  * the above Copyright Notice, the above License, this list of Conditions,
0047  * and the following Disclaimer and Export Compliance provision.  In addition,
0048  * Licensee must cause all Covered Code to which Licensee contributes to
0049  * contain a file documenting the changes Licensee made to create that Covered
0050  * Code and the date of any change.  Licensee must include in that file the
0051  * documentation of any changes made by any predecessor Licensee.  Licensee
0052  * must include a prominent statement that the modification is derived,
0053  * directly or indirectly, from Original Intel Code.
0054  *
0055  * 3.2. Redistribution of Source with no Rights to Further Distribute Source.
0056  * Redistribution of source code of any substantial portion of the Covered
0057  * Code or modification without rights to further distribute source must
0058  * include the following Disclaimer and Export Compliance provision in the
0059  * documentation and/or other materials provided with distribution.  In
0060  * addition, Licensee may not authorize further sublicense of source of any
0061  * portion of the Covered Code, and must include terms to the effect that the
0062  * license from Licensee to its licensee is limited to the intellectual
0063  * property embodied in the software Licensee provides to its licensee, and
0064  * not to intellectual property embodied in modifications its licensee may
0065  * make.
0066  *
0067  * 3.3. Redistribution of Executable. Redistribution in executable form of any
0068  * substantial portion of the Covered Code or modification must reproduce the
0069  * above Copyright Notice, and the following Disclaimer and Export Compliance
0070  * provision in the documentation and/or other materials provided with the
0071  * distribution.
0072  *
0073  * 3.4. Intel retains all right, title, and interest in and to the Original
0074  * Intel Code.
0075  *
0076  * 3.5. Neither the name Intel nor any other trademark owned or controlled by
0077  * Intel shall be used in advertising or otherwise to promote the sale, use or
0078  * other dealings in products derived from or relating to the Covered Code
0079  * without prior written authorization from Intel.
0080  *
0081  * 4. Disclaimer and Export Compliance
0082  *
0083  * 4.1. INTEL MAKES NO WARRANTY OF ANY KIND REGARDING ANY SOFTWARE PROVIDED
0084  * HERE.  ANY SOFTWARE ORIGINATING FROM INTEL OR DERIVED FROM INTEL SOFTWARE
0085  * IS PROVIDED "AS IS," AND INTEL WILL NOT PROVIDE ANY SUPPORT,  ASSISTANCE,
0086  * INSTALLATION, TRAINING OR OTHER SERVICES.  INTEL WILL NOT PROVIDE ANY
0087  * UPDATES, ENHANCEMENTS OR EXTENSIONS.  INTEL SPECIFICALLY DISCLAIMS ANY
0088  * IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT AND FITNESS FOR A
0089  * PARTICULAR PURPOSE.
0090  *
0091  * 4.2. IN NO EVENT SHALL INTEL HAVE ANY LIABILITY TO LICENSEE, ITS LICENSEES
0092  * OR ANY OTHER THIRD PARTY, FOR ANY LOST PROFITS, LOST DATA, LOSS OF USE OR
0093  * COSTS OF PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, OR FOR ANY INDIRECT,
0094  * SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THIS AGREEMENT, UNDER ANY
0095  * CAUSE OF ACTION OR THEORY OF LIABILITY, AND IRRESPECTIVE OF WHETHER INTEL
0096  * HAS ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES.  THESE LIMITATIONS
0097  * SHALL APPLY NOTWITHSTANDING THE FAILURE OF THE ESSENTIAL PURPOSE OF ANY
0098  * LIMITED REMEDY.
0099  *
0100  * 4.3. Licensee shall not export, either directly or indirectly, any of this
0101  * software or system incorporating such software without first obtaining any
0102  * required license or other approval from the U. S. Department of Commerce or
0103  * any other agency or department of the United States Government.  In the
0104  * event Licensee exports any such software from the United States or
0105  * re-exports any such software from a foreign destination, Licensee shall
0106  * ensure that the distribution and export/re-export of the software is in
0107  * compliance with all laws, regulations, orders, or other restrictions of the
0108  * U.S. Export Administration Regulations. Licensee agrees that neither it nor
0109  * any of its subsidiaries will export/re-export any technical data, process,
0110  * software, or service, directly or indirectly, to any country for which the
0111  * United States government or any agency thereof requires an export license,
0112  * other governmental approval, or letter of assurance, without first obtaining
0113  * such license, approval or letter.
0114  *
0115  *****************************************************************************/
0116 
0117 #include "acpi.h"
0118 #include "accommon.h"
0119 
0120 #define _COMPONENT          ACPI_HARDWARE
0121         ACPI_MODULE_NAME    ("hwsleep")
0122 
0123 
0124 /*******************************************************************************
0125  *
0126  * FUNCTION:    AcpiSetFirmwareWakingVector
0127  *
0128  * PARAMETERS:  PhysicalAddress     - 32-bit physical address of ACPI real mode
0129  *                                    entry point.
0130  *
0131  * RETURN:      Status
0132  *
0133  * DESCRIPTION: Sets the 32-bit FirmwareWakingVector field of the FACS
0134  *
0135  ******************************************************************************/
0136 
0137 ACPI_STATUS
0138 AcpiSetFirmwareWakingVector (
0139     UINT32                  PhysicalAddress)
0140 {
0141     ACPI_FUNCTION_TRACE (AcpiSetFirmwareWakingVector);
0142 
0143 
0144     /* Set the 32-bit vector */
0145 
0146     AcpiGbl_FACS->FirmwareWakingVector = PhysicalAddress;
0147 
0148     /* Clear the 64-bit vector if it exists */
0149 
0150     if ((AcpiGbl_FACS->Length > 32) && (AcpiGbl_FACS->Version >= 1))
0151     {
0152         AcpiGbl_FACS->XFirmwareWakingVector = 0;
0153     }
0154 
0155     return_ACPI_STATUS (AE_OK);
0156 }
0157 
0158 ACPI_EXPORT_SYMBOL (AcpiSetFirmwareWakingVector)
0159 
0160 
0161 #if ACPI_MACHINE_WIDTH == 64
0162 /*******************************************************************************
0163  *
0164  * FUNCTION:    AcpiSetFirmwareWakingVector64
0165  *
0166  * PARAMETERS:  PhysicalAddress     - 64-bit physical address of ACPI protected
0167  *                                    mode entry point.
0168  *
0169  * RETURN:      Status
0170  *
0171  * DESCRIPTION: Sets the 64-bit X_FirmwareWakingVector field of the FACS, if
0172  *              it exists in the table. This function is intended for use with
0173  *              64-bit host operating systems.
0174  *
0175  ******************************************************************************/
0176 
0177 ACPI_STATUS
0178 AcpiSetFirmwareWakingVector64 (
0179     UINT64                  PhysicalAddress)
0180 {
0181     ACPI_FUNCTION_TRACE (AcpiSetFirmwareWakingVector64);
0182 
0183 
0184     /* Determine if the 64-bit vector actually exists */
0185 
0186     if ((AcpiGbl_FACS->Length <= 32) || (AcpiGbl_FACS->Version < 1))
0187     {
0188         return_ACPI_STATUS (AE_NOT_EXIST);
0189     }
0190 
0191     /* Clear 32-bit vector, set the 64-bit X_ vector */
0192 
0193     AcpiGbl_FACS->FirmwareWakingVector = 0;
0194     AcpiGbl_FACS->XFirmwareWakingVector = PhysicalAddress;
0195     return_ACPI_STATUS (AE_OK);
0196 }
0197 
0198 ACPI_EXPORT_SYMBOL (AcpiSetFirmwareWakingVector64)
0199 #endif
0200 
0201 /*******************************************************************************
0202  *
0203  * FUNCTION:    AcpiEnterSleepStatePrep
0204  *
0205  * PARAMETERS:  SleepState          - Which sleep state to enter
0206  *
0207  * RETURN:      Status
0208  *
0209  * DESCRIPTION: Prepare to enter a system sleep state (see ACPI 2.0 spec p 231)
0210  *              This function must execute with interrupts enabled.
0211  *              We break sleeping into 2 stages so that OSPM can handle
0212  *              various OS-specific tasks between the two steps.
0213  *
0214  ******************************************************************************/
0215 
0216 ACPI_STATUS
0217 AcpiEnterSleepStatePrep (
0218     UINT8                   SleepState)
0219 {
0220     ACPI_STATUS             Status;
0221     ACPI_OBJECT_LIST        ArgList;
0222     ACPI_OBJECT             Arg;
0223 
0224 
0225     ACPI_FUNCTION_TRACE (AcpiEnterSleepStatePrep);
0226 
0227 
0228     /* _PSW methods could be run here to enable wake-on keyboard, LAN, etc. */
0229 
0230     Status = AcpiGetSleepTypeData (SleepState,
0231                     &AcpiGbl_SleepTypeA, &AcpiGbl_SleepTypeB);
0232     if (ACPI_FAILURE (Status))
0233     {
0234         return_ACPI_STATUS (Status);
0235     }
0236 
0237     /* Execute the _PTS method (Prepare To Sleep) */
0238 
0239     ArgList.Count = 1;
0240     ArgList.Pointer = &Arg;
0241     Arg.Type = ACPI_TYPE_INTEGER;
0242     Arg.Integer.Value = SleepState;
0243 
0244     Status = AcpiEvaluateObject (NULL, METHOD_NAME__PTS, &ArgList, NULL);
0245     if (ACPI_FAILURE (Status) && Status != AE_NOT_FOUND)
0246     {
0247         return_ACPI_STATUS (Status);
0248     }
0249 
0250     /* Setup the argument to the _SST method (System STatus) */
0251 
0252     switch (SleepState)
0253     {
0254     case ACPI_STATE_S0:
0255         Arg.Integer.Value = ACPI_SST_WORKING;
0256         break;
0257 
0258     case ACPI_STATE_S1:
0259     case ACPI_STATE_S2:
0260     case ACPI_STATE_S3:
0261         Arg.Integer.Value = ACPI_SST_SLEEPING;
0262         break;
0263 
0264     case ACPI_STATE_S4:
0265         Arg.Integer.Value = ACPI_SST_SLEEP_CONTEXT;
0266         break;
0267 
0268     default:
0269         Arg.Integer.Value = ACPI_SST_INDICATOR_OFF; /* Default is off */
0270         break;
0271     }
0272 
0273     /*
0274      * Set the system indicators to show the desired sleep state.
0275      * _SST is an optional method (return no error if not found)
0276      */
0277     Status = AcpiEvaluateObject (NULL, METHOD_NAME__SST, &ArgList, NULL);
0278     if (ACPI_FAILURE (Status) && Status != AE_NOT_FOUND)
0279     {
0280         ACPI_EXCEPTION ((AE_INFO, Status, "While executing method _SST"));
0281     }
0282 
0283     return_ACPI_STATUS (AE_OK);
0284 }
0285 
0286 ACPI_EXPORT_SYMBOL (AcpiEnterSleepStatePrep)
0287 
0288 
0289 /*******************************************************************************
0290  *
0291  * FUNCTION:    AcpiEnterSleepState
0292  *
0293  * PARAMETERS:  SleepState          - Which sleep state to enter
0294  *
0295  * RETURN:      Status
0296  *
0297  * DESCRIPTION: Enter a system sleep state
0298  *              THIS FUNCTION MUST BE CALLED WITH INTERRUPTS DISABLED
0299  *
0300  ******************************************************************************/
0301 
0302 ACPI_STATUS
0303 AcpiEnterSleepState (
0304     UINT8                   SleepState)
0305 {
0306     UINT32                  Pm1aControl;
0307     UINT32                  Pm1bControl;
0308     ACPI_BIT_REGISTER_INFO  *SleepTypeRegInfo;
0309     ACPI_BIT_REGISTER_INFO  *SleepEnableRegInfo;
0310     UINT32                  InValue;
0311     ACPI_OBJECT_LIST        ArgList;
0312     ACPI_OBJECT             Arg;
0313     ACPI_STATUS             Status;
0314 
0315 
0316     ACPI_FUNCTION_TRACE (AcpiEnterSleepState);
0317 
0318 
0319     if ((AcpiGbl_SleepTypeA > ACPI_SLEEP_TYPE_MAX) ||
0320         (AcpiGbl_SleepTypeB > ACPI_SLEEP_TYPE_MAX))
0321     {
0322         ACPI_ERROR ((AE_INFO, "Sleep values out of range: A=%X B=%X",
0323             AcpiGbl_SleepTypeA, AcpiGbl_SleepTypeB));
0324         return_ACPI_STATUS (AE_AML_OPERAND_VALUE);
0325     }
0326 
0327     SleepTypeRegInfo   = AcpiHwGetBitRegisterInfo (ACPI_BITREG_SLEEP_TYPE);
0328     SleepEnableRegInfo = AcpiHwGetBitRegisterInfo (ACPI_BITREG_SLEEP_ENABLE);
0329 
0330     /* Clear wake status */
0331 
0332     Status = AcpiWriteBitRegister (ACPI_BITREG_WAKE_STATUS, ACPI_CLEAR_STATUS);
0333     if (ACPI_FAILURE (Status))
0334     {
0335         return_ACPI_STATUS (Status);
0336     }
0337 
0338     /* Clear all fixed and general purpose status bits */
0339 
0340     Status = AcpiHwClearAcpiStatus ();
0341     if (ACPI_FAILURE (Status))
0342     {
0343         return_ACPI_STATUS (Status);
0344     }
0345 
0346     if (SleepState != ACPI_STATE_S5)
0347     {
0348         /* Disable BM arbitration */
0349 
0350         Status = AcpiWriteBitRegister (ACPI_BITREG_ARB_DISABLE, 1);
0351         if (ACPI_FAILURE (Status))
0352         {
0353             return_ACPI_STATUS (Status);
0354         }
0355     }
0356 
0357     /*
0358      * 1) Disable/Clear all GPEs
0359      * 2) Enable all wakeup GPEs
0360      */
0361     Status = AcpiHwDisableAllGpes ();
0362     if (ACPI_FAILURE (Status))
0363     {
0364         return_ACPI_STATUS (Status);
0365     }
0366     AcpiGbl_SystemAwakeAndRunning = FALSE;
0367 
0368     Status = AcpiHwEnableAllWakeupGpes ();
0369     if (ACPI_FAILURE (Status))
0370     {
0371         return_ACPI_STATUS (Status);
0372     }
0373 
0374     /* Execute the _GTS method (Going To Sleep) */
0375 
0376     ArgList.Count = 1;
0377     ArgList.Pointer = &Arg;
0378     Arg.Type = ACPI_TYPE_INTEGER;
0379     Arg.Integer.Value = SleepState;
0380 
0381     Status = AcpiEvaluateObject (NULL, METHOD_NAME__GTS, &ArgList, NULL);
0382     if (ACPI_FAILURE (Status) && Status != AE_NOT_FOUND)
0383     {
0384         return_ACPI_STATUS (Status);
0385     }
0386 
0387     /* Get current value of PM1A control */
0388 
0389     Status = AcpiHwRegisterRead (ACPI_REGISTER_PM1_CONTROL,
0390                 &Pm1aControl);
0391     if (ACPI_FAILURE (Status))
0392     {
0393         return_ACPI_STATUS (Status);
0394     }
0395     ACPI_DEBUG_PRINT ((ACPI_DB_INIT,
0396         "Entering sleep state [S%d]\n", SleepState));
0397 
0398     /* Clear the SLP_EN and SLP_TYP fields */
0399 
0400     Pm1aControl &= ~(SleepTypeRegInfo->AccessBitMask |
0401                      SleepEnableRegInfo->AccessBitMask);
0402     Pm1bControl = Pm1aControl;
0403 
0404     /* Insert the SLP_TYP bits */
0405 
0406     Pm1aControl |= (AcpiGbl_SleepTypeA << SleepTypeRegInfo->BitPosition);
0407     Pm1bControl |= (AcpiGbl_SleepTypeB << SleepTypeRegInfo->BitPosition);
0408 
0409     /*
0410      * We split the writes of SLP_TYP and SLP_EN to workaround
0411      * poorly implemented hardware.
0412      */
0413 
0414     /* Write #1: write the SLP_TYP data to the PM1 Control registers */
0415 
0416     Status = AcpiHwWritePm1Control (Pm1aControl, Pm1bControl);
0417     if (ACPI_FAILURE (Status))
0418     {
0419         return_ACPI_STATUS (Status);
0420     }
0421 
0422     /* Insert the sleep enable (SLP_EN) bit */
0423 
0424     Pm1aControl |= SleepEnableRegInfo->AccessBitMask;
0425     Pm1bControl |= SleepEnableRegInfo->AccessBitMask;
0426 
0427     /* Flush caches, as per ACPI specification */
0428 
0429     ACPI_FLUSH_CPU_CACHE ();
0430 
0431     /* Write #2: Write both SLP_TYP + SLP_EN */
0432 
0433     Status = AcpiHwWritePm1Control (Pm1aControl, Pm1bControl);
0434     if (ACPI_FAILURE (Status))
0435     {
0436         return_ACPI_STATUS (Status);
0437     }
0438 
0439     if (SleepState > ACPI_STATE_S3)
0440     {
0441         /*
0442          * We wanted to sleep > S3, but it didn't happen (by virtue of the
0443          * fact that we are still executing!)
0444          *
0445          * Wait ten seconds, then try again. This is to get S4/S5 to work on
0446          * all machines.
0447          *
0448          * We wait so long to allow chipsets that poll this reg very slowly
0449          * to still read the right value. Ideally, this block would go
0450          * away entirely.
0451          */
0452         AcpiOsStall (10000000);
0453 
0454         Status = AcpiHwRegisterWrite (ACPI_REGISTER_PM1_CONTROL,
0455                     SleepEnableRegInfo->AccessBitMask);
0456         if (ACPI_FAILURE (Status))
0457         {
0458             return_ACPI_STATUS (Status);
0459         }
0460     }
0461 
0462     /* Wait until we enter sleep state */
0463 
0464     do
0465     {
0466         Status = AcpiReadBitRegister (ACPI_BITREG_WAKE_STATUS, &InValue);
0467         if (ACPI_FAILURE (Status))
0468         {
0469             return_ACPI_STATUS (Status);
0470         }
0471 
0472         /* Spin until we wake */
0473 
0474     } while (!InValue);
0475 
0476     return_ACPI_STATUS (AE_OK);
0477 }
0478 
0479 ACPI_EXPORT_SYMBOL (AcpiEnterSleepState)
0480 
0481 
0482 /*******************************************************************************
0483  *
0484  * FUNCTION:    AcpiEnterSleepStateS4bios
0485  *
0486  * PARAMETERS:  None
0487  *
0488  * RETURN:      Status
0489  *
0490  * DESCRIPTION: Perform a S4 bios request.
0491  *              THIS FUNCTION MUST BE CALLED WITH INTERRUPTS DISABLED
0492  *
0493  ******************************************************************************/
0494 
0495 ACPI_STATUS
0496 AcpiEnterSleepStateS4bios (
0497     void)
0498 {
0499     UINT32                  InValue;
0500     ACPI_STATUS             Status;
0501 
0502 
0503     ACPI_FUNCTION_TRACE (AcpiEnterSleepStateS4bios);
0504 
0505 
0506     /* Clear the wake status bit (PM1) */
0507 
0508     Status = AcpiWriteBitRegister (ACPI_BITREG_WAKE_STATUS, ACPI_CLEAR_STATUS);
0509     if (ACPI_FAILURE (Status))
0510     {
0511         return_ACPI_STATUS (Status);
0512     }
0513 
0514     Status = AcpiHwClearAcpiStatus ();
0515     if (ACPI_FAILURE (Status))
0516     {
0517         return_ACPI_STATUS (Status);
0518     }
0519 
0520     /*
0521      * 1) Disable/Clear all GPEs
0522      * 2) Enable all wakeup GPEs
0523      */
0524     Status = AcpiHwDisableAllGpes ();
0525     if (ACPI_FAILURE (Status))
0526     {
0527         return_ACPI_STATUS (Status);
0528     }
0529     AcpiGbl_SystemAwakeAndRunning = FALSE;
0530 
0531     Status = AcpiHwEnableAllWakeupGpes ();
0532     if (ACPI_FAILURE (Status))
0533     {
0534         return_ACPI_STATUS (Status);
0535     }
0536 
0537     ACPI_FLUSH_CPU_CACHE ();
0538 
0539     Status = AcpiHwWritePort (AcpiGbl_FADT.SmiCommand,
0540                 (UINT32) AcpiGbl_FADT.S4BiosRequest, 8);
0541 
0542     do {
0543         AcpiOsStall(1000);
0544         Status = AcpiReadBitRegister (ACPI_BITREG_WAKE_STATUS, &InValue);
0545         if (ACPI_FAILURE (Status))
0546         {
0547             return_ACPI_STATUS (Status);
0548         }
0549     } while (!InValue);
0550 
0551     return_ACPI_STATUS (AE_OK);
0552 }
0553 
0554 ACPI_EXPORT_SYMBOL (AcpiEnterSleepStateS4bios)
0555 
0556 
0557 /*******************************************************************************
0558  *
0559  * FUNCTION:    AcpiLeaveSleepState
0560  *
0561  * PARAMETERS:  SleepState          - Which sleep state we just exited
0562  *
0563  * RETURN:      Status
0564  *
0565  * DESCRIPTION: Perform OS-independent ACPI cleanup after a sleep
0566  *              Called with interrupts ENABLED.
0567  *
0568  ******************************************************************************/
0569 
0570 ACPI_STATUS
0571 AcpiLeaveSleepState (
0572     UINT8                   SleepState)
0573 {
0574     ACPI_OBJECT_LIST        ArgList;
0575     ACPI_OBJECT             Arg;
0576     ACPI_STATUS             Status;
0577     ACPI_BIT_REGISTER_INFO  *SleepTypeRegInfo;
0578     ACPI_BIT_REGISTER_INFO  *SleepEnableRegInfo;
0579     UINT32                  Pm1aControl;
0580     UINT32                  Pm1bControl;
0581 
0582 
0583     ACPI_FUNCTION_TRACE (AcpiLeaveSleepState);
0584 
0585 
0586     /*
0587      * Set SLP_TYPE and SLP_EN to state S0.
0588      * This is unclear from the ACPI Spec, but it is required
0589      * by some machines.
0590      */
0591     Status = AcpiGetSleepTypeData (ACPI_STATE_S0,
0592                     &AcpiGbl_SleepTypeA, &AcpiGbl_SleepTypeB);
0593     if (ACPI_SUCCESS (Status))
0594     {
0595         SleepTypeRegInfo =
0596             AcpiHwGetBitRegisterInfo (ACPI_BITREG_SLEEP_TYPE);
0597         SleepEnableRegInfo =
0598             AcpiHwGetBitRegisterInfo (ACPI_BITREG_SLEEP_ENABLE);
0599 
0600         /* Get current value of PM1A control */
0601 
0602         Status = AcpiHwRegisterRead (ACPI_REGISTER_PM1_CONTROL,
0603                     &Pm1aControl);
0604         if (ACPI_SUCCESS (Status))
0605         {
0606             /* Clear the SLP_EN and SLP_TYP fields */
0607 
0608             Pm1aControl &= ~(SleepTypeRegInfo->AccessBitMask |
0609                 SleepEnableRegInfo->AccessBitMask);
0610             Pm1bControl = Pm1aControl;
0611 
0612             /* Insert the SLP_TYP bits */
0613 
0614             Pm1aControl |= (AcpiGbl_SleepTypeA <<
0615                 SleepTypeRegInfo->BitPosition);
0616             Pm1bControl |= (AcpiGbl_SleepTypeB <<
0617                 SleepTypeRegInfo->BitPosition);
0618 
0619             /* Write the control registers and ignore any errors */
0620 
0621             (void) AcpiHwWritePm1Control (Pm1aControl, Pm1bControl);
0622         }
0623     }
0624 
0625     /* Ensure EnterSleepStatePrep -> EnterSleepState ordering */
0626 
0627     AcpiGbl_SleepTypeA = ACPI_SLEEP_TYPE_INVALID;
0628 
0629     /* Setup parameter object */
0630 
0631     ArgList.Count = 1;
0632     ArgList.Pointer = &Arg;
0633     Arg.Type = ACPI_TYPE_INTEGER;
0634 
0635     /* Ignore any errors from these methods */
0636 
0637     Arg.Integer.Value = ACPI_SST_WAKING;
0638     Status = AcpiEvaluateObject (NULL, METHOD_NAME__SST, &ArgList, NULL);
0639     if (ACPI_FAILURE (Status) && Status != AE_NOT_FOUND)
0640     {
0641         ACPI_EXCEPTION ((AE_INFO, Status, "During Method _SST"));
0642     }
0643 
0644     Arg.Integer.Value = SleepState;
0645     Status = AcpiEvaluateObject (NULL, METHOD_NAME__BFS, &ArgList, NULL);
0646     if (ACPI_FAILURE (Status) && Status != AE_NOT_FOUND)
0647     {
0648         ACPI_EXCEPTION ((AE_INFO, Status, "During Method _BFS"));
0649     }
0650 
0651     Status = AcpiEvaluateObject (NULL, METHOD_NAME__WAK, &ArgList, NULL);
0652     if (ACPI_FAILURE (Status) && Status != AE_NOT_FOUND)
0653     {
0654         ACPI_EXCEPTION ((AE_INFO, Status, "During Method _WAK"));
0655     }
0656     /* TBD: _WAK "sometimes" returns stuff - do we want to look at it? */
0657 
0658     /*
0659      * Restore the GPEs:
0660      * 1) Disable/Clear all GPEs
0661      * 2) Enable all runtime GPEs
0662      */
0663     Status = AcpiHwDisableAllGpes ();
0664     if (ACPI_FAILURE (Status))
0665     {
0666         return_ACPI_STATUS (Status);
0667     }
0668     AcpiGbl_SystemAwakeAndRunning = TRUE;
0669 
0670     Status = AcpiHwEnableAllRuntimeGpes ();
0671     if (ACPI_FAILURE (Status))
0672     {
0673         return_ACPI_STATUS (Status);
0674     }
0675 
0676     /* Enable power button */
0677 
0678     (void) AcpiWriteBitRegister(
0679             AcpiGbl_FixedEventInfo[ACPI_EVENT_POWER_BUTTON].EnableRegisterId,
0680             ACPI_ENABLE_EVENT);
0681 
0682     (void) AcpiWriteBitRegister(
0683             AcpiGbl_FixedEventInfo[ACPI_EVENT_POWER_BUTTON].StatusRegisterId,
0684             ACPI_CLEAR_STATUS);
0685 
0686     /* Enable BM arbitration */
0687 
0688     Status = AcpiWriteBitRegister (ACPI_BITREG_ARB_DISABLE, 0);
0689     if (ACPI_FAILURE (Status))
0690     {
0691         return_ACPI_STATUS (Status);
0692     }
0693 
0694     Arg.Integer.Value = ACPI_SST_WORKING;
0695     Status = AcpiEvaluateObject (NULL, METHOD_NAME__SST, &ArgList, NULL);
0696     if (ACPI_FAILURE (Status) && Status != AE_NOT_FOUND)
0697     {
0698         ACPI_EXCEPTION ((AE_INFO, Status, "During Method _SST"));
0699     }
0700 
0701     return_ACPI_STATUS (Status);
0702 }
0703 
0704 ACPI_EXPORT_SYMBOL (AcpiLeaveSleepState)
0705