nsinit.c revision 245582
167754Smsmith/******************************************************************************
267754Smsmith *
367754Smsmith * Module Name: nsinit - namespace initialization
467754Smsmith *
567754Smsmith *****************************************************************************/
667754Smsmith
7217365Sjkim/*
8245582Sjkim * Copyright (C) 2000 - 2013, 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
4467754Smsmith
4567754Smsmith#define __NSXFINIT_C__
4667754Smsmith
47193341Sjkim#include <contrib/dev/acpica/include/acpi.h>
48193341Sjkim#include <contrib/dev/acpica/include/accommon.h>
49193341Sjkim#include <contrib/dev/acpica/include/acnamesp.h>
50193341Sjkim#include <contrib/dev/acpica/include/acdispat.h>
51193341Sjkim#include <contrib/dev/acpica/include/acinterp.h>
5267754Smsmith
5377424Smsmith#define _COMPONENT          ACPI_NAMESPACE
5491116Smsmith        ACPI_MODULE_NAME    ("nsinit")
5567754Smsmith
56151937Sjkim/* Local prototypes */
5767754Smsmith
58151937Sjkimstatic ACPI_STATUS
59151937SjkimAcpiNsInitOneObject (
60151937Sjkim    ACPI_HANDLE             ObjHandle,
61151937Sjkim    UINT32                  Level,
62151937Sjkim    void                    *Context,
63151937Sjkim    void                    **ReturnValue);
64151937Sjkim
65151937Sjkimstatic ACPI_STATUS
66151937SjkimAcpiNsInitOneDevice (
67151937Sjkim    ACPI_HANDLE             ObjHandle,
68151937Sjkim    UINT32                  NestingLevel,
69151937Sjkim    void                    *Context,
70151937Sjkim    void                    **ReturnValue);
71151937Sjkim
72167802Sjkimstatic ACPI_STATUS
73167802SjkimAcpiNsFindIniMethods (
74167802Sjkim    ACPI_HANDLE             ObjHandle,
75167802Sjkim    UINT32                  NestingLevel,
76167802Sjkim    void                    *Context,
77167802Sjkim    void                    **ReturnValue);
78151937Sjkim
79167802Sjkim
8067754Smsmith/*******************************************************************************
8167754Smsmith *
8267754Smsmith * FUNCTION:    AcpiNsInitializeObjects
8367754Smsmith *
8467754Smsmith * PARAMETERS:  None
8567754Smsmith *
8667754Smsmith * RETURN:      Status
8767754Smsmith *
8867754Smsmith * DESCRIPTION: Walk the entire namespace and perform any necessary
8967754Smsmith *              initialization on the objects found therein
9067754Smsmith *
9167754Smsmith ******************************************************************************/
9267754Smsmith
9367754SmsmithACPI_STATUS
9467754SmsmithAcpiNsInitializeObjects (
9567754Smsmith    void)
9667754Smsmith{
9767754Smsmith    ACPI_STATUS             Status;
9867754Smsmith    ACPI_INIT_WALK_INFO     Info;
9967754Smsmith
10067754Smsmith
101167802Sjkim    ACPI_FUNCTION_TRACE (NsInitializeObjects);
10267754Smsmith
10367754Smsmith
10482367Smsmith    ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
10582367Smsmith        "**** Starting initialization of namespace objects ****\n"));
106138287Smarks    ACPI_DEBUG_PRINT_RAW ((ACPI_DB_INIT,
107245582Sjkim        "Completing Region/Field/Buffer/Package initialization:\n"));
10867754Smsmith
10999146Siwasaki    /* Set all init info to zero */
11067754Smsmith
11199146Siwasaki    ACPI_MEMSET (&Info, 0, sizeof (ACPI_INIT_WALK_INFO));
11267754Smsmith
11367754Smsmith    /* Walk entire namespace from the supplied root */
11467754Smsmith
11567754Smsmith    Status = AcpiWalkNamespace (ACPI_TYPE_ANY, ACPI_ROOT_OBJECT,
116209746Sjkim                ACPI_UINT32_MAX, AcpiNsInitOneObject, NULL,
117209746Sjkim                &Info, NULL);
11867754Smsmith    if (ACPI_FAILURE (Status))
11967754Smsmith    {
120167802Sjkim        ACPI_EXCEPTION ((AE_INFO, Status, "During WalkNamespace"));
12167754Smsmith    }
12267754Smsmith
123114237Snjl    ACPI_DEBUG_PRINT_RAW ((ACPI_DB_INIT,
124245582Sjkim        "    Initialized %u/%u Regions %u/%u Fields %u/%u "
125209746Sjkim        "Buffers %u/%u Packages (%u nodes)\n",
126102550Siwasaki        Info.OpRegionInit,  Info.OpRegionCount,
127102550Siwasaki        Info.FieldInit,     Info.FieldCount,
128102550Siwasaki        Info.BufferInit,    Info.BufferCount,
12999146Siwasaki        Info.PackageInit,   Info.PackageCount, Info.ObjectCount));
130114237Snjl
13182367Smsmith    ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
132209746Sjkim        "%u Control Methods found\n", Info.MethodCount));
13382367Smsmith    ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
134209746Sjkim        "%u Op Regions found\n", Info.OpRegionCount));
13567754Smsmith
13667754Smsmith    return_ACPI_STATUS (AE_OK);
13767754Smsmith}
13867754Smsmith
13967754Smsmith
14077424Smsmith/*******************************************************************************
14167754Smsmith *
14267754Smsmith * FUNCTION:    AcpiNsInitializeDevices
14367754Smsmith *
14467754Smsmith * PARAMETERS:  None
14567754Smsmith *
14667754Smsmith * RETURN:      ACPI_STATUS
14767754Smsmith *
14867754Smsmith * DESCRIPTION: Walk the entire namespace and initialize all ACPI devices.
14967754Smsmith *              This means running _INI on all present devices.
15067754Smsmith *
15177424Smsmith *              Note: We install PCI config space handler on region access,
15277424Smsmith *              not here.
15367754Smsmith *
15477424Smsmith ******************************************************************************/
15567754Smsmith
15667754SmsmithACPI_STATUS
15767754SmsmithAcpiNsInitializeDevices (
15873561Smsmith    void)
15967754Smsmith{
16067754Smsmith    ACPI_STATUS             Status;
16167754Smsmith    ACPI_DEVICE_WALK_INFO   Info;
16267754Smsmith
16367754Smsmith
164167802Sjkim    ACPI_FUNCTION_TRACE (NsInitializeDevices);
16567754Smsmith
16667754Smsmith
16799146Siwasaki    /* Init counters */
16899146Siwasaki
16967754Smsmith    Info.DeviceCount = 0;
17067754Smsmith    Info.Num_STA = 0;
17167754Smsmith    Info.Num_INI = 0;
17267754Smsmith
173138287Smarks    ACPI_DEBUG_PRINT_RAW ((ACPI_DB_INIT,
174193267Sjkim        "Initializing Device/Processor/Thermal objects "
175245582Sjkim        "and executing _INI/_STA methods:\n"));
17667754Smsmith
177167802Sjkim    /* Tree analysis: find all subtrees that contain _INI methods */
178167802Sjkim
179167802Sjkim    Status = AcpiNsWalkNamespace (ACPI_TYPE_ANY, ACPI_ROOT_OBJECT,
180199337Sjkim                ACPI_UINT32_MAX, FALSE, AcpiNsFindIniMethods, NULL, &Info, NULL);
181123315Snjl    if (ACPI_FAILURE (Status))
182123315Snjl    {
183167802Sjkim        goto ErrorExit;
184123315Snjl    }
18567754Smsmith
186167802Sjkim    /* Allocate the evaluation information block */
18767754Smsmith
188167802Sjkim    Info.EvaluateInfo = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_EVALUATE_INFO));
189167802Sjkim    if (!Info.EvaluateInfo)
190167802Sjkim    {
191167802Sjkim        Status = AE_NO_MEMORY;
192167802Sjkim        goto ErrorExit;
193167802Sjkim    }
194167802Sjkim
195197104Sjkim    /*
196197104Sjkim     * Execute the "global" _INI method that may appear at the root. This
197197104Sjkim     * support is provided for Windows compatibility (Vista+) and is not
198197104Sjkim     * part of the ACPI specification.
199197104Sjkim     */
200197104Sjkim    Info.EvaluateInfo->PrefixNode = AcpiGbl_RootNode;
201197104Sjkim    Info.EvaluateInfo->Pathname = METHOD_NAME__INI;
202197104Sjkim    Info.EvaluateInfo->Parameters = NULL;
203197104Sjkim    Info.EvaluateInfo->Flags = ACPI_IGNORE_RETURN_VALUE;
204197104Sjkim
205197104Sjkim    Status = AcpiNsEvaluate (Info.EvaluateInfo);
206197104Sjkim    if (ACPI_SUCCESS (Status))
207197104Sjkim    {
208197104Sjkim        Info.Num_INI++;
209197104Sjkim    }
210197104Sjkim
211167802Sjkim    /* Walk namespace to execute all _INIs on present devices */
212167802Sjkim
213123315Snjl    Status = AcpiNsWalkNamespace (ACPI_TYPE_ANY, ACPI_ROOT_OBJECT,
214199337Sjkim                ACPI_UINT32_MAX, FALSE, AcpiNsInitOneDevice, NULL, &Info, NULL);
215123315Snjl
216209746Sjkim    /*
217209746Sjkim     * Any _OSI requests should be completed by now. If the BIOS has
218209746Sjkim     * requested any Windows OSI strings, we will always truncate
219209746Sjkim     * I/O addresses to 16 bits -- for Windows compatibility.
220209746Sjkim     */
221209746Sjkim    if (AcpiGbl_OsiData >= ACPI_OSI_WIN_2000)
222209746Sjkim    {
223209746Sjkim        AcpiGbl_TruncateIoAddresses = TRUE;
224209746Sjkim    }
225209746Sjkim
226167802Sjkim    ACPI_FREE (Info.EvaluateInfo);
22767754Smsmith    if (ACPI_FAILURE (Status))
22867754Smsmith    {
229167802Sjkim        goto ErrorExit;
23067754Smsmith    }
23167754Smsmith
232114237Snjl    ACPI_DEBUG_PRINT_RAW ((ACPI_DB_INIT,
233245582Sjkim        "    Executed %u _INI methods requiring %u _STA executions "
234209746Sjkim        "(examined %u objects)\n",
235167802Sjkim        Info.Num_INI, Info.Num_STA, Info.DeviceCount));
23667754Smsmith
23767754Smsmith    return_ACPI_STATUS (Status);
238167802Sjkim
239167802Sjkim
240167802SjkimErrorExit:
241167802Sjkim    ACPI_EXCEPTION ((AE_INFO, Status, "During device initialization"));
242167802Sjkim    return_ACPI_STATUS (Status);
24367754Smsmith}
24467754Smsmith
24567754Smsmith
24667754Smsmith/*******************************************************************************
24767754Smsmith *
24867754Smsmith * FUNCTION:    AcpiNsInitOneObject
24967754Smsmith *
25067754Smsmith * PARAMETERS:  ObjHandle       - Node
25167754Smsmith *              Level           - Current nesting level
25267754Smsmith *              Context         - Points to a init info struct
25367754Smsmith *              ReturnValue     - Not used
25467754Smsmith *
25567754Smsmith * RETURN:      Status
25667754Smsmith *
257241973Sjkim * DESCRIPTION: Callback from AcpiWalkNamespace. Invoked for every object
25867754Smsmith *              within the  namespace.
25967754Smsmith *
26067754Smsmith *              Currently, the only objects that require initialization are:
26167754Smsmith *              1) Methods
26267754Smsmith *              2) Op Regions
26367754Smsmith *
26467754Smsmith ******************************************************************************/
26567754Smsmith
266151937Sjkimstatic ACPI_STATUS
26767754SmsmithAcpiNsInitOneObject (
26867754Smsmith    ACPI_HANDLE             ObjHandle,
26967754Smsmith    UINT32                  Level,
27067754Smsmith    void                    *Context,
27167754Smsmith    void                    **ReturnValue)
27267754Smsmith{
27391116Smsmith    ACPI_OBJECT_TYPE        Type;
274167802Sjkim    ACPI_STATUS             Status = AE_OK;
27567754Smsmith    ACPI_INIT_WALK_INFO     *Info = (ACPI_INIT_WALK_INFO *) Context;
27667754Smsmith    ACPI_NAMESPACE_NODE     *Node = (ACPI_NAMESPACE_NODE *) ObjHandle;
27767754Smsmith    ACPI_OPERAND_OBJECT     *ObjDesc;
27867754Smsmith
27967754Smsmith
280167802Sjkim    ACPI_FUNCTION_NAME (NsInitOneObject);
28182367Smsmith
28282367Smsmith
28367754Smsmith    Info->ObjectCount++;
28467754Smsmith
28567754Smsmith    /* And even then, we are only interested in a few object types */
28667754Smsmith
28767754Smsmith    Type = AcpiNsGetType (ObjHandle);
28887031Smsmith    ObjDesc = AcpiNsGetAttachedObject (Node);
28967754Smsmith    if (!ObjDesc)
29067754Smsmith    {
29167754Smsmith        return (AE_OK);
29267754Smsmith    }
29367754Smsmith
29499146Siwasaki    /* Increment counters for object types we are looking for */
29599146Siwasaki
29699146Siwasaki    switch (Type)
29780062Smsmith    {
29899146Siwasaki    case ACPI_TYPE_REGION:
29999146Siwasaki        Info->OpRegionCount++;
30099146Siwasaki        break;
30199146Siwasaki
30299146Siwasaki    case ACPI_TYPE_BUFFER_FIELD:
30399146Siwasaki        Info->FieldCount++;
30499146Siwasaki        break;
30599146Siwasaki
306193267Sjkim    case ACPI_TYPE_LOCAL_BANK_FIELD:
307193267Sjkim        Info->FieldCount++;
308193267Sjkim        break;
309193267Sjkim
31099146Siwasaki    case ACPI_TYPE_BUFFER:
31199146Siwasaki        Info->BufferCount++;
31299146Siwasaki        break;
31399146Siwasaki
31499146Siwasaki    case ACPI_TYPE_PACKAGE:
31599146Siwasaki        Info->PackageCount++;
31699146Siwasaki        break;
31799146Siwasaki
31899146Siwasaki    default:
31999146Siwasaki
32099146Siwasaki        /* No init required, just exit now */
32180062Smsmith        return (AE_OK);
32280062Smsmith    }
32380062Smsmith
324193267Sjkim    /* If the object is already initialized, nothing else to do */
325193267Sjkim
32699146Siwasaki    if (ObjDesc->Common.Flags & AOPOBJ_DATA_VALID)
32799146Siwasaki    {
32899146Siwasaki        return (AE_OK);
32999146Siwasaki    }
33080062Smsmith
331193267Sjkim    /* Must lock the interpreter before executing AML code */
332193267Sjkim
333167802Sjkim    AcpiExEnterInterpreter ();
33480062Smsmith
33599146Siwasaki    /*
336138287Smarks     * Each of these types can contain executable AML code within the
337138287Smarks     * declaration.
33899146Siwasaki     */
33967754Smsmith    switch (Type)
34067754Smsmith    {
34167754Smsmith    case ACPI_TYPE_REGION:
34267754Smsmith
34367754Smsmith        Info->OpRegionInit++;
34467754Smsmith        Status = AcpiDsGetRegionArguments (ObjDesc);
34567754Smsmith        break;
34667754Smsmith
34777424Smsmith    case ACPI_TYPE_BUFFER_FIELD:
34867754Smsmith
34967754Smsmith        Info->FieldInit++;
35077424Smsmith        Status = AcpiDsGetBufferFieldArguments (ObjDesc);
35199146Siwasaki        break;
35267754Smsmith
353193267Sjkim    case ACPI_TYPE_LOCAL_BANK_FIELD:
354193267Sjkim
355193267Sjkim        Info->FieldInit++;
356193267Sjkim        Status = AcpiDsGetBankFieldArguments (ObjDesc);
357193267Sjkim        break;
358193267Sjkim
35999146Siwasaki    case ACPI_TYPE_BUFFER:
36099146Siwasaki
36199146Siwasaki        Info->BufferInit++;
36299146Siwasaki        Status = AcpiDsGetBufferArguments (ObjDesc);
36367754Smsmith        break;
36467754Smsmith
36599146Siwasaki    case ACPI_TYPE_PACKAGE:
36699146Siwasaki
36799146Siwasaki        Info->PackageInit++;
36899146Siwasaki        Status = AcpiDsGetPackageArguments (ObjDesc);
36967754Smsmith        break;
37099679Siwasaki
37199679Siwasaki    default:
37299679Siwasaki        /* No other types can get here */
37399679Siwasaki        break;
37467754Smsmith    }
37567754Smsmith
37699146Siwasaki    if (ACPI_FAILURE (Status))
37799146Siwasaki    {
378167802Sjkim        ACPI_EXCEPTION ((AE_INFO, Status,
379167802Sjkim            "Could not execute arguments for [%4.4s] (%s)",
380167802Sjkim            AcpiUtGetNodeName (Node), AcpiUtGetTypeName (Type)));
38199146Siwasaki    }
38280062Smsmith
383138287Smarks    /*
384138287Smarks     * We ignore errors from above, and always return OK, since we don't want
385138287Smarks     * to abort the walk on any single error.
38667754Smsmith     */
38780062Smsmith    AcpiExExitInterpreter ();
38867754Smsmith    return (AE_OK);
38967754Smsmith}
39067754Smsmith
39167754Smsmith
39277424Smsmith/*******************************************************************************
39367754Smsmith *
394167802Sjkim * FUNCTION:    AcpiNsFindIniMethods
395167802Sjkim *
396167802Sjkim * PARAMETERS:  ACPI_WALK_CALLBACK
397167802Sjkim *
398167802Sjkim * RETURN:      ACPI_STATUS
399167802Sjkim *
400167802Sjkim * DESCRIPTION: Called during namespace walk. Finds objects named _INI under
401167802Sjkim *              device/processor/thermal objects, and marks the entire subtree
402167802Sjkim *              with a SUBTREE_HAS_INI flag. This flag is used during the
403167802Sjkim *              subsequent device initialization walk to avoid entire subtrees
404167802Sjkim *              that do not contain an _INI.
405167802Sjkim *
406167802Sjkim ******************************************************************************/
407167802Sjkim
408167802Sjkimstatic ACPI_STATUS
409167802SjkimAcpiNsFindIniMethods (
410167802Sjkim    ACPI_HANDLE             ObjHandle,
411167802Sjkim    UINT32                  NestingLevel,
412167802Sjkim    void                    *Context,
413167802Sjkim    void                    **ReturnValue)
414167802Sjkim{
415167802Sjkim    ACPI_DEVICE_WALK_INFO   *Info = ACPI_CAST_PTR (ACPI_DEVICE_WALK_INFO, Context);
416167802Sjkim    ACPI_NAMESPACE_NODE     *Node;
417167802Sjkim    ACPI_NAMESPACE_NODE     *ParentNode;
418167802Sjkim
419167802Sjkim
420167802Sjkim    /* Keep count of device/processor/thermal objects */
421167802Sjkim
422167802Sjkim    Node = ACPI_CAST_PTR (ACPI_NAMESPACE_NODE, ObjHandle);
423167802Sjkim    if ((Node->Type == ACPI_TYPE_DEVICE)    ||
424167802Sjkim        (Node->Type == ACPI_TYPE_PROCESSOR) ||
425167802Sjkim        (Node->Type == ACPI_TYPE_THERMAL))
426167802Sjkim    {
427167802Sjkim        Info->DeviceCount++;
428167802Sjkim        return (AE_OK);
429167802Sjkim    }
430167802Sjkim
431167802Sjkim    /* We are only looking for methods named _INI */
432167802Sjkim
433167802Sjkim    if (!ACPI_COMPARE_NAME (Node->Name.Ascii, METHOD_NAME__INI))
434167802Sjkim    {
435167802Sjkim        return (AE_OK);
436167802Sjkim    }
437167802Sjkim
438167802Sjkim    /*
439167802Sjkim     * The only _INI methods that we care about are those that are
440167802Sjkim     * present under Device, Processor, and Thermal objects.
441167802Sjkim     */
442209746Sjkim    ParentNode = Node->Parent;
443167802Sjkim    switch (ParentNode->Type)
444167802Sjkim    {
445167802Sjkim    case ACPI_TYPE_DEVICE:
446167802Sjkim    case ACPI_TYPE_PROCESSOR:
447167802Sjkim    case ACPI_TYPE_THERMAL:
448167802Sjkim
449167802Sjkim        /* Mark parent and bubble up the INI present flag to the root */
450167802Sjkim
451167802Sjkim        while (ParentNode)
452167802Sjkim        {
453167802Sjkim            ParentNode->Flags |= ANOBJ_SUBTREE_HAS_INI;
454209746Sjkim            ParentNode = ParentNode->Parent;
455167802Sjkim        }
456167802Sjkim        break;
457167802Sjkim
458167802Sjkim    default:
459167802Sjkim        break;
460167802Sjkim    }
461167802Sjkim
462167802Sjkim    return (AE_OK);
463167802Sjkim}
464167802Sjkim
465167802Sjkim
466167802Sjkim/*******************************************************************************
467167802Sjkim *
46867754Smsmith * FUNCTION:    AcpiNsInitOneDevice
46967754Smsmith *
47077424Smsmith * PARAMETERS:  ACPI_WALK_CALLBACK
47167754Smsmith *
47267754Smsmith * RETURN:      ACPI_STATUS
47367754Smsmith *
47467754Smsmith * DESCRIPTION: This is called once per device soon after ACPI is enabled
47567754Smsmith *              to initialize each device. It determines if the device is
47667754Smsmith *              present, and if so, calls _INI.
47767754Smsmith *
47877424Smsmith ******************************************************************************/
47967754Smsmith
480151937Sjkimstatic ACPI_STATUS
48167754SmsmithAcpiNsInitOneDevice (
48267754Smsmith    ACPI_HANDLE             ObjHandle,
48367754Smsmith    UINT32                  NestingLevel,
48467754Smsmith    void                    *Context,
48567754Smsmith    void                    **ReturnValue)
48667754Smsmith{
487167802Sjkim    ACPI_DEVICE_WALK_INFO   *WalkInfo = ACPI_CAST_PTR (ACPI_DEVICE_WALK_INFO, Context);
488167802Sjkim    ACPI_EVALUATE_INFO      *Info = WalkInfo->EvaluateInfo;
489129684Snjl    UINT32                  Flags;
49067754Smsmith    ACPI_STATUS             Status;
491167802Sjkim    ACPI_NAMESPACE_NODE     *DeviceNode;
49267754Smsmith
49367754Smsmith
494167802Sjkim    ACPI_FUNCTION_TRACE (NsInitOneDevice);
49567754Smsmith
49667754Smsmith
497167802Sjkim    /* We are interested in Devices, Processors and ThermalZones only */
498129684Snjl
499167802Sjkim    DeviceNode = ACPI_CAST_PTR (ACPI_NAMESPACE_NODE, ObjHandle);
500167802Sjkim    if ((DeviceNode->Type != ACPI_TYPE_DEVICE)    &&
501167802Sjkim        (DeviceNode->Type != ACPI_TYPE_PROCESSOR) &&
502167802Sjkim        (DeviceNode->Type != ACPI_TYPE_THERMAL))
50373561Smsmith    {
504167802Sjkim        return_ACPI_STATUS (AE_OK);
50573561Smsmith    }
50673561Smsmith
507123315Snjl    /*
508167802Sjkim     * Because of an earlier namespace analysis, all subtrees that contain an
509167802Sjkim     * _INI method are tagged.
510167802Sjkim     *
511167802Sjkim     * If this device subtree does not contain any _INI methods, we
512167802Sjkim     * can exit now and stop traversing this entire subtree.
513123315Snjl     */
514167802Sjkim    if (!(DeviceNode->Flags & ANOBJ_SUBTREE_HAS_INI))
51591116Smsmith    {
516167802Sjkim        return_ACPI_STATUS (AE_CTRL_DEPTH);
51791116Smsmith    }
51867754Smsmith
51967754Smsmith    /*
520167802Sjkim     * Run _STA to determine if this device is present and functioning. We
521167802Sjkim     * must know this information for two important reasons (from ACPI spec):
522167802Sjkim     *
523167802Sjkim     * 1) We can only run _INI if the device is present.
524167802Sjkim     * 2) We must abort the device tree walk on this subtree if the device is
525167802Sjkim     *    not present and is not functional (we will not examine the children)
526167802Sjkim     *
527167802Sjkim     * The _STA method is not required to be present under the device, we
528167802Sjkim     * assume the device is present if _STA does not exist.
52967754Smsmith     */
530167802Sjkim    ACPI_DEBUG_EXEC (AcpiUtDisplayInitPathname (
531167802Sjkim        ACPI_TYPE_METHOD, DeviceNode, METHOD_NAME__STA));
532123315Snjl
533167802Sjkim    Status = AcpiUtExecute_STA (DeviceNode, &Flags);
53467754Smsmith    if (ACPI_FAILURE (Status))
53567754Smsmith    {
536167802Sjkim        /* Ignore error and move on to next device */
53771867Smsmith
538167802Sjkim        return_ACPI_STATUS (AE_OK);
539167802Sjkim    }
540123315Snjl
541167802Sjkim    /*
542167802Sjkim     * Flags == -1 means that _STA was not found. In this case, we assume that
543167802Sjkim     * the device is both present and functional.
544167802Sjkim     *
545167802Sjkim     * From the ACPI spec, description of _STA:
546167802Sjkim     *
547167802Sjkim     * "If a device object (including the processor object) does not have an
548167802Sjkim     * _STA object, then OSPM assumes that all of the above bits are set (in
549167802Sjkim     * other words, the device is present, ..., and functioning)"
550167802Sjkim     */
551167802Sjkim    if (Flags != ACPI_UINT32_MAX)
552167802Sjkim    {
553167802Sjkim        WalkInfo->Num_STA++;
55467754Smsmith    }
555167802Sjkim
556167802Sjkim    /*
557167802Sjkim     * Examine the PRESENT and FUNCTIONING status bits
558167802Sjkim     *
559167802Sjkim     * Note: ACPI spec does not seem to specify behavior for the present but
560167802Sjkim     * not functioning case, so we assume functioning if present.
561167802Sjkim     */
562167802Sjkim    if (!(Flags & ACPI_STA_DEVICE_PRESENT))
563123315Snjl    {
564167802Sjkim        /* Device is not present, we must examine the Functioning bit */
56567754Smsmith
566167802Sjkim        if (Flags & ACPI_STA_DEVICE_FUNCTIONING)
567123315Snjl        {
568167802Sjkim            /*
569167802Sjkim             * Device is not present but is "functioning". In this case,
570167802Sjkim             * we will not run _INI, but we continue to examine the children
571167802Sjkim             * of this device.
572167802Sjkim             *
573167802Sjkim             * From the ACPI spec, description of _STA: (Note - no mention
574167802Sjkim             * of whether to run _INI or not on the device in question)
575167802Sjkim             *
576167802Sjkim             * "_STA may return bit 0 clear (not present) with bit 3 set
577167802Sjkim             * (device is functional). This case is used to indicate a valid
578167802Sjkim             * device for which no device driver should be loaded (for example,
579167802Sjkim             * a bridge device.) Children of this device may be present and
580167802Sjkim             * valid. OSPM should continue enumeration below a device whose
581167802Sjkim             * _STA returns this bit combination"
582167802Sjkim             */
583167802Sjkim            return_ACPI_STATUS (AE_OK);
584123315Snjl        }
585167802Sjkim        else
586167802Sjkim        {
587167802Sjkim            /*
588167802Sjkim             * Device is not present and is not functioning. We must abort the
589167802Sjkim             * walk of this subtree immediately -- don't look at the children
590167802Sjkim             * of such a device.
591167802Sjkim             *
592167802Sjkim             * From the ACPI spec, description of _INI:
593167802Sjkim             *
594167802Sjkim             * "If the _STA method indicates that the device is not present,
595167802Sjkim             * OSPM will not run the _INI and will not examine the children
596167802Sjkim             * of the device for _INI methods"
597167802Sjkim             */
598167802Sjkim            return_ACPI_STATUS (AE_CTRL_DEPTH);
599167802Sjkim        }
60067754Smsmith    }
60167754Smsmith
60267754Smsmith    /*
603167802Sjkim     * The device is present or is assumed present if no _STA exists.
604167802Sjkim     * Run the _INI if it exists (not required to exist)
605167802Sjkim     *
606167802Sjkim     * Note: We know there is an _INI within this subtree, but it may not be
607167802Sjkim     * under this particular device, it may be lower in the branch.
60867754Smsmith     */
609167802Sjkim    ACPI_DEBUG_EXEC (AcpiUtDisplayInitPathname (
610167802Sjkim        ACPI_TYPE_METHOD, DeviceNode, METHOD_NAME__INI));
611167802Sjkim
612167802Sjkim    Info->PrefixNode = DeviceNode;
613167802Sjkim    Info->Pathname = METHOD_NAME__INI;
614167802Sjkim    Info->Parameters = NULL;
615167802Sjkim    Info->Flags = ACPI_IGNORE_RETURN_VALUE;
616167802Sjkim
617167802Sjkim    Status = AcpiNsEvaluate (Info);
618167802Sjkim    if (ACPI_SUCCESS (Status))
61967754Smsmith    {
620167802Sjkim        WalkInfo->Num_INI++;
621167802Sjkim    }
62267754Smsmith
623129684Snjl#ifdef ACPI_DEBUG_OUTPUT
624167802Sjkim    else if (Status != AE_NOT_FOUND)
625167802Sjkim    {
626167802Sjkim        /* Ignore error and move on to next device */
62771867Smsmith
628167802Sjkim        char *ScopeName = AcpiNsGetExternalPathname (Info->ResolvedNode);
62967754Smsmith
630167802Sjkim        ACPI_EXCEPTION ((AE_INFO, Status, "during %s._INI execution",
631167802Sjkim            ScopeName));
632167802Sjkim        ACPI_FREE (ScopeName);
633167802Sjkim    }
634129684Snjl#endif
63567754Smsmith
636167802Sjkim    /* Ignore errors from above */
637140216Snjl
638167802Sjkim    Status = AE_OK;
639140216Snjl
640167802Sjkim    /*
641167802Sjkim     * The _INI method has been run if present; call the Global Initialization
642167802Sjkim     * Handler for this device.
643167802Sjkim     */
64499679Siwasaki    if (AcpiGbl_InitHandler)
64599679Siwasaki    {
646167802Sjkim        Status = AcpiGbl_InitHandler (DeviceNode, ACPI_INIT_DEVICE_INI);
64799679Siwasaki    }
64899679Siwasaki
64999679Siwasaki    return_ACPI_STATUS (Status);
65067754Smsmith}
651