hwregs.c revision 151937
167754Smsmith
267754Smsmith/*******************************************************************************
367754Smsmith *
467754Smsmith * Module Name: hwregs - Read/write access functions for the various ACPI
567754Smsmith *                       control and status registers.
6151937Sjkim *              $Revision: 1.172 $
767754Smsmith *
867754Smsmith ******************************************************************************/
967754Smsmith
1067754Smsmith/******************************************************************************
1167754Smsmith *
1267754Smsmith * 1. Copyright Notice
1367754Smsmith *
14151937Sjkim * Some or all of this work - Copyright (c) 1999 - 2005, Intel Corp.
1570243Smsmith * All rights reserved.
1667754Smsmith *
1767754Smsmith * 2. License
1867754Smsmith *
1967754Smsmith * 2.1. This is your license from Intel Corp. under its intellectual property
2067754Smsmith * rights.  You may have additional license terms from the party that provided
2167754Smsmith * you this software, covering your right to use that party's intellectual
2267754Smsmith * property rights.
2367754Smsmith *
2467754Smsmith * 2.2. Intel grants, free of charge, to any person ("Licensee") obtaining a
2567754Smsmith * copy of the source code appearing in this file ("Covered Code") an
2667754Smsmith * irrevocable, perpetual, worldwide license under Intel's copyrights in the
2767754Smsmith * base code distributed originally by Intel ("Original Intel Code") to copy,
2867754Smsmith * make derivatives, distribute, use and display any portion of the Covered
2967754Smsmith * Code in any form, with the right to sublicense such rights; and
3067754Smsmith *
3167754Smsmith * 2.3. Intel grants Licensee a non-exclusive and non-transferable patent
3267754Smsmith * license (with the right to sublicense), under only those claims of Intel
3367754Smsmith * patents that are infringed by the Original Intel Code, to make, use, sell,
3467754Smsmith * offer to sell, and import the Covered Code and derivative works thereof
3567754Smsmith * solely to the minimum extent necessary to exercise the above copyright
3667754Smsmith * license, and in no event shall the patent license extend to any additions
3767754Smsmith * to or modifications of the Original Intel Code.  No other license or right
3867754Smsmith * is granted directly or by implication, estoppel or otherwise;
3967754Smsmith *
4067754Smsmith * The above copyright and patent license is granted only if the following
4167754Smsmith * conditions are met:
4267754Smsmith *
4367754Smsmith * 3. Conditions
4467754Smsmith *
4567754Smsmith * 3.1. Redistribution of Source with Rights to Further Distribute Source.
4667754Smsmith * Redistribution of source code of any substantial portion of the Covered
4767754Smsmith * Code or modification with rights to further distribute source must include
4867754Smsmith * the above Copyright Notice, the above License, this list of Conditions,
4967754Smsmith * and the following Disclaimer and Export Compliance provision.  In addition,
5067754Smsmith * Licensee must cause all Covered Code to which Licensee contributes to
5167754Smsmith * contain a file documenting the changes Licensee made to create that Covered
5267754Smsmith * Code and the date of any change.  Licensee must include in that file the
5367754Smsmith * documentation of any changes made by any predecessor Licensee.  Licensee
5467754Smsmith * must include a prominent statement that the modification is derived,
5567754Smsmith * directly or indirectly, from Original Intel Code.
5667754Smsmith *
5767754Smsmith * 3.2. Redistribution of Source with no Rights to Further Distribute Source.
5867754Smsmith * Redistribution of source code of any substantial portion of the Covered
5967754Smsmith * Code or modification without rights to further distribute source must
6067754Smsmith * include the following Disclaimer and Export Compliance provision in the
6167754Smsmith * documentation and/or other materials provided with distribution.  In
6267754Smsmith * addition, Licensee may not authorize further sublicense of source of any
6367754Smsmith * portion of the Covered Code, and must include terms to the effect that the
6467754Smsmith * license from Licensee to its licensee is limited to the intellectual
6567754Smsmith * property embodied in the software Licensee provides to its licensee, and
6667754Smsmith * not to intellectual property embodied in modifications its licensee may
6767754Smsmith * make.
6867754Smsmith *
6967754Smsmith * 3.3. Redistribution of Executable. Redistribution in executable form of any
7067754Smsmith * substantial portion of the Covered Code or modification must reproduce the
7167754Smsmith * above Copyright Notice, and the following Disclaimer and Export Compliance
7267754Smsmith * provision in the documentation and/or other materials provided with the
7367754Smsmith * distribution.
7467754Smsmith *
7567754Smsmith * 3.4. Intel retains all right, title, and interest in and to the Original
7667754Smsmith * Intel Code.
7767754Smsmith *
7867754Smsmith * 3.5. Neither the name Intel nor any other trademark owned or controlled by
7967754Smsmith * Intel shall be used in advertising or otherwise to promote the sale, use or
8067754Smsmith * other dealings in products derived from or relating to the Covered Code
8167754Smsmith * without prior written authorization from Intel.
8267754Smsmith *
8367754Smsmith * 4. Disclaimer and Export Compliance
8467754Smsmith *
8567754Smsmith * 4.1. INTEL MAKES NO WARRANTY OF ANY KIND REGARDING ANY SOFTWARE PROVIDED
8667754Smsmith * HERE.  ANY SOFTWARE ORIGINATING FROM INTEL OR DERIVED FROM INTEL SOFTWARE
8767754Smsmith * IS PROVIDED "AS IS," AND INTEL WILL NOT PROVIDE ANY SUPPORT,  ASSISTANCE,
8867754Smsmith * INSTALLATION, TRAINING OR OTHER SERVICES.  INTEL WILL NOT PROVIDE ANY
8967754Smsmith * UPDATES, ENHANCEMENTS OR EXTENSIONS.  INTEL SPECIFICALLY DISCLAIMS ANY
9067754Smsmith * IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT AND FITNESS FOR A
9167754Smsmith * PARTICULAR PURPOSE.
9267754Smsmith *
9367754Smsmith * 4.2. IN NO EVENT SHALL INTEL HAVE ANY LIABILITY TO LICENSEE, ITS LICENSEES
9467754Smsmith * OR ANY OTHER THIRD PARTY, FOR ANY LOST PROFITS, LOST DATA, LOSS OF USE OR
9567754Smsmith * COSTS OF PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, OR FOR ANY INDIRECT,
9667754Smsmith * SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THIS AGREEMENT, UNDER ANY
9767754Smsmith * CAUSE OF ACTION OR THEORY OF LIABILITY, AND IRRESPECTIVE OF WHETHER INTEL
9867754Smsmith * HAS ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES.  THESE LIMITATIONS
9967754Smsmith * SHALL APPLY NOTWITHSTANDING THE FAILURE OF THE ESSENTIAL PURPOSE OF ANY
10067754Smsmith * LIMITED REMEDY.
10167754Smsmith *
10267754Smsmith * 4.3. Licensee shall not export, either directly or indirectly, any of this
10367754Smsmith * software or system incorporating such software without first obtaining any
10467754Smsmith * required license or other approval from the U. S. Department of Commerce or
10567754Smsmith * any other agency or department of the United States Government.  In the
10667754Smsmith * event Licensee exports any such software from the United States or
10767754Smsmith * re-exports any such software from a foreign destination, Licensee shall
10867754Smsmith * ensure that the distribution and export/re-export of the software is in
10967754Smsmith * compliance with all laws, regulations, orders, or other restrictions of the
11067754Smsmith * U.S. Export Administration Regulations. Licensee agrees that neither it nor
11167754Smsmith * any of its subsidiaries will export/re-export any technical data, process,
11267754Smsmith * software, or service, directly or indirectly, to any country for which the
11367754Smsmith * United States government or any agency thereof requires an export license,
11467754Smsmith * other governmental approval, or letter of assurance, without first obtaining
11567754Smsmith * such license, approval or letter.
11667754Smsmith *
11767754Smsmith *****************************************************************************/
11867754Smsmith
11967754Smsmith#define __HWREGS_C__
12067754Smsmith
121151600Sobrien#include <contrib/dev/acpica/acpi.h>
122151600Sobrien#include <contrib/dev/acpica/acnamesp.h>
123151600Sobrien#include <contrib/dev/acpica/acevents.h>
12467754Smsmith
12577424Smsmith#define _COMPONENT          ACPI_HARDWARE
12691116Smsmith        ACPI_MODULE_NAME    ("hwregs")
12767754Smsmith
12867754Smsmith
12967754Smsmith/*******************************************************************************
13067754Smsmith *
13167754Smsmith * FUNCTION:    AcpiHwClearAcpiStatus
13267754Smsmith *
133117521Snjl * PARAMETERS:  Flags           - Lock the hardware or not
13467754Smsmith *
13567754Smsmith * RETURN:      none
13667754Smsmith *
13767754Smsmith * DESCRIPTION: Clears all fixed and general purpose status bits
138138287Smarks *              THIS FUNCTION MUST BE CALLED WITH INTERRUPTS DISABLED
13967754Smsmith *
14067754Smsmith ******************************************************************************/
14167754Smsmith
14299679SiwasakiACPI_STATUS
143117521SnjlAcpiHwClearAcpiStatus (
144117521Snjl    UINT32                  Flags)
14567754Smsmith{
14691116Smsmith    ACPI_STATUS             Status;
14767754Smsmith
14867754Smsmith
14991116Smsmith    ACPI_FUNCTION_TRACE ("HwClearAcpiStatus");
15067754Smsmith
15167754Smsmith
15282367Smsmith    ACPI_DEBUG_PRINT ((ACPI_DB_IO, "About to write %04X to %04X\n",
15391116Smsmith        ACPI_BITMASK_ALL_FIXED_STATUS,
15477424Smsmith        (UINT16) ACPI_GET_ADDRESS (AcpiGbl_FADT->XPm1aEvtBlk.Address)));
15567754Smsmith
156117521Snjl    if (Flags & ACPI_MTX_LOCK)
15791116Smsmith    {
158117521Snjl        Status = AcpiUtAcquireMutex (ACPI_MTX_HARDWARE);
159117521Snjl        if (ACPI_FAILURE (Status))
160117521Snjl        {
161117521Snjl            return_ACPI_STATUS (Status);
162117521Snjl        }
16391116Smsmith    }
16467754Smsmith
165151937Sjkim    Status = AcpiHwRegisterWrite (ACPI_MTX_DO_NOT_LOCK,
166151937Sjkim                ACPI_REGISTER_PM1_STATUS,
167151937Sjkim                ACPI_BITMASK_ALL_FIXED_STATUS);
16899679Siwasaki    if (ACPI_FAILURE (Status))
16999679Siwasaki    {
17099679Siwasaki        goto UnlockAndExit;
17199679Siwasaki    }
17267754Smsmith
17391116Smsmith    /* Clear the fixed events */
17469450Smsmith
17570243Smsmith    if (ACPI_VALID_ADDRESS (AcpiGbl_FADT->XPm1bEvtBlk.Address))
17667754Smsmith    {
17799679Siwasaki        Status = AcpiHwLowLevelWrite (16, ACPI_BITMASK_ALL_FIXED_STATUS,
178117521Snjl                    &AcpiGbl_FADT->XPm1bEvtBlk);
17999679Siwasaki        if (ACPI_FAILURE (Status))
18099679Siwasaki        {
18199679Siwasaki            goto UnlockAndExit;
18299679Siwasaki        }
18367754Smsmith    }
18467754Smsmith
185114237Snjl    /* Clear the GPE Bits in all GPE registers in all GPE blocks */
18667754Smsmith
187151937Sjkim    Status = AcpiEvWalkGpeList (AcpiHwClearGpeBlock);
188117521Snjl
189117521SnjlUnlockAndExit:
190117521Snjl    if (Flags & ACPI_MTX_LOCK)
19167754Smsmith    {
192117521Snjl        (void) AcpiUtReleaseMutex (ACPI_MTX_HARDWARE);
19367754Smsmith    }
19499679Siwasaki    return_ACPI_STATUS (Status);
19567754Smsmith}
19667754Smsmith
19767754Smsmith
19867754Smsmith/*******************************************************************************
19967754Smsmith *
20099679Siwasaki * FUNCTION:    AcpiGetSleepTypeData
20167754Smsmith *
20291116Smsmith * PARAMETERS:  SleepState          - Numeric sleep state
20391116Smsmith *              *SleepTypeA         - Where SLP_TYPa is returned
20491116Smsmith *              *SleepTypeB         - Where SLP_TYPb is returned
20567754Smsmith *
20667754Smsmith * RETURN:      Status - ACPI status
20767754Smsmith *
20891116Smsmith * DESCRIPTION: Obtain the SLP_TYPa and SLP_TYPb values for the requested sleep
20991116Smsmith *              state.
21067754Smsmith *
21167754Smsmith ******************************************************************************/
21267754Smsmith
21367754SmsmithACPI_STATUS
21499679SiwasakiAcpiGetSleepTypeData (
21567754Smsmith    UINT8                   SleepState,
21691116Smsmith    UINT8                   *SleepTypeA,
21791116Smsmith    UINT8                   *SleepTypeB)
21867754Smsmith{
21967754Smsmith    ACPI_STATUS             Status = AE_OK;
220129684Snjl    ACPI_PARAMETER_INFO     Info;
221151937Sjkim    char                    *SleepStateName;
22267754Smsmith
22367754Smsmith
22499679Siwasaki    ACPI_FUNCTION_TRACE ("AcpiGetSleepTypeData");
22567754Smsmith
22667754Smsmith
227151937Sjkim    /* Validate parameters */
228151937Sjkim
22967754Smsmith    if ((SleepState > ACPI_S_STATES_MAX) ||
23091116Smsmith        !SleepTypeA || !SleepTypeB)
23167754Smsmith    {
23267754Smsmith        return_ACPI_STATUS (AE_BAD_PARAMETER);
23367754Smsmith    }
23467754Smsmith
235151937Sjkim    /* Evaluate the namespace object containing the values for this state */
236151937Sjkim
237129684Snjl    Info.Parameters = NULL;
238151937Sjkim    Info.ReturnObject = NULL;
239151937Sjkim    SleepStateName = (char *) AcpiGbl_SleepStateNames[SleepState];
240151937Sjkim
241151937Sjkim    Status = AcpiNsEvaluateByName (SleepStateName, &Info);
24267754Smsmith    if (ACPI_FAILURE (Status))
24367754Smsmith    {
244151937Sjkim        ACPI_DEBUG_PRINT ((ACPI_DB_EXEC,
245151937Sjkim            "%s while evaluating SleepState [%s]\n",
246151937Sjkim            AcpiFormatException (Status), SleepStateName));
247114237Snjl
24867754Smsmith        return_ACPI_STATUS (Status);
24967754Smsmith    }
25067754Smsmith
25199679Siwasaki    /* Must have a return object */
25299679Siwasaki
253129684Snjl    if (!Info.ReturnObject)
25467754Smsmith    {
255151937Sjkim        ACPI_REPORT_ERROR (("No Sleep State object returned from [%s]\n",
256151937Sjkim            SleepStateName));
25799679Siwasaki        Status = AE_NOT_EXIST;
25867754Smsmith    }
25967754Smsmith
26099679Siwasaki    /* It must be of type Package */
26167754Smsmith
262129684Snjl    else if (ACPI_GET_OBJECT_TYPE (Info.ReturnObject) != ACPI_TYPE_PACKAGE)
26399679Siwasaki    {
264151937Sjkim        ACPI_REPORT_ERROR (("Sleep State return object is not a Package\n"));
26599679Siwasaki        Status = AE_AML_OPERAND_TYPE;
26699679Siwasaki    }
26767754Smsmith
268151937Sjkim    /*
269151937Sjkim     * The package must have at least two elements.  NOTE (March 2005): This
270151937Sjkim     * goes against the current ACPI spec which defines this object as a
271151937Sjkim     * package with one encoded DWORD element.  However, existing practice
272151937Sjkim     * by BIOS vendors seems to be to have 2 or more elements, at least
273151937Sjkim     * one per sleep type (A/B).
274151937Sjkim     */
275129684Snjl    else if (Info.ReturnObject->Package.Count < 2)
27667754Smsmith    {
277151937Sjkim        ACPI_REPORT_ERROR ((
278151937Sjkim            "Sleep State return package does not have at least two elements\n"));
27991116Smsmith        Status = AE_AML_NO_OPERAND;
28067754Smsmith    }
28199679Siwasaki
28299679Siwasaki    /* The first two elements must both be of type Integer */
28399679Siwasaki
284151937Sjkim    else if ((ACPI_GET_OBJECT_TYPE (Info.ReturnObject->Package.Elements[0])
285151937Sjkim                != ACPI_TYPE_INTEGER) ||
286151937Sjkim             (ACPI_GET_OBJECT_TYPE (Info.ReturnObject->Package.Elements[1])
287151937Sjkim                != ACPI_TYPE_INTEGER))
28867754Smsmith    {
289151937Sjkim        ACPI_REPORT_ERROR ((
290151937Sjkim            "Sleep State return package elements are not both Integers (%s, %s)\n",
291129684Snjl            AcpiUtGetObjectTypeName (Info.ReturnObject->Package.Elements[0]),
292129684Snjl            AcpiUtGetObjectTypeName (Info.ReturnObject->Package.Elements[1])));
29391116Smsmith        Status = AE_AML_OPERAND_TYPE;
29467754Smsmith    }
29567754Smsmith    else
29667754Smsmith    {
297151937Sjkim        /* Valid _Sx_ package size, type, and value */
298151937Sjkim
299151937Sjkim        *SleepTypeA = (UINT8)
300151937Sjkim            (Info.ReturnObject->Package.Elements[0])->Integer.Value;
301151937Sjkim        *SleepTypeB = (UINT8)
302151937Sjkim            (Info.ReturnObject->Package.Elements[1])->Integer.Value;
30367754Smsmith    }
30467754Smsmith
30567754Smsmith    if (ACPI_FAILURE (Status))
30667754Smsmith    {
307129684Snjl        ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
308151937Sjkim            "%s While evaluating SleepState [%s], bad Sleep object %p type %s\n",
309151937Sjkim            AcpiFormatException (Status),
310151937Sjkim            SleepStateName, Info.ReturnObject,
311129684Snjl            AcpiUtGetObjectTypeName (Info.ReturnObject)));
31267754Smsmith    }
31367754Smsmith
314129684Snjl    AcpiUtRemoveReference (Info.ReturnObject);
31567754Smsmith    return_ACPI_STATUS (Status);
31667754Smsmith}
31767754Smsmith
31867754Smsmith
31967754Smsmith/*******************************************************************************
32067754Smsmith *
32191116Smsmith * FUNCTION:    AcpiHwGetRegisterBitMask
32267754Smsmith *
32399679Siwasaki * PARAMETERS:  RegisterId          - Index of ACPI Register to access
324102550Siwasaki *
325151937Sjkim * RETURN:      The bitmask to be used when accessing the register
32691116Smsmith *
327151937Sjkim * DESCRIPTION: Map RegisterId into a register bitmask.
32891116Smsmith *
32991116Smsmith ******************************************************************************/
33091116Smsmith
33191116SmsmithACPI_BIT_REGISTER_INFO *
33291116SmsmithAcpiHwGetBitRegisterInfo (
33391116Smsmith    UINT32                  RegisterId)
33491116Smsmith{
33591116Smsmith    ACPI_FUNCTION_NAME ("HwGetBitRegisterInfo");
33691116Smsmith
33791116Smsmith
33891116Smsmith    if (RegisterId > ACPI_BITREG_MAX)
33991116Smsmith    {
34091116Smsmith        ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Invalid BitRegister ID: %X\n", RegisterId));
34191116Smsmith        return (NULL);
34291116Smsmith    }
34391116Smsmith
34491116Smsmith    return (&AcpiGbl_BitRegisterInfo[RegisterId]);
34591116Smsmith}
34691116Smsmith
34791116Smsmith
34891116Smsmith/*******************************************************************************
34991116Smsmith *
35099679Siwasaki * FUNCTION:    AcpiGetRegister
35191116Smsmith *
352117521Snjl * PARAMETERS:  RegisterId      - ID of ACPI BitRegister to access
353117521Snjl *              ReturnValue     - Value that was read from the register
354117521Snjl *              Flags           - Lock the hardware or not
35567754Smsmith *
356138287Smarks * RETURN:      Status and the value read from specified Register.  Value
357138287Smarks *              returned is normalized to bit0 (is shifted all the way right)
35867754Smsmith *
35991116Smsmith * DESCRIPTION: ACPI BitRegister read function.
36067754Smsmith *
36167754Smsmith ******************************************************************************/
36267754Smsmith
36399679SiwasakiACPI_STATUS
36499679SiwasakiAcpiGetRegister (
36567754Smsmith    UINT32                  RegisterId,
36699679Siwasaki    UINT32                  *ReturnValue,
36791116Smsmith    UINT32                  Flags)
36867754Smsmith{
36967754Smsmith    UINT32                  RegisterValue = 0;
37091116Smsmith    ACPI_BIT_REGISTER_INFO  *BitRegInfo;
37199679Siwasaki    ACPI_STATUS             Status;
37267754Smsmith
37377424Smsmith
37499679Siwasaki    ACPI_FUNCTION_TRACE ("AcpiGetRegister");
37567754Smsmith
37667754Smsmith
37791116Smsmith    /* Get the info structure corresponding to the requested ACPI Register */
37891116Smsmith
37991116Smsmith    BitRegInfo = AcpiHwGetBitRegisterInfo (RegisterId);
38091116Smsmith    if (!BitRegInfo)
38177424Smsmith    {
38291116Smsmith        return_ACPI_STATUS (AE_BAD_PARAMETER);
38369450Smsmith    }
38467754Smsmith
38599679Siwasaki    if (Flags & ACPI_MTX_LOCK)
38699679Siwasaki    {
38799679Siwasaki        Status = AcpiUtAcquireMutex (ACPI_MTX_HARDWARE);
38899679Siwasaki        if (ACPI_FAILURE (Status))
38999679Siwasaki        {
39099679Siwasaki            return_ACPI_STATUS (Status);
39199679Siwasaki        }
39299679Siwasaki    }
39391116Smsmith
394138287Smarks    /* Read from the register */
395138287Smarks
396102550Siwasaki    Status = AcpiHwRegisterRead (ACPI_MTX_DO_NOT_LOCK,
39799679Siwasaki                    BitRegInfo->ParentRegister, &RegisterValue);
39899679Siwasaki
39991116Smsmith    if (Flags & ACPI_MTX_LOCK)
40067754Smsmith    {
40191116Smsmith        (void) AcpiUtReleaseMutex (ACPI_MTX_HARDWARE);
40291116Smsmith    }
40367754Smsmith
40499679Siwasaki    if (ACPI_SUCCESS (Status))
40599679Siwasaki    {
40699679Siwasaki        /* Normalize the value that was read */
40767754Smsmith
408102550Siwasaki        RegisterValue = ((RegisterValue & BitRegInfo->AccessBitMask)
40999679Siwasaki                            >> BitRegInfo->BitPosition);
41067754Smsmith
41199679Siwasaki        *ReturnValue = RegisterValue;
41299679Siwasaki
413123315Snjl        ACPI_DEBUG_PRINT ((ACPI_DB_IO, "Read value %8.8X register %X\n",
414117521Snjl                RegisterValue, BitRegInfo->ParentRegister));
41599679Siwasaki    }
41699679Siwasaki
41799679Siwasaki    return_ACPI_STATUS (Status);
41891116Smsmith}
41967754Smsmith
42067754Smsmith
42191116Smsmith/*******************************************************************************
42291116Smsmith *
42399679Siwasaki * FUNCTION:    AcpiSetRegister
42491116Smsmith *
42591116Smsmith * PARAMETERS:  RegisterId      - ID of ACPI BitRegister to access
42691116Smsmith *              Value           - (only used on write) value to write to the
427138287Smarks *                                Register, NOT pre-normalized to the bit pos
42891116Smsmith *              Flags           - Lock the hardware or not
42991116Smsmith *
430138287Smarks * RETURN:      Status
43191116Smsmith *
43291116Smsmith * DESCRIPTION: ACPI Bit Register write function.
43391116Smsmith *
43491116Smsmith ******************************************************************************/
43567754Smsmith
43699679SiwasakiACPI_STATUS
43799679SiwasakiAcpiSetRegister (
43891116Smsmith    UINT32                  RegisterId,
43991116Smsmith    UINT32                  Value,
44091116Smsmith    UINT32                  Flags)
44191116Smsmith{
44291116Smsmith    UINT32                  RegisterValue = 0;
44391116Smsmith    ACPI_BIT_REGISTER_INFO  *BitRegInfo;
44499679Siwasaki    ACPI_STATUS             Status;
44567754Smsmith
44667754Smsmith
44799679Siwasaki    ACPI_FUNCTION_TRACE_U32 ("AcpiSetRegister", RegisterId);
44867754Smsmith
44967754Smsmith
45091116Smsmith    /* Get the info structure corresponding to the requested ACPI Register */
45167754Smsmith
45291116Smsmith    BitRegInfo = AcpiHwGetBitRegisterInfo (RegisterId);
45391116Smsmith    if (!BitRegInfo)
45491116Smsmith    {
45599679Siwasaki        ACPI_REPORT_ERROR (("Bad ACPI HW RegisterId: %X\n", RegisterId));
45691116Smsmith        return_ACPI_STATUS (AE_BAD_PARAMETER);
45791116Smsmith    }
45867754Smsmith
45999679Siwasaki    if (Flags & ACPI_MTX_LOCK)
46099679Siwasaki    {
46199679Siwasaki        Status = AcpiUtAcquireMutex (ACPI_MTX_HARDWARE);
46299679Siwasaki        if (ACPI_FAILURE (Status))
46399679Siwasaki        {
46499679Siwasaki            return_ACPI_STATUS (Status);
46599679Siwasaki        }
46699679Siwasaki    }
46799679Siwasaki
46891116Smsmith    /* Always do a register read first so we can insert the new bits  */
46967754Smsmith
470102550Siwasaki    Status = AcpiHwRegisterRead (ACPI_MTX_DO_NOT_LOCK,
471151937Sjkim                BitRegInfo->ParentRegister, &RegisterValue);
47299679Siwasaki    if (ACPI_FAILURE (Status))
47399679Siwasaki    {
47499679Siwasaki        goto UnlockAndExit;
47599679Siwasaki    }
47667754Smsmith
47791116Smsmith    /*
47891116Smsmith     * Decode the Register ID
479123315Snjl     * Register ID = [Register block ID] | [bit ID]
48091116Smsmith     *
481123315Snjl     * Check bit ID to fine locate Register offset.
48291116Smsmith     * Check Mask to determine Register offset, and then read-write.
48391116Smsmith     */
48491116Smsmith    switch (BitRegInfo->ParentRegister)
48591116Smsmith    {
48691116Smsmith    case ACPI_REGISTER_PM1_STATUS:
48767754Smsmith
48891116Smsmith        /*
48991116Smsmith         * Status Registers are different from the rest.  Clear by
490123315Snjl         * writing 1, and writing 0 has no effect.  So, the only relevant
49191116Smsmith         * information is the single bit we're interested in, all others should
492123315Snjl         * be written as 0 so they will be left unchanged.
49391116Smsmith         */
494102550Siwasaki        Value = ACPI_REGISTER_PREPARE_BITS (Value,
49599679Siwasaki                    BitRegInfo->BitPosition, BitRegInfo->AccessBitMask);
49691116Smsmith        if (Value)
49769450Smsmith        {
498102550Siwasaki            Status = AcpiHwRegisterWrite (ACPI_MTX_DO_NOT_LOCK,
49999679Siwasaki                        ACPI_REGISTER_PM1_STATUS, (UINT16) Value);
50091116Smsmith            RegisterValue = 0;
50169450Smsmith        }
50267754Smsmith        break;
50367754Smsmith
50467754Smsmith
50591116Smsmith    case ACPI_REGISTER_PM1_ENABLE:
50667754Smsmith
507102550Siwasaki        ACPI_REGISTER_INSERT_VALUE (RegisterValue, BitRegInfo->BitPosition,
50899679Siwasaki                BitRegInfo->AccessBitMask, Value);
50967754Smsmith
510102550Siwasaki        Status = AcpiHwRegisterWrite (ACPI_MTX_DO_NOT_LOCK,
511151937Sjkim                    ACPI_REGISTER_PM1_ENABLE, (UINT16) RegisterValue);
51291116Smsmith        break;
51367754Smsmith
51467754Smsmith
51591116Smsmith    case ACPI_REGISTER_PM1_CONTROL:
51667754Smsmith
51769450Smsmith        /*
518123315Snjl         * Write the PM1 Control register.
51969450Smsmith         * Note that at this level, the fact that there are actually TWO
520123315Snjl         * registers (A and B - and B may not exist) is abstracted.
52169450Smsmith         */
52282367Smsmith        ACPI_DEBUG_PRINT ((ACPI_DB_IO, "PM1 control: Read %X\n", RegisterValue));
52369450Smsmith
524102550Siwasaki        ACPI_REGISTER_INSERT_VALUE (RegisterValue, BitRegInfo->BitPosition,
52599679Siwasaki                BitRegInfo->AccessBitMask, Value);
52667754Smsmith
527117525Snjl        Status = AcpiHwRegisterWrite (ACPI_MTX_DO_NOT_LOCK,
528151937Sjkim                    ACPI_REGISTER_PM1_CONTROL, (UINT16) RegisterValue);
52967754Smsmith        break;
53067754Smsmith
53167754Smsmith
53291116Smsmith    case ACPI_REGISTER_PM2_CONTROL:
53367754Smsmith
534102550Siwasaki        Status = AcpiHwRegisterRead (ACPI_MTX_DO_NOT_LOCK,
53599679Siwasaki                    ACPI_REGISTER_PM2_CONTROL, &RegisterValue);
53699679Siwasaki        if (ACPI_FAILURE (Status))
53799679Siwasaki        {
53899679Siwasaki            goto UnlockAndExit;
53999679Siwasaki        }
54067754Smsmith
54185756Smsmith        ACPI_DEBUG_PRINT ((ACPI_DB_IO, "PM2 control: Read %X from %8.8X%8.8X\n",
542102550Siwasaki            RegisterValue,
543151937Sjkim            ACPI_FORMAT_UINT64 (ACPI_GET_ADDRESS (
544151937Sjkim                AcpiGbl_FADT->XPm2CntBlk.Address))));
54569450Smsmith
546102550Siwasaki        ACPI_REGISTER_INSERT_VALUE (RegisterValue, BitRegInfo->BitPosition,
54799679Siwasaki                BitRegInfo->AccessBitMask, Value);
54867754Smsmith
54999679Siwasaki        ACPI_DEBUG_PRINT ((ACPI_DB_IO, "About to write %4.4X to %8.8X%8.8X\n",
55085756Smsmith            RegisterValue,
551151937Sjkim            ACPI_FORMAT_UINT64 (ACPI_GET_ADDRESS (
552151937Sjkim                AcpiGbl_FADT->XPm2CntBlk.Address))));
55367754Smsmith
55499679Siwasaki        Status = AcpiHwRegisterWrite (ACPI_MTX_DO_NOT_LOCK,
555151937Sjkim                    ACPI_REGISTER_PM2_CONTROL, (UINT8) (RegisterValue));
55667754Smsmith        break;
55767754Smsmith
55867754Smsmith
55967754Smsmith    default:
56067754Smsmith        break;
56167754Smsmith    }
56267754Smsmith
56399679Siwasaki
56499679SiwasakiUnlockAndExit:
56599679Siwasaki
56691116Smsmith    if (Flags & ACPI_MTX_LOCK)
56791116Smsmith    {
56891116Smsmith        (void) AcpiUtReleaseMutex (ACPI_MTX_HARDWARE);
56969450Smsmith    }
57067754Smsmith
57191116Smsmith    /* Normalize the value that was read */
57269450Smsmith
573151937Sjkim    ACPI_DEBUG_EXEC (RegisterValue =
574151937Sjkim        ((RegisterValue & BitRegInfo->AccessBitMask) >>
575151937Sjkim            BitRegInfo->BitPosition));
57667754Smsmith
577117521Snjl    ACPI_DEBUG_PRINT ((ACPI_DB_IO, "Set bits: %8.8X actual %8.8X register %X\n",
578117521Snjl            Value, RegisterValue, BitRegInfo->ParentRegister));
57999679Siwasaki    return_ACPI_STATUS (Status);
58067754Smsmith}
58169450Smsmith
58269450Smsmith
58369450Smsmith/******************************************************************************
58469450Smsmith *
58569450Smsmith * FUNCTION:    AcpiHwRegisterRead
58669450Smsmith *
587138287Smarks * PARAMETERS:  UseLock             - Mutex hw access
588138287Smarks *              RegisterId          - RegisterID + Offset
589151937Sjkim *              ReturnValue         - Where the register value is returned
59069450Smsmith *
591138287Smarks * RETURN:      Status and the value read.
59269450Smsmith *
59369450Smsmith * DESCRIPTION: Acpi register read function.  Registers are read at the
59469450Smsmith *              given offset.
59569450Smsmith *
59669450Smsmith ******************************************************************************/
59769450Smsmith
59899679SiwasakiACPI_STATUS
59969450SmsmithAcpiHwRegisterRead (
60069450Smsmith    BOOLEAN                 UseLock,
60199679Siwasaki    UINT32                  RegisterId,
60299679Siwasaki    UINT32                  *ReturnValue)
60369450Smsmith{
60499679Siwasaki    UINT32                  Value1 = 0;
60599679Siwasaki    UINT32                  Value2 = 0;
60699679Siwasaki    ACPI_STATUS             Status;
60769450Smsmith
60877424Smsmith
60991116Smsmith    ACPI_FUNCTION_TRACE ("HwRegisterRead");
61069450Smsmith
61177424Smsmith
61269450Smsmith    if (ACPI_MTX_LOCK == UseLock)
61369450Smsmith    {
61499679Siwasaki        Status = AcpiUtAcquireMutex (ACPI_MTX_HARDWARE);
61599679Siwasaki        if (ACPI_FAILURE (Status))
61691116Smsmith        {
61799679Siwasaki            return_ACPI_STATUS (Status);
61891116Smsmith        }
61969450Smsmith    }
62069450Smsmith
62191116Smsmith    switch (RegisterId)
62269450Smsmith    {
62391116Smsmith    case ACPI_REGISTER_PM1_STATUS:           /* 16-bit access */
62469450Smsmith
625117521Snjl        Status = AcpiHwLowLevelRead (16, &Value1, &AcpiGbl_FADT->XPm1aEvtBlk);
62699679Siwasaki        if (ACPI_FAILURE (Status))
62799679Siwasaki        {
62899679Siwasaki            goto UnlockAndExit;
62999679Siwasaki        }
63099679Siwasaki
631117521Snjl        /* PM1B is optional */
632117521Snjl
633117521Snjl        Status = AcpiHwLowLevelRead (16, &Value2, &AcpiGbl_FADT->XPm1bEvtBlk);
63499679Siwasaki        Value1 |= Value2;
63569450Smsmith        break;
63669450Smsmith
63769450Smsmith
638117521Snjl    case ACPI_REGISTER_PM1_ENABLE:           /* 16-bit access */
63969450Smsmith
640117521Snjl        Status = AcpiHwLowLevelRead (16, &Value1, &AcpiGbl_XPm1aEnable);
64199679Siwasaki        if (ACPI_FAILURE (Status))
64299679Siwasaki        {
64399679Siwasaki            goto UnlockAndExit;
64499679Siwasaki        }
64599679Siwasaki
646117521Snjl        /* PM1B is optional */
647117521Snjl
648117521Snjl        Status = AcpiHwLowLevelRead (16, &Value2, &AcpiGbl_XPm1bEnable);
64999679Siwasaki        Value1 |= Value2;
65069450Smsmith        break;
65169450Smsmith
65269450Smsmith
65391116Smsmith    case ACPI_REGISTER_PM1_CONTROL:          /* 16-bit access */
65469450Smsmith
655117521Snjl        Status = AcpiHwLowLevelRead (16, &Value1, &AcpiGbl_FADT->XPm1aCntBlk);
65699679Siwasaki        if (ACPI_FAILURE (Status))
65799679Siwasaki        {
65899679Siwasaki            goto UnlockAndExit;
65999679Siwasaki        }
66099679Siwasaki
661117521Snjl        Status = AcpiHwLowLevelRead (16, &Value2, &AcpiGbl_FADT->XPm1bCntBlk);
66299679Siwasaki        Value1 |= Value2;
66369450Smsmith        break;
66469450Smsmith
66569450Smsmith
66691116Smsmith    case ACPI_REGISTER_PM2_CONTROL:          /* 8-bit access */
66769450Smsmith
668117521Snjl        Status = AcpiHwLowLevelRead (8, &Value1, &AcpiGbl_FADT->XPm2CntBlk);
66969450Smsmith        break;
67069450Smsmith
67169450Smsmith
67291116Smsmith    case ACPI_REGISTER_PM_TIMER:             /* 32-bit access */
67369450Smsmith
674117521Snjl        Status = AcpiHwLowLevelRead (32, &Value1, &AcpiGbl_FADT->XPmTmrBlk);
67569450Smsmith        break;
67669450Smsmith
67791116Smsmith    case ACPI_REGISTER_SMI_COMMAND_BLOCK:    /* 8-bit access */
67869450Smsmith
67999679Siwasaki        Status = AcpiOsReadPort (AcpiGbl_FADT->SmiCmd, &Value1, 8);
68069450Smsmith        break;
68169450Smsmith
68269450Smsmith    default:
683151937Sjkim        ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Unknown Register ID: %X\n",
684151937Sjkim            RegisterId));
68599679Siwasaki        Status = AE_BAD_PARAMETER;
68669450Smsmith        break;
68769450Smsmith    }
68869450Smsmith
68999679SiwasakiUnlockAndExit:
69069450Smsmith    if (ACPI_MTX_LOCK == UseLock)
69169450Smsmith    {
69291116Smsmith        (void) AcpiUtReleaseMutex (ACPI_MTX_HARDWARE);
69369450Smsmith    }
69469450Smsmith
69599679Siwasaki    if (ACPI_SUCCESS (Status))
69699679Siwasaki    {
69799679Siwasaki        *ReturnValue = Value1;
69899679Siwasaki    }
69999679Siwasaki
70099679Siwasaki    return_ACPI_STATUS (Status);
70169450Smsmith}
70269450Smsmith
70369450Smsmith
70469450Smsmith/******************************************************************************
70569450Smsmith *
70669450Smsmith * FUNCTION:    AcpiHwRegisterWrite
70769450Smsmith *
708138287Smarks * PARAMETERS:  UseLock             - Mutex hw access
709138287Smarks *              RegisterId          - RegisterID + Offset
710138287Smarks *              Value               - The value to write
71169450Smsmith *
712138287Smarks * RETURN:      Status
71369450Smsmith *
71469450Smsmith * DESCRIPTION: Acpi register Write function.  Registers are written at the
71569450Smsmith *              given offset.
71669450Smsmith *
71769450Smsmith ******************************************************************************/
71869450Smsmith
71999679SiwasakiACPI_STATUS
72069450SmsmithAcpiHwRegisterWrite (
72169450Smsmith    BOOLEAN                 UseLock,
72269450Smsmith    UINT32                  RegisterId,
72369450Smsmith    UINT32                  Value)
72469450Smsmith{
72599679Siwasaki    ACPI_STATUS             Status;
72669450Smsmith
72769450Smsmith
72891116Smsmith    ACPI_FUNCTION_TRACE ("HwRegisterWrite");
72969450Smsmith
73083174Smsmith
73169450Smsmith    if (ACPI_MTX_LOCK == UseLock)
73269450Smsmith    {
73399679Siwasaki        Status = AcpiUtAcquireMutex (ACPI_MTX_HARDWARE);
73499679Siwasaki        if (ACPI_FAILURE (Status))
73591116Smsmith        {
73699679Siwasaki            return_ACPI_STATUS (Status);
73791116Smsmith        }
73869450Smsmith    }
73969450Smsmith
74091116Smsmith    switch (RegisterId)
74169450Smsmith    {
74291116Smsmith    case ACPI_REGISTER_PM1_STATUS:           /* 16-bit access */
74369450Smsmith
744117521Snjl        Status = AcpiHwLowLevelWrite (16, Value, &AcpiGbl_FADT->XPm1aEvtBlk);
74599679Siwasaki        if (ACPI_FAILURE (Status))
74699679Siwasaki        {
74799679Siwasaki            goto UnlockAndExit;
74899679Siwasaki        }
74999679Siwasaki
750117521Snjl        /* PM1B is optional */
751117521Snjl
752117521Snjl        Status = AcpiHwLowLevelWrite (16, Value, &AcpiGbl_FADT->XPm1bEvtBlk);
75369450Smsmith        break;
75469450Smsmith
75569450Smsmith
75691116Smsmith    case ACPI_REGISTER_PM1_ENABLE:           /* 16-bit access*/
75769450Smsmith
758117521Snjl        Status = AcpiHwLowLevelWrite (16, Value, &AcpiGbl_XPm1aEnable);
75999679Siwasaki        if (ACPI_FAILURE (Status))
76099679Siwasaki        {
76199679Siwasaki            goto UnlockAndExit;
76299679Siwasaki        }
76399679Siwasaki
764117521Snjl        /* PM1B is optional */
765117521Snjl
766117521Snjl        Status = AcpiHwLowLevelWrite (16, Value, &AcpiGbl_XPm1bEnable);
76769450Smsmith        break;
76869450Smsmith
76969450Smsmith
77091116Smsmith    case ACPI_REGISTER_PM1_CONTROL:          /* 16-bit access */
77169450Smsmith
772117521Snjl        Status = AcpiHwLowLevelWrite (16, Value, &AcpiGbl_FADT->XPm1aCntBlk);
77399679Siwasaki        if (ACPI_FAILURE (Status))
77499679Siwasaki        {
77599679Siwasaki            goto UnlockAndExit;
77699679Siwasaki        }
77799679Siwasaki
778117521Snjl        Status = AcpiHwLowLevelWrite (16, Value, &AcpiGbl_FADT->XPm1bCntBlk);
77971867Smsmith        break;
78069450Smsmith
78169450Smsmith
78291116Smsmith    case ACPI_REGISTER_PM1A_CONTROL:         /* 16-bit access */
78369450Smsmith
784117521Snjl        Status = AcpiHwLowLevelWrite (16, Value, &AcpiGbl_FADT->XPm1aCntBlk);
78569450Smsmith        break;
78669450Smsmith
78769450Smsmith
78891116Smsmith    case ACPI_REGISTER_PM1B_CONTROL:         /* 16-bit access */
78971867Smsmith
790117521Snjl        Status = AcpiHwLowLevelWrite (16, Value, &AcpiGbl_FADT->XPm1bCntBlk);
79171867Smsmith        break;
79271867Smsmith
79371867Smsmith
79491116Smsmith    case ACPI_REGISTER_PM2_CONTROL:          /* 8-bit access */
79569450Smsmith
796117521Snjl        Status = AcpiHwLowLevelWrite (8, Value, &AcpiGbl_FADT->XPm2CntBlk);
79769450Smsmith        break;
79869450Smsmith
79969450Smsmith
80091116Smsmith    case ACPI_REGISTER_PM_TIMER:             /* 32-bit access */
80169450Smsmith
802117521Snjl        Status = AcpiHwLowLevelWrite (32, Value, &AcpiGbl_FADT->XPmTmrBlk);
80369450Smsmith        break;
80469450Smsmith
80569450Smsmith
80691116Smsmith    case ACPI_REGISTER_SMI_COMMAND_BLOCK:    /* 8-bit access */
80769450Smsmith
80891116Smsmith        /* SMI_CMD is currently always in IO space */
80969450Smsmith
810117521Snjl        Status = AcpiOsWritePort (AcpiGbl_FADT->SmiCmd, Value, 8);
81169450Smsmith        break;
81269450Smsmith
81369450Smsmith
81469450Smsmith    default:
81599679Siwasaki        Status = AE_BAD_PARAMETER;
81669450Smsmith        break;
81769450Smsmith    }
81869450Smsmith
81999679SiwasakiUnlockAndExit:
82069450Smsmith    if (ACPI_MTX_LOCK == UseLock)
82169450Smsmith    {
82291116Smsmith        (void) AcpiUtReleaseMutex (ACPI_MTX_HARDWARE);
82369450Smsmith    }
82469450Smsmith
82599679Siwasaki    return_ACPI_STATUS (Status);
82669450Smsmith}
82769450Smsmith
82869450Smsmith
82969450Smsmith/******************************************************************************
83069450Smsmith *
83169450Smsmith * FUNCTION:    AcpiHwLowLevelRead
83269450Smsmith *
833117521Snjl * PARAMETERS:  Width               - 8, 16, or 32
834117521Snjl *              Value               - Where the value is returned
835138287Smarks *              Reg                 - GAS register structure
83669450Smsmith *
837117521Snjl * RETURN:      Status
83869450Smsmith *
839138287Smarks * DESCRIPTION: Read from either memory or IO space.
84069450Smsmith *
84169450Smsmith ******************************************************************************/
84269450Smsmith
84399679SiwasakiACPI_STATUS
84469450SmsmithAcpiHwLowLevelRead (
84569450Smsmith    UINT32                  Width,
84699679Siwasaki    UINT32                  *Value,
847117521Snjl    ACPI_GENERIC_ADDRESS    *Reg)
84869450Smsmith{
849138287Smarks    UINT64                  Address;
85099679Siwasaki    ACPI_STATUS             Status;
85169450Smsmith
85269450Smsmith
85399679Siwasaki    ACPI_FUNCTION_NAME ("HwLowLevelRead");
85483174Smsmith
85583174Smsmith
85669450Smsmith    /*
85769450Smsmith     * Must have a valid pointer to a GAS structure, and
85899679Siwasaki     * a non-zero address within. However, don't return an error
85999679Siwasaki     * because the PM1A/B code must not fail if B isn't present.
86069450Smsmith     */
861138287Smarks    if (!Reg)
86269450Smsmith    {
86399679Siwasaki        return (AE_OK);
86469450Smsmith    }
865138287Smarks
866138287Smarks    /* Get a local copy of the address.  Handles possible alignment issues */
867138287Smarks
868138287Smarks    ACPI_MOVE_64_TO_64 (&Address, &Reg->Address);
869138287Smarks    if (!ACPI_VALID_ADDRESS (Address))
870138287Smarks    {
871138287Smarks        return (AE_OK);
872138287Smarks    }
87399679Siwasaki    *Value = 0;
87469450Smsmith
87569450Smsmith    /*
876138287Smarks     * Two address spaces supported: Memory or IO.
877138287Smarks     * PCI_Config is not supported here because the GAS struct is insufficient
87869450Smsmith     */
87969450Smsmith    switch (Reg->AddressSpaceId)
88069450Smsmith    {
88177424Smsmith    case ACPI_ADR_SPACE_SYSTEM_MEMORY:
88269450Smsmith
883117521Snjl        Status = AcpiOsReadMemory (
884138287Smarks                    (ACPI_PHYSICAL_ADDRESS) ACPI_GET_ADDRESS (Address),
885117521Snjl                    Value, Width);
88669450Smsmith        break;
88769450Smsmith
88869450Smsmith
88977424Smsmith    case ACPI_ADR_SPACE_SYSTEM_IO:
89069450Smsmith
891138287Smarks        Status = AcpiOsReadPort ((ACPI_IO_ADDRESS) ACPI_GET_ADDRESS (Address),
892117521Snjl                    Value, Width);
89369450Smsmith        break;
89469450Smsmith
89569450Smsmith
89699679Siwasaki    default:
897117521Snjl        ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
898117521Snjl            "Unsupported address space: %X\n", Reg->AddressSpaceId));
899117521Snjl        return (AE_BAD_PARAMETER);
90069450Smsmith    }
90169450Smsmith
902151937Sjkim    ACPI_DEBUG_PRINT ((ACPI_DB_IO,
903151937Sjkim        "Read:  %8.8X width %2d from %8.8X%8.8X (%s)\n",
904151937Sjkim        *Value, Width,
905151937Sjkim        ACPI_FORMAT_UINT64 (ACPI_GET_ADDRESS (Address)),
906151937Sjkim        AcpiUtGetRegionName (Reg->AddressSpaceId)));
907117521Snjl
90899679Siwasaki    return (Status);
90969450Smsmith}
91069450Smsmith
91169450Smsmith
91269450Smsmith/******************************************************************************
91369450Smsmith *
91469450Smsmith * FUNCTION:    AcpiHwLowLevelWrite
91569450Smsmith *
91669450Smsmith * PARAMETERS:  Width               - 8, 16, or 32
91769450Smsmith *              Value               - To be written
918138287Smarks *              Reg                 - GAS register structure
91969450Smsmith *
920117521Snjl * RETURN:      Status
92169450Smsmith *
922138287Smarks * DESCRIPTION: Write to either memory or IO space.
92369450Smsmith *
92469450Smsmith ******************************************************************************/
92569450Smsmith
92699679SiwasakiACPI_STATUS
92769450SmsmithAcpiHwLowLevelWrite (
92869450Smsmith    UINT32                  Width,
92969450Smsmith    UINT32                  Value,
930117521Snjl    ACPI_GENERIC_ADDRESS    *Reg)
93169450Smsmith{
932138287Smarks    UINT64                  Address;
93399679Siwasaki    ACPI_STATUS             Status;
93469450Smsmith
93569450Smsmith
93699679Siwasaki    ACPI_FUNCTION_NAME ("HwLowLevelWrite");
93783174Smsmith
93883174Smsmith
93969450Smsmith    /*
94069450Smsmith     * Must have a valid pointer to a GAS structure, and
94199679Siwasaki     * a non-zero address within. However, don't return an error
94299679Siwasaki     * because the PM1A/B code must not fail if B isn't present.
94369450Smsmith     */
944138287Smarks    if (!Reg)
94569450Smsmith    {
94699679Siwasaki        return (AE_OK);
94769450Smsmith    }
948123315Snjl
949138287Smarks    /* Get a local copy of the address.  Handles possible alignment issues */
950138287Smarks
951138287Smarks    ACPI_MOVE_64_TO_64 (&Address, &Reg->Address);
952138287Smarks    if (!ACPI_VALID_ADDRESS (Address))
953138287Smarks    {
954138287Smarks        return (AE_OK);
955138287Smarks    }
956138287Smarks
95769450Smsmith    /*
958138287Smarks     * Two address spaces supported: Memory or IO.
959138287Smarks     * PCI_Config is not supported here because the GAS struct is insufficient
96069450Smsmith     */
96169450Smsmith    switch (Reg->AddressSpaceId)
96269450Smsmith    {
96377424Smsmith    case ACPI_ADR_SPACE_SYSTEM_MEMORY:
96469450Smsmith
965117521Snjl        Status = AcpiOsWriteMemory (
966138287Smarks                    (ACPI_PHYSICAL_ADDRESS) ACPI_GET_ADDRESS (Address),
967117521Snjl                    Value, Width);
96869450Smsmith        break;
96969450Smsmith
97069450Smsmith
97177424Smsmith    case ACPI_ADR_SPACE_SYSTEM_IO:
97269450Smsmith
973138287Smarks        Status = AcpiOsWritePort ((ACPI_IO_ADDRESS) ACPI_GET_ADDRESS (Address),
974117521Snjl                    Value, Width);
97569450Smsmith        break;
97669450Smsmith
97769450Smsmith
97899679Siwasaki    default:
979117521Snjl        ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
980117521Snjl            "Unsupported address space: %X\n", Reg->AddressSpaceId));
981117521Snjl        return (AE_BAD_PARAMETER);
98269450Smsmith    }
98399679Siwasaki
984151937Sjkim    ACPI_DEBUG_PRINT ((ACPI_DB_IO,
985151937Sjkim        "Wrote: %8.8X width %2d   to %8.8X%8.8X (%s)\n",
986151937Sjkim        Value, Width,
987151937Sjkim        ACPI_FORMAT_UINT64 (ACPI_GET_ADDRESS (Address)),
988151937Sjkim        AcpiUtGetRegionName (Reg->AddressSpaceId)));
989117521Snjl
99099679Siwasaki    return (Status);
99169450Smsmith}
992