summaryrefslogtreecommitdiffstats
path: root/drivers/acpi/namespace
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/acpi/namespace')
-rw-r--r--drivers/acpi/namespace/Makefile14
-rw-r--r--drivers/acpi/namespace/nsaccess.c45
-rw-r--r--drivers/acpi/namespace/nsalloc.c4
-rw-r--r--drivers/acpi/namespace/nsdump.c36
-rw-r--r--drivers/acpi/namespace/nseval.c38
-rw-r--r--drivers/acpi/namespace/nsinit.c271
-rw-r--r--drivers/acpi/namespace/nsload.c177
-rw-r--r--drivers/acpi/namespace/nsnames.c10
-rw-r--r--drivers/acpi/namespace/nsobject.c12
-rw-r--r--drivers/acpi/namespace/nssearch.c18
-rw-r--r--drivers/acpi/namespace/nsutils.c253
-rw-r--r--drivers/acpi/namespace/nsxfname.c124
-rw-r--r--drivers/acpi/namespace/nsxfobj.c153
13 files changed, 866 insertions, 289 deletions
diff --git a/drivers/acpi/namespace/Makefile b/drivers/acpi/namespace/Makefile
index edd897133..751ef5de8 100644
--- a/drivers/acpi/namespace/Makefile
+++ b/drivers/acpi/namespace/Makefile
@@ -2,26 +2,14 @@
# Makefile for all Linux ACPI interpreter subdirectories
#
-SUB_DIRS :=
-MOD_SUB_DIRS := $(SUB_DIRS)
-MOD_IN_SUB_DIRS :=
-ALL_SUB_DIRS := $(SUB_DIRS)
-
O_TARGET := ../$(shell basename `pwd`).o
-O_OBJS :=
-M_OBJS :=
-ACPI_OBJS := $(patsubst %.c,%.o,$(wildcard *.c))
+obj-$(CONFIG_ACPI) := $(patsubst %.c,%.o,$(wildcard *.c))
EXTRA_CFLAGS += -I../include
EXTRA_CFLAGS += $(ACPI_CFLAGS)
-# if the interpreter is used, it overrides arch/i386/kernel/acpi.c
-ifeq ($(CONFIG_ACPI_INTERPRETER),y)
- O_OBJS := $(ACPI_OBJS)
-endif
-
include $(TOPDIR)/Rules.make
clean:
diff --git a/drivers/acpi/namespace/nsaccess.c b/drivers/acpi/namespace/nsaccess.c
index e04ffe4e9..27c02e22a 100644
--- a/drivers/acpi/namespace/nsaccess.c
+++ b/drivers/acpi/namespace/nsaccess.c
@@ -1,7 +1,7 @@
/*******************************************************************************
*
* Module Name: nsaccess - Top-level functions for accessing ACPI namespace
- * $Revision: 108 $
+ * $Revision: 117 $
*
******************************************************************************/
@@ -87,8 +87,6 @@ acpi_ns_root_initialize (void)
IMODE_LOAD_PASS2, NS_NO_UPSEARCH,
NULL, &new_node);
- if (ACPI_FAILURE (status) ||
- (!new_node))
/*
* Name entered successfully.
@@ -122,7 +120,7 @@ acpi_ns_root_initialize (void)
case ACPI_TYPE_NUMBER:
obj_desc->number.value =
- (u32) STRTOUL (init_val->val, NULL, 10);
+ (ACPI_INTEGER) STRTOUL (init_val->val, NULL, 10);
break;
@@ -138,11 +136,7 @@ acpi_ns_root_initialize (void)
*/
obj_desc->string.pointer = acpi_cm_allocate (
(obj_desc->string.length + 1));
-
if (!obj_desc->string.pointer) {
- REPORT_ERROR ("Initial value string"
- "allocation failure");
-
acpi_cm_remove_reference (obj_desc);
status = AE_NO_MEMORY;
goto unlock_and_exit;
@@ -190,7 +184,8 @@ acpi_ns_root_initialize (void)
default:
- REPORT_ERROR ("Unsupported initial type value");
+ REPORT_ERROR (("Unsupported initial type value %X\n",
+ init_val->type));
acpi_cm_remove_reference (obj_desc);
obj_desc = NULL;
continue;
@@ -214,14 +209,14 @@ unlock_and_exit:
*
* FUNCTION: Acpi_ns_lookup
*
- * PARAMETERS: Prefix_node - Search scope if name is not fully qualified
+ * PARAMETERS: Prefix_node - Search scope if name is not fully qualified
* Pathname - Search pathname, in internal format
* (as represented in the AML stream)
* Type - Type associated with name
* Interpreter_mode - IMODE_LOAD_PASS2 => add name if not found
* Flags - Flags describing the search restrictions
* Walk_state - Current state of the walk
- * Return_node - Where the Node is placed (if found
+ * Return_node - Where the Node is placed (if found
* or created successfully)
*
* RETURN: Status
@@ -254,6 +249,9 @@ acpi_ns_lookup (
OBJECT_TYPE_INTERNAL type_to_check_for;
OBJECT_TYPE_INTERNAL this_search_type;
+ DEBUG_ONLY_MEMBERS (u32 i)
+
+
if (!return_node) {
return (AE_BAD_PARAMETER);
}
@@ -379,8 +377,7 @@ acpi_ns_lookup (
if (!this_node) {
/* Current scope has no parent scope */
- REPORT_ERROR ("Too many parent prefixes (^) - reached root");
-
+ REPORT_ERROR (("Too many parent prefixes (^) - reached root\n"));
return (AE_NOT_FOUND);
}
@@ -442,7 +439,7 @@ acpi_ns_lookup (
this_search_type = type;
}
- /* Pluck and ACPI name from the front of the pathname */
+ /* Pluck one ACPI name from the front of the pathname */
MOVE_UNALIGNED32_TO_32 (&simple_name, pathname);
@@ -467,25 +464,29 @@ acpi_ns_lookup (
* If 1) This is the last segment (Num_segments == 0)
* 2) and looking for a specific type
* (Not checking for TYPE_ANY)
- * 3) which is not a local type (TYPE_DEF_ANY)
- * 4) which is not a local type (TYPE_SCOPE)
- * 5) which is not a local type (TYPE_INDEX_FIELD_DEFN)
- * 6) and type of object is known (not TYPE_ANY)
- * 7) and object does not match request
+ * 3) Which is not an alias
+ * 4) which is not a local type (TYPE_DEF_ANY)
+ * 5) which is not a local type (TYPE_SCOPE)
+ * 6) which is not a local type (TYPE_INDEX_FIELD_DEFN)
+ * 7) and type of object is known (not TYPE_ANY)
+ * 8) and object does not match request
*
* Then we have a type mismatch. Just warn and ignore it.
*/
if ((num_segments == 0) &&
(type_to_check_for != ACPI_TYPE_ANY) &&
+ (type_to_check_for != INTERNAL_TYPE_ALIAS) &&
(type_to_check_for != INTERNAL_TYPE_DEF_ANY) &&
(type_to_check_for != INTERNAL_TYPE_SCOPE) &&
(type_to_check_for != INTERNAL_TYPE_INDEX_FIELD_DEFN) &&
- (this_node->type != ACPI_TYPE_ANY) &&
- (this_node->type != type_to_check_for))
+ (this_node->type != ACPI_TYPE_ANY) &&
+ (this_node->type != type_to_check_for))
{
/* Complain about a type mismatch */
- REPORT_WARNING ("Type mismatch");
+ REPORT_WARNING (
+ ("Ns_lookup: %4.4s, type %X, checking for type %X\n",
+ &simple_name, this_node->type, type_to_check_for));
}
/*
diff --git a/drivers/acpi/namespace/nsalloc.c b/drivers/acpi/namespace/nsalloc.c
index 0b8272724..9f1d5377e 100644
--- a/drivers/acpi/namespace/nsalloc.c
+++ b/drivers/acpi/namespace/nsalloc.c
@@ -1,7 +1,7 @@
/*******************************************************************************
*
* Module Name: nsalloc - Namespace allocation and deletion utilities
- * $Revision: 41 $
+ * $Revision: 43 $
*
******************************************************************************/
@@ -434,7 +434,7 @@ acpi_ns_delete_namespace_subtree (
*
******************************************************************************/
-void
+static void
acpi_ns_remove_reference (
ACPI_NAMESPACE_NODE *node)
{
diff --git a/drivers/acpi/namespace/nsdump.c b/drivers/acpi/namespace/nsdump.c
deleted file mode 100644
index 117af81e3..000000000
--- a/drivers/acpi/namespace/nsdump.c
+++ /dev/null
@@ -1,36 +0,0 @@
-/******************************************************************************
- *
- * Module Name: nsdump - table dumping routines for debug
- * $Revision: 78 $
- *
- *****************************************************************************/
-
-/*
- * Copyright (C) 2000 R. Byron Moore
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-
-#include "acpi.h"
-#include "acinterp.h"
-#include "acnamesp.h"
-#include "actables.h"
-
-
-#define _COMPONENT NAMESPACE
- MODULE_NAME ("nsdump")
-
-
diff --git a/drivers/acpi/namespace/nseval.c b/drivers/acpi/namespace/nseval.c
index 2df17e94f..fbba7840c 100644
--- a/drivers/acpi/namespace/nseval.c
+++ b/drivers/acpi/namespace/nseval.c
@@ -2,7 +2,7 @@
*
* Module Name: nseval - Object evaluation interfaces -- includes control
* method lookup and execution.
- * $Revision: 76 $
+ * $Revision: 79 $
*
******************************************************************************/
@@ -99,7 +99,7 @@ acpi_ns_evaluate_relative (
/* Lookup the name in the namespace */
- scope_info.scope.node = prefix_node->child;
+ scope_info.scope.node = prefix_node;
status = acpi_ns_lookup (&scope_info, internal_path, ACPI_TYPE_ANY,
IMODE_EXECUTE, NS_NO_UPSEARCH, NULL,
&node);
@@ -432,28 +432,14 @@ acpi_ns_get_object_value (
}
/*
- * Just copy from the original to the return object
+ * Just copy from the original to the return object
+ *
+ * TBD: [Future] - need a low-level object copy that handles
+ * the reference count automatically. (Don't want to copy it)
*/
- switch (node->type)
- {
- case ACPI_TYPE_PROCESSOR:
- obj_desc->processor.proc_id = val_desc->processor.proc_id;
- obj_desc->processor.address = val_desc->processor.address;
- obj_desc->processor.sys_handler = val_desc->processor.sys_handler;
- obj_desc->processor.drv_handler = val_desc->processor.drv_handler;
- obj_desc->processor.addr_handler = val_desc->processor.addr_handler;
-
- break;
-
- case ACPI_TYPE_POWER:
- obj_desc->power_resource.system_level = val_desc->power_resource.system_level;
- obj_desc->power_resource.resource_order = val_desc->power_resource.resource_order;
- obj_desc->power_resource.sys_handler = val_desc->power_resource.sys_handler;
- obj_desc->power_resource.drv_handler = val_desc->power_resource.drv_handler;
-
- break;
- }
+ MEMCPY (obj_desc, val_desc, sizeof (ACPI_OPERAND_OBJECT));
+ obj_desc->common.reference_count = 1;
}
@@ -483,9 +469,17 @@ acpi_ns_get_object_value (
* NOTE: we can get away with passing in NULL for a walk state
* because Obj_desc is guaranteed to not be a reference to either
* a method local or a method argument
+ *
+ * Even though we do not technically need to use the interpreter
+ * for this, we must enter it because we could hit an opregion.
+ * The opregion access code assumes it is in the interpreter.
*/
+ acpi_aml_enter_interpreter();
+
status = acpi_aml_resolve_to_value (&obj_desc, NULL);
+
+ acpi_aml_exit_interpreter();
}
/*
diff --git a/drivers/acpi/namespace/nsinit.c b/drivers/acpi/namespace/nsinit.c
new file mode 100644
index 000000000..ddacd7b8c
--- /dev/null
+++ b/drivers/acpi/namespace/nsinit.c
@@ -0,0 +1,271 @@
+/******************************************************************************
+ *
+ * Module Name: nsinit - namespace initialization
+ * $Revision: 9 $
+ *
+ *****************************************************************************/
+
+/*
+ * Copyright (C) 2000 R. Byron Moore
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+
+#include "acpi.h"
+#include "acnamesp.h"
+#include "acdispat.h"
+
+#define _COMPONENT NAMESPACE
+ MODULE_NAME ("nsinit")
+
+
+/*******************************************************************************
+ *
+ * FUNCTION: Acpi_ns_initialize_objects
+ *
+ * PARAMETERS: None
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Walk the entire namespace and perform any necessary
+ * initialization on the objects found therein
+ *
+ ******************************************************************************/
+
+ACPI_STATUS
+acpi_ns_initialize_objects (
+ void)
+{
+ ACPI_STATUS status;
+ ACPI_INIT_WALK_INFO info;
+
+
+ info.field_count = 0;
+ info.field_init = 0;
+ info.op_region_count = 0;
+ info.op_region_init = 0;
+ info.object_count = 0;
+
+
+ /* Walk entire namespace from the supplied root */
+
+ status = acpi_walk_namespace (ACPI_TYPE_ANY, ACPI_ROOT_OBJECT,
+ ACPI_UINT32_MAX, acpi_ns_init_one_object,
+ &info, NULL);
+
+ return (AE_OK);
+}
+
+
+/******************************************************************************
+ *
+ * FUNCTION: Acpi_ns_initialize_devices
+ *
+ * PARAMETERS: None
+ *
+ * RETURN: ACPI_STATUS
+ *
+ * DESCRIPTION: Walk the entire namespace and initialize all ACPI devices.
+ * This means running _INI on all present devices.
+ *
+ * Also: Install PCI config space handler for all PCI root bridges.
+ * A PCI root bridge is found by searching for devices containing
+ * a HID with the value EISAID("PNP0A03")
+ *
+ *****************************************************************************/
+
+ACPI_STATUS
+acpi_ns_initialize_devices (
+ u32 flags)
+{
+ ACPI_STATUS status;
+ ACPI_DEVICE_WALK_INFO info;
+
+
+ info.flags = flags;
+ info.device_count = 0;
+ info.num_STA = 0;
+ info.num_INI = 0;
+
+
+ status = acpi_ns_walk_namespace (ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT, ACPI_UINT32_MAX,
+ FALSE, acpi_ns_init_one_device, &info, NULL);
+
+
+
+ return (status);
+}
+
+
+/*******************************************************************************
+ *
+ * FUNCTION: Acpi_ns_init_one_object
+ *
+ * PARAMETERS: Obj_handle - Node
+ * Level - Current nesting level
+ * Context - Points to a init info struct
+ * Return_value - Not used
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Callback from Acpi_walk_namespace. Invoked for every object
+ * within the namespace.
+ *
+ * Currently, the only objects that require initialization are:
+ * 1) Methods
+ * 2) Op Regions
+ *
+ ******************************************************************************/
+
+ACPI_STATUS
+acpi_ns_init_one_object (
+ ACPI_HANDLE obj_handle,
+ u32 level,
+ void *context,
+ void **return_value)
+{
+ OBJECT_TYPE_INTERNAL type;
+ ACPI_STATUS status;
+ ACPI_INIT_WALK_INFO *info = (ACPI_INIT_WALK_INFO *) context;
+ ACPI_NAMESPACE_NODE *node = (ACPI_NAMESPACE_NODE *) obj_handle;
+ ACPI_OPERAND_OBJECT *obj_desc;
+
+
+ info->object_count++;
+
+
+ /* And even then, we are only interested in a few object types */
+
+ type = acpi_ns_get_type (obj_handle);
+ obj_desc = node->object;
+ if (!obj_desc) {
+ return (AE_OK);
+ }
+
+ switch (type)
+ {
+
+ case ACPI_TYPE_REGION:
+
+ info->op_region_count++;
+ if (obj_desc->common.flags & AOPOBJ_DATA_VALID) {
+ break;
+ }
+
+ info->op_region_init++;
+ status = acpi_ds_get_region_arguments (obj_desc);
+
+ break;
+
+
+ case ACPI_TYPE_FIELD_UNIT:
+
+ info->field_count++;
+ if (obj_desc->common.flags & AOPOBJ_DATA_VALID) {
+ break;
+ }
+
+ info->field_init++;
+ status = acpi_ds_get_field_unit_arguments (obj_desc);
+ break;
+
+ default:
+ break;
+ }
+
+ /*
+ * We ignore errors from above, and always return OK, since
+ * we don't want to abort the walk on a single error.
+ */
+ return (AE_OK);
+}
+
+
+/******************************************************************************
+ *
+ * FUNCTION: Acpi_ns_init_one_device
+ *
+ * PARAMETERS: The usual "I'm a namespace callback" stuff
+ *
+ * RETURN: ACPI_STATUS
+ *
+ * DESCRIPTION: This is called once per device soon after ACPI is enabled
+ * to initialize each device. It determines if the device is
+ * present, and if so, calls _INI.
+ *
+ *****************************************************************************/
+
+ACPI_STATUS
+acpi_ns_init_one_device (
+ ACPI_HANDLE obj_handle,
+ u32 nesting_level,
+ void *context,
+ void **return_value)
+{
+ ACPI_STATUS status;
+ ACPI_NAMESPACE_NODE *node;
+ u32 flags;
+ ACPI_DEVICE_WALK_INFO *info = (ACPI_DEVICE_WALK_INFO *) context;
+
+
+ info->device_count++;
+
+ acpi_cm_acquire_mutex (ACPI_MTX_NAMESPACE);
+
+ node = acpi_ns_convert_handle_to_entry (obj_handle);
+ if (!node) {
+ acpi_cm_release_mutex (ACPI_MTX_NAMESPACE);
+ return (AE_BAD_PARAMETER);
+ }
+
+ acpi_cm_release_mutex (ACPI_MTX_NAMESPACE);
+
+ /*
+ * Run _STA to determine if we can run _INI on the device.
+ */
+
+ status = acpi_cm_execute_STA (node, &flags);
+ if (ACPI_FAILURE (status)) {
+ return (status);
+ }
+
+ info->num_STA++;
+
+ if (!(flags & 0x01)) {
+ /* don't look at children of a not present device */
+ return(AE_CTRL_DEPTH);
+ }
+
+ /*
+ * The device is present. Run _INI.
+ */
+
+ status = acpi_ns_evaluate_relative (obj_handle, "_INI", NULL, NULL);
+ if (AE_NOT_FOUND == status) {
+ /* No _INI means device requires no initialization */
+ status = AE_OK;
+ }
+
+ else if (ACPI_FAILURE (status)) {
+ return (status);
+ }
+
+ else {
+ info->num_INI++;
+ }
+
+ return (status);
+}
diff --git a/drivers/acpi/namespace/nsload.c b/drivers/acpi/namespace/nsload.c
index 8faa8ea4f..28a26376d 100644
--- a/drivers/acpi/namespace/nsload.c
+++ b/drivers/acpi/namespace/nsload.c
@@ -1,7 +1,7 @@
/******************************************************************************
*
* Module Name: nsload - namespace loading/expanding/contracting procedures
- * $Revision: 28 $
+ * $Revision: 33 $
*
*****************************************************************************/
@@ -37,6 +37,123 @@
MODULE_NAME ("nsload")
+/******************************************************************************
+ *
+ * FUNCTION: Acpi_load_namespace
+ *
+ * PARAMETERS: Display_aml_during_load
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Load the name space from what ever is pointed to by DSDT.
+ * (DSDT points to either the BIOS or a buffer.)
+ *
+ ******************************************************************************/
+
+ACPI_STATUS
+acpi_ns_load_namespace (
+ void)
+{
+ ACPI_STATUS status;
+
+
+ /* There must be at least a DSDT installed */
+
+ if (acpi_gbl_DSDT == NULL) {
+ return (AE_NO_ACPI_TABLES);
+ }
+
+
+ /*
+ * Load the namespace. The DSDT is required,
+ * but the SSDT and PSDT tables are optional.
+ */
+
+ status = acpi_ns_load_table_by_type (ACPI_TABLE_DSDT);
+ if (ACPI_FAILURE (status)) {
+ return (status);
+ }
+
+ /* Ignore exceptions from these */
+
+ acpi_ns_load_table_by_type (ACPI_TABLE_SSDT);
+ acpi_ns_load_table_by_type (ACPI_TABLE_PSDT);
+
+
+ return (status);
+}
+
+
+/*******************************************************************************
+ *
+ * FUNCTION: Acpi_ns_one_parse_pass
+ *
+ * PARAMETERS:
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION:
+ *
+ ******************************************************************************/
+
+ACPI_STATUS
+acpi_ns_one_complete_parse (
+ u32 pass_number,
+ ACPI_TABLE_DESC *table_desc)
+{
+ ACPI_PARSE_DOWNWARDS descending_callback;
+ ACPI_PARSE_UPWARDS ascending_callback;
+ ACPI_PARSE_OBJECT *parse_root;
+ ACPI_STATUS status;
+
+
+ switch (pass_number)
+ {
+ case 1:
+ descending_callback = acpi_ds_load1_begin_op;
+ ascending_callback = acpi_ds_load1_end_op;
+ break;
+
+ case 2:
+ descending_callback = acpi_ds_load2_begin_op;
+ ascending_callback = acpi_ds_load2_end_op;
+ break;
+
+ case 3:
+ descending_callback = acpi_ds_exec_begin_op;
+ ascending_callback = acpi_ds_exec_end_op;
+ break;
+
+ default:
+ return (AE_BAD_PARAMETER);
+ }
+
+ /* Create and init a Root Node */
+
+ parse_root = acpi_ps_alloc_op (AML_SCOPE_OP);
+ if (!parse_root) {
+ return (AE_NO_MEMORY);
+ }
+
+ ((ACPI_PARSE2_OBJECT *) parse_root)->name = ACPI_ROOT_NAME;
+
+
+ /* Pass 1: Parse everything except control method bodies */
+
+ status = acpi_ps_parse_aml (parse_root,
+ table_desc->aml_pointer,
+ table_desc->aml_length,
+ ACPI_PARSE_LOAD_PASS1 | ACPI_PARSE_DELETE_TREE,
+ NULL, NULL, NULL,
+ descending_callback,
+ ascending_callback);
+
+ acpi_ps_delete_parse_tree (parse_root);
+
+ return (status);
+}
+
+
/*******************************************************************************
*
* FUNCTION: Acpi_ns_parse_table
@@ -69,32 +186,11 @@ acpi_ns_parse_table (
* performs another complete parse of the AML..
*/
- /* Create and init a Root Node */
-
- acpi_gbl_parsed_namespace_root = acpi_ps_alloc_op (AML_SCOPE_OP);
- if (!acpi_gbl_parsed_namespace_root) {
- return (AE_NO_MEMORY);
- }
-
- ((ACPI_PARSE2_OBJECT *) acpi_gbl_parsed_namespace_root)->name = ACPI_ROOT_NAME;
-
-
- /* Pass 1: Parse everything except control method bodies */
-
- status = acpi_ps_parse_aml (acpi_gbl_parsed_namespace_root,
- table_desc->aml_pointer,
- table_desc->aml_length,
- ACPI_PARSE_LOAD_PASS1 | ACPI_PARSE_DELETE_TREE,
- NULL, NULL, NULL,
- acpi_ds_load1_begin_op,
- acpi_ds_load1_end_op);
-
+ status = acpi_ns_one_complete_parse (1, table_desc);
if (ACPI_FAILURE (status)) {
return (status);
}
- acpi_ps_delete_parse_tree (acpi_gbl_parsed_namespace_root);
-
/*
* AML Parse, pass 2
@@ -106,34 +202,11 @@ acpi_ns_parse_table (
* parse objects are all cached.
*/
- /* Create and init a Root Node */
-
- acpi_gbl_parsed_namespace_root = acpi_ps_alloc_op (AML_SCOPE_OP);
- if (!acpi_gbl_parsed_namespace_root) {
- return (AE_NO_MEMORY);
- }
-
- ((ACPI_PARSE2_OBJECT *) acpi_gbl_parsed_namespace_root)->name = ACPI_ROOT_NAME;
-
-
- /* Pass 2: Resolve forward references */
-
- status = acpi_ps_parse_aml (acpi_gbl_parsed_namespace_root,
- table_desc->aml_pointer,
- table_desc->aml_length,
- ACPI_PARSE_LOAD_PASS1 | ACPI_PARSE_DELETE_TREE,
- NULL, NULL, NULL,
- acpi_ds_load2_begin_op,
- acpi_ds_load2_end_op);
-
+ status = acpi_ns_one_complete_parse (2, table_desc);
if (ACPI_FAILURE (status)) {
return (status);
}
- acpi_ps_delete_parse_tree (acpi_gbl_parsed_namespace_root);
- acpi_gbl_parsed_namespace_root = NULL;
-
-
return (status);
}
@@ -147,8 +220,7 @@ acpi_ns_parse_table (
*
* RETURN: Status
*
- * DESCRIPTION: Mainline of the AML load/dump subsystem. Sets up the
- * input engine, calls handler for outermost object type.
+ * DESCRIPTION: Load one ACPI table into the namespace
*
****************************************************************************/
@@ -248,13 +320,6 @@ acpi_ns_load_table_by_type (
table_desc->table_id = TABLE_ID_DSDT;
- /* Initialize the root of the namespace tree */
-
- status = acpi_ns_root_initialize ();
- if (ACPI_FAILURE (status)) {
- goto unlock_and_exit;
- }
-
/* Now load the single DSDT */
status = acpi_ns_load_table (table_desc, acpi_gbl_root_node);
diff --git a/drivers/acpi/namespace/nsnames.c b/drivers/acpi/namespace/nsnames.c
index 3c18cf87f..faf8fe56a 100644
--- a/drivers/acpi/namespace/nsnames.c
+++ b/drivers/acpi/namespace/nsnames.c
@@ -1,7 +1,7 @@
/*******************************************************************************
*
* Module Name: nsnames - Name manipulation and search
- * $Revision: 48 $
+ * $Revision: 51 $
*
******************************************************************************/
@@ -86,7 +86,7 @@ acpi_ns_get_table_pathname (
name_buffer = acpi_cm_callocate (size + 1);
if (!name_buffer) {
- REPORT_ERROR ("Ns_get_table_pathname: allocation failure");
+ REPORT_ERROR (("Ns_get_table_pathname: allocation failure\n"));
return (NULL);
}
@@ -170,6 +170,12 @@ acpi_ns_handle_to_pathname (
size += PATH_SEGMENT_LENGTH;
}
+ /* Special case for size still 0 - no parent for "special" nodes */
+
+ if (!size) {
+ size = PATH_SEGMENT_LENGTH;
+ }
+
/* Set return length to the required path length */
path_length = size + 1;
diff --git a/drivers/acpi/namespace/nsobject.c b/drivers/acpi/namespace/nsobject.c
index df4c28239..6d41b91ce 100644
--- a/drivers/acpi/namespace/nsobject.c
+++ b/drivers/acpi/namespace/nsobject.c
@@ -2,7 +2,7 @@
*
* Module Name: nsobject - Utilities for objects attached to namespace
* table entries
- * $Revision: 44 $
+ * $Revision: 47 $
*
******************************************************************************/
@@ -73,29 +73,28 @@ acpi_ns_attach_object (
if (!acpi_gbl_root_node) {
/* Name space not initialized */
- REPORT_ERROR ("Ns_attach_object: Name space not initialized");
+ REPORT_ERROR (("Ns_attach_object: Namespace not initialized\n"));
return (AE_NO_NAMESPACE);
}
if (!node) {
/* Invalid handle */
- REPORT_ERROR ("Ns_attach_object: Null Named_obj handle");
+ REPORT_ERROR (("Ns_attach_object: Null Named_obj handle\n"));
return (AE_BAD_PARAMETER);
}
if (!object && (ACPI_TYPE_ANY != type)) {
/* Null object */
- REPORT_ERROR ("Ns_attach_object: Null object, but type"
- "not ACPI_TYPE_ANY");
+ REPORT_ERROR (("Ns_attach_object: Null object, but type not ACPI_TYPE_ANY\n"));
return (AE_BAD_PARAMETER);
}
if (!VALID_DESCRIPTOR_TYPE (node, ACPI_DESC_TYPE_NAMED)) {
/* Not a name handle */
- REPORT_ERROR ("Ns_attach_object: Invalid handle");
+ REPORT_ERROR (("Ns_attach_object: Invalid handle\n"));
return (AE_BAD_PARAMETER);
}
@@ -355,7 +354,6 @@ acpi_ns_get_attached_object (
if (!handle) {
/* handle invalid */
- REPORT_WARNING ("Ns_get_attached_object: Null handle");
return (NULL);
}
diff --git a/drivers/acpi/namespace/nssearch.c b/drivers/acpi/namespace/nssearch.c
index b6abbd782..001f57d9d 100644
--- a/drivers/acpi/namespace/nssearch.c
+++ b/drivers/acpi/namespace/nssearch.c
@@ -1,7 +1,7 @@
/*******************************************************************************
*
* Module Name: nssearch - Namespace search
- * $Revision: 57 $
+ * $Revision: 62 $
*
******************************************************************************/
@@ -169,7 +169,7 @@ acpi_ns_search_node (
*
******************************************************************************/
-ACPI_STATUS
+static ACPI_STATUS
acpi_ns_search_parent_tree (
u32 target_name,
ACPI_NAMESPACE_NODE *node,
@@ -270,7 +270,7 @@ acpi_ns_search_and_enter (
/* Parameter validation */
if (!node || !target_name || !return_node) {
- REPORT_ERROR ("Ns_search_and_enter: bad (null)parameter");
+ REPORT_ERROR (("Ns_search_and_enter: bad (null) parameter\n"));
return (AE_BAD_PARAMETER);
}
@@ -278,7 +278,7 @@ acpi_ns_search_and_enter (
/* Name must consist of printable characters */
if (!acpi_cm_valid_acpi_name (target_name)) {
- REPORT_ERROR ("Ns_search_and_enter: Bad character in ACPI Name");
+ REPORT_ERROR (("Ns_search_and_enter: Bad character in ACPI Name\n"));
return (AE_BAD_CHARACTER);
}
@@ -290,6 +290,16 @@ acpi_ns_search_and_enter (
type, return_node);
if (status != AE_NOT_FOUND) {
/*
+ * If we found it AND the request specifies that a
+ * find is an error, return the error
+ */
+ if ((status == AE_OK) &&
+ (flags & NS_ERROR_IF_FOUND))
+ {
+ status = AE_EXIST;
+ }
+
+ /*
* Either found it or there was an error
* -- finished either way
*/
diff --git a/drivers/acpi/namespace/nsutils.c b/drivers/acpi/namespace/nsutils.c
index 3d5a98a07..593064dbb 100644
--- a/drivers/acpi/namespace/nsutils.c
+++ b/drivers/acpi/namespace/nsutils.c
@@ -2,7 +2,7 @@
*
* Module Name: nsutils - Utilities for accessing ACPI namespace, accessing
* parents and siblings and Scope manipulation
- * $Revision: 69 $
+ * $Revision: 74 $
*
*****************************************************************************/
@@ -93,7 +93,7 @@ acpi_ns_get_type (
{
if (!handle) {
- REPORT_WARNING ("Ns_get_type: Null handle");
+ REPORT_WARNING (("Ns_get_type: Null handle\n"));
return (ACPI_TYPE_ANY);
}
@@ -120,7 +120,7 @@ acpi_ns_local (
if (!acpi_cm_valid_object_type (type)) {
/* Type code out of range */
- REPORT_WARNING ("Ns_local: Invalid Object Type");
+ REPORT_WARNING (("Ns_local: Invalid Object Type\n"));
return (NSP_NORMAL);
}
@@ -150,9 +150,10 @@ acpi_ns_internalize_name (
{
NATIVE_CHAR *result = NULL;
NATIVE_CHAR *internal_name;
- u32 num_segments;
+ u32 num_segments = 0;
u8 fully_qualified = FALSE;
u32 i;
+ u32 num_carats = 0;
if ((!external_name) ||
@@ -178,6 +179,16 @@ acpi_ns_internalize_name (
external_name++;
}
+ else {
+ /*
+ * Handle Carat prefixes
+ */
+
+ while (*external_name == '^') {
+ num_carats++;
+ external_name++;
+ }
+ }
/*
* Determine the number of ACPI name "segments" by counting
@@ -186,17 +197,19 @@ acpi_ns_internalize_name (
* + 1, and zero separators is ok.
*/
- num_segments = 1;
- for (i = 0; external_name[i]; i++) {
- if (acpi_ns_valid_path_separator (external_name[i])) {
- num_segments++;
+ if (*external_name) {
+ num_segments = 1;
+ for (i = 0; external_name[i]; i++) {
+ if (acpi_ns_valid_path_separator (external_name[i])) {
+ num_segments++;
+ }
}
}
/* We need a segment to store the internal version of the name */
- internal_name = acpi_cm_callocate ((ACPI_NAME_SIZE * num_segments) + 4);
+ internal_name = acpi_cm_callocate ((ACPI_NAME_SIZE * num_segments) + 4 + num_carats);
if (!internal_name) {
return (AE_NO_MEMORY);
}
@@ -206,14 +219,49 @@ acpi_ns_internalize_name (
if (fully_qualified) {
internal_name[0] = '\\';
- internal_name[1] = AML_MULTI_NAME_PREFIX_OP;
- internal_name[2] = (char) num_segments;
- result = &internal_name[3];
+
+ if (num_segments <= 1) {
+ result = &internal_name[1];
+ }
+ else if (num_segments == 2) {
+ internal_name[1] = AML_DUAL_NAME_PREFIX;
+ result = &internal_name[2];
+ }
+ else {
+ internal_name[1] = AML_MULTI_NAME_PREFIX_OP;
+ internal_name[2] = (char) num_segments;
+ result = &internal_name[3];
+ }
+
}
+
else {
- internal_name[0] = AML_MULTI_NAME_PREFIX_OP;
- internal_name[1] = (char) num_segments;
- result = &internal_name[2];
+ /*
+ * Not fully qualified.
+ * Handle Carats first, then append the name segments
+ */
+
+ i = 0;
+ if (num_carats) {
+ for (i = 0; i < num_carats; i++) {
+ internal_name[i] = '^';
+ }
+ }
+
+ if (num_segments == 1) {
+ result = &internal_name[i];
+ }
+
+ else if (num_segments == 2) {
+ internal_name[i] = AML_DUAL_NAME_PREFIX;
+ result = &internal_name[i+1];
+ }
+
+ else {
+ internal_name[i] = AML_MULTI_NAME_PREFIX_OP;
+ internal_name[i+1] = (char) num_segments;
+ result = &internal_name[i+2];
+ }
}
@@ -271,6 +319,157 @@ acpi_ns_internalize_name (
/****************************************************************************
*
+ * FUNCTION: Acpi_ns_externalize_name
+ *
+ * PARAMETERS: *Internal_name - Internal representation of name
+ * **Converted_name - Where to return the resulting
+ * external representation of name
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Convert internal name (e.g. 5c 2f 02 5f 50 52 5f 43 50 55 30)
+ * to its external form (e.g. "\_PR_.CPU0")
+ *
+ ****************************************************************************/
+
+ACPI_STATUS
+acpi_ns_externalize_name (
+ u32 internal_name_length,
+ char *internal_name,
+ u32 *converted_name_length,
+ char **converted_name)
+{
+ u32 prefix_length = 0;
+ u32 names_index = 0;
+ u32 names_count = 0;
+ u32 i = 0;
+ u32 j = 0;
+
+
+ if (!internal_name_length ||
+ !internal_name ||
+ !converted_name_length ||
+ !converted_name)
+ {
+ return (AE_BAD_PARAMETER);
+ }
+
+
+ /*
+ * Check for a prefix (one '\' | one or more '^').
+ */
+ switch (internal_name[0])
+ {
+ case '\\':
+ prefix_length = 1;
+ break;
+
+ case '^':
+ for (i = 0; i < internal_name_length; i++) {
+ if (internal_name[i] != '^') {
+ prefix_length = i + 1;
+ }
+ }
+
+ if (i == internal_name_length) {
+ prefix_length = i;
+ }
+
+ break;
+ }
+
+ /*
+ * Check for object names. Note that there could be 0-255 of these
+ * 4-byte elements.
+ */
+ if (prefix_length < internal_name_length) {
+ switch (internal_name[prefix_length])
+ {
+
+ /* <count> 4-byte names */
+
+ case AML_MULTI_NAME_PREFIX_OP:
+ names_index = prefix_length + 2;
+ names_count = (u32) internal_name[prefix_length + 1];
+ break;
+
+
+ /* two 4-byte names */
+
+ case AML_DUAL_NAME_PREFIX:
+ names_index = prefix_length + 1;
+ names_count = 2;
+ break;
+
+
+ /* Null_name */
+
+ case 0:
+ names_index = 0;
+ names_count = 0;
+ break;
+
+
+ /* one 4-byte name */
+
+ default:
+ names_index = prefix_length;
+ names_count = 1;
+ break;
+ }
+ }
+
+ /*
+ * Calculate the length of Converted_name, which equals the length
+ * of the prefix, length of all object names, length of any required
+ * punctuation ('.') between object names, plus the NULL terminator.
+ */
+ *converted_name_length = prefix_length + (4 * names_count) +
+ ((names_count > 0) ? (names_count - 1) : 0) + 1;
+
+ /*
+ * Check to see if we're still in bounds. If not, there's a problem
+ * with Internal_name (invalid format).
+ */
+ if (*converted_name_length > internal_name_length) {
+ REPORT_ERROR (("Ns_externalize_name: Invalid internal name\n"));
+ return (AE_BAD_PATHNAME);
+ }
+
+ /*
+ * Build Converted_name...
+ */
+
+ (*converted_name) = acpi_cm_callocate (*converted_name_length);
+ if (!(*converted_name)) {
+ return (AE_NO_MEMORY);
+ }
+
+ j = 0;
+
+ for (i = 0; i < prefix_length; i++) {
+ (*converted_name)[j++] = internal_name[i];
+ }
+
+ if (names_count > 0) {
+ for (i = 0; i < names_count; i++) {
+ if (i > 0) {
+ (*converted_name)[j++] = '.';
+ }
+
+ (*converted_name)[j++] = internal_name[names_index++];
+ (*converted_name)[j++] = internal_name[names_index++];
+ (*converted_name)[j++] = internal_name[names_index++];
+ (*converted_name)[j++] = internal_name[names_index++];
+ }
+ }
+
+ return (AE_OK);
+}
+
+
+/****************************************************************************
+ *
* FUNCTION: Acpi_ns_convert_handle_to_entry
*
* PARAMETERS: Handle - Handle to be converted to an Node
@@ -425,7 +624,7 @@ acpi_ns_opens_scope (
if (!acpi_cm_valid_object_type (type)) {
/* type code out of range */
- REPORT_WARNING ("Ns_opens_scope: Invalid Object Type");
+ REPORT_WARNING (("Ns_opens_scope: Invalid Object Type\n"));
return (NSP_NORMAL);
}
@@ -464,8 +663,6 @@ acpi_ns_get_node (
NATIVE_CHAR *internal_path = NULL;
- scope_info.scope.node = start_node;
-
/* Ensure that the namespace has been initialized */
if (!acpi_gbl_root_node) {
@@ -487,19 +684,9 @@ acpi_ns_get_node (
acpi_cm_acquire_mutex (ACPI_MTX_NAMESPACE);
- /* NS_ALL means start from the root */
-
- if (NS_ALL == scope_info.scope.node) {
- scope_info.scope.node = acpi_gbl_root_node;
- }
+ /* Setup lookup scope (search starting point) */
- else {
- scope_info.scope.node = start_node;
- if (!scope_info.scope.node) {
- status = AE_BAD_PARAMETER;
- goto unlock_and_exit;
- }
- }
+ scope_info.scope.node = start_node;
/* Lookup the name in the namespace */
@@ -510,8 +697,6 @@ acpi_ns_get_node (
-unlock_and_exit:
-
acpi_cm_release_mutex (ACPI_MTX_NAMESPACE);
/* Cleanup */
@@ -579,6 +764,10 @@ acpi_ns_get_parent_object (
{
+ if (!node) {
+ return (NULL);
+ }
+
/*
* Walk to the end of this peer list.
* The last entry is marked with a flag and the peer
diff --git a/drivers/acpi/namespace/nsxfname.c b/drivers/acpi/namespace/nsxfname.c
index dc02c6407..2947f7f06 100644
--- a/drivers/acpi/namespace/nsxfname.c
+++ b/drivers/acpi/namespace/nsxfname.c
@@ -2,7 +2,7 @@
*
* Module Name: nsxfname - Public interfaces to the ACPI subsystem
* ACPI Namespace oriented interfaces
- * $Revision: 64 $
+ * $Revision: 73 $
*
*****************************************************************************/
@@ -38,60 +38,6 @@
MODULE_NAME ("nsxfname")
-/******************************************************************************
- *
- * FUNCTION: Acpi_load_namespace
- *
- * PARAMETERS: Display_aml_during_load
- *
- * RETURN: Status
- *
- * DESCRIPTION: Load the name space from what ever is pointed to by DSDT.
- * (DSDT points to either the BIOS or a buffer.)
- *
- ******************************************************************************/
-
-ACPI_STATUS
-acpi_load_namespace (
- void)
-{
- ACPI_STATUS status;
-
-
- /* There must be at least a DSDT installed */
-
- if (acpi_gbl_DSDT == NULL) {
- return (AE_NO_ACPI_TABLES);
- }
-
-
- /*
- * Load the namespace. The DSDT is required,
- * but the SSDT and PSDT tables are optional.
- */
-
- status = acpi_ns_load_table_by_type (ACPI_TABLE_DSDT);
- if (ACPI_FAILURE (status)) {
- return (status);
- }
-
- /* Ignore exceptions from these */
-
- acpi_ns_load_table_by_type (ACPI_TABLE_SSDT);
- acpi_ns_load_table_by_type (ACPI_TABLE_PSDT);
-
-
- /*
- * Install the default Op_region handlers, ignore the return
- * code right now.
- */
-
- acpi_ev_install_default_address_space_handlers ();
-
- return (status);
-}
-
-
/****************************************************************************
*
* FUNCTION: Acpi_get_handle
@@ -117,7 +63,7 @@ acpi_get_handle (
ACPI_HANDLE *ret_handle)
{
ACPI_STATUS status;
- ACPI_NAMESPACE_NODE *node;
+ ACPI_NAMESPACE_NODE *node = NULL;
ACPI_NAMESPACE_NODE *prefix_node = NULL;
@@ -125,21 +71,21 @@ acpi_get_handle (
return (AE_BAD_PARAMETER);
}
+ /* Convert a parent handle to a prefix node */
+
if (parent) {
acpi_cm_acquire_mutex (ACPI_MTX_NAMESPACE);
- node = acpi_ns_convert_handle_to_entry (parent);
- if (!node) {
+ prefix_node = acpi_ns_convert_handle_to_entry (parent);
+ if (!prefix_node) {
acpi_cm_release_mutex (ACPI_MTX_NAMESPACE);
return (AE_BAD_PARAMETER);
}
- prefix_node = node->child;
acpi_cm_release_mutex (ACPI_MTX_NAMESPACE);
}
/* Special case for root, since we can't search for it */
- /* TBD: [Investigate] Check for both forward and backslash?? */
if (STRCMP (pathname, NS_ROOT_PATH) == 0) {
*ret_handle = acpi_ns_convert_entry_to_handle (acpi_gbl_root_node);
@@ -147,13 +93,12 @@ acpi_get_handle (
}
/*
- * Find the Node and convert to the user format
+ * Find the Node and convert to a handle
*/
- node = NULL;
status = acpi_ns_get_node (pathname, prefix_node, &node);
*ret_handle = NULL;
- if(ACPI_SUCCESS(status)) {
+ if (ACPI_SUCCESS (status)) {
*ret_handle = acpi_ns_convert_entry_to_handle (node);
}
@@ -253,42 +198,41 @@ unlock_and_exit:
*
* RETURN: Status
*
- * DESCRIPTION: Returns information about an object as gleaned from running
- * several standard control methods.
+ * DESCRIPTION: Returns information about an object as gleaned from the
+ * namespace node and possibly by running several standard
+ * control methods (Such as in the case of a device.)
*
******************************************************************************/
ACPI_STATUS
acpi_get_object_info (
- ACPI_HANDLE device,
+ ACPI_HANDLE handle,
ACPI_DEVICE_INFO *info)
{
DEVICE_ID hid;
DEVICE_ID uid;
ACPI_STATUS status;
u32 device_status = 0;
- u32 address = 0;
- ACPI_NAMESPACE_NODE *device_node;
+ ACPI_INTEGER address = 0;
+ ACPI_NAMESPACE_NODE *node;
/* Parameter validation */
- if (!device || !info) {
+ if (!handle || !info) {
return (AE_BAD_PARAMETER);
}
acpi_cm_acquire_mutex (ACPI_MTX_NAMESPACE);
- device_node = acpi_ns_convert_handle_to_entry (device);
- if (!device_node) {
+ node = acpi_ns_convert_handle_to_entry (handle);
+ if (!node) {
acpi_cm_release_mutex (ACPI_MTX_NAMESPACE);
return (AE_BAD_PARAMETER);
}
- info->type = device_node->type;
- info->name = device_node->name;
- info->parent = acpi_ns_convert_entry_to_handle (
- acpi_ns_get_parent_object (device_node));
+ info->type = node->type;
+ info->name = node->name;
acpi_cm_release_mutex (ACPI_MTX_NAMESPACE);
@@ -300,34 +244,30 @@ acpi_get_object_info (
}
- /* Get extra info for ACPI devices */
+ /*
+ * Get extra info for ACPI devices only. Run the
+ * _HID, _UID, _STA, and _ADR methods. Note: none
+ * of these methods are required, so they may or may
+ * not be present. The Info->Valid bits are used
+ * to indicate which methods ran successfully.
+ */
info->valid = 0;
/* Execute the _HID method and save the result */
- status = acpi_cm_execute_HID (device_node, &hid);
+ status = acpi_cm_execute_HID (node, &hid);
if (ACPI_SUCCESS (status)) {
- if (hid.type == STRING_PTR_DEVICE_ID) {
- STRCPY (info->hardware_id, hid.data.string_ptr);
- }
- else {
- STRCPY (info->hardware_id, hid.data.buffer);
- }
+ STRNCPY (info->hardware_id, hid.buffer, sizeof(info->hardware_id));
info->valid |= ACPI_VALID_HID;
}
/* Execute the _UID method and save the result */
- status = acpi_cm_execute_UID (device_node, &uid);
+ status = acpi_cm_execute_UID (node, &uid);
if (ACPI_SUCCESS (status)) {
- if (hid.type == STRING_PTR_DEVICE_ID) {
- STRCPY (info->unique_id, uid.data.string_ptr);
- }
- else {
- STRCPY (info->unique_id, uid.data.buffer);
- }
+ STRCPY (info->unique_id, uid.buffer);
info->valid |= ACPI_VALID_UID;
}
@@ -337,7 +277,7 @@ acpi_get_object_info (
* _STA is not always present
*/
- status = acpi_cm_execute_STA (device_node, &device_status);
+ status = acpi_cm_execute_STA (node, &device_status);
if (ACPI_SUCCESS (status)) {
info->current_status = device_status;
info->valid |= ACPI_VALID_STA;
@@ -349,7 +289,7 @@ acpi_get_object_info (
*/
status = acpi_cm_evaluate_numeric_object (METHOD_NAME__ADR,
- device_node, &address);
+ node, &address);
if (ACPI_SUCCESS (status)) {
info->address = address;
diff --git a/drivers/acpi/namespace/nsxfobj.c b/drivers/acpi/namespace/nsxfobj.c
index 9b254ea99..b9f93fdcb 100644
--- a/drivers/acpi/namespace/nsxfobj.c
+++ b/drivers/acpi/namespace/nsxfobj.c
@@ -2,7 +2,7 @@
*
* Module Name: nsxfobj - Public interfaces to the ACPI subsystem
* ACPI Object oriented interfaces
- * $Revision: 65 $
+ * $Revision: 75 $
*
******************************************************************************/
@@ -28,6 +28,7 @@
#include "acpi.h"
#include "acinterp.h"
#include "acnamesp.h"
+#include "acdispat.h"
#define _COMPONENT NAMESPACE
@@ -484,6 +485,8 @@ unlock_and_exit:
* Max_depth - Depth to which search is to reach
* User_function - Called when an object of "Type" is found
* Context - Passed to user function
+ * Return_value - Location where return value of
+ * User_function is put if terminated early
*
* RETURNS Return value from the User_function if terminated early.
* Otherwise, returns NULL.
@@ -544,3 +547,151 @@ acpi_walk_namespace (
}
+/*******************************************************************************
+ *
+ * FUNCTION: Acpi_ns_get_device_callback
+ *
+ * PARAMETERS: Callback from Acpi_get_device
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Takes callbacks from Walk_namespace and filters out all non-
+ * present devices, or if they specified a HID, it filters based
+ * on that.
+ *
+ ******************************************************************************/
+
+static ACPI_STATUS
+acpi_ns_get_device_callback (
+ ACPI_HANDLE obj_handle,
+ u32 nesting_level,
+ void *context,
+ void **return_value)
+{
+ ACPI_STATUS status;
+ ACPI_NAMESPACE_NODE *node;
+ u32 flags;
+ DEVICE_ID device_id;
+ ACPI_GET_DEVICES_INFO *info;
+
+
+ info = context;
+
+ acpi_cm_acquire_mutex (ACPI_MTX_NAMESPACE);
+
+ node = acpi_ns_convert_handle_to_entry (obj_handle);
+ if (!node) {
+ acpi_cm_release_mutex (ACPI_MTX_NAMESPACE);
+ return (AE_BAD_PARAMETER);
+ }
+
+ acpi_cm_release_mutex (ACPI_MTX_NAMESPACE);
+
+ /*
+ * Run _STA to determine if device is present
+ */
+
+ status = acpi_cm_execute_STA (node, &flags);
+ if (ACPI_FAILURE (status)) {
+ return (status);
+ }
+
+ if (!(flags & 0x01)) {
+ /* don't return at the device or children of the device if not there */
+
+ return (AE_CTRL_DEPTH);
+ }
+
+ /*
+ * Filter based on device HID
+ */
+ if (info->hid != NULL) {
+ status = acpi_cm_execute_HID (node, &device_id);
+
+ if (status == AE_NOT_FOUND) {
+ return (AE_OK);
+ }
+
+ else if (ACPI_FAILURE (status)) {
+ return (status);
+ }
+
+ if (STRNCMP (device_id.buffer, info->hid, sizeof (device_id.buffer)) != 0) {
+ return (AE_OK);
+ }
+ }
+
+ info->user_function (obj_handle, nesting_level, info->context, return_value);
+
+ return (AE_OK);
+}
+
+
+/*******************************************************************************
+ *
+ * FUNCTION: Acpi_get_devices
+ *
+ * PARAMETERS: HID - HID to search for. Can be NULL.
+ * User_function - Called when a matching object is found
+ * Context - Passed to user function
+ * Return_value - Location where return value of
+ * User_function is put if terminated early
+ *
+ * RETURNS Return value from the User_function if terminated early.
+ * Otherwise, returns NULL.
+ *
+ * DESCRIPTION: Performs a modified depth-first walk of the namespace tree,
+ * starting (and ending) at the object specified by Start_handle.
+ * The User_function is called whenever an object that matches
+ * the type parameter is found. If the user function returns
+ * a non-zero value, the search is terminated immediately and this
+ * value is returned to the caller.
+ *
+ * This is a wrapper for Walk_namespace, but the callback performs
+ * additional filtering. Please see Acpi_get_device_callback.
+ *
+ ******************************************************************************/
+
+ACPI_STATUS
+acpi_get_devices (
+ NATIVE_CHAR *HID,
+ WALK_CALLBACK user_function,
+ void *context,
+ void **return_value)
+{
+ ACPI_STATUS status;
+ ACPI_GET_DEVICES_INFO info;
+
+
+ /* Parameter validation */
+
+ if (!user_function) {
+ return (AE_BAD_PARAMETER);
+ }
+
+ /*
+ * We're going to call their callback from OUR callback, so we need
+ * to know what it is, and their context parameter.
+ */
+ info.context = context;
+ info.user_function = user_function;
+ info.hid = HID;
+
+ /*
+ * Lock the namespace around the walk.
+ * The namespace will be unlocked/locked around each call
+ * to the user function - since this function
+ * must be allowed to make Acpi calls itself.
+ */
+
+ acpi_cm_acquire_mutex (ACPI_MTX_NAMESPACE);
+ status = acpi_ns_walk_namespace (ACPI_TYPE_DEVICE,
+ ACPI_ROOT_OBJECT, ACPI_UINT32_MAX,
+ NS_WALK_UNLOCK,
+ acpi_ns_get_device_callback, &info,
+ return_value);
+
+ acpi_cm_release_mutex (ACPI_MTX_NAMESPACE);
+
+ return (status);
+} \ No newline at end of file