evregion.c revision 1.6
1/******************************************************************************
2 *
3 * Module Name: evregion - Operation Region support
4 *
5 *****************************************************************************/
6
7/*
8 * Copyright (C) 2000 - 2018, Intel Corp.
9 * All rights reserved.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 *    notice, this list of conditions, and the following disclaimer,
16 *    without modification.
17 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
18 *    substantially similar to the "NO WARRANTY" disclaimer below
19 *    ("Disclaimer") and any redistribution must be conditioned upon
20 *    including a substantially similar Disclaimer requirement for further
21 *    binary redistribution.
22 * 3. Neither the names of the above-listed copyright holders nor the names
23 *    of any contributors may be used to endorse or promote products derived
24 *    from this software without specific prior written permission.
25 *
26 * Alternatively, this software may be distributed under the terms of the
27 * GNU General Public License ("GPL") version 2 as published by the Free
28 * Software Foundation.
29 *
30 * NO WARRANTY
31 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
33 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
34 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
35 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
40 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41 * POSSIBILITY OF SUCH DAMAGES.
42 */
43
44#include "acpi.h"
45#include "accommon.h"
46#include "acevents.h"
47#include "acnamesp.h"
48#include "acinterp.h"
49
50#define _COMPONENT          ACPI_EVENTS
51        ACPI_MODULE_NAME    ("evregion")
52
53
54extern UINT8        AcpiGbl_DefaultAddressSpaces[];
55
56/* Local prototypes */
57
58static void
59AcpiEvOrphanEcRegMethod (
60    ACPI_NAMESPACE_NODE     *EcDeviceNode);
61
62static ACPI_STATUS
63AcpiEvRegRun (
64    ACPI_HANDLE             ObjHandle,
65    UINT32                  Level,
66    void                    *Context,
67    void                    **ReturnValue);
68
69
70/*******************************************************************************
71 *
72 * FUNCTION:    AcpiEvInitializeOpRegions
73 *
74 * PARAMETERS:  None
75 *
76 * RETURN:      Status
77 *
78 * DESCRIPTION: Execute _REG methods for all Operation Regions that have
79 *              an installed default region handler.
80 *
81 ******************************************************************************/
82
83ACPI_STATUS
84AcpiEvInitializeOpRegions (
85    void)
86{
87    ACPI_STATUS             Status;
88    UINT32                  i;
89
90
91    ACPI_FUNCTION_TRACE (EvInitializeOpRegions);
92
93
94    Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
95    if (ACPI_FAILURE (Status))
96    {
97        return_ACPI_STATUS (Status);
98    }
99
100    /* Run the _REG methods for OpRegions in each default address space */
101
102    for (i = 0; i < ACPI_NUM_DEFAULT_SPACES; i++)
103    {
104        /*
105         * Make sure the installed handler is the DEFAULT handler. If not the
106         * default, the _REG methods will have already been run (when the
107         * handler was installed)
108         */
109        if (AcpiEvHasDefaultHandler (AcpiGbl_RootNode,
110               AcpiGbl_DefaultAddressSpaces[i]))
111        {
112            AcpiEvExecuteRegMethods (AcpiGbl_RootNode,
113                AcpiGbl_DefaultAddressSpaces[i], ACPI_REG_CONNECT);
114        }
115    }
116
117    (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
118    return_ACPI_STATUS (Status);
119}
120
121
122/*******************************************************************************
123 *
124 * FUNCTION:    AcpiEvAddressSpaceDispatch
125 *
126 * PARAMETERS:  RegionObj           - Internal region object
127 *              FieldObj            - Corresponding field. Can be NULL.
128 *              Function            - Read or Write operation
129 *              RegionOffset        - Where in the region to read or write
130 *              BitWidth            - Field width in bits (8, 16, 32, or 64)
131 *              Value               - Pointer to in or out value, must be
132 *                                    a full 64-bit integer
133 *
134 * RETURN:      Status
135 *
136 * DESCRIPTION: Dispatch an address space or operation region access to
137 *              a previously installed handler.
138 *
139 * NOTE: During early initialization, we always install the default region
140 * handlers for Memory, I/O and PCI_Config. This ensures that these operation
141 * region address spaces are always available as per the ACPI specification.
142 * This is especially needed in order to support the execution of
143 * module-level AML code during loading of the ACPI tables.
144 *
145 ******************************************************************************/
146
147ACPI_STATUS
148AcpiEvAddressSpaceDispatch (
149    ACPI_OPERAND_OBJECT     *RegionObj,
150    ACPI_OPERAND_OBJECT     *FieldObj,
151    UINT32                  Function,
152    UINT32                  RegionOffset,
153    UINT32                  BitWidth,
154    UINT64                  *Value)
155{
156    ACPI_STATUS             Status;
157    ACPI_ADR_SPACE_HANDLER  Handler;
158    ACPI_ADR_SPACE_SETUP    RegionSetup;
159    ACPI_OPERAND_OBJECT     *HandlerDesc;
160    ACPI_OPERAND_OBJECT     *RegionObj2;
161    void                    *RegionContext = NULL;
162    ACPI_CONNECTION_INFO    *Context;
163    ACPI_PHYSICAL_ADDRESS   Address;
164
165
166    ACPI_FUNCTION_TRACE (EvAddressSpaceDispatch);
167
168
169    RegionObj2 = AcpiNsGetSecondaryObject (RegionObj);
170    if (!RegionObj2)
171    {
172        return_ACPI_STATUS (AE_NOT_EXIST);
173    }
174
175    /* Ensure that there is a handler associated with this region */
176
177    HandlerDesc = RegionObj->Region.Handler;
178    if (!HandlerDesc)
179    {
180        ACPI_ERROR ((AE_INFO,
181            "No handler for Region [%4.4s] (%p) [%s]",
182            AcpiUtGetNodeName (RegionObj->Region.Node),
183            RegionObj, AcpiUtGetRegionName (RegionObj->Region.SpaceId)));
184
185        return_ACPI_STATUS (AE_NOT_EXIST);
186    }
187
188    Context = HandlerDesc->AddressSpace.Context;
189
190    /*
191     * It may be the case that the region has never been initialized.
192     * Some types of regions require special init code
193     */
194    if (!(RegionObj->Region.Flags & AOPOBJ_SETUP_COMPLETE))
195    {
196        /* This region has not been initialized yet, do it */
197
198        RegionSetup = HandlerDesc->AddressSpace.Setup;
199        if (!RegionSetup)
200        {
201            /* No initialization routine, exit with error */
202
203            ACPI_ERROR ((AE_INFO,
204                "No init routine for region(%p) [%s]",
205                RegionObj, AcpiUtGetRegionName (RegionObj->Region.SpaceId)));
206            return_ACPI_STATUS (AE_NOT_EXIST);
207        }
208
209        /*
210         * We must exit the interpreter because the region setup will
211         * potentially execute control methods (for example, the _REG method
212         * for this region)
213         */
214        AcpiExExitInterpreter ();
215
216        Status = RegionSetup (RegionObj, ACPI_REGION_ACTIVATE,
217            Context, &RegionContext);
218
219        /* Re-enter the interpreter */
220
221        AcpiExEnterInterpreter ();
222
223        /* Check for failure of the Region Setup */
224
225        if (ACPI_FAILURE (Status))
226        {
227            ACPI_EXCEPTION ((AE_INFO, Status,
228                "During region initialization: [%s]",
229                AcpiUtGetRegionName (RegionObj->Region.SpaceId)));
230            return_ACPI_STATUS (Status);
231        }
232
233        /* Region initialization may have been completed by RegionSetup */
234
235        if (!(RegionObj->Region.Flags & AOPOBJ_SETUP_COMPLETE))
236        {
237            RegionObj->Region.Flags |= AOPOBJ_SETUP_COMPLETE;
238
239            /*
240             * Save the returned context for use in all accesses to
241             * the handler for this particular region
242             */
243            if (!(RegionObj2->Extra.RegionContext))
244            {
245                RegionObj2->Extra.RegionContext = RegionContext;
246            }
247        }
248    }
249
250    /* We have everything we need, we can invoke the address space handler */
251
252    Handler = HandlerDesc->AddressSpace.Handler;
253    Address = (RegionObj->Region.Address + RegionOffset);
254
255    /*
256     * Special handling for GenericSerialBus and GeneralPurposeIo:
257     * There are three extra parameters that must be passed to the
258     * handler via the context:
259     *   1) Connection buffer, a resource template from Connection() op
260     *   2) Length of the above buffer
261     *   3) Actual access length from the AccessAs() op
262     *
263     * In addition, for GeneralPurposeIo, the Address and BitWidth fields
264     * are defined as follows:
265     *   1) Address is the pin number index of the field (bit offset from
266     *      the previous Connection)
267     *   2) BitWidth is the actual bit length of the field (number of pins)
268     */
269    if ((RegionObj->Region.SpaceId == ACPI_ADR_SPACE_GSBUS) &&
270        Context &&
271        FieldObj)
272    {
273        /* Get the Connection (ResourceTemplate) buffer */
274
275        Context->Connection = FieldObj->Field.ResourceBuffer;
276        Context->Length = FieldObj->Field.ResourceLength;
277        Context->AccessLength = FieldObj->Field.AccessLength;
278    }
279    if ((RegionObj->Region.SpaceId == ACPI_ADR_SPACE_GPIO) &&
280        Context &&
281        FieldObj)
282    {
283        /* Get the Connection (ResourceTemplate) buffer */
284
285        Context->Connection = FieldObj->Field.ResourceBuffer;
286        Context->Length = FieldObj->Field.ResourceLength;
287        Context->AccessLength = FieldObj->Field.AccessLength;
288        Address = FieldObj->Field.PinNumberIndex;
289        BitWidth = FieldObj->Field.BitLength;
290    }
291
292    ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION,
293        "Handler %p (@%p) Address %8.8X%8.8X [%s]\n",
294        &RegionObj->Region.Handler->AddressSpace, Handler,
295        ACPI_FORMAT_UINT64 (Address),
296        AcpiUtGetRegionName (RegionObj->Region.SpaceId)));
297
298    if (!(HandlerDesc->AddressSpace.HandlerFlags &
299        ACPI_ADDR_HANDLER_DEFAULT_INSTALLED))
300    {
301        /*
302         * For handlers other than the default (supplied) handlers, we must
303         * exit the interpreter because the handler *might* block -- we don't
304         * know what it will do, so we can't hold the lock on the intepreter.
305         */
306        AcpiExExitInterpreter();
307    }
308
309    /* Call the handler */
310
311    Status = Handler (Function, Address, BitWidth, Value, Context,
312        RegionObj2->Extra.RegionContext);
313
314    if (ACPI_FAILURE (Status))
315    {
316        ACPI_EXCEPTION ((AE_INFO, Status, "Returned by Handler for [%s]",
317            AcpiUtGetRegionName (RegionObj->Region.SpaceId)));
318
319        /*
320         * Special case for an EC timeout. These are seen so frequently
321         * that an additional error message is helpful
322         */
323        if ((RegionObj->Region.SpaceId == ACPI_ADR_SPACE_EC) &&
324            (Status == AE_TIME))
325        {
326            ACPI_ERROR ((AE_INFO,
327                "Timeout from EC hardware or EC device driver"));
328        }
329    }
330
331    if (!(HandlerDesc->AddressSpace.HandlerFlags &
332        ACPI_ADDR_HANDLER_DEFAULT_INSTALLED))
333    {
334        /*
335         * We just returned from a non-default handler, we must re-enter the
336         * interpreter
337         */
338        AcpiExEnterInterpreter ();
339    }
340
341    return_ACPI_STATUS (Status);
342}
343
344
345/*******************************************************************************
346 *
347 * FUNCTION:    AcpiEvDetachRegion
348 *
349 * PARAMETERS:  RegionObj           - Region Object
350 *              AcpiNsIsLocked      - Namespace Region Already Locked?
351 *
352 * RETURN:      None
353 *
354 * DESCRIPTION: Break the association between the handler and the region
355 *              this is a two way association.
356 *
357 ******************************************************************************/
358
359void
360AcpiEvDetachRegion (
361    ACPI_OPERAND_OBJECT     *RegionObj,
362    BOOLEAN                 AcpiNsIsLocked)
363{
364    ACPI_OPERAND_OBJECT     *HandlerObj;
365    ACPI_OPERAND_OBJECT     *ObjDesc;
366    ACPI_OPERAND_OBJECT     *StartDesc;
367    ACPI_OPERAND_OBJECT     **LastObjPtr;
368    ACPI_ADR_SPACE_SETUP    RegionSetup;
369    void                    **RegionContext;
370    ACPI_OPERAND_OBJECT     *RegionObj2;
371    ACPI_STATUS             Status;
372
373
374    ACPI_FUNCTION_TRACE (EvDetachRegion);
375
376
377    RegionObj2 = AcpiNsGetSecondaryObject (RegionObj);
378    if (!RegionObj2)
379    {
380        return_VOID;
381    }
382    RegionContext = &RegionObj2->Extra.RegionContext;
383
384    /* Get the address handler from the region object */
385
386    HandlerObj = RegionObj->Region.Handler;
387    if (!HandlerObj)
388    {
389        /* This region has no handler, all done */
390
391        return_VOID;
392    }
393
394    /* Find this region in the handler's list */
395
396    ObjDesc = HandlerObj->AddressSpace.RegionList;
397    StartDesc = ObjDesc;
398    LastObjPtr = &HandlerObj->AddressSpace.RegionList;
399
400    while (ObjDesc)
401    {
402        /* Is this the correct Region? */
403
404        if (ObjDesc == RegionObj)
405        {
406            ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION,
407                "Removing Region %p from address handler %p\n",
408                RegionObj, HandlerObj));
409
410            /* This is it, remove it from the handler's list */
411
412            *LastObjPtr = ObjDesc->Region.Next;
413            ObjDesc->Region.Next = NULL;        /* Must clear field */
414
415            if (AcpiNsIsLocked)
416            {
417                Status = AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
418                if (ACPI_FAILURE (Status))
419                {
420                    return_VOID;
421                }
422            }
423
424            /* Now stop region accesses by executing the _REG method */
425
426            Status = AcpiEvExecuteRegMethod (RegionObj, ACPI_REG_DISCONNECT);
427            if (ACPI_FAILURE (Status))
428            {
429                ACPI_EXCEPTION ((AE_INFO, Status, "from region _REG, [%s]",
430                    AcpiUtGetRegionName (RegionObj->Region.SpaceId)));
431            }
432
433            if (AcpiNsIsLocked)
434            {
435                Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
436                if (ACPI_FAILURE (Status))
437                {
438                    return_VOID;
439                }
440            }
441
442            /*
443             * If the region has been activated, call the setup handler with
444             * the deactivate notification
445             */
446            if (RegionObj->Region.Flags & AOPOBJ_SETUP_COMPLETE)
447            {
448                RegionSetup = HandlerObj->AddressSpace.Setup;
449                Status = RegionSetup (RegionObj, ACPI_REGION_DEACTIVATE,
450                    HandlerObj->AddressSpace.Context, RegionContext);
451
452                /*
453                 * RegionContext should have been released by the deactivate
454                 * operation. We don't need access to it anymore here.
455                 */
456                if (RegionContext)
457                {
458                    *RegionContext = NULL;
459                }
460
461                /* Init routine may fail, Just ignore errors */
462
463                if (ACPI_FAILURE (Status))
464                {
465                    ACPI_EXCEPTION ((AE_INFO, Status,
466                        "from region handler - deactivate, [%s]",
467                        AcpiUtGetRegionName (RegionObj->Region.SpaceId)));
468                }
469
470                RegionObj->Region.Flags &= ~(AOPOBJ_SETUP_COMPLETE);
471            }
472
473            /*
474             * Remove handler reference in the region
475             *
476             * NOTE: this doesn't mean that the region goes away, the region
477             * is just inaccessible as indicated to the _REG method
478             *
479             * If the region is on the handler's list, this must be the
480             * region's handler
481             */
482            RegionObj->Region.Handler = NULL;
483            AcpiUtRemoveReference (HandlerObj);
484
485            return_VOID;
486        }
487
488        /* Walk the linked list of handlers */
489
490        LastObjPtr = &ObjDesc->Region.Next;
491        ObjDesc = ObjDesc->Region.Next;
492
493        /* Prevent infinite loop if list is corrupted */
494
495        if (ObjDesc == StartDesc)
496        {
497            ACPI_ERROR ((AE_INFO,
498                "Circular handler list in region object %p",
499                RegionObj));
500            return_VOID;
501        }
502    }
503
504    /* If we get here, the region was not in the handler's region list */
505
506    ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION,
507        "Cannot remove region %p from address handler %p\n",
508        RegionObj, HandlerObj));
509
510    return_VOID;
511}
512
513
514/*******************************************************************************
515 *
516 * FUNCTION:    AcpiEvAttachRegion
517 *
518 * PARAMETERS:  HandlerObj          - Handler Object
519 *              RegionObj           - Region Object
520 *              AcpiNsIsLocked      - Namespace Region Already Locked?
521 *
522 * RETURN:      None
523 *
524 * DESCRIPTION: Create the association between the handler and the region
525 *              this is a two way association.
526 *
527 ******************************************************************************/
528
529ACPI_STATUS
530AcpiEvAttachRegion (
531    ACPI_OPERAND_OBJECT     *HandlerObj,
532    ACPI_OPERAND_OBJECT     *RegionObj,
533    BOOLEAN                 AcpiNsIsLocked)
534{
535
536    ACPI_FUNCTION_TRACE (EvAttachRegion);
537
538
539    /* Install the region's handler */
540
541    if (RegionObj->Region.Handler)
542    {
543        return_ACPI_STATUS (AE_ALREADY_EXISTS);
544    }
545
546    ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION,
547        "Adding Region [%4.4s] %p to address handler %p [%s]\n",
548        AcpiUtGetNodeName (RegionObj->Region.Node),
549        RegionObj, HandlerObj,
550        AcpiUtGetRegionName (RegionObj->Region.SpaceId)));
551
552    /* Link this region to the front of the handler's list */
553
554    RegionObj->Region.Next = HandlerObj->AddressSpace.RegionList;
555    HandlerObj->AddressSpace.RegionList = RegionObj;
556    RegionObj->Region.Handler = HandlerObj;
557    AcpiUtAddReference (HandlerObj);
558
559    return_ACPI_STATUS (AE_OK);
560}
561
562
563/*******************************************************************************
564 *
565 * FUNCTION:    AcpiEvExecuteRegMethod
566 *
567 * PARAMETERS:  RegionObj           - Region object
568 *              Function            - Passed to _REG: On (1) or Off (0)
569 *
570 * RETURN:      Status
571 *
572 * DESCRIPTION: Execute _REG method for a region
573 *
574 ******************************************************************************/
575
576ACPI_STATUS
577AcpiEvExecuteRegMethod (
578    ACPI_OPERAND_OBJECT     *RegionObj,
579    UINT32                  Function)
580{
581    ACPI_EVALUATE_INFO      *Info;
582    ACPI_OPERAND_OBJECT     *Args[3];
583    ACPI_OPERAND_OBJECT     *RegionObj2;
584    const ACPI_NAME         *RegNamePtr = ACPI_CAST_PTR (ACPI_NAME, METHOD_NAME__REG);
585    ACPI_NAMESPACE_NODE     *MethodNode;
586    ACPI_NAMESPACE_NODE     *Node;
587    ACPI_STATUS             Status;
588
589
590    ACPI_FUNCTION_TRACE (EvExecuteRegMethod);
591
592
593    if (!AcpiGbl_NamespaceInitialized ||
594        RegionObj->Region.Handler == NULL)
595    {
596        return_ACPI_STATUS (AE_OK);
597    }
598
599    RegionObj2 = AcpiNsGetSecondaryObject (RegionObj);
600    if (!RegionObj2)
601    {
602        return_ACPI_STATUS (AE_NOT_EXIST);
603    }
604
605    /*
606     * Find any "_REG" method associated with this region definition.
607     * The method should always be updated as this function may be
608     * invoked after a namespace change.
609     */
610    Node = RegionObj->Region.Node->Parent;
611    Status = AcpiNsSearchOneScope (
612        *RegNamePtr, Node, ACPI_TYPE_METHOD, &MethodNode);
613    if (ACPI_SUCCESS (Status))
614    {
615        /*
616         * The _REG method is optional and there can be only one per
617         * region definition. This will be executed when the handler is
618         * attached or removed.
619         */
620        RegionObj2->Extra.Method_REG = MethodNode;
621    }
622    if (RegionObj2->Extra.Method_REG == NULL)
623    {
624        return_ACPI_STATUS (AE_OK);
625    }
626
627    /* _REG(DISCONNECT) should be paired with _REG(CONNECT) */
628
629    if ((Function == ACPI_REG_CONNECT &&
630        RegionObj->Common.Flags & AOPOBJ_REG_CONNECTED) ||
631        (Function == ACPI_REG_DISCONNECT &&
632         !(RegionObj->Common.Flags & AOPOBJ_REG_CONNECTED)))
633    {
634        return_ACPI_STATUS (AE_OK);
635    }
636
637    /* Allocate and initialize the evaluation information block */
638
639    Info = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_EVALUATE_INFO));
640    if (!Info)
641    {
642        return_ACPI_STATUS (AE_NO_MEMORY);
643    }
644
645    Info->PrefixNode = RegionObj2->Extra.Method_REG;
646    Info->RelativePathname = NULL;
647    Info->Parameters = Args;
648    Info->Flags = ACPI_IGNORE_RETURN_VALUE;
649
650    /*
651     * The _REG method has two arguments:
652     *
653     * Arg0 - Integer:
654     *  Operation region space ID Same value as RegionObj->Region.SpaceId
655     *
656     * Arg1 - Integer:
657     *  connection status 1 for connecting the handler, 0 for disconnecting
658     *  the handler (Passed as a parameter)
659     */
660    Args[0] = AcpiUtCreateIntegerObject ((UINT64) RegionObj->Region.SpaceId);
661    if (!Args[0])
662    {
663        Status = AE_NO_MEMORY;
664        goto Cleanup1;
665    }
666
667    Args[1] = AcpiUtCreateIntegerObject ((UINT64) Function);
668    if (!Args[1])
669    {
670        Status = AE_NO_MEMORY;
671        goto Cleanup2;
672    }
673
674    Args[2] = NULL; /* Terminate list */
675
676    /* Execute the method, no return value */
677
678    ACPI_DEBUG_EXEC (
679        AcpiUtDisplayInitPathname (ACPI_TYPE_METHOD, Info->PrefixNode, NULL));
680
681    Status = AcpiNsEvaluate (Info);
682    AcpiUtRemoveReference (Args[1]);
683
684    if (ACPI_FAILURE (Status))
685    {
686        goto Cleanup2;
687    }
688
689    if (Function == ACPI_REG_CONNECT)
690    {
691        RegionObj->Common.Flags |= AOPOBJ_REG_CONNECTED;
692    }
693    else
694    {
695        RegionObj->Common.Flags &= ~AOPOBJ_REG_CONNECTED;
696    }
697
698Cleanup2:
699    AcpiUtRemoveReference (Args[0]);
700
701Cleanup1:
702    ACPI_FREE (Info);
703    return_ACPI_STATUS (Status);
704}
705
706
707/*******************************************************************************
708 *
709 * FUNCTION:    AcpiEvExecuteRegMethods
710 *
711 * PARAMETERS:  Node            - Namespace node for the device
712 *              SpaceId         - The address space ID
713 *              Function        - Passed to _REG: On (1) or Off (0)
714 *
715 * RETURN:      None
716 *
717 * DESCRIPTION: Run all _REG methods for the input Space ID;
718 *              Note: assumes namespace is locked, or system init time.
719 *
720 ******************************************************************************/
721
722void
723AcpiEvExecuteRegMethods (
724    ACPI_NAMESPACE_NODE     *Node,
725    ACPI_ADR_SPACE_TYPE     SpaceId,
726    UINT32                  Function)
727{
728    ACPI_REG_WALK_INFO      Info;
729
730
731    ACPI_FUNCTION_TRACE (EvExecuteRegMethods);
732
733    Info.SpaceId = SpaceId;
734    Info.Function = Function;
735    Info.RegRunCount = 0;
736
737    ACPI_DEBUG_PRINT_RAW ((ACPI_DB_NAMES,
738        "    Running _REG methods for SpaceId %s\n",
739        AcpiUtGetRegionName (Info.SpaceId)));
740
741    /*
742     * Run all _REG methods for all Operation Regions for this space ID. This
743     * is a separate walk in order to handle any interdependencies between
744     * regions and _REG methods. (i.e. handlers must be installed for all
745     * regions of this Space ID before we can run any _REG methods)
746     */
747    (void) AcpiNsWalkNamespace (ACPI_TYPE_ANY, Node, ACPI_UINT32_MAX,
748        ACPI_NS_WALK_UNLOCK, AcpiEvRegRun, NULL, &Info, NULL);
749
750    /* Special case for EC: handle "orphan" _REG methods with no region */
751
752    if (SpaceId == ACPI_ADR_SPACE_EC)
753    {
754        AcpiEvOrphanEcRegMethod (Node);
755    }
756
757    ACPI_DEBUG_PRINT_RAW ((ACPI_DB_NAMES,
758        "    Executed %u _REG methods for SpaceId %s\n",
759        Info.RegRunCount, AcpiUtGetRegionName (Info.SpaceId)));
760
761    return_VOID;
762}
763
764
765/*******************************************************************************
766 *
767 * FUNCTION:    AcpiEvRegRun
768 *
769 * PARAMETERS:  WalkNamespace callback
770 *
771 * DESCRIPTION: Run _REG method for region objects of the requested spaceID
772 *
773 ******************************************************************************/
774
775static ACPI_STATUS
776AcpiEvRegRun (
777    ACPI_HANDLE             ObjHandle,
778    UINT32                  Level,
779    void                    *Context,
780    void                    **ReturnValue)
781{
782    ACPI_OPERAND_OBJECT     *ObjDesc;
783    ACPI_NAMESPACE_NODE     *Node;
784    ACPI_STATUS             Status;
785    ACPI_REG_WALK_INFO      *Info;
786
787
788    Info = ACPI_CAST_PTR (ACPI_REG_WALK_INFO, Context);
789
790    /* Convert and validate the device handle */
791
792    Node = AcpiNsValidateHandle (ObjHandle);
793    if (!Node)
794    {
795        return (AE_BAD_PARAMETER);
796    }
797
798    /*
799     * We only care about regions.and objects that are allowed to have address
800     * space handlers
801     */
802    if ((Node->Type != ACPI_TYPE_REGION) &&
803        (Node != AcpiGbl_RootNode))
804    {
805        return (AE_OK);
806    }
807
808    /* Check for an existing internal object */
809
810    ObjDesc = AcpiNsGetAttachedObject (Node);
811    if (!ObjDesc)
812    {
813        /* No object, just exit */
814
815        return (AE_OK);
816    }
817
818    /* Object is a Region */
819
820    if (ObjDesc->Region.SpaceId != Info->SpaceId)
821    {
822        /* This region is for a different address space, just ignore it */
823
824        return (AE_OK);
825    }
826
827    Info->RegRunCount++;
828    Status = AcpiEvExecuteRegMethod (ObjDesc, Info->Function);
829    return (Status);
830}
831
832
833/*******************************************************************************
834 *
835 * FUNCTION:    AcpiEvOrphanEcRegMethod
836 *
837 * PARAMETERS:  EcDeviceNode        - Namespace node for an EC device
838 *
839 * RETURN:      None
840 *
841 * DESCRIPTION: Execute an "orphan" _REG method that appears under the EC
842 *              device. This is a _REG method that has no corresponding region
843 *              within the EC device scope. The orphan _REG method appears to
844 *              have been enabled by the description of the ECDT in the ACPI
845 *              specification: "The availability of the region space can be
846 *              detected by providing a _REG method object underneath the
847 *              Embedded Controller device."
848 *
849 *              To quickly access the EC device, we use the EcDeviceNode used
850 *              during EC handler installation. Otherwise, we would need to
851 *              perform a time consuming namespace walk, executing _HID
852 *              methods to find the EC device.
853 *
854 *  MUTEX:      Assumes the namespace is locked
855 *
856 ******************************************************************************/
857
858static void
859AcpiEvOrphanEcRegMethod (
860    ACPI_NAMESPACE_NODE     *EcDeviceNode)
861{
862    ACPI_HANDLE             RegMethod;
863    ACPI_NAMESPACE_NODE     *NextNode;
864    ACPI_STATUS             Status;
865    ACPI_OBJECT_LIST        Args;
866    ACPI_OBJECT             Objects[2];
867
868
869    ACPI_FUNCTION_TRACE (EvOrphanEcRegMethod);
870
871
872    if (!EcDeviceNode)
873    {
874        return_VOID;
875    }
876
877    /* Namespace is currently locked, must release */
878
879    (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
880
881    /* Get a handle to a _REG method immediately under the EC device */
882
883    Status = AcpiGetHandle (EcDeviceNode, METHOD_NAME__REG, &RegMethod);
884    if (ACPI_FAILURE (Status))
885    {
886        goto Exit; /* There is no _REG method present */
887    }
888
889    /*
890     * Execute the _REG method only if there is no Operation Region in
891     * this scope with the Embedded Controller space ID. Otherwise, it
892     * will already have been executed. Note, this allows for Regions
893     * with other space IDs to be present; but the code below will then
894     * execute the _REG method with the EmbeddedControl SpaceID argument.
895     */
896    NextNode = AcpiNsGetNextNode (EcDeviceNode, NULL);
897    while (NextNode)
898    {
899        if ((NextNode->Type == ACPI_TYPE_REGION) &&
900            (NextNode->Object) &&
901            (NextNode->Object->Region.SpaceId == ACPI_ADR_SPACE_EC))
902        {
903            goto Exit; /* Do not execute the _REG */
904        }
905
906        NextNode = AcpiNsGetNextNode (EcDeviceNode, NextNode);
907    }
908
909    /* Evaluate the _REG(EmbeddedControl,Connect) method */
910
911    Args.Count = 2;
912    Args.Pointer = Objects;
913    Objects[0].Type = ACPI_TYPE_INTEGER;
914    Objects[0].Integer.Value = ACPI_ADR_SPACE_EC;
915    Objects[1].Type = ACPI_TYPE_INTEGER;
916    Objects[1].Integer.Value = ACPI_REG_CONNECT;
917
918    Status = AcpiEvaluateObject (RegMethod, NULL, &Args, NULL);
919
920Exit:
921    /* We ignore all errors from above, don't care */
922
923    Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
924    return_VOID;
925}
926