Home | History | Annotate | Line # | Download | only in hardware
      1 /*******************************************************************************
      2  *
      3  * Module Name: hwregs - Read/write access functions for the various ACPI
      4  *                       control and status registers.
      5  *
      6  ******************************************************************************/
      7 
      8 /******************************************************************************
      9  *
     10  * 1. Copyright Notice
     11  *
     12  * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
     13  * All rights reserved.
     14  *
     15  * 2. License
     16  *
     17  * 2.1. This is your license from Intel Corp. under its intellectual property
     18  * rights. You may have additional license terms from the party that provided
     19  * you this software, covering your right to use that party's intellectual
     20  * property rights.
     21  *
     22  * 2.2. Intel grants, free of charge, to any person ("Licensee") obtaining a
     23  * copy of the source code appearing in this file ("Covered Code") an
     24  * irrevocable, perpetual, worldwide license under Intel's copyrights in the
     25  * base code distributed originally by Intel ("Original Intel Code") to copy,
     26  * make derivatives, distribute, use and display any portion of the Covered
     27  * Code in any form, with the right to sublicense such rights; and
     28  *
     29  * 2.3. Intel grants Licensee a non-exclusive and non-transferable patent
     30  * license (with the right to sublicense), under only those claims of Intel
     31  * patents that are infringed by the Original Intel Code, to make, use, sell,
     32  * offer to sell, and import the Covered Code and derivative works thereof
     33  * solely to the minimum extent necessary to exercise the above copyright
     34  * license, and in no event shall the patent license extend to any additions
     35  * to or modifications of the Original Intel Code. No other license or right
     36  * is granted directly or by implication, estoppel or otherwise;
     37  *
     38  * The above copyright and patent license is granted only if the following
     39  * conditions are met:
     40  *
     41  * 3. Conditions
     42  *
     43  * 3.1. Redistribution of Source with Rights to Further Distribute Source.
     44  * Redistribution of source code of any substantial portion of the Covered
     45  * Code or modification with rights to further distribute source must include
     46  * the above Copyright Notice, the above License, this list of Conditions,
     47  * and the following Disclaimer and Export Compliance provision. In addition,
     48  * Licensee must cause all Covered Code to which Licensee contributes to
     49  * contain a file documenting the changes Licensee made to create that Covered
     50  * Code and the date of any change. Licensee must include in that file the
     51  * documentation of any changes made by any predecessor Licensee. Licensee
     52  * must include a prominent statement that the modification is derived,
     53  * directly or indirectly, from Original Intel Code.
     54  *
     55  * 3.2. Redistribution of Source with no Rights to Further Distribute Source.
     56  * Redistribution of source code of any substantial portion of the Covered
     57  * Code or modification without rights to further distribute source must
     58  * include the following Disclaimer and Export Compliance provision in the
     59  * documentation and/or other materials provided with distribution. In
     60  * addition, Licensee may not authorize further sublicense of source of any
     61  * portion of the Covered Code, and must include terms to the effect that the
     62  * license from Licensee to its licensee is limited to the intellectual
     63  * property embodied in the software Licensee provides to its licensee, and
     64  * not to intellectual property embodied in modifications its licensee may
     65  * make.
     66  *
     67  * 3.3. Redistribution of Executable. Redistribution in executable form of any
     68  * substantial portion of the Covered Code or modification must reproduce the
     69  * above Copyright Notice, and the following Disclaimer and Export Compliance
     70  * provision in the documentation and/or other materials provided with the
     71  * distribution.
     72  *
     73  * 3.4. Intel retains all right, title, and interest in and to the Original
     74  * Intel Code.
     75  *
     76  * 3.5. Neither the name Intel nor any other trademark owned or controlled by
     77  * Intel shall be used in advertising or otherwise to promote the sale, use or
     78  * other dealings in products derived from or relating to the Covered Code
     79  * without prior written authorization from Intel.
     80  *
     81  * 4. Disclaimer and Export Compliance
     82  *
     83  * 4.1. INTEL MAKES NO WARRANTY OF ANY KIND REGARDING ANY SOFTWARE PROVIDED
     84  * HERE. ANY SOFTWARE ORIGINATING FROM INTEL OR DERIVED FROM INTEL SOFTWARE
     85  * IS PROVIDED "AS IS," AND INTEL WILL NOT PROVIDE ANY SUPPORT, ASSISTANCE,
     86  * INSTALLATION, TRAINING OR OTHER SERVICES. INTEL WILL NOT PROVIDE ANY
     87  * UPDATES, ENHANCEMENTS OR EXTENSIONS. INTEL SPECIFICALLY DISCLAIMS ANY
     88  * IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT AND FITNESS FOR A
     89  * PARTICULAR PURPOSE.
     90  *
     91  * 4.2. IN NO EVENT SHALL INTEL HAVE ANY LIABILITY TO LICENSEE, ITS LICENSEES
     92  * OR ANY OTHER THIRD PARTY, FOR ANY LOST PROFITS, LOST DATA, LOSS OF USE OR
     93  * COSTS OF PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, OR FOR ANY INDIRECT,
     94  * SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THIS AGREEMENT, UNDER ANY
     95  * CAUSE OF ACTION OR THEORY OF LIABILITY, AND IRRESPECTIVE OF WHETHER INTEL
     96  * HAS ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES. THESE LIMITATIONS
     97  * SHALL APPLY NOTWITHSTANDING THE FAILURE OF THE ESSENTIAL PURPOSE OF ANY
     98  * LIMITED REMEDY.
     99  *
    100  * 4.3. Licensee shall not export, either directly or indirectly, any of this
    101  * software or system incorporating such software without first obtaining any
    102  * required license or other approval from the U. S. Department of Commerce or
    103  * any other agency or department of the United States Government. In the
    104  * event Licensee exports any such software from the United States or
    105  * re-exports any such software from a foreign destination, Licensee shall
    106  * ensure that the distribution and export/re-export of the software is in
    107  * compliance with all laws, regulations, orders, or other restrictions of the
    108  * U.S. Export Administration Regulations. Licensee agrees that neither it nor
    109  * any of its subsidiaries will export/re-export any technical data, process,
    110  * software, or service, directly or indirectly, to any country for which the
    111  * United States government or any agency thereof requires an export license,
    112  * other governmental approval, or letter of assurance, without first obtaining
    113  * such license, approval or letter.
    114  *
    115  *****************************************************************************
    116  *
    117  * Alternatively, you may choose to be licensed under the terms of the
    118  * following license:
    119  *
    120  * Redistribution and use in source and binary forms, with or without
    121  * modification, are permitted provided that the following conditions
    122  * are met:
    123  * 1. Redistributions of source code must retain the above copyright
    124  *    notice, this list of conditions, and the following disclaimer,
    125  *    without modification.
    126  * 2. Redistributions in binary form must reproduce at minimum a disclaimer
    127  *    substantially similar to the "NO WARRANTY" disclaimer below
    128  *    ("Disclaimer") and any redistribution must be conditioned upon
    129  *    including a substantially similar Disclaimer requirement for further
    130  *    binary redistribution.
    131  * 3. Neither the names of the above-listed copyright holders nor the names
    132  *    of any contributors may be used to endorse or promote products derived
    133  *    from this software without specific prior written permission.
    134  *
    135  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
    136  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
    137  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
    138  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
    139  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
    140  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
    141  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
    142  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
    143  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
    144  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
    145  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    146  *
    147  * Alternatively, you may choose to be licensed under the terms of the
    148  * GNU General Public License ("GPL") version 2 as published by the Free
    149  * Software Foundation.
    150  *
    151  *****************************************************************************/
    152 
    153 #include "acpi.h"
    154 #include "accommon.h"
    155 #include "acevents.h"
    156 
    157 #define _COMPONENT          ACPI_HARDWARE
    158         ACPI_MODULE_NAME    ("hwregs")
    159 
    160 
    161 #if (!ACPI_REDUCED_HARDWARE)
    162 
    163 /* Local Prototypes */
    164 
    165 static UINT8
    166 AcpiHwGetAccessBitWidth (
    167     UINT64                  Address,
    168     ACPI_GENERIC_ADDRESS    *Reg,
    169     UINT8                   MaxBitWidth);
    170 
    171 static ACPI_STATUS
    172 AcpiHwReadMultiple (
    173     UINT32                  *Value,
    174     ACPI_GENERIC_ADDRESS    *RegisterA,
    175     ACPI_GENERIC_ADDRESS    *RegisterB);
    176 
    177 static ACPI_STATUS
    178 AcpiHwWriteMultiple (
    179     UINT32                  Value,
    180     ACPI_GENERIC_ADDRESS    *RegisterA,
    181     ACPI_GENERIC_ADDRESS    *RegisterB);
    182 
    183 #endif /* !ACPI_REDUCED_HARDWARE */
    184 
    185 
    186 /******************************************************************************
    187  *
    188  * FUNCTION:    AcpiHwGetAccessBitWidth
    189  *
    190  * PARAMETERS:  Address             - GAS register address
    191  *              Reg                 - GAS register structure
    192  *              MaxBitWidth         - Max BitWidth supported (32 or 64)
    193  *
    194  * RETURN:      Status
    195  *
    196  * DESCRIPTION: Obtain optimal access bit width
    197  *
    198  ******************************************************************************/
    199 
    200 static UINT8
    201 AcpiHwGetAccessBitWidth (
    202     UINT64                  Address,
    203     ACPI_GENERIC_ADDRESS    *Reg,
    204     UINT8                   MaxBitWidth)
    205 {
    206     UINT8                   AccessBitWidth;
    207 
    208 
    209     /*
    210      * GAS format "register", used by FADT:
    211      *  1. Detected if BitOffset is 0 and BitWidth is 8/16/32/64;
    212      *  2. AccessSize field is ignored and BitWidth field is used for
    213      *     determining the boundary of the IO accesses.
    214      * GAS format "region", used by APEI registers:
    215      *  1. Detected if BitOffset is not 0 or BitWidth is not 8/16/32/64;
    216      *  2. AccessSize field is used for determining the boundary of the
    217      *     IO accesses;
    218      *  3. BitOffset/BitWidth fields are used to describe the "region".
    219      *
    220      * Note: This algorithm assumes that the "Address" fields should always
    221      *       contain aligned values.
    222      */
    223     if (!Reg->BitOffset && Reg->BitWidth &&
    224         ACPI_IS_POWER_OF_TWO (Reg->BitWidth) &&
    225         ACPI_IS_ALIGNED (Reg->BitWidth, 8))
    226     {
    227         AccessBitWidth = Reg->BitWidth;
    228     }
    229     else if (Reg->AccessWidth)
    230     {
    231         AccessBitWidth = ACPI_ACCESS_BIT_WIDTH (Reg->AccessWidth);
    232     }
    233     else
    234     {
    235         AccessBitWidth = ACPI_ROUND_UP_POWER_OF_TWO_8 (
    236             Reg->BitOffset + Reg->BitWidth);
    237         if (AccessBitWidth <= 8)
    238         {
    239             AccessBitWidth = 8;
    240         }
    241         else
    242         {
    243             while (!ACPI_IS_ALIGNED (Address, AccessBitWidth >> 3))
    244             {
    245                 AccessBitWidth >>= 1;
    246             }
    247         }
    248     }
    249 
    250     /* Maximum IO port access bit width is 32 */
    251 
    252     if (Reg->SpaceId == ACPI_ADR_SPACE_SYSTEM_IO)
    253     {
    254         MaxBitWidth = 32;
    255     }
    256 
    257     /*
    258      * Return access width according to the requested maximum access bit width,
    259      * as the caller should know the format of the register and may enforce
    260      * a 32-bit accesses.
    261      */
    262     if (AccessBitWidth < MaxBitWidth)
    263     {
    264         return (AccessBitWidth);
    265     }
    266     return (MaxBitWidth);
    267 }
    268 
    269 
    270 /******************************************************************************
    271  *
    272  * FUNCTION:    AcpiHwValidateRegister
    273  *
    274  * PARAMETERS:  Reg                 - GAS register structure
    275  *              MaxBitWidth         - Max BitWidth supported (32 or 64)
    276  *              Address             - Pointer to where the gas->address
    277  *                                    is returned
    278  *
    279  * RETURN:      Status
    280  *
    281  * DESCRIPTION: Validate the contents of a GAS register. Checks the GAS
    282  *              pointer, Address, SpaceId, BitWidth, and BitOffset.
    283  *
    284  ******************************************************************************/
    285 
    286 ACPI_STATUS
    287 AcpiHwValidateRegister (
    288     ACPI_GENERIC_ADDRESS    *Reg,
    289     UINT8                   MaxBitWidth,
    290     UINT64                  *Address)
    291 {
    292     UINT8                   BitWidth;
    293     UINT8                   AccessWidth;
    294 
    295 
    296     /* Must have a valid pointer to a GAS structure */
    297 
    298     if (!Reg)
    299     {
    300         return (AE_BAD_PARAMETER);
    301     }
    302 
    303     /*
    304      * Copy the target address. This handles possible alignment issues.
    305      * Address must not be null. A null address also indicates an optional
    306      * ACPI register that is not supported, so no error message.
    307      */
    308     ACPI_MOVE_64_TO_64 (Address, &Reg->Address);
    309     if (!(*Address))
    310     {
    311         return (AE_BAD_ADDRESS);
    312     }
    313 
    314     /* Validate the SpaceID */
    315 
    316     if ((Reg->SpaceId != ACPI_ADR_SPACE_SYSTEM_MEMORY) &&
    317         (Reg->SpaceId != ACPI_ADR_SPACE_SYSTEM_IO))
    318     {
    319         ACPI_ERROR ((AE_INFO,
    320             "Unsupported address space: 0x%X", Reg->SpaceId));
    321         return (AE_SUPPORT);
    322     }
    323 
    324     /* Validate the AccessWidth */
    325 
    326     if (Reg->AccessWidth > 4)
    327     {
    328         ACPI_ERROR ((AE_INFO,
    329             "Unsupported register access width: 0x%X", Reg->AccessWidth));
    330         return (AE_SUPPORT);
    331     }
    332 
    333     /* Validate the BitWidth, convert AccessWidth into number of bits */
    334 
    335     AccessWidth = AcpiHwGetAccessBitWidth (*Address, Reg, MaxBitWidth);
    336     BitWidth = ACPI_ROUND_UP (Reg->BitOffset + Reg->BitWidth, AccessWidth);
    337     if (MaxBitWidth < BitWidth)
    338     {
    339         ACPI_WARNING ((AE_INFO,
    340             "Requested bit width 0x%X is smaller than register bit width 0x%X",
    341             MaxBitWidth, BitWidth));
    342         return (AE_SUPPORT);
    343     }
    344 
    345     return (AE_OK);
    346 }
    347 
    348 
    349 /******************************************************************************
    350  *
    351  * FUNCTION:    AcpiHwRead
    352  *
    353  * PARAMETERS:  Value               - Where the value is returned
    354  *              Reg                 - GAS register structure
    355  *
    356  * RETURN:      Status
    357  *
    358  * DESCRIPTION: Read from either memory or IO space. This is a 64-bit max
    359  *              version of AcpiRead.
    360  *
    361  * LIMITATIONS: <These limitations also apply to AcpiHwWrite>
    362  *      SpaceID must be SystemMemory or SystemIO.
    363  *
    364  ******************************************************************************/
    365 
    366 ACPI_STATUS
    367 AcpiHwRead (
    368     UINT64                  *Value,
    369     ACPI_GENERIC_ADDRESS    *Reg)
    370 {
    371     UINT64                  Address;
    372     UINT8                   AccessWidth;
    373     UINT32                  BitWidth;
    374     UINT8                   BitOffset;
    375     UINT64                  Value64;
    376     UINT32                  Value32;
    377     UINT8                   Index;
    378     ACPI_STATUS             Status;
    379 
    380 
    381     ACPI_FUNCTION_NAME (HwRead);
    382 
    383 
    384     /* Validate contents of the GAS register */
    385 
    386     Status = AcpiHwValidateRegister (Reg, 64, &Address);
    387     if (ACPI_FAILURE (Status))
    388     {
    389         return (Status);
    390     }
    391 
    392     /*
    393      * Initialize entire 64-bit return value to zero, convert AccessWidth
    394      * into number of bits based
    395      */
    396     *Value = 0;
    397     AccessWidth = AcpiHwGetAccessBitWidth (Address, Reg, 64);
    398     BitWidth = Reg->BitOffset + Reg->BitWidth;
    399     BitOffset = Reg->BitOffset;
    400 
    401     /*
    402      * Two address spaces supported: Memory or IO. PCI_Config is
    403      * not supported here because the GAS structure is insufficient
    404      */
    405     Index = 0;
    406     while (BitWidth)
    407     {
    408         if (BitOffset >= AccessWidth)
    409         {
    410             Value64 = 0;
    411             BitOffset -= AccessWidth;
    412         }
    413         else
    414         {
    415             if (Reg->SpaceId == ACPI_ADR_SPACE_SYSTEM_MEMORY)
    416             {
    417                 Status = AcpiOsReadMemory ((ACPI_PHYSICAL_ADDRESS)
    418                     Address + Index * ACPI_DIV_8 (AccessWidth),
    419                     &Value64, AccessWidth);
    420             }
    421             else /* ACPI_ADR_SPACE_SYSTEM_IO, validated earlier */
    422             {
    423                 Status = AcpiHwReadPort ((ACPI_IO_ADDRESS)
    424                     Address + Index * ACPI_DIV_8 (AccessWidth),
    425                     &Value32, AccessWidth);
    426                 Value64 = (UINT64) Value32;
    427             }
    428         }
    429 
    430         /*
    431          * Use offset style bit writes because "Index * AccessWidth" is
    432          * ensured to be less than 64-bits by AcpiHwValidateRegister().
    433          */
    434         ACPI_SET_BITS (Value, Index * AccessWidth,
    435             ACPI_MASK_BITS_ABOVE_64 (AccessWidth), Value64);
    436 
    437         BitWidth -= BitWidth > AccessWidth ? AccessWidth : BitWidth;
    438         Index++;
    439     }
    440 
    441     ACPI_DEBUG_PRINT ((ACPI_DB_IO,
    442         "Read:  %8.8X%8.8X width %2d from %8.8X%8.8X (%s)\n",
    443         ACPI_FORMAT_UINT64 (*Value), AccessWidth,
    444         ACPI_FORMAT_UINT64 (Address), AcpiUtGetRegionName (Reg->SpaceId)));
    445 
    446     return (Status);
    447 }
    448 
    449 
    450 /******************************************************************************
    451  *
    452  * FUNCTION:    AcpiHwWrite
    453  *
    454  * PARAMETERS:  Value               - Value to be written
    455  *              Reg                 - GAS register structure
    456  *
    457  * RETURN:      Status
    458  *
    459  * DESCRIPTION: Write to either memory or IO space. This is a 64-bit max
    460  *              version of AcpiWrite.
    461  *
    462  ******************************************************************************/
    463 
    464 ACPI_STATUS
    465 AcpiHwWrite (
    466     UINT64                  Value,
    467     ACPI_GENERIC_ADDRESS    *Reg)
    468 {
    469     UINT64                  Address;
    470     UINT8                   AccessWidth;
    471     UINT32                  BitWidth;
    472     UINT8                   BitOffset;
    473     UINT64                  Value64;
    474     UINT8                   Index;
    475     ACPI_STATUS             Status;
    476 
    477 
    478     ACPI_FUNCTION_NAME (HwWrite);
    479 
    480 
    481     /* Validate contents of the GAS register */
    482 
    483     Status = AcpiHwValidateRegister (Reg, 64, &Address);
    484     if (ACPI_FAILURE (Status))
    485     {
    486         return (Status);
    487     }
    488 
    489     /* Convert AccessWidth into number of bits based */
    490 
    491     AccessWidth = AcpiHwGetAccessBitWidth (Address, Reg, 64);
    492     BitWidth = Reg->BitOffset + Reg->BitWidth;
    493     BitOffset = Reg->BitOffset;
    494 
    495     /*
    496      * Two address spaces supported: Memory or IO. PCI_Config is
    497      * not supported here because the GAS structure is insufficient
    498      */
    499     Index = 0;
    500     while (BitWidth)
    501     {
    502         /*
    503          * Use offset style bit reads because "Index * AccessWidth" is
    504          * ensured to be less than 64-bits by AcpiHwValidateRegister().
    505          */
    506         Value64 = ACPI_GET_BITS (&Value, Index * AccessWidth,
    507             ACPI_MASK_BITS_ABOVE_64 (AccessWidth));
    508 
    509         if (BitOffset >= AccessWidth)
    510         {
    511             BitOffset -= AccessWidth;
    512         }
    513         else
    514         {
    515             if (Reg->SpaceId == ACPI_ADR_SPACE_SYSTEM_MEMORY)
    516             {
    517                 Status = AcpiOsWriteMemory ((ACPI_PHYSICAL_ADDRESS)
    518                     Address + Index * ACPI_DIV_8 (AccessWidth),
    519                     Value64, AccessWidth);
    520             }
    521             else /* ACPI_ADR_SPACE_SYSTEM_IO, validated earlier */
    522             {
    523                 Status = AcpiHwWritePort ((ACPI_IO_ADDRESS)
    524                     Address + Index * ACPI_DIV_8 (AccessWidth),
    525                     (UINT32) Value64, AccessWidth);
    526             }
    527         }
    528 
    529         /*
    530          * Index * AccessWidth is ensured to be less than 32-bits by
    531          * AcpiHwValidateRegister().
    532          */
    533         BitWidth -= BitWidth > AccessWidth ? AccessWidth : BitWidth;
    534         Index++;
    535     }
    536 
    537     ACPI_DEBUG_PRINT ((ACPI_DB_IO,
    538         "Wrote: %8.8X%8.8X width %2d   to %8.8X%8.8X (%s)\n",
    539         ACPI_FORMAT_UINT64 (Value), AccessWidth,
    540         ACPI_FORMAT_UINT64 (Address), AcpiUtGetRegionName (Reg->SpaceId)));
    541 
    542     return (Status);
    543 }
    544 
    545 
    546 #if (!ACPI_REDUCED_HARDWARE)
    547 /*******************************************************************************
    548  *
    549  * FUNCTION:    AcpiHwClearAcpiStatus
    550  *
    551  * PARAMETERS:  None
    552  *
    553  * RETURN:      Status
    554  *
    555  * DESCRIPTION: Clears all fixed and general purpose status bits
    556  *
    557  ******************************************************************************/
    558 
    559 ACPI_STATUS
    560 AcpiHwClearAcpiStatus (
    561     void)
    562 {
    563     ACPI_STATUS             Status;
    564     ACPI_CPU_FLAGS          LockFlags = 0;
    565 
    566 
    567     ACPI_FUNCTION_TRACE (HwClearAcpiStatus);
    568 
    569 
    570     ACPI_DEBUG_PRINT ((ACPI_DB_IO, "About to write %04X to %8.8X%8.8X\n",
    571         ACPI_BITMASK_ALL_FIXED_STATUS,
    572         ACPI_FORMAT_UINT64 (AcpiGbl_XPm1aStatus.Address)));
    573 
    574     LockFlags = AcpiOsAcquireLock (AcpiGbl_HardwareLock);
    575 
    576     /* Clear the fixed events in PM1 A/B */
    577 
    578     Status = AcpiHwRegisterWrite (ACPI_REGISTER_PM1_STATUS,
    579         ACPI_BITMASK_ALL_FIXED_STATUS);
    580 
    581     AcpiOsReleaseLock (AcpiGbl_HardwareLock, LockFlags);
    582 
    583     if (ACPI_FAILURE (Status))
    584     {
    585         goto Exit;
    586     }
    587 
    588     /* Clear the GPE Bits in all GPE registers in all GPE blocks */
    589 
    590     Status = AcpiEvWalkGpeList (AcpiHwClearGpeBlock, NULL);
    591 
    592 Exit:
    593     return_ACPI_STATUS (Status);
    594 }
    595 
    596 
    597 /*******************************************************************************
    598  *
    599  * FUNCTION:    AcpiHwGetBitRegisterInfo
    600  *
    601  * PARAMETERS:  RegisterId          - Index of ACPI Register to access
    602  *
    603  * RETURN:      The bitmask to be used when accessing the register
    604  *
    605  * DESCRIPTION: Map RegisterId into a register bitmask.
    606  *
    607  ******************************************************************************/
    608 
    609 ACPI_BIT_REGISTER_INFO *
    610 AcpiHwGetBitRegisterInfo (
    611     UINT32                  RegisterId)
    612 {
    613     ACPI_FUNCTION_ENTRY ();
    614 
    615 
    616     if (RegisterId > ACPI_BITREG_MAX)
    617     {
    618         ACPI_ERROR ((AE_INFO, "Invalid BitRegister ID: 0x%X", RegisterId));
    619         return (NULL);
    620     }
    621 
    622     return (&AcpiGbl_BitRegisterInfo[RegisterId]);
    623 }
    624 
    625 
    626 /******************************************************************************
    627  *
    628  * FUNCTION:    AcpiHwWritePm1Control
    629  *
    630  * PARAMETERS:  Pm1aControl         - Value to be written to PM1A control
    631  *              Pm1bControl         - Value to be written to PM1B control
    632  *
    633  * RETURN:      Status
    634  *
    635  * DESCRIPTION: Write the PM1 A/B control registers. These registers are
    636  *              different than the PM1 A/B status and enable registers
    637  *              in that different values can be written to the A/B registers.
    638  *              Most notably, the SLP_TYP bits can be different, as per the
    639  *              values returned from the _Sx predefined methods.
    640  *
    641  ******************************************************************************/
    642 
    643 ACPI_STATUS
    644 AcpiHwWritePm1Control (
    645     UINT32                  Pm1aControl,
    646     UINT32                  Pm1bControl)
    647 {
    648     ACPI_STATUS             Status;
    649 
    650 
    651     ACPI_FUNCTION_TRACE (HwWritePm1Control);
    652 
    653 
    654     Status = AcpiHwWrite (Pm1aControl, &AcpiGbl_FADT.XPm1aControlBlock);
    655     if (ACPI_FAILURE (Status))
    656     {
    657         return_ACPI_STATUS (Status);
    658     }
    659 
    660     if (AcpiGbl_FADT.XPm1bControlBlock.Address)
    661     {
    662         Status = AcpiHwWrite (Pm1bControl, &AcpiGbl_FADT.XPm1bControlBlock);
    663     }
    664     return_ACPI_STATUS (Status);
    665 }
    666 
    667 
    668 /******************************************************************************
    669  *
    670  * FUNCTION:    AcpiHwRegisterRead
    671  *
    672  * PARAMETERS:  RegisterId          - ACPI Register ID
    673  *              ReturnValue         - Where the register value is returned
    674  *
    675  * RETURN:      Status and the value read.
    676  *
    677  * DESCRIPTION: Read from the specified ACPI register
    678  *
    679  ******************************************************************************/
    680 
    681 ACPI_STATUS
    682 AcpiHwRegisterRead (
    683     UINT32                  RegisterId,
    684     UINT32                  *ReturnValue)
    685 {
    686     UINT32                  Value = 0;
    687     UINT64                  Value64;
    688     ACPI_STATUS             Status;
    689 
    690 
    691     ACPI_FUNCTION_TRACE (HwRegisterRead);
    692 
    693 
    694     switch (RegisterId)
    695     {
    696     case ACPI_REGISTER_PM1_STATUS:           /* PM1 A/B: 16-bit access each */
    697 
    698         Status = AcpiHwReadMultiple (&Value,
    699             &AcpiGbl_XPm1aStatus,
    700             &AcpiGbl_XPm1bStatus);
    701         break;
    702 
    703     case ACPI_REGISTER_PM1_ENABLE:           /* PM1 A/B: 16-bit access each */
    704 
    705         Status = AcpiHwReadMultiple (&Value,
    706             &AcpiGbl_XPm1aEnable,
    707             &AcpiGbl_XPm1bEnable);
    708         break;
    709 
    710     case ACPI_REGISTER_PM1_CONTROL:          /* PM1 A/B: 16-bit access each */
    711 
    712         Status = AcpiHwReadMultiple (&Value,
    713             &AcpiGbl_FADT.XPm1aControlBlock,
    714             &AcpiGbl_FADT.XPm1bControlBlock);
    715 
    716         /*
    717          * Zero the write-only bits. From the ACPI specification, "Hardware
    718          * Write-Only Bits": "Upon reads to registers with write-only bits,
    719          * software masks out all write-only bits."
    720          */
    721         Value &= ~ACPI_PM1_CONTROL_WRITEONLY_BITS;
    722         break;
    723 
    724     case ACPI_REGISTER_PM2_CONTROL:          /* 8-bit access */
    725 
    726         Status = AcpiHwRead (&Value64, &AcpiGbl_FADT.XPm2ControlBlock);
    727         if (ACPI_SUCCESS (Status))
    728         {
    729             Value = (UINT32) Value64;
    730         }
    731         break;
    732 
    733     case ACPI_REGISTER_PM_TIMER:             /* 32-bit access */
    734 
    735         Status = AcpiHwRead (&Value64, &AcpiGbl_FADT.XPmTimerBlock);
    736         if (ACPI_SUCCESS (Status))
    737         {
    738             Value = (UINT32) Value64;
    739         }
    740 
    741         break;
    742 
    743     case ACPI_REGISTER_SMI_COMMAND_BLOCK:    /* 8-bit access */
    744 
    745         Status = AcpiHwReadPort (AcpiGbl_FADT.SmiCommand, &Value, 8);
    746         break;
    747 
    748     default:
    749 
    750         ACPI_ERROR ((AE_INFO, "Unknown Register ID: 0x%X",
    751             RegisterId));
    752         Status = AE_BAD_PARAMETER;
    753         break;
    754     }
    755 
    756     if (ACPI_SUCCESS (Status))
    757     {
    758         *ReturnValue = (UINT32) Value;
    759     }
    760 
    761     return_ACPI_STATUS (Status);
    762 }
    763 
    764 
    765 /******************************************************************************
    766  *
    767  * FUNCTION:    AcpiHwRegisterWrite
    768  *
    769  * PARAMETERS:  RegisterId          - ACPI Register ID
    770  *              Value               - The value to write
    771  *
    772  * RETURN:      Status
    773  *
    774  * DESCRIPTION: Write to the specified ACPI register
    775  *
    776  * NOTE: In accordance with the ACPI specification, this function automatically
    777  * preserves the value of the following bits, meaning that these bits cannot be
    778  * changed via this interface:
    779  *
    780  * PM1_CONTROL[0] = SCI_EN
    781  * PM1_CONTROL[9]
    782  * PM1_STATUS[11]
    783  *
    784  * ACPI References:
    785  * 1) Hardware Ignored Bits: When software writes to a register with ignored
    786  *      bit fields, it preserves the ignored bit fields
    787  * 2) SCI_EN: OSPM always preserves this bit position
    788  *
    789  ******************************************************************************/
    790 
    791 ACPI_STATUS
    792 AcpiHwRegisterWrite (
    793     UINT32                  RegisterId,
    794     UINT32                  Value)
    795 {
    796     ACPI_STATUS             Status;
    797     UINT32                  ReadValue;
    798     UINT64                  ReadValue64;
    799 
    800 
    801     ACPI_FUNCTION_TRACE (HwRegisterWrite);
    802 
    803 
    804     switch (RegisterId)
    805     {
    806     case ACPI_REGISTER_PM1_STATUS:           /* PM1 A/B: 16-bit access each */
    807         /*
    808          * Handle the "ignored" bit in PM1 Status. According to the ACPI
    809          * specification, ignored bits are to be preserved when writing.
    810          * Normally, this would mean a read/modify/write sequence. However,
    811          * preserving a bit in the status register is different. Writing a
    812          * one clears the status, and writing a zero preserves the status.
    813          * Therefore, we must always write zero to the ignored bit.
    814          *
    815          * This behavior is clarified in the ACPI 4.0 specification.
    816          */
    817         Value &= ~ACPI_PM1_STATUS_PRESERVED_BITS;
    818 
    819         Status = AcpiHwWriteMultiple (Value,
    820             &AcpiGbl_XPm1aStatus,
    821             &AcpiGbl_XPm1bStatus);
    822         break;
    823 
    824     case ACPI_REGISTER_PM1_ENABLE:           /* PM1 A/B: 16-bit access each */
    825 
    826         Status = AcpiHwWriteMultiple (Value,
    827             &AcpiGbl_XPm1aEnable,
    828             &AcpiGbl_XPm1bEnable);
    829         break;
    830 
    831     case ACPI_REGISTER_PM1_CONTROL:          /* PM1 A/B: 16-bit access each */
    832         /*
    833          * Perform a read first to preserve certain bits (per ACPI spec)
    834          * Note: This includes SCI_EN, we never want to change this bit
    835          */
    836         Status = AcpiHwReadMultiple (&ReadValue,
    837             &AcpiGbl_FADT.XPm1aControlBlock,
    838             &AcpiGbl_FADT.XPm1bControlBlock);
    839         if (ACPI_FAILURE (Status))
    840         {
    841             goto Exit;
    842         }
    843 
    844         /* Insert the bits to be preserved */
    845 
    846         ACPI_INSERT_BITS (Value, ACPI_PM1_CONTROL_PRESERVED_BITS, ReadValue);
    847 
    848         /* Now we can write the data */
    849 
    850         Status = AcpiHwWriteMultiple (Value,
    851             &AcpiGbl_FADT.XPm1aControlBlock,
    852             &AcpiGbl_FADT.XPm1bControlBlock);
    853         break;
    854 
    855     case ACPI_REGISTER_PM2_CONTROL:          /* 8-bit access */
    856         /*
    857          * For control registers, all reserved bits must be preserved,
    858          * as per the ACPI spec.
    859          */
    860         Status = AcpiHwRead (&ReadValue64, &AcpiGbl_FADT.XPm2ControlBlock);
    861         if (ACPI_FAILURE (Status))
    862         {
    863             goto Exit;
    864         }
    865         ReadValue = (UINT32) ReadValue64;
    866 
    867         /* Insert the bits to be preserved */
    868 
    869         ACPI_INSERT_BITS (Value, ACPI_PM2_CONTROL_PRESERVED_BITS, ReadValue);
    870 
    871         Status = AcpiHwWrite (Value, &AcpiGbl_FADT.XPm2ControlBlock);
    872         break;
    873 
    874     case ACPI_REGISTER_PM_TIMER:             /* 32-bit access */
    875 
    876         Status = AcpiHwWrite (Value, &AcpiGbl_FADT.XPmTimerBlock);
    877         break;
    878 
    879     case ACPI_REGISTER_SMI_COMMAND_BLOCK:    /* 8-bit access */
    880 
    881         /* SMI_CMD is currently always in IO space */
    882 
    883         Status = AcpiHwWritePort (AcpiGbl_FADT.SmiCommand, Value, 8);
    884         break;
    885 
    886     default:
    887 
    888         ACPI_ERROR ((AE_INFO, "Unknown Register ID: 0x%X",
    889             RegisterId));
    890         Status = AE_BAD_PARAMETER;
    891         break;
    892     }
    893 
    894 Exit:
    895     return_ACPI_STATUS (Status);
    896 }
    897 
    898 
    899 /******************************************************************************
    900  *
    901  * FUNCTION:    AcpiHwReadMultiple
    902  *
    903  * PARAMETERS:  Value               - Where the register value is returned
    904  *              RegisterA           - First ACPI register (required)
    905  *              RegisterB           - Second ACPI register (optional)
    906  *
    907  * RETURN:      Status
    908  *
    909  * DESCRIPTION: Read from the specified two-part ACPI register (such as PM1 A/B)
    910  *
    911  ******************************************************************************/
    912 
    913 static ACPI_STATUS
    914 AcpiHwReadMultiple (
    915     UINT32                  *Value,
    916     ACPI_GENERIC_ADDRESS    *RegisterA,
    917     ACPI_GENERIC_ADDRESS    *RegisterB)
    918 {
    919     UINT32                  ValueA = 0;
    920     UINT32                  ValueB = 0;
    921     UINT64                  Value64;
    922     ACPI_STATUS             Status;
    923 
    924 
    925     /* The first register is always required */
    926 
    927     Status = AcpiHwRead (&Value64, RegisterA);
    928     if (ACPI_FAILURE (Status))
    929     {
    930         return (Status);
    931     }
    932     ValueA = (UINT32) Value64;
    933 
    934     /* Second register is optional */
    935 
    936     if (RegisterB->Address)
    937     {
    938         Status = AcpiHwRead (&Value64, RegisterB);
    939         if (ACPI_FAILURE (Status))
    940         {
    941             return (Status);
    942         }
    943         ValueB = (UINT32) Value64;
    944     }
    945 
    946     /*
    947      * OR the two return values together. No shifting or masking is necessary,
    948      * because of how the PM1 registers are defined in the ACPI specification:
    949      *
    950      * "Although the bits can be split between the two register blocks (each
    951      * register block has a unique pointer within the FADT), the bit positions
    952      * are maintained. The register block with unimplemented bits (that is,
    953      * those implemented in the other register block) always returns zeros,
    954      * and writes have no side effects"
    955      */
    956     *Value = (ValueA | ValueB);
    957     return (AE_OK);
    958 }
    959 
    960 
    961 /******************************************************************************
    962  *
    963  * FUNCTION:    AcpiHwWriteMultiple
    964  *
    965  * PARAMETERS:  Value               - The value to write
    966  *              RegisterA           - First ACPI register (required)
    967  *              RegisterB           - Second ACPI register (optional)
    968  *
    969  * RETURN:      Status
    970  *
    971  * DESCRIPTION: Write to the specified two-part ACPI register (such as PM1 A/B)
    972  *
    973  ******************************************************************************/
    974 
    975 static ACPI_STATUS
    976 AcpiHwWriteMultiple (
    977     UINT32                  Value,
    978     ACPI_GENERIC_ADDRESS    *RegisterA,
    979     ACPI_GENERIC_ADDRESS    *RegisterB)
    980 {
    981     ACPI_STATUS             Status;
    982 
    983 
    984     /* The first register is always required */
    985 
    986     Status = AcpiHwWrite (Value, RegisterA);
    987     if (ACPI_FAILURE (Status))
    988     {
    989         return (Status);
    990     }
    991 
    992     /*
    993      * Second register is optional
    994      *
    995      * No bit shifting or clearing is necessary, because of how the PM1
    996      * registers are defined in the ACPI specification:
    997      *
    998      * "Although the bits can be split between the two register blocks (each
    999      * register block has a unique pointer within the FADT), the bit positions
   1000      * are maintained. The register block with unimplemented bits (that is,
   1001      * those implemented in the other register block) always returns zeros,
   1002      * and writes have no side effects"
   1003      */
   1004     if (RegisterB->Address)
   1005     {
   1006         Status = AcpiHwWrite (Value, RegisterB);
   1007     }
   1008 
   1009     return (Status);
   1010 }
   1011 
   1012 #endif /* !ACPI_REDUCED_HARDWARE */
   1013