nsinit.c revision 281075
167754Smsmith/******************************************************************************
267754Smsmith *
367754Smsmith * Module Name: nsinit - namespace initialization
467754Smsmith *
567754Smsmith *****************************************************************************/
667754Smsmith
7217365Sjkim/*
8281075Sdim * Copyright (C) 2000 - 2015, Intel Corp.
970243Smsmith * All rights reserved.
1067754Smsmith *
11217365Sjkim * Redistribution and use in source and binary forms, with or without
12217365Sjkim * modification, are permitted provided that the following conditions
13217365Sjkim * are met:
14217365Sjkim * 1. Redistributions of source code must retain the above copyright
15217365Sjkim *    notice, this list of conditions, and the following disclaimer,
16217365Sjkim *    without modification.
17217365Sjkim * 2. Redistributions in binary form must reproduce at minimum a disclaimer
18217365Sjkim *    substantially similar to the "NO WARRANTY" disclaimer below
19217365Sjkim *    ("Disclaimer") and any redistribution must be conditioned upon
20217365Sjkim *    including a substantially similar Disclaimer requirement for further
21217365Sjkim *    binary redistribution.
22217365Sjkim * 3. Neither the names of the above-listed copyright holders nor the names
23217365Sjkim *    of any contributors may be used to endorse or promote products derived
24217365Sjkim *    from this software without specific prior written permission.
2567754Smsmith *
26217365Sjkim * Alternatively, this software may be distributed under the terms of the
27217365Sjkim * GNU General Public License ("GPL") version 2 as published by the Free
28217365Sjkim * Software Foundation.
2967754Smsmith *
30217365Sjkim * NO WARRANTY
31217365Sjkim * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32217365Sjkim * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
33217365Sjkim * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
34217365Sjkim * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
35217365Sjkim * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36217365Sjkim * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37217365Sjkim * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38217365Sjkim * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39217365Sjkim * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
40217365Sjkim * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41217365Sjkim * POSSIBILITY OF SUCH DAMAGES.
42217365Sjkim */
4367754Smsmith
44193341Sjkim#include <contrib/dev/acpica/include/acpi.h>
45193341Sjkim#include <contrib/dev/acpica/include/accommon.h>
46193341Sjkim#include <contrib/dev/acpica/include/acnamesp.h>
47193341Sjkim#include <contrib/dev/acpica/include/acdispat.h>
48193341Sjkim#include <contrib/dev/acpica/include/acinterp.h>
4967754Smsmith
5077424Smsmith#define _COMPONENT          ACPI_NAMESPACE
5191116Smsmith        ACPI_MODULE_NAME    ("nsinit")
5267754Smsmith
53151937Sjkim/* Local prototypes */
5467754Smsmith
55151937Sjkimstatic ACPI_STATUS
56151937SjkimAcpiNsInitOneObject (
57151937Sjkim    ACPI_HANDLE             ObjHandle,
58151937Sjkim    UINT32                  Level,
59151937Sjkim    void                    *Context,
60151937Sjkim    void                    **ReturnValue);
61151937Sjkim
62151937Sjkimstatic ACPI_STATUS
63151937SjkimAcpiNsInitOneDevice (
64151937Sjkim    ACPI_HANDLE             ObjHandle,
65151937Sjkim    UINT32                  NestingLevel,
66151937Sjkim    void                    *Context,
67151937Sjkim    void                    **ReturnValue);
68151937Sjkim
69167802Sjkimstatic ACPI_STATUS
70167802SjkimAcpiNsFindIniMethods (
71167802Sjkim    ACPI_HANDLE             ObjHandle,
72167802Sjkim    UINT32                  NestingLevel,
73167802Sjkim    void                    *Context,
74167802Sjkim    void                    **ReturnValue);
75151937Sjkim
76167802Sjkim
7767754Smsmith/*******************************************************************************
7867754Smsmith *
7967754Smsmith * FUNCTION:    AcpiNsInitializeObjects
8067754Smsmith *
8167754Smsmith * PARAMETERS:  None
8267754Smsmith *
8367754Smsmith * RETURN:      Status
8467754Smsmith *
8567754Smsmith * DESCRIPTION: Walk the entire namespace and perform any necessary
8667754Smsmith *              initialization on the objects found therein
8767754Smsmith *
8867754Smsmith ******************************************************************************/
8967754Smsmith
9067754SmsmithACPI_STATUS
9167754SmsmithAcpiNsInitializeObjects (
9267754Smsmith    void)
9367754Smsmith{
9467754Smsmith    ACPI_STATUS             Status;
9567754Smsmith    ACPI_INIT_WALK_INFO     Info;
9667754Smsmith
9767754Smsmith
98167802Sjkim    ACPI_FUNCTION_TRACE (NsInitializeObjects);
9967754Smsmith
10067754Smsmith
10182367Smsmith    ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
10282367Smsmith        "**** Starting initialization of namespace objects ****\n"));
103138287Smarks    ACPI_DEBUG_PRINT_RAW ((ACPI_DB_INIT,
104245582Sjkim        "Completing Region/Field/Buffer/Package initialization:\n"));
10567754Smsmith
10699146Siwasaki    /* Set all init info to zero */
10767754Smsmith
10899146Siwasaki    ACPI_MEMSET (&Info, 0, sizeof (ACPI_INIT_WALK_INFO));
10967754Smsmith
11067754Smsmith    /* Walk entire namespace from the supplied root */
11167754Smsmith
11267754Smsmith    Status = AcpiWalkNamespace (ACPI_TYPE_ANY, ACPI_ROOT_OBJECT,
113209746Sjkim                ACPI_UINT32_MAX, AcpiNsInitOneObject, NULL,
114209746Sjkim                &Info, NULL);
11567754Smsmith    if (ACPI_FAILURE (Status))
11667754Smsmith    {
117167802Sjkim        ACPI_EXCEPTION ((AE_INFO, Status, "During WalkNamespace"));
11867754Smsmith    }
11967754Smsmith
120114237Snjl    ACPI_DEBUG_PRINT_RAW ((ACPI_DB_INIT,
121245582Sjkim        "    Initialized %u/%u Regions %u/%u Fields %u/%u "
122209746Sjkim        "Buffers %u/%u Packages (%u nodes)\n",
123102550Siwasaki        Info.OpRegionInit,  Info.OpRegionCount,
124102550Siwasaki        Info.FieldInit,     Info.FieldCount,
125102550Siwasaki        Info.BufferInit,    Info.BufferCount,
12699146Siwasaki        Info.PackageInit,   Info.PackageCount, Info.ObjectCount));
127114237Snjl
12882367Smsmith    ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
129281075Sdim        "%u Control Methods found\n%u Op Regions found\n",
130281075Sdim        Info.MethodCount, Info.OpRegionCount));
13167754Smsmith
13267754Smsmith    return_ACPI_STATUS (AE_OK);
13367754Smsmith}
13467754Smsmith
13567754Smsmith
13677424Smsmith/*******************************************************************************
13767754Smsmith *
13867754Smsmith * FUNCTION:    AcpiNsInitializeDevices
13967754Smsmith *
14067754Smsmith * PARAMETERS:  None
14167754Smsmith *
14267754Smsmith * RETURN:      ACPI_STATUS
14367754Smsmith *
14467754Smsmith * DESCRIPTION: Walk the entire namespace and initialize all ACPI devices.
14567754Smsmith *              This means running _INI on all present devices.
14667754Smsmith *
14777424Smsmith *              Note: We install PCI config space handler on region access,
14877424Smsmith *              not here.
14967754Smsmith *
15077424Smsmith ******************************************************************************/
15167754Smsmith
15267754SmsmithACPI_STATUS
15367754SmsmithAcpiNsInitializeDevices (
15473561Smsmith    void)
15567754Smsmith{
15667754Smsmith    ACPI_STATUS             Status;
15767754Smsmith    ACPI_DEVICE_WALK_INFO   Info;
15867754Smsmith
15967754Smsmith
160167802Sjkim    ACPI_FUNCTION_TRACE (NsInitializeDevices);
16167754Smsmith
16267754Smsmith
16399146Siwasaki    /* Init counters */
16499146Siwasaki
16567754Smsmith    Info.DeviceCount = 0;
16667754Smsmith    Info.Num_STA = 0;
16767754Smsmith    Info.Num_INI = 0;
16867754Smsmith
169138287Smarks    ACPI_DEBUG_PRINT_RAW ((ACPI_DB_INIT,
170193267Sjkim        "Initializing Device/Processor/Thermal objects "
171245582Sjkim        "and executing _INI/_STA methods:\n"));
17267754Smsmith
173167802Sjkim    /* Tree analysis: find all subtrees that contain _INI methods */
174167802Sjkim
175167802Sjkim    Status = AcpiNsWalkNamespace (ACPI_TYPE_ANY, ACPI_ROOT_OBJECT,
176199337Sjkim                ACPI_UINT32_MAX, FALSE, AcpiNsFindIniMethods, NULL, &Info, NULL);
177123315Snjl    if (ACPI_FAILURE (Status))
178123315Snjl    {
179167802Sjkim        goto ErrorExit;
180123315Snjl    }
18167754Smsmith
182167802Sjkim    /* Allocate the evaluation information block */
18367754Smsmith
184167802Sjkim    Info.EvaluateInfo = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_EVALUATE_INFO));
185167802Sjkim    if (!Info.EvaluateInfo)
186167802Sjkim    {
187167802Sjkim        Status = AE_NO_MEMORY;
188167802Sjkim        goto ErrorExit;
189167802Sjkim    }
190167802Sjkim
191197104Sjkim    /*
192197104Sjkim     * Execute the "global" _INI method that may appear at the root. This
193197104Sjkim     * support is provided for Windows compatibility (Vista+) and is not
194197104Sjkim     * part of the ACPI specification.
195197104Sjkim     */
196197104Sjkim    Info.EvaluateInfo->PrefixNode = AcpiGbl_RootNode;
197249663Sjkim    Info.EvaluateInfo->RelativePathname = METHOD_NAME__INI;
198197104Sjkim    Info.EvaluateInfo->Parameters = NULL;
199197104Sjkim    Info.EvaluateInfo->Flags = ACPI_IGNORE_RETURN_VALUE;
200197104Sjkim
201197104Sjkim    Status = AcpiNsEvaluate (Info.EvaluateInfo);
202197104Sjkim    if (ACPI_SUCCESS (Status))
203197104Sjkim    {
204197104Sjkim        Info.Num_INI++;
205197104Sjkim    }
206197104Sjkim
207167802Sjkim    /* Walk namespace to execute all _INIs on present devices */
208167802Sjkim
209123315Snjl    Status = AcpiNsWalkNamespace (ACPI_TYPE_ANY, ACPI_ROOT_OBJECT,
210199337Sjkim                ACPI_UINT32_MAX, FALSE, AcpiNsInitOneDevice, NULL, &Info, NULL);
211123315Snjl
212209746Sjkim    /*
213209746Sjkim     * Any _OSI requests should be completed by now. If the BIOS has
214209746Sjkim     * requested any Windows OSI strings, we will always truncate
215209746Sjkim     * I/O addresses to 16 bits -- for Windows compatibility.
216209746Sjkim     */
217209746Sjkim    if (AcpiGbl_OsiData >= ACPI_OSI_WIN_2000)
218209746Sjkim    {
219209746Sjkim        AcpiGbl_TruncateIoAddresses = TRUE;
220209746Sjkim    }
221209746Sjkim
222167802Sjkim    ACPI_FREE (Info.EvaluateInfo);
22367754Smsmith    if (ACPI_FAILURE (Status))
22467754Smsmith    {
225167802Sjkim        goto ErrorExit;
22667754Smsmith    }
22767754Smsmith
228114237Snjl    ACPI_DEBUG_PRINT_RAW ((ACPI_DB_INIT,
229245582Sjkim        "    Executed %u _INI methods requiring %u _STA executions "
230209746Sjkim        "(examined %u objects)\n",
231167802Sjkim        Info.Num_INI, Info.Num_STA, Info.DeviceCount));
23267754Smsmith
23367754Smsmith    return_ACPI_STATUS (Status);
234167802Sjkim
235167802Sjkim
236167802SjkimErrorExit:
237167802Sjkim    ACPI_EXCEPTION ((AE_INFO, Status, "During device initialization"));
238167802Sjkim    return_ACPI_STATUS (Status);
23967754Smsmith}
24067754Smsmith
24167754Smsmith
24267754Smsmith/*******************************************************************************
24367754Smsmith *
24467754Smsmith * FUNCTION:    AcpiNsInitOneObject
24567754Smsmith *
24667754Smsmith * PARAMETERS:  ObjHandle       - Node
24767754Smsmith *              Level           - Current nesting level
24867754Smsmith *              Context         - Points to a init info struct
24967754Smsmith *              ReturnValue     - Not used
25067754Smsmith *
25167754Smsmith * RETURN:      Status
25267754Smsmith *
253241973Sjkim * DESCRIPTION: Callback from AcpiWalkNamespace. Invoked for every object
25467754Smsmith *              within the  namespace.
25567754Smsmith *
25667754Smsmith *              Currently, the only objects that require initialization are:
25767754Smsmith *              1) Methods
25867754Smsmith *              2) Op Regions
25967754Smsmith *
26067754Smsmith ******************************************************************************/
26167754Smsmith
262151937Sjkimstatic ACPI_STATUS
26367754SmsmithAcpiNsInitOneObject (
26467754Smsmith    ACPI_HANDLE             ObjHandle,
26567754Smsmith    UINT32                  Level,
26667754Smsmith    void                    *Context,
26767754Smsmith    void                    **ReturnValue)
26867754Smsmith{
26991116Smsmith    ACPI_OBJECT_TYPE        Type;
270167802Sjkim    ACPI_STATUS             Status = AE_OK;
27167754Smsmith    ACPI_INIT_WALK_INFO     *Info = (ACPI_INIT_WALK_INFO *) Context;
27267754Smsmith    ACPI_NAMESPACE_NODE     *Node = (ACPI_NAMESPACE_NODE *) ObjHandle;
27367754Smsmith    ACPI_OPERAND_OBJECT     *ObjDesc;
27467754Smsmith
27567754Smsmith
276167802Sjkim    ACPI_FUNCTION_NAME (NsInitOneObject);
27782367Smsmith
27882367Smsmith
27967754Smsmith    Info->ObjectCount++;
28067754Smsmith
28167754Smsmith    /* And even then, we are only interested in a few object types */
28267754Smsmith
28367754Smsmith    Type = AcpiNsGetType (ObjHandle);
28487031Smsmith    ObjDesc = AcpiNsGetAttachedObject (Node);
28567754Smsmith    if (!ObjDesc)
28667754Smsmith    {
28767754Smsmith        return (AE_OK);
28867754Smsmith    }
28967754Smsmith
29099146Siwasaki    /* Increment counters for object types we are looking for */
29199146Siwasaki
29299146Siwasaki    switch (Type)
29380062Smsmith    {
29499146Siwasaki    case ACPI_TYPE_REGION:
295250838Sjkim
29699146Siwasaki        Info->OpRegionCount++;
29799146Siwasaki        break;
29899146Siwasaki
29999146Siwasaki    case ACPI_TYPE_BUFFER_FIELD:
300250838Sjkim
30199146Siwasaki        Info->FieldCount++;
30299146Siwasaki        break;
30399146Siwasaki
304193267Sjkim    case ACPI_TYPE_LOCAL_BANK_FIELD:
305250838Sjkim
306193267Sjkim        Info->FieldCount++;
307193267Sjkim        break;
308193267Sjkim
30999146Siwasaki    case ACPI_TYPE_BUFFER:
310250838Sjkim
31199146Siwasaki        Info->BufferCount++;
31299146Siwasaki        break;
31399146Siwasaki
31499146Siwasaki    case ACPI_TYPE_PACKAGE:
315250838Sjkim
31699146Siwasaki        Info->PackageCount++;
31799146Siwasaki        break;
31899146Siwasaki
31999146Siwasaki    default:
32099146Siwasaki
32199146Siwasaki        /* No init required, just exit now */
322250838Sjkim
32380062Smsmith        return (AE_OK);
32480062Smsmith    }
32580062Smsmith
326193267Sjkim    /* If the object is already initialized, nothing else to do */
327193267Sjkim
32899146Siwasaki    if (ObjDesc->Common.Flags & AOPOBJ_DATA_VALID)
32999146Siwasaki    {
33099146Siwasaki        return (AE_OK);
33199146Siwasaki    }
33280062Smsmith
333193267Sjkim    /* Must lock the interpreter before executing AML code */
334193267Sjkim
335167802Sjkim    AcpiExEnterInterpreter ();
33680062Smsmith
33799146Siwasaki    /*
338138287Smarks     * Each of these types can contain executable AML code within the
339138287Smarks     * declaration.
34099146Siwasaki     */
34167754Smsmith    switch (Type)
34267754Smsmith    {
34367754Smsmith    case ACPI_TYPE_REGION:
34467754Smsmith
34567754Smsmith        Info->OpRegionInit++;
34667754Smsmith        Status = AcpiDsGetRegionArguments (ObjDesc);
34767754Smsmith        break;
34867754Smsmith
34977424Smsmith    case ACPI_TYPE_BUFFER_FIELD:
35067754Smsmith
35167754Smsmith        Info->FieldInit++;
35277424Smsmith        Status = AcpiDsGetBufferFieldArguments (ObjDesc);
35399146Siwasaki        break;
35467754Smsmith
355193267Sjkim    case ACPI_TYPE_LOCAL_BANK_FIELD:
356193267Sjkim
357193267Sjkim        Info->FieldInit++;
358193267Sjkim        Status = AcpiDsGetBankFieldArguments (ObjDesc);
359193267Sjkim        break;
360193267Sjkim
36199146Siwasaki    case ACPI_TYPE_BUFFER:
36299146Siwasaki
36399146Siwasaki        Info->BufferInit++;
36499146Siwasaki        Status = AcpiDsGetBufferArguments (ObjDesc);
36567754Smsmith        break;
36667754Smsmith
36799146Siwasaki    case ACPI_TYPE_PACKAGE:
36899146Siwasaki
36999146Siwasaki        Info->PackageInit++;
37099146Siwasaki        Status = AcpiDsGetPackageArguments (ObjDesc);
37167754Smsmith        break;
37299679Siwasaki
37399679Siwasaki    default:
374250838Sjkim
37599679Siwasaki        /* No other types can get here */
376250838Sjkim
37799679Siwasaki        break;
37867754Smsmith    }
37967754Smsmith
38099146Siwasaki    if (ACPI_FAILURE (Status))
38199146Siwasaki    {
382167802Sjkim        ACPI_EXCEPTION ((AE_INFO, Status,
383167802Sjkim            "Could not execute arguments for [%4.4s] (%s)",
384167802Sjkim            AcpiUtGetNodeName (Node), AcpiUtGetTypeName (Type)));
38599146Siwasaki    }
38680062Smsmith
387138287Smarks    /*
388138287Smarks     * We ignore errors from above, and always return OK, since we don't want
389138287Smarks     * to abort the walk on any single error.
39067754Smsmith     */
39180062Smsmith    AcpiExExitInterpreter ();
39267754Smsmith    return (AE_OK);
39367754Smsmith}
39467754Smsmith
39567754Smsmith
39677424Smsmith/*******************************************************************************
39767754Smsmith *
398167802Sjkim * FUNCTION:    AcpiNsFindIniMethods
399167802Sjkim *
400167802Sjkim * PARAMETERS:  ACPI_WALK_CALLBACK
401167802Sjkim *
402167802Sjkim * RETURN:      ACPI_STATUS
403167802Sjkim *
404167802Sjkim * DESCRIPTION: Called during namespace walk. Finds objects named _INI under
405167802Sjkim *              device/processor/thermal objects, and marks the entire subtree
406167802Sjkim *              with a SUBTREE_HAS_INI flag. This flag is used during the
407167802Sjkim *              subsequent device initialization walk to avoid entire subtrees
408167802Sjkim *              that do not contain an _INI.
409167802Sjkim *
410167802Sjkim ******************************************************************************/
411167802Sjkim
412167802Sjkimstatic ACPI_STATUS
413167802SjkimAcpiNsFindIniMethods (
414167802Sjkim    ACPI_HANDLE             ObjHandle,
415167802Sjkim    UINT32                  NestingLevel,
416167802Sjkim    void                    *Context,
417167802Sjkim    void                    **ReturnValue)
418167802Sjkim{
419167802Sjkim    ACPI_DEVICE_WALK_INFO   *Info = ACPI_CAST_PTR (ACPI_DEVICE_WALK_INFO, Context);
420167802Sjkim    ACPI_NAMESPACE_NODE     *Node;
421167802Sjkim    ACPI_NAMESPACE_NODE     *ParentNode;
422167802Sjkim
423167802Sjkim
424167802Sjkim    /* Keep count of device/processor/thermal objects */
425167802Sjkim
426167802Sjkim    Node = ACPI_CAST_PTR (ACPI_NAMESPACE_NODE, ObjHandle);
427167802Sjkim    if ((Node->Type == ACPI_TYPE_DEVICE)    ||
428167802Sjkim        (Node->Type == ACPI_TYPE_PROCESSOR) ||
429167802Sjkim        (Node->Type == ACPI_TYPE_THERMAL))
430167802Sjkim    {
431167802Sjkim        Info->DeviceCount++;
432167802Sjkim        return (AE_OK);
433167802Sjkim    }
434167802Sjkim
435167802Sjkim    /* We are only looking for methods named _INI */
436167802Sjkim
437167802Sjkim    if (!ACPI_COMPARE_NAME (Node->Name.Ascii, METHOD_NAME__INI))
438167802Sjkim    {
439167802Sjkim        return (AE_OK);
440167802Sjkim    }
441167802Sjkim
442167802Sjkim    /*
443167802Sjkim     * The only _INI methods that we care about are those that are
444167802Sjkim     * present under Device, Processor, and Thermal objects.
445167802Sjkim     */
446209746Sjkim    ParentNode = Node->Parent;
447167802Sjkim    switch (ParentNode->Type)
448167802Sjkim    {
449167802Sjkim    case ACPI_TYPE_DEVICE:
450167802Sjkim    case ACPI_TYPE_PROCESSOR:
451167802Sjkim    case ACPI_TYPE_THERMAL:
452167802Sjkim
453167802Sjkim        /* Mark parent and bubble up the INI present flag to the root */
454167802Sjkim
455167802Sjkim        while (ParentNode)
456167802Sjkim        {
457167802Sjkim            ParentNode->Flags |= ANOBJ_SUBTREE_HAS_INI;
458209746Sjkim            ParentNode = ParentNode->Parent;
459167802Sjkim        }
460167802Sjkim        break;
461167802Sjkim
462167802Sjkim    default:
463250838Sjkim
464167802Sjkim        break;
465167802Sjkim    }
466167802Sjkim
467167802Sjkim    return (AE_OK);
468167802Sjkim}
469167802Sjkim
470167802Sjkim
471167802Sjkim/*******************************************************************************
472167802Sjkim *
47367754Smsmith * FUNCTION:    AcpiNsInitOneDevice
47467754Smsmith *
47577424Smsmith * PARAMETERS:  ACPI_WALK_CALLBACK
47667754Smsmith *
47767754Smsmith * RETURN:      ACPI_STATUS
47867754Smsmith *
47967754Smsmith * DESCRIPTION: This is called once per device soon after ACPI is enabled
48067754Smsmith *              to initialize each device. It determines if the device is
48167754Smsmith *              present, and if so, calls _INI.
48267754Smsmith *
48377424Smsmith ******************************************************************************/
48467754Smsmith
485151937Sjkimstatic ACPI_STATUS
48667754SmsmithAcpiNsInitOneDevice (
48767754Smsmith    ACPI_HANDLE             ObjHandle,
48867754Smsmith    UINT32                  NestingLevel,
48967754Smsmith    void                    *Context,
49067754Smsmith    void                    **ReturnValue)
49167754Smsmith{
492167802Sjkim    ACPI_DEVICE_WALK_INFO   *WalkInfo = ACPI_CAST_PTR (ACPI_DEVICE_WALK_INFO, Context);
493167802Sjkim    ACPI_EVALUATE_INFO      *Info = WalkInfo->EvaluateInfo;
494129684Snjl    UINT32                  Flags;
49567754Smsmith    ACPI_STATUS             Status;
496167802Sjkim    ACPI_NAMESPACE_NODE     *DeviceNode;
49767754Smsmith
49867754Smsmith
499167802Sjkim    ACPI_FUNCTION_TRACE (NsInitOneDevice);
50067754Smsmith
50167754Smsmith
502167802Sjkim    /* We are interested in Devices, Processors and ThermalZones only */
503129684Snjl
504167802Sjkim    DeviceNode = ACPI_CAST_PTR (ACPI_NAMESPACE_NODE, ObjHandle);
505167802Sjkim    if ((DeviceNode->Type != ACPI_TYPE_DEVICE)    &&
506167802Sjkim        (DeviceNode->Type != ACPI_TYPE_PROCESSOR) &&
507167802Sjkim        (DeviceNode->Type != ACPI_TYPE_THERMAL))
50873561Smsmith    {
509167802Sjkim        return_ACPI_STATUS (AE_OK);
51073561Smsmith    }
51173561Smsmith
512123315Snjl    /*
513167802Sjkim     * Because of an earlier namespace analysis, all subtrees that contain an
514167802Sjkim     * _INI method are tagged.
515167802Sjkim     *
516167802Sjkim     * If this device subtree does not contain any _INI methods, we
517167802Sjkim     * can exit now and stop traversing this entire subtree.
518123315Snjl     */
519167802Sjkim    if (!(DeviceNode->Flags & ANOBJ_SUBTREE_HAS_INI))
52091116Smsmith    {
521167802Sjkim        return_ACPI_STATUS (AE_CTRL_DEPTH);
52291116Smsmith    }
52367754Smsmith
52467754Smsmith    /*
525167802Sjkim     * Run _STA to determine if this device is present and functioning. We
526167802Sjkim     * must know this information for two important reasons (from ACPI spec):
527167802Sjkim     *
528167802Sjkim     * 1) We can only run _INI if the device is present.
529167802Sjkim     * 2) We must abort the device tree walk on this subtree if the device is
530167802Sjkim     *    not present and is not functional (we will not examine the children)
531167802Sjkim     *
532167802Sjkim     * The _STA method is not required to be present under the device, we
533167802Sjkim     * assume the device is present if _STA does not exist.
53467754Smsmith     */
535167802Sjkim    ACPI_DEBUG_EXEC (AcpiUtDisplayInitPathname (
536167802Sjkim        ACPI_TYPE_METHOD, DeviceNode, METHOD_NAME__STA));
537123315Snjl
538167802Sjkim    Status = AcpiUtExecute_STA (DeviceNode, &Flags);
53967754Smsmith    if (ACPI_FAILURE (Status))
54067754Smsmith    {
541167802Sjkim        /* Ignore error and move on to next device */
54271867Smsmith
543167802Sjkim        return_ACPI_STATUS (AE_OK);
544167802Sjkim    }
545123315Snjl
546167802Sjkim    /*
547167802Sjkim     * Flags == -1 means that _STA was not found. In this case, we assume that
548167802Sjkim     * the device is both present and functional.
549167802Sjkim     *
550167802Sjkim     * From the ACPI spec, description of _STA:
551167802Sjkim     *
552167802Sjkim     * "If a device object (including the processor object) does not have an
553167802Sjkim     * _STA object, then OSPM assumes that all of the above bits are set (in
554167802Sjkim     * other words, the device is present, ..., and functioning)"
555167802Sjkim     */
556167802Sjkim    if (Flags != ACPI_UINT32_MAX)
557167802Sjkim    {
558167802Sjkim        WalkInfo->Num_STA++;
55967754Smsmith    }
560167802Sjkim
561167802Sjkim    /*
562167802Sjkim     * Examine the PRESENT and FUNCTIONING status bits
563167802Sjkim     *
564167802Sjkim     * Note: ACPI spec does not seem to specify behavior for the present but
565167802Sjkim     * not functioning case, so we assume functioning if present.
566167802Sjkim     */
567167802Sjkim    if (!(Flags & ACPI_STA_DEVICE_PRESENT))
568123315Snjl    {
569167802Sjkim        /* Device is not present, we must examine the Functioning bit */
57067754Smsmith
571167802Sjkim        if (Flags & ACPI_STA_DEVICE_FUNCTIONING)
572123315Snjl        {
573167802Sjkim            /*
574167802Sjkim             * Device is not present but is "functioning". In this case,
575167802Sjkim             * we will not run _INI, but we continue to examine the children
576167802Sjkim             * of this device.
577167802Sjkim             *
578167802Sjkim             * From the ACPI spec, description of _STA: (Note - no mention
579167802Sjkim             * of whether to run _INI or not on the device in question)
580167802Sjkim             *
581167802Sjkim             * "_STA may return bit 0 clear (not present) with bit 3 set
582167802Sjkim             * (device is functional). This case is used to indicate a valid
583167802Sjkim             * device for which no device driver should be loaded (for example,
584167802Sjkim             * a bridge device.) Children of this device may be present and
585167802Sjkim             * valid. OSPM should continue enumeration below a device whose
586167802Sjkim             * _STA returns this bit combination"
587167802Sjkim             */
588167802Sjkim            return_ACPI_STATUS (AE_OK);
589123315Snjl        }
590167802Sjkim        else
591167802Sjkim        {
592167802Sjkim            /*
593167802Sjkim             * Device is not present and is not functioning. We must abort the
594167802Sjkim             * walk of this subtree immediately -- don't look at the children
595167802Sjkim             * of such a device.
596167802Sjkim             *
597167802Sjkim             * From the ACPI spec, description of _INI:
598167802Sjkim             *
599167802Sjkim             * "If the _STA method indicates that the device is not present,
600167802Sjkim             * OSPM will not run the _INI and will not examine the children
601167802Sjkim             * of the device for _INI methods"
602167802Sjkim             */
603167802Sjkim            return_ACPI_STATUS (AE_CTRL_DEPTH);
604167802Sjkim        }
60567754Smsmith    }
60667754Smsmith
60767754Smsmith    /*
608167802Sjkim     * The device is present or is assumed present if no _STA exists.
609167802Sjkim     * Run the _INI if it exists (not required to exist)
610167802Sjkim     *
611167802Sjkim     * Note: We know there is an _INI within this subtree, but it may not be
612167802Sjkim     * under this particular device, it may be lower in the branch.
61367754Smsmith     */
614167802Sjkim    ACPI_DEBUG_EXEC (AcpiUtDisplayInitPathname (
615167802Sjkim        ACPI_TYPE_METHOD, DeviceNode, METHOD_NAME__INI));
616167802Sjkim
617250341Sjkim    ACPI_MEMSET (Info, 0, sizeof (ACPI_EVALUATE_INFO));
618167802Sjkim    Info->PrefixNode = DeviceNode;
619249663Sjkim    Info->RelativePathname = METHOD_NAME__INI;
620167802Sjkim    Info->Parameters = NULL;
621167802Sjkim    Info->Flags = ACPI_IGNORE_RETURN_VALUE;
622167802Sjkim
623167802Sjkim    Status = AcpiNsEvaluate (Info);
624167802Sjkim    if (ACPI_SUCCESS (Status))
62567754Smsmith    {
626167802Sjkim        WalkInfo->Num_INI++;
627167802Sjkim    }
62867754Smsmith
629129684Snjl#ifdef ACPI_DEBUG_OUTPUT
630167802Sjkim    else if (Status != AE_NOT_FOUND)
631167802Sjkim    {
632167802Sjkim        /* Ignore error and move on to next device */
63371867Smsmith
634249663Sjkim        char *ScopeName = AcpiNsGetExternalPathname (Info->Node);
63567754Smsmith
636167802Sjkim        ACPI_EXCEPTION ((AE_INFO, Status, "during %s._INI execution",
637167802Sjkim            ScopeName));
638167802Sjkim        ACPI_FREE (ScopeName);
639167802Sjkim    }
640129684Snjl#endif
64167754Smsmith
642167802Sjkim    /* Ignore errors from above */
643140216Snjl
644167802Sjkim    Status = AE_OK;
645140216Snjl
646167802Sjkim    /*
647167802Sjkim     * The _INI method has been run if present; call the Global Initialization
648167802Sjkim     * Handler for this device.
649167802Sjkim     */
65099679Siwasaki    if (AcpiGbl_InitHandler)
65199679Siwasaki    {
652167802Sjkim        Status = AcpiGbl_InitHandler (DeviceNode, ACPI_INIT_DEVICE_INI);
65399679Siwasaki    }
65499679Siwasaki
65599679Siwasaki    return_ACPI_STATUS (Status);
65667754Smsmith}
657