xref: /haiku/src/add-ons/kernel/bus_managers/acpi/acpica/components/events/evregion.c (revision 83b1a68c52ba3e0e8796282759f694b7fdddf06d)
1 /******************************************************************************
2  *
3  * Module Name: evregion - Operation Region support
4  *
5  *****************************************************************************/
6 
7 /******************************************************************************
8  *
9  * 1. Copyright Notice
10  *
11  * Some or all of this work - Copyright (c) 1999 - 2014, 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 extern UINT8        AcpiGbl_DefaultAddressSpaces[];
130 
131 /* Local prototypes */
132 
133 static void
134 AcpiEvOrphanEcRegMethod (
135     ACPI_NAMESPACE_NODE     *EcDeviceNode);
136 
137 static ACPI_STATUS
138 AcpiEvRegRun (
139     ACPI_HANDLE             ObjHandle,
140     UINT32                  Level,
141     void                    *Context,
142     void                    **ReturnValue);
143 
144 
145 /*******************************************************************************
146  *
147  * FUNCTION:    AcpiEvInitializeOpRegions
148  *
149  * PARAMETERS:  None
150  *
151  * RETURN:      Status
152  *
153  * DESCRIPTION: Execute _REG methods for all Operation Regions that have
154  *              an installed default region handler.
155  *
156  ******************************************************************************/
157 
158 ACPI_STATUS
159 AcpiEvInitializeOpRegions (
160     void)
161 {
162     ACPI_STATUS             Status;
163     UINT32                  i;
164 
165 
166     ACPI_FUNCTION_TRACE (EvInitializeOpRegions);
167 
168 
169     Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
170     if (ACPI_FAILURE (Status))
171     {
172         return_ACPI_STATUS (Status);
173     }
174 
175     /* Run the _REG methods for OpRegions in each default address space */
176 
177     for (i = 0; i < ACPI_NUM_DEFAULT_SPACES; i++)
178     {
179         /*
180          * Make sure the installed handler is the DEFAULT handler. If not the
181          * default, the _REG methods will have already been run (when the
182          * handler was installed)
183          */
184         if (AcpiEvHasDefaultHandler (AcpiGbl_RootNode,
185                AcpiGbl_DefaultAddressSpaces[i]))
186         {
187             Status = AcpiEvExecuteRegMethods (AcpiGbl_RootNode,
188                         AcpiGbl_DefaultAddressSpaces[i]);
189         }
190     }
191 
192     AcpiGbl_RegMethodsExecuted = TRUE;
193 
194     (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
195     return_ACPI_STATUS (Status);
196 }
197 
198 
199 /*******************************************************************************
200  *
201  * FUNCTION:    AcpiEvAddressSpaceDispatch
202  *
203  * PARAMETERS:  RegionObj           - Internal region object
204  *              FieldObj            - Corresponding field. Can be NULL.
205  *              Function            - Read or Write operation
206  *              RegionOffset        - Where in the region to read or write
207  *              BitWidth            - Field width in bits (8, 16, 32, or 64)
208  *              Value               - Pointer to in or out value, must be
209  *                                    a full 64-bit integer
210  *
211  * RETURN:      Status
212  *
213  * DESCRIPTION: Dispatch an address space or operation region access to
214  *              a previously installed handler.
215  *
216  ******************************************************************************/
217 
218 ACPI_STATUS
219 AcpiEvAddressSpaceDispatch (
220     ACPI_OPERAND_OBJECT     *RegionObj,
221     ACPI_OPERAND_OBJECT     *FieldObj,
222     UINT32                  Function,
223     UINT32                  RegionOffset,
224     UINT32                  BitWidth,
225     UINT64                  *Value)
226 {
227     ACPI_STATUS             Status;
228     ACPI_ADR_SPACE_HANDLER  Handler;
229     ACPI_ADR_SPACE_SETUP    RegionSetup;
230     ACPI_OPERAND_OBJECT     *HandlerDesc;
231     ACPI_OPERAND_OBJECT     *RegionObj2;
232     void                    *RegionContext = NULL;
233     ACPI_CONNECTION_INFO    *Context;
234 
235 
236     ACPI_FUNCTION_TRACE (EvAddressSpaceDispatch);
237 
238 
239     RegionObj2 = AcpiNsGetSecondaryObject (RegionObj);
240     if (!RegionObj2)
241     {
242         return_ACPI_STATUS (AE_NOT_EXIST);
243     }
244 
245     /* Ensure that there is a handler associated with this region */
246 
247     HandlerDesc = RegionObj->Region.Handler;
248     if (!HandlerDesc)
249     {
250         ACPI_ERROR ((AE_INFO,
251             "No handler for Region [%4.4s] (%p) [%s]",
252             AcpiUtGetNodeName (RegionObj->Region.Node),
253             RegionObj, AcpiUtGetRegionName (RegionObj->Region.SpaceId)));
254 
255         return_ACPI_STATUS (AE_NOT_EXIST);
256     }
257 
258     Context = HandlerDesc->AddressSpace.Context;
259 
260     /*
261      * It may be the case that the region has never been initialized.
262      * Some types of regions require special init code
263      */
264     if (!(RegionObj->Region.Flags & AOPOBJ_SETUP_COMPLETE))
265     {
266         /* This region has not been initialized yet, do it */
267 
268         RegionSetup = HandlerDesc->AddressSpace.Setup;
269         if (!RegionSetup)
270         {
271             /* No initialization routine, exit with error */
272 
273             ACPI_ERROR ((AE_INFO,
274                 "No init routine for region(%p) [%s]",
275                 RegionObj, AcpiUtGetRegionName (RegionObj->Region.SpaceId)));
276             return_ACPI_STATUS (AE_NOT_EXIST);
277         }
278 
279         /*
280          * We must exit the interpreter because the region setup will
281          * potentially execute control methods (for example, the _REG method
282          * for this region)
283          */
284         AcpiExExitInterpreter ();
285 
286         Status = RegionSetup (RegionObj, ACPI_REGION_ACTIVATE,
287                     Context, &RegionContext);
288 
289         /* Re-enter the interpreter */
290 
291         AcpiExEnterInterpreter ();
292 
293         /* Check for failure of the Region Setup */
294 
295         if (ACPI_FAILURE (Status))
296         {
297             ACPI_EXCEPTION ((AE_INFO, Status,
298                 "During region initialization: [%s]",
299                 AcpiUtGetRegionName (RegionObj->Region.SpaceId)));
300             return_ACPI_STATUS (Status);
301         }
302 
303         /* Region initialization may have been completed by RegionSetup */
304 
305         if (!(RegionObj->Region.Flags & AOPOBJ_SETUP_COMPLETE))
306         {
307             RegionObj->Region.Flags |= AOPOBJ_SETUP_COMPLETE;
308 
309             /*
310              * Save the returned context for use in all accesses to
311              * the handler for this particular region
312              */
313             if (!(RegionObj2->Extra.RegionContext))
314             {
315                 RegionObj2->Extra.RegionContext = RegionContext;
316             }
317         }
318     }
319 
320     /* We have everything we need, we can invoke the address space handler */
321 
322     Handler = HandlerDesc->AddressSpace.Handler;
323 
324     ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION,
325         "Handler %p (@%p) Address %8.8X%8.8X [%s]\n",
326         &RegionObj->Region.Handler->AddressSpace, Handler,
327         ACPI_FORMAT_NATIVE_UINT (RegionObj->Region.Address + RegionOffset),
328         AcpiUtGetRegionName (RegionObj->Region.SpaceId)));
329 
330     /*
331      * Special handling for GenericSerialBus and GeneralPurposeIo:
332      * There are three extra parameters that must be passed to the
333      * handler via the context:
334      *   1) Connection buffer, a resource template from Connection() op.
335      *   2) Length of the above buffer.
336      *   3) Actual access length from the AccessAs() op.
337      */
338     if (((RegionObj->Region.SpaceId == ACPI_ADR_SPACE_GSBUS) ||
339             (RegionObj->Region.SpaceId == ACPI_ADR_SPACE_GPIO)) &&
340         Context &&
341         FieldObj)
342     {
343         /* Get the Connection (ResourceTemplate) buffer */
344 
345         Context->Connection = FieldObj->Field.ResourceBuffer;
346         Context->Length = FieldObj->Field.ResourceLength;
347         Context->AccessLength = FieldObj->Field.AccessLength;
348     }
349 
350     if (!(HandlerDesc->AddressSpace.HandlerFlags &
351             ACPI_ADDR_HANDLER_DEFAULT_INSTALLED))
352     {
353         /*
354          * For handlers other than the default (supplied) handlers, we must
355          * exit the interpreter because the handler *might* block -- we don't
356          * know what it will do, so we can't hold the lock on the intepreter.
357          */
358         AcpiExExitInterpreter();
359     }
360 
361     /* Call the handler */
362 
363     Status = Handler (Function,
364         (RegionObj->Region.Address + RegionOffset), BitWidth, Value,
365         Context, RegionObj2->Extra.RegionContext);
366 
367     if (ACPI_FAILURE (Status))
368     {
369         ACPI_EXCEPTION ((AE_INFO, Status, "Returned by Handler for [%s]",
370             AcpiUtGetRegionName (RegionObj->Region.SpaceId)));
371     }
372 
373     if (!(HandlerDesc->AddressSpace.HandlerFlags &
374             ACPI_ADDR_HANDLER_DEFAULT_INSTALLED))
375     {
376         /*
377          * We just returned from a non-default handler, we must re-enter the
378          * interpreter
379          */
380        AcpiExEnterInterpreter ();
381     }
382 
383     return_ACPI_STATUS (Status);
384 }
385 
386 
387 /*******************************************************************************
388  *
389  * FUNCTION:    AcpiEvDetachRegion
390  *
391  * PARAMETERS:  RegionObj           - Region Object
392  *              AcpiNsIsLocked      - Namespace Region Already Locked?
393  *
394  * RETURN:      None
395  *
396  * DESCRIPTION: Break the association between the handler and the region
397  *              this is a two way association.
398  *
399  ******************************************************************************/
400 
401 void
402 AcpiEvDetachRegion(
403     ACPI_OPERAND_OBJECT     *RegionObj,
404     BOOLEAN                 AcpiNsIsLocked)
405 {
406     ACPI_OPERAND_OBJECT     *HandlerObj;
407     ACPI_OPERAND_OBJECT     *ObjDesc;
408     ACPI_OPERAND_OBJECT     *StartDesc;
409     ACPI_OPERAND_OBJECT     **LastObjPtr;
410     ACPI_ADR_SPACE_SETUP    RegionSetup;
411     void                    **RegionContext;
412     ACPI_OPERAND_OBJECT     *RegionObj2;
413     ACPI_STATUS             Status;
414 
415 
416     ACPI_FUNCTION_TRACE (EvDetachRegion);
417 
418 
419     RegionObj2 = AcpiNsGetSecondaryObject (RegionObj);
420     if (!RegionObj2)
421     {
422         return_VOID;
423     }
424     RegionContext = &RegionObj2->Extra.RegionContext;
425 
426     /* Get the address handler from the region object */
427 
428     HandlerObj = RegionObj->Region.Handler;
429     if (!HandlerObj)
430     {
431         /* This region has no handler, all done */
432 
433         return_VOID;
434     }
435 
436     /* Find this region in the handler's list */
437 
438     ObjDesc = HandlerObj->AddressSpace.RegionList;
439     StartDesc = ObjDesc;
440     LastObjPtr = &HandlerObj->AddressSpace.RegionList;
441 
442     while (ObjDesc)
443     {
444         /* Is this the correct Region? */
445 
446         if (ObjDesc == RegionObj)
447         {
448             ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION,
449                 "Removing Region %p from address handler %p\n",
450                 RegionObj, HandlerObj));
451 
452             /* This is it, remove it from the handler's list */
453 
454             *LastObjPtr = ObjDesc->Region.Next;
455             ObjDesc->Region.Next = NULL;        /* Must clear field */
456 
457             if (AcpiNsIsLocked)
458             {
459                 Status = AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
460                 if (ACPI_FAILURE (Status))
461                 {
462                     return_VOID;
463                 }
464             }
465 
466             /* Now stop region accesses by executing the _REG method */
467 
468             Status = AcpiEvExecuteRegMethod (RegionObj, ACPI_REG_DISCONNECT);
469             if (ACPI_FAILURE (Status))
470             {
471                 ACPI_EXCEPTION ((AE_INFO, Status, "from region _REG, [%s]",
472                     AcpiUtGetRegionName (RegionObj->Region.SpaceId)));
473             }
474 
475             if (AcpiNsIsLocked)
476             {
477                 Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
478                 if (ACPI_FAILURE (Status))
479                 {
480                     return_VOID;
481                 }
482             }
483 
484             /*
485              * If the region has been activated, call the setup handler with
486              * the deactivate notification
487              */
488             if (RegionObj->Region.Flags & AOPOBJ_SETUP_COMPLETE)
489             {
490                 RegionSetup = HandlerObj->AddressSpace.Setup;
491                 Status = RegionSetup (RegionObj, ACPI_REGION_DEACTIVATE,
492                     HandlerObj->AddressSpace.Context, RegionContext);
493 
494                 /*
495                  * RegionContext should have been released by the deactivate
496                  * operation. We don't need access to it anymore here.
497                  */
498                 if (RegionContext)
499                 {
500                     *RegionContext = NULL;
501                 }
502 
503                 /* Init routine may fail, Just ignore errors */
504 
505                 if (ACPI_FAILURE (Status))
506                 {
507                     ACPI_EXCEPTION ((AE_INFO, Status,
508                         "from region handler - deactivate, [%s]",
509                         AcpiUtGetRegionName (RegionObj->Region.SpaceId)));
510                 }
511 
512                 RegionObj->Region.Flags &= ~(AOPOBJ_SETUP_COMPLETE);
513             }
514 
515             /*
516              * Remove handler reference in the region
517              *
518              * NOTE: this doesn't mean that the region goes away, the region
519              * is just inaccessible as indicated to the _REG method
520              *
521              * If the region is on the handler's list, this must be the
522              * region's handler
523              */
524             RegionObj->Region.Handler = NULL;
525             AcpiUtRemoveReference (HandlerObj);
526 
527             return_VOID;
528         }
529 
530         /* Walk the linked list of handlers */
531 
532         LastObjPtr = &ObjDesc->Region.Next;
533         ObjDesc = ObjDesc->Region.Next;
534 
535         /* Prevent infinite loop if list is corrupted */
536 
537         if (ObjDesc == StartDesc)
538         {
539             ACPI_ERROR ((AE_INFO,
540                 "Circular handler list in region object %p",
541                 RegionObj));
542             return_VOID;
543         }
544     }
545 
546     /* If we get here, the region was not in the handler's region list */
547 
548     ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION,
549         "Cannot remove region %p from address handler %p\n",
550         RegionObj, HandlerObj));
551 
552     return_VOID;
553 }
554 
555 
556 /*******************************************************************************
557  *
558  * FUNCTION:    AcpiEvAttachRegion
559  *
560  * PARAMETERS:  HandlerObj          - Handler Object
561  *              RegionObj           - Region Object
562  *              AcpiNsIsLocked      - Namespace Region Already Locked?
563  *
564  * RETURN:      None
565  *
566  * DESCRIPTION: Create the association between the handler and the region
567  *              this is a two way association.
568  *
569  ******************************************************************************/
570 
571 ACPI_STATUS
572 AcpiEvAttachRegion (
573     ACPI_OPERAND_OBJECT     *HandlerObj,
574     ACPI_OPERAND_OBJECT     *RegionObj,
575     BOOLEAN                 AcpiNsIsLocked)
576 {
577 
578     ACPI_FUNCTION_TRACE (EvAttachRegion);
579 
580 
581     ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION,
582         "Adding Region [%4.4s] %p to address handler %p [%s]\n",
583         AcpiUtGetNodeName (RegionObj->Region.Node),
584         RegionObj, HandlerObj,
585         AcpiUtGetRegionName (RegionObj->Region.SpaceId)));
586 
587     /* Link this region to the front of the handler's list */
588 
589     RegionObj->Region.Next = HandlerObj->AddressSpace.RegionList;
590     HandlerObj->AddressSpace.RegionList = RegionObj;
591 
592     /* Install the region's handler */
593 
594     if (RegionObj->Region.Handler)
595     {
596         return_ACPI_STATUS (AE_ALREADY_EXISTS);
597     }
598 
599     RegionObj->Region.Handler = HandlerObj;
600     AcpiUtAddReference (HandlerObj);
601 
602     return_ACPI_STATUS (AE_OK);
603 }
604 
605 
606 /*******************************************************************************
607  *
608  * FUNCTION:    AcpiEvExecuteRegMethod
609  *
610  * PARAMETERS:  RegionObj           - Region object
611  *              Function            - Passed to _REG: On (1) or Off (0)
612  *
613  * RETURN:      Status
614  *
615  * DESCRIPTION: Execute _REG method for a region
616  *
617  ******************************************************************************/
618 
619 ACPI_STATUS
620 AcpiEvExecuteRegMethod (
621     ACPI_OPERAND_OBJECT     *RegionObj,
622     UINT32                  Function)
623 {
624     ACPI_EVALUATE_INFO      *Info;
625     ACPI_OPERAND_OBJECT     *Args[3];
626     ACPI_OPERAND_OBJECT     *RegionObj2;
627     ACPI_STATUS             Status;
628 
629 
630     ACPI_FUNCTION_TRACE (EvExecuteRegMethod);
631 
632 
633     RegionObj2 = AcpiNsGetSecondaryObject (RegionObj);
634     if (!RegionObj2)
635     {
636         return_ACPI_STATUS (AE_NOT_EXIST);
637     }
638 
639     if (RegionObj2->Extra.Method_REG == NULL)
640     {
641         return_ACPI_STATUS (AE_OK);
642     }
643 
644     /* Allocate and initialize the evaluation information block */
645 
646     Info = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_EVALUATE_INFO));
647     if (!Info)
648     {
649         return_ACPI_STATUS (AE_NO_MEMORY);
650     }
651 
652     Info->PrefixNode = RegionObj2->Extra.Method_REG;
653     Info->RelativePathname = NULL;
654     Info->Parameters = Args;
655     Info->Flags = ACPI_IGNORE_RETURN_VALUE;
656 
657     /*
658      * The _REG method has two arguments:
659      *
660      * Arg0 - Integer:
661      *  Operation region space ID Same value as RegionObj->Region.SpaceId
662      *
663      * Arg1 - Integer:
664      *  connection status 1 for connecting the handler, 0 for disconnecting
665      *  the handler (Passed as a parameter)
666      */
667     Args[0] = AcpiUtCreateIntegerObject ((UINT64) RegionObj->Region.SpaceId);
668     if (!Args[0])
669     {
670         Status = AE_NO_MEMORY;
671         goto Cleanup1;
672     }
673 
674     Args[1] = AcpiUtCreateIntegerObject ((UINT64) Function);
675     if (!Args[1])
676     {
677         Status = AE_NO_MEMORY;
678         goto Cleanup2;
679     }
680 
681     Args[2] = NULL; /* Terminate list */
682 
683     /* Execute the method, no return value */
684 
685     ACPI_DEBUG_EXEC (
686         AcpiUtDisplayInitPathname (ACPI_TYPE_METHOD, Info->PrefixNode, NULL));
687 
688     Status = AcpiNsEvaluate (Info);
689     AcpiUtRemoveReference (Args[1]);
690 
691 Cleanup2:
692     AcpiUtRemoveReference (Args[0]);
693 
694 Cleanup1:
695     ACPI_FREE (Info);
696     return_ACPI_STATUS (Status);
697 }
698 
699 
700 /*******************************************************************************
701  *
702  * FUNCTION:    AcpiEvExecuteRegMethods
703  *
704  * PARAMETERS:  Node            - Namespace node for the device
705  *              SpaceId         - The address space ID
706  *
707  * RETURN:      Status
708  *
709  * DESCRIPTION: Run all _REG methods for the input Space ID;
710  *              Note: assumes namespace is locked, or system init time.
711  *
712  ******************************************************************************/
713 
714 ACPI_STATUS
715 AcpiEvExecuteRegMethods (
716     ACPI_NAMESPACE_NODE     *Node,
717     ACPI_ADR_SPACE_TYPE     SpaceId)
718 {
719     ACPI_STATUS             Status;
720 
721 
722     ACPI_FUNCTION_TRACE (EvExecuteRegMethods);
723 
724 
725     /*
726      * Run all _REG methods for all Operation Regions for this space ID. This
727      * is a separate walk in order to handle any interdependencies between
728      * regions and _REG methods. (i.e. handlers must be installed for all
729      * regions of this Space ID before we can run any _REG methods)
730      */
731     Status = AcpiNsWalkNamespace (ACPI_TYPE_ANY, Node, ACPI_UINT32_MAX,
732                 ACPI_NS_WALK_UNLOCK, AcpiEvRegRun, NULL,
733                 &SpaceId, NULL);
734 
735     /* Special case for EC: handle "orphan" _REG methods with no region */
736 
737     if (SpaceId == ACPI_ADR_SPACE_EC)
738     {
739         AcpiEvOrphanEcRegMethod (Node);
740     }
741 
742     return_ACPI_STATUS (Status);
743 }
744 
745 
746 /*******************************************************************************
747  *
748  * FUNCTION:    AcpiEvRegRun
749  *
750  * PARAMETERS:  WalkNamespace callback
751  *
752  * DESCRIPTION: Run _REG method for region objects of the requested spaceID
753  *
754  ******************************************************************************/
755 
756 static ACPI_STATUS
757 AcpiEvRegRun (
758     ACPI_HANDLE             ObjHandle,
759     UINT32                  Level,
760     void                    *Context,
761     void                    **ReturnValue)
762 {
763     ACPI_OPERAND_OBJECT     *ObjDesc;
764     ACPI_NAMESPACE_NODE     *Node;
765     ACPI_ADR_SPACE_TYPE     SpaceId;
766     ACPI_STATUS             Status;
767 
768 
769     SpaceId = *ACPI_CAST_PTR (ACPI_ADR_SPACE_TYPE, Context);
770 
771     /* Convert and validate the device handle */
772 
773     Node = AcpiNsValidateHandle (ObjHandle);
774     if (!Node)
775     {
776         return (AE_BAD_PARAMETER);
777     }
778 
779     /*
780      * We only care about regions.and objects that are allowed to have address
781      * space handlers
782      */
783     if ((Node->Type != ACPI_TYPE_REGION) &&
784         (Node != AcpiGbl_RootNode))
785     {
786         return (AE_OK);
787     }
788 
789     /* Check for an existing internal object */
790 
791     ObjDesc = AcpiNsGetAttachedObject (Node);
792     if (!ObjDesc)
793     {
794         /* No object, just exit */
795 
796         return (AE_OK);
797     }
798 
799     /* Object is a Region */
800 
801     if (ObjDesc->Region.SpaceId != SpaceId)
802     {
803         /* This region is for a different address space, just ignore it */
804 
805         return (AE_OK);
806     }
807 
808     Status = AcpiEvExecuteRegMethod (ObjDesc, ACPI_REG_CONNECT);
809     return (Status);
810 }
811 
812 
813 /*******************************************************************************
814  *
815  * FUNCTION:    AcpiEvOrphanEcRegMethod
816  *
817  * PARAMETERS:  EcDeviceNode        - Namespace node for an EC device
818  *
819  * RETURN:      None
820  *
821  * DESCRIPTION: Execute an "orphan" _REG method that appears under the EC
822  *              device. This is a _REG method that has no corresponding region
823  *              within the EC device scope. The orphan _REG method appears to
824  *              have been enabled by the description of the ECDT in the ACPI
825  *              specification: "The availability of the region space can be
826  *              detected by providing a _REG method object underneath the
827  *              Embedded Controller device."
828  *
829  *              To quickly access the EC device, we use the EcDeviceNode used
830  *              during EC handler installation. Otherwise, we would need to
831  *              perform a time consuming namespace walk, executing _HID
832  *              methods to find the EC device.
833  *
834  *  MUTEX:      Assumes the namespace is locked
835  *
836  ******************************************************************************/
837 
838 static void
839 AcpiEvOrphanEcRegMethod (
840     ACPI_NAMESPACE_NODE     *EcDeviceNode)
841 {
842     ACPI_HANDLE             RegMethod;
843     ACPI_NAMESPACE_NODE     *NextNode;
844     ACPI_STATUS             Status;
845     ACPI_OBJECT_LIST        Args;
846     ACPI_OBJECT             Objects[2];
847 
848 
849     ACPI_FUNCTION_TRACE (EvOrphanEcRegMethod);
850 
851 
852     if (!EcDeviceNode)
853     {
854         return_VOID;
855     }
856 
857     /* Namespace is currently locked, must release */
858 
859     (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
860 
861     /* Get a handle to a _REG method immediately under the EC device */
862 
863     Status = AcpiGetHandle (EcDeviceNode, METHOD_NAME__REG, &RegMethod);
864     if (ACPI_FAILURE (Status))
865     {
866         goto Exit; /* There is no _REG method present */
867     }
868 
869     /*
870      * Execute the _REG method only if there is no Operation Region in
871      * this scope with the Embedded Controller space ID. Otherwise, it
872      * will already have been executed. Note, this allows for Regions
873      * with other space IDs to be present; but the code below will then
874      * execute the _REG method with the EmbeddedControl SpaceID argument.
875      */
876     NextNode = AcpiNsGetNextNode (EcDeviceNode, NULL);
877     while (NextNode)
878     {
879         if ((NextNode->Type == ACPI_TYPE_REGION) &&
880             (NextNode->Object) &&
881             (NextNode->Object->Region.SpaceId == ACPI_ADR_SPACE_EC))
882         {
883             goto Exit; /* Do not execute the _REG */
884         }
885 
886         NextNode = AcpiNsGetNextNode (EcDeviceNode, NextNode);
887     }
888 
889     /* Evaluate the _REG(EmbeddedControl,Connect) method */
890 
891     Args.Count = 2;
892     Args.Pointer = Objects;
893     Objects[0].Type = ACPI_TYPE_INTEGER;
894     Objects[0].Integer.Value = ACPI_ADR_SPACE_EC;
895     Objects[1].Type = ACPI_TYPE_INTEGER;
896     Objects[1].Integer.Value = ACPI_REG_CONNECT;
897 
898     Status = AcpiEvaluateObject (RegMethod, NULL, &Args, NULL);
899 
900 Exit:
901     /* We ignore all errors from above, don't care */
902 
903     Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
904     return_VOID;
905 }
906