hwregs.c revision 82367
167754Smsmith
267754Smsmith/*******************************************************************************
367754Smsmith *
467754Smsmith * Module Name: hwregs - Read/write access functions for the various ACPI
567754Smsmith *                       control and status registers.
682367Smsmith *              $Revision: 104 $
767754Smsmith *
867754Smsmith ******************************************************************************/
967754Smsmith
1067754Smsmith/******************************************************************************
1167754Smsmith *
1267754Smsmith * 1. Copyright Notice
1367754Smsmith *
1471867Smsmith * Some or all of this work - Copyright (c) 1999, 2000, 2001, 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
12167754Smsmith#include "acpi.h"
12267754Smsmith#include "achware.h"
12367754Smsmith#include "acnamesp.h"
12467754Smsmith
12577424Smsmith#define _COMPONENT          ACPI_HARDWARE
12667754Smsmith        MODULE_NAME         ("hwregs")
12767754Smsmith
12867754Smsmith
12967754Smsmith/* This matches the #defines in actypes.h. */
13067754Smsmith
13169450SmsmithNATIVE_CHAR                 *SleepStateTable[] = {"\\_S0_","\\_S1_","\\_S2_","\\_S3_",
13271867Smsmith                                                  "\\_S4_","\\_S5_","\\_S4B"};
13367754Smsmith
13467754Smsmith
13567754Smsmith/*******************************************************************************
13667754Smsmith *
13767754Smsmith * FUNCTION:    AcpiHwGetBitShift
13867754Smsmith *
13967754Smsmith * PARAMETERS:  Mask            - Input mask to determine bit shift from.
14067754Smsmith *                                Must have at least 1 bit set.
14167754Smsmith *
14267754Smsmith * RETURN:      Bit location of the lsb of the mask
14367754Smsmith *
14467754Smsmith * DESCRIPTION: Returns the bit number for the low order bit that's set.
14567754Smsmith *
14667754Smsmith ******************************************************************************/
14767754Smsmith
14871867SmsmithUINT32
14967754SmsmithAcpiHwGetBitShift (
15067754Smsmith    UINT32                  Mask)
15167754Smsmith{
15267754Smsmith    UINT32                  Shift;
15367754Smsmith
15467754Smsmith
15567754Smsmith    FUNCTION_TRACE ("HwGetBitShift");
15667754Smsmith
15767754Smsmith
15867754Smsmith    for (Shift = 0; ((Mask >> Shift) & 1) == 0; Shift++)
15967754Smsmith    { ; }
16067754Smsmith
16167754Smsmith    return_VALUE (Shift);
16267754Smsmith}
16367754Smsmith
16467754Smsmith
16567754Smsmith/*******************************************************************************
16667754Smsmith *
16767754Smsmith * FUNCTION:    AcpiHwClearAcpiStatus
16867754Smsmith *
16967754Smsmith * PARAMETERS:  none
17067754Smsmith *
17167754Smsmith * RETURN:      none
17267754Smsmith *
17367754Smsmith * DESCRIPTION: Clears all fixed and general purpose status bits
17467754Smsmith *
17567754Smsmith ******************************************************************************/
17667754Smsmith
17767754Smsmithvoid
17867754SmsmithAcpiHwClearAcpiStatus (void)
17967754Smsmith{
18067754Smsmith    UINT16                  GpeLength;
18167754Smsmith    UINT16                  Index;
18267754Smsmith
18367754Smsmith
18467754Smsmith    FUNCTION_TRACE ("HwClearAcpiStatus");
18567754Smsmith
18667754Smsmith
18782367Smsmith    ACPI_DEBUG_PRINT ((ACPI_DB_IO, "About to write %04X to %04X\n",
18877424Smsmith        ALL_FIXED_STS_BITS,
18977424Smsmith        (UINT16) ACPI_GET_ADDRESS (AcpiGbl_FADT->XPm1aEvtBlk.Address)));
19067754Smsmith
19167754Smsmith
19277424Smsmith    AcpiUtAcquireMutex (ACPI_MTX_HARDWARE);
19367754Smsmith
19469450Smsmith    AcpiHwRegisterWrite (ACPI_MTX_DO_NOT_LOCK, PM1_STS, ALL_FIXED_STS_BITS);
19567754Smsmith
19669450Smsmith
19770243Smsmith    if (ACPI_VALID_ADDRESS (AcpiGbl_FADT->XPm1bEvtBlk.Address))
19867754Smsmith    {
19980062Smsmith        AcpiOsWritePort ((ACPI_IO_ADDRESS)
20080062Smsmith            ACPI_GET_ADDRESS (AcpiGbl_FADT->XPm1bEvtBlk.Address),
20180062Smsmith            ALL_FIXED_STS_BITS, 16);
20267754Smsmith    }
20367754Smsmith
20467754Smsmith    /* now clear the GPE Bits */
20567754Smsmith
20669450Smsmith    if (AcpiGbl_FADT->Gpe0BlkLen)
20767754Smsmith    {
20869450Smsmith        GpeLength = (UINT16) DIV_2 (AcpiGbl_FADT->Gpe0BlkLen);
20967754Smsmith
21067754Smsmith        for (Index = 0; Index < GpeLength; Index++)
21167754Smsmith        {
21280062Smsmith            AcpiOsWritePort ((ACPI_IO_ADDRESS) (
21377424Smsmith                ACPI_GET_ADDRESS (AcpiGbl_FADT->XGpe0Blk.Address) + Index),
21480062Smsmith                    0xFF, 8);
21567754Smsmith        }
21667754Smsmith    }
21767754Smsmith
21869450Smsmith    if (AcpiGbl_FADT->Gpe1BlkLen)
21967754Smsmith    {
22069450Smsmith        GpeLength = (UINT16) DIV_2 (AcpiGbl_FADT->Gpe1BlkLen);
22167754Smsmith
22267754Smsmith        for (Index = 0; Index < GpeLength; Index++)
22367754Smsmith        {
22480062Smsmith            AcpiOsWritePort ((ACPI_IO_ADDRESS) (
22577424Smsmith                ACPI_GET_ADDRESS (AcpiGbl_FADT->XGpe1Blk.Address) + Index),
22680062Smsmith                0xFF, 8);
22767754Smsmith        }
22867754Smsmith    }
22967754Smsmith
23077424Smsmith    AcpiUtReleaseMutex (ACPI_MTX_HARDWARE);
23167754Smsmith    return_VOID;
23267754Smsmith}
23367754Smsmith
23467754Smsmith
23567754Smsmith/*******************************************************************************
23667754Smsmith *
23767754Smsmith * FUNCTION:    AcpiHwObtainSleepTypeRegisterData
23867754Smsmith *
23967754Smsmith * PARAMETERS:  SleepState        - Numeric state requested
24067754Smsmith *              *Slp_TypA         - Pointer to byte to receive SLP_TYPa value
24167754Smsmith *              *Slp_TypB         - Pointer to byte to receive SLP_TYPb value
24267754Smsmith *
24367754Smsmith * RETURN:      Status - ACPI status
24467754Smsmith *
24567754Smsmith * DESCRIPTION: AcpiHwObtainSleepTypeRegisterData() obtains the SLP_TYP and
24667754Smsmith *              SLP_TYPb values for the sleep state requested.
24767754Smsmith *
24867754Smsmith ******************************************************************************/
24967754Smsmith
25067754SmsmithACPI_STATUS
25167754SmsmithAcpiHwObtainSleepTypeRegisterData (
25267754Smsmith    UINT8                   SleepState,
25367754Smsmith    UINT8                   *Slp_TypA,
25467754Smsmith    UINT8                   *Slp_TypB)
25567754Smsmith{
25667754Smsmith    ACPI_STATUS             Status = AE_OK;
25767754Smsmith    ACPI_OPERAND_OBJECT     *ObjDesc;
25867754Smsmith
25967754Smsmith
26067754Smsmith    FUNCTION_TRACE ("HwObtainSleepTypeRegisterData");
26167754Smsmith
26267754Smsmith
26367754Smsmith    /*
26467754Smsmith     *  Validate parameters
26567754Smsmith     */
26667754Smsmith
26767754Smsmith    if ((SleepState > ACPI_S_STATES_MAX) ||
26867754Smsmith        !Slp_TypA || !Slp_TypB)
26967754Smsmith    {
27067754Smsmith        return_ACPI_STATUS (AE_BAD_PARAMETER);
27167754Smsmith    }
27267754Smsmith
27367754Smsmith    /*
27467754Smsmith     *  AcpiEvaluate the namespace object containing the values for this state
27567754Smsmith     */
27667754Smsmith
27767754Smsmith    Status = AcpiNsEvaluateByName (SleepStateTable[SleepState], NULL, &ObjDesc);
27867754Smsmith    if (ACPI_FAILURE (Status))
27967754Smsmith    {
28067754Smsmith        return_ACPI_STATUS (Status);
28167754Smsmith    }
28267754Smsmith
28367754Smsmith    if (!ObjDesc)
28467754Smsmith    {
28567754Smsmith        REPORT_ERROR (("Missing Sleep State object\n"));
28667754Smsmith        return_ACPI_STATUS (AE_NOT_EXIST);
28767754Smsmith    }
28867754Smsmith
28967754Smsmith    /*
29067754Smsmith     *  We got something, now ensure it is correct.  The object must
29167754Smsmith     *  be a package and must have at least 2 numeric values as the
29267754Smsmith     *  two elements
29367754Smsmith     */
29467754Smsmith
29577424Smsmith    /* Even though AcpiEvaluateObject resolves package references,
29677424Smsmith     * NsEvaluate dpesn't. So, we do it here.
29777424Smsmith     */
29877424Smsmith    Status = AcpiUtResolvePackageReferences(ObjDesc);
29967754Smsmith
30067754Smsmith    if (ObjDesc->Package.Count < 2)
30167754Smsmith    {
30267754Smsmith        /* Must have at least two elements */
30367754Smsmith
30467754Smsmith        REPORT_ERROR (("Sleep State package does not have at least two elements\n"));
30567754Smsmith        Status = AE_ERROR;
30667754Smsmith    }
30767754Smsmith
30867754Smsmith    else if (((ObjDesc->Package.Elements[0])->Common.Type !=
30971867Smsmith                ACPI_TYPE_INTEGER) ||
31067754Smsmith             ((ObjDesc->Package.Elements[1])->Common.Type !=
31171867Smsmith                ACPI_TYPE_INTEGER))
31267754Smsmith    {
31367754Smsmith        /* Must have two  */
31467754Smsmith
31567754Smsmith        REPORT_ERROR (("Sleep State package elements are not both of type Number\n"));
31667754Smsmith        Status = AE_ERROR;
31767754Smsmith    }
31867754Smsmith
31967754Smsmith    else
32067754Smsmith    {
32167754Smsmith        /*
32267754Smsmith         *  Valid _Sx_ package size, type, and value
32367754Smsmith         */
32471867Smsmith        *Slp_TypA = (UINT8) (ObjDesc->Package.Elements[0])->Integer.Value;
32567754Smsmith
32671867Smsmith        *Slp_TypB = (UINT8) (ObjDesc->Package.Elements[1])->Integer.Value;
32767754Smsmith    }
32867754Smsmith
32967754Smsmith
33067754Smsmith    if (ACPI_FAILURE (Status))
33167754Smsmith    {
33282367Smsmith        ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Bad Sleep object %p type %X\n",
33367754Smsmith            ObjDesc, ObjDesc->Common.Type));
33467754Smsmith    }
33567754Smsmith
33677424Smsmith    AcpiUtRemoveReference (ObjDesc);
33767754Smsmith
33867754Smsmith    return_ACPI_STATUS (Status);
33967754Smsmith}
34067754Smsmith
34167754Smsmith
34267754Smsmith/*******************************************************************************
34367754Smsmith *
34469450Smsmith * FUNCTION:    AcpiHwRegisterBitAccess
34567754Smsmith *
34667754Smsmith * PARAMETERS:  ReadWrite       - Either ACPI_READ or ACPI_WRITE.
34767754Smsmith *              UseLock         - Lock the hardware
34869450Smsmith *              RegisterId      - index of ACPI Register to access
34967754Smsmith *              Value           - (only used on write) value to write to the
35069450Smsmith *                                Register.  Shifted all the way right.
35167754Smsmith *
35269450Smsmith * RETURN:      Value written to or read from specified Register.  This value
35367754Smsmith *              is shifted all the way right.
35467754Smsmith *
35569450Smsmith * DESCRIPTION: Generic ACPI Register read/write function.
35667754Smsmith *
35767754Smsmith ******************************************************************************/
35867754Smsmith
35967754SmsmithUINT32
36069450SmsmithAcpiHwRegisterBitAccess (
36167754Smsmith    NATIVE_UINT             ReadWrite,
36267754Smsmith    BOOLEAN                 UseLock,
36367754Smsmith    UINT32                  RegisterId,
36467754Smsmith    ...)                    /* Value (only used on write) */
36567754Smsmith{
36667754Smsmith    UINT32                  RegisterValue = 0;
36767754Smsmith    UINT32                  Mask = 0;
36867754Smsmith    UINT32                  Value = 0;
36977424Smsmith    va_list                 marker;
37067754Smsmith
37177424Smsmith
37269450Smsmith    FUNCTION_TRACE ("HwRegisterBitAccess");
37367754Smsmith
37467754Smsmith
37567754Smsmith    if (ReadWrite == ACPI_WRITE)
37667754Smsmith    {
37767754Smsmith        va_start (marker, RegisterId);
37867754Smsmith        Value = va_arg (marker, UINT32);
37967754Smsmith        va_end (marker);
38067754Smsmith    }
38167754Smsmith
38277424Smsmith    if (ACPI_MTX_LOCK == UseLock)
38377424Smsmith    {
38477424Smsmith        AcpiUtAcquireMutex (ACPI_MTX_HARDWARE);
38569450Smsmith    }
38667754Smsmith
38767754Smsmith    /*
38867754Smsmith     * Decode the Register ID
38977424Smsmith     * Register id = Register block id | bit id
39069450Smsmith     *
39169450Smsmith     * Check bit id to fine locate Register offset.
39277424Smsmith     * Check Mask to determine Register offset, and then read-write.
39367754Smsmith     */
39467754Smsmith
39577424Smsmith    switch (REGISTER_BLOCK_ID (RegisterId))
39667754Smsmith    {
39769450Smsmith    case PM1_STS:
39867754Smsmith
39969450Smsmith        switch (RegisterId)
40067754Smsmith        {
40169450Smsmith        case TMR_STS:
40269450Smsmith            Mask = TMR_STS_MASK;
40369450Smsmith            break;
40467754Smsmith
40569450Smsmith        case BM_STS:
40669450Smsmith            Mask = BM_STS_MASK;
40769450Smsmith            break;
40867754Smsmith
40969450Smsmith        case GBL_STS:
41069450Smsmith            Mask = GBL_STS_MASK;
41169450Smsmith            break;
41267754Smsmith
41369450Smsmith        case PWRBTN_STS:
41469450Smsmith            Mask = PWRBTN_STS_MASK;
41569450Smsmith            break;
41667754Smsmith
41769450Smsmith        case SLPBTN_STS:
41869450Smsmith            Mask = SLPBTN_STS_MASK;
41969450Smsmith            break;
42067754Smsmith
42169450Smsmith        case RTC_STS:
42269450Smsmith            Mask = RTC_STS_MASK;
42369450Smsmith            break;
42467754Smsmith
42569450Smsmith        case WAK_STS:
42669450Smsmith            Mask = WAK_STS_MASK;
42769450Smsmith            break;
42867754Smsmith
42969450Smsmith        default:
43069450Smsmith            Mask = 0;
43169450Smsmith            break;
43269450Smsmith        }
43367754Smsmith
43469450Smsmith        RegisterValue = AcpiHwRegisterRead (ACPI_MTX_DO_NOT_LOCK, PM1_STS);
43567754Smsmith
43669450Smsmith        if (ReadWrite == ACPI_WRITE)
43769450Smsmith        {
43869450Smsmith            /*
43969450Smsmith             * Status Registers are different from the rest.  Clear by
44069450Smsmith             * writing 1, writing 0 has no effect.  So, the only relevent
44169450Smsmith             * information is the single bit we're interested in, all
44269450Smsmith             * others should be written as 0 so they will be left
44369450Smsmith             * unchanged
44469450Smsmith             */
44567754Smsmith
44669450Smsmith            Value <<= AcpiHwGetBitShift (Mask);
44769450Smsmith            Value &= Mask;
44867754Smsmith
44969450Smsmith            if (Value)
45067754Smsmith            {
45177424Smsmith                AcpiHwRegisterWrite (ACPI_MTX_DO_NOT_LOCK, PM1_STS,
45277424Smsmith                    (UINT16) Value);
45369450Smsmith                RegisterValue = 0;
45467754Smsmith            }
45567754Smsmith        }
45667754Smsmith
45769450Smsmith        break;
45867754Smsmith
45967754Smsmith
46069450Smsmith    case PM1_EN:
46167754Smsmith
46269450Smsmith        switch (RegisterId)
46369450Smsmith        {
46469450Smsmith        case TMR_EN:
46569450Smsmith            Mask = TMR_EN_MASK;
46669450Smsmith            break;
46767754Smsmith
46869450Smsmith        case GBL_EN:
46969450Smsmith            Mask = GBL_EN_MASK;
47069450Smsmith            break;
47167754Smsmith
47269450Smsmith        case PWRBTN_EN:
47369450Smsmith            Mask = PWRBTN_EN_MASK;
47469450Smsmith            break;
47567754Smsmith
47669450Smsmith        case SLPBTN_EN:
47769450Smsmith            Mask = SLPBTN_EN_MASK;
47869450Smsmith            break;
47967754Smsmith
48069450Smsmith        case RTC_EN:
48169450Smsmith            Mask = RTC_EN_MASK;
48269450Smsmith            break;
48367754Smsmith
48469450Smsmith        default:
48569450Smsmith            Mask = 0;
48669450Smsmith            break;
48769450Smsmith        }
48867754Smsmith
48969450Smsmith        RegisterValue = AcpiHwRegisterRead (ACPI_MTX_DO_NOT_LOCK, PM1_EN);
49067754Smsmith
49169450Smsmith        if (ReadWrite == ACPI_WRITE)
49269450Smsmith        {
49369450Smsmith            RegisterValue &= ~Mask;
49469450Smsmith            Value          <<= AcpiHwGetBitShift (Mask);
49569450Smsmith            Value          &= Mask;
49669450Smsmith            RegisterValue |= Value;
49767754Smsmith
49869450Smsmith            AcpiHwRegisterWrite (ACPI_MTX_DO_NOT_LOCK, PM1_EN, (UINT16) RegisterValue);
49969450Smsmith        }
50067754Smsmith
50167754Smsmith        break;
50267754Smsmith
50367754Smsmith
50467754Smsmith    case PM1_CONTROL:
50567754Smsmith
50667754Smsmith        switch (RegisterId)
50767754Smsmith        {
50867754Smsmith        case SCI_EN:
50967754Smsmith            Mask = SCI_EN_MASK;
51067754Smsmith            break;
51167754Smsmith
51267754Smsmith        case BM_RLD:
51367754Smsmith            Mask = BM_RLD_MASK;
51467754Smsmith            break;
51567754Smsmith
51667754Smsmith        case GBL_RLS:
51767754Smsmith            Mask = GBL_RLS_MASK;
51867754Smsmith            break;
51967754Smsmith
52067754Smsmith        case SLP_TYPE_A:
52167754Smsmith        case SLP_TYPE_B:
52267754Smsmith            Mask = SLP_TYPE_X_MASK;
52367754Smsmith            break;
52467754Smsmith
52567754Smsmith        case SLP_EN:
52667754Smsmith            Mask = SLP_EN_MASK;
52767754Smsmith            break;
52867754Smsmith
52967754Smsmith        default:
53067754Smsmith            Mask = 0;
53167754Smsmith            break;
53267754Smsmith        }
53367754Smsmith
53469450Smsmith
53569450Smsmith        /*
53669450Smsmith         * Read the PM1 Control register.
53769450Smsmith         * Note that at this level, the fact that there are actually TWO
53869450Smsmith         * registers (A and B) and that B may not exist, are abstracted.
53969450Smsmith         */
54069450Smsmith        RegisterValue = AcpiHwRegisterRead (ACPI_MTX_DO_NOT_LOCK, PM1_CONTROL);
54169450Smsmith
54282367Smsmith        ACPI_DEBUG_PRINT ((ACPI_DB_IO, "PM1 control: Read %X\n", RegisterValue));
54369450Smsmith
54467754Smsmith        if (ReadWrite == ACPI_WRITE)
54567754Smsmith        {
54667754Smsmith            RegisterValue  &= ~Mask;
54767754Smsmith            Value          <<= AcpiHwGetBitShift (Mask);
54867754Smsmith            Value          &= Mask;
54967754Smsmith            RegisterValue  |= Value;
55067754Smsmith
55167754Smsmith            /*
55269450Smsmith             * SLP_TYPE_x Registers are written differently
55369450Smsmith             * than any other control Registers with
55469450Smsmith             * respect to A and B Registers.  The value
55567754Smsmith             * for A may be different than the value for B
55669746Smsmith             *
55769746Smsmith             * Therefore, pass the RegisterId, not just generic PM1_CONTROL,
55869746Smsmith             * because we need to do different things. Yuck.
55967754Smsmith             */
56067754Smsmith
56177424Smsmith            AcpiHwRegisterWrite (ACPI_MTX_DO_NOT_LOCK, RegisterId,
56277424Smsmith                    (UINT16) RegisterValue);
56367754Smsmith        }
56467754Smsmith        break;
56567754Smsmith
56667754Smsmith
56767754Smsmith    case PM2_CONTROL:
56867754Smsmith
56967754Smsmith        switch (RegisterId)
57067754Smsmith        {
57167754Smsmith        case ARB_DIS:
57267754Smsmith            Mask = ARB_DIS_MASK;
57367754Smsmith            break;
57467754Smsmith
57567754Smsmith        default:
57667754Smsmith            Mask = 0;
57767754Smsmith            break;
57867754Smsmith        }
57967754Smsmith
58069450Smsmith        RegisterValue = AcpiHwRegisterRead (ACPI_MTX_DO_NOT_LOCK, PM2_CONTROL);
58169450Smsmith
58282367Smsmith        ACPI_DEBUG_PRINT ((ACPI_DB_IO, "PM2 control: Read %X from %p\n",
58377424Smsmith            RegisterValue, ACPI_GET_ADDRESS (AcpiGbl_FADT->XPm2CntBlk.Address)));
58469450Smsmith
58567754Smsmith        if (ReadWrite == ACPI_WRITE)
58667754Smsmith        {
58767754Smsmith            RegisterValue  &= ~Mask;
58867754Smsmith            Value          <<= AcpiHwGetBitShift (Mask);
58967754Smsmith            Value          &= Mask;
59067754Smsmith            RegisterValue  |= Value;
59167754Smsmith
59282367Smsmith            ACPI_DEBUG_PRINT ((ACPI_DB_IO, "About to write %04X to %p\n", RegisterValue,
59369450Smsmith                AcpiGbl_FADT->XPm2CntBlk.Address));
59467754Smsmith
59569450Smsmith            AcpiHwRegisterWrite (ACPI_MTX_DO_NOT_LOCK,
59669450Smsmith                                PM2_CONTROL, (UINT8) (RegisterValue));
59767754Smsmith        }
59867754Smsmith        break;
59967754Smsmith
60067754Smsmith
60167754Smsmith    case PM_TIMER:
60267754Smsmith
60369450Smsmith        Mask = TMR_VAL_MASK;
60469450Smsmith        RegisterValue = AcpiHwRegisterRead (ACPI_MTX_DO_NOT_LOCK,
60569450Smsmith                                            PM_TIMER);
60682367Smsmith        ACPI_DEBUG_PRINT ((ACPI_DB_IO, "PM_TIMER: Read %X from %p\n",
60777424Smsmith            RegisterValue, ACPI_GET_ADDRESS (AcpiGbl_FADT->XPmTmrBlk.Address)));
60867754Smsmith
60967754Smsmith        break;
61067754Smsmith
61167754Smsmith
61267754Smsmith    case GPE1_EN_BLOCK:
61367754Smsmith    case GPE1_STS_BLOCK:
61467754Smsmith    case GPE0_EN_BLOCK:
61567754Smsmith    case GPE0_STS_BLOCK:
61667754Smsmith
61769450Smsmith        /* Determine the bit to be accessed
61869450Smsmith         *
61969450Smsmith         *  (UINT32) RegisterId:
62069450Smsmith         *      31      24       16       8        0
62169450Smsmith         *      +--------+--------+--------+--------+
62269450Smsmith         *      |  gpe_block_id   |  gpe_bit_number |
62369450Smsmith         *      +--------+--------+--------+--------+
62469450Smsmith         *
62569450Smsmith         *     gpe_block_id is one of GPE[01]_EN_BLOCK and GPE[01]_STS_BLOCK
62669450Smsmith         *     gpe_bit_number is relative from the gpe_block (0x00~0xFF)
62769450Smsmith         */
62867754Smsmith
62969450Smsmith        Mask = REGISTER_BIT_ID(RegisterId); /* gpe_bit_number */
63069450Smsmith        RegisterId = REGISTER_BLOCK_ID(RegisterId) | (Mask >> 3);
63169450Smsmith        Mask = AcpiGbl_DecodeTo8bit [Mask % 8];
63267754Smsmith
63367754Smsmith        /*
63467754Smsmith         * The base address of the GPE 0 Register Block
63567754Smsmith         * Plus 1/2 the length of the GPE 0 Register Block
63669450Smsmith         * The enable Register is the Register following the Status Register
63769450Smsmith         * and each Register is defined as 1/2 of the total Register Block
63867754Smsmith         */
63967754Smsmith
64067754Smsmith        /*
64167754Smsmith         * This sets the bit within EnableBit that needs to be written to
64269450Smsmith         * the Register indicated in Mask to a 1, all others are 0
64367754Smsmith         */
64467754Smsmith
64567754Smsmith        /* Now get the current Enable Bits in the selected Reg */
64667754Smsmith
64769450Smsmith        RegisterValue = AcpiHwRegisterRead (ACPI_MTX_DO_NOT_LOCK, RegisterId);
64882367Smsmith        ACPI_DEBUG_PRINT ((ACPI_DB_IO, "GPE Enable bits: Read %X from %X\n",
64977424Smsmith            RegisterValue, RegisterId));
65067754Smsmith
65167754Smsmith        if (ReadWrite == ACPI_WRITE)
65267754Smsmith        {
65367754Smsmith            RegisterValue  &= ~Mask;
65467754Smsmith            Value          <<= AcpiHwGetBitShift (Mask);
65567754Smsmith            Value          &= Mask;
65667754Smsmith            RegisterValue  |= Value;
65767754Smsmith
65867754Smsmith            /* This write will put the Action state into the General Purpose */
65967754Smsmith            /* Enable Register indexed by the value in Mask */
66067754Smsmith
66182367Smsmith            ACPI_DEBUG_PRINT ((ACPI_DB_IO, "About to write %04X to %04X\n",
66277424Smsmith                RegisterValue, RegisterId));
66377424Smsmith            AcpiHwRegisterWrite (ACPI_MTX_DO_NOT_LOCK, RegisterId,
66477424Smsmith                (UINT8) RegisterValue);
66577424Smsmith            RegisterValue = AcpiHwRegisterRead (ACPI_MTX_DO_NOT_LOCK,
66677424Smsmith                                RegisterId);
66767754Smsmith        }
66867754Smsmith        break;
66967754Smsmith
67067754Smsmith
67169450Smsmith    case SMI_CMD_BLOCK:
67267754Smsmith    case PROCESSOR_BLOCK:
67377424Smsmith        /* Not used by any callers at this time - therefore, not implemented */
67477424Smsmith
67567754Smsmith    default:
67667754Smsmith
67767754Smsmith        Mask = 0;
67867754Smsmith        break;
67967754Smsmith    }
68067754Smsmith
68169450Smsmith    if (ACPI_MTX_LOCK == UseLock) {
68277424Smsmith        AcpiUtReleaseMutex (ACPI_MTX_HARDWARE);
68369450Smsmith    }
68467754Smsmith
68569450Smsmith
68667754Smsmith    RegisterValue &= Mask;
68767754Smsmith    RegisterValue >>= AcpiHwGetBitShift (Mask);
68867754Smsmith
68982367Smsmith    ACPI_DEBUG_PRINT ((ACPI_DB_IO, "Register I/O: returning %X\n", RegisterValue));
69067754Smsmith    return_VALUE (RegisterValue);
69167754Smsmith}
69269450Smsmith
69369450Smsmith
69469450Smsmith/******************************************************************************
69569450Smsmith *
69669450Smsmith * FUNCTION:    AcpiHwRegisterRead
69769450Smsmith *
69869450Smsmith * PARAMETERS:  UseLock                - Mutex hw access.
69969450Smsmith *              RegisterId             - RegisterID + Offset.
70069450Smsmith *
70169450Smsmith * RETURN:      Value read or written.
70269450Smsmith *
70369450Smsmith * DESCRIPTION: Acpi register read function.  Registers are read at the
70469450Smsmith *              given offset.
70569450Smsmith *
70669450Smsmith ******************************************************************************/
70769450Smsmith
70869450SmsmithUINT32
70969450SmsmithAcpiHwRegisterRead (
71069450Smsmith    BOOLEAN                 UseLock,
71169450Smsmith    UINT32                  RegisterId)
71269450Smsmith{
71380062Smsmith    UINT32                  Value = 0;
71469450Smsmith    UINT32                  BankOffset;
71569450Smsmith
71677424Smsmith
71769450Smsmith    FUNCTION_TRACE ("AcpiHwRegisterRead");
71869450Smsmith
71977424Smsmith
72069450Smsmith    if (ACPI_MTX_LOCK == UseLock)
72169450Smsmith    {
72277424Smsmith        AcpiUtAcquireMutex (ACPI_MTX_HARDWARE);
72369450Smsmith    }
72469450Smsmith
72569450Smsmith
72669450Smsmith    switch (REGISTER_BLOCK_ID(RegisterId))
72769450Smsmith    {
72869450Smsmith    case PM1_STS: /* 16-bit access */
72969450Smsmith
73069746Smsmith        Value =  AcpiHwLowLevelRead (16, &AcpiGbl_FADT->XPm1aEvtBlk, 0);
73169746Smsmith        Value |= AcpiHwLowLevelRead (16, &AcpiGbl_FADT->XPm1bEvtBlk, 0);
73269450Smsmith        break;
73369450Smsmith
73469450Smsmith
73569450Smsmith    case PM1_EN: /* 16-bit access*/
73669450Smsmith
73769450Smsmith        BankOffset  = DIV_2 (AcpiGbl_FADT->Pm1EvtLen);
73869746Smsmith        Value =  AcpiHwLowLevelRead (16, &AcpiGbl_FADT->XPm1aEvtBlk, BankOffset);
73969746Smsmith        Value |= AcpiHwLowLevelRead (16, &AcpiGbl_FADT->XPm1bEvtBlk, BankOffset);
74069450Smsmith        break;
74169450Smsmith
74269450Smsmith
74369450Smsmith    case PM1_CONTROL: /* 16-bit access */
74469450Smsmith
74571867Smsmith        Value =  AcpiHwLowLevelRead (16, &AcpiGbl_FADT->XPm1aCntBlk, 0);
74671867Smsmith        Value |= AcpiHwLowLevelRead (16, &AcpiGbl_FADT->XPm1bCntBlk, 0);
74769450Smsmith        break;
74869450Smsmith
74969450Smsmith
75069450Smsmith    case PM2_CONTROL: /* 8-bit access */
75169450Smsmith
75269746Smsmith        Value =  AcpiHwLowLevelRead (8, &AcpiGbl_FADT->XPm2CntBlk, 0);
75369450Smsmith        break;
75469450Smsmith
75569450Smsmith
75669450Smsmith    case PM_TIMER: /* 32-bit access */
75769450Smsmith
75869746Smsmith        Value =  AcpiHwLowLevelRead (32, &AcpiGbl_FADT->XPmTmrBlk, 0);
75969450Smsmith        break;
76069450Smsmith
76169450Smsmith
76282367Smsmith    /*
76382367Smsmith     * For the GPE? Blocks, the lower word of RegisterId contains the
76482367Smsmith     * byte offset for which to read, as each part of each block may be
76582367Smsmith     * several bytes long.
76682367Smsmith     */
76769450Smsmith    case GPE0_STS_BLOCK: /* 8-bit access */
76869450Smsmith
76982367Smsmith	BankOffset = REGISTER_BIT_ID(RegisterId);
77082367Smsmith        Value = AcpiHwLowLevelRead (8, &AcpiGbl_FADT->XGpe0Blk, BankOffset);
77169450Smsmith        break;
77269450Smsmith
77369450Smsmith    case GPE0_EN_BLOCK: /* 8-bit access */
77469450Smsmith
77582367Smsmith        BankOffset = DIV_2 (AcpiGbl_FADT->Gpe0BlkLen) + REGISTER_BIT_ID(RegisterId);
77682367Smsmith        Value = AcpiHwLowLevelRead (8, &AcpiGbl_FADT->XGpe0Blk, BankOffset);
77769450Smsmith        break;
77869450Smsmith
77969450Smsmith    case GPE1_STS_BLOCK: /* 8-bit access */
78069450Smsmith
78182367Smsmith	BankOffset = REGISTER_BIT_ID(RegisterId);
78282367Smsmith        Value = AcpiHwLowLevelRead (8, &AcpiGbl_FADT->XGpe1Blk, BankOffset);
78369450Smsmith        break;
78469450Smsmith
78569450Smsmith    case GPE1_EN_BLOCK: /* 8-bit access */
78669450Smsmith
78782367Smsmith        BankOffset  = DIV_2 (AcpiGbl_FADT->Gpe1BlkLen) + REGISTER_BIT_ID(RegisterId);
78882367Smsmith        Value = AcpiHwLowLevelRead (8, &AcpiGbl_FADT->XGpe1Blk, BankOffset);
78969450Smsmith        break;
79069450Smsmith
79169450Smsmith    case SMI_CMD_BLOCK: /* 8bit */
79269450Smsmith
79380062Smsmith        AcpiOsReadPort (AcpiGbl_FADT->SmiCmd, &Value, 8);
79469450Smsmith        break;
79569450Smsmith
79669450Smsmith    default:
79780062Smsmith        /* Value will be returned as 0 */
79869450Smsmith        break;
79969450Smsmith    }
80069450Smsmith
80169450Smsmith
80269450Smsmith    if (ACPI_MTX_LOCK == UseLock)
80369450Smsmith    {
80477424Smsmith        AcpiUtReleaseMutex (ACPI_MTX_HARDWARE);
80569450Smsmith    }
80669450Smsmith
80769450Smsmith    return_VALUE (Value);
80869450Smsmith}
80969450Smsmith
81069450Smsmith
81169450Smsmith/******************************************************************************
81269450Smsmith *
81369450Smsmith * FUNCTION:    AcpiHwRegisterWrite
81469450Smsmith *
81569450Smsmith * PARAMETERS:  UseLock                - Mutex hw access.
81669450Smsmith *              RegisterId             - RegisterID + Offset.
81769450Smsmith *
81869450Smsmith * RETURN:      Value read or written.
81969450Smsmith *
82069450Smsmith * DESCRIPTION: Acpi register Write function.  Registers are written at the
82169450Smsmith *              given offset.
82269450Smsmith *
82369450Smsmith ******************************************************************************/
82469450Smsmith
82569450Smsmithvoid
82669450SmsmithAcpiHwRegisterWrite (
82769450Smsmith    BOOLEAN                 UseLock,
82869450Smsmith    UINT32                  RegisterId,
82969450Smsmith    UINT32                  Value)
83069450Smsmith{
83169450Smsmith    UINT32                  BankOffset;
83269450Smsmith
83369450Smsmith    FUNCTION_TRACE ("AcpiHwRegisterWrite");
83469450Smsmith
83569450Smsmith
83669450Smsmith    if (ACPI_MTX_LOCK == UseLock)
83769450Smsmith    {
83877424Smsmith        AcpiUtAcquireMutex (ACPI_MTX_HARDWARE);
83969450Smsmith    }
84069450Smsmith
84169450Smsmith
84269450Smsmith    switch (REGISTER_BLOCK_ID (RegisterId))
84369450Smsmith    {
84469450Smsmith    case PM1_STS: /* 16-bit access */
84569450Smsmith
84669746Smsmith        AcpiHwLowLevelWrite (16, Value, &AcpiGbl_FADT->XPm1aEvtBlk, 0);
84769746Smsmith        AcpiHwLowLevelWrite (16, Value, &AcpiGbl_FADT->XPm1bEvtBlk, 0);
84869450Smsmith        break;
84969450Smsmith
85069450Smsmith
85169450Smsmith    case PM1_EN: /* 16-bit access*/
85269450Smsmith
85369450Smsmith        BankOffset = DIV_2 (AcpiGbl_FADT->Pm1EvtLen);
85469746Smsmith        AcpiHwLowLevelWrite (16, Value, &AcpiGbl_FADT->XPm1aEvtBlk, BankOffset);
85569746Smsmith        AcpiHwLowLevelWrite (16, Value, &AcpiGbl_FADT->XPm1bEvtBlk, BankOffset);
85669450Smsmith        break;
85769450Smsmith
85869450Smsmith
85969450Smsmith    case PM1_CONTROL: /* 16-bit access */
86069450Smsmith
86171867Smsmith        AcpiHwLowLevelWrite (16, Value, &AcpiGbl_FADT->XPm1aCntBlk, 0);
86271867Smsmith        AcpiHwLowLevelWrite (16, Value, &AcpiGbl_FADT->XPm1bCntBlk, 0);
86371867Smsmith        break;
86469450Smsmith
86569450Smsmith
86671867Smsmith    case PM1A_CONTROL: /* 16-bit access */
86769450Smsmith
86871867Smsmith        AcpiHwLowLevelWrite (16, Value, &AcpiGbl_FADT->XPm1aCntBlk, 0);
86969450Smsmith        break;
87069450Smsmith
87169450Smsmith
87271867Smsmith    case PM1B_CONTROL: /* 16-bit access */
87371867Smsmith
87471867Smsmith        AcpiHwLowLevelWrite (16, Value, &AcpiGbl_FADT->XPm1bCntBlk, 0);
87571867Smsmith        break;
87671867Smsmith
87771867Smsmith
87869450Smsmith    case PM2_CONTROL: /* 8-bit access */
87969450Smsmith
88069746Smsmith        AcpiHwLowLevelWrite (8, Value, &AcpiGbl_FADT->XPm2CntBlk, 0);
88169450Smsmith        break;
88269450Smsmith
88369450Smsmith
88469450Smsmith    case PM_TIMER: /* 32-bit access */
88569450Smsmith
88669746Smsmith        AcpiHwLowLevelWrite (32, Value, &AcpiGbl_FADT->XPmTmrBlk, 0);
88769450Smsmith        break;
88869450Smsmith
88969450Smsmith
89069450Smsmith    case GPE0_STS_BLOCK: /* 8-bit access */
89169450Smsmith
89282367Smsmith	BankOffset = REGISTER_BIT_ID(RegisterId);
89382367Smsmith        AcpiHwLowLevelWrite (8, Value, &AcpiGbl_FADT->XGpe0Blk, BankOffset);
89469450Smsmith        break;
89569450Smsmith
89669450Smsmith
89769450Smsmith    case GPE0_EN_BLOCK: /* 8-bit access */
89869450Smsmith
89982367Smsmith        BankOffset  = DIV_2 (AcpiGbl_FADT->Gpe0BlkLen) + REGISTER_BIT_ID(RegisterId);
90069746Smsmith        AcpiHwLowLevelWrite (8, Value, &AcpiGbl_FADT->XGpe0Blk, BankOffset);
90169450Smsmith        break;
90269450Smsmith
90369450Smsmith
90469450Smsmith    case GPE1_STS_BLOCK: /* 8-bit access */
90569450Smsmith
90682367Smsmith	BankOffset = REGISTER_BIT_ID(RegisterId);
90782367Smsmith        AcpiHwLowLevelWrite (8, Value, &AcpiGbl_FADT->XGpe1Blk, BankOffset);
90869450Smsmith        break;
90969450Smsmith
91069450Smsmith
91169450Smsmith    case GPE1_EN_BLOCK: /* 8-bit access */
91269450Smsmith
91382367Smsmith        BankOffset  = DIV_2 (AcpiGbl_FADT->Gpe1BlkLen) + REGISTER_BIT_ID(RegisterId);
91469746Smsmith        AcpiHwLowLevelWrite (8, Value, &AcpiGbl_FADT->XGpe1Blk, BankOffset);
91569450Smsmith        break;
91669450Smsmith
91769450Smsmith
91869450Smsmith    case SMI_CMD_BLOCK: /* 8bit */
91969450Smsmith
92069450Smsmith        /* For 2.0, SMI_CMD is always in IO space */
92169450Smsmith        /* TBD: what about 1.0? 0.71? */
92269450Smsmith
92380062Smsmith        AcpiOsWritePort (AcpiGbl_FADT->SmiCmd, Value, 8);
92469450Smsmith        break;
92569450Smsmith
92669450Smsmith
92769450Smsmith    default:
92869450Smsmith        Value = 0;
92969450Smsmith        break;
93069450Smsmith    }
93169450Smsmith
93269450Smsmith
93369450Smsmith    if (ACPI_MTX_LOCK == UseLock)
93469450Smsmith    {
93577424Smsmith        AcpiUtReleaseMutex (ACPI_MTX_HARDWARE);
93669450Smsmith    }
93769450Smsmith
93869450Smsmith    return_VOID;
93969450Smsmith}
94069450Smsmith
94169450Smsmith
94269450Smsmith/******************************************************************************
94369450Smsmith *
94469450Smsmith * FUNCTION:    AcpiHwLowLevelRead
94569450Smsmith *
94669450Smsmith * PARAMETERS:  Register            - GAS register structure
94769450Smsmith *              Offset              - Offset from the base address in the GAS
94869450Smsmith *              Width               - 8, 16, or 32
94969450Smsmith *
95069450Smsmith * RETURN:      Value read
95169450Smsmith *
95269450Smsmith * DESCRIPTION: Read from either memory, IO, or PCI config space.
95369450Smsmith *
95469450Smsmith ******************************************************************************/
95569450Smsmith
95669450SmsmithUINT32
95769450SmsmithAcpiHwLowLevelRead (
95869450Smsmith    UINT32                  Width,
95977424Smsmith    ACPI_GENERIC_ADDRESS    *Reg,
96069450Smsmith    UINT32                  Offset)
96169450Smsmith{
96269450Smsmith    UINT32                  Value = 0;
96369450Smsmith    ACPI_PHYSICAL_ADDRESS   MemAddress;
96469450Smsmith    ACPI_IO_ADDRESS         IoAddress;
96580062Smsmith    ACPI_PCI_ID             PciId;
96680062Smsmith    UINT16                  PciRegister;
96769450Smsmith
96869450Smsmith
96969450Smsmith    /*
97069450Smsmith     * Must have a valid pointer to a GAS structure, and
97169450Smsmith     * a non-zero address within
97269450Smsmith     */
97369450Smsmith    if ((!Reg) ||
97470243Smsmith        (!ACPI_VALID_ADDRESS (Reg->Address)))
97569450Smsmith    {
97669450Smsmith        return 0;
97769450Smsmith    }
97869450Smsmith
97969450Smsmith
98069450Smsmith    /*
98169450Smsmith     * Three address spaces supported:
98269450Smsmith     * Memory, Io, or PCI config.
98369450Smsmith     */
98469450Smsmith
98569450Smsmith    switch (Reg->AddressSpaceId)
98669450Smsmith    {
98777424Smsmith    case ACPI_ADR_SPACE_SYSTEM_MEMORY:
98869450Smsmith
98970243Smsmith        MemAddress = (ACPI_PHYSICAL_ADDRESS) (ACPI_GET_ADDRESS (Reg->Address) + Offset);
99069450Smsmith
99180062Smsmith        AcpiOsReadMemory (MemAddress, &Value, Width);
99269450Smsmith        break;
99369450Smsmith
99469450Smsmith
99577424Smsmith    case ACPI_ADR_SPACE_SYSTEM_IO:
99669450Smsmith
99770243Smsmith        IoAddress = (ACPI_IO_ADDRESS) (ACPI_GET_ADDRESS (Reg->Address) + Offset);
99869450Smsmith
99980062Smsmith        AcpiOsReadPort (IoAddress, &Value, Width);
100069450Smsmith        break;
100169450Smsmith
100269450Smsmith
100377424Smsmith    case ACPI_ADR_SPACE_PCI_CONFIG:
100469450Smsmith
100580062Smsmith        PciId.Segment  = 0;
100680062Smsmith        PciId.Bus      = 0;
100780062Smsmith        PciId.Device   = ACPI_PCI_DEVICE (ACPI_GET_ADDRESS (Reg->Address));
100880062Smsmith        PciId.Function = ACPI_PCI_FUNCTION (ACPI_GET_ADDRESS (Reg->Address));
100980062Smsmith        PciRegister    = (UINT16) (ACPI_PCI_REGISTER (ACPI_GET_ADDRESS (Reg->Address)) + Offset);
101069450Smsmith
101180062Smsmith        AcpiOsReadPciConfiguration  (&PciId, PciRegister, &Value, Width);
101269450Smsmith        break;
101369450Smsmith    }
101469450Smsmith
101569450Smsmith    return Value;
101669450Smsmith}
101769450Smsmith
101869450Smsmith
101969450Smsmith/******************************************************************************
102069450Smsmith *
102169450Smsmith * FUNCTION:    AcpiHwLowLevelWrite
102269450Smsmith *
102369450Smsmith * PARAMETERS:  Width               - 8, 16, or 32
102469450Smsmith *              Value               - To be written
102569450Smsmith *              Register            - GAS register structure
102669450Smsmith *              Offset              - Offset from the base address in the GAS
102769450Smsmith *
102869450Smsmith *
102969450Smsmith * RETURN:      Value read
103069450Smsmith *
103169450Smsmith * DESCRIPTION: Read from either memory, IO, or PCI config space.
103269450Smsmith *
103369450Smsmith ******************************************************************************/
103469450Smsmith
103569450Smsmithvoid
103669450SmsmithAcpiHwLowLevelWrite (
103769450Smsmith    UINT32                  Width,
103869450Smsmith    UINT32                  Value,
103977424Smsmith    ACPI_GENERIC_ADDRESS    *Reg,
104069450Smsmith    UINT32                  Offset)
104169450Smsmith{
104269450Smsmith    ACPI_PHYSICAL_ADDRESS   MemAddress;
104369450Smsmith    ACPI_IO_ADDRESS         IoAddress;
104480062Smsmith    ACPI_PCI_ID             PciId;
104580062Smsmith    UINT16                  PciRegister;
104669450Smsmith
104769450Smsmith
104869450Smsmith    /*
104969450Smsmith     * Must have a valid pointer to a GAS structure, and
105069450Smsmith     * a non-zero address within
105169450Smsmith     */
105269450Smsmith    if ((!Reg) ||
105370243Smsmith        (!ACPI_VALID_ADDRESS (Reg->Address)))
105469450Smsmith    {
105569450Smsmith        return;
105669450Smsmith    }
105769450Smsmith
105869450Smsmith
105969450Smsmith    /*
106069450Smsmith     * Three address spaces supported:
106169450Smsmith     * Memory, Io, or PCI config.
106269450Smsmith     */
106369450Smsmith
106469450Smsmith    switch (Reg->AddressSpaceId)
106569450Smsmith    {
106677424Smsmith    case ACPI_ADR_SPACE_SYSTEM_MEMORY:
106769450Smsmith
106870243Smsmith        MemAddress = (ACPI_PHYSICAL_ADDRESS) (ACPI_GET_ADDRESS (Reg->Address) + Offset);
106969450Smsmith
107080062Smsmith        AcpiOsWriteMemory (MemAddress, Value, Width);
107169450Smsmith        break;
107269450Smsmith
107369450Smsmith
107477424Smsmith    case ACPI_ADR_SPACE_SYSTEM_IO:
107569450Smsmith
107670243Smsmith        IoAddress = (ACPI_IO_ADDRESS) (ACPI_GET_ADDRESS (Reg->Address) + Offset);
107769450Smsmith
107880062Smsmith        AcpiOsWritePort (IoAddress, Value, Width);
107969450Smsmith        break;
108069450Smsmith
108169450Smsmith
108277424Smsmith    case ACPI_ADR_SPACE_PCI_CONFIG:
108369450Smsmith
108480062Smsmith        PciId.Segment  = 0;
108580062Smsmith        PciId.Bus      = 0;
108680062Smsmith        PciId.Device   = ACPI_PCI_DEVICE (ACPI_GET_ADDRESS (Reg->Address));
108780062Smsmith        PciId.Function = ACPI_PCI_FUNCTION (ACPI_GET_ADDRESS (Reg->Address));
108880062Smsmith        PciRegister    = (UINT16) (ACPI_PCI_REGISTER (ACPI_GET_ADDRESS (Reg->Address)) + Offset);
108969450Smsmith
109080062Smsmith        AcpiOsWritePciConfiguration (&PciId, PciRegister, Value, Width);
109169450Smsmith        break;
109269450Smsmith    }
109369450Smsmith}
1094