Back to home page

Quest Cross Reference

 
 

    


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

0001 
0002 /******************************************************************************
0003  *
0004  * Module Name: hwxface - Public ACPICA hardware interfaces
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 #include "acnamesp.h"
0120 
0121 #define _COMPONENT          ACPI_HARDWARE
0122         ACPI_MODULE_NAME    ("hwxface")
0123 
0124 
0125 /******************************************************************************
0126  *
0127  * FUNCTION:    AcpiReset
0128  *
0129  * PARAMETERS:  None
0130  *
0131  * RETURN:      Status
0132  *
0133  * DESCRIPTION: Set reset register in memory or IO space. Note: Does not
0134  *              support reset register in PCI config space, this must be
0135  *              handled separately.
0136  *
0137  ******************************************************************************/
0138 
0139 ACPI_STATUS
0140 AcpiReset (
0141     void)
0142 {
0143     ACPI_GENERIC_ADDRESS    *ResetReg;
0144     ACPI_STATUS             Status;
0145 
0146 
0147     ACPI_FUNCTION_TRACE (AcpiReset);
0148 
0149 
0150     ResetReg = &AcpiGbl_FADT.ResetRegister;
0151 
0152     /* Check if the reset register is supported */
0153 
0154     if (!(AcpiGbl_FADT.Flags & ACPI_FADT_RESET_REGISTER) ||
0155         !ResetReg->Address)
0156     {
0157         return_ACPI_STATUS (AE_NOT_EXIST);
0158     }
0159 
0160     /* Write the reset value to the reset register */
0161 
0162     Status = AcpiHwWrite (AcpiGbl_FADT.ResetValue, ResetReg);
0163     return_ACPI_STATUS (Status);
0164 }
0165 
0166 ACPI_EXPORT_SYMBOL (AcpiReset)
0167 
0168 
0169 /******************************************************************************
0170  *
0171  * FUNCTION:    AcpiRead
0172  *
0173  * PARAMETERS:  Value               - Where the value is returned
0174  *              Reg                 - GAS register structure
0175  *
0176  * RETURN:      Status
0177  *
0178  * DESCRIPTION: Read from either memory or IO space.
0179  *
0180  * LIMITATIONS: <These limitations also apply to AcpiWrite>
0181  *      BitWidth must be exactly 8, 16, 32, or 64.
0182  *      SpaceID must be SystemMemory or SystemIO.
0183  *      BitOffset and AccessWidth are currently ignored, as there has
0184  *          not been a need to implement these.
0185  *
0186  ******************************************************************************/
0187 
0188 ACPI_STATUS
0189 AcpiRead (
0190     UINT64                  *ReturnValue,
0191     ACPI_GENERIC_ADDRESS    *Reg)
0192 {
0193     UINT32                  Value;
0194     UINT32                  Width;
0195     UINT64                  Address;
0196     ACPI_STATUS             Status;
0197 
0198 
0199     ACPI_FUNCTION_NAME (AcpiRead);
0200 
0201 
0202     if (!ReturnValue)
0203     {
0204         return (AE_BAD_PARAMETER);
0205     }
0206 
0207     /* Validate contents of the GAS register. Allow 64-bit transfers */
0208 
0209     Status = AcpiHwValidateRegister (Reg, 64, &Address);
0210     if (ACPI_FAILURE (Status))
0211     {
0212         return (Status);
0213     }
0214 
0215     Width = Reg->BitWidth;
0216     if (Width == 64)
0217     {
0218         Width = 32; /* Break into two 32-bit transfers */
0219     }
0220 
0221     /* Initialize entire 64-bit return value to zero */
0222 
0223     *ReturnValue = 0;
0224     Value = 0;
0225 
0226     /*
0227      * Two address spaces supported: Memory or IO. PCI_Config is
0228      * not supported here because the GAS structure is insufficient
0229      */
0230     if (Reg->SpaceId == ACPI_ADR_SPACE_SYSTEM_MEMORY)
0231     {
0232         Status = AcpiOsReadMemory ((ACPI_PHYSICAL_ADDRESS)
0233                     Address, &Value, Width);
0234         if (ACPI_FAILURE (Status))
0235         {
0236             return (Status);
0237         }
0238         *ReturnValue = Value;
0239 
0240         if (Reg->BitWidth == 64)
0241         {
0242             /* Read the top 32 bits */
0243 
0244             Status = AcpiOsReadMemory ((ACPI_PHYSICAL_ADDRESS)
0245                         (Address + 4), &Value, 32);
0246             if (ACPI_FAILURE (Status))
0247             {
0248                 return (Status);
0249             }
0250             *ReturnValue |= ((UINT64) Value << 32);
0251         }
0252     }
0253     else /* ACPI_ADR_SPACE_SYSTEM_IO, validated earlier */
0254     {
0255         Status = AcpiHwReadPort ((ACPI_IO_ADDRESS)
0256                     Address, &Value, Width);
0257         if (ACPI_FAILURE (Status))
0258         {
0259             return (Status);
0260         }
0261         *ReturnValue = Value;
0262 
0263         if (Reg->BitWidth == 64)
0264         {
0265             /* Read the top 32 bits */
0266 
0267             Status = AcpiHwReadPort ((ACPI_IO_ADDRESS)
0268                         (Address + 4), &Value, 32);
0269             if (ACPI_FAILURE (Status))
0270             {
0271                 return (Status);
0272             }
0273             *ReturnValue |= ((UINT64) Value << 32);
0274         }
0275     }
0276 
0277     ACPI_DEBUG_PRINT ((ACPI_DB_IO,
0278         "Read:  %8.8X%8.8X width %2d from %8.8X%8.8X (%s)\n",
0279         ACPI_FORMAT_UINT64 (*ReturnValue), Reg->BitWidth,
0280         ACPI_FORMAT_UINT64 (Address),
0281         AcpiUtGetRegionName (Reg->SpaceId)));
0282 
0283     return (Status);
0284 }
0285 
0286 ACPI_EXPORT_SYMBOL (AcpiRead)
0287 
0288 
0289 /******************************************************************************
0290  *
0291  * FUNCTION:    AcpiWrite
0292  *
0293  * PARAMETERS:  Value               - Value to be written
0294  *              Reg                 - GAS register structure
0295  *
0296  * RETURN:      Status
0297  *
0298  * DESCRIPTION: Write to either memory or IO space.
0299  *
0300  ******************************************************************************/
0301 
0302 ACPI_STATUS
0303 AcpiWrite (
0304     UINT64                  Value,
0305     ACPI_GENERIC_ADDRESS    *Reg)
0306 {
0307     UINT32                  Width;
0308     UINT64                  Address;
0309     ACPI_STATUS             Status;
0310 
0311 
0312     ACPI_FUNCTION_NAME (AcpiWrite);
0313 
0314 
0315     /* Validate contents of the GAS register. Allow 64-bit transfers */
0316 
0317     Status = AcpiHwValidateRegister (Reg, 64, &Address);
0318     if (ACPI_FAILURE (Status))
0319     {
0320         return (Status);
0321     }
0322 
0323     Width = Reg->BitWidth;
0324     if (Width == 64)
0325     {
0326         Width = 32; /* Break into two 32-bit transfers */
0327     }
0328 
0329     /*
0330      * Two address spaces supported: Memory or IO. PCI_Config is
0331      * not supported here because the GAS structure is insufficient
0332      */
0333     if (Reg->SpaceId == ACPI_ADR_SPACE_SYSTEM_MEMORY)
0334     {
0335         Status = AcpiOsWriteMemory ((ACPI_PHYSICAL_ADDRESS)
0336                     Address, ACPI_LODWORD (Value), Width);
0337         if (ACPI_FAILURE (Status))
0338         {
0339             return (Status);
0340         }
0341 
0342         if (Reg->BitWidth == 64)
0343         {
0344             Status = AcpiOsWriteMemory ((ACPI_PHYSICAL_ADDRESS)
0345                         (Address + 4), ACPI_HIDWORD (Value), 32);
0346             if (ACPI_FAILURE (Status))
0347             {
0348                 return (Status);
0349             }
0350         }
0351     }
0352     else /* ACPI_ADR_SPACE_SYSTEM_IO, validated earlier */
0353     {
0354         Status = AcpiHwWritePort ((ACPI_IO_ADDRESS)
0355                     Address, ACPI_LODWORD (Value), Width);
0356         if (ACPI_FAILURE (Status))
0357         {
0358             return (Status);
0359         }
0360 
0361         if (Reg->BitWidth == 64)
0362         {
0363             Status = AcpiHwWritePort ((ACPI_IO_ADDRESS)
0364                         (Address + 4), ACPI_HIDWORD (Value), 32);
0365             if (ACPI_FAILURE (Status))
0366             {
0367                 return (Status);
0368             }
0369         }
0370     }
0371 
0372     ACPI_DEBUG_PRINT ((ACPI_DB_IO,
0373         "Wrote: %8.8X%8.8X width %2d   to %8.8X%8.8X (%s)\n",
0374         ACPI_FORMAT_UINT64 (Value), Reg->BitWidth,
0375         ACPI_FORMAT_UINT64 (Address),
0376         AcpiUtGetRegionName (Reg->SpaceId)));
0377 
0378     return (Status);
0379 }
0380 
0381 ACPI_EXPORT_SYMBOL (AcpiWrite)
0382 
0383 
0384 /*******************************************************************************
0385  *
0386  * FUNCTION:    AcpiReadBitRegister
0387  *
0388  * PARAMETERS:  RegisterId      - ID of ACPI Bit Register to access
0389  *              ReturnValue     - Value that was read from the register,
0390  *                                normalized to bit position zero.
0391  *
0392  * RETURN:      Status and the value read from the specified Register. Value
0393  *              returned is normalized to bit0 (is shifted all the way right)
0394  *
0395  * DESCRIPTION: ACPI BitRegister read function. Does not acquire the HW lock.
0396  *
0397  * SUPPORTS:    Bit fields in PM1 Status, PM1 Enable, PM1 Control, and
0398  *              PM2 Control.
0399  *
0400  * Note: The hardware lock is not required when reading the ACPI bit registers
0401  *       since almost all of them are single bit and it does not matter that
0402  *       the parent hardware register can be split across two physical
0403  *       registers. The only multi-bit field is SLP_TYP in the PM1 control
0404  *       register, but this field does not cross an 8-bit boundary (nor does
0405  *       it make much sense to actually read this field.)
0406  *
0407  ******************************************************************************/
0408 
0409 ACPI_STATUS
0410 AcpiReadBitRegister (
0411     UINT32                  RegisterId,
0412     UINT32                  *ReturnValue)
0413 {
0414     ACPI_BIT_REGISTER_INFO  *BitRegInfo;
0415     UINT32                  RegisterValue;
0416     UINT32                  Value;
0417     ACPI_STATUS             Status;
0418 
0419 
0420     ACPI_FUNCTION_TRACE_U32 (AcpiReadBitRegister, RegisterId);
0421 
0422 
0423     /* Get the info structure corresponding to the requested ACPI Register */
0424 
0425     BitRegInfo = AcpiHwGetBitRegisterInfo (RegisterId);
0426     if (!BitRegInfo)
0427     {
0428         return_ACPI_STATUS (AE_BAD_PARAMETER);
0429     }
0430 
0431     /* Read the entire parent register */
0432 
0433     Status = AcpiHwRegisterRead (BitRegInfo->ParentRegister,
0434                 &RegisterValue);
0435     if (ACPI_FAILURE (Status))
0436     {
0437         return_ACPI_STATUS (Status);
0438     }
0439 
0440     /* Normalize the value that was read, mask off other bits */
0441 
0442     Value = ((RegisterValue & BitRegInfo->AccessBitMask)
0443                 >> BitRegInfo->BitPosition);
0444 
0445     ACPI_DEBUG_PRINT ((ACPI_DB_IO,
0446         "BitReg %X, ParentReg %X, Actual %8.8X, ReturnValue %8.8X\n",
0447         RegisterId, BitRegInfo->ParentRegister, RegisterValue, Value));
0448 
0449     *ReturnValue = Value;
0450     return_ACPI_STATUS (AE_OK);
0451 }
0452 
0453 ACPI_EXPORT_SYMBOL (AcpiReadBitRegister)
0454 
0455 
0456 /*******************************************************************************
0457  *
0458  * FUNCTION:    AcpiWriteBitRegister
0459  *
0460  * PARAMETERS:  RegisterId      - ID of ACPI Bit Register to access
0461  *              Value           - Value to write to the register, in bit
0462  *                                position zero. The bit is automaticallly
0463  *                                shifted to the correct position.
0464  *
0465  * RETURN:      Status
0466  *
0467  * DESCRIPTION: ACPI Bit Register write function. Acquires the hardware lock
0468  *              since most operations require a read/modify/write sequence.
0469  *
0470  * SUPPORTS:    Bit fields in PM1 Status, PM1 Enable, PM1 Control, and
0471  *              PM2 Control.
0472  *
0473  * Note that at this level, the fact that there may be actually two
0474  * hardware registers (A and B - and B may not exist) is abstracted.
0475  *
0476  ******************************************************************************/
0477 
0478 ACPI_STATUS
0479 AcpiWriteBitRegister (
0480     UINT32                  RegisterId,
0481     UINT32                  Value)
0482 {
0483     ACPI_BIT_REGISTER_INFO  *BitRegInfo;
0484     ACPI_CPU_FLAGS          LockFlags;
0485     UINT32                  RegisterValue;
0486     ACPI_STATUS             Status = AE_OK;
0487 
0488 
0489     ACPI_FUNCTION_TRACE_U32 (AcpiWriteBitRegister, RegisterId);
0490 
0491 
0492     /* Get the info structure corresponding to the requested ACPI Register */
0493 
0494     BitRegInfo = AcpiHwGetBitRegisterInfo (RegisterId);
0495     if (!BitRegInfo)
0496     {
0497         return_ACPI_STATUS (AE_BAD_PARAMETER);
0498     }
0499 
0500     LockFlags = AcpiOsAcquireLock (AcpiGbl_HardwareLock);
0501 
0502     /*
0503      * At this point, we know that the parent register is one of the
0504      * following: PM1 Status, PM1 Enable, PM1 Control, or PM2 Control
0505      */
0506     if (BitRegInfo->ParentRegister != ACPI_REGISTER_PM1_STATUS)
0507     {
0508         /*
0509          * 1) Case for PM1 Enable, PM1 Control, and PM2 Control
0510          *
0511          * Perform a register read to preserve the bits that we are not
0512          * interested in
0513          */
0514         Status = AcpiHwRegisterRead (BitRegInfo->ParentRegister,
0515                     &RegisterValue);
0516         if (ACPI_FAILURE (Status))
0517         {
0518             goto UnlockAndExit;
0519         }
0520 
0521         /*
0522          * Insert the input bit into the value that was just read
0523          * and write the register
0524          */
0525         ACPI_REGISTER_INSERT_VALUE (RegisterValue, BitRegInfo->BitPosition,
0526             BitRegInfo->AccessBitMask, Value);
0527 
0528         Status = AcpiHwRegisterWrite (BitRegInfo->ParentRegister,
0529                     RegisterValue);
0530     }
0531     else
0532     {
0533         /*
0534          * 2) Case for PM1 Status
0535          *
0536          * The Status register is different from the rest. Clear an event
0537          * by writing 1, writing 0 has no effect. So, the only relevant
0538          * information is the single bit we're interested in, all others
0539          * should be written as 0 so they will be left unchanged.
0540          */
0541         RegisterValue = ACPI_REGISTER_PREPARE_BITS (Value,
0542             BitRegInfo->BitPosition, BitRegInfo->AccessBitMask);
0543 
0544         /* No need to write the register if value is all zeros */
0545 
0546         if (RegisterValue)
0547         {
0548             Status = AcpiHwRegisterWrite (ACPI_REGISTER_PM1_STATUS,
0549                         RegisterValue);
0550         }
0551     }
0552 
0553     ACPI_DEBUG_PRINT ((ACPI_DB_IO,
0554         "BitReg %X, ParentReg %X, Value %8.8X, Actual %8.8X\n",
0555         RegisterId, BitRegInfo->ParentRegister, Value, RegisterValue));
0556 
0557 
0558 UnlockAndExit:
0559 
0560     AcpiOsReleaseLock (AcpiGbl_HardwareLock, LockFlags);
0561     return_ACPI_STATUS (Status);
0562 }
0563 
0564 ACPI_EXPORT_SYMBOL (AcpiWriteBitRegister)
0565 
0566 
0567 /*******************************************************************************
0568  *
0569  * FUNCTION:    AcpiGetSleepTypeData
0570  *
0571  * PARAMETERS:  SleepState          - Numeric sleep state
0572  *              *SleepTypeA         - Where SLP_TYPa is returned
0573  *              *SleepTypeB         - Where SLP_TYPb is returned
0574  *
0575  * RETURN:      Status - ACPI status
0576  *
0577  * DESCRIPTION: Obtain the SLP_TYPa and SLP_TYPb values for the requested sleep
0578  *              state.
0579  *
0580  ******************************************************************************/
0581 
0582 ACPI_STATUS
0583 AcpiGetSleepTypeData (
0584     UINT8                   SleepState,
0585     UINT8                   *SleepTypeA,
0586     UINT8                   *SleepTypeB)
0587 {
0588     ACPI_STATUS             Status = AE_OK;
0589     ACPI_EVALUATE_INFO      *Info;
0590 
0591 
0592     ACPI_FUNCTION_TRACE (AcpiGetSleepTypeData);
0593 
0594 
0595     /* Validate parameters */
0596 
0597     if ((SleepState > ACPI_S_STATES_MAX) ||
0598         !SleepTypeA ||
0599         !SleepTypeB)
0600     {
0601         return_ACPI_STATUS (AE_BAD_PARAMETER);
0602     }
0603 
0604     /* Allocate the evaluation information block */
0605 
0606     Info = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_EVALUATE_INFO));
0607     if (!Info)
0608     {
0609         return_ACPI_STATUS (AE_NO_MEMORY);
0610     }
0611 
0612     Info->Pathname = ACPI_CAST_PTR (char, AcpiGbl_SleepStateNames[SleepState]);
0613 
0614     /* Evaluate the namespace object containing the values for this state */
0615 
0616     Status = AcpiNsEvaluate (Info);
0617     if (ACPI_FAILURE (Status))
0618     {
0619         ACPI_DEBUG_PRINT ((ACPI_DB_EXEC,
0620             "%s while evaluating SleepState [%s]\n",
0621             AcpiFormatException (Status), Info->Pathname));
0622 
0623         goto Cleanup;
0624     }
0625 
0626     /* Must have a return object */
0627 
0628     if (!Info->ReturnObject)
0629     {
0630         ACPI_ERROR ((AE_INFO, "No Sleep State object returned from [%s]",
0631             Info->Pathname));
0632         Status = AE_NOT_EXIST;
0633     }
0634 
0635     /* It must be of type Package */
0636 
0637     else if (Info->ReturnObject->Common.Type != ACPI_TYPE_PACKAGE)
0638     {
0639         ACPI_ERROR ((AE_INFO, "Sleep State return object is not a Package"));
0640         Status = AE_AML_OPERAND_TYPE;
0641     }
0642 
0643     /*
0644      * The package must have at least two elements. NOTE (March 2005): This
0645      * goes against the current ACPI spec which defines this object as a
0646      * package with one encoded DWORD element. However, existing practice
0647      * by BIOS vendors seems to be to have 2 or more elements, at least
0648      * one per sleep type (A/B).
0649      */
0650     else if (Info->ReturnObject->Package.Count < 2)
0651     {
0652         ACPI_ERROR ((AE_INFO,
0653             "Sleep State return package does not have at least two elements"));
0654         Status = AE_AML_NO_OPERAND;
0655     }
0656 
0657     /* The first two elements must both be of type Integer */
0658 
0659     else if (((Info->ReturnObject->Package.Elements[0])->Common.Type
0660                 != ACPI_TYPE_INTEGER) ||
0661              ((Info->ReturnObject->Package.Elements[1])->Common.Type
0662                 != ACPI_TYPE_INTEGER))
0663     {
0664         ACPI_ERROR ((AE_INFO,
0665             "Sleep State return package elements are not both Integers "
0666             "(%s, %s)",
0667             AcpiUtGetObjectTypeName (Info->ReturnObject->Package.Elements[0]),
0668             AcpiUtGetObjectTypeName (Info->ReturnObject->Package.Elements[1])));
0669         Status = AE_AML_OPERAND_TYPE;
0670     }
0671     else
0672     {
0673         /* Valid _Sx_ package size, type, and value */
0674 
0675         *SleepTypeA = (UINT8)
0676             (Info->ReturnObject->Package.Elements[0])->Integer.Value;
0677         *SleepTypeB = (UINT8)
0678             (Info->ReturnObject->Package.Elements[1])->Integer.Value;
0679     }
0680 
0681     if (ACPI_FAILURE (Status))
0682     {
0683         ACPI_EXCEPTION ((AE_INFO, Status,
0684             "While evaluating SleepState [%s], bad Sleep object %p type %s",
0685             Info->Pathname, Info->ReturnObject,
0686             AcpiUtGetObjectTypeName (Info->ReturnObject)));
0687     }
0688 
0689     AcpiUtRemoveReference (Info->ReturnObject);
0690 
0691 Cleanup:
0692     ACPI_FREE (Info);
0693     return_ACPI_STATUS (Status);
0694 }
0695 
0696 ACPI_EXPORT_SYMBOL (AcpiGetSleepTypeData)