167754Smsmith/******************************************************************************
267754Smsmith *
367754Smsmith * Module Name: nsinit - namespace initialization
467754Smsmith *
567754Smsmith *****************************************************************************/
667754Smsmith
7217365Sjkim/*
8306536Sjkim * Copyright (C) 2000 - 2016, 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>
49306536Sjkim#include <contrib/dev/acpica/include/acevents.h>
5067754Smsmith
5177424Smsmith#define _COMPONENT          ACPI_NAMESPACE
5291116Smsmith        ACPI_MODULE_NAME    ("nsinit")
5367754Smsmith
54151937Sjkim/* Local prototypes */
5567754Smsmith
56151937Sjkimstatic ACPI_STATUS
57151937SjkimAcpiNsInitOneObject (
58151937Sjkim    ACPI_HANDLE             ObjHandle,
59151937Sjkim    UINT32                  Level,
60151937Sjkim    void                    *Context,
61151937Sjkim    void                    **ReturnValue);
62151937Sjkim
63151937Sjkimstatic ACPI_STATUS
64151937SjkimAcpiNsInitOneDevice (
65151937Sjkim    ACPI_HANDLE             ObjHandle,
66151937Sjkim    UINT32                  NestingLevel,
67151937Sjkim    void                    *Context,
68151937Sjkim    void                    **ReturnValue);
69151937Sjkim
70167802Sjkimstatic ACPI_STATUS
71167802SjkimAcpiNsFindIniMethods (
72167802Sjkim    ACPI_HANDLE             ObjHandle,
73167802Sjkim    UINT32                  NestingLevel,
74167802Sjkim    void                    *Context,
75167802Sjkim    void                    **ReturnValue);
76151937Sjkim
77167802Sjkim
7867754Smsmith/*******************************************************************************
7967754Smsmith *
8067754Smsmith * FUNCTION:    AcpiNsInitializeObjects
8167754Smsmith *
8267754Smsmith * PARAMETERS:  None
8367754Smsmith *
8467754Smsmith * RETURN:      Status
8567754Smsmith *
8667754Smsmith * DESCRIPTION: Walk the entire namespace and perform any necessary
8767754Smsmith *              initialization on the objects found therein
8867754Smsmith *
8967754Smsmith ******************************************************************************/
9067754Smsmith
9167754SmsmithACPI_STATUS
9267754SmsmithAcpiNsInitializeObjects (
9367754Smsmith    void)
9467754Smsmith{
9567754Smsmith    ACPI_STATUS             Status;
9667754Smsmith    ACPI_INIT_WALK_INFO     Info;
9767754Smsmith
9867754Smsmith
99167802Sjkim    ACPI_FUNCTION_TRACE (NsInitializeObjects);
10067754Smsmith
10167754Smsmith
102306536Sjkim    ACPI_DEBUG_PRINT ((ACPI_DB_EXEC,
103306536Sjkim        "[Init] Completing Initialization of ACPI Objects\n"));
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
111306536Sjkim    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,
116306536Sjkim        ACPI_UINT32_MAX, AcpiNsInitOneObject, NULL,
117306536Sjkim        &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,
132281075Sdim        "%u Control Methods found\n%u Op Regions found\n",
133281075Sdim        Info.MethodCount, Info.OpRegionCount));
13467754Smsmith
13567754Smsmith    return_ACPI_STATUS (AE_OK);
13667754Smsmith}
13767754Smsmith
13867754Smsmith
13977424Smsmith/*******************************************************************************
14067754Smsmith *
14167754Smsmith * FUNCTION:    AcpiNsInitializeDevices
14267754Smsmith *
14367754Smsmith * PARAMETERS:  None
14467754Smsmith *
14567754Smsmith * RETURN:      ACPI_STATUS
14667754Smsmith *
14767754Smsmith * DESCRIPTION: Walk the entire namespace and initialize all ACPI devices.
14867754Smsmith *              This means running _INI on all present devices.
14967754Smsmith *
15077424Smsmith *              Note: We install PCI config space handler on region access,
15177424Smsmith *              not here.
15267754Smsmith *
15377424Smsmith ******************************************************************************/
15467754Smsmith
15567754SmsmithACPI_STATUS
15667754SmsmithAcpiNsInitializeDevices (
157306536Sjkim    UINT32                  Flags)
15867754Smsmith{
159306536Sjkim    ACPI_STATUS             Status = AE_OK;
16067754Smsmith    ACPI_DEVICE_WALK_INFO   Info;
161306536Sjkim    ACPI_HANDLE             Handle;
16267754Smsmith
16367754Smsmith
164167802Sjkim    ACPI_FUNCTION_TRACE (NsInitializeDevices);
16567754Smsmith
16667754Smsmith
167306536Sjkim    if (!(Flags & ACPI_NO_DEVICE_INIT))
168306536Sjkim    {
169306536Sjkim        ACPI_DEBUG_PRINT ((ACPI_DB_EXEC,
170306536Sjkim            "[Init] Initializing ACPI Devices\n"));
17199146Siwasaki
172306536Sjkim        /* Init counters */
17367754Smsmith
174306536Sjkim        Info.DeviceCount = 0;
175306536Sjkim        Info.Num_STA = 0;
176306536Sjkim        Info.Num_INI = 0;
17767754Smsmith
178306536Sjkim        ACPI_DEBUG_PRINT_RAW ((ACPI_DB_INIT,
179306536Sjkim            "Initializing Device/Processor/Thermal objects "
180306536Sjkim            "and executing _INI/_STA methods:\n"));
181167802Sjkim
182306536Sjkim        /* Tree analysis: find all subtrees that contain _INI methods */
18367754Smsmith
184306536Sjkim        Status = AcpiNsWalkNamespace (ACPI_TYPE_ANY, ACPI_ROOT_OBJECT,
185306536Sjkim            ACPI_UINT32_MAX, FALSE, AcpiNsFindIniMethods, NULL, &Info, NULL);
186306536Sjkim        if (ACPI_FAILURE (Status))
187306536Sjkim        {
188306536Sjkim            goto ErrorExit;
189306536Sjkim        }
19067754Smsmith
191306536Sjkim        /* Allocate the evaluation information block */
192167802Sjkim
193306536Sjkim        Info.EvaluateInfo = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_EVALUATE_INFO));
194306536Sjkim        if (!Info.EvaluateInfo)
195306536Sjkim        {
196306536Sjkim            Status = AE_NO_MEMORY;
197306536Sjkim            goto ErrorExit;
198306536Sjkim        }
199197104Sjkim
200306536Sjkim        /*
201306536Sjkim         * Execute the "global" _INI method that may appear at the root.
202306536Sjkim         * This support is provided for Windows compatibility (Vista+) and
203306536Sjkim         * is not part of the ACPI specification.
204306536Sjkim         */
205306536Sjkim        Info.EvaluateInfo->PrefixNode = AcpiGbl_RootNode;
206306536Sjkim        Info.EvaluateInfo->RelativePathname = METHOD_NAME__INI;
207306536Sjkim        Info.EvaluateInfo->Parameters = NULL;
208306536Sjkim        Info.EvaluateInfo->Flags = ACPI_IGNORE_RETURN_VALUE;
209197104Sjkim
210306536Sjkim        Status = AcpiNsEvaluate (Info.EvaluateInfo);
211306536Sjkim        if (ACPI_SUCCESS (Status))
212306536Sjkim        {
213306536Sjkim            Info.Num_INI++;
214306536Sjkim        }
215167802Sjkim
216306536Sjkim        /*
217306536Sjkim         * Execute \_SB._INI.
218306536Sjkim         * There appears to be a strict order requirement for \_SB._INI,
219306536Sjkim         * which should be evaluated before any _REG evaluations.
220306536Sjkim         */
221306536Sjkim        Status = AcpiGetHandle (NULL, "\\_SB", &Handle);
222306536Sjkim        if (ACPI_SUCCESS (Status))
223306536Sjkim        {
224306536Sjkim            memset (Info.EvaluateInfo, 0, sizeof (ACPI_EVALUATE_INFO));
225306536Sjkim            Info.EvaluateInfo->PrefixNode = Handle;
226306536Sjkim            Info.EvaluateInfo->RelativePathname = METHOD_NAME__INI;
227306536Sjkim            Info.EvaluateInfo->Parameters = NULL;
228306536Sjkim            Info.EvaluateInfo->Flags = ACPI_IGNORE_RETURN_VALUE;
229123315Snjl
230306536Sjkim            Status = AcpiNsEvaluate (Info.EvaluateInfo);
231306536Sjkim            if (ACPI_SUCCESS (Status))
232306536Sjkim            {
233306536Sjkim                Info.Num_INI++;
234306536Sjkim            }
235306536Sjkim        }
236306536Sjkim    }
237306536Sjkim
238209746Sjkim    /*
239306536Sjkim     * Run all _REG methods
240306536Sjkim     *
241306536Sjkim     * Note: Any objects accessed by the _REG methods will be automatically
242306536Sjkim     * initialized, even if they contain executable AML (see the call to
243306536Sjkim     * AcpiNsInitializeObjects below).
244306536Sjkim     *
245306536Sjkim     * Note: According to the ACPI specification, we actually needn't execute
246306536Sjkim     * _REG for SystemMemory/SystemIo operation regions, but for PCI_Config
247306536Sjkim     * operation regions, it is required to evaluate _REG for those on a PCI
248306536Sjkim     * root bus that doesn't contain _BBN object. So this code is kept here
249306536Sjkim     * in order not to break things.
250209746Sjkim     */
251306536Sjkim    if (!(Flags & ACPI_NO_ADDRESS_SPACE_INIT))
252209746Sjkim    {
253306536Sjkim        ACPI_DEBUG_PRINT ((ACPI_DB_EXEC,
254306536Sjkim            "[Init] Executing _REG OpRegion methods\n"));
255306536Sjkim
256306536Sjkim        Status = AcpiEvInitializeOpRegions ();
257306536Sjkim        if (ACPI_FAILURE (Status))
258306536Sjkim        {
259306536Sjkim            goto ErrorExit;
260306536Sjkim        }
261209746Sjkim    }
262209746Sjkim
263306536Sjkim    if (!(Flags & ACPI_NO_DEVICE_INIT))
26467754Smsmith    {
265306536Sjkim        /* Walk namespace to execute all _INIs on present devices */
266306536Sjkim
267306536Sjkim        Status = AcpiNsWalkNamespace (ACPI_TYPE_ANY, ACPI_ROOT_OBJECT,
268306536Sjkim            ACPI_UINT32_MAX, FALSE, AcpiNsInitOneDevice, NULL, &Info, NULL);
269306536Sjkim
270306536Sjkim        /*
271306536Sjkim         * Any _OSI requests should be completed by now. If the BIOS has
272306536Sjkim         * requested any Windows OSI strings, we will always truncate
273306536Sjkim         * I/O addresses to 16 bits -- for Windows compatibility.
274306536Sjkim         */
275306536Sjkim        if (AcpiGbl_OsiData >= ACPI_OSI_WIN_2000)
276306536Sjkim        {
277306536Sjkim            AcpiGbl_TruncateIoAddresses = TRUE;
278306536Sjkim        }
279306536Sjkim
280306536Sjkim        ACPI_FREE (Info.EvaluateInfo);
281306536Sjkim        if (ACPI_FAILURE (Status))
282306536Sjkim        {
283306536Sjkim            goto ErrorExit;
284306536Sjkim        }
285306536Sjkim
286306536Sjkim        ACPI_DEBUG_PRINT_RAW ((ACPI_DB_INIT,
287306536Sjkim            "    Executed %u _INI methods requiring %u _STA executions "
288306536Sjkim            "(examined %u objects)\n",
289306536Sjkim            Info.Num_INI, Info.Num_STA, Info.DeviceCount));
29067754Smsmith    }
29167754Smsmith
29267754Smsmith    return_ACPI_STATUS (Status);
293167802Sjkim
294167802Sjkim
295167802SjkimErrorExit:
296167802Sjkim    ACPI_EXCEPTION ((AE_INFO, Status, "During device initialization"));
297167802Sjkim    return_ACPI_STATUS (Status);
29867754Smsmith}
29967754Smsmith
30067754Smsmith
30167754Smsmith/*******************************************************************************
30267754Smsmith *
30367754Smsmith * FUNCTION:    AcpiNsInitOneObject
30467754Smsmith *
30567754Smsmith * PARAMETERS:  ObjHandle       - Node
30667754Smsmith *              Level           - Current nesting level
30767754Smsmith *              Context         - Points to a init info struct
30867754Smsmith *              ReturnValue     - Not used
30967754Smsmith *
31067754Smsmith * RETURN:      Status
31167754Smsmith *
312241973Sjkim * DESCRIPTION: Callback from AcpiWalkNamespace. Invoked for every object
31367754Smsmith *              within the  namespace.
31467754Smsmith *
31567754Smsmith *              Currently, the only objects that require initialization are:
31667754Smsmith *              1) Methods
31767754Smsmith *              2) Op Regions
31867754Smsmith *
31967754Smsmith ******************************************************************************/
32067754Smsmith
321151937Sjkimstatic ACPI_STATUS
32267754SmsmithAcpiNsInitOneObject (
32367754Smsmith    ACPI_HANDLE             ObjHandle,
32467754Smsmith    UINT32                  Level,
32567754Smsmith    void                    *Context,
32667754Smsmith    void                    **ReturnValue)
32767754Smsmith{
32891116Smsmith    ACPI_OBJECT_TYPE        Type;
329167802Sjkim    ACPI_STATUS             Status = AE_OK;
33067754Smsmith    ACPI_INIT_WALK_INFO     *Info = (ACPI_INIT_WALK_INFO *) Context;
33167754Smsmith    ACPI_NAMESPACE_NODE     *Node = (ACPI_NAMESPACE_NODE *) ObjHandle;
33267754Smsmith    ACPI_OPERAND_OBJECT     *ObjDesc;
33367754Smsmith
33467754Smsmith
335167802Sjkim    ACPI_FUNCTION_NAME (NsInitOneObject);
33682367Smsmith
33782367Smsmith
33867754Smsmith    Info->ObjectCount++;
33967754Smsmith
34067754Smsmith    /* And even then, we are only interested in a few object types */
34167754Smsmith
34267754Smsmith    Type = AcpiNsGetType (ObjHandle);
34387031Smsmith    ObjDesc = AcpiNsGetAttachedObject (Node);
34467754Smsmith    if (!ObjDesc)
34567754Smsmith    {
34667754Smsmith        return (AE_OK);
34767754Smsmith    }
34867754Smsmith
34999146Siwasaki    /* Increment counters for object types we are looking for */
35099146Siwasaki
35199146Siwasaki    switch (Type)
35280062Smsmith    {
35399146Siwasaki    case ACPI_TYPE_REGION:
354250838Sjkim
35599146Siwasaki        Info->OpRegionCount++;
35699146Siwasaki        break;
35799146Siwasaki
35899146Siwasaki    case ACPI_TYPE_BUFFER_FIELD:
359250838Sjkim
36099146Siwasaki        Info->FieldCount++;
36199146Siwasaki        break;
36299146Siwasaki
363193267Sjkim    case ACPI_TYPE_LOCAL_BANK_FIELD:
364250838Sjkim
365193267Sjkim        Info->FieldCount++;
366193267Sjkim        break;
367193267Sjkim
36899146Siwasaki    case ACPI_TYPE_BUFFER:
369250838Sjkim
37099146Siwasaki        Info->BufferCount++;
37199146Siwasaki        break;
37299146Siwasaki
37399146Siwasaki    case ACPI_TYPE_PACKAGE:
374250838Sjkim
37599146Siwasaki        Info->PackageCount++;
37699146Siwasaki        break;
37799146Siwasaki
37899146Siwasaki    default:
37999146Siwasaki
38099146Siwasaki        /* No init required, just exit now */
381250838Sjkim
38280062Smsmith        return (AE_OK);
38380062Smsmith    }
38480062Smsmith
385193267Sjkim    /* If the object is already initialized, nothing else to do */
386193267Sjkim
38799146Siwasaki    if (ObjDesc->Common.Flags & AOPOBJ_DATA_VALID)
38899146Siwasaki    {
38999146Siwasaki        return (AE_OK);
39099146Siwasaki    }
39180062Smsmith
392193267Sjkim    /* Must lock the interpreter before executing AML code */
393193267Sjkim
394167802Sjkim    AcpiExEnterInterpreter ();
39580062Smsmith
39699146Siwasaki    /*
397138287Smarks     * Each of these types can contain executable AML code within the
398138287Smarks     * declaration.
39999146Siwasaki     */
40067754Smsmith    switch (Type)
40167754Smsmith    {
40267754Smsmith    case ACPI_TYPE_REGION:
40367754Smsmith
40467754Smsmith        Info->OpRegionInit++;
40567754Smsmith        Status = AcpiDsGetRegionArguments (ObjDesc);
40667754Smsmith        break;
40767754Smsmith
40877424Smsmith    case ACPI_TYPE_BUFFER_FIELD:
40967754Smsmith
41067754Smsmith        Info->FieldInit++;
41177424Smsmith        Status = AcpiDsGetBufferFieldArguments (ObjDesc);
41299146Siwasaki        break;
41367754Smsmith
414193267Sjkim    case ACPI_TYPE_LOCAL_BANK_FIELD:
415193267Sjkim
416193267Sjkim        Info->FieldInit++;
417193267Sjkim        Status = AcpiDsGetBankFieldArguments (ObjDesc);
418193267Sjkim        break;
419193267Sjkim
42099146Siwasaki    case ACPI_TYPE_BUFFER:
42199146Siwasaki
42299146Siwasaki        Info->BufferInit++;
42399146Siwasaki        Status = AcpiDsGetBufferArguments (ObjDesc);
42467754Smsmith        break;
42567754Smsmith
42699146Siwasaki    case ACPI_TYPE_PACKAGE:
42799146Siwasaki
42899146Siwasaki        Info->PackageInit++;
42999146Siwasaki        Status = AcpiDsGetPackageArguments (ObjDesc);
43067754Smsmith        break;
43199679Siwasaki
43299679Siwasaki    default:
433250838Sjkim
43499679Siwasaki        /* No other types can get here */
435250838Sjkim
43699679Siwasaki        break;
43767754Smsmith    }
43867754Smsmith
43999146Siwasaki    if (ACPI_FAILURE (Status))
44099146Siwasaki    {
441167802Sjkim        ACPI_EXCEPTION ((AE_INFO, Status,
442167802Sjkim            "Could not execute arguments for [%4.4s] (%s)",
443167802Sjkim            AcpiUtGetNodeName (Node), AcpiUtGetTypeName (Type)));
44499146Siwasaki    }
44580062Smsmith
446138287Smarks    /*
447138287Smarks     * We ignore errors from above, and always return OK, since we don't want
448138287Smarks     * to abort the walk on any single error.
44967754Smsmith     */
45080062Smsmith    AcpiExExitInterpreter ();
45167754Smsmith    return (AE_OK);
45267754Smsmith}
45367754Smsmith
45467754Smsmith
45577424Smsmith/*******************************************************************************
45667754Smsmith *
457167802Sjkim * FUNCTION:    AcpiNsFindIniMethods
458167802Sjkim *
459167802Sjkim * PARAMETERS:  ACPI_WALK_CALLBACK
460167802Sjkim *
461167802Sjkim * RETURN:      ACPI_STATUS
462167802Sjkim *
463167802Sjkim * DESCRIPTION: Called during namespace walk. Finds objects named _INI under
464167802Sjkim *              device/processor/thermal objects, and marks the entire subtree
465167802Sjkim *              with a SUBTREE_HAS_INI flag. This flag is used during the
466167802Sjkim *              subsequent device initialization walk to avoid entire subtrees
467167802Sjkim *              that do not contain an _INI.
468167802Sjkim *
469167802Sjkim ******************************************************************************/
470167802Sjkim
471167802Sjkimstatic ACPI_STATUS
472167802SjkimAcpiNsFindIniMethods (
473167802Sjkim    ACPI_HANDLE             ObjHandle,
474167802Sjkim    UINT32                  NestingLevel,
475167802Sjkim    void                    *Context,
476167802Sjkim    void                    **ReturnValue)
477167802Sjkim{
478167802Sjkim    ACPI_DEVICE_WALK_INFO   *Info = ACPI_CAST_PTR (ACPI_DEVICE_WALK_INFO, Context);
479167802Sjkim    ACPI_NAMESPACE_NODE     *Node;
480167802Sjkim    ACPI_NAMESPACE_NODE     *ParentNode;
481167802Sjkim
482167802Sjkim
483167802Sjkim    /* Keep count of device/processor/thermal objects */
484167802Sjkim
485167802Sjkim    Node = ACPI_CAST_PTR (ACPI_NAMESPACE_NODE, ObjHandle);
486167802Sjkim    if ((Node->Type == ACPI_TYPE_DEVICE)    ||
487167802Sjkim        (Node->Type == ACPI_TYPE_PROCESSOR) ||
488167802Sjkim        (Node->Type == ACPI_TYPE_THERMAL))
489167802Sjkim    {
490167802Sjkim        Info->DeviceCount++;
491167802Sjkim        return (AE_OK);
492167802Sjkim    }
493167802Sjkim
494167802Sjkim    /* We are only looking for methods named _INI */
495167802Sjkim
496167802Sjkim    if (!ACPI_COMPARE_NAME (Node->Name.Ascii, METHOD_NAME__INI))
497167802Sjkim    {
498167802Sjkim        return (AE_OK);
499167802Sjkim    }
500167802Sjkim
501167802Sjkim    /*
502167802Sjkim     * The only _INI methods that we care about are those that are
503167802Sjkim     * present under Device, Processor, and Thermal objects.
504167802Sjkim     */
505209746Sjkim    ParentNode = Node->Parent;
506167802Sjkim    switch (ParentNode->Type)
507167802Sjkim    {
508167802Sjkim    case ACPI_TYPE_DEVICE:
509167802Sjkim    case ACPI_TYPE_PROCESSOR:
510167802Sjkim    case ACPI_TYPE_THERMAL:
511167802Sjkim
512167802Sjkim        /* Mark parent and bubble up the INI present flag to the root */
513167802Sjkim
514167802Sjkim        while (ParentNode)
515167802Sjkim        {
516167802Sjkim            ParentNode->Flags |= ANOBJ_SUBTREE_HAS_INI;
517209746Sjkim            ParentNode = ParentNode->Parent;
518167802Sjkim        }
519167802Sjkim        break;
520167802Sjkim
521167802Sjkim    default:
522250838Sjkim
523167802Sjkim        break;
524167802Sjkim    }
525167802Sjkim
526167802Sjkim    return (AE_OK);
527167802Sjkim}
528167802Sjkim
529167802Sjkim
530167802Sjkim/*******************************************************************************
531167802Sjkim *
53267754Smsmith * FUNCTION:    AcpiNsInitOneDevice
53367754Smsmith *
53477424Smsmith * PARAMETERS:  ACPI_WALK_CALLBACK
53567754Smsmith *
53667754Smsmith * RETURN:      ACPI_STATUS
53767754Smsmith *
53867754Smsmith * DESCRIPTION: This is called once per device soon after ACPI is enabled
53967754Smsmith *              to initialize each device. It determines if the device is
54067754Smsmith *              present, and if so, calls _INI.
54167754Smsmith *
54277424Smsmith ******************************************************************************/
54367754Smsmith
544151937Sjkimstatic ACPI_STATUS
54567754SmsmithAcpiNsInitOneDevice (
54667754Smsmith    ACPI_HANDLE             ObjHandle,
54767754Smsmith    UINT32                  NestingLevel,
54867754Smsmith    void                    *Context,
54967754Smsmith    void                    **ReturnValue)
55067754Smsmith{
551167802Sjkim    ACPI_DEVICE_WALK_INFO   *WalkInfo = ACPI_CAST_PTR (ACPI_DEVICE_WALK_INFO, Context);
552167802Sjkim    ACPI_EVALUATE_INFO      *Info = WalkInfo->EvaluateInfo;
553129684Snjl    UINT32                  Flags;
55467754Smsmith    ACPI_STATUS             Status;
555167802Sjkim    ACPI_NAMESPACE_NODE     *DeviceNode;
55667754Smsmith
55767754Smsmith
558167802Sjkim    ACPI_FUNCTION_TRACE (NsInitOneDevice);
55967754Smsmith
56067754Smsmith
561167802Sjkim    /* We are interested in Devices, Processors and ThermalZones only */
562129684Snjl
563167802Sjkim    DeviceNode = ACPI_CAST_PTR (ACPI_NAMESPACE_NODE, ObjHandle);
564167802Sjkim    if ((DeviceNode->Type != ACPI_TYPE_DEVICE)    &&
565167802Sjkim        (DeviceNode->Type != ACPI_TYPE_PROCESSOR) &&
566167802Sjkim        (DeviceNode->Type != ACPI_TYPE_THERMAL))
56773561Smsmith    {
568167802Sjkim        return_ACPI_STATUS (AE_OK);
56973561Smsmith    }
57073561Smsmith
571123315Snjl    /*
572167802Sjkim     * Because of an earlier namespace analysis, all subtrees that contain an
573167802Sjkim     * _INI method are tagged.
574167802Sjkim     *
575167802Sjkim     * If this device subtree does not contain any _INI methods, we
576167802Sjkim     * can exit now and stop traversing this entire subtree.
577123315Snjl     */
578167802Sjkim    if (!(DeviceNode->Flags & ANOBJ_SUBTREE_HAS_INI))
57991116Smsmith    {
580167802Sjkim        return_ACPI_STATUS (AE_CTRL_DEPTH);
58191116Smsmith    }
58267754Smsmith
58367754Smsmith    /*
584167802Sjkim     * Run _STA to determine if this device is present and functioning. We
585167802Sjkim     * must know this information for two important reasons (from ACPI spec):
586167802Sjkim     *
587167802Sjkim     * 1) We can only run _INI if the device is present.
588167802Sjkim     * 2) We must abort the device tree walk on this subtree if the device is
589167802Sjkim     *    not present and is not functional (we will not examine the children)
590167802Sjkim     *
591167802Sjkim     * The _STA method is not required to be present under the device, we
592167802Sjkim     * assume the device is present if _STA does not exist.
59367754Smsmith     */
594167802Sjkim    ACPI_DEBUG_EXEC (AcpiUtDisplayInitPathname (
595167802Sjkim        ACPI_TYPE_METHOD, DeviceNode, METHOD_NAME__STA));
596123315Snjl
597167802Sjkim    Status = AcpiUtExecute_STA (DeviceNode, &Flags);
59867754Smsmith    if (ACPI_FAILURE (Status))
59967754Smsmith    {
600167802Sjkim        /* Ignore error and move on to next device */
60171867Smsmith
602167802Sjkim        return_ACPI_STATUS (AE_OK);
603167802Sjkim    }
604123315Snjl
605167802Sjkim    /*
606167802Sjkim     * Flags == -1 means that _STA was not found. In this case, we assume that
607167802Sjkim     * the device is both present and functional.
608167802Sjkim     *
609167802Sjkim     * From the ACPI spec, description of _STA:
610167802Sjkim     *
611167802Sjkim     * "If a device object (including the processor object) does not have an
612167802Sjkim     * _STA object, then OSPM assumes that all of the above bits are set (in
613167802Sjkim     * other words, the device is present, ..., and functioning)"
614167802Sjkim     */
615167802Sjkim    if (Flags != ACPI_UINT32_MAX)
616167802Sjkim    {
617167802Sjkim        WalkInfo->Num_STA++;
61867754Smsmith    }
619167802Sjkim
620167802Sjkim    /*
621167802Sjkim     * Examine the PRESENT and FUNCTIONING status bits
622167802Sjkim     *
623167802Sjkim     * Note: ACPI spec does not seem to specify behavior for the present but
624167802Sjkim     * not functioning case, so we assume functioning if present.
625167802Sjkim     */
626167802Sjkim    if (!(Flags & ACPI_STA_DEVICE_PRESENT))
627123315Snjl    {
628167802Sjkim        /* Device is not present, we must examine the Functioning bit */
62967754Smsmith
630167802Sjkim        if (Flags & ACPI_STA_DEVICE_FUNCTIONING)
631123315Snjl        {
632167802Sjkim            /*
633167802Sjkim             * Device is not present but is "functioning". In this case,
634167802Sjkim             * we will not run _INI, but we continue to examine the children
635167802Sjkim             * of this device.
636167802Sjkim             *
637167802Sjkim             * From the ACPI spec, description of _STA: (Note - no mention
638167802Sjkim             * of whether to run _INI or not on the device in question)
639167802Sjkim             *
640167802Sjkim             * "_STA may return bit 0 clear (not present) with bit 3 set
641167802Sjkim             * (device is functional). This case is used to indicate a valid
642167802Sjkim             * device for which no device driver should be loaded (for example,
643167802Sjkim             * a bridge device.) Children of this device may be present and
644167802Sjkim             * valid. OSPM should continue enumeration below a device whose
645167802Sjkim             * _STA returns this bit combination"
646167802Sjkim             */
647167802Sjkim            return_ACPI_STATUS (AE_OK);
648123315Snjl        }
649167802Sjkim        else
650167802Sjkim        {
651167802Sjkim            /*
652167802Sjkim             * Device is not present and is not functioning. We must abort the
653167802Sjkim             * walk of this subtree immediately -- don't look at the children
654167802Sjkim             * of such a device.
655167802Sjkim             *
656167802Sjkim             * From the ACPI spec, description of _INI:
657167802Sjkim             *
658167802Sjkim             * "If the _STA method indicates that the device is not present,
659167802Sjkim             * OSPM will not run the _INI and will not examine the children
660167802Sjkim             * of the device for _INI methods"
661167802Sjkim             */
662167802Sjkim            return_ACPI_STATUS (AE_CTRL_DEPTH);
663167802Sjkim        }
66467754Smsmith    }
66567754Smsmith
66667754Smsmith    /*
667167802Sjkim     * The device is present or is assumed present if no _STA exists.
668167802Sjkim     * Run the _INI if it exists (not required to exist)
669167802Sjkim     *
670167802Sjkim     * Note: We know there is an _INI within this subtree, but it may not be
671167802Sjkim     * under this particular device, it may be lower in the branch.
67267754Smsmith     */
673306536Sjkim    if (!ACPI_COMPARE_NAME (DeviceNode->Name.Ascii, "_SB_") ||
674306536Sjkim        DeviceNode->Parent != AcpiGbl_RootNode)
675306536Sjkim    {
676306536Sjkim        ACPI_DEBUG_EXEC (AcpiUtDisplayInitPathname (
677306536Sjkim            ACPI_TYPE_METHOD, DeviceNode, METHOD_NAME__INI));
678167802Sjkim
679306536Sjkim        memset (Info, 0, sizeof (ACPI_EVALUATE_INFO));
680306536Sjkim        Info->PrefixNode = DeviceNode;
681306536Sjkim        Info->RelativePathname = METHOD_NAME__INI;
682306536Sjkim        Info->Parameters = NULL;
683306536Sjkim        Info->Flags = ACPI_IGNORE_RETURN_VALUE;
684167802Sjkim
685306536Sjkim        Status = AcpiNsEvaluate (Info);
686306536Sjkim        if (ACPI_SUCCESS (Status))
687306536Sjkim        {
688306536Sjkim            WalkInfo->Num_INI++;
689306536Sjkim        }
69067754Smsmith
691129684Snjl#ifdef ACPI_DEBUG_OUTPUT
692306536Sjkim        else if (Status != AE_NOT_FOUND)
693306536Sjkim        {
694306536Sjkim            /* Ignore error and move on to next device */
69571867Smsmith
696306536Sjkim            char *ScopeName = AcpiNsGetNormalizedPathname (DeviceNode, TRUE);
69767754Smsmith
698306536Sjkim            ACPI_EXCEPTION ((AE_INFO, Status, "during %s._INI execution",
699306536Sjkim                ScopeName));
700306536Sjkim            ACPI_FREE (ScopeName);
701306536Sjkim        }
702306536Sjkim#endif
703167802Sjkim    }
70467754Smsmith
705167802Sjkim    /* Ignore errors from above */
706140216Snjl
707167802Sjkim    Status = AE_OK;
708140216Snjl
709167802Sjkim    /*
710167802Sjkim     * The _INI method has been run if present; call the Global Initialization
711167802Sjkim     * Handler for this device.
712167802Sjkim     */
71399679Siwasaki    if (AcpiGbl_InitHandler)
71499679Siwasaki    {
715167802Sjkim        Status = AcpiGbl_InitHandler (DeviceNode, ACPI_INIT_DEVICE_INI);
71699679Siwasaki    }
71799679Siwasaki
71899679Siwasaki    return_ACPI_STATUS (Status);
71967754Smsmith}
720