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