1 /******************************************************************************
3 * Module Name: nswalk - Functions for walking the APCI namespace
6 *****************************************************************************/
9 * Copyright (C) 2000, 2001 R. Byron Moore
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
32 #define _COMPONENT ACPI_NAMESPACE
33 MODULE_NAME ("nswalk")
36 /****************************************************************************
38 * FUNCTION: Acpi_get_next_object
40 * PARAMETERS: Type - Type of object to be searched for
41 * Parent - Parent object whose children we are
43 * Last_child - Previous child that was found.
44 * The NEXT child will be returned
46 * RETURN: ACPI_NAMESPACE_NODE - Pointer to the NEXT child or NULL if
49 * DESCRIPTION: Return the next peer object within the namespace. If Handle
50 * is valid, Scope is ignored. Otherwise, the first object
51 * within Scope is returned.
53 ****************************************************************************/
56 acpi_ns_get_next_object (
57 OBJECT_TYPE_INTERNAL type
,
58 ACPI_NAMESPACE_NODE
*parent_node
,
59 ACPI_NAMESPACE_NODE
*child_node
)
61 ACPI_NAMESPACE_NODE
*next_node
= NULL
;
66 /* It's really the parent's _scope_ that we want */
68 if (parent_node
->child
) {
69 next_node
= parent_node
->child
;
74 /* Start search at the NEXT object */
76 next_node
= acpi_ns_get_next_valid_object (child_node
);
80 /* If any type is OK, we are done */
82 if (type
== ACPI_TYPE_ANY
) {
83 /* Next_node is NULL if we are at the end-of-list */
89 /* Must search for the object -- but within this scope only */
92 /* If type matches, we are done */
94 if (next_node
->type
== type
) {
98 /* Otherwise, move on to the next object */
100 next_node
= acpi_ns_get_next_valid_object (next_node
);
110 /******************************************************************************
112 * FUNCTION: Acpi_ns_walk_namespace
114 * PARAMETERS: Type - ACPI_OBJECT_TYPE to search for
115 * Start_node - Handle in namespace where search begins
116 * Max_depth - Depth to which search is to reach
117 * Unlock_before_callback- Whether to unlock the NS before invoking
118 * the callback routine
119 * User_function - Called when an object of "Type" is found
120 * Context - Passed to user function
122 * RETURNS Return value from the User_function if terminated early.
123 * Otherwise, returns NULL.
125 * DESCRIPTION: Performs a modified depth-first walk of the namespace tree,
126 * starting (and ending) at the object specified by Start_handle.
127 * The User_function is called whenever an object that matches
128 * the type parameter is found. If the user function returns
129 * a non-zero value, the search is terminated immediately and this
130 * value is returned to the caller.
132 * The point of this procedure is to provide a generic namespace
133 * walk routine that can be called from multiple places to
134 * provide multiple services; the User Function can be tailored
135 * to each task, whether it is a print function, a compare
138 ******************************************************************************/
141 acpi_ns_walk_namespace (
142 OBJECT_TYPE_INTERNAL type
,
143 ACPI_HANDLE start_node
,
145 u8 unlock_before_callback
,
146 WALK_CALLBACK user_function
,
151 ACPI_NAMESPACE_NODE
*child_node
;
152 ACPI_NAMESPACE_NODE
*parent_node
;
153 OBJECT_TYPE_INTERNAL child_type
;
157 /* Special case for the namespace Root Node */
159 if (start_node
== ACPI_ROOT_OBJECT
) {
160 start_node
= acpi_gbl_root_node
;
164 /* Null child means "get first object" */
166 parent_node
= start_node
;
168 child_type
= ACPI_TYPE_ANY
;
172 * Traverse the tree of objects until we bubble back up to where we
173 * started. When Level is zero, the loop is done because we have
174 * bubbled up to (and passed) the original parent handle (Start_entry)
179 * Get the next typed object in this scope. Null returned
184 child_node
= acpi_ns_get_next_object (ACPI_TYPE_ANY
,
190 * Found an object, Get the type if we are not
194 if (type
!= ACPI_TYPE_ANY
) {
195 child_type
= child_node
->type
;
198 if (child_type
== type
) {
200 * Found a matching object, invoke the user
204 if (unlock_before_callback
) {
205 acpi_cm_release_mutex (ACPI_MTX_NAMESPACE
);
208 status
= user_function (child_node
, level
,
209 context
, return_value
);
211 if (unlock_before_callback
) {
212 acpi_cm_acquire_mutex (ACPI_MTX_NAMESPACE
);
218 /* Just keep going */
221 case AE_CTRL_TERMINATE
:
222 /* Exit now, with OK status */
227 /* All others are valid exceptions */
234 * Depth first search:
235 * Attempt to go down another level in the namespace
236 * if we are allowed to. Don't go any further if we
237 * have reached the caller specified maximum depth
238 * or if the user function has specified that the
239 * maximum depth has been reached.
242 if ((level
< max_depth
) && (status
!= AE_CTRL_DEPTH
)) {
243 if (acpi_ns_get_next_object (ACPI_TYPE_ANY
,
246 * There is at least one child of this
247 * object, visit the object
250 parent_node
= child_node
;
258 * No more children in this object (Acpi_ns_get_next_object
259 * failed), go back upwards in the namespace tree to
260 * the object's parent.
263 child_node
= parent_node
;
264 parent_node
= acpi_ns_get_parent_object (parent_node
);
268 /* Complete walk, not terminated by user function */