evregion.c revision 91116
167754Smsmith/******************************************************************************
267754Smsmith *
369450Smsmith * Module Name: evregion - ACPI AddressSpace (OpRegion) handler dispatch
491116Smsmith *              $Revision: 128 $
567754Smsmith *
667754Smsmith *****************************************************************************/
767754Smsmith
867754Smsmith/******************************************************************************
967754Smsmith *
1067754Smsmith * 1. Copyright Notice
1167754Smsmith *
1291116Smsmith * Some or all of this work - Copyright (c) 1999 - 2002, Intel Corp.
1370243Smsmith * All rights reserved.
1467754Smsmith *
1567754Smsmith * 2. License
1667754Smsmith *
1767754Smsmith * 2.1. This is your license from Intel Corp. under its intellectual property
1867754Smsmith * rights.  You may have additional license terms from the party that provided
1967754Smsmith * you this software, covering your right to use that party's intellectual
2067754Smsmith * property rights.
2167754Smsmith *
2267754Smsmith * 2.2. Intel grants, free of charge, to any person ("Licensee") obtaining a
2367754Smsmith * copy of the source code appearing in this file ("Covered Code") an
2467754Smsmith * irrevocable, perpetual, worldwide license under Intel's copyrights in the
2567754Smsmith * base code distributed originally by Intel ("Original Intel Code") to copy,
2667754Smsmith * make derivatives, distribute, use and display any portion of the Covered
2767754Smsmith * Code in any form, with the right to sublicense such rights; and
2867754Smsmith *
2967754Smsmith * 2.3. Intel grants Licensee a non-exclusive and non-transferable patent
3067754Smsmith * license (with the right to sublicense), under only those claims of Intel
3167754Smsmith * patents that are infringed by the Original Intel Code, to make, use, sell,
3267754Smsmith * offer to sell, and import the Covered Code and derivative works thereof
3367754Smsmith * solely to the minimum extent necessary to exercise the above copyright
3467754Smsmith * license, and in no event shall the patent license extend to any additions
3567754Smsmith * to or modifications of the Original Intel Code.  No other license or right
3667754Smsmith * is granted directly or by implication, estoppel or otherwise;
3767754Smsmith *
3867754Smsmith * The above copyright and patent license is granted only if the following
3967754Smsmith * conditions are met:
4067754Smsmith *
4167754Smsmith * 3. Conditions
4267754Smsmith *
4367754Smsmith * 3.1. Redistribution of Source with Rights to Further Distribute Source.
4467754Smsmith * Redistribution of source code of any substantial portion of the Covered
4567754Smsmith * Code or modification with rights to further distribute source must include
4667754Smsmith * the above Copyright Notice, the above License, this list of Conditions,
4767754Smsmith * and the following Disclaimer and Export Compliance provision.  In addition,
4867754Smsmith * Licensee must cause all Covered Code to which Licensee contributes to
4967754Smsmith * contain a file documenting the changes Licensee made to create that Covered
5067754Smsmith * Code and the date of any change.  Licensee must include in that file the
5167754Smsmith * documentation of any changes made by any predecessor Licensee.  Licensee
5267754Smsmith * must include a prominent statement that the modification is derived,
5367754Smsmith * directly or indirectly, from Original Intel Code.
5467754Smsmith *
5567754Smsmith * 3.2. Redistribution of Source with no Rights to Further Distribute Source.
5667754Smsmith * Redistribution of source code of any substantial portion of the Covered
5767754Smsmith * Code or modification without rights to further distribute source must
5867754Smsmith * include the following Disclaimer and Export Compliance provision in the
5967754Smsmith * documentation and/or other materials provided with distribution.  In
6067754Smsmith * addition, Licensee may not authorize further sublicense of source of any
6167754Smsmith * portion of the Covered Code, and must include terms to the effect that the
6267754Smsmith * license from Licensee to its licensee is limited to the intellectual
6367754Smsmith * property embodied in the software Licensee provides to its licensee, and
6467754Smsmith * not to intellectual property embodied in modifications its licensee may
6567754Smsmith * make.
6667754Smsmith *
6767754Smsmith * 3.3. Redistribution of Executable. Redistribution in executable form of any
6867754Smsmith * substantial portion of the Covered Code or modification must reproduce the
6967754Smsmith * above Copyright Notice, and the following Disclaimer and Export Compliance
7067754Smsmith * provision in the documentation and/or other materials provided with the
7167754Smsmith * distribution.
7267754Smsmith *
7367754Smsmith * 3.4. Intel retains all right, title, and interest in and to the Original
7467754Smsmith * Intel Code.
7567754Smsmith *
7667754Smsmith * 3.5. Neither the name Intel nor any other trademark owned or controlled by
7767754Smsmith * Intel shall be used in advertising or otherwise to promote the sale, use or
7867754Smsmith * other dealings in products derived from or relating to the Covered Code
7967754Smsmith * without prior written authorization from Intel.
8067754Smsmith *
8167754Smsmith * 4. Disclaimer and Export Compliance
8267754Smsmith *
8367754Smsmith * 4.1. INTEL MAKES NO WARRANTY OF ANY KIND REGARDING ANY SOFTWARE PROVIDED
8467754Smsmith * HERE.  ANY SOFTWARE ORIGINATING FROM INTEL OR DERIVED FROM INTEL SOFTWARE
8567754Smsmith * IS PROVIDED "AS IS," AND INTEL WILL NOT PROVIDE ANY SUPPORT,  ASSISTANCE,
8667754Smsmith * INSTALLATION, TRAINING OR OTHER SERVICES.  INTEL WILL NOT PROVIDE ANY
8767754Smsmith * UPDATES, ENHANCEMENTS OR EXTENSIONS.  INTEL SPECIFICALLY DISCLAIMS ANY
8867754Smsmith * IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT AND FITNESS FOR A
8967754Smsmith * PARTICULAR PURPOSE.
9067754Smsmith *
9167754Smsmith * 4.2. IN NO EVENT SHALL INTEL HAVE ANY LIABILITY TO LICENSEE, ITS LICENSEES
9267754Smsmith * OR ANY OTHER THIRD PARTY, FOR ANY LOST PROFITS, LOST DATA, LOSS OF USE OR
9367754Smsmith * COSTS OF PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, OR FOR ANY INDIRECT,
9467754Smsmith * SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THIS AGREEMENT, UNDER ANY
9567754Smsmith * CAUSE OF ACTION OR THEORY OF LIABILITY, AND IRRESPECTIVE OF WHETHER INTEL
9667754Smsmith * HAS ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES.  THESE LIMITATIONS
9767754Smsmith * SHALL APPLY NOTWITHSTANDING THE FAILURE OF THE ESSENTIAL PURPOSE OF ANY
9867754Smsmith * LIMITED REMEDY.
9967754Smsmith *
10067754Smsmith * 4.3. Licensee shall not export, either directly or indirectly, any of this
10167754Smsmith * software or system incorporating such software without first obtaining any
10267754Smsmith * required license or other approval from the U. S. Department of Commerce or
10367754Smsmith * any other agency or department of the United States Government.  In the
10467754Smsmith * event Licensee exports any such software from the United States or
10567754Smsmith * re-exports any such software from a foreign destination, Licensee shall
10667754Smsmith * ensure that the distribution and export/re-export of the software is in
10767754Smsmith * compliance with all laws, regulations, orders, or other restrictions of the
10867754Smsmith * U.S. Export Administration Regulations. Licensee agrees that neither it nor
10967754Smsmith * any of its subsidiaries will export/re-export any technical data, process,
11067754Smsmith * software, or service, directly or indirectly, to any country for which the
11167754Smsmith * United States government or any agency thereof requires an export license,
11267754Smsmith * other governmental approval, or letter of assurance, without first obtaining
11367754Smsmith * such license, approval or letter.
11467754Smsmith *
11567754Smsmith *****************************************************************************/
11667754Smsmith
11767754Smsmith
11867754Smsmith#define __EVREGION_C__
11967754Smsmith
12067754Smsmith#include "acpi.h"
12167754Smsmith#include "acevents.h"
12267754Smsmith#include "acnamesp.h"
12367754Smsmith#include "acinterp.h"
12467754Smsmith#include "amlcode.h"
12567754Smsmith
12677424Smsmith#define _COMPONENT          ACPI_EVENTS
12791116Smsmith        ACPI_MODULE_NAME    ("evregion")
12867754Smsmith
12967754Smsmith
13077424Smsmith/*******************************************************************************
13167754Smsmith *
13267754Smsmith * FUNCTION:    AcpiEvInstallDefaultAddressSpaceHandlers
13367754Smsmith *
13467754Smsmith * PARAMETERS:
13567754Smsmith *
13667754Smsmith * RETURN:      Status
13767754Smsmith *
13867754Smsmith * DESCRIPTION: Installs the core subsystem address space handlers.
13967754Smsmith *
14077424Smsmith ******************************************************************************/
14167754Smsmith
14267754SmsmithACPI_STATUS
14367754SmsmithAcpiEvInstallDefaultAddressSpaceHandlers (
14467754Smsmith    void)
14567754Smsmith{
14667754Smsmith    ACPI_STATUS             Status;
14767754Smsmith
14867754Smsmith
14991116Smsmith    ACPI_FUNCTION_TRACE ("EvInstallDefaultAddressSpaceHandlers");
15067754Smsmith
15183174Smsmith
15267754Smsmith    /*
15367754Smsmith     * All address spaces (PCI Config, EC, SMBus) are scope dependent
15467754Smsmith     * and registration must occur for a specific device.  In the case
15567754Smsmith     * system memory and IO address spaces there is currently no device
15667754Smsmith     * associated with the address space.  For these we use the root.
15767754Smsmith     * We install the default PCI config space handler at the root so
15867754Smsmith     * that this space is immediately available even though the we have
15967754Smsmith     * not enumerated all the PCI Root Buses yet.  This is to conform
16067754Smsmith     * to the ACPI specification which states that the PCI config
16167754Smsmith     * space must be always available -- even though we are nowhere
16267754Smsmith     * near ready to find the PCI root buses at this point.
16367754Smsmith     *
16487031Smsmith     * NOTE: We ignore AE_ALREADY_EXISTS because this means that a handler
16587031Smsmith     * has already been installed (via AcpiInstallAddressSpaceHandler)
16667754Smsmith     */
16791116Smsmith
16891116Smsmith    Status = AcpiInstallAddressSpaceHandler ((ACPI_HANDLE) AcpiGbl_RootNode,
16977424Smsmith                                             ACPI_ADR_SPACE_SYSTEM_MEMORY,
17067754Smsmith                                             ACPI_DEFAULT_HANDLER, NULL, NULL);
17167754Smsmith    if ((ACPI_FAILURE (Status)) &&
17287031Smsmith        (Status != AE_ALREADY_EXISTS))
17367754Smsmith    {
17467754Smsmith        return_ACPI_STATUS (Status);
17567754Smsmith    }
17667754Smsmith
17791116Smsmith    Status = AcpiInstallAddressSpaceHandler ((ACPI_HANDLE) AcpiGbl_RootNode,
17877424Smsmith                                             ACPI_ADR_SPACE_SYSTEM_IO,
17967754Smsmith                                             ACPI_DEFAULT_HANDLER, NULL, NULL);
18067754Smsmith    if ((ACPI_FAILURE (Status)) &&
18187031Smsmith        (Status != AE_ALREADY_EXISTS))
18267754Smsmith    {
18367754Smsmith        return_ACPI_STATUS (Status);
18467754Smsmith    }
18567754Smsmith
18691116Smsmith    Status = AcpiInstallAddressSpaceHandler ((ACPI_HANDLE) AcpiGbl_RootNode,
18777424Smsmith                                             ACPI_ADR_SPACE_PCI_CONFIG,
18867754Smsmith                                             ACPI_DEFAULT_HANDLER, NULL, NULL);
18967754Smsmith    if ((ACPI_FAILURE (Status)) &&
19087031Smsmith        (Status != AE_ALREADY_EXISTS))
19167754Smsmith    {
19267754Smsmith        return_ACPI_STATUS (Status);
19367754Smsmith    }
19467754Smsmith
19591116Smsmith    Status = AcpiInstallAddressSpaceHandler ((ACPI_HANDLE) AcpiGbl_RootNode,
19691116Smsmith                                             ACPI_ADR_SPACE_DATA_TABLE,
19791116Smsmith                                             ACPI_DEFAULT_HANDLER, NULL, NULL);
19891116Smsmith    if ((ACPI_FAILURE (Status)) &&
19991116Smsmith        (Status != AE_ALREADY_EXISTS))
20091116Smsmith    {
20191116Smsmith        return_ACPI_STATUS (Status);
20291116Smsmith    }
20367754Smsmith
20467754Smsmith    return_ACPI_STATUS (AE_OK);
20567754Smsmith}
20667754Smsmith
20767754Smsmith
20877424Smsmith/*******************************************************************************
20967754Smsmith *
21067754Smsmith * FUNCTION:    AcpiEvExecuteRegMethod
21167754Smsmith *
21267754Smsmith * PARAMETERS:  RegionObj           - Object structure
21367754Smsmith *              Function            - On (1) or Off (0)
21467754Smsmith *
21567754Smsmith * RETURN:      Status
21667754Smsmith *
21767754Smsmith * DESCRIPTION: Execute _REG method for a region
21867754Smsmith *
21977424Smsmith ******************************************************************************/
22067754Smsmith
22169450Smsmithstatic ACPI_STATUS
22267754SmsmithAcpiEvExecuteRegMethod (
22367754Smsmith    ACPI_OPERAND_OBJECT    *RegionObj,
22467754Smsmith    UINT32                  Function)
22567754Smsmith{
22667754Smsmith    ACPI_OPERAND_OBJECT    *Params[3];
22787031Smsmith    ACPI_OPERAND_OBJECT    *RegionObj2;
22867754Smsmith    ACPI_STATUS             Status;
22967754Smsmith
23067754Smsmith
23191116Smsmith    ACPI_FUNCTION_TRACE ("EvExecuteRegMethod");
23267754Smsmith
23367754Smsmith
23487031Smsmith    RegionObj2 = AcpiNsGetSecondaryObject (RegionObj);
23587031Smsmith    if (!RegionObj2)
23667754Smsmith    {
23787031Smsmith        return_ACPI_STATUS (AE_NOT_EXIST);
23887031Smsmith    }
23987031Smsmith
24087031Smsmith    if (RegionObj2->Extra.Method_REG == NULL)
24187031Smsmith    {
24267754Smsmith        return_ACPI_STATUS (AE_OK);
24367754Smsmith    }
24467754Smsmith
24567754Smsmith    /*
24667754Smsmith     *  _REG method has two arguments
24767754Smsmith     *  Arg0:   Integer: Operation region space ID
24867754Smsmith     *          Same value as RegionObj->Region.SpaceId
24967754Smsmith     *  Arg1:   Integer: connection status
25067754Smsmith     *          1 for connecting the handler,
25167754Smsmith     *          0 for disconnecting the handler
25267754Smsmith     *          Passed as a parameter
25367754Smsmith     */
25484491Smsmith    Params[0] = AcpiUtCreateInternalObject (ACPI_TYPE_INTEGER);
25584491Smsmith    if (!Params[0])
25684491Smsmith    {
25784491Smsmith        return_ACPI_STATUS (AE_NO_MEMORY);
25884491Smsmith    }
25967754Smsmith
26084491Smsmith    Params[1] = AcpiUtCreateInternalObject (ACPI_TYPE_INTEGER);
26184491Smsmith    if (!Params[1])
26284491Smsmith    {
26385756Smsmith        Status = AE_NO_MEMORY;
26485756Smsmith        goto Cleanup;
26584491Smsmith    }
26667754Smsmith
26767754Smsmith    /*
26867754Smsmith     *  Set up the parameter objects
26967754Smsmith     */
27084491Smsmith    Params[0]->Integer.Value  = RegionObj->Region.SpaceId;
27184491Smsmith    Params[1]->Integer.Value = Function;
27285756Smsmith    Params[2] = NULL;
27367754Smsmith
27467754Smsmith    /*
27567754Smsmith     *  Execute the method, no return value
27667754Smsmith     */
27791116Smsmith    ACPI_DEBUG_EXEC(AcpiUtDisplayInitPathname (RegionObj2->Extra.Method_REG, "  [Method]"));
27887031Smsmith    Status = AcpiNsEvaluateByHandle (RegionObj2->Extra.Method_REG, Params, NULL);
27984491Smsmith
28085756Smsmith    AcpiUtRemoveReference (Params[1]);
28184491Smsmith
28285756SmsmithCleanup:
28384491Smsmith    AcpiUtRemoveReference (Params[0]);
28484491Smsmith
28567754Smsmith    return_ACPI_STATUS (Status);
28667754Smsmith}
28767754Smsmith
28867754Smsmith
28977424Smsmith/*******************************************************************************
29067754Smsmith *
29167754Smsmith * FUNCTION:    AcpiEvAddressSpaceDispatch
29267754Smsmith *
29367754Smsmith * PARAMETERS:  RegionObj           - internal region object
29467754Smsmith *              SpaceId             - ID of the address space (0-255)
29567754Smsmith *              Function            - Read or Write operation
29667754Smsmith *              Address             - Where in the space to read or write
29787031Smsmith *              BitWidth            - Field width in bits (8, 16, 32, or 64)
29867754Smsmith *              Value               - Pointer to in or out value
29967754Smsmith *
30067754Smsmith * RETURN:      Status
30167754Smsmith *
30267754Smsmith * DESCRIPTION: Dispatch an address space or operation region access to
30367754Smsmith *              a previously installed handler.
30467754Smsmith *
30577424Smsmith ******************************************************************************/
30667754Smsmith
30767754SmsmithACPI_STATUS
30867754SmsmithAcpiEvAddressSpaceDispatch (
30967754Smsmith    ACPI_OPERAND_OBJECT     *RegionObj,
31067754Smsmith    UINT32                  Function,
31169450Smsmith    ACPI_PHYSICAL_ADDRESS   Address,
31267754Smsmith    UINT32                  BitWidth,
31387031Smsmith    ACPI_INTEGER            *Value)
31467754Smsmith{
31567754Smsmith    ACPI_STATUS             Status;
31677424Smsmith    ACPI_ADR_SPACE_HANDLER  Handler;
31777424Smsmith    ACPI_ADR_SPACE_SETUP    RegionSetup;
31867754Smsmith    ACPI_OPERAND_OBJECT     *HandlerDesc;
31987031Smsmith    ACPI_OPERAND_OBJECT     *RegionObj2;
32067754Smsmith    void                    *RegionContext = NULL;
32167754Smsmith
32267754Smsmith
32391116Smsmith    ACPI_FUNCTION_TRACE ("EvAddressSpaceDispatch");
32467754Smsmith
32567754Smsmith
32687031Smsmith    RegionObj2 = AcpiNsGetSecondaryObject (RegionObj);
32787031Smsmith    if (!RegionObj2)
32887031Smsmith    {
32987031Smsmith        return_ACPI_STATUS (AE_NOT_EXIST);
33087031Smsmith    }
33187031Smsmith
33267754Smsmith    /*
33377424Smsmith     * Ensure that there is a handler associated with this region
33467754Smsmith     */
33567754Smsmith    HandlerDesc = RegionObj->Region.AddrHandler;
33667754Smsmith    if (!HandlerDesc)
33767754Smsmith    {
33882367Smsmith        ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "no handler for region(%p) [%s]\n",
33977424Smsmith            RegionObj, AcpiUtGetRegionName (RegionObj->Region.SpaceId)));
34077424Smsmith
34187031Smsmith        return_ACPI_STATUS (AE_NOT_EXIST);
34267754Smsmith    }
34367754Smsmith
34467754Smsmith    /*
34577424Smsmith     * It may be the case that the region has never been initialized
34677424Smsmith     * Some types of regions require special init code
34767754Smsmith     */
34887031Smsmith    if (!(RegionObj->Region.Flags & AOPOBJ_SETUP_COMPLETE))
34967754Smsmith    {
35067754Smsmith        /*
35177424Smsmith         * This region has not been initialized yet, do it
35267754Smsmith         */
35367754Smsmith        RegionSetup = HandlerDesc->AddrHandler.Setup;
35467754Smsmith        if (!RegionSetup)
35567754Smsmith        {
35667754Smsmith            /*
35767754Smsmith             *  Bad news, no init routine and not init'd
35867754Smsmith             */
35982367Smsmith            ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "No init routine for region(%p) [%s]\n",
36077424Smsmith                RegionObj, AcpiUtGetRegionName (RegionObj->Region.SpaceId)));
36167754Smsmith            return_ACPI_STATUS (AE_UNKNOWN_STATUS);
36267754Smsmith        }
36367754Smsmith
36467754Smsmith        /*
36567754Smsmith         * We must exit the interpreter because the region setup will potentially
36667754Smsmith         * execute control methods
36767754Smsmith         */
36877424Smsmith        AcpiExExitInterpreter ();
36967754Smsmith
37067754Smsmith        Status = RegionSetup (RegionObj, ACPI_REGION_ACTIVATE,
37177424Smsmith                        HandlerDesc->AddrHandler.Context, &RegionContext);
37267754Smsmith
37367754Smsmith        /* Re-enter the interpreter */
37467754Smsmith
37577424Smsmith        AcpiExEnterInterpreter ();
37667754Smsmith
37767754Smsmith        /*
37867754Smsmith         *  Init routine may fail
37967754Smsmith         */
38067754Smsmith        if (ACPI_FAILURE (Status))
38167754Smsmith        {
38282367Smsmith            ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Region Init: %s [%s]\n",
38380062Smsmith                AcpiFormatException (Status),
38477424Smsmith                AcpiUtGetRegionName (RegionObj->Region.SpaceId)));
38587031Smsmith            return_ACPI_STATUS (Status);
38667754Smsmith        }
38767754Smsmith
38887031Smsmith        RegionObj->Region.Flags |= AOPOBJ_SETUP_COMPLETE;
38967754Smsmith
39067754Smsmith        /*
39167754Smsmith         *  Save the returned context for use in all accesses to
39267754Smsmith         *  this particular region.
39367754Smsmith         */
39487031Smsmith        RegionObj2->Extra.RegionContext = RegionContext;
39567754Smsmith    }
39667754Smsmith
39767754Smsmith    /*
39867754Smsmith     *  We have everything we need, begin the process
39967754Smsmith     */
40067754Smsmith    Handler = HandlerDesc->AddrHandler.Handler;
40167754Smsmith
40282367Smsmith    ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION,
40385756Smsmith        "Addrhandler %p (%p), Address %8.8X%8.8X\n",
40491116Smsmith        &RegionObj->Region.AddrHandler->AddrHandler, Handler,
40591116Smsmith        ACPI_HIDWORD (Address), ACPI_LODWORD (Address)));
40667754Smsmith
40791116Smsmith    if (!(HandlerDesc->AddrHandler.Flags & ACPI_ADDR_HANDLER_DEFAULT_INSTALLED))
40867754Smsmith    {
40967754Smsmith        /*
41067754Smsmith         *  For handlers other than the default (supplied) handlers, we must
41167754Smsmith         *  exit the interpreter because the handler *might* block -- we don't
41267754Smsmith         *  know what it will do, so we can't hold the lock on the intepreter.
41367754Smsmith         */
41477424Smsmith        AcpiExExitInterpreter();
41567754Smsmith    }
41667754Smsmith
41767754Smsmith    /*
41867754Smsmith     *  Invoke the handler.
41967754Smsmith     */
42067754Smsmith    Status = Handler (Function, Address, BitWidth, Value,
42167754Smsmith                      HandlerDesc->AddrHandler.Context,
42287031Smsmith                      RegionObj2->Extra.RegionContext);
42367754Smsmith
42467754Smsmith    if (ACPI_FAILURE (Status))
42567754Smsmith    {
42691116Smsmith        ACPI_REPORT_ERROR (("Handler for [%s] returned %s\n",
42791116Smsmith            AcpiUtGetRegionName (RegionObj->Region.SpaceId),
42891116Smsmith            AcpiFormatException (Status)));
42967754Smsmith    }
43067754Smsmith
43191116Smsmith    if (!(HandlerDesc->AddrHandler.Flags & ACPI_ADDR_HANDLER_DEFAULT_INSTALLED))
43267754Smsmith    {
43383174Smsmith        /*
43483174Smsmith         * We just returned from a non-default handler, we must re-enter the
43583174Smsmith         * interpreter
43683174Smsmith         */
43777424Smsmith        AcpiExEnterInterpreter ();
43867754Smsmith    }
43967754Smsmith
44067754Smsmith    return_ACPI_STATUS (Status);
44167754Smsmith}
44267754Smsmith
44377424Smsmith/*******************************************************************************
44467754Smsmith *
44567754Smsmith * FUNCTION:    AcpiEvDisassociateRegionFromHandler
44667754Smsmith *
44770243Smsmith * PARAMETERS:  RegionObj       - Region Object
44870243Smsmith *              AcpiNsIsLocked  - Namespace Region Already Locked?
44967754Smsmith *
45067754Smsmith * RETURN:      None
45167754Smsmith *
45267754Smsmith * DESCRIPTION: Break the association between the handler and the region
45367754Smsmith *              this is a two way association.
45467754Smsmith *
45567754Smsmith ******************************************************************************/
45667754Smsmith
45767754Smsmithvoid
45867754SmsmithAcpiEvDisassociateRegionFromHandler(
45970243Smsmith    ACPI_OPERAND_OBJECT     *RegionObj,
46070243Smsmith    BOOLEAN                 AcpiNsIsLocked)
46167754Smsmith{
46267754Smsmith    ACPI_OPERAND_OBJECT     *HandlerObj;
46367754Smsmith    ACPI_OPERAND_OBJECT     *ObjDesc;
46467754Smsmith    ACPI_OPERAND_OBJECT     **LastObjPtr;
46577424Smsmith    ACPI_ADR_SPACE_SETUP    RegionSetup;
46667754Smsmith    void                    *RegionContext;
46787031Smsmith    ACPI_OPERAND_OBJECT     *RegionObj2;
46867754Smsmith    ACPI_STATUS             Status;
46967754Smsmith
47067754Smsmith
47191116Smsmith    ACPI_FUNCTION_TRACE ("EvDisassociateRegionFromHandler");
47267754Smsmith
47383174Smsmith
47487031Smsmith    RegionObj2 = AcpiNsGetSecondaryObject (RegionObj);
47587031Smsmith    if (!RegionObj2)
47687031Smsmith    {
47787031Smsmith        return;
47887031Smsmith    }
47987031Smsmith    RegionContext = RegionObj2->Extra.RegionContext;
48067754Smsmith
48167754Smsmith    /*
48267754Smsmith     *  Get the address handler from the region object
48367754Smsmith     */
48467754Smsmith    HandlerObj = RegionObj->Region.AddrHandler;
48567754Smsmith    if (!HandlerObj)
48667754Smsmith    {
48767754Smsmith        /*
48867754Smsmith         *  This region has no handler, all done
48967754Smsmith         */
49067754Smsmith        return_VOID;
49167754Smsmith    }
49267754Smsmith
49367754Smsmith
49467754Smsmith    /*
49567754Smsmith     *  Find this region in the handler's list
49667754Smsmith     */
49767754Smsmith    ObjDesc = HandlerObj->AddrHandler.RegionList;
49867754Smsmith    LastObjPtr = &HandlerObj->AddrHandler.RegionList;
49967754Smsmith
50067754Smsmith    while (ObjDesc)
50167754Smsmith    {
50267754Smsmith        /*
50367754Smsmith         *  See if this is the one
50467754Smsmith         */
50567754Smsmith        if (ObjDesc == RegionObj)
50667754Smsmith        {
50782367Smsmith            ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION,
50882367Smsmith                "Removing Region %p from address handler %p\n",
50967754Smsmith                RegionObj, HandlerObj));
51067754Smsmith            /*
51167754Smsmith             *  This is it, remove it from the handler's list
51267754Smsmith             */
51367754Smsmith            *LastObjPtr = ObjDesc->Region.Next;
51467754Smsmith            ObjDesc->Region.Next = NULL;            /* Must clear field */
51567754Smsmith
51670243Smsmith            if (AcpiNsIsLocked)
51770243Smsmith            {
51891116Smsmith                Status = AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
51991116Smsmith                if (ACPI_FAILURE (Status))
52091116Smsmith                {
52191116Smsmith                    return_VOID;
52291116Smsmith                }
52370243Smsmith            }
52470243Smsmith
52567754Smsmith            /*
52667754Smsmith             *  Now stop region accesses by executing the _REG method
52767754Smsmith             */
52867754Smsmith            AcpiEvExecuteRegMethod (RegionObj, 0);
52967754Smsmith
53070243Smsmith            if (AcpiNsIsLocked)
53170243Smsmith            {
53291116Smsmith                Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
53391116Smsmith                if (ACPI_FAILURE (Status))
53491116Smsmith                {
53591116Smsmith                    return_VOID;
53691116Smsmith                }
53770243Smsmith            }
53870243Smsmith
53967754Smsmith            /*
54067754Smsmith             *  Call the setup handler with the deactivate notification
54167754Smsmith             */
54267754Smsmith            RegionSetup = HandlerObj->AddrHandler.Setup;
54367754Smsmith            Status = RegionSetup (RegionObj, ACPI_REGION_DEACTIVATE,
54477424Smsmith                            HandlerObj->AddrHandler.Context, &RegionContext);
54567754Smsmith
54667754Smsmith            /*
54767754Smsmith             *  Init routine may fail, Just ignore errors
54867754Smsmith             */
54967754Smsmith            if (ACPI_FAILURE (Status))
55067754Smsmith            {
55182367Smsmith                ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "%s from region init, [%s]\n",
55280062Smsmith                    AcpiFormatException (Status),
55377424Smsmith                    AcpiUtGetRegionName (RegionObj->Region.SpaceId)));
55467754Smsmith            }
55567754Smsmith
55687031Smsmith            RegionObj->Region.Flags &= ~(AOPOBJ_SETUP_COMPLETE);
55767754Smsmith
55867754Smsmith            /*
55967754Smsmith             *  Remove handler reference in the region
56067754Smsmith             *
56167754Smsmith             *  NOTE: this doesn't mean that the region goes away
56267754Smsmith             *  The region is just inaccessible as indicated to
56367754Smsmith             *  the _REG method
56467754Smsmith             *
56567754Smsmith             *  If the region is on the handler's list
56667754Smsmith             *  this better be the region's handler
56767754Smsmith             */
56867754Smsmith            RegionObj->Region.AddrHandler = NULL;
56967754Smsmith
57067754Smsmith            return_VOID;
57167754Smsmith
57267754Smsmith        } /* found the right handler */
57367754Smsmith
57467754Smsmith        /*
57567754Smsmith         *  Move through the linked list of handlers
57667754Smsmith         */
57767754Smsmith        LastObjPtr = &ObjDesc->Region.Next;
57867754Smsmith        ObjDesc = ObjDesc->Region.Next;
57967754Smsmith    }
58067754Smsmith
58167754Smsmith    /*
58267754Smsmith     *  If we get here, the region was not in the handler's region list
58367754Smsmith     */
58482367Smsmith    ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION,
58582367Smsmith        "Cannot remove region %p from address handler %p\n",
58667754Smsmith        RegionObj, HandlerObj));
58767754Smsmith
58867754Smsmith    return_VOID;
58967754Smsmith}
59067754Smsmith
59167754Smsmith
59277424Smsmith/*******************************************************************************
59367754Smsmith *
59467754Smsmith * FUNCTION:    AcpiEvAssociateRegionAndHandler
59567754Smsmith *
59667754Smsmith * PARAMETERS:  HandlerObj      - Handler Object
59767754Smsmith *              RegionObj       - Region Object
59870243Smsmith *              AcpiNsIsLocked  - Namespace Region Already Locked?
59967754Smsmith *
60067754Smsmith * RETURN:      None
60167754Smsmith *
60267754Smsmith * DESCRIPTION: Create the association between the handler and the region
60367754Smsmith *              this is a two way association.
60467754Smsmith *
60567754Smsmith ******************************************************************************/
60667754Smsmith
60767754SmsmithACPI_STATUS
60867754SmsmithAcpiEvAssociateRegionAndHandler (
60967754Smsmith    ACPI_OPERAND_OBJECT     *HandlerObj,
61067754Smsmith    ACPI_OPERAND_OBJECT     *RegionObj,
61167754Smsmith    BOOLEAN                 AcpiNsIsLocked)
61267754Smsmith{
61367754Smsmith    ACPI_STATUS     Status;
61467754Smsmith
61567754Smsmith
61691116Smsmith    ACPI_FUNCTION_TRACE ("EvAssociateRegionAndHandler");
61767754Smsmith
61867754Smsmith
61983174Smsmith    ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION,
62082367Smsmith        "Adding Region %p to address handler %p [%s]\n",
62177424Smsmith        RegionObj, HandlerObj, AcpiUtGetRegionName (RegionObj->Region.SpaceId)));
62267754Smsmith
62367754Smsmith
62467754Smsmith    /*
62587031Smsmith     * Link this region to the front of the handler's list
62667754Smsmith     */
62767754Smsmith    RegionObj->Region.Next = HandlerObj->AddrHandler.RegionList;
62867754Smsmith    HandlerObj->AddrHandler.RegionList = RegionObj;
62967754Smsmith
63067754Smsmith    /*
63187031Smsmith     * Set the region's handler
63267754Smsmith     */
63367754Smsmith    RegionObj->Region.AddrHandler = HandlerObj;
63467754Smsmith
63567754Smsmith    /*
63687031Smsmith     * Tell all users that this region is usable by running the _REG
63787031Smsmith     * method
63867754Smsmith     */
63967754Smsmith    if (AcpiNsIsLocked)
64067754Smsmith    {
64177424Smsmith        AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
64267754Smsmith    }
64367754Smsmith
64467754Smsmith    Status = AcpiEvExecuteRegMethod (RegionObj, 1);
64567754Smsmith
64667754Smsmith    if (AcpiNsIsLocked)
64767754Smsmith    {
64891116Smsmith        (void) AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
64967754Smsmith    }
65067754Smsmith
65167754Smsmith    return_ACPI_STATUS (Status);
65267754Smsmith}
65367754Smsmith
65467754Smsmith
65577424Smsmith/*******************************************************************************
65667754Smsmith *
65767754Smsmith * FUNCTION:    AcpiEvAddrHandlerHelper
65867754Smsmith *
65967754Smsmith * PARAMETERS:  Handle              - Node to be dumped
66067754Smsmith *              Level               - Nesting level of the handle
66167754Smsmith *              Context             - Passed into AcpiNsWalkNamespace
66267754Smsmith *
66387031Smsmith * DESCRIPTION: This routine installs an address handler into objects that are
66487031Smsmith *              of type Region.
66567754Smsmith *
66667754Smsmith *              If the Object is a Device, and the device has a handler of
66767754Smsmith *              the same type then the search is terminated in that branch.
66867754Smsmith *
66967754Smsmith *              This is because the existing handler is closer in proximity
67067754Smsmith *              to any more regions than the one we are trying to install.
67167754Smsmith *
67277424Smsmith ******************************************************************************/
67367754Smsmith
67467754SmsmithACPI_STATUS
67567754SmsmithAcpiEvAddrHandlerHelper (
67667754Smsmith    ACPI_HANDLE             ObjHandle,
67767754Smsmith    UINT32                  Level,
67867754Smsmith    void                    *Context,
67967754Smsmith    void                    **ReturnValue)
68067754Smsmith{
68167754Smsmith    ACPI_OPERAND_OBJECT     *HandlerObj;
68267754Smsmith    ACPI_OPERAND_OBJECT     *TmpObj;
68367754Smsmith    ACPI_OPERAND_OBJECT     *ObjDesc;
68467754Smsmith    ACPI_NAMESPACE_NODE     *Node;
68567754Smsmith    ACPI_STATUS             Status;
68667754Smsmith
68767754Smsmith
68891116Smsmith    ACPI_FUNCTION_NAME ("EvAddrHandlerHelper");
68977424Smsmith
69077424Smsmith
69167754Smsmith    HandlerObj = (ACPI_OPERAND_OBJECT  *) Context;
69267754Smsmith
69367754Smsmith    /* Parameter validation */
69467754Smsmith
69567754Smsmith    if (!HandlerObj)
69667754Smsmith    {
69767754Smsmith        return (AE_OK);
69867754Smsmith    }
69967754Smsmith
70067754Smsmith    /* Convert and validate the device handle */
70167754Smsmith
70285756Smsmith    Node = AcpiNsMapHandleToNode (ObjHandle);
70367754Smsmith    if (!Node)
70467754Smsmith    {
70567754Smsmith        return (AE_BAD_PARAMETER);
70667754Smsmith    }
70767754Smsmith
70867754Smsmith    /*
70967754Smsmith     *  We only care about regions.and objects
71067754Smsmith     *  that can have address handlers
71167754Smsmith     */
71267754Smsmith    if ((Node->Type != ACPI_TYPE_DEVICE) &&
71367754Smsmith        (Node->Type != ACPI_TYPE_REGION) &&
71467754Smsmith        (Node != AcpiGbl_RootNode))
71567754Smsmith    {
71667754Smsmith        return (AE_OK);
71767754Smsmith    }
71867754Smsmith
71967754Smsmith    /* Check for an existing internal object */
72067754Smsmith
72177424Smsmith    ObjDesc = AcpiNsGetAttachedObject (Node);
72267754Smsmith    if (!ObjDesc)
72367754Smsmith    {
72467754Smsmith        /*
72567754Smsmith         *  The object DNE, we don't care about it
72667754Smsmith         */
72767754Smsmith        return (AE_OK);
72867754Smsmith    }
72967754Smsmith
73067754Smsmith    /*
73167754Smsmith     *  Devices are handled different than regions
73267754Smsmith     */
73391116Smsmith    if (ObjDesc->Common.Type == ACPI_TYPE_DEVICE)
73467754Smsmith    {
73567754Smsmith        /*
73667754Smsmith         *  See if this guy has any handlers
73767754Smsmith         */
73867754Smsmith        TmpObj = ObjDesc->Device.AddrHandler;
73967754Smsmith        while (TmpObj)
74067754Smsmith        {
74167754Smsmith            /*
74267754Smsmith             *  Now let's see if it's for the same address space.
74367754Smsmith             */
74467754Smsmith            if (TmpObj->AddrHandler.SpaceId == HandlerObj->AddrHandler.SpaceId)
74567754Smsmith            {
74667754Smsmith                /*
74767754Smsmith                 *  It's for the same address space
74867754Smsmith                 */
74982367Smsmith                ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION,
75082367Smsmith                    "Found handler for region [%s] in device %p(%p) handler %p\n",
75177424Smsmith                    AcpiUtGetRegionName (HandlerObj->AddrHandler.SpaceId),
75277424Smsmith                    ObjDesc, TmpObj, HandlerObj));
75367754Smsmith
75467754Smsmith                /*
75567754Smsmith                 *  Since the object we found it on was a device, then it
75667754Smsmith                 *  means that someone has already installed a handler for
75767754Smsmith                 *  the branch of the namespace from this device on.  Just
75867754Smsmith                 *  bail out telling the walk routine to not traverse this
75967754Smsmith                 *  branch.  This preserves the scoping rule for handlers.
76067754Smsmith                 */
76167754Smsmith                return (AE_CTRL_DEPTH);
76267754Smsmith            }
76367754Smsmith
76467754Smsmith            /*
76567754Smsmith             *  Move through the linked list of handlers
76667754Smsmith             */
76767754Smsmith            TmpObj = TmpObj->AddrHandler.Next;
76867754Smsmith        }
76967754Smsmith
77067754Smsmith        /*
77167754Smsmith         *  As long as the device didn't have a handler for this
77267754Smsmith         *  space we don't care about it.  We just ignore it and
77367754Smsmith         *  proceed.
77467754Smsmith         */
77567754Smsmith        return (AE_OK);
77667754Smsmith    }
77767754Smsmith
77867754Smsmith    /*
77967754Smsmith     *  Only here if it was a region
78067754Smsmith     */
78167754Smsmith    if (ObjDesc->Region.SpaceId != HandlerObj->AddrHandler.SpaceId)
78267754Smsmith    {
78367754Smsmith        /*
78467754Smsmith         *  This region is for a different address space
78567754Smsmith         *  ignore it
78667754Smsmith         */
78767754Smsmith        return (AE_OK);
78867754Smsmith    }
78967754Smsmith
79067754Smsmith    /*
79167754Smsmith     *  Now we have a region and it is for the handler's address
79267754Smsmith     *  space type.
79367754Smsmith     *
79467754Smsmith     *  First disconnect region for any previous handler (if any)
79567754Smsmith     */
79670243Smsmith    AcpiEvDisassociateRegionFromHandler (ObjDesc, FALSE);
79767754Smsmith
79867754Smsmith    /*
79967754Smsmith     *  Then connect the region to the new handler
80067754Smsmith     */
80167754Smsmith    Status = AcpiEvAssociateRegionAndHandler (HandlerObj, ObjDesc, FALSE);
80267754Smsmith
80367754Smsmith    return (Status);
80467754Smsmith}
80567754Smsmith
80667754Smsmith
807