evregion.c revision 249663
167754Smsmith/******************************************************************************
267754Smsmith *
3245582Sjkim * Module Name: evregion - Operation Region support
467754Smsmith *
567754Smsmith *****************************************************************************/
667754Smsmith
7217365Sjkim/*
8245582Sjkim * Copyright (C) 2000 - 2013, Intel Corp.
970243Smsmith * All rights reserved.
1067754Smsmith *
11217365Sjkim * Redistribution and use in source and binary forms, with or without
12217365Sjkim * modification, are permitted provided that the following conditions
13217365Sjkim * are met:
14217365Sjkim * 1. Redistributions of source code must retain the above copyright
15217365Sjkim *    notice, this list of conditions, and the following disclaimer,
16217365Sjkim *    without modification.
17217365Sjkim * 2. Redistributions in binary form must reproduce at minimum a disclaimer
18217365Sjkim *    substantially similar to the "NO WARRANTY" disclaimer below
19217365Sjkim *    ("Disclaimer") and any redistribution must be conditioned upon
20217365Sjkim *    including a substantially similar Disclaimer requirement for further
21217365Sjkim *    binary redistribution.
22217365Sjkim * 3. Neither the names of the above-listed copyright holders nor the names
23217365Sjkim *    of any contributors may be used to endorse or promote products derived
24217365Sjkim *    from this software without specific prior written permission.
2567754Smsmith *
26217365Sjkim * Alternatively, this software may be distributed under the terms of the
27217365Sjkim * GNU General Public License ("GPL") version 2 as published by the Free
28217365Sjkim * Software Foundation.
2967754Smsmith *
30217365Sjkim * NO WARRANTY
31217365Sjkim * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32217365Sjkim * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
33217365Sjkim * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
34217365Sjkim * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
35217365Sjkim * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36217365Sjkim * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37217365Sjkim * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38217365Sjkim * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39217365Sjkim * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
40217365Sjkim * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41217365Sjkim * POSSIBILITY OF SUCH DAMAGES.
42217365Sjkim */
4367754Smsmith
4467754Smsmith
4567754Smsmith#define __EVREGION_C__
4667754Smsmith
47193341Sjkim#include <contrib/dev/acpica/include/acpi.h>
48193341Sjkim#include <contrib/dev/acpica/include/accommon.h>
49193341Sjkim#include <contrib/dev/acpica/include/acevents.h>
50193341Sjkim#include <contrib/dev/acpica/include/acnamesp.h>
51193341Sjkim#include <contrib/dev/acpica/include/acinterp.h>
5267754Smsmith
5377424Smsmith#define _COMPONENT          ACPI_EVENTS
5491116Smsmith        ACPI_MODULE_NAME    ("evregion")
5567754Smsmith
5667754Smsmith
57245582Sjkimextern UINT8        AcpiGbl_DefaultAddressSpaces[];
58245582Sjkim
59151937Sjkim/* Local prototypes */
60117521Snjl
61220663Sjkimstatic void
62220663SjkimAcpiEvOrphanEcRegMethod (
63249663Sjkim    ACPI_NAMESPACE_NODE     *EcDeviceNode);
64220663Sjkim
65151937Sjkimstatic ACPI_STATUS
66151937SjkimAcpiEvRegRun (
67151937Sjkim    ACPI_HANDLE             ObjHandle,
68151937Sjkim    UINT32                  Level,
69151937Sjkim    void                    *Context,
70151937Sjkim    void                    **ReturnValue);
71151937Sjkim
72151937Sjkim
7377424Smsmith/*******************************************************************************
7467754Smsmith *
75129684Snjl * FUNCTION:    AcpiEvInitializeOpRegions
76129684Snjl *
77129684Snjl * PARAMETERS:  None
78129684Snjl *
79129684Snjl * RETURN:      Status
80129684Snjl *
81129684Snjl * DESCRIPTION: Execute _REG methods for all Operation Regions that have
82129684Snjl *              an installed default region handler.
83129684Snjl *
84129684Snjl ******************************************************************************/
85129684Snjl
86129684SnjlACPI_STATUS
87129684SnjlAcpiEvInitializeOpRegions (
88129684Snjl    void)
89129684Snjl{
90129684Snjl    ACPI_STATUS             Status;
91193267Sjkim    UINT32                  i;
92129684Snjl
93129684Snjl
94167802Sjkim    ACPI_FUNCTION_TRACE (EvInitializeOpRegions);
95129684Snjl
96129684Snjl
97129684Snjl    Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
98129684Snjl    if (ACPI_FAILURE (Status))
99129684Snjl    {
100129684Snjl        return_ACPI_STATUS (Status);
101129684Snjl    }
102129684Snjl
103193267Sjkim    /* Run the _REG methods for OpRegions in each default address space */
104193267Sjkim
105129684Snjl    for (i = 0; i < ACPI_NUM_DEFAULT_SPACES; i++)
106129684Snjl    {
107193267Sjkim        /*
108198237Sjkim         * Make sure the installed handler is the DEFAULT handler. If not the
109198237Sjkim         * default, the _REG methods will have already been run (when the
110198237Sjkim         * handler was installed)
111129684Snjl         */
112198237Sjkim        if (AcpiEvHasDefaultHandler (AcpiGbl_RootNode,
113198237Sjkim               AcpiGbl_DefaultAddressSpaces[i]))
114198237Sjkim        {
115198237Sjkim            Status = AcpiEvExecuteRegMethods (AcpiGbl_RootNode,
116198237Sjkim                        AcpiGbl_DefaultAddressSpaces[i]);
117198237Sjkim        }
118129684Snjl    }
119129684Snjl
120218590Sjkim    AcpiGbl_RegMethodsExecuted = TRUE;
121218590Sjkim
122129684Snjl    (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
123129684Snjl    return_ACPI_STATUS (Status);
124129684Snjl}
125129684Snjl
126129684Snjl
127129684Snjl/*******************************************************************************
128129684Snjl *
12967754Smsmith * FUNCTION:    AcpiEvAddressSpaceDispatch
13067754Smsmith *
131123315Snjl * PARAMETERS:  RegionObj           - Internal region object
132228110Sjkim *              FieldObj            - Corresponding field. Can be NULL.
13367754Smsmith *              Function            - Read or Write operation
134193267Sjkim *              RegionOffset        - Where in the region to read or write
13587031Smsmith *              BitWidth            - Field width in bits (8, 16, 32, or 64)
136167802Sjkim *              Value               - Pointer to in or out value, must be
137202771Sjkim *                                    a full 64-bit integer
13867754Smsmith *
13967754Smsmith * RETURN:      Status
14067754Smsmith *
14167754Smsmith * DESCRIPTION: Dispatch an address space or operation region access to
14267754Smsmith *              a previously installed handler.
14367754Smsmith *
14477424Smsmith ******************************************************************************/
14567754Smsmith
14667754SmsmithACPI_STATUS
14767754SmsmithAcpiEvAddressSpaceDispatch (
14867754Smsmith    ACPI_OPERAND_OBJECT     *RegionObj,
149228110Sjkim    ACPI_OPERAND_OBJECT     *FieldObj,
15067754Smsmith    UINT32                  Function,
151193267Sjkim    UINT32                  RegionOffset,
15267754Smsmith    UINT32                  BitWidth,
153202771Sjkim    UINT64                  *Value)
15467754Smsmith{
15567754Smsmith    ACPI_STATUS             Status;
15677424Smsmith    ACPI_ADR_SPACE_HANDLER  Handler;
15777424Smsmith    ACPI_ADR_SPACE_SETUP    RegionSetup;
15867754Smsmith    ACPI_OPERAND_OBJECT     *HandlerDesc;
15987031Smsmith    ACPI_OPERAND_OBJECT     *RegionObj2;
16067754Smsmith    void                    *RegionContext = NULL;
161228110Sjkim    ACPI_CONNECTION_INFO    *Context;
16267754Smsmith
16367754Smsmith
164167802Sjkim    ACPI_FUNCTION_TRACE (EvAddressSpaceDispatch);
16567754Smsmith
16667754Smsmith
16787031Smsmith    RegionObj2 = AcpiNsGetSecondaryObject (RegionObj);
16887031Smsmith    if (!RegionObj2)
16987031Smsmith    {
17087031Smsmith        return_ACPI_STATUS (AE_NOT_EXIST);
17187031Smsmith    }
17287031Smsmith
173117521Snjl    /* Ensure that there is a handler associated with this region */
174117521Snjl
175123315Snjl    HandlerDesc = RegionObj->Region.Handler;
17667754Smsmith    if (!HandlerDesc)
17767754Smsmith    {
178167802Sjkim        ACPI_ERROR ((AE_INFO,
179167802Sjkim            "No handler for Region [%4.4s] (%p) [%s]",
180123315Snjl            AcpiUtGetNodeName (RegionObj->Region.Node),
18177424Smsmith            RegionObj, AcpiUtGetRegionName (RegionObj->Region.SpaceId)));
18277424Smsmith
18387031Smsmith        return_ACPI_STATUS (AE_NOT_EXIST);
18467754Smsmith    }
18567754Smsmith
186228110Sjkim    Context = HandlerDesc->AddressSpace.Context;
187228110Sjkim
18867754Smsmith    /*
189193267Sjkim     * It may be the case that the region has never been initialized.
19077424Smsmith     * Some types of regions require special init code
19167754Smsmith     */
19287031Smsmith    if (!(RegionObj->Region.Flags & AOPOBJ_SETUP_COMPLETE))
19367754Smsmith    {
194193267Sjkim        /* This region has not been initialized yet, do it */
195193267Sjkim
196117521Snjl        RegionSetup = HandlerDesc->AddressSpace.Setup;
19767754Smsmith        if (!RegionSetup)
19867754Smsmith        {
199117521Snjl            /* No initialization routine, exit with error */
200117521Snjl
201167802Sjkim            ACPI_ERROR ((AE_INFO,
202167802Sjkim                "No init routine for region(%p) [%s]",
20377424Smsmith                RegionObj, AcpiUtGetRegionName (RegionObj->Region.SpaceId)));
204117521Snjl            return_ACPI_STATUS (AE_NOT_EXIST);
20567754Smsmith        }
20667754Smsmith
20767754Smsmith        /*
208193267Sjkim         * We must exit the interpreter because the region setup will
209193267Sjkim         * potentially execute control methods (for example, the _REG method
210193267Sjkim         * for this region)
21167754Smsmith         */
212193267Sjkim        AcpiExExitInterpreter ();
21367754Smsmith
21467754Smsmith        Status = RegionSetup (RegionObj, ACPI_REGION_ACTIVATE,
215228110Sjkim                    Context, &RegionContext);
21667754Smsmith
21767754Smsmith        /* Re-enter the interpreter */
21867754Smsmith
219193267Sjkim        AcpiExEnterInterpreter ();
22067754Smsmith
221117521Snjl        /* Check for failure of the Region Setup */
222117521Snjl
22367754Smsmith        if (ACPI_FAILURE (Status))
22467754Smsmith        {
225167802Sjkim            ACPI_EXCEPTION ((AE_INFO, Status,
226167802Sjkim                "During region initialization: [%s]",
22777424Smsmith                AcpiUtGetRegionName (RegionObj->Region.SpaceId)));
22887031Smsmith            return_ACPI_STATUS (Status);
22967754Smsmith        }
23067754Smsmith
231193267Sjkim        /* Region initialization may have been completed by RegionSetup */
232193267Sjkim
233117521Snjl        if (!(RegionObj->Region.Flags & AOPOBJ_SETUP_COMPLETE))
234117521Snjl        {
235117521Snjl            RegionObj->Region.Flags |= AOPOBJ_SETUP_COMPLETE;
236117521Snjl
237117521Snjl            if (RegionObj2->Extra.RegionContext)
238117521Snjl            {
239117521Snjl                /* The handler for this region was already installed */
240117521Snjl
241167802Sjkim                ACPI_FREE (RegionContext);
242117521Snjl            }
243117521Snjl            else
244117521Snjl            {
245117521Snjl                /*
246117521Snjl                 * Save the returned context for use in all accesses to
247117521Snjl                 * this particular region
248117521Snjl                 */
249117521Snjl                RegionObj2->Extra.RegionContext = RegionContext;
250117521Snjl            }
251117521Snjl        }
25267754Smsmith    }
25367754Smsmith
254117521Snjl    /* We have everything we need, we can invoke the address space handler */
25567754Smsmith
256117521Snjl    Handler = HandlerDesc->AddressSpace.Handler;
257117521Snjl
25882367Smsmith    ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION,
259117521Snjl        "Handler %p (@%p) Address %8.8X%8.8X [%s]\n",
260123315Snjl        &RegionObj->Region.Handler->AddressSpace, Handler,
261193267Sjkim        ACPI_FORMAT_NATIVE_UINT (RegionObj->Region.Address + RegionOffset),
262117521Snjl        AcpiUtGetRegionName (RegionObj->Region.SpaceId)));
26367754Smsmith
264228110Sjkim
265228110Sjkim    /*
266228110Sjkim     * Special handling for GenericSerialBus and GeneralPurposeIo:
267228110Sjkim     * There are three extra parameters that must be passed to the
268228110Sjkim     * handler via the context:
269228110Sjkim     *   1) Connection buffer, a resource template from Connection() op.
270228110Sjkim     *   2) Length of the above buffer.
271228110Sjkim     *   3) Actual access length from the AccessAs() op.
272228110Sjkim     */
273228110Sjkim    if (((RegionObj->Region.SpaceId == ACPI_ADR_SPACE_GSBUS) ||
274228110Sjkim            (RegionObj->Region.SpaceId == ACPI_ADR_SPACE_GPIO)) &&
275228110Sjkim        Context &&
276228110Sjkim        FieldObj)
277228110Sjkim    {
278228110Sjkim        /* Get the Connection (ResourceTemplate) buffer */
279228110Sjkim
280228110Sjkim        Context->Connection = FieldObj->Field.ResourceBuffer;
281228110Sjkim        Context->Length = FieldObj->Field.ResourceLength;
282228110Sjkim        Context->AccessLength = FieldObj->Field.AccessLength;
283228110Sjkim    }
284228110Sjkim
285167802Sjkim    if (!(HandlerDesc->AddressSpace.HandlerFlags &
286167802Sjkim            ACPI_ADDR_HANDLER_DEFAULT_INSTALLED))
28767754Smsmith    {
28867754Smsmith        /*
289117521Snjl         * For handlers other than the default (supplied) handlers, we must
290117521Snjl         * exit the interpreter because the handler *might* block -- we don't
291117521Snjl         * know what it will do, so we can't hold the lock on the intepreter.
29267754Smsmith         */
293193267Sjkim        AcpiExExitInterpreter();
29467754Smsmith    }
29567754Smsmith
296117521Snjl    /* Call the handler */
297117521Snjl
298193267Sjkim    Status = Handler (Function,
299193267Sjkim        (RegionObj->Region.Address + RegionOffset), BitWidth, Value,
300228110Sjkim        Context, RegionObj2->Extra.RegionContext);
30167754Smsmith
30267754Smsmith    if (ACPI_FAILURE (Status))
30367754Smsmith    {
304167802Sjkim        ACPI_EXCEPTION ((AE_INFO, Status, "Returned by Handler for [%s]",
305167802Sjkim            AcpiUtGetRegionName (RegionObj->Region.SpaceId)));
30667754Smsmith    }
30767754Smsmith
308167802Sjkim    if (!(HandlerDesc->AddressSpace.HandlerFlags &
309167802Sjkim            ACPI_ADDR_HANDLER_DEFAULT_INSTALLED))
31067754Smsmith    {
31183174Smsmith        /*
31283174Smsmith         * We just returned from a non-default handler, we must re-enter the
31383174Smsmith         * interpreter
31483174Smsmith         */
315193267Sjkim       AcpiExEnterInterpreter ();
31667754Smsmith    }
31767754Smsmith
31867754Smsmith    return_ACPI_STATUS (Status);
31967754Smsmith}
32067754Smsmith
321123315Snjl
32277424Smsmith/*******************************************************************************
32367754Smsmith *
32499679Siwasaki * FUNCTION:    AcpiEvDetachRegion
32567754Smsmith *
326138287Smarks * PARAMETERS:  RegionObj           - Region Object
327138287Smarks *              AcpiNsIsLocked      - Namespace Region Already Locked?
32867754Smsmith *
32967754Smsmith * RETURN:      None
33067754Smsmith *
33167754Smsmith * DESCRIPTION: Break the association between the handler and the region
33267754Smsmith *              this is a two way association.
33367754Smsmith *
33467754Smsmith ******************************************************************************/
33567754Smsmith
33667754Smsmithvoid
33799679SiwasakiAcpiEvDetachRegion(
33870243Smsmith    ACPI_OPERAND_OBJECT     *RegionObj,
33970243Smsmith    BOOLEAN                 AcpiNsIsLocked)
34067754Smsmith{
34167754Smsmith    ACPI_OPERAND_OBJECT     *HandlerObj;
34267754Smsmith    ACPI_OPERAND_OBJECT     *ObjDesc;
34367754Smsmith    ACPI_OPERAND_OBJECT     **LastObjPtr;
34477424Smsmith    ACPI_ADR_SPACE_SETUP    RegionSetup;
345123315Snjl    void                    **RegionContext;
34687031Smsmith    ACPI_OPERAND_OBJECT     *RegionObj2;
34767754Smsmith    ACPI_STATUS             Status;
34867754Smsmith
34967754Smsmith
350167802Sjkim    ACPI_FUNCTION_TRACE (EvDetachRegion);
35167754Smsmith
35283174Smsmith
35387031Smsmith    RegionObj2 = AcpiNsGetSecondaryObject (RegionObj);
35487031Smsmith    if (!RegionObj2)
35587031Smsmith    {
35699679Siwasaki        return_VOID;
35787031Smsmith    }
358123315Snjl    RegionContext = &RegionObj2->Extra.RegionContext;
35967754Smsmith
360117521Snjl    /* Get the address handler from the region object */
361117521Snjl
362123315Snjl    HandlerObj = RegionObj->Region.Handler;
36367754Smsmith    if (!HandlerObj)
36467754Smsmith    {
365117521Snjl        /* This region has no handler, all done */
366117521Snjl
36767754Smsmith        return_VOID;
36867754Smsmith    }
36967754Smsmith
370117521Snjl    /* Find this region in the handler's list */
37167754Smsmith
372117521Snjl    ObjDesc = HandlerObj->AddressSpace.RegionList;
373117521Snjl    LastObjPtr = &HandlerObj->AddressSpace.RegionList;
37467754Smsmith
37567754Smsmith    while (ObjDesc)
37667754Smsmith    {
377117521Snjl        /* Is this the correct Region? */
378117521Snjl
37967754Smsmith        if (ObjDesc == RegionObj)
38067754Smsmith        {
38182367Smsmith            ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION,
38282367Smsmith                "Removing Region %p from address handler %p\n",
38367754Smsmith                RegionObj, HandlerObj));
384117521Snjl
385117521Snjl            /* This is it, remove it from the handler's list */
386117521Snjl
38767754Smsmith            *LastObjPtr = ObjDesc->Region.Next;
388193267Sjkim            ObjDesc->Region.Next = NULL;        /* Must clear field */
38967754Smsmith
39070243Smsmith            if (AcpiNsIsLocked)
39170243Smsmith            {
39291116Smsmith                Status = AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
39391116Smsmith                if (ACPI_FAILURE (Status))
39491116Smsmith                {
39591116Smsmith                    return_VOID;
39691116Smsmith                }
39770243Smsmith            }
39870243Smsmith
399117521Snjl            /* Now stop region accesses by executing the _REG method */
400117521Snjl
401220663Sjkim            Status = AcpiEvExecuteRegMethod (RegionObj, ACPI_REG_DISCONNECT);
40299679Siwasaki            if (ACPI_FAILURE (Status))
40399679Siwasaki            {
404167802Sjkim                ACPI_EXCEPTION ((AE_INFO, Status, "from region _REG, [%s]",
40599679Siwasaki                    AcpiUtGetRegionName (RegionObj->Region.SpaceId)));
40699679Siwasaki            }
40767754Smsmith
40870243Smsmith            if (AcpiNsIsLocked)
40970243Smsmith            {
41091116Smsmith                Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
41191116Smsmith                if (ACPI_FAILURE (Status))
41291116Smsmith                {
41391116Smsmith                    return_VOID;
41491116Smsmith                }
41570243Smsmith            }
41670243Smsmith
417167802Sjkim            /*
418193267Sjkim             * If the region has been activated, call the setup handler with
419193267Sjkim             * the deactivate notification
420167802Sjkim             */
421167802Sjkim            if (RegionObj->Region.Flags & AOPOBJ_SETUP_COMPLETE)
422167802Sjkim            {
423167802Sjkim                RegionSetup = HandlerObj->AddressSpace.Setup;
424167802Sjkim                Status = RegionSetup (RegionObj, ACPI_REGION_DEACTIVATE,
425167802Sjkim                    HandlerObj->AddressSpace.Context, RegionContext);
426117521Snjl
427167802Sjkim                /* Init routine may fail, Just ignore errors */
42867754Smsmith
429167802Sjkim                if (ACPI_FAILURE (Status))
430167802Sjkim                {
431167802Sjkim                    ACPI_EXCEPTION ((AE_INFO, Status,
432167802Sjkim                        "from region handler - deactivate, [%s]",
433167802Sjkim                        AcpiUtGetRegionName (RegionObj->Region.SpaceId)));
434167802Sjkim                }
435117521Snjl
436167802Sjkim                RegionObj->Region.Flags &= ~(AOPOBJ_SETUP_COMPLETE);
43767754Smsmith            }
43867754Smsmith
43967754Smsmith            /*
440117521Snjl             * Remove handler reference in the region
44167754Smsmith             *
442167802Sjkim             * NOTE: this doesn't mean that the region goes away, the region
443167802Sjkim             * is just inaccessible as indicated to the _REG method
44467754Smsmith             *
445167802Sjkim             * If the region is on the handler's list, this must be the
446167802Sjkim             * region's handler
44767754Smsmith             */
448123315Snjl            RegionObj->Region.Handler = NULL;
449117521Snjl            AcpiUtRemoveReference (HandlerObj);
45067754Smsmith
45167754Smsmith            return_VOID;
452117521Snjl        }
45367754Smsmith
454117521Snjl        /* Walk the linked list of handlers */
45567754Smsmith
45667754Smsmith        LastObjPtr = &ObjDesc->Region.Next;
45767754Smsmith        ObjDesc = ObjDesc->Region.Next;
45867754Smsmith    }
45967754Smsmith
460117521Snjl    /* If we get here, the region was not in the handler's region list */
461117521Snjl
46282367Smsmith    ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION,
46382367Smsmith        "Cannot remove region %p from address handler %p\n",
46467754Smsmith        RegionObj, HandlerObj));
46567754Smsmith
46667754Smsmith    return_VOID;
46767754Smsmith}
46867754Smsmith
46967754Smsmith
47077424Smsmith/*******************************************************************************
47167754Smsmith *
47299679Siwasaki * FUNCTION:    AcpiEvAttachRegion
47367754Smsmith *
474138287Smarks * PARAMETERS:  HandlerObj          - Handler Object
475138287Smarks *              RegionObj           - Region Object
476138287Smarks *              AcpiNsIsLocked      - Namespace Region Already Locked?
47767754Smsmith *
47867754Smsmith * RETURN:      None
47967754Smsmith *
48067754Smsmith * DESCRIPTION: Create the association between the handler and the region
48167754Smsmith *              this is a two way association.
48267754Smsmith *
48367754Smsmith ******************************************************************************/
48467754Smsmith
48567754SmsmithACPI_STATUS
48699679SiwasakiAcpiEvAttachRegion (
48767754Smsmith    ACPI_OPERAND_OBJECT     *HandlerObj,
48867754Smsmith    ACPI_OPERAND_OBJECT     *RegionObj,
48967754Smsmith    BOOLEAN                 AcpiNsIsLocked)
49067754Smsmith{
49167754Smsmith
492167802Sjkim    ACPI_FUNCTION_TRACE (EvAttachRegion);
49367754Smsmith
49467754Smsmith
49583174Smsmith    ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION,
496123315Snjl        "Adding Region [%4.4s] %p to address handler %p [%s]\n",
497123315Snjl        AcpiUtGetNodeName (RegionObj->Region.Node),
498126372Snjl        RegionObj, HandlerObj,
499123315Snjl        AcpiUtGetRegionName (RegionObj->Region.SpaceId)));
50067754Smsmith
501117521Snjl    /* Link this region to the front of the handler's list */
50267754Smsmith
503117521Snjl    RegionObj->Region.Next = HandlerObj->AddressSpace.RegionList;
504117521Snjl    HandlerObj->AddressSpace.RegionList = RegionObj;
50567754Smsmith
506117521Snjl    /* Install the region's handler */
507117521Snjl
508123315Snjl    if (RegionObj->Region.Handler)
509117521Snjl    {
510117521Snjl        return_ACPI_STATUS (AE_ALREADY_EXISTS);
511117521Snjl    }
512117521Snjl
513123315Snjl    RegionObj->Region.Handler = HandlerObj;
514117521Snjl    AcpiUtAddReference (HandlerObj);
515117521Snjl
516123315Snjl    return_ACPI_STATUS (AE_OK);
51767754Smsmith}
51867754Smsmith
51967754Smsmith
52077424Smsmith/*******************************************************************************
52167754Smsmith *
522245582Sjkim * FUNCTION:    AcpiEvExecuteRegMethod
52367754Smsmith *
524245582Sjkim * PARAMETERS:  RegionObj           - Region object
525245582Sjkim *              Function            - Passed to _REG: On (1) or Off (0)
52667754Smsmith *
527245582Sjkim * RETURN:      Status
52867754Smsmith *
529245582Sjkim * DESCRIPTION: Execute _REG method for a region
53067754Smsmith *
53177424Smsmith ******************************************************************************/
53267754Smsmith
533245582SjkimACPI_STATUS
534245582SjkimAcpiEvExecuteRegMethod (
535245582Sjkim    ACPI_OPERAND_OBJECT     *RegionObj,
536245582Sjkim    UINT32                  Function)
53767754Smsmith{
538245582Sjkim    ACPI_EVALUATE_INFO      *Info;
539245582Sjkim    ACPI_OPERAND_OBJECT     *Args[3];
540245582Sjkim    ACPI_OPERAND_OBJECT     *RegionObj2;
54167754Smsmith    ACPI_STATUS             Status;
54267754Smsmith
54367754Smsmith
544245582Sjkim    ACPI_FUNCTION_TRACE (EvExecuteRegMethod);
54577424Smsmith
54677424Smsmith
547245582Sjkim    RegionObj2 = AcpiNsGetSecondaryObject (RegionObj);
548245582Sjkim    if (!RegionObj2)
54967754Smsmith    {
550245582Sjkim        return_ACPI_STATUS (AE_NOT_EXIST);
55167754Smsmith    }
55267754Smsmith
553245582Sjkim    if (RegionObj2->Extra.Method_REG == NULL)
55467754Smsmith    {
555245582Sjkim        return_ACPI_STATUS (AE_OK);
55667754Smsmith    }
55767754Smsmith
558245582Sjkim    /* Allocate and initialize the evaluation information block */
55967754Smsmith
560245582Sjkim    Info = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_EVALUATE_INFO));
561245582Sjkim    if (!Info)
56267754Smsmith    {
563245582Sjkim        return_ACPI_STATUS (AE_NO_MEMORY);
56467754Smsmith    }
56567754Smsmith
566245582Sjkim    Info->PrefixNode = RegionObj2->Extra.Method_REG;
567249663Sjkim    Info->RelativePathname = NULL;
568245582Sjkim    Info->Parameters = Args;
569245582Sjkim    Info->Flags = ACPI_IGNORE_RETURN_VALUE;
570117521Snjl
57167754Smsmith    /*
572245582Sjkim     * The _REG method has two arguments:
57367754Smsmith     *
574245582Sjkim     * Arg0 - Integer:
575245582Sjkim     *  Operation region space ID Same value as RegionObj->Region.SpaceId
576245582Sjkim     *
577245582Sjkim     * Arg1 - Integer:
578245582Sjkim     *  connection status 1 for connecting the handler, 0 for disconnecting
579245582Sjkim     *  the handler (Passed as a parameter)
58067754Smsmith     */
581245582Sjkim    Args[0] = AcpiUtCreateIntegerObject ((UINT64) RegionObj->Region.SpaceId);
582245582Sjkim    if (!Args[0])
583129684Snjl    {
584245582Sjkim        Status = AE_NO_MEMORY;
585245582Sjkim        goto Cleanup1;
586129684Snjl    }
587129684Snjl
588245582Sjkim    Args[1] = AcpiUtCreateIntegerObject ((UINT64) Function);
589245582Sjkim    if (!Args[1])
590129684Snjl    {
591129684Snjl        Status = AE_NO_MEMORY;
592245582Sjkim        goto Cleanup2;
593129684Snjl    }
594129684Snjl
595245582Sjkim    Args[2] = NULL; /* Terminate list */
596129684Snjl
597245582Sjkim    /* Execute the method, no return value */
598129684Snjl
599245582Sjkim    ACPI_DEBUG_EXEC (
600245582Sjkim        AcpiUtDisplayInitPathname (ACPI_TYPE_METHOD, Info->PrefixNode, NULL));
601129684Snjl
602245582Sjkim    Status = AcpiNsEvaluate (Info);
603245582Sjkim    AcpiUtRemoveReference (Args[1]);
604129684Snjl
605245582SjkimCleanup2:
606245582Sjkim    AcpiUtRemoveReference (Args[0]);
607129684Snjl
608245582SjkimCleanup1:
609245582Sjkim    ACPI_FREE (Info);
610129684Snjl    return_ACPI_STATUS (Status);
611129684Snjl}
612129684Snjl
613129684Snjl
614129684Snjl/*******************************************************************************
615129684Snjl *
616129684Snjl * FUNCTION:    AcpiEvExecuteRegMethods
617129684Snjl *
618129684Snjl * PARAMETERS:  Node            - Namespace node for the device
619129684Snjl *              SpaceId         - The address space ID
620129684Snjl *
621129684Snjl * RETURN:      Status
622129684Snjl *
623138287Smarks * DESCRIPTION: Run all _REG methods for the input Space ID;
624129684Snjl *              Note: assumes namespace is locked, or system init time.
625129684Snjl *
626129684Snjl ******************************************************************************/
627129684Snjl
628129684SnjlACPI_STATUS
629129684SnjlAcpiEvExecuteRegMethods (
630129684Snjl    ACPI_NAMESPACE_NODE     *Node,
631129684Snjl    ACPI_ADR_SPACE_TYPE     SpaceId)
632129684Snjl{
633129684Snjl    ACPI_STATUS             Status;
634129684Snjl
635129684Snjl
636167802Sjkim    ACPI_FUNCTION_TRACE (EvExecuteRegMethods);
637129684Snjl
638129684Snjl
639129684Snjl    /*
640193267Sjkim     * Run all _REG methods for all Operation Regions for this space ID. This
641193267Sjkim     * is a separate walk in order to handle any interdependencies between
642193267Sjkim     * regions and _REG methods. (i.e. handlers must be installed for all
643193267Sjkim     * regions of this Space ID before we can run any _REG methods)
644129684Snjl     */
645129684Snjl    Status = AcpiNsWalkNamespace (ACPI_TYPE_ANY, Node, ACPI_UINT32_MAX,
646199337Sjkim                ACPI_NS_WALK_UNLOCK, AcpiEvRegRun, NULL,
647167802Sjkim                &SpaceId, NULL);
648129684Snjl
649220663Sjkim    /* Special case for EC: handle "orphan" _REG methods with no region */
650220663Sjkim
651220663Sjkim    if (SpaceId == ACPI_ADR_SPACE_EC)
652220663Sjkim    {
653249663Sjkim        AcpiEvOrphanEcRegMethod (Node);
654220663Sjkim    }
655220663Sjkim
656129684Snjl    return_ACPI_STATUS (Status);
657129684Snjl}
658129684Snjl
659129684Snjl
660129684Snjl/*******************************************************************************
661129684Snjl *
662123315Snjl * FUNCTION:    AcpiEvRegRun
663123315Snjl *
664123315Snjl * PARAMETERS:  WalkNamespace callback
665123315Snjl *
666123315Snjl * DESCRIPTION: Run _REG method for region objects of the requested spaceID
667123315Snjl *
668123315Snjl ******************************************************************************/
66967754Smsmith
670151937Sjkimstatic ACPI_STATUS
671123315SnjlAcpiEvRegRun (
672123315Snjl    ACPI_HANDLE             ObjHandle,
673123315Snjl    UINT32                  Level,
674123315Snjl    void                    *Context,
675123315Snjl    void                    **ReturnValue)
676123315Snjl{
677123315Snjl    ACPI_OPERAND_OBJECT     *ObjDesc;
678123315Snjl    ACPI_NAMESPACE_NODE     *Node;
679129684Snjl    ACPI_ADR_SPACE_TYPE     SpaceId;
680123315Snjl    ACPI_STATUS             Status;
681123315Snjl
682123315Snjl
683129684Snjl    SpaceId = *ACPI_CAST_PTR (ACPI_ADR_SPACE_TYPE, Context);
684123315Snjl
685123315Snjl    /* Convert and validate the device handle */
686123315Snjl
687200553Sjkim    Node = AcpiNsValidateHandle (ObjHandle);
688123315Snjl    if (!Node)
689123315Snjl    {
690123315Snjl        return (AE_BAD_PARAMETER);
691123315Snjl    }
692123315Snjl
693123315Snjl    /*
694193267Sjkim     * We only care about regions.and objects that are allowed to have address
695193267Sjkim     * space handlers
696123315Snjl     */
697123315Snjl    if ((Node->Type != ACPI_TYPE_REGION) &&
698123315Snjl        (Node != AcpiGbl_RootNode))
699123315Snjl    {
700123315Snjl        return (AE_OK);
701123315Snjl    }
702123315Snjl
703123315Snjl    /* Check for an existing internal object */
704123315Snjl
705123315Snjl    ObjDesc = AcpiNsGetAttachedObject (Node);
706123315Snjl    if (!ObjDesc)
707123315Snjl    {
708123315Snjl        /* No object, just exit */
709123315Snjl
710123315Snjl        return (AE_OK);
711123315Snjl    }
712123315Snjl
713123315Snjl    /* Object is a Region */
714123315Snjl
715129684Snjl    if (ObjDesc->Region.SpaceId != SpaceId)
716123315Snjl    {
717193267Sjkim        /* This region is for a different address space, just ignore it */
718193267Sjkim
719123315Snjl        return (AE_OK);
720123315Snjl    }
721123315Snjl
722220663Sjkim    Status = AcpiEvExecuteRegMethod (ObjDesc, ACPI_REG_CONNECT);
723123315Snjl    return (Status);
724123315Snjl}
725123315Snjl
726220663Sjkim
727220663Sjkim/*******************************************************************************
728220663Sjkim *
729220663Sjkim * FUNCTION:    AcpiEvOrphanEcRegMethod
730220663Sjkim *
731249663Sjkim * PARAMETERS:  EcDeviceNode        - Namespace node for an EC device
732220663Sjkim *
733220663Sjkim * RETURN:      None
734220663Sjkim *
735220663Sjkim * DESCRIPTION: Execute an "orphan" _REG method that appears under the EC
736220663Sjkim *              device. This is a _REG method that has no corresponding region
737220663Sjkim *              within the EC device scope. The orphan _REG method appears to
738220663Sjkim *              have been enabled by the description of the ECDT in the ACPI
739220663Sjkim *              specification: "The availability of the region space can be
740220663Sjkim *              detected by providing a _REG method object underneath the
741220663Sjkim *              Embedded Controller device."
742220663Sjkim *
743249663Sjkim *              To quickly access the EC device, we use the EcDeviceNode used
744249663Sjkim *              during EC handler installation. Otherwise, we would need to
745249663Sjkim *              perform a time consuming namespace walk, executing _HID
746249663Sjkim *              methods to find the EC device.
747220663Sjkim *
748249663Sjkim *  MUTEX:      Assumes the namespace is locked
749249663Sjkim *
750220663Sjkim ******************************************************************************/
751220663Sjkim
752220663Sjkimstatic void
753220663SjkimAcpiEvOrphanEcRegMethod (
754249663Sjkim    ACPI_NAMESPACE_NODE     *EcDeviceNode)
755220663Sjkim{
756249663Sjkim    ACPI_HANDLE             RegMethod;
757249663Sjkim    ACPI_NAMESPACE_NODE     *NextNode;
758220663Sjkim    ACPI_STATUS             Status;
759220663Sjkim    ACPI_OBJECT_LIST        Args;
760220663Sjkim    ACPI_OBJECT             Objects[2];
761220663Sjkim
762220663Sjkim
763220663Sjkim    ACPI_FUNCTION_TRACE (EvOrphanEcRegMethod);
764220663Sjkim
765220663Sjkim
766249663Sjkim    if (!EcDeviceNode)
767220663Sjkim    {
768220663Sjkim        return_VOID;
769220663Sjkim    }
770220663Sjkim
771220663Sjkim    /* Namespace is currently locked, must release */
772220663Sjkim
773220663Sjkim    (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
774220663Sjkim
775220663Sjkim    /* Get a handle to a _REG method immediately under the EC device */
776220663Sjkim
777249663Sjkim    Status = AcpiGetHandle (EcDeviceNode, METHOD_NAME__REG, &RegMethod);
778220663Sjkim    if (ACPI_FAILURE (Status))
779220663Sjkim    {
780249663Sjkim        goto Exit; /* There is no _REG method present */
781220663Sjkim    }
782220663Sjkim
783220663Sjkim    /*
784220663Sjkim     * Execute the _REG method only if there is no Operation Region in
785220663Sjkim     * this scope with the Embedded Controller space ID. Otherwise, it
786220663Sjkim     * will already have been executed. Note, this allows for Regions
787220663Sjkim     * with other space IDs to be present; but the code below will then
788249663Sjkim     * execute the _REG method with the EmbeddedControl SpaceID argument.
789220663Sjkim     */
790220663Sjkim    NextNode = AcpiNsGetNextNode (EcDeviceNode, NULL);
791220663Sjkim    while (NextNode)
792220663Sjkim    {
793220663Sjkim        if ((NextNode->Type == ACPI_TYPE_REGION) &&
794220663Sjkim            (NextNode->Object) &&
795220663Sjkim            (NextNode->Object->Region.SpaceId == ACPI_ADR_SPACE_EC))
796220663Sjkim        {
797249663Sjkim            goto Exit; /* Do not execute the _REG */
798220663Sjkim        }
799249663Sjkim
800220663Sjkim        NextNode = AcpiNsGetNextNode (EcDeviceNode, NextNode);
801220663Sjkim    }
802220663Sjkim
803249663Sjkim    /* Evaluate the _REG(EmbeddedControl,Connect) method */
804220663Sjkim
805220663Sjkim    Args.Count = 2;
806220663Sjkim    Args.Pointer = Objects;
807220663Sjkim    Objects[0].Type = ACPI_TYPE_INTEGER;
808220663Sjkim    Objects[0].Integer.Value = ACPI_ADR_SPACE_EC;
809220663Sjkim    Objects[1].Type = ACPI_TYPE_INTEGER;
810220663Sjkim    Objects[1].Integer.Value = ACPI_REG_CONNECT;
811220663Sjkim
812220663Sjkim    Status = AcpiEvaluateObject (RegMethod, NULL, &Args, NULL);
813220663Sjkim
814220663SjkimExit:
815220663Sjkim    /* We ignore all errors from above, don't care */
816220663Sjkim
817220663Sjkim    Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
818220663Sjkim    return_VOID;
819220663Sjkim}
820