hwregs.c revision 193341
167754Smsmith
267754Smsmith/*******************************************************************************
367754Smsmith *
467754Smsmith * Module Name: hwregs - Read/write access functions for the various ACPI
567754Smsmith *                       control and status registers.
667754Smsmith *
767754Smsmith ******************************************************************************/
867754Smsmith
967754Smsmith/******************************************************************************
1067754Smsmith *
1167754Smsmith * 1. Copyright Notice
1267754Smsmith *
13193267Sjkim * Some or all of this work - Copyright (c) 1999 - 2009, Intel Corp.
1470243Smsmith * All rights reserved.
1567754Smsmith *
1667754Smsmith * 2. License
1767754Smsmith *
1867754Smsmith * 2.1. This is your license from Intel Corp. under its intellectual property
1967754Smsmith * rights.  You may have additional license terms from the party that provided
2067754Smsmith * you this software, covering your right to use that party's intellectual
2167754Smsmith * property rights.
2267754Smsmith *
2367754Smsmith * 2.2. Intel grants, free of charge, to any person ("Licensee") obtaining a
2467754Smsmith * copy of the source code appearing in this file ("Covered Code") an
2567754Smsmith * irrevocable, perpetual, worldwide license under Intel's copyrights in the
2667754Smsmith * base code distributed originally by Intel ("Original Intel Code") to copy,
2767754Smsmith * make derivatives, distribute, use and display any portion of the Covered
2867754Smsmith * Code in any form, with the right to sublicense such rights; and
2967754Smsmith *
3067754Smsmith * 2.3. Intel grants Licensee a non-exclusive and non-transferable patent
3167754Smsmith * license (with the right to sublicense), under only those claims of Intel
3267754Smsmith * patents that are infringed by the Original Intel Code, to make, use, sell,
3367754Smsmith * offer to sell, and import the Covered Code and derivative works thereof
3467754Smsmith * solely to the minimum extent necessary to exercise the above copyright
3567754Smsmith * license, and in no event shall the patent license extend to any additions
3667754Smsmith * to or modifications of the Original Intel Code.  No other license or right
3767754Smsmith * is granted directly or by implication, estoppel or otherwise;
3867754Smsmith *
3967754Smsmith * The above copyright and patent license is granted only if the following
4067754Smsmith * conditions are met:
4167754Smsmith *
4267754Smsmith * 3. Conditions
4367754Smsmith *
4467754Smsmith * 3.1. Redistribution of Source with Rights to Further Distribute Source.
4567754Smsmith * Redistribution of source code of any substantial portion of the Covered
4667754Smsmith * Code or modification with rights to further distribute source must include
4767754Smsmith * the above Copyright Notice, the above License, this list of Conditions,
4867754Smsmith * and the following Disclaimer and Export Compliance provision.  In addition,
4967754Smsmith * Licensee must cause all Covered Code to which Licensee contributes to
5067754Smsmith * contain a file documenting the changes Licensee made to create that Covered
5167754Smsmith * Code and the date of any change.  Licensee must include in that file the
5267754Smsmith * documentation of any changes made by any predecessor Licensee.  Licensee
5367754Smsmith * must include a prominent statement that the modification is derived,
5467754Smsmith * directly or indirectly, from Original Intel Code.
5567754Smsmith *
5667754Smsmith * 3.2. Redistribution of Source with no Rights to Further Distribute Source.
5767754Smsmith * Redistribution of source code of any substantial portion of the Covered
5867754Smsmith * Code or modification without rights to further distribute source must
5967754Smsmith * include the following Disclaimer and Export Compliance provision in the
6067754Smsmith * documentation and/or other materials provided with distribution.  In
6167754Smsmith * addition, Licensee may not authorize further sublicense of source of any
6267754Smsmith * portion of the Covered Code, and must include terms to the effect that the
6367754Smsmith * license from Licensee to its licensee is limited to the intellectual
6467754Smsmith * property embodied in the software Licensee provides to its licensee, and
6567754Smsmith * not to intellectual property embodied in modifications its licensee may
6667754Smsmith * make.
6767754Smsmith *
6867754Smsmith * 3.3. Redistribution of Executable. Redistribution in executable form of any
6967754Smsmith * substantial portion of the Covered Code or modification must reproduce the
7067754Smsmith * above Copyright Notice, and the following Disclaimer and Export Compliance
7167754Smsmith * provision in the documentation and/or other materials provided with the
7267754Smsmith * distribution.
7367754Smsmith *
7467754Smsmith * 3.4. Intel retains all right, title, and interest in and to the Original
7567754Smsmith * Intel Code.
7667754Smsmith *
7767754Smsmith * 3.5. Neither the name Intel nor any other trademark owned or controlled by
7867754Smsmith * Intel shall be used in advertising or otherwise to promote the sale, use or
7967754Smsmith * other dealings in products derived from or relating to the Covered Code
8067754Smsmith * without prior written authorization from Intel.
8167754Smsmith *
8267754Smsmith * 4. Disclaimer and Export Compliance
8367754Smsmith *
8467754Smsmith * 4.1. INTEL MAKES NO WARRANTY OF ANY KIND REGARDING ANY SOFTWARE PROVIDED
8567754Smsmith * HERE.  ANY SOFTWARE ORIGINATING FROM INTEL OR DERIVED FROM INTEL SOFTWARE
8667754Smsmith * IS PROVIDED "AS IS," AND INTEL WILL NOT PROVIDE ANY SUPPORT,  ASSISTANCE,
8767754Smsmith * INSTALLATION, TRAINING OR OTHER SERVICES.  INTEL WILL NOT PROVIDE ANY
8867754Smsmith * UPDATES, ENHANCEMENTS OR EXTENSIONS.  INTEL SPECIFICALLY DISCLAIMS ANY
8967754Smsmith * IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT AND FITNESS FOR A
9067754Smsmith * PARTICULAR PURPOSE.
9167754Smsmith *
9267754Smsmith * 4.2. IN NO EVENT SHALL INTEL HAVE ANY LIABILITY TO LICENSEE, ITS LICENSEES
9367754Smsmith * OR ANY OTHER THIRD PARTY, FOR ANY LOST PROFITS, LOST DATA, LOSS OF USE OR
9467754Smsmith * COSTS OF PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, OR FOR ANY INDIRECT,
9567754Smsmith * SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THIS AGREEMENT, UNDER ANY
9667754Smsmith * CAUSE OF ACTION OR THEORY OF LIABILITY, AND IRRESPECTIVE OF WHETHER INTEL
9767754Smsmith * HAS ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES.  THESE LIMITATIONS
9867754Smsmith * SHALL APPLY NOTWITHSTANDING THE FAILURE OF THE ESSENTIAL PURPOSE OF ANY
9967754Smsmith * LIMITED REMEDY.
10067754Smsmith *
10167754Smsmith * 4.3. Licensee shall not export, either directly or indirectly, any of this
10267754Smsmith * software or system incorporating such software without first obtaining any
10367754Smsmith * required license or other approval from the U. S. Department of Commerce or
10467754Smsmith * any other agency or department of the United States Government.  In the
10567754Smsmith * event Licensee exports any such software from the United States or
10667754Smsmith * re-exports any such software from a foreign destination, Licensee shall
10767754Smsmith * ensure that the distribution and export/re-export of the software is in
10867754Smsmith * compliance with all laws, regulations, orders, or other restrictions of the
10967754Smsmith * U.S. Export Administration Regulations. Licensee agrees that neither it nor
11067754Smsmith * any of its subsidiaries will export/re-export any technical data, process,
11167754Smsmith * software, or service, directly or indirectly, to any country for which the
11267754Smsmith * United States government or any agency thereof requires an export license,
11367754Smsmith * other governmental approval, or letter of assurance, without first obtaining
11467754Smsmith * such license, approval or letter.
11567754Smsmith *
11667754Smsmith *****************************************************************************/
11767754Smsmith
11867754Smsmith#define __HWREGS_C__
11967754Smsmith
120193341Sjkim#include <contrib/dev/acpica/include/acpi.h>
121193341Sjkim#include <contrib/dev/acpica/include/accommon.h>
122193341Sjkim#include <contrib/dev/acpica/include/acevents.h>
12367754Smsmith
12477424Smsmith#define _COMPONENT          ACPI_HARDWARE
12591116Smsmith        ACPI_MODULE_NAME    ("hwregs")
12667754Smsmith
12767754Smsmith
128193267Sjkim/* Local Prototypes */
129193267Sjkim
130193267Sjkimstatic ACPI_STATUS
131193267SjkimAcpiHwReadMultiple (
132193267Sjkim    UINT32                  *Value,
133193267Sjkim    ACPI_GENERIC_ADDRESS    *RegisterA,
134193267Sjkim    ACPI_GENERIC_ADDRESS    *RegisterB);
135193267Sjkim
136193267Sjkimstatic ACPI_STATUS
137193267SjkimAcpiHwWriteMultiple (
138193267Sjkim    UINT32                  Value,
139193267Sjkim    ACPI_GENERIC_ADDRESS    *RegisterA,
140193267Sjkim    ACPI_GENERIC_ADDRESS    *RegisterB);
141193267Sjkim
142193267Sjkim
14367754Smsmith/*******************************************************************************
14467754Smsmith *
14567754Smsmith * FUNCTION:    AcpiHwClearAcpiStatus
14667754Smsmith *
147167802Sjkim * PARAMETERS:  None
14867754Smsmith *
149193267Sjkim * RETURN:      Status
15067754Smsmith *
15167754Smsmith * DESCRIPTION: Clears all fixed and general purpose status bits
15267754Smsmith *
15367754Smsmith ******************************************************************************/
15467754Smsmith
15599679SiwasakiACPI_STATUS
156117521SnjlAcpiHwClearAcpiStatus (
157167802Sjkim    void)
15867754Smsmith{
15991116Smsmith    ACPI_STATUS             Status;
160167802Sjkim    ACPI_CPU_FLAGS          LockFlags = 0;
16167754Smsmith
16267754Smsmith
163167802Sjkim    ACPI_FUNCTION_TRACE (HwClearAcpiStatus);
16467754Smsmith
16567754Smsmith
166193267Sjkim    ACPI_DEBUG_PRINT ((ACPI_DB_IO, "About to write %04X to %8.8X%8.8X\n",
16791116Smsmith        ACPI_BITMASK_ALL_FIXED_STATUS,
168193267Sjkim        ACPI_FORMAT_UINT64 (AcpiGbl_XPm1aStatus.Address)));
16967754Smsmith
170167802Sjkim    LockFlags = AcpiOsAcquireLock (AcpiGbl_HardwareLock);
17167754Smsmith
172193267Sjkim    /* Clear the fixed events in PM1 A/B */
173193267Sjkim
174193267Sjkim    Status = AcpiHwRegisterWrite (ACPI_REGISTER_PM1_STATUS,
175151937Sjkim                ACPI_BITMASK_ALL_FIXED_STATUS);
17699679Siwasaki    if (ACPI_FAILURE (Status))
17799679Siwasaki    {
17899679Siwasaki        goto UnlockAndExit;
17999679Siwasaki    }
18067754Smsmith
181114237Snjl    /* Clear the GPE Bits in all GPE registers in all GPE blocks */
18267754Smsmith
183193267Sjkim    Status = AcpiEvWalkGpeList (AcpiHwClearGpeBlock, NULL);
184117521Snjl
185117521SnjlUnlockAndExit:
186167802Sjkim    AcpiOsReleaseLock (AcpiGbl_HardwareLock, LockFlags);
18799679Siwasaki    return_ACPI_STATUS (Status);
18867754Smsmith}
18967754Smsmith
19067754Smsmith
19167754Smsmith/*******************************************************************************
19267754Smsmith *
19391116Smsmith * FUNCTION:    AcpiHwGetRegisterBitMask
19467754Smsmith *
19599679Siwasaki * PARAMETERS:  RegisterId          - Index of ACPI Register to access
196102550Siwasaki *
197151937Sjkim * RETURN:      The bitmask to be used when accessing the register
19891116Smsmith *
199151937Sjkim * DESCRIPTION: Map RegisterId into a register bitmask.
20091116Smsmith *
20191116Smsmith ******************************************************************************/
20291116Smsmith
20391116SmsmithACPI_BIT_REGISTER_INFO *
20491116SmsmithAcpiHwGetBitRegisterInfo (
20591116Smsmith    UINT32                  RegisterId)
20691116Smsmith{
207167802Sjkim    ACPI_FUNCTION_ENTRY ();
20891116Smsmith
20991116Smsmith
21091116Smsmith    if (RegisterId > ACPI_BITREG_MAX)
21191116Smsmith    {
212167802Sjkim        ACPI_ERROR ((AE_INFO, "Invalid BitRegister ID: %X", RegisterId));
21391116Smsmith        return (NULL);
21491116Smsmith    }
21591116Smsmith
21691116Smsmith    return (&AcpiGbl_BitRegisterInfo[RegisterId]);
21791116Smsmith}
21891116Smsmith
21991116Smsmith
220193267Sjkim/******************************************************************************
22191116Smsmith *
222193267Sjkim * FUNCTION:    AcpiHwWritePm1Control
22391116Smsmith *
224193267Sjkim * PARAMETERS:  Pm1aControl         - Value to be written to PM1A control
225193267Sjkim *              Pm1bControl         - Value to be written to PM1B control
22667754Smsmith *
227138287Smarks * RETURN:      Status
22891116Smsmith *
229193267Sjkim * DESCRIPTION: Write the PM1 A/B control registers. These registers are
230193267Sjkim *              different than than the PM1 A/B status and enable registers
231193267Sjkim *              in that different values can be written to the A/B registers.
232193267Sjkim *              Most notably, the SLP_TYP bits can be different, as per the
233193267Sjkim *              values returned from the _Sx predefined methods.
23491116Smsmith *
23591116Smsmith ******************************************************************************/
23667754Smsmith
23799679SiwasakiACPI_STATUS
238193267SjkimAcpiHwWritePm1Control (
239193267Sjkim    UINT32                  Pm1aControl,
240193267Sjkim    UINT32                  Pm1bControl)
24191116Smsmith{
24299679Siwasaki    ACPI_STATUS             Status;
24367754Smsmith
24467754Smsmith
245193267Sjkim    ACPI_FUNCTION_TRACE (HwWritePm1Control);
24667754Smsmith
24767754Smsmith
248193267Sjkim    Status = AcpiWrite (Pm1aControl, &AcpiGbl_FADT.XPm1aControlBlock);
24999679Siwasaki    if (ACPI_FAILURE (Status))
25099679Siwasaki    {
251193267Sjkim        return_ACPI_STATUS (Status);
25299679Siwasaki    }
25367754Smsmith
254193267Sjkim    if (AcpiGbl_FADT.XPm1bControlBlock.Address)
25591116Smsmith    {
256193267Sjkim        Status = AcpiWrite (Pm1bControl, &AcpiGbl_FADT.XPm1bControlBlock);
25767754Smsmith    }
25899679Siwasaki    return_ACPI_STATUS (Status);
25967754Smsmith}
26069450Smsmith
26169450Smsmith
26269450Smsmith/******************************************************************************
26369450Smsmith *
26469450Smsmith * FUNCTION:    AcpiHwRegisterRead
26569450Smsmith *
266193267Sjkim * PARAMETERS:  RegisterId          - ACPI Register ID
267151937Sjkim *              ReturnValue         - Where the register value is returned
26869450Smsmith *
269138287Smarks * RETURN:      Status and the value read.
27069450Smsmith *
271167802Sjkim * DESCRIPTION: Read from the specified ACPI register
27269450Smsmith *
27369450Smsmith ******************************************************************************/
27469450Smsmith
27599679SiwasakiACPI_STATUS
27669450SmsmithAcpiHwRegisterRead (
27799679Siwasaki    UINT32                  RegisterId,
27899679Siwasaki    UINT32                  *ReturnValue)
27969450Smsmith{
280193267Sjkim    UINT32                  Value = 0;
28199679Siwasaki    ACPI_STATUS             Status;
28269450Smsmith
28377424Smsmith
284167802Sjkim    ACPI_FUNCTION_TRACE (HwRegisterRead);
28569450Smsmith
28677424Smsmith
28791116Smsmith    switch (RegisterId)
28869450Smsmith    {
289193267Sjkim    case ACPI_REGISTER_PM1_STATUS:           /* PM1 A/B: 16-bit access each */
29069450Smsmith
291193267Sjkim        Status = AcpiHwReadMultiple (&Value,
292193267Sjkim                    &AcpiGbl_XPm1aStatus,
293193267Sjkim                    &AcpiGbl_XPm1bStatus);
29469450Smsmith        break;
29569450Smsmith
29669450Smsmith
297193267Sjkim    case ACPI_REGISTER_PM1_ENABLE:           /* PM1 A/B: 16-bit access each */
29869450Smsmith
299193267Sjkim        Status = AcpiHwReadMultiple (&Value,
300193267Sjkim                    &AcpiGbl_XPm1aEnable,
301193267Sjkim                    &AcpiGbl_XPm1bEnable);
30269450Smsmith        break;
30369450Smsmith
30469450Smsmith
305193267Sjkim    case ACPI_REGISTER_PM1_CONTROL:          /* PM1 A/B: 16-bit access each */
30669450Smsmith
307193267Sjkim        Status = AcpiHwReadMultiple (&Value,
308193267Sjkim                    &AcpiGbl_FADT.XPm1aControlBlock,
309193267Sjkim                    &AcpiGbl_FADT.XPm1bControlBlock);
31099679Siwasaki
311193267Sjkim        /*
312193267Sjkim         * Zero the write-only bits. From the ACPI specification, "Hardware
313193267Sjkim         * Write-Only Bits": "Upon reads to registers with write-only bits,
314193267Sjkim         * software masks out all write-only bits."
315193267Sjkim         */
316193267Sjkim        Value &= ~ACPI_PM1_CONTROL_WRITEONLY_BITS;
31769450Smsmith        break;
31869450Smsmith
31969450Smsmith
32091116Smsmith    case ACPI_REGISTER_PM2_CONTROL:          /* 8-bit access */
32169450Smsmith
322193267Sjkim        Status = AcpiRead (&Value, &AcpiGbl_FADT.XPm2ControlBlock);
32369450Smsmith        break;
32469450Smsmith
32569450Smsmith
32691116Smsmith    case ACPI_REGISTER_PM_TIMER:             /* 32-bit access */
32769450Smsmith
328193267Sjkim        Status = AcpiRead (&Value, &AcpiGbl_FADT.XPmTimerBlock);
32969450Smsmith        break;
33069450Smsmith
331193267Sjkim
33291116Smsmith    case ACPI_REGISTER_SMI_COMMAND_BLOCK:    /* 8-bit access */
33369450Smsmith
334193267Sjkim        Status = AcpiHwReadPort (AcpiGbl_FADT.SmiCommand, &Value, 8);
33569450Smsmith        break;
33669450Smsmith
337193267Sjkim
33869450Smsmith    default:
339167802Sjkim        ACPI_ERROR ((AE_INFO, "Unknown Register ID: %X",
340151937Sjkim            RegisterId));
34199679Siwasaki        Status = AE_BAD_PARAMETER;
34269450Smsmith        break;
34369450Smsmith    }
34469450Smsmith
34599679Siwasaki    if (ACPI_SUCCESS (Status))
34699679Siwasaki    {
347193267Sjkim        *ReturnValue = Value;
34899679Siwasaki    }
34999679Siwasaki
35099679Siwasaki    return_ACPI_STATUS (Status);
35169450Smsmith}
35269450Smsmith
35369450Smsmith
35469450Smsmith/******************************************************************************
35569450Smsmith *
35669450Smsmith * FUNCTION:    AcpiHwRegisterWrite
35769450Smsmith *
358193267Sjkim * PARAMETERS:  RegisterId          - ACPI Register ID
359138287Smarks *              Value               - The value to write
36069450Smsmith *
361138287Smarks * RETURN:      Status
36269450Smsmith *
363167802Sjkim * DESCRIPTION: Write to the specified ACPI register
36469450Smsmith *
365167802Sjkim * NOTE: In accordance with the ACPI specification, this function automatically
366167802Sjkim * preserves the value of the following bits, meaning that these bits cannot be
367167802Sjkim * changed via this interface:
368167802Sjkim *
369167802Sjkim * PM1_CONTROL[0] = SCI_EN
370167802Sjkim * PM1_CONTROL[9]
371167802Sjkim * PM1_STATUS[11]
372167802Sjkim *
373167802Sjkim * ACPI References:
374167802Sjkim * 1) Hardware Ignored Bits: When software writes to a register with ignored
375167802Sjkim *      bit fields, it preserves the ignored bit fields
376167802Sjkim * 2) SCI_EN: OSPM always preserves this bit position
377167802Sjkim *
37869450Smsmith ******************************************************************************/
37969450Smsmith
38099679SiwasakiACPI_STATUS
38169450SmsmithAcpiHwRegisterWrite (
38269450Smsmith    UINT32                  RegisterId,
38369450Smsmith    UINT32                  Value)
38469450Smsmith{
38599679Siwasaki    ACPI_STATUS             Status;
386167802Sjkim    UINT32                  ReadValue;
38769450Smsmith
38869450Smsmith
389167802Sjkim    ACPI_FUNCTION_TRACE (HwRegisterWrite);
39069450Smsmith
39183174Smsmith
39291116Smsmith    switch (RegisterId)
39369450Smsmith    {
394193267Sjkim    case ACPI_REGISTER_PM1_STATUS:           /* PM1 A/B: 16-bit access each */
395193267Sjkim        /*
396193267Sjkim         * Handle the "ignored" bit in PM1 Status. According to the ACPI
397193267Sjkim         * specification, ignored bits are to be preserved when writing.
398193267Sjkim         * Normally, this would mean a read/modify/write sequence. However,
399193267Sjkim         * preserving a bit in the status register is different. Writing a
400193267Sjkim         * one clears the status, and writing a zero preserves the status.
401193267Sjkim         * Therefore, we must always write zero to the ignored bit.
402193267Sjkim         *
403193267Sjkim         * This behavior is clarified in the ACPI 4.0 specification.
404193267Sjkim         */
405193267Sjkim        Value &= ~ACPI_PM1_STATUS_PRESERVED_BITS;
40669450Smsmith
407193267Sjkim        Status = AcpiHwWriteMultiple (Value,
408193267Sjkim                    &AcpiGbl_XPm1aStatus,
409193267Sjkim                    &AcpiGbl_XPm1bStatus);
41069450Smsmith        break;
41169450Smsmith
41269450Smsmith
413193267Sjkim    case ACPI_REGISTER_PM1_ENABLE:           /* PM1 A/B: 16-bit access each */
41469450Smsmith
415193267Sjkim        Status = AcpiHwWriteMultiple (Value,
416193267Sjkim                    &AcpiGbl_XPm1aEnable,
417193267Sjkim                    &AcpiGbl_XPm1bEnable);
41869450Smsmith        break;
41969450Smsmith
42069450Smsmith
421193267Sjkim    case ACPI_REGISTER_PM1_CONTROL:          /* PM1 A/B: 16-bit access each */
42269450Smsmith
423167802Sjkim        /*
424167802Sjkim         * Perform a read first to preserve certain bits (per ACPI spec)
425167802Sjkim         * Note: This includes SCI_EN, we never want to change this bit
426167802Sjkim         */
427193267Sjkim        Status = AcpiHwReadMultiple (&ReadValue,
428193267Sjkim                    &AcpiGbl_FADT.XPm1aControlBlock,
429193267Sjkim                    &AcpiGbl_FADT.XPm1bControlBlock);
43099679Siwasaki        if (ACPI_FAILURE (Status))
43199679Siwasaki        {
432193267Sjkim            goto Exit;
43399679Siwasaki        }
43499679Siwasaki
435167802Sjkim        /* Insert the bits to be preserved */
436167802Sjkim
437167802Sjkim        ACPI_INSERT_BITS (Value, ACPI_PM1_CONTROL_PRESERVED_BITS, ReadValue);
438167802Sjkim
439167802Sjkim        /* Now we can write the data */
440167802Sjkim
441193267Sjkim        Status = AcpiHwWriteMultiple (Value,
442193267Sjkim                    &AcpiGbl_FADT.XPm1aControlBlock,
443193267Sjkim                    &AcpiGbl_FADT.XPm1bControlBlock);
44471867Smsmith        break;
44569450Smsmith
44669450Smsmith
447193267Sjkim    case ACPI_REGISTER_PM2_CONTROL:          /* 8-bit access */
44869450Smsmith
449193267Sjkim        /*
450193267Sjkim         * For control registers, all reserved bits must be preserved,
451193267Sjkim         * as per the ACPI spec.
452193267Sjkim         */
453193267Sjkim        Status = AcpiRead (&ReadValue, &AcpiGbl_FADT.XPm2ControlBlock);
454193267Sjkim        if (ACPI_FAILURE (Status))
455193267Sjkim        {
456193267Sjkim            goto Exit;
457193267Sjkim        }
45869450Smsmith
459193267Sjkim        /* Insert the bits to be preserved */
46069450Smsmith
461193267Sjkim        ACPI_INSERT_BITS (Value, ACPI_PM2_CONTROL_PRESERVED_BITS, ReadValue);
46271867Smsmith
463193267Sjkim        Status = AcpiWrite (Value, &AcpiGbl_FADT.XPm2ControlBlock);
46471867Smsmith        break;
46571867Smsmith
46671867Smsmith
46791116Smsmith    case ACPI_REGISTER_PM_TIMER:             /* 32-bit access */
46869450Smsmith
469193267Sjkim        Status = AcpiWrite (Value, &AcpiGbl_FADT.XPmTimerBlock);
47069450Smsmith        break;
47169450Smsmith
47269450Smsmith
47391116Smsmith    case ACPI_REGISTER_SMI_COMMAND_BLOCK:    /* 8-bit access */
47469450Smsmith
47591116Smsmith        /* SMI_CMD is currently always in IO space */
47669450Smsmith
477193267Sjkim        Status = AcpiHwWritePort (AcpiGbl_FADT.SmiCommand, Value, 8);
47869450Smsmith        break;
47969450Smsmith
48069450Smsmith
48169450Smsmith    default:
482193267Sjkim        ACPI_ERROR ((AE_INFO, "Unknown Register ID: %X",
483193267Sjkim            RegisterId));
48499679Siwasaki        Status = AE_BAD_PARAMETER;
48569450Smsmith        break;
48669450Smsmith    }
48769450Smsmith
488193267SjkimExit:
48999679Siwasaki    return_ACPI_STATUS (Status);
49069450Smsmith}
49169450Smsmith
49269450Smsmith
49369450Smsmith/******************************************************************************
49469450Smsmith *
495193267Sjkim * FUNCTION:    AcpiHwReadMultiple
49669450Smsmith *
497193267Sjkim * PARAMETERS:  Value               - Where the register value is returned
498193267Sjkim *              RegisterA           - First ACPI register (required)
499193267Sjkim *              RegisterB           - Second ACPI register (optional)
50069450Smsmith *
501117521Snjl * RETURN:      Status
50269450Smsmith *
503193267Sjkim * DESCRIPTION: Read from the specified two-part ACPI register (such as PM1 A/B)
50469450Smsmith *
50569450Smsmith ******************************************************************************/
50669450Smsmith
507193267Sjkimstatic ACPI_STATUS
508193267SjkimAcpiHwReadMultiple (
50999679Siwasaki    UINT32                  *Value,
510193267Sjkim    ACPI_GENERIC_ADDRESS    *RegisterA,
511193267Sjkim    ACPI_GENERIC_ADDRESS    *RegisterB)
51269450Smsmith{
513193267Sjkim    UINT32                  ValueA = 0;
514193267Sjkim    UINT32                  ValueB = 0;
51599679Siwasaki    ACPI_STATUS             Status;
51669450Smsmith
51769450Smsmith
518193267Sjkim    /* The first register is always required */
51983174Smsmith
520193267Sjkim    Status = AcpiRead (&ValueA, RegisterA);
521193267Sjkim    if (ACPI_FAILURE (Status))
52269450Smsmith    {
523193267Sjkim        return (Status);
52469450Smsmith    }
525138287Smarks
526193267Sjkim    /* Second register is optional */
527138287Smarks
528193267Sjkim    if (RegisterB->Address)
529138287Smarks    {
530193267Sjkim        Status = AcpiRead (&ValueB, RegisterB);
531193267Sjkim        if (ACPI_FAILURE (Status))
532193267Sjkim        {
533193267Sjkim            return (Status);
534193267Sjkim        }
535138287Smarks    }
53669450Smsmith
53769450Smsmith    /*
538193267Sjkim     * OR the two return values together. No shifting or masking is necessary,
539193267Sjkim     * because of how the PM1 registers are defined in the ACPI specification:
540193267Sjkim     *
541193267Sjkim     * "Although the bits can be split between the two register blocks (each
542193267Sjkim     * register block has a unique pointer within the FADT), the bit positions
543193267Sjkim     * are maintained. The register block with unimplemented bits (that is,
544193267Sjkim     * those implemented in the other register block) always returns zeros,
545193267Sjkim     * and writes have no side effects"
54669450Smsmith     */
547193267Sjkim    *Value = (ValueA | ValueB);
548193267Sjkim    return (AE_OK);
54969450Smsmith}
55069450Smsmith
55169450Smsmith
55269450Smsmith/******************************************************************************
55369450Smsmith *
554193267Sjkim * FUNCTION:    AcpiHwWriteMultiple
55569450Smsmith *
556193267Sjkim * PARAMETERS:  Value               - The value to write
557193267Sjkim *              RegisterA           - First ACPI register (required)
558193267Sjkim *              RegisterB           - Second ACPI register (optional)
55969450Smsmith *
560117521Snjl * RETURN:      Status
56169450Smsmith *
562193267Sjkim * DESCRIPTION: Write to the specified two-part ACPI register (such as PM1 A/B)
56369450Smsmith *
56469450Smsmith ******************************************************************************/
56569450Smsmith
566193267Sjkimstatic ACPI_STATUS
567193267SjkimAcpiHwWriteMultiple (
56869450Smsmith    UINT32                  Value,
569193267Sjkim    ACPI_GENERIC_ADDRESS    *RegisterA,
570193267Sjkim    ACPI_GENERIC_ADDRESS    *RegisterB)
57169450Smsmith{
57299679Siwasaki    ACPI_STATUS             Status;
57369450Smsmith
57469450Smsmith
575193267Sjkim    /* The first register is always required */
57683174Smsmith
577193267Sjkim    Status = AcpiWrite (Value, RegisterA);
578193267Sjkim    if (ACPI_FAILURE (Status))
57969450Smsmith    {
580193267Sjkim        return (Status);
58169450Smsmith    }
582123315Snjl
58369450Smsmith    /*
584193267Sjkim     * Second register is optional
585193267Sjkim     *
586193267Sjkim     * No bit shifting or clearing is necessary, because of how the PM1
587193267Sjkim     * registers are defined in the ACPI specification:
588193267Sjkim     *
589193267Sjkim     * "Although the bits can be split between the two register blocks (each
590193267Sjkim     * register block has a unique pointer within the FADT), the bit positions
591193267Sjkim     * are maintained. The register block with unimplemented bits (that is,
592193267Sjkim     * those implemented in the other register block) always returns zeros,
593193267Sjkim     * and writes have no side effects"
59469450Smsmith     */
595193267Sjkim    if (RegisterB->Address)
59669450Smsmith    {
597193267Sjkim        Status = AcpiWrite (Value, RegisterB);
59869450Smsmith    }
59999679Siwasaki
60099679Siwasaki    return (Status);
60169450Smsmith}
602193267Sjkim
603