Back to home page

LXR

 
 

    


File indexing completed on 2025-05-11 08:24:02

0001 /*******************************************************************************
0002  *
0003  * Module Name: hwregs - Read/write access functions for the various ACPI
0004  *                       control and status registers.
0005  *
0006  ******************************************************************************/
0007 
0008 /******************************************************************************
0009  *
0010  * 1. Copyright Notice
0011  *
0012  * Some or all of this work - Copyright (c) 1999 - 2024, Intel Corp.
0013  * All rights reserved.
0014  *
0015  * 2. License
0016  *
0017  * 2.1. This is your license from Intel Corp. under its intellectual property
0018  * rights. You may have additional license terms from the party that provided
0019  * you this software, covering your right to use that party's intellectual
0020  * property rights.
0021  *
0022  * 2.2. Intel grants, free of charge, to any person ("Licensee") obtaining a
0023  * copy of the source code appearing in this file ("Covered Code") an
0024  * irrevocable, perpetual, worldwide license under Intel's copyrights in the
0025  * base code distributed originally by Intel ("Original Intel Code") to copy,
0026  * make derivatives, distribute, use and display any portion of the Covered
0027  * Code in any form, with the right to sublicense such rights; and
0028  *
0029  * 2.3. Intel grants Licensee a non-exclusive and non-transferable patent
0030  * license (with the right to sublicense), under only those claims of Intel
0031  * patents that are infringed by the Original Intel Code, to make, use, sell,
0032  * offer to sell, and import the Covered Code and derivative works thereof
0033  * solely to the minimum extent necessary to exercise the above copyright
0034  * license, and in no event shall the patent license extend to any additions
0035  * to or modifications of the Original Intel Code. No other license or right
0036  * is granted directly or by implication, estoppel or otherwise;
0037  *
0038  * The above copyright and patent license is granted only if the following
0039  * conditions are met:
0040  *
0041  * 3. Conditions
0042  *
0043  * 3.1. Redistribution of Source with Rights to Further Distribute Source.
0044  * Redistribution of source code of any substantial portion of the Covered
0045  * Code or modification with rights to further distribute source must include
0046  * the above Copyright Notice, the above License, this list of Conditions,
0047  * and the following Disclaimer and Export Compliance provision. In addition,
0048  * Licensee must cause all Covered Code to which Licensee contributes to
0049  * contain a file documenting the changes Licensee made to create that Covered
0050  * Code and the date of any change. Licensee must include in that file the
0051  * documentation of any changes made by any predecessor Licensee. Licensee
0052  * must include a prominent statement that the modification is derived,
0053  * directly or indirectly, from Original Intel Code.
0054  *
0055  * 3.2. Redistribution of Source with no Rights to Further Distribute Source.
0056  * Redistribution of source code of any substantial portion of the Covered
0057  * Code or modification without rights to further distribute source must
0058  * include the following Disclaimer and Export Compliance provision in the
0059  * documentation and/or other materials provided with distribution. In
0060  * addition, Licensee may not authorize further sublicense of source of any
0061  * portion of the Covered Code, and must include terms to the effect that the
0062  * license from Licensee to its licensee is limited to the intellectual
0063  * property embodied in the software Licensee provides to its licensee, and
0064  * not to intellectual property embodied in modifications its licensee may
0065  * make.
0066  *
0067  * 3.3. Redistribution of Executable. Redistribution in executable form of any
0068  * substantial portion of the Covered Code or modification must reproduce the
0069  * above Copyright Notice, and the following Disclaimer and Export Compliance
0070  * provision in the documentation and/or other materials provided with the
0071  * distribution.
0072  *
0073  * 3.4. Intel retains all right, title, and interest in and to the Original
0074  * Intel Code.
0075  *
0076  * 3.5. Neither the name Intel nor any other trademark owned or controlled by
0077  * Intel shall be used in advertising or otherwise to promote the sale, use or
0078  * other dealings in products derived from or relating to the Covered Code
0079  * without prior written authorization from Intel.
0080  *
0081  * 4. Disclaimer and Export Compliance
0082  *
0083  * 4.1. INTEL MAKES NO WARRANTY OF ANY KIND REGARDING ANY SOFTWARE PROVIDED
0084  * HERE. ANY SOFTWARE ORIGINATING FROM INTEL OR DERIVED FROM INTEL SOFTWARE
0085  * IS PROVIDED "AS IS," AND INTEL WILL NOT PROVIDE ANY SUPPORT, ASSISTANCE,
0086  * INSTALLATION, TRAINING OR OTHER SERVICES. INTEL WILL NOT PROVIDE ANY
0087  * UPDATES, ENHANCEMENTS OR EXTENSIONS. INTEL SPECIFICALLY DISCLAIMS ANY
0088  * IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT AND FITNESS FOR A
0089  * PARTICULAR PURPOSE.
0090  *
0091  * 4.2. IN NO EVENT SHALL INTEL HAVE ANY LIABILITY TO LICENSEE, ITS LICENSEES
0092  * OR ANY OTHER THIRD PARTY, FOR ANY LOST PROFITS, LOST DATA, LOSS OF USE OR
0093  * COSTS OF PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, OR FOR ANY INDIRECT,
0094  * SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THIS AGREEMENT, UNDER ANY
0095  * CAUSE OF ACTION OR THEORY OF LIABILITY, AND IRRESPECTIVE OF WHETHER INTEL
0096  * HAS ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES. THESE LIMITATIONS
0097  * SHALL APPLY NOTWITHSTANDING THE FAILURE OF THE ESSENTIAL PURPOSE OF ANY
0098  * LIMITED REMEDY.
0099  *
0100  * 4.3. Licensee shall not export, either directly or indirectly, any of this
0101  * software or system incorporating such software without first obtaining any
0102  * required license or other approval from the U. S. Department of Commerce or
0103  * any other agency or department of the United States Government. In the
0104  * event Licensee exports any such software from the United States or
0105  * re-exports any such software from a foreign destination, Licensee shall
0106  * ensure that the distribution and export/re-export of the software is in
0107  * compliance with all laws, regulations, orders, or other restrictions of the
0108  * U.S. Export Administration Regulations. Licensee agrees that neither it nor
0109  * any of its subsidiaries will export/re-export any technical data, process,
0110  * software, or service, directly or indirectly, to any country for which the
0111  * United States government or any agency thereof requires an export license,
0112  * other governmental approval, or letter of assurance, without first obtaining
0113  * such license, approval or letter.
0114  *
0115  *****************************************************************************
0116  *
0117  * Alternatively, you may choose to be licensed under the terms of the
0118  * following license:
0119  *
0120  * Redistribution and use in source and binary forms, with or without
0121  * modification, are permitted provided that the following conditions
0122  * are met:
0123  * 1. Redistributions of source code must retain the above copyright
0124  *    notice, this list of conditions, and the following disclaimer,
0125  *    without modification.
0126  * 2. Redistributions in binary form must reproduce at minimum a disclaimer
0127  *    substantially similar to the "NO WARRANTY" disclaimer below
0128  *    ("Disclaimer") and any redistribution must be conditioned upon
0129  *    including a substantially similar Disclaimer requirement for further
0130  *    binary redistribution.
0131  * 3. Neither the names of the above-listed copyright holders nor the names
0132  *    of any contributors may be used to endorse or promote products derived
0133  *    from this software without specific prior written permission.
0134  *
0135  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
0136  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
0137  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
0138  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
0139  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
0140  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
0141  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
0142  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
0143  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
0144  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
0145  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
0146  *
0147  * Alternatively, you may choose to be licensed under the terms of the
0148  * GNU General Public License ("GPL") version 2 as published by the Free
0149  * Software Foundation.
0150  *
0151  *****************************************************************************/
0152 
0153 #include "acpi.h"
0154 #include "accommon.h"
0155 #include "acevents.h"
0156 
0157 #define _COMPONENT          ACPI_HARDWARE
0158         ACPI_MODULE_NAME    ("hwregs")
0159 
0160 
0161 #if (!ACPI_REDUCED_HARDWARE)
0162 
0163 /* Local Prototypes */
0164 
0165 static UINT8
0166 AcpiHwGetAccessBitWidth (
0167     UINT64                  Address,
0168     ACPI_GENERIC_ADDRESS    *Reg,
0169     UINT8                   MaxBitWidth);
0170 
0171 static ACPI_STATUS
0172 AcpiHwReadMultiple (
0173     UINT32                  *Value,
0174     ACPI_GENERIC_ADDRESS    *RegisterA,
0175     ACPI_GENERIC_ADDRESS    *RegisterB);
0176 
0177 static ACPI_STATUS
0178 AcpiHwWriteMultiple (
0179     UINT32                  Value,
0180     ACPI_GENERIC_ADDRESS    *RegisterA,
0181     ACPI_GENERIC_ADDRESS    *RegisterB);
0182 
0183 #endif /* !ACPI_REDUCED_HARDWARE */
0184 
0185 
0186 /******************************************************************************
0187  *
0188  * FUNCTION:    AcpiHwGetAccessBitWidth
0189  *
0190  * PARAMETERS:  Address             - GAS register address
0191  *              Reg                 - GAS register structure
0192  *              MaxBitWidth         - Max BitWidth supported (32 or 64)
0193  *
0194  * RETURN:      Status
0195  *
0196  * DESCRIPTION: Obtain optimal access bit width
0197  *
0198  ******************************************************************************/
0199 
0200 static UINT8
0201 AcpiHwGetAccessBitWidth (
0202     UINT64                  Address,
0203     ACPI_GENERIC_ADDRESS    *Reg,
0204     UINT8                   MaxBitWidth)
0205 {
0206     UINT8                   AccessBitWidth;
0207 
0208 
0209     /*
0210      * GAS format "register", used by FADT:
0211      *  1. Detected if BitOffset is 0 and BitWidth is 8/16/32/64;
0212      *  2. AccessSize field is ignored and BitWidth field is used for
0213      *     determining the boundary of the IO accesses.
0214      * GAS format "region", used by APEI registers:
0215      *  1. Detected if BitOffset is not 0 or BitWidth is not 8/16/32/64;
0216      *  2. AccessSize field is used for determining the boundary of the
0217      *     IO accesses;
0218      *  3. BitOffset/BitWidth fields are used to describe the "region".
0219      *
0220      * Note: This algorithm assumes that the "Address" fields should always
0221      *       contain aligned values.
0222      */
0223     if (!Reg->BitOffset && Reg->BitWidth &&
0224         ACPI_IS_POWER_OF_TWO (Reg->BitWidth) &&
0225         ACPI_IS_ALIGNED (Reg->BitWidth, 8))
0226     {
0227         AccessBitWidth = Reg->BitWidth;
0228     }
0229     else if (Reg->AccessWidth)
0230     {
0231         AccessBitWidth = ACPI_ACCESS_BIT_WIDTH (Reg->AccessWidth);
0232     }
0233     else
0234     {
0235         AccessBitWidth = ACPI_ROUND_UP_POWER_OF_TWO_8 (
0236             Reg->BitOffset + Reg->BitWidth);
0237         if (AccessBitWidth <= 8)
0238         {
0239             AccessBitWidth = 8;
0240         }
0241         else
0242         {
0243             while (!ACPI_IS_ALIGNED (Address, AccessBitWidth >> 3))
0244             {
0245                 AccessBitWidth >>= 1;
0246             }
0247         }
0248     }
0249 
0250     /* Maximum IO port access bit width is 32 */
0251 
0252     if (Reg->SpaceId == ACPI_ADR_SPACE_SYSTEM_IO)
0253     {
0254         MaxBitWidth = 32;
0255     }
0256 
0257     /*
0258      * Return access width according to the requested maximum access bit width,
0259      * as the caller should know the format of the register and may enforce
0260      * a 32-bit accesses.
0261      */
0262     if (AccessBitWidth < MaxBitWidth)
0263     {
0264         return (AccessBitWidth);
0265     }
0266     return (MaxBitWidth);
0267 }
0268 
0269 
0270 /******************************************************************************
0271  *
0272  * FUNCTION:    AcpiHwValidateRegister
0273  *
0274  * PARAMETERS:  Reg                 - GAS register structure
0275  *              MaxBitWidth         - Max BitWidth supported (32 or 64)
0276  *              Address             - Pointer to where the gas->address
0277  *                                    is returned
0278  *
0279  * RETURN:      Status
0280  *
0281  * DESCRIPTION: Validate the contents of a GAS register. Checks the GAS
0282  *              pointer, Address, SpaceId, BitWidth, and BitOffset.
0283  *
0284  ******************************************************************************/
0285 
0286 ACPI_STATUS
0287 AcpiHwValidateRegister (
0288     ACPI_GENERIC_ADDRESS    *Reg,
0289     UINT8                   MaxBitWidth,
0290     UINT64                  *Address)
0291 {
0292     UINT8                   BitWidth;
0293     UINT8                   AccessWidth;
0294 
0295 
0296     /* Must have a valid pointer to a GAS structure */
0297 
0298     if (!Reg)
0299     {
0300         return (AE_BAD_PARAMETER);
0301     }
0302 
0303     /*
0304      * Copy the target address. This handles possible alignment issues.
0305      * Address must not be null. A null address also indicates an optional
0306      * ACPI register that is not supported, so no error message.
0307      */
0308     ACPI_MOVE_64_TO_64 (Address, &Reg->Address);
0309     if (!(*Address))
0310     {
0311         return (AE_BAD_ADDRESS);
0312     }
0313 
0314     /* Validate the SpaceID */
0315 
0316     if ((Reg->SpaceId != ACPI_ADR_SPACE_SYSTEM_MEMORY) &&
0317         (Reg->SpaceId != ACPI_ADR_SPACE_SYSTEM_IO))
0318     {
0319         ACPI_ERROR ((AE_INFO,
0320             "Unsupported address space: 0x%X", Reg->SpaceId));
0321         return (AE_SUPPORT);
0322     }
0323 
0324     /* Validate the AccessWidth */
0325 
0326     if (Reg->AccessWidth > 4)
0327     {
0328         ACPI_ERROR ((AE_INFO,
0329             "Unsupported register access width: 0x%X", Reg->AccessWidth));
0330         return (AE_SUPPORT);
0331     }
0332 
0333     /* Validate the BitWidth, convert AccessWidth into number of bits */
0334 
0335     AccessWidth = AcpiHwGetAccessBitWidth (*Address, Reg, MaxBitWidth);
0336     BitWidth = ACPI_ROUND_UP (Reg->BitOffset + Reg->BitWidth, AccessWidth);
0337     if (MaxBitWidth < BitWidth)
0338     {
0339         ACPI_WARNING ((AE_INFO,
0340             "Requested bit width 0x%X is smaller than register bit width 0x%X",
0341             MaxBitWidth, BitWidth));
0342         return (AE_SUPPORT);
0343     }
0344 
0345     return (AE_OK);
0346 }
0347 
0348 
0349 /******************************************************************************
0350  *
0351  * FUNCTION:    AcpiHwRead
0352  *
0353  * PARAMETERS:  Value               - Where the value is returned
0354  *              Reg                 - GAS register structure
0355  *
0356  * RETURN:      Status
0357  *
0358  * DESCRIPTION: Read from either memory or IO space. This is a 64-bit max
0359  *              version of AcpiRead.
0360  *
0361  * LIMITATIONS: <These limitations also apply to AcpiHwWrite>
0362  *      SpaceID must be SystemMemory or SystemIO.
0363  *
0364  ******************************************************************************/
0365 
0366 ACPI_STATUS
0367 AcpiHwRead (
0368     UINT64                  *Value,
0369     ACPI_GENERIC_ADDRESS    *Reg)
0370 {
0371     UINT64                  Address;
0372     UINT8                   AccessWidth;
0373     UINT32                  BitWidth;
0374     UINT8                   BitOffset;
0375     UINT64                  Value64;
0376     UINT32                  Value32;
0377     UINT8                   Index;
0378     ACPI_STATUS             Status;
0379 
0380 
0381     ACPI_FUNCTION_NAME (HwRead);
0382 
0383 
0384     /* Validate contents of the GAS register */
0385 
0386     Status = AcpiHwValidateRegister (Reg, 64, &Address);
0387     if (ACPI_FAILURE (Status))
0388     {
0389         return (Status);
0390     }
0391 
0392     /*
0393      * Initialize entire 64-bit return value to zero, convert AccessWidth
0394      * into number of bits based
0395      */
0396     *Value = 0;
0397     AccessWidth = AcpiHwGetAccessBitWidth (Address, Reg, 64);
0398     BitWidth = Reg->BitOffset + Reg->BitWidth;
0399     BitOffset = Reg->BitOffset;
0400 
0401     /*
0402      * Two address spaces supported: Memory or IO. PCI_Config is
0403      * not supported here because the GAS structure is insufficient
0404      */
0405     Index = 0;
0406     while (BitWidth)
0407     {
0408         if (BitOffset >= AccessWidth)
0409         {
0410             Value64 = 0;
0411             BitOffset -= AccessWidth;
0412         }
0413         else
0414         {
0415             if (Reg->SpaceId == ACPI_ADR_SPACE_SYSTEM_MEMORY)
0416             {
0417                 Status = AcpiOsReadMemory ((ACPI_PHYSICAL_ADDRESS)
0418                     Address + Index * ACPI_DIV_8 (AccessWidth),
0419                     &Value64, AccessWidth);
0420             }
0421             else /* ACPI_ADR_SPACE_SYSTEM_IO, validated earlier */
0422             {
0423                 Status = AcpiHwReadPort ((ACPI_IO_ADDRESS)
0424                     Address + Index * ACPI_DIV_8 (AccessWidth),
0425                     &Value32, AccessWidth);
0426                 Value64 = (UINT64) Value32;
0427             }
0428         }
0429 
0430         /*
0431          * Use offset style bit writes because "Index * AccessWidth" is
0432          * ensured to be less than 64-bits by AcpiHwValidateRegister().
0433          */
0434         ACPI_SET_BITS (Value, Index * AccessWidth,
0435             ACPI_MASK_BITS_ABOVE_64 (AccessWidth), Value64);
0436 
0437         BitWidth -= BitWidth > AccessWidth ? AccessWidth : BitWidth;
0438         Index++;
0439     }
0440 
0441     ACPI_DEBUG_PRINT ((ACPI_DB_IO,
0442         "Read:  %8.8X%8.8X width %2d from %8.8X%8.8X (%s)\n",
0443         ACPI_FORMAT_UINT64 (*Value), AccessWidth,
0444         ACPI_FORMAT_UINT64 (Address), AcpiUtGetRegionName (Reg->SpaceId)));
0445 
0446     return (Status);
0447 }
0448 
0449 
0450 /******************************************************************************
0451  *
0452  * FUNCTION:    AcpiHwWrite
0453  *
0454  * PARAMETERS:  Value               - Value to be written
0455  *              Reg                 - GAS register structure
0456  *
0457  * RETURN:      Status
0458  *
0459  * DESCRIPTION: Write to either memory or IO space. This is a 64-bit max
0460  *              version of AcpiWrite.
0461  *
0462  ******************************************************************************/
0463 
0464 ACPI_STATUS
0465 AcpiHwWrite (
0466     UINT64                  Value,
0467     ACPI_GENERIC_ADDRESS    *Reg)
0468 {
0469     UINT64                  Address;
0470     UINT8                   AccessWidth;
0471     UINT32                  BitWidth;
0472     UINT8                   BitOffset;
0473     UINT64                  Value64;
0474     UINT8                   Index;
0475     ACPI_STATUS             Status;
0476 
0477 
0478     ACPI_FUNCTION_NAME (HwWrite);
0479 
0480 
0481     /* Validate contents of the GAS register */
0482 
0483     Status = AcpiHwValidateRegister (Reg, 64, &Address);
0484     if (ACPI_FAILURE (Status))
0485     {
0486         return (Status);
0487     }
0488 
0489     /* Convert AccessWidth into number of bits based */
0490 
0491     AccessWidth = AcpiHwGetAccessBitWidth (Address, Reg, 64);
0492     BitWidth = Reg->BitOffset + Reg->BitWidth;
0493     BitOffset = Reg->BitOffset;
0494 
0495     /*
0496      * Two address spaces supported: Memory or IO. PCI_Config is
0497      * not supported here because the GAS structure is insufficient
0498      */
0499     Index = 0;
0500     while (BitWidth)
0501     {
0502         /*
0503          * Use offset style bit reads because "Index * AccessWidth" is
0504          * ensured to be less than 64-bits by AcpiHwValidateRegister().
0505          */
0506         Value64 = ACPI_GET_BITS (&Value, Index * AccessWidth,
0507             ACPI_MASK_BITS_ABOVE_64 (AccessWidth));
0508 
0509         if (BitOffset >= AccessWidth)
0510         {
0511             BitOffset -= AccessWidth;
0512         }
0513         else
0514         {
0515             if (Reg->SpaceId == ACPI_ADR_SPACE_SYSTEM_MEMORY)
0516             {
0517                 Status = AcpiOsWriteMemory ((ACPI_PHYSICAL_ADDRESS)
0518                     Address + Index * ACPI_DIV_8 (AccessWidth),
0519                     Value64, AccessWidth);
0520             }
0521             else /* ACPI_ADR_SPACE_SYSTEM_IO, validated earlier */
0522             {
0523                 Status = AcpiHwWritePort ((ACPI_IO_ADDRESS)
0524                     Address + Index * ACPI_DIV_8 (AccessWidth),
0525                     (UINT32) Value64, AccessWidth);
0526             }
0527         }
0528 
0529         /*
0530          * Index * AccessWidth is ensured to be less than 32-bits by
0531          * AcpiHwValidateRegister().
0532          */
0533         BitWidth -= BitWidth > AccessWidth ? AccessWidth : BitWidth;
0534         Index++;
0535     }
0536 
0537     ACPI_DEBUG_PRINT ((ACPI_DB_IO,
0538         "Wrote: %8.8X%8.8X width %2d   to %8.8X%8.8X (%s)\n",
0539         ACPI_FORMAT_UINT64 (Value), AccessWidth,
0540         ACPI_FORMAT_UINT64 (Address), AcpiUtGetRegionName (Reg->SpaceId)));
0541 
0542     return (Status);
0543 }
0544 
0545 
0546 #if (!ACPI_REDUCED_HARDWARE)
0547 /*******************************************************************************
0548  *
0549  * FUNCTION:    AcpiHwClearAcpiStatus
0550  *
0551  * PARAMETERS:  None
0552  *
0553  * RETURN:      Status
0554  *
0555  * DESCRIPTION: Clears all fixed and general purpose status bits
0556  *
0557  ******************************************************************************/
0558 
0559 ACPI_STATUS
0560 AcpiHwClearAcpiStatus (
0561     void)
0562 {
0563     ACPI_STATUS             Status;
0564     ACPI_CPU_FLAGS          LockFlags = 0;
0565 
0566 
0567     ACPI_FUNCTION_TRACE (HwClearAcpiStatus);
0568 
0569 
0570     ACPI_DEBUG_PRINT ((ACPI_DB_IO, "About to write %04X to %8.8X%8.8X\n",
0571         ACPI_BITMASK_ALL_FIXED_STATUS,
0572         ACPI_FORMAT_UINT64 (AcpiGbl_XPm1aStatus.Address)));
0573 
0574     LockFlags = AcpiOsAcquireLock (AcpiGbl_HardwareLock);
0575 
0576     /* Clear the fixed events in PM1 A/B */
0577 
0578     Status = AcpiHwRegisterWrite (ACPI_REGISTER_PM1_STATUS,
0579         ACPI_BITMASK_ALL_FIXED_STATUS);
0580 
0581     AcpiOsReleaseLock (AcpiGbl_HardwareLock, LockFlags);
0582 
0583     if (ACPI_FAILURE (Status))
0584     {
0585         goto Exit;
0586     }
0587 
0588     /* Clear the GPE Bits in all GPE registers in all GPE blocks */
0589 
0590     Status = AcpiEvWalkGpeList (AcpiHwClearGpeBlock, NULL);
0591 
0592 Exit:
0593     return_ACPI_STATUS (Status);
0594 }
0595 
0596 
0597 /*******************************************************************************
0598  *
0599  * FUNCTION:    AcpiHwGetBitRegisterInfo
0600  *
0601  * PARAMETERS:  RegisterId          - Index of ACPI Register to access
0602  *
0603  * RETURN:      The bitmask to be used when accessing the register
0604  *
0605  * DESCRIPTION: Map RegisterId into a register bitmask.
0606  *
0607  ******************************************************************************/
0608 
0609 ACPI_BIT_REGISTER_INFO *
0610 AcpiHwGetBitRegisterInfo (
0611     UINT32                  RegisterId)
0612 {
0613     ACPI_FUNCTION_ENTRY ();
0614 
0615 
0616     if (RegisterId > ACPI_BITREG_MAX)
0617     {
0618         ACPI_ERROR ((AE_INFO, "Invalid BitRegister ID: 0x%X", RegisterId));
0619         return (NULL);
0620     }
0621 
0622     return (&AcpiGbl_BitRegisterInfo[RegisterId]);
0623 }
0624 
0625 
0626 /******************************************************************************
0627  *
0628  * FUNCTION:    AcpiHwWritePm1Control
0629  *
0630  * PARAMETERS:  Pm1aControl         - Value to be written to PM1A control
0631  *              Pm1bControl         - Value to be written to PM1B control
0632  *
0633  * RETURN:      Status
0634  *
0635  * DESCRIPTION: Write the PM1 A/B control registers. These registers are
0636  *              different than the PM1 A/B status and enable registers
0637  *              in that different values can be written to the A/B registers.
0638  *              Most notably, the SLP_TYP bits can be different, as per the
0639  *              values returned from the _Sx predefined methods.
0640  *
0641  ******************************************************************************/
0642 
0643 ACPI_STATUS
0644 AcpiHwWritePm1Control (
0645     UINT32                  Pm1aControl,
0646     UINT32                  Pm1bControl)
0647 {
0648     ACPI_STATUS             Status;
0649 
0650 
0651     ACPI_FUNCTION_TRACE (HwWritePm1Control);
0652 
0653 
0654     Status = AcpiHwWrite (Pm1aControl, &AcpiGbl_FADT.XPm1aControlBlock);
0655     if (ACPI_FAILURE (Status))
0656     {
0657         return_ACPI_STATUS (Status);
0658     }
0659 
0660     if (AcpiGbl_FADT.XPm1bControlBlock.Address)
0661     {
0662         Status = AcpiHwWrite (Pm1bControl, &AcpiGbl_FADT.XPm1bControlBlock);
0663     }
0664     return_ACPI_STATUS (Status);
0665 }
0666 
0667 
0668 /******************************************************************************
0669  *
0670  * FUNCTION:    AcpiHwRegisterRead
0671  *
0672  * PARAMETERS:  RegisterId          - ACPI Register ID
0673  *              ReturnValue         - Where the register value is returned
0674  *
0675  * RETURN:      Status and the value read.
0676  *
0677  * DESCRIPTION: Read from the specified ACPI register
0678  *
0679  ******************************************************************************/
0680 
0681 ACPI_STATUS
0682 AcpiHwRegisterRead (
0683     UINT32                  RegisterId,
0684     UINT32                  *ReturnValue)
0685 {
0686     UINT32                  Value = 0;
0687     UINT64                  Value64;
0688     ACPI_STATUS             Status;
0689 
0690 
0691     ACPI_FUNCTION_TRACE (HwRegisterRead);
0692 
0693 
0694     switch (RegisterId)
0695     {
0696     case ACPI_REGISTER_PM1_STATUS:           /* PM1 A/B: 16-bit access each */
0697 
0698         Status = AcpiHwReadMultiple (&Value,
0699             &AcpiGbl_XPm1aStatus,
0700             &AcpiGbl_XPm1bStatus);
0701         break;
0702 
0703     case ACPI_REGISTER_PM1_ENABLE:           /* PM1 A/B: 16-bit access each */
0704 
0705         Status = AcpiHwReadMultiple (&Value,
0706             &AcpiGbl_XPm1aEnable,
0707             &AcpiGbl_XPm1bEnable);
0708         break;
0709 
0710     case ACPI_REGISTER_PM1_CONTROL:          /* PM1 A/B: 16-bit access each */
0711 
0712         Status = AcpiHwReadMultiple (&Value,
0713             &AcpiGbl_FADT.XPm1aControlBlock,
0714             &AcpiGbl_FADT.XPm1bControlBlock);
0715 
0716         /*
0717          * Zero the write-only bits. From the ACPI specification, "Hardware
0718          * Write-Only Bits": "Upon reads to registers with write-only bits,
0719          * software masks out all write-only bits."
0720          */
0721         Value &= ~ACPI_PM1_CONTROL_WRITEONLY_BITS;
0722         break;
0723 
0724     case ACPI_REGISTER_PM2_CONTROL:          /* 8-bit access */
0725 
0726         Status = AcpiHwRead (&Value64, &AcpiGbl_FADT.XPm2ControlBlock);
0727         if (ACPI_SUCCESS (Status))
0728         {
0729             Value = (UINT32) Value64;
0730         }
0731         break;
0732 
0733     case ACPI_REGISTER_PM_TIMER:             /* 32-bit access */
0734 
0735         Status = AcpiHwRead (&Value64, &AcpiGbl_FADT.XPmTimerBlock);
0736         if (ACPI_SUCCESS (Status))
0737         {
0738             Value = (UINT32) Value64;
0739         }
0740 
0741         break;
0742 
0743     case ACPI_REGISTER_SMI_COMMAND_BLOCK:    /* 8-bit access */
0744 
0745         Status = AcpiHwReadPort (AcpiGbl_FADT.SmiCommand, &Value, 8);
0746         break;
0747 
0748     default:
0749 
0750         ACPI_ERROR ((AE_INFO, "Unknown Register ID: 0x%X",
0751             RegisterId));
0752         Status = AE_BAD_PARAMETER;
0753         break;
0754     }
0755 
0756     if (ACPI_SUCCESS (Status))
0757     {
0758         *ReturnValue = (UINT32) Value;
0759     }
0760 
0761     return_ACPI_STATUS (Status);
0762 }
0763 
0764 
0765 /******************************************************************************
0766  *
0767  * FUNCTION:    AcpiHwRegisterWrite
0768  *
0769  * PARAMETERS:  RegisterId          - ACPI Register ID
0770  *              Value               - The value to write
0771  *
0772  * RETURN:      Status
0773  *
0774  * DESCRIPTION: Write to the specified ACPI register
0775  *
0776  * NOTE: In accordance with the ACPI specification, this function automatically
0777  * preserves the value of the following bits, meaning that these bits cannot be
0778  * changed via this interface:
0779  *
0780  * PM1_CONTROL[0] = SCI_EN
0781  * PM1_CONTROL[9]
0782  * PM1_STATUS[11]
0783  *
0784  * ACPI References:
0785  * 1) Hardware Ignored Bits: When software writes to a register with ignored
0786  *      bit fields, it preserves the ignored bit fields
0787  * 2) SCI_EN: OSPM always preserves this bit position
0788  *
0789  ******************************************************************************/
0790 
0791 ACPI_STATUS
0792 AcpiHwRegisterWrite (
0793     UINT32                  RegisterId,
0794     UINT32                  Value)
0795 {
0796     ACPI_STATUS             Status;
0797     UINT32                  ReadValue;
0798     UINT64                  ReadValue64;
0799 
0800 
0801     ACPI_FUNCTION_TRACE (HwRegisterWrite);
0802 
0803 
0804     switch (RegisterId)
0805     {
0806     case ACPI_REGISTER_PM1_STATUS:           /* PM1 A/B: 16-bit access each */
0807         /*
0808          * Handle the "ignored" bit in PM1 Status. According to the ACPI
0809          * specification, ignored bits are to be preserved when writing.
0810          * Normally, this would mean a read/modify/write sequence. However,
0811          * preserving a bit in the status register is different. Writing a
0812          * one clears the status, and writing a zero preserves the status.
0813          * Therefore, we must always write zero to the ignored bit.
0814          *
0815          * This behavior is clarified in the ACPI 4.0 specification.
0816          */
0817         Value &= ~ACPI_PM1_STATUS_PRESERVED_BITS;
0818 
0819         Status = AcpiHwWriteMultiple (Value,
0820             &AcpiGbl_XPm1aStatus,
0821             &AcpiGbl_XPm1bStatus);
0822         break;
0823 
0824     case ACPI_REGISTER_PM1_ENABLE:           /* PM1 A/B: 16-bit access each */
0825 
0826         Status = AcpiHwWriteMultiple (Value,
0827             &AcpiGbl_XPm1aEnable,
0828             &AcpiGbl_XPm1bEnable);
0829         break;
0830 
0831     case ACPI_REGISTER_PM1_CONTROL:          /* PM1 A/B: 16-bit access each */
0832         /*
0833          * Perform a read first to preserve certain bits (per ACPI spec)
0834          * Note: This includes SCI_EN, we never want to change this bit
0835          */
0836         Status = AcpiHwReadMultiple (&ReadValue,
0837             &AcpiGbl_FADT.XPm1aControlBlock,
0838             &AcpiGbl_FADT.XPm1bControlBlock);
0839         if (ACPI_FAILURE (Status))
0840         {
0841             goto Exit;
0842         }
0843 
0844         /* Insert the bits to be preserved */
0845 
0846         ACPI_INSERT_BITS (Value, ACPI_PM1_CONTROL_PRESERVED_BITS, ReadValue);
0847 
0848         /* Now we can write the data */
0849 
0850         Status = AcpiHwWriteMultiple (Value,
0851             &AcpiGbl_FADT.XPm1aControlBlock,
0852             &AcpiGbl_FADT.XPm1bControlBlock);
0853         break;
0854 
0855     case ACPI_REGISTER_PM2_CONTROL:          /* 8-bit access */
0856         /*
0857          * For control registers, all reserved bits must be preserved,
0858          * as per the ACPI spec.
0859          */
0860         Status = AcpiHwRead (&ReadValue64, &AcpiGbl_FADT.XPm2ControlBlock);
0861         if (ACPI_FAILURE (Status))
0862         {
0863             goto Exit;
0864         }
0865         ReadValue = (UINT32) ReadValue64;
0866 
0867         /* Insert the bits to be preserved */
0868 
0869         ACPI_INSERT_BITS (Value, ACPI_PM2_CONTROL_PRESERVED_BITS, ReadValue);
0870 
0871         Status = AcpiHwWrite (Value, &AcpiGbl_FADT.XPm2ControlBlock);
0872         break;
0873 
0874     case ACPI_REGISTER_PM_TIMER:             /* 32-bit access */
0875 
0876         Status = AcpiHwWrite (Value, &AcpiGbl_FADT.XPmTimerBlock);
0877         break;
0878 
0879     case ACPI_REGISTER_SMI_COMMAND_BLOCK:    /* 8-bit access */
0880 
0881         /* SMI_CMD is currently always in IO space */
0882 
0883         Status = AcpiHwWritePort (AcpiGbl_FADT.SmiCommand, Value, 8);
0884         break;
0885 
0886     default:
0887 
0888         ACPI_ERROR ((AE_INFO, "Unknown Register ID: 0x%X",
0889             RegisterId));
0890         Status = AE_BAD_PARAMETER;
0891         break;
0892     }
0893 
0894 Exit:
0895     return_ACPI_STATUS (Status);
0896 }
0897 
0898 
0899 /******************************************************************************
0900  *
0901  * FUNCTION:    AcpiHwReadMultiple
0902  *
0903  * PARAMETERS:  Value               - Where the register value is returned
0904  *              RegisterA           - First ACPI register (required)
0905  *              RegisterB           - Second ACPI register (optional)
0906  *
0907  * RETURN:      Status
0908  *
0909  * DESCRIPTION: Read from the specified two-part ACPI register (such as PM1 A/B)
0910  *
0911  ******************************************************************************/
0912 
0913 static ACPI_STATUS
0914 AcpiHwReadMultiple (
0915     UINT32                  *Value,
0916     ACPI_GENERIC_ADDRESS    *RegisterA,
0917     ACPI_GENERIC_ADDRESS    *RegisterB)
0918 {
0919     UINT32                  ValueA = 0;
0920     UINT32                  ValueB = 0;
0921     UINT64                  Value64;
0922     ACPI_STATUS             Status;
0923 
0924 
0925     /* The first register is always required */
0926 
0927     Status = AcpiHwRead (&Value64, RegisterA);
0928     if (ACPI_FAILURE (Status))
0929     {
0930         return (Status);
0931     }
0932     ValueA = (UINT32) Value64;
0933 
0934     /* Second register is optional */
0935 
0936     if (RegisterB->Address)
0937     {
0938         Status = AcpiHwRead (&Value64, RegisterB);
0939         if (ACPI_FAILURE (Status))
0940         {
0941             return (Status);
0942         }
0943         ValueB = (UINT32) Value64;
0944     }
0945 
0946     /*
0947      * OR the two return values together. No shifting or masking is necessary,
0948      * because of how the PM1 registers are defined in the ACPI specification:
0949      *
0950      * "Although the bits can be split between the two register blocks (each
0951      * register block has a unique pointer within the FADT), the bit positions
0952      * are maintained. The register block with unimplemented bits (that is,
0953      * those implemented in the other register block) always returns zeros,
0954      * and writes have no side effects"
0955      */
0956     *Value = (ValueA | ValueB);
0957     return (AE_OK);
0958 }
0959 
0960 
0961 /******************************************************************************
0962  *
0963  * FUNCTION:    AcpiHwWriteMultiple
0964  *
0965  * PARAMETERS:  Value               - The value to write
0966  *              RegisterA           - First ACPI register (required)
0967  *              RegisterB           - Second ACPI register (optional)
0968  *
0969  * RETURN:      Status
0970  *
0971  * DESCRIPTION: Write to the specified two-part ACPI register (such as PM1 A/B)
0972  *
0973  ******************************************************************************/
0974 
0975 static ACPI_STATUS
0976 AcpiHwWriteMultiple (
0977     UINT32                  Value,
0978     ACPI_GENERIC_ADDRESS    *RegisterA,
0979     ACPI_GENERIC_ADDRESS    *RegisterB)
0980 {
0981     ACPI_STATUS             Status;
0982 
0983 
0984     /* The first register is always required */
0985 
0986     Status = AcpiHwWrite (Value, RegisterA);
0987     if (ACPI_FAILURE (Status))
0988     {
0989         return (Status);
0990     }
0991 
0992     /*
0993      * Second register is optional
0994      *
0995      * No bit shifting or clearing is necessary, because of how the PM1
0996      * registers are defined in the ACPI specification:
0997      *
0998      * "Although the bits can be split between the two register blocks (each
0999      * 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 */