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