summaryrefslogtreecommitdiffstats
path: root/drivers/acpi/namespace
diff options
context:
space:
mode:
authorRalf Baechle <ralf@linux-mips.org>2000-07-08 00:53:00 +0000
committerRalf Baechle <ralf@linux-mips.org>2000-07-08 00:53:00 +0000
commitb8553086288629b4efb77e97f5582e08bc50ad65 (patch)
tree0a19bd1c21e148f35c7a0f76baa4f7a056b966b0 /drivers/acpi/namespace
parent75b6d92f2dd5112b02f4e78cf9f35f9825946ef0 (diff)
Merge with 2.4.0-test3-pre4.
Diffstat (limited to 'drivers/acpi/namespace')
-rw-r--r--drivers/acpi/namespace/nsaccess.c647
-rw-r--r--drivers/acpi/namespace/nsalloc.c411
-rw-r--r--drivers/acpi/namespace/nseval.c507
-rw-r--r--drivers/acpi/namespace/nsload.c488
-rw-r--r--drivers/acpi/namespace/nsnames.c503
-rw-r--r--drivers/acpi/namespace/nsobject.c556
-rw-r--r--drivers/acpi/namespace/nssearch.c646
-rw-r--r--drivers/acpi/namespace/nsutils.c886
-rw-r--r--drivers/acpi/namespace/nswalk.c279
-rw-r--r--drivers/acpi/namespace/nsxfname.c372
-rw-r--r--drivers/acpi/namespace/nsxfobj.c554
11 files changed, 5849 insertions, 0 deletions
diff --git a/drivers/acpi/namespace/nsaccess.c b/drivers/acpi/namespace/nsaccess.c
new file mode 100644
index 000000000..7cb9ac409
--- /dev/null
+++ b/drivers/acpi/namespace/nsaccess.c
@@ -0,0 +1,647 @@
+
+/******************************************************************************
+ *
+ * Module Name: nsaccess - Top-level functions for accessing ACPI namespace
+ *
+ *****************************************************************************/
+
+/*
+ * 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 "amlcode.h"
+#include "interp.h"
+#include "namesp.h"
+#include "dispatch.h"
+
+
+#define _COMPONENT NAMESPACE
+ MODULE_NAME ("nsaccess");
+
+
+/****************************************************************************
+ *
+ * FUNCTION: Acpi_ns_root_create_scope
+ *
+ * PARAMETERS: Entry - NTE for which a scope will be created
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Create a scope table for the given name table entry
+ *
+ * MUTEX: Expects namespace to be locked
+ *
+ ***************************************************************************/
+
+ACPI_STATUS
+acpi_ns_root_create_scope (
+ ACPI_NAMED_OBJECT *entry)
+{
+
+ /* Allocate a scope table */
+
+ if (entry->child_table) {
+ return (AE_EXIST);
+ }
+
+ entry->child_table = acpi_ns_allocate_name_table (NS_TABLE_SIZE);
+ if (!entry->child_table) {
+ /* root name table allocation failure */
+
+ REPORT_ERROR ("Root name table allocation failure");
+ return (AE_NO_MEMORY);
+ }
+
+ /*
+ * Init the scope first entry -- since it is the exemplar of
+ * the scope (Some fields are duplicated to new entries!)
+ */
+ acpi_ns_initialize_table (entry->child_table, NULL, entry);
+ return (AE_OK);
+
+}
+
+
+/****************************************************************************
+ *
+ * FUNCTION: Acpi_ns_root_initialize
+ *
+ * PARAMETERS: None
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Allocate and initialize the root name table
+ *
+ * MUTEX: Locks namespace for entire execution
+ *
+ ***************************************************************************/
+
+ACPI_STATUS
+acpi_ns_root_initialize (void)
+{
+ ACPI_STATUS status = AE_OK;
+ PREDEFINED_NAMES *init_val = NULL;
+ ACPI_NAMED_OBJECT *new_entry;
+ ACPI_OBJECT_INTERNAL *obj_desc;
+
+
+ acpi_cm_acquire_mutex (ACPI_MTX_NAMESPACE);
+
+ /*
+ * Root is initially NULL, so a non-NULL value indicates
+ * that Acpi_ns_root_initialize() has already been called; just return.
+ */
+
+ if (acpi_gbl_root_object->child_table) {
+ status = AE_OK;
+ goto unlock_and_exit;
+ }
+
+
+ /* Create the root scope */
+
+ status = acpi_ns_root_create_scope (acpi_gbl_root_object);
+ if (ACPI_FAILURE (status)) {
+ goto unlock_and_exit;
+ }
+
+ /* Enter the pre-defined names in the name table */
+
+ for (init_val = acpi_gbl_pre_defined_names; init_val->name; init_val++) {
+ status = acpi_ns_lookup (NULL, init_val->name,
+ (OBJECT_TYPE_INTERNAL) init_val->type,
+ IMODE_LOAD_PASS2, NS_NO_UPSEARCH,
+ NULL, &new_entry);
+
+ /*
+ * if name entered successfully
+ * && its entry in Pre_defined_names[] specifies an
+ * initial value
+ */
+
+ if ((status == AE_OK) &&
+ new_entry && init_val->val)
+ {
+ /*
+ * Entry requests an initial value, allocate a
+ * descriptor for it.
+ */
+
+ obj_desc =
+ acpi_cm_create_internal_object (
+ (OBJECT_TYPE_INTERNAL) init_val->type);
+
+ if (!obj_desc) {
+ status = AE_NO_MEMORY;
+ goto unlock_and_exit;
+ }
+
+ /*
+ * Convert value string from table entry to
+ * internal representation. Only types actually
+ * used for initial values are implemented here.
+ */
+
+ switch (init_val->type)
+ {
+
+ case ACPI_TYPE_NUMBER:
+
+ obj_desc->number.value =
+ (u32) STRTOUL (init_val->val, NULL, 10);
+ break;
+
+
+ case ACPI_TYPE_STRING:
+
+ obj_desc->string.length =
+ (u16) STRLEN (init_val->val);
+
+ /*
+ * Allocate a buffer for the string. All
+ * String.Pointers must be allocated buffers!
+ * (makes deletion simpler)
+ */
+ obj_desc->string.pointer =
+ acpi_cm_allocate ((ACPI_SIZE)
+ (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;
+ }
+
+ STRCPY ((char *) obj_desc->string.pointer,
+ init_val->val);
+ break;
+
+
+ case ACPI_TYPE_MUTEX:
+
+ obj_desc->mutex.sync_level =
+ (u16) STRTOUL (init_val->val, NULL, 10);
+
+ if (STRCMP (init_val->name, "_GL_") == 0) {
+ /*
+ * Create a counting semaphore for the
+ * global lock
+ */
+ status =
+ acpi_os_create_semaphore (ACPI_NO_UNIT_LIMIT,
+ 1, &obj_desc->mutex.semaphore);
+
+ if (ACPI_FAILURE (status)) {
+ goto unlock_and_exit;
+ }
+ /*
+ * We just created the mutex for the
+ * global lock, save it
+ */
+
+ acpi_gbl_global_lock_semaphore =
+ obj_desc->mutex.semaphore;
+ }
+
+ else {
+ /* Create a mutex */
+
+ status = acpi_os_create_semaphore (1, 1,
+ &obj_desc->mutex.semaphore);
+
+ if (ACPI_FAILURE (status)) {
+ goto unlock_and_exit;
+ }
+ }
+
+ /* TBD: [Restructure] These fields may be obsolete */
+
+ obj_desc->mutex.lock_count = 0;
+ obj_desc->mutex.thread_id = 0;
+ break;
+
+
+ default:
+ REPORT_ERROR ("Unsupported initial type value");
+ acpi_cm_remove_reference (obj_desc);
+ obj_desc = NULL;
+ continue;
+ }
+
+ /* Store pointer to value descriptor in nte */
+
+ acpi_ns_attach_object (new_entry, obj_desc,
+ obj_desc->common.type);
+ }
+ }
+
+
+unlock_and_exit:
+ acpi_cm_release_mutex (ACPI_MTX_NAMESPACE);
+ return (status);
+}
+
+
+/****************************************************************************
+ *
+ * FUNCTION: Acpi_ns_lookup
+ *
+ * PARAMETERS: Prefix_scope - 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
+ * Ret_entry - Where the new entry (NTE) is placed
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Find or enter the passed name in the name space.
+ * Log an error if name not found in Exec mode.
+ *
+ * MUTEX: Assumes namespace is locked.
+ *
+ ***************************************************************************/
+
+ACPI_STATUS
+acpi_ns_lookup (
+ ACPI_GENERIC_STATE *scope_info,
+ char *pathname,
+ OBJECT_TYPE_INTERNAL type,
+ OPERATING_MODE interpreter_mode,
+ u32 flags,
+ ACPI_WALK_STATE *walk_state,
+ ACPI_NAMED_OBJECT **ret_entry)
+{
+ ACPI_STATUS status;
+ ACPI_NAME_TABLE *prefix_scope;
+ ACPI_NAME_TABLE *table_to_search = NULL;
+ ACPI_NAME_TABLE *scope_to_push = NULL;
+ ACPI_NAMED_OBJECT *this_entry = NULL;
+ u32 num_segments;
+ ACPI_NAME simple_name;
+ u8 null_name_path = FALSE;
+ OBJECT_TYPE_INTERNAL type_to_check_for;
+ OBJECT_TYPE_INTERNAL this_search_type;
+
+ if (!ret_entry) {
+ return (AE_BAD_PARAMETER);
+ }
+
+
+ acpi_gbl_ns_lookup_count++;
+
+ *ret_entry = ENTRY_NOT_FOUND;
+ if (!acpi_gbl_root_object->child_table) {
+ /*
+ * If the name space has not been initialized:
+ * - In Pass1 of Load mode, we need to initialize it
+ * before trying to define a name.
+ * - In Exec mode, there are no names to be found.
+ */
+
+ if (IMODE_LOAD_PASS1 == interpreter_mode) {
+ if ((status = acpi_ns_root_initialize ()) != AE_OK) {
+ return (status);
+ }
+ }
+ else {
+ return (AE_NOT_FOUND);
+ }
+ }
+
+
+ /*
+ * Get the prefix scope.
+ * A null scope means use the root scope
+ */
+
+ if ((!scope_info) ||
+ (!scope_info->scope.name_table))
+ {
+ prefix_scope = acpi_gbl_root_object->child_table;
+ }
+ else {
+ prefix_scope = scope_info->scope.name_table;
+ }
+
+
+ /*
+ * This check is explicitly split provide relax the Type_to_check_for
+ * conditions for Bank_field_defn. Originally, both Bank_field_defn and
+ * Def_field_defn caused Type_to_check_for to be set to ACPI_TYPE_REGION,
+ * but the Bank_field_defn may also check for a Field definition as well
+ * as an Operation_region.
+ */
+
+ if (INTERNAL_TYPE_DEF_FIELD_DEFN == type) {
+ /* Def_field_defn defines fields in a Region */
+
+ type_to_check_for = ACPI_TYPE_REGION;
+ }
+
+ else if (INTERNAL_TYPE_BANK_FIELD_DEFN == type) {
+ /* Bank_field_defn defines data fields in a Field Object */
+
+ type_to_check_for = ACPI_TYPE_ANY;
+ }
+
+ else {
+ type_to_check_for = type;
+ }
+
+
+ /* Examine the name pointer */
+
+ if (!pathname) {
+ /* 8-12-98 ASL Grammar Update supports null Name_path */
+
+ null_name_path = TRUE;
+ num_segments = 0;
+ this_entry = acpi_gbl_root_object;
+
+ }
+
+ else {
+ /*
+ * Valid name pointer (Internal name format)
+ *
+ * Check for prefixes. As represented in the AML stream, a
+ * Pathname consists of an optional scope prefix followed by
+ * a segment part.
+ *
+ * If present, the scope prefix is either a Root_prefix (in
+ * which case the name is fully qualified), or zero or more
+ * Parent_prefixes (in which case the name's scope is relative
+ * to the current scope).
+ *
+ * The segment part consists of either:
+ * - A single 4-byte name segment, or
+ * - A Dual_name_prefix followed by two 4-byte name segments, or
+ * - A Multi_name_prefix_op, followed by a byte indicating the
+ * number of segments and the segments themselves.
+ */
+
+ if (*pathname == AML_ROOT_PREFIX) {
+ /* Pathname is fully qualified, look in root name table */
+
+ table_to_search = acpi_gbl_root_object->child_table;
+ /* point to segment part */
+ pathname++;
+
+ /* Direct reference to root, "\" */
+
+ if (!(*pathname)) {
+ this_entry = acpi_gbl_root_object;
+ goto check_for_new_scope_and_exit;
+ }
+ }
+
+ else {
+ /* Pathname is relative to current scope, start there */
+
+ table_to_search = prefix_scope;
+
+ /*
+ * Handle up-prefix (carat). More than one prefix
+ * is supported
+ */
+
+ while (*pathname == AML_PARENT_PREFIX) {
+
+ /* Point to segment part or next Parent_prefix */
+
+ pathname++;
+
+ /* Backup to the parent's scope */
+
+ table_to_search = table_to_search->parent_table;
+ if (!table_to_search) {
+ /* Current scope has no parent scope */
+
+ REPORT_ERROR ("Ns_lookup: Too many parent"
+ "prefixes or scope has no parent");
+
+
+ return (AE_NOT_FOUND);
+ }
+ }
+ }
+
+
+ /*
+ * Examine the name prefix opcode, if any,
+ * to determine the number of segments
+ */
+
+ if (*pathname == AML_DUAL_NAME_PREFIX) {
+ num_segments = 2;
+ /* point to first segment */
+ pathname++;
+
+ }
+
+ else if (*pathname == AML_MULTI_NAME_PREFIX_OP) {
+ num_segments = (s32)* (u8 *) ++pathname;
+ /* point to first segment */
+ pathname++;
+
+ }
+
+ else {
+ /*
+ * No Dual or Multi prefix, hence there is only one
+ * segment and Pathname is already pointing to it.
+ */
+ num_segments = 1;
+
+ }
+
+ }
+
+
+ /*
+ * Search namespace for each segment of the name.
+ * Loop through and verify/add each name segment.
+ */
+
+
+ while (num_segments-- && table_to_search) {
+ /*
+ * Search for the current segment in the table where
+ * it should be.
+ * Type is significant only at the last (topmost) level.
+ */
+ this_search_type = ACPI_TYPE_ANY;
+ if (!num_segments) {
+ this_search_type = type;
+ }
+
+ MOVE_UNALIGNED32_TO_32 (&simple_name, pathname);
+ status = acpi_ns_search_and_enter (simple_name, walk_state,
+ table_to_search, interpreter_mode,
+ this_search_type, flags,
+ &this_entry);
+
+ if (status != AE_OK) {
+ if (status == AE_NOT_FOUND) {
+ /* Name not in ACPI namespace */
+
+ if (IMODE_LOAD_PASS1 == interpreter_mode ||
+ IMODE_LOAD_PASS2 == interpreter_mode)
+ {
+ REPORT_ERROR ("Name table overflow");
+ }
+
+ }
+
+ return (status);
+ }
+
+
+ /*
+ * If 1) 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 entry is known (not TYPE_ANY)
+ * 7) and entry 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_DEF_ANY) &&
+ (type_to_check_for != INTERNAL_TYPE_SCOPE) &&
+ (type_to_check_for != INTERNAL_TYPE_INDEX_FIELD_DEFN) &&
+ (this_entry->type != ACPI_TYPE_ANY) &&
+ (this_entry->type != type_to_check_for))
+ {
+ /* Complain about type mismatch */
+
+ REPORT_WARNING ("Type mismatch");
+ }
+
+ /*
+ * If last segment and not looking for a specific type, but type of
+ * found entry is known, use that type to see if it opens a scope.
+ */
+
+ if ((0 == num_segments) && (ACPI_TYPE_ANY == type)) {
+ type = this_entry->type;
+ }
+
+ if ((num_segments || acpi_ns_opens_scope (type)) &&
+ (this_entry->child_table == NULL))
+ {
+ /*
+ * More segments or the type implies enclosed scope,
+ * and the next scope has not been allocated.
+ */
+
+ if ((IMODE_LOAD_PASS1 == interpreter_mode) ||
+ (IMODE_LOAD_PASS2 == interpreter_mode))
+ {
+ /*
+ * First or second pass load mode
+ * ==> locate the next scope
+ */
+
+ this_entry->child_table =
+ acpi_ns_allocate_name_table (NS_TABLE_SIZE);
+
+ if (!this_entry->child_table) {
+ return (AE_NO_MEMORY);
+ }
+ }
+
+ /* Now complain if there is no next scope */
+
+ if (this_entry->child_table == NULL) {
+ if (IMODE_LOAD_PASS1 == interpreter_mode ||
+ IMODE_LOAD_PASS2 == interpreter_mode)
+ {
+ REPORT_ERROR ("Name Table allocation failure");
+ return (AE_NOT_FOUND);
+ }
+
+ return (AE_NOT_FOUND);
+ }
+
+
+ /* Scope table initialization */
+
+ if (IMODE_LOAD_PASS1 == interpreter_mode ||
+ IMODE_LOAD_PASS2 == interpreter_mode)
+ {
+ /* Initialize the new table */
+
+ acpi_ns_initialize_table (this_entry->child_table,
+ table_to_search,
+ this_entry);
+ }
+ }
+
+ table_to_search = this_entry->child_table;
+ /* point to next name segment */
+ pathname += ACPI_NAME_SIZE;
+ }
+
+
+ /*
+ * Always check if we need to open a new scope
+ */
+
+check_for_new_scope_and_exit:
+
+ if (!(flags & NS_DONT_OPEN_SCOPE) && (walk_state)) {
+ /*
+ * If entry is a type which opens a scope,
+ * push the new scope on the scope stack.
+ */
+
+ if (acpi_ns_opens_scope (type_to_check_for)) {
+ /* 8-12-98 ASL Grammar Update supports null Name_path */
+
+ if (null_name_path) {
+ /* TBD: [Investigate] - is this the correct thing to do? */
+
+ scope_to_push = NULL;
+ }
+ else {
+ scope_to_push = this_entry->child_table;
+ }
+
+ status = acpi_ds_scope_stack_push (scope_to_push, type,
+ walk_state);
+ if (ACPI_FAILURE (status)) {
+ return (status);
+ }
+
+ }
+ }
+
+ *ret_entry = this_entry;
+ return (AE_OK);
+}
+
diff --git a/drivers/acpi/namespace/nsalloc.c b/drivers/acpi/namespace/nsalloc.c
new file mode 100644
index 000000000..414f3791a
--- /dev/null
+++ b/drivers/acpi/namespace/nsalloc.c
@@ -0,0 +1,411 @@
+
+/******************************************************************************
+ *
+ * Module Name: nsalloc - Namespace allocation and deletion utilities
+ *
+ *****************************************************************************/
+
+/*
+ * 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 "namesp.h"
+#include "interp.h"
+
+
+#define _COMPONENT NAMESPACE
+ MODULE_NAME ("nsalloc");
+
+
+/****************************************************************************
+ *
+ * FUNCTION: Acpi_ns_allocate_name_table
+ *
+ * PARAMETERS: Nte_count - Count of NTEs to allocate
+ *
+ * RETURN: The address of the first nte in the array, or NULL
+ *
+ * DESCRIPTION: Allocate an array of nte, including prepended link space
+ * Array is set to all zeros via Acpi_os_callcate().
+ *
+ ***************************************************************************/
+
+ACPI_NAME_TABLE *
+acpi_ns_allocate_name_table (
+ u32 num_entries)
+{
+ ACPI_NAME_TABLE *name_table = NULL;
+ ACPI_SIZE alloc_size;
+
+
+ alloc_size = sizeof (ACPI_NAME_TABLE) + ((num_entries - 1) *
+ sizeof (ACPI_NAMED_OBJECT));
+
+ name_table = acpi_cm_callocate (alloc_size);
+
+
+ return (name_table);
+}
+
+
+/****************************************************************************
+ *
+ * FUNCTION: Acpi_ns_delete_namespace_subtree
+ *
+ * PARAMETERS: None.
+ *
+ * RETURN: None.
+ *
+ * DESCRIPTION: Delete a subtree of the namespace. This includes all objects stored
+ * within the subtree. Scope tables are deleted also
+ *
+ ***************************************************************************/
+
+ACPI_STATUS
+acpi_ns_delete_namespace_subtree (
+ ACPI_NAMED_OBJECT *parent_entry)
+{
+ ACPI_NAMED_OBJECT *child_entry;
+ u32 level;
+ ACPI_OBJECT_INTERNAL *obj_desc;
+
+
+ child_entry = 0;
+ level = 1;
+
+ /*
+ * Traverse the tree of objects until we bubble back up
+ * to where we started.
+ */
+
+ while (level > 0) {
+ /*
+ * Get the next typed object in this scope.
+ * Null returned if not found
+ */
+
+ child_entry = acpi_ns_get_next_object (ACPI_TYPE_ANY,
+ parent_entry,
+ child_entry);
+
+ if (child_entry) {
+ /*
+ * Found an object - delete the object within
+ * the Value field
+ */
+
+ obj_desc = acpi_ns_get_attached_object (child_entry);
+ if (obj_desc) {
+ acpi_ns_detach_object (child_entry);
+ acpi_cm_remove_reference (obj_desc);
+ }
+
+
+ /*
+ * Clear the NTE in case this scope is reused
+ * (e.g., a control method scope)
+ */
+
+ child_entry->type = ACPI_TYPE_ANY;
+ child_entry->name = 0;
+
+ /* Check if this object has any children */
+
+ if (acpi_ns_get_next_object (ACPI_TYPE_ANY, child_entry, 0)) {
+ /*
+ * There is at least one child of this object,
+ * visit the object
+ */
+
+ level++;
+ parent_entry = child_entry;
+ child_entry = 0;
+ }
+
+ else {
+ /*
+ * There may be a name table even if there are
+ * no children
+ */
+
+ acpi_ns_delete_name_table (child_entry->child_table);
+ child_entry->child_table = NULL;
+
+ }
+ }
+
+ else {
+ /*
+ * No more children in this object.
+ * We will move up to the grandparent.
+ */
+ level--;
+
+ /*
+ * Delete the scope (Name Table) associated with
+ * the parent object
+ */
+ /* Don't delete the top level scope, this allows
+ * the dynamic deletion of objects created underneath
+ * control methods!
+ */
+
+ if (level != 0) {
+ acpi_ns_delete_name_table (parent_entry->child_table);
+ parent_entry->child_table = NULL;
+ }
+
+ /* New "last child" is this parent object */
+
+ child_entry = parent_entry;
+
+ /* Now we can move up the tree to the grandparent */
+
+ parent_entry = acpi_ns_get_parent_entry (parent_entry);
+ }
+ }
+
+
+ return (AE_OK);
+}
+
+
+/****************************************************************************
+ *
+ * FUNCTION: Acpi_ns_remove_reference
+ *
+ * PARAMETERS: Entry - NTE whose reference count is to be decremented
+ *
+ * RETURN: None.
+ *
+ * DESCRIPTION: Remove an NTE reference. Decrements the reference count of
+ * all parent NTEs up to the root. Any NTE along the way that
+ * reaches zero references is freed.
+ *
+ ***************************************************************************/
+
+void
+acpi_ns_remove_reference (
+ ACPI_NAMED_OBJECT *entry)
+{
+ ACPI_NAMED_OBJECT *this_entry;
+
+
+ /* There may be a name table even if there are no children */
+
+ acpi_ns_delete_name_table (entry->child_table);
+ entry->child_table = NULL;
+
+
+ /*
+ * Decrement the reference count(s) of all parents up to the root,
+ * And delete anything with zero remaining references.
+ */
+ this_entry = entry;
+ while (this_entry) {
+ /* Decrement the reference */
+
+ this_entry->reference_count--;
+
+ /* Delete entry if no more references */
+
+ if (!this_entry->reference_count) {
+ /* Delete the scope if present */
+
+ if (this_entry->child_table) {
+ acpi_ns_delete_name_table (this_entry->child_table);
+ this_entry->child_table = NULL;
+ }
+
+ /*
+ * Mark the entry free
+ * (This doesn't deallocate anything)
+ */
+
+ acpi_ns_free_table_entry (this_entry);
+
+ }
+
+ /* Move up to parent */
+
+ this_entry = acpi_ns_get_parent_entry (this_entry);
+ }
+}
+
+
+/****************************************************************************
+ *
+ * FUNCTION: Acpi_ns_delete_namespace_by_owner
+ *
+ * PARAMETERS: None.
+ *
+ * RETURN: None.
+ *
+ * DESCRIPTION: Delete entries within the namespace that are owned by a
+ * specific ID. Used to delete entire ACPI tables. All
+ * reference counts are updated.
+ *
+ ***************************************************************************/
+
+ACPI_STATUS
+acpi_ns_delete_namespace_by_owner (
+ u16 owner_id)
+{
+ ACPI_NAMED_OBJECT *child_entry;
+ u32 level;
+ ACPI_OBJECT_INTERNAL *obj_desc;
+ ACPI_NAMED_OBJECT *parent_entry;
+
+
+ parent_entry = acpi_gbl_root_object;
+ child_entry = 0;
+ level = 1;
+
+ /*
+ * Traverse the tree of objects until we bubble back up
+ * to where we started.
+ */
+
+ while (level > 0) {
+ /*
+ * Get the next typed object in this scope.
+ * Null returned if not found
+ */
+
+ child_entry = acpi_ns_get_next_object (ACPI_TYPE_ANY,
+ parent_entry,
+ child_entry);
+
+ if (child_entry) {
+ if (child_entry->owner_id == owner_id) {
+ /*
+ * Found an object - delete the object within
+ * the Value field
+ */
+
+ obj_desc = acpi_ns_get_attached_object (child_entry);
+ if (obj_desc) {
+ acpi_ns_detach_object (child_entry);
+ acpi_cm_remove_reference (obj_desc);
+ }
+ }
+
+ /* Check if this object has any children */
+
+ if (acpi_ns_get_next_object (ACPI_TYPE_ANY, child_entry, 0)) {
+ /*
+ * There is at least one child of this object,
+ * visit the object
+ */
+
+ level++;
+ parent_entry = child_entry;
+ child_entry = 0;
+ }
+
+ else if (child_entry->owner_id == owner_id) {
+ acpi_ns_remove_reference (child_entry);
+ }
+ }
+
+ else {
+ /*
+ * No more children in this object.
+ * We will move up to the grandparent.
+ */
+ level--;
+
+ /*
+ * Delete the scope (Name Table) associated with
+ * the parent object
+ */
+ /* Don't delete the top level scope, this allows
+ * the dynamic deletion of objects created underneath
+ * control methods!
+ */
+
+
+ if (level != 0) {
+ if (parent_entry->owner_id == owner_id) {
+ acpi_ns_remove_reference (parent_entry);
+ }
+ }
+
+
+ /* New "last child" is this parent object */
+
+ child_entry = parent_entry;
+
+ /* Now we can move up the tree to the grandparent */
+
+ parent_entry = acpi_ns_get_parent_entry (parent_entry);
+ }
+ }
+
+
+ return (AE_OK);
+}
+
+
+/****************************************************************************
+ *
+ * FUNCTION: Acpi_ns_delete_name_table
+ *
+ * PARAMETERS: Scope - A handle to the scope to be deleted
+ *
+ * RETURN: None.
+ *
+ * DESCRIPTION: Delete a namespace Name Table with zero or
+ * more appendages. The table and all appendages are deleted.
+ *
+ ***************************************************************************/
+
+void
+acpi_ns_delete_name_table (
+ ACPI_NAME_TABLE *name_table)
+{
+ ACPI_NAME_TABLE *this_table;
+ ACPI_NAME_TABLE *next_table;
+
+
+ if (!name_table) {
+ return;
+ }
+
+ this_table = name_table;
+
+
+ /*
+ * Deallocate the name table and all appendages
+ */
+ do
+ {
+ next_table = this_table->next_table;
+
+ /* Now we can free the table */
+
+ acpi_cm_free (this_table);
+ this_table = next_table;
+
+ } while (this_table);
+
+ return;
+}
+
+
diff --git a/drivers/acpi/namespace/nseval.c b/drivers/acpi/namespace/nseval.c
new file mode 100644
index 000000000..ea3e15621
--- /dev/null
+++ b/drivers/acpi/namespace/nseval.c
@@ -0,0 +1,507 @@
+
+/******************************************************************************
+ *
+ * Module Name: nseval - Object evaluation interfaces -- includes control
+ * method lookup and execution.
+ *
+ *****************************************************************************/
+
+/*
+ * 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 "amlcode.h"
+#include "parser.h"
+#include "interp.h"
+#include "namesp.h"
+
+
+#define _COMPONENT NAMESPACE
+ MODULE_NAME ("nseval");
+
+
+/****************************************************************************
+ *
+ * FUNCTION: Acpi_ns_evaluate_relative
+ *
+ * PARAMETERS: Rel_obj_entry - NTE of the relative containing object
+ * *Pathname - Name of method to execute, If NULL, the
+ * handle is the object to execute
+ * **Params - List of parameters to pass to the method,
+ * terminated by NULL. Params itself may be
+ * NULL if no parameters are being passed.
+ * *Return_object - Where to put method's return value (if
+ * any). If NULL, no value is returned.
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Find and execute the requested method using the handle as a
+ * scope
+ *
+ * MUTEX: Locks Namespace
+ *
+ ****************************************************************************/
+
+ACPI_STATUS
+acpi_ns_evaluate_relative (
+ ACPI_NAMED_OBJECT *handle,
+ char *pathname,
+ ACPI_OBJECT_INTERNAL **params,
+ ACPI_OBJECT_INTERNAL **return_object)
+{
+ ACPI_NAMED_OBJECT *rel_obj_entry;
+ ACPI_STATUS status;
+ ACPI_NAMED_OBJECT *obj_entry = NULL;
+ char *internal_path = NULL;
+ ACPI_GENERIC_STATE scope_info;
+
+
+ /*
+ * Must have a valid object handle
+ */
+ if (!handle) {
+ return (AE_BAD_PARAMETER);
+ }
+
+ /* Build an internal name string for the method */
+
+ status = acpi_ns_internalize_name (pathname, &internal_path);
+ if (ACPI_FAILURE (status)) {
+ return (status);
+ }
+
+ /* Get the prefix handle and NTE */
+
+ acpi_cm_acquire_mutex (ACPI_MTX_NAMESPACE);
+
+ rel_obj_entry = acpi_ns_convert_handle_to_entry (handle);
+ if (!rel_obj_entry) {
+ acpi_cm_release_mutex (ACPI_MTX_NAMESPACE);
+ status = AE_BAD_PARAMETER;
+ goto cleanup;
+ }
+
+ /* Lookup the name in the namespace */
+
+ scope_info.scope.name_table = rel_obj_entry->child_table;
+ status = acpi_ns_lookup (&scope_info, internal_path, ACPI_TYPE_ANY,
+ IMODE_EXECUTE,
+ NS_NO_UPSEARCH, NULL,
+ &obj_entry);
+
+ acpi_cm_release_mutex (ACPI_MTX_NAMESPACE);
+
+ if (status != AE_OK) {
+ goto cleanup;
+ }
+
+ /*
+ * Now that we have a handle to the object, we can attempt
+ * to evaluate it.
+ */
+
+ status = acpi_ns_evaluate_by_handle (obj_entry, params, return_object);
+
+cleanup:
+
+ /* Cleanup */
+
+ acpi_cm_free (internal_path);
+
+ return (status);
+}
+
+
+/****************************************************************************
+ *
+ * FUNCTION: Acpi_ns_evaluate_by_name
+ *
+ * PARAMETERS: Pathname - Fully qualified pathname to the object
+ * *Return_object - Where to put method's return value (if
+ * any). If NULL, no value is returned.
+ * **Params - List of parameters to pass to the method,
+ * terminated by NULL. Params itself may be
+ * NULL if no parameters are being passed.
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Find and execute the requested method passing the given
+ * parameters
+ *
+ * MUTEX: Locks Namespace
+ *
+ ****************************************************************************/
+
+ACPI_STATUS
+acpi_ns_evaluate_by_name (
+ char *pathname,
+ ACPI_OBJECT_INTERNAL **params,
+ ACPI_OBJECT_INTERNAL **return_object)
+{
+ ACPI_STATUS status;
+ ACPI_NAMED_OBJECT *obj_entry = NULL;
+ char *internal_path = NULL;
+
+
+ /* Build an internal name string for the method */
+
+ if (pathname[0] != '\\' || pathname[1] != '/') {
+ status = acpi_ns_internalize_name (pathname, &internal_path);
+ if (ACPI_FAILURE (status)) {
+ return (status);
+ }
+ }
+
+ acpi_cm_acquire_mutex (ACPI_MTX_NAMESPACE);
+
+ /* Lookup the name in the namespace */
+
+ status = acpi_ns_lookup (NULL, internal_path, ACPI_TYPE_ANY,
+ IMODE_EXECUTE,
+ NS_NO_UPSEARCH, NULL,
+ &obj_entry);
+
+ acpi_cm_release_mutex (ACPI_MTX_NAMESPACE);
+
+ if (status != AE_OK) {
+ goto cleanup;
+ }
+
+ /*
+ * Now that we have a handle to the object, we can attempt
+ * to evaluate it.
+ */
+
+ status = acpi_ns_evaluate_by_handle (obj_entry, params, return_object);
+
+
+cleanup:
+
+ /* Cleanup */
+
+ if (internal_path) {
+ acpi_cm_free (internal_path);
+ }
+
+ return (status);
+}
+
+
+/****************************************************************************
+ *
+ * FUNCTION: Acpi_ns_evaluate_by_handle
+ *
+ * PARAMETERS: Obj_entry - NTE of method to execute
+ * *Return_object - Where to put method's return value (if
+ * any). If NULL, no value is returned.
+ * **Params - List of parameters to pass to the method,
+ * terminated by NULL. Params itself may be
+ * NULL if no parameters are being passed.
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Execute the requested method passing the given parameters
+ *
+ * MUTEX: Locks Namespace
+ *
+ ****************************************************************************/
+
+ACPI_STATUS
+acpi_ns_evaluate_by_handle (
+ ACPI_NAMED_OBJECT *handle,
+ ACPI_OBJECT_INTERNAL **params,
+ ACPI_OBJECT_INTERNAL **return_object)
+{
+ ACPI_NAMED_OBJECT *obj_entry;
+ ACPI_STATUS status;
+ ACPI_OBJECT_INTERNAL *local_return_object;
+
+
+ /* Check if namespace has been initialized */
+
+ if (!acpi_gbl_root_object->child_table) {
+ return (AE_NO_NAMESPACE);
+ }
+
+ /* Parameter Validation */
+
+ if (!handle) {
+ return (AE_BAD_PARAMETER);
+ }
+
+ if (return_object) {
+ /* Initialize the return value to an invalid object */
+
+ *return_object = NULL;
+ }
+
+ /* Get the prefix handle and NTE */
+
+ acpi_cm_acquire_mutex (ACPI_MTX_NAMESPACE);
+
+ obj_entry = acpi_ns_convert_handle_to_entry (handle);
+ if (!obj_entry) {
+ status = AE_BAD_PARAMETER;
+ goto unlock_and_exit;
+ }
+
+
+ /*
+ * Two major cases here:
+ * 1) The object is an actual control method -- execute it.
+ * 2) The object is not a method -- just return it's current
+ * value
+ *
+ * In both cases, the namespace is unlocked by the
+ * Acpi_ns* procedure
+ */
+
+ if (acpi_ns_get_type (obj_entry) == ACPI_TYPE_METHOD) {
+ /*
+ * Case 1) We have an actual control method to execute
+ */
+
+ status = acpi_ns_execute_control_method (obj_entry,
+ params,
+ &local_return_object);
+ }
+
+ else {
+ /*
+ * Case 2) Object is NOT a method, just return its
+ * current value
+ */
+
+ status = acpi_ns_get_object_value (obj_entry,
+ &local_return_object);
+ }
+
+
+ /*
+ * Check if there is a return value on the stack that must
+ * be dealt with
+ */
+
+ if (status == AE_CTRL_RETURN_VALUE) {
+ /*
+ * If the Method returned a value and the caller
+ * provided a place to store a returned value, Copy
+ * the returned value to the object descriptor provided
+ * by the caller.
+ */
+
+ if (return_object) {
+ /*
+ * Valid return object, copy the pointer to
+ * the returned object
+ */
+
+ *return_object = local_return_object;
+ }
+
+
+ /* Map AE_RETURN_VALUE to AE_OK, we are done with it */
+
+ if (status == AE_CTRL_RETURN_VALUE) {
+ status = AE_OK;
+ }
+ }
+
+ /*
+ * Namespace was unlocked by the handling Acpi_ns* function,
+ * so we just return
+ */
+
+ return (status);
+
+
+unlock_and_exit:
+
+ acpi_cm_release_mutex (ACPI_MTX_NAMESPACE);
+ return (status);
+}
+
+
+/****************************************************************************
+ *
+ * FUNCTION: Acpi_ns_execute_control_method
+ *
+ * PARAMETERS: Method_entry - The Nte of the object/method
+ * **Params - List of parameters to pass to the method,
+ * terminated by NULL. Params itself may be
+ * NULL if no parameters are being passed.
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Execute the requested method passing the given parameters
+ *
+ * MUTEX: Assumes namespace is locked
+ *
+ ****************************************************************************/
+
+ACPI_STATUS
+acpi_ns_execute_control_method (
+ ACPI_NAMED_OBJECT *method_entry,
+ ACPI_OBJECT_INTERNAL **params,
+ ACPI_OBJECT_INTERNAL **return_obj_desc)
+{
+ ACPI_STATUS status;
+ ACPI_OBJECT_INTERNAL *obj_desc;
+
+
+ /* Verify that there is a method associated with this object */
+
+ obj_desc = acpi_ns_get_attached_object ((ACPI_HANDLE) method_entry);
+ if (!obj_desc) {
+ return (AE_ERROR);
+ }
+
+ /*
+ * Valid method, Set the current scope to that of the Method,
+ * and execute it.
+ */
+
+
+ /*
+ * Unlock the namespace before execution. This allows namespace access
+ * via the external Acpi* interfaces while a method is being executed.
+ * However, any namespace deletion must acquire both the namespace and
+ * interpter locks to ensure that no thread is using the portion of the
+ * namespace that is being deleted.
+ */
+
+ acpi_cm_release_mutex (ACPI_MTX_NAMESPACE);
+
+ /*
+ * Excecute the method via the interpreter
+ */
+ status = acpi_aml_execute_method (method_entry, params, return_obj_desc);
+
+ return (status);
+}
+
+
+/****************************************************************************
+ *
+ * FUNCTION: Acpi_ns_get_object_value
+ *
+ * PARAMETERS: Object_entry - The Nte of the object
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Return the current value of the object
+ *
+ * MUTEX: Assumes namespace is locked
+ *
+ ****************************************************************************/
+
+ACPI_STATUS
+acpi_ns_get_object_value (
+ ACPI_NAMED_OBJECT *object_entry,
+ ACPI_OBJECT_INTERNAL **return_obj_desc)
+{
+ ACPI_STATUS status = AE_OK;
+ ACPI_OBJECT_INTERNAL *obj_desc;
+ ACPI_OBJECT_INTERNAL *val_desc;
+
+
+ /*
+ * We take the value from certain objects directly
+ */
+
+ if ((object_entry->type == ACPI_TYPE_PROCESSOR) ||
+ (object_entry->type == ACPI_TYPE_POWER))
+ {
+
+ /*
+ * Create a Reference object to contain the object
+ */
+ obj_desc = acpi_cm_create_internal_object (object_entry->type);
+ if (!obj_desc) {
+ status = AE_NO_MEMORY;
+ goto unlock_and_exit;
+ }
+
+ /*
+ * Get the attached object
+ */
+
+ val_desc = acpi_ns_get_attached_object (object_entry);
+ if (!val_desc) {
+ status = AE_NULL_OBJECT;
+ goto unlock_and_exit;
+ }
+
+ /*
+ * Just copy from the original to the return object
+ */
+
+ MEMCPY (&obj_desc->common.first_non_common_byte,
+ &val_desc->common.first_non_common_byte,
+ (sizeof(ACPI_OBJECT_COMMON) -
+ sizeof(obj_desc->common.first_non_common_byte)));
+ }
+
+
+ /*
+ * Other objects require a reference object wrapper which we
+ * then attempt to resolve.
+ */
+ else {
+ /* Create an Reference object to contain the object */
+
+ obj_desc = acpi_cm_create_internal_object (INTERNAL_TYPE_REFERENCE);
+ if (!obj_desc) {
+ status = AE_NO_MEMORY;
+ goto unlock_and_exit;
+ }
+
+ /* Construct a descriptor pointing to the name */
+
+ obj_desc->reference.op_code = (u8) AML_NAME_OP;
+ obj_desc->reference.object = (void *) object_entry;
+
+ /*
+ * Use Acpi_aml_resolve_to_value() to get the associated value.
+ * The call to Acpi_aml_resolve_to_value causes
+ * Obj_desc (allocated above) to always be deleted.
+ */
+
+ status = acpi_aml_resolve_to_value (&obj_desc);
+ }
+
+ /*
+ * If Acpi_aml_resolve_to_value() succeeded, the return value was
+ * placed in Obj_desc.
+ */
+
+ if (status == AE_OK) {
+ status = AE_CTRL_RETURN_VALUE;
+
+ *return_obj_desc = obj_desc;
+ }
+
+
+unlock_and_exit:
+
+ /* Unlock the namespace */
+
+ acpi_cm_release_mutex (ACPI_MTX_NAMESPACE);
+ return (status);
+}
diff --git a/drivers/acpi/namespace/nsload.c b/drivers/acpi/namespace/nsload.c
new file mode 100644
index 000000000..4b6b3f309
--- /dev/null
+++ b/drivers/acpi/namespace/nsload.c
@@ -0,0 +1,488 @@
+
+/******************************************************************************
+ *
+ * Module Name: nsload - namespace loading/expanding/contracting procedures
+ *
+ *****************************************************************************/
+
+/*
+ * 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 "interp.h"
+#include "namesp.h"
+#include "amlcode.h"
+#include "parser.h"
+#include "dispatch.h"
+#include "debugger.h"
+
+
+#define _COMPONENT NAMESPACE
+ MODULE_NAME ("nsload");
+
+
+/*******************************************************************************
+ *
+ * FUNCTION: Acpi_ns_parse_table
+ *
+ * PARAMETERS: Table_desc - An ACPI table descriptor for table to parse
+ * Scope - Where to enter the table into the namespace
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Parse AML within an ACPI table and return a tree of ops
+ *
+ ******************************************************************************/
+
+ACPI_STATUS
+acpi_ns_parse_table (
+ ACPI_TABLE_DESC *table_desc,
+ ACPI_NAME_TABLE *scope)
+{
+ ACPI_STATUS status;
+
+
+ /* Create the root object */
+
+ acpi_gbl_parsed_namespace_root = acpi_ps_alloc_op (AML_SCOPE_OP);
+ if (!acpi_gbl_parsed_namespace_root) {
+ return (AE_NO_MEMORY);
+ }
+
+ /* Initialize the root object */
+
+ ((ACPI_NAMED_OP *) 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, 0);
+
+ if (ACPI_FAILURE (status)) {
+ return (status);
+ }
+
+
+#ifndef PARSER_ONLY
+ status = acpi_ps_walk_parsed_aml (acpi_ps_get_child (acpi_gbl_parsed_namespace_root),
+ acpi_gbl_parsed_namespace_root, NULL,
+ scope, NULL, NULL,
+ table_desc->table_id,
+ acpi_ds_load2_begin_op,
+ acpi_ds_load2_end_op);
+
+
+ /*
+ * Now that the internal namespace has been constructed, we can delete the
+ * parsed namespace, since it is no longer needed
+ */
+
+ acpi_ps_delete_parse_tree (acpi_gbl_parsed_namespace_root);
+ acpi_gbl_parsed_namespace_root = NULL;
+#endif
+
+
+ return (status);
+}
+
+
+/*****************************************************************************
+ *
+ * FUNCTION: Acpi_ns_load_table
+ *
+ * PARAMETERS: *Pcode_addr - Address of pcode block
+ * Pcode_length - Length of pcode block
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Mainline of the AML load/dump subsystem. Sets up the
+ * input engine, calls handler for outermost object type.
+ *
+ ****************************************************************************/
+
+ACPI_STATUS
+acpi_ns_load_table (
+ ACPI_TABLE_DESC *table_desc,
+ ACPI_NAMED_OBJECT *entry)
+{
+ ACPI_STATUS status;
+
+
+ if (!table_desc->aml_pointer) {
+ return (AE_BAD_PARAMETER);
+ }
+
+
+ if (!table_desc->aml_length) {
+ return (AE_BAD_PARAMETER);
+ }
+
+
+ /*
+ * Parse the table and load the namespace with all named
+ * objects found within. Control methods are NOT parsed
+ * at this time. In fact, the control methods cannot be
+ * parsed until the entire namespace is loaded, because
+ * if a control method makes a forward reference (call)
+ * to another control method, we can't continue parsing
+ * because we don't know how many arguments to parse next!
+ */
+
+ acpi_cm_acquire_mutex (ACPI_MTX_NAMESPACE);
+ status = acpi_ns_parse_table (table_desc, entry->child_table);
+ acpi_cm_release_mutex (ACPI_MTX_NAMESPACE);
+
+ if (ACPI_FAILURE (status)) {
+ return (status);
+ }
+
+ /*
+ * Now we can parse the control methods. We always parse
+ * them here for a sanity check, and if configured for
+ * just-in-time parsing, we delete the control method
+ * parse trees.
+ */
+
+ status = acpi_ds_initialize_objects (table_desc, entry);
+
+ return (status);
+}
+
+
+/******************************************************************************
+ *
+ * FUNCTION: Acpi_ns_load_table_by_type
+ *
+ * PARAMETERS: Table_type - Id of the table type to load
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Load an ACPI table or tables into the namespace. All tables
+ * of the given type are loaded. The mechanism allows this
+ * routine to be called repeatedly.
+ *
+ *****************************************************************************/
+
+ACPI_STATUS
+acpi_ns_load_table_by_type (
+ ACPI_TABLE_TYPE table_type)
+{
+ u32 i;
+ ACPI_STATUS status = AE_OK;
+ ACPI_TABLE_HEADER *table_ptr;
+ ACPI_TABLE_DESC *table_desc;
+
+
+ acpi_cm_acquire_mutex (ACPI_MTX_TABLES);
+
+
+ /*
+ * Table types supported are:
+ * DSDT (one), SSDT/PSDT (multiple)
+ */
+
+ switch (table_type)
+ {
+
+ case ACPI_TABLE_DSDT:
+
+ table_desc = &acpi_gbl_acpi_tables[ACPI_TABLE_DSDT];
+
+ /* If table already loaded into namespace, just return */
+
+ if (table_desc->loaded_into_namespace) {
+ goto unlock_and_exit;
+ }
+
+ 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_object);
+ if (ACPI_SUCCESS (status)) {
+ table_desc->loaded_into_namespace = TRUE;
+ }
+
+ break;
+
+
+ case ACPI_TABLE_SSDT:
+
+ /*
+ * Traverse list of SSDT tables
+ */
+
+ table_desc = &acpi_gbl_acpi_tables[ACPI_TABLE_SSDT];
+ for (i = 0; i < acpi_gbl_acpi_tables[ACPI_TABLE_SSDT].count; i++) {
+ table_ptr = table_desc->pointer;
+
+ /*
+ * Only attempt to load table if it is not
+ * already loaded!
+ */
+
+ if (!table_desc->loaded_into_namespace) {
+ status = acpi_ns_load_table (table_desc,
+ acpi_gbl_root_object);
+ if (ACPI_FAILURE (status)) {
+ break;
+ }
+
+ table_desc->loaded_into_namespace = TRUE;
+ }
+
+ table_desc = table_desc->next;
+ }
+
+ break;
+
+
+ case ACPI_TABLE_PSDT:
+
+ /*
+ * Traverse list of PSDT tables
+ */
+
+ table_desc = &acpi_gbl_acpi_tables[ACPI_TABLE_PSDT];
+
+ for (i = 0; i < acpi_gbl_acpi_tables[ACPI_TABLE_PSDT].count; i++) {
+ table_ptr = table_desc->pointer;
+
+ /* Only attempt to load table if it is not already loaded! */
+
+ if (!table_desc->loaded_into_namespace) {
+ status = acpi_ns_load_table (table_desc,
+ acpi_gbl_root_object);
+ if (ACPI_FAILURE (status)) {
+ break;
+ }
+
+ table_desc->loaded_into_namespace = TRUE;
+ }
+
+ table_desc = table_desc->next;
+ }
+
+ break;
+
+
+ default:
+ status = AE_SUPPORT;
+ }
+
+
+unlock_and_exit:
+
+ acpi_cm_release_mutex (ACPI_MTX_TABLES);
+
+ return (status);
+
+}
+
+
+/******************************************************************************
+ *
+ * FUNCTION: Acpi_ns_free_table_entry
+ *
+ * PARAMETERS: Entry - The entry to be deleted
+ *
+ * RETURNS None
+ *
+ * DESCRIPTION: Free an entry in a namespace table. Delete any objects contained
+ * in the entry, unlink the entry, then mark it unused.
+ *
+ ******************************************************************************/
+
+void
+acpi_ns_free_table_entry (
+ ACPI_NAMED_OBJECT *entry)
+{
+
+ if (!entry) {
+ return;
+ }
+
+ /*
+ * Need to delete
+ * 1) The scope, if any
+ * 2) An attached object, if any
+ */
+
+ if (entry->child_table) {
+ acpi_cm_free (entry->child_table);
+ entry->child_table = NULL;
+ }
+
+ if (entry->object) {
+ acpi_ns_detach_object (entry->object);
+ entry->object = NULL;
+ }
+
+ /* Mark the entry unallocated */
+
+ entry->name = 0;
+
+ return;
+}
+
+
+/******************************************************************************
+ *
+ * FUNCTION: Acpi_ns_delete_subtree
+ *
+ * PARAMETERS: Start_handle - Handle in namespace where search begins
+ *
+ * RETURNS Status
+ *
+ * DESCRIPTION: Walks the namespace starting at the given handle and deletes
+ * all objects, entries, and scopes in the entire subtree.
+ *
+ * TBD: [Investigate] What if any part of this subtree is in use?
+ * (i.e. on one of the object stacks?)
+ *
+ ******************************************************************************/
+
+ACPI_STATUS
+acpi_ns_delete_subtree (
+ ACPI_HANDLE start_handle)
+{
+ ACPI_STATUS status;
+ ACPI_HANDLE child_handle;
+ ACPI_HANDLE parent_handle;
+ ACPI_HANDLE next_child_handle;
+ ACPI_HANDLE dummy;
+ u32 level;
+
+
+ parent_handle = start_handle;
+ child_handle = 0;
+ level = 1;
+
+ /*
+ * Traverse the tree of objects until we bubble back up
+ * to where we started.
+ */
+
+ while (level > 0) {
+ /* Attempt to get the next object in this scope */
+
+ status = acpi_get_next_object (ACPI_TYPE_ANY, parent_handle,
+ child_handle,
+ &next_child_handle);
+
+ /*
+ * Regardless of the success or failure of the
+ * previous operation, we are done with the previous
+ * object (if there was one), and any children it
+ * may have had. So we can now safely delete it (and
+ * its scope, if any)
+ */
+
+ acpi_ns_free_table_entry (child_handle);
+ child_handle = next_child_handle;
+
+
+ /* Did we get a new object? */
+
+ if (ACPI_SUCCESS (status)) {
+ /* Check if this object has any children */
+
+ if (ACPI_SUCCESS (acpi_get_next_object (ACPI_TYPE_ANY,
+ child_handle, 0,
+ &dummy)))
+ {
+ /*
+ * There is at least one child of this object,
+ * visit the object
+ */
+
+ level++;
+ parent_handle = child_handle;
+ child_handle = 0;
+ }
+ }
+
+ else {
+ /*
+ * No more children in this object, go back up to
+ * the object's parent
+ */
+ level--;
+ child_handle = parent_handle;
+ acpi_get_parent (parent_handle, &parent_handle);
+ }
+ }
+
+ /* Now delete the starting object, and we are done */
+
+ acpi_ns_free_table_entry ((ACPI_NAMED_OBJECT*) child_handle);
+
+
+ return (AE_OK);
+}
+
+
+/****************************************************************************
+ *
+ * FUNCTION: Acpi_ns_unload_name_space
+ *
+ * PARAMETERS: Handle - Root of namespace subtree to be deleted
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Shrinks the namespace, typically in response to an undocking
+ * event. Deletes an entire subtree starting from (and
+ * including) the given handle.
+ *
+ ****************************************************************************/
+
+ACPI_STATUS
+acpi_ns_unload_namespace (
+ ACPI_HANDLE handle)
+{
+ ACPI_STATUS status;
+
+
+ /* Parameter validation */
+
+ if (!acpi_gbl_root_object->child_table) {
+ return (AE_NO_NAMESPACE);
+ }
+
+ if (!handle) {
+ return (AE_BAD_PARAMETER);
+ }
+
+
+ /* This function does the real work */
+
+ status = acpi_ns_delete_subtree (handle);
+
+ return (status);
+}
+
+
diff --git a/drivers/acpi/namespace/nsnames.c b/drivers/acpi/namespace/nsnames.c
new file mode 100644
index 000000000..1c4ab7c0b
--- /dev/null
+++ b/drivers/acpi/namespace/nsnames.c
@@ -0,0 +1,503 @@
+
+/******************************************************************************
+ *
+ * Module Name: nsnames - Name manipulation and search
+ *
+ *****************************************************************************/
+
+/*
+ * 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 "amlcode.h"
+#include "interp.h"
+#include "namesp.h"
+
+
+#define _COMPONENT NAMESPACE
+ MODULE_NAME ("nsnames");
+
+
+/****************************************************************************
+ *
+ * FUNCTION: Acpi_ns_name_of_scope
+ *
+ * PARAMETERS: Scope - Scope whose name is needed
+ *
+ * RETURN: Pointer to storage containing the fully qualified name of
+ * the scope, in Label format (all segments strung together
+ * with no separators)
+ *
+ * DESCRIPTION: Used via Acpi_ns_name_of_current_scope() and Acpi_ns_last_fQN()
+ * for label generation in the interpreter, and for debug
+ * printing in Acpi_ns_search_table().
+ *
+ ***************************************************************************/
+
+char *
+acpi_ns_name_of_scope (
+ ACPI_NAME_TABLE *scope)
+{
+ char *name_buffer;
+ ACPI_SIZE size;
+ ACPI_NAME name;
+ ACPI_NAMED_OBJECT *entry_to_search;
+ ACPI_NAMED_OBJECT *parent_entry;
+
+
+ if (!acpi_gbl_root_object->child_table || !scope) {
+ /*
+ * If the name space has not been initialized,
+ * this function should not have been called.
+ */
+ return (NULL);
+ }
+
+ entry_to_search = scope->entries;
+
+
+ /* Calculate required buffer size based on depth below root NT */
+
+ size = 1;
+ parent_entry = entry_to_search;
+ while (parent_entry) {
+ parent_entry = acpi_ns_get_parent_entry (parent_entry);
+ if (parent_entry) {
+ size += ACPI_NAME_SIZE;
+ }
+ }
+
+
+ /* Allocate the buffer */
+
+ name_buffer = acpi_cm_callocate (size + 1);
+ if (!name_buffer) {
+ REPORT_ERROR ("Ns_name_of_scope: allocation failure");
+ return (NULL);
+ }
+
+
+ /* Store terminator byte, then build name backwards */
+
+ name_buffer[size] = '\0';
+ while ((size > ACPI_NAME_SIZE) &&
+ acpi_ns_get_parent_entry (entry_to_search))
+ {
+ size -= ACPI_NAME_SIZE;
+ name = acpi_ns_find_parent_name (entry_to_search);
+
+ /* Put the name into the buffer */
+
+ MOVE_UNALIGNED32_TO_32 ((name_buffer + size), &name);
+ entry_to_search = acpi_ns_get_parent_entry (entry_to_search);
+ }
+
+ name_buffer[--size] = AML_ROOT_PREFIX;
+
+
+ return (name_buffer);
+}
+
+
+/****************************************************************************
+ *
+ * FUNCTION: Acpi_ns_name_of_current_scope
+ *
+ * PARAMETERS: none
+ *
+ * RETURN: pointer to storage containing the name of the current scope
+ *
+ ***************************************************************************/
+
+char *
+acpi_ns_name_of_current_scope (
+ ACPI_WALK_STATE *walk_state)
+{
+ char *scope_name;
+
+
+ if (walk_state && walk_state->scope_info) {
+ scope_name =
+ acpi_ns_name_of_scope (walk_state->scope_info->scope.name_table);
+
+ return (scope_name);
+ }
+
+ REPORT_ERROR ("Current scope pointer is invalid");
+
+ return (NULL);
+}
+
+
+/****************************************************************************
+ *
+ * FUNCTION: Acpi_ns_handle_to_pathname
+ *
+ * PARAMETERS: Target_handle - Handle of nte whose name is to be found
+ * Buf_size - Size of the buffer provided
+ * User_buffer - Where the pathname is returned
+ *
+ * RETURN: Status, Buffer is filled with pathname if status == AE_OK
+ *
+ * DESCRIPTION: Build and return a full namespace pathname
+ *
+ * MUTEX: Locks Namespace
+ *
+ ***************************************************************************/
+
+ACPI_STATUS
+acpi_ns_handle_to_pathname (
+ ACPI_HANDLE target_handle,
+ u32 *buf_size,
+ char *user_buffer)
+{
+ ACPI_STATUS status = AE_OK;
+ ACPI_NAMED_OBJECT *entry_to_search = NULL;
+ ACPI_NAMED_OBJECT *temp = NULL;
+ ACPI_SIZE path_length = 0;
+ ACPI_SIZE size;
+ u32 user_buf_size;
+ ACPI_NAME name;
+ u8 namespace_was_locked;
+
+
+ if (!acpi_gbl_root_object->child_table || !target_handle) {
+ /*
+ * If the name space has not been initialized,
+ * this function should not have been called.
+ */
+
+ return (AE_NO_NAMESPACE);
+ }
+
+ namespace_was_locked = acpi_gbl_acpi_mutex_info[ACPI_MTX_NAMESPACE].locked;
+ if (!namespace_was_locked) {
+ acpi_cm_acquire_mutex (ACPI_MTX_NAMESPACE);
+ }
+
+ entry_to_search = acpi_ns_convert_handle_to_entry (target_handle);
+ if (!entry_to_search) {
+ return (AE_BAD_PARAMETER);
+ }
+
+ /*
+ * Compute length of pathname as 5 * number of name segments.
+ * Go back up the parent tree to the root
+ */
+ for (size = 0, temp = entry_to_search;
+ acpi_ns_get_parent_entry (temp);
+ temp = acpi_ns_get_parent_entry (temp))
+ {
+ size += PATH_SEGMENT_LENGTH;
+ }
+
+ /* Set return length to the required path length */
+
+ path_length = size + 1;
+ user_buf_size = *buf_size;
+ *buf_size = path_length;
+
+ /* Check if the user buffer is sufficiently large */
+
+ if (path_length > user_buf_size) {
+ status = AE_BUFFER_OVERFLOW;
+ goto unlock_and_exit;
+ }
+
+ /* Store null terminator */
+
+ user_buffer[size] = 0;
+ size -= ACPI_NAME_SIZE;
+
+ /* Put the original ACPI name at the end of the path */
+
+ MOVE_UNALIGNED32_TO_32 ((user_buffer + size),
+ &entry_to_search->name);
+
+ user_buffer[--size] = PATH_SEPARATOR;
+
+ /* Build name backwards, putting "." between segments */
+
+ while ((size > ACPI_NAME_SIZE) && entry_to_search) {
+ size -= ACPI_NAME_SIZE;
+ name = acpi_ns_find_parent_name (entry_to_search);
+ MOVE_UNALIGNED32_TO_32 ((user_buffer + size), &name);
+
+ user_buffer[--size] = PATH_SEPARATOR;
+ entry_to_search = acpi_ns_get_parent_entry (entry_to_search);
+ }
+
+ /*
+ * Overlay the "." preceding the first segment with
+ * the root name "\"
+ */
+
+ user_buffer[size] = '\\';
+
+
+unlock_and_exit:
+
+ if (!namespace_was_locked) {
+ acpi_cm_release_mutex (ACPI_MTX_NAMESPACE);
+ }
+
+ return (status);
+}
+
+
+/****************************************************************************
+ *
+ * FUNCTION: Acpi_ns_pattern_match
+ *
+ * PARAMETERS: Obj_entry - A namespace entry
+ * Search_for - Wildcard pattern string
+ *
+ * DESCRIPTION: Matches a namespace name against a wildcard pattern. Only
+ * a very simple pattern - 4 chars, either a valid char or a "?"
+ * to match any.
+ *
+ ***************************************************************************/
+
+u8
+acpi_ns_pattern_match (
+ ACPI_NAMED_OBJECT *obj_entry,
+ char *search_for)
+{
+ s32 i;
+
+
+ for (i = 0; i < ACPI_NAME_SIZE; i++) {
+ if (search_for[i] != '?' &&
+ search_for[i] != ((char *) &obj_entry->name)[i])
+ {
+ /* No match */
+
+ return FALSE;
+ }
+ }
+
+ /* name matches pattern */
+
+ return TRUE;
+}
+
+
+/****************************************************************************
+ *
+ * FUNCTION: Acpi_ns_name_compare
+ *
+ * PARAMETERS: Obj_handle - A namespace entry
+ * Level - Current nesting level
+ * Context - A FIND_CONTEXT structure
+ *
+ * DESCRIPTION: A User_function called by Acpi_ns_walk_namespace(). It performs
+ * a pattern match for Acpi_ns_low_find_names(), and updates the list
+ * and count as required.
+ *
+ ***************************************************************************/
+
+ACPI_STATUS
+acpi_ns_name_compare (
+ ACPI_HANDLE obj_handle,
+ u32 level,
+ void *context,
+ void **return_value)
+{
+ FIND_CONTEXT *find = context;
+
+
+ /* Match, yes or no? */
+
+ if (acpi_ns_pattern_match ((ACPI_NAMED_OBJECT*) obj_handle,
+ find->search_for))
+ {
+ /* Name matches pattern */
+
+ if (find->list) {
+ find->list[*(find->count)] = obj_handle;
+ }
+
+ ++*(find->count);
+ }
+
+ /* Don't terminate the walk */
+ return AE_OK;
+}
+
+
+/****************************************************************************
+ *
+ * FUNCTION: Acpi_ns_low_find_names
+ *
+ * PARAMETERS: *This_entry - Table to be searched
+ * *Search_for - Pattern to be found.
+ * 4 bytes, ? matches any character.
+ * *Count - Output count of matches found.
+ * Outermost caller should preset to 0
+ * List[] - Output array of handles. If
+ * null, only the count is obtained.
+ * Max_depth - Maximum depth of search. Use
+ * INT_MAX for an effectively
+ * unlimited depth.
+ *
+ * DESCRIPTION: Low-level find name.
+ * Traverse the name space finding names which match a search
+ * pattern, and return an array of handles in List[].
+ *
+ ***************************************************************************/
+
+void
+acpi_ns_low_find_names (
+ ACPI_NAMED_OBJECT *this_entry,
+ char *search_for,
+ s32 *count,
+ ACPI_HANDLE list[],
+ s32 max_depth)
+{
+ FIND_CONTEXT find;
+
+
+ if (0 == max_depth || !this_entry || !search_for || !count) {
+ /*
+ * Zero requested depth, nothing to search,
+ * nothing to search for, or count pointer bad
+ */
+
+ return;
+ }
+
+ /* Init the context structure used by compare routine */
+
+ find.list = list;
+ find.count = count;
+ find.search_for = search_for;
+
+ /* Walk the namespace and find all matches */
+
+ acpi_ns_walk_namespace (ACPI_TYPE_ANY, (ACPI_HANDLE) this_entry,
+ max_depth, NS_WALK_NO_UNLOCK,
+ acpi_ns_name_compare, &find, NULL);
+
+ if (list) {
+ /* null-terminate the output array */
+
+ list[*count] = (ACPI_HANDLE) 0;
+ }
+
+ return;
+}
+
+
+/****************************************************************************
+ *
+ * FUNCTION: Acpi_ns_find_names
+
+ *
+ * PARAMETERS: *Search_for - pattern to be found.
+ * 4 bytes, ? matches any character.
+ * If NULL, "????" will be used.
+ * Start_handle - Root of subtree to be searched, or
+ * NS_ALL to search the entire namespace
+ * Max_depth - Maximum depth of search. Use INT_MAX
+ * for an effectively unlimited depth.
+ *
+ * DESCRIPTION: Traverse the name space finding names which match a search
+ * pattern, and return an array of handles. The end of the
+ * array is marked by the value (ACPI_HANDLE)0. A return value
+ * of (ACPI_HANDLE *)0 indicates that no matching names were
+ * found or that space for the list could not be allocated.
+ * if Start_handle is NS_ALL (null) search from the root,
+ * else it is a handle whose children are to be searched.
+ *
+ ***************************************************************************/
+
+ACPI_HANDLE *
+acpi_ns_find_names (
+ char *search_for,
+ ACPI_HANDLE start_handle,
+ s32 max_depth)
+{
+ ACPI_HANDLE *list = NULL;
+ s32 count;
+
+
+ if (!acpi_gbl_root_object->child_table) {
+ /*
+ * If the name space has not been initialized,
+ * there surely are no matching names.
+ */
+ return (NULL);
+ }
+
+ if (NS_ALL == start_handle) {
+ /* base is root */
+
+ start_handle = acpi_gbl_root_object;
+ }
+
+ else if (((ACPI_NAMED_OBJECT *) start_handle)->child_table) {
+ /* base has children to search */
+
+ start_handle =
+ ((ACPI_NAMED_OBJECT *) start_handle)->child_table->entries;
+ }
+
+ else {
+ /*
+ * If base is not the root and has no children,
+ * there is nothing to search.
+ */
+ return (NULL);
+ }
+
+ if (!search_for) {
+ /* Search name not specified */
+
+ search_for = "????";
+ }
+
+
+ /* Pass 1. Get required buffer size, don't try to build list */
+
+ count = 0;
+ acpi_ns_low_find_names (start_handle, search_for, &count,
+ NULL, max_depth);
+
+ if (0 == count) {
+ return (NULL);
+ }
+
+ /* Allow for trailing null */
+ count++;
+
+ list = acpi_cm_callocate (count * sizeof(ACPI_HANDLE));
+ if (!list) {
+ REPORT_ERROR ("Ns_find_names: allocation failure");
+ return (NULL);
+ }
+
+ /* Pass 2. Fill buffer */
+
+ count = 0;
+ acpi_ns_low_find_names (start_handle, search_for, &count, list, max_depth);
+
+ return (list);
+}
+
+
diff --git a/drivers/acpi/namespace/nsobject.c b/drivers/acpi/namespace/nsobject.c
new file mode 100644
index 000000000..56e497bb0
--- /dev/null
+++ b/drivers/acpi/namespace/nsobject.c
@@ -0,0 +1,556 @@
+
+/******************************************************************************
+ *
+ * Module Name: nsobject - Utilities for objects attached to namespace
+ * table entries
+ *
+ *****************************************************************************/
+
+/*
+ * 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 "amlcode.h"
+#include "namesp.h"
+#include "interp.h"
+#include "tables.h"
+
+
+#define _COMPONENT NAMESPACE
+ MODULE_NAME ("nsobject");
+
+
+/****************************************************************************
+ *
+ * FUNCTION: Acpi_ns_attach_object
+ *
+ * PARAMETERS: Handle - Handle of nte
+ * Object - Object to be attached
+ * Type - Type of object, or ACPI_TYPE_ANY if not
+ * known
+ *
+ * DESCRIPTION: Record the given object as the value associated with the
+ * name whose ACPI_HANDLE is passed. If Object is NULL
+ * and Type is ACPI_TYPE_ANY, set the name as having no value.
+ *
+ * MUTEX: Assumes namespace is locked
+ *
+ ***************************************************************************/
+
+ACPI_STATUS
+acpi_ns_attach_object (
+ ACPI_HANDLE handle,
+ ACPI_HANDLE object,
+ OBJECT_TYPE_INTERNAL type)
+{
+ ACPI_NAMED_OBJECT *this_entry = (ACPI_NAMED_OBJECT*) handle;
+ ACPI_OBJECT_INTERNAL *obj_desc;
+ ACPI_OBJECT_INTERNAL *previous_obj_desc;
+ OBJECT_TYPE_INTERNAL obj_type = ACPI_TYPE_ANY;
+ u8 flags;
+ u16 opcode;
+
+
+ /*
+ * Parameter validation
+ */
+
+ if (!acpi_gbl_root_object->child_table) {
+ /* Name space not initialized */
+
+ REPORT_ERROR ("Ns_attach_object: Name space not initialized");
+ return (AE_NO_NAMESPACE);
+ }
+
+ if (!handle) {
+ /* Invalid handle */
+
+ REPORT_ERROR ("Ns_attach_object: Null name handle");
+ 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");
+ return (AE_BAD_PARAMETER);
+ }
+
+ if (!VALID_DESCRIPTOR_TYPE (handle, ACPI_DESC_TYPE_NAMED)) {
+ /* Not a name handle */
+
+ REPORT_ERROR ("Ns_attach_object: Invalid handle");
+ return (AE_BAD_PARAMETER);
+ }
+
+ /* Check if this object is already attached */
+
+ if (this_entry->object == object) {
+ return (AE_OK);
+ }
+
+
+ /* Get the current flags field of the NTE */
+
+ flags = this_entry->flags;
+ flags &= ~NTE_AML_ATTACHMENT;
+
+
+ /* If null object, we will just install it */
+
+ if (!object) {
+ obj_desc = NULL;
+ obj_type = ACPI_TYPE_ANY;
+ }
+
+ /*
+ * If the object is an NTE with an attached object,
+ * we will use that (attached) object
+ */
+
+ else if (VALID_DESCRIPTOR_TYPE (object, ACPI_DESC_TYPE_NAMED) &&
+ ((ACPI_NAMED_OBJECT*) object)->object)
+ {
+ /*
+ * Value passed is a name handle and that name has a
+ * non-null value. Use that name's value and type.
+ */
+
+ obj_desc = ((ACPI_NAMED_OBJECT*) object)->object;
+ obj_type = ((ACPI_NAMED_OBJECT*) object)->type;
+
+ /*
+ * Copy appropriate flags
+ */
+
+ if (((ACPI_NAMED_OBJECT*) object)->flags & NTE_AML_ATTACHMENT) {
+ flags |= NTE_AML_ATTACHMENT;
+ }
+ }
+
+
+ /*
+ * Otherwise, we will use the parameter object, but we must type
+ * it first
+ */
+
+ else {
+ obj_desc = (ACPI_OBJECT_INTERNAL *) object;
+
+
+ /* If a valid type (non-ANY) was given, just use it */
+
+ if (ACPI_TYPE_ANY != type) {
+ obj_type = type;
+ }
+
+
+ /*
+ * Type is TYPE_Any, we must try to determinte the
+ * actual type of the object
+ */
+
+ /*
+ * Check if value points into the AML code
+ */
+ else if (acpi_tb_system_table_pointer (object)) {
+ /*
+ * Object points into the AML stream.
+ * Set a flag bit in the NTE to indicate this
+ */
+
+ flags |= NTE_AML_ATTACHMENT;
+
+ /*
+ * The next byte (perhaps the next two bytes)
+ * will be the AML opcode
+ */
+
+ MOVE_UNALIGNED16_TO_16 (&opcode, object);
+
+ /* Check for a recognized Op_code */
+
+ switch ((u8) opcode)
+ {
+
+ case AML_OP_PREFIX:
+
+ if (opcode != AML_REVISION_OP) {
+ /*
+ * Op_prefix is unrecognized unless part
+ * of Revision_op
+ */
+
+ break;
+ }
+
+ /* Else fall through to set type as Number */
+
+
+ case AML_ZERO_OP: case AML_ONES_OP: case AML_ONE_OP:
+ case AML_BYTE_OP: case AML_WORD_OP: case AML_DWORD_OP:
+
+ obj_type = ACPI_TYPE_NUMBER;
+ break;
+
+
+ case AML_STRING_OP:
+
+ obj_type = ACPI_TYPE_STRING;
+ break;
+
+
+ case AML_BUFFER_OP:
+
+ obj_type = ACPI_TYPE_BUFFER;
+ break;
+
+
+ case AML_MUTEX_OP:
+
+ obj_type = ACPI_TYPE_MUTEX;
+ break;
+
+
+ case AML_PACKAGE_OP:
+
+ obj_type = ACPI_TYPE_PACKAGE;
+ break;
+
+
+ default:
+
+ return (AE_TYPE);
+ break;
+ }
+ }
+
+ else {
+ /*
+ * Cannot figure out the type -- set to Def_any which
+ * will print as an error in the name table dump
+ */
+
+
+ obj_type = INTERNAL_TYPE_DEF_ANY;
+ }
+ }
+
+
+ /*
+ * Must increment the new value's reference count
+ * (if it is an internal object)
+ */
+
+ acpi_cm_add_reference (obj_desc);
+
+ /* Save the existing object (if any) for deletion later */
+
+ previous_obj_desc = this_entry->object;
+
+ /* Install the object and set the type, flags */
+
+ this_entry->object = obj_desc;
+ this_entry->type = (u8) obj_type;
+ this_entry->flags = flags;
+
+
+ /*
+ * Delete an existing attached object.
+ */
+
+ if (previous_obj_desc) {
+ /* One for the attach to the NTE */
+ acpi_cm_remove_reference (previous_obj_desc);
+ /* Now delete */
+ acpi_cm_remove_reference (previous_obj_desc);
+ }
+
+ return (AE_OK);
+}
+
+
+/****************************************************************************
+ *
+ * FUNCTION: Acpi_ns_attach_method
+ *
+ * PARAMETERS: Handle - Handle of nte to be set
+ * Offset - Value to be set
+ * Length - Length associated with value
+ *
+ * DESCRIPTION: Record the given offset and p-code length of the method
+ * whose handle is passed
+ *
+ * MUTEX: Assumes namespace is locked
+ *
+ ***************************************************************************/
+
+ACPI_STATUS
+acpi_ns_attach_method (
+ ACPI_HANDLE handle,
+ u8 *pcode_addr,
+ u32 pcode_length)
+{
+ ACPI_OBJECT_INTERNAL *obj_desc;
+ ACPI_OBJECT_INTERNAL *previous_obj_desc;
+ ACPI_NAMED_OBJECT *this_entry = (ACPI_NAMED_OBJECT*) handle;
+
+
+ /* Parameter validation */
+
+ if (!acpi_gbl_root_object->child_table) {
+ /* Name space uninitialized */
+
+ REPORT_ERROR ("Ns_attach_method: name space uninitialized");
+ return (AE_NO_NAMESPACE);
+ }
+
+ if (!handle) {
+ /* Null name handle */
+
+ REPORT_ERROR ("Ns_attach_method: null name handle");
+ return (AE_BAD_PARAMETER);
+ }
+
+
+ /* Allocate a method descriptor */
+
+ obj_desc = acpi_cm_create_internal_object (ACPI_TYPE_METHOD);
+ if (!obj_desc) {
+ /* Method allocation failure */
+
+ REPORT_ERROR ("Ns_attach_method: allocation failure");
+ return (AE_NO_MEMORY);
+ }
+
+ /* Init the method info */
+
+ obj_desc->method.pcode = pcode_addr;
+ obj_desc->method.pcode_length = pcode_length;
+
+ /* Update reference count and install */
+
+ acpi_cm_add_reference (obj_desc);
+
+ previous_obj_desc = this_entry->object;
+ this_entry->object = obj_desc;
+
+
+ /*
+ * Delete an existing object. Don't try to re-use in case it is shared
+ */
+ if (previous_obj_desc) {
+ acpi_cm_remove_reference (previous_obj_desc);
+ }
+
+ return (AE_OK);
+}
+
+
+/****************************************************************************
+ *
+ * FUNCTION: Acpi_ns_detach_object
+ *
+ * PARAMETERS: Object - An object whose Value will be deleted
+ *
+ * RETURN: None.
+ *
+ * DESCRIPTION: Delete the Value associated with a namespace object. If the
+ * Value is an allocated object, it is freed. Otherwise, the
+ * field is simply cleared.
+ *
+ ***************************************************************************/
+
+void
+acpi_ns_detach_object (
+ ACPI_HANDLE object)
+{
+ ACPI_NAMED_OBJECT *entry = object;
+ ACPI_OBJECT_INTERNAL *obj_desc;
+
+
+ obj_desc = entry->object;
+ if (!obj_desc) {
+ return;
+ }
+
+ /* Clear the entry in all cases */
+
+ entry->object = NULL;
+
+ /* Found a valid value */
+
+ /*
+ * Not every value is an object allocated via Acpi_cm_callocate,
+ * - must check
+ */
+
+ if (!acpi_tb_system_table_pointer (obj_desc)) {
+ /* Attempt to delete the object (and all subobjects) */
+
+ acpi_cm_remove_reference (obj_desc);
+ }
+
+ return;
+}
+
+
+/****************************************************************************
+ *
+ * FUNCTION: Acpi_ns_get_attached_object
+ *
+ * PARAMETERS: Handle - Handle of nte to be examined
+ *
+ * RETURN: Current value of the object field from nte whose handle is
+ * passed
+ *
+ ***************************************************************************/
+
+void *
+acpi_ns_get_attached_object (
+ ACPI_HANDLE handle)
+{
+
+ if (!handle) {
+ /* handle invalid */
+
+ REPORT_WARNING ("Ns_get_attached_object: Null handle");
+ return (NULL);
+ }
+
+ return (((ACPI_NAMED_OBJECT*) handle)->object);
+}
+
+
+/****************************************************************************
+ *
+ * FUNCTION: Acpi_ns_compare_object
+ *
+ * PARAMETERS: Obj_handle - A namespace entry
+ * Level - Current nesting level
+ * Obj_desc - The value to be compared
+ *
+ * DESCRIPTION: A User_function called by Acpi_ns_walk_namespace(). It performs
+ * a comparison for Acpi_ns_find_attached_object(). The comparison is against
+ * the value in the value field of the Obj_handle (an NTE).
+ * If a match is found, the handle is returned, which aborts
+ * Acpi_ns_walk_namespace.
+ *
+ ***************************************************************************/
+
+ACPI_STATUS
+acpi_ns_compare_object (
+ ACPI_HANDLE obj_handle,
+ u32 level,
+ void *obj_desc,
+ void **return_value)
+{
+
+ if (((ACPI_NAMED_OBJECT*) obj_handle)->object == obj_desc) {
+ if (return_value) {
+ *return_value = obj_handle;
+ }
+
+ /* Stop the walk */
+ return AE_CTRL_TERMINATE;
+ }
+
+ /* Not found, continue the walk */
+ return AE_OK;
+}
+
+
+/****************************************************************************
+ *
+ * FUNCTION: Acpi_ns_find_attached_object
+ *
+ * PARAMETERS: *Obj_desc - Value to be found in ptr_val field.
+ * Start_handle - Root of subtree to be searched, or
+ * NS_ALL to search the entire namespace
+ * Max_depth - Maximum depth of search. Use INT_MAX
+ * for an effectively unlimited depth.
+ *
+ * DESCRIPTION: Traverse the name space until finding a name whose Value field
+ * matches the Obj_desc parameter, and return a handle to that
+ * name, or (ACPI_HANDLE)0 if none exists.
+ * if Start_handle is NS_ALL (null) search from the root,
+ * else it is a handle whose children are to be searched.
+ *
+ ***************************************************************************/
+
+ACPI_HANDLE
+acpi_ns_find_attached_object (
+ ACPI_OBJECT_INTERNAL *obj_desc,
+ ACPI_HANDLE start_handle,
+ s32 max_depth)
+{
+ ACPI_HANDLE ret_object;
+ ACPI_STATUS status;
+
+
+ /* Parameter validation */
+
+ if (!obj_desc) {
+ return (NULL);
+ }
+
+ if (0 == max_depth) {
+ return (NULL);
+ }
+
+ if (!acpi_gbl_root_object->child_table) {
+ /*
+ * If the name space has not been initialized,
+ * there surely are no matching values.
+ */
+ return (NULL);
+ }
+
+ if (NS_ALL == start_handle) {
+ start_handle = acpi_gbl_root_object;
+ }
+
+ else {
+ /*
+ * If base is not the root and has no children,
+ * there is nothing to search.
+ */
+ return (NULL);
+ }
+
+
+ /*
+ * Walk namespace until a match is found.
+ * Either the matching object is returned, or NULL in case
+ * of no match.
+ */
+ status = acpi_ns_walk_namespace (ACPI_TYPE_ANY, start_handle,
+ max_depth, NS_WALK_NO_UNLOCK,
+ acpi_ns_compare_object,
+ obj_desc, &ret_object);
+
+ if (ACPI_FAILURE (status)) {
+ ret_object = NULL;
+ }
+
+ return (ret_object);
+}
+
+
diff --git a/drivers/acpi/namespace/nssearch.c b/drivers/acpi/namespace/nssearch.c
new file mode 100644
index 000000000..19fad8ad6
--- /dev/null
+++ b/drivers/acpi/namespace/nssearch.c
@@ -0,0 +1,646 @@
+
+/******************************************************************************
+ *
+ * Module Name: nssearch - Namespace search
+ *
+ *****************************************************************************/
+
+/*
+ * 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 "amlcode.h"
+#include "interp.h"
+#include "namesp.h"
+
+
+#define _COMPONENT NAMESPACE
+ MODULE_NAME ("nssearch");
+
+
+/****************************************************************************
+ *
+ * FUNCTION: Acpi_ns_search_one_scope
+ *
+ * PARAMETERS: *Entry_name - Ascii ACPI name to search for
+ * *Name_table - Starting table where search will begin
+ * Type - Object type to match
+ * **Ret_entry - Where the matched NTE is returned
+ * *Ret_info - Where info about the search is returned
+ *
+ * RETURN: Status and return information via NS_SEARCH_DATA
+ *
+ * DESCRIPTION: Search a single namespace table. Performs a simple search,
+ * does not add entries or search parents.
+ *
+ ***************************************************************************/
+
+ACPI_STATUS
+acpi_ns_search_one_scope (
+ u32 entry_name,
+ ACPI_NAME_TABLE *name_table,
+ OBJECT_TYPE_INTERNAL type,
+ ACPI_NAMED_OBJECT **ret_entry,
+ NS_SEARCH_DATA *ret_info)
+{
+ u32 position;
+ ACPI_NAME_TABLE *this_table;
+ ACPI_NAME_TABLE *previous_table = name_table;
+ ACPI_NAMED_OBJECT *entries;
+ u8 table_full = TRUE;
+ ACPI_NAME_TABLE *table_with_empty_slots = NULL;
+ u32 empty_slot_position = 0;
+
+
+
+ /*
+ * Name tables are built (and subsequently dumped) in the
+ * order in which the names are encountered during the namespace load;
+ *
+ * All namespace searching will be linear; If a table overflows an
+ * additional segment will be allocated and added (chained).
+ *
+ * Start linear search at top of table
+ */
+ position = 0;
+ this_table = name_table;
+ entries = this_table->entries;
+
+
+ /* Init return data */
+
+ if (ret_info) {
+ ret_info->name_table = this_table;
+ }
+
+
+ /*
+ * Search entire name table, including all linked appendages
+ */
+
+ while (this_table) {
+ /*
+ * Search for name in table, starting at Position. Stop
+ * searching upon examining all entries in the table.
+ *
+ */
+
+ entries = this_table->entries;
+ while (position < NS_TABLE_SIZE) {
+ /* Check for a valid entry */
+
+ if (!entries[position].name) {
+ if (table_full) {
+ /*
+ * There is room in the table for more
+ * entries, if necessary
+ */
+
+ table_full = FALSE;
+ table_with_empty_slots = this_table;
+ empty_slot_position = position;
+ }
+ }
+
+ /* Search for name in table */
+
+ else if (entries[position].name == entry_name) {
+ /*
+ * Found matching entry. Capture type if
+ * appropriate before returning the entry.
+ */
+
+ /*
+ * The Def_field_defn and Bank_field_defn cases
+ * are actually looking up the Region in which
+ * the field will be defined
+ */
+
+ if ((INTERNAL_TYPE_DEF_FIELD_DEFN == type) ||
+ (INTERNAL_TYPE_BANK_FIELD_DEFN == type))
+ {
+ type = ACPI_TYPE_REGION;
+ }
+
+ /*
+ * Scope, Def_any, and Index_field_defn are bogus
+ * "types" which do not actually have anything
+ * to do with the type of the name being looked
+ * up. For any other value of Type, if the type
+ * stored in the entry is Any (i.e. unknown),
+ * save the actual type.
+ */
+
+ if (type != INTERNAL_TYPE_SCOPE &&
+ type != INTERNAL_TYPE_DEF_ANY &&
+ type != INTERNAL_TYPE_INDEX_FIELD_DEFN &&
+ entries[position].type == ACPI_TYPE_ANY)
+ {
+ entries[position].type = (u8) type;
+ }
+
+ *ret_entry = &entries[position];
+ return (AE_OK);
+ }
+
+
+ /* Didn't match name, move on to the next entry */
+
+ position++;
+ }
+
+
+ /*
+ * Just examined last slot in this table, move on
+ * to next appendate.
+ * All appendages, even to the root NT, contain
+ * NS_TABLE_SIZE entries.
+ */
+
+ previous_table = this_table;
+ this_table = this_table->next_table;
+
+ position = 0;
+ }
+
+
+ /* Searched entire table, not found */
+
+
+ if (ret_info) {
+ /*
+ * Save info on if/where a slot is available
+ * (name was not found)
+ */
+
+ ret_info->table_full = table_full;
+ if (table_full) {
+ ret_info->name_table = previous_table;
+ }
+
+ else {
+ ret_info->position = empty_slot_position;
+ ret_info->name_table = table_with_empty_slots;
+ }
+ }
+
+ return (AE_NOT_FOUND);
+}
+
+
+/****************************************************************************
+ *
+ * FUNCTION: Acpi_ns_search_parent_tree
+ *
+ * PARAMETERS: *Entry_name - Ascii ACPI name to search for
+ * *Name_table - Starting table where search will begin
+ * Type - Object type to match
+ * **Ret_entry - Where the matched NTE is returned
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Called when a name has not been found in the current namespace
+ * table. Before adding it or giving up, ACPI scope rules require
+ * searching enclosing scopes in cases identified by Acpi_ns_local().
+ *
+ * "A name is located by finding the matching name in the current
+ * name space, and then in the parent name space. If the parent
+ * name space does not contain the name, the search continues
+ * recursively until either the name is found or the name space
+ * does not have a parent (the root of the name space). This
+ * indicates that the name is not found" (From ACPI Specification,
+ * section 5.3)
+ *
+ ***************************************************************************/
+
+
+ACPI_STATUS
+acpi_ns_search_parent_tree (
+ u32 entry_name,
+ ACPI_NAME_TABLE *name_table,
+ OBJECT_TYPE_INTERNAL type,
+ ACPI_NAMED_OBJECT **ret_entry)
+{
+ ACPI_STATUS status;
+ ACPI_NAMED_OBJECT *parent_entry;
+ ACPI_NAMED_OBJECT *entries;
+
+
+ entries = name_table->entries;
+
+ /*
+ * If no parent or type is "local", we won't be searching the
+ * parent tree.
+ */
+
+ if (!acpi_ns_local (type) &&
+ name_table->parent_entry)
+ {
+ parent_entry = name_table->parent_entry;
+ /*
+ * Search parents until found or we have backed up to
+ * the root
+ */
+
+ while (parent_entry) {
+ /* Search parent scope */
+ /* TBD: [Investigate] Why ACPI_TYPE_ANY? */
+
+ status = acpi_ns_search_one_scope (entry_name,
+ parent_entry->child_table,
+ ACPI_TYPE_ANY,
+ ret_entry, NULL);
+
+ if (status == AE_OK) {
+ return (status);
+ }
+
+ /*
+ * Not found here, go up another level
+ * (until we reach the root)
+ */
+
+ parent_entry = acpi_ns_get_parent_entry (parent_entry);
+ }
+
+ /* Not found in parent tree */
+ }
+
+
+ return (AE_NOT_FOUND);
+}
+
+
+/****************************************************************************
+ *
+ * FUNCTION: Acpi_ns_create_and_link_new_table
+ *
+ * PARAMETERS: *Name_table - The table that is to be "extended" by
+ * the creation of an appendage table.
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Allocate a new namespace table, initialize it, and link it
+ * into the parent table.
+ *
+ * NOTE: We are in the first or second pass load mode, want to
+ * add a new table entry, and the current table is full.
+ *
+ ***************************************************************************/
+
+ACPI_STATUS
+acpi_ns_create_and_link_new_table (
+ ACPI_NAME_TABLE *name_table)
+{
+ ACPI_NAME_TABLE *new_table;
+ ACPI_NAMED_OBJECT *parent_entry;
+ ACPI_STATUS status = AE_OK;
+
+
+ /* Sanity check on the data structure */
+
+ if (name_table->next_table) {
+ /* We should never get here (an appendage already allocated) */
+
+ return (AE_AML_INTERNAL);
+ }
+
+
+ /*
+ * We can use the parent entries from the current table
+ * Since the parent information remains the same.
+ */
+ parent_entry = name_table->parent_entry;
+
+
+ /* Allocate and chain an appendage to the filled table */
+
+ new_table = acpi_ns_allocate_name_table (NS_TABLE_SIZE);
+ if (!new_table) {
+ REPORT_ERROR ("Name Table appendage allocation failure");
+ return (AE_NO_MEMORY);
+ }
+
+ /*
+ * Allocation successful. Init the new table.
+ */
+ name_table->next_table = new_table;
+ acpi_ns_initialize_table (new_table, parent_entry->child_table,
+ parent_entry);
+
+ return (status);
+}
+
+
+/****************************************************************************
+ *
+ * FUNCTION: Acpi_ns_initialize_table
+ *
+ * PARAMETERS: New_table - The new table to be initialized
+ * Parent_table - The parent (owner) scope
+ * Parent_entry - The NTE for the parent
+ *
+ * RETURN: None
+ *
+ * DESCRIPTION: Initialize a new namespace table. Simple, but called
+ * from several places -- code should be kept in one place.
+ *
+ ***************************************************************************/
+
+void
+acpi_ns_initialize_table (
+ ACPI_NAME_TABLE *new_table,
+ ACPI_NAME_TABLE *parent_table,
+ ACPI_NAMED_OBJECT *parent_entry)
+{
+ u8 i;
+
+
+ new_table->parent_entry = parent_entry;
+ new_table->parent_table = parent_table;
+
+
+ /* Init each named object entry in the table */
+
+ for (i = 0; i < NS_TABLE_SIZE; i++) {
+ new_table->entries[i].this_index = i;
+ new_table->entries[i].data_type = ACPI_DESC_TYPE_NAMED;
+ }
+
+}
+
+
+/****************************************************************************
+ *
+ * FUNCTION: Acpi_ns_initialize_entry
+ *
+ * PARAMETERS: Name_table - The containing table for the new NTE
+ * Position - Position (index) of the new NTE in the table
+ * Entry_name - ACPI name of the new entry
+ * Type - ACPI object type of the new entry
+ * Previous_entry - Link back to the previous entry (can span
+ * multiple tables)
+ *
+ * RETURN: None
+ *
+ * DESCRIPTION: Initialize a new entry within a namespace table.
+ *
+ ***************************************************************************/
+
+void
+acpi_ns_initialize_entry (
+ ACPI_WALK_STATE *walk_state,
+ ACPI_NAME_TABLE *name_table,
+ u32 position,
+ u32 entry_name,
+ OBJECT_TYPE_INTERNAL type)
+{
+ ACPI_NAMED_OBJECT *new_entry;
+ u16 owner_id = TABLE_ID_DSDT;
+ ACPI_NAMED_OBJECT *entries;
+
+
+ /*
+ * Get the owner ID from the Walk state
+ * The owner ID is used to track table deletion and
+ * deletion of objects created by methods
+ */
+ if (walk_state) {
+ owner_id = walk_state->owner_id;
+ }
+
+ /* The new entry is given by two parameters */
+
+ entries = name_table->entries;
+ new_entry = &entries[position];
+
+ /* Init the new entry */
+
+ new_entry->data_type = ACPI_DESC_TYPE_NAMED;
+ new_entry->name = entry_name;
+ new_entry->owner_id = owner_id;
+ new_entry->reference_count = 1;
+
+
+ /*
+ * If adding a name with unknown type, or having to
+ * add the region in order to define fields in it, we
+ * have a forward reference.
+ */
+
+ if ((ACPI_TYPE_ANY == type) ||
+ (INTERNAL_TYPE_DEF_FIELD_DEFN == type) ||
+ (INTERNAL_TYPE_BANK_FIELD_DEFN == type))
+ {
+ /*
+ * We don't want to abort here, however!
+ * We will fill in the actual type when the
+ * real definition is found later.
+ */
+
+ }
+
+ /*
+ * The Def_field_defn and Bank_field_defn cases are actually
+ * looking up the Region in which the field will be defined
+ */
+
+ if ((INTERNAL_TYPE_DEF_FIELD_DEFN == type) ||
+ (INTERNAL_TYPE_BANK_FIELD_DEFN == type))
+ {
+ type = ACPI_TYPE_REGION;
+ }
+
+ /*
+ * Scope, Def_any, and Index_field_defn are bogus "types" which do
+ * not actually have anything to do with the type of the name
+ * being looked up. Save any other value of Type as the type of
+ * the entry.
+ */
+
+ if ((type != INTERNAL_TYPE_SCOPE) &&
+ (type != INTERNAL_TYPE_DEF_ANY) &&
+ (type != INTERNAL_TYPE_INDEX_FIELD_DEFN))
+ {
+ new_entry->type = (u8) type;
+ }
+
+ return;
+}
+
+
+/****************************************************************************
+ *
+ * FUNCTION: Acpi_ns_search_and_enter
+ *
+ * PARAMETERS: Entry_name - Ascii ACPI name to search for (4 chars)
+ * *Name_table - Starting table where search will begin
+ * Interpreter_mode - Add names only in MODE_Load_pass_x. Otherwise,
+ * search only.
+ * Type - Object type to match
+ * **Ret_entry - Where the matched NTE is returned
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Search for a name segment in a single name table,
+ * optionally adding it if it is not found. If the passed
+ * Type is not Any and the type previously stored in the
+ * entry was Any (i.e. unknown), update the stored type.
+ *
+ * In IMODE_EXECUTE, search only.
+ * In other modes, search and add if not found.
+ *
+ ***************************************************************************/
+
+ACPI_STATUS
+acpi_ns_search_and_enter (
+ u32 entry_name,
+ ACPI_WALK_STATE *walk_state,
+ ACPI_NAME_TABLE *name_table,
+ OPERATING_MODE interpreter_mode,
+ OBJECT_TYPE_INTERNAL type,
+ u32 flags,
+ ACPI_NAMED_OBJECT **ret_entry)
+{
+ u32 position; /* position in table */
+ ACPI_STATUS status;
+ NS_SEARCH_DATA search_info;
+ ACPI_NAMED_OBJECT *entry;
+ ACPI_NAMED_OBJECT *entries;
+
+
+ /* Parameter validation */
+
+ if (!name_table || !entry_name || !ret_entry) {
+ REPORT_ERROR ("Ns_search_and_enter: bad parameter");
+ return (AE_BAD_PARAMETER);
+ }
+
+
+ /* Name must consist of printable characters */
+
+ if (!acpi_cm_valid_acpi_name (entry_name)) {
+ return (AE_BAD_CHARACTER);
+ }
+
+
+ /* Try to find the name in the table specified by the caller */
+
+ *ret_entry = ENTRY_NOT_FOUND;
+ status = acpi_ns_search_one_scope (entry_name, name_table,
+ type, ret_entry, &search_info);
+ if (status != AE_NOT_FOUND) {
+ /*
+ * Either found it or there was an error
+ * -- finished either way
+ */
+
+ return (status);
+ }
+
+
+ /*
+ * Not found in the table. If we are NOT performing the
+ * first pass (name entry) of loading the namespace, search
+ * the parent tree (all the way to the root if necessary.)
+ * We don't want to perform the parent search when the
+ * namespace is actually being loaded. We want to perform
+ * the search when namespace references are being resolved
+ * (load pass 2) and during the execution phase.
+ */
+
+ if ((interpreter_mode != IMODE_LOAD_PASS1) &&
+ (flags & NS_SEARCH_PARENT))
+ {
+ /*
+ * Not found in table - search parent tree according
+ * to ACPI specification
+ */
+
+ status = acpi_ns_search_parent_tree (entry_name, name_table,
+ type, ret_entry);
+
+ if (status == AE_OK) {
+ return (status);
+ }
+ }
+
+
+ /*
+ * In execute mode, just search, never add names. Exit now.
+ */
+
+ if (interpreter_mode == IMODE_EXECUTE) {
+ return (AE_NOT_FOUND);
+ }
+
+
+ /*
+ * Extract the pertinent info from the search result struct.
+ * Name_table and position might now point to an appendage
+ */
+ name_table = search_info.name_table;
+ position = search_info.position;
+
+
+ /*
+ * This block handles the case where the existing table is full.
+ * we must allocate a new table before we can initialize a new entry
+ */
+
+ if (search_info.table_full) {
+ status = acpi_ns_create_and_link_new_table (name_table);
+ if (status != AE_OK) {
+ return (status);
+ }
+
+ /* Point to the first slot in the new table */
+
+ name_table = name_table->next_table;
+ position = 0;
+ }
+
+
+ /*
+ * There is room in the table (or we have just allocated a new one.)
+ * Initialize the new entry
+ */
+
+ acpi_ns_initialize_entry (walk_state, name_table, position,
+ entry_name, type);
+
+
+ entries = name_table->entries;
+ *ret_entry = &entries[position];
+ entry = &entries[position];
+
+ /*
+ * Increment the reference count(s) of all parents up to
+ * the root!
+ */
+
+ while (acpi_ns_get_parent_entry (entry)) {
+ entry = acpi_ns_get_parent_entry (entry);
+ entry->reference_count++;
+ }
+
+
+ return (AE_OK);
+}
+
diff --git a/drivers/acpi/namespace/nsutils.c b/drivers/acpi/namespace/nsutils.c
new file mode 100644
index 000000000..c938ede93
--- /dev/null
+++ b/drivers/acpi/namespace/nsutils.c
@@ -0,0 +1,886 @@
+
+/******************************************************************************
+ *
+ * Module Name: nsutils - Utilities for accessing ACPI namespace, accessing
+ * parents and siblings and Scope manipulation
+ *
+ *****************************************************************************/
+
+/*
+ * 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 "namesp.h"
+#include "interp.h"
+#include "amlcode.h"
+#include "tables.h"
+
+#define _COMPONENT NAMESPACE
+ MODULE_NAME ("nsutils");
+
+
+/****************************************************************************
+ *
+ * FUNCTION: Acpi_ns_valid_root_prefix
+ *
+ * PARAMETERS: Prefix - Character to be checked
+ *
+ * RETURN: TRUE if a valid prefix
+ *
+ * DESCRIPTION: Check if a character is a valid ACPI Root prefix
+ *
+ ***************************************************************************/
+
+u8
+acpi_ns_valid_root_prefix (
+ char prefix)
+{
+
+ return ((u8) (prefix == '\\'));
+}
+
+
+/****************************************************************************
+ *
+ * FUNCTION: Acpi_ns_valid_path_separator
+ *
+ * PARAMETERS: Sep - Character to be checked
+ *
+ * RETURN: TRUE if a valid path separator
+ *
+ * DESCRIPTION: Check if a character is a valid ACPI path separator
+ *
+ ***************************************************************************/
+
+u8
+acpi_ns_valid_path_separator (
+ char sep)
+{
+
+ return ((u8) (sep == '.'));
+}
+
+
+/****************************************************************************
+ *
+ * FUNCTION: Acpi_ns_get_type
+ *
+ * PARAMETERS: Handle - Handle of nte to be examined
+ *
+ * RETURN: Type field from nte whose handle is passed
+ *
+ ***************************************************************************/
+
+OBJECT_TYPE_INTERNAL
+acpi_ns_get_type (
+ ACPI_HANDLE handle)
+{
+
+ if (!handle) {
+ /* Handle invalid */
+
+ REPORT_WARNING ("Ns_get_type: Null handle");
+ return (ACPI_TYPE_ANY);
+ }
+
+ return (((ACPI_NAMED_OBJECT*) handle)->type);
+}
+
+
+/****************************************************************************
+ *
+ * FUNCTION: Acpi_ns_local
+ *
+ * PARAMETERS: Type - A namespace object type
+ *
+ * RETURN: LOCAL if names must be found locally in objects of the
+ * passed type, 0 if enclosing scopes should be searched
+ *
+ ***************************************************************************/
+
+s32
+acpi_ns_local (
+ OBJECT_TYPE_INTERNAL type)
+{
+
+ if (!acpi_cm_valid_object_type (type)) {
+ /* type code out of range */
+
+ REPORT_WARNING ("Ns_local: Invalid Object Type");
+ return (NSP_NORMAL);
+ }
+
+ return ((s32) acpi_gbl_ns_properties[type] & NSP_LOCAL);
+}
+
+
+/****************************************************************************
+ *
+ * FUNCTION: Acpi_ns_internalize_name
+ *
+ * PARAMETERS: *External_name - External representation of name
+ * **Converted Name - Where to return the resulting
+ * internal represention of the name
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Convert an external representation (e.g. "\_PR_.CPU0")
+ * to internal form (e.g. 5c 2f 02 5f 50 52 5f 43 50 55 30)
+ *
+ ****************************************************************************/
+
+ACPI_STATUS
+acpi_ns_internalize_name (
+ char *external_name,
+ char **converted_name)
+{
+ char *result = NULL;
+ char *internal_name;
+ ACPI_SIZE num_segments;
+ u8 fully_qualified = FALSE;
+ u32 i;
+
+
+ if ((!external_name) ||
+ (*external_name == 0) ||
+ (!converted_name))
+ {
+ return (AE_BAD_PARAMETER);
+ }
+
+
+ /*
+ * For the internal name, the required length is 4 bytes
+ * per segment, plus 1 each for Root_prefix, Multi_name_prefix_op,
+ * segment count, trailing null (which is not really needed,
+ * but no there's harm in putting it there)
+ *
+ * strlen() + 1 covers the first Name_seg, which has no
+ * path separator
+ */
+
+ if (acpi_ns_valid_root_prefix (external_name[0])) {
+ fully_qualified = TRUE;
+ external_name++;
+ }
+
+
+ /*
+ * Determine the number of ACPI name "segments" by counting
+ * the number of path separators within the string. Start
+ * with one segment since the segment count is (# separators)
+ * + 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++;
+ }
+ }
+
+
+ /* We need a segment to store the internal version of the name */
+
+ internal_name = acpi_cm_callocate ((ACPI_NAME_SIZE * num_segments) + 4);
+ if (!internal_name) {
+ return (AE_NO_MEMORY);
+ }
+
+
+ /* Setup the correct prefixes, counts, and pointers */
+
+ if (fully_qualified) {
+ internal_name[0] = '\\';
+ 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];
+ }
+
+
+ /* Build the name (minus path separators) */
+
+ for (; num_segments; num_segments--) {
+ for (i = 0; i < ACPI_NAME_SIZE; i++) {
+ if (acpi_ns_valid_path_separator (*external_name) ||
+ (*external_name == 0))
+ {
+ /*
+ * Pad the segment with underscore(s) if
+ * segment is short
+ */
+
+ result[i] = '_';
+ }
+
+ else {
+ /* Convert char to uppercase and save it */
+
+ result[i] = (char) TOUPPER (*external_name);
+ external_name++;
+ }
+
+ }
+
+ /* Now we must have a path separator, or the pathname is bad */
+
+ if (!acpi_ns_valid_path_separator (*external_name) &&
+ (*external_name != 0))
+ {
+ acpi_cm_free (internal_name);
+ return (AE_BAD_PARAMETER);
+ }
+
+ /* Move on the next segment */
+
+ external_name++;
+ result += ACPI_NAME_SIZE;
+ }
+
+
+ /* Return the completed name */
+
+ /* Terminate the string! */
+ *result = 0;
+ *converted_name = internal_name;
+
+
+
+ return (AE_OK);
+}
+
+
+/****************************************************************************
+ *
+ * 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 < 0 ||
+ !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 NTE
+ *
+ * RETURN: A Name table entry pointer
+ *
+ * DESCRIPTION: Convert a namespace handle to a real NTE
+ *
+ ****************************************************************************/
+
+ACPI_NAMED_OBJECT*
+acpi_ns_convert_handle_to_entry (
+ ACPI_HANDLE handle)
+{
+
+ /*
+ * Simple implementation for now;
+ * TBD: [Future] Real integer handles allow for more verification
+ * and keep all pointers within this subsystem!
+ */
+
+ if (!handle) {
+ return NULL;
+ }
+
+ if (handle == ACPI_ROOT_OBJECT) {
+ return acpi_gbl_root_object;
+ }
+
+
+ /* We can at least attempt to verify the handle */
+
+ if (!VALID_DESCRIPTOR_TYPE (handle, ACPI_DESC_TYPE_NAMED)) {
+ return NULL;
+ }
+
+ return (ACPI_NAMED_OBJECT*) handle;
+}
+
+
+/****************************************************************************
+ *
+ * FUNCTION: Acpi_ns_convert_entry_to_handle
+ *
+ * PARAMETERS: Nte - NTE to be converted to a Handle
+ *
+ * RETURN: An USER ACPI_HANDLE
+ *
+ * DESCRIPTION: Convert a real NTE to a namespace handle
+ *
+ ****************************************************************************/
+
+ACPI_HANDLE
+acpi_ns_convert_entry_to_handle(ACPI_NAMED_OBJECT*nte)
+{
+
+
+ /*
+ * Simple implementation for now;
+ * TBD: [Future] Real integer handles allow for more verification
+ * and keep all pointers within this subsystem!
+ */
+
+ return (ACPI_HANDLE) nte;
+
+
+/* ---------------------------------------------------
+
+ if (!Nte) {
+ return NULL;
+ }
+
+ if (Nte == Acpi_gbl_Root_object) {
+ return ACPI_ROOT_OBJECT;
+ }
+
+
+ return (ACPI_HANDLE) Nte;
+------------------------------------------------------*/
+}
+
+
+/******************************************************************************
+ *
+ * FUNCTION: Acpi_ns_terminate
+ *
+ * PARAMETERS: none
+ *
+ * RETURN: none
+ *
+ * DESCRIPTION: free memory allocated for table storage.
+ *
+ ******************************************************************************/
+
+void
+acpi_ns_terminate (void)
+{
+ ACPI_OBJECT_INTERNAL *obj_desc;
+ ACPI_NAMED_OBJECT *entry;
+
+
+ entry = acpi_gbl_root_object;
+
+ /*
+ * 1) Free the entire namespace -- all objects, tables, and stacks
+ */
+ /*
+ * Delete all objects linked to the root
+ * (additional table descriptors)
+ */
+
+ acpi_ns_delete_namespace_subtree (entry);
+
+ /* Detach any object(s) attached to the root */
+
+ obj_desc = acpi_ns_get_attached_object (entry);
+ if (obj_desc) {
+ acpi_ns_detach_object (entry);
+ acpi_cm_remove_reference (obj_desc);
+ }
+
+ acpi_ns_delete_name_table (entry->child_table);
+ entry->child_table = NULL;
+
+
+ REPORT_SUCCESS ("Entire namespace and objects deleted");
+
+ /*
+ * 2) Now we can delete the ACPI tables
+ */
+
+ acpi_tb_delete_acpi_tables ();
+
+ return;
+}
+
+
+/****************************************************************************
+ *
+ * FUNCTION: Acpi_ns_opens_scope
+ *
+ * PARAMETERS: Type - A valid namespace type
+ *
+ * RETURN: NEWSCOPE if the passed type "opens a name scope" according
+ * to the ACPI specification, else 0
+ *
+ ***************************************************************************/
+
+s32
+acpi_ns_opens_scope (
+ OBJECT_TYPE_INTERNAL type)
+{
+
+ if (!acpi_cm_valid_object_type (type)) {
+ /* type code out of range */
+
+ REPORT_WARNING ("Ns_opens_scope: Invalid Object Type");
+ return (NSP_NORMAL);
+ }
+
+ return (((s32) acpi_gbl_ns_properties[type]) & NSP_NEWSCOPE);
+}
+
+
+/****************************************************************************
+ *
+ * FUNCTION: Acpi_ns_get_named_object
+ *
+ * PARAMETERS: *Pathname - Name to be found, in external (ASL) format. The
+ * \ (backslash) and ^ (carat) prefixes, and the
+ * . (period) to separate segments are supported.
+ * In_scope - Root of subtree to be searched, or NS_ALL for the
+ * root of the name space. If Name is fully
+ * qualified (first char is '\'), the passed value
+ * of Scope will not be accessed.
+ * Out_nte - Where the Nte is returned
+ *
+ * DESCRIPTION: Look up a name relative to a given scope and return the
+ * corresponding NTE. NOTE: Scope can be null.
+ *
+ * MUTEX: Locks namespace
+ *
+ ***************************************************************************/
+
+ACPI_STATUS
+acpi_ns_get_named_object (
+ char *pathname,
+ ACPI_NAME_TABLE *in_scope,
+ ACPI_NAMED_OBJECT **out_nte)
+{
+ ACPI_GENERIC_STATE scope_info;
+ ACPI_STATUS status;
+ ACPI_NAMED_OBJECT *obj_entry = NULL;
+ char *internal_path = NULL;
+
+
+ scope_info.scope.name_table = in_scope;
+
+ /* Ensure that the namespace has been initialized */
+
+ if (!acpi_gbl_root_object->child_table) {
+ return (AE_NO_NAMESPACE);
+ }
+
+ if (!pathname) {
+ return (AE_BAD_PARAMETER);
+ }
+
+
+ /* Convert path to internal representation */
+
+ status = acpi_ns_internalize_name (pathname, &internal_path);
+ if (ACPI_FAILURE (status)) {
+ return (status);
+ }
+
+
+ acpi_cm_acquire_mutex (ACPI_MTX_NAMESPACE);
+
+ /* NS_ALL means start from the root */
+
+ if (NS_ALL == scope_info.scope.name_table) {
+ scope_info.scope.name_table = acpi_gbl_root_object->child_table;
+ }
+
+ else {
+ scope_info.scope.name_table = in_scope;
+ if (!scope_info.scope.name_table) {
+ status = AE_BAD_PARAMETER;
+ goto unlock_and_exit;
+ }
+ }
+
+ /* Lookup the name in the namespace */
+
+ status = acpi_ns_lookup (&scope_info, internal_path,
+ ACPI_TYPE_ANY, IMODE_EXECUTE,
+ NS_NO_UPSEARCH | NS_DONT_OPEN_SCOPE,
+ NULL, &obj_entry);
+
+
+ /* Return what was wanted - the NTE that matches the name */
+
+ *out_nte = obj_entry;
+
+
+unlock_and_exit:
+
+ acpi_cm_release_mutex (ACPI_MTX_NAMESPACE);
+
+ /* Cleanup */
+
+ acpi_cm_free (internal_path);
+
+ return (status);
+}
+
+
+/****************************************************************************
+ *
+ * FUNCTION: Acpi_ns_find_parent_name
+ *
+ * PARAMETERS: *Child_entry - nte whose name is to be found
+ *
+ * RETURN: The ACPI name
+ *
+ * DESCRIPTION: Search for the given nte in its parent scope and return the
+ * name segment, or "????" if the parent name can't be found
+ * (which "should not happen").
+ *
+ ***************************************************************************/
+
+ACPI_NAME
+acpi_ns_find_parent_name (
+ ACPI_NAMED_OBJECT *child_entry)
+{
+ ACPI_NAMED_OBJECT *parent_entry;
+
+
+ if (child_entry) {
+ /* Valid entry. Get the parent Nte */
+
+ parent_entry = acpi_ns_get_parent_entry (child_entry);
+ if (parent_entry) {
+ if (parent_entry->name) {
+ return (parent_entry->name);
+ }
+ }
+
+ }
+
+
+ return (ACPI_UNKNOWN_NAME);
+}
+
+/****************************************************************************
+ *
+ * FUNCTION: Acpi_ns_exist_downstream_sibling
+ *
+ * PARAMETERS: *This_entry - pointer to first nte to examine
+ *
+ * RETURN: TRUE if sibling is found, FALSE otherwise
+ *
+ * DESCRIPTION: Searches remainder of scope being processed to determine
+ * whether there is a downstream sibling to the current
+ * object. This function is used to determine what type of
+ * line drawing character to use when displaying namespace
+ * trees.
+ *
+ ***************************************************************************/
+
+u8
+acpi_ns_exist_downstream_sibling (
+ ACPI_NAMED_OBJECT *this_entry)
+{
+
+ if (!this_entry) {
+ return FALSE;
+ }
+
+ if (this_entry->name) {
+ return TRUE;
+ }
+
+
+/* TBD: what did this really do?
+ if (This_entry->Next_entry) {
+ return TRUE;
+ }
+*/
+ return FALSE;
+}
+
+
+/****************************************************************************
+ *
+ * FUNCTION: Acpi_ns_get_owner_table
+ *
+ * PARAMETERS:
+ *
+ * RETURN:
+ *
+ * DESCRIPTION:
+ *
+ ***************************************************************************/
+
+
+ACPI_NAME_TABLE *
+acpi_ns_get_owner_table (
+ ACPI_NAMED_OBJECT *this_entry)
+{
+
+ /*
+ * Given an entry in the Name_table->Entries field of a name table,
+ * we can create a pointer to the beginning of the table as follows:
+ *
+ * 1) Starting with the the pointer to the entry,
+ * 2) Subtract the entry index * size of each entry to get a
+ * pointer to Entries[0]
+ * 3) Subtract the size of NAME_TABLE structure to get a pointer
+ * to the start.
+ *
+ * This saves having to put a pointer in every entry that points
+ * back to the beginning of the table and/or a pointer back to
+ * the parent.
+ */
+
+ return (ACPI_NAME_TABLE *) ((char *) this_entry -
+ (this_entry->this_index *
+ sizeof (ACPI_NAMED_OBJECT)) -
+ (sizeof (ACPI_NAME_TABLE) -
+ sizeof (ACPI_NAMED_OBJECT)));
+
+}
+
+
+/****************************************************************************
+ *
+ * FUNCTION: Acpi_ns_get_parent_entry
+ *
+ * PARAMETERS: This_entry - Current table entry
+ *
+ * RETURN: Parent entry of the given entry
+ *
+ * DESCRIPTION: Obtain the parent entry for a given entry in the namespace.
+ *
+ ***************************************************************************/
+
+
+ACPI_NAMED_OBJECT *
+acpi_ns_get_parent_entry (
+ ACPI_NAMED_OBJECT *this_entry)
+{
+ ACPI_NAME_TABLE *name_table;
+
+
+ name_table = acpi_ns_get_owner_table (this_entry);
+
+ /*
+ * Now that we have a pointer to the name table, we can just pluck
+ * the parent
+ */
+
+ return (name_table->parent_entry);
+}
+
+
+/****************************************************************************
+ *
+ * FUNCTION: Acpi_ns_get_next_valid_entry
+ *
+ * PARAMETERS: This_entry - Current table entry
+ *
+ * RETURN: Next valid object in the table. NULL if no more valid
+ * objects
+ *
+ * DESCRIPTION: Find the next valid object within a name table.
+ *
+ ***************************************************************************/
+
+
+ACPI_NAMED_OBJECT *
+acpi_ns_get_next_valid_entry (
+ ACPI_NAMED_OBJECT *this_entry)
+{
+ ACPI_NAME_TABLE *name_table;
+ u32 index;
+
+
+ index = this_entry->this_index + 1;
+ name_table = acpi_ns_get_owner_table (this_entry);
+
+
+ while (name_table) {
+ if (index >= NS_TABLE_SIZE) {
+ /* We are at the end of this table */
+
+ name_table = name_table->next_table;
+ index = 0;
+ continue;
+ }
+
+
+ /* Is this a valid (occupied) slot? */
+
+ if (name_table->entries[index].name) {
+ /* Found a valid entry, all done */
+
+ return (&name_table->entries[index]);
+ }
+
+ /* Go to the next slot */
+
+ index++;
+ }
+
+ /* No more valid entries in this name table */
+
+ return NULL;
+}
+
+
diff --git a/drivers/acpi/namespace/nswalk.c b/drivers/acpi/namespace/nswalk.c
new file mode 100644
index 000000000..6fcb14b76
--- /dev/null
+++ b/drivers/acpi/namespace/nswalk.c
@@ -0,0 +1,279 @@
+
+/******************************************************************************
+ *
+ * Module Name: nswalk - Functions for walking the APCI namespace
+ *
+ *****************************************************************************/
+
+/*
+ * 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 "interp.h"
+#include "namesp.h"
+
+
+#define _COMPONENT NAMESPACE
+ MODULE_NAME ("nswalk");
+
+
+/****************************************************************************
+ *
+ * FUNCTION: Acpi_get_next_object
+ *
+ * PARAMETERS: Type - Type of object to be searched for
+ * Parent - Parent object whose children we are getting
+ * Last_child - Previous child that was found.
+ * The NEXT child will be returned
+ * Ret_handle - Where handle to the next object is placed
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Return the next peer object within the namespace. If Handle is
+ * valid, Scope is ignored. Otherwise, the first object within
+ * Scope is returned.
+ *
+ ******************************************************************************/
+
+ACPI_NAMED_OBJECT*
+acpi_ns_get_next_object (
+ OBJECT_TYPE_INTERNAL type,
+ ACPI_NAMED_OBJECT *parent,
+ ACPI_NAMED_OBJECT *child)
+{
+ ACPI_NAMED_OBJECT *this_entry = NULL;
+
+
+ if (!child) {
+
+ /* It's really the parent's _scope_ that we want */
+
+ if (parent->child_table) {
+ this_entry = parent->child_table->entries;
+ }
+ }
+
+ else {
+ /* Start search at the NEXT object */
+
+ this_entry = acpi_ns_get_next_valid_entry (child);
+ }
+
+
+ /* If any type is OK, we are done */
+
+ if (type == ACPI_TYPE_ANY) {
+ /* Make sure this is valid entry first */
+
+ if ((!this_entry) ||
+ (!this_entry->name))
+ {
+ return NULL;
+ }
+
+ return (this_entry);
+ }
+
+
+ /* Must search for the object -- but within this scope only */
+
+ while (this_entry) {
+ /* If type matches, we are done */
+
+ if (this_entry->type == type) {
+ return (this_entry);
+ }
+
+ /* Otherwise, move on to the next object */
+
+ this_entry = acpi_ns_get_next_valid_entry (this_entry);
+ }
+
+
+ /* Not found */
+
+ return NULL;
+}
+
+
+/******************************************************************************
+ *
+ * FUNCTION: Acpi_ns_walk_namespace
+ *
+ * PARAMETERS: Type - ACPI_OBJECT_TYPE to search for
+ * Start_object - Handle in namespace where search begins
+ * Max_depth - Depth to which search is to reach
+ * Unlock_before_callback- Whether to unlock the NS before invoking
+ * the callback routine
+ * User_function - Called when an object of "Type" is found
+ * Context - Passed to user function
+ *
+ * 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.
+ *
+ * The point of this procedure is to provide a generic namespace
+ * walk routine that can be called from multiple places to
+ * provide multiple services; the User Function can be tailored
+ * to each task, whether it is a print function, a compare
+ * function, etc.
+ *
+ ******************************************************************************/
+
+ACPI_STATUS
+acpi_ns_walk_namespace (
+ OBJECT_TYPE_INTERNAL type,
+ ACPI_HANDLE start_object,
+ u32 max_depth,
+ u8 unlock_before_callback,
+ WALK_CALLBACK user_function,
+ void *context,
+ void **return_value)
+{
+ ACPI_STATUS status;
+ ACPI_NAMED_OBJECT *child_entry;
+ ACPI_NAMED_OBJECT *parent_entry;
+ OBJECT_TYPE_INTERNAL child_type;
+ u32 level;
+
+
+ /* Special case for the namespace root object */
+
+ if (start_object == ACPI_ROOT_OBJECT) {
+ start_object = acpi_gbl_root_object;
+ }
+
+
+ /* Null child means "get first object" */
+
+ parent_entry = start_object;
+ child_entry = 0;
+ child_type = ACPI_TYPE_ANY;
+ level = 1;
+
+ /*
+ * Traverse the tree of objects until we bubble back up to where we
+ * started. When Level is zero, the loop is done because we have
+ * bubbled up to (and passed) the original parent handle (Start_entry)
+ */
+
+ while (level > 0) {
+ /*
+ * Get the next typed object in this scope. Null returned
+ * if not found
+ */
+
+ status = AE_OK;
+ child_entry = acpi_ns_get_next_object (ACPI_TYPE_ANY,
+ parent_entry,
+ child_entry);
+
+ if (child_entry) {
+ /*
+ * Found an object, Get the type if we are not
+ * searching for ANY
+ */
+
+ if (type != ACPI_TYPE_ANY) {
+ child_type = child_entry->type;
+ }
+
+ if (child_type == type) {
+ /*
+ * Found a matching object, invoke the user
+ * callback function
+ */
+
+ if (unlock_before_callback) {
+ acpi_cm_release_mutex (ACPI_MTX_NAMESPACE);
+ }
+
+ status = user_function (child_entry, level,
+ context, return_value);
+
+ if (unlock_before_callback) {
+ acpi_cm_acquire_mutex (ACPI_MTX_NAMESPACE);
+ }
+
+ switch (status)
+ {
+ case AE_OK:
+ case AE_CTRL_DEPTH:
+ /* Just keep going */
+ break;
+
+ case AE_CTRL_TERMINATE:
+ /* Exit now, with OK status */
+ return (AE_OK);
+ break;
+
+ default:
+ /* All others are valid exceptions */
+ return (status);
+ break;
+ }
+ }
+
+ /*
+ * Depth first search:
+ * Attempt to go down another level in the namespace
+ * if we are allowed to. Don't go any further if we
+ * have reached the caller specified maximum depth
+ * or if the user function has specified that the
+ * maximum depth has been reached.
+ */
+
+ if ((level < max_depth) && (status != AE_CTRL_DEPTH)) {
+ if (acpi_ns_get_next_object (ACPI_TYPE_ANY,
+ child_entry, 0))
+ {
+ /*
+ * There is at least one child of this
+ * object, visit the object
+ */
+ level++;
+ parent_entry = child_entry;
+ child_entry = 0;
+ }
+ }
+ }
+
+ else {
+ /*
+ * No more children in this object (Acpi_ns_get_next_object
+ * failed), go back upwards in the namespace tree to
+ * the object's parent.
+ */
+ level--;
+ child_entry = parent_entry;
+ parent_entry = acpi_ns_get_parent_entry (parent_entry);
+ }
+ }
+
+ /* Complete walk, not terminated by user function */
+ return (AE_OK);
+}
+
+
diff --git a/drivers/acpi/namespace/nsxfname.c b/drivers/acpi/namespace/nsxfname.c
new file mode 100644
index 000000000..2622a9be8
--- /dev/null
+++ b/drivers/acpi/namespace/nsxfname.c
@@ -0,0 +1,372 @@
+/******************************************************************************
+ *
+ * Module Name: nsxfname - Public interfaces to the ACPI subsystem
+ * ACPI Namespace oriented interfaces
+ *
+ *****************************************************************************/
+
+/*
+ * 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 "interp.h"
+#include "namesp.h"
+#include "amlcode.h"
+#include "parser.h"
+#include "dispatch.h"
+#include "events.h"
+
+
+#define _COMPONENT NAMESPACE
+ 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);
+ }
+
+
+ /* Init the hardware */
+
+ /*
+ * TBD: [Restructure] Should this should be moved elsewhere,
+ * like Acpi_enable! ??
+ */
+
+ /* we need to be able to call this interface repeatedly! */
+ /* Does H/W require init before loading the namespace? */
+
+ status = acpi_cm_hardware_initialize ();
+ if (ACPI_FAILURE (status)) {
+ return (status);
+ }
+
+ /*
+ * 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
+ *
+ * PARAMETERS: Parent - Object to search under (search scope).
+ * Path_name - Pointer to an asciiz string containing the
+ * name
+ * Ret_handle - Where the return handle is placed
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: This routine will search for a caller specified name in the
+ * name space. The caller can restrict the search region by
+ * specifying a non NULL parent. The parent value is itself a
+ * namespace handle.
+ *
+ ******************************************************************************/
+
+ACPI_STATUS
+acpi_get_handle (
+ ACPI_HANDLE parent,
+ ACPI_STRING pathname,
+ ACPI_HANDLE *ret_handle)
+{
+ ACPI_STATUS status;
+ ACPI_NAMED_OBJECT *this_entry;
+ ACPI_NAME_TABLE *scope = NULL;
+
+
+ if (!ret_handle || !pathname) {
+ return AE_BAD_PARAMETER;
+ }
+
+ if (parent) {
+ acpi_cm_acquire_mutex (ACPI_MTX_NAMESPACE);
+
+ this_entry = acpi_ns_convert_handle_to_entry (parent);
+ if (!this_entry) {
+ acpi_cm_release_mutex (ACPI_MTX_NAMESPACE);
+ return AE_BAD_PARAMETER;
+ }
+
+ scope = this_entry->child_table;
+ 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_object);
+ return AE_OK;
+ }
+
+ /*
+ * Find the Nte and convert to the user format
+ */
+ this_entry = NULL;
+ status = acpi_ns_get_named_object (pathname, scope, &this_entry);
+
+ *ret_handle = acpi_ns_convert_entry_to_handle (this_entry);
+
+ return (status);
+}
+
+
+/****************************************************************************
+ *
+ * FUNCTION: Acpi_get_pathname
+ *
+ * PARAMETERS: Handle - Handle to be converted to a pathname
+ * Name_type - Full pathname or single segment
+ * Ret_path_ptr - Buffer for returned path
+ *
+ * RETURN: Pointer to a string containing the fully qualified Name.
+ *
+ * DESCRIPTION: This routine returns the fully qualified name associated with
+ * the Handle parameter. This and the Acpi_pathname_to_handle are
+ * complementary functions.
+ *
+ ******************************************************************************/
+
+ACPI_STATUS
+acpi_get_name (
+ ACPI_HANDLE handle,
+ u32 name_type,
+ ACPI_BUFFER *ret_path_ptr)
+{
+ ACPI_STATUS status;
+ ACPI_NAMED_OBJECT *obj_entry;
+
+
+ /* Buffer pointer must be valid always */
+
+ if (!ret_path_ptr || (name_type > ACPI_NAME_TYPE_MAX)) {
+ return AE_BAD_PARAMETER;
+ }
+
+ /* Allow length to be zero and ignore the pointer */
+
+ if ((ret_path_ptr->length) &&
+ (!ret_path_ptr->pointer))
+ {
+ return AE_BAD_PARAMETER;
+ }
+
+ if (name_type == ACPI_FULL_PATHNAME) {
+ /* Get the full pathname (From the namespace root) */
+
+ status = acpi_ns_handle_to_pathname (handle, &ret_path_ptr->length,
+ ret_path_ptr->pointer);
+ return status;
+ }
+
+ /*
+ * Wants the single segment ACPI name.
+ * Validate handle and convert to an NTE
+ */
+
+ acpi_cm_acquire_mutex (ACPI_MTX_NAMESPACE);
+ obj_entry = acpi_ns_convert_handle_to_entry (handle);
+ if (!obj_entry) {
+ status = AE_BAD_PARAMETER;
+ goto unlock_and_exit;
+ }
+
+ /* Check if name will fit in buffer */
+
+ if (ret_path_ptr->length < PATH_SEGMENT_LENGTH) {
+ ret_path_ptr->length = PATH_SEGMENT_LENGTH;
+ status = AE_BUFFER_OVERFLOW;
+ goto unlock_and_exit;
+ }
+
+ /* Just copy the ACPI name from the NTE and zero terminate it */
+
+ STRNCPY (ret_path_ptr->pointer, (char *) &obj_entry->name,
+ ACPI_NAME_SIZE);
+ ((char *) ret_path_ptr->pointer) [ACPI_NAME_SIZE] = 0;
+ status = AE_OK;
+
+
+unlock_and_exit:
+
+ acpi_cm_release_mutex (ACPI_MTX_NAMESPACE);
+ return status;
+}
+
+
+/****************************************************************************
+ *
+ * FUNCTION: Acpi_get_object_info
+ *
+ * PARAMETERS: Handle - Object Handle
+ * Info - Where the info is returned
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Returns information about an object as gleaned from running
+ * several standard control methods.
+ *
+ ******************************************************************************/
+
+ACPI_STATUS
+acpi_get_object_info (
+ ACPI_HANDLE device,
+ ACPI_DEVICE_INFO *info)
+{
+ DEVICE_ID hid;
+ DEVICE_ID uid;
+ ACPI_STATUS status;
+ u32 device_status = 0;
+ u32 address = 0;
+ ACPI_NAMED_OBJECT *device_entry;
+
+
+ /* Parameter validation */
+
+ if (!device || !info) {
+ return AE_BAD_PARAMETER;
+ }
+
+ acpi_cm_acquire_mutex (ACPI_MTX_NAMESPACE);
+
+ device_entry = acpi_ns_convert_handle_to_entry (device);
+ if (!device_entry) {
+ acpi_cm_release_mutex (ACPI_MTX_NAMESPACE);
+ return AE_BAD_PARAMETER;
+ }
+
+ info->type = device_entry->type;
+ info->name = device_entry->name;
+ info->parent =
+ acpi_ns_convert_entry_to_handle (acpi_ns_get_parent_entry (device_entry));
+
+ acpi_cm_release_mutex (ACPI_MTX_NAMESPACE);
+
+ /*
+ * If not a device, we are all done.
+ */
+ if (info->type != ACPI_TYPE_DEVICE) {
+ return AE_OK;
+ }
+
+
+ /* Get extra info for ACPI devices */
+
+ info->valid = 0;
+
+ /* Execute the _HID method and save the result */
+
+ status = acpi_cm_execute_HID (device_entry, &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);
+ }
+
+ info->valid |= ACPI_VALID_HID;
+ }
+
+ /* Execute the _UID method and save the result */
+
+ status = acpi_cm_execute_UID (device_entry, &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);
+ }
+
+ info->valid |= ACPI_VALID_UID;
+ }
+
+ /*
+ * Execute the _STA method and save the result
+ * _STA is not always present
+ */
+
+ status = acpi_cm_execute_STA (device_entry, &device_status);
+ if (ACPI_SUCCESS (status)) {
+ info->current_status = device_status;
+ info->valid |= ACPI_VALID_STA;
+ }
+
+ /*
+ * Execute the _ADR method and save result if successful
+ * _ADR is not always present
+ */
+
+ status = acpi_cm_evaluate_numeric_object (METHOD_NAME__ADR,
+ device_entry, &address);
+
+ if (ACPI_SUCCESS (status)) {
+ info->address = address;
+ info->valid |= ACPI_VALID_ADR;
+ }
+
+ return AE_OK;
+}
+
diff --git a/drivers/acpi/namespace/nsxfobj.c b/drivers/acpi/namespace/nsxfobj.c
new file mode 100644
index 000000000..09c5e4e3d
--- /dev/null
+++ b/drivers/acpi/namespace/nsxfobj.c
@@ -0,0 +1,554 @@
+
+/******************************************************************************
+ *
+ * Module Name: nsxfobj - Public interfaces to the ACPI subsystem
+ * ACPI Object oriented interfaces
+ *
+ *****************************************************************************/
+
+/*
+ * 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 "interp.h"
+#include "namesp.h"
+
+
+#define _COMPONENT NAMESPACE
+ MODULE_NAME ("nsxfobj");
+
+
+/****************************************************************************
+ *
+ * FUNCTION: Acpi_evaluate_object
+ *
+ * PARAMETERS: Handle - Object handle (optional)
+ * *Pathname - Object pathname (optional)
+ * **Params - List of parameters to pass to
+ * method, terminated by NULL.
+ * Params itself may be NULL
+ * if no parameters are being
+ * passed.
+ * *Return_object - Where to put method's return value (if
+ * any). If NULL, no value is returned.
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Find and evaluate the given object, passing the given
+ * parameters if necessary. One of "Handle" or "Pathname" must
+ * be valid (non-null)
+ *
+ ****************************************************************************/
+
+ACPI_STATUS
+acpi_evaluate_object (
+ ACPI_HANDLE handle,
+ ACPI_STRING pathname,
+ ACPI_OBJECT_LIST *param_objects,
+ ACPI_BUFFER *return_buffer)
+{
+ ACPI_STATUS status;
+ ACPI_OBJECT_INTERNAL **param_ptr = NULL;
+ ACPI_OBJECT_INTERNAL *return_obj = NULL;
+ ACPI_OBJECT_INTERNAL *object_ptr = NULL;
+ u32 buffer_space_needed;
+ u32 user_buffer_length;
+ u32 count;
+ u32 i;
+ u32 param_length;
+ u32 object_length;
+
+
+ /*
+ * If there are parameters to be passed to the object
+ * (which must be a control method), the external objects
+ * must be converted to internal objects
+ */
+
+ if (param_objects && param_objects->count) {
+ /*
+ * Allocate a new parameter block for the internal objects
+ * Add 1 to count to allow for null terminated internal list
+ * TBD: [Restructure] merge into single allocation!
+ */
+
+ count = param_objects->count;
+ param_length = (count + 1) * sizeof (void *);
+ object_length = count * sizeof (ACPI_OBJECT_INTERNAL);
+
+ param_ptr = acpi_cm_callocate (param_length + /* Parameter List part */
+ object_length); /* Actual objects */
+ if (!param_ptr) {
+ return (AE_NO_MEMORY);
+ }
+
+ object_ptr = (ACPI_OBJECT_INTERNAL *) ((u8 *) param_ptr +
+ param_length);
+
+ /*
+ * Init the param array of pointers and NULL terminate
+ * the list
+ */
+
+ for (i = 0; i < count; i++) {
+ param_ptr[i] = &object_ptr[i];
+ acpi_cm_init_static_object (&object_ptr[i]);
+ }
+ param_ptr[count] = NULL;
+
+ /*
+ * Convert each external object in the list to an
+ * internal object
+ */
+ for (i = 0; i < count; i++) {
+ status =
+ acpi_cm_build_internal_object (&param_objects->pointer[i],
+ param_ptr[i]);
+
+ if (ACPI_FAILURE (status)) {
+ acpi_cm_delete_internal_object_list (param_ptr);
+ return (status);
+ }
+ }
+ }
+
+
+ /*
+ * Three major cases:
+ * 1) Fully qualified pathname
+ * 2) No handle, not fully qualified pathname (error)
+ * 3) Valid handle
+ */
+
+ if ((pathname) &&
+ (acpi_ns_valid_root_prefix (pathname[0])))
+ {
+ /*
+ * The path is fully qualified, just evaluate by name
+ */
+ status = acpi_ns_evaluate_by_name (pathname, param_ptr, &return_obj);
+ }
+
+ else if (!handle) {
+ /*
+ * A handle is optional iff a fully qualified pathname
+ * is specified. Since we've already handled fully
+ * qualified names above, this is an error
+ */
+
+
+
+ status = AE_BAD_PARAMETER;
+ }
+
+ else {
+ /*
+ * We get here if we have a handle -- and if we have a
+ * pathname it is relative. The handle will be validated
+ * in the lower procedures
+ */
+
+ if (!pathname) {
+ /*
+ * The null pathname case means the handle is for
+ * the actual object to be evaluated
+ */
+ status = acpi_ns_evaluate_by_handle (handle,
+ param_ptr,
+ &return_obj);
+ }
+
+ else {
+ /*
+ * Both a Handle and a relative Pathname
+ */
+ status = acpi_ns_evaluate_relative (handle, pathname,
+ param_ptr,
+ &return_obj);
+ }
+ }
+
+
+ /*
+ * If we are expecting a return value, and all went well above,
+ * copy the return value to an external object.
+ */
+
+ if (return_buffer) {
+ user_buffer_length = return_buffer->length;
+ return_buffer->length = 0;
+
+ if (return_obj) {
+ if (VALID_DESCRIPTOR_TYPE (return_obj,
+ ACPI_DESC_TYPE_NAMED))
+ {
+ /*
+ * If we got an NTE as a return object,
+ * this means the object we are evaluating
+ * has nothing interesting to return (such
+ * as a mutex, etc.) We return an error
+ * because these types are essentially
+ * unsupported by this interface. We
+ * don't check up front because this makes
+ * it easier to add support for various
+ * types at a later date if necessary.
+ */
+ status = AE_TYPE;
+ return_obj = NULL; /* No need to delete an NTE */
+ }
+
+ if (ACPI_SUCCESS (status)) {
+ /*
+ * Find out how large a buffer is needed
+ * to contain the returned object
+ */
+ status = acpi_cm_get_object_size (return_obj,
+ &buffer_space_needed);
+ if (ACPI_SUCCESS (status)) {
+ /*
+ * Check if there is enough room in the
+ * caller's buffer
+ */
+
+ if (user_buffer_length < buffer_space_needed) {
+ /*
+ * Caller's buffer is too small, can't
+ * give him partial results fail the call
+ * but return the buffer size needed
+ */
+
+ return_buffer->length = buffer_space_needed;
+ status = AE_BUFFER_OVERFLOW;
+ }
+
+ else {
+ /*
+ * We have enough space for the object, build it
+ */
+ status =
+ acpi_cm_build_external_object (return_obj,
+ return_buffer);
+ return_buffer->length = buffer_space_needed;
+ }
+ }
+ }
+ }
+ }
+
+
+ /* Delete the return and parameter objects */
+
+ if (return_obj) {
+ /*
+ * Delete the internal return object. (Or at least
+ * decrement the reference count by one)
+ */
+ acpi_cm_remove_reference (return_obj);
+ }
+
+ /*
+ * Free the input parameter list (if we created one),
+ */
+
+ if (param_ptr) {
+ /* Free the allocated parameter block */
+
+ acpi_cm_delete_internal_object_list (param_ptr);
+ }
+
+ return (status);
+}
+
+
+/****************************************************************************
+ *
+ * FUNCTION: Acpi_get_next_object
+ *
+ * PARAMETERS: Type - Type of object to be searched for
+ * Parent - Parent object whose children we are getting
+ * Last_child - Previous child that was found.
+ * The NEXT child will be returned
+ * Ret_handle - Where handle to the next object is placed
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Return the next peer object within the namespace. If Handle is
+ * valid, Scope is ignored. Otherwise, the first object within
+ * Scope is returned.
+ *
+ ******************************************************************************/
+
+ACPI_STATUS
+acpi_get_next_object (
+ ACPI_OBJECT_TYPE type,
+ ACPI_HANDLE parent,
+ ACPI_HANDLE child,
+ ACPI_HANDLE *ret_handle)
+{
+ ACPI_STATUS status = AE_OK;
+ ACPI_NAMED_OBJECT *entry;
+ ACPI_NAMED_OBJECT *parent_entry = NULL;
+ ACPI_NAMED_OBJECT *child_entry = NULL;
+
+
+ /* Parameter validation */
+
+ if (type > ACPI_TYPE_MAX) {
+ return AE_BAD_PARAMETER;
+ }
+
+ acpi_cm_acquire_mutex (ACPI_MTX_NAMESPACE);
+
+ /* If null handle, use the parent */
+
+ if (!child) {
+ /* Start search at the beginning of the specified scope */
+
+ parent_entry = acpi_ns_convert_handle_to_entry (parent);
+ if (!parent_entry) {
+ status = AE_BAD_PARAMETER;
+ goto unlock_and_exit;
+ }
+ }
+
+ /* Non-null handle, ignore the parent */
+
+ else {
+ /* Convert and validate the handle */
+
+ child_entry = acpi_ns_convert_handle_to_entry (child);
+ if (!child_entry) {
+ status = AE_BAD_PARAMETER;
+ goto unlock_and_exit;
+ }
+ }
+
+
+ /* Internal function does the real work */
+
+ entry = acpi_ns_get_next_object ((OBJECT_TYPE_INTERNAL) type,
+ parent_entry, child_entry);
+ if (!entry) {
+ status = AE_NOT_FOUND;
+ goto unlock_and_exit;
+ }
+
+ if (ret_handle) {
+ *ret_handle = acpi_ns_convert_entry_to_handle (entry);
+ }
+
+
+unlock_and_exit:
+
+ acpi_cm_release_mutex (ACPI_MTX_NAMESPACE);
+ return status;
+}
+
+
+/****************************************************************************
+ *
+ * FUNCTION: Acpi_get_type
+ *
+ * PARAMETERS: Handle - Handle of object whose type is desired
+ * *Ret_type - Where the type will be placed
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: This routine returns the type associatd with a particular handle
+ *
+ ******************************************************************************/
+
+ACPI_STATUS
+acpi_get_type (
+ ACPI_HANDLE handle,
+ ACPI_OBJECT_TYPE *ret_type)
+{
+ ACPI_NAMED_OBJECT *object;
+
+
+ /* Parameter Validation */
+
+ if (!ret_type) {
+ return AE_BAD_PARAMETER;
+ }
+
+ /*
+ * Special case for the predefined Root Object
+ * (return type ANY)
+ */
+
+ if (handle == ACPI_ROOT_OBJECT) {
+ *ret_type = ACPI_TYPE_ANY;
+ return AE_OK;
+ }
+
+ acpi_cm_acquire_mutex (ACPI_MTX_NAMESPACE);
+
+ /* Convert and validate the handle */
+
+ object = acpi_ns_convert_handle_to_entry (handle);
+ if (!object) {
+ acpi_cm_release_mutex (ACPI_MTX_NAMESPACE);
+ return AE_BAD_PARAMETER;
+ }
+
+ *ret_type = object->type;
+
+
+ acpi_cm_release_mutex (ACPI_MTX_NAMESPACE);
+ return AE_OK;
+}
+
+
+/****************************************************************************
+ *
+ * FUNCTION: Acpi_get_parent
+ *
+ * PARAMETERS: Handle - Handle of object whose parent is desired
+ * Ret_handle - Where the parent handle will be placed
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Returns a handle to the parent of the object represented by
+ * Handle.
+ *
+ ******************************************************************************/
+
+ACPI_STATUS
+acpi_get_parent (
+ ACPI_HANDLE handle,
+ ACPI_HANDLE *ret_handle)
+{
+ ACPI_NAMED_OBJECT *object;
+ ACPI_STATUS status = AE_OK;
+
+
+ /* No trace macro, too verbose */
+
+
+ if (!ret_handle) {
+ return AE_BAD_PARAMETER;
+ }
+
+ /* Special case for the predefined Root Object (no parent) */
+
+ if (handle == ACPI_ROOT_OBJECT) {
+ return AE_NULL_ENTRY;
+ }
+
+
+ acpi_cm_acquire_mutex (ACPI_MTX_NAMESPACE);
+
+ /* Convert and validate the handle */
+
+ object = acpi_ns_convert_handle_to_entry (handle);
+ if (!object) {
+ status = AE_BAD_PARAMETER;
+ goto unlock_and_exit;
+ }
+
+
+ /* Get the parent entry */
+
+ *ret_handle =
+ acpi_ns_convert_entry_to_handle (acpi_ns_get_parent_entry (object));
+
+ /* Return exeption if parent is null */
+
+ if (!acpi_ns_get_parent_entry (object)) {
+ status = AE_NULL_ENTRY;
+ }
+
+
+unlock_and_exit:
+
+ acpi_cm_release_mutex (ACPI_MTX_NAMESPACE);
+ return AE_OK;
+}
+
+
+/******************************************************************************
+ *
+ * FUNCTION: Acpi_walk_namespace
+ *
+ * PARAMETERS: Type - ACPI_OBJECT_TYPE to search for
+ * Start_object - Handle in namespace where search begins
+ * Max_depth - Depth to which search is to reach
+ * User_function - Called when an object of "Type" is found
+ * Context - Passed to user function
+ *
+ * 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.
+ *
+ * The point of this procedure is to provide a generic namespace
+ * walk routine that can be called from multiple places to
+ * provide multiple services; the User Function can be tailored
+ * to each task, whether it is a print function, a compare
+ * function, etc.
+ *
+ ******************************************************************************/
+
+ACPI_STATUS
+acpi_walk_namespace (
+ ACPI_OBJECT_TYPE type,
+ ACPI_HANDLE start_object,
+ u32 max_depth,
+ WALK_CALLBACK user_function,
+ void *context,
+ void **return_value)
+{
+ ACPI_STATUS status;
+
+
+ /* Parameter validation */
+
+ if ((type > ACPI_TYPE_MAX) ||
+ (!max_depth) ||
+ (!user_function))
+ {
+ return (AE_BAD_PARAMETER);
+ }
+
+ /*
+ * 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 ((OBJECT_TYPE_INTERNAL) type,
+ start_object, max_depth,
+ NS_WALK_UNLOCK,
+ user_function, context,
+ return_value);
+
+ acpi_cm_release_mutex (ACPI_MTX_NAMESPACE);
+
+ return (status);
+}
+
+