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