hwxface.c revision 193335
143410Snewton
243410Snewton/******************************************************************************
343410Snewton *
443410Snewton * Module Name: hwxface - Public ACPICA hardware interfaces
543410Snewton *
643410Snewton *****************************************************************************/
743410Snewton
843410Snewton/******************************************************************************
943410Snewton *
1043410Snewton * 1. Copyright Notice
1143410Snewton *
1243410Snewton * Some or all of this work - Copyright (c) 1999 - 2009, Intel Corp.
1343410Snewton * All rights reserved.
1443410Snewton *
1543410Snewton * 2. License
1643410Snewton *
1743410Snewton * 2.1. This is your license from Intel Corp. under its intellectual property
1843410Snewton * rights.  You may have additional license terms from the party that provided
1943410Snewton * you this software, covering your right to use that party's intellectual
2043410Snewton * property rights.
2143410Snewton *
2243410Snewton * 2.2. Intel grants, free of charge, to any person ("Licensee") obtaining a
2343410Snewton * copy of the source code appearing in this file ("Covered Code") an
2443410Snewton * irrevocable, perpetual, worldwide license under Intel's copyrights in the
2543410Snewton * base code distributed originally by Intel ("Original Intel Code") to copy,
2643410Snewton * make derivatives, distribute, use and display any portion of the Covered
2743410Snewton * Code in any form, with the right to sublicense such rights; and
2843410Snewton *
2943410Snewton * 2.3. Intel grants Licensee a non-exclusive and non-transferable patent
3043410Snewton * license (with the right to sublicense), under only those claims of Intel
3143410Snewton * patents that are infringed by the Original Intel Code, to make, use, sell,
3249263Snewton * offer to sell, and import the Covered Code and derivative works thereof
3350477Speter * solely to the minimum extent necessary to exercise the above copyright
3443410Snewton * license, and in no event shall the patent license extend to any additions
3543410Snewton * to or modifications of the Original Intel Code.  No other license or right
3643410Snewton * is granted directly or by implication, estoppel or otherwise;
3743410Snewton *
3843410Snewton * The above copyright and patent license is granted only if the following
3943410Snewton * conditions are met:
4043410Snewton *
4143410Snewton * 3. Conditions
4243410Snewton *
4343410Snewton * 3.1. Redistribution of Source with Rights to Further Distribute Source.
4443410Snewton * Redistribution of source code of any substantial portion of the Covered
4543410Snewton * Code or modification with rights to further distribute source must include
4643410Snewton * the above Copyright Notice, the above License, this list of Conditions,
4743410Snewton * and the following Disclaimer and Export Compliance provision.  In addition,
4843410Snewton * Licensee must cause all Covered Code to which Licensee contributes to
4943410Snewton * contain a file documenting the changes Licensee made to create that Covered
5043410Snewton * Code and the date of any change.  Licensee must include in that file the
5143410Snewton * documentation of any changes made by any predecessor Licensee.  Licensee
5243410Snewton * must include a prominent statement that the modification is derived,
5343410Snewton * directly or indirectly, from Original Intel Code.
5443410Snewton *
5543410Snewton * 3.2. Redistribution of Source with no Rights to Further Distribute Source.
5643410Snewton * Redistribution of source code of any substantial portion of the Covered
5765314Sobrien * Code or modification without rights to further distribute source must
5865314Sobrien * include the following Disclaimer and Export Compliance provision in the
5965314Sobrien * documentation and/or other materials provided with distribution.  In
6065314Sobrien * addition, Licensee may not authorize further sublicense of source of any
6165314Sobrien * portion of the Covered Code, and must include terms to the effect that the
6265314Sobrien * license from Licensee to its licensee is limited to the intellectual
6343410Snewton * property embodied in the software Licensee provides to its licensee, and
6492739Salfred * not to intellectual property embodied in modifications its licensee may
6592739Salfred * make.
6643410Snewton *
6743410Snewton * 3.3. Redistribution of Executable. Redistribution in executable form of any
68115550Sphk * substantial portion of the Covered Code or modification must reproduce the
6943410Snewton * above Copyright Notice, and the following Disclaimer and Export Compliance
7043410Snewton * provision in the documentation and/or other materials provided with the
7143410Snewton * distribution.
7243410Snewton *
7343410Snewton * 3.4. Intel retains all right, title, and interest in and to the Original
7443410Snewton * Intel Code.
7543410Snewton *
7643410Snewton * 3.5. Neither the name Intel nor any other trademark owned or controlled by
7743410Snewton * Intel shall be used in advertising or otherwise to promote the sale, use or
7843410Snewton * other dealings in products derived from or relating to the Covered Code
7943410Snewton * without prior written authorization from Intel.
8043410Snewton *
8143410Snewton * 4. Disclaimer and Export Compliance
8243410Snewton *
8343410Snewton * 4.1. INTEL MAKES NO WARRANTY OF ANY KIND REGARDING ANY SOFTWARE PROVIDED
8443410Snewton * HERE.  ANY SOFTWARE ORIGINATING FROM INTEL OR DERIVED FROM INTEL SOFTWARE
8543410Snewton * IS PROVIDED "AS IS," AND INTEL WILL NOT PROVIDE ANY SUPPORT,  ASSISTANCE,
8643410Snewton * INSTALLATION, TRAINING OR OTHER SERVICES.  INTEL WILL NOT PROVIDE ANY
8743410Snewton * UPDATES, ENHANCEMENTS OR EXTENSIONS.  INTEL SPECIFICALLY DISCLAIMS ANY
8843410Snewton * IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT AND FITNESS FOR A
8989059Smsmith * PARTICULAR PURPOSE.
9052114Snewton *
9152114Snewton * 4.2. IN NO EVENT SHALL INTEL HAVE ANY LIABILITY TO LICENSEE, ITS LICENSEES
9243410Snewton * OR ANY OTHER THIRD PARTY, FOR ANY LOST PROFITS, LOST DATA, LOSS OF USE OR
93108235Sphk * COSTS OF PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, OR FOR ANY INDIRECT,
9472521Sjlemon * SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THIS AGREEMENT, UNDER ANY
9543410Snewton * CAUSE OF ACTION OR THEORY OF LIABILITY, AND IRRESPECTIVE OF WHETHER INTEL
9643410Snewton * HAS ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES.  THESE LIMITATIONS
9743410Snewton * SHALL APPLY NOTWITHSTANDING THE FAILURE OF THE ESSENTIAL PURPOSE OF ANY
9843410Snewton * LIMITED REMEDY.
99111815Sphk *
100111815Sphk * 4.3. Licensee shall not export, either directly or indirectly, any of this
101111815Sphk * software or system incorporating such software without first obtaining any
10247625Sphk * required license or other approval from the U. S. Department of Commerce or
10343410Snewton * any other agency or department of the United States Government.  In the
10443410Snewton * event Licensee exports any such software from the United States or
10543410Snewton * re-exports any such software from a foreign destination, Licensee shall
10643410Snewton * ensure that the distribution and export/re-export of the software is in
10743410Snewton * compliance with all laws, regulations, orders, or other restrictions of the
10843410Snewton * U.S. Export Administration Regulations. Licensee agrees that neither it nor
10943410Snewton * any of its subsidiaries will export/re-export any technical data, process,
11043410Snewton * software, or service, directly or indirectly, to any country for which the
11143410Snewton * United States government or any agency thereof requires an export license,
11244208Snewton * other governmental approval, or letter of assurance, without first obtaining
11344208Snewton * such license, approval or letter.
11444208Snewton *
11544208Snewton *****************************************************************************/
11644208Snewton
11749344Snewton#include "acpi.h"
11852114Snewton#include "accommon.h"
11952114Snewton#include "acnamesp.h"
12052114Snewton
12152114Snewton#define _COMPONENT          ACPI_HARDWARE
12252114Snewton        ACPI_MODULE_NAME    ("hwxface")
12352114Snewton
12452114Snewton
12552114Snewton/******************************************************************************
12652114Snewton *
12752114Snewton * FUNCTION:    AcpiReset
12852114Snewton *
12952114Snewton * PARAMETERS:  None
13052114Snewton *
13152114Snewton * RETURN:      Status
13252114Snewton *
13352114Snewton * DESCRIPTION: Set reset register in memory or IO space. Note: Does not
13452114Snewton *              support reset register in PCI config space, this must be
13552114Snewton *              handled separately.
13652114Snewton *
13752114Snewton ******************************************************************************/
13852114Snewton
13952114SnewtonACPI_STATUS
14052114SnewtonAcpiReset (
14152114Snewton    void)
14252114Snewton{
14352114Snewton    ACPI_GENERIC_ADDRESS    *ResetReg;
14452114Snewton    ACPI_STATUS             Status;
14544208Snewton
14644208Snewton
14749344Snewton    ACPI_FUNCTION_TRACE (AcpiReset);
14853000Sphk
14953000Sphk
15053000Sphk    ResetReg = &AcpiGbl_FADT.ResetRegister;
15153000Sphk
15253000Sphk    /* Check if the reset register is supported */
15353000Sphk
15453000Sphk    if (!(AcpiGbl_FADT.Flags & ACPI_FADT_RESET_REGISTER) ||
15553000Sphk        !ResetReg->Address)
15653000Sphk    {
15753000Sphk        return_ACPI_STATUS (AE_NOT_EXIST);
15852114Snewton    }
15944208Snewton
16044208Snewton    /* Write the reset value to the reset register */
16144208Snewton
16244208Snewton    Status = AcpiWrite (AcpiGbl_FADT.ResetValue, ResetReg);
16344208Snewton    return_ACPI_STATUS (Status);
16444208Snewton}
16544208Snewton
16644208SnewtonACPI_EXPORT_SYMBOL (AcpiReset)
16744208Snewton
16844208Snewton
16944208Snewton/******************************************************************************
17044208Snewton *
17144208Snewton * FUNCTION:    AcpiRead
17260060Sgreen *
17344208Snewton * PARAMETERS:  Value               - Where the value is returned
17443410Snewton *              Reg                 - GAS register structure
17543410Snewton *
17643410Snewton * RETURN:      Status
17743410Snewton *
17843410Snewton * DESCRIPTION: Read from either memory or IO space.
17943410Snewton *
18043410Snewton ******************************************************************************/
18143410Snewton
18283366SjulianACPI_STATUS
18343410SnewtonAcpiRead (
18443410Snewton    UINT32                  *Value,
18543410Snewton    ACPI_GENERIC_ADDRESS    *Reg)
18643410Snewton{
18743410Snewton    UINT32                  Width;
18843410Snewton    UINT64                  Address;
18943410Snewton    ACPI_STATUS             Status;
19083366Sjulian
19143410Snewton
19271448Sjhb    ACPI_FUNCTION_NAME (AcpiRead);
19383366Sjulian
19471448Sjhb
19543410Snewton    /*
19671448Sjhb     * Must have a valid pointer to a GAS structure, and a non-zero address
19771448Sjhb     * within.
19843410Snewton     */
19943410Snewton    if (!Reg)
20043410Snewton    {
20143410Snewton        return (AE_BAD_PARAMETER);
20243410Snewton    }
20343410Snewton
20443410Snewton    /* Get a local copy of the address. Handles possible alignment issues */
20543410Snewton
20643410Snewton    ACPI_MOVE_64_TO_64 (&Address, &Reg->Address);
20743410Snewton    if (!Address)
20843410Snewton    {
20943410Snewton        return (AE_BAD_ADDRESS);
21043410Snewton    }
21143410Snewton
21243410Snewton    /* Supported widths are 8/16/32 */
21343410Snewton
21443410Snewton    Width = Reg->BitWidth;
21543410Snewton    if ((Width != 8) && (Width != 16) && (Width != 32))
21643410Snewton    {
21743410Snewton        return (AE_SUPPORT);
21843410Snewton    }
21943410Snewton
22043410Snewton    /* Initialize entire 32-bit return value to zero */
22143410Snewton
22243410Snewton    *Value = 0;
22343410Snewton
22443410Snewton    /*
22543410Snewton     * Two address spaces supported: Memory or IO. PCI_Config is
22643410Snewton     * not supported here because the GAS structure is insufficient
22743410Snewton     */
22843410Snewton    switch (Reg->SpaceId)
22943410Snewton    {
23043410Snewton    case ACPI_ADR_SPACE_SYSTEM_MEMORY:
23143410Snewton
23243410Snewton        Status = AcpiOsReadMemory (
23343410Snewton                    (ACPI_PHYSICAL_ADDRESS) Address, Value, Width);
23443410Snewton        break;
23543410Snewton
23643410Snewton
23743410Snewton    case ACPI_ADR_SPACE_SYSTEM_IO:
23843410Snewton
23983366Sjulian        Status = AcpiHwReadPort ((ACPI_IO_ADDRESS) Address, Value, Width);
24043410Snewton        break;
24143410Snewton
24243410Snewton
24343410Snewton    default:
24443410Snewton        ACPI_ERROR ((AE_INFO,
24583366Sjulian            "Unsupported address space: %X", Reg->SpaceId));
24643410Snewton        return (AE_BAD_PARAMETER);
24743410Snewton    }
24888739Srwatson
24991406Sjhb    ACPI_DEBUG_PRINT ((ACPI_DB_IO,
25089306Salfred        "Read:  %8.8X width %2d from %8.8X%8.8X (%s)\n",
25143410Snewton        *Value, Width, ACPI_FORMAT_UINT64 (Address),
25289306Salfred        AcpiUtGetRegionName (Reg->SpaceId)));
25343410Snewton
25443410Snewton    return (Status);
25543410Snewton}
25643410Snewton
25789306SalfredACPI_EXPORT_SYMBOL (AcpiRead)
258109153Sdillon
25943410Snewton
26049413Sgreen/******************************************************************************
26143410Snewton *
26289306Salfred * FUNCTION:    AcpiWrite
26343410Snewton *
26443410Snewton * PARAMETERS:  Value               - To be written
26571448Sjhb *              Reg                 - GAS register structure
26683366Sjulian *
26771448Sjhb * RETURN:      Status
26843410Snewton *
26943410Snewton * DESCRIPTION: Write to either memory or IO space.
27043410Snewton *
27143410Snewton ******************************************************************************/
27283366Sjulian
27383366SjulianACPI_STATUS
27443410SnewtonAcpiWrite (
27583366Sjulian    UINT32                  Value,
27643410Snewton    ACPI_GENERIC_ADDRESS    *Reg)
27743410Snewton{
27843410Snewton    UINT32                  Width;
27943410Snewton    UINT64                  Address;
28043410Snewton    ACPI_STATUS             Status;
28143410Snewton
28243410Snewton
28343410Snewton    ACPI_FUNCTION_NAME (AcpiWrite);
28443410Snewton
28543410Snewton
28643410Snewton    /*
28743410Snewton     * Must have a valid pointer to a GAS structure, and a non-zero address
28843410Snewton     * within.
28943410Snewton     */
29043410Snewton    if (!Reg)
29143410Snewton    {
29243410Snewton        return (AE_BAD_PARAMETER);
29343410Snewton    }
29443410Snewton
29543410Snewton    /* Get a local copy of the address. Handles possible alignment issues */
29643410Snewton
29743410Snewton    ACPI_MOVE_64_TO_64 (&Address, &Reg->Address);
29843410Snewton    if (!Address)
299107849Salfred    {
300107849Salfred        return (AE_BAD_ADDRESS);
301107849Salfred    }
30243410Snewton
30343410Snewton    /* Supported widths are 8/16/32 */
30443410Snewton
30543410Snewton    Width = Reg->BitWidth;
30643410Snewton    if ((Width != 8) && (Width != 16) && (Width != 32))
30743410Snewton    {
30843410Snewton        return (AE_SUPPORT);
30943410Snewton    }
31083366Sjulian
31143410Snewton    /*
31243410Snewton     * Two address spaces supported: Memory or IO.
31343410Snewton     * PCI_Config is not supported here because the GAS struct is insufficient
31443410Snewton     */
31571448Sjhb    switch (Reg->SpaceId)
31683366Sjulian    {
31771448Sjhb    case ACPI_ADR_SPACE_SYSTEM_MEMORY:
31843410Snewton
31943410Snewton        Status = AcpiOsWriteMemory (
32043410Snewton                    (ACPI_PHYSICAL_ADDRESS) Address, Value, Width);
32143410Snewton        break;
32243410Snewton
32343410Snewton
32443410Snewton    case ACPI_ADR_SPACE_SYSTEM_IO:
32543410Snewton
32643410Snewton        Status = AcpiHwWritePort (
32743410Snewton                    (ACPI_IO_ADDRESS) Address, Value, Width);
32843410Snewton        break;
32943410Snewton
33043410Snewton
33143410Snewton    default:
33243410Snewton        ACPI_ERROR ((AE_INFO,
33343410Snewton            "Unsupported address space: %X", Reg->SpaceId));
33443410Snewton        return (AE_BAD_PARAMETER);
33543410Snewton    }
33643410Snewton
33743410Snewton    ACPI_DEBUG_PRINT ((ACPI_DB_IO,
33843410Snewton        "Wrote: %8.8X width %2d   to %8.8X%8.8X (%s)\n",
33943410Snewton        Value, Width, ACPI_FORMAT_UINT64 (Address),
34043410Snewton        AcpiUtGetRegionName (Reg->SpaceId)));
341109153Sdillon
34243410Snewton    return (Status);
34389306Salfred}
34489306Salfred
34589306SalfredACPI_EXPORT_SYMBOL (AcpiWrite)
34689306Salfred
34743410Snewton
34889306Salfred/*******************************************************************************
34943410Snewton *
35043410Snewton * FUNCTION:    AcpiReadBitRegister
351111119Simp *
35243410Snewton * PARAMETERS:  RegisterId      - ID of ACPI Bit Register to access
35343410Snewton *              ReturnValue     - Value that was read from the register,
35443410Snewton *                                normalized to bit position zero.
35543410Snewton *
35689306Salfred * RETURN:      Status and the value read from the specified Register. Value
35789306Salfred *              returned is normalized to bit0 (is shifted all the way right)
35889306Salfred *
35989306Salfred * DESCRIPTION: ACPI BitRegister read function. Does not acquire the HW lock.
36089306Salfred *
36189306Salfred * SUPPORTS:    Bit fields in PM1 Status, PM1 Enable, PM1 Control, and
36289306Salfred *              PM2 Control.
36389306Salfred *
36489306Salfred * Note: The hardware lock is not required when reading the ACPI bit registers
36589306Salfred *       since almost all of them are single bit and it does not matter that
36689306Salfred *       the parent hardware register can be split across two physical
36789306Salfred *       registers. The only multi-bit field is SLP_TYP in the PM1 control
36889306Salfred *       register, but this field does not cross an 8-bit boundary (nor does
36943410Snewton *       it make much sense to actually read this field.)
37043410Snewton *
37143410Snewton ******************************************************************************/
37243410Snewton
37343410SnewtonACPI_STATUS
37443410SnewtonAcpiReadBitRegister (
37543410Snewton    UINT32                  RegisterId,
37643410Snewton    UINT32                  *ReturnValue)
37743410Snewton{
37843410Snewton    ACPI_BIT_REGISTER_INFO  *BitRegInfo;
379109153Sdillon    UINT32                  RegisterValue;
38043410Snewton    UINT32                  Value;
38171448Sjhb    ACPI_STATUS             Status;
38271448Sjhb
38371448Sjhb
38471448Sjhb    ACPI_FUNCTION_TRACE_U32 (AcpiReadBitRegister, RegisterId);
38571448Sjhb
38643410Snewton
38743410Snewton    /* Get the info structure corresponding to the requested ACPI Register */
38843410Snewton
38971448Sjhb    BitRegInfo = AcpiHwGetBitRegisterInfo (RegisterId);
39043410Snewton    if (!BitRegInfo)
39143410Snewton    {
39243410Snewton        return_ACPI_STATUS (AE_BAD_PARAMETER);
39385653Sdillon    }
39443410Snewton
39543410Snewton    /* Read the entire parent register */
39643410Snewton
39743410Snewton    Status = AcpiHwRegisterRead (BitRegInfo->ParentRegister,
39843410Snewton                &RegisterValue);
39943410Snewton    if (ACPI_FAILURE (Status))
40083366Sjulian    {
40143410Snewton        return_ACPI_STATUS (Status);
402109153Sdillon    }
40343410Snewton
40443410Snewton    /* Normalize the value that was read, mask off other bits */
40543410Snewton
40683366Sjulian    Value = ((RegisterValue & BitRegInfo->AccessBitMask)
40743410Snewton                >> BitRegInfo->BitPosition);
40883366Sjulian
40943410Snewton    ACPI_DEBUG_PRINT ((ACPI_DB_IO,
410        "BitReg %X, ParentReg %X, Actual %8.8X, ReturnValue %8.8X\n",
411        RegisterId, BitRegInfo->ParentRegister, RegisterValue, Value));
412
413    *ReturnValue = Value;
414    return_ACPI_STATUS (AE_OK);
415}
416
417ACPI_EXPORT_SYMBOL (AcpiReadBitRegister)
418
419
420/*******************************************************************************
421 *
422 * FUNCTION:    AcpiWriteBitRegister
423 *
424 * PARAMETERS:  RegisterId      - ID of ACPI Bit Register to access
425 *              Value           - Value to write to the register, in bit
426 *                                position zero. The bit is automaticallly
427 *                                shifted to the correct position.
428 *
429 * RETURN:      Status
430 *
431 * DESCRIPTION: ACPI Bit Register write function. Acquires the hardware lock
432 *              since most operations require a read/modify/write sequence.
433 *
434 * SUPPORTS:    Bit fields in PM1 Status, PM1 Enable, PM1 Control, and
435 *              PM2 Control.
436 *
437 * Note that at this level, the fact that there may be actually two
438 * hardware registers (A and B - and B may not exist) is abstracted.
439 *
440 ******************************************************************************/
441
442ACPI_STATUS
443AcpiWriteBitRegister (
444    UINT32                  RegisterId,
445    UINT32                  Value)
446{
447    ACPI_BIT_REGISTER_INFO  *BitRegInfo;
448    ACPI_CPU_FLAGS          LockFlags;
449    UINT32                  RegisterValue;
450    ACPI_STATUS             Status = AE_OK;
451
452
453    ACPI_FUNCTION_TRACE_U32 (AcpiWriteBitRegister, RegisterId);
454
455
456    /* Get the info structure corresponding to the requested ACPI Register */
457
458    BitRegInfo = AcpiHwGetBitRegisterInfo (RegisterId);
459    if (!BitRegInfo)
460    {
461        return_ACPI_STATUS (AE_BAD_PARAMETER);
462    }
463
464    LockFlags = AcpiOsAcquireLock (AcpiGbl_HardwareLock);
465
466    /*
467     * At this point, we know that the parent register is one of the
468     * following: PM1 Status, PM1 Enable, PM1 Control, or PM2 Control
469     */
470    if (BitRegInfo->ParentRegister != ACPI_REGISTER_PM1_STATUS)
471    {
472        /*
473         * 1) Case for PM1 Enable, PM1 Control, and PM2 Control
474         *
475         * Perform a register read to preserve the bits that we are not
476         * interested in
477         */
478        Status = AcpiHwRegisterRead (BitRegInfo->ParentRegister,
479                    &RegisterValue);
480        if (ACPI_FAILURE (Status))
481        {
482            goto UnlockAndExit;
483        }
484
485        /*
486         * Insert the input bit into the value that was just read
487         * and write the register
488         */
489        ACPI_REGISTER_INSERT_VALUE (RegisterValue, BitRegInfo->BitPosition,
490            BitRegInfo->AccessBitMask, Value);
491
492        Status = AcpiHwRegisterWrite (BitRegInfo->ParentRegister,
493                    RegisterValue);
494    }
495    else
496    {
497        /*
498         * 2) Case for PM1 Status
499         *
500         * The Status register is different from the rest. Clear an event
501         * by writing 1, writing 0 has no effect. So, the only relevant
502         * information is the single bit we're interested in, all others
503         * should be written as 0 so they will be left unchanged.
504         */
505        RegisterValue = ACPI_REGISTER_PREPARE_BITS (Value,
506            BitRegInfo->BitPosition, BitRegInfo->AccessBitMask);
507
508        /* No need to write the register if value is all zeros */
509
510        if (RegisterValue)
511        {
512            Status = AcpiHwRegisterWrite (ACPI_REGISTER_PM1_STATUS,
513                        RegisterValue);
514        }
515    }
516
517    ACPI_DEBUG_PRINT ((ACPI_DB_IO,
518        "BitReg %X, ParentReg %X, Value %8.8X, Actual %8.8X\n",
519        RegisterId, BitRegInfo->ParentRegister, Value, RegisterValue));
520
521
522UnlockAndExit:
523
524    AcpiOsReleaseLock (AcpiGbl_HardwareLock, LockFlags);
525    return_ACPI_STATUS (Status);
526}
527
528ACPI_EXPORT_SYMBOL (AcpiWriteBitRegister)
529
530
531/*******************************************************************************
532 *
533 * FUNCTION:    AcpiGetSleepTypeData
534 *
535 * PARAMETERS:  SleepState          - Numeric sleep state
536 *              *SleepTypeA         - Where SLP_TYPa is returned
537 *              *SleepTypeB         - Where SLP_TYPb is returned
538 *
539 * RETURN:      Status - ACPI status
540 *
541 * DESCRIPTION: Obtain the SLP_TYPa and SLP_TYPb values for the requested sleep
542 *              state.
543 *
544 ******************************************************************************/
545
546ACPI_STATUS
547AcpiGetSleepTypeData (
548    UINT8                   SleepState,
549    UINT8                   *SleepTypeA,
550    UINT8                   *SleepTypeB)
551{
552    ACPI_STATUS             Status = AE_OK;
553    ACPI_EVALUATE_INFO      *Info;
554
555
556    ACPI_FUNCTION_TRACE (AcpiGetSleepTypeData);
557
558
559    /* Validate parameters */
560
561    if ((SleepState > ACPI_S_STATES_MAX) ||
562        !SleepTypeA ||
563        !SleepTypeB)
564    {
565        return_ACPI_STATUS (AE_BAD_PARAMETER);
566    }
567
568    /* Allocate the evaluation information block */
569
570    Info = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_EVALUATE_INFO));
571    if (!Info)
572    {
573        return_ACPI_STATUS (AE_NO_MEMORY);
574    }
575
576    Info->Pathname = ACPI_CAST_PTR (char, AcpiGbl_SleepStateNames[SleepState]);
577
578    /* Evaluate the namespace object containing the values for this state */
579
580    Status = AcpiNsEvaluate (Info);
581    if (ACPI_FAILURE (Status))
582    {
583        ACPI_DEBUG_PRINT ((ACPI_DB_EXEC,
584            "%s while evaluating SleepState [%s]\n",
585            AcpiFormatException (Status), Info->Pathname));
586
587        goto Cleanup;
588    }
589
590    /* Must have a return object */
591
592    if (!Info->ReturnObject)
593    {
594        ACPI_ERROR ((AE_INFO, "No Sleep State object returned from [%s]",
595            Info->Pathname));
596        Status = AE_NOT_EXIST;
597    }
598
599    /* It must be of type Package */
600
601    else if (Info->ReturnObject->Common.Type != ACPI_TYPE_PACKAGE)
602    {
603        ACPI_ERROR ((AE_INFO, "Sleep State return object is not a Package"));
604        Status = AE_AML_OPERAND_TYPE;
605    }
606
607    /*
608     * The package must have at least two elements. NOTE (March 2005): This
609     * goes against the current ACPI spec which defines this object as a
610     * package with one encoded DWORD element. However, existing practice
611     * by BIOS vendors seems to be to have 2 or more elements, at least
612     * one per sleep type (A/B).
613     */
614    else if (Info->ReturnObject->Package.Count < 2)
615    {
616        ACPI_ERROR ((AE_INFO,
617            "Sleep State return package does not have at least two elements"));
618        Status = AE_AML_NO_OPERAND;
619    }
620
621    /* The first two elements must both be of type Integer */
622
623    else if (((Info->ReturnObject->Package.Elements[0])->Common.Type
624                != ACPI_TYPE_INTEGER) ||
625             ((Info->ReturnObject->Package.Elements[1])->Common.Type
626                != ACPI_TYPE_INTEGER))
627    {
628        ACPI_ERROR ((AE_INFO,
629            "Sleep State return package elements are not both Integers "
630            "(%s, %s)",
631            AcpiUtGetObjectTypeName (Info->ReturnObject->Package.Elements[0]),
632            AcpiUtGetObjectTypeName (Info->ReturnObject->Package.Elements[1])));
633        Status = AE_AML_OPERAND_TYPE;
634    }
635    else
636    {
637        /* Valid _Sx_ package size, type, and value */
638
639        *SleepTypeA = (UINT8)
640            (Info->ReturnObject->Package.Elements[0])->Integer.Value;
641        *SleepTypeB = (UINT8)
642            (Info->ReturnObject->Package.Elements[1])->Integer.Value;
643    }
644
645    if (ACPI_FAILURE (Status))
646    {
647        ACPI_EXCEPTION ((AE_INFO, Status,
648            "While evaluating SleepState [%s], bad Sleep object %p type %s",
649            Info->Pathname, Info->ReturnObject,
650            AcpiUtGetObjectTypeName (Info->ReturnObject)));
651    }
652
653    AcpiUtRemoveReference (Info->ReturnObject);
654
655Cleanup:
656    ACPI_FREE (Info);
657    return_ACPI_STATUS (Status);
658}
659
660ACPI_EXPORT_SYMBOL (AcpiGetSleepTypeData)
661