xref: /onnv-gate/usr/src/uts/intel/io/acpica/hardware/hwregs.c (revision 7851:e828bbb1689c)
13446Smrj 
23446Smrj /*******************************************************************************
33446Smrj  *
43446Smrj  * Module Name: hwregs - Read/write access functions for the various ACPI
53446Smrj  *                       control and status registers.
6*7851SDana.Myers@Sun.COM  *              $Revision: 1.188 $
73446Smrj  *
83446Smrj  ******************************************************************************/
93446Smrj 
103446Smrj /******************************************************************************
113446Smrj  *
123446Smrj  * 1. Copyright Notice
133446Smrj  *
14*7851SDana.Myers@Sun.COM  * Some or all of this work - Copyright (c) 1999 - 2008, Intel Corp.
153446Smrj  * All rights reserved.
163446Smrj  *
173446Smrj  * 2. License
183446Smrj  *
193446Smrj  * 2.1. This is your license from Intel Corp. under its intellectual property
203446Smrj  * rights.  You may have additional license terms from the party that provided
213446Smrj  * you this software, covering your right to use that party's intellectual
223446Smrj  * property rights.
233446Smrj  *
243446Smrj  * 2.2. Intel grants, free of charge, to any person ("Licensee") obtaining a
253446Smrj  * copy of the source code appearing in this file ("Covered Code") an
263446Smrj  * irrevocable, perpetual, worldwide license under Intel's copyrights in the
273446Smrj  * base code distributed originally by Intel ("Original Intel Code") to copy,
283446Smrj  * make derivatives, distribute, use and display any portion of the Covered
293446Smrj  * Code in any form, with the right to sublicense such rights; and
303446Smrj  *
313446Smrj  * 2.3. Intel grants Licensee a non-exclusive and non-transferable patent
323446Smrj  * license (with the right to sublicense), under only those claims of Intel
333446Smrj  * patents that are infringed by the Original Intel Code, to make, use, sell,
343446Smrj  * offer to sell, and import the Covered Code and derivative works thereof
353446Smrj  * solely to the minimum extent necessary to exercise the above copyright
363446Smrj  * license, and in no event shall the patent license extend to any additions
373446Smrj  * to or modifications of the Original Intel Code.  No other license or right
383446Smrj  * is granted directly or by implication, estoppel or otherwise;
393446Smrj  *
403446Smrj  * The above copyright and patent license is granted only if the following
413446Smrj  * conditions are met:
423446Smrj  *
433446Smrj  * 3. Conditions
443446Smrj  *
453446Smrj  * 3.1. Redistribution of Source with Rights to Further Distribute Source.
463446Smrj  * Redistribution of source code of any substantial portion of the Covered
473446Smrj  * Code or modification with rights to further distribute source must include
483446Smrj  * the above Copyright Notice, the above License, this list of Conditions,
493446Smrj  * and the following Disclaimer and Export Compliance provision.  In addition,
503446Smrj  * Licensee must cause all Covered Code to which Licensee contributes to
513446Smrj  * contain a file documenting the changes Licensee made to create that Covered
523446Smrj  * Code and the date of any change.  Licensee must include in that file the
533446Smrj  * documentation of any changes made by any predecessor Licensee.  Licensee
543446Smrj  * must include a prominent statement that the modification is derived,
553446Smrj  * directly or indirectly, from Original Intel Code.
563446Smrj  *
573446Smrj  * 3.2. Redistribution of Source with no Rights to Further Distribute Source.
583446Smrj  * Redistribution of source code of any substantial portion of the Covered
593446Smrj  * Code or modification without rights to further distribute source must
603446Smrj  * include the following Disclaimer and Export Compliance provision in the
613446Smrj  * documentation and/or other materials provided with distribution.  In
623446Smrj  * addition, Licensee may not authorize further sublicense of source of any
633446Smrj  * portion of the Covered Code, and must include terms to the effect that the
643446Smrj  * license from Licensee to its licensee is limited to the intellectual
653446Smrj  * property embodied in the software Licensee provides to its licensee, and
663446Smrj  * not to intellectual property embodied in modifications its licensee may
673446Smrj  * make.
683446Smrj  *
693446Smrj  * 3.3. Redistribution of Executable. Redistribution in executable form of any
703446Smrj  * substantial portion of the Covered Code or modification must reproduce the
713446Smrj  * above Copyright Notice, and the following Disclaimer and Export Compliance
723446Smrj  * provision in the documentation and/or other materials provided with the
733446Smrj  * distribution.
743446Smrj  *
753446Smrj  * 3.4. Intel retains all right, title, and interest in and to the Original
763446Smrj  * Intel Code.
773446Smrj  *
783446Smrj  * 3.5. Neither the name Intel nor any other trademark owned or controlled by
793446Smrj  * Intel shall be used in advertising or otherwise to promote the sale, use or
803446Smrj  * other dealings in products derived from or relating to the Covered Code
813446Smrj  * without prior written authorization from Intel.
823446Smrj  *
833446Smrj  * 4. Disclaimer and Export Compliance
843446Smrj  *
853446Smrj  * 4.1. INTEL MAKES NO WARRANTY OF ANY KIND REGARDING ANY SOFTWARE PROVIDED
863446Smrj  * HERE.  ANY SOFTWARE ORIGINATING FROM INTEL OR DERIVED FROM INTEL SOFTWARE
873446Smrj  * IS PROVIDED "AS IS," AND INTEL WILL NOT PROVIDE ANY SUPPORT,  ASSISTANCE,
883446Smrj  * INSTALLATION, TRAINING OR OTHER SERVICES.  INTEL WILL NOT PROVIDE ANY
893446Smrj  * UPDATES, ENHANCEMENTS OR EXTENSIONS.  INTEL SPECIFICALLY DISCLAIMS ANY
903446Smrj  * IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT AND FITNESS FOR A
913446Smrj  * PARTICULAR PURPOSE.
923446Smrj  *
933446Smrj  * 4.2. IN NO EVENT SHALL INTEL HAVE ANY LIABILITY TO LICENSEE, ITS LICENSEES
943446Smrj  * OR ANY OTHER THIRD PARTY, FOR ANY LOST PROFITS, LOST DATA, LOSS OF USE OR
953446Smrj  * COSTS OF PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, OR FOR ANY INDIRECT,
963446Smrj  * SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THIS AGREEMENT, UNDER ANY
973446Smrj  * CAUSE OF ACTION OR THEORY OF LIABILITY, AND IRRESPECTIVE OF WHETHER INTEL
983446Smrj  * HAS ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES.  THESE LIMITATIONS
993446Smrj  * SHALL APPLY NOTWITHSTANDING THE FAILURE OF THE ESSENTIAL PURPOSE OF ANY
1003446Smrj  * LIMITED REMEDY.
1013446Smrj  *
1023446Smrj  * 4.3. Licensee shall not export, either directly or indirectly, any of this
1033446Smrj  * software or system incorporating such software without first obtaining any
1043446Smrj  * required license or other approval from the U. S. Department of Commerce or
1053446Smrj  * any other agency or department of the United States Government.  In the
1063446Smrj  * event Licensee exports any such software from the United States or
1073446Smrj  * re-exports any such software from a foreign destination, Licensee shall
1083446Smrj  * ensure that the distribution and export/re-export of the software is in
1093446Smrj  * compliance with all laws, regulations, orders, or other restrictions of the
1103446Smrj  * U.S. Export Administration Regulations. Licensee agrees that neither it nor
1113446Smrj  * any of its subsidiaries will export/re-export any technical data, process,
1123446Smrj  * software, or service, directly or indirectly, to any country for which the
1133446Smrj  * United States government or any agency thereof requires an export license,
1143446Smrj  * other governmental approval, or letter of assurance, without first obtaining
1153446Smrj  * such license, approval or letter.
1163446Smrj  *
1173446Smrj  *****************************************************************************/
1183446Smrj 
1193446Smrj #define __HWREGS_C__
1203446Smrj 
1213446Smrj #include "acpi.h"
1223446Smrj #include "acnamesp.h"
1233446Smrj #include "acevents.h"
1243446Smrj 
1253446Smrj #define _COMPONENT          ACPI_HARDWARE
1263446Smrj         ACPI_MODULE_NAME    ("hwregs")
1273446Smrj 
1283446Smrj 
1293446Smrj /*******************************************************************************
1303446Smrj  *
1313446Smrj  * FUNCTION:    AcpiHwClearAcpiStatus
1323446Smrj  *
133*7851SDana.Myers@Sun.COM  * PARAMETERS:  None
1343446Smrj  *
135*7851SDana.Myers@Sun.COM  * RETURN:      None
1363446Smrj  *
1373446Smrj  * DESCRIPTION: Clears all fixed and general purpose status bits
1383446Smrj  *              THIS FUNCTION MUST BE CALLED WITH INTERRUPTS DISABLED
1393446Smrj  *
1403446Smrj  ******************************************************************************/
1413446Smrj 
1423446Smrj ACPI_STATUS
1433446Smrj AcpiHwClearAcpiStatus (
144*7851SDana.Myers@Sun.COM     void)
1453446Smrj {
1463446Smrj     ACPI_STATUS             Status;
1473446Smrj     ACPI_CPU_FLAGS          LockFlags = 0;
1483446Smrj 
1493446Smrj 
1503446Smrj     ACPI_FUNCTION_TRACE (HwClearAcpiStatus);
1513446Smrj 
1523446Smrj 
1533446Smrj     ACPI_DEBUG_PRINT ((ACPI_DB_IO, "About to write %04X to %04X\n",
1543446Smrj         ACPI_BITMASK_ALL_FIXED_STATUS,
155*7851SDana.Myers@Sun.COM         (UINT16) AcpiGbl_FADT.XPm1aEventBlock.Address));
1563446Smrj 
1573446Smrj     LockFlags = AcpiOsAcquireLock (AcpiGbl_HardwareLock);
1583446Smrj 
159*7851SDana.Myers@Sun.COM     Status = AcpiHwRegisterWrite (ACPI_REGISTER_PM1_STATUS,
1603446Smrj                 ACPI_BITMASK_ALL_FIXED_STATUS);
1613446Smrj     if (ACPI_FAILURE (Status))
1623446Smrj     {
1633446Smrj         goto UnlockAndExit;
1643446Smrj     }
1653446Smrj 
1663446Smrj     /* Clear the fixed events */
1673446Smrj 
168*7851SDana.Myers@Sun.COM     if (AcpiGbl_FADT.XPm1bEventBlock.Address)
1693446Smrj     {
1703446Smrj         Status = AcpiHwLowLevelWrite (16, ACPI_BITMASK_ALL_FIXED_STATUS,
171*7851SDana.Myers@Sun.COM                     &AcpiGbl_FADT.XPm1bEventBlock);
1723446Smrj         if (ACPI_FAILURE (Status))
1733446Smrj         {
1743446Smrj             goto UnlockAndExit;
1753446Smrj         }
1763446Smrj     }
1773446Smrj 
1783446Smrj     /* Clear the GPE Bits in all GPE registers in all GPE blocks */
1793446Smrj 
1803446Smrj     Status = AcpiEvWalkGpeList (AcpiHwClearGpeBlock);
1813446Smrj 
1823446Smrj UnlockAndExit:
1833446Smrj     AcpiOsReleaseLock (AcpiGbl_HardwareLock, LockFlags);
1843446Smrj     return_ACPI_STATUS (Status);
1853446Smrj }
1863446Smrj 
1873446Smrj 
1883446Smrj /*******************************************************************************
1893446Smrj  *
1903446Smrj  * FUNCTION:    AcpiGetSleepTypeData
1913446Smrj  *
1923446Smrj  * PARAMETERS:  SleepState          - Numeric sleep state
1933446Smrj  *              *SleepTypeA         - Where SLP_TYPa is returned
1943446Smrj  *              *SleepTypeB         - Where SLP_TYPb is returned
1953446Smrj  *
1963446Smrj  * RETURN:      Status - ACPI status
1973446Smrj  *
1983446Smrj  * DESCRIPTION: Obtain the SLP_TYPa and SLP_TYPb values for the requested sleep
1993446Smrj  *              state.
2003446Smrj  *
2013446Smrj  ******************************************************************************/
2023446Smrj 
2033446Smrj ACPI_STATUS
2043446Smrj AcpiGetSleepTypeData (
2053446Smrj     UINT8                   SleepState,
2063446Smrj     UINT8                   *SleepTypeA,
2073446Smrj     UINT8                   *SleepTypeB)
2083446Smrj {
2093446Smrj     ACPI_STATUS             Status = AE_OK;
2103446Smrj     ACPI_EVALUATE_INFO      *Info;
2113446Smrj 
2123446Smrj 
2133446Smrj     ACPI_FUNCTION_TRACE (AcpiGetSleepTypeData);
2143446Smrj 
2153446Smrj 
2163446Smrj     /* Validate parameters */
2173446Smrj 
2183446Smrj     if ((SleepState > ACPI_S_STATES_MAX) ||
2193446Smrj         !SleepTypeA || !SleepTypeB)
2203446Smrj     {
2213446Smrj         return_ACPI_STATUS (AE_BAD_PARAMETER);
2223446Smrj     }
2233446Smrj 
2243446Smrj     /* Allocate the evaluation information block */
2253446Smrj 
2263446Smrj     Info = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_EVALUATE_INFO));
2273446Smrj     if (!Info)
2283446Smrj     {
2293446Smrj         return_ACPI_STATUS (AE_NO_MEMORY);
2303446Smrj     }
2313446Smrj 
2323446Smrj     Info->Pathname = ACPI_CAST_PTR (char, AcpiGbl_SleepStateNames[SleepState]);
2333446Smrj 
2343446Smrj     /* Evaluate the namespace object containing the values for this state */
2353446Smrj 
2363446Smrj     Status = AcpiNsEvaluate (Info);
2373446Smrj     if (ACPI_FAILURE (Status))
2383446Smrj     {
2393446Smrj         ACPI_DEBUG_PRINT ((ACPI_DB_EXEC,
2403446Smrj             "%s while evaluating SleepState [%s]\n",
2413446Smrj             AcpiFormatException (Status), Info->Pathname));
2423446Smrj 
2433446Smrj         goto Cleanup;
2443446Smrj     }
2453446Smrj 
2463446Smrj     /* Must have a return object */
2473446Smrj 
2483446Smrj     if (!Info->ReturnObject)
2493446Smrj     {
2503446Smrj         ACPI_ERROR ((AE_INFO, "No Sleep State object returned from [%s]",
2513446Smrj             Info->Pathname));
2523446Smrj         Status = AE_NOT_EXIST;
2533446Smrj     }
2543446Smrj 
2553446Smrj     /* It must be of type Package */
2563446Smrj 
2573446Smrj     else if (ACPI_GET_OBJECT_TYPE (Info->ReturnObject) != ACPI_TYPE_PACKAGE)
2583446Smrj     {
2593446Smrj         ACPI_ERROR ((AE_INFO, "Sleep State return object is not a Package"));
2603446Smrj         Status = AE_AML_OPERAND_TYPE;
2613446Smrj     }
2623446Smrj 
2633446Smrj     /*
2643446Smrj      * The package must have at least two elements. NOTE (March 2005): This
2653446Smrj      * goes against the current ACPI spec which defines this object as a
2663446Smrj      * package with one encoded DWORD element. However, existing practice
2673446Smrj      * by BIOS vendors seems to be to have 2 or more elements, at least
2683446Smrj      * one per sleep type (A/B).
2693446Smrj      */
2703446Smrj     else if (Info->ReturnObject->Package.Count < 2)
2713446Smrj     {
2723446Smrj         ACPI_ERROR ((AE_INFO,
2733446Smrj             "Sleep State return package does not have at least two elements"));
2743446Smrj         Status = AE_AML_NO_OPERAND;
2753446Smrj     }
2763446Smrj 
2773446Smrj     /* The first two elements must both be of type Integer */
2783446Smrj 
2793446Smrj     else if ((ACPI_GET_OBJECT_TYPE (Info->ReturnObject->Package.Elements[0])
2803446Smrj                 != ACPI_TYPE_INTEGER) ||
2813446Smrj              (ACPI_GET_OBJECT_TYPE (Info->ReturnObject->Package.Elements[1])
2823446Smrj                 != ACPI_TYPE_INTEGER))
2833446Smrj     {
2843446Smrj         ACPI_ERROR ((AE_INFO,
2853446Smrj             "Sleep State return package elements are not both Integers (%s, %s)",
2863446Smrj             AcpiUtGetObjectTypeName (Info->ReturnObject->Package.Elements[0]),
2873446Smrj             AcpiUtGetObjectTypeName (Info->ReturnObject->Package.Elements[1])));
2883446Smrj         Status = AE_AML_OPERAND_TYPE;
2893446Smrj     }
2903446Smrj     else
2913446Smrj     {
2923446Smrj         /* Valid _Sx_ package size, type, and value */
2933446Smrj 
2943446Smrj         *SleepTypeA = (UINT8)
2953446Smrj             (Info->ReturnObject->Package.Elements[0])->Integer.Value;
2963446Smrj         *SleepTypeB = (UINT8)
2973446Smrj             (Info->ReturnObject->Package.Elements[1])->Integer.Value;
2983446Smrj     }
2993446Smrj 
3003446Smrj     if (ACPI_FAILURE (Status))
3013446Smrj     {
3023446Smrj         ACPI_EXCEPTION ((AE_INFO, Status,
3033446Smrj             "While evaluating SleepState [%s], bad Sleep object %p type %s",
3043446Smrj             Info->Pathname, Info->ReturnObject,
3053446Smrj             AcpiUtGetObjectTypeName (Info->ReturnObject)));
3063446Smrj     }
3073446Smrj 
3083446Smrj     AcpiUtRemoveReference (Info->ReturnObject);
3093446Smrj 
3103446Smrj Cleanup:
3113446Smrj     ACPI_FREE (Info);
3123446Smrj     return_ACPI_STATUS (Status);
3133446Smrj }
3143446Smrj 
3153446Smrj ACPI_EXPORT_SYMBOL (AcpiGetSleepTypeData)
3163446Smrj 
3173446Smrj 
3183446Smrj /*******************************************************************************
3193446Smrj  *
3203446Smrj  * FUNCTION:    AcpiHwGetRegisterBitMask
3213446Smrj  *
3223446Smrj  * PARAMETERS:  RegisterId          - Index of ACPI Register to access
3233446Smrj  *
3243446Smrj  * RETURN:      The bitmask to be used when accessing the register
3253446Smrj  *
3263446Smrj  * DESCRIPTION: Map RegisterId into a register bitmask.
3273446Smrj  *
3283446Smrj  ******************************************************************************/
3293446Smrj 
3303446Smrj ACPI_BIT_REGISTER_INFO *
3313446Smrj AcpiHwGetBitRegisterInfo (
3323446Smrj     UINT32                  RegisterId)
3333446Smrj {
3343446Smrj     ACPI_FUNCTION_ENTRY ();
3353446Smrj 
3363446Smrj 
3373446Smrj     if (RegisterId > ACPI_BITREG_MAX)
3383446Smrj     {
3393446Smrj         ACPI_ERROR ((AE_INFO, "Invalid BitRegister ID: %X", RegisterId));
3403446Smrj         return (NULL);
3413446Smrj     }
3423446Smrj 
3433446Smrj     return (&AcpiGbl_BitRegisterInfo[RegisterId]);
3443446Smrj }
3453446Smrj 
3463446Smrj 
3473446Smrj /*******************************************************************************
3483446Smrj  *
349*7851SDana.Myers@Sun.COM  * FUNCTION:    AcpiGetRegisterUnlocked
3503446Smrj  *
3513446Smrj  * PARAMETERS:  RegisterId      - ID of ACPI BitRegister to access
3523446Smrj  *              ReturnValue     - Value that was read from the register
3533446Smrj  *
3543446Smrj  * RETURN:      Status and the value read from specified Register. Value
3553446Smrj  *              returned is normalized to bit0 (is shifted all the way right)
3563446Smrj  *
357*7851SDana.Myers@Sun.COM  * DESCRIPTION: ACPI BitRegister read function. Does not acquire the HW lock.
3583446Smrj  *
3593446Smrj  ******************************************************************************/
3603446Smrj 
3613446Smrj ACPI_STATUS
362*7851SDana.Myers@Sun.COM AcpiGetRegisterUnlocked (
3633446Smrj     UINT32                  RegisterId,
364*7851SDana.Myers@Sun.COM     UINT32                  *ReturnValue)
3653446Smrj {
3663446Smrj     UINT32                  RegisterValue = 0;
3673446Smrj     ACPI_BIT_REGISTER_INFO  *BitRegInfo;
3683446Smrj     ACPI_STATUS             Status;
3693446Smrj 
3703446Smrj 
371*7851SDana.Myers@Sun.COM     ACPI_FUNCTION_TRACE (AcpiGetRegisterUnlocked);
3723446Smrj 
3733446Smrj 
3743446Smrj     /* Get the info structure corresponding to the requested ACPI Register */
3753446Smrj 
3763446Smrj     BitRegInfo = AcpiHwGetBitRegisterInfo (RegisterId);
3773446Smrj     if (!BitRegInfo)
3783446Smrj     {
3793446Smrj         return_ACPI_STATUS (AE_BAD_PARAMETER);
3803446Smrj     }
3813446Smrj 
3823446Smrj     /* Read from the register */
3833446Smrj 
384*7851SDana.Myers@Sun.COM     Status = AcpiHwRegisterRead (BitRegInfo->ParentRegister,
385*7851SDana.Myers@Sun.COM                 &RegisterValue);
3863446Smrj 
3873446Smrj     if (ACPI_SUCCESS (Status))
3883446Smrj     {
3893446Smrj         /* Normalize the value that was read */
3903446Smrj 
3913446Smrj         RegisterValue = ((RegisterValue & BitRegInfo->AccessBitMask)
3923446Smrj                             >> BitRegInfo->BitPosition);
3933446Smrj 
3943446Smrj         *ReturnValue = RegisterValue;
3953446Smrj 
3963446Smrj         ACPI_DEBUG_PRINT ((ACPI_DB_IO, "Read value %8.8X register %X\n",
3973446Smrj             RegisterValue, BitRegInfo->ParentRegister));
3983446Smrj     }
3993446Smrj 
4003446Smrj     return_ACPI_STATUS (Status);
4013446Smrj }
4023446Smrj 
403*7851SDana.Myers@Sun.COM 
404*7851SDana.Myers@Sun.COM /*******************************************************************************
405*7851SDana.Myers@Sun.COM  *
406*7851SDana.Myers@Sun.COM  * FUNCTION:    AcpiGetRegister
407*7851SDana.Myers@Sun.COM  *
408*7851SDana.Myers@Sun.COM  * PARAMETERS:  RegisterId      - ID of ACPI BitRegister to access
409*7851SDana.Myers@Sun.COM  *              ReturnValue     - Value that was read from the register
410*7851SDana.Myers@Sun.COM  *
411*7851SDana.Myers@Sun.COM  * RETURN:      Status and the value read from specified Register. Value
412*7851SDana.Myers@Sun.COM  *              returned is normalized to bit0 (is shifted all the way right)
413*7851SDana.Myers@Sun.COM  *
414*7851SDana.Myers@Sun.COM  * DESCRIPTION: ACPI BitRegister read function.
415*7851SDana.Myers@Sun.COM  *
416*7851SDana.Myers@Sun.COM  ******************************************************************************/
417*7851SDana.Myers@Sun.COM 
418*7851SDana.Myers@Sun.COM ACPI_STATUS
419*7851SDana.Myers@Sun.COM AcpiGetRegister (
420*7851SDana.Myers@Sun.COM     UINT32                  RegisterId,
421*7851SDana.Myers@Sun.COM     UINT32                  *ReturnValue)
422*7851SDana.Myers@Sun.COM {
423*7851SDana.Myers@Sun.COM     ACPI_STATUS             Status;
424*7851SDana.Myers@Sun.COM     ACPI_CPU_FLAGS          Flags;
425*7851SDana.Myers@Sun.COM 
426*7851SDana.Myers@Sun.COM 
427*7851SDana.Myers@Sun.COM     Flags = AcpiOsAcquireLock (AcpiGbl_HardwareLock);
428*7851SDana.Myers@Sun.COM     Status = AcpiGetRegisterUnlocked (RegisterId, ReturnValue);
429*7851SDana.Myers@Sun.COM     AcpiOsReleaseLock (AcpiGbl_HardwareLock, Flags);
430*7851SDana.Myers@Sun.COM 
431*7851SDana.Myers@Sun.COM     return (Status);
432*7851SDana.Myers@Sun.COM }
433*7851SDana.Myers@Sun.COM 
4343446Smrj ACPI_EXPORT_SYMBOL (AcpiGetRegister)
4353446Smrj 
4363446Smrj 
4373446Smrj /*******************************************************************************
4383446Smrj  *
4393446Smrj  * FUNCTION:    AcpiSetRegister
4403446Smrj  *
4413446Smrj  * PARAMETERS:  RegisterId      - ID of ACPI BitRegister to access
4423446Smrj  *              Value           - (only used on write) value to write to the
4433446Smrj  *                                Register, NOT pre-normalized to the bit pos
4443446Smrj  *
4453446Smrj  * RETURN:      Status
4463446Smrj  *
4473446Smrj  * DESCRIPTION: ACPI Bit Register write function.
4483446Smrj  *
4493446Smrj  ******************************************************************************/
4503446Smrj 
4513446Smrj ACPI_STATUS
4523446Smrj AcpiSetRegister (
4533446Smrj     UINT32                  RegisterId,
454*7851SDana.Myers@Sun.COM     UINT32                  Value)
4553446Smrj {
4563446Smrj     UINT32                  RegisterValue = 0;
4573446Smrj     ACPI_BIT_REGISTER_INFO  *BitRegInfo;
4583446Smrj     ACPI_STATUS             Status;
4593446Smrj     ACPI_CPU_FLAGS          LockFlags;
4603446Smrj 
4613446Smrj 
4623446Smrj     ACPI_FUNCTION_TRACE_U32 (AcpiSetRegister, RegisterId);
4633446Smrj 
4643446Smrj 
4653446Smrj     /* Get the info structure corresponding to the requested ACPI Register */
4663446Smrj 
4673446Smrj     BitRegInfo = AcpiHwGetBitRegisterInfo (RegisterId);
4683446Smrj     if (!BitRegInfo)
4693446Smrj     {
4703446Smrj         ACPI_ERROR ((AE_INFO, "Bad ACPI HW RegisterId: %X", RegisterId));
4713446Smrj         return_ACPI_STATUS (AE_BAD_PARAMETER);
4723446Smrj     }
4733446Smrj 
4743446Smrj     LockFlags = AcpiOsAcquireLock (AcpiGbl_HardwareLock);
4753446Smrj 
4763446Smrj     /* Always do a register read first so we can insert the new bits  */
4773446Smrj 
478*7851SDana.Myers@Sun.COM     Status = AcpiHwRegisterRead (BitRegInfo->ParentRegister,
479*7851SDana.Myers@Sun.COM                 &RegisterValue);
4803446Smrj     if (ACPI_FAILURE (Status))
4813446Smrj     {
4823446Smrj         goto UnlockAndExit;
4833446Smrj     }
4843446Smrj 
4853446Smrj     /*
4863446Smrj      * Decode the Register ID
4873446Smrj      * Register ID = [Register block ID] | [bit ID]
4883446Smrj      *
4893446Smrj      * Check bit ID to fine locate Register offset.
4903446Smrj      * Check Mask to determine Register offset, and then read-write.
4913446Smrj      */
4923446Smrj     switch (BitRegInfo->ParentRegister)
4933446Smrj     {
4943446Smrj     case ACPI_REGISTER_PM1_STATUS:
4953446Smrj 
4963446Smrj         /*
4973446Smrj          * Status Registers are different from the rest. Clear by
4983446Smrj          * writing 1, and writing 0 has no effect. So, the only relevant
4993446Smrj          * information is the single bit we're interested in, all others should
5003446Smrj          * be written as 0 so they will be left unchanged.
5013446Smrj          */
5023446Smrj         Value = ACPI_REGISTER_PREPARE_BITS (Value,
5033446Smrj                     BitRegInfo->BitPosition, BitRegInfo->AccessBitMask);
5043446Smrj         if (Value)
5053446Smrj         {
506*7851SDana.Myers@Sun.COM             Status = AcpiHwRegisterWrite (ACPI_REGISTER_PM1_STATUS,
507*7851SDana.Myers@Sun.COM                         (UINT16) Value);
5083446Smrj             RegisterValue = 0;
5093446Smrj         }
5103446Smrj         break;
5113446Smrj 
5123446Smrj 
5133446Smrj     case ACPI_REGISTER_PM1_ENABLE:
5143446Smrj 
5153446Smrj         ACPI_REGISTER_INSERT_VALUE (RegisterValue, BitRegInfo->BitPosition,
5163446Smrj             BitRegInfo->AccessBitMask, Value);
5173446Smrj 
518*7851SDana.Myers@Sun.COM         Status = AcpiHwRegisterWrite (ACPI_REGISTER_PM1_ENABLE,
519*7851SDana.Myers@Sun.COM                     (UINT16) RegisterValue);
5203446Smrj         break;
5213446Smrj 
5223446Smrj 
5233446Smrj     case ACPI_REGISTER_PM1_CONTROL:
5243446Smrj 
5253446Smrj         /*
5263446Smrj          * Write the PM1 Control register.
5273446Smrj          * Note that at this level, the fact that there are actually TWO
5283446Smrj          * registers (A and B - and B may not exist) is abstracted.
5293446Smrj          */
5303446Smrj         ACPI_DEBUG_PRINT ((ACPI_DB_IO, "PM1 control: Read %X\n",
5313446Smrj             RegisterValue));
5323446Smrj 
5333446Smrj         ACPI_REGISTER_INSERT_VALUE (RegisterValue, BitRegInfo->BitPosition,
5343446Smrj             BitRegInfo->AccessBitMask, Value);
5353446Smrj 
536*7851SDana.Myers@Sun.COM         Status = AcpiHwRegisterWrite (ACPI_REGISTER_PM1_CONTROL,
537*7851SDana.Myers@Sun.COM                     (UINT16) RegisterValue);
5383446Smrj         break;
5393446Smrj 
5403446Smrj 
5413446Smrj     case ACPI_REGISTER_PM2_CONTROL:
5423446Smrj 
543*7851SDana.Myers@Sun.COM         Status = AcpiHwRegisterRead (ACPI_REGISTER_PM2_CONTROL,
544*7851SDana.Myers@Sun.COM                     &RegisterValue);
5453446Smrj         if (ACPI_FAILURE (Status))
5463446Smrj         {
5473446Smrj             goto UnlockAndExit;
5483446Smrj         }
5493446Smrj 
5503446Smrj         ACPI_DEBUG_PRINT ((ACPI_DB_IO, "PM2 control: Read %X from %8.8X%8.8X\n",
5513446Smrj             RegisterValue,
552*7851SDana.Myers@Sun.COM             ACPI_FORMAT_UINT64 (AcpiGbl_FADT.XPm2ControlBlock.Address)));
5533446Smrj 
5543446Smrj         ACPI_REGISTER_INSERT_VALUE (RegisterValue, BitRegInfo->BitPosition,
5553446Smrj                 BitRegInfo->AccessBitMask, Value);
5563446Smrj 
5573446Smrj         ACPI_DEBUG_PRINT ((ACPI_DB_IO, "About to write %4.4X to %8.8X%8.8X\n",
5583446Smrj             RegisterValue,
559*7851SDana.Myers@Sun.COM             ACPI_FORMAT_UINT64 (AcpiGbl_FADT.XPm2ControlBlock.Address)));
5603446Smrj 
561*7851SDana.Myers@Sun.COM         Status = AcpiHwRegisterWrite (ACPI_REGISTER_PM2_CONTROL,
562*7851SDana.Myers@Sun.COM                     (UINT8) (RegisterValue));
5633446Smrj         break;
5643446Smrj 
5653446Smrj 
5663446Smrj     default:
5673446Smrj         break;
5683446Smrj     }
5693446Smrj 
5703446Smrj 
5713446Smrj UnlockAndExit:
5723446Smrj 
5733446Smrj     AcpiOsReleaseLock (AcpiGbl_HardwareLock, LockFlags);
5743446Smrj 
5753446Smrj     /* Normalize the value that was read */
5763446Smrj 
5773446Smrj     ACPI_DEBUG_EXEC (RegisterValue =
5783446Smrj         ((RegisterValue & BitRegInfo->AccessBitMask) >>
5793446Smrj             BitRegInfo->BitPosition));
5803446Smrj 
5813446Smrj     ACPI_DEBUG_PRINT ((ACPI_DB_IO, "Set bits: %8.8X actual %8.8X register %X\n",
5823446Smrj         Value, RegisterValue, BitRegInfo->ParentRegister));
5833446Smrj     return_ACPI_STATUS (Status);
5843446Smrj }
5853446Smrj 
5863446Smrj ACPI_EXPORT_SYMBOL (AcpiSetRegister)
5873446Smrj 
5883446Smrj 
5893446Smrj /******************************************************************************
5903446Smrj  *
5913446Smrj  * FUNCTION:    AcpiHwRegisterRead
5923446Smrj  *
593*7851SDana.Myers@Sun.COM  * PARAMETERS:  RegisterId          - ACPI Register ID
5943446Smrj  *              ReturnValue         - Where the register value is returned
5953446Smrj  *
5963446Smrj  * RETURN:      Status and the value read.
5973446Smrj  *
5983446Smrj  * DESCRIPTION: Read from the specified ACPI register
5993446Smrj  *
6003446Smrj  ******************************************************************************/
6013446Smrj 
6023446Smrj ACPI_STATUS
6033446Smrj AcpiHwRegisterRead (
6043446Smrj     UINT32                  RegisterId,
6053446Smrj     UINT32                  *ReturnValue)
6063446Smrj {
6073446Smrj     UINT32                  Value1 = 0;
6083446Smrj     UINT32                  Value2 = 0;
6093446Smrj     ACPI_STATUS             Status;
6103446Smrj 
6113446Smrj 
6123446Smrj     ACPI_FUNCTION_TRACE (HwRegisterRead);
6133446Smrj 
6143446Smrj 
6153446Smrj     switch (RegisterId)
6163446Smrj     {
6173446Smrj     case ACPI_REGISTER_PM1_STATUS:           /* 16-bit access */
6183446Smrj 
619*7851SDana.Myers@Sun.COM         Status = AcpiHwLowLevelRead (16, &Value1, &AcpiGbl_FADT.XPm1aEventBlock);
6203446Smrj         if (ACPI_FAILURE (Status))
6213446Smrj         {
622*7851SDana.Myers@Sun.COM             goto Exit;
6233446Smrj         }
6243446Smrj 
6253446Smrj         /* PM1B is optional */
6263446Smrj 
627*7851SDana.Myers@Sun.COM         Status = AcpiHwLowLevelRead (16, &Value2, &AcpiGbl_FADT.XPm1bEventBlock);
6283446Smrj         Value1 |= Value2;
6293446Smrj         break;
6303446Smrj 
6313446Smrj 
6323446Smrj     case ACPI_REGISTER_PM1_ENABLE:           /* 16-bit access */
6333446Smrj 
6343446Smrj         Status = AcpiHwLowLevelRead (16, &Value1, &AcpiGbl_XPm1aEnable);
6353446Smrj         if (ACPI_FAILURE (Status))
6363446Smrj         {
637*7851SDana.Myers@Sun.COM             goto Exit;
6383446Smrj         }
6393446Smrj 
6403446Smrj         /* PM1B is optional */
6413446Smrj 
6423446Smrj         Status = AcpiHwLowLevelRead (16, &Value2, &AcpiGbl_XPm1bEnable);
6433446Smrj         Value1 |= Value2;
6443446Smrj         break;
6453446Smrj 
6463446Smrj 
6473446Smrj     case ACPI_REGISTER_PM1_CONTROL:          /* 16-bit access */
6483446Smrj 
649*7851SDana.Myers@Sun.COM         Status = AcpiHwLowLevelRead (16, &Value1, &AcpiGbl_FADT.XPm1aControlBlock);
6503446Smrj         if (ACPI_FAILURE (Status))
6513446Smrj         {
652*7851SDana.Myers@Sun.COM             goto Exit;
6533446Smrj         }
6543446Smrj 
655*7851SDana.Myers@Sun.COM         Status = AcpiHwLowLevelRead (16, &Value2, &AcpiGbl_FADT.XPm1bControlBlock);
6563446Smrj         Value1 |= Value2;
6573446Smrj         break;
6583446Smrj 
6593446Smrj 
6603446Smrj     case ACPI_REGISTER_PM2_CONTROL:          /* 8-bit access */
6613446Smrj 
662*7851SDana.Myers@Sun.COM         Status = AcpiHwLowLevelRead (8, &Value1, &AcpiGbl_FADT.XPm2ControlBlock);
6633446Smrj         break;
6643446Smrj 
6653446Smrj 
6663446Smrj     case ACPI_REGISTER_PM_TIMER:             /* 32-bit access */
6673446Smrj 
668*7851SDana.Myers@Sun.COM         Status = AcpiHwLowLevelRead (32, &Value1, &AcpiGbl_FADT.XPmTimerBlock);
6693446Smrj         break;
6703446Smrj 
6713446Smrj     case ACPI_REGISTER_SMI_COMMAND_BLOCK:    /* 8-bit access */
6723446Smrj 
673*7851SDana.Myers@Sun.COM         Status = AcpiOsReadPort (AcpiGbl_FADT.SmiCommand, &Value1, 8);
6743446Smrj         break;
6753446Smrj 
6763446Smrj     default:
6773446Smrj         ACPI_ERROR ((AE_INFO, "Unknown Register ID: %X",
6783446Smrj             RegisterId));
6793446Smrj         Status = AE_BAD_PARAMETER;
6803446Smrj         break;
6813446Smrj     }
6823446Smrj 
683*7851SDana.Myers@Sun.COM Exit:
6843446Smrj     if (ACPI_SUCCESS (Status))
6853446Smrj     {
6863446Smrj         *ReturnValue = Value1;
6873446Smrj     }
6883446Smrj 
6893446Smrj     return_ACPI_STATUS (Status);
6903446Smrj }
6913446Smrj 
6923446Smrj 
6933446Smrj /******************************************************************************
6943446Smrj  *
6953446Smrj  * FUNCTION:    AcpiHwRegisterWrite
6963446Smrj  *
697*7851SDana.Myers@Sun.COM  * PARAMETERS:  RegisterId          - ACPI Register ID
6983446Smrj  *              Value               - The value to write
6993446Smrj  *
7003446Smrj  * RETURN:      Status
7013446Smrj  *
7023446Smrj  * DESCRIPTION: Write to the specified ACPI register
7033446Smrj  *
7043446Smrj  * NOTE: In accordance with the ACPI specification, this function automatically
7053446Smrj  * preserves the value of the following bits, meaning that these bits cannot be
7063446Smrj  * changed via this interface:
7073446Smrj  *
7083446Smrj  * PM1_CONTROL[0] = SCI_EN
7093446Smrj  * PM1_CONTROL[9]
7103446Smrj  * PM1_STATUS[11]
7113446Smrj  *
7123446Smrj  * ACPI References:
7133446Smrj  * 1) Hardware Ignored Bits: When software writes to a register with ignored
7143446Smrj  *      bit fields, it preserves the ignored bit fields
7153446Smrj  * 2) SCI_EN: OSPM always preserves this bit position
7163446Smrj  *
7173446Smrj  ******************************************************************************/
7183446Smrj 
7193446Smrj ACPI_STATUS
7203446Smrj AcpiHwRegisterWrite (
7213446Smrj     UINT32                  RegisterId,
7223446Smrj     UINT32                  Value)
7233446Smrj {
7243446Smrj     ACPI_STATUS             Status;
7253446Smrj     UINT32                  ReadValue;
7263446Smrj 
7273446Smrj 
7283446Smrj     ACPI_FUNCTION_TRACE (HwRegisterWrite);
7293446Smrj 
7303446Smrj 
7313446Smrj     switch (RegisterId)
7323446Smrj     {
7333446Smrj     case ACPI_REGISTER_PM1_STATUS:           /* 16-bit access */
7343446Smrj 
7353446Smrj         /* Perform a read first to preserve certain bits (per ACPI spec) */
7363446Smrj 
737*7851SDana.Myers@Sun.COM         Status = AcpiHwRegisterRead (ACPI_REGISTER_PM1_STATUS,
738*7851SDana.Myers@Sun.COM                     &ReadValue);
7393446Smrj         if (ACPI_FAILURE (Status))
7403446Smrj         {
741*7851SDana.Myers@Sun.COM             goto Exit;
7423446Smrj         }
7433446Smrj 
7443446Smrj         /* Insert the bits to be preserved */
7453446Smrj 
7463446Smrj         ACPI_INSERT_BITS (Value, ACPI_PM1_STATUS_PRESERVED_BITS, ReadValue);
7473446Smrj 
7483446Smrj         /* Now we can write the data */
7493446Smrj 
750*7851SDana.Myers@Sun.COM         Status = AcpiHwLowLevelWrite (16, Value, &AcpiGbl_FADT.XPm1aEventBlock);
7513446Smrj         if (ACPI_FAILURE (Status))
7523446Smrj         {
753*7851SDana.Myers@Sun.COM             goto Exit;
7543446Smrj         }
7553446Smrj 
7563446Smrj         /* PM1B is optional */
7573446Smrj 
758*7851SDana.Myers@Sun.COM         Status = AcpiHwLowLevelWrite (16, Value, &AcpiGbl_FADT.XPm1bEventBlock);
7593446Smrj         break;
7603446Smrj 
7613446Smrj 
7623446Smrj     case ACPI_REGISTER_PM1_ENABLE:           /* 16-bit access */
7633446Smrj 
7643446Smrj         Status = AcpiHwLowLevelWrite (16, Value, &AcpiGbl_XPm1aEnable);
7653446Smrj         if (ACPI_FAILURE (Status))
7663446Smrj         {
767*7851SDana.Myers@Sun.COM             goto Exit;
7683446Smrj         }
7693446Smrj 
7703446Smrj         /* PM1B is optional */
7713446Smrj 
7723446Smrj         Status = AcpiHwLowLevelWrite (16, Value, &AcpiGbl_XPm1bEnable);
7733446Smrj         break;
7743446Smrj 
7753446Smrj 
7763446Smrj     case ACPI_REGISTER_PM1_CONTROL:          /* 16-bit access */
7773446Smrj 
7783446Smrj         /*
7793446Smrj          * Perform a read first to preserve certain bits (per ACPI spec)
7803446Smrj          *
7813446Smrj          * Note: This includes SCI_EN, we never want to change this bit
7823446Smrj          */
783*7851SDana.Myers@Sun.COM         Status = AcpiHwRegisterRead (ACPI_REGISTER_PM1_CONTROL,
784*7851SDana.Myers@Sun.COM                     &ReadValue);
7853446Smrj         if (ACPI_FAILURE (Status))
7863446Smrj         {
787*7851SDana.Myers@Sun.COM             goto Exit;
7883446Smrj         }
7893446Smrj 
7903446Smrj         /* Insert the bits to be preserved */
7913446Smrj 
7923446Smrj         ACPI_INSERT_BITS (Value, ACPI_PM1_CONTROL_PRESERVED_BITS, ReadValue);
7933446Smrj 
7943446Smrj         /* Now we can write the data */
7953446Smrj 
796*7851SDana.Myers@Sun.COM         Status = AcpiHwLowLevelWrite (16, Value, &AcpiGbl_FADT.XPm1aControlBlock);
7973446Smrj         if (ACPI_FAILURE (Status))
7983446Smrj         {
799*7851SDana.Myers@Sun.COM             goto Exit;
8003446Smrj         }
8013446Smrj 
802*7851SDana.Myers@Sun.COM         Status = AcpiHwLowLevelWrite (16, Value, &AcpiGbl_FADT.XPm1bControlBlock);
8033446Smrj         break;
8043446Smrj 
8053446Smrj 
8063446Smrj     case ACPI_REGISTER_PM1A_CONTROL:         /* 16-bit access */
8073446Smrj 
808*7851SDana.Myers@Sun.COM         Status = AcpiHwLowLevelWrite (16, Value, &AcpiGbl_FADT.XPm1aControlBlock);
8093446Smrj         break;
8103446Smrj 
8113446Smrj 
8123446Smrj     case ACPI_REGISTER_PM1B_CONTROL:         /* 16-bit access */
8133446Smrj 
814*7851SDana.Myers@Sun.COM         Status = AcpiHwLowLevelWrite (16, Value, &AcpiGbl_FADT.XPm1bControlBlock);
8153446Smrj         break;
8163446Smrj 
8173446Smrj 
8183446Smrj     case ACPI_REGISTER_PM2_CONTROL:          /* 8-bit access */
8193446Smrj 
820*7851SDana.Myers@Sun.COM         Status = AcpiHwLowLevelWrite (8, Value, &AcpiGbl_FADT.XPm2ControlBlock);
8213446Smrj         break;
8223446Smrj 
8233446Smrj 
8243446Smrj     case ACPI_REGISTER_PM_TIMER:             /* 32-bit access */
8253446Smrj 
826*7851SDana.Myers@Sun.COM         Status = AcpiHwLowLevelWrite (32, Value, &AcpiGbl_FADT.XPmTimerBlock);
8273446Smrj         break;
8283446Smrj 
8293446Smrj 
8303446Smrj     case ACPI_REGISTER_SMI_COMMAND_BLOCK:    /* 8-bit access */
8313446Smrj 
8323446Smrj         /* SMI_CMD is currently always in IO space */
8333446Smrj 
834*7851SDana.Myers@Sun.COM         Status = AcpiOsWritePort (AcpiGbl_FADT.SmiCommand, Value, 8);
8353446Smrj         break;
8363446Smrj 
8373446Smrj 
8383446Smrj     default:
8393446Smrj         Status = AE_BAD_PARAMETER;
8403446Smrj         break;
8413446Smrj     }
8423446Smrj 
843*7851SDana.Myers@Sun.COM Exit:
8443446Smrj     return_ACPI_STATUS (Status);
8453446Smrj }
8463446Smrj 
8473446Smrj 
8483446Smrj /******************************************************************************
8493446Smrj  *
8503446Smrj  * FUNCTION:    AcpiHwLowLevelRead
8513446Smrj  *
8523446Smrj  * PARAMETERS:  Width               - 8, 16, or 32
8533446Smrj  *              Value               - Where the value is returned
8543446Smrj  *              Reg                 - GAS register structure
8553446Smrj  *
8563446Smrj  * RETURN:      Status
8573446Smrj  *
8583446Smrj  * DESCRIPTION: Read from either memory or IO space.
8593446Smrj  *
8603446Smrj  ******************************************************************************/
8613446Smrj 
8623446Smrj ACPI_STATUS
8633446Smrj AcpiHwLowLevelRead (
8643446Smrj     UINT32                  Width,
8653446Smrj     UINT32                  *Value,
8663446Smrj     ACPI_GENERIC_ADDRESS    *Reg)
8673446Smrj {
8683446Smrj     UINT64                  Address;
8693446Smrj     ACPI_STATUS             Status;
8703446Smrj 
8713446Smrj 
8723446Smrj     ACPI_FUNCTION_NAME (HwLowLevelRead);
8733446Smrj 
8743446Smrj 
8753446Smrj     /*
8763446Smrj      * Must have a valid pointer to a GAS structure, and
8773446Smrj      * a non-zero address within. However, don't return an error
8783446Smrj      * because the PM1A/B code must not fail if B isn't present.
8793446Smrj      */
8803446Smrj     if (!Reg)
8813446Smrj     {
8823446Smrj         return (AE_OK);
8833446Smrj     }
8843446Smrj 
8853446Smrj     /* Get a local copy of the address. Handles possible alignment issues */
8863446Smrj 
8873446Smrj     ACPI_MOVE_64_TO_64 (&Address, &Reg->Address);
888*7851SDana.Myers@Sun.COM     if (!Address)
8893446Smrj     {
8903446Smrj         return (AE_OK);
8913446Smrj     }
8923446Smrj     *Value = 0;
8933446Smrj 
8943446Smrj     /*
8953446Smrj      * Two address spaces supported: Memory or IO.
8963446Smrj      * PCI_Config is not supported here because the GAS struct is insufficient
8973446Smrj      */
898*7851SDana.Myers@Sun.COM     switch (Reg->SpaceId)
8993446Smrj     {
9003446Smrj     case ACPI_ADR_SPACE_SYSTEM_MEMORY:
9013446Smrj 
9023446Smrj         Status = AcpiOsReadMemory (
903*7851SDana.Myers@Sun.COM                     (ACPI_PHYSICAL_ADDRESS) Address, Value, Width);
9043446Smrj         break;
9053446Smrj 
9063446Smrj 
9073446Smrj     case ACPI_ADR_SPACE_SYSTEM_IO:
9083446Smrj 
909*7851SDana.Myers@Sun.COM         Status = AcpiOsReadPort ((ACPI_IO_ADDRESS) Address, Value, Width);
9103446Smrj         break;
9113446Smrj 
9123446Smrj 
9133446Smrj     default:
9143446Smrj         ACPI_ERROR ((AE_INFO,
915*7851SDana.Myers@Sun.COM             "Unsupported address space: %X", Reg->SpaceId));
9163446Smrj         return (AE_BAD_PARAMETER);
9173446Smrj     }
9183446Smrj 
9193446Smrj     ACPI_DEBUG_PRINT ((ACPI_DB_IO,
9203446Smrj         "Read:  %8.8X width %2d from %8.8X%8.8X (%s)\n",
921*7851SDana.Myers@Sun.COM         *Value, Width, ACPI_FORMAT_UINT64 (Address),
922*7851SDana.Myers@Sun.COM         AcpiUtGetRegionName (Reg->SpaceId)));
9233446Smrj 
9243446Smrj     return (Status);
9253446Smrj }
9263446Smrj 
9273446Smrj 
9283446Smrj /******************************************************************************
9293446Smrj  *
9303446Smrj  * FUNCTION:    AcpiHwLowLevelWrite
9313446Smrj  *
9323446Smrj  * PARAMETERS:  Width               - 8, 16, or 32
9333446Smrj  *              Value               - To be written
9343446Smrj  *              Reg                 - GAS register structure
9353446Smrj  *
9363446Smrj  * RETURN:      Status
9373446Smrj  *
9383446Smrj  * DESCRIPTION: Write to either memory or IO space.
9393446Smrj  *
9403446Smrj  ******************************************************************************/
9413446Smrj 
9423446Smrj ACPI_STATUS
9433446Smrj AcpiHwLowLevelWrite (
9443446Smrj     UINT32                  Width,
9453446Smrj     UINT32                  Value,
9463446Smrj     ACPI_GENERIC_ADDRESS    *Reg)
9473446Smrj {
9483446Smrj     UINT64                  Address;
9493446Smrj     ACPI_STATUS             Status;
9503446Smrj 
9513446Smrj 
9523446Smrj     ACPI_FUNCTION_NAME (HwLowLevelWrite);
9533446Smrj 
9543446Smrj 
9553446Smrj     /*
9563446Smrj      * Must have a valid pointer to a GAS structure, and
9573446Smrj      * a non-zero address within. However, don't return an error
9583446Smrj      * because the PM1A/B code must not fail if B isn't present.
9593446Smrj      */
9603446Smrj     if (!Reg)
9613446Smrj     {
9623446Smrj         return (AE_OK);
9633446Smrj     }
9643446Smrj 
9653446Smrj     /* Get a local copy of the address. Handles possible alignment issues */
9663446Smrj 
9673446Smrj     ACPI_MOVE_64_TO_64 (&Address, &Reg->Address);
968*7851SDana.Myers@Sun.COM     if (!Address)
9693446Smrj     {
9703446Smrj         return (AE_OK);
9713446Smrj     }
9723446Smrj 
9733446Smrj     /*
9743446Smrj      * Two address spaces supported: Memory or IO.
9753446Smrj      * PCI_Config is not supported here because the GAS struct is insufficient
9763446Smrj      */
977*7851SDana.Myers@Sun.COM     switch (Reg->SpaceId)
9783446Smrj     {
9793446Smrj     case ACPI_ADR_SPACE_SYSTEM_MEMORY:
9803446Smrj 
9813446Smrj         Status = AcpiOsWriteMemory (
982*7851SDana.Myers@Sun.COM                     (ACPI_PHYSICAL_ADDRESS) Address, Value, Width);
9833446Smrj         break;
9843446Smrj 
9853446Smrj 
9863446Smrj     case ACPI_ADR_SPACE_SYSTEM_IO:
9873446Smrj 
988*7851SDana.Myers@Sun.COM         Status = AcpiOsWritePort (
989*7851SDana.Myers@Sun.COM                     (ACPI_IO_ADDRESS) Address, Value, Width);
9903446Smrj         break;
9913446Smrj 
9923446Smrj 
9933446Smrj     default:
9943446Smrj         ACPI_ERROR ((AE_INFO,
995*7851SDana.Myers@Sun.COM             "Unsupported address space: %X", Reg->SpaceId));
9963446Smrj         return (AE_BAD_PARAMETER);
9973446Smrj     }
9983446Smrj 
9993446Smrj     ACPI_DEBUG_PRINT ((ACPI_DB_IO,
10003446Smrj         "Wrote: %8.8X width %2d   to %8.8X%8.8X (%s)\n",
1001*7851SDana.Myers@Sun.COM         Value, Width, ACPI_FORMAT_UINT64 (Address),
1002*7851SDana.Myers@Sun.COM         AcpiUtGetRegionName (Reg->SpaceId)));
10033446Smrj 
10043446Smrj     return (Status);
10053446Smrj }
1006