diff options
author | Ralf Baechle <ralf@linux-mips.org> | 2000-07-08 00:53:00 +0000 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 2000-07-08 00:53:00 +0000 |
commit | b8553086288629b4efb77e97f5582e08bc50ad65 (patch) | |
tree | 0a19bd1c21e148f35c7a0f76baa4f7a056b966b0 /drivers/acpi/namespace/nsobject.c | |
parent | 75b6d92f2dd5112b02f4e78cf9f35f9825946ef0 (diff) |
Merge with 2.4.0-test3-pre4.
Diffstat (limited to 'drivers/acpi/namespace/nsobject.c')
-rw-r--r-- | drivers/acpi/namespace/nsobject.c | 556 |
1 files changed, 556 insertions, 0 deletions
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); +} + + |