xref: /haiku/src/add-ons/kernel/bus_managers/acpi/acpica/components/events/evregion.c (revision 25a7b01d15612846f332751841da3579db313082)
1 /******************************************************************************
2  *
3  * Module Name: evregion - ACPI AddressSpace (OpRegion) handler dispatch
4  *
5  *****************************************************************************/
6 
7 /******************************************************************************
8  *
9  * 1. Copyright Notice
10  *
11  * Some or all of this work - Copyright (c) 1999 - 2012, Intel Corp.
12  * All rights reserved.
13  *
14  * 2. License
15  *
16  * 2.1. This is your license from Intel Corp. under its intellectual property
17  * rights. You may have additional license terms from the party that provided
18  * you this software, covering your right to use that party's intellectual
19  * property rights.
20  *
21  * 2.2. Intel grants, free of charge, to any person ("Licensee") obtaining a
22  * copy of the source code appearing in this file ("Covered Code") an
23  * irrevocable, perpetual, worldwide license under Intel's copyrights in the
24  * base code distributed originally by Intel ("Original Intel Code") to copy,
25  * make derivatives, distribute, use and display any portion of the Covered
26  * Code in any form, with the right to sublicense such rights; and
27  *
28  * 2.3. Intel grants Licensee a non-exclusive and non-transferable patent
29  * license (with the right to sublicense), under only those claims of Intel
30  * patents that are infringed by the Original Intel Code, to make, use, sell,
31  * offer to sell, and import the Covered Code and derivative works thereof
32  * solely to the minimum extent necessary to exercise the above copyright
33  * license, and in no event shall the patent license extend to any additions
34  * to or modifications of the Original Intel Code. No other license or right
35  * is granted directly or by implication, estoppel or otherwise;
36  *
37  * The above copyright and patent license is granted only if the following
38  * conditions are met:
39  *
40  * 3. Conditions
41  *
42  * 3.1. Redistribution of Source with Rights to Further Distribute Source.
43  * Redistribution of source code of any substantial portion of the Covered
44  * Code or modification with rights to further distribute source must include
45  * the above Copyright Notice, the above License, this list of Conditions,
46  * and the following Disclaimer and Export Compliance provision. In addition,
47  * Licensee must cause all Covered Code to which Licensee contributes to
48  * contain a file documenting the changes Licensee made to create that Covered
49  * Code and the date of any change. Licensee must include in that file the
50  * documentation of any changes made by any predecessor Licensee. Licensee
51  * must include a prominent statement that the modification is derived,
52  * directly or indirectly, from Original Intel Code.
53  *
54  * 3.2. Redistribution of Source with no Rights to Further Distribute Source.
55  * Redistribution of source code of any substantial portion of the Covered
56  * Code or modification without rights to further distribute source must
57  * include the following Disclaimer and Export Compliance provision in the
58  * documentation and/or other materials provided with distribution. In
59  * addition, Licensee may not authorize further sublicense of source of any
60  * portion of the Covered Code, and must include terms to the effect that the
61  * license from Licensee to its licensee is limited to the intellectual
62  * property embodied in the software Licensee provides to its licensee, and
63  * not to intellectual property embodied in modifications its licensee may
64  * make.
65  *
66  * 3.3. Redistribution of Executable. Redistribution in executable form of any
67  * substantial portion of the Covered Code or modification must reproduce the
68  * above Copyright Notice, and the following Disclaimer and Export Compliance
69  * provision in the documentation and/or other materials provided with the
70  * distribution.
71  *
72  * 3.4. Intel retains all right, title, and interest in and to the Original
73  * Intel Code.
74  *
75  * 3.5. Neither the name Intel nor any other trademark owned or controlled by
76  * Intel shall be used in advertising or otherwise to promote the sale, use or
77  * other dealings in products derived from or relating to the Covered Code
78  * without prior written authorization from Intel.
79  *
80  * 4. Disclaimer and Export Compliance
81  *
82  * 4.1. INTEL MAKES NO WARRANTY OF ANY KIND REGARDING ANY SOFTWARE PROVIDED
83  * HERE. ANY SOFTWARE ORIGINATING FROM INTEL OR DERIVED FROM INTEL SOFTWARE
84  * IS PROVIDED "AS IS," AND INTEL WILL NOT PROVIDE ANY SUPPORT, ASSISTANCE,
85  * INSTALLATION, TRAINING OR OTHER SERVICES. INTEL WILL NOT PROVIDE ANY
86  * UPDATES, ENHANCEMENTS OR EXTENSIONS. INTEL SPECIFICALLY DISCLAIMS ANY
87  * IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT AND FITNESS FOR A
88  * PARTICULAR PURPOSE.
89  *
90  * 4.2. IN NO EVENT SHALL INTEL HAVE ANY LIABILITY TO LICENSEE, ITS LICENSEES
91  * OR ANY OTHER THIRD PARTY, FOR ANY LOST PROFITS, LOST DATA, LOSS OF USE OR
92  * COSTS OF PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, OR FOR ANY INDIRECT,
93  * SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THIS AGREEMENT, UNDER ANY
94  * CAUSE OF ACTION OR THEORY OF LIABILITY, AND IRRESPECTIVE OF WHETHER INTEL
95  * HAS ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES. THESE LIMITATIONS
96  * SHALL APPLY NOTWITHSTANDING THE FAILURE OF THE ESSENTIAL PURPOSE OF ANY
97  * LIMITED REMEDY.
98  *
99  * 4.3. Licensee shall not export, either directly or indirectly, any of this
100  * software or system incorporating such software without first obtaining any
101  * required license or other approval from the U. S. Department of Commerce or
102  * any other agency or department of the United States Government. In the
103  * event Licensee exports any such software from the United States or
104  * re-exports any such software from a foreign destination, Licensee shall
105  * ensure that the distribution and export/re-export of the software is in
106  * compliance with all laws, regulations, orders, or other restrictions of the
107  * U.S. Export Administration Regulations. Licensee agrees that neither it nor
108  * any of its subsidiaries will export/re-export any technical data, process,
109  * software, or service, directly or indirectly, to any country for which the
110  * United States government or any agency thereof requires an export license,
111  * other governmental approval, or letter of assurance, without first obtaining
112  * such license, approval or letter.
113  *
114  *****************************************************************************/
115 
116 
117 #define __EVREGION_C__
118 
119 #include "acpi.h"
120 #include "accommon.h"
121 #include "acevents.h"
122 #include "acnamesp.h"
123 #include "acinterp.h"
124 
125 #define _COMPONENT          ACPI_EVENTS
126         ACPI_MODULE_NAME    ("evregion")
127 
128 
129 /* Local prototypes */
130 
131 static BOOLEAN
132 AcpiEvHasDefaultHandler (
133     ACPI_NAMESPACE_NODE     *Node,
134     ACPI_ADR_SPACE_TYPE     SpaceId);
135 
136 static void
137 AcpiEvOrphanEcRegMethod (
138     void);
139 
140 static ACPI_STATUS
141 AcpiEvRegRun (
142     ACPI_HANDLE             ObjHandle,
143     UINT32                  Level,
144     void                    *Context,
145     void                    **ReturnValue);
146 
147 static ACPI_STATUS
148 AcpiEvInstallHandler (
149     ACPI_HANDLE             ObjHandle,
150     UINT32                  Level,
151     void                    *Context,
152     void                    **ReturnValue);
153 
154 /* These are the address spaces that will get default handlers */
155 
156 #define ACPI_NUM_DEFAULT_SPACES     4
157 
158 static UINT8        AcpiGbl_DefaultAddressSpaces[ACPI_NUM_DEFAULT_SPACES] =
159 {
160     ACPI_ADR_SPACE_SYSTEM_MEMORY,
161     ACPI_ADR_SPACE_SYSTEM_IO,
162     ACPI_ADR_SPACE_PCI_CONFIG,
163     ACPI_ADR_SPACE_DATA_TABLE
164 };
165 
166 
167 /*******************************************************************************
168  *
169  * FUNCTION:    AcpiEvInstallRegionHandlers
170  *
171  * PARAMETERS:  None
172  *
173  * RETURN:      Status
174  *
175  * DESCRIPTION: Installs the core subsystem default address space handlers.
176  *
177  ******************************************************************************/
178 
179 ACPI_STATUS
180 AcpiEvInstallRegionHandlers (
181     void)
182 {
183     ACPI_STATUS             Status;
184     UINT32                  i;
185 
186 
187     ACPI_FUNCTION_TRACE (EvInstallRegionHandlers);
188 
189 
190     Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
191     if (ACPI_FAILURE (Status))
192     {
193         return_ACPI_STATUS (Status);
194     }
195 
196     /*
197      * All address spaces (PCI Config, EC, SMBus) are scope dependent and
198      * registration must occur for a specific device.
199      *
200      * In the case of the system memory and IO address spaces there is
201      * currently no device associated with the address space. For these we
202      * use the root.
203      *
204      * We install the default PCI config space handler at the root so that
205      * this space is immediately available even though the we have not
206      * enumerated all the PCI Root Buses yet. This is to conform to the ACPI
207      * specification which states that the PCI config space must be always
208      * available -- even though we are nowhere near ready to find the PCI root
209      * buses at this point.
210      *
211      * NOTE: We ignore AE_ALREADY_EXISTS because this means that a handler
212      * has already been installed (via AcpiInstallAddressSpaceHandler).
213      * Similar for AE_SAME_HANDLER.
214      */
215     for (i = 0; i < ACPI_NUM_DEFAULT_SPACES; i++)
216     {
217         Status = AcpiEvInstallSpaceHandler (AcpiGbl_RootNode,
218                     AcpiGbl_DefaultAddressSpaces[i],
219                     ACPI_DEFAULT_HANDLER, NULL, NULL);
220         switch (Status)
221         {
222         case AE_OK:
223         case AE_SAME_HANDLER:
224         case AE_ALREADY_EXISTS:
225 
226             /* These exceptions are all OK */
227 
228             Status = AE_OK;
229             break;
230 
231         default:
232 
233             goto UnlockAndExit;
234         }
235     }
236 
237 UnlockAndExit:
238     (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
239     return_ACPI_STATUS (Status);
240 }
241 
242 
243 /*******************************************************************************
244  *
245  * FUNCTION:    AcpiEvHasDefaultHandler
246  *
247  * PARAMETERS:  Node                - Namespace node for the device
248  *              SpaceId             - The address space ID
249  *
250  * RETURN:      TRUE if default handler is installed, FALSE otherwise
251  *
252  * DESCRIPTION: Check if the default handler is installed for the requested
253  *              space ID.
254  *
255  ******************************************************************************/
256 
257 static BOOLEAN
258 AcpiEvHasDefaultHandler (
259     ACPI_NAMESPACE_NODE     *Node,
260     ACPI_ADR_SPACE_TYPE     SpaceId)
261 {
262     ACPI_OPERAND_OBJECT     *ObjDesc;
263     ACPI_OPERAND_OBJECT     *HandlerObj;
264 
265 
266     /* Must have an existing internal object */
267 
268     ObjDesc = AcpiNsGetAttachedObject (Node);
269     if (ObjDesc)
270     {
271         HandlerObj = ObjDesc->Device.Handler;
272 
273         /* Walk the linked list of handlers for this object */
274 
275         while (HandlerObj)
276         {
277             if (HandlerObj->AddressSpace.SpaceId == SpaceId)
278             {
279                 if (HandlerObj->AddressSpace.HandlerFlags &
280                         ACPI_ADDR_HANDLER_DEFAULT_INSTALLED)
281                 {
282                     return (TRUE);
283                 }
284             }
285 
286             HandlerObj = HandlerObj->AddressSpace.Next;
287         }
288     }
289 
290     return (FALSE);
291 }
292 
293 
294 /*******************************************************************************
295  *
296  * FUNCTION:    AcpiEvInitializeOpRegions
297  *
298  * PARAMETERS:  None
299  *
300  * RETURN:      Status
301  *
302  * DESCRIPTION: Execute _REG methods for all Operation Regions that have
303  *              an installed default region handler.
304  *
305  ******************************************************************************/
306 
307 ACPI_STATUS
308 AcpiEvInitializeOpRegions (
309     void)
310 {
311     ACPI_STATUS             Status;
312     UINT32                  i;
313 
314 
315     ACPI_FUNCTION_TRACE (EvInitializeOpRegions);
316 
317 
318     Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
319     if (ACPI_FAILURE (Status))
320     {
321         return_ACPI_STATUS (Status);
322     }
323 
324     /* Run the _REG methods for OpRegions in each default address space */
325 
326     for (i = 0; i < ACPI_NUM_DEFAULT_SPACES; i++)
327     {
328         /*
329          * Make sure the installed handler is the DEFAULT handler. If not the
330          * default, the _REG methods will have already been run (when the
331          * handler was installed)
332          */
333         if (AcpiEvHasDefaultHandler (AcpiGbl_RootNode,
334                AcpiGbl_DefaultAddressSpaces[i]))
335         {
336             Status = AcpiEvExecuteRegMethods (AcpiGbl_RootNode,
337                         AcpiGbl_DefaultAddressSpaces[i]);
338         }
339     }
340 
341     AcpiGbl_RegMethodsExecuted = TRUE;
342 
343     (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
344     return_ACPI_STATUS (Status);
345 }
346 
347 
348 /*******************************************************************************
349  *
350  * FUNCTION:    AcpiEvExecuteRegMethod
351  *
352  * PARAMETERS:  RegionObj           - Region object
353  *              Function            - Passed to _REG: On (1) or Off (0)
354  *
355  * RETURN:      Status
356  *
357  * DESCRIPTION: Execute _REG method for a region
358  *
359  ******************************************************************************/
360 
361 ACPI_STATUS
362 AcpiEvExecuteRegMethod (
363     ACPI_OPERAND_OBJECT     *RegionObj,
364     UINT32                  Function)
365 {
366     ACPI_EVALUATE_INFO      *Info;
367     ACPI_OPERAND_OBJECT     *Args[3];
368     ACPI_OPERAND_OBJECT     *RegionObj2;
369     ACPI_STATUS             Status;
370 
371 
372     ACPI_FUNCTION_TRACE (EvExecuteRegMethod);
373 
374 
375     RegionObj2 = AcpiNsGetSecondaryObject (RegionObj);
376     if (!RegionObj2)
377     {
378         return_ACPI_STATUS (AE_NOT_EXIST);
379     }
380 
381     if (RegionObj2->Extra.Method_REG == NULL)
382     {
383         return_ACPI_STATUS (AE_OK);
384     }
385 
386     /* Allocate and initialize the evaluation information block */
387 
388     Info = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_EVALUATE_INFO));
389     if (!Info)
390     {
391         return_ACPI_STATUS (AE_NO_MEMORY);
392     }
393 
394     Info->PrefixNode = RegionObj2->Extra.Method_REG;
395     Info->Pathname = NULL;
396     Info->Parameters = Args;
397     Info->Flags = ACPI_IGNORE_RETURN_VALUE;
398 
399     /*
400      * The _REG method has two arguments:
401      *
402      * Arg0 - Integer:
403      *  Operation region space ID Same value as RegionObj->Region.SpaceId
404      *
405      * Arg1 - Integer:
406      *  connection status 1 for connecting the handler, 0 for disconnecting
407      *  the handler (Passed as a parameter)
408      */
409     Args[0] = AcpiUtCreateIntegerObject ((UINT64) RegionObj->Region.SpaceId);
410     if (!Args[0])
411     {
412         Status = AE_NO_MEMORY;
413         goto Cleanup1;
414     }
415 
416     Args[1] = AcpiUtCreateIntegerObject ((UINT64) Function);
417     if (!Args[1])
418     {
419         Status = AE_NO_MEMORY;
420         goto Cleanup2;
421     }
422 
423     Args[2] = NULL; /* Terminate list */
424 
425     /* Execute the method, no return value */
426 
427     ACPI_DEBUG_EXEC (
428         AcpiUtDisplayInitPathname (ACPI_TYPE_METHOD, Info->PrefixNode, NULL));
429 
430     Status = AcpiNsEvaluate (Info);
431     AcpiUtRemoveReference (Args[1]);
432 
433 Cleanup2:
434     AcpiUtRemoveReference (Args[0]);
435 
436 Cleanup1:
437     ACPI_FREE (Info);
438     return_ACPI_STATUS (Status);
439 }
440 
441 
442 /*******************************************************************************
443  *
444  * FUNCTION:    AcpiEvAddressSpaceDispatch
445  *
446  * PARAMETERS:  RegionObj           - Internal region object
447  *              FieldObj            - Corresponding field. Can be NULL.
448  *              Function            - Read or Write operation
449  *              RegionOffset        - Where in the region to read or write
450  *              BitWidth            - Field width in bits (8, 16, 32, or 64)
451  *              Value               - Pointer to in or out value, must be
452  *                                    a full 64-bit integer
453  *
454  * RETURN:      Status
455  *
456  * DESCRIPTION: Dispatch an address space or operation region access to
457  *              a previously installed handler.
458  *
459  ******************************************************************************/
460 
461 ACPI_STATUS
462 AcpiEvAddressSpaceDispatch (
463     ACPI_OPERAND_OBJECT     *RegionObj,
464     ACPI_OPERAND_OBJECT     *FieldObj,
465     UINT32                  Function,
466     UINT32                  RegionOffset,
467     UINT32                  BitWidth,
468     UINT64                  *Value)
469 {
470     ACPI_STATUS             Status;
471     ACPI_ADR_SPACE_HANDLER  Handler;
472     ACPI_ADR_SPACE_SETUP    RegionSetup;
473     ACPI_OPERAND_OBJECT     *HandlerDesc;
474     ACPI_OPERAND_OBJECT     *RegionObj2;
475     void                    *RegionContext = NULL;
476     ACPI_CONNECTION_INFO    *Context;
477 
478 
479     ACPI_FUNCTION_TRACE (EvAddressSpaceDispatch);
480 
481 
482     RegionObj2 = AcpiNsGetSecondaryObject (RegionObj);
483     if (!RegionObj2)
484     {
485         return_ACPI_STATUS (AE_NOT_EXIST);
486     }
487 
488     /* Ensure that there is a handler associated with this region */
489 
490     HandlerDesc = RegionObj->Region.Handler;
491     if (!HandlerDesc)
492     {
493         ACPI_ERROR ((AE_INFO,
494             "No handler for Region [%4.4s] (%p) [%s]",
495             AcpiUtGetNodeName (RegionObj->Region.Node),
496             RegionObj, AcpiUtGetRegionName (RegionObj->Region.SpaceId)));
497 
498         return_ACPI_STATUS (AE_NOT_EXIST);
499     }
500 
501     Context = HandlerDesc->AddressSpace.Context;
502 
503     /*
504      * It may be the case that the region has never been initialized.
505      * Some types of regions require special init code
506      */
507     if (!(RegionObj->Region.Flags & AOPOBJ_SETUP_COMPLETE))
508     {
509         /* This region has not been initialized yet, do it */
510 
511         RegionSetup = HandlerDesc->AddressSpace.Setup;
512         if (!RegionSetup)
513         {
514             /* No initialization routine, exit with error */
515 
516             ACPI_ERROR ((AE_INFO,
517                 "No init routine for region(%p) [%s]",
518                 RegionObj, AcpiUtGetRegionName (RegionObj->Region.SpaceId)));
519             return_ACPI_STATUS (AE_NOT_EXIST);
520         }
521 
522         /*
523          * We must exit the interpreter because the region setup will
524          * potentially execute control methods (for example, the _REG method
525          * for this region)
526          */
527         AcpiExExitInterpreter ();
528 
529         Status = RegionSetup (RegionObj, ACPI_REGION_ACTIVATE,
530                     Context, &RegionContext);
531 
532         /* Re-enter the interpreter */
533 
534         AcpiExEnterInterpreter ();
535 
536         /* Check for failure of the Region Setup */
537 
538         if (ACPI_FAILURE (Status))
539         {
540             ACPI_EXCEPTION ((AE_INFO, Status,
541                 "During region initialization: [%s]",
542                 AcpiUtGetRegionName (RegionObj->Region.SpaceId)));
543             return_ACPI_STATUS (Status);
544         }
545 
546         /* Region initialization may have been completed by RegionSetup */
547 
548         if (!(RegionObj->Region.Flags & AOPOBJ_SETUP_COMPLETE))
549         {
550             RegionObj->Region.Flags |= AOPOBJ_SETUP_COMPLETE;
551 
552             if (RegionObj2->Extra.RegionContext)
553             {
554                 /* The handler for this region was already installed */
555 
556                 ACPI_FREE (RegionContext);
557             }
558             else
559             {
560                 /*
561                  * Save the returned context for use in all accesses to
562                  * this particular region
563                  */
564                 RegionObj2->Extra.RegionContext = RegionContext;
565             }
566         }
567     }
568 
569     /* We have everything we need, we can invoke the address space handler */
570 
571     Handler = HandlerDesc->AddressSpace.Handler;
572 
573     ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION,
574         "Handler %p (@%p) Address %8.8X%8.8X [%s]\n",
575         &RegionObj->Region.Handler->AddressSpace, Handler,
576         ACPI_FORMAT_NATIVE_UINT (RegionObj->Region.Address + RegionOffset),
577         AcpiUtGetRegionName (RegionObj->Region.SpaceId)));
578 
579 
580     /*
581      * Special handling for GenericSerialBus and GeneralPurposeIo:
582      * There are three extra parameters that must be passed to the
583      * handler via the context:
584      *   1) Connection buffer, a resource template from Connection() op.
585      *   2) Length of the above buffer.
586      *   3) Actual access length from the AccessAs() op.
587      */
588     if (((RegionObj->Region.SpaceId == ACPI_ADR_SPACE_GSBUS) ||
589             (RegionObj->Region.SpaceId == ACPI_ADR_SPACE_GPIO)) &&
590         Context &&
591         FieldObj)
592     {
593         /* Get the Connection (ResourceTemplate) buffer */
594 
595         Context->Connection = FieldObj->Field.ResourceBuffer;
596         Context->Length = FieldObj->Field.ResourceLength;
597         Context->AccessLength = FieldObj->Field.AccessLength;
598     }
599 
600     if (!(HandlerDesc->AddressSpace.HandlerFlags &
601             ACPI_ADDR_HANDLER_DEFAULT_INSTALLED))
602     {
603         /*
604          * For handlers other than the default (supplied) handlers, we must
605          * exit the interpreter because the handler *might* block -- we don't
606          * know what it will do, so we can't hold the lock on the intepreter.
607          */
608         AcpiExExitInterpreter();
609     }
610 
611     /* Call the handler */
612 
613     Status = Handler (Function,
614         (RegionObj->Region.Address + RegionOffset), BitWidth, Value,
615         Context, RegionObj2->Extra.RegionContext);
616 
617     if (ACPI_FAILURE (Status))
618     {
619         ACPI_EXCEPTION ((AE_INFO, Status, "Returned by Handler for [%s]",
620             AcpiUtGetRegionName (RegionObj->Region.SpaceId)));
621     }
622 
623     if (!(HandlerDesc->AddressSpace.HandlerFlags &
624             ACPI_ADDR_HANDLER_DEFAULT_INSTALLED))
625     {
626         /*
627          * We just returned from a non-default handler, we must re-enter the
628          * interpreter
629          */
630        AcpiExEnterInterpreter ();
631     }
632 
633     return_ACPI_STATUS (Status);
634 }
635 
636 
637 /*******************************************************************************
638  *
639  * FUNCTION:    AcpiEvDetachRegion
640  *
641  * PARAMETERS:  RegionObj           - Region Object
642  *              AcpiNsIsLocked      - Namespace Region Already Locked?
643  *
644  * RETURN:      None
645  *
646  * DESCRIPTION: Break the association between the handler and the region
647  *              this is a two way association.
648  *
649  ******************************************************************************/
650 
651 void
652 AcpiEvDetachRegion(
653     ACPI_OPERAND_OBJECT     *RegionObj,
654     BOOLEAN                 AcpiNsIsLocked)
655 {
656     ACPI_OPERAND_OBJECT     *HandlerObj;
657     ACPI_OPERAND_OBJECT     *ObjDesc;
658     ACPI_OPERAND_OBJECT     **LastObjPtr;
659     ACPI_ADR_SPACE_SETUP    RegionSetup;
660     void                    **RegionContext;
661     ACPI_OPERAND_OBJECT     *RegionObj2;
662     ACPI_STATUS             Status;
663 
664 
665     ACPI_FUNCTION_TRACE (EvDetachRegion);
666 
667 
668     RegionObj2 = AcpiNsGetSecondaryObject (RegionObj);
669     if (!RegionObj2)
670     {
671         return_VOID;
672     }
673     RegionContext = &RegionObj2->Extra.RegionContext;
674 
675     /* Get the address handler from the region object */
676 
677     HandlerObj = RegionObj->Region.Handler;
678     if (!HandlerObj)
679     {
680         /* This region has no handler, all done */
681 
682         return_VOID;
683     }
684 
685     /* Find this region in the handler's list */
686 
687     ObjDesc = HandlerObj->AddressSpace.RegionList;
688     LastObjPtr = &HandlerObj->AddressSpace.RegionList;
689 
690     while (ObjDesc)
691     {
692         /* Is this the correct Region? */
693 
694         if (ObjDesc == RegionObj)
695         {
696             ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION,
697                 "Removing Region %p from address handler %p\n",
698                 RegionObj, HandlerObj));
699 
700             /* This is it, remove it from the handler's list */
701 
702             *LastObjPtr = ObjDesc->Region.Next;
703             ObjDesc->Region.Next = NULL;        /* Must clear field */
704 
705             if (AcpiNsIsLocked)
706             {
707                 Status = AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
708                 if (ACPI_FAILURE (Status))
709                 {
710                     return_VOID;
711                 }
712             }
713 
714             /* Now stop region accesses by executing the _REG method */
715 
716             Status = AcpiEvExecuteRegMethod (RegionObj, ACPI_REG_DISCONNECT);
717             if (ACPI_FAILURE (Status))
718             {
719                 ACPI_EXCEPTION ((AE_INFO, Status, "from region _REG, [%s]",
720                     AcpiUtGetRegionName (RegionObj->Region.SpaceId)));
721             }
722 
723             if (AcpiNsIsLocked)
724             {
725                 Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
726                 if (ACPI_FAILURE (Status))
727                 {
728                     return_VOID;
729                 }
730             }
731 
732             /*
733              * If the region has been activated, call the setup handler with
734              * the deactivate notification
735              */
736             if (RegionObj->Region.Flags & AOPOBJ_SETUP_COMPLETE)
737             {
738                 RegionSetup = HandlerObj->AddressSpace.Setup;
739                 Status = RegionSetup (RegionObj, ACPI_REGION_DEACTIVATE,
740                     HandlerObj->AddressSpace.Context, RegionContext);
741 
742                 /* Init routine may fail, Just ignore errors */
743 
744                 if (ACPI_FAILURE (Status))
745                 {
746                     ACPI_EXCEPTION ((AE_INFO, Status,
747                         "from region handler - deactivate, [%s]",
748                         AcpiUtGetRegionName (RegionObj->Region.SpaceId)));
749                 }
750 
751                 RegionObj->Region.Flags &= ~(AOPOBJ_SETUP_COMPLETE);
752             }
753 
754             /*
755              * Remove handler reference in the region
756              *
757              * NOTE: this doesn't mean that the region goes away, the region
758              * is just inaccessible as indicated to the _REG method
759              *
760              * If the region is on the handler's list, this must be the
761              * region's handler
762              */
763             RegionObj->Region.Handler = NULL;
764             AcpiUtRemoveReference (HandlerObj);
765 
766             return_VOID;
767         }
768 
769         /* Walk the linked list of handlers */
770 
771         LastObjPtr = &ObjDesc->Region.Next;
772         ObjDesc = ObjDesc->Region.Next;
773     }
774 
775     /* If we get here, the region was not in the handler's region list */
776 
777     ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION,
778         "Cannot remove region %p from address handler %p\n",
779         RegionObj, HandlerObj));
780 
781     return_VOID;
782 }
783 
784 
785 /*******************************************************************************
786  *
787  * FUNCTION:    AcpiEvAttachRegion
788  *
789  * PARAMETERS:  HandlerObj          - Handler Object
790  *              RegionObj           - Region Object
791  *              AcpiNsIsLocked      - Namespace Region Already Locked?
792  *
793  * RETURN:      None
794  *
795  * DESCRIPTION: Create the association between the handler and the region
796  *              this is a two way association.
797  *
798  ******************************************************************************/
799 
800 ACPI_STATUS
801 AcpiEvAttachRegion (
802     ACPI_OPERAND_OBJECT     *HandlerObj,
803     ACPI_OPERAND_OBJECT     *RegionObj,
804     BOOLEAN                 AcpiNsIsLocked)
805 {
806 
807     ACPI_FUNCTION_TRACE (EvAttachRegion);
808 
809 
810     ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION,
811         "Adding Region [%4.4s] %p to address handler %p [%s]\n",
812         AcpiUtGetNodeName (RegionObj->Region.Node),
813         RegionObj, HandlerObj,
814         AcpiUtGetRegionName (RegionObj->Region.SpaceId)));
815 
816     /* Link this region to the front of the handler's list */
817 
818     RegionObj->Region.Next = HandlerObj->AddressSpace.RegionList;
819     HandlerObj->AddressSpace.RegionList = RegionObj;
820 
821     /* Install the region's handler */
822 
823     if (RegionObj->Region.Handler)
824     {
825         return_ACPI_STATUS (AE_ALREADY_EXISTS);
826     }
827 
828     RegionObj->Region.Handler = HandlerObj;
829     AcpiUtAddReference (HandlerObj);
830 
831     return_ACPI_STATUS (AE_OK);
832 }
833 
834 
835 /*******************************************************************************
836  *
837  * FUNCTION:    AcpiEvInstallHandler
838  *
839  * PARAMETERS:  WalkNamespace callback
840  *
841  * DESCRIPTION: This routine installs an address handler into objects that are
842  *              of type Region or Device.
843  *
844  *              If the Object is a Device, and the device has a handler of
845  *              the same type then the search is terminated in that branch.
846  *
847  *              This is because the existing handler is closer in proximity
848  *              to any more regions than the one we are trying to install.
849  *
850  ******************************************************************************/
851 
852 static ACPI_STATUS
853 AcpiEvInstallHandler (
854     ACPI_HANDLE             ObjHandle,
855     UINT32                  Level,
856     void                    *Context,
857     void                    **ReturnValue)
858 {
859     ACPI_OPERAND_OBJECT     *HandlerObj;
860     ACPI_OPERAND_OBJECT     *NextHandlerObj;
861     ACPI_OPERAND_OBJECT     *ObjDesc;
862     ACPI_NAMESPACE_NODE     *Node;
863     ACPI_STATUS             Status;
864 
865 
866     ACPI_FUNCTION_NAME (EvInstallHandler);
867 
868 
869     HandlerObj = (ACPI_OPERAND_OBJECT  *) Context;
870 
871     /* Parameter validation */
872 
873     if (!HandlerObj)
874     {
875         return (AE_OK);
876     }
877 
878     /* Convert and validate the device handle */
879 
880     Node = AcpiNsValidateHandle (ObjHandle);
881     if (!Node)
882     {
883         return (AE_BAD_PARAMETER);
884     }
885 
886     /*
887      * We only care about regions and objects that are allowed to have
888      * address space handlers
889      */
890     if ((Node->Type != ACPI_TYPE_DEVICE) &&
891         (Node->Type != ACPI_TYPE_REGION) &&
892         (Node != AcpiGbl_RootNode))
893     {
894         return (AE_OK);
895     }
896 
897     /* Check for an existing internal object */
898 
899     ObjDesc = AcpiNsGetAttachedObject (Node);
900     if (!ObjDesc)
901     {
902         /* No object, just exit */
903 
904         return (AE_OK);
905     }
906 
907     /* Devices are handled different than regions */
908 
909     if (ObjDesc->Common.Type == ACPI_TYPE_DEVICE)
910     {
911         /* Check if this Device already has a handler for this address space */
912 
913         NextHandlerObj = ObjDesc->Device.Handler;
914         while (NextHandlerObj)
915         {
916             /* Found a handler, is it for the same address space? */
917 
918             if (NextHandlerObj->AddressSpace.SpaceId ==
919                     HandlerObj->AddressSpace.SpaceId)
920             {
921                 ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION,
922                     "Found handler for region [%s] in device %p(%p) "
923                     "handler %p\n",
924                     AcpiUtGetRegionName (HandlerObj->AddressSpace.SpaceId),
925                     ObjDesc, NextHandlerObj, HandlerObj));
926 
927                 /*
928                  * Since the object we found it on was a device, then it
929                  * means that someone has already installed a handler for
930                  * the branch of the namespace from this device on. Just
931                  * bail out telling the walk routine to not traverse this
932                  * branch. This preserves the scoping rule for handlers.
933                  */
934                 return (AE_CTRL_DEPTH);
935             }
936 
937             /* Walk the linked list of handlers attached to this device */
938 
939             NextHandlerObj = NextHandlerObj->AddressSpace.Next;
940         }
941 
942         /*
943          * As long as the device didn't have a handler for this space we
944          * don't care about it. We just ignore it and proceed.
945          */
946         return (AE_OK);
947     }
948 
949     /* Object is a Region */
950 
951     if (ObjDesc->Region.SpaceId != HandlerObj->AddressSpace.SpaceId)
952     {
953         /* This region is for a different address space, just ignore it */
954 
955         return (AE_OK);
956     }
957 
958     /*
959      * Now we have a region and it is for the handler's address space type.
960      *
961      * First disconnect region for any previous handler (if any)
962      */
963     AcpiEvDetachRegion (ObjDesc, FALSE);
964 
965     /* Connect the region to the new handler */
966 
967     Status = AcpiEvAttachRegion (HandlerObj, ObjDesc, FALSE);
968     return (Status);
969 }
970 
971 
972 /*******************************************************************************
973  *
974  * FUNCTION:    AcpiEvInstallSpaceHandler
975  *
976  * PARAMETERS:  Node            - Namespace node for the device
977  *              SpaceId         - The address space ID
978  *              Handler         - Address of the handler
979  *              Setup           - Address of the setup function
980  *              Context         - Value passed to the handler on each access
981  *
982  * RETURN:      Status
983  *
984  * DESCRIPTION: Install a handler for all OpRegions of a given SpaceId.
985  *              Assumes namespace is locked
986  *
987  ******************************************************************************/
988 
989 ACPI_STATUS
990 AcpiEvInstallSpaceHandler (
991     ACPI_NAMESPACE_NODE     *Node,
992     ACPI_ADR_SPACE_TYPE     SpaceId,
993     ACPI_ADR_SPACE_HANDLER  Handler,
994     ACPI_ADR_SPACE_SETUP    Setup,
995     void                    *Context)
996 {
997     ACPI_OPERAND_OBJECT     *ObjDesc;
998     ACPI_OPERAND_OBJECT     *HandlerObj;
999     ACPI_STATUS             Status;
1000     ACPI_OBJECT_TYPE        Type;
1001     UINT8                  Flags = 0;
1002 
1003 
1004     ACPI_FUNCTION_TRACE (EvInstallSpaceHandler);
1005 
1006 
1007     /*
1008      * This registration is valid for only the types below and the root. This
1009      * is where the default handlers get placed.
1010      */
1011     if ((Node->Type != ACPI_TYPE_DEVICE)     &&
1012         (Node->Type != ACPI_TYPE_PROCESSOR)  &&
1013         (Node->Type != ACPI_TYPE_THERMAL)    &&
1014         (Node != AcpiGbl_RootNode))
1015     {
1016         Status = AE_BAD_PARAMETER;
1017         goto UnlockAndExit;
1018     }
1019 
1020     if (Handler == ACPI_DEFAULT_HANDLER)
1021     {
1022         Flags = ACPI_ADDR_HANDLER_DEFAULT_INSTALLED;
1023 
1024         switch (SpaceId)
1025         {
1026         case ACPI_ADR_SPACE_SYSTEM_MEMORY:
1027             Handler = AcpiExSystemMemorySpaceHandler;
1028             Setup   = AcpiEvSystemMemoryRegionSetup;
1029             break;
1030 
1031         case ACPI_ADR_SPACE_SYSTEM_IO:
1032             Handler = AcpiExSystemIoSpaceHandler;
1033             Setup   = AcpiEvIoSpaceRegionSetup;
1034             break;
1035 
1036         case ACPI_ADR_SPACE_PCI_CONFIG:
1037             Handler = AcpiExPciConfigSpaceHandler;
1038             Setup   = AcpiEvPciConfigRegionSetup;
1039             break;
1040 
1041         case ACPI_ADR_SPACE_CMOS:
1042             Handler = AcpiExCmosSpaceHandler;
1043             Setup   = AcpiEvCmosRegionSetup;
1044             break;
1045 
1046         case ACPI_ADR_SPACE_PCI_BAR_TARGET:
1047             Handler = AcpiExPciBarSpaceHandler;
1048             Setup   = AcpiEvPciBarRegionSetup;
1049             break;
1050 
1051         case ACPI_ADR_SPACE_DATA_TABLE:
1052             Handler = AcpiExDataTableSpaceHandler;
1053             Setup   = NULL;
1054             break;
1055 
1056         default:
1057             Status = AE_BAD_PARAMETER;
1058             goto UnlockAndExit;
1059         }
1060     }
1061 
1062     /* If the caller hasn't specified a setup routine, use the default */
1063 
1064     if (!Setup)
1065     {
1066         Setup = AcpiEvDefaultRegionSetup;
1067     }
1068 
1069     /* Check for an existing internal object */
1070 
1071     ObjDesc = AcpiNsGetAttachedObject (Node);
1072     if (ObjDesc)
1073     {
1074         /*
1075          * The attached device object already exists. Make sure the handler
1076          * is not already installed.
1077          */
1078         HandlerObj = ObjDesc->Device.Handler;
1079 
1080         /* Walk the handler list for this device */
1081 
1082         while (HandlerObj)
1083         {
1084             /* Same SpaceId indicates a handler already installed */
1085 
1086             if (HandlerObj->AddressSpace.SpaceId == SpaceId)
1087             {
1088                 if (HandlerObj->AddressSpace.Handler == Handler)
1089                 {
1090                     /*
1091                      * It is (relatively) OK to attempt to install the SAME
1092                      * handler twice. This can easily happen with the
1093                      * PCI_Config space.
1094                      */
1095                     Status = AE_SAME_HANDLER;
1096                     goto UnlockAndExit;
1097                 }
1098                 else
1099                 {
1100                     /* A handler is already installed */
1101 
1102                     Status = AE_ALREADY_EXISTS;
1103                 }
1104                 goto UnlockAndExit;
1105             }
1106 
1107             /* Walk the linked list of handlers */
1108 
1109             HandlerObj = HandlerObj->AddressSpace.Next;
1110         }
1111     }
1112     else
1113     {
1114         ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION,
1115             "Creating object on Device %p while installing handler\n", Node));
1116 
1117         /* ObjDesc does not exist, create one */
1118 
1119         if (Node->Type == ACPI_TYPE_ANY)
1120         {
1121             Type = ACPI_TYPE_DEVICE;
1122         }
1123         else
1124         {
1125             Type = Node->Type;
1126         }
1127 
1128         ObjDesc = AcpiUtCreateInternalObject (Type);
1129         if (!ObjDesc)
1130         {
1131             Status = AE_NO_MEMORY;
1132             goto UnlockAndExit;
1133         }
1134 
1135         /* Init new descriptor */
1136 
1137         ObjDesc->Common.Type = (UINT8) Type;
1138 
1139         /* Attach the new object to the Node */
1140 
1141         Status = AcpiNsAttachObject (Node, ObjDesc, Type);
1142 
1143         /* Remove local reference to the object */
1144 
1145         AcpiUtRemoveReference (ObjDesc);
1146 
1147         if (ACPI_FAILURE (Status))
1148         {
1149             goto UnlockAndExit;
1150         }
1151     }
1152 
1153     ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION,
1154         "Installing address handler for region %s(%X) on Device %4.4s %p(%p)\n",
1155         AcpiUtGetRegionName (SpaceId), SpaceId,
1156         AcpiUtGetNodeName (Node), Node, ObjDesc));
1157 
1158     /*
1159      * Install the handler
1160      *
1161      * At this point there is no existing handler. Just allocate the object
1162      * for the handler and link it into the list.
1163      */
1164     HandlerObj = AcpiUtCreateInternalObject (ACPI_TYPE_LOCAL_ADDRESS_HANDLER);
1165     if (!HandlerObj)
1166     {
1167         Status = AE_NO_MEMORY;
1168         goto UnlockAndExit;
1169     }
1170 
1171     /* Init handler obj */
1172 
1173     HandlerObj->AddressSpace.SpaceId = (UINT8) SpaceId;
1174     HandlerObj->AddressSpace.HandlerFlags = Flags;
1175     HandlerObj->AddressSpace.RegionList = NULL;
1176     HandlerObj->AddressSpace.Node = Node;
1177     HandlerObj->AddressSpace.Handler = Handler;
1178     HandlerObj->AddressSpace.Context = Context;
1179     HandlerObj->AddressSpace.Setup  = Setup;
1180 
1181     /* Install at head of Device.AddressSpace list */
1182 
1183     HandlerObj->AddressSpace.Next = ObjDesc->Device.Handler;
1184 
1185     /*
1186      * The Device object is the first reference on the HandlerObj.
1187      * Each region that uses the handler adds a reference.
1188      */
1189     ObjDesc->Device.Handler = HandlerObj;
1190 
1191     /*
1192      * Walk the namespace finding all of the regions this
1193      * handler will manage.
1194      *
1195      * Start at the device and search the branch toward
1196      * the leaf nodes until either the leaf is encountered or
1197      * a device is detected that has an address handler of the
1198      * same type.
1199      *
1200      * In either case, back up and search down the remainder
1201      * of the branch
1202      */
1203     Status = AcpiNsWalkNamespace (ACPI_TYPE_ANY, Node, ACPI_UINT32_MAX,
1204                 ACPI_NS_WALK_UNLOCK, AcpiEvInstallHandler, NULL,
1205                 HandlerObj, NULL);
1206 
1207 UnlockAndExit:
1208     return_ACPI_STATUS (Status);
1209 }
1210 
1211 
1212 /*******************************************************************************
1213  *
1214  * FUNCTION:    AcpiEvExecuteRegMethods
1215  *
1216  * PARAMETERS:  Node            - Namespace node for the device
1217  *              SpaceId         - The address space ID
1218  *
1219  * RETURN:      Status
1220  *
1221  * DESCRIPTION: Run all _REG methods for the input Space ID;
1222  *              Note: assumes namespace is locked, or system init time.
1223  *
1224  ******************************************************************************/
1225 
1226 ACPI_STATUS
1227 AcpiEvExecuteRegMethods (
1228     ACPI_NAMESPACE_NODE     *Node,
1229     ACPI_ADR_SPACE_TYPE     SpaceId)
1230 {
1231     ACPI_STATUS             Status;
1232 
1233 
1234     ACPI_FUNCTION_TRACE (EvExecuteRegMethods);
1235 
1236 
1237     /*
1238      * Run all _REG methods for all Operation Regions for this space ID. This
1239      * is a separate walk in order to handle any interdependencies between
1240      * regions and _REG methods. (i.e. handlers must be installed for all
1241      * regions of this Space ID before we can run any _REG methods)
1242      */
1243     Status = AcpiNsWalkNamespace (ACPI_TYPE_ANY, Node, ACPI_UINT32_MAX,
1244                 ACPI_NS_WALK_UNLOCK, AcpiEvRegRun, NULL,
1245                 &SpaceId, NULL);
1246 
1247     /* Special case for EC: handle "orphan" _REG methods with no region */
1248 
1249     if (SpaceId == ACPI_ADR_SPACE_EC)
1250     {
1251         AcpiEvOrphanEcRegMethod ();
1252     }
1253 
1254     return_ACPI_STATUS (Status);
1255 }
1256 
1257 
1258 /*******************************************************************************
1259  *
1260  * FUNCTION:    AcpiEvRegRun
1261  *
1262  * PARAMETERS:  WalkNamespace callback
1263  *
1264  * DESCRIPTION: Run _REG method for region objects of the requested spaceID
1265  *
1266  ******************************************************************************/
1267 
1268 static ACPI_STATUS
1269 AcpiEvRegRun (
1270     ACPI_HANDLE             ObjHandle,
1271     UINT32                  Level,
1272     void                    *Context,
1273     void                    **ReturnValue)
1274 {
1275     ACPI_OPERAND_OBJECT     *ObjDesc;
1276     ACPI_NAMESPACE_NODE     *Node;
1277     ACPI_ADR_SPACE_TYPE     SpaceId;
1278     ACPI_STATUS             Status;
1279 
1280 
1281     SpaceId = *ACPI_CAST_PTR (ACPI_ADR_SPACE_TYPE, Context);
1282 
1283     /* Convert and validate the device handle */
1284 
1285     Node = AcpiNsValidateHandle (ObjHandle);
1286     if (!Node)
1287     {
1288         return (AE_BAD_PARAMETER);
1289     }
1290 
1291     /*
1292      * We only care about regions.and objects that are allowed to have address
1293      * space handlers
1294      */
1295     if ((Node->Type != ACPI_TYPE_REGION) &&
1296         (Node != AcpiGbl_RootNode))
1297     {
1298         return (AE_OK);
1299     }
1300 
1301     /* Check for an existing internal object */
1302 
1303     ObjDesc = AcpiNsGetAttachedObject (Node);
1304     if (!ObjDesc)
1305     {
1306         /* No object, just exit */
1307 
1308         return (AE_OK);
1309     }
1310 
1311     /* Object is a Region */
1312 
1313     if (ObjDesc->Region.SpaceId != SpaceId)
1314     {
1315         /* This region is for a different address space, just ignore it */
1316 
1317         return (AE_OK);
1318     }
1319 
1320     Status = AcpiEvExecuteRegMethod (ObjDesc, ACPI_REG_CONNECT);
1321     return (Status);
1322 }
1323 
1324 
1325 /*******************************************************************************
1326  *
1327  * FUNCTION:    AcpiEvOrphanEcRegMethod
1328  *
1329  * PARAMETERS:  None
1330  *
1331  * RETURN:      None
1332  *
1333  * DESCRIPTION: Execute an "orphan" _REG method that appears under the EC
1334  *              device. This is a _REG method that has no corresponding region
1335  *              within the EC device scope. The orphan _REG method appears to
1336  *              have been enabled by the description of the ECDT in the ACPI
1337  *              specification: "The availability of the region space can be
1338  *              detected by providing a _REG method object underneath the
1339  *              Embedded Controller device."
1340  *
1341  *              To quickly access the EC device, we use the EC_ID that appears
1342  *              within the ECDT. Otherwise, we would need to perform a time-
1343  *              consuming namespace walk, executing _HID methods to find the
1344  *              EC device.
1345  *
1346  ******************************************************************************/
1347 
1348 static void
1349 AcpiEvOrphanEcRegMethod (
1350     void)
1351 {
1352     ACPI_TABLE_ECDT         *Table;
1353     ACPI_STATUS             Status;
1354     ACPI_OBJECT_LIST        Args;
1355     ACPI_OBJECT             Objects[2];
1356     ACPI_NAMESPACE_NODE     *EcDeviceNode;
1357     ACPI_NAMESPACE_NODE     *RegMethod;
1358     ACPI_NAMESPACE_NODE     *NextNode;
1359 
1360 
1361     ACPI_FUNCTION_TRACE (EvOrphanEcRegMethod);
1362 
1363 
1364     /* Get the ECDT (if present in system) */
1365 
1366     Status = AcpiGetTable (ACPI_SIG_ECDT, 0,
1367         ACPI_CAST_INDIRECT_PTR (ACPI_TABLE_HEADER, &Table));
1368     if (ACPI_FAILURE (Status))
1369     {
1370         return_VOID;
1371     }
1372 
1373     /* We need a valid EC_ID string */
1374 
1375     if (!(*Table->Id))
1376     {
1377         return_VOID;
1378     }
1379 
1380     /* Namespace is currently locked, must release */
1381 
1382     (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
1383 
1384     /* Get a handle to the EC device referenced in the ECDT */
1385 
1386     Status = AcpiGetHandle (NULL,
1387         ACPI_CAST_PTR (char, Table->Id),
1388         ACPI_CAST_PTR (ACPI_HANDLE, &EcDeviceNode));
1389     if (ACPI_FAILURE (Status))
1390     {
1391         goto Exit;
1392     }
1393 
1394     /* Get a handle to a _REG method immediately under the EC device */
1395 
1396     Status = AcpiGetHandle (EcDeviceNode,
1397         METHOD_NAME__REG, ACPI_CAST_PTR (ACPI_HANDLE, &RegMethod));
1398     if (ACPI_FAILURE (Status))
1399     {
1400         goto Exit;
1401     }
1402 
1403     /*
1404      * Execute the _REG method only if there is no Operation Region in
1405      * this scope with the Embedded Controller space ID. Otherwise, it
1406      * will already have been executed. Note, this allows for Regions
1407      * with other space IDs to be present; but the code below will then
1408      * execute the _REG method with the EC space ID argument.
1409      */
1410     NextNode = AcpiNsGetNextNode (EcDeviceNode, NULL);
1411     while (NextNode)
1412     {
1413         if ((NextNode->Type == ACPI_TYPE_REGION) &&
1414             (NextNode->Object) &&
1415             (NextNode->Object->Region.SpaceId == ACPI_ADR_SPACE_EC))
1416         {
1417             goto Exit; /* Do not execute _REG */
1418         }
1419         NextNode = AcpiNsGetNextNode (EcDeviceNode, NextNode);
1420     }
1421 
1422     /* Evaluate the _REG(EC,Connect) method */
1423 
1424     Args.Count = 2;
1425     Args.Pointer = Objects;
1426     Objects[0].Type = ACPI_TYPE_INTEGER;
1427     Objects[0].Integer.Value = ACPI_ADR_SPACE_EC;
1428     Objects[1].Type = ACPI_TYPE_INTEGER;
1429     Objects[1].Integer.Value = ACPI_REG_CONNECT;
1430 
1431     Status = AcpiEvaluateObject (RegMethod, NULL, &Args, NULL);
1432 
1433 Exit:
1434     /* We ignore all errors from above, don't care */
1435 
1436     Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
1437     return_VOID;
1438 }
1439