Bring in acpica 20110211, still not ok anyway
[dragonfly.git] / sys / contrib / dev / acpica-unix / namespace / nswalk.c
1 /******************************************************************************
2  *
3  * Module Name: nswalk - Functions for walking the ACPI namespace
4  *
5  *****************************************************************************/
6
7 /******************************************************************************
8  *
9  * 1. Copyright Notice
10  *
11  * Some or all of this work - Copyright (c) 1999 - 2011, Intel Corp.
12  * All rights reserved.
13  *
14  * 2. License
15  *
16  * 2.1. This is your license from Intel Corp. under its intellectual property
17  * rights.  You may have additional license terms from the party that provided
18  * you this software, covering your right to use that party's intellectual
19  * property rights.
20  *
21  * 2.2. Intel grants, free of charge, to any person ("Licensee") obtaining a
22  * copy of the source code appearing in this file ("Covered Code") an
23  * irrevocable, perpetual, worldwide license under Intel's copyrights in the
24  * base code distributed originally by Intel ("Original Intel Code") to copy,
25  * make derivatives, distribute, use and display any portion of the Covered
26  * Code in any form, with the right to sublicense such rights; and
27  *
28  * 2.3. Intel grants Licensee a non-exclusive and non-transferable patent
29  * license (with the right to sublicense), under only those claims of Intel
30  * patents that are infringed by the Original Intel Code, to make, use, sell,
31  * offer to sell, and import the Covered Code and derivative works thereof
32  * solely to the minimum extent necessary to exercise the above copyright
33  * license, and in no event shall the patent license extend to any additions
34  * to or modifications of the Original Intel Code.  No other license or right
35  * is granted directly or by implication, estoppel or otherwise;
36  *
37  * The above copyright and patent license is granted only if the following
38  * conditions are met:
39  *
40  * 3. Conditions
41  *
42  * 3.1. Redistribution of Source with Rights to Further Distribute Source.
43  * Redistribution of source code of any substantial portion of the Covered
44  * Code or modification with rights to further distribute source must include
45  * the above Copyright Notice, the above License, this list of Conditions,
46  * and the following Disclaimer and Export Compliance provision.  In addition,
47  * Licensee must cause all Covered Code to which Licensee contributes to
48  * contain a file documenting the changes Licensee made to create that Covered
49  * Code and the date of any change.  Licensee must include in that file the
50  * documentation of any changes made by any predecessor Licensee.  Licensee
51  * must include a prominent statement that the modification is derived,
52  * directly or indirectly, from Original Intel Code.
53  *
54  * 3.2. Redistribution of Source with no Rights to Further Distribute Source.
55  * Redistribution of source code of any substantial portion of the Covered
56  * Code or modification without rights to further distribute source must
57  * include the following Disclaimer and Export Compliance provision in the
58  * documentation and/or other materials provided with distribution.  In
59  * addition, Licensee may not authorize further sublicense of source of any
60  * portion of the Covered Code, and must include terms to the effect that the
61  * license from Licensee to its licensee is limited to the intellectual
62  * property embodied in the software Licensee provides to its licensee, and
63  * not to intellectual property embodied in modifications its licensee may
64  * make.
65  *
66  * 3.3. Redistribution of Executable. Redistribution in executable form of any
67  * substantial portion of the Covered Code or modification must reproduce the
68  * above Copyright Notice, and the following Disclaimer and Export Compliance
69  * provision in the documentation and/or other materials provided with the
70  * distribution.
71  *
72  * 3.4. Intel retains all right, title, and interest in and to the Original
73  * Intel Code.
74  *
75  * 3.5. Neither the name Intel nor any other trademark owned or controlled by
76  * Intel shall be used in advertising or otherwise to promote the sale, use or
77  * other dealings in products derived from or relating to the Covered Code
78  * without prior written authorization from Intel.
79  *
80  * 4. Disclaimer and Export Compliance
81  *
82  * 4.1. INTEL MAKES NO WARRANTY OF ANY KIND REGARDING ANY SOFTWARE PROVIDED
83  * HERE.  ANY SOFTWARE ORIGINATING FROM INTEL OR DERIVED FROM INTEL SOFTWARE
84  * IS PROVIDED "AS IS," AND INTEL WILL NOT PROVIDE ANY SUPPORT,  ASSISTANCE,
85  * INSTALLATION, TRAINING OR OTHER SERVICES.  INTEL WILL NOT PROVIDE ANY
86  * UPDATES, ENHANCEMENTS OR EXTENSIONS.  INTEL SPECIFICALLY DISCLAIMS ANY
87  * IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT AND FITNESS FOR A
88  * PARTICULAR PURPOSE.
89  *
90  * 4.2. IN NO EVENT SHALL INTEL HAVE ANY LIABILITY TO LICENSEE, ITS LICENSEES
91  * OR ANY OTHER THIRD PARTY, FOR ANY LOST PROFITS, LOST DATA, LOSS OF USE OR
92  * COSTS OF PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, OR FOR ANY INDIRECT,
93  * SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THIS AGREEMENT, UNDER ANY
94  * CAUSE OF ACTION OR THEORY OF LIABILITY, AND IRRESPECTIVE OF WHETHER INTEL
95  * HAS ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES.  THESE LIMITATIONS
96  * SHALL APPLY NOTWITHSTANDING THE FAILURE OF THE ESSENTIAL PURPOSE OF ANY
97  * LIMITED REMEDY.
98  *
99  * 4.3. Licensee shall not export, either directly or indirectly, any of this
100  * software or system incorporating such software without first obtaining any
101  * required license or other approval from the U. S. Department of Commerce or
102  * any other agency or department of the United States Government.  In the
103  * event Licensee exports any such software from the United States or
104  * re-exports any such software from a foreign destination, Licensee shall
105  * ensure that the distribution and export/re-export of the software is in
106  * compliance with all laws, regulations, orders, or other restrictions of the
107  * U.S. Export Administration Regulations. Licensee agrees that neither it nor
108  * any of its subsidiaries will export/re-export any technical data, process,
109  * software, or service, directly or indirectly, to any country for which the
110  * United States government or any agency thereof requires an export license,
111  * other governmental approval, or letter of assurance, without first obtaining
112  * such license, approval or letter.
113  *
114  *****************************************************************************/
115
116
117 #define __NSWALK_C__
118
119 #include "acpi.h"
120 #include "accommon.h"
121 #include "acnamesp.h"
122
123
124 #define _COMPONENT          ACPI_NAMESPACE
125         ACPI_MODULE_NAME    ("nswalk")
126
127
128 /*******************************************************************************
129  *
130  * FUNCTION:    AcpiNsGetNextNode
131  *
132  * PARAMETERS:  ParentNode          - Parent node whose children we are
133  *                                    getting
134  *              ChildNode           - Previous child that was found.
135  *                                    The NEXT child will be returned
136  *
137  * RETURN:      ACPI_NAMESPACE_NODE - Pointer to the NEXT child or NULL if
138  *                                    none is found.
139  *
140  * DESCRIPTION: Return the next peer node within the namespace.  If Handle
141  *              is valid, Scope is ignored.  Otherwise, the first node
142  *              within Scope is returned.
143  *
144  ******************************************************************************/
145
146 ACPI_NAMESPACE_NODE *
147 AcpiNsGetNextNode (
148     ACPI_NAMESPACE_NODE     *ParentNode,
149     ACPI_NAMESPACE_NODE     *ChildNode)
150 {
151     ACPI_FUNCTION_ENTRY ();
152
153
154     if (!ChildNode)
155     {
156         /* It's really the parent's _scope_ that we want */
157
158         return (ParentNode->Child);
159     }
160
161     /* Otherwise just return the next peer */
162
163     return (ChildNode->Peer);
164 }
165
166
167 /*******************************************************************************
168  *
169  * FUNCTION:    AcpiNsGetNextNodeTyped
170  *
171  * PARAMETERS:  Type                - Type of node to be searched for
172  *              ParentNode          - Parent node whose children we are
173  *                                    getting
174  *              ChildNode           - Previous child that was found.
175  *                                    The NEXT child will be returned
176  *
177  * RETURN:      ACPI_NAMESPACE_NODE - Pointer to the NEXT child or NULL if
178  *                                    none is found.
179  *
180  * DESCRIPTION: Return the next peer node within the namespace.  If Handle
181  *              is valid, Scope is ignored.  Otherwise, the first node
182  *              within Scope is returned.
183  *
184  ******************************************************************************/
185
186 ACPI_NAMESPACE_NODE *
187 AcpiNsGetNextNodeTyped (
188     ACPI_OBJECT_TYPE        Type,
189     ACPI_NAMESPACE_NODE     *ParentNode,
190     ACPI_NAMESPACE_NODE     *ChildNode)
191 {
192     ACPI_NAMESPACE_NODE     *NextNode = NULL;
193
194
195     ACPI_FUNCTION_ENTRY ();
196
197
198     NextNode = AcpiNsGetNextNode (ParentNode, ChildNode);
199
200     /* If any type is OK, we are done */
201
202     if (Type == ACPI_TYPE_ANY)
203     {
204         /* NextNode is NULL if we are at the end-of-list */
205
206         return (NextNode);
207     }
208
209     /* Must search for the node -- but within this scope only */
210
211     while (NextNode)
212     {
213         /* If type matches, we are done */
214
215         if (NextNode->Type == Type)
216         {
217             return (NextNode);
218         }
219
220         /* Otherwise, move on to the next peer node */
221
222         NextNode = NextNode->Peer;
223     }
224
225     /* Not found */
226
227     return (NULL);
228 }
229
230
231 /*******************************************************************************
232  *
233  * FUNCTION:    AcpiNsWalkNamespace
234  *
235  * PARAMETERS:  Type                - ACPI_OBJECT_TYPE to search for
236  *              StartNode           - Handle in namespace where search begins
237  *              MaxDepth            - Depth to which search is to reach
238  *              Flags               - Whether to unlock the NS before invoking
239  *                                    the callback routine
240  *              PreOrderVisit       - Called during tree pre-order visit
241  *                                    when an object of "Type" is found
242  *              PostOrderVisit      - Called during tree post-order visit
243  *                                    when an object of "Type" is found
244  *              Context             - Passed to user function(s) above
245  *              ReturnValue         - from the UserFunction if terminated
246  *                                    early. Otherwise, returns NULL.
247  * RETURNS:     Status
248  *
249  * DESCRIPTION: Performs a modified depth-first walk of the namespace tree,
250  *              starting (and ending) at the node specified by StartHandle.
251  *              The callback function is called whenever a node that matches
252  *              the type parameter is found. If the callback function returns
253  *              a non-zero value, the search is terminated immediately and
254  *              this value is returned to the caller.
255  *
256  *              The point of this procedure is to provide a generic namespace
257  *              walk routine that can be called from multiple places to
258  *              provide multiple services; the callback function(s) can be
259  *              tailored to each task, whether it is a print function,
260  *              a compare function, etc.
261  *
262  ******************************************************************************/
263
264 ACPI_STATUS
265 AcpiNsWalkNamespace (
266     ACPI_OBJECT_TYPE        Type,
267     ACPI_HANDLE             StartNode,
268     UINT32                  MaxDepth,
269     UINT32                  Flags,
270     ACPI_WALK_CALLBACK      PreOrderVisit,
271     ACPI_WALK_CALLBACK      PostOrderVisit,
272     void                    *Context,
273     void                    **ReturnValue)
274 {
275     ACPI_STATUS             Status;
276     ACPI_STATUS             MutexStatus;
277     ACPI_NAMESPACE_NODE     *ChildNode;
278     ACPI_NAMESPACE_NODE     *ParentNode;
279     ACPI_OBJECT_TYPE        ChildType;
280     UINT32                  Level;
281     BOOLEAN                 NodePreviouslyVisited = FALSE;
282
283
284     ACPI_FUNCTION_TRACE (NsWalkNamespace);
285
286
287     /* Special case for the namespace Root Node */
288
289     if (StartNode == ACPI_ROOT_OBJECT)
290     {
291         StartNode = AcpiGbl_RootNode;
292     }
293
294     /* Null child means "get first node" */
295
296     ParentNode  = StartNode;
297     ChildNode   = AcpiNsGetNextNode (ParentNode, NULL);
298     ChildType   = ACPI_TYPE_ANY;
299     Level       = 1;
300
301     /*
302      * Traverse the tree of nodes until we bubble back up to where we
303      * started. When Level is zero, the loop is done because we have
304      * bubbled up to (and passed) the original parent handle (StartEntry)
305      */
306     while (Level > 0 && ChildNode)
307     {
308         Status = AE_OK;
309
310         /* Found next child, get the type if we are not searching for ANY */
311
312         if (Type != ACPI_TYPE_ANY)
313         {
314             ChildType = ChildNode->Type;
315         }
316
317         /*
318          * Ignore all temporary namespace nodes (created during control
319          * method execution) unless told otherwise. These temporary nodes
320          * can cause a race condition because they can be deleted during
321          * the execution of the user function (if the namespace is
322          * unlocked before invocation of the user function.) Only the
323          * debugger namespace dump will examine the temporary nodes.
324          */
325         if ((ChildNode->Flags & ANOBJ_TEMPORARY) &&
326             !(Flags & ACPI_NS_WALK_TEMP_NODES))
327         {
328             Status = AE_CTRL_DEPTH;
329         }
330
331         /* Type must match requested type */
332
333         else if (ChildType == Type)
334         {
335             /*
336              * Found a matching node, invoke the user callback function.
337              * Unlock the namespace if flag is set.
338              */
339             if (Flags & ACPI_NS_WALK_UNLOCK)
340             {
341                 MutexStatus = AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
342                 if (ACPI_FAILURE (MutexStatus))
343                 {
344                     return_ACPI_STATUS (MutexStatus);
345                 }
346             }
347
348             /*
349              * Invoke the user function, either pre-order or post-order
350              * or both.
351              */
352             if (!NodePreviouslyVisited)
353             {
354                 if (PreOrderVisit)
355                 {
356                     Status = PreOrderVisit (ChildNode, Level,
357                                 Context, ReturnValue);
358                 }
359             }
360             else
361             {
362                 if (PostOrderVisit)
363                 {
364                     Status = PostOrderVisit (ChildNode, Level,
365                                 Context, ReturnValue);
366                 }
367             }
368
369             if (Flags & ACPI_NS_WALK_UNLOCK)
370             {
371                 MutexStatus = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
372                 if (ACPI_FAILURE (MutexStatus))
373                 {
374                     return_ACPI_STATUS (MutexStatus);
375                 }
376             }
377
378             switch (Status)
379             {
380             case AE_OK:
381             case AE_CTRL_DEPTH:
382
383                 /* Just keep going */
384                 break;
385
386             case AE_CTRL_TERMINATE:
387
388                 /* Exit now, with OK status */
389
390                 return_ACPI_STATUS (AE_OK);
391
392             default:
393
394                 /* All others are valid exceptions */
395
396                 return_ACPI_STATUS (Status);
397             }
398         }
399
400         /*
401          * Depth first search: Attempt to go down another level in the
402          * namespace if we are allowed to.  Don't go any further if we have
403          * reached the caller specified maximum depth or if the user
404          * function has specified that the maximum depth has been reached.
405          */
406         if (!NodePreviouslyVisited &&
407             (Level < MaxDepth) &&
408             (Status != AE_CTRL_DEPTH))
409         {
410             if (ChildNode->Child)
411             {
412                 /* There is at least one child of this node, visit it */
413
414                 Level++;
415                 ParentNode = ChildNode;
416                 ChildNode = AcpiNsGetNextNode (ParentNode, NULL);
417                 continue;
418             }
419         }
420
421         /* No more children, re-visit this node */
422
423         if (!NodePreviouslyVisited)
424         {
425             NodePreviouslyVisited = TRUE;
426             continue;
427         }
428
429         /* No more children, visit peers */
430
431         ChildNode = AcpiNsGetNextNode (ParentNode, ChildNode);
432         if (ChildNode)
433         {
434             NodePreviouslyVisited = FALSE;
435         }
436
437         /* No peers, re-visit parent */
438
439         else
440         {
441             /*
442              * No more children of this node (AcpiNsGetNextNode failed), go
443              * back upwards in the namespace tree to the node's parent.
444              */
445             Level--;
446             ChildNode = ParentNode;
447             ParentNode = ParentNode->Parent;
448
449             NodePreviouslyVisited = TRUE;
450         }
451     }
452
453     /* Complete walk, not terminated by user function */
454
455     return_ACPI_STATUS (AE_OK);
456 }
457
458