summaryrefslogtreecommitdiffstats
path: root/drivers/acpi/namespace/nsobject.c
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/nsobject.c
parent75b6d92f2dd5112b02f4e78cf9f35f9825946ef0 (diff)
Merge with 2.4.0-test3-pre4.
Diffstat (limited to 'drivers/acpi/namespace/nsobject.c')
-rw-r--r--drivers/acpi/namespace/nsobject.c556
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);
+}
+
+