nsinit.c revision 281075
189051Sjake/******************************************************************************
289051Sjake *
389051Sjake * Module Name: nsinit - namespace initialization
489051Sjake *
589051Sjake *****************************************************************************/
689051Sjake
789051Sjake/*
889051Sjake * Copyright (C) 2000 - 2015, Intel Corp.
989051Sjake * All rights reserved.
1089051Sjake *
1189051Sjake * Redistribution and use in source and binary forms, with or without
1289051Sjake * modification, are permitted provided that the following conditions
1389051Sjake * are met:
1489051Sjake * 1. Redistributions of source code must retain the above copyright
1589051Sjake *    notice, this list of conditions, and the following disclaimer,
1689051Sjake *    without modification.
1789051Sjake * 2. Redistributions in binary form must reproduce at minimum a disclaimer
1889051Sjake *    substantially similar to the "NO WARRANTY" disclaimer below
1989051Sjake *    ("Disclaimer") and any redistribution must be conditioned upon
2089051Sjake *    including a substantially similar Disclaimer requirement for further
2189051Sjake *    binary redistribution.
2289051Sjake * 3. Neither the names of the above-listed copyright holders nor the names
2389051Sjake *    of any contributors may be used to endorse or promote products derived
2489051Sjake *    from this software without specific prior written permission.
2589051Sjake *
2689051Sjake * Alternatively, this software may be distributed under the terms of the
2789051Sjake * GNU General Public License ("GPL") version 2 as published by the Free
2889051Sjake * Software Foundation.
2989051Sjake *
3089051Sjake * NO WARRANTY
3189051Sjake * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32211050Smarius * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
3389051Sjake * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
3489051Sjake * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
3589051Sjake * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
3689051Sjake * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
3789051Sjake * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
3889051Sjake * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
3989051Sjake * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
4089051Sjake * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
4189051Sjake * POSSIBILITY OF SUCH DAMAGES.
4289051Sjake */
4389051Sjake
4489051Sjake#include <contrib/dev/acpica/include/acpi.h>
4589051Sjake#include <contrib/dev/acpica/include/accommon.h>
4689051Sjake#include <contrib/dev/acpica/include/acnamesp.h>
4789051Sjake#include <contrib/dev/acpica/include/acdispat.h>
4889051Sjake#include <contrib/dev/acpica/include/acinterp.h>
4989051Sjake
5089051Sjake#define _COMPONENT          ACPI_NAMESPACE
5189051Sjake        ACPI_MODULE_NAME    ("nsinit")
5289051Sjake
5389051Sjake/* Local prototypes */
5489051Sjake
5589051Sjakestatic ACPI_STATUS
5689051SjakeAcpiNsInitOneObject (
57145150Smarius    ACPI_HANDLE             ObjHandle,
58145150Smarius    UINT32                  Level,
59145150Smarius    void                    *Context,
6089051Sjake    void                    **ReturnValue);
6189051Sjake
6289051Sjakestatic ACPI_STATUS
63131950SmarcelAcpiNsInitOneDevice (
6489051Sjake    ACPI_HANDLE             ObjHandle,
6589051Sjake    UINT32                  NestingLevel,
6689051Sjake    void                    *Context,
6789051Sjake    void                    **ReturnValue);
6889051Sjake
69170846Smariusstatic ACPI_STATUS
7089051SjakeAcpiNsFindIniMethods (
7189051Sjake    ACPI_HANDLE             ObjHandle,
7289051Sjake    UINT32                  NestingLevel,
7389051Sjake    void                    *Context,
7489051Sjake    void                    **ReturnValue);
7589051Sjake
7689051Sjake
7789051Sjake/*******************************************************************************
7889051Sjake *
7989051Sjake * FUNCTION:    AcpiNsInitializeObjects
8089051Sjake *
8189051Sjake * PARAMETERS:  None
8292205Sjake *
83119696Smarcel * RETURN:      Status
84182730Smarius *
85285839Smarius * DESCRIPTION: Walk the entire namespace and perform any necessary
8689051Sjake *              initialization on the objects found therein
8797511Sjake *
8892205Sjake ******************************************************************************/
89152022Sjhb
9089051SjakeACPI_STATUS
9195132SjakeAcpiNsInitializeObjects (
9291617Sjake    void)
93216803Smarius{
9489051Sjake    ACPI_STATUS             Status;
95170846Smarius    ACPI_INIT_WALK_INFO     Info;
9689051Sjake
97183142Smarius
98183142Smarius    ACPI_FUNCTION_TRACE (NsInitializeObjects);
99183142Smarius
10089051Sjake
101210601Smav    ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
102178048Smarius        "**** Starting initialization of namespace objects ****\n"));
10389051Sjake    ACPI_DEBUG_PRINT_RAW ((ACPI_DB_INIT,
10489051Sjake        "Completing Region/Field/Buffer/Package initialization:\n"));
10589051Sjake
10689051Sjake    /* Set all init info to zero */
107169796Smarius
108169796Smarius    ACPI_MEMSET (&Info, 0, sizeof (ACPI_INIT_WALK_INFO));
10989051Sjake
11089051Sjake    /* Walk entire namespace from the supplied root */
111182730Smarius
11297001Sjake    Status = AcpiWalkNamespace (ACPI_TYPE_ANY, ACPI_ROOT_OBJECT,
113211071Smarius                ACPI_UINT32_MAX, AcpiNsInitOneObject, NULL,
11491783Sjake                &Info, NULL);
115152022Sjhb    if (ACPI_FAILURE (Status))
11689051Sjake    {
117285839Smarius        ACPI_EXCEPTION ((AE_INFO, Status, "During WalkNamespace"));
118285839Smarius    }
119170846Smarius
120211050Smarius    ACPI_DEBUG_PRINT_RAW ((ACPI_DB_INIT,
12191617Sjake        "    Initialized %u/%u Regions %u/%u Fields %u/%u "
122170846Smarius        "Buffers %u/%u Packages (%u nodes)\n",
123291121Smarius        Info.OpRegionInit,  Info.OpRegionCount,
124222813Sattilio        Info.FieldInit,     Info.FieldCount,
125291121Smarius        Info.BufferInit,    Info.BufferCount,
126291121Smarius        Info.PackageInit,   Info.PackageCount, Info.ObjectCount));
12792205Sjake
128204152Smarius    ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
129204152Smarius        "%u Control Methods found\n%u Op Regions found\n",
130169796Smarius        Info.MethodCount, Info.OpRegionCount));
131203838Smarius
132204152Smarius    return_ACPI_STATUS (AE_OK);
133169796Smarius}
134169796Smarius
135170846Smarius
136211050Smarius/*******************************************************************************
137211050Smarius *
138211050Smarius * FUNCTION:    AcpiNsInitializeDevices
139170846Smarius *
140211050Smarius * PARAMETERS:  None
141170846Smarius *
14291617Sjake * RETURN:      ACPI_STATUS
14391617Sjake *
144170846Smarius * DESCRIPTION: Walk the entire namespace and initialize all ACPI devices.
145285839Smarius *              This means running _INI on all present devices.
14691617Sjake *
14791617Sjake *              Note: We install PCI config space handler on region access,
14891617Sjake *              not here.
14991617Sjake *
150170846Smarius ******************************************************************************/
151170846Smarius
152169796SmariusACPI_STATUS
153170846SmariusAcpiNsInitializeDevices (
154170846Smarius    void)
155170846Smarius{
156170846Smarius    ACPI_STATUS             Status;
15797511Sjake    ACPI_DEVICE_WALK_INFO   Info;
158102042Sjake
15997511Sjake
16097511Sjake    ACPI_FUNCTION_TRACE (NsInitializeDevices);
16197511Sjake
162170846Smarius
163170846Smarius    /* Init counters */
16491617Sjake
16591617Sjake    Info.DeviceCount = 0;
166203838Smarius    Info.Num_STA = 0;
167204152Smarius    Info.Num_INI = 0;
168204152Smarius
169203838Smarius    ACPI_DEBUG_PRINT_RAW ((ACPI_DB_INIT,
170291121Smarius        "Initializing Device/Processor/Thermal objects "
171203838Smarius        "and executing _INI/_STA methods:\n"));
172291121Smarius
173211050Smarius    /* Tree analysis: find all subtrees that contain _INI methods */
174203838Smarius
175291121Smarius    Status = AcpiNsWalkNamespace (ACPI_TYPE_ANY, ACPI_ROOT_OBJECT,
176203838Smarius                ACPI_UINT32_MAX, FALSE, AcpiNsFindIniMethods, NULL, &Info, NULL);
177203838Smarius    if (ACPI_FAILURE (Status))
178203838Smarius    {
179203838Smarius        goto ErrorExit;
180203838Smarius    }
181203838Smarius
182203838Smarius    /* Allocate the evaluation information block */
183203838Smarius
184203838Smarius    Info.EvaluateInfo = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_EVALUATE_INFO));
185203838Smarius    if (!Info.EvaluateInfo)
186203838Smarius    {
187203838Smarius        Status = AE_NO_MEMORY;
188204152Smarius        goto ErrorExit;
189204152Smarius    }
190204152Smarius
191204152Smarius    /*
192291121Smarius     * Execute the "global" _INI method that may appear at the root. This
193291121Smarius     * support is provided for Windows compatibility (Vista+) and is not
194291121Smarius     * part of the ACPI specification.
195204152Smarius     */
196291121Smarius    Info.EvaluateInfo->PrefixNode = AcpiGbl_RootNode;
197203838Smarius    Info.EvaluateInfo->RelativePathname = METHOD_NAME__INI;
198291121Smarius    Info.EvaluateInfo->Parameters = NULL;
199203838Smarius    Info.EvaluateInfo->Flags = ACPI_IGNORE_RETURN_VALUE;
200203838Smarius
201203838Smarius    Status = AcpiNsEvaluate (Info.EvaluateInfo);
202203838Smarius    if (ACPI_SUCCESS (Status))
20389051Sjake    {
204169796Smarius        Info.Num_INI++;
20589051Sjake    }
206122947Sjhb
207285839Smarius    /* Walk namespace to execute all _INIs on present devices */
20889051Sjake
20989051Sjake    Status = AcpiNsWalkNamespace (ACPI_TYPE_ANY, ACPI_ROOT_OBJECT,
210222813Sattilio                ACPI_UINT32_MAX, FALSE, AcpiNsInitOneDevice, NULL, &Info, NULL);
21189051Sjake
21289051Sjake    /*
213203838Smarius     * Any _OSI requests should be completed by now. If the BIOS has
214291121Smarius     * requested any Windows OSI strings, we will always truncate
215291121Smarius     * I/O addresses to 16 bits -- for Windows compatibility.
21689051Sjake     */
21789051Sjake    if (AcpiGbl_OsiData >= ACPI_OSI_WIN_2000)
218203838Smarius    {
219204152Smarius        AcpiGbl_TruncateIoAddresses = TRUE;
220203838Smarius    }
221203838Smarius
222291121Smarius    ACPI_FREE (Info.EvaluateInfo);
223203838Smarius    if (ACPI_FAILURE (Status))
224203838Smarius    {
225122947Sjhb        goto ErrorExit;
226122947Sjhb    }
227122947Sjhb
228122947Sjhb    ACPI_DEBUG_PRINT_RAW ((ACPI_DB_INIT,
229123126Sjhb        "    Executed %u _INI methods requiring %u _STA executions "
230122947Sjhb        "(examined %u objects)\n",
231122947Sjhb        Info.Num_INI, Info.Num_STA, Info.DeviceCount));
232176734Sjeff
233176734Sjeff    return_ACPI_STATUS (Status);
234176734Sjeff
235176734Sjeff
236176994SmariusErrorExit:
237176734Sjeff    ACPI_EXCEPTION ((AE_INFO, Status, "During device initialization"));
238176734Sjeff    return_ACPI_STATUS (Status);
23991617Sjake}
24091617Sjake
24191617Sjake
24291617Sjake/*******************************************************************************
24391617Sjake *
24491617Sjake * FUNCTION:    AcpiNsInitOneObject
24591617Sjake *
24691617Sjake * PARAMETERS:  ObjHandle       - Node
24791617Sjake *              Level           - Current nesting level
24891617Sjake *              Context         - Points to a init info struct
24991617Sjake *              ReturnValue     - Not used
250183142Smarius *
25191617Sjake * RETURN:      Status
25291617Sjake *
25391617Sjake * DESCRIPTION: Callback from AcpiWalkNamespace. Invoked for every object
25491617Sjake *              within the  namespace.
25591617Sjake *
25691617Sjake *              Currently, the only objects that require initialization are:
257186347Snwhitehorn *              1) Methods
25891617Sjake *              2) Op Regions
25991617Sjake *
26089051Sjake ******************************************************************************/
26189051Sjake
26289051Sjakestatic ACPI_STATUS
26389051SjakeAcpiNsInitOneObject (
26489051Sjake    ACPI_HANDLE             ObjHandle,
26589051Sjake    UINT32                  Level,
266285839Smarius    void                    *Context,
26789051Sjake    void                    **ReturnValue)
268285839Smarius{
269285839Smarius    ACPI_OBJECT_TYPE        Type;
270285839Smarius    ACPI_STATUS             Status = AE_OK;
271285839Smarius    ACPI_INIT_WALK_INFO     *Info = (ACPI_INIT_WALK_INFO *) Context;
272285839Smarius    ACPI_NAMESPACE_NODE     *Node = (ACPI_NAMESPACE_NODE *) ObjHandle;
273285839Smarius    ACPI_OPERAND_OBJECT     *ObjDesc;
274285839Smarius
275285839Smarius
276285839Smarius    ACPI_FUNCTION_NAME (NsInitOneObject);
277285839Smarius
278285839Smarius
279285839Smarius    Info->ObjectCount++;
280285839Smarius
281285839Smarius    /* And even then, we are only interested in a few object types */
282285839Smarius
283285839Smarius    Type = AcpiNsGetType (ObjHandle);
284285839Smarius    ObjDesc = AcpiNsGetAttachedObject (Node);
285285839Smarius    if (!ObjDesc)
28689051Sjake    {
28789051Sjake        return (AE_OK);
28889051Sjake    }
28989051Sjake
290178048Smarius    /* Increment counters for object types we are looking for */
291210601Smav
29289051Sjake    switch (Type)
293169796Smarius    {
294157240Smarius    case ACPI_TYPE_REGION:
295203838Smarius
296203838Smarius        Info->OpRegionCount++;
297203838Smarius        break;
298203838Smarius
299203838Smarius    case ACPI_TYPE_BUFFER_FIELD:
300203838Smarius
301203838Smarius        Info->FieldCount++;
302204152Smarius        break;
303203838Smarius
304203838Smarius    case ACPI_TYPE_LOCAL_BANK_FIELD:
305203838Smarius
306203838Smarius        Info->FieldCount++;
307203838Smarius        break;
308203838Smarius
309204152Smarius    case ACPI_TYPE_BUFFER:
310203838Smarius
311291121Smarius        Info->BufferCount++;
312203838Smarius        break;
313203838Smarius
314203838Smarius    case ACPI_TYPE_PACKAGE:
315204152Smarius
316203838Smarius        Info->PackageCount++;
317214071Smarius        break;
318203838Smarius
31989051Sjake    default:
320203838Smarius
321203838Smarius        /* No init required, just exit now */
322203838Smarius
323203838Smarius        return (AE_OK);
324203838Smarius    }
325203838Smarius
326203838Smarius    /* If the object is already initialized, nothing else to do */
327207537Smarius
328207537Smarius    if (ObjDesc->Common.Flags & AOPOBJ_DATA_VALID)
329203838Smarius    {
33091617Sjake        return (AE_OK);
33191617Sjake    }
332203838Smarius
333203838Smarius    /* Must lock the interpreter before executing AML code */
334203838Smarius
335203838Smarius    AcpiExEnterInterpreter ();
336203838Smarius
337203838Smarius    /*
33891617Sjake     * Each of these types can contain executable AML code within the
339291121Smarius     * declaration.
340203838Smarius     */
341203838Smarius    switch (Type)
34291617Sjake    {
343254025Sjeff    case ACPI_TYPE_REGION:
344254025Sjeff
345203838Smarius        Info->OpRegionInit++;
346203838Smarius        Status = AcpiDsGetRegionArguments (ObjDesc);
347254025Sjeff        break;
348254025Sjeff
349203838Smarius    case ACPI_TYPE_BUFFER_FIELD:
350203838Smarius
351204152Smarius        Info->FieldInit++;
352203838Smarius        Status = AcpiDsGetBufferFieldArguments (ObjDesc);
353203838Smarius        break;
35489051Sjake
355203838Smarius    case ACPI_TYPE_LOCAL_BANK_FIELD:
356182689Smarius
357222813Sattilio        Info->FieldInit++;
358203838Smarius        Status = AcpiDsGetBankFieldArguments (ObjDesc);
35989051Sjake        break;
36089051Sjake
36189051Sjake    case ACPI_TYPE_BUFFER:
36289051Sjake
36389051Sjake        Info->BufferInit++;
364169796Smarius        Status = AcpiDsGetBufferArguments (ObjDesc);
36589051Sjake        break;
36689051Sjake
367169796Smarius    case ACPI_TYPE_PACKAGE:
368285839Smarius
36989051Sjake        Info->PackageInit++;
37091617Sjake        Status = AcpiDsGetPackageArguments (ObjDesc);
37191617Sjake        break;
372169796Smarius
37391617Sjake    default:
374113238Sjake
375181701Smarius        /* No other types can get here */
37691617Sjake
37791617Sjake        break;
37889051Sjake    }
37991783Sjake
38091783Sjake    if (ACPI_FAILURE (Status))
38189051Sjake    {
38291783Sjake        ACPI_EXCEPTION ((AE_INFO, Status,
383222531Snwhitehorn            "Could not execute arguments for [%4.4s] (%s)",
38491617Sjake            AcpiUtGetNodeName (Node), AcpiUtGetTypeName (Type)));
38591617Sjake    }
38691617Sjake
38791617Sjake    /*
38889051Sjake     * We ignore errors from above, and always return OK, since we don't want
389169796Smarius     * to abort the walk on any single error.
39091617Sjake     */
39191617Sjake    AcpiExExitInterpreter ();
392169796Smarius    return (AE_OK);
393169796Smarius}
39491617Sjake
39591617Sjake
39691617Sjake/*******************************************************************************
39791617Sjake *
39891617Sjake * FUNCTION:    AcpiNsFindIniMethods
399169796Smarius *
400102042Sjake * PARAMETERS:  ACPI_WALK_CALLBACK
40191617Sjake *
40291617Sjake * RETURN:      ACPI_STATUS
40391617Sjake *
40491617Sjake * DESCRIPTION: Called during namespace walk. Finds objects named _INI under
40591783Sjake *              device/processor/thermal objects, and marks the entire subtree
40691617Sjake *              with a SUBTREE_HAS_INI flag. This flag is used during the
40791617Sjake *              subsequent device initialization walk to avoid entire subtrees
40891617Sjake *              that do not contain an _INI.
40991617Sjake *
41091617Sjake ******************************************************************************/
41191617Sjake
41291783Sjakestatic ACPI_STATUS
41391783SjakeAcpiNsFindIniMethods (
414169796Smarius    ACPI_HANDLE             ObjHandle,
41591617Sjake    UINT32                  NestingLevel,
41689051Sjake    void                    *Context,
41791617Sjake    void                    **ReturnValue)
41891617Sjake{
41991617Sjake    ACPI_DEVICE_WALK_INFO   *Info = ACPI_CAST_PTR (ACPI_DEVICE_WALK_INFO, Context);
42091617Sjake    ACPI_NAMESPACE_NODE     *Node;
42189051Sjake    ACPI_NAMESPACE_NODE     *ParentNode;
42291617Sjake
423207248Smarius
424207248Smarius    /* Keep count of device/processor/thermal objects */
425223719Smarius
426204152Smarius    Node = ACPI_CAST_PTR (ACPI_NAMESPACE_NODE, ObjHandle);
427223719Smarius    if ((Node->Type == ACPI_TYPE_DEVICE)    ||
428223719Smarius        (Node->Type == ACPI_TYPE_PROCESSOR) ||
429223719Smarius        (Node->Type == ACPI_TYPE_THERMAL))
430207248Smarius    {
431207248Smarius        Info->DeviceCount++;
432207248Smarius        return (AE_OK);
433204152Smarius    }
434207248Smarius
435213868Smarius    /* We are only looking for methods named _INI */
436213868Smarius
437213868Smarius    if (!ACPI_COMPARE_NAME (Node->Name.Ascii, METHOD_NAME__INI))
438213868Smarius    {
439213868Smarius        return (AE_OK);
440213868Smarius    }
441216803Smarius
442216803Smarius    /*
443207248Smarius     * The only _INI methods that we care about are those that are
444216803Smarius     * present under Device, Processor, and Thermal objects.
445216803Smarius     */
446216803Smarius    ParentNode = Node->Parent;
447216803Smarius    switch (ParentNode->Type)
448176994Smarius    {
449176994Smarius    case ACPI_TYPE_DEVICE:
450176994Smarius    case ACPI_TYPE_PROCESSOR:
451176994Smarius    case ACPI_TYPE_THERMAL:
452176994Smarius
453207248Smarius        /* Mark parent and bubble up the INI present flag to the root */
454213868Smarius
455213868Smarius        while (ParentNode)
456213868Smarius        {
457213868Smarius            ParentNode->Flags |= ANOBJ_SUBTREE_HAS_INI;
458213868Smarius            ParentNode = ParentNode->Parent;
459207248Smarius        }
460207248Smarius        break;
46189051Sjake
462169796Smarius    default:
463169796Smarius
46489051Sjake        break;
46591783Sjake    }
46691783Sjake
46791617Sjake    return (AE_OK);
46891783Sjake}
46991617Sjake
47089051Sjake
471285839Smarius/*******************************************************************************
472285839Smarius *
473285839Smarius * FUNCTION:    AcpiNsInitOneDevice
474210601Smav *
475210601Smav * PARAMETERS:  ACPI_WALK_CALLBACK
476210601Smav *
477182020Smarius * RETURN:      ACPI_STATUS
478170303Sjeff *
47989051Sjake * DESCRIPTION: This is called once per device soon after ACPI is enabled
48089051Sjake *              to initialize each device. It determines if the device is
48192205Sjake *              present, and if so, calls _INI.
48292205Sjake *
48392205Sjake ******************************************************************************/
484222813Sattilio
48592205Sjakestatic ACPI_STATUS
48692205SjakeAcpiNsInitOneDevice (
48792205Sjake    ACPI_HANDLE             ObjHandle,
488223346Smarius    UINT32                  NestingLevel,
489223346Smarius    void                    *Context,
490222813Sattilio    void                    **ReturnValue)
491222813Sattilio{
492222813Sattilio    ACPI_DEVICE_WALK_INFO   *WalkInfo = ACPI_CAST_PTR (ACPI_DEVICE_WALK_INFO, Context);
493222813Sattilio    ACPI_EVALUATE_INFO      *Info = WalkInfo->EvaluateInfo;
494222813Sattilio    UINT32                  Flags;
495223346Smarius    ACPI_STATUS             Status;
496222813Sattilio    ACPI_NAMESPACE_NODE     *DeviceNode;
497222813Sattilio
498222813Sattilio
49992205Sjake    ACPI_FUNCTION_TRACE (NsInitOneDevice);
500222813Sattilio
50192205Sjake
50292205Sjake    /* We are interested in Devices, Processors and ThermalZones only */
50392205Sjake
50492205Sjake    DeviceNode = ACPI_CAST_PTR (ACPI_NAMESPACE_NODE, ObjHandle);
50592205Sjake    if ((DeviceNode->Type != ACPI_TYPE_DEVICE)    &&
50692205Sjake        (DeviceNode->Type != ACPI_TYPE_PROCESSOR) &&
50792205Sjake        (DeviceNode->Type != ACPI_TYPE_THERMAL))
50892205Sjake    {
50989051Sjake        return_ACPI_STATUS (AE_OK);
510239864Smarius    }
51189051Sjake
512169796Smarius    /*
51389051Sjake     * Because of an earlier namespace analysis, all subtrees that contain an
51489051Sjake     * _INI method are tagged.
51589051Sjake     *
516239864Smarius     * If this device subtree does not contain any _INI methods, we
51789051Sjake     * can exit now and stop traversing this entire subtree.
518223346Smarius     */
51992205Sjake    if (!(DeviceNode->Flags & ANOBJ_SUBTREE_HAS_INI))
520169796Smarius    {
521222813Sattilio        return_ACPI_STATUS (AE_CTRL_DEPTH);
522169796Smarius    }
523223346Smarius
524223346Smarius    /*
525223346Smarius     * Run _STA to determine if this device is present and functioning. We
526223346Smarius     * must know this information for two important reasons (from ACPI spec):
527223346Smarius     *
528183142Smarius     * 1) We can only run _INI if the device is present.
529183142Smarius     * 2) We must abort the device tree walk on this subtree if the device is
530183142Smarius     *    not present and is not functional (we will not examine the children)
53192205Sjake     *
53292205Sjake     * The _STA method is not required to be present under the device, we
533223346Smarius     * assume the device is present if _STA does not exist.
534223346Smarius     */
535222813Sattilio    ACPI_DEBUG_EXEC (AcpiUtDisplayInitPathname (
536169796Smarius        ACPI_TYPE_METHOD, DeviceNode, METHOD_NAME__STA));
53789051Sjake
53889051Sjake    Status = AcpiUtExecute_STA (DeviceNode, &Flags);
539170846Smarius    if (ACPI_FAILURE (Status))
540285839Smarius    {
541178048Smarius        /* Ignore error and move on to next device */
542178048Smarius
543178048Smarius        return_ACPI_STATUS (AE_OK);
544178048Smarius    }
545178048Smarius
546178048Smarius    /*
547210601Smav     * Flags == -1 means that _STA was not found. In this case, we assume that
548210601Smav     * the device is both present and functional.
549212541Smav     *
550212541Smav     * From the ACPI spec, description of _STA:
551210601Smav     *
552212541Smav     * "If a device object (including the processor object) does not have an
553212541Smav     * _STA object, then OSPM assumes that all of the above bits are set (in
554212541Smav     * other words, the device is present, ..., and functioning)"
555212541Smav     */
556212541Smav    if (Flags != ACPI_UINT32_MAX)
557212541Smav    {
558212541Smav        WalkInfo->Num_STA++;
559212541Smav    }
560212541Smav
561210601Smav    /*
562210601Smav     * Examine the PRESENT and FUNCTIONING status bits
563210601Smav     *
564222813Sattilio     * Note: ACPI spec does not seem to specify behavior for the present but
56589051Sjake     * not functioning case, so we assume functioning if present.
56689051Sjake     */
56789051Sjake    if (!(Flags & ACPI_STA_DEVICE_PRESENT))
568251703Sjeff    {
569222813Sattilio        /* Device is not present, we must examine the Functioning bit */
570222813Sattilio
571211050Smarius        if (Flags & ACPI_STA_DEVICE_FUNCTIONING)
57289051Sjake        {
57389051Sjake            /*
57489051Sjake             * Device is not present but is "functioning". In this case,
575169796Smarius             * we will not run _INI, but we continue to examine the children
576211050Smarius             * of this device.
57789051Sjake             *
578169796Smarius             * From the ACPI spec, description of _STA: (Note - no mention
579157240Smarius             * of whether to run _INI or not on the device in question)
580211050Smarius             *
58189051Sjake             * "_STA may return bit 0 clear (not present) with bit 3 set
58289051Sjake             * (device is functional). This case is used to indicate a valid
583285839Smarius             * device for which no device driver should be loaded (for example,
584211050Smarius             * a bridge device.) Children of this device may be present and
58589051Sjake             * valid. OSPM should continue enumeration below a device whose
586169796Smarius             * _STA returns this bit combination"
587285839Smarius             */
588211050Smarius            return_ACPI_STATUS (AE_OK);
58989051Sjake        }
59091783Sjake        else
59189051Sjake        {
59289051Sjake            /*
59389051Sjake             * Device is not present and is not functioning. We must abort the
594170846Smarius             * walk of this subtree immediately -- don't look at the children
595169796Smarius             * of such a device.
596169796Smarius             *
597157240Smarius             * From the ACPI spec, description of _INI:
598157240Smarius             *
599157240Smarius             * "If the _STA method indicates that the device is not present,
600157240Smarius             * OSPM will not run the _INI and will not examine the children
601157240Smarius             * of the device for _INI methods"
602157240Smarius             */
603157240Smarius            return_ACPI_STATUS (AE_CTRL_DEPTH);
60489051Sjake        }
605157240Smarius    }
606157240Smarius
607169796Smarius    /*
608169796Smarius     * The device is present or is assumed present if no _STA exists.
60989051Sjake     * Run the _INI if it exists (not required to exist)
61091783Sjake     *
611170846Smarius     * Note: We know there is an _INI within this subtree, but it may not be
61289051Sjake     * under this particular device, it may be lower in the branch.
61389051Sjake     */
614190106Smarius    ACPI_DEBUG_EXEC (AcpiUtDisplayInitPathname (
615169796Smarius        ACPI_TYPE_METHOD, DeviceNode, METHOD_NAME__INI));
616169796Smarius
61792205Sjake    ACPI_MEMSET (Info, 0, sizeof (ACPI_EVALUATE_INFO));
618186395Smarius    Info->PrefixNode = DeviceNode;
619186395Smarius    Info->RelativePathname = METHOD_NAME__INI;
62089051Sjake    Info->Parameters = NULL;
62189051Sjake    Info->Flags = ACPI_IGNORE_RETURN_VALUE;
622170846Smarius
623211050Smarius    Status = AcpiNsEvaluate (Info);
624211050Smarius    if (ACPI_SUCCESS (Status))
625211050Smarius    {
626211050Smarius        WalkInfo->Num_INI++;
627211050Smarius    }
628211050Smarius
629211050Smarius#ifdef ACPI_DEBUG_OUTPUT
630285839Smarius    else if (Status != AE_NOT_FOUND)
631211050Smarius    {
632211050Smarius        /* Ignore error and move on to next device */
633211050Smarius
634211050Smarius        char *ScopeName = AcpiNsGetExternalPathname (Info->Node);
635285839Smarius
636211050Smarius        ACPI_EXCEPTION ((AE_INFO, Status, "during %s._INI execution",
637211050Smarius            ScopeName));
638211050Smarius        ACPI_FREE (ScopeName);
639211050Smarius    }
640211050Smarius#endif
641211050Smarius
642211050Smarius    /* Ignore errors from above */
643211050Smarius
644211050Smarius    Status = AE_OK;
645211050Smarius
646211050Smarius    /*
647211050Smarius     * The _INI method has been run if present; call the Global Initialization
648211050Smarius     * Handler for this device.
649211050Smarius     */
650211050Smarius    if (AcpiGbl_InitHandler)
651211050Smarius    {
652211050Smarius        Status = AcpiGbl_InitHandler (DeviceNode, ACPI_INIT_DEVICE_INI);
653211050Smarius    }
654211050Smarius
655211050Smarius    return_ACPI_STATUS (Status);
656211050Smarius}
657211050Smarius