hwregs.c revision 167802
167754Smsmith
267754Smsmith/*******************************************************************************
367754Smsmith *
467754Smsmith * Module Name: hwregs - Read/write access functions for the various ACPI
567754Smsmith *                       control and status registers.
6167802Sjkim *              $Revision: 1.187 $
767754Smsmith *
867754Smsmith ******************************************************************************/
967754Smsmith
1067754Smsmith/******************************************************************************
1167754Smsmith *
1267754Smsmith * 1. Copyright Notice
1367754Smsmith *
14167802Sjkim * Some or all of this work - Copyright (c) 1999 - 2007, 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 *
133167802Sjkim * PARAMETERS:  None
13467754Smsmith *
135167802Sjkim * 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 (
144167802Sjkim    void)
14567754Smsmith{
14691116Smsmith    ACPI_STATUS             Status;
147167802Sjkim    ACPI_CPU_FLAGS          LockFlags = 0;
14867754Smsmith
14967754Smsmith
150167802Sjkim    ACPI_FUNCTION_TRACE (HwClearAcpiStatus);
15167754Smsmith
15267754Smsmith
15382367Smsmith    ACPI_DEBUG_PRINT ((ACPI_DB_IO, "About to write %04X to %04X\n",
15491116Smsmith        ACPI_BITMASK_ALL_FIXED_STATUS,
155167802Sjkim        (UINT16) AcpiGbl_FADT.XPm1aEventBlock.Address));
15667754Smsmith
157167802Sjkim    LockFlags = AcpiOsAcquireLock (AcpiGbl_HardwareLock);
15867754Smsmith
159151937Sjkim    Status = AcpiHwRegisterWrite (ACPI_MTX_DO_NOT_LOCK,
160151937Sjkim                ACPI_REGISTER_PM1_STATUS,
161151937Sjkim                ACPI_BITMASK_ALL_FIXED_STATUS);
16299679Siwasaki    if (ACPI_FAILURE (Status))
16399679Siwasaki    {
16499679Siwasaki        goto UnlockAndExit;
16599679Siwasaki    }
16667754Smsmith
16791116Smsmith    /* Clear the fixed events */
16869450Smsmith
169167802Sjkim    if (AcpiGbl_FADT.XPm1bEventBlock.Address)
17067754Smsmith    {
17199679Siwasaki        Status = AcpiHwLowLevelWrite (16, ACPI_BITMASK_ALL_FIXED_STATUS,
172167802Sjkim                    &AcpiGbl_FADT.XPm1bEventBlock);
17399679Siwasaki        if (ACPI_FAILURE (Status))
17499679Siwasaki        {
17599679Siwasaki            goto UnlockAndExit;
17699679Siwasaki        }
17767754Smsmith    }
17867754Smsmith
179114237Snjl    /* Clear the GPE Bits in all GPE registers in all GPE blocks */
18067754Smsmith
181151937Sjkim    Status = AcpiEvWalkGpeList (AcpiHwClearGpeBlock);
182117521Snjl
183117521SnjlUnlockAndExit:
184167802Sjkim    AcpiOsReleaseLock (AcpiGbl_HardwareLock, LockFlags);
18599679Siwasaki    return_ACPI_STATUS (Status);
18667754Smsmith}
18767754Smsmith
18867754Smsmith
18967754Smsmith/*******************************************************************************
19067754Smsmith *
19199679Siwasaki * FUNCTION:    AcpiGetSleepTypeData
19267754Smsmith *
19391116Smsmith * PARAMETERS:  SleepState          - Numeric sleep state
19491116Smsmith *              *SleepTypeA         - Where SLP_TYPa is returned
19591116Smsmith *              *SleepTypeB         - Where SLP_TYPb is returned
19667754Smsmith *
19767754Smsmith * RETURN:      Status - ACPI status
19867754Smsmith *
19991116Smsmith * DESCRIPTION: Obtain the SLP_TYPa and SLP_TYPb values for the requested sleep
20091116Smsmith *              state.
20167754Smsmith *
20267754Smsmith ******************************************************************************/
20367754Smsmith
20467754SmsmithACPI_STATUS
20599679SiwasakiAcpiGetSleepTypeData (
20667754Smsmith    UINT8                   SleepState,
20791116Smsmith    UINT8                   *SleepTypeA,
20891116Smsmith    UINT8                   *SleepTypeB)
20967754Smsmith{
21067754Smsmith    ACPI_STATUS             Status = AE_OK;
211167802Sjkim    ACPI_EVALUATE_INFO      *Info;
21267754Smsmith
21367754Smsmith
214167802Sjkim    ACPI_FUNCTION_TRACE (AcpiGetSleepTypeData);
21567754Smsmith
21667754Smsmith
217151937Sjkim    /* Validate parameters */
218151937Sjkim
21967754Smsmith    if ((SleepState > ACPI_S_STATES_MAX) ||
22091116Smsmith        !SleepTypeA || !SleepTypeB)
22167754Smsmith    {
22267754Smsmith        return_ACPI_STATUS (AE_BAD_PARAMETER);
22367754Smsmith    }
22467754Smsmith
225167802Sjkim    /* Allocate the evaluation information block */
226167802Sjkim
227167802Sjkim    Info = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_EVALUATE_INFO));
228167802Sjkim    if (!Info)
229167802Sjkim    {
230167802Sjkim        return_ACPI_STATUS (AE_NO_MEMORY);
231167802Sjkim    }
232167802Sjkim
233167802Sjkim    Info->Pathname = ACPI_CAST_PTR (char, AcpiGbl_SleepStateNames[SleepState]);
234167802Sjkim
235151937Sjkim    /* Evaluate the namespace object containing the values for this state */
236151937Sjkim
237167802Sjkim    Status = AcpiNsEvaluate (Info);
23867754Smsmith    if (ACPI_FAILURE (Status))
23967754Smsmith    {
240151937Sjkim        ACPI_DEBUG_PRINT ((ACPI_DB_EXEC,
241151937Sjkim            "%s while evaluating SleepState [%s]\n",
242167802Sjkim            AcpiFormatException (Status), Info->Pathname));
243114237Snjl
244167802Sjkim        goto Cleanup;
24567754Smsmith    }
24667754Smsmith
24799679Siwasaki    /* Must have a return object */
24899679Siwasaki
249167802Sjkim    if (!Info->ReturnObject)
25067754Smsmith    {
251167802Sjkim        ACPI_ERROR ((AE_INFO, "No Sleep State object returned from [%s]",
252167802Sjkim            Info->Pathname));
25399679Siwasaki        Status = AE_NOT_EXIST;
25467754Smsmith    }
25567754Smsmith
25699679Siwasaki    /* It must be of type Package */
25767754Smsmith
258167802Sjkim    else if (ACPI_GET_OBJECT_TYPE (Info->ReturnObject) != ACPI_TYPE_PACKAGE)
25999679Siwasaki    {
260167802Sjkim        ACPI_ERROR ((AE_INFO, "Sleep State return object is not a Package"));
26199679Siwasaki        Status = AE_AML_OPERAND_TYPE;
26299679Siwasaki    }
26367754Smsmith
264151937Sjkim    /*
265167802Sjkim     * The package must have at least two elements. NOTE (March 2005): This
266151937Sjkim     * goes against the current ACPI spec which defines this object as a
267167802Sjkim     * package with one encoded DWORD element. However, existing practice
268151937Sjkim     * by BIOS vendors seems to be to have 2 or more elements, at least
269151937Sjkim     * one per sleep type (A/B).
270151937Sjkim     */
271167802Sjkim    else if (Info->ReturnObject->Package.Count < 2)
27267754Smsmith    {
273167802Sjkim        ACPI_ERROR ((AE_INFO,
274167802Sjkim            "Sleep State return package does not have at least two elements"));
27591116Smsmith        Status = AE_AML_NO_OPERAND;
27667754Smsmith    }
27799679Siwasaki
27899679Siwasaki    /* The first two elements must both be of type Integer */
27999679Siwasaki
280167802Sjkim    else if ((ACPI_GET_OBJECT_TYPE (Info->ReturnObject->Package.Elements[0])
281151937Sjkim                != ACPI_TYPE_INTEGER) ||
282167802Sjkim             (ACPI_GET_OBJECT_TYPE (Info->ReturnObject->Package.Elements[1])
283151937Sjkim                != ACPI_TYPE_INTEGER))
28467754Smsmith    {
285167802Sjkim        ACPI_ERROR ((AE_INFO,
286167802Sjkim            "Sleep State return package elements are not both Integers (%s, %s)",
287167802Sjkim            AcpiUtGetObjectTypeName (Info->ReturnObject->Package.Elements[0]),
288167802Sjkim            AcpiUtGetObjectTypeName (Info->ReturnObject->Package.Elements[1])));
28991116Smsmith        Status = AE_AML_OPERAND_TYPE;
29067754Smsmith    }
29167754Smsmith    else
29267754Smsmith    {
293151937Sjkim        /* Valid _Sx_ package size, type, and value */
294151937Sjkim
295151937Sjkim        *SleepTypeA = (UINT8)
296167802Sjkim            (Info->ReturnObject->Package.Elements[0])->Integer.Value;
297151937Sjkim        *SleepTypeB = (UINT8)
298167802Sjkim            (Info->ReturnObject->Package.Elements[1])->Integer.Value;
29967754Smsmith    }
30067754Smsmith
30167754Smsmith    if (ACPI_FAILURE (Status))
30267754Smsmith    {
303167802Sjkim        ACPI_EXCEPTION ((AE_INFO, Status,
304167802Sjkim            "While evaluating SleepState [%s], bad Sleep object %p type %s",
305167802Sjkim            Info->Pathname, Info->ReturnObject,
306167802Sjkim            AcpiUtGetObjectTypeName (Info->ReturnObject)));
30767754Smsmith    }
30867754Smsmith
309167802Sjkim    AcpiUtRemoveReference (Info->ReturnObject);
310167802Sjkim
311167802SjkimCleanup:
312167802Sjkim    ACPI_FREE (Info);
31367754Smsmith    return_ACPI_STATUS (Status);
31467754Smsmith}
31567754Smsmith
316167802SjkimACPI_EXPORT_SYMBOL (AcpiGetSleepTypeData)
31767754Smsmith
318167802Sjkim
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{
335167802Sjkim    ACPI_FUNCTION_ENTRY ();
33691116Smsmith
33791116Smsmith
33891116Smsmith    if (RegisterId > ACPI_BITREG_MAX)
33991116Smsmith    {
340167802Sjkim        ACPI_ERROR ((AE_INFO, "Invalid BitRegister ID: %X", 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
35467754Smsmith *
355167802Sjkim * RETURN:      Status and the value read from specified Register. Value
356138287Smarks *              returned is normalized to bit0 (is shifted all the way right)
35767754Smsmith *
35891116Smsmith * DESCRIPTION: ACPI BitRegister read function.
35967754Smsmith *
36067754Smsmith ******************************************************************************/
36167754Smsmith
36299679SiwasakiACPI_STATUS
36399679SiwasakiAcpiGetRegister (
36467754Smsmith    UINT32                  RegisterId,
365167802Sjkim    UINT32                  *ReturnValue)
36667754Smsmith{
36767754Smsmith    UINT32                  RegisterValue = 0;
36891116Smsmith    ACPI_BIT_REGISTER_INFO  *BitRegInfo;
36999679Siwasaki    ACPI_STATUS             Status;
37067754Smsmith
37177424Smsmith
372167802Sjkim    ACPI_FUNCTION_TRACE (AcpiGetRegister);
37367754Smsmith
37467754Smsmith
37591116Smsmith    /* Get the info structure corresponding to the requested ACPI Register */
37691116Smsmith
37791116Smsmith    BitRegInfo = AcpiHwGetBitRegisterInfo (RegisterId);
37891116Smsmith    if (!BitRegInfo)
37977424Smsmith    {
38091116Smsmith        return_ACPI_STATUS (AE_BAD_PARAMETER);
38169450Smsmith    }
38267754Smsmith
383138287Smarks    /* Read from the register */
384138287Smarks
385167802Sjkim    Status = AcpiHwRegisterRead (ACPI_MTX_LOCK,
386167802Sjkim                BitRegInfo->ParentRegister, &RegisterValue);
38799679Siwasaki
38899679Siwasaki    if (ACPI_SUCCESS (Status))
38999679Siwasaki    {
39099679Siwasaki        /* Normalize the value that was read */
39167754Smsmith
392102550Siwasaki        RegisterValue = ((RegisterValue & BitRegInfo->AccessBitMask)
39399679Siwasaki                            >> BitRegInfo->BitPosition);
39467754Smsmith
39599679Siwasaki        *ReturnValue = RegisterValue;
39699679Siwasaki
397123315Snjl        ACPI_DEBUG_PRINT ((ACPI_DB_IO, "Read value %8.8X register %X\n",
398167802Sjkim            RegisterValue, BitRegInfo->ParentRegister));
39999679Siwasaki    }
40099679Siwasaki
40199679Siwasaki    return_ACPI_STATUS (Status);
40291116Smsmith}
40367754Smsmith
404167802SjkimACPI_EXPORT_SYMBOL (AcpiGetRegister)
40567754Smsmith
406167802Sjkim
40791116Smsmith/*******************************************************************************
40891116Smsmith *
40999679Siwasaki * FUNCTION:    AcpiSetRegister
41091116Smsmith *
41191116Smsmith * PARAMETERS:  RegisterId      - ID of ACPI BitRegister to access
41291116Smsmith *              Value           - (only used on write) value to write to the
413138287Smarks *                                Register, NOT pre-normalized to the bit pos
41491116Smsmith *
415138287Smarks * RETURN:      Status
41691116Smsmith *
41791116Smsmith * DESCRIPTION: ACPI Bit Register write function.
41891116Smsmith *
41991116Smsmith ******************************************************************************/
42067754Smsmith
42199679SiwasakiACPI_STATUS
42299679SiwasakiAcpiSetRegister (
42391116Smsmith    UINT32                  RegisterId,
424167802Sjkim    UINT32                  Value)
42591116Smsmith{
42691116Smsmith    UINT32                  RegisterValue = 0;
42791116Smsmith    ACPI_BIT_REGISTER_INFO  *BitRegInfo;
42899679Siwasaki    ACPI_STATUS             Status;
429167802Sjkim    ACPI_CPU_FLAGS          LockFlags;
43067754Smsmith
43167754Smsmith
432167802Sjkim    ACPI_FUNCTION_TRACE_U32 (AcpiSetRegister, RegisterId);
43367754Smsmith
43467754Smsmith
43591116Smsmith    /* Get the info structure corresponding to the requested ACPI Register */
43667754Smsmith
43791116Smsmith    BitRegInfo = AcpiHwGetBitRegisterInfo (RegisterId);
43891116Smsmith    if (!BitRegInfo)
43991116Smsmith    {
440167802Sjkim        ACPI_ERROR ((AE_INFO, "Bad ACPI HW RegisterId: %X", RegisterId));
44191116Smsmith        return_ACPI_STATUS (AE_BAD_PARAMETER);
44291116Smsmith    }
44367754Smsmith
444167802Sjkim    LockFlags = AcpiOsAcquireLock (AcpiGbl_HardwareLock);
44599679Siwasaki
44691116Smsmith    /* Always do a register read first so we can insert the new bits  */
44767754Smsmith
448102550Siwasaki    Status = AcpiHwRegisterRead (ACPI_MTX_DO_NOT_LOCK,
449151937Sjkim                BitRegInfo->ParentRegister, &RegisterValue);
45099679Siwasaki    if (ACPI_FAILURE (Status))
45199679Siwasaki    {
45299679Siwasaki        goto UnlockAndExit;
45399679Siwasaki    }
45467754Smsmith
45591116Smsmith    /*
45691116Smsmith     * Decode the Register ID
457123315Snjl     * Register ID = [Register block ID] | [bit ID]
45891116Smsmith     *
459123315Snjl     * Check bit ID to fine locate Register offset.
46091116Smsmith     * Check Mask to determine Register offset, and then read-write.
46191116Smsmith     */
46291116Smsmith    switch (BitRegInfo->ParentRegister)
46391116Smsmith    {
46491116Smsmith    case ACPI_REGISTER_PM1_STATUS:
46567754Smsmith
46691116Smsmith        /*
467167802Sjkim         * Status Registers are different from the rest. Clear by
468167802Sjkim         * writing 1, and writing 0 has no effect. So, the only relevant
46991116Smsmith         * information is the single bit we're interested in, all others should
470123315Snjl         * be written as 0 so they will be left unchanged.
47191116Smsmith         */
472102550Siwasaki        Value = ACPI_REGISTER_PREPARE_BITS (Value,
47399679Siwasaki                    BitRegInfo->BitPosition, BitRegInfo->AccessBitMask);
47491116Smsmith        if (Value)
47569450Smsmith        {
476102550Siwasaki            Status = AcpiHwRegisterWrite (ACPI_MTX_DO_NOT_LOCK,
47799679Siwasaki                        ACPI_REGISTER_PM1_STATUS, (UINT16) Value);
47891116Smsmith            RegisterValue = 0;
47969450Smsmith        }
48067754Smsmith        break;
48167754Smsmith
48267754Smsmith
48391116Smsmith    case ACPI_REGISTER_PM1_ENABLE:
48467754Smsmith
485102550Siwasaki        ACPI_REGISTER_INSERT_VALUE (RegisterValue, BitRegInfo->BitPosition,
486167802Sjkim            BitRegInfo->AccessBitMask, Value);
48767754Smsmith
488102550Siwasaki        Status = AcpiHwRegisterWrite (ACPI_MTX_DO_NOT_LOCK,
489151937Sjkim                    ACPI_REGISTER_PM1_ENABLE, (UINT16) RegisterValue);
49091116Smsmith        break;
49167754Smsmith
49267754Smsmith
49391116Smsmith    case ACPI_REGISTER_PM1_CONTROL:
49467754Smsmith
49569450Smsmith        /*
496123315Snjl         * Write the PM1 Control register.
49769450Smsmith         * Note that at this level, the fact that there are actually TWO
498123315Snjl         * registers (A and B - and B may not exist) is abstracted.
49969450Smsmith         */
500167802Sjkim        ACPI_DEBUG_PRINT ((ACPI_DB_IO, "PM1 control: Read %X\n",
501167802Sjkim            RegisterValue));
50269450Smsmith
503102550Siwasaki        ACPI_REGISTER_INSERT_VALUE (RegisterValue, BitRegInfo->BitPosition,
504167802Sjkim            BitRegInfo->AccessBitMask, Value);
50567754Smsmith
506117525Snjl        Status = AcpiHwRegisterWrite (ACPI_MTX_DO_NOT_LOCK,
507151937Sjkim                    ACPI_REGISTER_PM1_CONTROL, (UINT16) RegisterValue);
50867754Smsmith        break;
50967754Smsmith
51067754Smsmith
51191116Smsmith    case ACPI_REGISTER_PM2_CONTROL:
51267754Smsmith
513102550Siwasaki        Status = AcpiHwRegisterRead (ACPI_MTX_DO_NOT_LOCK,
51499679Siwasaki                    ACPI_REGISTER_PM2_CONTROL, &RegisterValue);
51599679Siwasaki        if (ACPI_FAILURE (Status))
51699679Siwasaki        {
51799679Siwasaki            goto UnlockAndExit;
51899679Siwasaki        }
51967754Smsmith
52085756Smsmith        ACPI_DEBUG_PRINT ((ACPI_DB_IO, "PM2 control: Read %X from %8.8X%8.8X\n",
521102550Siwasaki            RegisterValue,
522167802Sjkim            ACPI_FORMAT_UINT64 (AcpiGbl_FADT.XPm2ControlBlock.Address)));
52369450Smsmith
524102550Siwasaki        ACPI_REGISTER_INSERT_VALUE (RegisterValue, BitRegInfo->BitPosition,
52599679Siwasaki                BitRegInfo->AccessBitMask, Value);
52667754Smsmith
52799679Siwasaki        ACPI_DEBUG_PRINT ((ACPI_DB_IO, "About to write %4.4X to %8.8X%8.8X\n",
52885756Smsmith            RegisterValue,
529167802Sjkim            ACPI_FORMAT_UINT64 (AcpiGbl_FADT.XPm2ControlBlock.Address)));
53067754Smsmith
53199679Siwasaki        Status = AcpiHwRegisterWrite (ACPI_MTX_DO_NOT_LOCK,
532151937Sjkim                    ACPI_REGISTER_PM2_CONTROL, (UINT8) (RegisterValue));
53367754Smsmith        break;
53467754Smsmith
53567754Smsmith
53667754Smsmith    default:
53767754Smsmith        break;
53867754Smsmith    }
53967754Smsmith
54099679Siwasaki
54199679SiwasakiUnlockAndExit:
54299679Siwasaki
543167802Sjkim    AcpiOsReleaseLock (AcpiGbl_HardwareLock, LockFlags);
54467754Smsmith
54591116Smsmith    /* Normalize the value that was read */
54669450Smsmith
547151937Sjkim    ACPI_DEBUG_EXEC (RegisterValue =
548151937Sjkim        ((RegisterValue & BitRegInfo->AccessBitMask) >>
549151937Sjkim            BitRegInfo->BitPosition));
55067754Smsmith
551117521Snjl    ACPI_DEBUG_PRINT ((ACPI_DB_IO, "Set bits: %8.8X actual %8.8X register %X\n",
552167802Sjkim        Value, RegisterValue, BitRegInfo->ParentRegister));
55399679Siwasaki    return_ACPI_STATUS (Status);
55467754Smsmith}
55569450Smsmith
556167802SjkimACPI_EXPORT_SYMBOL (AcpiSetRegister)
55769450Smsmith
558167802Sjkim
55969450Smsmith/******************************************************************************
56069450Smsmith *
56169450Smsmith * FUNCTION:    AcpiHwRegisterRead
56269450Smsmith *
563167802Sjkim * PARAMETERS:  UseLock             - Lock hardware? True/False
564167802Sjkim *              RegisterId          - ACPI Register ID
565151937Sjkim *              ReturnValue         - Where the register value is returned
56669450Smsmith *
567138287Smarks * RETURN:      Status and the value read.
56869450Smsmith *
569167802Sjkim * DESCRIPTION: Read from the specified ACPI register
57069450Smsmith *
57169450Smsmith ******************************************************************************/
57269450Smsmith
57399679SiwasakiACPI_STATUS
57469450SmsmithAcpiHwRegisterRead (
57569450Smsmith    BOOLEAN                 UseLock,
57699679Siwasaki    UINT32                  RegisterId,
57799679Siwasaki    UINT32                  *ReturnValue)
57869450Smsmith{
57999679Siwasaki    UINT32                  Value1 = 0;
58099679Siwasaki    UINT32                  Value2 = 0;
58199679Siwasaki    ACPI_STATUS             Status;
582167802Sjkim    ACPI_CPU_FLAGS          LockFlags = 0;
58369450Smsmith
58477424Smsmith
585167802Sjkim    ACPI_FUNCTION_TRACE (HwRegisterRead);
58669450Smsmith
58777424Smsmith
58869450Smsmith    if (ACPI_MTX_LOCK == UseLock)
58969450Smsmith    {
590167802Sjkim        LockFlags = AcpiOsAcquireLock (AcpiGbl_HardwareLock);
59169450Smsmith    }
59269450Smsmith
59391116Smsmith    switch (RegisterId)
59469450Smsmith    {
59591116Smsmith    case ACPI_REGISTER_PM1_STATUS:           /* 16-bit access */
59669450Smsmith
597167802Sjkim        Status = AcpiHwLowLevelRead (16, &Value1, &AcpiGbl_FADT.XPm1aEventBlock);
59899679Siwasaki        if (ACPI_FAILURE (Status))
59999679Siwasaki        {
60099679Siwasaki            goto UnlockAndExit;
60199679Siwasaki        }
60299679Siwasaki
603117521Snjl        /* PM1B is optional */
604117521Snjl
605167802Sjkim        Status = AcpiHwLowLevelRead (16, &Value2, &AcpiGbl_FADT.XPm1bEventBlock);
60699679Siwasaki        Value1 |= Value2;
60769450Smsmith        break;
60869450Smsmith
60969450Smsmith
610117521Snjl    case ACPI_REGISTER_PM1_ENABLE:           /* 16-bit access */
61169450Smsmith
612117521Snjl        Status = AcpiHwLowLevelRead (16, &Value1, &AcpiGbl_XPm1aEnable);
61399679Siwasaki        if (ACPI_FAILURE (Status))
61499679Siwasaki        {
61599679Siwasaki            goto UnlockAndExit;
61699679Siwasaki        }
61799679Siwasaki
618117521Snjl        /* PM1B is optional */
619117521Snjl
620117521Snjl        Status = AcpiHwLowLevelRead (16, &Value2, &AcpiGbl_XPm1bEnable);
62199679Siwasaki        Value1 |= Value2;
62269450Smsmith        break;
62369450Smsmith
62469450Smsmith
62591116Smsmith    case ACPI_REGISTER_PM1_CONTROL:          /* 16-bit access */
62669450Smsmith
627167802Sjkim        Status = AcpiHwLowLevelRead (16, &Value1, &AcpiGbl_FADT.XPm1aControlBlock);
62899679Siwasaki        if (ACPI_FAILURE (Status))
62999679Siwasaki        {
63099679Siwasaki            goto UnlockAndExit;
63199679Siwasaki        }
63299679Siwasaki
633167802Sjkim        Status = AcpiHwLowLevelRead (16, &Value2, &AcpiGbl_FADT.XPm1bControlBlock);
63499679Siwasaki        Value1 |= Value2;
63569450Smsmith        break;
63669450Smsmith
63769450Smsmith
63891116Smsmith    case ACPI_REGISTER_PM2_CONTROL:          /* 8-bit access */
63969450Smsmith
640167802Sjkim        Status = AcpiHwLowLevelRead (8, &Value1, &AcpiGbl_FADT.XPm2ControlBlock);
64169450Smsmith        break;
64269450Smsmith
64369450Smsmith
64491116Smsmith    case ACPI_REGISTER_PM_TIMER:             /* 32-bit access */
64569450Smsmith
646167802Sjkim        Status = AcpiHwLowLevelRead (32, &Value1, &AcpiGbl_FADT.XPmTimerBlock);
64769450Smsmith        break;
64869450Smsmith
64991116Smsmith    case ACPI_REGISTER_SMI_COMMAND_BLOCK:    /* 8-bit access */
65069450Smsmith
651167802Sjkim        Status = AcpiOsReadPort (AcpiGbl_FADT.SmiCommand, &Value1, 8);
65269450Smsmith        break;
65369450Smsmith
65469450Smsmith    default:
655167802Sjkim        ACPI_ERROR ((AE_INFO, "Unknown Register ID: %X",
656151937Sjkim            RegisterId));
65799679Siwasaki        Status = AE_BAD_PARAMETER;
65869450Smsmith        break;
65969450Smsmith    }
66069450Smsmith
66199679SiwasakiUnlockAndExit:
66269450Smsmith    if (ACPI_MTX_LOCK == UseLock)
66369450Smsmith    {
664167802Sjkim        AcpiOsReleaseLock (AcpiGbl_HardwareLock, LockFlags);
66569450Smsmith    }
66669450Smsmith
66799679Siwasaki    if (ACPI_SUCCESS (Status))
66899679Siwasaki    {
66999679Siwasaki        *ReturnValue = Value1;
67099679Siwasaki    }
67199679Siwasaki
67299679Siwasaki    return_ACPI_STATUS (Status);
67369450Smsmith}
67469450Smsmith
67569450Smsmith
67669450Smsmith/******************************************************************************
67769450Smsmith *
67869450Smsmith * FUNCTION:    AcpiHwRegisterWrite
67969450Smsmith *
680167802Sjkim * PARAMETERS:  UseLock             - Lock hardware? True/False
681167802Sjkim *              RegisterId          - ACPI Register ID
682138287Smarks *              Value               - The value to write
68369450Smsmith *
684138287Smarks * RETURN:      Status
68569450Smsmith *
686167802Sjkim * DESCRIPTION: Write to the specified ACPI register
68769450Smsmith *
688167802Sjkim * NOTE: In accordance with the ACPI specification, this function automatically
689167802Sjkim * preserves the value of the following bits, meaning that these bits cannot be
690167802Sjkim * changed via this interface:
691167802Sjkim *
692167802Sjkim * PM1_CONTROL[0] = SCI_EN
693167802Sjkim * PM1_CONTROL[9]
694167802Sjkim * PM1_STATUS[11]
695167802Sjkim *
696167802Sjkim * ACPI References:
697167802Sjkim * 1) Hardware Ignored Bits: When software writes to a register with ignored
698167802Sjkim *      bit fields, it preserves the ignored bit fields
699167802Sjkim * 2) SCI_EN: OSPM always preserves this bit position
700167802Sjkim *
70169450Smsmith ******************************************************************************/
70269450Smsmith
70399679SiwasakiACPI_STATUS
70469450SmsmithAcpiHwRegisterWrite (
70569450Smsmith    BOOLEAN                 UseLock,
70669450Smsmith    UINT32                  RegisterId,
70769450Smsmith    UINT32                  Value)
70869450Smsmith{
70999679Siwasaki    ACPI_STATUS             Status;
710167802Sjkim    ACPI_CPU_FLAGS          LockFlags = 0;
711167802Sjkim    UINT32                  ReadValue;
71269450Smsmith
71369450Smsmith
714167802Sjkim    ACPI_FUNCTION_TRACE (HwRegisterWrite);
71569450Smsmith
71683174Smsmith
71769450Smsmith    if (ACPI_MTX_LOCK == UseLock)
71869450Smsmith    {
719167802Sjkim        LockFlags = AcpiOsAcquireLock (AcpiGbl_HardwareLock);
72069450Smsmith    }
72169450Smsmith
72291116Smsmith    switch (RegisterId)
72369450Smsmith    {
72491116Smsmith    case ACPI_REGISTER_PM1_STATUS:           /* 16-bit access */
72569450Smsmith
726167802Sjkim        /* Perform a read first to preserve certain bits (per ACPI spec) */
727167802Sjkim
728167802Sjkim        Status = AcpiHwRegisterRead (ACPI_MTX_DO_NOT_LOCK,
729167802Sjkim                    ACPI_REGISTER_PM1_STATUS, &ReadValue);
73099679Siwasaki        if (ACPI_FAILURE (Status))
73199679Siwasaki        {
73299679Siwasaki            goto UnlockAndExit;
73399679Siwasaki        }
73499679Siwasaki
735167802Sjkim        /* Insert the bits to be preserved */
736167802Sjkim
737167802Sjkim        ACPI_INSERT_BITS (Value, ACPI_PM1_STATUS_PRESERVED_BITS, ReadValue);
738167802Sjkim
739167802Sjkim        /* Now we can write the data */
740167802Sjkim
741167802Sjkim        Status = AcpiHwLowLevelWrite (16, Value, &AcpiGbl_FADT.XPm1aEventBlock);
742167802Sjkim        if (ACPI_FAILURE (Status))
743167802Sjkim        {
744167802Sjkim            goto UnlockAndExit;
745167802Sjkim        }
746167802Sjkim
747117521Snjl        /* PM1B is optional */
748117521Snjl
749167802Sjkim        Status = AcpiHwLowLevelWrite (16, Value, &AcpiGbl_FADT.XPm1bEventBlock);
75069450Smsmith        break;
75169450Smsmith
75269450Smsmith
753167802Sjkim    case ACPI_REGISTER_PM1_ENABLE:           /* 16-bit access */
75469450Smsmith
755117521Snjl        Status = AcpiHwLowLevelWrite (16, Value, &AcpiGbl_XPm1aEnable);
75699679Siwasaki        if (ACPI_FAILURE (Status))
75799679Siwasaki        {
75899679Siwasaki            goto UnlockAndExit;
75999679Siwasaki        }
76099679Siwasaki
761117521Snjl        /* PM1B is optional */
762117521Snjl
763117521Snjl        Status = AcpiHwLowLevelWrite (16, Value, &AcpiGbl_XPm1bEnable);
76469450Smsmith        break;
76569450Smsmith
76669450Smsmith
76791116Smsmith    case ACPI_REGISTER_PM1_CONTROL:          /* 16-bit access */
76869450Smsmith
769167802Sjkim        /*
770167802Sjkim         * Perform a read first to preserve certain bits (per ACPI spec)
771167802Sjkim         *
772167802Sjkim         * Note: This includes SCI_EN, we never want to change this bit
773167802Sjkim         */
774167802Sjkim        Status = AcpiHwRegisterRead (ACPI_MTX_DO_NOT_LOCK,
775167802Sjkim                    ACPI_REGISTER_PM1_CONTROL, &ReadValue);
77699679Siwasaki        if (ACPI_FAILURE (Status))
77799679Siwasaki        {
77899679Siwasaki            goto UnlockAndExit;
77999679Siwasaki        }
78099679Siwasaki
781167802Sjkim        /* Insert the bits to be preserved */
782167802Sjkim
783167802Sjkim        ACPI_INSERT_BITS (Value, ACPI_PM1_CONTROL_PRESERVED_BITS, ReadValue);
784167802Sjkim
785167802Sjkim        /* Now we can write the data */
786167802Sjkim
787167802Sjkim        Status = AcpiHwLowLevelWrite (16, Value, &AcpiGbl_FADT.XPm1aControlBlock);
788167802Sjkim        if (ACPI_FAILURE (Status))
789167802Sjkim        {
790167802Sjkim            goto UnlockAndExit;
791167802Sjkim        }
792167802Sjkim
793167802Sjkim        Status = AcpiHwLowLevelWrite (16, Value, &AcpiGbl_FADT.XPm1bControlBlock);
79471867Smsmith        break;
79569450Smsmith
79669450Smsmith
79791116Smsmith    case ACPI_REGISTER_PM1A_CONTROL:         /* 16-bit access */
79869450Smsmith
799167802Sjkim        Status = AcpiHwLowLevelWrite (16, Value, &AcpiGbl_FADT.XPm1aControlBlock);
80069450Smsmith        break;
80169450Smsmith
80269450Smsmith
80391116Smsmith    case ACPI_REGISTER_PM1B_CONTROL:         /* 16-bit access */
80471867Smsmith
805167802Sjkim        Status = AcpiHwLowLevelWrite (16, Value, &AcpiGbl_FADT.XPm1bControlBlock);
80671867Smsmith        break;
80771867Smsmith
80871867Smsmith
80991116Smsmith    case ACPI_REGISTER_PM2_CONTROL:          /* 8-bit access */
81069450Smsmith
811167802Sjkim        Status = AcpiHwLowLevelWrite (8, Value, &AcpiGbl_FADT.XPm2ControlBlock);
81269450Smsmith        break;
81369450Smsmith
81469450Smsmith
81591116Smsmith    case ACPI_REGISTER_PM_TIMER:             /* 32-bit access */
81669450Smsmith
817167802Sjkim        Status = AcpiHwLowLevelWrite (32, Value, &AcpiGbl_FADT.XPmTimerBlock);
81869450Smsmith        break;
81969450Smsmith
82069450Smsmith
82191116Smsmith    case ACPI_REGISTER_SMI_COMMAND_BLOCK:    /* 8-bit access */
82269450Smsmith
82391116Smsmith        /* SMI_CMD is currently always in IO space */
82469450Smsmith
825167802Sjkim        Status = AcpiOsWritePort (AcpiGbl_FADT.SmiCommand, Value, 8);
82669450Smsmith        break;
82769450Smsmith
82869450Smsmith
82969450Smsmith    default:
83099679Siwasaki        Status = AE_BAD_PARAMETER;
83169450Smsmith        break;
83269450Smsmith    }
83369450Smsmith
83499679SiwasakiUnlockAndExit:
83569450Smsmith    if (ACPI_MTX_LOCK == UseLock)
83669450Smsmith    {
837167802Sjkim        AcpiOsReleaseLock (AcpiGbl_HardwareLock, LockFlags);
83869450Smsmith    }
83969450Smsmith
84099679Siwasaki    return_ACPI_STATUS (Status);
84169450Smsmith}
84269450Smsmith
84369450Smsmith
84469450Smsmith/******************************************************************************
84569450Smsmith *
84669450Smsmith * FUNCTION:    AcpiHwLowLevelRead
84769450Smsmith *
848117521Snjl * PARAMETERS:  Width               - 8, 16, or 32
849117521Snjl *              Value               - Where the value is returned
850138287Smarks *              Reg                 - GAS register structure
85169450Smsmith *
852117521Snjl * RETURN:      Status
85369450Smsmith *
854138287Smarks * DESCRIPTION: Read from either memory or IO space.
85569450Smsmith *
85669450Smsmith ******************************************************************************/
85769450Smsmith
85899679SiwasakiACPI_STATUS
85969450SmsmithAcpiHwLowLevelRead (
86069450Smsmith    UINT32                  Width,
86199679Siwasaki    UINT32                  *Value,
862117521Snjl    ACPI_GENERIC_ADDRESS    *Reg)
86369450Smsmith{
864138287Smarks    UINT64                  Address;
86599679Siwasaki    ACPI_STATUS             Status;
86669450Smsmith
86769450Smsmith
868167802Sjkim    ACPI_FUNCTION_NAME (HwLowLevelRead);
86983174Smsmith
87083174Smsmith
87169450Smsmith    /*
87269450Smsmith     * Must have a valid pointer to a GAS structure, and
87399679Siwasaki     * a non-zero address within. However, don't return an error
87499679Siwasaki     * because the PM1A/B code must not fail if B isn't present.
87569450Smsmith     */
876138287Smarks    if (!Reg)
87769450Smsmith    {
87899679Siwasaki        return (AE_OK);
87969450Smsmith    }
880138287Smarks
881167802Sjkim    /* Get a local copy of the address. Handles possible alignment issues */
882138287Smarks
883138287Smarks    ACPI_MOVE_64_TO_64 (&Address, &Reg->Address);
884167802Sjkim    if (!Address)
885138287Smarks    {
886138287Smarks        return (AE_OK);
887138287Smarks    }
88899679Siwasaki    *Value = 0;
88969450Smsmith
89069450Smsmith    /*
891138287Smarks     * Two address spaces supported: Memory or IO.
892138287Smarks     * PCI_Config is not supported here because the GAS struct is insufficient
89369450Smsmith     */
894167802Sjkim    switch (Reg->SpaceId)
89569450Smsmith    {
89677424Smsmith    case ACPI_ADR_SPACE_SYSTEM_MEMORY:
89769450Smsmith
898117521Snjl        Status = AcpiOsReadMemory (
899167802Sjkim                    (ACPI_PHYSICAL_ADDRESS) Address, Value, Width);
90069450Smsmith        break;
90169450Smsmith
90269450Smsmith
90377424Smsmith    case ACPI_ADR_SPACE_SYSTEM_IO:
90469450Smsmith
905167802Sjkim        Status = AcpiOsReadPort ((ACPI_IO_ADDRESS) Address, Value, Width);
90669450Smsmith        break;
90769450Smsmith
90869450Smsmith
90999679Siwasaki    default:
910167802Sjkim        ACPI_ERROR ((AE_INFO,
911167802Sjkim            "Unsupported address space: %X", Reg->SpaceId));
912117521Snjl        return (AE_BAD_PARAMETER);
91369450Smsmith    }
91469450Smsmith
915151937Sjkim    ACPI_DEBUG_PRINT ((ACPI_DB_IO,
916151937Sjkim        "Read:  %8.8X width %2d from %8.8X%8.8X (%s)\n",
917167802Sjkim        *Value, Width, ACPI_FORMAT_UINT64 (Address),
918167802Sjkim        AcpiUtGetRegionName (Reg->SpaceId)));
919117521Snjl
92099679Siwasaki    return (Status);
92169450Smsmith}
92269450Smsmith
92369450Smsmith
92469450Smsmith/******************************************************************************
92569450Smsmith *
92669450Smsmith * FUNCTION:    AcpiHwLowLevelWrite
92769450Smsmith *
92869450Smsmith * PARAMETERS:  Width               - 8, 16, or 32
92969450Smsmith *              Value               - To be written
930138287Smarks *              Reg                 - GAS register structure
93169450Smsmith *
932117521Snjl * RETURN:      Status
93369450Smsmith *
934138287Smarks * DESCRIPTION: Write to either memory or IO space.
93569450Smsmith *
93669450Smsmith ******************************************************************************/
93769450Smsmith
93899679SiwasakiACPI_STATUS
93969450SmsmithAcpiHwLowLevelWrite (
94069450Smsmith    UINT32                  Width,
94169450Smsmith    UINT32                  Value,
942117521Snjl    ACPI_GENERIC_ADDRESS    *Reg)
94369450Smsmith{
944138287Smarks    UINT64                  Address;
94599679Siwasaki    ACPI_STATUS             Status;
94669450Smsmith
94769450Smsmith
948167802Sjkim    ACPI_FUNCTION_NAME (HwLowLevelWrite);
94983174Smsmith
95083174Smsmith
95169450Smsmith    /*
95269450Smsmith     * Must have a valid pointer to a GAS structure, and
95399679Siwasaki     * a non-zero address within. However, don't return an error
95499679Siwasaki     * because the PM1A/B code must not fail if B isn't present.
95569450Smsmith     */
956138287Smarks    if (!Reg)
95769450Smsmith    {
95899679Siwasaki        return (AE_OK);
95969450Smsmith    }
960123315Snjl
961167802Sjkim    /* Get a local copy of the address. Handles possible alignment issues */
962138287Smarks
963138287Smarks    ACPI_MOVE_64_TO_64 (&Address, &Reg->Address);
964167802Sjkim    if (!Address)
965138287Smarks    {
966138287Smarks        return (AE_OK);
967138287Smarks    }
968138287Smarks
96969450Smsmith    /*
970138287Smarks     * Two address spaces supported: Memory or IO.
971138287Smarks     * PCI_Config is not supported here because the GAS struct is insufficient
97269450Smsmith     */
973167802Sjkim    switch (Reg->SpaceId)
97469450Smsmith    {
97577424Smsmith    case ACPI_ADR_SPACE_SYSTEM_MEMORY:
97669450Smsmith
977117521Snjl        Status = AcpiOsWriteMemory (
978167802Sjkim                    (ACPI_PHYSICAL_ADDRESS) Address, Value, Width);
97969450Smsmith        break;
98069450Smsmith
98169450Smsmith
98277424Smsmith    case ACPI_ADR_SPACE_SYSTEM_IO:
98369450Smsmith
984167802Sjkim        Status = AcpiOsWritePort (
985167802Sjkim                    (ACPI_IO_ADDRESS) Address, Value, Width);
98669450Smsmith        break;
98769450Smsmith
98869450Smsmith
98999679Siwasaki    default:
990167802Sjkim        ACPI_ERROR ((AE_INFO,
991167802Sjkim            "Unsupported address space: %X", Reg->SpaceId));
992117521Snjl        return (AE_BAD_PARAMETER);
99369450Smsmith    }
99499679Siwasaki
995151937Sjkim    ACPI_DEBUG_PRINT ((ACPI_DB_IO,
996151937Sjkim        "Wrote: %8.8X width %2d   to %8.8X%8.8X (%s)\n",
997167802Sjkim        Value, Width, ACPI_FORMAT_UINT64 (Address),
998167802Sjkim        AcpiUtGetRegionName (Reg->SpaceId)));
999117521Snjl
100099679Siwasaki    return (Status);
100169450Smsmith}
1002