Print this page
acpica-unix2-20130823
PANKOVs restructure
   1 
   2 /*******************************************************************************
   3  *
   4  * Module Name: hwregs - Read/write access functions for the various ACPI
   5  *                       control and status registers.
   6  *
   7  ******************************************************************************/
   8 
   9 /*
  10  * Copyright (C) 2000 - 2011, Intel Corp.
  11  * All rights reserved.
  12  *
  13  * Redistribution and use in source and binary forms, with or without
  14  * modification, are permitted provided that the following conditions
  15  * are met:
  16  * 1. Redistributions of source code must retain the above copyright
  17  *    notice, this list of conditions, and the following disclaimer,
  18  *    without modification.
  19  * 2. Redistributions in binary form must reproduce at minimum a disclaimer
  20  *    substantially similar to the "NO WARRANTY" disclaimer below
  21  *    ("Disclaimer") and any redistribution must be conditioned upon
  22  *    including a substantially similar Disclaimer requirement for further
  23  *    binary redistribution.
  24  * 3. Neither the names of the above-listed copyright holders nor the names
  25  *    of any contributors may be used to endorse or promote products derived
  26  *    from this software without specific prior written permission.
  27  *
  28  * Alternatively, this software may be distributed under the terms of the
  29  * GNU General Public License ("GPL") version 2 as published by the Free
  30  * Software Foundation.


  36  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  37  * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  38  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  39  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  40  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
  41  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
  42  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  43  * POSSIBILITY OF SUCH DAMAGES.
  44  */
  45 
  46 #define __HWREGS_C__
  47 
  48 #include "acpi.h"
  49 #include "accommon.h"
  50 #include "acevents.h"
  51 
  52 #define _COMPONENT          ACPI_HARDWARE
  53         ACPI_MODULE_NAME    ("hwregs")
  54 
  55 


  56 /* Local Prototypes */
  57 
  58 static ACPI_STATUS
  59 AcpiHwReadMultiple (
  60     UINT32                  *Value,
  61     ACPI_GENERIC_ADDRESS    *RegisterA,
  62     ACPI_GENERIC_ADDRESS    *RegisterB);
  63 
  64 static ACPI_STATUS
  65 AcpiHwWriteMultiple (
  66     UINT32                  Value,
  67     ACPI_GENERIC_ADDRESS    *RegisterA,
  68     ACPI_GENERIC_ADDRESS    *RegisterB);
  69 

  70 
  71 /******************************************************************************
  72  *
  73  * FUNCTION:    AcpiHwValidateRegister
  74  *
  75  * PARAMETERS:  Reg                 - GAS register structure
  76  *              MaxBitWidth         - Max BitWidth supported (32 or 64)
  77  *              Address             - Pointer to where the gas->address
  78  *                                    is returned
  79  *
  80  * RETURN:      Status
  81  *
  82  * DESCRIPTION: Validate the contents of a GAS register. Checks the GAS
  83  *              pointer, Address, SpaceId, BitWidth, and BitOffset.
  84  *
  85  ******************************************************************************/
  86 
  87 ACPI_STATUS
  88 AcpiHwValidateRegister (
  89     ACPI_GENERIC_ADDRESS    *Reg,


 153  * RETURN:      Status
 154  *
 155  * DESCRIPTION: Read from either memory or IO space. This is a 32-bit max
 156  *              version of AcpiRead, used internally since the overhead of
 157  *              64-bit values is not needed.
 158  *
 159  * LIMITATIONS: <These limitations also apply to AcpiHwWrite>
 160  *      BitWidth must be exactly 8, 16, or 32.
 161  *      SpaceID must be SystemMemory or SystemIO.
 162  *      BitOffset and AccessWidth are currently ignored, as there has
 163  *          not been a need to implement these.
 164  *
 165  ******************************************************************************/
 166 
 167 ACPI_STATUS
 168 AcpiHwRead (
 169     UINT32                  *Value,
 170     ACPI_GENERIC_ADDRESS    *Reg)
 171 {
 172     UINT64                  Address;

 173     ACPI_STATUS             Status;
 174 
 175 
 176     ACPI_FUNCTION_NAME (HwRead);
 177 
 178 
 179     /* Validate contents of the GAS register */
 180 
 181     Status = AcpiHwValidateRegister (Reg, 32, &Address);
 182     if (ACPI_FAILURE (Status))
 183     {
 184         return (Status);
 185     }
 186 
 187     /* Initialize entire 32-bit return value to zero */
 188 
 189     *Value = 0;
 190 
 191     /*
 192      * Two address spaces supported: Memory or IO. PCI_Config is
 193      * not supported here because the GAS structure is insufficient
 194      */
 195     if (Reg->SpaceId == ACPI_ADR_SPACE_SYSTEM_MEMORY)
 196     {
 197         Status = AcpiOsReadMemory ((ACPI_PHYSICAL_ADDRESS)
 198                     Address, Value, Reg->BitWidth);


 199     }
 200     else /* ACPI_ADR_SPACE_SYSTEM_IO, validated earlier */
 201     {
 202         Status = AcpiHwReadPort ((ACPI_IO_ADDRESS)
 203                     Address, Value, Reg->BitWidth);
 204     }
 205 
 206     ACPI_DEBUG_PRINT ((ACPI_DB_IO,
 207         "Read:  %8.8X width %2d from %8.8X%8.8X (%s)\n",
 208         *Value, Reg->BitWidth, ACPI_FORMAT_UINT64 (Address),
 209         AcpiUtGetRegionName (Reg->SpaceId)));
 210 
 211     return (Status);
 212 }
 213 
 214 
 215 /******************************************************************************
 216  *
 217  * FUNCTION:    AcpiHwWrite
 218  *


 237 
 238 
 239     ACPI_FUNCTION_NAME (HwWrite);
 240 
 241 
 242     /* Validate contents of the GAS register */
 243 
 244     Status = AcpiHwValidateRegister (Reg, 32, &Address);
 245     if (ACPI_FAILURE (Status))
 246     {
 247         return (Status);
 248     }
 249 
 250     /*
 251      * Two address spaces supported: Memory or IO. PCI_Config is
 252      * not supported here because the GAS structure is insufficient
 253      */
 254     if (Reg->SpaceId == ACPI_ADR_SPACE_SYSTEM_MEMORY)
 255     {
 256         Status = AcpiOsWriteMemory ((ACPI_PHYSICAL_ADDRESS)
 257                     Address, Value, Reg->BitWidth);
 258     }
 259     else /* ACPI_ADR_SPACE_SYSTEM_IO, validated earlier */
 260     {
 261         Status = AcpiHwWritePort ((ACPI_IO_ADDRESS)
 262                     Address, Value, Reg->BitWidth);
 263     }
 264 
 265     ACPI_DEBUG_PRINT ((ACPI_DB_IO,
 266         "Wrote: %8.8X width %2d   to %8.8X%8.8X (%s)\n",
 267         Value, Reg->BitWidth, ACPI_FORMAT_UINT64 (Address),
 268         AcpiUtGetRegionName (Reg->SpaceId)));
 269 
 270     return (Status);
 271 }
 272 
 273 

 274 /*******************************************************************************
 275  *
 276  * FUNCTION:    AcpiHwClearAcpiStatus
 277  *
 278  * PARAMETERS:  None
 279  *
 280  * RETURN:      Status
 281  *
 282  * DESCRIPTION: Clears all fixed and general purpose status bits
 283  *
 284  ******************************************************************************/
 285 
 286 ACPI_STATUS
 287 AcpiHwClearAcpiStatus (
 288     void)
 289 {
 290     ACPI_STATUS             Status;
 291     ACPI_CPU_FLAGS          LockFlags = 0;
 292 
 293 


 304 
 305     Status = AcpiHwRegisterWrite (ACPI_REGISTER_PM1_STATUS,
 306                 ACPI_BITMASK_ALL_FIXED_STATUS);
 307     if (ACPI_FAILURE (Status))
 308     {
 309         goto UnlockAndExit;
 310     }
 311 
 312     /* Clear the GPE Bits in all GPE registers in all GPE blocks */
 313 
 314     Status = AcpiEvWalkGpeList (AcpiHwClearGpeBlock, NULL);
 315 
 316 UnlockAndExit:
 317     AcpiOsReleaseLock (AcpiGbl_HardwareLock, LockFlags);
 318     return_ACPI_STATUS (Status);
 319 }
 320 
 321 
 322 /*******************************************************************************
 323  *
 324  * FUNCTION:    AcpiHwGetRegisterBitMask
 325  *
 326  * PARAMETERS:  RegisterId          - Index of ACPI Register to access
 327  *
 328  * RETURN:      The bitmask to be used when accessing the register
 329  *
 330  * DESCRIPTION: Map RegisterId into a register bitmask.
 331  *
 332  ******************************************************************************/
 333 
 334 ACPI_BIT_REGISTER_INFO *
 335 AcpiHwGetBitRegisterInfo (
 336     UINT32                  RegisterId)
 337 {
 338     ACPI_FUNCTION_ENTRY ();
 339 
 340 
 341     if (RegisterId > ACPI_BITREG_MAX)
 342     {
 343         ACPI_ERROR ((AE_INFO, "Invalid BitRegister ID: 0x%X", RegisterId));
 344         return (NULL);


 407 AcpiHwRegisterRead (
 408     UINT32                  RegisterId,
 409     UINT32                  *ReturnValue)
 410 {
 411     UINT32                  Value = 0;
 412     ACPI_STATUS             Status;
 413 
 414 
 415     ACPI_FUNCTION_TRACE (HwRegisterRead);
 416 
 417 
 418     switch (RegisterId)
 419     {
 420     case ACPI_REGISTER_PM1_STATUS:           /* PM1 A/B: 16-bit access each */
 421 
 422         Status = AcpiHwReadMultiple (&Value,
 423                     &AcpiGbl_XPm1aStatus,
 424                     &AcpiGbl_XPm1bStatus);
 425         break;
 426 
 427 
 428     case ACPI_REGISTER_PM1_ENABLE:           /* PM1 A/B: 16-bit access each */
 429 
 430         Status = AcpiHwReadMultiple (&Value,
 431                     &AcpiGbl_XPm1aEnable,
 432                     &AcpiGbl_XPm1bEnable);
 433         break;
 434 
 435 
 436     case ACPI_REGISTER_PM1_CONTROL:          /* PM1 A/B: 16-bit access each */
 437 
 438         Status = AcpiHwReadMultiple (&Value,
 439                     &AcpiGbl_FADT.XPm1aControlBlock,
 440                     &AcpiGbl_FADT.XPm1bControlBlock);
 441 
 442         /*
 443          * Zero the write-only bits. From the ACPI specification, "Hardware
 444          * Write-Only Bits": "Upon reads to registers with write-only bits,
 445          * software masks out all write-only bits."
 446          */
 447         Value &= ~ACPI_PM1_CONTROL_WRITEONLY_BITS;
 448         break;
 449 
 450 
 451     case ACPI_REGISTER_PM2_CONTROL:          /* 8-bit access */
 452 
 453         Status = AcpiHwRead (&Value, &AcpiGbl_FADT.XPm2ControlBlock);
 454         break;
 455 
 456 
 457     case ACPI_REGISTER_PM_TIMER:             /* 32-bit access */
 458 
 459         Status = AcpiHwRead (&Value, &AcpiGbl_FADT.XPmTimerBlock);
 460         break;
 461 
 462 
 463     case ACPI_REGISTER_SMI_COMMAND_BLOCK:    /* 8-bit access */
 464 
 465         Status = AcpiHwReadPort (AcpiGbl_FADT.SmiCommand, &Value, 8);
 466         break;
 467 
 468 
 469     default:

 470         ACPI_ERROR ((AE_INFO, "Unknown Register ID: 0x%X",
 471             RegisterId));
 472         Status = AE_BAD_PARAMETER;
 473         break;
 474     }
 475 
 476     if (ACPI_SUCCESS (Status))
 477     {
 478         *ReturnValue = Value;
 479     }
 480 
 481     return_ACPI_STATUS (Status);
 482 }
 483 
 484 
 485 /******************************************************************************
 486  *
 487  * FUNCTION:    AcpiHwRegisterWrite
 488  *
 489  * PARAMETERS:  RegisterId          - ACPI Register ID


 523     switch (RegisterId)
 524     {
 525     case ACPI_REGISTER_PM1_STATUS:           /* PM1 A/B: 16-bit access each */
 526         /*
 527          * Handle the "ignored" bit in PM1 Status. According to the ACPI
 528          * specification, ignored bits are to be preserved when writing.
 529          * Normally, this would mean a read/modify/write sequence. However,
 530          * preserving a bit in the status register is different. Writing a
 531          * one clears the status, and writing a zero preserves the status.
 532          * Therefore, we must always write zero to the ignored bit.
 533          *
 534          * This behavior is clarified in the ACPI 4.0 specification.
 535          */
 536         Value &= ~ACPI_PM1_STATUS_PRESERVED_BITS;
 537 
 538         Status = AcpiHwWriteMultiple (Value,
 539                     &AcpiGbl_XPm1aStatus,
 540                     &AcpiGbl_XPm1bStatus);
 541         break;
 542 
 543 
 544     case ACPI_REGISTER_PM1_ENABLE:           /* PM1 A/B: 16-bit access each */
 545 
 546         Status = AcpiHwWriteMultiple (Value,
 547                     &AcpiGbl_XPm1aEnable,
 548                     &AcpiGbl_XPm1bEnable);
 549         break;
 550 
 551 
 552     case ACPI_REGISTER_PM1_CONTROL:          /* PM1 A/B: 16-bit access each */
 553 
 554         /*
 555          * Perform a read first to preserve certain bits (per ACPI spec)
 556          * Note: This includes SCI_EN, we never want to change this bit
 557          */
 558         Status = AcpiHwReadMultiple (&ReadValue,
 559                     &AcpiGbl_FADT.XPm1aControlBlock,
 560                     &AcpiGbl_FADT.XPm1bControlBlock);
 561         if (ACPI_FAILURE (Status))
 562         {
 563             goto Exit;
 564         }
 565 
 566         /* Insert the bits to be preserved */
 567 
 568         ACPI_INSERT_BITS (Value, ACPI_PM1_CONTROL_PRESERVED_BITS, ReadValue);
 569 
 570         /* Now we can write the data */
 571 
 572         Status = AcpiHwWriteMultiple (Value,
 573                     &AcpiGbl_FADT.XPm1aControlBlock,
 574                     &AcpiGbl_FADT.XPm1bControlBlock);
 575         break;
 576 
 577 
 578     case ACPI_REGISTER_PM2_CONTROL:          /* 8-bit access */
 579 
 580         /*
 581          * For control registers, all reserved bits must be preserved,
 582          * as per the ACPI spec.
 583          */
 584         Status = AcpiHwRead (&ReadValue, &AcpiGbl_FADT.XPm2ControlBlock);
 585         if (ACPI_FAILURE (Status))
 586         {
 587             goto Exit;
 588         }
 589 
 590         /* Insert the bits to be preserved */
 591 
 592         ACPI_INSERT_BITS (Value, ACPI_PM2_CONTROL_PRESERVED_BITS, ReadValue);
 593 
 594         Status = AcpiHwWrite (Value, &AcpiGbl_FADT.XPm2ControlBlock);
 595         break;
 596 
 597 
 598     case ACPI_REGISTER_PM_TIMER:             /* 32-bit access */
 599 
 600         Status = AcpiHwWrite (Value, &AcpiGbl_FADT.XPmTimerBlock);
 601         break;
 602 
 603 
 604     case ACPI_REGISTER_SMI_COMMAND_BLOCK:    /* 8-bit access */
 605 
 606         /* SMI_CMD is currently always in IO space */
 607 
 608         Status = AcpiHwWritePort (AcpiGbl_FADT.SmiCommand, Value, 8);
 609         break;
 610 
 611 
 612     default:

 613         ACPI_ERROR ((AE_INFO, "Unknown Register ID: 0x%X",
 614             RegisterId));
 615         Status = AE_BAD_PARAMETER;
 616         break;
 617     }
 618 
 619 Exit:
 620     return_ACPI_STATUS (Status);
 621 }
 622 
 623 
 624 /******************************************************************************
 625  *
 626  * FUNCTION:    AcpiHwReadMultiple
 627  *
 628  * PARAMETERS:  Value               - Where the register value is returned
 629  *              RegisterA           - First ACPI register (required)
 630  *              RegisterB           - Second ACPI register (optional)
 631  *
 632  * RETURN:      Status


 714     /*
 715      * Second register is optional
 716      *
 717      * No bit shifting or clearing is necessary, because of how the PM1
 718      * registers are defined in the ACPI specification:
 719      *
 720      * "Although the bits can be split between the two register blocks (each
 721      * register block has a unique pointer within the FADT), the bit positions
 722      * are maintained. The register block with unimplemented bits (that is,
 723      * those implemented in the other register block) always returns zeros,
 724      * and writes have no side effects"
 725      */
 726     if (RegisterB->Address)
 727     {
 728         Status = AcpiHwWrite (Value, RegisterB);
 729     }
 730 
 731     return (Status);
 732 }
 733 


   1 /*******************************************************************************
   2  *
   3  * Module Name: hwregs - Read/write access functions for the various ACPI
   4  *                       control and status registers.
   5  *
   6  ******************************************************************************/
   7 
   8 /*
   9  * Copyright (C) 2000 - 2013, Intel Corp.
  10  * All rights reserved.
  11  *
  12  * Redistribution and use in source and binary forms, with or without
  13  * modification, are permitted provided that the following conditions
  14  * are met:
  15  * 1. Redistributions of source code must retain the above copyright
  16  *    notice, this list of conditions, and the following disclaimer,
  17  *    without modification.
  18  * 2. Redistributions in binary form must reproduce at minimum a disclaimer
  19  *    substantially similar to the "NO WARRANTY" disclaimer below
  20  *    ("Disclaimer") and any redistribution must be conditioned upon
  21  *    including a substantially similar Disclaimer requirement for further
  22  *    binary redistribution.
  23  * 3. Neither the names of the above-listed copyright holders nor the names
  24  *    of any contributors may be used to endorse or promote products derived
  25  *    from this software without specific prior written permission.
  26  *
  27  * Alternatively, this software may be distributed under the terms of the
  28  * GNU General Public License ("GPL") version 2 as published by the Free
  29  * Software Foundation.


  35  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  36  * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  37  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  38  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  39  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
  40  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
  41  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  42  * POSSIBILITY OF SUCH DAMAGES.
  43  */
  44 
  45 #define __HWREGS_C__
  46 
  47 #include "acpi.h"
  48 #include "accommon.h"
  49 #include "acevents.h"
  50 
  51 #define _COMPONENT          ACPI_HARDWARE
  52         ACPI_MODULE_NAME    ("hwregs")
  53 
  54 
  55 #if (!ACPI_REDUCED_HARDWARE)
  56 
  57 /* Local Prototypes */
  58 
  59 static ACPI_STATUS
  60 AcpiHwReadMultiple (
  61     UINT32                  *Value,
  62     ACPI_GENERIC_ADDRESS    *RegisterA,
  63     ACPI_GENERIC_ADDRESS    *RegisterB);
  64 
  65 static ACPI_STATUS
  66 AcpiHwWriteMultiple (
  67     UINT32                  Value,
  68     ACPI_GENERIC_ADDRESS    *RegisterA,
  69     ACPI_GENERIC_ADDRESS    *RegisterB);
  70 
  71 #endif /* !ACPI_REDUCED_HARDWARE */
  72 
  73 /******************************************************************************
  74  *
  75  * FUNCTION:    AcpiHwValidateRegister
  76  *
  77  * PARAMETERS:  Reg                 - GAS register structure
  78  *              MaxBitWidth         - Max BitWidth supported (32 or 64)
  79  *              Address             - Pointer to where the gas->address
  80  *                                    is returned
  81  *
  82  * RETURN:      Status
  83  *
  84  * DESCRIPTION: Validate the contents of a GAS register. Checks the GAS
  85  *              pointer, Address, SpaceId, BitWidth, and BitOffset.
  86  *
  87  ******************************************************************************/
  88 
  89 ACPI_STATUS
  90 AcpiHwValidateRegister (
  91     ACPI_GENERIC_ADDRESS    *Reg,


 155  * RETURN:      Status
 156  *
 157  * DESCRIPTION: Read from either memory or IO space. This is a 32-bit max
 158  *              version of AcpiRead, used internally since the overhead of
 159  *              64-bit values is not needed.
 160  *
 161  * LIMITATIONS: <These limitations also apply to AcpiHwWrite>
 162  *      BitWidth must be exactly 8, 16, or 32.
 163  *      SpaceID must be SystemMemory or SystemIO.
 164  *      BitOffset and AccessWidth are currently ignored, as there has
 165  *          not been a need to implement these.
 166  *
 167  ******************************************************************************/
 168 
 169 ACPI_STATUS
 170 AcpiHwRead (
 171     UINT32                  *Value,
 172     ACPI_GENERIC_ADDRESS    *Reg)
 173 {
 174     UINT64                  Address;
 175     UINT64                  Value64;
 176     ACPI_STATUS             Status;
 177 
 178 
 179     ACPI_FUNCTION_NAME (HwRead);
 180 
 181 
 182     /* Validate contents of the GAS register */
 183 
 184     Status = AcpiHwValidateRegister (Reg, 32, &Address);
 185     if (ACPI_FAILURE (Status))
 186     {
 187         return (Status);
 188     }
 189 
 190     /* Initialize entire 32-bit return value to zero */
 191 
 192     *Value = 0;
 193 
 194     /*
 195      * Two address spaces supported: Memory or IO. PCI_Config is
 196      * not supported here because the GAS structure is insufficient
 197      */
 198     if (Reg->SpaceId == ACPI_ADR_SPACE_SYSTEM_MEMORY)
 199     {
 200         Status = AcpiOsReadMemory ((ACPI_PHYSICAL_ADDRESS)
 201                     Address, &Value64, Reg->BitWidth);
 202 
 203         *Value = (UINT32) Value64;
 204     }
 205     else /* ACPI_ADR_SPACE_SYSTEM_IO, validated earlier */
 206     {
 207         Status = AcpiHwReadPort ((ACPI_IO_ADDRESS)
 208                     Address, Value, Reg->BitWidth);
 209     }
 210 
 211     ACPI_DEBUG_PRINT ((ACPI_DB_IO,
 212         "Read:  %8.8X width %2d from %8.8X%8.8X (%s)\n",
 213         *Value, Reg->BitWidth, ACPI_FORMAT_UINT64 (Address),
 214         AcpiUtGetRegionName (Reg->SpaceId)));
 215 
 216     return (Status);
 217 }
 218 
 219 
 220 /******************************************************************************
 221  *
 222  * FUNCTION:    AcpiHwWrite
 223  *


 242 
 243 
 244     ACPI_FUNCTION_NAME (HwWrite);
 245 
 246 
 247     /* Validate contents of the GAS register */
 248 
 249     Status = AcpiHwValidateRegister (Reg, 32, &Address);
 250     if (ACPI_FAILURE (Status))
 251     {
 252         return (Status);
 253     }
 254 
 255     /*
 256      * Two address spaces supported: Memory or IO. PCI_Config is
 257      * not supported here because the GAS structure is insufficient
 258      */
 259     if (Reg->SpaceId == ACPI_ADR_SPACE_SYSTEM_MEMORY)
 260     {
 261         Status = AcpiOsWriteMemory ((ACPI_PHYSICAL_ADDRESS)
 262                     Address, (UINT64) Value, Reg->BitWidth);
 263     }
 264     else /* ACPI_ADR_SPACE_SYSTEM_IO, validated earlier */
 265     {
 266         Status = AcpiHwWritePort ((ACPI_IO_ADDRESS)
 267                     Address, Value, Reg->BitWidth);
 268     }
 269 
 270     ACPI_DEBUG_PRINT ((ACPI_DB_IO,
 271         "Wrote: %8.8X width %2d   to %8.8X%8.8X (%s)\n",
 272         Value, Reg->BitWidth, ACPI_FORMAT_UINT64 (Address),
 273         AcpiUtGetRegionName (Reg->SpaceId)));
 274 
 275     return (Status);
 276 }
 277 
 278 
 279 #if (!ACPI_REDUCED_HARDWARE)
 280 /*******************************************************************************
 281  *
 282  * FUNCTION:    AcpiHwClearAcpiStatus
 283  *
 284  * PARAMETERS:  None
 285  *
 286  * RETURN:      Status
 287  *
 288  * DESCRIPTION: Clears all fixed and general purpose status bits
 289  *
 290  ******************************************************************************/
 291 
 292 ACPI_STATUS
 293 AcpiHwClearAcpiStatus (
 294     void)
 295 {
 296     ACPI_STATUS             Status;
 297     ACPI_CPU_FLAGS          LockFlags = 0;
 298 
 299 


 310 
 311     Status = AcpiHwRegisterWrite (ACPI_REGISTER_PM1_STATUS,
 312                 ACPI_BITMASK_ALL_FIXED_STATUS);
 313     if (ACPI_FAILURE (Status))
 314     {
 315         goto UnlockAndExit;
 316     }
 317 
 318     /* Clear the GPE Bits in all GPE registers in all GPE blocks */
 319 
 320     Status = AcpiEvWalkGpeList (AcpiHwClearGpeBlock, NULL);
 321 
 322 UnlockAndExit:
 323     AcpiOsReleaseLock (AcpiGbl_HardwareLock, LockFlags);
 324     return_ACPI_STATUS (Status);
 325 }
 326 
 327 
 328 /*******************************************************************************
 329  *
 330  * FUNCTION:    AcpiHwGetBitRegisterInfo
 331  *
 332  * PARAMETERS:  RegisterId          - Index of ACPI Register to access
 333  *
 334  * RETURN:      The bitmask to be used when accessing the register
 335  *
 336  * DESCRIPTION: Map RegisterId into a register bitmask.
 337  *
 338  ******************************************************************************/
 339 
 340 ACPI_BIT_REGISTER_INFO *
 341 AcpiHwGetBitRegisterInfo (
 342     UINT32                  RegisterId)
 343 {
 344     ACPI_FUNCTION_ENTRY ();
 345 
 346 
 347     if (RegisterId > ACPI_BITREG_MAX)
 348     {
 349         ACPI_ERROR ((AE_INFO, "Invalid BitRegister ID: 0x%X", RegisterId));
 350         return (NULL);


 413 AcpiHwRegisterRead (
 414     UINT32                  RegisterId,
 415     UINT32                  *ReturnValue)
 416 {
 417     UINT32                  Value = 0;
 418     ACPI_STATUS             Status;
 419 
 420 
 421     ACPI_FUNCTION_TRACE (HwRegisterRead);
 422 
 423 
 424     switch (RegisterId)
 425     {
 426     case ACPI_REGISTER_PM1_STATUS:           /* PM1 A/B: 16-bit access each */
 427 
 428         Status = AcpiHwReadMultiple (&Value,
 429                     &AcpiGbl_XPm1aStatus,
 430                     &AcpiGbl_XPm1bStatus);
 431         break;
 432 

 433     case ACPI_REGISTER_PM1_ENABLE:           /* PM1 A/B: 16-bit access each */
 434 
 435         Status = AcpiHwReadMultiple (&Value,
 436                     &AcpiGbl_XPm1aEnable,
 437                     &AcpiGbl_XPm1bEnable);
 438         break;
 439 

 440     case ACPI_REGISTER_PM1_CONTROL:          /* PM1 A/B: 16-bit access each */
 441 
 442         Status = AcpiHwReadMultiple (&Value,
 443                     &AcpiGbl_FADT.XPm1aControlBlock,
 444                     &AcpiGbl_FADT.XPm1bControlBlock);
 445 
 446         /*
 447          * Zero the write-only bits. From the ACPI specification, "Hardware
 448          * Write-Only Bits": "Upon reads to registers with write-only bits,
 449          * software masks out all write-only bits."
 450          */
 451         Value &= ~ACPI_PM1_CONTROL_WRITEONLY_BITS;
 452         break;
 453 

 454     case ACPI_REGISTER_PM2_CONTROL:          /* 8-bit access */
 455 
 456         Status = AcpiHwRead (&Value, &AcpiGbl_FADT.XPm2ControlBlock);
 457         break;
 458 

 459     case ACPI_REGISTER_PM_TIMER:             /* 32-bit access */
 460 
 461         Status = AcpiHwRead (&Value, &AcpiGbl_FADT.XPmTimerBlock);
 462         break;
 463 

 464     case ACPI_REGISTER_SMI_COMMAND_BLOCK:    /* 8-bit access */
 465 
 466         Status = AcpiHwReadPort (AcpiGbl_FADT.SmiCommand, &Value, 8);
 467         break;
 468 

 469     default:
 470 
 471         ACPI_ERROR ((AE_INFO, "Unknown Register ID: 0x%X",
 472             RegisterId));
 473         Status = AE_BAD_PARAMETER;
 474         break;
 475     }
 476 
 477     if (ACPI_SUCCESS (Status))
 478     {
 479         *ReturnValue = Value;
 480     }
 481 
 482     return_ACPI_STATUS (Status);
 483 }
 484 
 485 
 486 /******************************************************************************
 487  *
 488  * FUNCTION:    AcpiHwRegisterWrite
 489  *
 490  * PARAMETERS:  RegisterId          - ACPI Register ID


 524     switch (RegisterId)
 525     {
 526     case ACPI_REGISTER_PM1_STATUS:           /* PM1 A/B: 16-bit access each */
 527         /*
 528          * Handle the "ignored" bit in PM1 Status. According to the ACPI
 529          * specification, ignored bits are to be preserved when writing.
 530          * Normally, this would mean a read/modify/write sequence. However,
 531          * preserving a bit in the status register is different. Writing a
 532          * one clears the status, and writing a zero preserves the status.
 533          * Therefore, we must always write zero to the ignored bit.
 534          *
 535          * This behavior is clarified in the ACPI 4.0 specification.
 536          */
 537         Value &= ~ACPI_PM1_STATUS_PRESERVED_BITS;
 538 
 539         Status = AcpiHwWriteMultiple (Value,
 540                     &AcpiGbl_XPm1aStatus,
 541                     &AcpiGbl_XPm1bStatus);
 542         break;
 543 

 544     case ACPI_REGISTER_PM1_ENABLE:           /* PM1 A/B: 16-bit access each */
 545 
 546         Status = AcpiHwWriteMultiple (Value,
 547                     &AcpiGbl_XPm1aEnable,
 548                     &AcpiGbl_XPm1bEnable);
 549         break;
 550 

 551     case ACPI_REGISTER_PM1_CONTROL:          /* PM1 A/B: 16-bit access each */

 552         /*
 553          * Perform a read first to preserve certain bits (per ACPI spec)
 554          * Note: This includes SCI_EN, we never want to change this bit
 555          */
 556         Status = AcpiHwReadMultiple (&ReadValue,
 557                     &AcpiGbl_FADT.XPm1aControlBlock,
 558                     &AcpiGbl_FADT.XPm1bControlBlock);
 559         if (ACPI_FAILURE (Status))
 560         {
 561             goto Exit;
 562         }
 563 
 564         /* Insert the bits to be preserved */
 565 
 566         ACPI_INSERT_BITS (Value, ACPI_PM1_CONTROL_PRESERVED_BITS, ReadValue);
 567 
 568         /* Now we can write the data */
 569 
 570         Status = AcpiHwWriteMultiple (Value,
 571                     &AcpiGbl_FADT.XPm1aControlBlock,
 572                     &AcpiGbl_FADT.XPm1bControlBlock);
 573         break;
 574 

 575     case ACPI_REGISTER_PM2_CONTROL:          /* 8-bit access */

 576         /*
 577          * For control registers, all reserved bits must be preserved,
 578          * as per the ACPI spec.
 579          */
 580         Status = AcpiHwRead (&ReadValue, &AcpiGbl_FADT.XPm2ControlBlock);
 581         if (ACPI_FAILURE (Status))
 582         {
 583             goto Exit;
 584         }
 585 
 586         /* Insert the bits to be preserved */
 587 
 588         ACPI_INSERT_BITS (Value, ACPI_PM2_CONTROL_PRESERVED_BITS, ReadValue);
 589 
 590         Status = AcpiHwWrite (Value, &AcpiGbl_FADT.XPm2ControlBlock);
 591         break;
 592 

 593     case ACPI_REGISTER_PM_TIMER:             /* 32-bit access */
 594 
 595         Status = AcpiHwWrite (Value, &AcpiGbl_FADT.XPmTimerBlock);
 596         break;
 597 

 598     case ACPI_REGISTER_SMI_COMMAND_BLOCK:    /* 8-bit access */
 599 
 600         /* SMI_CMD is currently always in IO space */
 601 
 602         Status = AcpiHwWritePort (AcpiGbl_FADT.SmiCommand, Value, 8);
 603         break;
 604 

 605     default:
 606 
 607         ACPI_ERROR ((AE_INFO, "Unknown Register ID: 0x%X",
 608             RegisterId));
 609         Status = AE_BAD_PARAMETER;
 610         break;
 611     }
 612 
 613 Exit:
 614     return_ACPI_STATUS (Status);
 615 }
 616 
 617 
 618 /******************************************************************************
 619  *
 620  * FUNCTION:    AcpiHwReadMultiple
 621  *
 622  * PARAMETERS:  Value               - Where the register value is returned
 623  *              RegisterA           - First ACPI register (required)
 624  *              RegisterB           - Second ACPI register (optional)
 625  *
 626  * RETURN:      Status


 708     /*
 709      * Second register is optional
 710      *
 711      * No bit shifting or clearing is necessary, because of how the PM1
 712      * registers are defined in the ACPI specification:
 713      *
 714      * "Although the bits can be split between the two register blocks (each
 715      * register block has a unique pointer within the FADT), the bit positions
 716      * are maintained. The register block with unimplemented bits (that is,
 717      * those implemented in the other register block) always returns zeros,
 718      * and writes have no side effects"
 719      */
 720     if (RegisterB->Address)
 721     {
 722         Status = AcpiHwWrite (Value, RegisterB);
 723     }
 724 
 725     return (Status);
 726 }
 727 
 728 #endif /* !ACPI_REDUCED_HARDWARE */