ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

hwregs.c
Go to the documentation of this file.
00001 
00002 /*******************************************************************************
00003  *
00004  * Module Name: hwregs - Read/write access functions for the various ACPI
00005  *                       control and status registers.
00006  *
00007  ******************************************************************************/
00008 
00009 /******************************************************************************
00010  *
00011  * 1. Copyright Notice
00012  *
00013  * Some or all of this work - Copyright (c) 1999 - 2011, Intel Corp.
00014  * All rights reserved.
00015  *
00016  * 2. License
00017  *
00018  * 2.1. This is your license from Intel Corp. under its intellectual property
00019  * rights.  You may have additional license terms from the party that provided
00020  * you this software, covering your right to use that party's intellectual
00021  * property rights.
00022  *
00023  * 2.2. Intel grants, free of charge, to any person ("Licensee") obtaining a
00024  * copy of the source code appearing in this file ("Covered Code") an
00025  * irrevocable, perpetual, worldwide license under Intel's copyrights in the
00026  * base code distributed originally by Intel ("Original Intel Code") to copy,
00027  * make derivatives, distribute, use and display any portion of the Covered
00028  * Code in any form, with the right to sublicense such rights; and
00029  *
00030  * 2.3. Intel grants Licensee a non-exclusive and non-transferable patent
00031  * license (with the right to sublicense), under only those claims of Intel
00032  * patents that are infringed by the Original Intel Code, to make, use, sell,
00033  * offer to sell, and import the Covered Code and derivative works thereof
00034  * solely to the minimum extent necessary to exercise the above copyright
00035  * license, and in no event shall the patent license extend to any additions
00036  * to or modifications of the Original Intel Code.  No other license or right
00037  * is granted directly or by implication, estoppel or otherwise;
00038  *
00039  * The above copyright and patent license is granted only if the following
00040  * conditions are met:
00041  *
00042  * 3. Conditions
00043  *
00044  * 3.1. Redistribution of Source with Rights to Further Distribute Source.
00045  * Redistribution of source code of any substantial portion of the Covered
00046  * Code or modification with rights to further distribute source must include
00047  * the above Copyright Notice, the above License, this list of Conditions,
00048  * and the following Disclaimer and Export Compliance provision.  In addition,
00049  * Licensee must cause all Covered Code to which Licensee contributes to
00050  * contain a file documenting the changes Licensee made to create that Covered
00051  * Code and the date of any change.  Licensee must include in that file the
00052  * documentation of any changes made by any predecessor Licensee.  Licensee
00053  * must include a prominent statement that the modification is derived,
00054  * directly or indirectly, from Original Intel Code.
00055  *
00056  * 3.2. Redistribution of Source with no Rights to Further Distribute Source.
00057  * Redistribution of source code of any substantial portion of the Covered
00058  * Code or modification without rights to further distribute source must
00059  * include the following Disclaimer and Export Compliance provision in the
00060  * documentation and/or other materials provided with distribution.  In
00061  * addition, Licensee may not authorize further sublicense of source of any
00062  * portion of the Covered Code, and must include terms to the effect that the
00063  * license from Licensee to its licensee is limited to the intellectual
00064  * property embodied in the software Licensee provides to its licensee, and
00065  * not to intellectual property embodied in modifications its licensee may
00066  * make.
00067  *
00068  * 3.3. Redistribution of Executable. Redistribution in executable form of any
00069  * substantial portion of the Covered Code or modification must reproduce the
00070  * above Copyright Notice, and the following Disclaimer and Export Compliance
00071  * provision in the documentation and/or other materials provided with the
00072  * distribution.
00073  *
00074  * 3.4. Intel retains all right, title, and interest in and to the Original
00075  * Intel Code.
00076  *
00077  * 3.5. Neither the name Intel nor any other trademark owned or controlled by
00078  * Intel shall be used in advertising or otherwise to promote the sale, use or
00079  * other dealings in products derived from or relating to the Covered Code
00080  * without prior written authorization from Intel.
00081  *
00082  * 4. Disclaimer and Export Compliance
00083  *
00084  * 4.1. INTEL MAKES NO WARRANTY OF ANY KIND REGARDING ANY SOFTWARE PROVIDED
00085  * HERE.  ANY SOFTWARE ORIGINATING FROM INTEL OR DERIVED FROM INTEL SOFTWARE
00086  * IS PROVIDED "AS IS," AND INTEL WILL NOT PROVIDE ANY SUPPORT,  ASSISTANCE,
00087  * INSTALLATION, TRAINING OR OTHER SERVICES.  INTEL WILL NOT PROVIDE ANY
00088  * UPDATES, ENHANCEMENTS OR EXTENSIONS.  INTEL SPECIFICALLY DISCLAIMS ANY
00089  * IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT AND FITNESS FOR A
00090  * PARTICULAR PURPOSE.
00091  *
00092  * 4.2. IN NO EVENT SHALL INTEL HAVE ANY LIABILITY TO LICENSEE, ITS LICENSEES
00093  * OR ANY OTHER THIRD PARTY, FOR ANY LOST PROFITS, LOST DATA, LOSS OF USE OR
00094  * COSTS OF PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, OR FOR ANY INDIRECT,
00095  * SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THIS AGREEMENT, UNDER ANY
00096  * CAUSE OF ACTION OR THEORY OF LIABILITY, AND IRRESPECTIVE OF WHETHER INTEL
00097  * HAS ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES.  THESE LIMITATIONS
00098  * SHALL APPLY NOTWITHSTANDING THE FAILURE OF THE ESSENTIAL PURPOSE OF ANY
00099  * LIMITED REMEDY.
00100  *
00101  * 4.3. Licensee shall not export, either directly or indirectly, any of this
00102  * software or system incorporating such software without first obtaining any
00103  * required license or other approval from the U. S. Department of Commerce or
00104  * any other agency or department of the United States Government.  In the
00105  * event Licensee exports any such software from the United States or
00106  * re-exports any such software from a foreign destination, Licensee shall
00107  * ensure that the distribution and export/re-export of the software is in
00108  * compliance with all laws, regulations, orders, or other restrictions of the
00109  * U.S. Export Administration Regulations. Licensee agrees that neither it nor
00110  * any of its subsidiaries will export/re-export any technical data, process,
00111  * software, or service, directly or indirectly, to any country for which the
00112  * United States government or any agency thereof requires an export license,
00113  * other governmental approval, or letter of assurance, without first obtaining
00114  * such license, approval or letter.
00115  *
00116  *****************************************************************************/
00117 
00118 #define __HWREGS_C__
00119 
00120 #include "acpi.h"
00121 #include "accommon.h"
00122 #include "acevents.h"
00123 
00124 #define _COMPONENT          ACPI_HARDWARE
00125         ACPI_MODULE_NAME    ("hwregs")
00126 
00127 
00128 /* Local Prototypes */
00129 
00130 static ACPI_STATUS
00131 AcpiHwReadMultiple (
00132     UINT32                  *Value,
00133     ACPI_GENERIC_ADDRESS    *RegisterA,
00134     ACPI_GENERIC_ADDRESS    *RegisterB);
00135 
00136 static ACPI_STATUS
00137 AcpiHwWriteMultiple (
00138     UINT32                  Value,
00139     ACPI_GENERIC_ADDRESS    *RegisterA,
00140     ACPI_GENERIC_ADDRESS    *RegisterB);
00141 
00142 
00143 /******************************************************************************
00144  *
00145  * FUNCTION:    AcpiHwValidateRegister
00146  *
00147  * PARAMETERS:  Reg                 - GAS register structure
00148  *              MaxBitWidth         - Max BitWidth supported (32 or 64)
00149  *              Address             - Pointer to where the gas->address
00150  *                                    is returned
00151  *
00152  * RETURN:      Status
00153  *
00154  * DESCRIPTION: Validate the contents of a GAS register. Checks the GAS
00155  *              pointer, Address, SpaceId, BitWidth, and BitOffset.
00156  *
00157  ******************************************************************************/
00158 
00159 ACPI_STATUS
00160 AcpiHwValidateRegister (
00161     ACPI_GENERIC_ADDRESS    *Reg,
00162     UINT8                   MaxBitWidth,
00163     UINT64                  *Address)
00164 {
00165 
00166     /* Must have a valid pointer to a GAS structure */
00167 
00168     if (!Reg)
00169     {
00170         return (AE_BAD_PARAMETER);
00171     }
00172 
00173     /*
00174      * Copy the target address. This handles possible alignment issues.
00175      * Address must not be null. A null address also indicates an optional
00176      * ACPI register that is not supported, so no error message.
00177      */
00178     ACPI_MOVE_64_TO_64 (Address, &Reg->Address);
00179     if (!(*Address))
00180     {
00181         return (AE_BAD_ADDRESS);
00182     }
00183 
00184     /* Validate the SpaceID */
00185 
00186     if ((Reg->SpaceId != ACPI_ADR_SPACE_SYSTEM_MEMORY) &&
00187         (Reg->SpaceId != ACPI_ADR_SPACE_SYSTEM_IO))
00188     {
00189         ACPI_ERROR ((AE_INFO,
00190             "Unsupported address space: 0x%X", Reg->SpaceId));
00191         return (AE_SUPPORT);
00192     }
00193 
00194     /* Validate the BitWidth */
00195 
00196     if ((Reg->BitWidth != 8) &&
00197         (Reg->BitWidth != 16) &&
00198         (Reg->BitWidth != 32) &&
00199         (Reg->BitWidth != MaxBitWidth))
00200     {
00201         ACPI_ERROR ((AE_INFO,
00202             "Unsupported register bit width: 0x%X", Reg->BitWidth));
00203         return (AE_SUPPORT);
00204     }
00205 
00206     /* Validate the BitOffset. Just a warning for now. */
00207 
00208     if (Reg->BitOffset != 0)
00209     {
00210         ACPI_WARNING ((AE_INFO,
00211             "Unsupported register bit offset: 0x%X", Reg->BitOffset));
00212     }
00213 
00214     return (AE_OK);
00215 }
00216 
00217 
00218 /******************************************************************************
00219  *
00220  * FUNCTION:    AcpiHwRead
00221  *
00222  * PARAMETERS:  Value               - Where the value is returned
00223  *              Reg                 - GAS register structure
00224  *
00225  * RETURN:      Status
00226  *
00227  * DESCRIPTION: Read from either memory or IO space. This is a 32-bit max
00228  *              version of AcpiRead, used internally since the overhead of
00229  *              64-bit values is not needed.
00230  *
00231  * LIMITATIONS: <These limitations also apply to AcpiHwWrite>
00232  *      BitWidth must be exactly 8, 16, or 32.
00233  *      SpaceID must be SystemMemory or SystemIO.
00234  *      BitOffset and AccessWidth are currently ignored, as there has
00235  *          not been a need to implement these.
00236  *
00237  ******************************************************************************/
00238 
00239 ACPI_STATUS
00240 AcpiHwRead (
00241     UINT32                  *Value,
00242     ACPI_GENERIC_ADDRESS    *Reg)
00243 {
00244     UINT64                  Address;
00245     ACPI_STATUS             Status;
00246 
00247 
00248     ACPI_FUNCTION_NAME (HwRead);
00249 
00250 
00251     /* Validate contents of the GAS register */
00252 
00253     Status = AcpiHwValidateRegister (Reg, 32, &Address);
00254     if (ACPI_FAILURE (Status))
00255     {
00256         return (Status);
00257     }
00258 
00259     /* Initialize entire 32-bit return value to zero */
00260 
00261     *Value = 0;
00262 
00263     /*
00264      * Two address spaces supported: Memory or IO. PCI_Config is
00265      * not supported here because the GAS structure is insufficient
00266      */
00267     if (Reg->SpaceId == ACPI_ADR_SPACE_SYSTEM_MEMORY)
00268     {
00269         Status = AcpiOsReadMemory ((ACPI_PHYSICAL_ADDRESS)
00270                     Address, Value, Reg->BitWidth);
00271     }
00272     else /* ACPI_ADR_SPACE_SYSTEM_IO, validated earlier */
00273     {
00274         Status = AcpiHwReadPort ((ACPI_IO_ADDRESS)
00275                     Address, Value, Reg->BitWidth);
00276     }
00277 
00278     ACPI_DEBUG_PRINT ((ACPI_DB_IO,
00279         "Read:  %8.8X width %2d from %8.8X%8.8X (%s)\n",
00280         *Value, Reg->BitWidth, ACPI_FORMAT_UINT64 (Address),
00281         AcpiUtGetRegionName (Reg->SpaceId)));
00282 
00283     return (Status);
00284 }
00285 
00286 
00287 /******************************************************************************
00288  *
00289  * FUNCTION:    AcpiHwWrite
00290  *
00291  * PARAMETERS:  Value               - Value to be written
00292  *              Reg                 - GAS register structure
00293  *
00294  * RETURN:      Status
00295  *
00296  * DESCRIPTION: Write to either memory or IO space. This is a 32-bit max
00297  *              version of AcpiWrite, used internally since the overhead of
00298  *              64-bit values is not needed.
00299  *
00300  ******************************************************************************/
00301 
00302 ACPI_STATUS
00303 AcpiHwWrite (
00304     UINT32                  Value,
00305     ACPI_GENERIC_ADDRESS    *Reg)
00306 {
00307     UINT64                  Address;
00308     ACPI_STATUS             Status;
00309 
00310 
00311     ACPI_FUNCTION_NAME (HwWrite);
00312 
00313 
00314     /* Validate contents of the GAS register */
00315 
00316     Status = AcpiHwValidateRegister (Reg, 32, &Address);
00317     if (ACPI_FAILURE (Status))
00318     {
00319         return (Status);
00320     }
00321 
00322     /*
00323      * Two address spaces supported: Memory or IO. PCI_Config is
00324      * not supported here because the GAS structure is insufficient
00325      */
00326     if (Reg->SpaceId == ACPI_ADR_SPACE_SYSTEM_MEMORY)
00327     {
00328         Status = AcpiOsWriteMemory ((ACPI_PHYSICAL_ADDRESS)
00329                     Address, Value, Reg->BitWidth);
00330     }
00331     else /* ACPI_ADR_SPACE_SYSTEM_IO, validated earlier */
00332     {
00333         Status = AcpiHwWritePort ((ACPI_IO_ADDRESS)
00334                     Address, Value, Reg->BitWidth);
00335     }
00336 
00337     ACPI_DEBUG_PRINT ((ACPI_DB_IO,
00338         "Wrote: %8.8X width %2d   to %8.8X%8.8X (%s)\n",
00339         Value, Reg->BitWidth, ACPI_FORMAT_UINT64 (Address),
00340         AcpiUtGetRegionName (Reg->SpaceId)));
00341 
00342     return (Status);
00343 }
00344 
00345 
00346 /*******************************************************************************
00347  *
00348  * FUNCTION:    AcpiHwClearAcpiStatus
00349  *
00350  * PARAMETERS:  None
00351  *
00352  * RETURN:      Status
00353  *
00354  * DESCRIPTION: Clears all fixed and general purpose status bits
00355  *
00356  ******************************************************************************/
00357 
00358 ACPI_STATUS
00359 AcpiHwClearAcpiStatus (
00360     void)
00361 {
00362     ACPI_STATUS             Status;
00363     ACPI_CPU_FLAGS          LockFlags = 0;
00364 
00365 
00366     ACPI_FUNCTION_TRACE (HwClearAcpiStatus);
00367 
00368 
00369     ACPI_DEBUG_PRINT ((ACPI_DB_IO, "About to write %04X to %8.8X%8.8X\n",
00370         ACPI_BITMASK_ALL_FIXED_STATUS,
00371         ACPI_FORMAT_UINT64 (AcpiGbl_XPm1aStatus.Address)));
00372 
00373     LockFlags = AcpiOsAcquireLock (AcpiGbl_HardwareLock);
00374 
00375     /* Clear the fixed events in PM1 A/B */
00376 
00377     Status = AcpiHwRegisterWrite (ACPI_REGISTER_PM1_STATUS,
00378                 ACPI_BITMASK_ALL_FIXED_STATUS);
00379     if (ACPI_FAILURE (Status))
00380     {
00381         goto UnlockAndExit;
00382     }
00383 
00384     /* Clear the GPE Bits in all GPE registers in all GPE blocks */
00385 
00386     Status = AcpiEvWalkGpeList (AcpiHwClearGpeBlock, NULL);
00387 
00388 UnlockAndExit:
00389     AcpiOsReleaseLock (AcpiGbl_HardwareLock, LockFlags);
00390     return_ACPI_STATUS (Status);
00391 }
00392 
00393 
00394 /*******************************************************************************
00395  *
00396  * FUNCTION:    AcpiHwGetRegisterBitMask
00397  *
00398  * PARAMETERS:  RegisterId          - Index of ACPI Register to access
00399  *
00400  * RETURN:      The bitmask to be used when accessing the register
00401  *
00402  * DESCRIPTION: Map RegisterId into a register bitmask.
00403  *
00404  ******************************************************************************/
00405 
00406 ACPI_BIT_REGISTER_INFO *
00407 AcpiHwGetBitRegisterInfo (
00408     UINT32                  RegisterId)
00409 {
00410     ACPI_FUNCTION_ENTRY ();
00411 
00412 
00413     if (RegisterId > ACPI_BITREG_MAX)
00414     {
00415         ACPI_ERROR ((AE_INFO, "Invalid BitRegister ID: 0x%X", RegisterId));
00416         return (NULL);
00417     }
00418 
00419     return (&AcpiGbl_BitRegisterInfo[RegisterId]);
00420 }
00421 
00422 
00423 /******************************************************************************
00424  *
00425  * FUNCTION:    AcpiHwWritePm1Control
00426  *
00427  * PARAMETERS:  Pm1aControl         - Value to be written to PM1A control
00428  *              Pm1bControl         - Value to be written to PM1B control
00429  *
00430  * RETURN:      Status
00431  *
00432  * DESCRIPTION: Write the PM1 A/B control registers. These registers are
00433  *              different than than the PM1 A/B status and enable registers
00434  *              in that different values can be written to the A/B registers.
00435  *              Most notably, the SLP_TYP bits can be different, as per the
00436  *              values returned from the _Sx predefined methods.
00437  *
00438  ******************************************************************************/
00439 
00440 ACPI_STATUS
00441 AcpiHwWritePm1Control (
00442     UINT32                  Pm1aControl,
00443     UINT32                  Pm1bControl)
00444 {
00445     ACPI_STATUS             Status;
00446 
00447 
00448     ACPI_FUNCTION_TRACE (HwWritePm1Control);
00449 
00450 
00451     Status = AcpiHwWrite (Pm1aControl, &AcpiGbl_FADT.XPm1aControlBlock);
00452     if (ACPI_FAILURE (Status))
00453     {
00454         return_ACPI_STATUS (Status);
00455     }
00456 
00457     if (AcpiGbl_FADT.XPm1bControlBlock.Address)
00458     {
00459         Status = AcpiHwWrite (Pm1bControl, &AcpiGbl_FADT.XPm1bControlBlock);
00460     }
00461     return_ACPI_STATUS (Status);
00462 }
00463 
00464 
00465 /******************************************************************************
00466  *
00467  * FUNCTION:    AcpiHwRegisterRead
00468  *
00469  * PARAMETERS:  RegisterId          - ACPI Register ID
00470  *              ReturnValue         - Where the register value is returned
00471  *
00472  * RETURN:      Status and the value read.
00473  *
00474  * DESCRIPTION: Read from the specified ACPI register
00475  *
00476  ******************************************************************************/
00477 
00478 ACPI_STATUS
00479 AcpiHwRegisterRead (
00480     UINT32                  RegisterId,
00481     UINT32                  *ReturnValue)
00482 {
00483     UINT32                  Value = 0;
00484     ACPI_STATUS             Status;
00485 
00486 
00487     ACPI_FUNCTION_TRACE (HwRegisterRead);
00488 
00489 
00490     switch (RegisterId)
00491     {
00492     case ACPI_REGISTER_PM1_STATUS:           /* PM1 A/B: 16-bit access each */
00493 
00494         Status = AcpiHwReadMultiple (&Value,
00495                     &AcpiGbl_XPm1aStatus,
00496                     &AcpiGbl_XPm1bStatus);
00497         break;
00498 
00499 
00500     case ACPI_REGISTER_PM1_ENABLE:           /* PM1 A/B: 16-bit access each */
00501 
00502         Status = AcpiHwReadMultiple (&Value,
00503                     &AcpiGbl_XPm1aEnable,
00504                     &AcpiGbl_XPm1bEnable);
00505         break;
00506 
00507 
00508     case ACPI_REGISTER_PM1_CONTROL:          /* PM1 A/B: 16-bit access each */
00509 
00510         Status = AcpiHwReadMultiple (&Value,
00511                     &AcpiGbl_FADT.XPm1aControlBlock,
00512                     &AcpiGbl_FADT.XPm1bControlBlock);
00513 
00514         /*
00515          * Zero the write-only bits. From the ACPI specification, "Hardware
00516          * Write-Only Bits": "Upon reads to registers with write-only bits,
00517          * software masks out all write-only bits."
00518          */
00519         Value &= ~ACPI_PM1_CONTROL_WRITEONLY_BITS;
00520         break;
00521 
00522 
00523     case ACPI_REGISTER_PM2_CONTROL:          /* 8-bit access */
00524 
00525         Status = AcpiHwRead (&Value, &AcpiGbl_FADT.XPm2ControlBlock);
00526         break;
00527 
00528 
00529     case ACPI_REGISTER_PM_TIMER:             /* 32-bit access */
00530 
00531         Status = AcpiHwRead (&Value, &AcpiGbl_FADT.XPmTimerBlock);
00532         break;
00533 
00534 
00535     case ACPI_REGISTER_SMI_COMMAND_BLOCK:    /* 8-bit access */
00536 
00537         Status = AcpiHwReadPort (AcpiGbl_FADT.SmiCommand, &Value, 8);
00538         break;
00539 
00540 
00541     default:
00542         ACPI_ERROR ((AE_INFO, "Unknown Register ID: 0x%X",
00543             RegisterId));
00544         Status = AE_BAD_PARAMETER;
00545         break;
00546     }
00547 
00548     if (ACPI_SUCCESS (Status))
00549     {
00550         *ReturnValue = Value;
00551     }
00552 
00553     return_ACPI_STATUS (Status);
00554 }
00555 
00556 
00557 /******************************************************************************
00558  *
00559  * FUNCTION:    AcpiHwRegisterWrite
00560  *
00561  * PARAMETERS:  RegisterId          - ACPI Register ID
00562  *              Value               - The value to write
00563  *
00564  * RETURN:      Status
00565  *
00566  * DESCRIPTION: Write to the specified ACPI register
00567  *
00568  * NOTE: In accordance with the ACPI specification, this function automatically
00569  * preserves the value of the following bits, meaning that these bits cannot be
00570  * changed via this interface:
00571  *
00572  * PM1_CONTROL[0] = SCI_EN
00573  * PM1_CONTROL[9]
00574  * PM1_STATUS[11]
00575  *
00576  * ACPI References:
00577  * 1) Hardware Ignored Bits: When software writes to a register with ignored
00578  *      bit fields, it preserves the ignored bit fields
00579  * 2) SCI_EN: OSPM always preserves this bit position
00580  *
00581  ******************************************************************************/
00582 
00583 ACPI_STATUS
00584 AcpiHwRegisterWrite (
00585     UINT32                  RegisterId,
00586     UINT32                  Value)
00587 {
00588     ACPI_STATUS             Status;
00589     UINT32                  ReadValue;
00590 
00591 
00592     ACPI_FUNCTION_TRACE (HwRegisterWrite);
00593 
00594 
00595     switch (RegisterId)
00596     {
00597     case ACPI_REGISTER_PM1_STATUS:           /* PM1 A/B: 16-bit access each */
00598         /*
00599          * Handle the "ignored" bit in PM1 Status. According to the ACPI
00600          * specification, ignored bits are to be preserved when writing.
00601          * Normally, this would mean a read/modify/write sequence. However,
00602          * preserving a bit in the status register is different. Writing a
00603          * one clears the status, and writing a zero preserves the status.
00604          * Therefore, we must always write zero to the ignored bit.
00605          *
00606          * This behavior is clarified in the ACPI 4.0 specification.
00607          */
00608         Value &= ~ACPI_PM1_STATUS_PRESERVED_BITS;
00609 
00610         Status = AcpiHwWriteMultiple (Value,
00611                     &AcpiGbl_XPm1aStatus,
00612                     &AcpiGbl_XPm1bStatus);
00613         break;
00614 
00615 
00616     case ACPI_REGISTER_PM1_ENABLE:           /* PM1 A/B: 16-bit access each */
00617 
00618         Status = AcpiHwWriteMultiple (Value,
00619                     &AcpiGbl_XPm1aEnable,
00620                     &AcpiGbl_XPm1bEnable);
00621         break;
00622 
00623 
00624     case ACPI_REGISTER_PM1_CONTROL:          /* PM1 A/B: 16-bit access each */
00625 
00626         /*
00627          * Perform a read first to preserve certain bits (per ACPI spec)
00628          * Note: This includes SCI_EN, we never want to change this bit
00629          */
00630         Status = AcpiHwReadMultiple (&ReadValue,
00631                     &AcpiGbl_FADT.XPm1aControlBlock,
00632                     &AcpiGbl_FADT.XPm1bControlBlock);
00633         if (ACPI_FAILURE (Status))
00634         {
00635             goto Exit;
00636         }
00637 
00638         /* Insert the bits to be preserved */
00639 
00640         ACPI_INSERT_BITS (Value, ACPI_PM1_CONTROL_PRESERVED_BITS, ReadValue);
00641 
00642         /* Now we can write the data */
00643 
00644         Status = AcpiHwWriteMultiple (Value,
00645                     &AcpiGbl_FADT.XPm1aControlBlock,
00646                     &AcpiGbl_FADT.XPm1bControlBlock);
00647         break;
00648 
00649 
00650     case ACPI_REGISTER_PM2_CONTROL:          /* 8-bit access */
00651 
00652         /*
00653          * For control registers, all reserved bits must be preserved,
00654          * as per the ACPI spec.
00655          */
00656         Status = AcpiHwRead (&ReadValue, &AcpiGbl_FADT.XPm2ControlBlock);
00657         if (ACPI_FAILURE (Status))
00658         {
00659             goto Exit;
00660         }
00661 
00662         /* Insert the bits to be preserved */
00663 
00664         ACPI_INSERT_BITS (Value, ACPI_PM2_CONTROL_PRESERVED_BITS, ReadValue);
00665 
00666         Status = AcpiHwWrite (Value, &AcpiGbl_FADT.XPm2ControlBlock);
00667         break;
00668 
00669 
00670     case ACPI_REGISTER_PM_TIMER:             /* 32-bit access */
00671 
00672         Status = AcpiHwWrite (Value, &AcpiGbl_FADT.XPmTimerBlock);
00673         break;
00674 
00675 
00676     case ACPI_REGISTER_SMI_COMMAND_BLOCK:    /* 8-bit access */
00677 
00678         /* SMI_CMD is currently always in IO space */
00679 
00680         Status = AcpiHwWritePort (AcpiGbl_FADT.SmiCommand, Value, 8);
00681         break;
00682 
00683 
00684     default:
00685         ACPI_ERROR ((AE_INFO, "Unknown Register ID: 0x%X",
00686             RegisterId));
00687         Status = AE_BAD_PARAMETER;
00688         break;
00689     }
00690 
00691 Exit:
00692     return_ACPI_STATUS (Status);
00693 }
00694 
00695 
00696 /******************************************************************************
00697  *
00698  * FUNCTION:    AcpiHwReadMultiple
00699  *
00700  * PARAMETERS:  Value               - Where the register value is returned
00701  *              RegisterA           - First ACPI register (required)
00702  *              RegisterB           - Second ACPI register (optional)
00703  *
00704  * RETURN:      Status
00705  *
00706  * DESCRIPTION: Read from the specified two-part ACPI register (such as PM1 A/B)
00707  *
00708  ******************************************************************************/
00709 
00710 static ACPI_STATUS
00711 AcpiHwReadMultiple (
00712     UINT32                  *Value,
00713     ACPI_GENERIC_ADDRESS    *RegisterA,
00714     ACPI_GENERIC_ADDRESS    *RegisterB)
00715 {
00716     UINT32                  ValueA = 0;
00717     UINT32                  ValueB = 0;
00718     ACPI_STATUS             Status;
00719 
00720 
00721     /* The first register is always required */
00722 
00723     Status = AcpiHwRead (&ValueA, RegisterA);
00724     if (ACPI_FAILURE (Status))
00725     {
00726         return (Status);
00727     }
00728 
00729     /* Second register is optional */
00730 
00731     if (RegisterB->Address)
00732     {
00733         Status = AcpiHwRead (&ValueB, RegisterB);
00734         if (ACPI_FAILURE (Status))
00735         {
00736             return (Status);
00737         }
00738     }
00739 
00740     /*
00741      * OR the two return values together. No shifting or masking is necessary,
00742      * because of how the PM1 registers are defined in the ACPI specification:
00743      *
00744      * "Although the bits can be split between the two register blocks (each
00745      * register block has a unique pointer within the FADT), the bit positions
00746      * are maintained. The register block with unimplemented bits (that is,
00747      * those implemented in the other register block) always returns zeros,
00748      * and writes have no side effects"
00749      */
00750     *Value = (ValueA | ValueB);
00751     return (AE_OK);
00752 }
00753 
00754 
00755 /******************************************************************************
00756  *
00757  * FUNCTION:    AcpiHwWriteMultiple
00758  *
00759  * PARAMETERS:  Value               - The value to write
00760  *              RegisterA           - First ACPI register (required)
00761  *              RegisterB           - Second ACPI register (optional)
00762  *
00763  * RETURN:      Status
00764  *
00765  * DESCRIPTION: Write to the specified two-part ACPI register (such as PM1 A/B)
00766  *
00767  ******************************************************************************/
00768 
00769 static ACPI_STATUS
00770 AcpiHwWriteMultiple (
00771     UINT32                  Value,
00772     ACPI_GENERIC_ADDRESS    *RegisterA,
00773     ACPI_GENERIC_ADDRESS    *RegisterB)
00774 {
00775     ACPI_STATUS             Status;
00776 
00777 
00778     /* The first register is always required */
00779 
00780     Status = AcpiHwWrite (Value, RegisterA);
00781     if (ACPI_FAILURE (Status))
00782     {
00783         return (Status);
00784     }
00785 
00786     /*
00787      * Second register is optional
00788      *
00789      * No bit shifting or clearing is necessary, because of how the PM1
00790      * registers are defined in the ACPI specification:
00791      *
00792      * "Although the bits can be split between the two register blocks (each
00793      * register block has a unique pointer within the FADT), the bit positions
00794      * are maintained. The register block with unimplemented bits (that is,
00795      * those implemented in the other register block) always returns zeros,
00796      * and writes have no side effects"
00797      */
00798     if (RegisterB->Address)
00799     {
00800         Status = AcpiHwWrite (Value, RegisterB);
00801     }
00802 
00803     return (Status);
00804 }
00805 

Generated on Fri May 25 2012 04:25:32 for ReactOS by doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.