xref: /netbsd-src/sys/external/bsd/acpica/dist/namespace/nsinit.c (revision 2c7d7e3ca2e4f0b675c6c58e614f6aede66c678e)
128c506b8Sjruoho /******************************************************************************
228c506b8Sjruoho  *
328c506b8Sjruoho  * Module Name: nsinit - namespace initialization
428c506b8Sjruoho  *
528c506b8Sjruoho  *****************************************************************************/
628c506b8Sjruoho 
7159c4e26Sjruoho /*
8*2c7d7e3cSchristos  * Copyright (C) 2000 - 2023, Intel Corp.
928c506b8Sjruoho  * All rights reserved.
1028c506b8Sjruoho  *
11159c4e26Sjruoho  * Redistribution and use in source and binary forms, with or without
12159c4e26Sjruoho  * modification, are permitted provided that the following conditions
13159c4e26Sjruoho  * are met:
14159c4e26Sjruoho  * 1. Redistributions of source code must retain the above copyright
15159c4e26Sjruoho  *    notice, this list of conditions, and the following disclaimer,
16159c4e26Sjruoho  *    without modification.
17159c4e26Sjruoho  * 2. Redistributions in binary form must reproduce at minimum a disclaimer
18159c4e26Sjruoho  *    substantially similar to the "NO WARRANTY" disclaimer below
19159c4e26Sjruoho  *    ("Disclaimer") and any redistribution must be conditioned upon
20159c4e26Sjruoho  *    including a substantially similar Disclaimer requirement for further
21159c4e26Sjruoho  *    binary redistribution.
22159c4e26Sjruoho  * 3. Neither the names of the above-listed copyright holders nor the names
23159c4e26Sjruoho  *    of any contributors may be used to endorse or promote products derived
24159c4e26Sjruoho  *    from this software without specific prior written permission.
2528c506b8Sjruoho  *
26159c4e26Sjruoho  * Alternatively, this software may be distributed under the terms of the
27159c4e26Sjruoho  * GNU General Public License ("GPL") version 2 as published by the Free
28159c4e26Sjruoho  * Software Foundation.
2928c506b8Sjruoho  *
30159c4e26Sjruoho  * NO WARRANTY
31159c4e26Sjruoho  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32159c4e26Sjruoho  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
3398244dcfSchristos  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
34159c4e26Sjruoho  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
35159c4e26Sjruoho  * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36159c4e26Sjruoho  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37159c4e26Sjruoho  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38159c4e26Sjruoho  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39159c4e26Sjruoho  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
40159c4e26Sjruoho  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41159c4e26Sjruoho  * POSSIBILITY OF SUCH DAMAGES.
42159c4e26Sjruoho  */
4328c506b8Sjruoho 
4428c506b8Sjruoho #include "acpi.h"
4528c506b8Sjruoho #include "accommon.h"
4628c506b8Sjruoho #include "acnamesp.h"
4728c506b8Sjruoho #include "acdispat.h"
4828c506b8Sjruoho #include "acinterp.h"
4949c2f1f4Schristos #include "acevents.h"
5028c506b8Sjruoho 
5128c506b8Sjruoho #define _COMPONENT          ACPI_NAMESPACE
5228c506b8Sjruoho         ACPI_MODULE_NAME    ("nsinit")
5328c506b8Sjruoho 
5428c506b8Sjruoho /* Local prototypes */
5528c506b8Sjruoho 
5628c506b8Sjruoho static ACPI_STATUS
5728c506b8Sjruoho AcpiNsInitOneObject (
5828c506b8Sjruoho     ACPI_HANDLE             ObjHandle,
5928c506b8Sjruoho     UINT32                  Level,
6028c506b8Sjruoho     void                    *Context,
6128c506b8Sjruoho     void                    **ReturnValue);
6228c506b8Sjruoho 
6328c506b8Sjruoho static ACPI_STATUS
6428c506b8Sjruoho AcpiNsInitOneDevice (
6528c506b8Sjruoho     ACPI_HANDLE             ObjHandle,
6628c506b8Sjruoho     UINT32                  NestingLevel,
6728c506b8Sjruoho     void                    *Context,
6828c506b8Sjruoho     void                    **ReturnValue);
6928c506b8Sjruoho 
7028c506b8Sjruoho static ACPI_STATUS
7128c506b8Sjruoho AcpiNsFindIniMethods (
7228c506b8Sjruoho     ACPI_HANDLE             ObjHandle,
7328c506b8Sjruoho     UINT32                  NestingLevel,
7428c506b8Sjruoho     void                    *Context,
7528c506b8Sjruoho     void                    **ReturnValue);
7628c506b8Sjruoho 
7728c506b8Sjruoho 
7828c506b8Sjruoho /*******************************************************************************
7928c506b8Sjruoho  *
8028c506b8Sjruoho  * FUNCTION:    AcpiNsInitializeObjects
8128c506b8Sjruoho  *
8228c506b8Sjruoho  * PARAMETERS:  None
8328c506b8Sjruoho  *
8428c506b8Sjruoho  * RETURN:      Status
8528c506b8Sjruoho  *
8628c506b8Sjruoho  * DESCRIPTION: Walk the entire namespace and perform any necessary
8728c506b8Sjruoho  *              initialization on the objects found therein
8828c506b8Sjruoho  *
8928c506b8Sjruoho  ******************************************************************************/
9028c506b8Sjruoho 
9128c506b8Sjruoho ACPI_STATUS
AcpiNsInitializeObjects(void)9228c506b8Sjruoho AcpiNsInitializeObjects (
9328c506b8Sjruoho     void)
9428c506b8Sjruoho {
9528c506b8Sjruoho     ACPI_STATUS             Status;
9628c506b8Sjruoho     ACPI_INIT_WALK_INFO     Info;
9728c506b8Sjruoho 
9828c506b8Sjruoho 
9928c506b8Sjruoho     ACPI_FUNCTION_TRACE (NsInitializeObjects);
10028c506b8Sjruoho 
10128c506b8Sjruoho 
10249c2f1f4Schristos     ACPI_DEBUG_PRINT ((ACPI_DB_EXEC,
10349c2f1f4Schristos         "[Init] Completing Initialization of ACPI Objects\n"));
10428c506b8Sjruoho     ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
10528c506b8Sjruoho         "**** Starting initialization of namespace objects ****\n"));
10628c506b8Sjruoho     ACPI_DEBUG_PRINT_RAW ((ACPI_DB_INIT,
1077ab6b89bSchristos         "Final data object initialization: "));
10828c506b8Sjruoho 
1097ab6b89bSchristos     /* Clear the info block */
11028c506b8Sjruoho 
1119b9ee194Schristos     memset (&Info, 0, sizeof (ACPI_INIT_WALK_INFO));
11228c506b8Sjruoho 
11328c506b8Sjruoho     /* Walk entire namespace from the supplied root */
11428c506b8Sjruoho 
1157ab6b89bSchristos     /*
1167ab6b89bSchristos      * TBD: will become ACPI_TYPE_PACKAGE as this type object
1177ab6b89bSchristos      * is now the only one that supports deferred initialization
1187ab6b89bSchristos      * (forward references).
1197ab6b89bSchristos      */
12028c506b8Sjruoho     Status = AcpiWalkNamespace (ACPI_TYPE_ANY, ACPI_ROOT_OBJECT,
1217ab6b89bSchristos         ACPI_UINT32_MAX, AcpiNsInitOneObject, NULL, &Info, NULL);
12228c506b8Sjruoho     if (ACPI_FAILURE (Status))
12328c506b8Sjruoho     {
12428c506b8Sjruoho         ACPI_EXCEPTION ((AE_INFO, Status, "During WalkNamespace"));
12528c506b8Sjruoho     }
12628c506b8Sjruoho 
12728c506b8Sjruoho     ACPI_DEBUG_PRINT_RAW ((ACPI_DB_INIT,
1287ab6b89bSchristos         "Namespace contains %u (0x%X) objects\n",
1297ab6b89bSchristos         Info.ObjectCount,
1307ab6b89bSchristos         Info.ObjectCount));
13128c506b8Sjruoho 
13228c506b8Sjruoho     ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
133414ef032Schristos         "%u Control Methods found\n%u Op Regions found\n",
134414ef032Schristos         Info.MethodCount, Info.OpRegionCount));
13528c506b8Sjruoho 
13628c506b8Sjruoho     return_ACPI_STATUS (AE_OK);
13728c506b8Sjruoho }
13828c506b8Sjruoho 
13928c506b8Sjruoho 
14028c506b8Sjruoho /*******************************************************************************
14128c506b8Sjruoho  *
14228c506b8Sjruoho  * FUNCTION:    AcpiNsInitializeDevices
14328c506b8Sjruoho  *
14428c506b8Sjruoho  * PARAMETERS:  None
14528c506b8Sjruoho  *
14628c506b8Sjruoho  * RETURN:      ACPI_STATUS
14728c506b8Sjruoho  *
14828c506b8Sjruoho  * DESCRIPTION: Walk the entire namespace and initialize all ACPI devices.
14928c506b8Sjruoho  *              This means running _INI on all present devices.
15028c506b8Sjruoho  *
15128c506b8Sjruoho  *              Note: We install PCI config space handler on region access,
15228c506b8Sjruoho  *              not here.
15328c506b8Sjruoho  *
15428c506b8Sjruoho  ******************************************************************************/
15528c506b8Sjruoho 
15628c506b8Sjruoho ACPI_STATUS
AcpiNsInitializeDevices(UINT32 Flags)15728c506b8Sjruoho AcpiNsInitializeDevices (
15849c2f1f4Schristos     UINT32                  Flags)
15928c506b8Sjruoho {
16049c2f1f4Schristos     ACPI_STATUS             Status = AE_OK;
16128c506b8Sjruoho     ACPI_DEVICE_WALK_INFO   Info;
16249c2f1f4Schristos     ACPI_HANDLE             Handle;
16328c506b8Sjruoho 
16428c506b8Sjruoho 
16528c506b8Sjruoho     ACPI_FUNCTION_TRACE (NsInitializeDevices);
16628c506b8Sjruoho 
16728c506b8Sjruoho 
16849c2f1f4Schristos     if (!(Flags & ACPI_NO_DEVICE_INIT))
16949c2f1f4Schristos     {
17049c2f1f4Schristos         ACPI_DEBUG_PRINT ((ACPI_DB_EXEC,
17149c2f1f4Schristos             "[Init] Initializing ACPI Devices\n"));
17249c2f1f4Schristos 
17328c506b8Sjruoho         /* Init counters */
17428c506b8Sjruoho 
17528c506b8Sjruoho         Info.DeviceCount = 0;
17628c506b8Sjruoho         Info.Num_STA = 0;
17728c506b8Sjruoho         Info.Num_INI = 0;
17828c506b8Sjruoho 
17928c506b8Sjruoho         ACPI_DEBUG_PRINT_RAW ((ACPI_DB_INIT,
18028c506b8Sjruoho             "Initializing Device/Processor/Thermal objects "
181a2c051a9Schristos             "and executing _INI/_STA methods:\n"));
18228c506b8Sjruoho 
18328c506b8Sjruoho         /* Tree analysis: find all subtrees that contain _INI methods */
18428c506b8Sjruoho 
18528c506b8Sjruoho         Status = AcpiNsWalkNamespace (ACPI_TYPE_ANY, ACPI_ROOT_OBJECT,
18628c506b8Sjruoho             ACPI_UINT32_MAX, FALSE, AcpiNsFindIniMethods, NULL, &Info, NULL);
18728c506b8Sjruoho         if (ACPI_FAILURE (Status))
18828c506b8Sjruoho         {
18928c506b8Sjruoho             goto ErrorExit;
19028c506b8Sjruoho         }
19128c506b8Sjruoho 
19228c506b8Sjruoho         /* Allocate the evaluation information block */
19328c506b8Sjruoho 
19428c506b8Sjruoho         Info.EvaluateInfo = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_EVALUATE_INFO));
19528c506b8Sjruoho         if (!Info.EvaluateInfo)
19628c506b8Sjruoho         {
19728c506b8Sjruoho             Status = AE_NO_MEMORY;
19828c506b8Sjruoho             goto ErrorExit;
19928c506b8Sjruoho         }
20028c506b8Sjruoho 
20128c506b8Sjruoho         /*
20249c2f1f4Schristos          * Execute the "global" _INI method that may appear at the root.
20349c2f1f4Schristos          * This support is provided for Windows compatibility (Vista+) and
20449c2f1f4Schristos          * is not part of the ACPI specification.
20528c506b8Sjruoho          */
20628c506b8Sjruoho         Info.EvaluateInfo->PrefixNode = AcpiGbl_RootNode;
20749c2f1f4Schristos         Info.EvaluateInfo->RelativePathname = METHOD_NAME__INI;
20828c506b8Sjruoho         Info.EvaluateInfo->Parameters = NULL;
20928c506b8Sjruoho         Info.EvaluateInfo->Flags = ACPI_IGNORE_RETURN_VALUE;
21028c506b8Sjruoho 
21128c506b8Sjruoho         Status = AcpiNsEvaluate (Info.EvaluateInfo);
21228c506b8Sjruoho         if (ACPI_SUCCESS (Status))
21328c506b8Sjruoho         {
21428c506b8Sjruoho             Info.Num_INI++;
21528c506b8Sjruoho         }
21628c506b8Sjruoho 
21749c2f1f4Schristos         /*
21849c2f1f4Schristos          * Execute \_SB._INI.
21949c2f1f4Schristos          * There appears to be a strict order requirement for \_SB._INI,
22049c2f1f4Schristos          * which should be evaluated before any _REG evaluations.
22149c2f1f4Schristos          */
22249c2f1f4Schristos         Status = AcpiGetHandle (NULL, "\\_SB", &Handle);
22349c2f1f4Schristos         if (ACPI_SUCCESS (Status))
22449c2f1f4Schristos         {
22549c2f1f4Schristos             memset (Info.EvaluateInfo, 0, sizeof (ACPI_EVALUATE_INFO));
22649c2f1f4Schristos             Info.EvaluateInfo->PrefixNode = Handle;
22749c2f1f4Schristos             Info.EvaluateInfo->RelativePathname = METHOD_NAME__INI;
22849c2f1f4Schristos             Info.EvaluateInfo->Parameters = NULL;
22949c2f1f4Schristos             Info.EvaluateInfo->Flags = ACPI_IGNORE_RETURN_VALUE;
23049c2f1f4Schristos 
23149c2f1f4Schristos             Status = AcpiNsEvaluate (Info.EvaluateInfo);
23249c2f1f4Schristos             if (ACPI_SUCCESS (Status))
23349c2f1f4Schristos             {
23449c2f1f4Schristos                 Info.Num_INI++;
23549c2f1f4Schristos             }
23649c2f1f4Schristos         }
23749c2f1f4Schristos     }
23849c2f1f4Schristos 
23949c2f1f4Schristos     /*
24049c2f1f4Schristos      * Run all _REG methods
24149c2f1f4Schristos      *
24249c2f1f4Schristos      * Note: Any objects accessed by the _REG methods will be automatically
24349c2f1f4Schristos      * initialized, even if they contain executable AML (see the call to
24449c2f1f4Schristos      * AcpiNsInitializeObjects below).
24549c2f1f4Schristos      *
24649c2f1f4Schristos      * Note: According to the ACPI specification, we actually needn't execute
24749c2f1f4Schristos      * _REG for SystemMemory/SystemIo operation regions, but for PCI_Config
24849c2f1f4Schristos      * operation regions, it is required to evaluate _REG for those on a PCI
24949c2f1f4Schristos      * root bus that doesn't contain _BBN object. So this code is kept here
25049c2f1f4Schristos      * in order not to break things.
25149c2f1f4Schristos      */
25249c2f1f4Schristos     if (!(Flags & ACPI_NO_ADDRESS_SPACE_INIT))
25349c2f1f4Schristos     {
25449c2f1f4Schristos         ACPI_DEBUG_PRINT ((ACPI_DB_EXEC,
25549c2f1f4Schristos             "[Init] Executing _REG OpRegion methods\n"));
25649c2f1f4Schristos 
25749c2f1f4Schristos         Status = AcpiEvInitializeOpRegions ();
25849c2f1f4Schristos         if (ACPI_FAILURE (Status))
25949c2f1f4Schristos         {
26049c2f1f4Schristos             goto ErrorExit;
26149c2f1f4Schristos         }
26249c2f1f4Schristos     }
26349c2f1f4Schristos 
26449c2f1f4Schristos     if (!(Flags & ACPI_NO_DEVICE_INIT))
26549c2f1f4Schristos     {
26628c506b8Sjruoho         /* Walk namespace to execute all _INIs on present devices */
26728c506b8Sjruoho 
26828c506b8Sjruoho         Status = AcpiNsWalkNamespace (ACPI_TYPE_ANY, ACPI_ROOT_OBJECT,
26928c506b8Sjruoho             ACPI_UINT32_MAX, FALSE, AcpiNsInitOneDevice, NULL, &Info, NULL);
27028c506b8Sjruoho 
27128c506b8Sjruoho         /*
27228c506b8Sjruoho          * Any _OSI requests should be completed by now. If the BIOS has
27328c506b8Sjruoho          * requested any Windows OSI strings, we will always truncate
27428c506b8Sjruoho          * I/O addresses to 16 bits -- for Windows compatibility.
27528c506b8Sjruoho          */
27628c506b8Sjruoho         if (AcpiGbl_OsiData >= ACPI_OSI_WIN_2000)
27728c506b8Sjruoho         {
27828c506b8Sjruoho             AcpiGbl_TruncateIoAddresses = TRUE;
27928c506b8Sjruoho         }
28028c506b8Sjruoho 
28128c506b8Sjruoho         ACPI_FREE (Info.EvaluateInfo);
28228c506b8Sjruoho         if (ACPI_FAILURE (Status))
28328c506b8Sjruoho         {
28428c506b8Sjruoho             goto ErrorExit;
28528c506b8Sjruoho         }
28628c506b8Sjruoho 
28728c506b8Sjruoho         ACPI_DEBUG_PRINT_RAW ((ACPI_DB_INIT,
288a2c051a9Schristos             "    Executed %u _INI methods requiring %u _STA executions "
28928c506b8Sjruoho             "(examined %u objects)\n",
29028c506b8Sjruoho             Info.Num_INI, Info.Num_STA, Info.DeviceCount));
29149c2f1f4Schristos     }
29228c506b8Sjruoho 
29328c506b8Sjruoho     return_ACPI_STATUS (Status);
29428c506b8Sjruoho 
29528c506b8Sjruoho 
29628c506b8Sjruoho ErrorExit:
29728c506b8Sjruoho     ACPI_EXCEPTION ((AE_INFO, Status, "During device initialization"));
29828c506b8Sjruoho     return_ACPI_STATUS (Status);
29928c506b8Sjruoho }
30028c506b8Sjruoho 
30128c506b8Sjruoho 
30228c506b8Sjruoho /*******************************************************************************
30328c506b8Sjruoho  *
304a147b75fSchristos  * FUNCTION:    AcpiNsInitOnePackage
305a147b75fSchristos  *
306a147b75fSchristos  * PARAMETERS:  ObjHandle       - Node
307a147b75fSchristos  *              Level           - Current nesting level
308a147b75fSchristos  *              Context         - Not used
309a147b75fSchristos  *              ReturnValue     - Not used
310a147b75fSchristos  *
311a147b75fSchristos  * RETURN:      Status
312a147b75fSchristos  *
313a147b75fSchristos  * DESCRIPTION: Callback from AcpiWalkNamespace. Invoked for every package
314a147b75fSchristos  *              within the namespace. Used during dynamic load of an SSDT.
315a147b75fSchristos  *
316a147b75fSchristos  ******************************************************************************/
317a147b75fSchristos 
318a147b75fSchristos ACPI_STATUS
AcpiNsInitOnePackage(ACPI_HANDLE ObjHandle,UINT32 Level,void * Context,void ** ReturnValue)319a147b75fSchristos AcpiNsInitOnePackage (
320a147b75fSchristos     ACPI_HANDLE             ObjHandle,
321a147b75fSchristos     UINT32                  Level,
322a147b75fSchristos     void                    *Context,
323a147b75fSchristos     void                    **ReturnValue)
324a147b75fSchristos {
325a147b75fSchristos     ACPI_STATUS             Status;
326a147b75fSchristos     ACPI_OPERAND_OBJECT     *ObjDesc;
327a147b75fSchristos     ACPI_NAMESPACE_NODE     *Node = (ACPI_NAMESPACE_NODE *) ObjHandle;
328a147b75fSchristos 
329a147b75fSchristos 
330a147b75fSchristos     ObjDesc = AcpiNsGetAttachedObject (Node);
331a147b75fSchristos     if (!ObjDesc)
332a147b75fSchristos     {
333a147b75fSchristos         return (AE_OK);
334a147b75fSchristos     }
335a147b75fSchristos 
336a147b75fSchristos     /* Exit if package is already initialized */
337a147b75fSchristos 
338a147b75fSchristos     if (ObjDesc->Package.Flags & AOPOBJ_DATA_VALID)
339a147b75fSchristos     {
340a147b75fSchristos         return (AE_OK);
341a147b75fSchristos     }
342a147b75fSchristos 
343a147b75fSchristos     Status = AcpiDsGetPackageArguments (ObjDesc);
344a147b75fSchristos     if (ACPI_FAILURE (Status))
345a147b75fSchristos     {
346a147b75fSchristos         return (AE_OK);
347a147b75fSchristos     }
348a147b75fSchristos 
349a147b75fSchristos     Status = AcpiUtWalkPackageTree (ObjDesc, NULL, AcpiDsInitPackageElement,
350a147b75fSchristos         NULL);
351a147b75fSchristos     if (ACPI_FAILURE (Status))
352a147b75fSchristos     {
353a147b75fSchristos         return (AE_OK);
354a147b75fSchristos     }
355a147b75fSchristos 
356a147b75fSchristos     ObjDesc->Package.Flags |= AOPOBJ_DATA_VALID;
357a147b75fSchristos     return (AE_OK);
358a147b75fSchristos }
359a147b75fSchristos 
360a147b75fSchristos 
361a147b75fSchristos /*******************************************************************************
362a147b75fSchristos  *
36328c506b8Sjruoho  * FUNCTION:    AcpiNsInitOneObject
36428c506b8Sjruoho  *
36528c506b8Sjruoho  * PARAMETERS:  ObjHandle       - Node
36628c506b8Sjruoho  *              Level           - Current nesting level
36728c506b8Sjruoho  *              Context         - Points to a init info struct
36828c506b8Sjruoho  *              ReturnValue     - Not used
36928c506b8Sjruoho  *
37028c506b8Sjruoho  * RETURN:      Status
37128c506b8Sjruoho  *
37228c506b8Sjruoho  * DESCRIPTION: Callback from AcpiWalkNamespace. Invoked for every object
37328c506b8Sjruoho  *              within the namespace.
37428c506b8Sjruoho  *
37528c506b8Sjruoho  *              Currently, the only objects that require initialization are:
37628c506b8Sjruoho  *              1) Methods
37728c506b8Sjruoho  *              2) Op Regions
37828c506b8Sjruoho  *
37928c506b8Sjruoho  ******************************************************************************/
38028c506b8Sjruoho 
38128c506b8Sjruoho static ACPI_STATUS
AcpiNsInitOneObject(ACPI_HANDLE ObjHandle,UINT32 Level,void * Context,void ** ReturnValue)38228c506b8Sjruoho AcpiNsInitOneObject (
38328c506b8Sjruoho     ACPI_HANDLE             ObjHandle,
38428c506b8Sjruoho     UINT32                  Level,
38528c506b8Sjruoho     void                    *Context,
38628c506b8Sjruoho     void                    **ReturnValue)
38728c506b8Sjruoho {
38828c506b8Sjruoho     ACPI_OBJECT_TYPE        Type;
38928c506b8Sjruoho     ACPI_STATUS             Status = AE_OK;
39028c506b8Sjruoho     ACPI_INIT_WALK_INFO     *Info = (ACPI_INIT_WALK_INFO *) Context;
39128c506b8Sjruoho     ACPI_NAMESPACE_NODE     *Node = (ACPI_NAMESPACE_NODE *) ObjHandle;
39228c506b8Sjruoho     ACPI_OPERAND_OBJECT     *ObjDesc;
39328c506b8Sjruoho 
39428c506b8Sjruoho 
39528c506b8Sjruoho     ACPI_FUNCTION_NAME (NsInitOneObject);
39628c506b8Sjruoho 
39728c506b8Sjruoho 
39828c506b8Sjruoho     Info->ObjectCount++;
39928c506b8Sjruoho 
40028c506b8Sjruoho     /* And even then, we are only interested in a few object types */
40128c506b8Sjruoho 
40228c506b8Sjruoho     Type = AcpiNsGetType (ObjHandle);
40328c506b8Sjruoho     ObjDesc = AcpiNsGetAttachedObject (Node);
40428c506b8Sjruoho     if (!ObjDesc)
40528c506b8Sjruoho     {
40628c506b8Sjruoho         return (AE_OK);
40728c506b8Sjruoho     }
40828c506b8Sjruoho 
40928c506b8Sjruoho     /* Increment counters for object types we are looking for */
41028c506b8Sjruoho 
41128c506b8Sjruoho     switch (Type)
41228c506b8Sjruoho     {
41328c506b8Sjruoho     case ACPI_TYPE_REGION:
414a2c051a9Schristos 
41528c506b8Sjruoho         Info->OpRegionCount++;
41628c506b8Sjruoho         break;
41728c506b8Sjruoho 
41828c506b8Sjruoho     case ACPI_TYPE_BUFFER_FIELD:
419a2c051a9Schristos 
42028c506b8Sjruoho         Info->FieldCount++;
42128c506b8Sjruoho         break;
42228c506b8Sjruoho 
42328c506b8Sjruoho     case ACPI_TYPE_LOCAL_BANK_FIELD:
424a2c051a9Schristos 
42528c506b8Sjruoho         Info->FieldCount++;
42628c506b8Sjruoho         break;
42728c506b8Sjruoho 
42828c506b8Sjruoho     case ACPI_TYPE_BUFFER:
429a2c051a9Schristos 
43028c506b8Sjruoho         Info->BufferCount++;
43128c506b8Sjruoho         break;
43228c506b8Sjruoho 
43328c506b8Sjruoho     case ACPI_TYPE_PACKAGE:
434a2c051a9Schristos 
43528c506b8Sjruoho         Info->PackageCount++;
43628c506b8Sjruoho         break;
43728c506b8Sjruoho 
43828c506b8Sjruoho     default:
43928c506b8Sjruoho 
44028c506b8Sjruoho         /* No init required, just exit now */
441a2c051a9Schristos 
44228c506b8Sjruoho         return (AE_OK);
44328c506b8Sjruoho     }
44428c506b8Sjruoho 
44528c506b8Sjruoho     /* If the object is already initialized, nothing else to do */
44628c506b8Sjruoho 
44728c506b8Sjruoho     if (ObjDesc->Common.Flags & AOPOBJ_DATA_VALID)
44828c506b8Sjruoho     {
44928c506b8Sjruoho         return (AE_OK);
45028c506b8Sjruoho     }
45128c506b8Sjruoho 
45228c506b8Sjruoho     /* Must lock the interpreter before executing AML code */
45328c506b8Sjruoho 
45428c506b8Sjruoho     AcpiExEnterInterpreter ();
45528c506b8Sjruoho 
45628c506b8Sjruoho     /*
4577ab6b89bSchristos      * Only initialization of Package objects can be deferred, in order
4587ab6b89bSchristos      * to support forward references.
45928c506b8Sjruoho      */
46028c506b8Sjruoho     switch (Type)
46128c506b8Sjruoho     {
46228c506b8Sjruoho     case ACPI_TYPE_LOCAL_BANK_FIELD:
46328c506b8Sjruoho 
4647ab6b89bSchristos         /* TBD: BankFields do not require deferred init, remove this code */
4657ab6b89bSchristos 
46628c506b8Sjruoho         Info->FieldInit++;
46728c506b8Sjruoho         Status = AcpiDsGetBankFieldArguments (ObjDesc);
46828c506b8Sjruoho         break;
46928c506b8Sjruoho 
47028c506b8Sjruoho     case ACPI_TYPE_PACKAGE:
47128c506b8Sjruoho 
472a147b75fSchristos         /* Complete the initialization/resolution of the package object */
473a147b75fSchristos 
47428c506b8Sjruoho         Info->PackageInit++;
475a147b75fSchristos         Status = AcpiNsInitOnePackage (ObjHandle, Level, NULL, NULL);
47628c506b8Sjruoho         break;
47728c506b8Sjruoho 
47828c506b8Sjruoho     default:
479a2c051a9Schristos 
4807ab6b89bSchristos         /* No other types should get here */
481a2c051a9Schristos 
4827ab6b89bSchristos         Status = AE_TYPE;
4837ab6b89bSchristos         ACPI_EXCEPTION ((AE_INFO, Status,
4847ab6b89bSchristos             "Opcode is not deferred [%4.4s] (%s)",
4857ab6b89bSchristos             AcpiUtGetNodeName (Node), AcpiUtGetTypeName (Type)));
48628c506b8Sjruoho         break;
48728c506b8Sjruoho     }
48828c506b8Sjruoho 
48928c506b8Sjruoho     if (ACPI_FAILURE (Status))
49028c506b8Sjruoho     {
49128c506b8Sjruoho         ACPI_EXCEPTION ((AE_INFO, Status,
49228c506b8Sjruoho             "Could not execute arguments for [%4.4s] (%s)",
49328c506b8Sjruoho             AcpiUtGetNodeName (Node), AcpiUtGetTypeName (Type)));
49428c506b8Sjruoho     }
49528c506b8Sjruoho 
49628c506b8Sjruoho     /*
49728c506b8Sjruoho      * We ignore errors from above, and always return OK, since we don't want
49828c506b8Sjruoho      * to abort the walk on any single error.
49928c506b8Sjruoho      */
50028c506b8Sjruoho     AcpiExExitInterpreter ();
50128c506b8Sjruoho     return (AE_OK);
50228c506b8Sjruoho }
50328c506b8Sjruoho 
50428c506b8Sjruoho 
50528c506b8Sjruoho /*******************************************************************************
50628c506b8Sjruoho  *
50728c506b8Sjruoho  * FUNCTION:    AcpiNsFindIniMethods
50828c506b8Sjruoho  *
50928c506b8Sjruoho  * PARAMETERS:  ACPI_WALK_CALLBACK
51028c506b8Sjruoho  *
51128c506b8Sjruoho  * RETURN:      ACPI_STATUS
51228c506b8Sjruoho  *
51328c506b8Sjruoho  * DESCRIPTION: Called during namespace walk. Finds objects named _INI under
51428c506b8Sjruoho  *              device/processor/thermal objects, and marks the entire subtree
51528c506b8Sjruoho  *              with a SUBTREE_HAS_INI flag. This flag is used during the
51628c506b8Sjruoho  *              subsequent device initialization walk to avoid entire subtrees
51728c506b8Sjruoho  *              that do not contain an _INI.
51828c506b8Sjruoho  *
51928c506b8Sjruoho  ******************************************************************************/
52028c506b8Sjruoho 
52128c506b8Sjruoho static ACPI_STATUS
AcpiNsFindIniMethods(ACPI_HANDLE ObjHandle,UINT32 NestingLevel,void * Context,void ** ReturnValue)52228c506b8Sjruoho AcpiNsFindIniMethods (
52328c506b8Sjruoho     ACPI_HANDLE             ObjHandle,
52428c506b8Sjruoho     UINT32                  NestingLevel,
52528c506b8Sjruoho     void                    *Context,
52628c506b8Sjruoho     void                    **ReturnValue)
52728c506b8Sjruoho {
52828c506b8Sjruoho     ACPI_DEVICE_WALK_INFO   *Info = ACPI_CAST_PTR (ACPI_DEVICE_WALK_INFO, Context);
52928c506b8Sjruoho     ACPI_NAMESPACE_NODE     *Node;
53028c506b8Sjruoho     ACPI_NAMESPACE_NODE     *ParentNode;
53128c506b8Sjruoho 
53228c506b8Sjruoho 
53328c506b8Sjruoho     /* Keep count of device/processor/thermal objects */
53428c506b8Sjruoho 
53528c506b8Sjruoho     Node = ACPI_CAST_PTR (ACPI_NAMESPACE_NODE, ObjHandle);
53628c506b8Sjruoho     if ((Node->Type == ACPI_TYPE_DEVICE)    ||
53728c506b8Sjruoho         (Node->Type == ACPI_TYPE_PROCESSOR) ||
53828c506b8Sjruoho         (Node->Type == ACPI_TYPE_THERMAL))
53928c506b8Sjruoho     {
54028c506b8Sjruoho         Info->DeviceCount++;
54128c506b8Sjruoho         return (AE_OK);
54228c506b8Sjruoho     }
54328c506b8Sjruoho 
54428c506b8Sjruoho     /* We are only looking for methods named _INI */
54528c506b8Sjruoho 
5465b948c02Schristos     if (!ACPI_COMPARE_NAMESEG (Node->Name.Ascii, METHOD_NAME__INI))
54728c506b8Sjruoho     {
54828c506b8Sjruoho         return (AE_OK);
54928c506b8Sjruoho     }
55028c506b8Sjruoho 
55128c506b8Sjruoho     /*
55228c506b8Sjruoho      * The only _INI methods that we care about are those that are
55328c506b8Sjruoho      * present under Device, Processor, and Thermal objects.
55428c506b8Sjruoho      */
55528c506b8Sjruoho     ParentNode = Node->Parent;
55628c506b8Sjruoho     switch (ParentNode->Type)
55728c506b8Sjruoho     {
55828c506b8Sjruoho     case ACPI_TYPE_DEVICE:
55928c506b8Sjruoho     case ACPI_TYPE_PROCESSOR:
56028c506b8Sjruoho     case ACPI_TYPE_THERMAL:
56128c506b8Sjruoho 
56228c506b8Sjruoho         /* Mark parent and bubble up the INI present flag to the root */
56328c506b8Sjruoho 
56428c506b8Sjruoho         while (ParentNode)
56528c506b8Sjruoho         {
56628c506b8Sjruoho             ParentNode->Flags |= ANOBJ_SUBTREE_HAS_INI;
56728c506b8Sjruoho             ParentNode = ParentNode->Parent;
56828c506b8Sjruoho         }
56928c506b8Sjruoho         break;
57028c506b8Sjruoho 
57128c506b8Sjruoho     default:
572a2c051a9Schristos 
57328c506b8Sjruoho         break;
57428c506b8Sjruoho     }
57528c506b8Sjruoho 
57628c506b8Sjruoho     return (AE_OK);
57728c506b8Sjruoho }
57828c506b8Sjruoho 
57928c506b8Sjruoho 
58028c506b8Sjruoho /*******************************************************************************
58128c506b8Sjruoho  *
58228c506b8Sjruoho  * FUNCTION:    AcpiNsInitOneDevice
58328c506b8Sjruoho  *
58428c506b8Sjruoho  * PARAMETERS:  ACPI_WALK_CALLBACK
58528c506b8Sjruoho  *
58628c506b8Sjruoho  * RETURN:      ACPI_STATUS
58728c506b8Sjruoho  *
58828c506b8Sjruoho  * DESCRIPTION: This is called once per device soon after ACPI is enabled
58928c506b8Sjruoho  *              to initialize each device. It determines if the device is
59028c506b8Sjruoho  *              present, and if so, calls _INI.
59128c506b8Sjruoho  *
59228c506b8Sjruoho  ******************************************************************************/
59328c506b8Sjruoho 
59428c506b8Sjruoho static ACPI_STATUS
AcpiNsInitOneDevice(ACPI_HANDLE ObjHandle,UINT32 NestingLevel,void * Context,void ** ReturnValue)59528c506b8Sjruoho AcpiNsInitOneDevice (
59628c506b8Sjruoho     ACPI_HANDLE             ObjHandle,
59728c506b8Sjruoho     UINT32                  NestingLevel,
59828c506b8Sjruoho     void                    *Context,
59928c506b8Sjruoho     void                    **ReturnValue)
60028c506b8Sjruoho {
60128c506b8Sjruoho     ACPI_DEVICE_WALK_INFO   *WalkInfo = ACPI_CAST_PTR (ACPI_DEVICE_WALK_INFO, Context);
60228c506b8Sjruoho     ACPI_EVALUATE_INFO      *Info = WalkInfo->EvaluateInfo;
60328c506b8Sjruoho     UINT32                  Flags;
60428c506b8Sjruoho     ACPI_STATUS             Status;
60528c506b8Sjruoho     ACPI_NAMESPACE_NODE     *DeviceNode;
60628c506b8Sjruoho 
60728c506b8Sjruoho 
60828c506b8Sjruoho     ACPI_FUNCTION_TRACE (NsInitOneDevice);
60928c506b8Sjruoho 
61028c506b8Sjruoho 
61128c506b8Sjruoho     /* We are interested in Devices, Processors and ThermalZones only */
61228c506b8Sjruoho 
61328c506b8Sjruoho     DeviceNode = ACPI_CAST_PTR (ACPI_NAMESPACE_NODE, ObjHandle);
61428c506b8Sjruoho     if ((DeviceNode->Type != ACPI_TYPE_DEVICE)    &&
61528c506b8Sjruoho         (DeviceNode->Type != ACPI_TYPE_PROCESSOR) &&
61628c506b8Sjruoho         (DeviceNode->Type != ACPI_TYPE_THERMAL))
61728c506b8Sjruoho     {
61828c506b8Sjruoho         return_ACPI_STATUS (AE_OK);
61928c506b8Sjruoho     }
62028c506b8Sjruoho 
62128c506b8Sjruoho     /*
62228c506b8Sjruoho      * Because of an earlier namespace analysis, all subtrees that contain an
62328c506b8Sjruoho      * _INI method are tagged.
62428c506b8Sjruoho      *
62528c506b8Sjruoho      * If this device subtree does not contain any _INI methods, we
62628c506b8Sjruoho      * can exit now and stop traversing this entire subtree.
62728c506b8Sjruoho      */
62828c506b8Sjruoho     if (!(DeviceNode->Flags & ANOBJ_SUBTREE_HAS_INI))
62928c506b8Sjruoho     {
63028c506b8Sjruoho         return_ACPI_STATUS (AE_CTRL_DEPTH);
63128c506b8Sjruoho     }
63228c506b8Sjruoho 
63328c506b8Sjruoho     /*
63428c506b8Sjruoho      * Run _STA to determine if this device is present and functioning. We
63528c506b8Sjruoho      * must know this information for two important reasons (from ACPI spec):
63628c506b8Sjruoho      *
63728c506b8Sjruoho      * 1) We can only run _INI if the device is present.
63828c506b8Sjruoho      * 2) We must abort the device tree walk on this subtree if the device is
63928c506b8Sjruoho      *    not present and is not functional (we will not examine the children)
64028c506b8Sjruoho      *
64128c506b8Sjruoho      * The _STA method is not required to be present under the device, we
64228c506b8Sjruoho      * assume the device is present if _STA does not exist.
64328c506b8Sjruoho      */
64428c506b8Sjruoho     ACPI_DEBUG_EXEC (AcpiUtDisplayInitPathname (
64528c506b8Sjruoho         ACPI_TYPE_METHOD, DeviceNode, METHOD_NAME__STA));
64628c506b8Sjruoho 
64728c506b8Sjruoho     Status = AcpiUtExecute_STA (DeviceNode, &Flags);
64828c506b8Sjruoho     if (ACPI_FAILURE (Status))
64928c506b8Sjruoho     {
65028c506b8Sjruoho         /* Ignore error and move on to next device */
65128c506b8Sjruoho 
65228c506b8Sjruoho         return_ACPI_STATUS (AE_OK);
65328c506b8Sjruoho     }
65428c506b8Sjruoho 
65528c506b8Sjruoho     /*
65628c506b8Sjruoho      * Flags == -1 means that _STA was not found. In this case, we assume that
65728c506b8Sjruoho      * the device is both present and functional.
65828c506b8Sjruoho      *
65928c506b8Sjruoho      * From the ACPI spec, description of _STA:
66028c506b8Sjruoho      *
66128c506b8Sjruoho      * "If a device object (including the processor object) does not have an
66228c506b8Sjruoho      * _STA object, then OSPM assumes that all of the above bits are set (in
66328c506b8Sjruoho      * other words, the device is present, ..., and functioning)"
66428c506b8Sjruoho      */
66528c506b8Sjruoho     if (Flags != ACPI_UINT32_MAX)
66628c506b8Sjruoho     {
66728c506b8Sjruoho         WalkInfo->Num_STA++;
66828c506b8Sjruoho     }
66928c506b8Sjruoho 
67028c506b8Sjruoho     /*
67128c506b8Sjruoho      * Examine the PRESENT and FUNCTIONING status bits
67228c506b8Sjruoho      *
67328c506b8Sjruoho      * Note: ACPI spec does not seem to specify behavior for the present but
67428c506b8Sjruoho      * not functioning case, so we assume functioning if present.
67528c506b8Sjruoho      */
67628c506b8Sjruoho     if (!(Flags & ACPI_STA_DEVICE_PRESENT))
67728c506b8Sjruoho     {
67828c506b8Sjruoho         /* Device is not present, we must examine the Functioning bit */
67928c506b8Sjruoho 
68028c506b8Sjruoho         if (Flags & ACPI_STA_DEVICE_FUNCTIONING)
68128c506b8Sjruoho         {
68228c506b8Sjruoho             /*
68328c506b8Sjruoho              * Device is not present but is "functioning". In this case,
68428c506b8Sjruoho              * we will not run _INI, but we continue to examine the children
68528c506b8Sjruoho              * of this device.
68628c506b8Sjruoho              *
68728c506b8Sjruoho              * From the ACPI spec, description of _STA: (Note - no mention
68828c506b8Sjruoho              * of whether to run _INI or not on the device in question)
68928c506b8Sjruoho              *
69028c506b8Sjruoho              * "_STA may return bit 0 clear (not present) with bit 3 set
69128c506b8Sjruoho              * (device is functional). This case is used to indicate a valid
69228c506b8Sjruoho              * device for which no device driver should be loaded (for example,
69328c506b8Sjruoho              * a bridge device.) Children of this device may be present and
69428c506b8Sjruoho              * valid. OSPM should continue enumeration below a device whose
69528c506b8Sjruoho              * _STA returns this bit combination"
69628c506b8Sjruoho              */
69728c506b8Sjruoho             return_ACPI_STATUS (AE_OK);
69828c506b8Sjruoho         }
69928c506b8Sjruoho         else
70028c506b8Sjruoho         {
70128c506b8Sjruoho             /*
70228c506b8Sjruoho              * Device is not present and is not functioning. We must abort the
70328c506b8Sjruoho              * walk of this subtree immediately -- don't look at the children
70428c506b8Sjruoho              * of such a device.
70528c506b8Sjruoho              *
70628c506b8Sjruoho              * From the ACPI spec, description of _INI:
70728c506b8Sjruoho              *
70828c506b8Sjruoho              * "If the _STA method indicates that the device is not present,
70928c506b8Sjruoho              * OSPM will not run the _INI and will not examine the children
71028c506b8Sjruoho              * of the device for _INI methods"
71128c506b8Sjruoho              */
71228c506b8Sjruoho             return_ACPI_STATUS (AE_CTRL_DEPTH);
71328c506b8Sjruoho         }
71428c506b8Sjruoho     }
71528c506b8Sjruoho 
71628c506b8Sjruoho     /*
71728c506b8Sjruoho      * The device is present or is assumed present if no _STA exists.
71828c506b8Sjruoho      * Run the _INI if it exists (not required to exist)
71928c506b8Sjruoho      *
72028c506b8Sjruoho      * Note: We know there is an _INI within this subtree, but it may not be
72128c506b8Sjruoho      * under this particular device, it may be lower in the branch.
72228c506b8Sjruoho      */
7235b948c02Schristos     if (!ACPI_COMPARE_NAMESEG (DeviceNode->Name.Ascii, "_SB_") ||
72449c2f1f4Schristos         DeviceNode->Parent != AcpiGbl_RootNode)
72549c2f1f4Schristos     {
72628c506b8Sjruoho         ACPI_DEBUG_EXEC (AcpiUtDisplayInitPathname (
72728c506b8Sjruoho             ACPI_TYPE_METHOD, DeviceNode, METHOD_NAME__INI));
72828c506b8Sjruoho 
7299b9ee194Schristos         memset (Info, 0, sizeof (ACPI_EVALUATE_INFO));
73028c506b8Sjruoho         Info->PrefixNode = DeviceNode;
73149c2f1f4Schristos         Info->RelativePathname = METHOD_NAME__INI;
73228c506b8Sjruoho         Info->Parameters = NULL;
73328c506b8Sjruoho         Info->Flags = ACPI_IGNORE_RETURN_VALUE;
73428c506b8Sjruoho 
73528c506b8Sjruoho         Status = AcpiNsEvaluate (Info);
73628c506b8Sjruoho         if (ACPI_SUCCESS (Status))
73728c506b8Sjruoho         {
73828c506b8Sjruoho             WalkInfo->Num_INI++;
73928c506b8Sjruoho         }
74028c506b8Sjruoho 
74128c506b8Sjruoho #ifdef ACPI_DEBUG_OUTPUT
74228c506b8Sjruoho         else if (Status != AE_NOT_FOUND)
74328c506b8Sjruoho         {
74428c506b8Sjruoho             /* Ignore error and move on to next device */
74528c506b8Sjruoho 
74681bd9c9cSchristos             char *ScopeName = AcpiNsGetNormalizedPathname (DeviceNode, TRUE);
74728c506b8Sjruoho 
74828c506b8Sjruoho             ACPI_EXCEPTION ((AE_INFO, Status, "during %s._INI execution",
74928c506b8Sjruoho                 ScopeName));
75028c506b8Sjruoho             ACPI_FREE (ScopeName);
75128c506b8Sjruoho         }
75228c506b8Sjruoho #endif
75349c2f1f4Schristos     }
75428c506b8Sjruoho 
75528c506b8Sjruoho     /* Ignore errors from above */
75628c506b8Sjruoho 
75728c506b8Sjruoho     Status = AE_OK;
75828c506b8Sjruoho 
75928c506b8Sjruoho     /*
76028c506b8Sjruoho      * The _INI method has been run if present; call the Global Initialization
76128c506b8Sjruoho      * Handler for this device.
76228c506b8Sjruoho      */
76328c506b8Sjruoho     if (AcpiGbl_InitHandler)
76428c506b8Sjruoho     {
76528c506b8Sjruoho         Status = AcpiGbl_InitHandler (DeviceNode, ACPI_INIT_DEVICE_INI);
76628c506b8Sjruoho     }
76728c506b8Sjruoho 
76828c506b8Sjruoho     return_ACPI_STATUS (Status);
76928c506b8Sjruoho }
770