patch-2.4.0-test3 linux/drivers/acpi/namespace/nsnames.c
Next file: linux/drivers/acpi/namespace/nsobject.c
Previous file: linux/drivers/acpi/namespace/nsload.c
Back to the patch index
Back to the overall index
- Lines: 504
- Date:
Wed Jul 5 11:23:12 2000
- Orig file:
v2.4.0-test2/linux/drivers/acpi/namespace/nsnames.c
- Orig date:
Wed Dec 31 16:00:00 1969
diff -u --recursive --new-file v2.4.0-test2/linux/drivers/acpi/namespace/nsnames.c linux/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);
+}
+
+
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)