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