nsinit.c revision 217365
167754Smsmith/******************************************************************************
267754Smsmith *
367754Smsmith * Module Name: nsinit - namespace initialization
467754Smsmith *
567754Smsmith *****************************************************************************/
667754Smsmith
7217365Sjkim/*
8229989Sjkim * Copyright (C) 2000 - 2011, 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,
107138287Smarks        "Completing Region/Field/Buffer/Package initialization:"));
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,
124209746Sjkim        "\nInitialized %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 "
175193267Sjkim        "by executing _INI methods:"));
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,
233209746Sjkim        "\nExecuted %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     * Print a dot for each object unless we are going to print the entire
385138287Smarks     * pathname
386138287Smarks     */
387114237Snjl    if (!(AcpiDbgLevel & ACPI_LV_INIT_NAMES))
38899146Siwasaki    {
389114237Snjl        ACPI_DEBUG_PRINT_RAW ((ACPI_DB_INIT, "."));
39099146Siwasaki    }
39199146Siwasaki
39267754Smsmith    /*
393138287Smarks     * We ignore errors from above, and always return OK, since we don't want
394138287Smarks     * to abort the walk on any single error.
39567754Smsmith     */
39680062Smsmith    AcpiExExitInterpreter ();
39767754Smsmith    return (AE_OK);
39867754Smsmith}
39967754Smsmith
40067754Smsmith
40177424Smsmith/*******************************************************************************
40267754Smsmith *
403167802Sjkim * FUNCTION:    AcpiNsFindIniMethods
404167802Sjkim *
405167802Sjkim * PARAMETERS:  ACPI_WALK_CALLBACK
406167802Sjkim *
407167802Sjkim * RETURN:      ACPI_STATUS
408167802Sjkim *
409167802Sjkim * DESCRIPTION: Called during namespace walk. Finds objects named _INI under
410167802Sjkim *              device/processor/thermal objects, and marks the entire subtree
411167802Sjkim *              with a SUBTREE_HAS_INI flag. This flag is used during the
412167802Sjkim *              subsequent device initialization walk to avoid entire subtrees
413167802Sjkim *              that do not contain an _INI.
414167802Sjkim *
415167802Sjkim ******************************************************************************/
416167802Sjkim
417167802Sjkimstatic ACPI_STATUS
418167802SjkimAcpiNsFindIniMethods (
419167802Sjkim    ACPI_HANDLE             ObjHandle,
420167802Sjkim    UINT32                  NestingLevel,
421167802Sjkim    void                    *Context,
422167802Sjkim    void                    **ReturnValue)
423167802Sjkim{
424167802Sjkim    ACPI_DEVICE_WALK_INFO   *Info = ACPI_CAST_PTR (ACPI_DEVICE_WALK_INFO, Context);
425167802Sjkim    ACPI_NAMESPACE_NODE     *Node;
426167802Sjkim    ACPI_NAMESPACE_NODE     *ParentNode;
427167802Sjkim
428167802Sjkim
429167802Sjkim    /* Keep count of device/processor/thermal objects */
430167802Sjkim
431167802Sjkim    Node = ACPI_CAST_PTR (ACPI_NAMESPACE_NODE, ObjHandle);
432167802Sjkim    if ((Node->Type == ACPI_TYPE_DEVICE)    ||
433167802Sjkim        (Node->Type == ACPI_TYPE_PROCESSOR) ||
434167802Sjkim        (Node->Type == ACPI_TYPE_THERMAL))
435167802Sjkim    {
436167802Sjkim        Info->DeviceCount++;
437167802Sjkim        return (AE_OK);
438167802Sjkim    }
439167802Sjkim
440167802Sjkim    /* We are only looking for methods named _INI */
441167802Sjkim
442167802Sjkim    if (!ACPI_COMPARE_NAME (Node->Name.Ascii, METHOD_NAME__INI))
443167802Sjkim    {
444167802Sjkim        return (AE_OK);
445167802Sjkim    }
446167802Sjkim
447167802Sjkim    /*
448167802Sjkim     * The only _INI methods that we care about are those that are
449167802Sjkim     * present under Device, Processor, and Thermal objects.
450167802Sjkim     */
451209746Sjkim    ParentNode = Node->Parent;
452167802Sjkim    switch (ParentNode->Type)
453167802Sjkim    {
454167802Sjkim    case ACPI_TYPE_DEVICE:
455167802Sjkim    case ACPI_TYPE_PROCESSOR:
456167802Sjkim    case ACPI_TYPE_THERMAL:
457167802Sjkim
458167802Sjkim        /* Mark parent and bubble up the INI present flag to the root */
459167802Sjkim
460167802Sjkim        while (ParentNode)
461167802Sjkim        {
462167802Sjkim            ParentNode->Flags |= ANOBJ_SUBTREE_HAS_INI;
463209746Sjkim            ParentNode = ParentNode->Parent;
464167802Sjkim        }
465167802Sjkim        break;
466167802Sjkim
467167802Sjkim    default:
468167802Sjkim        break;
469167802Sjkim    }
470167802Sjkim
471167802Sjkim    return (AE_OK);
472167802Sjkim}
473167802Sjkim
474167802Sjkim
475167802Sjkim/*******************************************************************************
476167802Sjkim *
47767754Smsmith * FUNCTION:    AcpiNsInitOneDevice
47867754Smsmith *
47977424Smsmith * PARAMETERS:  ACPI_WALK_CALLBACK
48067754Smsmith *
48167754Smsmith * RETURN:      ACPI_STATUS
48267754Smsmith *
48367754Smsmith * DESCRIPTION: This is called once per device soon after ACPI is enabled
48467754Smsmith *              to initialize each device. It determines if the device is
48567754Smsmith *              present, and if so, calls _INI.
48667754Smsmith *
48777424Smsmith ******************************************************************************/
48867754Smsmith
489151937Sjkimstatic ACPI_STATUS
49067754SmsmithAcpiNsInitOneDevice (
49167754Smsmith    ACPI_HANDLE             ObjHandle,
49267754Smsmith    UINT32                  NestingLevel,
49367754Smsmith    void                    *Context,
49467754Smsmith    void                    **ReturnValue)
49567754Smsmith{
496167802Sjkim    ACPI_DEVICE_WALK_INFO   *WalkInfo = ACPI_CAST_PTR (ACPI_DEVICE_WALK_INFO, Context);
497167802Sjkim    ACPI_EVALUATE_INFO      *Info = WalkInfo->EvaluateInfo;
498129684Snjl    UINT32                  Flags;
49967754Smsmith    ACPI_STATUS             Status;
500167802Sjkim    ACPI_NAMESPACE_NODE     *DeviceNode;
50167754Smsmith
50267754Smsmith
503167802Sjkim    ACPI_FUNCTION_TRACE (NsInitOneDevice);
50467754Smsmith
50567754Smsmith
506167802Sjkim    /* We are interested in Devices, Processors and ThermalZones only */
507129684Snjl
508167802Sjkim    DeviceNode = ACPI_CAST_PTR (ACPI_NAMESPACE_NODE, ObjHandle);
509167802Sjkim    if ((DeviceNode->Type != ACPI_TYPE_DEVICE)    &&
510167802Sjkim        (DeviceNode->Type != ACPI_TYPE_PROCESSOR) &&
511167802Sjkim        (DeviceNode->Type != ACPI_TYPE_THERMAL))
51273561Smsmith    {
513167802Sjkim        return_ACPI_STATUS (AE_OK);
51473561Smsmith    }
51573561Smsmith
516123315Snjl    /*
517167802Sjkim     * Because of an earlier namespace analysis, all subtrees that contain an
518167802Sjkim     * _INI method are tagged.
519167802Sjkim     *
520167802Sjkim     * If this device subtree does not contain any _INI methods, we
521167802Sjkim     * can exit now and stop traversing this entire subtree.
522123315Snjl     */
523167802Sjkim    if (!(DeviceNode->Flags & ANOBJ_SUBTREE_HAS_INI))
52491116Smsmith    {
525167802Sjkim        return_ACPI_STATUS (AE_CTRL_DEPTH);
52691116Smsmith    }
52767754Smsmith
52867754Smsmith    /*
529167802Sjkim     * Run _STA to determine if this device is present and functioning. We
530167802Sjkim     * must know this information for two important reasons (from ACPI spec):
531167802Sjkim     *
532167802Sjkim     * 1) We can only run _INI if the device is present.
533167802Sjkim     * 2) We must abort the device tree walk on this subtree if the device is
534167802Sjkim     *    not present and is not functional (we will not examine the children)
535167802Sjkim     *
536167802Sjkim     * The _STA method is not required to be present under the device, we
537167802Sjkim     * assume the device is present if _STA does not exist.
53867754Smsmith     */
539167802Sjkim    ACPI_DEBUG_EXEC (AcpiUtDisplayInitPathname (
540167802Sjkim        ACPI_TYPE_METHOD, DeviceNode, METHOD_NAME__STA));
541123315Snjl
542167802Sjkim    Status = AcpiUtExecute_STA (DeviceNode, &Flags);
54367754Smsmith    if (ACPI_FAILURE (Status))
54467754Smsmith    {
545167802Sjkim        /* Ignore error and move on to next device */
54671867Smsmith
547167802Sjkim        return_ACPI_STATUS (AE_OK);
548167802Sjkim    }
549123315Snjl
550167802Sjkim    /*
551167802Sjkim     * Flags == -1 means that _STA was not found. In this case, we assume that
552167802Sjkim     * the device is both present and functional.
553167802Sjkim     *
554167802Sjkim     * From the ACPI spec, description of _STA:
555167802Sjkim     *
556167802Sjkim     * "If a device object (including the processor object) does not have an
557167802Sjkim     * _STA object, then OSPM assumes that all of the above bits are set (in
558167802Sjkim     * other words, the device is present, ..., and functioning)"
559167802Sjkim     */
560167802Sjkim    if (Flags != ACPI_UINT32_MAX)
561167802Sjkim    {
562167802Sjkim        WalkInfo->Num_STA++;
56367754Smsmith    }
564167802Sjkim
565167802Sjkim    /*
566167802Sjkim     * Examine the PRESENT and FUNCTIONING status bits
567167802Sjkim     *
568167802Sjkim     * Note: ACPI spec does not seem to specify behavior for the present but
569167802Sjkim     * not functioning case, so we assume functioning if present.
570167802Sjkim     */
571167802Sjkim    if (!(Flags & ACPI_STA_DEVICE_PRESENT))
572123315Snjl    {
573167802Sjkim        /* Device is not present, we must examine the Functioning bit */
57467754Smsmith
575167802Sjkim        if (Flags & ACPI_STA_DEVICE_FUNCTIONING)
576123315Snjl        {
577167802Sjkim            /*
578167802Sjkim             * Device is not present but is "functioning". In this case,
579167802Sjkim             * we will not run _INI, but we continue to examine the children
580167802Sjkim             * of this device.
581167802Sjkim             *
582167802Sjkim             * From the ACPI spec, description of _STA: (Note - no mention
583167802Sjkim             * of whether to run _INI or not on the device in question)
584167802Sjkim             *
585167802Sjkim             * "_STA may return bit 0 clear (not present) with bit 3 set
586167802Sjkim             * (device is functional). This case is used to indicate a valid
587167802Sjkim             * device for which no device driver should be loaded (for example,
588167802Sjkim             * a bridge device.) Children of this device may be present and
589167802Sjkim             * valid. OSPM should continue enumeration below a device whose
590167802Sjkim             * _STA returns this bit combination"
591167802Sjkim             */
592167802Sjkim            return_ACPI_STATUS (AE_OK);
593123315Snjl        }
594167802Sjkim        else
595167802Sjkim        {
596167802Sjkim            /*
597167802Sjkim             * Device is not present and is not functioning. We must abort the
598167802Sjkim             * walk of this subtree immediately -- don't look at the children
599167802Sjkim             * of such a device.
600167802Sjkim             *
601167802Sjkim             * From the ACPI spec, description of _INI:
602167802Sjkim             *
603167802Sjkim             * "If the _STA method indicates that the device is not present,
604167802Sjkim             * OSPM will not run the _INI and will not examine the children
605167802Sjkim             * of the device for _INI methods"
606167802Sjkim             */
607167802Sjkim            return_ACPI_STATUS (AE_CTRL_DEPTH);
608167802Sjkim        }
60967754Smsmith    }
61067754Smsmith
61167754Smsmith    /*
612167802Sjkim     * The device is present or is assumed present if no _STA exists.
613167802Sjkim     * Run the _INI if it exists (not required to exist)
614167802Sjkim     *
615167802Sjkim     * Note: We know there is an _INI within this subtree, but it may not be
616167802Sjkim     * under this particular device, it may be lower in the branch.
61767754Smsmith     */
618167802Sjkim    ACPI_DEBUG_EXEC (AcpiUtDisplayInitPathname (
619167802Sjkim        ACPI_TYPE_METHOD, DeviceNode, METHOD_NAME__INI));
620167802Sjkim
621167802Sjkim    Info->PrefixNode = DeviceNode;
622167802Sjkim    Info->Pathname = METHOD_NAME__INI;
623167802Sjkim    Info->Parameters = NULL;
624167802Sjkim    Info->Flags = ACPI_IGNORE_RETURN_VALUE;
625167802Sjkim
626167802Sjkim    Status = AcpiNsEvaluate (Info);
627167802Sjkim    if (ACPI_SUCCESS (Status))
62867754Smsmith    {
629167802Sjkim        WalkInfo->Num_INI++;
63077424Smsmith
631167802Sjkim        if ((AcpiDbgLevel <= ACPI_LV_ALL_EXCEPTIONS) &&
632167802Sjkim            (!(AcpiDbgLevel & ACPI_LV_INFO)))
63399679Siwasaki        {
634167802Sjkim            ACPI_DEBUG_PRINT_RAW ((ACPI_DB_INIT, "."));
635167802Sjkim        }
636167802Sjkim    }
63767754Smsmith
638129684Snjl#ifdef ACPI_DEBUG_OUTPUT
639167802Sjkim    else if (Status != AE_NOT_FOUND)
640167802Sjkim    {
641167802Sjkim        /* Ignore error and move on to next device */
64271867Smsmith
643167802Sjkim        char *ScopeName = AcpiNsGetExternalPathname (Info->ResolvedNode);
64467754Smsmith
645167802Sjkim        ACPI_EXCEPTION ((AE_INFO, Status, "during %s._INI execution",
646167802Sjkim            ScopeName));
647167802Sjkim        ACPI_FREE (ScopeName);
648167802Sjkim    }
649129684Snjl#endif
65067754Smsmith
651167802Sjkim    /* Ignore errors from above */
652140216Snjl
653167802Sjkim    Status = AE_OK;
654140216Snjl
655167802Sjkim    /*
656167802Sjkim     * The _INI method has been run if present; call the Global Initialization
657167802Sjkim     * Handler for this device.
658167802Sjkim     */
65999679Siwasaki    if (AcpiGbl_InitHandler)
66099679Siwasaki    {
661167802Sjkim        Status = AcpiGbl_InitHandler (DeviceNode, ACPI_INIT_DEVICE_INI);
66299679Siwasaki    }
66399679Siwasaki
66499679Siwasaki    return_ACPI_STATUS (Status);
66567754Smsmith}
666