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